Merge remote-tracking branch 'remotes/origin/master' into clipper2
Conflicts: src/engine/engine.cpp src/engine/engine.h src/graphics/render_scene.cpp
This commit is contained in:
commit
4a4c3c1ce8
90 changed files with 6331 additions and 3106 deletions
|
@ -37,6 +37,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtEditor", "..\..\qteditor\
|
||||||
{A0A17BB4-760B-4E34-B1B0-3E43E5F2778A} = {A0A17BB4-760B-4E34-B1B0-3E43E5F2778A}
|
{A0A17BB4-760B-4E34-B1B0-3E43E5F2778A} = {A0A17BB4-760B-4E34-B1B0-3E43E5F2778A}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "animation", "animation\animation.vcxproj", "{63F2E301-5062-4910-87FB-0243772F6852}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{E1A0C677-DE71-4AD8-B802-AA7A3332D822} = {E1A0C677-DE71-4AD8-B802-AA7A3332D822}
|
||||||
|
{A0A17BB4-760B-4E34-B1B0-3E43E5F2778A} = {A0A17BB4-760B-4E34-B1B0-3E43E5F2778A}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Win32 = Debug|Win32
|
Debug|Win32 = Debug|Win32
|
||||||
|
@ -64,27 +70,41 @@ Global
|
||||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Debug|Win32.ActiveCfg = Debug|Win32
|
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Debug|Win32.Build.0 = Debug|Win32
|
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Debug|x64.ActiveCfg = Debug|x64
|
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Debug|x64.Build.0 = Debug|x64
|
||||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|Win32.ActiveCfg = Release|Win32
|
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|Win32.Build.0 = Release|Win32
|
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|Win32.Build.0 = Release|Win32
|
||||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|x64.ActiveCfg = Release|x64
|
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|x64.Build.0 = Release|x64
|
||||||
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|Win32.ActiveCfg = Debug|Win32
|
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|Win32.Build.0 = Debug|Win32
|
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|x64.ActiveCfg = Debug|Win32
|
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|x64.Build.0 = Debug|x64
|
||||||
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Release|Win32.ActiveCfg = Release|Win32
|
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Release|Win32.Build.0 = Release|Win32
|
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Release|Win32.Build.0 = Release|Win32
|
||||||
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Release|x64.ActiveCfg = Release|Win32
|
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Release|x64.Build.0 = Release|x64
|
||||||
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Debug|Win32.ActiveCfg = Debug|Win32
|
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Debug|Win32.Build.0 = Debug|Win32
|
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Debug|x64.ActiveCfg = Debug|Win32
|
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Debug|x64.Build.0 = Debug|x64
|
||||||
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Release|Win32.ActiveCfg = Release|Win32
|
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Release|Win32.Build.0 = Release|Win32
|
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Release|Win32.Build.0 = Release|Win32
|
||||||
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Release|x64.ActiveCfg = Release|x64
|
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}.Release|x64.Build.0 = Release|x64
|
||||||
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Debug|Win32.ActiveCfg = Debug|Win32
|
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Debug|Win32.Build.0 = Debug|Win32
|
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Debug|x64.ActiveCfg = Debug|Win32
|
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Debug|x64.ActiveCfg = Debug|Win32
|
||||||
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Release|Win32.ActiveCfg = Release|Win32
|
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Release|Win32.Build.0 = Release|Win32
|
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Release|Win32.Build.0 = Release|Win32
|
||||||
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Release|x64.ActiveCfg = Release|Win32
|
{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}.Release|x64.ActiveCfg = Release|Win32
|
||||||
|
{63F2E301-5062-4910-87FB-0243772F6852}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{63F2E301-5062-4910-87FB-0243772F6852}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{63F2E301-5062-4910-87FB-0243772F6852}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{63F2E301-5062-4910-87FB-0243772F6852}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{63F2E301-5062-4910-87FB-0243772F6852}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{63F2E301-5062-4910-87FB-0243772F6852}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
{63F2E301-5062-4910-87FB-0243772F6852}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{63F2E301-5062-4910-87FB-0243772F6852}.Release|x64.Build.0 = Release|x64
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
160
projects/vs2013/animation/animation.vcxproj
Normal file
160
projects/vs2013/animation/animation.vcxproj
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{63F2E301-5062-4910-87FB-0243772F6852}</ProjectGuid>
|
||||||
|
<RootNamespace>animation</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>NotSet</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>NotSet</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>NotSet</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>NotSet</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
|
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
|
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
|
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
|
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>BUILDING_ANIMATION;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>BUILDING_ANIMATION;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>BUILDING_ANIMATION;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>BUILDING_ANIMATION;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\src\animation\animation.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\animation\animation_system.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\core\new.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\src\animation\animation.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\animation\animation_system.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
12
projects/vs2013/animation/animation.vcxproj.filters
Normal file
12
projects/vs2013/animation/animation.vcxproj.filters
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\src\animation\animation.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\animation\animation_system.cpp" />
|
||||||
|
<ClCompile Include="..\..\..\src\core\new.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\src\animation\animation.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\animation\animation_system.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -161,8 +161,6 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\..\src\animation\animation.cpp" />
|
|
||||||
<ClCompile Include="..\..\..\src\animation\animation_system.cpp" />
|
|
||||||
<ClCompile Include="..\..\..\src\core\new.cpp" />
|
<ClCompile Include="..\..\..\src\core\new.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\editor\editor_icon.cpp" />
|
<ClCompile Include="..\..\..\src\editor\editor_icon.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\editor\entity_template_system.cpp" />
|
<ClCompile Include="..\..\..\src\editor\entity_template_system.cpp" />
|
||||||
|
@ -193,8 +191,6 @@
|
||||||
<ClCompile Include="..\..\..\src\universe\universe.cpp" />
|
<ClCompile Include="..\..\..\src\universe\universe.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\src\animation\animation.h" />
|
|
||||||
<ClInclude Include="..\..\..\src\animation\animation_system.h" />
|
|
||||||
<ClInclude Include="..\..\..\src\editor\ieditor_command.h" />
|
<ClInclude Include="..\..\..\src\editor\ieditor_command.h" />
|
||||||
<ClInclude Include="..\..\..\src\editor\editor_icon.h" />
|
<ClInclude Include="..\..\..\src\editor\editor_icon.h" />
|
||||||
<ClInclude Include="..\..\..\src\editor\entity_template_system.h" />
|
<ClInclude Include="..\..\..\src\editor\entity_template_system.h" />
|
||||||
|
|
|
@ -13,17 +13,8 @@
|
||||||
<Filter Include="graphics">
|
<Filter Include="graphics">
|
||||||
<UniqueIdentifier>{4958eded-acc7-41f8-ac9b-6f6bc47bd0ae}</UniqueIdentifier>
|
<UniqueIdentifier>{4958eded-acc7-41f8-ac9b-6f6bc47bd0ae}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="animation">
|
|
||||||
<UniqueIdentifier>{240998ba-942c-45cf-a31c-06007274bd82}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\..\src\animation\animation.cpp">
|
|
||||||
<Filter>animation</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\src\animation\animation_system.cpp">
|
|
||||||
<Filter>animation</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\..\src\graphics\frame_buffer.cpp">
|
<ClCompile Include="..\..\..\src\graphics\frame_buffer.cpp">
|
||||||
<Filter>graphics</Filter>
|
<Filter>graphics</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -108,12 +99,6 @@
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\src\animation\animation.h">
|
|
||||||
<Filter>animation</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\..\src\animation\animation_system.h">
|
|
||||||
<Filter>animation</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\..\..\src\graphics\frame_buffer.h">
|
<ClInclude Include="..\..\..\src\graphics\frame_buffer.h">
|
||||||
<Filter>graphics</Filter>
|
<Filter>graphics</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
|
@ -66,20 +66,20 @@
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
|
|
|
@ -5,10 +5,18 @@
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
<Platform>Win32</Platform>
|
<Platform>Win32</Platform>
|
||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
<Configuration>Release</Configuration>
|
<Configuration>Release</Configuration>
|
||||||
<Platform>Win32</Platform>
|
<Platform>Win32</Platform>
|
||||||
</ProjectConfiguration>
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\..\src\core\new.cpp" />
|
<ClCompile Include="..\..\..\src\core\new.cpp" />
|
||||||
|
@ -16,6 +24,7 @@
|
||||||
<ClCompile Include="..\..\..\src\unit_tests\core\ut_fixed_lock_free_queue.cpp" />
|
<ClCompile Include="..\..\..\src\unit_tests\core\ut_fixed_lock_free_queue.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\unit_tests\core\ut_hash_map.cpp">
|
<ClCompile Include="..\..\..\src\unit_tests\core\ut_hash_map.cpp">
|
||||||
<PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreprocessToFile>
|
<PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreprocessToFile>
|
||||||
|
<PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</PreprocessToFile>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\..\src\unit_tests\core\ut_mtjd_framework.cpp" />
|
<ClCompile Include="..\..\..\src\unit_tests\core\ut_mtjd_framework.cpp" />
|
||||||
<ClCompile Include="..\..\..\src\unit_tests\core\ut_path.cpp" />
|
<ClCompile Include="..\..\..\src\unit_tests\core\ut_path.cpp" />
|
||||||
|
@ -47,6 +56,12 @@
|
||||||
<PlatformToolset>v120</PlatformToolset>
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
<CharacterSet>NotSet</CharacterSet>
|
<CharacterSet>NotSet</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<CharacterSet>NotSet</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<ConfigurationType>Application</ConfigurationType>
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
@ -54,26 +69,49 @@
|
||||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
<CharacterSet>NotSet</CharacterSet>
|
<CharacterSet>NotSet</CharacterSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v120</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>NotSet</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
<ImportGroup Label="ExtensionSettings">
|
<ImportGroup Label="ExtensionSettings">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
<PropertyGroup Label="UserMacros" />
|
<PropertyGroup Label="UserMacros" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PrecompiledHeader>
|
<PrecompiledHeader>
|
||||||
|
@ -86,7 +124,23 @@
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>animation.lib;core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\external\glew\include</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>animation.lib;core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
@ -106,7 +160,27 @@
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>animation.lib;core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\external\glew\include</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>animation.lib;core.lib;engine.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>..\..\..\bin\$(Platform)_$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
|
@ -24,11 +24,13 @@ SOURCES += main.cpp\
|
||||||
scripts/scriptcompiler.cpp \
|
scripts/scriptcompiler.cpp \
|
||||||
scripts/scriptcompilerwidget.cpp \
|
scripts/scriptcompilerwidget.cpp \
|
||||||
fileserverwidget.cpp \
|
fileserverwidget.cpp \
|
||||||
materialmanager.cpp \
|
|
||||||
profilerui.cpp \
|
profilerui.cpp \
|
||||||
profilergraph.cpp \
|
profilergraph.cpp \
|
||||||
pc/file_system_watcher.cpp \
|
pc/file_system_watcher.cpp \
|
||||||
entity_template_list.cpp
|
entity_template_list.cpp \
|
||||||
|
notifications.cpp \
|
||||||
|
insert_mesh_command.cpp \
|
||||||
|
entity_list.cpp
|
||||||
|
|
||||||
HEADERS += mainwindow.h \
|
HEADERS += mainwindow.h \
|
||||||
sceneview.h \
|
sceneview.h \
|
||||||
|
@ -39,13 +41,15 @@ HEADERS += mainwindow.h \
|
||||||
scripts/scriptcompiler.h \
|
scripts/scriptcompiler.h \
|
||||||
scripts/scriptcompilerwidget.h \
|
scripts/scriptcompilerwidget.h \
|
||||||
fileserverwidget.h \
|
fileserverwidget.h \
|
||||||
materialmanager.h \
|
|
||||||
wgl_render_device.h \
|
wgl_render_device.h \
|
||||||
renderdevicewidget.h \
|
renderdevicewidget.h \
|
||||||
profilerui.h \
|
profilerui.h \
|
||||||
profilergraph.h \
|
profilergraph.h \
|
||||||
file_system_watcher.h \
|
file_system_watcher.h \
|
||||||
entity_template_list.h
|
entity_template_list.h \
|
||||||
|
notifications.h \
|
||||||
|
insert_mesh_command.h \
|
||||||
|
entity_list.h
|
||||||
|
|
||||||
FORMS += mainwindow.ui \
|
FORMS += mainwindow.ui \
|
||||||
logwidget.ui \
|
logwidget.ui \
|
||||||
|
@ -54,15 +58,15 @@ FORMS += mainwindow.ui \
|
||||||
assetbrowser.ui \
|
assetbrowser.ui \
|
||||||
scripts/scriptcompilerwidget.ui \
|
scripts/scriptcompilerwidget.ui \
|
||||||
fileserverwidget.ui \
|
fileserverwidget.ui \
|
||||||
materialmanager.ui \
|
|
||||||
profilerui.ui \
|
profilerui.ui \
|
||||||
profilergraph.ui \
|
profilergraph.ui \
|
||||||
entity_template_list.ui
|
entity_template_list.ui \
|
||||||
|
entity_list.ui
|
||||||
|
|
||||||
win32
|
win32
|
||||||
{
|
{
|
||||||
INCLUDEPATH = ../../src \
|
INCLUDEPATH = ../../src \
|
||||||
../../external/glew/include
|
../../external/glew/include
|
||||||
Release:LIBS = -L../../bin/Win32_Release -lcore -lengine -lopengl32 -lphysics
|
Release:LIBS = -L../../bin/Win32_Release -lcore -lengine -lopengl32 -lphysics -lanimation
|
||||||
Debug:LIBS = -L../../bin/Win32_Debug -lcore -lengine -lopengl32 -lphysics
|
Debug:LIBS = -L../../bin/Win32_Debug -lcore -lengine -lopengl32 -lphysics -lanimation
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "core/resource_manager.h"
|
#include "core/resource_manager.h"
|
||||||
#include "editor/world_editor.h"
|
#include "editor/world_editor.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
|
#include "insert_mesh_command.h"
|
||||||
#include <qfilesystemmodel.h>
|
#include <qfilesystemmodel.h>
|
||||||
#include <qlistwidget.h>
|
#include <qlistwidget.h>
|
||||||
#include <qmenu.h>
|
#include <qmenu.h>
|
||||||
|
@ -21,7 +22,7 @@ struct ProcessInfo
|
||||||
|
|
||||||
void getDefaultFilters(QStringList& filters)
|
void getDefaultFilters(QStringList& filters)
|
||||||
{
|
{
|
||||||
filters << "*.msh" << "*.unv" << "*.ani" << "*.blend" << "*.tga" << "*.mat";
|
filters << "*.msh" << "*.unv" << "*.ani" << "*.blend" << "*.tga" << "*.mat" << "*.dds";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ AssetBrowser::AssetBrowser(QWidget* parent) :
|
||||||
m_watcher = FileSystemWatcher::create(QDir::currentPath().toLatin1().data());
|
m_watcher = FileSystemWatcher::create(QDir::currentPath().toLatin1().data());
|
||||||
m_watcher->getCallback().bind<AssetBrowser, &AssetBrowser::onFileSystemWatcherCallback>(this);
|
m_watcher->getCallback().bind<AssetBrowser, &AssetBrowser::onFileSystemWatcherCallback>(this);
|
||||||
m_base_path = QDir::currentPath();
|
m_base_path = QDir::currentPath();
|
||||||
m_server = NULL;
|
m_editor = NULL;
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
m_model = new QFileSystemModel;
|
m_model = new QFileSystemModel;
|
||||||
m_model->setRootPath(QDir::currentPath());
|
m_model->setRootPath(QDir::currentPath());
|
||||||
|
@ -48,6 +49,7 @@ AssetBrowser::AssetBrowser(QWidget* parent) :
|
||||||
m_ui->treeView->hideColumn(4);
|
m_ui->treeView->hideColumn(4);
|
||||||
m_ui->listWidget->hide();
|
m_ui->listWidget->hide();
|
||||||
connect(this, SIGNAL(fileChanged(const QString&)), this, SLOT(onFileChanged(const QString&)));
|
connect(this, SIGNAL(fileChanged(const QString&)), this, SLOT(onFileChanged(const QString&)));
|
||||||
|
connect(m_ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, this, &AssetBrowser::onTreeViewSelectionChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetBrowser::~AssetBrowser()
|
AssetBrowser::~AssetBrowser()
|
||||||
|
@ -57,6 +59,18 @@ AssetBrowser::~AssetBrowser()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AssetBrowser::onTreeViewSelectionChanged(const QModelIndex&, const QModelIndex&)
|
||||||
|
{
|
||||||
|
/*if (current.isValid())
|
||||||
|
{
|
||||||
|
const QFileInfo& file_info = m_model->fileInfo(current);
|
||||||
|
QByteArray byte_array = file_info.filePath().toLower().toLatin1();
|
||||||
|
const char* filename = byte_array.data();
|
||||||
|
emit fileSelected(filename);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AssetBrowser::onFileSystemWatcherCallback(const char* path)
|
void AssetBrowser::onFileSystemWatcherCallback(const char* path)
|
||||||
{
|
{
|
||||||
emitFileChanged(path);
|
emitFileChanged(path);
|
||||||
|
@ -72,21 +86,21 @@ void AssetBrowser::emitFileChanged(const char* path)
|
||||||
void AssetBrowser::handleDoubleClick(const QFileInfo& file_info)
|
void AssetBrowser::handleDoubleClick(const QFileInfo& file_info)
|
||||||
{
|
{
|
||||||
const QString& suffix = file_info.suffix();
|
const QString& suffix = file_info.suffix();
|
||||||
QString file =file_info.filePath().toLower();
|
QString file = file_info.filePath().toLower();
|
||||||
if(suffix == "unv")
|
if(suffix == "unv")
|
||||||
{
|
{
|
||||||
m_server->loadUniverse(file.toLatin1().data());
|
m_editor->loadUniverse(file.toLatin1().data());
|
||||||
}
|
}
|
||||||
else if(suffix == "msh")
|
else if(suffix == "msh")
|
||||||
{
|
{
|
||||||
m_server->addEntity();
|
InsertMeshCommand* command = new InsertMeshCommand(*m_editor, m_editor->getCameraRaycastHit(), file.toLatin1().data());
|
||||||
m_server->addComponent(crc32("renderable"));
|
m_editor->executeCommand(command);
|
||||||
m_server->setProperty("renderable", "source", file.toLatin1().data(), file.length());
|
|
||||||
}
|
}
|
||||||
else if(suffix == "ani")
|
else if(suffix == "ani")
|
||||||
{
|
{
|
||||||
m_server->addComponent(crc32("animable"));
|
m_editor->addComponent(crc32("animable"));
|
||||||
m_server->setProperty("animable", "preview", file.toLatin1().data(), file.length());
|
m_editor->setProperty(crc32("animable"), -1, *m_editor->getProperty("animable", "preview"), file.toLatin1().data(), file.length());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,9 +122,9 @@ void AssetBrowser::onFileChanged(const QString& path)
|
||||||
exportAnimation(result_file_info);
|
exportAnimation(result_file_info);
|
||||||
exportModel(result_file_info);
|
exportModel(result_file_info);
|
||||||
}
|
}
|
||||||
else if(m_server)
|
else if(m_editor)
|
||||||
{
|
{
|
||||||
m_server->getEngine().getResourceManager().reload(path.toLatin1().data());
|
m_editor->getEngine().getResourceManager().reload(path.toLatin1().data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,3 +259,14 @@ void AssetBrowser::on_filterComboBox_currentTextChanged(const QString&)
|
||||||
}
|
}
|
||||||
m_model->setNameFilters(filters);
|
m_model->setNameFilters(filters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AssetBrowser::on_treeView_clicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
if (index.isValid())
|
||||||
|
{
|
||||||
|
const QFileInfo& file_info = m_model->fileInfo(index);
|
||||||
|
QByteArray byte_array = file_info.filePath().toLower().toLatin1();
|
||||||
|
const char* filename = byte_array.data();
|
||||||
|
emit fileSelected(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QDockWidget>
|
#include <qdockwidget.h>
|
||||||
|
#include <qitemselectionmodel.h>
|
||||||
|
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
|
@ -19,7 +20,7 @@ class AssetBrowser : public QDockWidget
|
||||||
public:
|
public:
|
||||||
explicit AssetBrowser(QWidget* parent = NULL);
|
explicit AssetBrowser(QWidget* parent = NULL);
|
||||||
~AssetBrowser();
|
~AssetBrowser();
|
||||||
void setWorldEditor(Lumix::WorldEditor& server) { m_server = &server; }
|
void setWorldEditor(Lumix::WorldEditor& editor) { m_editor = &editor; }
|
||||||
void emitFileChanged(const char* path);
|
void emitFileChanged(const char* path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -27,9 +28,11 @@ private:
|
||||||
void exportAnimation(const QFileInfo& file_info);
|
void exportAnimation(const QFileInfo& file_info);
|
||||||
void exportModel(const QFileInfo& file_info);
|
void exportModel(const QFileInfo& file_info);
|
||||||
void onFileSystemWatcherCallback(const char* path);
|
void onFileSystemWatcherCallback(const char* path);
|
||||||
|
void onTreeViewSelectionChanged(const QModelIndex& current, const QModelIndex& previous);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void fileChanged(const QString& string);
|
void fileChanged(const QString& string);
|
||||||
|
void fileSelected(const char* path);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_treeView_doubleClicked(const QModelIndex &index);
|
void on_treeView_doubleClicked(const QModelIndex &index);
|
||||||
|
@ -40,10 +43,12 @@ private slots:
|
||||||
void on_exportFinished(int);
|
void on_exportFinished(int);
|
||||||
void on_filterComboBox_currentTextChanged(const QString &arg1);
|
void on_filterComboBox_currentTextChanged(const QString &arg1);
|
||||||
|
|
||||||
private:
|
void on_treeView_clicked(const QModelIndex &index);
|
||||||
|
|
||||||
|
private:
|
||||||
Ui::AssetBrowser* m_ui;
|
Ui::AssetBrowser* m_ui;
|
||||||
class QFileSystemModel* m_model;
|
class QFileSystemModel* m_model;
|
||||||
class FileSystemWatcher* m_watcher;
|
class FileSystemWatcher* m_watcher;
|
||||||
Lumix::WorldEditor* m_server;
|
Lumix::WorldEditor* m_editor;
|
||||||
QString m_base_path;
|
QString m_base_path;
|
||||||
};
|
};
|
||||||
|
|
287
qteditor/QtEditor/entity_list.cpp
Normal file
287
qteditor/QtEditor/entity_list.cpp
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
#include "entity_list.h"
|
||||||
|
#include "ui_entity_list.h"
|
||||||
|
#include "core/crc32.h"
|
||||||
|
#include "editor/world_editor.h"
|
||||||
|
#include "engine/engine.h"
|
||||||
|
#include "universe/entity.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const char* component_map[] =
|
||||||
|
{
|
||||||
|
"Animable", "animable",
|
||||||
|
"Camera", "camera",
|
||||||
|
"Directional light", "light",
|
||||||
|
"Mesh", "renderable",
|
||||||
|
"Physics Box", "box_rigid_actor",
|
||||||
|
"Physics Controller", "physical_controller",
|
||||||
|
"Physics Mesh", "mesh_rigid_actor",
|
||||||
|
"Physics Heightfield", "physical_heightfield",
|
||||||
|
"Script", "script",
|
||||||
|
"Terrain", "terrain"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class EntityListFilter : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EntityListFilter(QWidget* parent) : QSortFilterProxyModel(parent), m_component(0) {}
|
||||||
|
void filterComponent(uint32_t component) { m_component = component; }
|
||||||
|
void setUniverse(Lumix::Universe* universe) { m_universe = universe; invalidate(); }
|
||||||
|
void setWorldEditor(Lumix::WorldEditor& editor)
|
||||||
|
{
|
||||||
|
editor.entityNameSet().bind<EntityListFilter, &EntityListFilter::onEntityNameSet>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override
|
||||||
|
{
|
||||||
|
QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
|
||||||
|
if (m_component == 0)
|
||||||
|
{
|
||||||
|
return sourceModel()->data(index).toString().contains(filterRegExp());
|
||||||
|
}
|
||||||
|
int entity_index = sourceModel()->data(index, Qt::UserRole).toInt();
|
||||||
|
return Lumix::Entity(m_universe, entity_index).getComponent(m_component).isValid() && sourceModel()->data(index).toString().contains(filterRegExp());
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEntityNameSet(const Lumix::Entity&, const char*)
|
||||||
|
{
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t m_component;
|
||||||
|
Lumix::Universe* m_universe;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class EntityListModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EntityListModel(QWidget* parent, EntityListFilter* filter)
|
||||||
|
: QAbstractItemModel(parent)
|
||||||
|
{
|
||||||
|
m_universe = NULL;
|
||||||
|
m_filter = filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant headerData(int section, Qt::Orientation, int role = Qt::DisplayRole) const override
|
||||||
|
{
|
||||||
|
if(role == Qt::DisplayRole)
|
||||||
|
{
|
||||||
|
switch(section)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return "ID";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT(false);
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual QModelIndex index(int row, int column, const QModelIndex&) const override
|
||||||
|
{
|
||||||
|
return createIndex(row, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual QModelIndex parent(const QModelIndex&) const override
|
||||||
|
{
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual int rowCount(const QModelIndex& parent_index) const override
|
||||||
|
{
|
||||||
|
return parent_index.isValid() ? 0 : m_entities.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual int columnCount(const QModelIndex&) const override
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual QVariant data(const QModelIndex& index, int role) const override
|
||||||
|
{
|
||||||
|
if (index.row() < m_entities.size())
|
||||||
|
{
|
||||||
|
if (index.isValid() && role == Qt::DisplayRole)
|
||||||
|
{
|
||||||
|
const char* name = m_entities[index.row()].getName();
|
||||||
|
return name && name[0] != '\0' ? QVariant(name) : QVariant(m_entities[index.row()].index);
|
||||||
|
}
|
||||||
|
else if (index.isValid() && role == Qt::UserRole)
|
||||||
|
{
|
||||||
|
return m_entities[index.row()].index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setUniverse(Lumix::Universe* universe)
|
||||||
|
{
|
||||||
|
m_filter->setUniverse(universe);
|
||||||
|
if(m_universe)
|
||||||
|
{
|
||||||
|
m_universe->entityCreated().unbind<EntityListModel, &EntityListModel::onEntityCreated>(this);
|
||||||
|
m_universe->entityDestroyed().unbind<EntityListModel, &EntityListModel::onEntityDestroyed>(this);
|
||||||
|
}
|
||||||
|
m_entities.clear();
|
||||||
|
m_universe = universe;
|
||||||
|
if(m_universe)
|
||||||
|
{
|
||||||
|
m_universe->entityCreated().bind<EntityListModel, &EntityListModel::onEntityCreated>(this);
|
||||||
|
m_universe->entityDestroyed().bind<EntityListModel, &EntityListModel::onEntityDestroyed>(this);
|
||||||
|
Lumix::Entity e = m_universe->getFirstEntity();
|
||||||
|
while(e.isValid())
|
||||||
|
{
|
||||||
|
m_entities.push(e);
|
||||||
|
e = m_universe->getNextEntity(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(m_universe)
|
||||||
|
{
|
||||||
|
emit dataChanged(createIndex(0, 0), createIndex(m_entities.size(), 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onEntityCreated(const Lumix::Entity& entity)
|
||||||
|
{
|
||||||
|
m_entities.push(entity);
|
||||||
|
emit dataChanged(createIndex(0, 0), createIndex(m_entities.size() - 1, 0));
|
||||||
|
m_filter->invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onEntityDestroyed(const Lumix::Entity& entity)
|
||||||
|
{
|
||||||
|
m_entities.eraseItem(entity);
|
||||||
|
emit dataChanged(createIndex(0, 0), createIndex(m_entities.size() - 1, 0));
|
||||||
|
m_filter->invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Lumix::Universe* m_universe;
|
||||||
|
Lumix::Array<Lumix::Entity> m_entities;
|
||||||
|
EntityListFilter* m_filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
EntityList::EntityList(QWidget *parent)
|
||||||
|
: QDockWidget(parent)
|
||||||
|
, m_ui(new Ui::EntityList)
|
||||||
|
{
|
||||||
|
m_universe = NULL;
|
||||||
|
m_ui->setupUi(this);
|
||||||
|
m_filter = new EntityListFilter(this);
|
||||||
|
m_model = new EntityListModel(this, m_filter);
|
||||||
|
m_filter->setDynamicSortFilter(true);
|
||||||
|
m_filter->setSourceModel(m_model);
|
||||||
|
m_ui->entityList->setModel(m_filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EntityList::~EntityList()
|
||||||
|
{
|
||||||
|
m_editor->universeCreated().unbind<EntityList, &EntityList::onUniverseCreated>(this);
|
||||||
|
m_editor->universeDestroyed().unbind<EntityList, &EntityList::onUniverseDestroyed>(this);
|
||||||
|
m_editor->universeLoaded().unbind<EntityList, &EntityList::onUniverseLoaded>(this);
|
||||||
|
m_editor->entitySelected().unbind<EntityList, &EntityList::onEntitySelected>(this);
|
||||||
|
|
||||||
|
delete m_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityList::setWorldEditor(Lumix::WorldEditor& editor)
|
||||||
|
{
|
||||||
|
m_editor = &editor;
|
||||||
|
editor.universeCreated().bind<EntityList, &EntityList::onUniverseCreated>(this);
|
||||||
|
editor.universeDestroyed().bind<EntityList, &EntityList::onUniverseDestroyed>(this);
|
||||||
|
editor.universeLoaded().bind<EntityList, &EntityList::onUniverseLoaded>(this);
|
||||||
|
m_universe = editor.getEngine().getUniverse();
|
||||||
|
m_model->setUniverse(m_universe);
|
||||||
|
m_filter->setSourceModel(m_model);
|
||||||
|
m_filter->setWorldEditor(editor);
|
||||||
|
m_ui->comboBox->clear();
|
||||||
|
m_ui->comboBox->addItem("All");
|
||||||
|
for (int i = 0; i < sizeof(component_map) / sizeof(component_map[0]); i += 2)
|
||||||
|
{
|
||||||
|
m_ui->comboBox->addItem(component_map[i]);
|
||||||
|
}
|
||||||
|
editor.entitySelected().bind<EntityList, &EntityList::onEntitySelected>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityList::onEntitySelected(const Lumix::Array<Lumix::Entity>& entities)
|
||||||
|
{
|
||||||
|
m_ui->entityList->selectionModel()->clear();
|
||||||
|
for(int j = entities.size() - 1; j >= 0; --j)
|
||||||
|
{
|
||||||
|
for (int i = 0, c = m_filter->rowCount(); i < c; ++i)
|
||||||
|
{
|
||||||
|
if (m_filter->data(m_filter->index(i, 0), Qt::UserRole).toInt() == entities[j].index)
|
||||||
|
{
|
||||||
|
m_ui->entityList->selectionModel()->select(m_filter->index(i, 0), QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityList::onUniverseCreated()
|
||||||
|
{
|
||||||
|
m_universe = m_editor->getEngine().getUniverse();
|
||||||
|
m_model->setUniverse(m_universe);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityList::onUniverseLoaded()
|
||||||
|
{
|
||||||
|
m_universe = m_editor->getEngine().getUniverse();
|
||||||
|
m_model->setUniverse(m_universe);
|
||||||
|
m_filter->invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityList::onUniverseDestroyed()
|
||||||
|
{
|
||||||
|
m_model->setUniverse(NULL);
|
||||||
|
m_universe = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityList::on_entityList_clicked(const QModelIndex &index)
|
||||||
|
{
|
||||||
|
m_editor->selectEntities(&Lumix::Entity(m_universe, m_filter->data(index, Qt::UserRole).toInt()), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityList::on_comboBox_activated(const QString &arg1)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < sizeof(component_map) / sizeof(component_map[0]); i += 2)
|
||||||
|
{
|
||||||
|
if (arg1 == component_map[i])
|
||||||
|
{
|
||||||
|
m_filter->filterComponent(crc32(component_map[i + 1]));
|
||||||
|
m_filter->invalidate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_filter->filterComponent(0);
|
||||||
|
m_filter->invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityList::on_nameFilterEdit_textChanged(const QString &arg1)
|
||||||
|
{
|
||||||
|
QRegExp regExp(arg1);
|
||||||
|
m_filter->setFilterRegExp(regExp);
|
||||||
|
}
|
52
qteditor/QtEditor/entity_list.h
Normal file
52
qteditor/QtEditor/entity_list.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <qsortfilterproxymodel.h>
|
||||||
|
#include "core/array.h"
|
||||||
|
#include "universe/entity.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ui
|
||||||
|
{
|
||||||
|
class EntityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Lumix
|
||||||
|
{
|
||||||
|
struct Entity;
|
||||||
|
class Universe;
|
||||||
|
class WorldEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
class EntityListModel;
|
||||||
|
class EntityListFilter;
|
||||||
|
|
||||||
|
|
||||||
|
class EntityList : public QDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit EntityList(QWidget* parent);
|
||||||
|
~EntityList();
|
||||||
|
void setWorldEditor(Lumix::WorldEditor& editor);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_entityList_clicked(const QModelIndex& index);
|
||||||
|
void on_comboBox_activated(const QString& arg1);
|
||||||
|
void on_nameFilterEdit_textChanged(const QString &arg1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onUniverseCreated();
|
||||||
|
void onUniverseDestroyed();
|
||||||
|
void onUniverseLoaded();
|
||||||
|
void onEntitySelected(const Lumix::Array<Lumix::Entity>& entity);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::EntityList* m_ui;
|
||||||
|
Lumix::WorldEditor* m_editor;
|
||||||
|
Lumix::Universe* m_universe;
|
||||||
|
EntityListModel* m_model;
|
||||||
|
EntityListFilter* m_filter;
|
||||||
|
};
|
||||||
|
|
89
qteditor/QtEditor/entity_list.ui
Normal file
89
qteditor/QtEditor/entity_list.ui
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>EntityList</class>
|
||||||
|
<widget class="QDockWidget" name="EntityList">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>389</width>
|
||||||
|
<height>422</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Entity list</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>All</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Animable</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Camera</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mesh</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Physics Box</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Physics Mesh</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Physics Heightfield</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Script</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="nameFilterEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListView" name="entityList">
|
||||||
|
<property name="modelColumn">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -43,14 +43,23 @@ void EntityTemplateList::onSystemUpdated()
|
||||||
|
|
||||||
void EntityTemplateList::on_templateList_doubleClicked(const QModelIndex &index)
|
void EntityTemplateList::on_templateList_doubleClicked(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
m_editor->getEntityTemplateSystem().createInstance(m_ui->templateList->item(index.row())->text().toLatin1().data());
|
Lumix::Vec3 pos = m_editor->getCameraRaycastHit();
|
||||||
|
m_editor->getEntityTemplateSystem().createInstance(m_ui->templateList->item(index.row())->text().toLatin1().data(), pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EntityTemplateList::instantiateTemplate()
|
void EntityTemplateList::instantiateTemplate()
|
||||||
|
{
|
||||||
|
instantiateTemplateAt(m_editor->getCameraRaycastHit());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EntityTemplateList::instantiateTemplateAt(const Lumix::Vec3& pos)
|
||||||
{
|
{
|
||||||
if (m_ui->templateList->currentIndex().row() >= 0)
|
if (m_ui->templateList->currentIndex().row() >= 0)
|
||||||
{
|
{
|
||||||
m_editor->getEntityTemplateSystem().createInstance(m_ui->templateList->item(m_ui->templateList->currentIndex().row())->text().toLatin1().data());
|
m_editor->getEntityTemplateSystem().createInstance(m_ui->templateList->item(m_ui->templateList->currentIndex().row())->text().toLatin1().data(), pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
|
#include "core/vec3.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,7 @@ class EntityTemplateList : public QDockWidget
|
||||||
|
|
||||||
void setWorldEditor(Lumix::WorldEditor& editor);
|
void setWorldEditor(Lumix::WorldEditor& editor);
|
||||||
void instantiateTemplate();
|
void instantiateTemplate();
|
||||||
|
void instantiateTemplateAt(const Lumix::Vec3& position);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onSystemUpdated();
|
void onSystemUpdated();
|
||||||
|
|
|
@ -37,6 +37,6 @@ void GameView::resizeEvent(QResizeEvent* event)
|
||||||
|
|
||||||
void GameView::on_playButton_clicked()
|
void GameView::on_playButton_clicked()
|
||||||
{
|
{
|
||||||
m_server->toggleGameMode();
|
m_editor->toggleGameMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ public:
|
||||||
|
|
||||||
QWidget* getContentWidget() const;
|
QWidget* getContentWidget() const;
|
||||||
void setPipeline(Lumix::PipelineInstance& pipeline) { m_pipeline = &pipeline; }
|
void setPipeline(Lumix::PipelineInstance& pipeline) { m_pipeline = &pipeline; }
|
||||||
|
void setWorldEditor(Lumix::WorldEditor& editor) { m_editor = &editor; }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_playButton_clicked();
|
void on_playButton_clicked();
|
||||||
|
@ -35,6 +36,6 @@ private:
|
||||||
private:
|
private:
|
||||||
Ui::GameView* m_ui;
|
Ui::GameView* m_ui;
|
||||||
Lumix::PipelineInstance* m_pipeline;
|
Lumix::PipelineInstance* m_pipeline;
|
||||||
Lumix::WorldEditor* m_server;
|
Lumix::WorldEditor* m_editor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
68
qteditor/QtEditor/insert_mesh_command.cpp
Normal file
68
qteditor/QtEditor/insert_mesh_command.cpp
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#include "insert_mesh_command.h"
|
||||||
|
#include "core/crc32.h"
|
||||||
|
#include "engine/engine.h"
|
||||||
|
#include "graphics/render_scene.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32_t RENDERABLE_HASH = crc32("renderable");
|
||||||
|
|
||||||
|
|
||||||
|
InsertMeshCommand::InsertMeshCommand(Lumix::WorldEditor& editor, const Lumix::Vec3& position, const Lumix::Path& mesh_path)
|
||||||
|
: m_mesh_path(mesh_path)
|
||||||
|
, m_position(position)
|
||||||
|
, m_editor(editor)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InsertMeshCommand::execute()
|
||||||
|
{
|
||||||
|
Lumix::Engine& engine = m_editor.getEngine();
|
||||||
|
m_entity = engine.getUniverse()->createEntity();
|
||||||
|
m_entity.setPosition(m_position);
|
||||||
|
const Lumix::Array<Lumix::IScene*>& scenes = engine.getScenes();
|
||||||
|
Lumix::Component cmp;
|
||||||
|
Lumix::IScene* scene = NULL;
|
||||||
|
for (int i = 0; i < scenes.size(); ++i)
|
||||||
|
{
|
||||||
|
cmp = scenes[i]->createComponent(RENDERABLE_HASH, m_entity);
|
||||||
|
if (cmp.isValid())
|
||||||
|
{
|
||||||
|
scene = scenes[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cmp.isValid())
|
||||||
|
{
|
||||||
|
char rel_path[LUMIX_MAX_PATH];
|
||||||
|
m_editor.getRelativePath(rel_path, LUMIX_MAX_PATH, m_mesh_path.c_str());
|
||||||
|
static_cast<Lumix::RenderScene*>(scene)->setRenderablePath(cmp, Lumix::string(rel_path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void InsertMeshCommand::undo()
|
||||||
|
{
|
||||||
|
const Lumix::Entity::ComponentList& cmps = m_entity.getComponents();
|
||||||
|
for (int i = 0; i < cmps.size(); ++i)
|
||||||
|
{
|
||||||
|
cmps[i].scene->destroyComponent(cmps[i]);
|
||||||
|
}
|
||||||
|
m_editor.getEngine().getUniverse()->destroyEntity(m_entity);
|
||||||
|
m_entity = Lumix::Entity::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t InsertMeshCommand::getType()
|
||||||
|
{
|
||||||
|
static const uint32_t type = crc32("insert_mesh");
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool InsertMeshCommand::merge(IEditorCommand&)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
25
qteditor/QtEditor/insert_mesh_command.h
Normal file
25
qteditor/QtEditor/insert_mesh_command.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "core/path.h"
|
||||||
|
#include "editor/ieditor_command.h"
|
||||||
|
#include "editor/world_editor.h"
|
||||||
|
|
||||||
|
|
||||||
|
class InsertMeshCommand : public Lumix::IEditorCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InsertMeshCommand(Lumix::WorldEditor& editor, const Lumix::Vec3& position, const Lumix::Path& mesh_path);
|
||||||
|
|
||||||
|
virtual void execute() override;
|
||||||
|
virtual void undo() override;
|
||||||
|
virtual uint32_t getType() override;
|
||||||
|
virtual bool merge(IEditorCommand&);
|
||||||
|
const Lumix::Entity& getEntity() const { return m_entity; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Lumix::Vec3 m_position;
|
||||||
|
Lumix::Path m_mesh_path;
|
||||||
|
Lumix::Entity m_entity;
|
||||||
|
Lumix::WorldEditor& m_editor;
|
||||||
|
};
|
|
@ -18,7 +18,6 @@
|
||||||
#include "sceneview.h"
|
#include "sceneview.h"
|
||||||
#include "gameview.h"
|
#include "gameview.h"
|
||||||
#include "wgl_render_device.h"
|
#include "wgl_render_device.h"
|
||||||
#include "materialmanager.h"
|
|
||||||
|
|
||||||
|
|
||||||
class App
|
class App
|
||||||
|
@ -42,8 +41,8 @@ class App
|
||||||
|
|
||||||
void onUniverseCreated()
|
void onUniverseCreated()
|
||||||
{
|
{
|
||||||
m_edit_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene());
|
m_edit_render_device->getPipeline().setScene((Lumix::RenderScene*)m_world_editor->getEngine().getScene(crc32("renderer")));
|
||||||
m_game_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene());
|
m_game_render_device->getPipeline().setScene((Lumix::RenderScene*)m_world_editor->getEngine().getScene(crc32("renderer")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void onUniverseDestroyed()
|
void onUniverseDestroyed()
|
||||||
|
@ -198,10 +197,10 @@ class App
|
||||||
|
|
||||||
void renderPhysics()
|
void renderPhysics()
|
||||||
{
|
{
|
||||||
Lumix::PhysicsSystem* system = static_cast<Lumix::PhysicsSystem*>(m_world_editor->getEngine().getPluginManager().getPlugin("physics"));
|
Lumix::PhysicsScene* scene = static_cast<Lumix::PhysicsScene*>(m_world_editor->getEngine().getScene(crc32("physics")));
|
||||||
if(system && system->getScene())
|
if(scene)
|
||||||
{
|
{
|
||||||
system->getScene()->render();
|
scene->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,8 +217,8 @@ class App
|
||||||
|
|
||||||
HWND hwnd = (HWND)m_main_window->getSceneView()->getViewWidget()->winId();
|
HWND hwnd = (HWND)m_main_window->getSceneView()->getViewWidget()->winId();
|
||||||
HWND game_hwnd = (HWND)m_main_window->getGameView()->getContentWidget()->winId();
|
HWND game_hwnd = (HWND)m_main_window->getGameView()->getContentWidget()->winId();
|
||||||
HWND hwnds[] = { hwnd, game_hwnd, (HWND)m_main_window->getMaterialManager()->getPreview()->winId() };
|
HWND hwnds[] = { hwnd, game_hwnd };
|
||||||
HGLRC hglrc = createGLContext(hwnds, 3);
|
HGLRC hglrc = createGLContext(hwnds, 2);
|
||||||
|
|
||||||
m_world_editor = Lumix::WorldEditor::create(QDir::currentPath().toLocal8Bit().data());
|
m_world_editor = Lumix::WorldEditor::create(QDir::currentPath().toLocal8Bit().data());
|
||||||
ASSERT(m_world_editor);
|
ASSERT(m_world_editor);
|
||||||
|
@ -231,14 +230,14 @@ class App
|
||||||
m_edit_render_device = new WGLRenderDevice(m_world_editor->getEngine(), "pipelines/main.json");
|
m_edit_render_device = new WGLRenderDevice(m_world_editor->getEngine(), "pipelines/main.json");
|
||||||
m_edit_render_device->m_hdc = GetDC(hwnd);
|
m_edit_render_device->m_hdc = GetDC(hwnd);
|
||||||
m_edit_render_device->m_opengl_context = hglrc;
|
m_edit_render_device->m_opengl_context = hglrc;
|
||||||
m_edit_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene()); /// TODO manage scene properly
|
m_edit_render_device->getPipeline().setScene((Lumix::RenderScene*)m_world_editor->getEngine().getScene(crc32("renderer")));
|
||||||
m_world_editor->setEditViewRenderDevice(*m_edit_render_device);
|
m_world_editor->setEditViewRenderDevice(*m_edit_render_device);
|
||||||
m_edit_render_device->getPipeline().addCustomCommandHandler("render_physics").bind<App, &App::renderPhysics>(this);
|
m_edit_render_device->getPipeline().addCustomCommandHandler("render_physics").bind<App, &App::renderPhysics>(this);
|
||||||
|
|
||||||
m_game_render_device = new WGLRenderDevice(m_world_editor->getEngine(), "pipelines/game_view.json");
|
m_game_render_device = new WGLRenderDevice(m_world_editor->getEngine(), "pipelines/game_view.json");
|
||||||
m_game_render_device->m_hdc = GetDC(game_hwnd);
|
m_game_render_device->m_hdc = GetDC(game_hwnd);
|
||||||
m_game_render_device->m_opengl_context = hglrc;
|
m_game_render_device->m_opengl_context = hglrc;
|
||||||
m_game_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene()); /// TODO manage scene properly
|
m_game_render_device->getPipeline().setScene((Lumix::RenderScene*)m_world_editor->getEngine().getScene(crc32("renderer")));
|
||||||
m_world_editor->getEngine().getRenderer().setRenderDevice(*m_game_render_device);
|
m_world_editor->getEngine().getRenderer().setRenderDevice(*m_game_render_device);
|
||||||
|
|
||||||
m_world_editor->universeCreated().bind<App, &App::onUniverseCreated>(this);
|
m_world_editor->universeCreated().bind<App, &App::onUniverseCreated>(this);
|
||||||
|
@ -248,6 +247,7 @@ class App
|
||||||
m_main_window->getGameView()->setPipeline(m_game_render_device->getPipeline());
|
m_main_window->getGameView()->setPipeline(m_game_render_device->getPipeline());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void shutdown()
|
void shutdown()
|
||||||
{
|
{
|
||||||
delete m_game_render_device;
|
delete m_game_render_device;
|
||||||
|
@ -256,6 +256,7 @@ class App
|
||||||
m_edit_render_device = NULL;
|
m_edit_render_device = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void renderEditView()
|
void renderEditView()
|
||||||
{
|
{
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
|
@ -265,10 +266,9 @@ class App
|
||||||
m_world_editor->getGizmo().updateScale(m_world_editor->getEditCamera());
|
m_world_editor->getGizmo().updateScale(m_world_editor->getEditCamera());
|
||||||
m_world_editor->getGizmo().render(m_world_editor->getEngine().getRenderer(), *m_edit_render_device);
|
m_world_editor->getGizmo().render(m_world_editor->getEngine().getRenderer(), *m_edit_render_device);
|
||||||
m_edit_render_device->endFrame();
|
m_edit_render_device->endFrame();
|
||||||
|
|
||||||
m_main_window->getMaterialManager()->updatePreview();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void handleEvents()
|
void handleEvents()
|
||||||
{
|
{
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
|
@ -308,12 +308,14 @@ class App
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
while (m_main_window->isVisible())
|
while (m_main_window->isVisible())
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
PROFILE_BLOCK("tick");
|
PROFILE_BLOCK("tick");
|
||||||
|
m_main_window->update();
|
||||||
renderEditView();
|
renderEditView();
|
||||||
m_world_editor->getEngine().getRenderer().renderGame();
|
m_world_editor->getEngine().getRenderer().renderGame();
|
||||||
m_world_editor->tick();
|
m_world_editor->tick();
|
||||||
|
|
|
@ -3,17 +3,20 @@
|
||||||
#include "assetbrowser.h"
|
#include "assetbrowser.h"
|
||||||
#include "editor/entity_template_system.h"
|
#include "editor/entity_template_system.h"
|
||||||
#include "editor/world_editor.h"
|
#include "editor/world_editor.h"
|
||||||
|
#include "engine/engine.h"
|
||||||
|
#include "entity_list.h"
|
||||||
#include "entity_template_list.h"
|
#include "entity_template_list.h"
|
||||||
#include "fileserverwidget.h"
|
#include "fileserverwidget.h"
|
||||||
#include "gameview.h"
|
#include "gameview.h"
|
||||||
#include "log_widget.h"
|
#include "log_widget.h"
|
||||||
|
#include "notifications.h"
|
||||||
#include "property_view.h"
|
#include "property_view.h"
|
||||||
#include "sceneview.h"
|
#include "sceneview.h"
|
||||||
#include "scripts/scriptcompilerwidget.h"
|
#include "scripts/scriptcompilerwidget.h"
|
||||||
#include "materialmanager.h"
|
|
||||||
#include "profilerui.h"
|
#include "profilerui.h"
|
||||||
#include <qfiledialog.h>
|
#include <qfiledialog.h>
|
||||||
#include <qinputdialog.h>
|
#include <qinputdialog.h>
|
||||||
|
#include <qevent.h>
|
||||||
#include <qsettings.h>
|
#include <qsettings.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,9 +35,10 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||||
m_asset_browser = new AssetBrowser;
|
m_asset_browser = new AssetBrowser;
|
||||||
m_script_compiler_ui = new ScriptCompilerWidget;
|
m_script_compiler_ui = new ScriptCompilerWidget;
|
||||||
m_file_server_ui = new FileServerWidget;
|
m_file_server_ui = new FileServerWidget;
|
||||||
m_material_manager_ui = new MaterialManager;
|
|
||||||
m_profiler_ui = new ProfilerUI;
|
m_profiler_ui = new ProfilerUI;
|
||||||
m_entity_template_list_ui = new EntityTemplateList;
|
m_entity_template_list_ui = new EntityTemplateList;
|
||||||
|
m_notifications = Notifications::create(*this);
|
||||||
|
m_entity_list = new EntityList(NULL);
|
||||||
|
|
||||||
QSettings settings("Lumix", "QtEditor");
|
QSettings settings("Lumix", "QtEditor");
|
||||||
restoreGeometry(settings.value("mainWindowGeometry").toByteArray());
|
restoreGeometry(settings.value("mainWindowGeometry").toByteArray());
|
||||||
|
@ -46,16 +50,30 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(1), m_property_view);
|
addDockWidget(static_cast<Qt::DockWidgetArea>(1), m_property_view);
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(2), m_scene_view);
|
addDockWidget(static_cast<Qt::DockWidgetArea>(2), m_scene_view);
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(2), m_asset_browser);
|
addDockWidget(static_cast<Qt::DockWidgetArea>(2), m_asset_browser);
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(8), m_material_manager_ui);
|
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(1), m_profiler_ui);
|
addDockWidget(static_cast<Qt::DockWidgetArea>(1), m_profiler_ui);
|
||||||
addDockWidget(static_cast<Qt::DockWidgetArea>(2), m_entity_template_list_ui);
|
addDockWidget(static_cast<Qt::DockWidgetArea>(2), m_entity_template_list_ui);
|
||||||
|
addDockWidget(static_cast<Qt::DockWidgetArea>(2), m_entity_list);
|
||||||
|
|
||||||
m_property_view->setScriptCompiler(m_script_compiler_ui->getCompiler());
|
m_property_view->setScriptCompiler(m_script_compiler_ui->getCompiler());
|
||||||
|
m_property_view->setAssetBrowser(*m_asset_browser);
|
||||||
|
m_property_view->setEntityTemplateList(m_entity_template_list_ui);
|
||||||
|
|
||||||
restoreState(settings.value("mainWindowState").toByteArray());
|
restoreState(settings.value("mainWindowState").toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::resizeEvent(QResizeEvent* event)
|
||||||
|
{
|
||||||
|
m_resized.invoke(event->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MainWindow::update()
|
||||||
|
{
|
||||||
|
m_notifications->update(m_world_editor->getEngine().getLastTimeDelta());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent *event)
|
void MainWindow::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
QSettings settings("Lumix", "QtEditor");
|
QSettings settings("Lumix", "QtEditor");
|
||||||
|
@ -74,9 +92,9 @@ MainWindow::~MainWindow()
|
||||||
delete m_asset_browser;
|
delete m_asset_browser;
|
||||||
delete m_script_compiler_ui;
|
delete m_script_compiler_ui;
|
||||||
delete m_file_server_ui;
|
delete m_file_server_ui;
|
||||||
delete m_material_manager_ui;
|
|
||||||
delete m_profiler_ui;
|
delete m_profiler_ui;
|
||||||
delete m_entity_template_list_ui;
|
delete m_entity_template_list_ui;
|
||||||
|
Notifications::destroy(m_notifications);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,9 +103,10 @@ void MainWindow::setWorldEditor(Lumix::WorldEditor& editor)
|
||||||
m_world_editor = &editor;
|
m_world_editor = &editor;
|
||||||
m_file_server_ui->setWorldEditor(editor);
|
m_file_server_ui->setWorldEditor(editor);
|
||||||
m_asset_browser->setWorldEditor(editor);
|
m_asset_browser->setWorldEditor(editor);
|
||||||
m_material_manager_ui->setWorldEditor(editor);
|
|
||||||
m_property_view->setWorldEditor(editor);
|
m_property_view->setWorldEditor(editor);
|
||||||
m_entity_template_list_ui->setWorldEditor(editor);
|
m_entity_template_list_ui->setWorldEditor(editor);
|
||||||
|
m_game_view->setWorldEditor(editor);
|
||||||
|
m_entity_list->setWorldEditor(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameView* MainWindow::getGameView() const
|
GameView* MainWindow::getGameView() const
|
||||||
|
@ -171,11 +190,6 @@ void MainWindow::on_actionProfiler_triggered()
|
||||||
m_profiler_ui->show();
|
m_profiler_ui->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionMaterial_manager_triggered()
|
|
||||||
{
|
|
||||||
m_material_manager_ui->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::on_actionPolygon_Mode_changed()
|
void MainWindow::on_actionPolygon_Mode_changed()
|
||||||
{
|
{
|
||||||
m_world_editor->setWireframe(m_ui->actionPolygon_Mode->isChecked());
|
m_world_editor->setWireframe(m_ui->actionPolygon_Mode->isChecked());
|
||||||
|
@ -215,13 +229,13 @@ void MainWindow::on_actionSnap_to_terrain_triggered()
|
||||||
|
|
||||||
void MainWindow::on_actionSave_as_template_triggered()
|
void MainWindow::on_actionSave_as_template_triggered()
|
||||||
{
|
{
|
||||||
if (m_world_editor->getSelectedEntity().isValid())
|
if (m_world_editor->getSelectedEntities().size() == 1)
|
||||||
{
|
{
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
QString text = QInputDialog::getText(this, tr("Entity template"), tr("Template name:"), QLineEdit::Normal, tr(""), &ok);
|
QString text = QInputDialog::getText(this, tr("Entity template"), tr("Template name:"), QLineEdit::Normal, tr(""), &ok);
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
m_world_editor->getEntityTemplateSystem().createTemplateFromEntity(text.toLatin1().data(), m_world_editor->getSelectedEntity());
|
m_world_editor->getEntityTemplateSystem().createTemplateFromEntity(text.toLatin1().data(), m_world_editor->getSelectedEntities()[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,3 +259,16 @@ void MainWindow::on_actionRedo_triggered()
|
||||||
{
|
{
|
||||||
m_world_editor->redo();
|
m_world_editor->redo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionRemove_triggered()
|
||||||
|
{
|
||||||
|
if (!m_world_editor->getSelectedEntities().empty())
|
||||||
|
{
|
||||||
|
m_world_editor->destroyEntities(&m_world_editor->getSelectedEntities()[0], m_world_editor->getSelectedEntities().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionEntity_list_triggered()
|
||||||
|
{
|
||||||
|
m_entity_list->show();
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include "core/delegate_list.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
|
@ -20,10 +22,11 @@ public:
|
||||||
explicit MainWindow(QWidget* parent = NULL);
|
explicit MainWindow(QWidget* parent = NULL);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
|
void update();
|
||||||
void setWorldEditor(Lumix::WorldEditor& world_editor);
|
void setWorldEditor(Lumix::WorldEditor& world_editor);
|
||||||
class SceneView* getSceneView() const;
|
class SceneView* getSceneView() const;
|
||||||
class GameView* getGameView() const;
|
class GameView* getGameView() const;
|
||||||
class MaterialManager* getMaterialManager() const { return m_material_manager_ui; }
|
Lumix::DelegateList<void(const QSize&)>& resized() { return m_resized; }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_actionLog_triggered();
|
void on_actionLog_triggered();
|
||||||
|
@ -39,7 +42,6 @@ private slots:
|
||||||
void on_actionScene_View_triggered();
|
void on_actionScene_View_triggered();
|
||||||
virtual void closeEvent(QCloseEvent* event) override;
|
virtual void closeEvent(QCloseEvent* event) override;
|
||||||
void on_actionProfiler_triggered();
|
void on_actionProfiler_triggered();
|
||||||
void on_actionMaterial_manager_triggered();
|
|
||||||
void on_actionPolygon_Mode_changed();
|
void on_actionPolygon_Mode_changed();
|
||||||
void on_actionGame_mode_triggered();
|
void on_actionGame_mode_triggered();
|
||||||
void on_actionLook_at_selected_entity_triggered();
|
void on_actionLook_at_selected_entity_triggered();
|
||||||
|
@ -48,12 +50,16 @@ private slots:
|
||||||
void on_actionSnap_to_terrain_triggered();
|
void on_actionSnap_to_terrain_triggered();
|
||||||
void on_actionSave_as_template_triggered();
|
void on_actionSave_as_template_triggered();
|
||||||
void on_actionEntity_templates_triggered();
|
void on_actionEntity_templates_triggered();
|
||||||
|
void on_actionInstantiate_template_triggered();
|
||||||
|
void on_actionUndo_triggered();
|
||||||
|
void on_actionRedo_triggered();
|
||||||
|
|
||||||
void on_actionInstantiate_template_triggered();
|
void on_actionRemove_triggered();
|
||||||
|
|
||||||
void on_actionUndo_triggered();
|
void on_actionEntity_list_triggered();
|
||||||
|
|
||||||
void on_actionRedo_triggered();
|
private:
|
||||||
|
virtual void resizeEvent(QResizeEvent* event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow* m_ui;
|
Ui::MainWindow* m_ui;
|
||||||
|
@ -65,8 +71,10 @@ private:
|
||||||
class AssetBrowser* m_asset_browser;
|
class AssetBrowser* m_asset_browser;
|
||||||
class ScriptCompilerWidget* m_script_compiler_ui;
|
class ScriptCompilerWidget* m_script_compiler_ui;
|
||||||
class FileServerWidget* m_file_server_ui;
|
class FileServerWidget* m_file_server_ui;
|
||||||
class MaterialManager* m_material_manager_ui;
|
|
||||||
class ProfilerUI* m_profiler_ui;
|
class ProfilerUI* m_profiler_ui;
|
||||||
class EntityTemplateList* m_entity_template_list_ui;
|
class EntityTemplateList* m_entity_template_list_ui;
|
||||||
|
class Notifications* m_notifications;
|
||||||
|
class EntityList* m_entity_list;
|
||||||
|
Lumix::DelegateList<void(const QSize&)> m_resized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,11 +52,11 @@
|
||||||
<string>Windows</string>
|
<string>Windows</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionAsset_Browser"/>
|
<addaction name="actionAsset_Browser"/>
|
||||||
|
<addaction name="actionEntity_list"/>
|
||||||
<addaction name="actionEntity_templates"/>
|
<addaction name="actionEntity_templates"/>
|
||||||
<addaction name="actionFile_server"/>
|
<addaction name="actionFile_server"/>
|
||||||
<addaction name="actionGame_view"/>
|
<addaction name="actionGame_view"/>
|
||||||
<addaction name="actionLog"/>
|
<addaction name="actionLog"/>
|
||||||
<addaction name="actionMaterial_manager"/>
|
|
||||||
<addaction name="actionProfiler"/>
|
<addaction name="actionProfiler"/>
|
||||||
<addaction name="actionProperties"/>
|
<addaction name="actionProperties"/>
|
||||||
<addaction name="actionScene_View"/>
|
<addaction name="actionScene_View"/>
|
||||||
|
@ -89,6 +89,7 @@
|
||||||
<string>Entity</string>
|
<string>Entity</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionCreate"/>
|
<addaction name="actionCreate"/>
|
||||||
|
<addaction name="actionRemove"/>
|
||||||
<addaction name="actionSave_as_template"/>
|
<addaction name="actionSave_as_template"/>
|
||||||
<addaction name="actionInstantiate_template"/>
|
<addaction name="actionInstantiate_template"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -272,6 +273,19 @@
|
||||||
<string>Ctrl+Shift+Z</string>
|
<string>Ctrl+Shift+Z</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionRemove">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+R</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionEntity_list">
|
||||||
|
<property name="text">
|
||||||
|
<string>Entity list</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|
|
@ -1,372 +0,0 @@
|
||||||
#include "materialmanager.h"
|
|
||||||
#include "ui_materialmanager.h"
|
|
||||||
#include <qboxlayout.h>
|
|
||||||
#include <qcheckbox.h>
|
|
||||||
#include <qfilesystemmodel.h>
|
|
||||||
#include <qformlayout.h>
|
|
||||||
#include <qlineedit.h>
|
|
||||||
#include <qpainter.h>
|
|
||||||
#include <qpushbutton.h>
|
|
||||||
#include "core/crc32.h"
|
|
||||||
#include "core/FS/file_system.h"
|
|
||||||
#include "core/json_serializer.h"
|
|
||||||
#include "core/log.h"
|
|
||||||
#include "core/profiler.h"
|
|
||||||
#include "editor/world_editor.h"
|
|
||||||
#include "engine/engine.h"
|
|
||||||
#include "graphics/material.h"
|
|
||||||
#include "graphics/model.h"
|
|
||||||
#include "graphics/pipeline.h"
|
|
||||||
#include "graphics/renderer.h"
|
|
||||||
#include "graphics/render_scene.h"
|
|
||||||
#include "graphics/shader.h"
|
|
||||||
#include "graphics/texture.h"
|
|
||||||
#include "universe/universe.h"
|
|
||||||
#include "wgl_render_device.h"
|
|
||||||
|
|
||||||
|
|
||||||
class MaterialManagerUI
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Lumix::Engine* m_engine;
|
|
||||||
Lumix::Universe* m_universe;
|
|
||||||
Lumix::RenderScene* m_render_scene;
|
|
||||||
WGLRenderDevice* m_render_device;
|
|
||||||
Lumix::Model* m_selected_object_model;
|
|
||||||
QFileSystemModel* m_fs_model;
|
|
||||||
Lumix::Material* m_material;
|
|
||||||
Lumix::WorldEditor* m_world_editor;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MaterialManager::MaterialManager(QWidget *parent)
|
|
||||||
: QDockWidget(parent)
|
|
||||||
, m_ui(new Ui::MaterialManager)
|
|
||||||
{
|
|
||||||
m_impl = new MaterialManagerUI();
|
|
||||||
m_impl->m_selected_object_model = NULL;
|
|
||||||
m_impl->m_world_editor = NULL;
|
|
||||||
m_ui->setupUi(this);
|
|
||||||
m_impl->m_fs_model = new QFileSystemModel();
|
|
||||||
m_impl->m_fs_model->setRootPath(QDir::currentPath());
|
|
||||||
QStringList filters;
|
|
||||||
filters << "*.mat";
|
|
||||||
m_impl->m_fs_model->setNameFilters(filters);
|
|
||||||
m_impl->m_fs_model->setNameFilterDisables(false);
|
|
||||||
m_ui->fileTreeView->setModel(m_impl->m_fs_model);
|
|
||||||
m_ui->fileTreeView->setRootIndex(m_impl->m_fs_model->index(QDir::currentPath()));
|
|
||||||
m_impl->m_engine = NULL;
|
|
||||||
m_impl->m_universe = NULL;
|
|
||||||
m_impl->m_render_scene = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::updatePreview()
|
|
||||||
{
|
|
||||||
PROFILE_FUNCTION();
|
|
||||||
m_impl->m_render_device->beginFrame();
|
|
||||||
m_impl->m_engine->getRenderer().render(*m_impl->m_render_device);
|
|
||||||
m_impl->m_render_device->endFrame();
|
|
||||||
m_impl->m_render_scene->update(0.01f); TODO("time");
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::fillObjectMaterials()
|
|
||||||
{
|
|
||||||
m_ui->objectMaterialList->clear();
|
|
||||||
if(m_impl->m_selected_object_model)
|
|
||||||
{
|
|
||||||
for(int i = 0; i < m_impl->m_selected_object_model->getMeshCount(); ++i)
|
|
||||||
{
|
|
||||||
const char* path = m_impl->m_selected_object_model->getMesh(i).getMaterial()->getPath().c_str();
|
|
||||||
m_ui->objectMaterialList->addItem(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QWidget* MaterialManager::getPreview() const
|
|
||||||
{
|
|
||||||
return m_ui->previewWidget;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MaterialManager::onEntitySelected(Lumix::Entity& entity)
|
|
||||||
{
|
|
||||||
if (entity.isValid())
|
|
||||||
{
|
|
||||||
Lumix::Component cmp = entity.getComponent(crc32("renderable"));
|
|
||||||
if (cmp.isValid())
|
|
||||||
{
|
|
||||||
m_impl->m_selected_object_model = static_cast<Lumix::RenderScene*>(cmp.system)->getModel(cmp);
|
|
||||||
fillObjectMaterials();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::setWorldEditor(Lumix::WorldEditor& editor)
|
|
||||||
{
|
|
||||||
ASSERT(m_impl->m_engine == NULL);
|
|
||||||
m_impl->m_world_editor = &editor;
|
|
||||||
HWND hwnd = (HWND)m_ui->previewWidget->winId();
|
|
||||||
editor.entitySelected().bind<MaterialManager, &MaterialManager::onEntitySelected>(this);
|
|
||||||
m_impl->m_engine = &editor.getEngine();
|
|
||||||
m_impl->m_universe = new Lumix::Universe();
|
|
||||||
m_impl->m_universe->create();
|
|
||||||
|
|
||||||
m_impl->m_render_scene = Lumix::RenderScene::createInstance(editor.getEngine(), *m_impl->m_universe);
|
|
||||||
m_impl->m_render_device = new WGLRenderDevice(editor.getEngine(), "pipelines/main.json");
|
|
||||||
m_impl->m_render_device->m_hdc = GetDC(hwnd);
|
|
||||||
m_impl->m_render_device->m_opengl_context = wglGetCurrentContext();
|
|
||||||
m_impl->m_render_device->getPipeline().setScene(m_impl->m_render_scene);
|
|
||||||
|
|
||||||
const Lumix::Entity& camera_entity = m_impl->m_universe->createEntity();
|
|
||||||
Lumix::Component cmp = m_impl->m_render_scene->createComponent(crc32("camera"), camera_entity);
|
|
||||||
m_impl->m_render_scene->setCameraSlot(cmp, Lumix::string("editor"));
|
|
||||||
|
|
||||||
Lumix::Entity light_entity = m_impl->m_universe->createEntity();
|
|
||||||
light_entity.setRotation(Lumix::Quat(Lumix::Vec3(0, 1, 0), 3.14159265f));
|
|
||||||
m_impl->m_render_scene->createComponent(crc32("light"), light_entity);
|
|
||||||
|
|
||||||
Lumix::Entity model_entity = m_impl->m_universe->createEntity();
|
|
||||||
model_entity.setPosition(0, 0, -5);
|
|
||||||
Lumix::Component cmp2 = m_impl->m_render_scene->createComponent(crc32("renderable"), model_entity);
|
|
||||||
m_impl->m_render_scene->setRenderablePath(cmp2, Lumix::string("models/editor/material_sphere.msh"));
|
|
||||||
|
|
||||||
m_ui->previewWidget->setAttribute(Qt::WA_NoSystemBackground);
|
|
||||||
m_ui->previewWidget->setAutoFillBackground(false);
|
|
||||||
m_ui->previewWidget->setAttribute(Qt::WA_OpaquePaintEvent);
|
|
||||||
m_ui->previewWidget->setAttribute(Qt::WA_TranslucentBackground);
|
|
||||||
m_ui->previewWidget->setAttribute(Qt::WA_PaintOnScreen);
|
|
||||||
m_ui->previewWidget->m_render_device = m_impl->m_render_device;
|
|
||||||
m_ui->previewWidget->m_engine = m_impl->m_engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialManager::~MaterialManager()
|
|
||||||
{
|
|
||||||
Lumix::RenderScene::destroyInstance(m_impl->m_render_scene);
|
|
||||||
m_impl->m_universe->destroy();
|
|
||||||
delete m_impl->m_render_device;
|
|
||||||
delete m_impl->m_universe;
|
|
||||||
delete m_impl;
|
|
||||||
delete m_ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
class ICppObjectProperty
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
BOOL,
|
|
||||||
SHADER,
|
|
||||||
UNKNOWN
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
Type getType() const { return m_type; }
|
|
||||||
const char* getName() const { return m_name.c_str(); }
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
static Type getType();
|
|
||||||
|
|
||||||
template <> static Type getType<bool>() { return BOOL; }
|
|
||||||
template <> static Type getType<Lumix::Shader*>() { return SHADER; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Type m_type;
|
|
||||||
Lumix::string m_name;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename V, class T>
|
|
||||||
class CppObjectProperty : public ICppObjectProperty
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef V (T::*Getter)() const;
|
|
||||||
typedef void (T::*Setter)(V);
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
CppObjectProperty(const char* name, Getter getter, Setter setter)
|
|
||||||
{
|
|
||||||
m_name = name;
|
|
||||||
m_type = ICppObjectProperty::getType<V>();
|
|
||||||
m_getter = getter;
|
|
||||||
m_setter = setter;
|
|
||||||
}
|
|
||||||
|
|
||||||
V get(const T& t)
|
|
||||||
{
|
|
||||||
return (t.*m_getter)();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set(T& t, const V& v)
|
|
||||||
{
|
|
||||||
(t.*m_setter)(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Getter m_getter;
|
|
||||||
Setter m_setter;
|
|
||||||
};
|
|
||||||
|
|
||||||
void MaterialManager::onBoolPropertyStateChanged(int)
|
|
||||||
{
|
|
||||||
QCheckBox* obj = qobject_cast<QCheckBox*>(QObject::sender());
|
|
||||||
if(obj)
|
|
||||||
{
|
|
||||||
CppObjectProperty<bool, Lumix::Material>* prop = static_cast<CppObjectProperty<bool, Lumix::Material>*>(obj->property("cpp_property").value<void*>());
|
|
||||||
prop->set(*m_impl->m_material, obj->isChecked());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::onTextureChanged()
|
|
||||||
{
|
|
||||||
QLineEdit* edit = qobject_cast<QLineEdit*>(QObject::sender());
|
|
||||||
if(edit)
|
|
||||||
{
|
|
||||||
int i = edit->property("texture_index").toInt();
|
|
||||||
m_impl->m_material->setTexture(i, static_cast<Lumix::Texture*>(m_impl->m_engine->getResourceManager().get(Lumix::ResourceManager::TEXTURE)->load(edit->text().toLatin1().data())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::onShaderChanged()
|
|
||||||
{
|
|
||||||
QLineEdit* edit = static_cast<QLineEdit*>(QObject::sender());
|
|
||||||
m_impl->m_material->setShader(static_cast<Lumix::Shader*>(m_impl->m_engine->getResourceManager().get(Lumix::ResourceManager::SHADER)->load(edit->text().toLatin1().data())));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::onTextureAdded()
|
|
||||||
{
|
|
||||||
m_impl->m_material->addTexture(static_cast<Lumix::Texture*>(m_impl->m_engine->getResourceManager().get(Lumix::ResourceManager::TEXTURE)->load("textures/default.dds")));
|
|
||||||
selectMaterial(m_impl->m_material->getPath().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::selectMaterial(const char* path)
|
|
||||||
{
|
|
||||||
char rel_path[LUMIX_MAX_PATH];
|
|
||||||
m_impl->m_world_editor->getRelativePath(rel_path, LUMIX_MAX_PATH, path);
|
|
||||||
Lumix::Material* material = static_cast<Lumix::Material*>(m_impl->m_engine->getResourceManager().get(Lumix::ResourceManager::MATERIAL)->load(rel_path));
|
|
||||||
material->getObserverCb().bind<MaterialManager, &MaterialManager::onMaterialLoaded>(this);
|
|
||||||
m_impl->m_material = material;
|
|
||||||
if(material->isReady())
|
|
||||||
{
|
|
||||||
onMaterialLoaded(Lumix::Resource::State::READY, Lumix::Resource::State::READY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::onMaterialLoaded(Lumix::Resource::State, Lumix::Resource::State)
|
|
||||||
{
|
|
||||||
ICppObjectProperty* properties[] =
|
|
||||||
{
|
|
||||||
new CppObjectProperty<bool, Lumix::Material>("Z test", &Lumix::Material::isZTest, &Lumix::Material::enableZTest),
|
|
||||||
new CppObjectProperty<bool, Lumix::Material>("Alpha to coverage", &Lumix::Material::isAlphaToCoverage, &Lumix::Material::enableAlphaToCoverage),
|
|
||||||
new CppObjectProperty<bool, Lumix::Material>("Backface culling", &Lumix::Material::isBackfaceCulling, &Lumix::Material::enableBackfaceCulling),
|
|
||||||
new CppObjectProperty<Lumix::Shader*, Lumix::Material>("Shader", &Lumix::Material::getShader, &Lumix::Material::setShader)
|
|
||||||
};
|
|
||||||
|
|
||||||
Lumix::Model* model = static_cast<Lumix::Model*>(m_impl->m_engine->getResourceManager().get(Lumix::ResourceManager::MODEL)->get("models/editor/material_sphere.msh"));
|
|
||||||
Lumix::Material* material = m_impl->m_material;
|
|
||||||
material->getObserverCb().unbind<MaterialManager, &MaterialManager::onMaterialLoaded>(this);
|
|
||||||
model->getMesh(0).setMaterial(material);
|
|
||||||
|
|
||||||
QFormLayout* layout = m_ui->materialPropertiesLayout;
|
|
||||||
QLayoutItem* item;
|
|
||||||
while((item = layout->takeAt(0)) != NULL)
|
|
||||||
{
|
|
||||||
delete item->widget();
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < sizeof(properties) / sizeof(ICppObjectProperty*); ++i)
|
|
||||||
{
|
|
||||||
switch(properties[i]->getType())
|
|
||||||
{
|
|
||||||
case ICppObjectProperty::BOOL:
|
|
||||||
{
|
|
||||||
QCheckBox* checkbox = new QCheckBox();
|
|
||||||
checkbox->setProperty("cpp_property", QVariant::fromValue((void*)properties[i]));
|
|
||||||
checkbox->setChecked(static_cast<CppObjectProperty<bool, Lumix::Material>*>(properties[i])->get(*material));
|
|
||||||
layout->addRow(properties[i]->getName(), checkbox);
|
|
||||||
connect(checkbox, SIGNAL(stateChanged(int)), this, SLOT(onBoolPropertyStateChanged(int)));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ICppObjectProperty::SHADER:
|
|
||||||
{
|
|
||||||
QLineEdit* edit = new QLineEdit();
|
|
||||||
Lumix::Shader* shader = static_cast<CppObjectProperty<Lumix::Shader*, Lumix::Material>*>(properties[i])->get(*material);
|
|
||||||
if(shader)
|
|
||||||
{
|
|
||||||
edit->setText(shader->getPath().c_str());
|
|
||||||
}
|
|
||||||
connect(edit, SIGNAL(editingFinished()), this, SLOT(onShaderChanged()));
|
|
||||||
layout->addRow(properties[i]->getName(), edit);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int i = 0; i < material->getTextureCount(); ++i)
|
|
||||||
{
|
|
||||||
QLineEdit* edit = new QLineEdit;
|
|
||||||
QBoxLayout* inner_layout = new QBoxLayout(QBoxLayout::Direction::LeftToRight);
|
|
||||||
QPushButton* button = new QPushButton();
|
|
||||||
button->setText("Remove");
|
|
||||||
inner_layout->addWidget(edit);
|
|
||||||
inner_layout->addWidget(button);
|
|
||||||
edit->setText(material->getTexture(i)->getPath().c_str());
|
|
||||||
edit->setProperty("texture_index", i);
|
|
||||||
layout->addRow("Texture", inner_layout);
|
|
||||||
connect(edit, SIGNAL(editingFinished()), this, SLOT(onTextureChanged()));
|
|
||||||
connect(button, SIGNAL(clicked()), this, SLOT(onTextureRemoved()));
|
|
||||||
button->setProperty("texture_id", i);
|
|
||||||
}
|
|
||||||
QPushButton* button = new QPushButton();
|
|
||||||
button->setText("Add Texture");
|
|
||||||
connect(button, SIGNAL(clicked()), this, SLOT(onTextureAdded()));
|
|
||||||
layout->addRow("", button);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::onTextureRemoved()
|
|
||||||
{
|
|
||||||
QPushButton* button = static_cast<QPushButton*>(QObject::sender());
|
|
||||||
int i = button->property("texture_id").toInt();
|
|
||||||
m_impl->m_material->removeTexture(i);
|
|
||||||
selectMaterial(m_impl->m_material->getPath().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::on_objectMaterialList_doubleClicked(const QModelIndex &index)
|
|
||||||
{
|
|
||||||
QListWidgetItem* item = m_ui->objectMaterialList->item(index.row());
|
|
||||||
selectMaterial(item->text().toLatin1().data());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::on_saveMaterialButton_clicked()
|
|
||||||
{
|
|
||||||
Lumix::FS::FileSystem& fs = m_impl->m_engine->getFileSystem();
|
|
||||||
// use temporary because otherwise the material is reloaded during saving
|
|
||||||
char tmp_path[LUMIX_MAX_PATH];
|
|
||||||
strcpy(tmp_path, m_impl->m_material->getPath().c_str());
|
|
||||||
strcat(tmp_path, ".tmp");
|
|
||||||
Lumix::FS::IFile* file = fs.open(fs.getDefaultDevice(), tmp_path, Lumix::FS::Mode::CREATE | Lumix::FS::Mode::WRITE);
|
|
||||||
if(file)
|
|
||||||
{
|
|
||||||
Lumix::JsonSerializer serializer(*file, Lumix::JsonSerializer::AccessMode::WRITE, m_impl->m_material->getPath().c_str());
|
|
||||||
m_impl->m_material->save(serializer);
|
|
||||||
fs.close(file);
|
|
||||||
|
|
||||||
QFile::remove(m_impl->m_material->getPath().c_str());
|
|
||||||
QFile::rename(tmp_path, m_impl->m_material->getPath().c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Lumix::g_log_error.log("Material manager") << "Could not save file " << m_impl->m_material->getPath().c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialManager::on_fileTreeView_doubleClicked(const QModelIndex &index)
|
|
||||||
{
|
|
||||||
QString file_path = m_impl->m_fs_model->fileInfo(index).filePath().toLower();
|
|
||||||
selectMaterial(file_path.toLatin1().data());
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QDockWidget>
|
|
||||||
#include "core/resource.h"
|
|
||||||
|
|
||||||
namespace Ui
|
|
||||||
{
|
|
||||||
class MaterialManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Lumix
|
|
||||||
{
|
|
||||||
class WorldEditor;
|
|
||||||
struct Entity;
|
|
||||||
class Event;
|
|
||||||
struct PropertyListEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MaterialManager : public QDockWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MaterialManager(QWidget* parent = NULL);
|
|
||||||
~MaterialManager();
|
|
||||||
void setWorldEditor(Lumix::WorldEditor& server);
|
|
||||||
void updatePreview();
|
|
||||||
QWidget* getPreview() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void fillObjectMaterials();
|
|
||||||
void selectMaterial(const char* path);
|
|
||||||
void onMaterialLoaded(Lumix::Resource::State, Lumix::Resource::State);
|
|
||||||
void onEntitySelected(Lumix::Entity& entity);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_objectMaterialList_doubleClicked(const QModelIndex& index);
|
|
||||||
void on_saveMaterialButton_clicked();
|
|
||||||
void onBoolPropertyStateChanged(int state);
|
|
||||||
void onShaderChanged();
|
|
||||||
void onTextureChanged();
|
|
||||||
void onTextureRemoved();
|
|
||||||
void onTextureAdded();
|
|
||||||
void on_fileTreeView_doubleClicked(const QModelIndex &index);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::MaterialManager* m_ui;
|
|
||||||
class MaterialManagerUI* m_impl;
|
|
||||||
};
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>MaterialManager</class>
|
|
||||||
<widget class="QDockWidget" name="MaterialManager">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>680</width>
|
|
||||||
<height>422</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Material manager</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="dockWidgetContents">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QSplitter" name="splitter">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="tab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Files</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QTreeView" name="fileTreeView"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="tab_2">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Object</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="objectMaterialList"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<widget class="RenderDeviceWidget" name="previewWidget" native="true"/>
|
|
||||||
<widget class="QWidget" name="materialProperties" native="true">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="materialPropertiesLayout"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="saveMaterialButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Save material</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>RenderDeviceWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>renderdevicewidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
128
qteditor/QtEditor/notifications.cpp
Normal file
128
qteditor/QtEditor/notifications.cpp
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
#include "notifications.h"
|
||||||
|
#include "core/log.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include <qlabel.h>
|
||||||
|
|
||||||
|
|
||||||
|
static const float DISPLAY_TIME = 2.0f;
|
||||||
|
static const int NOTIFICATION_WIDTH = 200;
|
||||||
|
static const int WIDGET_SPACING = 5;
|
||||||
|
|
||||||
|
class NotificationsImpl : public Notifications
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NotificationsImpl(MainWindow& main_window)
|
||||||
|
: m_main_window(main_window)
|
||||||
|
{
|
||||||
|
//Lumix::g_log_info.getCallback().bind<NotificationsImpl, &NotificationsImpl::onLogInfo>(this);
|
||||||
|
Lumix::g_log_warning.getCallback().bind<NotificationsImpl, &NotificationsImpl::onLogWarning>(this);
|
||||||
|
Lumix::g_log_error.getCallback().bind<NotificationsImpl, &NotificationsImpl::onLogError>(this);
|
||||||
|
m_main_window.resized().bind<NotificationsImpl, &NotificationsImpl::onMainWindowResized>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~NotificationsImpl()
|
||||||
|
{
|
||||||
|
//Lumix::g_log_info.getCallback().unbind<NotificationsImpl, &NotificationsImpl::onLogInfo>(this);
|
||||||
|
Lumix::g_log_warning.getCallback().unbind<NotificationsImpl, &NotificationsImpl::onLogWarning>(this);
|
||||||
|
Lumix::g_log_error.getCallback().unbind<NotificationsImpl, &NotificationsImpl::onLogError>(this);
|
||||||
|
m_main_window.resized().unbind<NotificationsImpl, &NotificationsImpl::onMainWindowResized>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onMainWindowResized(const QSize&)
|
||||||
|
{
|
||||||
|
updateLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void updateLayout()
|
||||||
|
{
|
||||||
|
int y = m_main_window.height() - WIDGET_SPACING;
|
||||||
|
for (int i = m_items.size() - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
QWidget* widget = m_items[i].m_widget;
|
||||||
|
y -= widget->height() + WIDGET_SPACING;
|
||||||
|
widget->move(m_main_window.width() - NOTIFICATION_WIDTH - WIDGET_SPACING, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onLogInfo(const char*, const char* message)
|
||||||
|
{
|
||||||
|
showNotification(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onLogWarning(const char*, const char* message)
|
||||||
|
{
|
||||||
|
showNotification(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onLogError(const char*, const char* message)
|
||||||
|
{
|
||||||
|
showNotification(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void update(float time_delta) override
|
||||||
|
{
|
||||||
|
if (!m_items.empty())
|
||||||
|
{
|
||||||
|
m_items[0].m_time -= time_delta;
|
||||||
|
if (m_items[0].m_time < 0)
|
||||||
|
{
|
||||||
|
delete m_items[0].m_widget;
|
||||||
|
m_items.erase(0);
|
||||||
|
updateLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void showNotification(const char* text) override
|
||||||
|
{
|
||||||
|
QWidget* widget = new QWidget(&m_main_window);
|
||||||
|
widget->setObjectName("notification");
|
||||||
|
QLabel* label = new QLabel(widget);
|
||||||
|
label->setMinimumWidth(NOTIFICATION_WIDTH);
|
||||||
|
label->setWordWrap(true);
|
||||||
|
label->setContentsMargins(2, 2, 2, 2);
|
||||||
|
label->setText(text);
|
||||||
|
widget->adjustSize();
|
||||||
|
widget->show();
|
||||||
|
widget->raise();
|
||||||
|
|
||||||
|
Notification n;
|
||||||
|
n.m_widget = widget;
|
||||||
|
n.m_time = DISPLAY_TIME;
|
||||||
|
m_items.push(n);
|
||||||
|
|
||||||
|
updateLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Notification
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QWidget* m_widget;
|
||||||
|
float m_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
MainWindow& m_main_window;
|
||||||
|
Lumix::Array<Notification> m_items;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Notifications* Notifications::create(MainWindow& main_window)
|
||||||
|
{
|
||||||
|
return new NotificationsImpl(main_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Notifications::destroy(Notifications* notifications)
|
||||||
|
{
|
||||||
|
delete notifications;
|
||||||
|
}
|
15
qteditor/QtEditor/notifications.h
Normal file
15
qteditor/QtEditor/notifications.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Notifications
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static Notifications* create(class MainWindow& main_window);
|
||||||
|
static void destroy(Notifications* notifications);
|
||||||
|
|
||||||
|
virtual void update(float time_delta) = 0;
|
||||||
|
virtual void showNotification(const char* text) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Notifications() {}
|
||||||
|
virtual ~Notifications() {}
|
||||||
|
};
|
|
@ -20,7 +20,8 @@ ProfileModel::Block::Block()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ProfileModel::ProfileModel()
|
ProfileModel::ProfileModel(QWidget* parent)
|
||||||
|
: QAbstractItemModel(parent)
|
||||||
{
|
{
|
||||||
Lumix::g_profiler.getFrameListeners().bind<ProfileModel, &ProfileModel::onFrame>(this);
|
Lumix::g_profiler.getFrameListeners().bind<ProfileModel, &ProfileModel::onFrame>(this);
|
||||||
m_root = NULL;
|
m_root = NULL;
|
||||||
|
@ -121,6 +122,8 @@ QVariant ProfileModel::headerData(int section, Qt::Orientation, int role) const
|
||||||
return "Name";
|
return "Name";
|
||||||
case Values::LENGTH:
|
case Values::LENGTH:
|
||||||
return "Length (ms)";
|
return "Length (ms)";
|
||||||
|
case Values::LENGTH_EXCLUSIVE:
|
||||||
|
return "Length exclusive (ms)";
|
||||||
case Values::HIT_COUNT:
|
case Values::HIT_COUNT:
|
||||||
return "Hit count";
|
return "Hit count";
|
||||||
break;
|
break;
|
||||||
|
@ -222,6 +225,7 @@ int ProfileModel::columnCount(const QModelIndex&) const
|
||||||
return (int)Values::COUNT;
|
return (int)Values::COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QVariant ProfileModel::data(const QModelIndex& index, int role) const
|
QVariant ProfileModel::data(const QModelIndex& index, int role) const
|
||||||
{
|
{
|
||||||
if (!index.isValid() || !index.internalPointer())
|
if (!index.isValid() || !index.internalPointer())
|
||||||
|
@ -242,6 +246,32 @@ QVariant ProfileModel::data(const QModelIndex& index, int role) const
|
||||||
return block->m_name;
|
return block->m_name;
|
||||||
case Values::LENGTH:
|
case Values::LENGTH:
|
||||||
return m_frame >= 0 && m_frame < block->m_frames.size() ? block->m_frames[m_frame] : (block->m_frames.isEmpty() ? 0 : block->m_frames.back());
|
return m_frame >= 0 && m_frame < block->m_frames.size() ? block->m_frames[m_frame] : (block->m_frames.isEmpty() ? 0 : block->m_frames.back());
|
||||||
|
case Values::LENGTH_EXCLUSIVE:
|
||||||
|
{
|
||||||
|
if (m_frame >= 0 && m_frame < block->m_frames.size())
|
||||||
|
{
|
||||||
|
float length = block->m_frames[m_frame];
|
||||||
|
Block* child = block->m_first_child;
|
||||||
|
while (child)
|
||||||
|
{
|
||||||
|
length -= m_frame < child->m_frames.size() ? child->m_frames[m_frame] : (child->m_frames.isEmpty() ? 0 : child->m_frames.back());
|
||||||
|
child = child->m_next;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float length = block->m_frames.isEmpty() ? 0 : block->m_frames.back();
|
||||||
|
Block* child = block->m_first_child;
|
||||||
|
while (child)
|
||||||
|
{
|
||||||
|
length -= child->m_frames.isEmpty() ? 0 : child->m_frames.back();
|
||||||
|
child = child->m_next;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Values::HIT_COUNT:
|
case Values::HIT_COUNT:
|
||||||
return m_frame >= 0 && m_frame < block->m_hit_counts.size() ? block->m_hit_counts[m_frame] : (block->m_hit_counts.isEmpty() ? 0 : block->m_hit_counts.back());
|
return m_frame >= 0 && m_frame < block->m_hit_counts.size() ? block->m_hit_counts[m_frame] : (block->m_hit_counts.isEmpty() ? 0 : block->m_hit_counts.back());
|
||||||
break;
|
break;
|
||||||
|
@ -256,9 +286,11 @@ ProfilerUI::ProfilerUI(QWidget* parent)
|
||||||
: QDockWidget(parent)
|
: QDockWidget(parent)
|
||||||
, m_ui(new Ui::ProfilerUI)
|
, m_ui(new Ui::ProfilerUI)
|
||||||
{
|
{
|
||||||
m_model = new ProfileModel;
|
m_sortable_model = new QSortFilterProxyModel(this);
|
||||||
|
m_model = new ProfileModel(this);
|
||||||
|
m_sortable_model->setSourceModel(m_model);
|
||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
m_ui->profileTreeView->setModel(m_model);
|
m_ui->profileTreeView->setModel(m_sortable_model);
|
||||||
m_ui->profileTreeView->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch);
|
m_ui->profileTreeView->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch);
|
||||||
m_ui->profileTreeView->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents);
|
m_ui->profileTreeView->header()->setSectionResizeMode(1, QHeaderView::ResizeMode::ResizeToContents);
|
||||||
m_ui->profileTreeView->header()->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents);
|
m_ui->profileTreeView->header()->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents);
|
||||||
|
@ -277,14 +309,14 @@ void ProfilerUI::on_dataChanged()
|
||||||
ProfilerUI::~ProfilerUI()
|
ProfilerUI::~ProfilerUI()
|
||||||
{
|
{
|
||||||
delete m_ui;
|
delete m_ui;
|
||||||
delete m_model;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProfilerUI::on_recordCheckBox_stateChanged(int)
|
void ProfilerUI::on_recordCheckBox_stateChanged(int)
|
||||||
{
|
{
|
||||||
Lumix::g_profiler.toggleRecording();
|
Lumix::g_profiler.toggleRecording();
|
||||||
m_ui->profileTreeView->setModel(NULL);
|
m_ui->profileTreeView->setModel(NULL);
|
||||||
m_ui->profileTreeView->setModel(m_model);
|
m_sortable_model->setSourceModel(m_model);
|
||||||
|
m_ui->profileTreeView->setModel(m_sortable_model);
|
||||||
m_ui->profileTreeView->update();
|
m_ui->profileTreeView->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <qabstractitemmodel.h>
|
#include <QSortFilterProxyModel>
|
||||||
#include "core/profiler.h"
|
#include "core/profiler.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
|
@ -11,6 +12,7 @@ class ProfilerUI;
|
||||||
|
|
||||||
class ProfileModel;
|
class ProfileModel;
|
||||||
|
|
||||||
|
|
||||||
class ProfilerUI : public QDockWidget
|
class ProfilerUI : public QDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -28,8 +30,10 @@ private slots:
|
||||||
private:
|
private:
|
||||||
Ui::ProfilerUI* m_ui;
|
Ui::ProfilerUI* m_ui;
|
||||||
ProfileModel* m_model;
|
ProfileModel* m_model;
|
||||||
|
QSortFilterProxyModel* m_sortable_model;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ProfileModel : public QAbstractItemModel
|
class ProfileModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -38,6 +42,7 @@ class ProfileModel : public QAbstractItemModel
|
||||||
NAME,
|
NAME,
|
||||||
FUNCTION,
|
FUNCTION,
|
||||||
LENGTH,
|
LENGTH,
|
||||||
|
LENGTH_EXCLUSIVE,
|
||||||
HIT_COUNT,
|
HIT_COUNT,
|
||||||
COUNT
|
COUNT
|
||||||
};
|
};
|
||||||
|
@ -56,7 +61,7 @@ class ProfileModel : public QAbstractItemModel
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ProfileModel();
|
ProfileModel(QWidget* parent);
|
||||||
Block* getRoot() { return m_root; }
|
Block* getRoot() { return m_root; }
|
||||||
void setFrame(int frame) { m_frame = frame; }
|
void setFrame(int frame) { m_frame = frame; }
|
||||||
|
|
||||||
|
|
|
@ -76,14 +76,23 @@
|
||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<attribute name="headerVisible">
|
<attribute name="headerVisible">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<attribute name="headerCascadingSectionResizes">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
<attribute name="headerDefaultSectionSize">
|
<attribute name="headerDefaultSectionSize">
|
||||||
<number>200</number>
|
<number>200</number>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<attribute name="headerShowSortIndicator" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</attribute>
|
||||||
<attribute name="headerStretchLastSection">
|
<attribute name="headerStretchLastSection">
|
||||||
<bool>false</bool>
|
<bool>true</bool>
|
||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="ProfilerGraph" name="graphView" native="true"/>
|
<widget class="ProfilerGraph" name="graphView" native="true"/>
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,16 +4,17 @@
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include "core/array.h"
|
#include "core/array.h"
|
||||||
#include "core/string.h"
|
#include "core/string.h"
|
||||||
|
#include "core/resource.h"
|
||||||
#include "universe/entity.h"
|
#include "universe/entity.h"
|
||||||
|
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
struct Component;
|
struct Component;
|
||||||
class WorldEditor;
|
|
||||||
struct Entity;
|
struct Entity;
|
||||||
class Event;
|
class Event;
|
||||||
class Path;
|
class Path;
|
||||||
struct PropertyListEvent;
|
class Resource;
|
||||||
|
class WorldEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
|
@ -21,89 +22,98 @@ namespace Ui
|
||||||
class PropertyView;
|
class PropertyView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AssetBrowser;
|
||||||
class QTreeWidgetItem;
|
class QTreeWidgetItem;
|
||||||
class ScriptCompiler;
|
class ScriptCompiler;
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyViewObject : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
typedef PropertyViewObject* (*Creator)(PropertyViewObject*, Lumix::Resource*);
|
||||||
|
|
||||||
|
public:
|
||||||
|
PropertyViewObject(PropertyViewObject* parent, const char* name)
|
||||||
|
: m_name(name)
|
||||||
|
, m_parent(parent)
|
||||||
|
{ }
|
||||||
|
virtual ~PropertyViewObject();
|
||||||
|
const char* getName() const { return m_name.c_str(); }
|
||||||
|
PropertyViewObject** getMembers() { return m_members.empty() ? NULL : &m_members[0]; }
|
||||||
|
int getMemberCount() const { return m_members.size(); }
|
||||||
|
void addMember(PropertyViewObject* member) { m_members.push(member); }
|
||||||
|
void removeMember(PropertyViewObject* member) { m_members.eraseItem(member); }
|
||||||
|
PropertyViewObject* getParent() const { return m_parent; }
|
||||||
|
|
||||||
|
virtual void createEditor(class PropertyView& view, QTreeWidgetItem* item) = 0;
|
||||||
|
virtual bool isEditable() const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Lumix::string m_name;
|
||||||
|
Lumix::Array<PropertyViewObject*> m_members;
|
||||||
|
PropertyViewObject* m_parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class PropertyView : public QDockWidget
|
class PropertyView : public QDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
|
||||||
class Property
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
FILE,
|
|
||||||
STRING,
|
|
||||||
DECIMAL,
|
|
||||||
VEC3,
|
|
||||||
BOOL
|
|
||||||
};
|
|
||||||
|
|
||||||
Type m_type;
|
|
||||||
uint32_t m_component;
|
|
||||||
Lumix::string m_name;
|
|
||||||
Lumix::string m_file_type;
|
|
||||||
Lumix::string m_component_name;
|
|
||||||
uint32_t m_name_hash;
|
|
||||||
QTreeWidgetItem* m_tree_item;
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PropertyView(QWidget* parent = NULL);
|
explicit PropertyView(QWidget* parent = NULL);
|
||||||
~PropertyView();
|
~PropertyView();
|
||||||
void setWorldEditor(Lumix::WorldEditor& server);
|
void setWorldEditor(Lumix::WorldEditor& editor);
|
||||||
|
Lumix::WorldEditor* getWorldEditor();
|
||||||
void setScriptCompiler(ScriptCompiler* compiler);
|
void setScriptCompiler(ScriptCompiler* compiler);
|
||||||
|
void setAssetBrowser(AssetBrowser& asset_browser);
|
||||||
|
void addResourcePlugin(PropertyViewObject::Creator plugin);
|
||||||
|
Lumix::Resource* getSelectedResource() const { return m_selected_resource; }
|
||||||
|
void setSelectedResourceFilename(const char* filename);
|
||||||
|
void setSelectedResource(Lumix::Resource* resource);
|
||||||
|
void setObject(PropertyViewObject* object);
|
||||||
|
PropertyViewObject* getObject();
|
||||||
|
void addTerrainCustomProperties(QTreeWidgetItem& item, const Lumix::Component& terrain_component);
|
||||||
|
void refresh();
|
||||||
|
void setEntityTemplateList(class EntityTemplateList* list) { m_entity_template_list = list; }
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_addComponentButton_clicked();
|
void on_addComponentButton_clicked();
|
||||||
void on_checkboxStateChanged();
|
|
||||||
void on_doubleSpinBoxValueChanged();
|
|
||||||
void on_vec3ValueChanged();
|
|
||||||
void on_lineEditEditingFinished();
|
|
||||||
void on_browseFilesClicked();
|
|
||||||
void on_compileScriptClicked();
|
void on_compileScriptClicked();
|
||||||
void on_editScriptClicked();
|
void on_editScriptClicked();
|
||||||
void on_animablePlayPause();
|
|
||||||
void on_animableTimeSet(int value);
|
|
||||||
void on_terrainBrushSizeChanged(int value);
|
|
||||||
void on_terrainBrushStrengthChanged(int value);
|
|
||||||
void on_TerrainHeightTypeClicked();
|
|
||||||
void on_TerrainTextureTypeClicked();
|
void on_TerrainTextureTypeClicked();
|
||||||
void on_terrainBrushTextureChanged(int value);
|
void on_terrainBrushTextureChanged(int value);
|
||||||
void on_TerrainHeightSaveClicked();
|
void on_positionX_valueChanged(double arg1);
|
||||||
void on_TerrainSplatSaveClicked();
|
void on_positionY_valueChanged(double arg1);
|
||||||
void on_positionX_valueChanged(double arg1);
|
void on_positionZ_valueChanged(double arg1);
|
||||||
void on_positionY_valueChanged(double arg1);
|
void on_propertyList_customContextMenuRequested(const QPoint &pos);
|
||||||
void on_positionZ_valueChanged(double arg1);
|
void on_nameEdit_editingFinished();
|
||||||
|
|
||||||
void on_propertyList_customContextMenuRequested(const QPoint &pos);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void createObjectEditor(QTreeWidgetItem* item, PropertyViewObject* object);
|
||||||
void clear();
|
void clear();
|
||||||
void onUniverseCreated();
|
void onUniverseCreated();
|
||||||
void onUniverseDestroyed();
|
void onUniverseDestroyed();
|
||||||
void onEntitySelected(Lumix::Entity& e);
|
void onEntitySelected(const Lumix::Array<Lumix::Entity>& e);
|
||||||
void onEntityPosition(Lumix::Entity& e);
|
void onEntityPosition(const Lumix::Entity& e);
|
||||||
void addProperty(const char* component, const char* name, const char* label, Property::Type type, const char* file_type);
|
|
||||||
void onPropertyValue(Property* property, const void* data, int32_t data_size);
|
|
||||||
void addScriptCustomProperties();
|
void addScriptCustomProperties();
|
||||||
void addAnimableCustomProperties(const Lumix::Component& cmp);
|
|
||||||
void addTerrainCustomProperties(const Lumix::Component& terrain_component);
|
|
||||||
void onScriptCompiled(const Lumix::Path& path, uint32_t status);
|
void onScriptCompiled(const Lumix::Path& path, uint32_t status);
|
||||||
void setScriptStatus(uint32_t status);
|
void setScriptStatus(uint32_t status);
|
||||||
void updateValues();
|
|
||||||
void updateSelectedEntityPosition();
|
void updateSelectedEntityPosition();
|
||||||
|
void onSelectedResourceLoaded(Lumix::Resource::State old_state, Lumix::Resource::State new_state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::PropertyView* m_ui;
|
Ui::PropertyView* m_ui;
|
||||||
Lumix::Array<Property*> m_properties;
|
|
||||||
ScriptCompiler* m_compiler;
|
ScriptCompiler* m_compiler;
|
||||||
Lumix::Entity m_selected_entity;
|
Lumix::Entity m_selected_entity;
|
||||||
Lumix::WorldEditor* m_world_editor;
|
Lumix::WorldEditor* m_world_editor;
|
||||||
bool m_is_updating_values;
|
bool m_is_updating_values;
|
||||||
class TerrainEditor* m_terrain_editor;
|
class TerrainEditor* m_terrain_editor;
|
||||||
|
AssetBrowser* m_asset_browser;
|
||||||
|
Lumix::Resource* m_selected_resource;
|
||||||
|
Lumix::Array<PropertyViewObject::Creator> m_resource_plugins;
|
||||||
|
PropertyViewObject* m_object;
|
||||||
|
class EntityTemplateList* m_entity_template_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,29 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>380</width>
|
<width>356</width>
|
||||||
<height>446</height>
|
<height>446</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Properties</string>
|
<string>Properties</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="dockWidgetContents">
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Ignored" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>9</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
|
@ -32,50 +44,126 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="widget_2" native="true">
|
<widget class="QWidget" name="widget_2" native="true">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<property name="sizePolicy">
|
||||||
<item>
|
<sizepolicy hsizetype="Ignored" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||||
|
</property>
|
||||||
|
<property name="horizontalSpacing">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="verticalSpacing">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Position</string>
|
<string>Position</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="0" column="1">
|
||||||
<widget class="QDoubleSpinBox" name="positionX">
|
<widget class="QWidget" name="widget_4" native="true">
|
||||||
<property name="decimals">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<number>4</number>
|
<property name="spacing">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="minimum">
|
</property>
|
||||||
<double>-999999.000000000000000</double>
|
<property name="leftMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
<property name="maximum">
|
</property>
|
||||||
<double>999999.000000000000000</double>
|
<property name="topMargin">
|
||||||
</property>
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="positionX">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>-999999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>999999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="positionY">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>-999999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>999999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDoubleSpinBox" name="positionZ">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="decimals">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<double>-999999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<double>999999.000000000000000</double>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="1" column="1">
|
||||||
<widget class="QDoubleSpinBox" name="positionY">
|
<widget class="QLineEdit" name="nameEdit"/>
|
||||||
<property name="decimals">
|
|
||||||
<number>4</number>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>-999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="1" column="0">
|
||||||
<widget class="QDoubleSpinBox" name="positionZ">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="decimals">
|
<property name="text">
|
||||||
<number>4</number>
|
<string>Name</string>
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<double>-999999.000000000000000</double>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<double>999999.000000000000000</double>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -84,6 +172,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTreeWidget" name="propertyList">
|
<widget class="QTreeWidget" name="propertyList">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Ignored" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>1</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
<enum>Qt::CustomContextMenu</enum>
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -104,6 +198,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="widget" native="true">
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Ignored" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
#include "sceneview.h"
|
#include "sceneview.h"
|
||||||
#include "editor/world_editor.h"
|
#include "editor/world_editor.h"
|
||||||
|
#include "core/crc32.h"
|
||||||
|
#include "editor/ieditor_command.h"
|
||||||
|
#include "engine/engine.h"
|
||||||
|
#include "engine/iplugin.h"
|
||||||
|
#include "graphics/pipeline.h"
|
||||||
|
#include "graphics/render_scene.h"
|
||||||
|
#include "insert_mesh_command.h"
|
||||||
#include <qapplication.h>
|
#include <qapplication.h>
|
||||||
#include <QDoubleSpinBox>
|
#include <QDoubleSpinBox>
|
||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include "core/crc32.h"
|
|
||||||
#include "graphics/pipeline.h"
|
|
||||||
|
|
||||||
class ViewWidget : public QWidget
|
class ViewWidget : public QWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ViewWidget(QWidget* parent)
|
ViewWidget(SceneView& view, QWidget* parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
, m_view(view)
|
||||||
{
|
{
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +33,16 @@ class ViewWidget : public QWidget
|
||||||
setFocus();
|
setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void wheelEvent(QWheelEvent* event) override
|
||||||
|
{
|
||||||
|
float speed = m_view.getNavivationSpeed();
|
||||||
|
if (QApplication::keyboardModifiers() & Qt::ShiftModifier)
|
||||||
|
{
|
||||||
|
speed *= 10;
|
||||||
|
}
|
||||||
|
m_world_editor->navigate(event->delta() * 0.1f, 0, speed);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void mouseMoveEvent(QMouseEvent* event) override
|
virtual void mouseMoveEvent(QMouseEvent* event) override
|
||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
@ -44,6 +61,7 @@ class ViewWidget : public QWidget
|
||||||
Lumix::WorldEditor* m_world_editor;
|
Lumix::WorldEditor* m_world_editor;
|
||||||
int m_last_x;
|
int m_last_x;
|
||||||
int m_last_y;
|
int m_last_y;
|
||||||
|
SceneView& m_view;
|
||||||
};
|
};
|
||||||
|
|
||||||
SceneView::SceneView(QWidget* parent) :
|
SceneView::SceneView(QWidget* parent) :
|
||||||
|
@ -53,7 +71,7 @@ SceneView::SceneView(QWidget* parent) :
|
||||||
QWidget* root = new QWidget();
|
QWidget* root = new QWidget();
|
||||||
QVBoxLayout* vertical_layout = new QVBoxLayout(root);
|
QVBoxLayout* vertical_layout = new QVBoxLayout(root);
|
||||||
QHBoxLayout* horizontal_layout = new QHBoxLayout(root);
|
QHBoxLayout* horizontal_layout = new QHBoxLayout(root);
|
||||||
m_view = new ViewWidget(root);
|
m_view = new ViewWidget(*this, root);
|
||||||
m_speed_input = new QDoubleSpinBox(root);
|
m_speed_input = new QDoubleSpinBox(root);
|
||||||
m_speed_input->setSingleStep(0.1f);
|
m_speed_input->setSingleStep(0.1f);
|
||||||
m_speed_input->setValue(0.1f);
|
m_speed_input->setValue(0.1f);
|
||||||
|
@ -98,12 +116,24 @@ void SceneView::dropEvent(QDropEvent *event)
|
||||||
QString file = list[0].toLocalFile();
|
QString file = list[0].toLocalFile();
|
||||||
if(file.endsWith(".msh"))
|
if(file.endsWith(".msh"))
|
||||||
{
|
{
|
||||||
m_world_editor->addEntityAt(event->pos().x(), event->pos().y());
|
Lumix::Vec3 position;
|
||||||
m_world_editor->addComponent(crc32("renderable"));
|
Lumix::RenderScene* scene = static_cast<Lumix::RenderScene*>(m_world_editor->getEditCamera().scene);
|
||||||
char rel_path[LUMIX_MAX_PATH];
|
|
||||||
m_world_editor->getRelativePath(rel_path, LUMIX_MAX_PATH, file.toLatin1().data());
|
Lumix::Vec3 origin;
|
||||||
m_world_editor->setProperty("renderable", "source", rel_path, strlen(rel_path));
|
Lumix::Vec3 dir;
|
||||||
m_world_editor->selectEntity(m_world_editor->getSelectedEntity());
|
scene->getRay(m_world_editor->getEditCamera(), event->pos().x(), event->pos().y(), origin, dir);
|
||||||
|
Lumix::RayCastModelHit hit = scene->castRay(origin, dir, Lumix::Component::INVALID);
|
||||||
|
if (hit.m_is_hit)
|
||||||
|
{
|
||||||
|
position = hit.m_origin + hit.m_dir * hit.m_t;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
position.set(0, 0, 0);
|
||||||
|
}
|
||||||
|
InsertMeshCommand* command = new InsertMeshCommand(*static_cast<ViewWidget&>(*m_view).m_world_editor, position, file.toLatin1().data());
|
||||||
|
m_world_editor->executeCommand(command);
|
||||||
|
m_world_editor->selectEntities(&command->getEntity(), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ class SceneView : public QDockWidget
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit SceneView(QWidget* parent = NULL);
|
explicit SceneView(QWidget* parent = NULL);
|
||||||
void setWorldEditor(Lumix::WorldEditor* server);
|
void setWorldEditor(Lumix::WorldEditor* editor);
|
||||||
void setPipeline(Lumix::PipelineInstance& pipeline) { m_pipeline = &pipeline; }
|
void setPipeline(Lumix::PipelineInstance& pipeline) { m_pipeline = &pipeline; }
|
||||||
QWidget* getViewWidget() { return m_view; }
|
QWidget* getViewWidget() { return m_view; }
|
||||||
float getNavivationSpeed() const;
|
float getNavivationSpeed() const;
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct Quat;
|
||||||
struct Vec3;
|
struct Vec3;
|
||||||
|
|
||||||
|
|
||||||
class LUMIX_ENGINE_API AnimationManager : public ResourceManagerBase
|
class LUMIX_ANIMATION_API AnimationManager : public ResourceManagerBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AnimationManager() : ResourceManagerBase() {}
|
AnimationManager() : ResourceManagerBase() {}
|
||||||
|
@ -30,7 +30,7 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Animation : public Resource
|
class LUMIX_ANIMATION_API Animation : public Resource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Animation(const Path& path, ResourceManager& resource_manager);
|
Animation(const Path& path, ResourceManager& resource_manager);
|
||||||
|
|
|
@ -8,16 +8,23 @@
|
||||||
#include "graphics/renderer.h"
|
#include "graphics/renderer.h"
|
||||||
#include "universe/universe.h"
|
#include "universe/universe.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
|
|
||||||
|
extern "C" IPlugin* createPlugin()
|
||||||
|
{
|
||||||
|
return AnimationSystem::createInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static const uint32_t RENDERABLE_HASH = crc32("renderable");
|
static const uint32_t RENDERABLE_HASH = crc32("renderable");
|
||||||
static const uint32_t ANIMABLE_HASH = crc32("animable");
|
static const uint32_t ANIMABLE_HASH = crc32("animable");
|
||||||
|
|
||||||
|
|
||||||
struct AnimationSystemImpl : public AnimationSystem
|
class AnimationSceneImpl : public AnimationScene
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
struct Animable
|
struct Animable
|
||||||
{
|
{
|
||||||
bool m_manual;
|
bool m_manual;
|
||||||
|
@ -27,28 +34,25 @@ namespace Lumix
|
||||||
class Animation* m_animation;
|
class Animation* m_animation;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
AnimationSceneImpl(AnimationSystem& anim_system, Engine& engine, Universe& universe)
|
||||||
void onCreateUniverse(Universe& universe)
|
: m_universe(universe)
|
||||||
|
, m_engine(engine)
|
||||||
|
, m_anim_system(anim_system)
|
||||||
{
|
{
|
||||||
ASSERT(!m_universe);
|
m_universe.componentCreated().bind<AnimationSceneImpl, &AnimationSceneImpl::onComponentCreated>(this);
|
||||||
m_universe = &universe;
|
|
||||||
m_universe->componentCreated().bind<AnimationSystemImpl, &AnimationSystemImpl::onComponentCreated>(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onDestroyUniverse(Universe&)
|
~AnimationSceneImpl()
|
||||||
{
|
{
|
||||||
ASSERT(m_universe);
|
m_universe.componentCreated().unbind<AnimationSceneImpl, &AnimationSceneImpl::onComponentCreated>(this);
|
||||||
m_animables.clear();
|
|
||||||
m_universe->componentCreated().unbind<AnimationSystemImpl, &AnimationSystemImpl::onComponentCreated>(this);
|
|
||||||
m_universe = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual Component createComponent(uint32_t component_type, const Entity& entity) override
|
virtual Component createComponent(uint32_t type, const Entity& entity) override
|
||||||
{
|
{
|
||||||
if (component_type == ANIMABLE_HASH)
|
if (type == ANIMABLE_HASH)
|
||||||
{
|
{
|
||||||
return createAnimable(entity);
|
return createAnimable(entity);
|
||||||
}
|
}
|
||||||
|
@ -56,12 +60,11 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void destroyComponent(const Component& component) override
|
virtual void destroyComponent(const Component& component)
|
||||||
{
|
{
|
||||||
m_animables[component.index].m_is_free = true;
|
m_animables[component.index].m_is_free = true;
|
||||||
m_universe->removeComponent(component);
|
m_universe.destroyComponent(component);
|
||||||
m_universe->componentDestroyed().invoke(component);
|
m_universe.componentDestroyed().invoke(component);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,7 +94,7 @@ namespace Lumix
|
||||||
serializer.deserializeArrayItem(m_animables[i].m_manual);
|
serializer.deserializeArrayItem(m_animables[i].m_manual);
|
||||||
int entity_index;
|
int entity_index;
|
||||||
serializer.deserializeArrayItem(entity_index);
|
serializer.deserializeArrayItem(entity_index);
|
||||||
Entity e(m_universe, entity_index);
|
Entity e(&m_universe, entity_index);
|
||||||
const Entity::ComponentList& cmps = e.getComponents();
|
const Entity::ComponentList& cmps = e.getComponents();
|
||||||
m_animables[i].m_renderable = Component::INVALID;
|
m_animables[i].m_renderable = Component::INVALID;
|
||||||
for (int j = 0; j < cmps.size(); ++j)
|
for (int j = 0; j < cmps.size(); ++j)
|
||||||
|
@ -104,70 +107,12 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayItem(m_animables[i].m_time);
|
serializer.deserializeArrayItem(m_animables[i].m_time);
|
||||||
serializer.deserializeArrayItem(m_animables[i].m_is_free);
|
serializer.deserializeArrayItem(m_animables[i].m_is_free);
|
||||||
m_universe->addComponent(e, ANIMABLE_HASH, this, i);
|
m_universe.addComponent(e, ANIMABLE_HASH, this, i);
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onComponentCreated(Component& cmp)
|
|
||||||
{
|
|
||||||
if (cmp.type == RENDERABLE_HASH)
|
|
||||||
{
|
|
||||||
const Entity::ComponentList& cmps = cmp.entity.getComponents();
|
|
||||||
for (int i = 0; i < cmps.size(); ++i)
|
|
||||||
{
|
|
||||||
if (cmps[i].type == ANIMABLE_HASH)
|
|
||||||
{
|
|
||||||
m_animables[cmps[i].index].m_renderable = cmp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Component createAnimable(const Entity& entity)
|
|
||||||
{
|
|
||||||
Animable* src = NULL;
|
|
||||||
for (int i = 0, c = m_animables.size(); i < c; ++i)
|
|
||||||
{
|
|
||||||
if (m_animables[i].m_is_free)
|
|
||||||
{
|
|
||||||
src = &m_animables[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Animable& animable = src ? *src : m_animables.pushEmpty();
|
|
||||||
animable.m_manual = true;
|
|
||||||
animable.m_time = 0;
|
|
||||||
animable.m_is_free = false;
|
|
||||||
animable.m_renderable = Component::INVALID;
|
|
||||||
animable.m_animation = NULL;
|
|
||||||
|
|
||||||
const Entity::ComponentList& cmps = entity.getComponents();
|
|
||||||
for (int i = 0; i < cmps.size(); ++i)
|
|
||||||
{
|
|
||||||
if (cmps[i].type == RENDERABLE_HASH)
|
|
||||||
{
|
|
||||||
animable.m_renderable = cmps[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component cmp = m_universe->addComponent(entity, ANIMABLE_HASH, this, m_animables.size() - 1);
|
|
||||||
m_universe->componentCreated().invoke(cmp);
|
|
||||||
return cmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Animation* loadAnimation(const char* path)
|
|
||||||
{
|
|
||||||
ResourceManager& rm = m_engine->getResourceManager();
|
|
||||||
return static_cast<Animation*>(rm.get(ResourceManager::ANIMATION)->load(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void setFrame(Component cmp, int frame) override
|
virtual void setFrame(Component cmp, int frame) override
|
||||||
{
|
{
|
||||||
m_animables[cmp.index].m_time = m_animables[cmp.index].m_animation->getLength() * frame / 30.0f; /// TODO get rid of the constant
|
m_animables[cmp.index].m_time = m_animables[cmp.index].m_animation->getLength() * frame / 30.0f; /// TODO get rid of the constant
|
||||||
|
@ -224,16 +169,17 @@ namespace Lumix
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void update(float time_delta) override
|
virtual void update(float time_delta) override
|
||||||
{
|
{
|
||||||
if (m_animables.empty())
|
if (m_animables.empty())
|
||||||
return;
|
return;
|
||||||
for (int i = 0, c = m_animables.size(); i < c; ++i)
|
for (int i = 0, c = m_animables.size(); i < c; ++i)
|
||||||
{
|
{
|
||||||
AnimationSystemImpl::Animable& animable = m_animables[i];
|
Animable& animable = m_animables[i];
|
||||||
if (!animable.m_is_free && animable.m_animation && animable.m_animation->isReady())
|
if (!animable.m_is_free && animable.m_animation && animable.m_animation->isReady())
|
||||||
{
|
{
|
||||||
RenderScene* scene = static_cast<RenderScene*>(animable.m_renderable.system);
|
RenderScene* scene = static_cast<RenderScene*>(animable.m_renderable.scene);
|
||||||
animable.m_animation->getPose(animable.m_time, scene->getPose(animable.m_renderable), *scene->getModel(animable.m_renderable));
|
animable.m_animation->getPose(animable.m_time, scene->getPose(animable.m_renderable), *scene->getModel(animable.m_renderable));
|
||||||
if (!animable.m_manual)
|
if (!animable.m_manual)
|
||||||
{
|
{
|
||||||
|
@ -250,6 +196,89 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Animation* loadAnimation(const char* path)
|
||||||
|
{
|
||||||
|
ResourceManager& rm = m_engine.getResourceManager();
|
||||||
|
return static_cast<Animation*>(rm.get(ResourceManager::ANIMATION)->load(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onComponentCreated(const Component& cmp)
|
||||||
|
{
|
||||||
|
if (cmp.type == RENDERABLE_HASH)
|
||||||
|
{
|
||||||
|
const Entity::ComponentList& cmps = cmp.entity.getComponents();
|
||||||
|
for (int i = 0; i < cmps.size(); ++i)
|
||||||
|
{
|
||||||
|
if (cmps[i].type == ANIMABLE_HASH)
|
||||||
|
{
|
||||||
|
m_animables[cmps[i].index].m_renderable = cmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Component createAnimable(const Entity& entity)
|
||||||
|
{
|
||||||
|
Animable* src = NULL;
|
||||||
|
for (int i = 0, c = m_animables.size(); i < c; ++i)
|
||||||
|
{
|
||||||
|
if (m_animables[i].m_is_free)
|
||||||
|
{
|
||||||
|
src = &m_animables[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Animable& animable = src ? *src : m_animables.pushEmpty();
|
||||||
|
animable.m_manual = true;
|
||||||
|
animable.m_time = 0;
|
||||||
|
animable.m_is_free = false;
|
||||||
|
animable.m_renderable = Component::INVALID;
|
||||||
|
animable.m_animation = NULL;
|
||||||
|
|
||||||
|
const Entity::ComponentList& cmps = entity.getComponents();
|
||||||
|
for (int i = 0; i < cmps.size(); ++i)
|
||||||
|
{
|
||||||
|
if (cmps[i].type == RENDERABLE_HASH)
|
||||||
|
{
|
||||||
|
animable.m_renderable = cmps[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component cmp = m_universe.addComponent(entity, ANIMABLE_HASH, this, m_animables.size() - 1);
|
||||||
|
m_universe.componentCreated().invoke(cmp);
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual IPlugin& getPlugin() const override
|
||||||
|
{
|
||||||
|
return m_anim_system;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Universe& m_universe;
|
||||||
|
AnimationSystem& m_anim_system;
|
||||||
|
Engine& m_engine;
|
||||||
|
Array<Animable> m_animables;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct AnimationSystemImpl : public AnimationSystem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual IScene* createScene(Universe& universe) override
|
||||||
|
{
|
||||||
|
ASSERT(m_engine);
|
||||||
|
return LUMIX_NEW(AnimationSceneImpl)(*this, *m_engine, universe);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual const char* getName() const override
|
virtual const char* getName() const override
|
||||||
{
|
{
|
||||||
return "animation";
|
return "animation";
|
||||||
|
@ -259,23 +288,19 @@ namespace Lumix
|
||||||
virtual bool create(Engine& engine) override
|
virtual bool create(Engine& engine) override
|
||||||
{
|
{
|
||||||
m_engine = &engine;
|
m_engine = &engine;
|
||||||
m_universe = 0;
|
engine.getWorldEditor()->registerProperty("animable", LUMIX_NEW(FilePropertyDescriptor<AnimationSceneImpl>)("preview", &AnimationSceneImpl::getPreview, &AnimationSceneImpl::setPreview, "Animation (*.ani)"));
|
||||||
if (engine.getWorldEditor())
|
m_animation_manager.create(ResourceManager::ANIMATION, engine.getResourceManager());
|
||||||
{
|
|
||||||
engine.getWorldEditor()->registerCreator(ANIMABLE_HASH, *this);
|
|
||||||
}
|
|
||||||
engine.getWorldEditor()->registerProperty("animable", LUMIX_NEW(PropertyDescriptor<AnimationSystem>)(crc32("preview"), &AnimationSystem::getPreview, &AnimationSystem::setPreview, IPropertyDescriptor::FILE));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void destroy() override
|
virtual void destroy() override
|
||||||
{
|
{
|
||||||
|
m_engine->getResourceManager().get(ResourceManager::ANIMATION)->releaseAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
Array<Animable> m_animables;
|
|
||||||
Universe* m_universe;
|
|
||||||
Engine* m_engine;
|
Engine* m_engine;
|
||||||
|
AnimationManager m_animation_manager;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void operator=(const AnimationSystemImpl&);
|
void operator=(const AnimationSystemImpl&);
|
||||||
|
|
|
@ -19,11 +19,9 @@ namespace Lumix
|
||||||
class ISerializer;
|
class ISerializer;
|
||||||
class Universe;
|
class Universe;
|
||||||
|
|
||||||
class LUMIX_ENGINE_API AnimationSystem : public IPlugin
|
class LUMIX_ANIMATION_API AnimationScene : public IScene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static AnimationSystem* createInstance();
|
|
||||||
|
|
||||||
virtual void setFrame(Component cmp, int frame) = 0;
|
virtual void setFrame(Component cmp, int frame) = 0;
|
||||||
virtual bool isManual(Component cmp) = 0;
|
virtual bool isManual(Component cmp) = 0;
|
||||||
virtual void setManual(Component cmp, bool is_manual) = 0;
|
virtual void setManual(Component cmp, bool is_manual) = 0;
|
||||||
|
@ -33,7 +31,20 @@ namespace Lumix
|
||||||
virtual void playAnimation(const Component& cmp, const char* path) = 0;
|
virtual void playAnimation(const Component& cmp, const char* path) = 0;
|
||||||
virtual void setAnimationFrame(const Component& cmp, int frame) = 0;
|
virtual void setAnimationFrame(const Component& cmp, int frame) = 0;
|
||||||
virtual int getFrameCount(const Component& cmp) const = 0;
|
virtual int getFrameCount(const Component& cmp) const = 0;
|
||||||
|
virtual void update(float time_delta) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LUMIX_ANIMATION_API AnimationSystem : public IPlugin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static AnimationSystem* createInstance();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
LUMIX_ANIMATION_API IPlugin* createPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
}// ~ namespace Lumix
|
}// ~ namespace Lumix
|
||||||
|
|
|
@ -86,6 +86,18 @@ class Array<T, Allocator, false>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void eraseItem(const T& item)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_size; ++i)
|
||||||
|
{
|
||||||
|
if (m_data[i] == item)
|
||||||
|
{
|
||||||
|
erase(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void erase(int index)
|
void erase(int index)
|
||||||
{
|
{
|
||||||
if(index >= 0 && index < m_size)
|
if(index >= 0 && index < m_size)
|
||||||
|
@ -293,6 +305,26 @@ public:
|
||||||
m_allocator.deallocate(m_data);
|
m_allocator.deallocate(m_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void swap(Array<T, Allocator, true>& rhs)
|
||||||
|
{
|
||||||
|
int i = rhs.m_capacity;
|
||||||
|
rhs.m_capacity = m_capacity;
|
||||||
|
m_capacity = i;
|
||||||
|
|
||||||
|
i = m_size;
|
||||||
|
m_size = rhs.m_size;
|
||||||
|
rhs.m_size = i;
|
||||||
|
|
||||||
|
T* p = rhs.m_data;
|
||||||
|
rhs.m_data = m_data;
|
||||||
|
m_data = p;
|
||||||
|
|
||||||
|
Allocator a = rhs.m_allocator;
|
||||||
|
rhs.m_allocator = m_allocator;
|
||||||
|
m_allocator = a;
|
||||||
|
}
|
||||||
|
|
||||||
void eraseFast(int index)
|
void eraseFast(int index)
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < m_size)
|
if (index >= 0 && index < m_size)
|
||||||
|
@ -326,6 +358,32 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void eraseItem(const T& item)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_size; ++i)
|
||||||
|
{
|
||||||
|
if (m_data[i] == item)
|
||||||
|
{
|
||||||
|
erase(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void insert(int index, const T& value)
|
||||||
|
{
|
||||||
|
if (m_size == m_capacity)
|
||||||
|
{
|
||||||
|
grow();
|
||||||
|
}
|
||||||
|
memmove(m_data + index + 1, m_data + index, m_size - index);
|
||||||
|
m_data[index] = value;
|
||||||
|
++m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void push(const T& value)
|
void push(const T& value)
|
||||||
{
|
{
|
||||||
if (m_size == m_capacity)
|
if (m_size == m_capacity)
|
||||||
|
|
|
@ -482,7 +482,10 @@ namespace Lumix
|
||||||
node_type* next = n->m_next;
|
node_type* next = n->m_next;
|
||||||
destruct(n);
|
destruct(n);
|
||||||
construct(n, next ? *next : m_sentinel);
|
construct(n, next ? *next : m_sentinel);
|
||||||
destruct(next);
|
if (next)
|
||||||
|
{
|
||||||
|
destruct(next);
|
||||||
|
}
|
||||||
m_allocator.deallocate(next);
|
m_allocator.deallocate(next);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -282,7 +282,7 @@ void JsonSerializer::deserializeRawString(char* buffer, int max_length)
|
||||||
{
|
{
|
||||||
strncpy(buffer, m_token, max_length);
|
strncpy(buffer, m_token, max_length);
|
||||||
size_t token_length = strlen(m_token);
|
size_t token_length = strlen(m_token);
|
||||||
if (token_length + 2 <= max_length)
|
if (token_length + 2 <= (size_t)max_length)
|
||||||
{
|
{
|
||||||
buffer[token_length] = '\n';
|
buffer[token_length] = '\n';
|
||||||
buffer[token_length + 1] = m_buffer;
|
buffer[token_length + 1] = m_buffer;
|
||||||
|
|
|
@ -29,54 +29,60 @@
|
||||||
const uint32_t LUMIX_MAX_PATH = 260;
|
const uint32_t LUMIX_MAX_PATH = 260;
|
||||||
|
|
||||||
#ifndef ASSERT
|
#ifndef ASSERT
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
#define ASSERT(x) { false ? (void)(x) : 0; }
|
#define ASSERT(x) { false ? (void)(x) : 0; }
|
||||||
#else
|
#else
|
||||||
#define ASSERT(x) { const volatile bool lumix_assert_b____ = !(x); if(lumix_assert_b____) __debugbreak(); }
|
#define ASSERT(x) { const volatile bool lumix_assert_b____ = !(x); if(lumix_assert_b____) __debugbreak(); }
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define ASSERT(x) assert(x)
|
#define ASSERT(x) assert(x)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NULL
|
#ifndef NULL
|
||||||
#define NULL nullptr
|
#define NULL nullptr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LUMIX_FORCE_INLINE __forceinline
|
#define LUMIX_FORCE_INLINE __forceinline
|
||||||
|
|
||||||
#ifdef BUILDING_CORE
|
#ifdef BUILDING_CORE
|
||||||
#define LUMIX_CORE_API __declspec(dllexport)
|
#define LUMIX_CORE_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define LUMIX_CORE_API __declspec(dllimport)
|
#define LUMIX_CORE_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef BUILDING_PHYSICS
|
#ifdef BUILDING_PHYSICS
|
||||||
#define LUMIX_PHYSICS_API __declspec(dllexport)
|
#define LUMIX_PHYSICS_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define LUMIX_PHYSICS_API __declspec(dllimport)
|
#define LUMIX_PHYSICS_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef BUILDING_NAVIGATION
|
#ifdef BUILDING_NAVIGATION
|
||||||
#define LUMIX_NAVIGATION_API __declspec(dllexport)
|
#define LUMIX_NAVIGATION_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define LUMIX_NAVIGATION_API __declspec(dllimport)
|
#define LUMIX_NAVIGATION_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef BUILDING_ENGINE
|
#ifdef BUILDING_ENGINE
|
||||||
#define LUMIX_ENGINE_API __declspec(dllexport)
|
#define LUMIX_ENGINE_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define LUMIX_ENGINE_API __declspec(dllimport)
|
#define LUMIX_ENGINE_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BUILDING_SCRIPT
|
#ifdef BUILDING_SCRIPT
|
||||||
#define LUMIX_SCRIPT_API __declspec(dllexport)
|
#define LUMIX_SCRIPT_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define LUMIX_SCRIPT_API __declspec(dllimport)
|
#define LUMIX_SCRIPT_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUILDING_ANIMATION
|
||||||
|
#define LUMIX_ANIMATION_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define LUMIX_ANIMATION_API __declspec(dllimport)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LUMIX_RESTRICT __restrict
|
#define LUMIX_RESTRICT __restrict
|
||||||
|
@ -85,4 +91,5 @@ const uint32_t LUMIX_MAX_PATH = 260;
|
||||||
#include "core/new_macros.h"
|
#include "core/new_macros.h"
|
||||||
|
|
||||||
#pragma warning(disable : 4251)
|
#pragma warning(disable : 4251)
|
||||||
|
#pragma warning(disable : 4512)
|
||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
|
|
|
@ -36,6 +36,16 @@ class Map
|
||||||
this->node = node;
|
this->node = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value& value()
|
||||||
|
{
|
||||||
|
return node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key& key()
|
||||||
|
{
|
||||||
|
return node->key;
|
||||||
|
}
|
||||||
|
|
||||||
Value& second()
|
Value& second()
|
||||||
{
|
{
|
||||||
return node->value;
|
return node->value;
|
||||||
|
@ -189,6 +199,11 @@ class Map
|
||||||
m_root = deleteNode(key, m_root);
|
m_root = deleteNode(key, m_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void erase(iterator& iter)
|
||||||
|
{
|
||||||
|
m_root = deleteNode(iter.key(), m_root);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clearNode(Node* node)
|
void clearNode(Node* node)
|
||||||
{
|
{
|
||||||
|
|
|
@ -93,8 +93,7 @@ void EditorIcon::render(Renderer* renderer, IRenderDevice& render_device)
|
||||||
Component camera = m_scene->getCameraInSlot("editor");
|
Component camera = m_scene->getCameraInSlot("editor");
|
||||||
Lumix::Matrix mtx = camera.entity.getMatrix();
|
Lumix::Matrix mtx = camera.entity.getMatrix();
|
||||||
|
|
||||||
float fov;
|
float fov = static_cast<RenderScene*>(camera.scene)->getCameraFOV(camera);
|
||||||
static_cast<RenderScene*>(camera.system)->getCameraFOV(camera, fov);
|
|
||||||
float scale = tan(fov * Math::PI / 180 * 0.5f) * (m_entity.getPosition() - mtx.getTranslation()).length() / 20;
|
float scale = tan(fov * Math::PI / 180 * 0.5f) * (m_entity.getPosition() - mtx.getTranslation()).length() / 20;
|
||||||
|
|
||||||
mtx.setTranslation(m_entity.getPosition());
|
mtx.setTranslation(m_entity.getPosition());
|
||||||
|
|
|
@ -4,25 +4,105 @@
|
||||||
#include "core/iserializer.h"
|
#include "core/iserializer.h"
|
||||||
#include "core/map.h"
|
#include "core/map.h"
|
||||||
#include "core/string.h"
|
#include "core/string.h"
|
||||||
|
#include "editor/ieditor_command.h"
|
||||||
#include "editor/world_editor.h"
|
#include "editor/world_editor.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
|
#include "engine/iplugin.h"
|
||||||
|
#include "graphics/render_scene.h"
|
||||||
#include "universe/entity.h"
|
#include "universe/entity.h"
|
||||||
#include "universe/universe.h"
|
#include "universe/universe.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32_t RENDERABLE_HASH = crc32("renderable");
|
||||||
|
static const uint32_t CAMERA_HASH = crc32("camera");
|
||||||
|
static const uint32_t LIGHT_HASH = crc32("light");
|
||||||
|
static const uint32_t SCRIPT_HASH = crc32("script");
|
||||||
|
static const uint32_t ANIMABLE_HASH = crc32("animable");
|
||||||
|
static const uint32_t TERRAIN_HASH = crc32("terrain");
|
||||||
|
|
||||||
|
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
class EntityTemplateSystemImpl : public EntityTemplateSystem
|
class EntityTemplateSystemImpl : public EntityTemplateSystem
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
class CreateInstanceCommand : public IEditorCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CreateInstanceCommand(EntityTemplateSystemImpl& entity_system, const char* template_name, const Vec3& position)
|
||||||
|
: m_entity_system(entity_system)
|
||||||
|
, m_template_name_hash(crc32(template_name))
|
||||||
|
, m_position(position)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void execute() override
|
||||||
|
{
|
||||||
|
Map<uint32_t, Array<Entity> >::iterator iter = m_entity_system.m_instances.find(m_template_name_hash);
|
||||||
|
if (iter != m_entity_system.m_instances.end())
|
||||||
|
{
|
||||||
|
m_entity = m_entity_system.m_editor.getEngine().getUniverse()->createEntity();
|
||||||
|
m_entity.setPosition(m_position);
|
||||||
|
|
||||||
|
m_entity_system.m_instances[m_template_name_hash].push(m_entity);
|
||||||
|
Entity template_entity = iter.second()[0];
|
||||||
|
const Entity::ComponentList& template_cmps = template_entity.getComponents();
|
||||||
|
for (int i = 0; i < template_cmps.size(); ++i)
|
||||||
|
{
|
||||||
|
m_entity_system.m_editor.cloneComponent(template_cmps[i], m_entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void undo() override
|
||||||
|
{
|
||||||
|
const Entity::ComponentList& cmps = m_entity.getComponents();
|
||||||
|
for (int i = 0; i < cmps.size(); ++i)
|
||||||
|
{
|
||||||
|
cmps[i].scene->destroyComponent(cmps[i]);
|
||||||
|
}
|
||||||
|
m_entity_system.m_universe->destroyEntity(m_entity);
|
||||||
|
m_entity = Entity::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual bool merge(IEditorCommand&) override
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual uint32_t getType() override
|
||||||
|
{
|
||||||
|
static const uint32_t hash = crc32("create_entity_template_instance");
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Entity& getEntity() const { return m_entity; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
EntityTemplateSystemImpl& m_entity_system;
|
||||||
|
uint32_t m_template_name_hash;
|
||||||
|
Entity m_entity;
|
||||||
|
Vec3 m_position;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EntityTemplateSystemImpl(WorldEditor& editor)
|
EntityTemplateSystemImpl(WorldEditor& editor)
|
||||||
: m_editor(editor)
|
: m_editor(editor)
|
||||||
|
, m_universe(NULL)
|
||||||
{
|
{
|
||||||
m_universe = editor.getEngine().getUniverse();
|
|
||||||
editor.universeCreated().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseCreated>(this);
|
editor.universeCreated().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseCreated>(this);
|
||||||
editor.universeDestroyed().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseDestroyed>(this);
|
editor.universeDestroyed().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseDestroyed>(this);
|
||||||
|
setUniverse(editor.getEngine().getUniverse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +110,21 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
m_editor.universeCreated().unbind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseCreated>(this);
|
m_editor.universeCreated().unbind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseCreated>(this);
|
||||||
m_editor.universeDestroyed().unbind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseDestroyed>(this);
|
m_editor.universeDestroyed().unbind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseDestroyed>(this);
|
||||||
|
setUniverse(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setUniverse(Universe* universe)
|
||||||
|
{
|
||||||
|
if (m_universe)
|
||||||
|
{
|
||||||
|
m_universe->entityDestroyed().unbind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onEntityDestroyed>(this);
|
||||||
|
}
|
||||||
|
m_universe = universe;
|
||||||
|
if (m_universe)
|
||||||
|
{
|
||||||
|
m_universe->entityDestroyed().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onEntityDestroyed>(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +132,7 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
m_instances.clear();
|
m_instances.clear();
|
||||||
m_template_names.clear();
|
m_template_names.clear();
|
||||||
m_universe = m_editor.getEngine().getUniverse();
|
setUniverse(m_editor.getEngine().getUniverse());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,7 +140,30 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
m_instances.clear();
|
m_instances.clear();
|
||||||
m_template_names.clear();
|
m_template_names.clear();
|
||||||
m_universe = NULL;
|
setUniverse(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void onEntityDestroyed(const Entity& entity)
|
||||||
|
{
|
||||||
|
uint32_t tpl = getTemplate(entity);
|
||||||
|
if (tpl != 0)
|
||||||
|
{
|
||||||
|
Array<Entity>& instances = m_instances[tpl];
|
||||||
|
instances.eraseItemFast(entity);
|
||||||
|
if (instances.empty())
|
||||||
|
{
|
||||||
|
m_instances.erase(tpl);
|
||||||
|
for (int i = 0; i < m_template_names.size(); ++i)
|
||||||
|
{
|
||||||
|
if (crc32(m_template_names[i].c_str()) == tpl)
|
||||||
|
{
|
||||||
|
m_template_names.eraseFast(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,27 +206,11 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual Entity createInstance(const char* name) override
|
virtual Entity createInstance(const char* name, const Vec3& position) override
|
||||||
{
|
{
|
||||||
uint32_t name_hash = crc32(name);
|
CreateInstanceCommand* command = LUMIX_NEW(CreateInstanceCommand)(*this, name, position);
|
||||||
Map<uint32_t, Array<Entity> >::iterator iter = m_instances.find(name_hash);
|
m_editor.executeCommand(command);
|
||||||
if (iter == m_instances.end())
|
return command->getEntity();
|
||||||
{
|
|
||||||
ASSERT(false);
|
|
||||||
return Entity::INVALID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Entity entity = m_editor.addEntity();
|
|
||||||
m_instances[name_hash].push(entity);
|
|
||||||
Entity template_entity = iter.second()[0];
|
|
||||||
const Entity::ComponentList& template_cmps = template_entity.getComponents();
|
|
||||||
for (int i = 0; i < template_cmps.size(); ++i)
|
|
||||||
{
|
|
||||||
m_editor.cloneComponent(template_cmps[i], entity);
|
|
||||||
}
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace Lumix
|
||||||
virtual uint32_t getTemplate(const Entity& entity) = 0;
|
virtual uint32_t getTemplate(const Entity& entity) = 0;
|
||||||
virtual const Array<Entity>& getInstances(uint32_t template_name_hash) = 0;
|
virtual const Array<Entity>& getInstances(uint32_t template_name_hash) = 0;
|
||||||
virtual class Array<string>& getTemplateNames() = 0;
|
virtual class Array<string>& getTemplateNames() = 0;
|
||||||
virtual Entity createInstance(const char* name) = 0;
|
virtual Entity createInstance(const char* name, const Vec3& position) = 0;
|
||||||
|
|
||||||
virtual DelegateList<void()>& updated() = 0;
|
virtual DelegateList<void()>& updated() = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,7 +23,6 @@ Gizmo::Gizmo(WorldEditor& editor)
|
||||||
: m_editor(editor)
|
: m_editor(editor)
|
||||||
{
|
{
|
||||||
m_model = NULL;
|
m_model = NULL;
|
||||||
m_selected_entity.index = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,35 +45,22 @@ void Gizmo::create(Renderer& renderer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Gizmo::hide()
|
|
||||||
{
|
|
||||||
//ASSERT(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Gizmo::show()
|
|
||||||
{
|
|
||||||
//ASSERT(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Gizmo::getMatrix(Matrix& mtx)
|
void Gizmo::getMatrix(Matrix& mtx)
|
||||||
{
|
{
|
||||||
m_selected_entity.getMatrix(mtx);
|
m_editor.getSelectedEntities()[0].getMatrix(mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Gizmo::updateScale(Component camera)
|
void Gizmo::updateScale(Component camera)
|
||||||
{
|
{
|
||||||
if (m_selected_entity.isValid())
|
if (!m_editor.getSelectedEntities().empty())
|
||||||
{
|
{
|
||||||
Matrix camera_mtx;
|
Matrix camera_mtx;
|
||||||
camera.entity.getMatrix(camera_mtx);
|
camera.entity.getMatrix(camera_mtx);
|
||||||
Matrix mtx;
|
Matrix mtx;
|
||||||
getMatrix(mtx);
|
getMatrix(mtx);
|
||||||
Vec3 pos = mtx.getTranslation();
|
Vec3 pos = mtx.getTranslation();
|
||||||
float fov;
|
float fov = static_cast<RenderScene*>(camera.scene)->getCameraFOV(camera);
|
||||||
static_cast<RenderScene*>(camera.system)->getCameraFOV(camera, fov);
|
|
||||||
float scale = tanf(fov * Math::PI / 180 * 0.5f) * (mtx.getTranslation() - camera_mtx.getTranslation()).length() * 2;
|
float scale = tanf(fov * Math::PI / 180 * 0.5f) * (mtx.getTranslation() - camera_mtx.getTranslation()).length() * 2;
|
||||||
scale /= 20 * mtx.getXVector().length();
|
scale /= 20 * mtx.getXVector().length();
|
||||||
m_scale = scale;
|
m_scale = scale;
|
||||||
|
@ -82,20 +68,6 @@ void Gizmo::updateScale(Component camera)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Gizmo::setEntity(Entity entity)
|
|
||||||
{
|
|
||||||
m_selected_entity = entity;
|
|
||||||
if(m_selected_entity.index != -1)
|
|
||||||
{
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Gizmo::setUniverse(Universe* universe)
|
void Gizmo::setUniverse(Universe* universe)
|
||||||
{
|
{
|
||||||
m_universe = universe;
|
m_universe = universe;
|
||||||
|
@ -104,9 +76,11 @@ void Gizmo::setUniverse(Universe* universe)
|
||||||
|
|
||||||
RayCastModelHit Gizmo::castRay(const Vec3& origin, const Vec3& dir)
|
RayCastModelHit Gizmo::castRay(const Vec3& origin, const Vec3& dir)
|
||||||
{
|
{
|
||||||
if (m_selected_entity.isValid())
|
if (!m_editor.getSelectedEntities().empty())
|
||||||
{
|
{
|
||||||
return m_model->castRay(origin, dir, m_selected_entity.getMatrix(), m_scale);
|
Matrix mtx;
|
||||||
|
getMatrix(mtx);
|
||||||
|
return m_model->castRay(origin, dir, mtx, m_scale);
|
||||||
}
|
}
|
||||||
RayCastModelHit hit;
|
RayCastModelHit hit;
|
||||||
hit.m_is_hit = false;
|
hit.m_is_hit = false;
|
||||||
|
@ -116,11 +90,13 @@ RayCastModelHit Gizmo::castRay(const Vec3& origin, const Vec3& dir)
|
||||||
|
|
||||||
void Gizmo::render(Renderer& renderer, IRenderDevice& render_device)
|
void Gizmo::render(Renderer& renderer, IRenderDevice& render_device)
|
||||||
{
|
{
|
||||||
if(m_selected_entity.isValid())
|
if(!m_editor.getSelectedEntities().empty())
|
||||||
{
|
{
|
||||||
Matrix scale_mtx = Matrix::IDENTITY;
|
Matrix scale_mtx = Matrix::IDENTITY;
|
||||||
scale_mtx.m11 = scale_mtx.m22 = scale_mtx.m33 = m_scale;
|
scale_mtx.m11 = scale_mtx.m22 = scale_mtx.m33 = m_scale;
|
||||||
Matrix mtx = m_selected_entity.getMatrix() * scale_mtx;
|
Matrix gizmo_mtx;
|
||||||
|
getMatrix(gizmo_mtx);
|
||||||
|
Matrix mtx = gizmo_mtx * scale_mtx;
|
||||||
renderer.renderModel(*m_model, mtx, render_device.getPipeline());
|
renderer.renderModel(*m_model, mtx, render_device.getPipeline());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,13 +112,15 @@ void Gizmo::startTransform(Component camera, int x, int y, TransformMode mode)
|
||||||
|
|
||||||
void Gizmo::transform(Component camera, TransformOperation operation, int x, int y, int relx, int rely, int flags)
|
void Gizmo::transform(Component camera, TransformOperation operation, int x, int y, int relx, int rely, int flags)
|
||||||
{
|
{
|
||||||
if(m_selected_entity.index != -1)
|
if(operation == TransformOperation::ROTATE && m_transform_mode != TransformMode::CAMERA_XZ)
|
||||||
{
|
{
|
||||||
if(operation == TransformOperation::ROTATE && m_transform_mode != TransformMode::CAMERA_XZ)
|
Array<Vec3> new_positions;
|
||||||
|
Array<Quat> new_rotations;
|
||||||
|
for(int i = 0, c = m_editor.getSelectedEntities().size(); i < c; ++i)
|
||||||
{
|
{
|
||||||
Vec3 pos = m_selected_entity.getPosition();
|
Vec3 pos = m_editor.getSelectedEntities()[i].getPosition();
|
||||||
Matrix emtx;
|
Matrix emtx;
|
||||||
m_selected_entity.getMatrix(emtx);
|
m_editor.getSelectedEntities()[i].getMatrix(emtx);
|
||||||
Vec3 axis;
|
Vec3 axis;
|
||||||
switch(m_transform_mode)
|
switch(m_transform_mode)
|
||||||
{
|
{
|
||||||
|
@ -180,19 +158,26 @@ void Gizmo::transform(Component camera, TransformOperation operation, int x, int
|
||||||
{
|
{
|
||||||
angle = (relx + rely) / 100.0f;
|
angle = (relx + rely) / 100.0f;
|
||||||
}
|
}
|
||||||
Quat new_rot = m_selected_entity.getRotation() * Quat(axis, angle);
|
Quat new_rot = m_editor.getSelectedEntities()[i].getRotation() * Quat(axis, angle);
|
||||||
new_rot.normalize();
|
new_rot.normalize();
|
||||||
m_editor.setEntityPositionAndRotaion(m_selected_entity, pos, new_rot);
|
new_rotations.push(new_rot);
|
||||||
|
new_positions.push(pos);
|
||||||
}
|
}
|
||||||
else
|
m_editor.setEntityPositionAndRotaion(m_editor.getSelectedEntities(), new_positions, new_rotations);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vec3 intersection = getMousePlaneIntersection(camera, x, y);
|
||||||
|
Vec3 delta = intersection - m_transform_point;
|
||||||
|
Array<Vec3> new_positions;
|
||||||
|
for(int i = 0, ci = m_editor.getSelectedEntities().size(); i < ci; ++i)
|
||||||
{
|
{
|
||||||
Vec3 intersection = getMousePlaneIntersection(camera, x, y);
|
Vec3 pos = m_editor.getSelectedEntities()[i].getPosition();
|
||||||
Vec3 delta = intersection - m_transform_point;
|
|
||||||
m_transform_point = intersection;
|
|
||||||
Vec3 pos = m_selected_entity.getPosition();
|
|
||||||
pos += delta;
|
pos += delta;
|
||||||
m_editor.setEntityPosition(m_selected_entity, pos);
|
new_positions.push(pos);
|
||||||
}
|
}
|
||||||
|
m_editor.setEntitiesPositions(m_editor.getSelectedEntities(), new_positions);
|
||||||
|
m_transform_point = intersection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,18 +185,20 @@ void Gizmo::transform(Component camera, TransformOperation operation, int x, int
|
||||||
Vec3 Gizmo::getMousePlaneIntersection(Component camera, int x, int y)
|
Vec3 Gizmo::getMousePlaneIntersection(Component camera, int x, int y)
|
||||||
{
|
{
|
||||||
Vec3 origin, dir;
|
Vec3 origin, dir;
|
||||||
RenderScene* scene = static_cast<RenderScene*>(camera.system);
|
RenderScene* scene = static_cast<RenderScene*>(camera.scene);
|
||||||
scene->getRay(camera, (float)x, (float)y, origin, dir);
|
scene->getRay(camera, (float)x, (float)y, origin, dir);
|
||||||
dir.normalize();
|
dir.normalize();
|
||||||
Matrix camera_mtx;
|
Matrix camera_mtx;
|
||||||
camera.entity.getMatrix(camera_mtx);
|
camera.entity.getMatrix(camera_mtx);
|
||||||
|
Matrix gizmo_mtx;
|
||||||
|
getMatrix(gizmo_mtx);
|
||||||
if(m_transform_mode == TransformMode::CAMERA_XZ)
|
if(m_transform_mode == TransformMode::CAMERA_XZ)
|
||||||
{
|
{
|
||||||
Vec3 a = crossProduct(Vec3(0, 1, 0), camera_mtx.getXVector());
|
Vec3 a = crossProduct(Vec3(0, 1, 0), camera_mtx.getXVector());
|
||||||
Vec3 b = crossProduct(Vec3(0, 1, 0), camera_mtx.getZVector());
|
Vec3 b = crossProduct(Vec3(0, 1, 0), camera_mtx.getZVector());
|
||||||
Vec3 plane_normal = crossProduct(a, b);
|
Vec3 plane_normal = crossProduct(a, b);
|
||||||
float t;
|
float t;
|
||||||
if (Math::getRayPlaneIntersecion(origin, dir, m_selected_entity.getPosition(), plane_normal, t))
|
if (Math::getRayPlaneIntersecion(origin, dir, gizmo_mtx.getTranslation(), plane_normal, t))
|
||||||
{
|
{
|
||||||
return origin + dir * t;
|
return origin + dir * t;
|
||||||
}
|
}
|
||||||
|
@ -221,16 +208,16 @@ Vec3 Gizmo::getMousePlaneIntersection(Component camera, int x, int y)
|
||||||
switch(m_transform_mode)
|
switch(m_transform_mode)
|
||||||
{
|
{
|
||||||
case TransformMode::X:
|
case TransformMode::X:
|
||||||
axis = m_selected_entity.getMatrix().getXVector();
|
axis = gizmo_mtx.getXVector();
|
||||||
break;
|
break;
|
||||||
case TransformMode::Y:
|
case TransformMode::Y:
|
||||||
axis = m_selected_entity.getMatrix().getYVector();
|
axis = gizmo_mtx.getYVector();
|
||||||
break;
|
break;
|
||||||
case TransformMode::Z:
|
case TransformMode::Z:
|
||||||
axis = m_selected_entity.getMatrix().getZVector();
|
axis = gizmo_mtx.getZVector();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Vec3 pos = m_selected_entity.getPosition();
|
Vec3 pos = gizmo_mtx.getTranslation();
|
||||||
Vec3 normal = crossProduct(crossProduct(dir, axis), dir);
|
Vec3 normal = crossProduct(crossProduct(dir, axis), dir);
|
||||||
float d = dotProduct(origin - pos, normal) / dotProduct(axis, normal);
|
float d = dotProduct(origin - pos, normal) / dotProduct(axis, normal);
|
||||||
return axis * d + pos;
|
return axis * d + pos;
|
||||||
|
|
|
@ -79,10 +79,7 @@ class LUMIX_ENGINE_API Gizmo
|
||||||
|
|
||||||
void create(Renderer& renderer);
|
void create(Renderer& renderer);
|
||||||
void destroy();
|
void destroy();
|
||||||
void hide();
|
|
||||||
void show();
|
|
||||||
void updateScale(Component camera);
|
void updateScale(Component camera);
|
||||||
void setEntity(Entity entity);
|
|
||||||
void setUniverse(Universe* universe);
|
void setUniverse(Universe* universe);
|
||||||
void startTransform(Component camera, int x, int y, TransformMode mode);
|
void startTransform(Component camera, int x, int y, TransformMode mode);
|
||||||
void transform(Component camera, TransformOperation operation, int x, int y, int relx, int rely, int flags);
|
void transform(Component camera, TransformOperation operation, int x, int y, int relx, int rely, int flags);
|
||||||
|
@ -96,7 +93,6 @@ class LUMIX_ENGINE_API Gizmo
|
||||||
private:
|
private:
|
||||||
WorldEditor& m_editor;
|
WorldEditor& m_editor;
|
||||||
Renderer* m_renderer;
|
Renderer* m_renderer;
|
||||||
Entity m_selected_entity;
|
|
||||||
Universe* m_universe;
|
Universe* m_universe;
|
||||||
TransformMode m_transform_mode;
|
TransformMode m_transform_mode;
|
||||||
Vec3 m_transform_point;
|
Vec3 m_transform_point;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "universe\universe.h"
|
#include "universe\universe.h"
|
||||||
#include "core/blob.h"
|
#include "core/blob.h"
|
||||||
|
#include "core/crc32.h"
|
||||||
#include "core/delegate.h"
|
#include "core/delegate.h"
|
||||||
#include "core/string.h"
|
#include "core/string.h"
|
||||||
|
|
||||||
|
@ -24,172 +25,597 @@ class IPropertyDescriptor
|
||||||
BOOL,
|
BOOL,
|
||||||
VEC3,
|
VEC3,
|
||||||
INTEGER,
|
INTEGER,
|
||||||
STRING
|
STRING,
|
||||||
|
ARRAY
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~IPropertyDescriptor() {}
|
||||||
|
|
||||||
virtual void set(Component cmp, Blob& stream) const = 0;
|
virtual void set(Component cmp, Blob& stream) const = 0;
|
||||||
virtual void get(Component cmp, Blob& stream) const = 0;
|
virtual void get(Component cmp, Blob& stream) const = 0;
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const = 0;
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const = 0;
|
||||||
|
|
||||||
uint32_t getNameHash() const { return m_name_hash; }
|
|
||||||
Type getType() const { return m_type; }
|
Type getType() const { return m_type; }
|
||||||
|
uint32_t getNameHash() const { return m_name_hash; }
|
||||||
|
const char* getName() const { return m_name.c_str(); }
|
||||||
|
void setName(const char* name) { m_name = name; m_name_hash = crc32(name); }
|
||||||
|
void addChild(IPropertyDescriptor* child) { m_children.push(child); }
|
||||||
|
const Array<IPropertyDescriptor*>& getChildren() const { return m_children; }
|
||||||
|
Array<IPropertyDescriptor*>& getChildren() { return m_children; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t m_name_hash;
|
uint32_t m_name_hash;
|
||||||
|
string m_name;
|
||||||
Type m_type;
|
Type m_type;
|
||||||
|
Array<IPropertyDescriptor*> m_children;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IIntPropertyDescriptor : public IPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IIntPropertyDescriptor()
|
||||||
|
{
|
||||||
|
m_min = INT_MIN;
|
||||||
|
m_max = INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLimit(int min, int max) { m_min = min; m_max = max; }
|
||||||
|
int getMin() const { return m_min; }
|
||||||
|
int getMax() const { return m_max; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_min;
|
||||||
|
int m_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
class PropertyDescriptor : public IPropertyDescriptor
|
class IntArrayObjectDescriptor : public IIntPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int (S::*IntegerGetter)(Component, int);
|
||||||
|
typedef void (S::*IntegerSetter)(Component, int, int);
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntArrayObjectDescriptor(const char* name, IntegerGetter _getter, IntegerSetter _setter)
|
||||||
|
{
|
||||||
|
setName(name);
|
||||||
|
m_integer_getter = _getter;
|
||||||
|
m_integer_setter = _setter;
|
||||||
|
m_type = INTEGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
stream.read(&i, sizeof(i));
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_integer_setter)(cmp, index, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
int32_t i = (static_cast<S*>(cmp.scene)->*m_integer_getter)(cmp, index);
|
||||||
|
int len = sizeof(i);
|
||||||
|
stream.write(&i, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component, Blob&) const {};
|
||||||
|
virtual void get(Component, Blob&) const {};
|
||||||
|
|
||||||
|
private:
|
||||||
|
IntegerGetter m_integer_getter;
|
||||||
|
IntegerSetter m_integer_setter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class BoolArrayObjectDescriptor : public IPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef void (S::*Getter)(Component, int, int&);
|
||||||
|
typedef void (S::*Setter)(Component, int, const int&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
BoolArrayObjectDescriptor(const char* name, Getter _getter, Setter _setter)
|
||||||
|
{
|
||||||
|
setName(name);
|
||||||
|
m_getter = _getter;
|
||||||
|
m_setter = _setter;
|
||||||
|
m_type = BOOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
bool b;
|
||||||
|
stream.read(&b, sizeof(b));
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_setter)(cmp, index, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
bool b;
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_getter)(cmp, index, b);
|
||||||
|
stream.write(&b, sizeof(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component, Blob&) const { ASSERT(false); };
|
||||||
|
virtual void get(Component, Blob&) const { ASSERT(false); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
Getter m_getter;
|
||||||
|
Setter m_setter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class DecimalArrayObjectDescriptor : public IPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef float (S::*Getter)(Component, int);
|
||||||
|
typedef void (S::*Setter)(Component, int, float);
|
||||||
|
|
||||||
|
public:
|
||||||
|
DecimalArrayObjectDescriptor(const char* name, Getter _getter, Setter _setter)
|
||||||
|
{
|
||||||
|
setName(name);
|
||||||
|
m_getter = _getter;
|
||||||
|
m_setter = _setter;
|
||||||
|
m_type = DECIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
stream.read(&f, sizeof(f));
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_setter)(cmp, index, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
float f = (static_cast<S*>(cmp.scene)->*m_getter)(cmp, index);
|
||||||
|
stream.write(&f, sizeof(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component, Blob&) const { ASSERT(false); };
|
||||||
|
virtual void get(Component, Blob&) const { ASSERT(false); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
Getter m_getter;
|
||||||
|
Setter m_setter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class StringArrayObjectDescriptor : public IPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef void (S::*Getter)(Component, int, string&);
|
||||||
|
typedef void (S::*Setter)(Component, int, const string&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
StringArrayObjectDescriptor(const char* name, Getter _getter, Setter _setter)
|
||||||
|
{
|
||||||
|
setName(name);
|
||||||
|
m_getter = _getter;
|
||||||
|
m_setter = _setter;
|
||||||
|
m_type = STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
char tmp[300];
|
||||||
|
char* c = tmp;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
stream.read(c, 1);
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
while (*(c - 1) && (c - 1) - tmp < 300);
|
||||||
|
string s((char*)tmp);
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_setter)(cmp, index, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_getter)(cmp, index, value);
|
||||||
|
int len = value.length() + 1;
|
||||||
|
stream.write(value.c_str(), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component, Blob&) const { ASSERT(false); };
|
||||||
|
virtual void get(Component, Blob&) const { ASSERT(false); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
Getter m_getter;
|
||||||
|
Setter m_setter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class FileArrayObjectDescriptor : public StringArrayObjectDescriptor<S>, public IFilePropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FileArrayObjectDescriptor(const char* name, Getter getter, Setter setter, const char* file_type)
|
||||||
|
: StringArrayObjectDescriptor(name, getter, setter)
|
||||||
|
, m_file_type(file_type)
|
||||||
|
{
|
||||||
|
m_type = IPropertyDescriptor::FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* getFileType() override
|
||||||
|
{
|
||||||
|
return m_file_type.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string m_file_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class Vec3ArrayObjectDescriptor : public IPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Vec3 (S::*Getter)(Component, int);
|
||||||
|
typedef void (S::*Setter)(Component, int, const Vec3&);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Vec3ArrayObjectDescriptor(const char* name, Getter _getter, Setter _setter) { setName(name); m_vec3_getter = _getter; m_vec3_setter = _setter; m_type = VEC3; }
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
Vec3 v;
|
||||||
|
stream.read(&v, sizeof(v));
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_vec3_setter)(cmp, index, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const override
|
||||||
|
{
|
||||||
|
Vec3 v = (static_cast<S*>(cmp.scene)->*m_vec3_getter)(cmp, index);
|
||||||
|
len = sizeof(v);
|
||||||
|
stream.write(&v, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component, Blob&) const {};
|
||||||
|
virtual void get(Component, Blob&) const {};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Getter m_getter;
|
||||||
|
Setter m_setter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class IArrayDescriptor : public IPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void removeArrayItem(Component cmp, int index) const = 0;
|
||||||
|
virtual void addArrayItem(Component cmp, int index) const = 0;
|
||||||
|
virtual int getCount(Component cmp) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class ArrayDescriptor : public IArrayDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int (S::*Counter)(Component);
|
||||||
|
typedef void (S::*Adder)(Component, int);
|
||||||
|
typedef void (S::*Remover)(Component, int);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ArrayDescriptor(const char* name, Counter counter, Adder adder, Remover remover) { setName(name); m_type = ARRAY; m_counter = counter; m_adder = adder; m_remover = remover; }
|
||||||
|
~ArrayDescriptor()
|
||||||
|
{
|
||||||
|
for(int i = 0; i < m_children.size(); ++i)
|
||||||
|
{
|
||||||
|
LUMIX_DELETE(m_children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, Blob& stream) const override
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
stream.read(count);
|
||||||
|
while (getCount(cmp) < count)
|
||||||
|
{
|
||||||
|
addArrayItem(cmp, -1);
|
||||||
|
}
|
||||||
|
while (getCount(cmp) > count)
|
||||||
|
{
|
||||||
|
removeArrayItem(cmp, getCount(cmp) - 1);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0, cj = getChildren().size(); j < cj; ++j)
|
||||||
|
{
|
||||||
|
getChildren()[j]->set(cmp, i, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, Blob& stream) const override
|
||||||
|
{
|
||||||
|
int count = getCount(cmp);
|
||||||
|
stream.write(count);
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
for (int j = 0, cj = getChildren().size(); j < cj; ++j)
|
||||||
|
{
|
||||||
|
getChildren()[j]->get(cmp, i, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component, int, Blob&) const override { ASSERT(false); };
|
||||||
|
virtual void get(Component, int, Blob&) const override { ASSERT(false); };
|
||||||
|
|
||||||
|
virtual int getCount(Component cmp) const override { return (static_cast<S*>(cmp.scene)->*m_counter)(cmp); }
|
||||||
|
virtual void addArrayItem(Component cmp, int index) const override { (static_cast<S*>(cmp.scene)->*m_adder)(cmp, index); }
|
||||||
|
virtual void removeArrayItem(Component cmp, int index) const override { (static_cast<S*>(cmp.scene)->*m_remover)(cmp, index); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Counter m_counter;
|
||||||
|
Adder m_adder;
|
||||||
|
Remover m_remover;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class IntPropertyDescriptor : public IIntPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int (S::*IntegerGetter)(Component);
|
||||||
|
typedef void (S::*IntegerSetter)(Component, int);
|
||||||
|
|
||||||
|
public:
|
||||||
|
IntPropertyDescriptor(const char* name, IntegerGetter _getter, IntegerSetter _setter) { setName(name); m_integer_getter = _getter; m_integer_setter = _setter; m_type = INTEGER; }
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, Blob& stream) const override
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
stream.read(&i, sizeof(i));
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_integer_setter)(cmp, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, Blob& stream) const override
|
||||||
|
{
|
||||||
|
int32_t i = (static_cast<S*>(cmp.scene)->*m_integer_getter)(cmp);
|
||||||
|
len = sizeof(i);
|
||||||
|
stream.write(&i, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); set(cmp, stream); };
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); get(cmp, stream); };
|
||||||
|
|
||||||
|
private:
|
||||||
|
IntegerGetter m_integer_getter;
|
||||||
|
IntegerSetter m_integer_setter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class StringPropertyDescriptor : public IPropertyDescriptor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef void (S::*Getter)(Component, string&);
|
typedef void (S::*Getter)(Component, string&);
|
||||||
typedef void (S::*Setter)(Component, const string&);
|
typedef void (S::*Setter)(Component, const string&);
|
||||||
typedef void (S::*BoolGetter)(Component, bool&);
|
|
||||||
typedef void (S::*BoolSetter)(Component, const bool&);
|
|
||||||
typedef void (S::*DecimalGetter)(Component, float&);
|
|
||||||
typedef void (S::*DecimalSetter)(Component, const float&);
|
|
||||||
typedef void (S::*IntegerGetter)(Component, int&);
|
|
||||||
typedef void (S::*IntegerSetter)(Component, const int&);
|
|
||||||
typedef void (S::*Vec3Getter)(Component, Vec3&);
|
|
||||||
typedef void (S::*Vec3Setter)(Component, const Vec3&);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PropertyDescriptor(uint32_t _name_hash, Getter _getter, Setter _setter, Type _type) { m_name_hash = _name_hash; m_getter = _getter; m_setter = _setter; m_type = _type; }
|
StringPropertyDescriptor(const char* name, Getter getter, Setter setter)
|
||||||
PropertyDescriptor(uint32_t _name_hash, BoolGetter _getter, BoolSetter _setter) { m_name_hash = _name_hash; m_bool_getter = _getter; m_bool_setter = _setter; m_type = BOOL; }
|
{
|
||||||
PropertyDescriptor(uint32_t _name_hash, DecimalGetter _getter, DecimalSetter _setter) { m_name_hash = _name_hash; m_decimal_getter = _getter; m_decimal_setter = _setter; m_type = DECIMAL; }
|
setName(name);
|
||||||
PropertyDescriptor(uint32_t _name_hash, IntegerGetter _getter, IntegerSetter _setter) { m_name_hash = _name_hash; m_integer_getter = _getter; m_integer_setter = _setter; m_type = INTEGER; }
|
m_getter = getter;
|
||||||
PropertyDescriptor(uint32_t _name_hash, Vec3Getter _getter, Vec3Setter _setter) { m_name_hash = _name_hash; m_vec3_getter = _getter; m_vec3_setter = _setter; m_type = VEC3; }
|
m_setter = setter;
|
||||||
virtual void set(Component cmp, Blob& stream) const override;
|
m_type = IPropertyDescriptor::STRING;
|
||||||
virtual void get(Component cmp, Blob& stream) const override;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, Blob& stream) const override
|
||||||
|
{
|
||||||
|
char tmp[300];
|
||||||
|
char* c = tmp;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
stream.read(c, 1);
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
while (*(c - 1) && (c - 1) - tmp < 300);
|
||||||
|
string s((char*)tmp);
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_setter)(cmp, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, Blob& stream) const override
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_getter)(cmp, value);
|
||||||
|
int len = value.length() + 1;
|
||||||
|
stream.write(value.c_str(), len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); set(cmp, stream); };
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); get(cmp, stream); };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
union
|
Getter m_getter;
|
||||||
{
|
Setter m_setter;
|
||||||
Getter m_getter;
|
|
||||||
BoolGetter m_bool_getter;
|
|
||||||
DecimalGetter m_decimal_getter;
|
|
||||||
IntegerGetter m_integer_getter;
|
|
||||||
Vec3Getter m_vec3_getter;
|
|
||||||
};
|
|
||||||
union
|
|
||||||
{
|
|
||||||
Setter m_setter;
|
|
||||||
BoolSetter m_bool_setter;
|
|
||||||
DecimalSetter m_decimal_setter;
|
|
||||||
IntegerSetter m_integer_setter;
|
|
||||||
Vec3Setter m_vec3_setter;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
void PropertyDescriptor<S>::set(Component cmp, Blob& stream) const
|
class BoolPropertyDescriptor : public IPropertyDescriptor
|
||||||
{
|
{
|
||||||
int len = stream.getBufferSize();
|
public:
|
||||||
switch(m_type)
|
typedef void (S::*Getter)(Component, bool&);
|
||||||
{
|
typedef void (S::*Setter)(Component, const bool&);
|
||||||
case DECIMAL:
|
|
||||||
{
|
public:
|
||||||
float f;
|
BoolPropertyDescriptor(const char* name, Getter getter, Setter setter)
|
||||||
stream.read(&f, sizeof(f));
|
{
|
||||||
(static_cast<S*>(cmp.system)->*m_decimal_setter)(cmp, f);
|
setName(name);
|
||||||
}
|
m_getter = getter;
|
||||||
break;
|
m_setter = setter;
|
||||||
case INTEGER:
|
m_type = IPropertyDescriptor::BOOL;
|
||||||
{
|
}
|
||||||
int32_t i;
|
|
||||||
stream.read(&i, sizeof(i));
|
|
||||||
(static_cast<S*>(cmp.system)->*m_integer_setter)(cmp, i);
|
virtual void set(Component cmp, Blob& stream) const override
|
||||||
}
|
{
|
||||||
break;
|
bool b;
|
||||||
case BOOL:
|
stream.read(&b, sizeof(b));
|
||||||
{
|
(static_cast<S*>(cmp.scene)->*m_setter)(cmp, b);
|
||||||
bool b;
|
}
|
||||||
stream.read(&b, sizeof(b));
|
|
||||||
(static_cast<S*>(cmp.system)->*m_bool_setter)(cmp, b);
|
|
||||||
}
|
virtual void get(Component cmp, Blob& stream) const override
|
||||||
break;
|
{
|
||||||
case STRING:
|
bool b;
|
||||||
case FILE:
|
(static_cast<S*>(cmp.scene)->*m_getter)(cmp, b);
|
||||||
{
|
int len = sizeof(b);
|
||||||
char tmp[301];
|
stream.write(&b, len);
|
||||||
ASSERT(len < 300);
|
}
|
||||||
stream.read(tmp, len);
|
|
||||||
tmp[len] = '\0';
|
|
||||||
string s((char*)tmp);
|
virtual void set(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); set(cmp, stream); };
|
||||||
(static_cast<S*>(cmp.system)->*m_setter)(cmp, s);
|
virtual void get(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); get(cmp, stream); };
|
||||||
}
|
|
||||||
break;
|
private:
|
||||||
case VEC3:
|
Getter m_getter;
|
||||||
{
|
Setter m_setter;
|
||||||
Vec3 v;
|
};
|
||||||
stream.read(&v, sizeof(v));
|
|
||||||
(static_cast<S*>(cmp.system)->*m_vec3_setter)(cmp, v);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class S>
|
template <class S>
|
||||||
void PropertyDescriptor<S>::get(Component cmp, Blob& stream) const
|
class Vec3PropertyDescriptor : public IPropertyDescriptor
|
||||||
{
|
{
|
||||||
int len = 4;
|
public:
|
||||||
switch(m_type)
|
typedef Vec3 (S::*Getter)(Component);
|
||||||
{
|
typedef void (S::*Setter)(Component, const Vec3&);
|
||||||
case STRING:
|
|
||||||
case FILE:
|
public:
|
||||||
{
|
Vec3PropertyDescriptor(const char* name, Getter getter, Setter setter)
|
||||||
string value;
|
{
|
||||||
(static_cast<S*>(cmp.system)->*m_getter)(cmp, value);
|
setName(name);
|
||||||
len = value.length() + 1;
|
m_getter = getter;
|
||||||
stream.write(value.c_str(), len);
|
m_setter = setter;
|
||||||
}
|
m_type = IPropertyDescriptor::VEC3;
|
||||||
break;
|
}
|
||||||
case DECIMAL:
|
|
||||||
{
|
|
||||||
float f;
|
virtual void set(Component cmp, Blob& stream) const override
|
||||||
(static_cast<S*>(cmp.system)->*m_decimal_getter)(cmp, f);
|
{
|
||||||
len = sizeof(f);
|
Vec3 v;
|
||||||
stream.write(&f, len);
|
stream.read(&v, sizeof(v));
|
||||||
}
|
(static_cast<S*>(cmp.scene)->*m_setter)(cmp, v);
|
||||||
break;
|
}
|
||||||
case INTEGER:
|
|
||||||
{
|
|
||||||
int32_t i;
|
virtual void get(Component cmp, Blob& stream) const override
|
||||||
(static_cast<S*>(cmp.system)->*m_integer_getter)(cmp, i);
|
{
|
||||||
len = sizeof(i);
|
Vec3 v = (static_cast<S*>(cmp.scene)->*m_getter)(cmp);
|
||||||
stream.write(&i, len);
|
int len = sizeof(v);
|
||||||
}
|
stream.write(&v, len);
|
||||||
break;
|
}
|
||||||
case BOOL:
|
|
||||||
{
|
|
||||||
bool b;
|
virtual void set(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); set(cmp, stream); };
|
||||||
(static_cast<S*>(cmp.system)->*m_bool_getter)(cmp, b);
|
virtual void get(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); get(cmp, stream); };
|
||||||
len = sizeof(b);
|
|
||||||
stream.write(&b, len);
|
private:
|
||||||
}
|
Getter m_getter;
|
||||||
break;
|
Setter m_setter;
|
||||||
case VEC3:
|
};
|
||||||
{
|
|
||||||
Vec3 v;
|
|
||||||
(static_cast<S*>(cmp.system)->*m_vec3_getter)(cmp, v);
|
class IFilePropertyDescriptor
|
||||||
len = sizeof(v);
|
{
|
||||||
stream.write(&v, len);
|
public:
|
||||||
}
|
virtual const char* getFileType() = 0;
|
||||||
break;
|
};
|
||||||
default:
|
|
||||||
ASSERT(false);
|
|
||||||
break;
|
template <class T>
|
||||||
}
|
class FilePropertyDescriptor : public StringPropertyDescriptor<T>, public IFilePropertyDescriptor
|
||||||
}
|
{
|
||||||
|
public:
|
||||||
|
FilePropertyDescriptor(const char* name, Getter getter, Setter setter, const char* file_type)
|
||||||
|
: StringPropertyDescriptor(name, getter, setter)
|
||||||
|
, m_file_type(file_type)
|
||||||
|
|
||||||
|
{
|
||||||
|
m_type = IPropertyDescriptor::FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char* getFileType() override
|
||||||
|
{
|
||||||
|
return m_file_type.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string m_file_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <class S>
|
||||||
|
class DecimalPropertyDescriptor : public IPropertyDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef float (S::*Getter)(Component);
|
||||||
|
typedef void (S::*Setter)(Component, float);
|
||||||
|
|
||||||
|
public:
|
||||||
|
DecimalPropertyDescriptor(const char* name, Getter _getter, Setter _setter) { setName(name); m_getter = _getter; m_setter = _setter; m_type = DECIMAL; }
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, Blob& stream) const override
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
stream.read(&f, sizeof(f));
|
||||||
|
(static_cast<S*>(cmp.scene)->*m_setter)(cmp, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void get(Component cmp, Blob& stream) const override
|
||||||
|
{
|
||||||
|
float f = (static_cast<S*>(cmp.scene)->*m_getter)(cmp);
|
||||||
|
int len = sizeof(f);
|
||||||
|
stream.write(&f, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void set(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); set(cmp, stream); };
|
||||||
|
virtual void get(Component cmp, int index, Blob& stream) const override { ASSERT(index == -1); get(cmp, stream);};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Getter m_getter;
|
||||||
|
Setter m_setter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // !namespace Lumix
|
} // !namespace Lumix
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -51,11 +51,12 @@ namespace Lumix
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static WorldEditor* create(const char* base_path);
|
static WorldEditor* create(const char* base_path);
|
||||||
static void destroy(WorldEditor* server);
|
static void destroy(WorldEditor* editor);
|
||||||
|
|
||||||
virtual void tick() = 0;
|
virtual void tick() = 0;
|
||||||
virtual void registerCreator(uint32_t type, IPlugin& creator) = 0;
|
|
||||||
virtual void registerProperty(const char* component_type, IPropertyDescriptor* descriptor) = 0;
|
virtual void registerProperty(const char* component_type, IPropertyDescriptor* descriptor) = 0;
|
||||||
|
virtual IPropertyDescriptor* getProperty(const char* component_type, const char* property_name) = 0;
|
||||||
|
virtual void executeCommand(class IEditorCommand* command) = 0;
|
||||||
virtual Engine& getEngine() = 0;
|
virtual Engine& getEngine() = 0;
|
||||||
virtual void render(IRenderDevice& render_device) = 0;
|
virtual void render(IRenderDevice& render_device) = 0;
|
||||||
virtual void renderIcons(IRenderDevice& render_device) = 0;
|
virtual void renderIcons(IRenderDevice& render_device) = 0;
|
||||||
|
@ -71,16 +72,20 @@ namespace Lumix
|
||||||
virtual Path getUniversePath() const = 0;
|
virtual Path getUniversePath() const = 0;
|
||||||
virtual void addComponent(uint32_t type_crc) = 0;
|
virtual void addComponent(uint32_t type_crc) = 0;
|
||||||
virtual void cloneComponent(const Component& src, Entity& entity) = 0;
|
virtual void cloneComponent(const Component& src, Entity& entity) = 0;
|
||||||
virtual void removeComponent(const Component& crc) = 0;
|
virtual void destroyComponent(const Component& crc) = 0;
|
||||||
virtual Entity addEntity() = 0;
|
virtual Entity addEntity() = 0;
|
||||||
virtual void selectEntity(Entity e) = 0;
|
virtual void destroyEntities(const Entity* entities, int count) = 0;
|
||||||
|
virtual void selectEntities(const Entity* entities, int count) = 0;
|
||||||
virtual Entity addEntityAt(int camera_x, int camera_y) = 0;
|
virtual Entity addEntityAt(int camera_x, int camera_y) = 0;
|
||||||
virtual void setEntityPosition(const Entity& entity, const Vec3& position) = 0;
|
virtual void setEntitiesPositions(const Array<Entity>& entity, const Array<Vec3>& position) = 0;
|
||||||
virtual void setEntityPositionAndRotaion(const Entity& entity, const Vec3& position, const Quat& rotation) = 0;
|
virtual void setEntityPositionAndRotaion(const Array<Entity>& entity, const Array<Vec3>& position, const Array<Quat>& rotation) = 0;
|
||||||
|
virtual void setEntityName(const Entity& entity, const char* name) = 0;
|
||||||
virtual void snapToTerrain() = 0;
|
virtual void snapToTerrain() = 0;
|
||||||
virtual void toggleGameMode() = 0;
|
virtual void toggleGameMode() = 0;
|
||||||
virtual void navigate(float forward, float right, float speed) = 0;
|
virtual void navigate(float forward, float right, float speed) = 0;
|
||||||
virtual void setProperty(const char* component, const char* property, const void* data, int size) = 0;
|
virtual void setProperty(uint32_t component, int index, IPropertyDescriptor& property, const void* data, int size) = 0;
|
||||||
|
virtual void addArrayPropertyItem(const Component& cmp, IArrayDescriptor& property) = 0;
|
||||||
|
virtual void removeArrayPropertyItem(const Component& cmp, int index, IArrayDescriptor& property) = 0;
|
||||||
virtual void onMouseDown(int x, int y, MouseButton::Value button) = 0;
|
virtual void onMouseDown(int x, int y, MouseButton::Value button) = 0;
|
||||||
virtual void onMouseMove(int x, int y, int relx, int rely, int mouse_flags) = 0;
|
virtual void onMouseMove(int x, int y, int relx, int rely, int mouse_flags) = 0;
|
||||||
virtual void onMouseUp(int x, int y, MouseButton::Value button) = 0;
|
virtual void onMouseUp(int x, int y, MouseButton::Value button) = 0;
|
||||||
|
@ -89,14 +94,18 @@ namespace Lumix
|
||||||
virtual void setWireframe(bool is_wireframe) = 0;
|
virtual void setWireframe(bool is_wireframe) = 0;
|
||||||
virtual void lookAtSelected() = 0;
|
virtual void lookAtSelected() = 0;
|
||||||
virtual const char* getBasePath() = 0;
|
virtual const char* getBasePath() = 0;
|
||||||
virtual Entity getSelectedEntity() const = 0;
|
virtual const Array<Entity>& getSelectedEntities() const = 0;
|
||||||
virtual const IPropertyDescriptor& getPropertyDescriptor(uint32_t type, uint32_t name_hash) = 0;
|
virtual const IPropertyDescriptor& getPropertyDescriptor(uint32_t type, uint32_t name_hash) = 0;
|
||||||
virtual DelegateList<void(Entity&)>& entitySelected() = 0;
|
virtual Array<IPropertyDescriptor*>& getPropertyDescriptors(uint32_t type) = 0;
|
||||||
|
virtual DelegateList<void(const Array<Entity>&)>& entitySelected() = 0;
|
||||||
virtual DelegateList<void()>& universeCreated() = 0;
|
virtual DelegateList<void()>& universeCreated() = 0;
|
||||||
virtual DelegateList<void()>& universeDestroyed() = 0;
|
virtual DelegateList<void()>& universeDestroyed() = 0;
|
||||||
|
virtual DelegateList<void()>& universeLoaded() = 0;
|
||||||
|
virtual DelegateList<void(const Entity&, const char*)>& entityNameSet() = 0;
|
||||||
virtual void addPlugin(Plugin* plugin) = 0;
|
virtual void addPlugin(Plugin* plugin) = 0;
|
||||||
virtual void getRelativePath(char* relative_path, int max_length, const Path& source) = 0;
|
virtual void getRelativePath(char* relative_path, int max_length, const Path& source) = 0;
|
||||||
virtual EntityTemplateSystem& getEntityTemplateSystem() = 0;
|
virtual EntityTemplateSystem& getEntityTemplateSystem() = 0;
|
||||||
|
virtual Vec3 getCameraRaycastHit() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~WorldEditor() {}
|
virtual ~WorldEditor() {}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
#include "core/lumix.h"
|
#include "core/lumix.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
|
|
||||||
#include "animation/animation.h"
|
|
||||||
#include "animation/animation_system.h"
|
|
||||||
|
|
||||||
#include "core/crc32.h"
|
#include "core/crc32.h"
|
||||||
#include "core/input_system.h"
|
#include "core/input_system.h"
|
||||||
|
@ -34,38 +32,285 @@
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
|
|
||||||
struct EngineImpl
|
class EngineImpl : public Engine
|
||||||
{
|
{
|
||||||
EngineImpl(Engine& engine) : m_owner(engine) {}
|
public:
|
||||||
~EngineImpl();
|
EngineImpl(const char* base_path, FS::FileSystem* file_system, WorldEditor* world_editor)
|
||||||
bool create(const char* base_path, Engine& owner);
|
{
|
||||||
|
m_editor = world_editor;
|
||||||
|
if (NULL == file_system)
|
||||||
|
{
|
||||||
|
m_file_system = FS::FileSystem::create();
|
||||||
|
|
||||||
Renderer* m_renderer;
|
m_mem_file_device = LUMIX_NEW(FS::MemoryFileDevice);
|
||||||
FS::FileSystem* m_file_system;
|
m_disk_file_device = LUMIX_NEW(FS::DiskFileDevice);
|
||||||
FS::MemoryFileDevice* m_mem_file_device;
|
|
||||||
FS::DiskFileDevice* m_disk_file_device;
|
|
||||||
|
|
||||||
ResourceManager m_resource_manager;
|
m_file_system->mount(m_mem_file_device);
|
||||||
MaterialManager m_material_manager;
|
m_file_system->mount(m_disk_file_device);
|
||||||
ModelManager m_model_manager;
|
m_file_system->setDefaultDevice("memory:disk");
|
||||||
ShaderManager m_shader_manager;
|
m_file_system->setSaveGameDevice("memory:disk");
|
||||||
TextureManager m_texture_manager;
|
}
|
||||||
PipelineManager m_pipeline_manager;
|
else
|
||||||
AnimationManager m_animation_manager;
|
{
|
||||||
|
m_file_system = file_system;
|
||||||
|
m_mem_file_device = NULL;
|
||||||
|
m_disk_file_device = NULL;
|
||||||
|
}
|
||||||
MTJD::Manager m_mtjd_manager;
|
MTJD::Manager m_mtjd_manager;
|
||||||
// CullingSystem* m_culling_system;
|
// CullingSystem* m_culling_system;
|
||||||
|
|
||||||
string m_base_path;
|
m_resource_manager.create(*m_file_system);
|
||||||
WorldEditor* m_editor_server;
|
m_material_manager.create(ResourceManager::MATERIAL, m_resource_manager);
|
||||||
PluginManager m_plugin_manager;
|
m_model_manager.create(ResourceManager::MODEL, m_resource_manager);
|
||||||
Universe* m_universe;
|
m_shader_manager.create(ResourceManager::SHADER, m_resource_manager);
|
||||||
RenderScene* m_render_scene;
|
m_texture_manager.create(ResourceManager::TEXTURE, m_resource_manager);
|
||||||
InputSystem m_input_system;
|
m_pipeline_manager.create(ResourceManager::PIPELINE, m_resource_manager);
|
||||||
Engine& m_owner;
|
|
||||||
Timer* m_timer;
|
m_timer = Timer::create();
|
||||||
Timer* m_fps_timer;
|
m_fps_timer = Timer::create();
|
||||||
int m_fps_frame;
|
m_fps_frame = 0;
|
||||||
float m_fps;
|
m_universe = 0;
|
||||||
|
m_base_path = base_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool create()
|
||||||
|
{
|
||||||
|
if (!m_plugin_manager.create(*this))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_renderer = Renderer::createInstance();
|
||||||
|
if (!m_renderer)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_renderer->create(*this))
|
||||||
|
{
|
||||||
|
Renderer::destroyInstance(*m_renderer);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_plugin_manager.addPlugin(m_renderer);
|
||||||
|
if (!m_input_system.create())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual ~EngineImpl()
|
||||||
|
{
|
||||||
|
m_resource_manager.get(ResourceManager::TEXTURE)->releaseAll();
|
||||||
|
m_resource_manager.get(ResourceManager::MATERIAL)->releaseAll();
|
||||||
|
m_resource_manager.get(ResourceManager::SHADER)->releaseAll();
|
||||||
|
m_resource_manager.get(ResourceManager::MODEL)->releaseAll();
|
||||||
|
m_resource_manager.get(ResourceManager::PIPELINE)->releaseAll();
|
||||||
|
|
||||||
|
Timer::destroy(m_timer);
|
||||||
|
Timer::destroy(m_fps_timer);
|
||||||
|
m_plugin_manager.destroy();
|
||||||
|
m_input_system.destroy();
|
||||||
|
m_material_manager.destroy();
|
||||||
|
|
||||||
|
if (m_disk_file_device)
|
||||||
|
{
|
||||||
|
FS::FileSystem::destroy(m_file_system);
|
||||||
|
LUMIX_DELETE(m_mem_file_device);
|
||||||
|
LUMIX_DELETE(m_disk_file_device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual Universe* createUniverse() override
|
||||||
|
{
|
||||||
|
m_universe = LUMIX_NEW(Universe)();
|
||||||
|
const Array<IPlugin*>& plugins = m_plugin_manager.getPlugins();
|
||||||
|
for (int i = 0; i < plugins.size(); ++i)
|
||||||
|
{
|
||||||
|
IScene* scene = plugins[i]->createScene(*m_universe);
|
||||||
|
if (scene)
|
||||||
|
{
|
||||||
|
m_scenes.push(scene);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_universe;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual IScene* getScene(uint32_t type) const override
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_scenes.size(); ++i)
|
||||||
|
{
|
||||||
|
if (crc32(m_scenes[i]->getPlugin().getName()) == type)
|
||||||
|
{
|
||||||
|
return m_scenes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual const Array<IScene*>& getScenes() const override
|
||||||
|
{
|
||||||
|
return m_scenes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_impl->m_culling_system = CullingSystem::create(m_impl->m_mtjd_manager);
|
||||||
|
|
||||||
|
virtual void destroyUniverse() override
|
||||||
|
{
|
||||||
|
ASSERT(m_universe);
|
||||||
|
if (m_universe)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_scenes.size(); ++i)
|
||||||
|
{
|
||||||
|
LUMIX_DELETE(m_scenes[i]);
|
||||||
|
}
|
||||||
|
m_scenes.clear();
|
||||||
|
LUMIX_DELETE(m_universe);
|
||||||
|
m_universe = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual WorldEditor* getWorldEditor() const override
|
||||||
|
{
|
||||||
|
return m_editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual PluginManager& getPluginManager() override
|
||||||
|
{
|
||||||
|
return m_plugin_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual FS::FileSystem& getFileSystem() override
|
||||||
|
{
|
||||||
|
return *m_file_system;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual Renderer& getRenderer() override
|
||||||
|
{
|
||||||
|
return *m_renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void update(bool is_game_running) override
|
||||||
|
{
|
||||||
|
if (is_game_running)
|
||||||
|
{
|
||||||
|
++m_fps_frame;
|
||||||
|
if (m_fps_frame == 30)
|
||||||
|
{
|
||||||
|
m_fps = 30.0f / m_fps_timer->tick();
|
||||||
|
m_fps_frame = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float dt = m_timer->tick();
|
||||||
|
m_last_time_delta = dt;
|
||||||
|
for (int i = 0; i < m_scenes.size(); ++i)
|
||||||
|
{
|
||||||
|
m_scenes[i]->update(dt);
|
||||||
|
}
|
||||||
|
if (is_game_running)
|
||||||
|
{
|
||||||
|
m_plugin_manager.update(dt);
|
||||||
|
m_input_system.update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual IPlugin* loadPlugin(const char* name) override
|
||||||
|
{
|
||||||
|
return m_plugin_manager.load(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual InputSystem& getInputSystem() override
|
||||||
|
{
|
||||||
|
return m_input_system;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual const char* getBasePath() const override
|
||||||
|
{
|
||||||
|
return m_base_path.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual Universe* getUniverse() const override
|
||||||
|
{
|
||||||
|
return m_universe;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ResourceManager& getResourceManager() override
|
||||||
|
{
|
||||||
|
return m_resource_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual float getFPS() const override
|
||||||
|
{
|
||||||
|
return m_fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void serialize(ISerializer& serializer) override
|
||||||
|
{
|
||||||
|
m_universe->serialize(serializer);
|
||||||
|
m_renderer->serialize(serializer);
|
||||||
|
m_plugin_manager.serialize(serializer);
|
||||||
|
for (int i = 0; i < m_scenes.size(); ++i)
|
||||||
|
{
|
||||||
|
m_scenes[i]->serialize(serializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void deserialize(ISerializer& serializer) override
|
||||||
|
{
|
||||||
|
m_universe->deserialize(serializer);
|
||||||
|
m_renderer->deserialize(serializer);
|
||||||
|
m_plugin_manager.deserialize(serializer);
|
||||||
|
for (int i = 0; i < m_scenes.size(); ++i)
|
||||||
|
{
|
||||||
|
m_scenes[i]->deserialize(serializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual float getLastTimeDelta() override
|
||||||
|
{
|
||||||
|
return m_last_time_delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Renderer* m_renderer;
|
||||||
|
FS::FileSystem* m_file_system;
|
||||||
|
FS::MemoryFileDevice* m_mem_file_device;
|
||||||
|
FS::DiskFileDevice* m_disk_file_device;
|
||||||
|
|
||||||
|
ResourceManager m_resource_manager;
|
||||||
|
MaterialManager m_material_manager;
|
||||||
|
ModelManager m_model_manager;
|
||||||
|
ShaderManager m_shader_manager;
|
||||||
|
TextureManager m_texture_manager;
|
||||||
|
PipelineManager m_pipeline_manager;
|
||||||
|
|
||||||
|
string m_base_path;
|
||||||
|
WorldEditor* m_editor;
|
||||||
|
PluginManager m_plugin_manager;
|
||||||
|
Universe* m_universe;
|
||||||
|
Array<IScene*> m_scenes;
|
||||||
|
InputSystem m_input_system;
|
||||||
|
Timer* m_timer;
|
||||||
|
Timer* m_fps_timer;
|
||||||
|
int m_fps_frame;
|
||||||
|
float m_fps;
|
||||||
|
float m_last_time_delta;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void operator=(const EngineImpl&);
|
void operator=(const EngineImpl&);
|
||||||
|
@ -79,262 +324,25 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EngineImpl::~EngineImpl()
|
Engine* Engine::create(const char* base_path, FS::FileSystem* file_system, WorldEditor* editor)
|
||||||
{
|
|
||||||
m_resource_manager.get(ResourceManager::TEXTURE)->releaseAll();
|
|
||||||
m_resource_manager.get(ResourceManager::MATERIAL)->releaseAll();
|
|
||||||
m_resource_manager.get(ResourceManager::SHADER)->releaseAll();
|
|
||||||
m_resource_manager.get(ResourceManager::ANIMATION)->releaseAll();
|
|
||||||
m_resource_manager.get(ResourceManager::MODEL)->releaseAll();
|
|
||||||
m_resource_manager.get(ResourceManager::PIPELINE)->releaseAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool EngineImpl::create(const char* base_path, Engine& owner)
|
|
||||||
{
|
|
||||||
m_timer = Timer::create();
|
|
||||||
m_fps_timer = Timer::create();
|
|
||||||
m_fps_frame = 0;
|
|
||||||
m_universe = 0;
|
|
||||||
m_base_path = base_path;
|
|
||||||
m_render_scene = NULL;
|
|
||||||
|
|
||||||
m_renderer = Renderer::createInstance();
|
|
||||||
if(!m_renderer)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!m_renderer->create(owner))
|
|
||||||
{
|
|
||||||
Renderer::destroyInstance(*m_renderer);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(!m_plugin_manager.create(owner))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
AnimationSystem* anim_system = AnimationSystem::createInstance();
|
|
||||||
if(!anim_system->create(owner))
|
|
||||||
{
|
|
||||||
LUMIX_DELETE(anim_system);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
m_plugin_manager.addPlugin(anim_system);
|
|
||||||
if(!m_input_system.create())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Engine::create(const char* base_path, FS::FileSystem* file_system, WorldEditor* editor_server)
|
|
||||||
{
|
{
|
||||||
g_log_info.getCallback().bind<showLogInVS>();
|
g_log_info.getCallback().bind<showLogInVS>();
|
||||||
g_log_warning.getCallback().bind<showLogInVS>();
|
g_log_warning.getCallback().bind<showLogInVS>();
|
||||||
g_log_error.getCallback().bind<showLogInVS>();
|
g_log_error.getCallback().bind<showLogInVS>();
|
||||||
|
|
||||||
m_impl = LUMIX_NEW(EngineImpl)(*this);
|
EngineImpl* engine = LUMIX_NEW(EngineImpl)(base_path, file_system, editor);
|
||||||
m_impl->m_editor_server = editor_server;
|
if (!engine->create())
|
||||||
|
|
||||||
if(NULL == file_system)
|
|
||||||
{
|
{
|
||||||
m_impl->m_file_system = FS::FileSystem::create();
|
LUMIX_DELETE(engine);
|
||||||
|
return NULL;
|
||||||
m_impl->m_mem_file_device = LUMIX_NEW(FS::MemoryFileDevice);
|
|
||||||
m_impl->m_disk_file_device = LUMIX_NEW(FS::DiskFileDevice);
|
|
||||||
|
|
||||||
m_impl->m_file_system->mount(m_impl->m_mem_file_device);
|
|
||||||
m_impl->m_file_system->mount(m_impl->m_disk_file_device);
|
|
||||||
m_impl->m_file_system->setDefaultDevice("memory:disk");
|
|
||||||
m_impl->m_file_system->setSaveGameDevice("memory:disk");
|
|
||||||
}
|
}
|
||||||
else
|
return engine;
|
||||||
{
|
|
||||||
m_impl->m_file_system = file_system;
|
|
||||||
m_impl->m_mem_file_device = NULL;
|
|
||||||
m_impl->m_disk_file_device = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!m_impl->create(base_path, *this))
|
|
||||||
{
|
|
||||||
LUMIX_DELETE(m_impl);
|
|
||||||
m_impl = NULL;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_impl->m_resource_manager.create(*m_impl->m_file_system);
|
|
||||||
m_impl->m_material_manager.create(ResourceManager::MATERIAL, m_impl->m_resource_manager);
|
|
||||||
m_impl->m_model_manager.create(ResourceManager::MODEL, m_impl->m_resource_manager);
|
|
||||||
m_impl->m_shader_manager.create(ResourceManager::SHADER, m_impl->m_resource_manager);
|
|
||||||
m_impl->m_texture_manager.create(ResourceManager::TEXTURE, m_impl->m_resource_manager);
|
|
||||||
m_impl->m_pipeline_manager.create(ResourceManager::PIPELINE, m_impl->m_resource_manager);
|
|
||||||
m_impl->m_animation_manager.create(ResourceManager::ANIMATION, m_impl->m_resource_manager);
|
|
||||||
// m_impl->m_culling_system = CullingSystem::create(m_impl->m_mtjd_manager);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Engine::destroy()
|
void Engine::destroy(Engine* engine)
|
||||||
{
|
{
|
||||||
Timer::destroy(m_impl->m_timer);
|
LUMIX_DELETE(engine);
|
||||||
Timer::destroy(m_impl->m_fps_timer);
|
|
||||||
m_impl->m_plugin_manager.destroy();
|
|
||||||
Renderer::destroyInstance(*m_impl->m_renderer);
|
|
||||||
// CullingSystem::destroy(*m_impl->m_culling_system);
|
|
||||||
|
|
||||||
m_impl->m_input_system.destroy();
|
|
||||||
m_impl->m_material_manager.destroy();
|
|
||||||
|
|
||||||
if(m_impl->m_disk_file_device)
|
|
||||||
{
|
|
||||||
FS::FileSystem::destroy(m_impl->m_file_system);
|
|
||||||
LUMIX_DELETE(m_impl->m_mem_file_device);
|
|
||||||
LUMIX_DELETE(m_impl->m_disk_file_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
LUMIX_DELETE(m_impl);
|
|
||||||
m_impl = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Universe* Engine::createUniverse()
|
|
||||||
{
|
|
||||||
m_impl->m_universe = LUMIX_NEW(Universe)();
|
|
||||||
m_impl->m_render_scene = RenderScene::createInstance(*this, *m_impl->m_universe);
|
|
||||||
m_impl->m_plugin_manager.onCreateUniverse(*m_impl->m_universe);
|
|
||||||
m_impl->m_universe->create();
|
|
||||||
|
|
||||||
return m_impl->m_universe;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Engine::destroyUniverse()
|
|
||||||
{
|
|
||||||
ASSERT(m_impl->m_universe);
|
|
||||||
if (m_impl->m_universe)
|
|
||||||
{
|
|
||||||
m_impl->m_plugin_manager.onDestroyUniverse(*m_impl->m_universe);
|
|
||||||
m_impl->m_universe->destroy();
|
|
||||||
RenderScene::destroyInstance(m_impl->m_render_scene);
|
|
||||||
m_impl->m_render_scene = NULL;
|
|
||||||
LUMIX_DELETE(m_impl->m_universe);
|
|
||||||
m_impl->m_universe = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldEditor* Engine::getWorldEditor() const
|
|
||||||
{
|
|
||||||
return m_impl->m_editor_server;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PluginManager& Engine::getPluginManager()
|
|
||||||
{
|
|
||||||
return m_impl->m_plugin_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
FS::FileSystem& Engine::getFileSystem()
|
|
||||||
{
|
|
||||||
return *m_impl->m_file_system;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Renderer& Engine::getRenderer()
|
|
||||||
{
|
|
||||||
return *m_impl->m_renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Engine::update(bool is_game_running)
|
|
||||||
{
|
|
||||||
if (is_game_running)
|
|
||||||
{
|
|
||||||
++m_impl->m_fps_frame;
|
|
||||||
if (m_impl->m_fps_frame == 30)
|
|
||||||
{
|
|
||||||
m_impl->m_fps = 30.0f / m_impl->m_fps_timer->tick();
|
|
||||||
m_impl->m_fps_frame = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
float dt = m_impl->m_timer->tick();
|
|
||||||
m_impl->m_render_scene->update(dt);
|
|
||||||
if (is_game_running)
|
|
||||||
{
|
|
||||||
m_impl->m_plugin_manager.update(dt);
|
|
||||||
m_impl->m_input_system.update(dt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
IPlugin* Engine::loadPlugin(const char* name)
|
|
||||||
{
|
|
||||||
return m_impl->m_plugin_manager.load(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
InputSystem& Engine::getInputSystem()
|
|
||||||
{
|
|
||||||
return m_impl->m_input_system;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* Engine::getBasePath() const
|
|
||||||
{
|
|
||||||
return m_impl->m_base_path.c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Universe* Engine::getUniverse() const
|
|
||||||
{
|
|
||||||
return m_impl->m_universe;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RenderScene* Engine::getRenderScene() const
|
|
||||||
{
|
|
||||||
return m_impl->m_render_scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MTJD::Manager& Engine::getMTJDManager() const
|
|
||||||
{
|
|
||||||
return m_impl->m_mtjd_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//CullingSystem& Engine::getCullingSystem() const
|
|
||||||
//{
|
|
||||||
// return *m_impl->m_culling_system;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
ResourceManager& Engine::getResourceManager() const
|
|
||||||
{
|
|
||||||
return m_impl->m_resource_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Engine::getFPS() const
|
|
||||||
{
|
|
||||||
return m_impl->m_fps;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Engine::serialize(ISerializer& serializer)
|
|
||||||
{
|
|
||||||
m_impl->m_universe->serialize(serializer);
|
|
||||||
m_impl->m_renderer->serialize(serializer);
|
|
||||||
m_impl->m_render_scene->serialize(serializer);
|
|
||||||
m_impl->m_plugin_manager.serialize(serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Engine::deserialize(ISerializer& serializer)
|
|
||||||
{
|
|
||||||
m_impl->m_universe->deserialize(serializer);
|
|
||||||
m_impl->m_renderer->deserialize(serializer);
|
|
||||||
m_impl->m_render_scene->deserialize(serializer);
|
|
||||||
m_impl->m_plugin_manager.deserialize(serializer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include "core/lumix.h"
|
||||||
|
#include "core/array.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
namespace FS
|
namespace FS
|
||||||
|
@ -18,10 +22,10 @@ namespace Lumix
|
||||||
class EditorServer;
|
class EditorServer;
|
||||||
class InputSystem;
|
class InputSystem;
|
||||||
class IPlugin;
|
class IPlugin;
|
||||||
|
class IScene;
|
||||||
class ISerializer;
|
class ISerializer;
|
||||||
class PluginManager;
|
class PluginManager;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class RenderScene;
|
|
||||||
class ResourceManager;
|
class ResourceManager;
|
||||||
class Universe;
|
class Universe;
|
||||||
|
|
||||||
|
@ -29,36 +33,37 @@ namespace Lumix
|
||||||
class LUMIX_ENGINE_API Engine
|
class LUMIX_ENGINE_API Engine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Engine() { m_impl = NULL; }
|
virtual ~Engine() {}
|
||||||
~Engine() { ASSERT(m_impl == NULL); }
|
|
||||||
|
|
||||||
bool create(const char* base_path, FS::FileSystem* fs, WorldEditor* editor_server);
|
static Engine* create(const char* base_path, FS::FileSystem* fs, WorldEditor* editor);
|
||||||
void destroy();
|
static void destroy(Engine* engine);
|
||||||
|
|
||||||
Universe* createUniverse();
|
virtual Universe* createUniverse() = 0;
|
||||||
void destroyUniverse();
|
virtual void destroyUniverse() = 0;
|
||||||
|
|
||||||
WorldEditor* getWorldEditor() const;
|
virtual WorldEditor* getWorldEditor() const = 0;
|
||||||
FS::FileSystem& getFileSystem();
|
virtual FS::FileSystem& getFileSystem() = 0;
|
||||||
Renderer& getRenderer();
|
virtual Renderer& getRenderer() = 0;
|
||||||
InputSystem& getInputSystem();
|
virtual InputSystem& getInputSystem() = 0;
|
||||||
PluginManager& getPluginManager();
|
virtual PluginManager& getPluginManager() = 0;
|
||||||
IPlugin* loadPlugin(const char* name);
|
virtual IPlugin* loadPlugin(const char* name) = 0;
|
||||||
Universe* getUniverse() const;
|
virtual Universe* getUniverse() const = 0;
|
||||||
RenderScene* getRenderScene() const;
|
virtual const Array<IScene*>& getScenes() const = 0;
|
||||||
|
virtual IScene* getScene(uint32_t type) const = 0;
|
||||||
MTJD::Manager& getMTJDManager() const;
|
MTJD::Manager& getMTJDManager() const;
|
||||||
// CullingSystem& getCullingSystem() const;
|
// CullingSystem& getCullingSystem() const;
|
||||||
|
|
||||||
ResourceManager& getResourceManager() const;
|
virtual ResourceManager& getResourceManager() = 0;
|
||||||
|
|
||||||
const char* getBasePath() const;
|
virtual const char* getBasePath() const = 0;
|
||||||
void update(bool is_game_running);
|
virtual void update(bool is_game_running) = 0;
|
||||||
void serialize(ISerializer& serializer);
|
virtual void serialize(ISerializer& serializer) = 0;
|
||||||
void deserialize(ISerializer& serializer);
|
virtual void deserialize(ISerializer& serializer) = 0;
|
||||||
float getFPS() const;
|
virtual float getFPS() const = 0;
|
||||||
|
virtual float getLastTimeDelta() = 0;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
struct EngineImpl* m_impl;
|
Engine() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,25 @@
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
class Engine;
|
class Engine;
|
||||||
|
class IPlugin;
|
||||||
class ISerializer;
|
class ISerializer;
|
||||||
class Universe;
|
class Universe;
|
||||||
|
|
||||||
|
|
||||||
|
class LUMIX_ENGINE_API IScene abstract
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IScene() {}
|
||||||
|
|
||||||
|
virtual Component createComponent(uint32_t, const Entity&) = 0;
|
||||||
|
virtual void destroyComponent(const Component& component) = 0;
|
||||||
|
virtual void serialize(ISerializer& serializer) = 0;
|
||||||
|
virtual void deserialize(ISerializer& serializer) = 0;
|
||||||
|
virtual IPlugin& getPlugin() const = 0;
|
||||||
|
virtual void update(float time_delta) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class LUMIX_ENGINE_API IPlugin abstract
|
class LUMIX_ENGINE_API IPlugin abstract
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -19,15 +34,13 @@ namespace Lumix
|
||||||
|
|
||||||
virtual bool create(Engine& engine) = 0;
|
virtual bool create(Engine& engine) = 0;
|
||||||
virtual void destroy() = 0;
|
virtual void destroy() = 0;
|
||||||
virtual void onCreateUniverse(Universe&) {}
|
|
||||||
virtual void onDestroyUniverse(Universe&) {}
|
|
||||||
virtual void serialize(ISerializer&) {}
|
virtual void serialize(ISerializer&) {}
|
||||||
virtual void deserialize(ISerializer&) {}
|
virtual void deserialize(ISerializer&) {}
|
||||||
virtual void update(float) {}
|
virtual void update(float) {}
|
||||||
virtual Component createComponent(uint32_t, const Entity&) = 0;
|
|
||||||
virtual void destroyComponent(const Component& component) = 0;
|
|
||||||
virtual const char* getName() const = 0;
|
virtual const char* getName() const = 0;
|
||||||
virtual void sendMessage(const char*) {};
|
virtual void sendMessage(const char*) {};
|
||||||
|
|
||||||
|
virtual IScene* createScene(Universe&) { return NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -45,24 +45,9 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Array<IPlugin*>& PluginManager::getPlugins() const
|
||||||
void PluginManager::onDestroyUniverse(Universe& universe)
|
|
||||||
{
|
{
|
||||||
PluginManagerImpl::PluginList& plugins = m_impl->m_plugins;
|
return m_impl->m_plugins;
|
||||||
for(int i = 0, c = plugins.size(); i < c; ++i)
|
|
||||||
{
|
|
||||||
plugins[i]->onDestroyUniverse(universe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PluginManager::onCreateUniverse(Universe& universe)
|
|
||||||
{
|
|
||||||
PluginManagerImpl::PluginList& plugins = m_impl->m_plugins;
|
|
||||||
for(int i = 0, c = plugins.size(); i < c; ++i)
|
|
||||||
{
|
|
||||||
plugins[i]->onCreateUniverse(universe);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IPlugin* PluginManager::getPlugin(const char* name)
|
IPlugin* PluginManager::getPlugin(const char* name)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "core/lumix.h"
|
#include "core/lumix.h"
|
||||||
|
#include "core/array.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
|
@ -24,9 +25,8 @@ namespace Lumix
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
void serialize(ISerializer& serializer);
|
void serialize(ISerializer& serializer);
|
||||||
void deserialize(ISerializer& serializer);
|
void deserialize(ISerializer& serializer);
|
||||||
void onDestroyUniverse(Universe& universe);
|
|
||||||
void onCreateUniverse(Universe& universe);
|
|
||||||
IPlugin* getPlugin(const char* name);
|
IPlugin* getPlugin(const char* name);
|
||||||
|
const Array<IPlugin*>& getPlugins() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PluginManagerImpl* m_impl;
|
struct PluginManagerImpl* m_impl;
|
||||||
|
|
|
@ -110,7 +110,7 @@ int VertexDef::getPositionOffset() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VertexDef::begin(Shader& shader)
|
void VertexDef::begin(Shader& shader) const
|
||||||
{
|
{
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
@ -167,7 +167,7 @@ void VertexDef::begin(Shader& shader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void VertexDef::end(Shader& shader)
|
void VertexDef::end(Shader& shader) const
|
||||||
{
|
{
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
int shader_attrib_idx = 0;
|
int shader_attrib_idx = 0;
|
||||||
|
@ -215,17 +215,6 @@ float Geometry::getBoundingRadius() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Geometry::draw(int start, int count, Shader& shader)
|
|
||||||
{
|
|
||||||
PROFILE_FUNCTION();
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, m_id);
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indices_id);
|
|
||||||
m_vertex_definition.begin(shader);
|
|
||||||
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, (void*)(start * sizeof(GLint)));
|
|
||||||
m_vertex_definition.end(shader);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Geometry::Geometry()
|
Geometry::Geometry()
|
||||||
{
|
{
|
||||||
glGenBuffers(1, &m_id);
|
glGenBuffers(1, &m_id);
|
||||||
|
|
|
@ -34,8 +34,8 @@ struct VertexDef
|
||||||
void parse(const char* data, int size);
|
void parse(const char* data, int size);
|
||||||
int getVertexSize() const { return m_vertex_size; }
|
int getVertexSize() const { return m_vertex_size; }
|
||||||
int getPositionOffset() const;
|
int getPositionOffset() const;
|
||||||
void begin(Shader& shader);
|
void begin(Shader& shader) const;
|
||||||
void end(Shader& shader);
|
void end(Shader& shader) const;
|
||||||
VertexAttributeDef::Type getAttributeType(int i) const { return i < m_attribute_count ? m_attributes[i] : VertexAttributeDef::NONE; }
|
VertexAttributeDef::Type getAttributeType(int i) const { return i < m_attribute_count ? m_attributes[i] : VertexAttributeDef::NONE; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -58,11 +58,12 @@ class Geometry
|
||||||
|
|
||||||
void copy(const uint8_t* data, int size, const Array<int32_t>& indices, VertexDef vertex_definition);
|
void copy(const uint8_t* data, int size, const Array<int32_t>& indices, VertexDef vertex_definition);
|
||||||
void copy(const Geometry& source, int times, VertexCallback& vertex_callback, IndexCallback& index_callback);
|
void copy(const Geometry& source, int times, VertexCallback& vertex_callback, IndexCallback& index_callback);
|
||||||
void draw(int start, int count, Shader& shader);
|
|
||||||
const Array<Vec3>& getVertices() const { return m_vertices; }
|
const Array<Vec3>& getVertices() const { return m_vertices; }
|
||||||
const Array<int32_t>& getIndices() const { return m_indices; }
|
const Array<int32_t>& getIndices() const { return m_indices; }
|
||||||
float getBoundingRadius() const;
|
float getBoundingRadius() const;
|
||||||
const VertexDef& getVertexDefinition() const { return m_vertex_definition; }
|
const VertexDef& getVertexDefinition() const { return m_vertex_definition; }
|
||||||
|
GLuint getID() const { return m_id; }
|
||||||
|
GLuint getIndicesID() const { return m_indices_id; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint m_id;
|
GLuint m_id;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "graphics/material.h"
|
#include "graphics/material.h"
|
||||||
|
#include "core/crc32.h"
|
||||||
#include "core/fs/file_system.h"
|
#include "core/fs/file_system.h"
|
||||||
#include "core/fs/ifile.h"
|
#include "core/fs/ifile.h"
|
||||||
#include "core/json_serializer.h"
|
#include "core/json_serializer.h"
|
||||||
|
@ -18,16 +19,21 @@
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32_t SHADOWMAP_HASH = crc32("shadowmap");
|
||||||
|
|
||||||
|
|
||||||
Material::~Material()
|
Material::~Material()
|
||||||
{
|
{
|
||||||
ASSERT(isEmpty());
|
ASSERT(isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Material::apply(Renderer& renderer, PipelineInstance& pipeline)
|
void Material::apply(Renderer& renderer, PipelineInstance& pipeline) const
|
||||||
{
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
if(getState() == State::READY)
|
if(getState() == State::READY)
|
||||||
{
|
{
|
||||||
m_shader->apply();
|
renderer.applyShader(*m_shader);
|
||||||
switch (m_depth_func)
|
switch (m_depth_func)
|
||||||
{
|
{
|
||||||
case DepthFunc::LEQUAL:
|
case DepthFunc::LEQUAL:
|
||||||
|
@ -57,16 +63,16 @@ void Material::apply(Renderer& renderer, PipelineInstance& pipeline)
|
||||||
switch (uniform.m_type)
|
switch (uniform.m_type)
|
||||||
{
|
{
|
||||||
case Uniform::FLOAT:
|
case Uniform::FLOAT:
|
||||||
m_shader->setUniform(uniform.m_name, uniform.m_float);
|
renderer.setUniform(*m_shader, uniform.m_name, uniform.m_name_hash, uniform.m_float);
|
||||||
break;
|
break;
|
||||||
case Uniform::INT:
|
case Uniform::INT:
|
||||||
m_shader->setUniform(uniform.m_name, uniform.m_int);
|
renderer.setUniform(*m_shader, uniform.m_name, uniform.m_name_hash, uniform.m_int);
|
||||||
break;
|
break;
|
||||||
case Uniform::MATRIX:
|
case Uniform::MATRIX:
|
||||||
m_shader->setUniform(uniform.m_name, uniform.m_matrix);
|
renderer.setUniform(*m_shader, uniform.m_name, uniform.m_name_hash, uniform.m_matrix);
|
||||||
break;
|
break;
|
||||||
case Uniform::TIME:
|
case Uniform::TIME:
|
||||||
m_shader->setUniform(uniform.m_name, pipeline.getScene()->getTimer()->getTimeSinceStart());
|
renderer.setUniform(*m_shader, uniform.m_name, uniform.m_name_hash, pipeline.getScene()->getTimer()->getTimeSinceStart());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
|
@ -79,7 +85,7 @@ void Material::apply(Renderer& renderer, PipelineInstance& pipeline)
|
||||||
glActiveTexture(GL_TEXTURE0 + m_textures.size());
|
glActiveTexture(GL_TEXTURE0 + m_textures.size());
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glBindTexture(GL_TEXTURE_2D, pipeline.getShadowmapFramebuffer()->getDepthTexture());
|
glBindTexture(GL_TEXTURE_2D, pipeline.getShadowmapFramebuffer()->getDepthTexture());
|
||||||
m_shader->setUniform("shadowmap", m_textures.size());
|
renderer.setUniform(*m_shader, "shadowmap", SHADOWMAP_HASH, m_textures.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -123,6 +129,9 @@ bool Material::save(ISerializer& serializer)
|
||||||
PathUtils::getFilename(path, LUMIX_MAX_PATH, m_textures[i]->getPath().c_str());
|
PathUtils::getFilename(path, LUMIX_MAX_PATH, m_textures[i]->getPath().c_str());
|
||||||
serializer.serialize("texture", path);
|
serializer.serialize("texture", path);
|
||||||
}
|
}
|
||||||
|
serializer.serialize("alpha_to_coverage", m_is_alpha_to_coverage);
|
||||||
|
serializer.serialize("backface_culling", m_is_backface_culling);
|
||||||
|
serializer.serialize("z_test", m_is_z_test);
|
||||||
serializer.endObject();
|
serializer.endObject();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -142,6 +151,7 @@ void Material::deserializeUniforms(ISerializer& serializer)
|
||||||
if (strcmp(label, "name") == 0)
|
if (strcmp(label, "name") == 0)
|
||||||
{
|
{
|
||||||
serializer.deserialize(uniform.m_name, Uniform::MAX_NAME_LENGTH);
|
serializer.deserialize(uniform.m_name, Uniform::MAX_NAME_LENGTH);
|
||||||
|
uniform.m_name_hash = crc32(uniform.m_name);
|
||||||
}
|
}
|
||||||
else if (strcmp(label, "int_value") == 0)
|
else if (strcmp(label, "int_value") == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void apply(Renderer& renderer, PipelineInstance& pipeline);
|
void apply(Renderer& renderer, PipelineInstance& pipeline) const;
|
||||||
bool isZTest() const { return m_is_z_test; }
|
bool isZTest() const { return m_is_z_test; }
|
||||||
void enableZTest(bool enable) { m_is_z_test = enable; }
|
void enableZTest(bool enable) { m_is_z_test = enable; }
|
||||||
bool isBackfaceCulling() const { return m_is_backface_culling; }
|
bool isBackfaceCulling() const { return m_is_backface_culling; }
|
||||||
|
@ -48,6 +48,7 @@ public:
|
||||||
void addTexture(Texture* texture);
|
void addTexture(Texture* texture);
|
||||||
void setTexture(int i, Texture* texture);
|
void setTexture(int i, Texture* texture);
|
||||||
void removeTexture(int i);
|
void removeTexture(int i);
|
||||||
|
bool save(ISerializer& serializer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Material(const Path& path, ResourceManager& resource_manager)
|
Material(const Path& path, ResourceManager& resource_manager)
|
||||||
|
@ -61,7 +62,6 @@ private:
|
||||||
|
|
||||||
~Material();
|
~Material();
|
||||||
|
|
||||||
bool save(ISerializer& serializer);
|
|
||||||
virtual void doUnload(void) override;
|
virtual void doUnload(void) override;
|
||||||
virtual FS::ReadCallback getReadCallback() override;
|
virtual FS::ReadCallback getReadCallback() override;
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ private:
|
||||||
};
|
};
|
||||||
static const int MAX_NAME_LENGTH = 30;
|
static const int MAX_NAME_LENGTH = 30;
|
||||||
char m_name[MAX_NAME_LENGTH + 1];
|
char m_name[MAX_NAME_LENGTH + 1];
|
||||||
|
uint32_t m_name_hash;
|
||||||
Type m_type;
|
Type m_type;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
|
|
@ -318,7 +318,7 @@ void Model::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_log_info.log("renderer") << "Error loading model " << m_path.c_str();
|
g_log_warning.log("renderer") << "Error loading model " << m_path.c_str();
|
||||||
onFailure();
|
onFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,19 +39,23 @@ class Mesh
|
||||||
m_start = start;
|
m_start = start;
|
||||||
m_count = count;
|
m_count = count;
|
||||||
m_name_hash = crc32(name);
|
m_name_hash = crc32(name);
|
||||||
|
m_name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Material* getMaterial() const { return m_material; }
|
Material* getMaterial() const { return m_material; }
|
||||||
void setMaterial(Material* material) { m_material = material; }
|
void setMaterial(Material* material) { m_material = material; }
|
||||||
int getCount() const { return m_count; }
|
int getCount() const { return m_count; }
|
||||||
|
int getTriangleCount() const { return m_count / 3; }
|
||||||
int getStart() const { return m_start; }
|
int getStart() const { return m_start; }
|
||||||
uint32_t getNameHash() const { return m_name_hash; }
|
uint32_t getNameHash() const { return m_name_hash; }
|
||||||
|
const char* getName() const { return m_name.c_str(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int32_t m_start;
|
int32_t m_start;
|
||||||
int32_t m_count;
|
int32_t m_count;
|
||||||
uint32_t m_name_hash;
|
uint32_t m_name_hash;
|
||||||
Material* m_material;
|
Material* m_material;
|
||||||
|
string m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ class ModelInstance
|
||||||
Matrix& getMatrix() { return m_matrix; }
|
Matrix& getMatrix() { return m_matrix; }
|
||||||
Model* getModel() const { return m_model; }
|
Model* getModel() const { return m_model; }
|
||||||
Pose& getPose() { return m_pose; }
|
Pose& getPose() { return m_pose; }
|
||||||
|
const Pose& getPose() const { return m_pose; }
|
||||||
void setMatrix(const Matrix& mtx);
|
void setMatrix(const Matrix& mtx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -29,6 +29,17 @@ namespace Lumix
|
||||||
struct PipelineImpl;
|
struct PipelineImpl;
|
||||||
struct PipelineInstanceImpl;
|
struct PipelineInstanceImpl;
|
||||||
|
|
||||||
|
|
||||||
|
static const uint32_t SHADOW_MATRIX0_HASH = crc32("shadowmap_matrix0");
|
||||||
|
static const uint32_t SHADOW_MATRIX1_HASH = crc32("shadowmap_matrix1");
|
||||||
|
static const uint32_t SHADOW_MATRIX2_HASH = crc32("shadowmap_matrix2");
|
||||||
|
static const uint32_t SHADOW_MATRIX3_HASH = crc32("shadowmap_matrix3");
|
||||||
|
static const uint32_t LIGHT_DIR_HASH = crc32("light_dir");
|
||||||
|
static const uint32_t TERRAIN_SCALE_HASH = crc32("terrain_scale");
|
||||||
|
static const uint32_t BONE_MATRICES_HASH = crc32("bone_matrices");
|
||||||
|
static const uint32_t CAMERA_POS_HASH = crc32("camera_pos");
|
||||||
|
|
||||||
|
|
||||||
struct Command
|
struct Command
|
||||||
{
|
{
|
||||||
virtual ~Command() {}
|
virtual ~Command() {}
|
||||||
|
@ -276,7 +287,7 @@ struct PipelineImpl : public Pipeline
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_log_error.log("renderer") << "Unknown pipeline command " << tmp;
|
g_log_error.log("renderer") << "Unknown pipeline command \"" << tmp << "\" in pipeline " << getPath().c_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
|
@ -440,6 +451,7 @@ struct PipelineInstanceImpl : public PipelineInstance
|
||||||
|
|
||||||
void renderShadowmap(Component camera, int64_t layer_mask)
|
void renderShadowmap(Component camera, int64_t layer_mask)
|
||||||
{
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
ASSERT(m_renderer != NULL);
|
ASSERT(m_renderer != NULL);
|
||||||
Component light_cmp = m_scene->getLight(0);
|
Component light_cmp = m_scene->getLight(0);
|
||||||
if (!light_cmp.isValid() || !camera.isValid())
|
if (!light_cmp.isValid() || !camera.isValid())
|
||||||
|
@ -482,6 +494,7 @@ struct PipelineInstanceImpl : public PipelineInstance
|
||||||
);
|
);
|
||||||
m_shadow_modelviewprojection[split_index] = biasMatrix * (projection_matrix * modelview_matrix);
|
m_shadow_modelviewprojection[split_index] = biasMatrix * (projection_matrix * modelview_matrix);
|
||||||
|
|
||||||
|
renderTerrains(layer_mask);
|
||||||
renderModels(layer_mask);
|
renderModels(layer_mask);
|
||||||
}
|
}
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
@ -526,15 +539,7 @@ struct PipelineInstanceImpl : public PipelineInstance
|
||||||
|
|
||||||
void renderDebugLines()
|
void renderDebugLines()
|
||||||
{
|
{
|
||||||
// cleanup
|
m_renderer->cleanup();
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
glUseProgram(0);
|
|
||||||
for (int i = 0; i < 16; ++i)
|
|
||||||
{
|
|
||||||
glActiveTexture(GL_TEXTURE0 + i);
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
}
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
const Array<DebugLine>& lines = m_scene->getDebugLines();
|
const Array<DebugLine>& lines = m_scene->getDebugLines();
|
||||||
glBegin(GL_LINES);
|
glBegin(GL_LINES);
|
||||||
|
@ -552,26 +557,29 @@ struct PipelineInstanceImpl : public PipelineInstance
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
if (m_active_camera.isValid())
|
if (m_active_camera.isValid())
|
||||||
{
|
{
|
||||||
Material* last_material = NULL;
|
const Material* last_material = NULL;
|
||||||
m_grass_infos.clear();
|
m_grass_infos.clear();
|
||||||
m_scene->getGrassInfos(m_grass_infos, layer_mask);
|
m_scene->getGrassInfos(m_grass_infos, layer_mask);
|
||||||
for (int i = 0; i < m_grass_infos.size(); ++i)
|
for (int i = 0; i < m_grass_infos.size(); ++i)
|
||||||
{
|
{
|
||||||
Shader* shader = m_grass_infos[i].m_mesh->getMaterial()->getShader();
|
const GrassInfo& info = m_grass_infos[i];
|
||||||
if (m_grass_infos[i].m_mesh->getMaterial() != last_material)
|
const Mesh& mesh = *info.m_mesh;
|
||||||
|
const Material& material = *mesh.getMaterial();
|
||||||
|
Shader* shader = material.getShader();
|
||||||
|
if (&material != last_material)
|
||||||
{
|
{
|
||||||
m_grass_infos[i].m_mesh->getMaterial()->apply(*m_renderer, *this);
|
material.apply(*m_renderer, *this);
|
||||||
shader->setUniform("shadowmap_matrix0", m_shadow_modelviewprojection[0]);
|
m_renderer->setUniform(*shader, "shadowmap_matrix0", SHADOW_MATRIX0_HASH, m_shadow_modelviewprojection[0]);
|
||||||
shader->setUniform("shadowmap_matrix1", m_shadow_modelviewprojection[1]);
|
m_renderer->setUniform(*shader, "shadowmap_matrix1", SHADOW_MATRIX1_HASH, m_shadow_modelviewprojection[1]);
|
||||||
shader->setUniform("shadowmap_matrix2", m_shadow_modelviewprojection[2]);
|
m_renderer->setUniform(*shader, "shadowmap_matrix2", SHADOW_MATRIX2_HASH, m_shadow_modelviewprojection[2]);
|
||||||
shader->setUniform("shadowmap_matrix3", m_shadow_modelviewprojection[3]);
|
m_renderer->setUniform(*shader, "shadowmap_matrix3", SHADOW_MATRIX3_HASH, m_shadow_modelviewprojection[3]);
|
||||||
shader->setUniform("light_dir", m_light_dir);
|
m_renderer->setUniform(*shader, "light_dir", LIGHT_DIR_HASH, m_light_dir);
|
||||||
last_material = m_grass_infos[i].m_mesh->getMaterial();
|
m_renderer->setUniform(*shader, "camera_pos", CAMERA_POS_HASH, m_active_camera.entity.getPosition());
|
||||||
|
last_material = &material;
|
||||||
}
|
}
|
||||||
shader->setUniform("grass_matrices", m_grass_infos[i].m_matrices, m_grass_infos[i].m_matrix_count);
|
m_renderer->setFixedCachedUniform(*shader, (int)Shader::FixedCachedUniforms::GRASS_MATRICES, info.m_matrices, info.m_matrix_count);
|
||||||
|
|
||||||
Mesh& mesh = *m_grass_infos[i].m_mesh;
|
m_renderer->renderGeometry(*info.m_geometry, mesh.getStart(), mesh.getCount() / info.m_mesh_copy_count * info.m_matrix_count, *shader);
|
||||||
m_grass_infos[i].m_geometry->draw(mesh.getStart(), mesh.getCount() / m_grass_infos[i].m_mesh_copy_count * m_grass_infos[i].m_matrix_count, *shader);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -586,65 +594,79 @@ struct PipelineInstanceImpl : public PipelineInstance
|
||||||
Vec3 camera_position = m_active_camera.entity.getPosition();
|
Vec3 camera_position = m_active_camera.entity.getPosition();
|
||||||
for (int i = 0; i < m_terrain_infos.size(); ++i)
|
for (int i = 0; i < m_terrain_infos.size(); ++i)
|
||||||
{
|
{
|
||||||
if (m_terrain_infos[i].m_material && m_terrain_infos[i].m_material->getShader())
|
if (m_terrain_infos[i].m_material && m_terrain_infos[i].m_material->isReady())
|
||||||
{
|
{
|
||||||
Matrix world_matrix;
|
Matrix world_matrix;
|
||||||
m_terrain_infos[i].m_entity.getMatrix(world_matrix);
|
m_terrain_infos[i].m_entity.getMatrix(world_matrix);
|
||||||
Shader* shader = m_terrain_infos[i].m_material->getShader();
|
Shader* shader = m_terrain_infos[i].m_material->getShader();
|
||||||
m_terrain_infos[i].m_material->apply(*m_renderer, *this);
|
m_terrain_infos[i].m_material->apply(*m_renderer, *this);
|
||||||
shader->setUniform("world_matrix", world_matrix);
|
m_renderer->setFixedCachedUniform(*shader, (int)Shader::FixedCachedUniforms::WORLD_MATRIX, world_matrix);
|
||||||
shader->setUniform("shadowmap_matrix0", m_shadow_modelviewprojection[0]);
|
m_renderer->setUniform(*shader, "shadowmap_matrix0", SHADOW_MATRIX0_HASH, m_shadow_modelviewprojection[0]);
|
||||||
shader->setUniform("shadowmap_matrix1", m_shadow_modelviewprojection[1]);
|
m_renderer->setUniform(*shader, "shadowmap_matrix1", SHADOW_MATRIX1_HASH, m_shadow_modelviewprojection[1]);
|
||||||
shader->setUniform("shadowmap_matrix2", m_shadow_modelviewprojection[2]);
|
m_renderer->setUniform(*shader, "shadowmap_matrix2", SHADOW_MATRIX2_HASH, m_shadow_modelviewprojection[2]);
|
||||||
shader->setUniform("shadowmap_matrix3", m_shadow_modelviewprojection[3]);
|
m_renderer->setUniform(*shader, "shadowmap_matrix3", SHADOW_MATRIX3_HASH, m_shadow_modelviewprojection[3]);
|
||||||
shader->setUniform("light_dir", m_light_dir);
|
m_renderer->setUniform(*shader, "light_dir", LIGHT_DIR_HASH, m_light_dir);
|
||||||
|
|
||||||
Vec3 scale;
|
Vec3 scale;
|
||||||
scale.x = m_terrain_infos[i].m_xz_scale;
|
scale.x = m_terrain_infos[i].m_xz_scale;
|
||||||
scale.y = m_terrain_infos[i].m_y_scale;
|
scale.y = m_terrain_infos[i].m_y_scale;
|
||||||
scale.z = scale.x;
|
scale.z = scale.x;
|
||||||
m_terrain_infos[i].m_material->getShader()->setUniform("terrain_scale", scale);
|
m_renderer->setUniform(*shader, "terrain_scale", TERRAIN_SCALE_HASH, scale);
|
||||||
m_scene->renderTerrain(m_terrain_infos[i], *m_renderer, *this, camera_position);
|
m_scene->renderTerrain(m_terrain_infos[i], *m_renderer, *this, camera_position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sortRenderables(Array<RenderableInfo>& infos)
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
if (!infos.empty())
|
||||||
|
{
|
||||||
|
qsort(&infos[0], infos.size(), sizeof(RenderableInfo), [](const void* a, const void* b) -> int
|
||||||
|
{
|
||||||
|
const RenderableInfo* info1 = static_cast<const RenderableInfo*>(a);
|
||||||
|
const RenderableInfo* info2 = static_cast<const RenderableInfo*>(b);
|
||||||
|
return (int)(info1->m_mesh - info2->m_mesh);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void renderModels(int64_t layer_mask)
|
void renderModels(int64_t layer_mask)
|
||||||
{
|
{
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
ASSERT(m_renderer != NULL);
|
|
||||||
renderTerrains(layer_mask);
|
|
||||||
|
|
||||||
m_renderable_infos.clear();
|
m_renderable_infos.clear();
|
||||||
m_scene->getRenderableInfos(m_renderable_infos, layer_mask);
|
m_scene->getRenderableInfos(m_renderable_infos, layer_mask);
|
||||||
int count = m_renderable_infos.size();
|
int count = m_renderable_infos.size();
|
||||||
Material* last_material = NULL;
|
const Material* last_material = NULL;
|
||||||
|
sortRenderables(m_renderable_infos);
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
glPushMatrix();
|
const RenderableInfo& info = m_renderable_infos[i];
|
||||||
Matrix world_matrix = m_renderable_infos[i].m_model ? m_renderable_infos[i].m_model->getMatrix() : *m_renderable_infos[i].m_matrix;
|
const Matrix& world_matrix = info.m_model->getMatrix();
|
||||||
world_matrix.multiply3x3(m_renderable_infos[i].m_scale);
|
const Mesh& mesh = *info.m_mesh;
|
||||||
glMultMatrixf(&world_matrix.m11);
|
const Material& material = *mesh.getMaterial();
|
||||||
|
Shader& shader = *material.getShader();
|
||||||
|
|
||||||
Mesh& mesh = *m_renderable_infos[i].m_mesh;
|
|
||||||
Material& material = *mesh.getMaterial();
|
|
||||||
if (last_material != &material)
|
if (last_material != &material)
|
||||||
{
|
{
|
||||||
material.apply(*m_renderer, *this);
|
material.apply(*m_renderer, *this);
|
||||||
material.getShader()->setUniform("world_matrix", world_matrix);
|
m_renderer->setUniform(shader, "shadowmap_matrix0", SHADOW_MATRIX0_HASH, m_shadow_modelviewprojection[0]);
|
||||||
material.getShader()->setUniform("shadowmap_matrix0", m_shadow_modelviewprojection[0]);
|
m_renderer->setUniform(shader, "shadowmap_matrix1", SHADOW_MATRIX1_HASH, m_shadow_modelviewprojection[1]);
|
||||||
material.getShader()->setUniform("shadowmap_matrix1", m_shadow_modelviewprojection[1]);
|
m_renderer->setUniform(shader, "shadowmap_matrix2", SHADOW_MATRIX2_HASH, m_shadow_modelviewprojection[2]);
|
||||||
material.getShader()->setUniform("shadowmap_matrix2", m_shadow_modelviewprojection[2]);
|
m_renderer->setUniform(shader, "shadowmap_matrix3", SHADOW_MATRIX3_HASH, m_shadow_modelviewprojection[3]);
|
||||||
material.getShader()->setUniform("shadowmap_matrix3", m_shadow_modelviewprojection[3]);
|
m_renderer->setUniform(shader, "light_dir", LIGHT_DIR_HASH, m_light_dir);
|
||||||
material.getShader()->setUniform("light_dir", m_light_dir);
|
|
||||||
last_material = &material;
|
last_material = &material;
|
||||||
}
|
}
|
||||||
|
m_renderer->setFixedCachedUniform(shader, (int)Shader::FixedCachedUniforms::WORLD_MATRIX, world_matrix);
|
||||||
|
|
||||||
static Matrix bone_mtx[64];
|
static Matrix bone_mtx[64];
|
||||||
if (m_renderable_infos[i].m_pose)
|
if (info.m_pose->getCount() > 0)
|
||||||
{
|
{
|
||||||
const Pose& pose = *m_renderable_infos[i].m_pose;
|
const Pose& pose = *info.m_pose;
|
||||||
const Model& model = *m_renderable_infos[i].m_model->getModel();
|
const Model& model = *info.m_model->getModel();
|
||||||
Vec3* poss = pose.getPositions();
|
Vec3* poss = pose.getPositions();
|
||||||
Quat* rots = pose.getRotations();
|
Quat* rots = pose.getRotations();
|
||||||
ASSERT(pose.getCount() <= 64);
|
ASSERT(pose.getCount() <= 64);
|
||||||
|
@ -654,14 +676,11 @@ struct PipelineInstanceImpl : public PipelineInstance
|
||||||
bone_mtx[bone_index].translate(poss[bone_index]);
|
bone_mtx[bone_index].translate(poss[bone_index]);
|
||||||
bone_mtx[bone_index] = bone_mtx[bone_index] * model.getBone(bone_index).inv_bind_matrix;
|
bone_mtx[bone_index] = bone_mtx[bone_index] * model.getBone(bone_index).inv_bind_matrix;
|
||||||
}
|
}
|
||||||
material.getShader()->setUniform("bone_matrices", bone_mtx, pose.getCount());
|
m_renderer->setUniform(shader, "bone_matrices", BONE_MATRICES_HASH, bone_mtx, pose.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderable_infos[i].m_geometry->draw(mesh.getStart(), mesh.getCount(), *material.getShader());
|
m_renderer->renderGeometry(*m_renderable_infos[i].m_geometry, mesh.getStart(), mesh.getCount(), *material.getShader());
|
||||||
glPopMatrix();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderGrass(layer_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void resize(int w, int h) override
|
virtual void resize(int w, int h) override
|
||||||
|
@ -789,7 +808,10 @@ void RenderModelsCommand::deserialize(PipelineImpl&, ISerializer& serializer)
|
||||||
|
|
||||||
void RenderModelsCommand::execute(PipelineInstanceImpl& pipeline)
|
void RenderModelsCommand::execute(PipelineInstanceImpl& pipeline)
|
||||||
{
|
{
|
||||||
|
pipeline.renderTerrains(m_layer_mask);
|
||||||
pipeline.renderModels(m_layer_mask);
|
pipeline.renderModels(m_layer_mask);
|
||||||
|
pipeline.renderGrass(m_layer_mask);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,6 @@ void Pose::computeAbsolute(Model& model, int i, bool* valid)
|
||||||
|
|
||||||
void Pose::computeAbsolute(Model& model)
|
void Pose::computeAbsolute(Model& model)
|
||||||
{
|
{
|
||||||
/// TODO remove recursion
|
|
||||||
if(!m_is_absolute)
|
if(!m_is_absolute)
|
||||||
{
|
{
|
||||||
ASSERT(m_count < 256);
|
ASSERT(m_count < 256);
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct Quat;
|
||||||
struct Vec3;
|
struct Vec3;
|
||||||
|
|
||||||
|
|
||||||
class Pose
|
class LUMIX_ENGINE_API Pose
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Pose();
|
Pose();
|
||||||
|
|
|
@ -44,11 +44,11 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
Renderable() {}
|
Renderable() {}
|
||||||
|
|
||||||
|
bool m_is_free;
|
||||||
|
int64_t m_layer_mask;
|
||||||
ModelInstance m_model;
|
ModelInstance m_model;
|
||||||
Entity m_entity;
|
Entity m_entity;
|
||||||
int64_t m_layer_mask;
|
|
||||||
float m_scale;
|
float m_scale;
|
||||||
bool m_is_free;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Renderable(const Renderable&) {}
|
Renderable(const Renderable&) {}
|
||||||
|
@ -64,6 +64,7 @@ namespace Lumix
|
||||||
|
|
||||||
Type m_type;
|
Type m_type;
|
||||||
Entity m_entity;
|
Entity m_entity;
|
||||||
|
bool m_is_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Camera
|
struct Camera
|
||||||
|
@ -78,15 +79,17 @@ namespace Lumix
|
||||||
float m_width;
|
float m_width;
|
||||||
float m_height;
|
float m_height;
|
||||||
bool m_is_active;
|
bool m_is_active;
|
||||||
|
bool m_is_free;
|
||||||
char m_slot[MAX_SLOT_LENGTH + 1];
|
char m_slot[MAX_SLOT_LENGTH + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderSceneImpl : public RenderScene
|
class RenderSceneImpl : public RenderScene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderSceneImpl(Engine& engine, Universe& universe)
|
RenderSceneImpl(Renderer& renderer, Engine& engine, Universe& universe)
|
||||||
: m_engine(engine)
|
: m_engine(engine)
|
||||||
, m_universe(universe)
|
, m_universe(universe)
|
||||||
|
, m_renderer(renderer)
|
||||||
{
|
{
|
||||||
m_universe.entityMoved().bind<RenderSceneImpl, &RenderSceneImpl::onEntityMoved>(this);
|
m_universe.entityMoved().bind<RenderSceneImpl, &RenderSceneImpl::onEntityMoved>(this);
|
||||||
m_timer = Timer::create();
|
m_timer = Timer::create();
|
||||||
|
@ -110,6 +113,11 @@ namespace Lumix
|
||||||
CullingSystem::destroy(*m_culling_system);
|
CullingSystem::destroy(*m_culling_system);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual IPlugin& getPlugin() const override
|
||||||
|
{
|
||||||
|
return m_renderer;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void getRay(Component camera, float x, float y, Vec3& origin, Vec3& dir) override
|
virtual void getRay(Component camera, float x, float y, Vec3& origin, Vec3& dir) override
|
||||||
{
|
{
|
||||||
Vec3 camera_pos = camera.entity.getPosition();
|
Vec3 camera_pos = camera.entity.getPosition();
|
||||||
|
@ -145,7 +153,7 @@ namespace Lumix
|
||||||
float height = m_cameras[cmp.index].m_height;
|
float height = m_cameras[cmp.index].m_height;
|
||||||
float near_plane = m_cameras[cmp.index].m_near;
|
float near_plane = m_cameras[cmp.index].m_near;
|
||||||
float far_plane = m_cameras[cmp.index].m_far;
|
float far_plane = m_cameras[cmp.index].m_far;
|
||||||
m_engine.getRenderer().setProjection(width, height, fov, near_plane, far_plane, mtx);
|
m_renderer.setProjection(width, height, fov, near_plane, far_plane, mtx);
|
||||||
|
|
||||||
m_camera_frustum.compute(
|
m_camera_frustum.compute(
|
||||||
mtx.getTranslation(),
|
mtx.getTranslation(),
|
||||||
|
@ -250,6 +258,7 @@ namespace Lumix
|
||||||
serializer.beginArray("cameras");
|
serializer.beginArray("cameras");
|
||||||
for (int i = 0; i < m_cameras.size(); ++i)
|
for (int i = 0; i < m_cameras.size(); ++i)
|
||||||
{
|
{
|
||||||
|
serializer.serializeArrayItem(m_cameras[i].m_is_free);
|
||||||
serializer.serializeArrayItem(m_cameras[i].m_far);
|
serializer.serializeArrayItem(m_cameras[i].m_far);
|
||||||
serializer.serializeArrayItem(m_cameras[i].m_near);
|
serializer.serializeArrayItem(m_cameras[i].m_near);
|
||||||
serializer.serializeArrayItem(m_cameras[i].m_fov);
|
serializer.serializeArrayItem(m_cameras[i].m_fov);
|
||||||
|
@ -270,6 +279,7 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
serializer.serializeArrayItem(m_lights[i].m_entity.index);
|
serializer.serializeArrayItem(m_lights[i].m_entity.index);
|
||||||
serializer.serializeArrayItem((int32_t)m_lights[i].m_type);
|
serializer.serializeArrayItem((int32_t)m_lights[i].m_type);
|
||||||
|
serializer.serializeArrayItem(m_lights[i].m_is_free);
|
||||||
}
|
}
|
||||||
serializer.endArray();
|
serializer.endArray();
|
||||||
}
|
}
|
||||||
|
@ -280,22 +290,25 @@ namespace Lumix
|
||||||
serializer.beginArray("renderables");
|
serializer.beginArray("renderables");
|
||||||
for (int i = 0; i < m_renderables.size(); ++i)
|
for (int i = 0; i < m_renderables.size(); ++i)
|
||||||
{
|
{
|
||||||
serializer.serializeArrayItem(m_renderables[i]->m_entity.index);
|
|
||||||
serializer.serializeArrayItem(m_renderables[i]->m_layer_mask);
|
|
||||||
serializer.serializeArrayItem(m_renderables[i]->m_is_free);
|
serializer.serializeArrayItem(m_renderables[i]->m_is_free);
|
||||||
if (m_renderables[i]->m_model.getModel())
|
if(!m_renderables[i]->m_is_free)
|
||||||
{
|
{
|
||||||
serializer.serializeArrayItem(m_renderables[i]->m_model.getModel()->getPath().c_str());
|
serializer.serializeArrayItem(m_renderables[i]->m_entity.index);
|
||||||
}
|
serializer.serializeArrayItem(m_renderables[i]->m_layer_mask);
|
||||||
else
|
if (m_renderables[i]->m_model.getModel())
|
||||||
{
|
{
|
||||||
serializer.serializeArrayItem("");
|
serializer.serializeArrayItem(m_renderables[i]->m_model.getModel()->getPath().c_str());
|
||||||
}
|
}
|
||||||
serializer.serializeArrayItem(m_renderables[i]->m_scale);
|
else
|
||||||
Matrix mtx = m_renderables[i]->m_model.getMatrix();
|
{
|
||||||
for (int j = 0; j < 16; ++j)
|
serializer.serializeArrayItem("");
|
||||||
{
|
}
|
||||||
serializer.serializeArrayItem((&mtx.m11)[j]);
|
serializer.serializeArrayItem(m_renderables[i]->m_scale);
|
||||||
|
Matrix mtx = m_renderables[i]->m_model.getMatrix();
|
||||||
|
for (int j = 0; j < 16; ++j)
|
||||||
|
{
|
||||||
|
serializer.serializeArrayItem((&mtx.m11)[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serializer.endArray();
|
serializer.endArray();
|
||||||
|
@ -307,7 +320,15 @@ namespace Lumix
|
||||||
serializer.beginArray("terrains");
|
serializer.beginArray("terrains");
|
||||||
for (int i = 0; i < m_terrains.size(); ++i)
|
for (int i = 0; i < m_terrains.size(); ++i)
|
||||||
{
|
{
|
||||||
m_terrains[i]->serialize(serializer);
|
if(m_terrains[i])
|
||||||
|
{
|
||||||
|
serializer.serializeArrayItem(true);
|
||||||
|
m_terrains[i]->serialize(serializer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serializer.serializeArrayItem(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.endArray();
|
serializer.endArray();
|
||||||
}
|
}
|
||||||
|
@ -328,6 +349,7 @@ namespace Lumix
|
||||||
m_cameras.resize(size);
|
m_cameras.resize(size);
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
|
serializer.deserializeArrayItem(m_cameras[i].m_is_free);
|
||||||
serializer.deserializeArrayItem(m_cameras[i].m_far);
|
serializer.deserializeArrayItem(m_cameras[i].m_far);
|
||||||
serializer.deserializeArrayItem(m_cameras[i].m_near);
|
serializer.deserializeArrayItem(m_cameras[i].m_near);
|
||||||
serializer.deserializeArrayItem(m_cameras[i].m_fov);
|
serializer.deserializeArrayItem(m_cameras[i].m_fov);
|
||||||
|
@ -338,7 +360,10 @@ namespace Lumix
|
||||||
serializer.deserializeArrayItem(m_cameras[i].m_entity.index);
|
serializer.deserializeArrayItem(m_cameras[i].m_entity.index);
|
||||||
m_cameras[i].m_entity.universe = &m_universe;
|
m_cameras[i].m_entity.universe = &m_universe;
|
||||||
serializer.deserializeArrayItem(m_cameras[i].m_slot, Camera::MAX_SLOT_LENGTH);
|
serializer.deserializeArrayItem(m_cameras[i].m_slot, Camera::MAX_SLOT_LENGTH);
|
||||||
m_universe.addComponent(m_cameras[i].m_entity, CAMERA_HASH, this, i);
|
if(!m_cameras[i].m_is_free)
|
||||||
|
{
|
||||||
|
m_universe.addComponent(m_cameras[i].m_entity, CAMERA_HASH, this, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
}
|
}
|
||||||
|
@ -360,21 +385,22 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
serializer.deserializeArrayItem(m_renderables[i]->m_entity.index);
|
|
||||||
m_renderables[i]->m_entity.universe = &m_universe;
|
|
||||||
serializer.deserializeArrayItem(m_renderables[i]->m_layer_mask);
|
|
||||||
serializer.deserializeArrayItem(m_renderables[i]->m_is_free);
|
serializer.deserializeArrayItem(m_renderables[i]->m_is_free);
|
||||||
char path[LUMIX_MAX_PATH];
|
if(!m_renderables[i]->m_is_free)
|
||||||
serializer.deserializeArrayItem(path, LUMIX_MAX_PATH);
|
|
||||||
serializer.deserializeArrayItem(m_renderables[i]->m_scale);
|
|
||||||
m_renderables[i]->m_model.setModel(static_cast<Model*>(m_engine.getResourceManager().get(ResourceManager::MODEL)->load(path)));
|
|
||||||
for (int j = 0; j < 16; ++j)
|
|
||||||
{
|
{
|
||||||
serializer.deserializeArrayItem((&m_renderables[i]->m_model.getMatrix().m11)[j]);
|
serializer.deserializeArrayItem(m_renderables[i]->m_entity.index);
|
||||||
|
m_renderables[i]->m_entity.universe = &m_universe;
|
||||||
|
serializer.deserializeArrayItem(m_renderables[i]->m_layer_mask);
|
||||||
|
char path[LUMIX_MAX_PATH];
|
||||||
|
serializer.deserializeArrayItem(path, LUMIX_MAX_PATH);
|
||||||
|
serializer.deserializeArrayItem(m_renderables[i]->m_scale);
|
||||||
|
m_renderables[i]->m_model.setModel(static_cast<Model*>(m_engine.getResourceManager().get(ResourceManager::MODEL)->load(path)));
|
||||||
|
for (int j = 0; j < 16; ++j)
|
||||||
|
{
|
||||||
|
serializer.deserializeArrayItem((&m_renderables[i]->m_model.getMatrix().m11)[j]);
|
||||||
|
}
|
||||||
|
m_universe.addComponent(m_renderables[i]->m_entity, RENDERABLE_HASH, this, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_culling_system->addStatic(Sphere(m_renderables[i]->m_entity.getPosition(), 1.0f), i);
|
|
||||||
m_universe.addComponent(m_renderables[i]->m_entity, RENDERABLE_HASH, this, i);
|
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
}
|
}
|
||||||
|
@ -390,7 +416,11 @@ namespace Lumix
|
||||||
serializer.deserializeArrayItem(m_lights[i].m_entity.index);
|
serializer.deserializeArrayItem(m_lights[i].m_entity.index);
|
||||||
m_lights[i].m_entity.universe = &m_universe;
|
m_lights[i].m_entity.universe = &m_universe;
|
||||||
serializer.deserializeArrayItem((int32_t&)m_lights[i].m_type);
|
serializer.deserializeArrayItem((int32_t&)m_lights[i].m_type);
|
||||||
m_universe.addComponent(m_lights[i].m_entity, LIGHT_HASH, this, i);
|
serializer.deserializeArrayItem(m_lights[i].m_is_free);
|
||||||
|
if(!m_lights[i].m_is_free)
|
||||||
|
{
|
||||||
|
m_universe.addComponent(m_lights[i].m_entity, LIGHT_HASH, this, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
}
|
}
|
||||||
|
@ -403,17 +433,23 @@ namespace Lumix
|
||||||
for (int i = size; i < m_terrains.size(); ++i)
|
for (int i = size; i < m_terrains.size(); ++i)
|
||||||
{
|
{
|
||||||
LUMIX_DELETE(m_terrains[i]);
|
LUMIX_DELETE(m_terrains[i]);
|
||||||
|
m_terrains[i] = NULL;
|
||||||
}
|
}
|
||||||
int old_size = m_terrains.size();
|
|
||||||
m_terrains.resize(size);
|
m_terrains.resize(size);
|
||||||
for (int i = old_size; i < size; ++i)
|
|
||||||
{
|
|
||||||
m_terrains[i] = LUMIX_NEW(Terrain)(Entity::INVALID, *this);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
{
|
{
|
||||||
Terrain* terrain = m_terrains[i];
|
bool exists;
|
||||||
terrain->deserialize(serializer, m_universe, *this, i);
|
serializer.deserializeArrayItem(exists);
|
||||||
|
if(exists)
|
||||||
|
{
|
||||||
|
m_terrains[i] = LUMIX_NEW(Terrain)(Entity::INVALID, *this);
|
||||||
|
Terrain* terrain = m_terrains[i];
|
||||||
|
terrain->deserialize(serializer, m_universe, *this, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_terrains[i] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
}
|
}
|
||||||
|
@ -433,7 +469,26 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
m_renderables[component.index]->m_model.setModel(NULL);
|
m_renderables[component.index]->m_model.setModel(NULL);
|
||||||
m_renderables[component.index]->m_is_free = true;
|
m_renderables[component.index]->m_is_free = true;
|
||||||
m_universe.removeComponent(component);
|
m_universe.destroyComponent(component);
|
||||||
|
m_universe.componentDestroyed().invoke(component);
|
||||||
|
}
|
||||||
|
else if (component.type == LIGHT_HASH)
|
||||||
|
{
|
||||||
|
m_lights[component.index].m_is_free = true;
|
||||||
|
m_universe.destroyComponent(component);
|
||||||
|
m_universe.componentDestroyed().invoke(component);
|
||||||
|
}
|
||||||
|
else if (component.type == CAMERA_HASH)
|
||||||
|
{
|
||||||
|
m_cameras[component.index].m_is_free = true;
|
||||||
|
m_universe.destroyComponent(component);
|
||||||
|
m_universe.componentDestroyed().invoke(component);
|
||||||
|
}
|
||||||
|
else if(component.type == TERRAIN_HASH)
|
||||||
|
{
|
||||||
|
LUMIX_DELETE(m_terrains[component.index]);
|
||||||
|
m_terrains[component.index] = NULL;
|
||||||
|
m_universe.destroyComponent(component);
|
||||||
m_universe.componentDestroyed().invoke(component);
|
m_universe.componentDestroyed().invoke(component);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -457,6 +512,7 @@ namespace Lumix
|
||||||
else if (type == CAMERA_HASH)
|
else if (type == CAMERA_HASH)
|
||||||
{
|
{
|
||||||
Camera& camera = m_cameras.pushEmpty();
|
Camera& camera = m_cameras.pushEmpty();
|
||||||
|
camera.m_is_free = false;
|
||||||
camera.m_is_active = false;
|
camera.m_is_active = false;
|
||||||
camera.m_entity = entity;
|
camera.m_entity = entity;
|
||||||
camera.m_fov = 60;
|
camera.m_fov = 60;
|
||||||
|
@ -505,15 +561,15 @@ namespace Lumix
|
||||||
Light& light = m_lights.pushEmpty();
|
Light& light = m_lights.pushEmpty();
|
||||||
light.m_type = Light::Type::DIRECTIONAL;
|
light.m_type = Light::Type::DIRECTIONAL;
|
||||||
light.m_entity = entity;
|
light.m_entity = entity;
|
||||||
|
light.m_is_free = false;
|
||||||
Component cmp = m_universe.addComponent(entity, type, this, m_lights.size() - 1);
|
Component cmp = m_universe.addComponent(entity, type, this, m_lights.size() - 1);
|
||||||
m_universe.componentCreated().invoke(cmp);
|
m_universe.componentCreated().invoke(cmp);
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
ASSERT(false);
|
|
||||||
return Component::INVALID;
|
return Component::INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onEntityMoved(Entity& entity)
|
void onEntityMoved(const Entity& entity)
|
||||||
{
|
{
|
||||||
const Entity::ComponentList& cmps = entity.getComponents();
|
const Entity::ComponentList& cmps = entity.getComponents();
|
||||||
for (int i = 0; i < cmps.size(); ++i)
|
for (int i = 0; i < cmps.size(); ++i)
|
||||||
|
@ -540,6 +596,12 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual float getTerrainHeightAt(Component cmp, float x, float z) override
|
||||||
|
{
|
||||||
|
return m_terrains[cmp.index]->getHeight(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void setTerrainMaterial(Component cmp, const string& path) override
|
virtual void setTerrainMaterial(Component cmp, const string& path) override
|
||||||
{
|
{
|
||||||
Material* material = static_cast<Material*>(m_engine.getResourceManager().get(ResourceManager::MATERIAL)->load(path.c_str()));
|
Material* material = static_cast<Material*>(m_engine.getResourceManager().get(ResourceManager::MATERIAL)->load(path.c_str()));
|
||||||
|
@ -547,6 +609,12 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual Material* getTerrainMaterial(Component cmp) override
|
||||||
|
{
|
||||||
|
return m_terrains[cmp.index]->getMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void getTerrainMaterial(Component cmp, string& path) override
|
virtual void getTerrainMaterial(Component cmp, string& path) override
|
||||||
{
|
{
|
||||||
if (m_terrains[cmp.index]->getMaterial())
|
if (m_terrains[cmp.index]->getMaterial())
|
||||||
|
@ -560,25 +628,25 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void setTerrainXZScale(Component cmp, const float& scale) override
|
virtual void setTerrainXZScale(Component cmp, float scale) override
|
||||||
{
|
{
|
||||||
m_terrains[cmp.index]->setXZScale(scale);
|
m_terrains[cmp.index]->setXZScale(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getTerrainXZScale(Component cmp, float& scale) override
|
virtual float getTerrainXZScale(Component cmp) override
|
||||||
{
|
{
|
||||||
scale = m_terrains[cmp.index]->getXZScale();
|
return m_terrains[cmp.index]->getXZScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void setTerrainYScale(Component cmp, const float& scale) override
|
virtual void setTerrainYScale(Component cmp, float scale) override
|
||||||
{
|
{
|
||||||
m_terrains[cmp.index]->setYScale(scale);
|
m_terrains[cmp.index]->setYScale(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getTerrainYScale(Component cmp, float& scale)
|
virtual float getTerrainYScale(Component cmp)
|
||||||
{
|
{
|
||||||
scale = m_terrains[cmp.index]->getYScale();
|
return m_terrains[cmp.index]->getYScale();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -611,7 +679,7 @@ namespace Lumix
|
||||||
m_renderables[cmp.index]->m_layer_mask = ((int64_t)1 << (int64_t)layer);
|
m_renderables[cmp.index]->m_layer_mask = ((int64_t)1 << (int64_t)layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setRenderableScale(Component cmp, const float& scale) override
|
virtual void setRenderableScale(Component cmp, float scale) override
|
||||||
{
|
{
|
||||||
m_renderables[cmp.index]->m_scale = scale;
|
m_renderables[cmp.index]->m_scale = scale;
|
||||||
}
|
}
|
||||||
|
@ -645,7 +713,7 @@ namespace Lumix
|
||||||
infos.reserve(m_terrains.size());
|
infos.reserve(m_terrains.size());
|
||||||
for (int i = 0; i < m_terrains.size(); ++i)
|
for (int i = 0; i < m_terrains.size(); ++i)
|
||||||
{
|
{
|
||||||
if ((m_terrains[i]->getLayerMask() & layer_mask) != 0)
|
if (m_terrains[i] && (m_terrains[i]->getLayerMask() & layer_mask) != 0)
|
||||||
{
|
{
|
||||||
TerrainInfo& info = infos.pushEmpty();
|
TerrainInfo& info = infos.pushEmpty();
|
||||||
info.m_entity = m_terrains[i]->getEntity();
|
info.m_entity = m_terrains[i]->getEntity();
|
||||||
|
@ -663,7 +731,7 @@ namespace Lumix
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
for (int i = 0; i < m_terrains.size(); ++i)
|
for (int i = 0; i < m_terrains.size(); ++i)
|
||||||
{
|
{
|
||||||
if ((m_terrains[i]->getLayerMask() & layer_mask) != 0)
|
if (m_terrains[i] && (m_terrains[i]->getLayerMask() & layer_mask) != 0)
|
||||||
{
|
{
|
||||||
m_terrains[i]->getGrassInfos(infos, m_applied_camera.entity.getPosition());
|
m_terrains[i]->getGrassInfos(infos, m_applied_camera.entity.getPosition());
|
||||||
}
|
}
|
||||||
|
@ -671,15 +739,57 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void setTerrainGrass(Component cmp, const string& path) override
|
virtual void setGrassDensity(Component cmp, int index, int density) override
|
||||||
{
|
{
|
||||||
m_terrains[cmp.index]->setGrassPath(path.c_str());
|
m_terrains[cmp.index]->setGrassTypeDensity(index, density);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual int getGrassDensity(Component cmp, int index) override
|
||||||
|
{
|
||||||
|
return m_terrains[cmp.index]->getGrassTypeDensity(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void getTerrainGrass(Component cmp, string& path) override
|
virtual void setGrassGround(Component cmp, int index, int ground) override
|
||||||
{
|
{
|
||||||
path = m_terrains[cmp.index]->getGrassPath().c_str();
|
m_terrains[cmp.index]->setGrassTypeGround(index, ground);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual int getGrassGround(Component cmp, int index) override
|
||||||
|
{
|
||||||
|
return m_terrains[cmp.index]->getGrassTypeGround(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setGrass(Component cmp, int index, const string& path) override
|
||||||
|
{
|
||||||
|
m_terrains[cmp.index]->setGrassTypePath(index, path.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void getGrass(Component cmp, int index, string& path) override
|
||||||
|
{
|
||||||
|
path = m_terrains[cmp.index]->getGrassTypePath(index).c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual int getGrassCount(Component cmp) override
|
||||||
|
{
|
||||||
|
return m_terrains[cmp.index]->getGrassTypeCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void addGrass(Component cmp, int index) override
|
||||||
|
{
|
||||||
|
m_terrains[cmp.index]->addGrassType(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void removeGrass(Component cmp, int index) override
|
||||||
|
{
|
||||||
|
m_terrains[cmp.index]->removeGrassType(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -693,6 +803,7 @@ namespace Lumix
|
||||||
m_culling_system->cullToFrustumAsync(m_camera_frustum);
|
m_culling_system->cullToFrustumAsync(m_camera_frustum);
|
||||||
|
|
||||||
infos.reserve(m_renderables.size() * 2);
|
infos.reserve(m_renderables.size() * 2);
|
||||||
|
for (int i = 0, c = m_renderables.size(); i < c; ++i)
|
||||||
|
|
||||||
//const CullingSystem::InputSpheres& spheres = m_culling_system->getSpheres();
|
//const CullingSystem::InputSpheres& spheres = m_culling_system->getSpheres();
|
||||||
|
|
||||||
|
@ -712,20 +823,23 @@ namespace Lumix
|
||||||
infos.reserve(m_renderables.size() * 2);
|
infos.reserve(m_renderables.size() * 2);
|
||||||
for (int i = 0; i < m_renderables.size(); ++i)
|
for (int i = 0; i < m_renderables.size(); ++i)
|
||||||
{
|
{
|
||||||
if (!m_renderables[i]->m_is_free)
|
const Renderable* LUMIX_RESTRICT renderable = m_renderables[i];
|
||||||
|
if (!renderable->m_is_free)
|
||||||
{
|
{
|
||||||
bool is_model_ready = m_renderables[i]->m_model.getModel() && m_renderables[i]->m_model.getModel()->isReady();
|
const ModelInstance& model_instance = renderable->m_model;
|
||||||
if (is_model_ready && (m_renderables[i]->m_layer_mask & layer_mask) != 0 && results[i] > -1)
|
const Model* model = model_instance.getModel();
|
||||||
|
bool is_model_ready = model && model->isReady();
|
||||||
|
if (is_model_ready && (renderable->m_layer_mask & layer_mask) != 0 && results[i] > -1)
|
||||||
{
|
{
|
||||||
for (int j = 0, c = m_renderables[i]->m_model.getModel()->getMeshCount(); j < c; ++j)
|
for (int j = 0, c = renderable->m_model.getModel()->getMeshCount(); j < c; ++j)
|
||||||
{
|
{
|
||||||
RenderableInfo& info = infos.pushEmpty();
|
RenderableInfo& info = infos.pushEmpty();
|
||||||
info.m_scale = m_renderables[i]->m_scale;
|
info.m_scale = renderable->m_scale;
|
||||||
info.m_geometry = m_renderables[i]->m_model.getModel()->getGeometry();
|
info.m_geometry = model->getGeometry();
|
||||||
info.m_mesh = &m_renderables[i]->m_model.getModel()->getMesh(j);
|
info.m_mesh = &model->getMesh(j);
|
||||||
info.m_pose = &m_renderables[i]->m_model.getPose();
|
info.m_pose = &model_instance.getPose();
|
||||||
info.m_model = &m_renderables[i]->m_model;
|
info.m_model = &model_instance;
|
||||||
info.m_matrix = &m_renderables[i]->m_model.getMatrix();
|
info.m_matrix = &model_instance.getMatrix();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -742,44 +856,44 @@ namespace Lumix
|
||||||
slot = m_cameras[camera.index].m_slot;
|
slot = m_cameras[camera.index].m_slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getCameraFOV(Component camera, float& fov) override
|
virtual float getCameraFOV(Component camera) override
|
||||||
{
|
{
|
||||||
fov = m_cameras[camera.index].m_fov;
|
return m_cameras[camera.index].m_fov;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setCameraFOV(Component camera, const float& fov) override
|
virtual void setCameraFOV(Component camera, float fov) override
|
||||||
{
|
{
|
||||||
m_cameras[camera.index].m_fov = fov;
|
m_cameras[camera.index].m_fov = fov;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setCameraNearPlane(Component camera, const float& near_plane) override
|
virtual void setCameraNearPlane(Component camera, float near_plane) override
|
||||||
{
|
{
|
||||||
m_cameras[camera.index].m_near = near_plane;
|
m_cameras[camera.index].m_near = near_plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getCameraNearPlane(Component camera, float& near_plane) override
|
virtual float getCameraNearPlane(Component camera) override
|
||||||
{
|
{
|
||||||
near_plane = m_cameras[camera.index].m_near;
|
return m_cameras[camera.index].m_near;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setCameraFarPlane(Component camera, const float& far_plane) override
|
virtual void setCameraFarPlane(Component camera, float far_plane) override
|
||||||
{
|
{
|
||||||
m_cameras[camera.index].m_far = far_plane;
|
m_cameras[camera.index].m_far = far_plane;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getCameraFarPlane(Component camera, float& far_plane) override
|
virtual float getCameraFarPlane(Component camera) override
|
||||||
{
|
{
|
||||||
far_plane = m_cameras[camera.index].m_far;
|
return m_cameras[camera.index].m_far;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getCameraWidth(Component camera, float& width) override
|
virtual float getCameraWidth(Component camera) override
|
||||||
{
|
{
|
||||||
width = m_cameras[camera.index].m_width;
|
return m_cameras[camera.index].m_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getCameraHeight(Component camera, float& height) override
|
virtual float getCameraHeight(Component camera) override
|
||||||
{
|
{
|
||||||
height = m_cameras[camera.index].m_height;
|
return m_cameras[camera.index].m_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setCameraSize(Component camera, int w, int h) override
|
virtual void setCameraSize(Component camera, int w, int h) override
|
||||||
|
@ -882,11 +996,14 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
for (int i = 0; i < m_terrains.size(); ++i)
|
for (int i = 0; i < m_terrains.size(); ++i)
|
||||||
{
|
{
|
||||||
RayCastModelHit terrain_hit = m_terrains[i]->castRay(origin, dir);
|
if(m_terrains[i])
|
||||||
if (terrain_hit.m_is_hit && ignore_terrain != m_terrains[i] && (!hit.m_is_hit || terrain_hit.m_t < hit.m_t))
|
|
||||||
{
|
{
|
||||||
terrain_hit.m_component = Component(m_terrains[i]->getEntity(), TERRAIN_HASH, this, i);
|
RayCastModelHit terrain_hit = m_terrains[i]->castRay(origin, dir);
|
||||||
hit = terrain_hit;
|
if (terrain_hit.m_is_hit && ignore_terrain != m_terrains[i] && (!hit.m_is_hit || terrain_hit.m_t < hit.m_t))
|
||||||
|
{
|
||||||
|
terrain_hit.m_component = Component(m_terrains[i]->getEntity(), TERRAIN_HASH, this, i);
|
||||||
|
hit = terrain_hit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hit;
|
return hit;
|
||||||
|
@ -894,7 +1011,7 @@ namespace Lumix
|
||||||
|
|
||||||
virtual Component getLight(int index) override
|
virtual Component getLight(int index) override
|
||||||
{
|
{
|
||||||
if (index >= m_lights.size())
|
if (index >= m_lights.size() || m_lights[index].m_is_free)
|
||||||
{
|
{
|
||||||
return Component::INVALID;
|
return Component::INVALID;
|
||||||
}
|
}
|
||||||
|
@ -905,7 +1022,7 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
for (int i = 0, c = m_cameras.size(); i < c; ++i)
|
for (int i = 0, c = m_cameras.size(); i < c; ++i)
|
||||||
{
|
{
|
||||||
if (strcmp(m_cameras[i].m_slot, slot) == 0)
|
if (!m_cameras[i].m_is_free && strcmp(m_cameras[i].m_slot, slot) == 0)
|
||||||
{
|
{
|
||||||
return Component(m_cameras[i].m_entity, CAMERA_HASH, this, i);
|
return Component(m_cameras[i].m_entity, CAMERA_HASH, this, i);
|
||||||
}
|
}
|
||||||
|
@ -946,6 +1063,7 @@ namespace Lumix
|
||||||
Array<Camera> m_cameras;
|
Array<Camera> m_cameras;
|
||||||
Array<Terrain*> m_terrains;
|
Array<Terrain*> m_terrains;
|
||||||
Universe& m_universe;
|
Universe& m_universe;
|
||||||
|
Renderer& m_renderer;
|
||||||
Engine& m_engine;
|
Engine& m_engine;
|
||||||
Array<DebugLine> m_debug_lines;
|
Array<DebugLine> m_debug_lines;
|
||||||
Timer* m_timer;
|
Timer* m_timer;
|
||||||
|
@ -955,9 +1073,9 @@ namespace Lumix
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
RenderScene* RenderScene::createInstance(Engine& engine, Universe& universe)
|
RenderScene* RenderScene::createInstance(Renderer& renderer, Engine& engine, Universe& universe)
|
||||||
{
|
{
|
||||||
return LUMIX_NEW(RenderSceneImpl)(engine, universe);
|
return LUMIX_NEW(RenderSceneImpl)(renderer, engine, universe);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "core/lumix.h"
|
#include "core/lumix.h"
|
||||||
#include "core/array.h"
|
#include "core/array.h"
|
||||||
#include "core/string.h"
|
#include "core/string.h"
|
||||||
|
#include "engine/iplugin.h"
|
||||||
#include "graphics/ray_cast_model_hit.h"
|
#include "graphics/ray_cast_model_hit.h"
|
||||||
#include "universe/component.h"
|
#include "universe/component.h"
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ namespace Lumix
|
||||||
struct RenderableInfo
|
struct RenderableInfo
|
||||||
{
|
{
|
||||||
Geometry* m_geometry;
|
Geometry* m_geometry;
|
||||||
Mesh* m_mesh;
|
const Mesh* m_mesh;
|
||||||
const Pose* m_pose;
|
const Pose* m_pose;
|
||||||
const ModelInstance* m_model;
|
const ModelInstance* m_model;
|
||||||
const Matrix* m_matrix;
|
const Matrix* m_matrix;
|
||||||
|
@ -59,16 +60,12 @@ namespace Lumix
|
||||||
float m_life;
|
float m_life;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LUMIX_ENGINE_API RenderScene
|
class LUMIX_ENGINE_API RenderScene : public IScene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static RenderScene* createInstance(Engine& engine, Universe& universe);
|
static RenderScene* createInstance(Renderer& renderer, Engine& engine, Universe& universe);
|
||||||
static void destroyInstance(RenderScene* scene);
|
static void destroyInstance(RenderScene* scene);
|
||||||
|
|
||||||
virtual void serialize(ISerializer& serializer) = 0;
|
|
||||||
virtual void deserialize(ISerializer& serializer) = 0;
|
|
||||||
virtual Component createComponent(uint32_t type, const Entity& entity) = 0;
|
|
||||||
virtual void destroyComponent(const Component& component) = 0;
|
|
||||||
virtual RayCastModelHit castRay(const Vec3& origin, const Vec3& dir, const Component& ignore) = 0;
|
virtual RayCastModelHit castRay(const Vec3& origin, const Vec3& dir, const Component& ignore) = 0;
|
||||||
virtual void getRay(Component camera, float x, float y, Vec3& origin, Vec3& dir) = 0;
|
virtual void getRay(Component camera, float x, float y, Vec3& origin, Vec3& dir) = 0;
|
||||||
virtual void applyCamera(Component camera) = 0;
|
virtual void applyCamera(Component camera) = 0;
|
||||||
|
@ -86,14 +83,14 @@ namespace Lumix
|
||||||
virtual void addDebugCircle(const Vec3& center, float radius, const Vec3& color, float life) = 0;
|
virtual void addDebugCircle(const Vec3& center, float radius, const Vec3& color, float life) = 0;
|
||||||
virtual const Array<DebugLine>& getDebugLines() const = 0;
|
virtual const Array<DebugLine>& getDebugLines() const = 0;
|
||||||
virtual Component getCameraInSlot(const char* slot) = 0;
|
virtual Component getCameraInSlot(const char* slot) = 0;
|
||||||
virtual void getCameraFOV(Component camera, float& fov) = 0;
|
virtual float getCameraFOV(Component camera) = 0;
|
||||||
virtual void setCameraFOV(Component camera, const float& fov) = 0;
|
virtual void setCameraFOV(Component camera, float fov) = 0;
|
||||||
virtual void setCameraFarPlane(Component camera, const float& far) = 0;
|
virtual void setCameraFarPlane(Component camera, float far) = 0;
|
||||||
virtual void setCameraNearPlane(Component camera, const float& near) = 0;
|
virtual void setCameraNearPlane(Component camera, float near) = 0;
|
||||||
virtual void getCameraFarPlane(Component camera, float& far) = 0;
|
virtual float getCameraFarPlane(Component camera) = 0;
|
||||||
virtual void getCameraNearPlane(Component camera, float& near) = 0;
|
virtual float getCameraNearPlane(Component camera) = 0;
|
||||||
virtual void getCameraWidth(Component camera, float& width) = 0;
|
virtual float getCameraWidth(Component camera) = 0;
|
||||||
virtual void getCameraHeight(Component camera, float& height) = 0;
|
virtual float getCameraHeight(Component camera) = 0;
|
||||||
virtual void setCameraSlot(Component camera, const string& slot) = 0;
|
virtual void setCameraSlot(Component camera, const string& slot) = 0;
|
||||||
virtual void getCameraSlot(Component camera, string& slot) = 0;
|
virtual void getCameraSlot(Component camera, string& slot) = 0;
|
||||||
virtual void setCameraSize(Component camera, int w, int h) = 0;
|
virtual void setCameraSize(Component camera, int w, int h) = 0;
|
||||||
|
@ -101,21 +98,31 @@ namespace Lumix
|
||||||
virtual void getRenderablePath(Component cmp, string& path) = 0;
|
virtual void getRenderablePath(Component cmp, string& path) = 0;
|
||||||
virtual void setRenderableLayer(Component cmp, const int32_t& layer) = 0;
|
virtual void setRenderableLayer(Component cmp, const int32_t& layer) = 0;
|
||||||
virtual void setRenderablePath(Component cmp, const string& path) = 0;
|
virtual void setRenderablePath(Component cmp, const string& path) = 0;
|
||||||
virtual void setRenderableScale(Component cmp, const float& scale) = 0;
|
virtual void setRenderableScale(Component cmp, float scale) = 0;
|
||||||
virtual void getRenderableInfos(Array<RenderableInfo>& infos, int64_t layer_mask) = 0;
|
virtual void getRenderableInfos(Array<RenderableInfo>& infos, int64_t layer_mask) = 0;
|
||||||
|
|
||||||
virtual void getGrassInfos(Array<GrassInfo>& infos, int64_t layer_mask) = 0;
|
virtual void getGrassInfos(Array<GrassInfo>& infos, int64_t layer_mask) = 0;
|
||||||
virtual void getTerrainInfos(Array<TerrainInfo>& infos, int64_t layer_mask) = 0;
|
virtual void getTerrainInfos(Array<TerrainInfo>& infos, int64_t layer_mask) = 0;
|
||||||
|
virtual float getTerrainHeightAt(Component cmp, float x, float z) = 0;
|
||||||
virtual void setTerrainMaterial(Component cmp, const string& path) = 0;
|
virtual void setTerrainMaterial(Component cmp, const string& path) = 0;
|
||||||
virtual void getTerrainMaterial(Component cmp, string& path) = 0;
|
virtual void getTerrainMaterial(Component cmp, string& path) = 0;
|
||||||
virtual void setTerrainXZScale(Component cmp, const float& scale) = 0;
|
virtual Material* getTerrainMaterial(Component cmp) = 0;
|
||||||
virtual void getTerrainXZScale(Component cmp, float& scale) = 0;
|
virtual void setTerrainXZScale(Component cmp, float scale) = 0;
|
||||||
virtual void setTerrainYScale(Component cmp, const float& scale) = 0;
|
virtual float getTerrainXZScale(Component cmp) = 0;
|
||||||
virtual void getTerrainYScale(Component cmp, float& scale) = 0;
|
virtual void setTerrainYScale(Component cmp, float scale) = 0;
|
||||||
virtual void setTerrainGrass(Component cmp, const string& path) = 0;
|
virtual float getTerrainYScale(Component cmp) = 0;
|
||||||
virtual void getTerrainGrass(Component cmp, string& path) = 0;
|
|
||||||
virtual void setTerrainBrush(Component cmp, const Vec3& position, float size) = 0;
|
virtual void setTerrainBrush(Component cmp, const Vec3& position, float size) = 0;
|
||||||
|
|
||||||
|
virtual void setGrass(Component cmp, int index, const string& path) = 0;
|
||||||
|
virtual void getGrass(Component cmp, int index, string& path) = 0;
|
||||||
|
virtual void setGrassGround(Component cmp, int index, int ground) = 0;
|
||||||
|
virtual int getGrassGround(Component cmp, int index) = 0;
|
||||||
|
virtual void setGrassDensity(Component cmp, int index, int density) = 0;
|
||||||
|
virtual int getGrassDensity(Component cmp, int index) = 0;
|
||||||
|
virtual int getGrassCount(Component cmp) = 0;
|
||||||
|
virtual void addGrass(Component cmp, int index) = 0;
|
||||||
|
virtual void removeGrass(Component cmp, int index) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~RenderScene() {}
|
virtual ~RenderScene() {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "core/resource_manager.h"
|
#include "core/resource_manager.h"
|
||||||
#include "core/resource_manager_base.h"
|
#include "core/resource_manager_base.h"
|
||||||
#include "core/vec4.h"
|
#include "core/vec4.h"
|
||||||
|
#include "editor/world_editor.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "graphics/geometry.h"
|
#include "graphics/geometry.h"
|
||||||
#include "graphics/gl_ext.h"
|
#include "graphics/gl_ext.h"
|
||||||
|
@ -33,12 +34,18 @@ static const uint32_t CAMERA_HASH = crc32("camera");
|
||||||
|
|
||||||
struct RendererImpl : public Renderer
|
struct RendererImpl : public Renderer
|
||||||
{
|
{
|
||||||
|
|
||||||
RendererImpl()
|
RendererImpl()
|
||||||
{
|
{
|
||||||
|
m_last_bind_geometry = NULL;
|
||||||
|
m_last_program_id = 0xffffFFFF;
|
||||||
m_is_editor_wireframe = false;
|
m_is_editor_wireframe = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual IScene* createScene(Universe& universe)
|
||||||
|
{
|
||||||
|
return RenderScene::createInstance(*this, *m_engine, universe);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void setProjection(float width, float height, float fov, float near_plane, float far_plane, const Matrix& mtx) override
|
virtual void setProjection(float width, float height, float fov, float near_plane, float far_plane, const Matrix& mtx) override
|
||||||
{
|
{
|
||||||
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
glViewport(0, 0, (GLsizei)width, (GLsizei)height);
|
||||||
|
@ -72,14 +79,21 @@ struct RendererImpl : public Renderer
|
||||||
virtual void render(IRenderDevice& device) override
|
virtual void render(IRenderDevice& device) override
|
||||||
{
|
{
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
// init
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
// render
|
|
||||||
device.getPipeline().render();
|
device.getPipeline().render();
|
||||||
|
|
||||||
// cleanup
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void cleanup() override
|
||||||
|
{
|
||||||
|
if(m_last_bind_geometry)
|
||||||
|
{
|
||||||
|
m_last_bind_geometry->getVertexDefinition().end(*m_last_bind_geometry_shader);
|
||||||
|
}
|
||||||
|
m_last_bind_geometry = NULL;
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
for(int i = 0; i < 16; ++i)
|
for(int i = 0; i < 16; ++i)
|
||||||
|
@ -90,8 +104,208 @@ struct RendererImpl : public Renderer
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, int value) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getUniformLocation(name, name_hash);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniform1i(loc, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, const Vec3& value) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getUniformLocation(name, name_hash);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniform3f(loc, value.x, value.y, value.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, float value) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getUniformLocation(name, name_hash);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniform1f(loc, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, const Matrix& mtx) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getUniformLocation(name, name_hash);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
//glProgramUniformMatrix4fv(shader.getProgramId(), loc, 1, false, &mtx.m11);
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniformMatrix4fv(loc, 1, false, &mtx.m11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, const Matrix* matrices, int count) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getUniformLocation(name, name_hash);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniformMatrix4fv(loc, count, false, (float*)matrices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setFixedCachedUniform(Shader& shader, int name, const Vec3& value) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getFixedCachedUniformLocation((Shader::FixedCachedUniforms)name);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniform3f(loc, value.x, value.y, value.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setFixedCachedUniform(Shader& shader, int name, float value) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getFixedCachedUniformLocation((Shader::FixedCachedUniforms)name);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniform1f(loc, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setFixedCachedUniform(Shader& shader, int name, const Matrix& mtx) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getFixedCachedUniformLocation((Shader::FixedCachedUniforms)name);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
//glProgramUniformMatrix4fv(shader.getProgramId(), loc, 1, false, &mtx.m11);
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniformMatrix4fv(loc, 1, false, &mtx.m11);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void setFixedCachedUniform(Shader& shader, int name, const Matrix* matrices, int count) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
GLint loc = shader.getFixedCachedUniformLocation((Shader::FixedCachedUniforms)name);
|
||||||
|
if (loc >= 0)
|
||||||
|
{
|
||||||
|
if (m_last_program_id != shader.getProgramId())
|
||||||
|
{
|
||||||
|
glUseProgram(shader.getProgramId());
|
||||||
|
m_last_program_id = shader.getProgramId();
|
||||||
|
}
|
||||||
|
glUniformMatrix4fv(loc, count, false, (float*)matrices);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void applyShader(const Shader& shader) override
|
||||||
|
{
|
||||||
|
GLuint id = shader.getProgramId();
|
||||||
|
m_last_program_id = id;
|
||||||
|
glUseProgram(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void renderGeometry(Geometry& geometry, int start, int count, Shader& shader) override
|
||||||
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
|
if (m_last_bind_geometry != &geometry)
|
||||||
|
{
|
||||||
|
if (m_last_bind_geometry)
|
||||||
|
{
|
||||||
|
m_last_bind_geometry->getVertexDefinition().end(shader);
|
||||||
|
}
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, geometry.getID());
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry.getIndicesID());
|
||||||
|
m_last_bind_geometry = &geometry;
|
||||||
|
m_last_bind_geometry_shader = &shader;
|
||||||
|
geometry.getVertexDefinition().begin(shader);
|
||||||
|
}
|
||||||
|
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, (void*)(start * sizeof(GLint)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void registerPropertyDescriptors(WorldEditor& editor)
|
||||||
|
{
|
||||||
|
editor.registerProperty("camera", LUMIX_NEW(StringPropertyDescriptor<RenderScene>)("slot", &RenderScene::getCameraSlot, &RenderScene::setCameraSlot));
|
||||||
|
editor.registerProperty("camera", LUMIX_NEW(DecimalPropertyDescriptor<RenderScene>)("fov", &RenderScene::getCameraFOV, &RenderScene::setCameraFOV));
|
||||||
|
editor.registerProperty("camera", LUMIX_NEW(DecimalPropertyDescriptor<RenderScene>)("near", &RenderScene::getCameraNearPlane, &RenderScene::setCameraNearPlane));
|
||||||
|
editor.registerProperty("camera", LUMIX_NEW(DecimalPropertyDescriptor<RenderScene>)("far", &RenderScene::getCameraFarPlane, &RenderScene::setCameraFarPlane));
|
||||||
|
|
||||||
|
editor.registerProperty("renderable", LUMIX_NEW(FilePropertyDescriptor<RenderScene>)("source", &RenderScene::getRenderablePath, &RenderScene::setRenderablePath, "Mesh (*.msh)"));
|
||||||
|
|
||||||
|
editor.registerProperty("terrain", LUMIX_NEW(FilePropertyDescriptor<RenderScene>)("material", &RenderScene::getTerrainMaterial, &RenderScene::setTerrainMaterial, "Material (*.mat)"));
|
||||||
|
editor.registerProperty("terrain", LUMIX_NEW(DecimalPropertyDescriptor<RenderScene>)("xz_scale", &RenderScene::getTerrainXZScale, &RenderScene::setTerrainXZScale));
|
||||||
|
editor.registerProperty("terrain", LUMIX_NEW(DecimalPropertyDescriptor<RenderScene>)("y_scale", &RenderScene::getTerrainYScale, &RenderScene::setTerrainYScale));
|
||||||
|
|
||||||
|
auto grass = LUMIX_NEW(ArrayDescriptor<RenderScene>)("grass", &RenderScene::getGrassCount, &RenderScene::addGrass, &RenderScene::removeGrass);
|
||||||
|
grass->addChild(LUMIX_NEW(FileArrayObjectDescriptor<RenderScene>)("mesh", &RenderScene::getGrass, &RenderScene::setGrass, "Mesh (*.msh)"));
|
||||||
|
auto ground = LUMIX_NEW(IntArrayObjectDescriptor<RenderScene>)("ground", &RenderScene::getGrassGround, &RenderScene::setGrassGround);
|
||||||
|
ground->setLimit(0, 4);
|
||||||
|
grass->addChild(ground);
|
||||||
|
grass->addChild(LUMIX_NEW(IntArrayObjectDescriptor<RenderScene>)("density", &RenderScene::getGrassDensity, &RenderScene::setGrassDensity));
|
||||||
|
editor.registerProperty("terrain", grass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual bool create(Engine& engine) override
|
virtual bool create(Engine& engine) override
|
||||||
{
|
{
|
||||||
|
registerPropertyDescriptors(*engine.getWorldEditor());
|
||||||
|
|
||||||
m_engine = &engine;
|
m_engine = &engine;
|
||||||
glewExperimental = GL_TRUE;
|
glewExperimental = GL_TRUE;
|
||||||
GLenum err = glewInit();
|
GLenum err = glewInit();
|
||||||
|
@ -110,18 +324,6 @@ struct RendererImpl : public Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void destroyComponent(const Component& component) override
|
|
||||||
{
|
|
||||||
static_cast<RenderScene*>(component.system)->destroyComponent(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual Component createComponent(uint32_t, const Entity&) override
|
|
||||||
{
|
|
||||||
return Component::INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void enableAlphaToCoverage(bool enable) override
|
virtual void enableAlphaToCoverage(bool enable) override
|
||||||
{
|
{
|
||||||
if (enable)
|
if (enable)
|
||||||
|
@ -166,7 +368,7 @@ struct RendererImpl : public Renderer
|
||||||
{
|
{
|
||||||
const Mesh& mesh = model.getMesh(i);
|
const Mesh& mesh = model.getMesh(i);
|
||||||
mesh.getMaterial()->apply(*this, pipeline);
|
mesh.getMaterial()->apply(*this, pipeline);
|
||||||
model.getGeometry()->draw(mesh.getStart(), mesh.getCount(), *mesh.getMaterial()->getShader());
|
renderGeometry(*model.getGeometry(), mesh.getStart(), mesh.getCount(), *mesh.getMaterial()->getShader());
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
@ -190,9 +392,11 @@ struct RendererImpl : public Renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine* m_engine;
|
Engine* m_engine;
|
||||||
Array<Model*> m_models;
|
|
||||||
IRenderDevice* m_render_device;
|
IRenderDevice* m_render_device;
|
||||||
bool m_is_editor_wireframe;
|
bool m_is_editor_wireframe;
|
||||||
|
Geometry* m_last_bind_geometry;
|
||||||
|
Shader* m_last_bind_geometry_shader;
|
||||||
|
GLuint m_last_program_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,19 @@ class LUMIX_ENGINE_API Renderer : public IPlugin
|
||||||
virtual void setRenderDevice(IRenderDevice& device) = 0;
|
virtual void setRenderDevice(IRenderDevice& device) = 0;
|
||||||
virtual void setEditorWireframe(bool is_wireframe) = 0;
|
virtual void setEditorWireframe(bool is_wireframe) = 0;
|
||||||
virtual bool isEditorWireframe() const = 0;
|
virtual bool isEditorWireframe() const = 0;
|
||||||
|
virtual void cleanup() = 0;
|
||||||
|
|
||||||
|
virtual void renderGeometry(Geometry& geometry, int start, int count, Shader& shader) = 0;
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, int value) = 0;
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, const Vec3& value) = 0;
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, float value) = 0;
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, const Matrix& mtx) = 0;
|
||||||
|
virtual void setUniform(Shader& shader, const char* name, const uint32_t name_hash, const Matrix* matrices, int count) = 0;
|
||||||
|
virtual void setFixedCachedUniform(Shader& shader, int name, const Vec3& value) = 0;
|
||||||
|
virtual void setFixedCachedUniform(Shader& shader, int name, float value) = 0;
|
||||||
|
virtual void setFixedCachedUniform(Shader& shader, int name, const Matrix& mtx) = 0;
|
||||||
|
virtual void setFixedCachedUniform(Shader& shader, int name, const Matrix* matrices, int count) = 0;
|
||||||
|
virtual void applyShader(const Shader& shader) = 0;
|
||||||
|
|
||||||
virtual void setProjection(float width, float height, float fov, float near_plane, float far_plane, const Matrix& mtx) = 0;
|
virtual void setProjection(float width, float height, float fov, float near_plane, float far_plane, const Matrix& mtx) = 0;
|
||||||
virtual Engine& getEngine() = 0;
|
virtual Engine& getEngine() = 0;
|
||||||
|
|
|
@ -32,75 +32,23 @@ Shader::~Shader()
|
||||||
glDeleteShader(m_fragment_id);
|
glDeleteShader(m_fragment_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::apply()
|
|
||||||
{
|
|
||||||
glUseProgram(m_program_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
GLint Shader::getUniformLocation(const char* name, uint32_t name_hash)
|
||||||
void Shader::setUniform(const char* name, int value)
|
|
||||||
{
|
{
|
||||||
PROFILE_FUNCTION();
|
for (int i = 0, c = m_uniforms.size(); i < c; ++i)
|
||||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
|
||||||
if(loc >= 0)
|
|
||||||
{
|
{
|
||||||
//glProgramUniform1i(m_program_id, loc, value);
|
if (m_uniforms[i].m_name_hash == name_hash)
|
||||||
glUseProgram(m_program_id);
|
{
|
||||||
glUniform1i(loc, value);
|
return m_uniforms[i].m_location;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
CachedUniform& unif = m_uniforms.pushEmpty();
|
||||||
|
unif.m_name_hash = name_hash;
|
||||||
|
unif.m_location = glGetUniformLocation(m_program_id, name);
|
||||||
|
return unif.m_location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Shader::setUniform(const char* name, const Vec3& value)
|
|
||||||
{
|
|
||||||
PROFILE_FUNCTION();
|
|
||||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
|
||||||
if(loc >= 0)
|
|
||||||
{
|
|
||||||
//glProgramUniform3f(m_program_id, loc, value.x, value.y, value.z);
|
|
||||||
glUseProgram(m_program_id);
|
|
||||||
glUniform3f(loc, value.x, value.y, value.z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Shader::setUniform(const char* name, GLfloat value)
|
|
||||||
{
|
|
||||||
PROFILE_FUNCTION();
|
|
||||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
|
||||||
if(loc >= 0)
|
|
||||||
{
|
|
||||||
//glProgramUniform1f(m_program_id, loc, value);
|
|
||||||
glUseProgram(m_program_id);
|
|
||||||
glUniform1f(loc, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Shader::setUniform(const char* name, const Matrix& mtx)
|
|
||||||
{
|
|
||||||
PROFILE_FUNCTION();
|
|
||||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
|
||||||
if(loc >= 0)
|
|
||||||
{
|
|
||||||
//glProgramUniformMatrix4fv(m_program_id, loc, 1, false, &mtx.m11);
|
|
||||||
glUseProgram(m_program_id);
|
|
||||||
glUniformMatrix4fv(loc, 1, false, &mtx.m11);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shader::setUniform(const char* name, const Matrix* matrices, int count)
|
|
||||||
{
|
|
||||||
PROFILE_FUNCTION();
|
|
||||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
|
||||||
if(loc >= 0) // this is here because of bug in some gl implementations
|
|
||||||
{
|
|
||||||
//glProgramUniformMatrix4fv(m_program_id, loc, count, false, &matrices[0].m11);
|
|
||||||
glUseProgram(m_program_id);
|
|
||||||
glUniformMatrix4fv(loc, count, false, &matrices[0].m11);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GLuint Shader::attach(GLenum type, const char* src, int32_t length)
|
GLuint Shader::attach(GLenum type, const char* src, int32_t length)
|
||||||
{
|
{
|
||||||
GLuint id = glCreateShader(type);
|
GLuint id = glCreateShader(type);
|
||||||
|
@ -179,9 +127,11 @@ void Shader::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
||||||
{
|
{
|
||||||
m_vertex_attributes_ids[i] = glGetAttribLocation(m_program_id, attributes[i]);
|
m_vertex_attributes_ids[i] = glGetAttribLocation(m_program_id, attributes[i]);
|
||||||
}
|
}
|
||||||
m_position_attrib_id = glGetAttribLocation(m_program_id, "in_position");
|
m_fixed_cached_uniforms[(int)FixedCachedUniforms::WORLD_MATRIX] = glGetUniformLocation(m_program_id, "world_matrix");
|
||||||
m_normal_attrib_id = glGetAttribLocation(m_program_id, "in_normal");
|
m_fixed_cached_uniforms[(int)FixedCachedUniforms::GRASS_MATRICES] = glGetUniformLocation(m_program_id, "grass_matrices");
|
||||||
m_tex_coord_attrib_id = glGetAttribLocation(m_program_id, "in_tex_coord");
|
m_fixed_cached_uniforms[(int)FixedCachedUniforms::MORPH_CONST] = glGetUniformLocation(m_program_id, "morph_const");
|
||||||
|
m_fixed_cached_uniforms[(int)FixedCachedUniforms::QUAD_SIZE] = glGetUniformLocation(m_program_id, "quad_size");
|
||||||
|
m_fixed_cached_uniforms[(int)FixedCachedUniforms::QUAD_MIN] = glGetUniformLocation(m_program_id, "quad_min");
|
||||||
|
|
||||||
m_size = file->size();
|
m_size = file->size();
|
||||||
decrementDepCount();
|
decrementDepCount();
|
||||||
|
@ -197,6 +147,7 @@ void Shader::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
||||||
|
|
||||||
void Shader::doUnload(void)
|
void Shader::doUnload(void)
|
||||||
{
|
{
|
||||||
|
m_uniforms.clear();
|
||||||
glDeleteProgram(m_program_id);
|
glDeleteProgram(m_program_id);
|
||||||
glDeleteShader(m_vertex_id);
|
glDeleteShader(m_vertex_id);
|
||||||
glDeleteShader(m_fragment_id);
|
glDeleteShader(m_fragment_id);
|
||||||
|
|
|
@ -16,6 +16,17 @@ struct Matrix;
|
||||||
|
|
||||||
class LUMIX_ENGINE_API Shader : public Resource
|
class LUMIX_ENGINE_API Shader : public Resource
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
enum class FixedCachedUniforms : int
|
||||||
|
{
|
||||||
|
WORLD_MATRIX,
|
||||||
|
GRASS_MATRICES,
|
||||||
|
MORPH_CONST,
|
||||||
|
QUAD_SIZE,
|
||||||
|
QUAD_MIN,
|
||||||
|
COUNT
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int MAX_ATTRIBUTE_COUNT = 16;
|
static const int MAX_ATTRIBUTE_COUNT = 16;
|
||||||
|
|
||||||
|
@ -23,17 +34,11 @@ class LUMIX_ENGINE_API Shader : public Resource
|
||||||
Shader(const Path& path, ResourceManager& resource_manager);
|
Shader(const Path& path, ResourceManager& resource_manager);
|
||||||
~Shader();
|
~Shader();
|
||||||
|
|
||||||
void apply();
|
|
||||||
void setUniform(const char* name, GLint value);
|
|
||||||
void setUniform(const char* name, const Vec3& value);
|
|
||||||
void setUniform(const char* name, GLfloat value);
|
|
||||||
void setUniform(const char* name, const Matrix& mtx);
|
|
||||||
void setUniform(const char* name, const Matrix* matrices, int count);
|
|
||||||
GLint getAttribId(int index) const { return m_vertex_attributes_ids[index]; }
|
GLint getAttribId(int index) const { return m_vertex_attributes_ids[index]; }
|
||||||
GLint getPositionAttribId() const { return m_position_attrib_id; }
|
|
||||||
GLint getNormalAttribId() const { return m_normal_attrib_id; }
|
|
||||||
GLint getTexCoordAttribId() const { return m_tex_coord_attrib_id; }
|
|
||||||
bool isShadowmapRequired() const { return m_is_shadowmap_required; }
|
bool isShadowmapRequired() const { return m_is_shadowmap_required; }
|
||||||
|
LUMIX_FORCE_INLINE GLint getUniformLocation(const char* name, uint32_t name_hash);
|
||||||
|
GLuint getProgramId() const { return m_program_id; }
|
||||||
|
GLint getFixedCachedUniformLocation(FixedCachedUniforms name) const { return m_fixed_cached_uniforms[(int)name]; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint attach(GLenum type, const char* src, int32_t length);
|
GLuint attach(GLenum type, const char* src, int32_t length);
|
||||||
|
@ -43,15 +48,22 @@ class LUMIX_ENGINE_API Shader : public Resource
|
||||||
virtual void doUnload(void) override;
|
virtual void doUnload(void) override;
|
||||||
virtual FS::ReadCallback getReadCallback() override;
|
virtual FS::ReadCallback getReadCallback() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class CachedUniform
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint32_t m_name_hash;
|
||||||
|
GLint m_location;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GLuint m_program_id;
|
GLuint m_program_id;
|
||||||
GLuint m_vertex_id;
|
GLuint m_vertex_id;
|
||||||
GLuint m_fragment_id;
|
GLuint m_fragment_id;
|
||||||
GLint m_vertex_attributes_ids[MAX_ATTRIBUTE_COUNT];
|
GLint m_vertex_attributes_ids[MAX_ATTRIBUTE_COUNT];
|
||||||
GLint m_position_attrib_id;
|
|
||||||
GLint m_normal_attrib_id;
|
|
||||||
GLint m_tex_coord_attrib_id;
|
|
||||||
bool m_is_shadowmap_required;
|
bool m_is_shadowmap_required;
|
||||||
|
Array<CachedUniform> m_uniforms;
|
||||||
|
GLint m_fixed_cached_uniforms[(int)FixedCachedUniforms::COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "graphics/model.h"
|
#include "graphics/model.h"
|
||||||
#include "graphics/pipeline.h"
|
#include "graphics/pipeline.h"
|
||||||
#include "graphics/render_scene.h"
|
#include "graphics/render_scene.h"
|
||||||
|
#include "graphics/renderer.h"
|
||||||
#include "graphics/shader.h"
|
#include "graphics/shader.h"
|
||||||
#include "graphics/texture.h"
|
#include "graphics/texture.h"
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
|
@ -21,6 +22,14 @@ namespace Lumix
|
||||||
static const int GRID_SIZE = 16;
|
static const int GRID_SIZE = 16;
|
||||||
static const int COPY_COUNT = 50;
|
static const int COPY_COUNT = 50;
|
||||||
static const uint32_t TERRAIN_HASH = crc32("terrain");
|
static const uint32_t TERRAIN_HASH = crc32("terrain");
|
||||||
|
static const uint32_t MORPH_CONST_HASH = crc32("morph_const");
|
||||||
|
static const uint32_t QUAD_SIZE_HASH = crc32("quad_size");
|
||||||
|
static const uint32_t QUAD_MIN_HASH = crc32("quad_min");
|
||||||
|
|
||||||
|
static const uint32_t BRUSH_POSITION_HASH = crc32("brush_position");
|
||||||
|
static const uint32_t BRUSH_SIZE_HASH = crc32("brush_size");
|
||||||
|
static const uint32_t MAP_SIZE_HASH = crc32("map_size");
|
||||||
|
static const uint32_t CAMERA_POS_HASH = crc32("camera_pos");
|
||||||
|
|
||||||
struct Sample
|
struct Sample
|
||||||
{
|
{
|
||||||
|
@ -116,8 +125,9 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool render(Mesh* mesh, Geometry& geometry, const Vec3& camera_pos, RenderScene& scene)
|
bool render(Renderer* renderer, Mesh* mesh, Geometry& geometry, const Vec3& camera_pos, RenderScene& scene)
|
||||||
{
|
{
|
||||||
|
PROFILE_FUNCTION();
|
||||||
float dist = getDistance(camera_pos);
|
float dist = getDistance(camera_pos);
|
||||||
float r = getRadiusOuter(m_size);
|
float r = getRadiusOuter(m_size);
|
||||||
if (dist > r && m_lod > 1)
|
if (dist > r && m_lod > 1)
|
||||||
|
@ -128,12 +138,12 @@ namespace Lumix
|
||||||
Shader& shader = *mesh->getMaterial()->getShader();
|
Shader& shader = *mesh->getMaterial()->getShader();
|
||||||
for (int i = 0; i < CHILD_COUNT; ++i)
|
for (int i = 0; i < CHILD_COUNT; ++i)
|
||||||
{
|
{
|
||||||
if (!m_children[i] || !m_children[i]->render(mesh, geometry, camera_pos, scene))
|
if (!m_children[i] || !m_children[i]->render(renderer, mesh, geometry, camera_pos, scene))
|
||||||
{
|
{
|
||||||
shader.setUniform("morph_const", morph_const);
|
renderer->setFixedCachedUniform(shader, (int)Shader::FixedCachedUniforms::MORPH_CONST, morph_const);
|
||||||
shader.setUniform("quad_size", m_size);
|
renderer->setFixedCachedUniform(shader, (int)Shader::FixedCachedUniforms::QUAD_SIZE, m_size);
|
||||||
shader.setUniform("quad_min", m_min);
|
renderer->setFixedCachedUniform(shader, (int)Shader::FixedCachedUniforms::QUAD_MIN, m_min);
|
||||||
geometry.draw(mesh->getCount() / 4 * i, mesh->getCount() / 4, shader);
|
renderer->renderGeometry(geometry, mesh->getCount() / 4 * i, mesh->getCount() / 4, shader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -157,69 +167,155 @@ namespace Lumix
|
||||||
, m_y_scale(1)
|
, m_y_scale(1)
|
||||||
, m_xz_scale(1)
|
, m_xz_scale(1)
|
||||||
, m_entity(entity)
|
, m_entity(entity)
|
||||||
, m_grass_geometry(NULL)
|
|
||||||
, m_grass_mesh(NULL)
|
|
||||||
, m_scene(scene)
|
, m_scene(scene)
|
||||||
, m_grass_model(NULL)
|
|
||||||
, m_brush_position(0, 0, 0)
|
, m_brush_position(0, 0, 0)
|
||||||
, m_brush_size(1)
|
, m_brush_size(1)
|
||||||
{
|
{
|
||||||
generateGeometry();
|
generateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Terrain::GrassType::~GrassType()
|
||||||
|
{
|
||||||
|
if (m_grass_model)
|
||||||
|
{
|
||||||
|
m_grass_model->getResourceManager().get(ResourceManager::MODEL)->unload(*m_grass_model);
|
||||||
|
m_grass_model->getObserverCb().unbind<GrassType, &GrassType::grassLoaded>(this);
|
||||||
|
LUMIX_DELETE(m_grass_mesh);
|
||||||
|
LUMIX_DELETE(m_grass_geometry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Terrain::~Terrain()
|
Terrain::~Terrain()
|
||||||
{
|
{
|
||||||
setMaterial(NULL);
|
setMaterial(NULL);
|
||||||
LUMIX_DELETE(m_mesh);
|
LUMIX_DELETE(m_mesh);
|
||||||
LUMIX_DELETE(m_root);
|
LUMIX_DELETE(m_root);
|
||||||
if (m_grass_model)
|
for(int i = 0; i < m_grass_types.size(); ++i)
|
||||||
{
|
{
|
||||||
m_grass_model->getResourceManager().get(ResourceManager::MODEL)->unload(*m_grass_model);
|
LUMIX_DELETE(m_grass_types[i]);
|
||||||
m_grass_model->getObserverCb().unbind<Terrain, &Terrain::grassLoaded>(this);
|
}
|
||||||
LUMIX_DELETE(m_grass_mesh);
|
for (int i = 0; i < m_grass_quads.size(); ++i)
|
||||||
LUMIX_DELETE(m_grass_geometry);
|
{
|
||||||
for (int i = 0; i < m_grass_quads.size(); ++i)
|
LUMIX_DELETE(m_grass_quads[i]);
|
||||||
{
|
}
|
||||||
LUMIX_DELETE(m_grass_quads[i]);
|
for (int i = 0; i < m_free_grass_quads.size(); ++i)
|
||||||
}
|
{
|
||||||
for (int i = 0; i < m_free_grass_quads.size(); ++i)
|
LUMIX_DELETE(m_free_grass_quads[i]);
|
||||||
{
|
|
||||||
LUMIX_DELETE(m_free_grass_quads[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Path Terrain::getGrassPath()
|
Terrain::GrassType::GrassType(Terrain& terrain)
|
||||||
|
: m_terrain(terrain)
|
||||||
{
|
{
|
||||||
if (m_grass_model)
|
m_grass_geometry = NULL;
|
||||||
|
m_grass_mesh = NULL;
|
||||||
|
m_grass_model = NULL;
|
||||||
|
m_ground = 0;
|
||||||
|
m_density = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Terrain::addGrassType(int index)
|
||||||
|
{
|
||||||
|
if(index < 0)
|
||||||
{
|
{
|
||||||
return m_grass_model->getPath();
|
m_grass_types.push(LUMIX_NEW(GrassType)(*this));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_grass_types.insert(index, LUMIX_NEW(GrassType)(*this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Terrain::removeGrassType(int index)
|
||||||
|
{
|
||||||
|
forceGrassUpdate();
|
||||||
|
LUMIX_DELETE(m_grass_types[index]);
|
||||||
|
m_grass_types.erase(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Terrain::setGrassTypeDensity(int index, int density)
|
||||||
|
{
|
||||||
|
forceGrassUpdate();
|
||||||
|
GrassType& type = *m_grass_types[index];
|
||||||
|
type.m_density = Math::clamp(density, 0, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Terrain::getGrassTypeDensity(int index)
|
||||||
|
{
|
||||||
|
GrassType& type = *m_grass_types[index];
|
||||||
|
return type.m_density;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Terrain::setGrassTypeGround(int index, int ground)
|
||||||
|
{
|
||||||
|
ground = Math::clamp(ground, 0, 3);
|
||||||
|
forceGrassUpdate();
|
||||||
|
GrassType& type = *m_grass_types[index];
|
||||||
|
type.m_ground = ground;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Terrain::getGrassTypeGround(int index)
|
||||||
|
{
|
||||||
|
GrassType& type = *m_grass_types[index];
|
||||||
|
return type.m_ground;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Path Terrain::getGrassTypePath(int index)
|
||||||
|
{
|
||||||
|
GrassType& type = *m_grass_types[index];
|
||||||
|
if (type.m_grass_model)
|
||||||
|
{
|
||||||
|
return type.m_grass_model->getPath();
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Terrain::setGrassPath(const Path& path)
|
void Terrain::setGrassTypePath(int index, const Path& path)
|
||||||
{
|
{
|
||||||
if (m_grass_model)
|
forceGrassUpdate();
|
||||||
|
GrassType& type = *m_grass_types[index];
|
||||||
|
if (type.m_grass_model)
|
||||||
{
|
{
|
||||||
m_grass_model->getResourceManager().get(ResourceManager::MODEL)->unload(*m_grass_model);
|
type.m_grass_model->getResourceManager().get(ResourceManager::MODEL)->unload(*type.m_grass_model);
|
||||||
m_grass_model->getObserverCb().unbind<Terrain, &Terrain::grassLoaded>(this);
|
type.m_grass_model->getObserverCb().unbind<GrassType, &GrassType::grassLoaded>(&type);
|
||||||
m_grass_model = NULL;
|
type.m_grass_model = NULL;
|
||||||
LUMIX_DELETE(m_grass_mesh);
|
LUMIX_DELETE(type.m_grass_mesh);
|
||||||
LUMIX_DELETE(m_grass_geometry);
|
LUMIX_DELETE(type.m_grass_geometry);
|
||||||
m_grass_mesh = NULL;
|
type.m_grass_mesh = NULL;
|
||||||
m_grass_geometry = NULL;
|
type.m_grass_geometry = NULL;
|
||||||
}
|
}
|
||||||
if (path.isValid())
|
if (path.isValid())
|
||||||
{
|
{
|
||||||
m_grass_model = static_cast<Model*>(m_scene.getEngine().getResourceManager().get(ResourceManager::MODEL)->load(path));
|
type.m_grass_model = static_cast<Model*>(m_scene.getEngine().getResourceManager().get(ResourceManager::MODEL)->load(path));
|
||||||
m_grass_model->getObserverCb().bind<Terrain, &Terrain::grassLoaded>(this);
|
type.m_grass_model->getObserverCb().bind<GrassType, &GrassType::grassLoaded>(&type);
|
||||||
|
if(type.m_grass_model->isReady())
|
||||||
|
{
|
||||||
|
type.grassLoaded(Resource::State::READY, Resource::State::READY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Terrain::forceGrassUpdate()
|
||||||
|
{
|
||||||
|
m_force_grass_update = true;
|
||||||
|
while(!m_grass_quads.empty())
|
||||||
|
{
|
||||||
|
m_free_grass_quads.push(m_grass_quads.back());
|
||||||
|
m_grass_quads.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Terrain::updateGrass(const Vec3& camera_position)
|
void Terrain::updateGrass(const Vec3& camera_position)
|
||||||
{
|
{
|
||||||
PROFILE_FUNCTION();
|
PROFILE_FUNCTION();
|
||||||
|
@ -232,8 +328,9 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_last_camera_position - camera_position).length() > 1)
|
if ((m_last_camera_position - camera_position).length() > 1 || m_force_grass_update)
|
||||||
{
|
{
|
||||||
|
m_force_grass_update = false;
|
||||||
Matrix mtx = m_entity.getMatrix();
|
Matrix mtx = m_entity.getMatrix();
|
||||||
Matrix inv_mtx = m_entity.getMatrix();
|
Matrix inv_mtx = m_entity.getMatrix();
|
||||||
inv_mtx.fastInverse();
|
inv_mtx.fastInverse();
|
||||||
|
@ -272,21 +369,41 @@ namespace Lumix
|
||||||
GrassQuad* quad = m_free_grass_quads.back();
|
GrassQuad* quad = m_free_grass_quads.back();
|
||||||
m_free_grass_quads.pop();
|
m_free_grass_quads.pop();
|
||||||
m_grass_quads.push(quad);
|
m_grass_quads.push(quad);
|
||||||
quad->m_matrices.resize(31 * 31);
|
|
||||||
quad->m_x = quad_x;
|
quad->m_x = quad_x;
|
||||||
quad->m_z = quad_z;
|
quad->m_z = quad_z;
|
||||||
|
quad->m_patches.clear();
|
||||||
srand((int)quad_x + (int)quad_z * GRASS_QUADS_WIDTH);
|
srand((int)quad_x + (int)quad_z * GRASS_QUADS_WIDTH);
|
||||||
int index = 0;
|
for(int grass_type_idx = 0; grass_type_idx < m_grass_types.size(); ++grass_type_idx)
|
||||||
for (float dx = 0; dx < GRASS_QUAD_SIZE; dx += 0.333f)
|
|
||||||
{
|
{
|
||||||
for (float dz = 0; dz < GRASS_QUAD_SIZE; dz += 0.333f)
|
GrassPatch& patch = quad->m_patches.pushEmpty();
|
||||||
|
patch.m_matrices.clear();
|
||||||
|
patch.m_type = m_grass_types[grass_type_idx];
|
||||||
|
if(patch.m_type->m_grass_geometry)
|
||||||
{
|
{
|
||||||
quad->m_matrices[index] = Matrix::IDENTITY;
|
int index = 0;
|
||||||
float x = quad_x + dx + (rand() % 100 - 50) / 100.0f;
|
Texture* splat_map = m_material->getTexture(m_material->getTextureCount() - 1);
|
||||||
float z = quad_z + dz + (rand() % 100 - 50) / 100.0f;;
|
float step = GRASS_QUAD_SIZE / (float)patch.m_type->m_density;
|
||||||
quad->m_matrices[index].setTranslation(Vec3(x, getHeight(x / m_xz_scale, z / m_xz_scale), z));
|
for (float dx = 0; dx < GRASS_QUAD_SIZE; dx += step)
|
||||||
quad->m_matrices[index] = mtx * quad->m_matrices[index];
|
{
|
||||||
++index;
|
for (float dz = 0; dz < GRASS_QUAD_SIZE; dz += step)
|
||||||
|
{
|
||||||
|
uint32_t pixel_value = splat_map->getPixel(splat_map->getWidth() * (quad_x + dx) / m_width, splat_map->getHeight() * (quad_z + dz) / m_height);
|
||||||
|
uint8_t count = (pixel_value >> (8 * patch.m_type->m_ground)) & 0xff;
|
||||||
|
float density = count / 255.0f;
|
||||||
|
if(density > 0.25f)
|
||||||
|
{
|
||||||
|
Matrix& grass_mtx = patch.m_matrices.pushEmpty();
|
||||||
|
grass_mtx = Matrix::IDENTITY;
|
||||||
|
float x = quad_x + dx + step * (rand() % 100 - 50) / 100.0f;
|
||||||
|
float z = quad_z + dz + step * (rand() % 100 - 50) / 100.0f;
|
||||||
|
grass_mtx.setTranslation(Vec3(x, getHeight(x / m_xz_scale, z / m_xz_scale), z));
|
||||||
|
grass_mtx = mtx * grass_mtx;
|
||||||
|
grass_mtx.multiply3x3(density + (rand() % 20 - 10) / 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,7 +414,7 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Terrain::grassVertexCopyCallback(Array<uint8_t>& data)
|
void Terrain::GrassType::grassVertexCopyCallback(Array<uint8_t>& data)
|
||||||
{
|
{
|
||||||
bool has_matrix_index_attribute = m_grass_model->getGeometry()->getVertexDefinition().getAttributeType(3) == VertexAttributeDef::INT1;
|
bool has_matrix_index_attribute = m_grass_model->getGeometry()->getVertexDefinition().getAttributeType(3) == VertexAttributeDef::INT1;
|
||||||
if (has_matrix_index_attribute)
|
if (has_matrix_index_attribute)
|
||||||
|
@ -320,7 +437,7 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Terrain::grassIndexCopyCallback(Array<int>& data)
|
void Terrain::GrassType::grassIndexCopyCallback(Array<int>& data)
|
||||||
{
|
{
|
||||||
int indices_count = m_grass_model->getGeometry()->getIndices().size();
|
int indices_count = m_grass_model->getGeometry()->getIndices().size();
|
||||||
int index_offset = m_grass_model->getGeometry()->getVertices().size();
|
int index_offset = m_grass_model->getGeometry()->getVertices().size();
|
||||||
|
@ -334,7 +451,7 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Terrain::grassLoaded(Resource::State, Resource::State)
|
void Terrain::GrassType::grassLoaded(Resource::State, Resource::State)
|
||||||
{
|
{
|
||||||
if (m_grass_model->isReady())
|
if (m_grass_model->isReady())
|
||||||
{
|
{
|
||||||
|
@ -343,38 +460,40 @@ namespace Lumix
|
||||||
m_grass_geometry = LUMIX_NEW(Geometry);
|
m_grass_geometry = LUMIX_NEW(Geometry);
|
||||||
Geometry::VertexCallback vertex_callback;
|
Geometry::VertexCallback vertex_callback;
|
||||||
Geometry::IndexCallback index_callback;
|
Geometry::IndexCallback index_callback;
|
||||||
vertex_callback.bind<Terrain, &Terrain::grassVertexCopyCallback>(this);
|
vertex_callback.bind<GrassType, &GrassType::grassVertexCopyCallback>(this);
|
||||||
index_callback.bind<Terrain, &Terrain::grassIndexCopyCallback>(this);
|
index_callback.bind<GrassType, &GrassType::grassIndexCopyCallback>(this);
|
||||||
m_grass_geometry->copy(*m_grass_model->getGeometry(), COPY_COUNT, vertex_callback, index_callback);
|
m_grass_geometry->copy(*m_grass_model->getGeometry(), COPY_COUNT, vertex_callback, index_callback);
|
||||||
Material* material = m_grass_model->getMesh(0).getMaterial();
|
Material* material = m_grass_model->getMesh(0).getMaterial();
|
||||||
m_grass_mesh = LUMIX_NEW(Mesh)(material, 0, m_grass_model->getMesh(0).getCount() * COPY_COUNT, "grass");
|
m_grass_mesh = LUMIX_NEW(Mesh)(material, 0, m_grass_model->getMesh(0).getCount() * COPY_COUNT, "grass");
|
||||||
|
m_terrain.forceGrassUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Terrain::getGrassInfos(Array<GrassInfo>& infos, const Vec3& camera_position)
|
void Terrain::getGrassInfos(Array<GrassInfo>& infos, const Vec3& camera_position)
|
||||||
{
|
{
|
||||||
if (m_grass_geometry && m_grass_model->isReady() && m_material->isReady())
|
updateGrass(camera_position);
|
||||||
|
for (int i = 0; i < m_grass_quads.size(); ++i)
|
||||||
{
|
{
|
||||||
updateGrass(camera_position);
|
for(int patch_idx = 0; patch_idx < m_grass_quads[i]->m_patches.size(); ++patch_idx)
|
||||||
for (int i = 0; i < m_grass_quads.size(); ++i)
|
|
||||||
{
|
{
|
||||||
for (int k = 0, kc = m_grass_quads[i]->m_matrices.size() / COPY_COUNT; k < kc; ++k)
|
GrassPatch& patch = m_grass_quads[i]->m_patches[patch_idx];
|
||||||
|
for (int k = 0, kc = patch.m_matrices.size() / COPY_COUNT; k < kc; ++k)
|
||||||
{
|
{
|
||||||
GrassInfo& info = infos.pushEmpty();
|
GrassInfo& info = infos.pushEmpty();
|
||||||
info.m_geometry = m_grass_geometry;
|
info.m_geometry = patch.m_type->m_grass_geometry;
|
||||||
info.m_matrices = &m_grass_quads[i]->m_matrices[COPY_COUNT * k];
|
info.m_matrices = &patch.m_matrices[COPY_COUNT * k];
|
||||||
info.m_mesh = m_grass_mesh;
|
info.m_mesh = patch.m_type->m_grass_mesh;
|
||||||
info.m_matrix_count = COPY_COUNT;
|
info.m_matrix_count = COPY_COUNT;
|
||||||
info.m_mesh_copy_count = COPY_COUNT;
|
info.m_mesh_copy_count = COPY_COUNT;
|
||||||
}
|
}
|
||||||
if (m_grass_quads[i]->m_matrices.size() % COPY_COUNT != 0)
|
if (patch.m_matrices.size() % COPY_COUNT != 0)
|
||||||
{
|
{
|
||||||
GrassInfo& info = infos.pushEmpty();
|
GrassInfo& info = infos.pushEmpty();
|
||||||
info.m_geometry = m_grass_geometry;
|
info.m_geometry = patch.m_type->m_grass_geometry;
|
||||||
info.m_matrices = &m_grass_quads[i]->m_matrices[COPY_COUNT * (m_grass_quads[i]->m_matrices.size() / COPY_COUNT)];
|
info.m_matrices = &patch.m_matrices[COPY_COUNT * (patch.m_matrices.size() / COPY_COUNT)];
|
||||||
info.m_mesh = m_grass_mesh;
|
info.m_mesh = patch.m_type->m_grass_mesh;
|
||||||
info.m_matrix_count = m_grass_quads[i]->m_matrices.size() % COPY_COUNT;
|
info.m_matrix_count = patch.m_matrices.size() % COPY_COUNT;
|
||||||
info.m_mesh_copy_count = COPY_COUNT;
|
info.m_mesh_copy_count = COPY_COUNT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -418,8 +537,24 @@ namespace Lumix
|
||||||
setMaterial(static_cast<Material*>(scene.getEngine().getResourceManager().get(ResourceManager::MATERIAL)->load(path)));
|
setMaterial(static_cast<Material*>(scene.getEngine().getResourceManager().get(ResourceManager::MATERIAL)->load(path)));
|
||||||
serializer.deserializeArrayItem(m_xz_scale);
|
serializer.deserializeArrayItem(m_xz_scale);
|
||||||
serializer.deserializeArrayItem(m_y_scale);
|
serializer.deserializeArrayItem(m_y_scale);
|
||||||
serializer.deserializeArrayItem(path, LUMIX_MAX_PATH);
|
int count;
|
||||||
setGrassPath(path);
|
serializer.deserializeArrayItem(count);
|
||||||
|
while(m_grass_types.size() > count)
|
||||||
|
{
|
||||||
|
removeGrassType(m_grass_types.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(m_grass_types.size() < count)
|
||||||
|
{
|
||||||
|
addGrassType(-1);
|
||||||
|
}
|
||||||
|
for(int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
serializer.deserializeArrayItem(path, LUMIX_MAX_PATH);
|
||||||
|
serializer.deserializeArrayItem(m_grass_types[i]->m_ground);
|
||||||
|
serializer.deserializeArrayItem(m_grass_types[i]->m_density);
|
||||||
|
setGrassTypePath(i, path);
|
||||||
|
}
|
||||||
universe.addComponent(m_entity, TERRAIN_HASH, &scene, index);
|
universe.addComponent(m_entity, TERRAIN_HASH, &scene, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,10 +563,18 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
serializer.serializeArrayItem(m_entity.index);
|
serializer.serializeArrayItem(m_entity.index);
|
||||||
serializer.serializeArrayItem(m_layer_mask);
|
serializer.serializeArrayItem(m_layer_mask);
|
||||||
serializer.serializeArrayItem(m_material->getPath().c_str());
|
serializer.serializeArrayItem(m_material ? m_material->getPath().c_str() : "");
|
||||||
serializer.serializeArrayItem(m_xz_scale);
|
serializer.serializeArrayItem(m_xz_scale);
|
||||||
serializer.serializeArrayItem(m_y_scale);
|
serializer.serializeArrayItem(m_y_scale);
|
||||||
serializer.serializeArrayItem(m_grass_model ? m_grass_model->getPath().c_str() : "");
|
serializer.serializeArrayItem(m_grass_types.size());
|
||||||
|
for(int i = 0; i < m_grass_types.size(); ++i)
|
||||||
|
{
|
||||||
|
GrassType& type = *m_grass_types[i];
|
||||||
|
serializer.serializeArrayItem(type.m_grass_model ? type.m_grass_model->getPath().c_str() : "");
|
||||||
|
serializer.serializeArrayItem(type.m_ground);
|
||||||
|
serializer.serializeArrayItem(type.m_density);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -444,11 +587,12 @@ namespace Lumix
|
||||||
m_entity.getMatrix(world_matrix);
|
m_entity.getMatrix(world_matrix);
|
||||||
world_matrix.fastInverse();
|
world_matrix.fastInverse();
|
||||||
Vec3 rel_cam_pos = world_matrix.multiplyPosition(camera_pos) / m_xz_scale;
|
Vec3 rel_cam_pos = world_matrix.multiplyPosition(camera_pos) / m_xz_scale;
|
||||||
m_mesh->getMaterial()->getShader()->setUniform("brush_position", m_brush_position);
|
Shader& shader = *m_mesh->getMaterial()->getShader();
|
||||||
m_mesh->getMaterial()->getShader()->setUniform("brush_size", m_brush_size);
|
renderer.setUniform(shader, "brush_position", BRUSH_POSITION_HASH, m_brush_position);
|
||||||
m_mesh->getMaterial()->getShader()->setUniform("map_size", m_root->m_size);
|
renderer.setUniform(shader, "brush_size", BRUSH_SIZE_HASH, m_brush_size);
|
||||||
m_mesh->getMaterial()->getShader()->setUniform("camera_pos", rel_cam_pos);
|
renderer.setUniform(shader, "map_size", MAP_SIZE_HASH, m_root->m_size);
|
||||||
m_root->render(m_mesh, m_geometry, rel_cam_pos, *pipeline.getScene());
|
renderer.setUniform(shader, "camera_pos", CAMERA_POS_HASH, rel_cam_pos);
|
||||||
|
m_root->render(&static_cast<Renderer&>(m_scene.getPlugin()), m_mesh, m_geometry, rel_cam_pos, *pipeline.getScene());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,8 +621,10 @@ namespace Lumix
|
||||||
|
|
||||||
float Terrain::getHeight(int x, int z)
|
float Terrain::getHeight(int x, int z)
|
||||||
{
|
{
|
||||||
|
int texture_x = (int)(x / m_xz_scale);
|
||||||
|
int texture_y = (int)(z / m_xz_scale);
|
||||||
Texture* t = m_material->getTexture(0);
|
Texture* t = m_material->getTexture(0);
|
||||||
int idx = Math::clamp(x, 0, m_width) + Math::clamp(z, 0, m_height) * m_width;
|
int idx = Math::clamp(texture_x, 0, m_width) + Math::clamp(texture_y, 0, m_height) * m_width;
|
||||||
if (t->getBytesPerPixel() == 2)
|
if (t->getBytesPerPixel() == 2)
|
||||||
{
|
{
|
||||||
return ((m_y_scale / (256.0f * 256.0f - 1)) * ((uint16_t*)t->getData())[idx]);
|
return ((m_y_scale / (256.0f * 256.0f - 1)) * ((uint16_t*)t->getData())[idx]);
|
||||||
|
@ -494,6 +640,7 @@ namespace Lumix
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool getRayTriangleIntersection(const Vec3& local_origin, const Vec3& local_dir, const Vec3& p0, const Vec3& p1, const Vec3& p2, float& out)
|
bool getRayTriangleIntersection(const Vec3& local_origin, const Vec3& local_dir, const Vec3& p0, const Vec3& p1, const Vec3& p2, float& out)
|
||||||
{
|
{
|
||||||
Vec3 normal = crossProduct(p1 - p0, p2 - p0);
|
Vec3 normal = crossProduct(p1 - p0, p2 - p0);
|
||||||
|
|
|
@ -26,10 +26,35 @@ struct TerrainQuad;
|
||||||
class Terrain
|
class Terrain
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
class GrassQuad
|
class GrassType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GrassType(Terrain& terrain);
|
||||||
|
~GrassType();
|
||||||
|
|
||||||
|
void grassLoaded(Resource::State, Resource::State);
|
||||||
|
void grassVertexCopyCallback(Array<uint8_t>& data);
|
||||||
|
void grassIndexCopyCallback(Array<int>& data);
|
||||||
|
|
||||||
|
Geometry* m_grass_geometry;
|
||||||
|
Mesh* m_grass_mesh;
|
||||||
|
Model* m_grass_model;
|
||||||
|
Terrain& m_terrain;
|
||||||
|
int m_ground;
|
||||||
|
int m_density;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GrassPatch
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Array<Matrix> m_matrices;
|
Array<Matrix> m_matrices;
|
||||||
|
GrassType* m_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GrassQuad
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Array<GrassPatch> m_patches;
|
||||||
float m_x;
|
float m_x;
|
||||||
float m_z;
|
float m_z;
|
||||||
};
|
};
|
||||||
|
@ -54,21 +79,26 @@ class Terrain
|
||||||
float getYScale() const { return m_y_scale; }
|
float getYScale() const { return m_y_scale; }
|
||||||
Entity getEntity() const { return m_entity; }
|
Entity getEntity() const { return m_entity; }
|
||||||
Material* getMaterial() const { return m_material; }
|
Material* getMaterial() const { return m_material; }
|
||||||
void setGrassPath(const Path& path);
|
void setGrassTypePath(int index, const Path& path);
|
||||||
Path getGrassPath();
|
Path getGrassTypePath(int index);
|
||||||
|
void setGrassTypeGround(int index, int ground);
|
||||||
|
int getGrassTypeGround(int index);
|
||||||
|
void setGrassTypeDensity(int index, int density);
|
||||||
|
int getGrassTypeDensity(int index);
|
||||||
|
void addGrassType(int index);
|
||||||
|
void removeGrassType(int index);
|
||||||
|
int getGrassTypeCount() const { return m_grass_types.size(); }
|
||||||
void setMaterial(Material* material);
|
void setMaterial(Material* material);
|
||||||
void getGrassInfos(Array<GrassInfo>& infos, const Vec3& camera_position);
|
void getGrassInfos(Array<GrassInfo>& infos, const Vec3& camera_position);
|
||||||
void setBrush(const Vec3& position, float size) { m_brush_position = position; m_brush_size = size; }
|
void setBrush(const Vec3& position, float size) { m_brush_position = position; m_brush_size = size; }
|
||||||
|
float getHeight(float x, float z);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateGrass(const Vec3& camera_position);
|
void updateGrass(const Vec3& camera_position);
|
||||||
void generateGeometry();
|
void generateGeometry();
|
||||||
void onMaterialLoaded(Resource::State, Resource::State new_state);
|
void onMaterialLoaded(Resource::State, Resource::State new_state);
|
||||||
float getHeight(int x, int z);
|
float getHeight(int x, int z);
|
||||||
float getHeight(float x, float z);
|
void forceGrassUpdate();
|
||||||
void grassLoaded(Resource::State, Resource::State);
|
|
||||||
void grassVertexCopyCallback(Array<uint8_t>& data);
|
|
||||||
void grassIndexCopyCallback(Array<int>& data);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mesh* m_mesh;
|
Mesh* m_mesh;
|
||||||
|
@ -81,15 +111,14 @@ class Terrain
|
||||||
float m_y_scale;
|
float m_y_scale;
|
||||||
Entity m_entity;
|
Entity m_entity;
|
||||||
Material* m_material;
|
Material* m_material;
|
||||||
Geometry* m_grass_geometry;
|
|
||||||
Mesh* m_grass_mesh;
|
|
||||||
RenderScene& m_scene;
|
RenderScene& m_scene;
|
||||||
Model* m_grass_model;
|
Array<GrassType*> m_grass_types;
|
||||||
Array<GrassQuad*> m_free_grass_quads;
|
Array<GrassQuad*> m_free_grass_quads;
|
||||||
Array<GrassQuad*> m_grass_quads;
|
Array<GrassQuad*> m_grass_quads;
|
||||||
Vec3 m_last_camera_position;
|
Vec3 m_last_camera_position;
|
||||||
Vec3 m_brush_position;
|
Vec3 m_brush_position;
|
||||||
float m_brush_size;
|
float m_brush_size;
|
||||||
|
bool m_force_grass_update;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -449,6 +449,43 @@ namespace Lumix
|
||||||
glBindTexture(m_is_cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, m_id);
|
glBindTexture(m_is_cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t Texture::getPixel(float x, float y) const
|
||||||
|
{
|
||||||
|
if(m_data.empty() || x >= m_width || y >= m_height || x < 0 || y < 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://fastcpp.blogspot.sk/2011/06/bilinear-pixel-interpolation-using-sse.html
|
||||||
|
int px = (int)x;
|
||||||
|
int py = (int)y;
|
||||||
|
const uint32_t* p0 = (uint32_t*)&m_data[(px + py * m_width) * 4];
|
||||||
|
|
||||||
|
const uint8_t* p1 = (uint8_t*)p0;
|
||||||
|
const uint8_t* p2 = (uint8_t*)(p0 + 1);
|
||||||
|
const uint8_t* p3 = (uint8_t*)(p0 + m_width);
|
||||||
|
const uint8_t* p4 = (uint8_t*)(p0 + 1 + m_width);
|
||||||
|
|
||||||
|
float fx = x - px;
|
||||||
|
float fy = y - py;
|
||||||
|
float fx1 = 1.0f - fx;
|
||||||
|
float fy1 = 1.0f - fy;
|
||||||
|
|
||||||
|
int w1 = (int)(fx1 * fy1 * 256.0f);
|
||||||
|
int w2 = (int)(fx * fy1 * 256.0f);
|
||||||
|
int w3 = (int)(fx1 * fy * 256.0f);
|
||||||
|
int w4 = (int)(fx * fy * 256.0f);
|
||||||
|
|
||||||
|
uint8_t res[4];
|
||||||
|
res[0] = (uint8_t)((p1[0] * w1 + p2[0] * w2 + p3[0] * w3 + p4[0] * w4) >> 8);
|
||||||
|
res[1] = (uint8_t)((p1[1] * w1 + p2[1] * w2 + p3[1] * w3 + p4[1] * w4) >> 8);
|
||||||
|
res[2] = (uint8_t)((p1[2] * w1 + p2[2] * w2 + p3[2] * w3 + p4[2] * w4) >> 8);
|
||||||
|
res[3] = (uint8_t)((p1[3] * w1 + p2[3] * w2 + p3[3] * w3 + p4[3] * w4) >> 8);
|
||||||
|
|
||||||
|
return *(uint32_t*)res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Texture::saveTGA()
|
void Texture::saveTGA()
|
||||||
{
|
{
|
||||||
|
@ -670,6 +707,8 @@ bool Texture::loadDDS(FS::IFile& file)
|
||||||
|
|
||||||
width = hdr.dwWidth;
|
width = hdr.dwWidth;
|
||||||
height = hdr.dwHeight;
|
height = hdr.dwHeight;
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
if ((width & (width - 1)) || (height & (height - 1)))
|
if ((width & (width - 1)) || (height & (height - 1)))
|
||||||
{
|
{
|
||||||
g_log_error.log("renderer") << "Wrong dds format " << m_path.c_str();
|
g_log_error.log("renderer") << "Wrong dds format " << m_path.c_str();
|
||||||
|
@ -863,7 +902,7 @@ void Texture::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
||||||
}
|
}
|
||||||
if(!loaded)
|
if(!loaded)
|
||||||
{
|
{
|
||||||
g_log_error.log("renderer") << "Error loading texture " << m_path.c_str();
|
g_log_warning.log("renderer") << "Error loading texture " << m_path.c_str();
|
||||||
onFailure();
|
onFailure();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -874,7 +913,7 @@ void Texture::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_log_error.log("renderer") << "Error loading texture " << m_path.c_str();
|
g_log_warning.log("renderer") << "Error loading texture " << m_path.c_str();
|
||||||
onFailure();
|
onFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ class LUMIX_ENGINE_API Texture : public Resource
|
||||||
void removeDataReference();
|
void removeDataReference();
|
||||||
void onDataUpdated();
|
void onDataUpdated();
|
||||||
void save();
|
void save();
|
||||||
|
uint32_t getPixel(float x, float y) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loaded(FS::IFile* file, bool success, FS::FileSystem& fs);
|
void loaded(FS::IFile* file, bool success, FS::FileSystem& fs);
|
||||||
|
|
|
@ -49,7 +49,7 @@ struct OutputStream : public physx::PxOutputStream
|
||||||
{
|
{
|
||||||
if (size + (int)count > capacity)
|
if (size + (int)count > capacity)
|
||||||
{
|
{
|
||||||
int new_capacity = Math::max(size + (int)count, capacity + 4096);
|
int new_capacity = Math::maxValue(size + (int)count, capacity + 4096);
|
||||||
uint8_t* new_data = LUMIX_NEW_ARRAY(unsigned char, new_capacity);
|
uint8_t* new_data = LUMIX_NEW_ARRAY(unsigned char, new_capacity);
|
||||||
memcpy(new_data, data, size);
|
memcpy(new_data, data, size);
|
||||||
LUMIX_DELETE_ARRAY(data);
|
LUMIX_DELETE_ARRAY(data);
|
||||||
|
@ -147,7 +147,63 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual Component createHeightfield(Entity entity) override
|
virtual IPlugin& getPlugin() const override
|
||||||
|
{
|
||||||
|
return *m_system;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual Component createComponent(uint32_t component_type, const Entity& entity) override
|
||||||
|
{
|
||||||
|
if (component_type == HEIGHTFIELD_HASH)
|
||||||
|
{
|
||||||
|
return createHeightfield(entity);
|
||||||
|
}
|
||||||
|
else if (component_type == CONTROLLER_HASH)
|
||||||
|
{
|
||||||
|
return createController(entity);
|
||||||
|
}
|
||||||
|
else if (component_type == BOX_ACTOR_HASH)
|
||||||
|
{
|
||||||
|
return createBoxRigidActor(entity);
|
||||||
|
}
|
||||||
|
else if (component_type == MESH_ACTOR_HASH)
|
||||||
|
{
|
||||||
|
return createMeshRigidActor(entity);
|
||||||
|
}
|
||||||
|
return Component::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void destroyComponent(const Component& cmp) override
|
||||||
|
{
|
||||||
|
if(cmp.type == HEIGHTFIELD_HASH)
|
||||||
|
{
|
||||||
|
LUMIX_DELETE(m_terrains[cmp.index]);
|
||||||
|
m_terrains[cmp.index] = NULL;
|
||||||
|
m_universe->destroyComponent(cmp);
|
||||||
|
m_universe->componentDestroyed().invoke(cmp);
|
||||||
|
}
|
||||||
|
else if(cmp.type == CONTROLLER_HASH)
|
||||||
|
{
|
||||||
|
m_controllers[cmp.index].m_is_free = true;
|
||||||
|
m_universe->destroyComponent(cmp);
|
||||||
|
m_universe->componentDestroyed().invoke(cmp);
|
||||||
|
}
|
||||||
|
else if (cmp.type == MESH_ACTOR_HASH || cmp.type == BOX_ACTOR_HASH)
|
||||||
|
{
|
||||||
|
m_actors[cmp.index]->m_entity.index = -1;
|
||||||
|
m_universe->destroyComponent(cmp);
|
||||||
|
m_universe->componentDestroyed().invoke(cmp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Component createHeightfield(Entity entity)
|
||||||
{
|
{
|
||||||
Terrain* terrain = LUMIX_NEW(Terrain);
|
Terrain* terrain = LUMIX_NEW(Terrain);
|
||||||
m_terrains.push(terrain);
|
m_terrains.push(terrain);
|
||||||
|
@ -161,7 +217,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual Component createController(Entity entity) override
|
Component createController(Entity entity)
|
||||||
{
|
{
|
||||||
physx::PxCapsuleControllerDesc cDesc;
|
physx::PxCapsuleControllerDesc cDesc;
|
||||||
cDesc.material = m_default_material;
|
cDesc.material = m_default_material;
|
||||||
|
@ -177,6 +233,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
PhysicsSceneImpl::Controller c;
|
PhysicsSceneImpl::Controller c;
|
||||||
c.m_controller = m_system->m_impl->m_controller_manager->createController(*m_system->m_impl->m_physics, m_scene, cDesc);
|
c.m_controller = m_system->m_impl->m_controller_manager->createController(*m_system->m_impl->m_physics, m_scene, cDesc);
|
||||||
c.m_entity = entity;
|
c.m_entity = entity;
|
||||||
|
c.m_is_free = false;
|
||||||
|
|
||||||
m_controllers.push(c);
|
m_controllers.push(c);
|
||||||
|
|
||||||
|
@ -186,7 +243,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual Component createBoxRigidActor(Entity entity) override
|
Component createBoxRigidActor(Entity entity)
|
||||||
{
|
{
|
||||||
RigidActor* actor = LUMIX_NEW(RigidActor);
|
RigidActor* actor = LUMIX_NEW(RigidActor);
|
||||||
m_actors.push(actor);
|
m_actors.push(actor);
|
||||||
|
@ -214,7 +271,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual Component createMeshRigidActor(Entity entity) override
|
Component createMeshRigidActor(Entity entity)
|
||||||
{
|
{
|
||||||
RigidActor* actor = LUMIX_NEW(RigidActor);
|
RigidActor* actor = LUMIX_NEW(RigidActor);
|
||||||
m_actors.push(actor);
|
m_actors.push(actor);
|
||||||
|
@ -234,13 +291,13 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void getHeightmapXZScale(Component cmp, float& scale) override
|
virtual float getHeightmapXZScale(Component cmp) override
|
||||||
{
|
{
|
||||||
scale = m_terrains[cmp.index]->m_xz_scale;
|
return m_terrains[cmp.index]->m_xz_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void setHeightmapXZScale(Component cmp, const float& scale) override
|
virtual void setHeightmapXZScale(Component cmp, float scale) override
|
||||||
{
|
{
|
||||||
if (scale != m_terrains[cmp.index]->m_xz_scale)
|
if (scale != m_terrains[cmp.index]->m_xz_scale)
|
||||||
{
|
{
|
||||||
|
@ -250,13 +307,13 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void getHeightmapYScale(Component cmp, float& scale) override
|
virtual float getHeightmapYScale(Component cmp) override
|
||||||
{
|
{
|
||||||
scale = m_terrains[cmp.index]->m_y_scale;
|
return m_terrains[cmp.index]->m_y_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void setHeightmapYScale(Component cmp, const float& scale) override
|
virtual void setHeightmapYScale(Component cmp, float scale) override
|
||||||
{
|
{
|
||||||
if (scale != m_terrains[cmp.index]->m_y_scale)
|
if (scale != m_terrains[cmp.index]->m_y_scale)
|
||||||
{
|
{
|
||||||
|
@ -460,9 +517,12 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
physx::PxVec3 g(0, time_delta * -9.8f, 0);
|
physx::PxVec3 g(0, time_delta * -9.8f, 0);
|
||||||
for (int i = 0; i < m_controllers.size(); ++i)
|
for (int i = 0; i < m_controllers.size(); ++i)
|
||||||
{
|
{
|
||||||
const physx::PxExtendedVec3& p = m_controllers[i].m_controller->getPosition();
|
if(!m_controllers[i].m_is_free)
|
||||||
m_controllers[i].m_controller->move(g, 0.0001f, time_delta, physx::PxControllerFilters());
|
{
|
||||||
m_controllers[i].m_entity.setPosition((float)p.x, (float)p.y, (float)p.z);
|
const physx::PxExtendedVec3& p = m_controllers[i].m_controller->getPosition();
|
||||||
|
m_controllers[i].m_controller->move(g, 0.0001f, time_delta, physx::PxControllerFilters());
|
||||||
|
m_controllers[i].m_entity.setPosition((float)p.x, (float)p.y, (float)p.z);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +560,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void onEntityMoved(Entity& entity)
|
void onEntityMoved(const Entity& entity)
|
||||||
{
|
{
|
||||||
const Entity::ComponentList& cmps = entity.getComponents();
|
const Entity::ComponentList& cmps = entity.getComponents();
|
||||||
for (int i = 0, c = cmps.size(); i < c; ++i)
|
for (int i = 0, c = cmps.size(); i < c; ++i)
|
||||||
|
@ -634,8 +694,9 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void getHalfExtents(Component cmp, Vec3& size) override
|
virtual Vec3 getHalfExtents(Component cmp) override
|
||||||
{
|
{
|
||||||
|
Vec3 size;
|
||||||
physx::PxRigidActor* actor = m_actors[cmp.index]->m_physx_actor;
|
physx::PxRigidActor* actor = m_actors[cmp.index]->m_physx_actor;
|
||||||
physx::PxShape* shapes;
|
physx::PxShape* shapes;
|
||||||
if (actor->getNbShapes() == 1 && m_actors[cmp.index]->m_physx_actor->getShapes(&shapes, 1))
|
if (actor->getNbShapes() == 1 && m_actors[cmp.index]->m_physx_actor->getShapes(&shapes, 1))
|
||||||
|
@ -645,6 +706,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
size.y = half.y;
|
size.y = half.y;
|
||||||
size.z = half.z;
|
size.z = half.z;
|
||||||
}
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -795,7 +857,10 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
serializer.serializeArrayItem(m_actors[i]->m_source);
|
serializer.serializeArrayItem(m_actors[i]->m_source);
|
||||||
serializer.serializeArrayItem(isDynamic(i));
|
serializer.serializeArrayItem(isDynamic(i));
|
||||||
serializer.serializeArrayItem(m_actors[i]->m_entity.index);
|
serializer.serializeArrayItem(m_actors[i]->m_entity.index);
|
||||||
serializeActor(serializer, i);
|
if(m_actors[i]->m_entity.index != -1)
|
||||||
|
{
|
||||||
|
serializeActor(serializer, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.endArray();
|
serializer.endArray();
|
||||||
serializer.serialize("count", m_controllers.size());
|
serializer.serialize("count", m_controllers.size());
|
||||||
|
@ -803,16 +868,25 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
for (int i = 0; i < m_controllers.size(); ++i)
|
for (int i = 0; i < m_controllers.size(); ++i)
|
||||||
{
|
{
|
||||||
serializer.serializeArrayItem(m_controllers[i].m_entity.index);
|
serializer.serializeArrayItem(m_controllers[i].m_entity.index);
|
||||||
|
serializer.serializeArrayItem(m_controllers[i].m_is_free);
|
||||||
}
|
}
|
||||||
serializer.endArray();
|
serializer.endArray();
|
||||||
serializer.serialize("count", m_terrains.size());
|
serializer.serialize("count", m_terrains.size());
|
||||||
serializer.beginArray("terrains");
|
serializer.beginArray("terrains");
|
||||||
for (int i = 0; i < m_terrains.size(); ++i)
|
for (int i = 0; i < m_terrains.size(); ++i)
|
||||||
{
|
{
|
||||||
serializer.serializeArrayItem(m_terrains[i]->m_entity.index);
|
if(m_terrains[i])
|
||||||
serializer.serializeArrayItem(m_terrains[i]->m_heightmap->getPath().c_str());
|
{
|
||||||
serializer.serializeArrayItem(m_terrains[i]->m_xz_scale);
|
serializer.serializeArrayItem(true);
|
||||||
serializer.serializeArrayItem(m_terrains[i]->m_y_scale);
|
serializer.serializeArrayItem(m_terrains[i]->m_entity.index);
|
||||||
|
serializer.serializeArrayItem(m_terrains[i]->m_heightmap->getPath().c_str());
|
||||||
|
serializer.serializeArrayItem(m_terrains[i]->m_xz_scale);
|
||||||
|
serializer.serializeArrayItem(m_terrains[i]->m_y_scale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serializer.serializeArrayItem(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.endArray();
|
serializer.endArray();
|
||||||
}
|
}
|
||||||
|
@ -839,8 +913,11 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
m_dynamic_actors.push(m_actors[i]);
|
m_dynamic_actors.push(m_actors[i]);
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayItem(m_actors[i]->m_entity.index);
|
serializer.deserializeArrayItem(m_actors[i]->m_entity.index);
|
||||||
m_actors[i]->m_entity.universe = m_universe;
|
if(m_actors[i]->m_entity.index != -1)
|
||||||
deserializeActor(serializer, i);
|
{
|
||||||
|
m_actors[i]->m_entity.universe = m_universe;
|
||||||
|
deserializeActor(serializer, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
}
|
}
|
||||||
|
@ -859,26 +936,32 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
bool is_free;
|
||||||
serializer.deserializeArrayItem(index);
|
serializer.deserializeArrayItem(index);
|
||||||
|
serializer.deserializeArrayItem(is_free);
|
||||||
Entity e(m_universe, index);
|
Entity e(m_universe, index);
|
||||||
|
|
||||||
physx::PxCapsuleControllerDesc cDesc;
|
|
||||||
cDesc.material = m_default_material;
|
|
||||||
cDesc.height = 1.8f;
|
|
||||||
cDesc.radius = 0.25f;
|
|
||||||
cDesc.slopeLimit = 0.0f;
|
|
||||||
cDesc.contactOffset = 0.1f;
|
|
||||||
cDesc.stepOffset = 0.02f;
|
|
||||||
cDesc.callback = NULL;
|
|
||||||
cDesc.behaviorCallback = NULL;
|
|
||||||
Vec3 position = e.getPosition();
|
|
||||||
cDesc.position.set(position.x, position.y, position.z);
|
|
||||||
Controller c;
|
Controller c;
|
||||||
c.m_controller = m_system->m_impl->m_controller_manager->createController(*m_system->m_impl->m_physics, m_scene, cDesc);
|
c.m_is_free = is_free;
|
||||||
c.m_entity = e;
|
|
||||||
|
|
||||||
m_controllers.push(c);
|
m_controllers.push(c);
|
||||||
m_universe->addComponent(e, CONTROLLER_HASH, this, i);
|
|
||||||
|
if(!is_free)
|
||||||
|
{
|
||||||
|
physx::PxCapsuleControllerDesc cDesc;
|
||||||
|
cDesc.material = m_default_material;
|
||||||
|
cDesc.height = 1.8f;
|
||||||
|
cDesc.radius = 0.25f;
|
||||||
|
cDesc.slopeLimit = 0.0f;
|
||||||
|
cDesc.contactOffset = 0.1f;
|
||||||
|
cDesc.stepOffset = 0.02f;
|
||||||
|
cDesc.callback = NULL;
|
||||||
|
cDesc.behaviorCallback = NULL;
|
||||||
|
Vec3 position = e.getPosition();
|
||||||
|
cDesc.position.set(position.x, position.y, position.z);
|
||||||
|
c.m_controller = m_system->m_impl->m_controller_manager->createController(*m_system->m_impl->m_physics, m_scene, cDesc);
|
||||||
|
c.m_entity = e;
|
||||||
|
m_universe->addComponent(e, CONTROLLER_HASH, this, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
}
|
}
|
||||||
|
@ -891,30 +974,36 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
for (int i = count; i < m_terrains.size(); ++i)
|
for (int i = count; i < m_terrains.size(); ++i)
|
||||||
{
|
{
|
||||||
LUMIX_DELETE(m_terrains[i]);
|
LUMIX_DELETE(m_terrains[i]);
|
||||||
|
m_terrains[i] = NULL;
|
||||||
}
|
}
|
||||||
int old_size = m_terrains.size();
|
int old_size = m_terrains.size();
|
||||||
m_terrains.resize(count);
|
m_terrains.resize(count);
|
||||||
for (int i = old_size; i < count; ++i)
|
|
||||||
{
|
|
||||||
m_terrains[i] = LUMIX_NEW(Terrain);
|
|
||||||
}
|
|
||||||
serializer.deserializeArrayBegin("terrains");
|
serializer.deserializeArrayBegin("terrains");
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
m_terrains[i]->m_scene = this;
|
bool exists;
|
||||||
m_terrains[i]->m_entity.universe = m_universe;
|
serializer.deserializeArrayItem(exists);
|
||||||
serializer.deserializeArrayItem(m_terrains[i]->m_entity.index);
|
if(exists)
|
||||||
char tmp[LUMIX_MAX_PATH];
|
|
||||||
serializer.deserializeArrayItem(tmp, LUMIX_MAX_PATH);
|
|
||||||
serializer.deserializeArrayItem(m_terrains[i]->m_xz_scale);
|
|
||||||
serializer.deserializeArrayItem(m_terrains[i]->m_y_scale);
|
|
||||||
|
|
||||||
Component cmp(m_terrains[i]->m_entity, HEIGHTFIELD_HASH, this, i);
|
|
||||||
if (m_terrains[i]->m_heightmap == NULL || strcmp(tmp, m_terrains[i]->m_heightmap->getPath().c_str()) != 0)
|
|
||||||
{
|
{
|
||||||
setHeightmap(cmp, string(tmp));
|
if(!m_terrains[i])
|
||||||
|
{
|
||||||
|
m_terrains[i] = LUMIX_NEW(Terrain);
|
||||||
|
}
|
||||||
|
m_terrains[i]->m_scene = this;
|
||||||
|
m_terrains[i]->m_entity.universe = m_universe;
|
||||||
|
serializer.deserializeArrayItem(m_terrains[i]->m_entity.index);
|
||||||
|
char tmp[LUMIX_MAX_PATH];
|
||||||
|
serializer.deserializeArrayItem(tmp, LUMIX_MAX_PATH);
|
||||||
|
serializer.deserializeArrayItem(m_terrains[i]->m_xz_scale);
|
||||||
|
serializer.deserializeArrayItem(m_terrains[i]->m_y_scale);
|
||||||
|
|
||||||
|
Component cmp(m_terrains[i]->m_entity, HEIGHTFIELD_HASH, this, i);
|
||||||
|
if (m_terrains[i]->m_heightmap == NULL || strcmp(tmp, m_terrains[i]->m_heightmap->getPath().c_str()) != 0)
|
||||||
|
{
|
||||||
|
setHeightmap(cmp, string(tmp));
|
||||||
|
}
|
||||||
|
m_universe->addComponent(m_terrains[i]->m_entity, HEIGHTFIELD_HASH, this, i);
|
||||||
}
|
}
|
||||||
m_universe->addComponent(m_terrains[i]->m_entity, HEIGHTFIELD_HASH, this, i);
|
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
}
|
}
|
||||||
|
@ -944,6 +1033,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
||||||
{
|
{
|
||||||
physx::PxController* m_controller;
|
physx::PxController* m_controller;
|
||||||
Entity m_entity;
|
Entity m_entity;
|
||||||
|
bool m_is_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
Universe* m_universe;
|
Universe* m_universe;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "core/lumix.h"
|
#include "core/lumix.h"
|
||||||
#include "core/string.h"
|
#include "core/string.h"
|
||||||
#include "core/vec3.h"
|
#include "core/vec3.h"
|
||||||
|
#include "engine/iplugin.h"
|
||||||
#include "universe/universe.h"
|
#include "universe/universe.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ struct RaycastHit
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class LUMIX_PHYSICS_API PhysicsScene
|
class LUMIX_PHYSICS_API PhysicsScene : public IScene
|
||||||
{
|
{
|
||||||
friend class PhysicsSystem;
|
friend class PhysicsSystem;
|
||||||
public:
|
public:
|
||||||
|
@ -33,29 +34,22 @@ class LUMIX_PHYSICS_API PhysicsScene
|
||||||
virtual void update(float time_delta) = 0;
|
virtual void update(float time_delta) = 0;
|
||||||
virtual void render() = 0;
|
virtual void render() = 0;
|
||||||
virtual bool raycast(const Vec3& origin, const Vec3& dir, float distance, RaycastHit& result) = 0;
|
virtual bool raycast(const Vec3& origin, const Vec3& dir, float distance, RaycastHit& result) = 0;
|
||||||
virtual Component createBoxRigidActor(Entity entity) = 0;
|
|
||||||
virtual Component createMeshRigidActor(Entity entity) = 0;
|
|
||||||
virtual Component createController(Entity entity) = 0;
|
|
||||||
virtual Component createHeightfield(Entity entity) = 0;
|
|
||||||
virtual PhysicsSystem& getSystem() const = 0;
|
virtual PhysicsSystem& getSystem() const = 0;
|
||||||
|
|
||||||
virtual void getIsDynamic(Component cmp, bool& is) = 0;
|
virtual void getIsDynamic(Component cmp, bool& is) = 0;
|
||||||
virtual void setIsDynamic(Component cmp, const bool& is) = 0;
|
virtual void setIsDynamic(Component cmp, const bool& is) = 0;
|
||||||
virtual void getHalfExtents(Component cmp, Vec3& size) = 0;
|
virtual Vec3 getHalfExtents(Component cmp) = 0;
|
||||||
virtual void setHalfExtents(Component cmp, const Vec3& size) = 0;
|
virtual void setHalfExtents(Component cmp, const Vec3& size) = 0;
|
||||||
virtual void getShapeSource(Component cmp, string& str) = 0;
|
virtual void getShapeSource(Component cmp, string& str) = 0;
|
||||||
virtual void setShapeSource(Component cmp, const string& str) = 0;
|
virtual void setShapeSource(Component cmp, const string& str) = 0;
|
||||||
virtual void getHeightmap(Component cmp, string& str) = 0;
|
virtual void getHeightmap(Component cmp, string& str) = 0;
|
||||||
virtual void setHeightmap(Component cmp, const string& str) = 0;
|
virtual void setHeightmap(Component cmp, const string& str) = 0;
|
||||||
virtual void getHeightmapXZScale(Component cmp, float& scale) = 0;
|
virtual float getHeightmapXZScale(Component cmp) = 0;
|
||||||
virtual void setHeightmapXZScale(Component cmp, const float& scale) = 0;
|
virtual void setHeightmapXZScale(Component cmp, float scale) = 0;
|
||||||
virtual void getHeightmapYScale(Component cmp, float& scale) = 0;
|
virtual float getHeightmapYScale(Component cmp) = 0;
|
||||||
virtual void setHeightmapYScale(Component cmp, const float& scale) = 0;
|
virtual void setHeightmapYScale(Component cmp, float scale) = 0;
|
||||||
|
|
||||||
virtual void moveController(Component cmp, const Vec3& v, float dt) = 0;
|
virtual void moveController(Component cmp, const Vec3& v, float dt) = 0;
|
||||||
|
|
||||||
virtual void serialize(ISerializer& serializer) = 0;
|
|
||||||
virtual void deserialize(ISerializer& serializer) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,78 +33,9 @@ struct CustomErrorCallback : public physx::PxErrorCallback
|
||||||
virtual void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line);
|
virtual void reportError(physx::PxErrorCode::Enum code, const char* message, const char* file, int line);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
IScene* PhysicsSystem::createScene(Universe& universe)
|
||||||
void PhysicsSystem::onCreateUniverse(Universe& universe)
|
|
||||||
{
|
{
|
||||||
m_impl->m_scene = PhysicsScene::create(*this, universe, *m_impl->m_engine);
|
return PhysicsScene::create(*this, universe, *m_impl->m_engine);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PhysicsSystem::onDestroyUniverse(Universe& universe)
|
|
||||||
{
|
|
||||||
PhysicsScene::destroy(m_impl->m_scene);
|
|
||||||
m_impl->m_scene = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PhysicsSystem::serialize(ISerializer& serializer)
|
|
||||||
{
|
|
||||||
m_impl->m_scene->serialize(serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PhysicsSystem::deserialize(ISerializer& serializer)
|
|
||||||
{
|
|
||||||
m_impl->m_scene->deserialize(serializer);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PhysicsSystem::sendMessage(const char* message)
|
|
||||||
{
|
|
||||||
if(strcmp("render", message) == 0)
|
|
||||||
{
|
|
||||||
m_impl->m_scene->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PhysicsSystem::destroyComponent(const Component& component)
|
|
||||||
{
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Component PhysicsSystem::createComponent(uint32_t component_type, const Entity& entity)
|
|
||||||
{
|
|
||||||
if (component_type == HEIGHTFIELD_HASH)
|
|
||||||
{
|
|
||||||
return m_impl->m_scene->createHeightfield(entity);
|
|
||||||
}
|
|
||||||
else if (component_type == CONTROLLER_HASH)
|
|
||||||
{
|
|
||||||
return m_impl->m_scene->createController(entity);
|
|
||||||
}
|
|
||||||
else if (component_type == BOX_ACTOR_HASH)
|
|
||||||
{
|
|
||||||
return m_impl->m_scene->createBoxRigidActor(entity);
|
|
||||||
}
|
|
||||||
else if (component_type == MESH_ACTOR_HASH)
|
|
||||||
{
|
|
||||||
return m_impl->m_scene->createMeshRigidActor(entity);
|
|
||||||
}
|
|
||||||
return Component::INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PhysicsSystem::update(float dt)
|
|
||||||
{
|
|
||||||
m_impl->m_scene->update(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PhysicsScene* PhysicsSystem::getScene() const
|
|
||||||
{
|
|
||||||
return m_impl->m_scene;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,16 +58,12 @@ class AssertNullAllocator : public physx::PxAllocatorCallback
|
||||||
|
|
||||||
bool PhysicsSystem::create(Engine& engine)
|
bool PhysicsSystem::create(Engine& engine)
|
||||||
{
|
{
|
||||||
engine.getWorldEditor()->registerProperty("box_rigid_actor", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("dynamic"), &PhysicsScene::getIsDynamic, &PhysicsScene::setIsDynamic));
|
engine.getWorldEditor()->registerProperty("box_rigid_actor", LUMIX_NEW(BoolPropertyDescriptor<PhysicsScene>)("dynamic", &PhysicsScene::getIsDynamic, &PhysicsScene::setIsDynamic));
|
||||||
engine.getWorldEditor()->registerProperty("box_rigid_actor", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("size"), &PhysicsScene::getHalfExtents, &PhysicsScene::setHalfExtents));
|
engine.getWorldEditor()->registerProperty("box_rigid_actor", LUMIX_NEW(Vec3PropertyDescriptor<PhysicsScene>)("size", &PhysicsScene::getHalfExtents, &PhysicsScene::setHalfExtents));
|
||||||
engine.getWorldEditor()->registerProperty("mesh_rigid_actor", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("source"), &PhysicsScene::getShapeSource, &PhysicsScene::setShapeSource, IPropertyDescriptor::FILE));
|
engine.getWorldEditor()->registerProperty("mesh_rigid_actor", LUMIX_NEW(FilePropertyDescriptor<PhysicsScene>)("source", &PhysicsScene::getShapeSource, &PhysicsScene::setShapeSource, "Physics (*.pda)"));
|
||||||
engine.getWorldEditor()->registerProperty("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("heightmap"), &PhysicsScene::getHeightmap, &PhysicsScene::setHeightmap, IPropertyDescriptor::FILE));
|
engine.getWorldEditor()->registerProperty("physical_heightfield", LUMIX_NEW(FilePropertyDescriptor<PhysicsScene>)("heightmap", &PhysicsScene::getHeightmap, &PhysicsScene::setHeightmap, "Image (*.raw)"));
|
||||||
engine.getWorldEditor()->registerProperty("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("xz_scale"), &PhysicsScene::getHeightmapXZScale, &PhysicsScene::setHeightmapXZScale));
|
engine.getWorldEditor()->registerProperty("physical_heightfield", LUMIX_NEW(DecimalPropertyDescriptor<PhysicsScene>)("xz_scale", &PhysicsScene::getHeightmapXZScale, &PhysicsScene::setHeightmapXZScale));
|
||||||
engine.getWorldEditor()->registerProperty("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("y_scale"), &PhysicsScene::getHeightmapYScale, &PhysicsScene::setHeightmapYScale));
|
engine.getWorldEditor()->registerProperty("physical_heightfield", LUMIX_NEW(DecimalPropertyDescriptor<PhysicsScene>)("y_scale", &PhysicsScene::getHeightmapYScale, &PhysicsScene::setHeightmapYScale));
|
||||||
engine.getWorldEditor()->registerCreator(HEIGHTFIELD_HASH, *this);
|
|
||||||
engine.getWorldEditor()->registerCreator(BOX_ACTOR_HASH, *this);
|
|
||||||
engine.getWorldEditor()->registerCreator(MESH_ACTOR_HASH, *this);
|
|
||||||
engine.getWorldEditor()->registerCreator(CONTROLLER_HASH, *this);
|
|
||||||
|
|
||||||
m_impl = LUMIX_NEW(PhysicsSystemImpl);
|
m_impl = LUMIX_NEW(PhysicsSystemImpl);
|
||||||
m_impl->m_allocator = LUMIX_NEW(AssertNullAllocator)();
|
m_impl->m_allocator = LUMIX_NEW(AssertNullAllocator)();
|
||||||
|
|
|
@ -17,17 +17,9 @@ class LUMIX_PHYSICS_API PhysicsSystem : public IPlugin
|
||||||
PhysicsSystem() { m_impl = 0; }
|
PhysicsSystem() { m_impl = 0; }
|
||||||
|
|
||||||
virtual bool create(Engine& engine) override;
|
virtual bool create(Engine& engine) override;
|
||||||
|
virtual IScene* createScene(Universe& universe) override;
|
||||||
virtual void destroy() override;
|
virtual void destroy() override;
|
||||||
virtual void onCreateUniverse(Universe& universe) override;
|
|
||||||
virtual void onDestroyUniverse(Universe& universe) override;
|
|
||||||
virtual void serialize(ISerializer& serializer) override;
|
|
||||||
virtual void deserialize(ISerializer& serializer) override;
|
|
||||||
virtual void update(float dt) override;
|
|
||||||
virtual Component createComponent(uint32_t component_type, const Entity& entity) override;
|
|
||||||
virtual void destroyComponent(const Component& component) override;
|
|
||||||
virtual const char* getName() const override { return "physics"; }
|
virtual const char* getName() const override { return "physics"; }
|
||||||
virtual void sendMessage(const char* message) override;
|
|
||||||
class PhysicsScene* getScene() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct PhysicsSystemImpl* m_impl;
|
struct PhysicsSystemImpl* m_impl;
|
||||||
|
|
|
@ -18,7 +18,6 @@ struct PhysicsSystemImpl
|
||||||
physx::PxAllocatorCallback* m_allocator;
|
physx::PxAllocatorCallback* m_allocator;
|
||||||
physx::PxErrorCallback* m_error_callback;
|
physx::PxErrorCallback* m_error_callback;
|
||||||
physx::PxCooking* m_cooking;
|
physx::PxCooking* m_cooking;
|
||||||
class PhysicsScene* m_scene;
|
|
||||||
class Engine* m_engine;
|
class Engine* m_engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace Lumix
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
class ScriptSystem;
|
class ScriptScene;
|
||||||
class ScriptVisitor;
|
class ScriptVisitor;
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class BaseScript
|
||||||
public:
|
public:
|
||||||
virtual ~BaseScript() {}
|
virtual ~BaseScript() {}
|
||||||
|
|
||||||
virtual void create(ScriptSystem& ctx, Entity e) = 0;
|
virtual void create(ScriptScene& ctx, Entity e) = 0;
|
||||||
virtual void update(float) {}
|
virtual void update(float) {}
|
||||||
virtual void visit(ScriptVisitor&) {}
|
virtual void visit(ScriptVisitor&) {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,273 +21,305 @@ namespace Lumix
|
||||||
typedef BaseScript* (*CreateScriptFunction)();
|
typedef BaseScript* (*CreateScriptFunction)();
|
||||||
typedef void (*DestroyScriptFunction)(BaseScript* script);
|
typedef void (*DestroyScriptFunction)(BaseScript* script);
|
||||||
|
|
||||||
|
class ScriptSceneImpl : public ScriptScene
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ScriptSceneImpl(ScriptSystem& system, Engine& engine, Universe& universe)
|
||||||
|
: m_universe(universe)
|
||||||
|
, m_engine(engine)
|
||||||
|
, m_system(system)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~ScriptSceneImpl()
|
||||||
|
{
|
||||||
|
stopAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual IPlugin& getPlugin() const
|
||||||
|
{
|
||||||
|
return m_system;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void deserialize(ISerializer& serializer) override
|
||||||
|
{
|
||||||
|
stopAll();
|
||||||
|
int count;
|
||||||
|
serializer.deserialize("count", count);
|
||||||
|
serializer.deserializeArrayBegin("scripts");
|
||||||
|
m_script_entities.resize(count);
|
||||||
|
m_paths.resize(count);
|
||||||
|
for (int i = 0; i < m_script_entities.size(); ++i)
|
||||||
|
{
|
||||||
|
serializer.deserializeArrayItem(m_script_entities[i]);
|
||||||
|
serializer.deserializeArrayItem(m_paths[i]);
|
||||||
|
Entity entity(&m_universe, m_script_entities[i]);
|
||||||
|
if(m_script_entities[i] != -1)
|
||||||
|
{
|
||||||
|
m_universe.addComponent(entity, SCRIPT_HASH, this, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serializer.deserializeArrayEnd();
|
||||||
|
runAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void update(float dt)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_running_scripts.size(); ++i)
|
||||||
|
{
|
||||||
|
m_running_scripts[i].m_script_object->update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void getScriptPath(Component cmp, string& str) override
|
||||||
|
{
|
||||||
|
str = m_paths[cmp.index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setScriptPath(Component cmp, const string& str) override
|
||||||
|
{
|
||||||
|
m_paths[cmp.index] = str;
|
||||||
|
stopScript(cmp.index);
|
||||||
|
if (!runScript(cmp.index, cmp.entity))
|
||||||
|
{
|
||||||
|
g_log_warning.log("script") << "Could not run script " << str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void getDll(const char* script_path, char* dll_path, char* full_path, int max_length)
|
||||||
|
{
|
||||||
|
copyString(dll_path, max_length, script_path);
|
||||||
|
int32_t len = (int32_t)strlen(script_path);
|
||||||
|
if (len > 4)
|
||||||
|
{
|
||||||
|
copyString(dll_path + len - 4, 5, ".dll");
|
||||||
|
}
|
||||||
|
copyString(full_path, max_length, m_engine.getBasePath());
|
||||||
|
catCString(full_path, max_length, "\\");
|
||||||
|
catCString(full_path, max_length, dll_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void getScriptDefaultPath(Entity e, char* path, char* full_path, int length, const char* ext)
|
||||||
|
{
|
||||||
|
char tmp[30];
|
||||||
|
toCString(e.index, tmp, 30);
|
||||||
|
|
||||||
|
copyString(full_path, length, m_engine.getBasePath());
|
||||||
|
catCString(full_path, length, "\\scripts\\e");
|
||||||
|
catCString(full_path, length, tmp);
|
||||||
|
catCString(full_path, length, ".");
|
||||||
|
catCString(full_path, length, ext);
|
||||||
|
|
||||||
|
copyString(path, length, "scripts\\e");
|
||||||
|
catCString(path, length, tmp);
|
||||||
|
catCString(path, length, ".");
|
||||||
|
catCString(path, length, ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void stopScript(int index)
|
||||||
|
{
|
||||||
|
int entity_idx = m_script_entities[index];
|
||||||
|
for (int i = 0; i < m_running_scripts.size(); ++i)
|
||||||
|
{
|
||||||
|
if (m_running_scripts[i].m_entity_idx == entity_idx)
|
||||||
|
{
|
||||||
|
DestroyScriptFunction f = (DestroyScriptFunction)GetProcAddress(m_running_scripts[i].m_lib, "destroyScript");
|
||||||
|
f(m_running_scripts[i].m_script_object);
|
||||||
|
BOOL b = FreeLibrary(m_running_scripts[i].m_lib);
|
||||||
|
ASSERT(b == TRUE);
|
||||||
|
m_running_scripts.eraseFast(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool runScript(int i, Entity entity)
|
||||||
|
{
|
||||||
|
char path[LUMIX_MAX_PATH];
|
||||||
|
char full_path[LUMIX_MAX_PATH];
|
||||||
|
getDll(m_paths[i].c_str(), path, full_path, LUMIX_MAX_PATH);
|
||||||
|
HMODULE h = LoadLibrary(full_path);
|
||||||
|
if (h)
|
||||||
|
{
|
||||||
|
CreateScriptFunction f = (CreateScriptFunction)GetProcAddress(h, TEXT("createScript"));
|
||||||
|
BaseScript* script = f();
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
g_log_warning.log("script") << "failed to create script " << m_paths[i].c_str();
|
||||||
|
FreeLibrary(h);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RunningScript running_script;
|
||||||
|
running_script.m_script_object = script;
|
||||||
|
running_script.m_entity_idx = entity.index;
|
||||||
|
running_script.m_lib = h;
|
||||||
|
m_running_scripts.push(running_script);
|
||||||
|
script->create(*this, entity);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Component createScript(Entity entity)
|
||||||
|
{
|
||||||
|
char path[LUMIX_MAX_PATH];
|
||||||
|
char full_path[LUMIX_MAX_PATH];
|
||||||
|
getScriptDefaultPath(entity, path, full_path, LUMIX_MAX_PATH, "cpp");
|
||||||
|
|
||||||
|
m_script_entities.push(entity.index);
|
||||||
|
m_paths.push(string(path));
|
||||||
|
|
||||||
|
Component cmp = m_universe.addComponent(entity, SCRIPT_HASH, this, m_script_entities.size() - 1);
|
||||||
|
m_universe.componentCreated().invoke(cmp);
|
||||||
|
|
||||||
|
runScript(m_paths.size() - 1, entity);
|
||||||
|
|
||||||
|
return cmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void runAll()
|
||||||
|
{
|
||||||
|
char path[MAX_PATH];
|
||||||
|
char full_path[MAX_PATH];
|
||||||
|
for (int i = 0; i < m_script_entities.size(); ++i)
|
||||||
|
{
|
||||||
|
if(m_script_entities[i] != -1)
|
||||||
|
{
|
||||||
|
Entity e(&m_universe, m_script_entities[i]);
|
||||||
|
getDll(m_paths[i].c_str(), path, full_path, MAX_PATH);
|
||||||
|
HMODULE h = LoadLibrary(full_path);
|
||||||
|
if (h)
|
||||||
|
{
|
||||||
|
CreateScriptFunction f = (CreateScriptFunction)GetProcAddress(h, TEXT("createScript"));
|
||||||
|
BaseScript* script = f();
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
g_log_warning.log("script") << "failed to create script " << m_paths[i].c_str();
|
||||||
|
FreeLibrary(h);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RunningScript running_script;
|
||||||
|
running_script.m_entity_idx = e.index;
|
||||||
|
running_script.m_lib = h;
|
||||||
|
running_script.m_script_object = script;
|
||||||
|
m_running_scripts.push(running_script);
|
||||||
|
script->create(*this, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_log_warning.log("script") << "failed to load script " << m_paths[i].c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void stopAll()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < m_running_scripts.size(); ++i)
|
||||||
|
{
|
||||||
|
DestroyScriptFunction f = (DestroyScriptFunction)GetProcAddress(m_running_scripts[i].m_lib, "destroyScript");
|
||||||
|
f(m_running_scripts[i].m_script_object);
|
||||||
|
BOOL b = FreeLibrary(m_running_scripts[i].m_lib);
|
||||||
|
ASSERT(b == TRUE);
|
||||||
|
}
|
||||||
|
m_running_scripts.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void serialize(ISerializer& serializer) override
|
||||||
|
{
|
||||||
|
serializer.serialize("count", m_script_entities.size());
|
||||||
|
serializer.beginArray("scripts");
|
||||||
|
for (int i = 0; i < m_script_entities.size(); ++i)
|
||||||
|
{
|
||||||
|
serializer.serializeArrayItem(m_script_entities[i]);
|
||||||
|
serializer.serializeArrayItem(m_paths[i]);
|
||||||
|
}
|
||||||
|
serializer.endArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual Component createComponent(uint32_t type, const Entity& entity)
|
||||||
|
{
|
||||||
|
if (type == SCRIPT_HASH)
|
||||||
|
{
|
||||||
|
return createScript(entity);
|
||||||
|
}
|
||||||
|
return Component::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void destroyComponent(const Component& cmp)
|
||||||
|
{
|
||||||
|
m_script_entities[cmp.index] = -1;
|
||||||
|
m_universe.destroyComponent(cmp);
|
||||||
|
m_universe.componentDestroyed().invoke(cmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct RunningScript
|
||||||
|
{
|
||||||
|
BaseScript* m_script_object;
|
||||||
|
HMODULE m_lib;
|
||||||
|
int m_entity_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
Array<RunningScript> m_running_scripts;
|
||||||
|
Array<int> m_script_entities;
|
||||||
|
Array<string> m_paths;
|
||||||
|
Universe& m_universe;
|
||||||
|
Engine& m_engine;
|
||||||
|
ScriptSystem& m_system;
|
||||||
|
};
|
||||||
|
|
||||||
struct ScriptSystemImpl : public ScriptSystem
|
struct ScriptSystemImpl : public ScriptSystem
|
||||||
{
|
{
|
||||||
struct RunningScript
|
|
||||||
{
|
|
||||||
BaseScript* m_script_object;
|
|
||||||
HMODULE m_lib;
|
|
||||||
int m_entity_idx;
|
|
||||||
};
|
|
||||||
|
|
||||||
Array<RunningScript> m_running_scripts;
|
|
||||||
Array<int> m_script_entities;
|
|
||||||
Array<string> m_paths;
|
|
||||||
Universe* m_universe;
|
|
||||||
Engine* m_engine;
|
Engine* m_engine;
|
||||||
|
|
||||||
|
|
||||||
ScriptSystemImpl()
|
ScriptSystemImpl()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Universe* getUniverse() const override
|
|
||||||
{
|
|
||||||
return m_universe;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Engine* getEngine() const override
|
Engine* getEngine() const override
|
||||||
{
|
{
|
||||||
return m_engine;
|
return m_engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void runAll()
|
virtual IScene* createScene(Universe& universe)
|
||||||
{
|
{
|
||||||
char path[MAX_PATH];
|
return LUMIX_NEW(ScriptSceneImpl)(*this, *m_engine, universe);
|
||||||
char full_path[MAX_PATH];
|
|
||||||
for(int i = 0; i < m_script_entities.size(); ++i)
|
|
||||||
{
|
|
||||||
Entity e(m_universe, m_script_entities[i]);
|
|
||||||
getDll(m_paths[i].c_str(), path, full_path, MAX_PATH);
|
|
||||||
HMODULE h = LoadLibrary(full_path);
|
|
||||||
if(h)
|
|
||||||
{
|
|
||||||
CreateScriptFunction f = (CreateScriptFunction)GetProcAddress(h, TEXT("createScript"));
|
|
||||||
BaseScript* script = f();
|
|
||||||
if(!f)
|
|
||||||
{
|
|
||||||
g_log_warning.log("script") << "failed to create script " << m_paths[i].c_str();
|
|
||||||
FreeLibrary(h);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RunningScript running_script;
|
|
||||||
running_script.m_entity_idx = e.index;
|
|
||||||
running_script.m_lib = h;
|
|
||||||
running_script.m_script_object = script;
|
|
||||||
m_running_scripts.push(running_script);
|
|
||||||
script->create(*this, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_log_warning.log("script") << "failed to load script " << m_paths[i].c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void deserialize(ISerializer& serializer) override
|
|
||||||
{
|
|
||||||
stopAll();
|
|
||||||
int count;
|
|
||||||
serializer.deserialize("count", count);
|
|
||||||
serializer.deserializeArrayBegin("scripts");
|
|
||||||
m_script_entities.resize(count);
|
|
||||||
m_paths.resize(count);
|
|
||||||
for (int i = 0; i < m_script_entities.size(); ++i)
|
|
||||||
{
|
|
||||||
serializer.deserializeArrayItem(m_script_entities[i]);
|
|
||||||
serializer.deserializeArrayItem(m_paths[i]);
|
|
||||||
Entity entity(m_universe, m_script_entities[i]);
|
|
||||||
m_universe->addComponent(entity, SCRIPT_HASH, this, i);
|
|
||||||
}
|
|
||||||
serializer.deserializeArrayEnd();
|
|
||||||
runAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void serialize(ISerializer& serializer) override
|
|
||||||
{
|
|
||||||
serializer.serialize("count", m_script_entities.size());
|
|
||||||
serializer.beginArray("scripts");
|
|
||||||
for (int i = 0; i < m_script_entities.size(); ++i)
|
|
||||||
{
|
|
||||||
serializer.serializeArrayItem(m_script_entities[i]);
|
|
||||||
serializer.serializeArrayItem(m_paths[i]);
|
|
||||||
}
|
|
||||||
serializer.endArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void stopAll()
|
|
||||||
{
|
|
||||||
for(int i = 0; i < m_running_scripts.size(); ++i)
|
|
||||||
{
|
|
||||||
DestroyScriptFunction f = (DestroyScriptFunction)GetProcAddress(m_running_scripts[i].m_lib, "destroyScript");
|
|
||||||
f(m_running_scripts[i].m_script_object);
|
|
||||||
BOOL b = FreeLibrary(m_running_scripts[i].m_lib);
|
|
||||||
ASSERT(b == TRUE);
|
|
||||||
}
|
|
||||||
m_running_scripts.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void update(float dt) override
|
|
||||||
{
|
|
||||||
for(int i = 0; i < m_running_scripts.size(); ++i)
|
|
||||||
{
|
|
||||||
m_running_scripts[i].m_script_object->update(dt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void getScriptPath(Component cmp, string& str) override
|
|
||||||
{
|
|
||||||
str = m_paths[cmp.index];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void setScriptPath(Component cmp, const string& str) override
|
|
||||||
{
|
|
||||||
m_paths[cmp.index] = str;
|
|
||||||
stopScript(cmp.index);
|
|
||||||
if (!runScript(cmp.index, cmp.entity))
|
|
||||||
{
|
|
||||||
g_log_warning.log("script") << "Could not run script " << str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void getDll(const char* script_path, char* dll_path, char* full_path, int max_length)
|
|
||||||
{
|
|
||||||
copyString(dll_path, max_length, script_path);
|
|
||||||
int32_t len = (int32_t)strlen(script_path);
|
|
||||||
if(len > 4)
|
|
||||||
{
|
|
||||||
copyString(dll_path + len - 4, 5, ".dll");
|
|
||||||
}
|
|
||||||
copyString(full_path, max_length, m_engine->getBasePath());
|
|
||||||
catCString(full_path, max_length, "\\");
|
|
||||||
catCString(full_path, max_length, dll_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void getScriptDefaultPath(Entity e, char* path, char* full_path, int length, const char* ext)
|
|
||||||
{
|
|
||||||
char tmp[30];
|
|
||||||
toCString(e.index, tmp, 30);
|
|
||||||
|
|
||||||
copyString(full_path, length, m_engine->getBasePath());
|
|
||||||
catCString(full_path, length, "\\scripts\\e");
|
|
||||||
catCString(full_path, length, tmp);
|
|
||||||
catCString(full_path, length, ".");
|
|
||||||
catCString(full_path, length, ext);
|
|
||||||
|
|
||||||
copyString(path, length, "scripts\\e");
|
|
||||||
catCString(path, length, tmp);
|
|
||||||
catCString(path, length, ".");
|
|
||||||
catCString(path, length, ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void stopScript(int index)
|
|
||||||
{
|
|
||||||
int entity_idx = m_script_entities[index];
|
|
||||||
for (int i = 0; i < m_running_scripts.size(); ++i)
|
|
||||||
{
|
|
||||||
if (m_running_scripts[i].m_entity_idx == entity_idx)
|
|
||||||
{
|
|
||||||
DestroyScriptFunction f = (DestroyScriptFunction)GetProcAddress(m_running_scripts[i].m_lib, "destroyScript");
|
|
||||||
f(m_running_scripts[i].m_script_object);
|
|
||||||
BOOL b = FreeLibrary(m_running_scripts[i].m_lib);
|
|
||||||
ASSERT(b == TRUE);
|
|
||||||
m_running_scripts.eraseFast(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool runScript(int i, Entity entity)
|
|
||||||
{
|
|
||||||
char path[LUMIX_MAX_PATH];
|
|
||||||
char full_path[LUMIX_MAX_PATH];
|
|
||||||
getDll(m_paths[i].c_str(), path, full_path, LUMIX_MAX_PATH);
|
|
||||||
HMODULE h = LoadLibrary(full_path);
|
|
||||||
if (h)
|
|
||||||
{
|
|
||||||
CreateScriptFunction f = (CreateScriptFunction)GetProcAddress(h, TEXT("createScript"));
|
|
||||||
BaseScript* script = f();
|
|
||||||
if (!f)
|
|
||||||
{
|
|
||||||
g_log_warning.log("script") << "failed to create script " << m_paths[i].c_str();
|
|
||||||
FreeLibrary(h);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RunningScript running_script;
|
|
||||||
running_script.m_script_object = script;
|
|
||||||
running_script.m_entity_idx = entity.index;
|
|
||||||
running_script.m_lib = h;
|
|
||||||
m_running_scripts.push(running_script);
|
|
||||||
script->create(*this, entity);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Component createScript(Entity entity) override
|
|
||||||
{
|
|
||||||
char path[LUMIX_MAX_PATH];
|
|
||||||
char full_path[LUMIX_MAX_PATH];
|
|
||||||
getScriptDefaultPath(entity, path, full_path, LUMIX_MAX_PATH, "cpp");
|
|
||||||
|
|
||||||
m_script_entities.push(entity.index);
|
|
||||||
m_paths.push(string(path));
|
|
||||||
|
|
||||||
Component cmp = m_universe->addComponent(entity, SCRIPT_HASH, this, m_script_entities.size() - 1);
|
|
||||||
m_universe->componentCreated().invoke(cmp);
|
|
||||||
|
|
||||||
runScript(m_paths.size() - 1, entity);
|
|
||||||
|
|
||||||
return cmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual bool create(Engine& engine) override
|
virtual bool create(Engine& engine) override
|
||||||
{
|
{
|
||||||
m_engine = &engine;
|
m_engine = &engine;
|
||||||
engine.getWorldEditor()->registerProperty("script", LUMIX_NEW(PropertyDescriptor<ScriptSystem>)(crc32("source"), &ScriptSystem::getScriptPath, &ScriptSystem::setScriptPath, IPropertyDescriptor::FILE));
|
engine.getWorldEditor()->registerProperty("script", LUMIX_NEW(FilePropertyDescriptor<ScriptSceneImpl>)("source", &ScriptSceneImpl::getScriptPath, &ScriptSceneImpl::setScriptPath, "Script (*.cpp)"));
|
||||||
engine.getWorldEditor()->registerCreator(SCRIPT_HASH, *this);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void destroy() override
|
virtual void destroy() override
|
||||||
{
|
{
|
||||||
stopAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void destroyComponent(const Component&) override
|
|
||||||
{
|
|
||||||
ASSERT(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual Component createComponent(uint32_t type, const Entity& entity) override
|
|
||||||
{
|
|
||||||
if (type == SCRIPT_HASH)
|
|
||||||
{
|
|
||||||
return createScript(entity);
|
|
||||||
}
|
|
||||||
return Component::INVALID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -297,18 +329,6 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void onCreateUniverse(Universe& universe) override
|
|
||||||
{
|
|
||||||
m_universe = &universe;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
virtual void onDestroyUniverse(Universe& universe) override
|
|
||||||
{
|
|
||||||
m_universe = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}; // ScriptSystemImpl
|
}; // ScriptSystemImpl
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,23 +14,21 @@ namespace Lumix
|
||||||
class Engine;
|
class Engine;
|
||||||
class InputSystem;
|
class InputSystem;
|
||||||
class Navigation;
|
class Navigation;
|
||||||
class Renderer;
|
|
||||||
|
|
||||||
|
class LUMIX_SCRIPT_API ScriptScene : public IScene
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void getScriptPath(Component cmp, string& str) = 0;
|
||||||
|
virtual void setScriptPath(Component cmp, const string& str) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class LUMIX_SCRIPT_API ScriptSystem : public IPlugin
|
class LUMIX_SCRIPT_API ScriptSystem : public IPlugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void update(float time_delta) = 0;
|
|
||||||
virtual Universe* getUniverse() const = 0;
|
|
||||||
virtual Component createScript(Entity entity) = 0;
|
|
||||||
virtual Engine* getEngine() const = 0;
|
virtual Engine* getEngine() const = 0;
|
||||||
|
|
||||||
virtual void deserialize(ISerializer& serializer) = 0;
|
|
||||||
virtual void serialize(ISerializer& serializer) = 0;
|
|
||||||
|
|
||||||
virtual void getScriptPath(Component cmp, string& str) = 0;
|
|
||||||
virtual void setScriptPath(Component cmp, const string& str) = 0;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ScriptSystem() {}
|
ScriptSystem() {}
|
||||||
virtual ~ScriptSystem() {}
|
virtual ~ScriptSystem() {}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
struct Entity;
|
struct Entity;
|
||||||
|
class IScene;
|
||||||
|
|
||||||
|
|
||||||
struct LUMIX_ENGINE_API Component final
|
struct LUMIX_ENGINE_API Component final
|
||||||
|
@ -16,23 +17,23 @@ namespace Lumix
|
||||||
typedef uint32_t Type;
|
typedef uint32_t Type;
|
||||||
|
|
||||||
Component() { index = -1; }
|
Component() { index = -1; }
|
||||||
Component(const Entity& _entity, uint32_t _type, void* _system, int _index)
|
Component(const Entity& _entity, uint32_t _type, IScene* _scene, int _index)
|
||||||
: entity(_entity)
|
: entity(_entity)
|
||||||
, type(_type)
|
, type(_type)
|
||||||
, system(_system)
|
, scene(_scene)
|
||||||
, index(_index)
|
, index(_index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity entity;
|
Entity entity;
|
||||||
Type type;
|
Type type;
|
||||||
void* system;
|
IScene* scene;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
static const Component INVALID;
|
static const Component INVALID;
|
||||||
|
|
||||||
bool operator ==(const Component& rhs) const { return type == rhs.type && system == rhs.system && index == rhs.index; }
|
bool operator ==(const Component& rhs) const { return type == rhs.type && scene == rhs.scene && index == rhs.index; }
|
||||||
bool operator !=(const Component& rhs) const { return type != rhs.type || system != rhs.system || index != rhs.index; }
|
bool operator !=(const Component& rhs) const { return type != rhs.type || scene != rhs.scene || index != rhs.index; }
|
||||||
bool isValid() const { return index >= 0; }
|
bool isValid() const { return index >= 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "universe/entity.h"
|
#include "universe/entity.h"
|
||||||
|
#include "core/crc32.h"
|
||||||
#include "universe/universe.h"
|
#include "universe/universe.h"
|
||||||
|
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
|
@ -86,14 +87,14 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Entity::setPosition(float x, float y, float z)
|
void Entity::setPosition(float x, float y, float z) const
|
||||||
{
|
{
|
||||||
universe->m_positions[index].set(x, y, z);
|
universe->m_positions[index].set(x, y, z);
|
||||||
universe->entityMoved().invoke(*this);
|
universe->entityMoved().invoke(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Entity::setPosition(const Vec3& pos)
|
void Entity::setPosition(const Vec3& pos) const
|
||||||
{
|
{
|
||||||
universe->m_positions[index] = pos;
|
universe->m_positions[index] = pos;
|
||||||
universe->entityMoved().invoke(*this);
|
universe->entityMoved().invoke(*this);
|
||||||
|
@ -112,19 +113,42 @@ namespace Lumix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Entity::setRotation(float x, float y, float z, float w)
|
void Entity::setRotation(float x, float y, float z, float w) const
|
||||||
{
|
{
|
||||||
universe->m_rotations[index].set(x, y, z, w);
|
universe->m_rotations[index].set(x, y, z, w);
|
||||||
universe->entityMoved().invoke(*this);
|
universe->entityMoved().invoke(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Entity::setRotation(const Quat& rot)
|
void Entity::setRotation(const Quat& rot) const
|
||||||
{
|
{
|
||||||
universe->m_rotations[index] = rot;
|
universe->m_rotations[index] = rot;
|
||||||
universe->entityMoved().invoke(*this);
|
universe->entityMoved().invoke(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* Entity::getName() const
|
||||||
|
{
|
||||||
|
auto iter = universe->m_id_to_name_map.find(index);
|
||||||
|
return iter == universe->m_id_to_name_map.end() ? "" : iter.value().c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Entity::setName(const char* name)
|
||||||
|
{
|
||||||
|
auto iter = universe->m_id_to_name_map.find(index);
|
||||||
|
if (iter != universe->m_id_to_name_map.end())
|
||||||
|
{
|
||||||
|
universe->m_name_to_id_map.erase(crc32(iter.value().c_str()));
|
||||||
|
universe->m_id_to_name_map.erase(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name && name[0] != '\0')
|
||||||
|
{
|
||||||
|
universe->m_name_to_id_map.insert(crc32(name), index);
|
||||||
|
universe->m_id_to_name_map.insert(index, string(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // ~namespace Lumix
|
} // ~namespace Lumix
|
||||||
|
|
||||||
|
|
|
@ -22,17 +22,19 @@ namespace Lumix
|
||||||
void getMatrix(Matrix& mtx) const;
|
void getMatrix(Matrix& mtx) const;
|
||||||
void setMatrix(const Vec3& pos, const Quat& rot);
|
void setMatrix(const Vec3& pos, const Quat& rot);
|
||||||
void setMatrix(const Matrix& mtx);
|
void setMatrix(const Matrix& mtx);
|
||||||
void setPosition(float x, float y, float z);
|
void setPosition(float x, float y, float z) const;
|
||||||
void setPosition(const Vec3& v);
|
void setPosition(const Vec3& v) const;
|
||||||
const Vec3& getPosition() const;
|
const Vec3& getPosition() const;
|
||||||
const Quat& getRotation() const;
|
const Quat& getRotation() const;
|
||||||
void setRotation(float x, float y, float z, float w);
|
void setRotation(float x, float y, float z, float w) const;
|
||||||
void setRotation(const Quat& rot);
|
void setRotation(const Quat& rot) const;
|
||||||
void translate(const Vec3& t);
|
void translate(const Vec3& t);
|
||||||
bool isValid() const { return index >= 0; }
|
bool isValid() const { return index >= 0; }
|
||||||
const Component& getComponent(uint32_t type) const;
|
const Component& getComponent(uint32_t type) const;
|
||||||
const ComponentList& getComponents() const;
|
const ComponentList& getComponents() const;
|
||||||
bool existsInUniverse() const;
|
bool existsInUniverse() const;
|
||||||
|
const char* getName() const;
|
||||||
|
void setName(const char* name);
|
||||||
|
|
||||||
bool operator ==(const Entity& rhs) const;
|
bool operator ==(const Entity& rhs) const;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "universe.h"
|
#include "universe.h"
|
||||||
|
#include "core/crc32.h"
|
||||||
#include "core/matrix.h"
|
#include "core/matrix.h"
|
||||||
#include "core/json_serializer.h"
|
#include "core/json_serializer.h"
|
||||||
|
|
||||||
|
@ -6,31 +7,21 @@
|
||||||
namespace Lumix
|
namespace Lumix
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
static const int RESERVED_ENTITIES = 5000;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Universe::~Universe()
|
Universe::~Universe()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Universe::destroy()
|
|
||||||
{
|
|
||||||
m_free_slots.clear();
|
|
||||||
m_positions.clear();
|
|
||||||
m_rotations.clear();
|
|
||||||
m_component_list.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Universe::create()
|
|
||||||
{
|
|
||||||
m_positions.reserve(1000);
|
|
||||||
m_rotations.reserve(1000);
|
|
||||||
m_component_list.reserve(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Universe::Universe()
|
Universe::Universe()
|
||||||
{
|
{
|
||||||
|
m_positions.reserve(RESERVED_ENTITIES);
|
||||||
|
m_rotations.reserve(RESERVED_ENTITIES);
|
||||||
|
m_component_list.reserve(RESERVED_ENTITIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -69,6 +60,50 @@ void Universe::destroyEntity(Entity& entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Entity Universe::getFirstEntity()
|
||||||
|
{
|
||||||
|
for(int i = 0; i < m_positions.size(); ++i)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for(int j = 0, cj = m_free_slots.size(); j < cj; ++j)
|
||||||
|
{
|
||||||
|
if(m_free_slots[j] == i)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
return Entity(this, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Entity::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Entity Universe::getNextEntity(Entity entity)
|
||||||
|
{
|
||||||
|
for(int i = entity.index + 1; i < m_positions.size(); ++i)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for(int j = 0, cj = m_free_slots.size(); j < cj; ++j)
|
||||||
|
{
|
||||||
|
if(m_free_slots[j] == i)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
|
{
|
||||||
|
return Entity(this, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Entity::INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Universe::serialize(ISerializer& serializer)
|
void Universe::serialize(ISerializer& serializer)
|
||||||
{
|
{
|
||||||
serializer.serialize("count", m_positions.size());
|
serializer.serialize("count", m_positions.size());
|
||||||
|
@ -89,6 +124,16 @@ void Universe::serialize(ISerializer& serializer)
|
||||||
serializer.serializeArrayItem(m_rotations[i].w);
|
serializer.serializeArrayItem(m_rotations[i].w);
|
||||||
}
|
}
|
||||||
serializer.endArray();
|
serializer.endArray();
|
||||||
|
|
||||||
|
serializer.serialize("name_count", m_id_to_name_map.size());
|
||||||
|
serializer.beginArray("names");
|
||||||
|
for (auto iter = m_id_to_name_map.begin(), end = m_id_to_name_map.end(); iter != end; ++iter)
|
||||||
|
{
|
||||||
|
serializer.serializeArrayItem(iter.key());
|
||||||
|
serializer.serializeArrayItem(iter.value().c_str());
|
||||||
|
}
|
||||||
|
serializer.endArray();
|
||||||
|
|
||||||
serializer.serialize("free_slot_count", m_free_slots.size());
|
serializer.serialize("free_slot_count", m_free_slots.size());
|
||||||
serializer.beginArray("free_slots");
|
serializer.beginArray("free_slots");
|
||||||
for(int i = 0; i < m_free_slots.size(); ++i)
|
for(int i = 0; i < m_free_slots.size(); ++i)
|
||||||
|
@ -127,6 +172,22 @@ void Universe::deserialize(ISerializer& serializer)
|
||||||
}
|
}
|
||||||
serializer.deserializeArrayEnd();
|
serializer.deserializeArrayEnd();
|
||||||
|
|
||||||
|
serializer.deserialize("name_count", count);
|
||||||
|
serializer.deserializeArrayBegin("names");
|
||||||
|
m_id_to_name_map.clear();
|
||||||
|
m_name_to_id_map.clear();
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
uint32_t key;
|
||||||
|
static const int MAX_NAME_LENGTH = 50;
|
||||||
|
char name[MAX_NAME_LENGTH];
|
||||||
|
serializer.deserializeArrayItem(key);
|
||||||
|
serializer.deserializeArrayItem(name, MAX_NAME_LENGTH);
|
||||||
|
m_id_to_name_map.insert(key, string(name));
|
||||||
|
m_name_to_id_map.insert(crc32(name), key);
|
||||||
|
}
|
||||||
|
serializer.deserializeArrayEnd();
|
||||||
|
|
||||||
serializer.deserialize("free_slot_count", count);
|
serializer.deserialize("free_slot_count", count);
|
||||||
m_free_slots.resize(count);
|
m_free_slots.resize(count);
|
||||||
serializer.deserializeArrayBegin("free_slots");
|
serializer.deserializeArrayBegin("free_slots");
|
||||||
|
@ -138,7 +199,7 @@ void Universe::deserialize(ISerializer& serializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Universe::removeComponent(const Component& cmp)
|
void Universe::destroyComponent(const Component& cmp)
|
||||||
{
|
{
|
||||||
Entity::ComponentList& cmps = m_component_list[cmp.entity.index];
|
Entity::ComponentList& cmps = m_component_list[cmp.entity.index];
|
||||||
for (int i = 0, c = cmps.size(); i < c; ++i)
|
for (int i = 0, c = cmps.size(); i < c; ++i)
|
||||||
|
@ -152,12 +213,25 @@ void Universe::removeComponent(const Component& cmp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Component Universe::addComponent(const Entity& entity, uint32_t component_type, void* system, int index)
|
Component Universe::addComponent(const Entity& entity, uint32_t component_type, IScene* scene, int index)
|
||||||
{
|
{
|
||||||
Component cmp(entity, component_type, system, index);
|
Component cmp(entity, component_type, scene, index);
|
||||||
m_component_list[entity.index].push(cmp);
|
m_component_list[entity.index].push(cmp);
|
||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Universe::nameExists(const char* name) const
|
||||||
|
{
|
||||||
|
for (auto iter = m_id_to_name_map.begin(), end = m_id_to_name_map.end(); iter != end; ++iter)
|
||||||
|
{
|
||||||
|
if (iter.value() == name)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // !namespace Lumix
|
} // !namespace Lumix
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
#include "core/lumix.h"
|
#include "core/lumix.h"
|
||||||
#include "core/array.h"
|
#include "core/array.h"
|
||||||
#include "core/delegate_list.h"
|
#include "core/delegate_list.h"
|
||||||
|
#include "core/map.h"
|
||||||
#include "core/quat.h"
|
#include "core/quat.h"
|
||||||
|
#include "core/string.h"
|
||||||
#include "core/vec3.h"
|
#include "core/vec3.h"
|
||||||
#include "universe/component.h"
|
#include "universe/component.h"
|
||||||
#include "universe/entity.h"
|
#include "universe/entity.h"
|
||||||
|
@ -32,38 +34,37 @@ class LUMIX_ENGINE_API Universe final
|
||||||
Universe();
|
Universe();
|
||||||
~Universe();
|
~Universe();
|
||||||
|
|
||||||
void create();
|
|
||||||
void destroy();
|
|
||||||
|
|
||||||
Entity createEntity();
|
Entity createEntity();
|
||||||
void destroyEntity(Entity& entity);
|
void destroyEntity(Entity& entity);
|
||||||
Vec3 getPosition(int index) { return m_positions[index]; }
|
Vec3 getPosition(int index) { return m_positions[index]; }
|
||||||
Quat getRotation(int index) { return m_rotations[index]; }
|
Quat getRotation(int index) { return m_rotations[index]; }
|
||||||
Component addComponent(const Entity& entity, uint32_t component_type, void* system, int index);
|
Component addComponent(const Entity& entity, uint32_t component_type, IScene* scene, int index);
|
||||||
void removeComponent(const Component& cmp);
|
void destroyComponent(const Component& cmp);
|
||||||
int getEntityCount() const { return m_positions.size(); }
|
int getEntityCount() const { return m_positions.size() - m_free_slots.size(); }
|
||||||
|
Entity getFirstEntity();
|
||||||
|
Entity getNextEntity(Entity entity);
|
||||||
|
bool nameExists(const char* name) const;
|
||||||
|
|
||||||
DelegateList<void(Entity&)>& entityMoved() { return m_entity_moved; }
|
DelegateList<void(const Entity&)>& entityMoved() { return m_entity_moved; }
|
||||||
DelegateList<void(Entity&)>& entityCreated() { return m_entity_created; }
|
DelegateList<void(const Entity&)>& entityCreated() { return m_entity_created; }
|
||||||
DelegateList<void(Entity&)>& entityDestroyed() { return m_entity_destroyed; }
|
DelegateList<void(const Entity&)>& entityDestroyed() { return m_entity_destroyed; }
|
||||||
DelegateList<void(Component&)>& componentCreated() { return m_component_created; }
|
DelegateList<void(const Component&)>& componentCreated() { return m_component_created; }
|
||||||
DelegateList<void(const Component&)>& componentDestroyed() { return m_component_destroyed; }
|
DelegateList<void(const Component&)>& componentDestroyed() { return m_component_destroyed; }
|
||||||
|
|
||||||
void serialize(ISerializer& serializer);
|
void serialize(ISerializer& serializer);
|
||||||
void deserialize(ISerializer& serializer);
|
void deserialize(ISerializer& serializer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onEvent(Event& event);
|
Array<Vec3> m_positions;
|
||||||
|
Array<Quat> m_rotations;
|
||||||
private:
|
|
||||||
Array<Vec3> m_positions; //< entity positions
|
|
||||||
Array<Quat> m_rotations; //< entity rotations
|
|
||||||
Array<int> m_free_slots;
|
Array<int> m_free_slots;
|
||||||
|
Map<uint32_t, uint32_t> m_name_to_id_map;
|
||||||
|
Map<uint32_t, string> m_id_to_name_map;
|
||||||
ComponentList m_component_list;
|
ComponentList m_component_list;
|
||||||
DelegateList<void(Entity&)> m_entity_moved;
|
DelegateList<void(const Entity&)> m_entity_moved;
|
||||||
DelegateList<void(Entity&)> m_entity_created;
|
DelegateList<void(const Entity&)> m_entity_created;
|
||||||
DelegateList<void(Entity&)> m_entity_destroyed;
|
DelegateList<void(const Entity&)> m_entity_destroyed;
|
||||||
DelegateList<void(Component&)> m_component_created;
|
DelegateList<void(const Component&)> m_component_created;
|
||||||
DelegateList<void(const Component&)> m_component_destroyed;
|
DelegateList<void(const Component&)> m_component_destroyed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue