Merge remote-tracking branch 'remotes/origin/master' into clipper2
Conflicts: projects/vs2013/LumixEngine.sln projects/vs2013/engine/engine.vcxproj.filters src/engine/engine.h src/graphics/render_scene.cpp
This commit is contained in:
commit
56161eee27
99 changed files with 5505 additions and 3658 deletions
BIN
docs/editor.png
BIN
docs/editor.png
Binary file not shown.
Before Width: | Height: | Size: 604 KiB After Width: | Height: | Size: 1 MiB |
|
@ -29,8 +29,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "script", "script\script.vcx
|
|||
{A0A17BB4-760B-4E34-B1B0-3E43E5F2778A} = {A0A17BB4-760B-4E34-B1B0-3E43E5F2778A}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtEditor", "..\..\qteditor\QtEditor\QtEditor.vcxproj", "{9776D012-8010-39DD-9E1F-2C1A1DB433C3}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QtEditor", "..\..\qteditor\QtEditor\QtEditor.vcxproj", "{D04C721A-BACC-3CE7-B285-D5A7D567F8BA}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{E56A8C15-C73D-43E4-8D7C-04BBFC062ACC} = {E56A8C15-C73D-43E4-8D7C-04BBFC062ACC}
|
||||
{E1A0C677-DE71-4AD8-B802-AA7A3332D822} = {E1A0C677-DE71-4AD8-B802-AA7A3332D822}
|
||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33} = {4D15098E-177F-44EE-BF3C-FF0298E1BA33}
|
||||
{A0A17BB4-760B-4E34-B1B0-3E43E5F2778A} = {A0A17BB4-760B-4E34-B1B0-3E43E5F2778A}
|
||||
|
@ -64,6 +65,7 @@ Global
|
|||
{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}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|Win32.Build.0 = Release|Win32
|
||||
{4D15098E-177F-44EE-BF3C-FF0298E1BA33}.Release|x64.ActiveCfg = Release|x64
|
||||
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B9B67659-001C-4E9A-823D-49C7EF3F49C2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
|
@ -77,12 +79,12 @@ Global
|
|||
{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|x64.ActiveCfg = Release|x64
|
||||
{9776D012-8010-39DD-9E1F-2C1A1DB433C3}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{9776D012-8010-39DD-9E1F-2C1A1DB433C3}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{9776D012-8010-39DD-9E1F-2C1A1DB433C3}.Debug|x64.ActiveCfg = Debug|Win32
|
||||
{9776D012-8010-39DD-9E1F-2C1A1DB433C3}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{9776D012-8010-39DD-9E1F-2C1A1DB433C3}.Release|Win32.Build.0 = Release|Win32
|
||||
{9776D012-8010-39DD-9E1F-2C1A1DB433C3}.Release|x64.ActiveCfg = Release|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|x64.ActiveCfg = Debug|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|x64.ActiveCfg = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -66,20 +66,20 @@
|
|||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
|
@ -122,7 +122,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>
|
||||
</SDLCheck>
|
||||
<PreprocessorDefinitions>MEM_TRACK;BUILDING_CORE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;MEM_TRACK;BUILDING_CORE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>..\..\..\src;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
|
|
|
@ -66,23 +66,23 @@
|
|||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<TargetExt>.dll</TargetExt>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<TargetExt>.dll</TargetExt>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<TargetExt>.dll</TargetExt>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)\..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)\..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<OutDir>$(SolutionDir)..\..\bin\$(Platform)_$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\..\tmp\$(Platform)_$(Configuration)\$(ProjectName)\</IntDir>
|
||||
<TargetExt>.dll</TargetExt>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
|
@ -130,7 +130,7 @@
|
|||
</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\..\external\physx\include;..\..\..\src;..\..\..\external\glew\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<PreprocessorDefinitions>WIN32;BUILDING_ENGINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;WIN32;BUILDING_ENGINE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
@ -164,11 +164,10 @@
|
|||
<ClCompile Include="..\..\..\src\animation\animation.cpp" />
|
||||
<ClCompile Include="..\..\..\src\animation\animation_system.cpp" />
|
||||
<ClCompile Include="..\..\..\src\core\new.cpp" />
|
||||
<ClCompile Include="..\..\..\src\editor\editor_client.cpp" />
|
||||
<ClCompile Include="..\..\..\src\editor\editor_icon.cpp" />
|
||||
<ClCompile Include="..\..\..\src\editor\editor_server.cpp" />
|
||||
<ClCompile Include="..\..\..\src\editor\entity_template_system.cpp" />
|
||||
<ClCompile Include="..\..\..\src\editor\world_editor.cpp" />
|
||||
<ClCompile Include="..\..\..\src\editor\gizmo.cpp" />
|
||||
<ClCompile Include="..\..\..\src\editor\server_message_types.cpp" />
|
||||
<ClCompile Include="..\..\..\src\engine\engine.cpp" />
|
||||
<ClCompile Include="..\..\..\src\engine\iplugin.cpp" />
|
||||
<ClCompile Include="..\..\..\src\engine\plugin_manager.cpp" />
|
||||
|
@ -196,13 +195,12 @@
|
|||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\animation\animation.h" />
|
||||
<ClInclude Include="..\..\..\src\animation\animation_system.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\client_message_types.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\editor_client.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\ieditor_command.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\editor_icon.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\editor_server.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\entity_template_system.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\world_editor.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\gizmo.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\property_descriptor.h" />
|
||||
<ClInclude Include="..\..\..\src\editor\server_message_types.h" />
|
||||
<ClInclude Include="..\..\..\src\engine\engine.h" />
|
||||
<ClInclude Include="..\..\..\src\engine\iplugin.h" />
|
||||
<ClInclude Include="..\..\..\src\engine\plugin_manager.h" />
|
||||
|
|
|
@ -63,21 +63,12 @@
|
|||
<ClCompile Include="..\..\..\src\engine\plugin_manager.cpp">
|
||||
<Filter>engine</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\editor\editor_client.cpp">
|
||||
<Filter>editor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\editor\editor_icon.cpp">
|
||||
<Filter>editor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\editor\editor_server.cpp">
|
||||
<Filter>editor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\editor\gizmo.cpp">
|
||||
<Filter>editor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\editor\server_message_types.cpp">
|
||||
<Filter>editor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\universe\component.cpp">
|
||||
<Filter>universe</Filter>
|
||||
</ClCompile>
|
||||
|
@ -106,6 +97,12 @@
|
|||
<ClCompile Include="..\..\..\src\graphics\terrain.cpp">
|
||||
<Filter>graphics</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\editor\world_editor.cpp">
|
||||
<Filter>editor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\editor\entity_template_system.cpp">
|
||||
<Filter>editor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\graphics\culling_system.cpp">
|
||||
<Filter>graphics</Filter>
|
||||
</ClCompile>
|
||||
|
@ -165,27 +162,15 @@
|
|||
<ClInclude Include="..\..\..\src\engine\plugin_manager.h">
|
||||
<Filter>engine</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\client_message_types.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\editor_client.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\editor_icon.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\editor_server.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\gizmo.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\property_descriptor.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\server_message_types.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\universe\component.h">
|
||||
<Filter>universe</Filter>
|
||||
</ClInclude>
|
||||
|
@ -216,5 +201,14 @@
|
|||
<ClInclude Include="..\..\..\src\graphics\terrain.h">
|
||||
<Filter>graphics</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\world_editor.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\entity_template_system.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\editor\ieditor_command.h">
|
||||
<Filter>editor</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -117,7 +117,7 @@
|
|||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalIncludeDirectories>..\..\..\src</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>BUILDING_SCRIPT;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;BUILDING_SCRIPT;_WINDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
|
|
@ -27,7 +27,8 @@ SOURCES += main.cpp\
|
|||
materialmanager.cpp \
|
||||
profilerui.cpp \
|
||||
profilergraph.cpp \
|
||||
pc/file_system_watcher.cpp
|
||||
pc/file_system_watcher.cpp \
|
||||
entity_template_list.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
sceneview.h \
|
||||
|
@ -43,7 +44,8 @@ HEADERS += mainwindow.h \
|
|||
renderdevicewidget.h \
|
||||
profilerui.h \
|
||||
profilergraph.h \
|
||||
file_system_watcher.h
|
||||
file_system_watcher.h \
|
||||
entity_template_list.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
logwidget.ui \
|
||||
|
@ -54,7 +56,8 @@ FORMS += mainwindow.ui \
|
|||
fileserverwidget.ui \
|
||||
materialmanager.ui \
|
||||
profilerui.ui \
|
||||
profilergraph.ui
|
||||
profilergraph.ui \
|
||||
entity_template_list.ui
|
||||
|
||||
win32
|
||||
{
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
#include "core/crc32.h"
|
||||
#include "core/resource.h"
|
||||
#include "core/resource_manager.h"
|
||||
#include "editor/editor_client.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "engine/engine.h"
|
||||
#include <qfilesystemmodel.h>
|
||||
#include <qlistwidget.h>
|
||||
|
@ -33,7 +32,6 @@ AssetBrowser::AssetBrowser(QWidget* parent) :
|
|||
m_watcher = FileSystemWatcher::create(QDir::currentPath().toLatin1().data());
|
||||
m_watcher->getCallback().bind<AssetBrowser, &AssetBrowser::onFileSystemWatcherCallback>(this);
|
||||
m_base_path = QDir::currentPath();
|
||||
m_client = NULL;
|
||||
m_server = NULL;
|
||||
m_ui->setupUi(this);
|
||||
m_model = new QFileSystemModel;
|
||||
|
@ -73,35 +71,22 @@ void AssetBrowser::emitFileChanged(const char* path)
|
|||
|
||||
void AssetBrowser::handleDoubleClick(const QFileInfo& file_info)
|
||||
{
|
||||
ASSERT(m_client);
|
||||
const QString& suffix = file_info.suffix();
|
||||
QString file =file_info.filePath().toLower();
|
||||
if(suffix == "unv")
|
||||
{
|
||||
m_client->loadUniverse(file.toLatin1().data());
|
||||
m_server->loadUniverse(file.toLatin1().data());
|
||||
}
|
||||
else if(suffix == "msh")
|
||||
{
|
||||
m_client->addEntity();
|
||||
m_client->addComponent(crc32("renderable"));
|
||||
QString base_path = m_client->getBasePath();
|
||||
if(file.startsWith(base_path))
|
||||
{
|
||||
file.remove(0, base_path.length());
|
||||
}
|
||||
m_client->setComponentProperty("renderable", "source", file.toLatin1().data(), file.length());
|
||||
m_client->requestProperties(crc32("renderable"));
|
||||
m_server->addEntity();
|
||||
m_server->addComponent(crc32("renderable"));
|
||||
m_server->setProperty("renderable", "source", file.toLatin1().data(), file.length());
|
||||
}
|
||||
else if(suffix == "ani")
|
||||
{
|
||||
m_client->addComponent(crc32("animable"));
|
||||
QString base_path = m_client->getBasePath();
|
||||
if(file.startsWith(base_path))
|
||||
{
|
||||
file.remove(0, base_path.length());
|
||||
}
|
||||
m_client->setComponentProperty("animable", "preview", file.toLatin1().data(), file.length());
|
||||
m_client->requestProperties(crc32("animable"));
|
||||
m_server->addComponent(crc32("animable"));
|
||||
m_server->setProperty("animable", "preview", file.toLatin1().data(), file.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
namespace Lumix
|
||||
{
|
||||
class EditorClient;
|
||||
class EditorServer;
|
||||
class WorldEditor;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
|
@ -20,8 +19,7 @@ class AssetBrowser : public QDockWidget
|
|||
public:
|
||||
explicit AssetBrowser(QWidget* parent = NULL);
|
||||
~AssetBrowser();
|
||||
void setEditorClient(Lumix::EditorClient& client) { m_client = &client; }
|
||||
void setEditorServer(Lumix::EditorServer& server) { m_server = &server; }
|
||||
void setWorldEditor(Lumix::WorldEditor& server) { m_server = &server; }
|
||||
void emitFileChanged(const char* path);
|
||||
|
||||
private:
|
||||
|
@ -46,7 +44,6 @@ private slots:
|
|||
Ui::AssetBrowser* m_ui;
|
||||
class QFileSystemModel* m_model;
|
||||
class FileSystemWatcher* m_watcher;
|
||||
Lumix::EditorClient* m_client;
|
||||
Lumix::EditorServer* m_server;
|
||||
Lumix::WorldEditor* m_server;
|
||||
QString m_base_path;
|
||||
};
|
||||
|
|
56
qteditor/QtEditor/entity_template_list.cpp
Normal file
56
qteditor/QtEditor/entity_template_list.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include "entity_template_list.h"
|
||||
#include "ui_entity_template_list.h"
|
||||
#include "editor/entity_template_system.h"
|
||||
#include "editor/world_editor.h"
|
||||
|
||||
|
||||
EntityTemplateList::EntityTemplateList()
|
||||
: QDockWidget(NULL)
|
||||
, m_ui(new Ui::EntityTemplateList)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_editor = NULL;
|
||||
}
|
||||
|
||||
EntityTemplateList::~EntityTemplateList()
|
||||
{
|
||||
if (m_editor)
|
||||
{
|
||||
m_editor->getEntityTemplateSystem().updated().unbind<EntityTemplateList, &EntityTemplateList::onSystemUpdated>(this);
|
||||
}
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void EntityTemplateList::setWorldEditor(Lumix::WorldEditor& editor)
|
||||
{
|
||||
m_editor = &editor;
|
||||
m_editor->getEntityTemplateSystem().updated().bind<EntityTemplateList, &EntityTemplateList::onSystemUpdated>(this);
|
||||
onSystemUpdated();
|
||||
}
|
||||
|
||||
|
||||
void EntityTemplateList::onSystemUpdated()
|
||||
{
|
||||
Lumix::Array<Lumix::string>& template_names = m_editor->getEntityTemplateSystem().getTemplateNames();
|
||||
m_ui->templateList->clear();
|
||||
for (int i = 0, c = template_names.size(); i < c; ++i)
|
||||
{
|
||||
m_ui->templateList->insertItem(i, template_names[i].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EntityTemplateList::on_templateList_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
m_editor->getEntityTemplateSystem().createInstance(m_ui->templateList->item(index.row())->text().toLatin1().data());
|
||||
}
|
||||
|
||||
|
||||
void EntityTemplateList::instantiateTemplate()
|
||||
{
|
||||
if (m_ui->templateList->currentIndex().row() >= 0)
|
||||
{
|
||||
m_editor->getEntityTemplateSystem().createInstance(m_ui->templateList->item(m_ui->templateList->currentIndex().row())->text().toLatin1().data());
|
||||
}
|
||||
}
|
36
qteditor/QtEditor/entity_template_list.h
Normal file
36
qteditor/QtEditor/entity_template_list.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class EntityTemplateList;
|
||||
}
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
class WorldEditor;
|
||||
}
|
||||
|
||||
class EntityTemplateList : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EntityTemplateList();
|
||||
~EntityTemplateList();
|
||||
|
||||
void setWorldEditor(Lumix::WorldEditor& editor);
|
||||
void instantiateTemplate();
|
||||
|
||||
private:
|
||||
void onSystemUpdated();
|
||||
|
||||
private slots:
|
||||
void on_templateList_doubleClicked(const QModelIndex& index);
|
||||
|
||||
private:
|
||||
Ui::EntityTemplateList* m_ui;
|
||||
Lumix::WorldEditor* m_editor;
|
||||
};
|
||||
|
38
qteditor/QtEditor/entity_template_list.ui
Normal file
38
qteditor/QtEditor/entity_template_list.ui
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EntityTemplateList</class>
|
||||
<widget class="QDockWidget" name="EntityTemplateList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Entity templates</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="QListWidget" name="templateList"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -5,7 +5,7 @@
|
|||
#include "core/fs/file_system.h"
|
||||
#include "core/fs/tcp_file_server.h"
|
||||
#include "core/fs/file_events_device.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/world_editor.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -120,14 +120,14 @@ void FileServerWidget::emitFileEvent(const Lumix::FS::Event& event, qint64 time)
|
|||
}
|
||||
|
||||
|
||||
void FileServerWidget::setEditorServer(Lumix::EditorServer& server)
|
||||
void FileServerWidget::setWorldEditor(Lumix::WorldEditor& server)
|
||||
{
|
||||
m_server = &server;
|
||||
|
||||
Lumix::FS::FileEventsDevice& dev = m_watcher->getFileEventDevice();
|
||||
Lumix::FS::FileSystem& fs = m_server->getEngine().getFileSystem();
|
||||
fs.mount(&dev);
|
||||
fs.setDefaultDevice("memory:events:tcp");
|
||||
fs.setDefaultDevice("memory:events:disk");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace Lumix
|
||||
{
|
||||
class EditorServer;
|
||||
class WorldEditor;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
|
@ -22,7 +22,7 @@ public:
|
|||
explicit FileServerWidget(QWidget* parent = NULL);
|
||||
~FileServerWidget();
|
||||
|
||||
void setEditorServer(Lumix::EditorServer& server);
|
||||
void setWorldEditor(Lumix::WorldEditor& server);
|
||||
void fsEventCb(const Lumix::FS::Event& event, int32_t param);
|
||||
void emitFileEvent(const Lumix::FS::Event& event, qint64 time);
|
||||
|
||||
|
@ -44,7 +44,7 @@ private:
|
|||
void filterTable();
|
||||
|
||||
Ui::FileServerWidget* m_ui;
|
||||
Lumix::EditorServer* m_server;
|
||||
Lumix::WorldEditor* m_server;
|
||||
class FileServerWatcher* m_watcher;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "gameview.h"
|
||||
#include "ui_gameview.h"
|
||||
#include <QMouseEvent>
|
||||
#include "editor/editor_client.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "graphics/pipeline.h"
|
||||
|
||||
GameView::GameView(QWidget* parent) :
|
||||
|
@ -10,7 +10,6 @@ GameView::GameView(QWidget* parent) :
|
|||
{
|
||||
m_ui->setupUi(this);
|
||||
m_pipeline = NULL;
|
||||
m_client = NULL;
|
||||
}
|
||||
|
||||
GameView::~GameView()
|
||||
|
@ -38,6 +37,6 @@ void GameView::resizeEvent(QResizeEvent* event)
|
|||
|
||||
void GameView::on_playButton_clicked()
|
||||
{
|
||||
m_client->toggleGameMode();
|
||||
m_server->toggleGameMode();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace Lumix
|
||||
{
|
||||
class EditorClient;
|
||||
class WorldEditor;
|
||||
class PipelineInstance;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@ public:
|
|||
|
||||
QWidget* getContentWidget() const;
|
||||
void setPipeline(Lumix::PipelineInstance& pipeline) { m_pipeline = &pipeline; }
|
||||
void setEditorClient(Lumix::EditorClient& client) { m_client = &client; }
|
||||
|
||||
private slots:
|
||||
void on_playButton_clicked();
|
||||
|
@ -36,6 +35,6 @@ private:
|
|||
private:
|
||||
Ui::GameView* m_ui;
|
||||
Lumix::PipelineInstance* m_pipeline;
|
||||
Lumix::EditorClient* m_client;
|
||||
Lumix::WorldEditor* m_server;
|
||||
};
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
#include "core/profiler.h"
|
||||
#include "core/resource_manager.h"
|
||||
#include "core/resource_manager_base.h"
|
||||
#include "editor/editor_client.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "editor/gizmo.h"
|
||||
#include "engine/engine.h"
|
||||
#include "engine/plugin_manager.h"
|
||||
#include <graphics/gl_ext.h>
|
||||
#include "graphics/irender_device.h"
|
||||
#include "graphics/pipeline.h"
|
||||
#include "graphics/renderer.h"
|
||||
|
@ -20,6 +20,7 @@
|
|||
#include "wgl_render_device.h"
|
||||
#include "materialmanager.h"
|
||||
|
||||
|
||||
class App
|
||||
{
|
||||
public:
|
||||
|
@ -29,20 +30,20 @@ class App
|
|||
m_edit_render_device = NULL;
|
||||
m_qt_app = NULL;
|
||||
m_main_window = NULL;
|
||||
m_world_editor = NULL;
|
||||
}
|
||||
|
||||
~App()
|
||||
{
|
||||
delete m_main_window;
|
||||
delete m_qt_app;
|
||||
m_client.destroy();
|
||||
m_server.destroy();
|
||||
Lumix::WorldEditor::destroy(m_world_editor);
|
||||
}
|
||||
|
||||
void onUniverseCreated()
|
||||
{
|
||||
m_edit_render_device->getPipeline().setScene(m_server.getEngine().getRenderScene());
|
||||
m_game_render_device->getPipeline().setScene(m_server.getEngine().getRenderScene());
|
||||
m_edit_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene());
|
||||
m_game_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene());
|
||||
}
|
||||
|
||||
void onUniverseDestroyed()
|
||||
|
@ -60,18 +61,20 @@ class App
|
|||
|
||||
HGLRC createGLContext(HWND hwnd[], int count)
|
||||
{
|
||||
|
||||
ASSERT(count > 0);
|
||||
QWidget* widget = new QWidget();
|
||||
HWND gl_hwnd = (HWND)widget->winId();
|
||||
HDC hdc;
|
||||
hdc = GetDC(hwnd[0]);
|
||||
hdc = GetDC(gl_hwnd);
|
||||
ASSERT(hdc != NULL);
|
||||
if (hdc == NULL)
|
||||
{
|
||||
Lumix::g_log_error.log("renderer") << "Could not get the device context";
|
||||
return NULL;
|
||||
}
|
||||
PIXELFORMATDESCRIPTOR pfd =
|
||||
{
|
||||
BOOL success;
|
||||
PIXELFORMATDESCRIPTOR pfd =
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
|
||||
1, // version number
|
||||
PFD_DRAW_TO_WINDOW | // support window
|
||||
|
@ -90,44 +93,27 @@ class App
|
|||
PFD_MAIN_PLANE, // main layer
|
||||
0, // reserved
|
||||
0, 0, 0 // layer masks ignored
|
||||
};
|
||||
};
|
||||
int pixelformat = ChoosePixelFormat(hdc, &pfd);
|
||||
if (pixelformat == 0)
|
||||
{
|
||||
delete widget;
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not choose a pixel format";
|
||||
return NULL;
|
||||
}
|
||||
BOOL success = SetPixelFormat(hdc, pixelformat, &pfd);
|
||||
success = SetPixelFormat(hdc, pixelformat, &pfd);
|
||||
if (success == FALSE)
|
||||
{
|
||||
delete widget;
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not set a pixel format";
|
||||
return NULL;
|
||||
}
|
||||
for (int i = 1; i < count; ++i)
|
||||
{
|
||||
if (hwnd[i])
|
||||
{
|
||||
HDC hdc2 = GetDC(hwnd[i]);
|
||||
if (hdc2 == NULL)
|
||||
{
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not get the device context";
|
||||
return NULL;
|
||||
}
|
||||
BOOL success = SetPixelFormat(hdc2, pixelformat, &pfd);
|
||||
if (success == FALSE)
|
||||
{
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not set a pixel format";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
HGLRC hglrc = wglCreateContext(hdc);
|
||||
if (hglrc == NULL)
|
||||
{
|
||||
delete widget;
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
|
||||
return NULL;
|
||||
|
@ -135,22 +121,91 @@ class App
|
|||
success = wglMakeCurrent(hdc, hglrc);
|
||||
if (success == FALSE)
|
||||
{
|
||||
delete widget;
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{
|
||||
UINT numFormats;
|
||||
int atrribs[] =
|
||||
{
|
||||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||
WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
|
||||
WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
|
||||
WGL_COLOR_BITS_ARB, 32,
|
||||
WGL_DEPTH_BITS_ARB, 24,
|
||||
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
||||
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
|
||||
WGL_SAMPLES_ARB, 4,
|
||||
0
|
||||
};
|
||||
PFNWGLCHOOSEPIXELFORMATARBPROC foo;
|
||||
foo = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||
if (!foo)
|
||||
{
|
||||
delete widget;
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not get function wglChoosePixelFormatARB";
|
||||
return NULL;
|
||||
}
|
||||
success = foo(hdc, atrribs, NULL, 1, &pixelformat, &numFormats);
|
||||
}
|
||||
wglDeleteContext(hglrc);
|
||||
hglrc = NULL;
|
||||
delete widget;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
if (hwnd[i])
|
||||
{
|
||||
hdc = GetDC(hwnd[i]);
|
||||
ChoosePixelFormat(hdc, &pfd);
|
||||
if (hdc == NULL)
|
||||
{
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not get the device context";
|
||||
return NULL;
|
||||
}
|
||||
SetPixelFormat(hdc, pixelformat, &pfd);
|
||||
|
||||
if (!hglrc)
|
||||
{
|
||||
hglrc = wglCreateContext(hdc);
|
||||
if (hglrc == NULL)
|
||||
{
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not create an opengl context";
|
||||
return NULL;
|
||||
}
|
||||
success = wglMakeCurrent(hdc, hglrc);
|
||||
if (success == FALSE)
|
||||
{
|
||||
ASSERT(false);
|
||||
Lumix::g_log_error.log("renderer") << "Could not make the opengl context current rendering context";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return hglrc;
|
||||
}
|
||||
|
||||
|
||||
void renderPhysics()
|
||||
{
|
||||
Lumix::PhysicsSystem* system = static_cast<Lumix::PhysicsSystem*>(m_server.getEngine().getPluginManager().getPlugin("physics"));
|
||||
Lumix::PhysicsSystem* system = static_cast<Lumix::PhysicsSystem*>(m_world_editor->getEngine().getPluginManager().getPlugin("physics"));
|
||||
if(system && system->getScene())
|
||||
{
|
||||
system->getScene()->render();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void init(int argc, char* argv[])
|
||||
{
|
||||
m_qt_app = new QApplication(argc, argv);
|
||||
|
@ -163,34 +218,31 @@ class App
|
|||
|
||||
HWND hwnd = (HWND)m_main_window->getSceneView()->getViewWidget()->winId();
|
||||
HWND game_hwnd = (HWND)m_main_window->getGameView()->getContentWidget()->winId();
|
||||
HWND hwnds[] = {hwnd, game_hwnd};
|
||||
HGLRC hglrc = createGLContext(hwnds, 2);
|
||||
HWND hwnds[] = { hwnd, game_hwnd, (HWND)m_main_window->getMaterialManager()->getPreview()->winId() };
|
||||
HGLRC hglrc = createGLContext(hwnds, 3);
|
||||
|
||||
bool server_created = m_server.create(QDir::currentPath().toLocal8Bit().data(), m_client);
|
||||
ASSERT(server_created);
|
||||
m_server.tick();
|
||||
bool client_created = m_client.create(m_server.getEngine().getBasePath(), m_server);
|
||||
ASSERT(client_created);
|
||||
m_world_editor = Lumix::WorldEditor::create(QDir::currentPath().toLocal8Bit().data());
|
||||
ASSERT(m_world_editor);
|
||||
m_world_editor->tick();
|
||||
|
||||
m_main_window->setEditorClient(m_client);
|
||||
m_main_window->setEditorServer(m_server);
|
||||
m_main_window->getSceneView()->setServer(&m_server);
|
||||
m_main_window->setWorldEditor(*m_world_editor);
|
||||
m_main_window->getSceneView()->setWorldEditor(m_world_editor);
|
||||
|
||||
m_edit_render_device = new WGLRenderDevice(m_server.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_opengl_context = hglrc;
|
||||
m_edit_render_device->getPipeline().setScene(m_server.getEngine().getRenderScene()); /// TODO manage scene properly
|
||||
m_server.setEditViewRenderDevice(*m_edit_render_device);
|
||||
m_edit_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene()); /// TODO manage scene properly
|
||||
m_world_editor->setEditViewRenderDevice(*m_edit_render_device);
|
||||
m_edit_render_device->getPipeline().addCustomCommandHandler("render_physics").bind<App, &App::renderPhysics>(this);
|
||||
|
||||
m_game_render_device = new WGLRenderDevice(m_server.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_opengl_context = hglrc;
|
||||
m_game_render_device->getPipeline().setScene(m_server.getEngine().getRenderScene()); /// TODO manage scene properly
|
||||
m_server.getEngine().getRenderer().setRenderDevice(*m_game_render_device);
|
||||
m_game_render_device->getPipeline().setScene(m_world_editor->getEngine().getRenderScene()); /// TODO manage scene properly
|
||||
m_world_editor->getEngine().getRenderer().setRenderDevice(*m_game_render_device);
|
||||
|
||||
m_server.universeCreated().bind<App, &App::onUniverseCreated>(this);
|
||||
m_server.universeDestroyed().bind<App, &App::onUniverseDestroyed>(this);
|
||||
m_world_editor->universeCreated().bind<App, &App::onUniverseCreated>(this);
|
||||
m_world_editor->universeDestroyed().bind<App, &App::onUniverseDestroyed>(this);
|
||||
|
||||
m_main_window->getSceneView()->setPipeline(m_edit_render_device->getPipeline());
|
||||
m_main_window->getGameView()->setPipeline(m_game_render_device->getPipeline());
|
||||
|
@ -208,10 +260,10 @@ class App
|
|||
{
|
||||
PROFILE_FUNCTION();
|
||||
m_edit_render_device->beginFrame();
|
||||
m_server.render(*m_edit_render_device);
|
||||
m_server.renderIcons(*m_edit_render_device);
|
||||
m_server.getGizmo().updateScale(m_server.getEditCamera());
|
||||
m_server.getGizmo().render(m_server.getEngine().getRenderer(), *m_edit_render_device);
|
||||
m_world_editor->render(*m_edit_render_device);
|
||||
m_world_editor->renderIcons(*m_edit_render_device);
|
||||
m_world_editor->getGizmo().updateScale(m_world_editor->getEditCamera());
|
||||
m_world_editor->getGizmo().render(m_world_editor->getEngine().getRenderer(), *m_edit_render_device);
|
||||
m_edit_render_device->endFrame();
|
||||
|
||||
m_main_window->getMaterialManager()->updatePreview();
|
||||
|
@ -238,19 +290,19 @@ class App
|
|||
}
|
||||
if (keys['W'] >> 7)
|
||||
{
|
||||
m_client.navigate(1, 0, speed);
|
||||
m_world_editor->navigate(1, 0, speed);
|
||||
}
|
||||
else if (keys['S'] >> 7)
|
||||
{
|
||||
m_client.navigate(-1, 0, speed);
|
||||
m_world_editor->navigate(-1, 0, speed);
|
||||
}
|
||||
if (keys['A'] >> 7)
|
||||
{
|
||||
m_client.navigate(0, -1, speed);
|
||||
m_world_editor->navigate(0, -1, speed);
|
||||
}
|
||||
else if (keys['D'] >> 7)
|
||||
{
|
||||
m_client.navigate(0, 1, speed);
|
||||
m_world_editor->navigate(0, 1, speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,8 +315,8 @@ class App
|
|||
{
|
||||
PROFILE_BLOCK("tick");
|
||||
renderEditView();
|
||||
m_server.getEngine().getRenderer().renderGame();
|
||||
m_server.tick();
|
||||
m_world_editor->getEngine().getRenderer().renderGame();
|
||||
m_world_editor->tick();
|
||||
handleEvents();
|
||||
}
|
||||
Lumix::g_profiler.frame();
|
||||
|
@ -275,8 +327,7 @@ class App
|
|||
WGLRenderDevice* m_edit_render_device;
|
||||
WGLRenderDevice* m_game_render_device;
|
||||
MainWindow* m_main_window;
|
||||
Lumix::EditorServer m_server;
|
||||
Lumix::EditorClient m_client;
|
||||
Lumix::WorldEditor* m_world_editor;
|
||||
QApplication* m_qt_app;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include <qfiledialog.h>
|
||||
#include <qsettings.h>
|
||||
#include "assetbrowser.h"
|
||||
#include "editor/editor_client.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/entity_template_system.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "entity_template_list.h"
|
||||
#include "fileserverwidget.h"
|
||||
#include "gameview.h"
|
||||
#include "log_widget.h"
|
||||
|
@ -13,13 +12,15 @@
|
|||
#include "scripts/scriptcompilerwidget.h"
|
||||
#include "materialmanager.h"
|
||||
#include "profilerui.h"
|
||||
#include <qfiledialog.h>
|
||||
#include <qinputdialog.h>
|
||||
#include <qsettings.h>
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
m_ui(new Ui::MainWindow)
|
||||
{
|
||||
m_client = NULL;
|
||||
m_ui->setupUi(this);
|
||||
m_ui->centralWidget->hide();
|
||||
setDockOptions(AllowNestedDocks | AnimatedDocks | AllowTabbedDocks);
|
||||
|
@ -33,6 +34,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
m_file_server_ui = new FileServerWidget;
|
||||
m_material_manager_ui = new MaterialManager;
|
||||
m_profiler_ui = new ProfilerUI;
|
||||
m_entity_template_list_ui = new EntityTemplateList;
|
||||
|
||||
QSettings settings("Lumix", "QtEditor");
|
||||
restoreGeometry(settings.value("mainWindowGeometry").toByteArray());
|
||||
|
@ -46,6 +48,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
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>(2), m_entity_template_list_ui);
|
||||
|
||||
m_property_view->setScriptCompiler(m_script_compiler_ui->getCompiler());
|
||||
|
||||
|
@ -73,27 +76,20 @@ MainWindow::~MainWindow()
|
|||
delete m_file_server_ui;
|
||||
delete m_material_manager_ui;
|
||||
delete m_profiler_ui;
|
||||
delete m_entity_template_list_ui;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::setEditorServer(Lumix::EditorServer& server)
|
||||
void MainWindow::setWorldEditor(Lumix::WorldEditor& editor)
|
||||
{
|
||||
m_file_server_ui->setEditorServer(server);
|
||||
m_asset_browser->setEditorServer(server);
|
||||
m_material_manager_ui->setEditorServer(server);
|
||||
m_world_editor = &editor;
|
||||
m_file_server_ui->setWorldEditor(editor);
|
||||
m_asset_browser->setWorldEditor(editor);
|
||||
m_material_manager_ui->setWorldEditor(editor);
|
||||
m_property_view->setWorldEditor(editor);
|
||||
m_entity_template_list_ui->setWorldEditor(editor);
|
||||
}
|
||||
|
||||
void MainWindow::setEditorClient(Lumix::EditorClient& client)
|
||||
{
|
||||
m_client = &client;
|
||||
m_property_view->setEditorClient(client);
|
||||
m_scene_view->setEditorClient(client);
|
||||
m_asset_browser->setEditorClient(client);
|
||||
m_game_view->setEditorClient(client);
|
||||
m_material_manager_ui->setEditorClient(client);
|
||||
}
|
||||
|
||||
|
||||
GameView* MainWindow::getGameView() const
|
||||
{
|
||||
return m_game_view;
|
||||
|
@ -111,43 +107,28 @@ void MainWindow::on_actionLog_triggered()
|
|||
m_log->show();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionOpen_triggered()
|
||||
{
|
||||
QByteArray path = QFileDialog::getOpenFileName(NULL, QString(), QString(), "universe (*.unv)").toLocal8Bit();
|
||||
int len = (int)strlen(m_client->getBasePath());
|
||||
if (!path.isEmpty())
|
||||
{
|
||||
if (strncmp(path.data(), m_client->getBasePath(), len) == 0)
|
||||
{
|
||||
m_client->loadUniverse(path.data() + len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->loadUniverse(path.data());
|
||||
}
|
||||
m_world_editor->loadUniverse(path.data());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSave_As_triggered()
|
||||
{
|
||||
QByteArray path = QFileDialog::getSaveFileName().toLocal8Bit();
|
||||
int len = (int)strlen(m_client->getBasePath());
|
||||
if (!path.isEmpty())
|
||||
{
|
||||
if (strncmp(path.data(), m_client->getBasePath(), len) == 0)
|
||||
{
|
||||
m_client->saveUniverse(path.data() + len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client->saveUniverse(path.data());
|
||||
}
|
||||
m_world_editor->saveUniverse(path.data());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCreate_triggered()
|
||||
{
|
||||
m_client->addEntity();
|
||||
m_world_editor->addEntity();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionProperties_triggered()
|
||||
|
@ -192,20 +173,75 @@ void MainWindow::on_actionProfiler_triggered()
|
|||
|
||||
void MainWindow::on_actionMaterial_manager_triggered()
|
||||
{
|
||||
m_material_manager_ui->show();
|
||||
m_material_manager_ui->show();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPolygon_Mode_changed()
|
||||
{
|
||||
m_client->setWireframe(m_ui->actionPolygon_Mode->isChecked());
|
||||
m_world_editor->setWireframe(m_ui->actionPolygon_Mode->isChecked());
|
||||
}
|
||||
|
||||
void MainWindow::on_actionGame_mode_triggered()
|
||||
{
|
||||
m_client->toggleGameMode();
|
||||
m_world_editor->toggleGameMode();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionLook_at_selected_entity_triggered()
|
||||
{
|
||||
m_client->lookAtSelected();
|
||||
m_world_editor->lookAtSelected();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionNew_triggered()
|
||||
{
|
||||
m_world_editor->newUniverse();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSave_triggered()
|
||||
{
|
||||
if (m_world_editor->getUniversePath()[0] == '\0')
|
||||
{
|
||||
on_actionSave_As_triggered();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_world_editor->saveUniverse(m_world_editor->getUniversePath());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSnap_to_terrain_triggered()
|
||||
{
|
||||
m_world_editor->snapToTerrain();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSave_as_template_triggered()
|
||||
{
|
||||
if (m_world_editor->getSelectedEntity().isValid())
|
||||
{
|
||||
bool ok = false;
|
||||
QString text = QInputDialog::getText(this, tr("Entity template"), tr("Template name:"), QLineEdit::Normal, tr(""), &ok);
|
||||
if (ok)
|
||||
{
|
||||
m_world_editor->getEntityTemplateSystem().createTemplateFromEntity(text.toLatin1().data(), m_world_editor->getSelectedEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionEntity_templates_triggered()
|
||||
{
|
||||
m_entity_template_list_ui->show();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionInstantiate_template_triggered()
|
||||
{
|
||||
m_entity_template_list_ui->instantiateTemplate();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionUndo_triggered()
|
||||
{
|
||||
m_world_editor->undo();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRedo_triggered()
|
||||
{
|
||||
m_world_editor->redo();
|
||||
}
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
|
||||
namespace Lumix
|
||||
{
|
||||
class EditorClient;
|
||||
class EditorServer;
|
||||
class WorldEditor;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
|
@ -21,8 +20,7 @@ public:
|
|||
explicit MainWindow(QWidget* parent = NULL);
|
||||
~MainWindow();
|
||||
|
||||
void setEditorClient(Lumix::EditorClient& client);
|
||||
void setEditorServer(Lumix::EditorServer& server);
|
||||
void setWorldEditor(Lumix::WorldEditor& world_editor);
|
||||
class SceneView* getSceneView() const;
|
||||
class GameView* getGameView() const;
|
||||
class MaterialManager* getMaterialManager() const { return m_material_manager_ui; }
|
||||
|
@ -40,20 +38,26 @@ private slots:
|
|||
void on_actionAsset_Browser_triggered();
|
||||
void on_actionScene_View_triggered();
|
||||
virtual void closeEvent(QCloseEvent* event) override;
|
||||
void on_actionProfiler_triggered();
|
||||
void on_actionMaterial_manager_triggered();
|
||||
void on_actionPolygon_Mode_changed();
|
||||
void on_actionGame_mode_triggered();
|
||||
void on_actionLook_at_selected_entity_triggered();
|
||||
void on_actionNew_triggered();
|
||||
void on_actionSave_triggered();
|
||||
void on_actionSnap_to_terrain_triggered();
|
||||
void on_actionSave_as_template_triggered();
|
||||
void on_actionEntity_templates_triggered();
|
||||
|
||||
void on_actionProfiler_triggered();
|
||||
void on_actionInstantiate_template_triggered();
|
||||
|
||||
void on_actionMaterial_manager_triggered();
|
||||
void on_actionUndo_triggered();
|
||||
|
||||
void on_actionPolygon_Mode_changed();
|
||||
|
||||
void on_actionGame_mode_triggered();
|
||||
|
||||
void on_actionLook_at_selected_entity_triggered();
|
||||
void on_actionRedo_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow* m_ui;
|
||||
Lumix::EditorClient* m_client;
|
||||
Lumix::WorldEditor* m_world_editor;
|
||||
class LogWidget* m_log;
|
||||
class PropertyView* m_property_view;
|
||||
class SceneView* m_scene_view;
|
||||
|
@ -63,5 +67,6 @@ private:
|
|||
class FileServerWidget* m_file_server_ui;
|
||||
class MaterialManager* m_material_manager_ui;
|
||||
class ProfilerUI* m_profiler_ui;
|
||||
class EntityTemplateList* m_entity_template_list_ui;
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
<string>Windows</string>
|
||||
</property>
|
||||
<addaction name="actionAsset_Browser"/>
|
||||
<addaction name="actionEntity_templates"/>
|
||||
<addaction name="actionFile_server"/>
|
||||
<addaction name="actionGame_view"/>
|
||||
<addaction name="actionLog"/>
|
||||
|
@ -81,14 +82,25 @@
|
|||
</property>
|
||||
<addaction name="actionGame_mode"/>
|
||||
<addaction name="actionCompile_scripts"/>
|
||||
<addaction name="actionSnap_to_terrain"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEntity">
|
||||
<property name="title">
|
||||
<string>Entity</string>
|
||||
</property>
|
||||
<addaction name="actionCreate"/>
|
||||
<addaction name="actionSave_as_template"/>
|
||||
<addaction name="actionInstantiate_template"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
<property name="title">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
<addaction name="actionUndo"/>
|
||||
<addaction name="actionRedo"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuTools"/>
|
||||
<addaction name="menuEntity"/>
|
||||
|
@ -218,6 +230,48 @@
|
|||
<string>Ctrl+Tab</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSnap_to_terrain">
|
||||
<property name="text">
|
||||
<string>Snap to terrain</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_as_template">
|
||||
<property name="text">
|
||||
<string>Create template</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionEntity_templates">
|
||||
<property name="text">
|
||||
<string>Entity templates</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInstantiate_template">
|
||||
<property name="text">
|
||||
<string>Instantiate template</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Q</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUndo">
|
||||
<property name="text">
|
||||
<string>Undo</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Z</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRedo">
|
||||
<property name="text">
|
||||
<string>Redo</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Shift+Z</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
|
|
|
@ -12,9 +12,7 @@
|
|||
#include "core/json_serializer.h"
|
||||
#include "core/log.h"
|
||||
#include "core/profiler.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/editor_client.h"
|
||||
#include "editor/server_message_types.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "engine/engine.h"
|
||||
#include "graphics/material.h"
|
||||
#include "graphics/model.h"
|
||||
|
@ -37,6 +35,7 @@ class MaterialManagerUI
|
|||
Lumix::Model* m_selected_object_model;
|
||||
QFileSystemModel* m_fs_model;
|
||||
Lumix::Material* m_material;
|
||||
Lumix::WorldEditor* m_world_editor;
|
||||
};
|
||||
|
||||
|
||||
|
@ -46,6 +45,7 @@ MaterialManager::MaterialManager(QWidget *parent)
|
|||
{
|
||||
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());
|
||||
|
@ -53,8 +53,8 @@ MaterialManager::MaterialManager(QWidget *parent)
|
|||
filters << "*.mat";
|
||||
m_impl->m_fs_model->setNameFilters(filters);
|
||||
m_impl->m_fs_model->setNameFilterDisables(false);
|
||||
m_ui->fileListView->setModel(m_impl->m_fs_model);
|
||||
m_ui->fileListView->setRootIndex(m_impl->m_fs_model->index(QDir::currentPath()));
|
||||
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;
|
||||
|
@ -82,36 +82,38 @@ void MaterialManager::fillObjectMaterials()
|
|||
}
|
||||
}
|
||||
|
||||
void MaterialManager::onPropertyList(Lumix::PropertyListEvent& event)
|
||||
|
||||
QWidget* MaterialManager::getPreview() const
|
||||
{
|
||||
if (event.type_hash == crc32("renderable"))
|
||||
return m_ui->previewWidget;
|
||||
}
|
||||
|
||||
|
||||
void MaterialManager::onEntitySelected(Lumix::Entity& entity)
|
||||
{
|
||||
if (entity.isValid())
|
||||
{
|
||||
for (int i = 0; i < event.properties.size(); ++i)
|
||||
Lumix::Component cmp = entity.getComponent(crc32("renderable"));
|
||||
if (cmp.isValid())
|
||||
{
|
||||
if (event.properties[i].name_hash == crc32("source"))
|
||||
{
|
||||
m_impl->m_selected_object_model = static_cast<Lumix::Model*>(m_impl->m_engine->getResourceManager().get(Lumix::ResourceManager::MODEL)->get((char*)event.properties[i].data));
|
||||
fillObjectMaterials();
|
||||
}
|
||||
m_impl->m_selected_object_model = static_cast<Lumix::RenderScene*>(cmp.system)->getModel(cmp);
|
||||
fillObjectMaterials();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialManager::setEditorClient(Lumix::EditorClient& client)
|
||||
{
|
||||
client.propertyListReceived().bind<MaterialManager, &MaterialManager::onPropertyList>(this);
|
||||
}
|
||||
|
||||
void MaterialManager::setEditorServer(Lumix::EditorServer& server)
|
||||
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();
|
||||
m_impl->m_engine = &server.getEngine();
|
||||
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(server.getEngine(), *m_impl->m_universe);
|
||||
m_impl->m_render_device = new WGLRenderDevice(server.getEngine(), "pipelines/main.json");
|
||||
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);
|
||||
|
@ -136,41 +138,6 @@ void MaterialManager::setEditorServer(Lumix::EditorServer& server)
|
|||
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;
|
||||
/// TODO refactor (EditorServer::create)
|
||||
HDC hdc;
|
||||
hdc = GetDC(hwnd);
|
||||
ASSERT(hdc != NULL);
|
||||
PIXELFORMATDESCRIPTOR pfd =
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
|
||||
1, // version number
|
||||
PFD_DRAW_TO_WINDOW | // support window
|
||||
PFD_SUPPORT_OPENGL | // support OpenGL
|
||||
PFD_DOUBLEBUFFER, // double buffered
|
||||
PFD_TYPE_RGBA, // RGBA type
|
||||
24, // 24-bit color depth
|
||||
0, 0, 0, 0, 0, 0, // color bits ignored
|
||||
0, // no alpha buffer
|
||||
0, // shift bit ignored
|
||||
0, // no accumulation buffer
|
||||
0, 0, 0, 0, // accum bits ignored
|
||||
32, // 32-bit z-buffer
|
||||
0, // no stencil buffer
|
||||
0, // no auxiliary buffer
|
||||
PFD_MAIN_PLANE, // main layer
|
||||
0, // reserved
|
||||
0, 0, 0 // layer masks ignored
|
||||
};
|
||||
int pixelformat = ChoosePixelFormat(hdc, &pfd);
|
||||
if (pixelformat == 0)
|
||||
{
|
||||
ASSERT(false);
|
||||
}
|
||||
BOOL success = SetPixelFormat(hdc, pixelformat, &pfd);
|
||||
if (success == FALSE)
|
||||
{
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
MaterialManager::~MaterialManager()
|
||||
|
@ -276,7 +243,9 @@ void MaterialManager::onTextureAdded()
|
|||
|
||||
void MaterialManager::selectMaterial(const char* path)
|
||||
{
|
||||
Lumix::Material* material = static_cast<Lumix::Material*>(m_impl->m_engine->getResourceManager().get(Lumix::ResourceManager::MATERIAL)->load(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())
|
||||
|
@ -290,6 +259,7 @@ void MaterialManager::onMaterialLoaded(Lumix::Resource::State, Lumix::Resource::
|
|||
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)
|
||||
};
|
||||
|
@ -366,12 +336,6 @@ void MaterialManager::onTextureRemoved()
|
|||
selectMaterial(m_impl->m_material->getPath().c_str());
|
||||
}
|
||||
|
||||
void MaterialManager::on_fileListView_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
QString file_path = m_impl->m_fs_model->fileInfo(index).filePath().toLower();
|
||||
selectMaterial(file_path.toLatin1().data());
|
||||
}
|
||||
|
||||
void MaterialManager::on_objectMaterialList_doubleClicked(const QModelIndex &index)
|
||||
{
|
||||
QListWidgetItem* item = m_ui->objectMaterialList->item(index.row());
|
||||
|
@ -400,3 +364,9 @@ void MaterialManager::on_saveMaterialButton_clicked()
|
|||
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());
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ namespace Ui
|
|||
|
||||
namespace Lumix
|
||||
{
|
||||
class EditorServer;
|
||||
class EditorClient;
|
||||
class WorldEditor;
|
||||
struct Entity;
|
||||
class Event;
|
||||
struct PropertyListEvent;
|
||||
}
|
||||
|
@ -23,18 +23,17 @@ class MaterialManager : public QDockWidget
|
|||
public:
|
||||
explicit MaterialManager(QWidget* parent = NULL);
|
||||
~MaterialManager();
|
||||
void setEditorServer(Lumix::EditorServer& server);
|
||||
void setEditorClient(Lumix::EditorClient& client);
|
||||
void setWorldEditor(Lumix::WorldEditor& server);
|
||||
void updatePreview();
|
||||
QWidget* getPreview() const;
|
||||
|
||||
private:
|
||||
void onPropertyList(Lumix::PropertyListEvent& event);
|
||||
void fillObjectMaterials();
|
||||
void selectMaterial(const char* path);
|
||||
void onMaterialLoaded(Lumix::Resource::State, Lumix::Resource::State);
|
||||
void onEntitySelected(Lumix::Entity& entity);
|
||||
|
||||
private slots:
|
||||
void on_fileListView_doubleClicked(const QModelIndex& index);
|
||||
void on_objectMaterialList_doubleClicked(const QModelIndex& index);
|
||||
void on_saveMaterialButton_clicked();
|
||||
void onBoolPropertyStateChanged(int state);
|
||||
|
@ -42,6 +41,7 @@ class MaterialManager : public QDockWidget
|
|||
void onTextureChanged();
|
||||
void onTextureRemoved();
|
||||
void onTextureAdded();
|
||||
void on_fileTreeView_doubleClicked(const QModelIndex &index);
|
||||
|
||||
private:
|
||||
Ui::MaterialManager* m_ui;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
</property>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
|
@ -42,7 +42,7 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QListView" name="fileListView"/>
|
||||
<widget class="QTreeView" name="fileTreeView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
|
@ -42,6 +42,7 @@ class FileSystemWatcherPC : public FileSystemWatcher
|
|||
{
|
||||
switch(info->Action)
|
||||
{
|
||||
case FILE_ACTION_RENAMED_NEW_NAME:
|
||||
case FILE_ACTION_ADDED:
|
||||
case FILE_ACTION_MODIFIED:
|
||||
{
|
||||
|
@ -51,6 +52,7 @@ class FileSystemWatcherPC : public FileSystemWatcher
|
|||
// watcher->m_asset_browser->emitFileChanged(tmp);
|
||||
}
|
||||
break;
|
||||
case FILE_ACTION_RENAMED_OLD_NAME:
|
||||
case FILE_ACTION_REMOVED:
|
||||
//do not do anything
|
||||
break;
|
||||
|
@ -76,14 +78,20 @@ class FileSystemWatcherPC : public FileSystemWatcher
|
|||
{
|
||||
switch(info->Action)
|
||||
{
|
||||
case FILE_ACTION_RENAMED_NEW_NAME:
|
||||
case FILE_ACTION_ADDED:
|
||||
case FILE_ACTION_MODIFIED:
|
||||
{
|
||||
char tmp[MAX_PATH];
|
||||
wcharToCharArray(info->FileName, tmp, info->FileNameLength);
|
||||
watcher->m_callback.invoke(tmp);
|
||||
// watcher->m_asset_browser->emitFileChanged(tmp);
|
||||
}
|
||||
break;
|
||||
case FILE_ACTION_RENAMED_OLD_NAME:
|
||||
case FILE_ACTION_REMOVED:
|
||||
//do not do anything
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
|
|
|
@ -39,6 +39,36 @@ void ProfilerGraph::mouseMoveEvent(QMouseEvent* event)
|
|||
}
|
||||
}
|
||||
|
||||
void ProfilerGraph::getRootPath(QPainterPath& path, float max)
|
||||
{
|
||||
ProfileModel::Block* root = m_model->getRoot();
|
||||
|
||||
int w = width();
|
||||
int h = height();
|
||||
|
||||
path.moveTo(0, height());
|
||||
|
||||
if (max > 0)
|
||||
{
|
||||
for (int i = 0; i < root->m_frames.size(); ++i)
|
||||
{
|
||||
float l = i * w / (float)m_model->getRoot()->m_frames.size();
|
||||
float time = 0;
|
||||
ProfileModel::Block* block = root;
|
||||
while (block)
|
||||
{
|
||||
time += block->m_frames[i];
|
||||
block = block->m_next;
|
||||
}
|
||||
float t = (h - 1) * (1.0f - time / max);
|
||||
path.lineTo(l, t);
|
||||
}
|
||||
}
|
||||
path.lineTo(width(), height());
|
||||
path.closeSubpath();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ProfilerGraph::getBlockPath(ProfileModel::Block* block, QPainterPath& path, float max)
|
||||
{
|
||||
|
@ -49,12 +79,11 @@ void ProfilerGraph::getBlockPath(ProfileModel::Block* block, QPainterPath& path,
|
|||
|
||||
if(max > 0)
|
||||
{
|
||||
int i = m_model->getRoot()->m_frames.size() - block->m_frames.size();
|
||||
for(auto iter = block->m_frames.begin(), end = block->m_frames.end(); iter != end; ++iter)
|
||||
for (int i = 0; i < block->m_frames.size(); ++i)
|
||||
{
|
||||
float l = i * w / (float)m_model->getRoot()->m_frames.size();
|
||||
++i;
|
||||
float t = (h - 1) * (1.0f - *iter / max);
|
||||
float time = block->m_frames[i];
|
||||
float t = (h - 1) * (1.0f - time / max);
|
||||
path.lineTo(l, t);
|
||||
}
|
||||
}
|
||||
|
@ -80,15 +109,22 @@ void ProfilerGraph::paintEvent(QPaintEvent*)
|
|||
gradient.setSpread(QGradient::Spread::ReflectSpread);
|
||||
|
||||
float max = 0;
|
||||
for(auto iter = root->m_frames.begin(), end = root->m_frames.end(); iter != end; ++iter)
|
||||
for (int i = 0; i < root->m_frames.size(); ++i)
|
||||
{
|
||||
max = max < *iter ? *iter : max;
|
||||
ProfileModel::Block* block = root;
|
||||
float time = 0;
|
||||
while (block)
|
||||
{
|
||||
time += block->m_frames[i];
|
||||
block = block->m_next;
|
||||
}
|
||||
max = max < time ? time : max;
|
||||
}
|
||||
|
||||
QPainterPath path;
|
||||
getBlockPath(root, path, max);
|
||||
getRootPath(path, max);
|
||||
painter.fillPath(path, gradient);
|
||||
if(m_block && m_block != root)
|
||||
if(m_block)
|
||||
{
|
||||
QPainterPath detail_path;
|
||||
getBlockPath(m_block, detail_path, max);
|
||||
|
|
|
@ -25,6 +25,7 @@ class ProfilerGraph : public QWidget
|
|||
|
||||
private:
|
||||
void getBlockPath(ProfileModel::Block* block, QPainterPath& path, float max);
|
||||
void getRootPath(QPainterPath& path, float max);
|
||||
|
||||
signals:
|
||||
void frameSet();
|
||||
|
|
|
@ -3,72 +3,79 @@
|
|||
#include <qpainter.h>
|
||||
#include <qpixmap.h>
|
||||
|
||||
static const int MAX_FRAMES = 200;
|
||||
|
||||
ProfileModel::Block::Block()
|
||||
{
|
||||
m_frames.reserve(MAX_FRAMES);
|
||||
for(int i = 0; i < MAX_FRAMES; ++i)
|
||||
{
|
||||
m_frames.push_back(0);
|
||||
}
|
||||
m_hit_counts.reserve(MAX_FRAMES);
|
||||
for (int i = 0; i < MAX_FRAMES; ++i)
|
||||
{
|
||||
m_hit_counts.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ProfileModel::ProfileModel()
|
||||
{
|
||||
Lumix::g_profiler.getFrameListeners().bind<ProfileModel, &ProfileModel::onFrame>(this);
|
||||
m_root = NULL;
|
||||
m_frame = 0;
|
||||
m_frame = -1;
|
||||
}
|
||||
|
||||
void ProfileModel::cloneBlock(Block* my_block, Lumix::Profiler::Block* remote_block)
|
||||
{
|
||||
ASSERT(my_block->m_name == remote_block->m_name);
|
||||
my_block->m_frames.push_back(remote_block->getLength());
|
||||
if(my_block->m_frames.size() > 200)
|
||||
my_block->m_hit_counts.push_back(remote_block->getHitCount());
|
||||
if (my_block->m_frames.size() > MAX_FRAMES)
|
||||
{
|
||||
my_block->m_frames.pop_front();
|
||||
}
|
||||
if(!my_block->m_first_child && remote_block->m_first_child)
|
||||
if (my_block->m_hit_counts.size() > MAX_FRAMES)
|
||||
{
|
||||
my_block->m_hit_counts.pop_front();
|
||||
}
|
||||
|
||||
if (!my_block->m_first_child && remote_block->m_first_child)
|
||||
{
|
||||
Lumix::Profiler::Block* remote_child = remote_block->m_first_child;
|
||||
Block* last_new_child = NULL;
|
||||
while(remote_child)
|
||||
{
|
||||
Block* my_child = new Block;
|
||||
my_child->m_function = remote_child->m_function;
|
||||
my_child->m_name = remote_child->m_name;
|
||||
my_child->m_parent = my_block;
|
||||
my_child->m_next = NULL;
|
||||
my_child->m_first_child = NULL;
|
||||
if(last_new_child)
|
||||
{
|
||||
last_new_child->m_next = my_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
my_block->m_first_child = my_child;
|
||||
}
|
||||
last_new_child = my_child;
|
||||
cloneBlock(my_child, remote_child);
|
||||
remote_child = remote_child->m_next;
|
||||
}
|
||||
Block* my_child = new Block;
|
||||
my_child->m_function = remote_child->m_function;
|
||||
my_child->m_name = remote_child->m_name;
|
||||
my_child->m_parent = my_block;
|
||||
my_child->m_next = NULL;
|
||||
my_child->m_first_child = NULL;
|
||||
my_block->m_first_child = my_child;
|
||||
cloneBlock(my_child, remote_child);
|
||||
}
|
||||
else if(my_block->m_first_child)
|
||||
{
|
||||
Lumix::Profiler::Block* remote_child = remote_block->m_first_child;
|
||||
Block* my_child = my_block->m_first_child;
|
||||
while(remote_child)
|
||||
{
|
||||
if(my_child->m_name != remote_child->m_name && my_child->m_function != remote_child->m_function)
|
||||
{
|
||||
Block* new_child = new Block;
|
||||
new_child->m_function = remote_child->m_function;
|
||||
new_child->m_name = remote_child->m_name;
|
||||
new_child->m_parent = my_block;
|
||||
new_child->m_next = my_child;
|
||||
new_child->m_first_child = NULL;
|
||||
my_child = new_child;
|
||||
if(my_child == my_block->m_first_child)
|
||||
{
|
||||
my_block->m_first_child = new_child;
|
||||
}
|
||||
}
|
||||
cloneBlock(my_child, remote_child);
|
||||
remote_child = remote_child->m_next;
|
||||
my_child = my_child->m_next;
|
||||
}
|
||||
cloneBlock(my_child, remote_child);
|
||||
}
|
||||
|
||||
if (!my_block->m_next && remote_block->m_next)
|
||||
{
|
||||
Lumix::Profiler::Block* remote_next = remote_block->m_next;
|
||||
Block* my_next = new Block;
|
||||
my_next->m_function = remote_next->m_function;
|
||||
my_next->m_name = remote_next->m_name;
|
||||
my_next->m_parent = my_block->m_parent;
|
||||
my_next->m_next = NULL;
|
||||
my_next->m_first_child = NULL;
|
||||
my_block->m_next = my_next;
|
||||
cloneBlock(my_next, remote_next);
|
||||
|
||||
}
|
||||
else if (my_block->m_next)
|
||||
{
|
||||
cloneBlock(my_block->m_next, remote_block->m_next);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,6 +121,9 @@ QVariant ProfileModel::headerData(int section, Qt::Orientation, int role) const
|
|||
return "Name";
|
||||
case Values::LENGTH:
|
||||
return "Length (ms)";
|
||||
case Values::HIT_COUNT:
|
||||
return "Hit count";
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return QVariant();
|
||||
|
@ -131,22 +141,21 @@ QModelIndex ProfileModel::index(int row, int column, const QModelIndex& parent)
|
|||
Block* block = NULL;
|
||||
if(parent.internalPointer() != NULL)
|
||||
{
|
||||
block = static_cast<Block*>(parent.internalPointer());
|
||||
block = static_cast<Block*>(parent.internalPointer())->m_first_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
return createIndex(0, column, m_root);
|
||||
block = m_root;
|
||||
}
|
||||
|
||||
int index = row;
|
||||
Block* child = block->m_first_child;
|
||||
while(child && index > 0)
|
||||
while (block && index > 0)
|
||||
{
|
||||
child = child->m_next;
|
||||
block = block->m_next;
|
||||
--index;
|
||||
}
|
||||
|
||||
return createIndex(row, column, child);
|
||||
return createIndex(row, column, block);
|
||||
}
|
||||
|
||||
QModelIndex ProfileModel::parent(const QModelIndex& index) const
|
||||
|
@ -183,7 +192,14 @@ int ProfileModel::rowCount(const QModelIndex& parent_index) const
|
|||
|
||||
if (!parent_index.isValid() || !parent_index.internalPointer())
|
||||
{
|
||||
return 1;
|
||||
int count = 0;
|
||||
Block* root = m_root;
|
||||
while (root)
|
||||
{
|
||||
++count;
|
||||
root = root->m_next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -225,9 +241,10 @@ QVariant ProfileModel::data(const QModelIndex& index, int role) const
|
|||
case Values::NAME:
|
||||
return block->m_name;
|
||||
case Values::LENGTH:
|
||||
{
|
||||
return m_frame >= 0 && m_frame < block->m_frames.size() ? block->m_frames[m_frame] : 0;
|
||||
}
|
||||
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::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());
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
return QVariant();
|
||||
|
|
|
@ -38,17 +38,21 @@ class ProfileModel : public QAbstractItemModel
|
|||
NAME,
|
||||
FUNCTION,
|
||||
LENGTH,
|
||||
HIT_COUNT,
|
||||
COUNT
|
||||
};
|
||||
|
||||
struct Block
|
||||
{
|
||||
Block();
|
||||
|
||||
const char* m_name;
|
||||
const char* m_function;
|
||||
Block* m_parent;
|
||||
Block* m_first_child;
|
||||
Block* m_next;
|
||||
QList<float> m_frames;
|
||||
QList<int> m_hit_counts;
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -4,12 +4,13 @@
|
|||
#include <QDockWidget>
|
||||
#include "core/array.h"
|
||||
#include "core/string.h"
|
||||
#include "universe/entity.h"
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
class EditorClient;
|
||||
struct EntityPositionEvent;
|
||||
struct EntitySelectedEvent;
|
||||
struct Component;
|
||||
class WorldEditor;
|
||||
struct Entity;
|
||||
class Event;
|
||||
class Path;
|
||||
struct PropertyListEvent;
|
||||
|
@ -52,8 +53,7 @@ public:
|
|||
public:
|
||||
explicit PropertyView(QWidget* parent = NULL);
|
||||
~PropertyView();
|
||||
void setEditorClient(Lumix::EditorClient& client);
|
||||
Lumix::EditorClient* getEditorClient();
|
||||
void setWorldEditor(Lumix::WorldEditor& server);
|
||||
void setScriptCompiler(ScriptCompiler* compiler);
|
||||
|
||||
private slots:
|
||||
|
@ -65,24 +65,45 @@ private slots:
|
|||
void on_browseFilesClicked();
|
||||
void on_compileScriptClicked();
|
||||
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_terrainBrushTextureChanged(int value);
|
||||
void on_TerrainHeightSaveClicked();
|
||||
void on_TerrainSplatSaveClicked();
|
||||
void on_positionX_valueChanged(double arg1);
|
||||
void on_positionY_valueChanged(double arg1);
|
||||
void on_positionZ_valueChanged(double arg1);
|
||||
|
||||
void on_propertyList_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
private:
|
||||
void clear();
|
||||
void onPropertyList(Lumix::PropertyListEvent& event);
|
||||
void onEntitySelected(Lumix::EntitySelectedEvent& event);
|
||||
void onEntityPosition(Lumix::EntityPositionEvent& e);
|
||||
void onUniverseCreated();
|
||||
void onUniverseDestroyed();
|
||||
void onEntitySelected(Lumix::Entity& e);
|
||||
void onEntityPosition(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, void* data, int32_t data_size);
|
||||
void onPropertyValue(Property* property, const void* data, int32_t data_size);
|
||||
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 setScriptStatus(uint32_t status);
|
||||
void updateValues();
|
||||
void updateSelectedEntityPosition();
|
||||
|
||||
private:
|
||||
Ui::PropertyView* m_ui;
|
||||
Lumix::EditorClient* m_client;
|
||||
Lumix::Array<Property*> m_properties;
|
||||
ScriptCompiler* m_compiler;
|
||||
int m_selected_entity_index;
|
||||
Lumix::Entity m_selected_entity;
|
||||
Lumix::WorldEditor* m_world_editor;
|
||||
bool m_is_updating_values;
|
||||
class TerrainEditor* m_terrain_editor;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="propertyList">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "sceneview.h"
|
||||
#include "editor/editor_client.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include <qapplication.h>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QDragEnterEvent>
|
||||
|
@ -16,11 +15,12 @@ class ViewWidget : public QWidget
|
|||
ViewWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent* event) override
|
||||
{
|
||||
m_client->mouseDown(event->x(), event->y(), event->button() == Qt::LeftButton ? 0 : 2);
|
||||
m_world_editor->onMouseDown(event->x(), event->y(), event->button() == Qt::RightButton ? Lumix::MouseButton::RIGHT : Lumix::MouseButton::LEFT);
|
||||
m_last_x = event->x();
|
||||
m_last_y = event->y();
|
||||
setFocus();
|
||||
|
@ -29,19 +29,19 @@ class ViewWidget : public QWidget
|
|||
virtual void mouseMoveEvent(QMouseEvent* event) override
|
||||
{
|
||||
int flags = 0;
|
||||
flags |= Qt::ControlModifier & QApplication::keyboardModifiers() ? (int)Lumix::EditorServer::MouseFlags::CONTROL : 0;
|
||||
flags |= Qt::AltModifier & QApplication::keyboardModifiers() ? (int)Lumix::EditorServer::MouseFlags::ALT : 0;
|
||||
m_client->mouseMove(event->x(), event->y(), event->x() - m_last_x, event->y() - m_last_y, flags);
|
||||
flags |= Qt::ControlModifier & QApplication::keyboardModifiers() ? (int)Lumix::WorldEditor::MouseFlags::CONTROL : 0;
|
||||
flags |= Qt::AltModifier & QApplication::keyboardModifiers() ? (int)Lumix::WorldEditor::MouseFlags::ALT : 0;
|
||||
m_world_editor->onMouseMove(event->x(), event->y(), event->x() - m_last_x, event->y() - m_last_y, flags);
|
||||
m_last_x = event->x();
|
||||
m_last_y = event->y();
|
||||
}
|
||||
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override
|
||||
{
|
||||
m_client->mouseUp(event->x(), event->y(), event->button() == Qt::LeftButton ? 0 : 2);
|
||||
m_world_editor->onMouseUp(event->x(), event->y(), event->button() == Qt::RightButton ? Lumix::MouseButton::RIGHT : Lumix::MouseButton::LEFT);
|
||||
}
|
||||
|
||||
Lumix::EditorClient* m_client;
|
||||
Lumix::WorldEditor* m_world_editor;
|
||||
int m_last_x;
|
||||
int m_last_y;
|
||||
};
|
||||
|
@ -69,10 +69,10 @@ SceneView::SceneView(QWidget* parent) :
|
|||
}
|
||||
|
||||
|
||||
void SceneView::setEditorClient(Lumix::EditorClient& client)
|
||||
void SceneView::setWorldEditor(Lumix::WorldEditor* world_editor)
|
||||
{
|
||||
m_client = &client;
|
||||
static_cast<ViewWidget*>(m_view)->m_client = &client;
|
||||
static_cast<ViewWidget*>(m_view)->m_world_editor = world_editor;
|
||||
m_world_editor = world_editor;
|
||||
}
|
||||
|
||||
|
||||
|
@ -98,14 +98,12 @@ void SceneView::dropEvent(QDropEvent *event)
|
|||
QString file = list[0].toLocalFile();
|
||||
if(file.endsWith(".msh"))
|
||||
{
|
||||
m_client->addEntity();
|
||||
m_client->addComponent(crc32("renderable"));
|
||||
QString base_path = m_client->getBasePath();
|
||||
if(file.startsWith(base_path))
|
||||
{
|
||||
file.remove(0, base_path.length());
|
||||
}
|
||||
m_client->setComponentProperty("renderable", "source", file.toLatin1().data(), file.length());
|
||||
m_world_editor->addEntityAt(event->pos().x(), event->pos().y());
|
||||
m_world_editor->addComponent(crc32("renderable"));
|
||||
char rel_path[LUMIX_MAX_PATH];
|
||||
m_world_editor->getRelativePath(rel_path, LUMIX_MAX_PATH, file.toLatin1().data());
|
||||
m_world_editor->setProperty("renderable", "source", rel_path, strlen(rel_path));
|
||||
m_world_editor->selectEntity(m_world_editor->getSelectedEntity());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
namespace Lumix
|
||||
{
|
||||
class EditorClient;
|
||||
class EditorServer;
|
||||
class WorldEditor;
|
||||
class PipelineInstance;
|
||||
}
|
||||
|
||||
|
@ -17,8 +16,7 @@ class SceneView : public QDockWidget
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit SceneView(QWidget* parent = NULL);
|
||||
void setEditorClient(Lumix::EditorClient& client);
|
||||
void setServer(Lumix::EditorServer* server) { m_server = server; }
|
||||
void setWorldEditor(Lumix::WorldEditor* server);
|
||||
void setPipeline(Lumix::PipelineInstance& pipeline) { m_pipeline = &pipeline; }
|
||||
QWidget* getViewWidget() { return m_view; }
|
||||
float getNavivationSpeed() const;
|
||||
|
@ -29,8 +27,7 @@ private:
|
|||
virtual void dropEvent(QDropEvent *event) override;
|
||||
|
||||
private:
|
||||
Lumix::EditorClient* m_client;
|
||||
Lumix::EditorServer* m_server;
|
||||
Lumix::WorldEditor* m_world_editor;
|
||||
Lumix::PipelineInstance* m_pipeline;
|
||||
QWidget* m_view;
|
||||
QDoubleSpinBox* m_speed_input;
|
||||
|
|
21
qteditor/QtEditor/terrain_editor.ui
Normal file
21
qteditor/QtEditor/terrain_editor.ui
Normal file
|
@ -0,0 +1,21 @@
|
|||
<ui version="4.0">
|
||||
<author/>
|
||||
<comment/>
|
||||
<exportmacro/>
|
||||
<class>TerrainEditor</class>
|
||||
<widget name="TerrainEditor" class="QWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
</widget>
|
||||
<pixmapfunction/>
|
||||
<connections/>
|
||||
</ui>
|
BIN
qteditor/QtEditor/vc120.pdb
Normal file
BIN
qteditor/QtEditor/vc120.pdb
Normal file
Binary file not shown.
|
@ -33,15 +33,13 @@ public:
|
|||
virtual void beginFrame() override
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
BOOL b = wglMakeCurrent(m_hdc, m_opengl_context);
|
||||
ASSERT(b);
|
||||
wglMakeCurrent(m_hdc, m_opengl_context);
|
||||
}
|
||||
|
||||
virtual void endFrame() override
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
BOOL b = wglSwapLayerBuffers(m_hdc, WGL_SWAP_MAIN_PLANE);
|
||||
ASSERT(b);
|
||||
wglSwapLayerBuffers(m_hdc, WGL_SWAP_MAIN_PLANE);
|
||||
}
|
||||
|
||||
virtual Lumix::PipelineInstance& getPipeline()
|
||||
|
|
|
@ -40,6 +40,7 @@ Animation::Animation(const Path& path, ResourceManager& resource_manager)
|
|||
{
|
||||
m_rotations = NULL;
|
||||
m_positions = NULL;
|
||||
m_bones = NULL;
|
||||
m_frame_count = 0;
|
||||
}
|
||||
|
||||
|
@ -48,6 +49,7 @@ Animation::~Animation()
|
|||
{
|
||||
LUMIX_DELETE_ARRAY(m_positions);
|
||||
LUMIX_DELETE_ARRAY(m_rotations);
|
||||
LUMIX_DELETE_ARRAY(m_bones);
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,13 +72,20 @@ void Animation::getPose(float time, Pose& pose, Model& model) const
|
|||
{
|
||||
for(int i = 0; i < m_bone_count; ++i)
|
||||
{
|
||||
lerp(m_positions[off + i], m_positions[off2 + i], &pos[i], t);
|
||||
nlerp(m_rotations[off + i], m_rotations[off2 + i], &rot[i], t);
|
||||
int parent = model.getBone(i).parent_idx;
|
||||
if (parent >= 0)
|
||||
Model::BoneMap::iterator iter = model.getBoneIndex(m_bones[i]);
|
||||
if (iter.isValid())
|
||||
{
|
||||
pos[i] = rot[parent] * pos[i] + pos[parent];
|
||||
rot[i] = rot[i] * rot[parent];
|
||||
int model_bone_index = iter.value();
|
||||
lerp(m_positions[off + i], m_positions[off2 + i], &pos[model_bone_index], t);
|
||||
nlerp(m_rotations[off + i], m_rotations[off2 + i], &rot[model_bone_index], t);
|
||||
|
||||
/*int parent = model.getBone(model_bone_index).parent_idx;
|
||||
ASSERT(parent < model_bone_index);
|
||||
if (parent >= 0)
|
||||
{
|
||||
pos[model_bone_index] = rot[parent] * pos[model_bone_index] + pos[parent];
|
||||
rot[model_bone_index] = rot[model_bone_index] * rot[parent];
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,16 +93,24 @@ void Animation::getPose(float time, Pose& pose, Model& model) const
|
|||
{
|
||||
for(int i = 0; i < m_bone_count; ++i)
|
||||
{
|
||||
pos[i] = m_positions[off + i];
|
||||
rot[i] = m_rotations[off + i];
|
||||
int parent = model.getBone(i).parent_idx;
|
||||
if (parent >= 0)
|
||||
Model::BoneMap::iterator iter = model.getBoneIndex(m_bones[i]);
|
||||
if (iter.isValid())
|
||||
{
|
||||
pos[i] = rot[parent] * pos[i] + pos[parent];
|
||||
rot[i] = rot[i] * rot[parent];
|
||||
int model_bone_index = iter.value();
|
||||
pos[model_bone_index] = m_positions[off + i];
|
||||
rot[model_bone_index] = m_rotations[off + i];
|
||||
/*int parent = model.getBone(model_bone_index).parent_idx;
|
||||
ASSERT(parent < model_bone_index);
|
||||
if (parent >= 0)
|
||||
{
|
||||
pos[model_bone_index] = rot[parent] * pos[model_bone_index] + pos[parent];
|
||||
rot[model_bone_index] = rot[model_bone_index] * rot[parent];
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
pose.setIsRelative();
|
||||
pose.computeAbsolute(model);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,9 +145,11 @@ void Animation::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
|||
|
||||
m_positions = LUMIX_NEW_ARRAY(Vec3, m_frame_count * m_bone_count);
|
||||
m_rotations = LUMIX_NEW_ARRAY(Quat, m_frame_count * m_bone_count);
|
||||
m_bones = LUMIX_NEW_ARRAY(uint32_t, m_bone_count);
|
||||
file->read(&m_positions[0], sizeof(Vec3)* m_bone_count * m_frame_count);
|
||||
file->read(&m_rotations[0], sizeof(Quat)* m_bone_count * m_frame_count);
|
||||
|
||||
file->read(m_bones, sizeof(m_bones[0]) * m_bone_count);
|
||||
|
||||
m_size = file->size();
|
||||
decrementDepCount();
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ class Animation : public Resource
|
|||
int m_bone_count;
|
||||
Vec3* m_positions;
|
||||
Quat* m_rotations;
|
||||
uint32_t* m_bones;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "core/crc32.h"
|
||||
#include "core/json_serializer.h"
|
||||
#include "core/resource_manager.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "engine/engine.h"
|
||||
#include "graphics/renderer.h"
|
||||
#include "universe/universe.h"
|
||||
|
@ -15,214 +15,278 @@ namespace Lumix
|
|||
static const uint32_t ANIMABLE_HASH = crc32("animable");
|
||||
|
||||
|
||||
struct AnimationSystemImpl
|
||||
struct AnimationSystemImpl : public AnimationSystem
|
||||
{
|
||||
public:
|
||||
AnimationSystemImpl(Engine& engine) : m_engine(engine) {}
|
||||
|
||||
struct Animable
|
||||
{
|
||||
bool m_manual;
|
||||
bool m_is_free;
|
||||
Component m_renderable;
|
||||
float m_time;
|
||||
class Animation* m_animation;
|
||||
};
|
||||
|
||||
|
||||
|
||||
void onCreateUniverse(Universe& universe)
|
||||
{
|
||||
ASSERT(!m_universe);
|
||||
m_universe = &universe;
|
||||
m_universe->componentCreated().bind<AnimationSystemImpl, &AnimationSystemImpl::onComponentCreated>(this);
|
||||
}
|
||||
|
||||
|
||||
void onDestroyUniverse(Universe&)
|
||||
{
|
||||
ASSERT(m_universe);
|
||||
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
|
||||
{
|
||||
if (component_type == ANIMABLE_HASH)
|
||||
{
|
||||
return createAnimable(entity);
|
||||
}
|
||||
return Component::INVALID;
|
||||
}
|
||||
|
||||
|
||||
virtual void destroyComponent(const Component& component) override
|
||||
{
|
||||
m_animables[component.index].m_is_free = true;
|
||||
m_universe->removeComponent(component);
|
||||
m_universe->componentDestroyed().invoke(component);
|
||||
|
||||
}
|
||||
|
||||
|
||||
virtual void serialize(ISerializer& serializer) override
|
||||
{
|
||||
serializer.serialize("count", m_animables.size());
|
||||
serializer.beginArray("animables");
|
||||
for (int i = 0; i < m_animables.size(); ++i)
|
||||
{
|
||||
serializer.serializeArrayItem(m_animables[i].m_manual);
|
||||
serializer.serializeArrayItem(m_animables[i].m_renderable.entity.index);
|
||||
serializer.serializeArrayItem(m_animables[i].m_time);
|
||||
serializer.serializeArrayItem(m_animables[i].m_is_free);
|
||||
}
|
||||
serializer.endArray();
|
||||
}
|
||||
|
||||
|
||||
virtual void deserialize(ISerializer& serializer) override
|
||||
{
|
||||
int count;
|
||||
serializer.deserialize("count", count);
|
||||
serializer.deserializeArrayBegin("animables");
|
||||
m_animables.resize(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
serializer.deserializeArrayItem(m_animables[i].m_manual);
|
||||
int entity_index;
|
||||
serializer.deserializeArrayItem(entity_index);
|
||||
Entity e(m_universe, entity_index);
|
||||
const Entity::ComponentList& cmps = e.getComponents();
|
||||
m_animables[i].m_renderable = Component::INVALID;
|
||||
for (int j = 0; j < cmps.size(); ++j)
|
||||
{
|
||||
if (cmps[j].type == RENDERABLE_HASH)
|
||||
{
|
||||
m_animables[i].m_renderable = cmps[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
serializer.deserializeArrayItem(m_animables[i].m_time);
|
||||
serializer.deserializeArrayItem(m_animables[i].m_is_free);
|
||||
m_universe->addComponent(e, ANIMABLE_HASH, this, i);
|
||||
}
|
||||
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
|
||||
{
|
||||
m_animables[cmp.index].m_time = m_animables[cmp.index].m_animation->getLength() * frame / 30.0f; /// TODO get rid of the constant
|
||||
}
|
||||
|
||||
|
||||
virtual bool isManual(Component cmp) override
|
||||
{
|
||||
return m_animables[cmp.index].m_manual;
|
||||
}
|
||||
|
||||
|
||||
virtual void setManual(Component cmp, bool is_manual) override
|
||||
{
|
||||
m_animables[cmp.index].m_manual = is_manual;
|
||||
}
|
||||
|
||||
|
||||
virtual void getPreview(Component cmp, string& path) override
|
||||
{
|
||||
path = m_animables[cmp.index].m_animation ? m_animables[cmp.index].m_animation->getPath().c_str() : "";
|
||||
}
|
||||
|
||||
|
||||
virtual void setPreview(Component cmp, const string& path) override
|
||||
{
|
||||
playAnimation(cmp, path.c_str());
|
||||
}
|
||||
|
||||
|
||||
virtual void playAnimation(const Component& cmp, const char* path) override
|
||||
{
|
||||
m_animables[cmp.index].m_animation = loadAnimation(path);
|
||||
m_animables[cmp.index].m_time = 0;
|
||||
m_animables[cmp.index].m_manual = false;
|
||||
}
|
||||
|
||||
|
||||
virtual void setAnimationFrame(const Component& cmp, int frame) override
|
||||
{
|
||||
if (m_animables[cmp.index].m_animation)
|
||||
{
|
||||
m_animables[cmp.index].m_time = m_animables[cmp.index].m_animation->getLength() * frame / m_animables[cmp.index].m_animation->getFrameCount();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual int getFrameCount(const Component& cmp) const override
|
||||
{
|
||||
if (m_animables[cmp.index].m_animation)
|
||||
{
|
||||
return m_animables[cmp.index].m_animation->getFrameCount();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual void update(float time_delta) override
|
||||
{
|
||||
if (m_animables.empty())
|
||||
return;
|
||||
for (int i = 0, c = m_animables.size(); i < c; ++i)
|
||||
{
|
||||
AnimationSystemImpl::Animable& animable = m_animables[i];
|
||||
if (!animable.m_is_free && animable.m_animation && animable.m_animation->isReady())
|
||||
{
|
||||
RenderScene* scene = static_cast<RenderScene*>(animable.m_renderable.system);
|
||||
animable.m_animation->getPose(animable.m_time, scene->getPose(animable.m_renderable), *scene->getModel(animable.m_renderable));
|
||||
if (!animable.m_manual)
|
||||
{
|
||||
float t = animable.m_time + time_delta;
|
||||
float l = animable.m_animation->getLength();
|
||||
while (t > l)
|
||||
{
|
||||
t -= l;
|
||||
}
|
||||
animable.m_time = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual const char* getName() const override
|
||||
{
|
||||
return "animation";
|
||||
}
|
||||
|
||||
|
||||
virtual bool create(Engine& engine) override
|
||||
{
|
||||
m_engine = &engine;
|
||||
m_universe = 0;
|
||||
if (engine.getWorldEditor())
|
||||
{
|
||||
engine.getWorldEditor()->registerCreator(ANIMABLE_HASH, *this);
|
||||
}
|
||||
engine.getWorldEditor()->registerProperty("animable", LUMIX_NEW(PropertyDescriptor<AnimationSystem>)(crc32("preview"), &AnimationSystem::getPreview, &AnimationSystem::setPreview, IPropertyDescriptor::FILE));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual void destroy() override
|
||||
{
|
||||
}
|
||||
|
||||
Array<Animable> m_animables;
|
||||
Universe* m_universe;
|
||||
Engine& m_engine;
|
||||
|
||||
void onComponentCreated(Component& component);
|
||||
|
||||
Engine* m_engine;
|
||||
|
||||
private:
|
||||
void operator=(const AnimationSystemImpl&);
|
||||
};
|
||||
|
||||
bool AnimationSystem::create(Engine& engine)
|
||||
|
||||
AnimationSystem* AnimationSystem::createInstance()
|
||||
{
|
||||
m_impl = LUMIX_NEW(AnimationSystemImpl)(engine);
|
||||
m_impl->m_universe = 0;
|
||||
if(engine.getEditorServer())
|
||||
{
|
||||
engine.getEditorServer()->registerCreator(ANIMABLE_HASH, *this);
|
||||
}
|
||||
engine.getEditorServer()->registerProperty("animable", LUMIX_NEW(PropertyDescriptor<AnimationSystem>)(crc32("preview"), &AnimationSystem::getPreview, &AnimationSystem::setPreview, IPropertyDescriptor::FILE));
|
||||
return true;
|
||||
return LUMIX_NEW(AnimationSystemImpl);
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::destroy()
|
||||
{
|
||||
LUMIX_DELETE(m_impl);
|
||||
m_impl = 0;
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::onCreateUniverse(Universe& universe)
|
||||
{
|
||||
ASSERT(!m_impl->m_universe);
|
||||
m_impl->m_universe = &universe;
|
||||
m_impl->m_universe->componentCreated().bind<AnimationSystemImpl, &AnimationSystemImpl::onComponentCreated>(m_impl);
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::onDestroyUniverse(Universe&)
|
||||
{
|
||||
ASSERT(m_impl->m_universe);
|
||||
m_impl->m_animables.clear();
|
||||
m_impl->m_universe->componentCreated().unbind<AnimationSystemImpl, &AnimationSystemImpl::onComponentCreated>(m_impl);
|
||||
m_impl->m_universe = 0;
|
||||
}
|
||||
|
||||
|
||||
Component AnimationSystem::createComponent(uint32_t component_type, const Entity& entity)
|
||||
{
|
||||
if(component_type == ANIMABLE_HASH)
|
||||
{
|
||||
return createAnimable(entity);
|
||||
}
|
||||
return Component::INVALID;
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::serialize(ISerializer& serializer)
|
||||
{
|
||||
serializer.serialize("count", m_impl->m_animables.size());
|
||||
serializer.beginArray("animables");
|
||||
for(int i = 0; i < m_impl->m_animables.size(); ++i)
|
||||
{
|
||||
serializer.serializeArrayItem(m_impl->m_animables[i].m_manual);
|
||||
serializer.serializeArrayItem(m_impl->m_animables[i].m_renderable.entity.index);
|
||||
serializer.serializeArrayItem(m_impl->m_animables[i].m_time);
|
||||
}
|
||||
serializer.endArray();
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::deserialize(ISerializer& serializer)
|
||||
{
|
||||
int count;
|
||||
serializer.deserialize("count", count);
|
||||
serializer.deserializeArrayBegin("animables");
|
||||
m_impl->m_animables.resize(count);
|
||||
for(int i = 0; i < count; ++i)
|
||||
{
|
||||
serializer.deserializeArrayItem(m_impl->m_animables[i].m_manual);
|
||||
int entity_index;
|
||||
serializer.deserializeArrayItem(entity_index);
|
||||
Entity e(m_impl->m_universe, entity_index);
|
||||
const Entity::ComponentList& cmps = e.getComponents();
|
||||
m_impl->m_animables[i].m_renderable = Component::INVALID;
|
||||
for(int j = 0; j < cmps.size(); ++j)
|
||||
{
|
||||
if(cmps[j].type == RENDERABLE_HASH)
|
||||
{
|
||||
m_impl->m_animables[i].m_renderable = cmps[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
serializer.deserializeArrayItem(m_impl->m_animables[i].m_time);
|
||||
m_impl->m_universe->addComponent(e, ANIMABLE_HASH, this, i);
|
||||
}
|
||||
serializer.deserializeArrayEnd();
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystemImpl::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 AnimationSystem::createAnimable(const Entity& entity)
|
||||
{
|
||||
AnimationSystemImpl::Animable& animable = m_impl->m_animables.pushEmpty();
|
||||
animable.m_manual = true;
|
||||
animable.m_time = 0;
|
||||
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_impl->m_universe->addComponent(entity, ANIMABLE_HASH, this, m_impl->m_animables.size() - 1);
|
||||
m_impl->m_universe->componentCreated().invoke(cmp);
|
||||
return cmp;
|
||||
}
|
||||
|
||||
|
||||
Animation* AnimationSystem::loadAnimation(const char* path)
|
||||
{
|
||||
ResourceManager& rm = m_impl->m_engine.getResourceManager();
|
||||
return static_cast<Animation*>(rm.get(ResourceManager::ANIMATION)->load(path));
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::getPreview(Component cmp, string& path)
|
||||
{
|
||||
path = m_impl->m_animables[cmp.index].m_animation ? m_impl->m_animables[cmp.index].m_animation->getPath().c_str() : "";
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::setPreview(Component cmp, const string& path)
|
||||
{
|
||||
playAnimation(cmp, path.c_str());
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::playAnimation(const Component& cmp, const char* path)
|
||||
{
|
||||
m_impl->m_animables[cmp.index].m_animation = loadAnimation(path);
|
||||
m_impl->m_animables[cmp.index].m_time = 0;
|
||||
m_impl->m_animables[cmp.index].m_manual = false;
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::setAnimationTime(const Component& cmp, float time)
|
||||
{
|
||||
m_impl->m_animables[cmp.index].m_time = time;
|
||||
}
|
||||
|
||||
|
||||
void AnimationSystem::update(float time_delta)
|
||||
{
|
||||
if(m_impl->m_animables.empty())
|
||||
return;
|
||||
for(int i = 0, c = m_impl->m_animables.size(); i < c; ++i)
|
||||
{
|
||||
AnimationSystemImpl::Animable& animable = m_impl->m_animables[i];
|
||||
if(!animable.m_manual && animable.m_animation->isReady())
|
||||
{
|
||||
RenderScene* scene = static_cast<RenderScene*>(animable.m_renderable.system);
|
||||
animable.m_animation->getPose(animable.m_time, scene->getPose(animable.m_renderable), *scene->getModel(animable.m_renderable));
|
||||
float t = animable.m_time + time_delta;
|
||||
float l = animable.m_animation->getLength();
|
||||
while(t > l)
|
||||
{
|
||||
t -= l;
|
||||
}
|
||||
animable.m_time = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // ~namespace Lumix
|
||||
|
|
|
@ -22,27 +22,17 @@ namespace Lumix
|
|||
class LUMIX_ENGINE_API AnimationSystem : public IPlugin
|
||||
{
|
||||
public:
|
||||
AnimationSystem() { m_impl = 0; }
|
||||
static AnimationSystem* createInstance();
|
||||
|
||||
virtual bool create(Engine&) override;
|
||||
virtual void update(float time_delta) 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 Component createComponent(uint32_t, const Entity&) override;
|
||||
virtual const char* getName() const override { return "animation"; }
|
||||
virtual void setFrame(Component cmp, int frame) = 0;
|
||||
virtual bool isManual(Component cmp) = 0;
|
||||
virtual void setManual(Component cmp, bool is_manual) = 0;
|
||||
virtual void getPreview(Component cmp, string& path) = 0;
|
||||
virtual void setPreview(Component cmp, const string& path) = 0;
|
||||
|
||||
void getPreview(Component cmp, string& path);
|
||||
void setPreview(Component cmp, const string& path);
|
||||
void destroy();
|
||||
Component createAnimable(const Entity& entity);
|
||||
void playAnimation(const Component& cmp, const char* path);
|
||||
void setAnimationTime(const Component& cmp, float time);
|
||||
Animation* loadAnimation(const char* path);
|
||||
|
||||
private:
|
||||
struct AnimationSystemImpl* m_impl;
|
||||
virtual void playAnimation(const Component& cmp, const char* path) = 0;
|
||||
virtual void setAnimationFrame(const Component& cmp, int frame) = 0;
|
||||
virtual int getFrameCount(const Component& cmp) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -362,6 +362,7 @@ public:
|
|||
|
||||
T& back()
|
||||
{
|
||||
ASSERT(m_size > 0);
|
||||
return m_data[m_size - 1];
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,28 @@ namespace Lumix
|
|||
}
|
||||
|
||||
|
||||
void Blob::rewindForRead()
|
||||
{
|
||||
m_pos = 0;
|
||||
if (!m_buffer.empty())
|
||||
{
|
||||
m_data = &m_buffer[0];
|
||||
m_size = m_buffer.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Blob::write(const void* data, int32_t size)
|
||||
{
|
||||
if(m_size + (int)size > m_buffer.size())
|
||||
{
|
||||
m_buffer.resize(m_size + size);
|
||||
m_data = &m_buffer[0];
|
||||
}
|
||||
if (size)
|
||||
{
|
||||
memcpy(&m_buffer[0] + m_size, data, size);
|
||||
}
|
||||
memcpy(&m_buffer[0] + m_size, data, size);
|
||||
m_size += size;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace Lumix
|
|||
template <class T>
|
||||
void read(T& value) { read(&value, sizeof(T)); }
|
||||
|
||||
void rewindForRead() { m_pos = 0; m_data = &m_buffer[0]; m_size = m_buffer.size(); }
|
||||
void rewindForRead();
|
||||
|
||||
|
||||
private:
|
||||
|
|
|
@ -409,6 +409,7 @@ namespace Lumix
|
|||
|
||||
void destruct(node_type* n)
|
||||
{
|
||||
(void)n; /// to avoid a bug in VS 2013 - n is unused warning
|
||||
n->~node_type();
|
||||
}
|
||||
|
||||
|
|
|
@ -280,8 +280,14 @@ void JsonSerializer::deserializeArrayBegin()
|
|||
|
||||
void JsonSerializer::deserializeRawString(char* buffer, int max_length)
|
||||
{
|
||||
buffer[0] = m_buffer;
|
||||
m_file.read(buffer + 1, max_length);
|
||||
strncpy(buffer, m_token, max_length);
|
||||
size_t token_length = strlen(m_token);
|
||||
if (token_length + 2 <= max_length)
|
||||
{
|
||||
buffer[token_length] = '\n';
|
||||
buffer[token_length + 1] = m_buffer;
|
||||
m_file.read(buffer + token_length + 2, max_length - token_length - 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -75,6 +75,12 @@ namespace Lumix
|
|||
virtual void nextArrayItem() override;
|
||||
virtual bool isObjectEnd() const override;
|
||||
|
||||
size_t getRestOfFileSize()
|
||||
{
|
||||
const size_t NEW_LINE_AND_M_BUFFER_SIZE = sizeof('\n') + sizeof(m_buffer);
|
||||
return m_file.size() - m_file.pos() + NEW_LINE_AND_M_BUFFER_SIZE + strlen(m_token);
|
||||
}
|
||||
|
||||
private:
|
||||
void deserializeLabel(const char* label);
|
||||
void deserializeToken();
|
||||
|
|
|
@ -60,6 +60,12 @@ namespace Lumix
|
|||
return *this;
|
||||
}
|
||||
|
||||
LogProxy& LogProxy::operator <<(float message)
|
||||
{
|
||||
m_message.cat(message);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LogProxy& LogProxy::operator <<(uint32_t message)
|
||||
{
|
||||
m_message.cat(message);
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace Lumix
|
|||
~LogProxy();
|
||||
|
||||
LogProxy& operator <<(const char* message);
|
||||
LogProxy& operator <<(float message);
|
||||
LogProxy& operator <<(int32_t message);
|
||||
LogProxy& operator <<(uint32_t message);
|
||||
LogProxy& operator <<(const Path& path);
|
||||
|
|
|
@ -30,7 +30,11 @@ const uint32_t LUMIX_MAX_PATH = 260;
|
|||
|
||||
#ifndef ASSERT
|
||||
#ifdef _WIN32
|
||||
#define ASSERT(x) { const volatile bool lumix_assert_b____ = !(x); if(lumix_assert_b____) __debugbreak(); }
|
||||
#ifdef NDEBUG
|
||||
#define ASSERT(x) { false ? (void)(x) : 0; }
|
||||
#else
|
||||
#define ASSERT(x) { const volatile bool lumix_assert_b____ = !(x); if(lumix_assert_b____) __debugbreak(); }
|
||||
#endif
|
||||
#else
|
||||
#define ASSERT(x) assert(x)
|
||||
#endif
|
||||
|
@ -75,6 +79,8 @@ const uint32_t LUMIX_MAX_PATH = 260;
|
|||
#define LUMIX_SCRIPT_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#define LUMIX_RESTRICT __restrict
|
||||
|
||||
#include "core/new.h"
|
||||
#include "core/new_macros.h"
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Lumix
|
|||
bool operator == (const char* rhs) const { Path path(rhs); return m_id == path.m_id; }
|
||||
bool operator == (uint32_t rhs) const { return m_id == rhs; }
|
||||
|
||||
bool isValid() { return NULL != m_path; }
|
||||
bool isValid() const { return m_path[0] != '\0'; }
|
||||
|
||||
private:
|
||||
char m_path[LUMIX_MAX_PATH];
|
||||
|
|
|
@ -50,6 +50,21 @@ namespace Lumix
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void getExtension(char* extension, int /*max_length*/, const char* src)
|
||||
{
|
||||
for (int i = strlen(src) - 1; i >= 0; --i)
|
||||
{
|
||||
if (src[i] == '.')
|
||||
{
|
||||
++i;
|
||||
strcpy(extension, src + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PathUtils();
|
||||
~PathUtils();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "profiler.h"
|
||||
#include "core/log.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
|
@ -57,22 +58,20 @@ namespace Lumix
|
|||
}
|
||||
if (!m_current_block)
|
||||
{
|
||||
if (m_root_block)
|
||||
Block* root = m_root_block;
|
||||
while (root && (root->m_name != name || root->m_function != function))
|
||||
{
|
||||
if (m_root_block->m_name == name && m_root_block->m_function == function)
|
||||
{
|
||||
m_current_block = m_root_block;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(false); // there can be only one root
|
||||
}
|
||||
root = root->m_next;
|
||||
}
|
||||
if (root)
|
||||
{
|
||||
m_current_block = root;
|
||||
}
|
||||
else
|
||||
{
|
||||
Block* root = LUMIX_NEW(Block);
|
||||
root->m_parent = NULL;
|
||||
root->m_next = NULL;
|
||||
root->m_next = m_root_block;
|
||||
root->m_first_child = NULL;
|
||||
root->m_name = name;
|
||||
root->m_function = function;
|
||||
|
@ -111,7 +110,8 @@ namespace Lumix
|
|||
return;
|
||||
}
|
||||
ASSERT(m_current_block);
|
||||
m_current_block->m_hits.back().m_length = 1000.0f * (m_timer->getTimeSinceStart() - m_current_block->m_hits.back().m_start);
|
||||
float now = m_timer->getTimeSinceStart();
|
||||
m_current_block->m_hits.back().m_length = 1000.0f * (now - m_current_block->m_hits.back().m_start);
|
||||
m_current_block = m_current_block->m_parent;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace Lumix
|
|||
~Block();
|
||||
void frame();
|
||||
float getLength();
|
||||
int getHitCount() const { return m_hits.size(); }
|
||||
|
||||
public:
|
||||
Block* m_parent;
|
||||
|
|
|
@ -165,6 +165,15 @@ class base_string
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<>
|
||||
base_string<T, Allocator>& cat<float>(float value)
|
||||
{
|
||||
char tmp[40];
|
||||
toCString(value, tmp, 30, 10);
|
||||
*this += tmp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<>
|
||||
base_string<T, Allocator>& cat<char*>(char* value)
|
||||
{
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
|
||||
struct ClientMessageType
|
||||
{
|
||||
enum
|
||||
{
|
||||
POINTER_DOWN = 1,
|
||||
POINTER_MOVE,
|
||||
POINTER_UP,
|
||||
PROPERTY_SET,
|
||||
MOVE_CAMERA, // 5
|
||||
SAVE,
|
||||
LOAD,
|
||||
ADD_COMPONENT = 8,
|
||||
GET_PROPERTIES = 9,
|
||||
REMOVE_COMPONENT = 10,
|
||||
ADD_ENTITY, // 11
|
||||
TOGGLE_GAME_MODE, // 12
|
||||
GET_POSITION, // 13
|
||||
SET_POSITION, // 14
|
||||
REMOVE_ENTITY, // 15
|
||||
SET_EDIT_MODE, // 16
|
||||
EDIT_SCRIPT, // 17
|
||||
SET_WIREFRAME, // 18
|
||||
NEW_UNIVERSE = 19, // 19
|
||||
LOOK_AT_SELECTED = 20, // 20
|
||||
STOP_GAME_MODE, // 21
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
} // ~namespace Lumix
|
|
@ -1,236 +0,0 @@
|
|||
#include "editor_client.h"
|
||||
#include "core/array.h"
|
||||
#include "core/blob.h"
|
||||
#include "core/crc32.h"
|
||||
#include "core/fifo_allocator.h"
|
||||
#include "core/mt/lock_free_queue.h"
|
||||
#include "core/mt/mutex.h"
|
||||
#include "core/mt/task.h"
|
||||
#include "core/net/tcp_connector.h"
|
||||
#include "core/net/tcp_stream.h"
|
||||
#include "core/path.h"
|
||||
#include "core/profiler.h"
|
||||
#include "editor/client_message_types.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/server_message_types.h"
|
||||
#include "universe/universe.h"
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
struct EditorClientImpl
|
||||
{
|
||||
EditorClientImpl(EditorServer& server)
|
||||
: m_server(server)
|
||||
{}
|
||||
|
||||
void sendMessage(uint32_t type, const void* data, int32_t size);
|
||||
void onMessage(const uint8_t* data, int size);
|
||||
|
||||
Path m_base_path;
|
||||
EditorServer& m_server;
|
||||
DelegateList<void(EntityPositionEvent&)> m_entity_position_changed;
|
||||
DelegateList<void(EntitySelectedEvent&)> m_entity_selected;
|
||||
DelegateList <void(LogEvent&)> m_message_logged;
|
||||
DelegateList <void(PropertyListEvent&)> m_property_list_received;
|
||||
};
|
||||
|
||||
|
||||
bool EditorClient::create(const char* base_path, EditorServer& server)
|
||||
{
|
||||
m_impl = LUMIX_NEW(EditorClientImpl)(server);
|
||||
m_impl->m_base_path = base_path;
|
||||
return true;
|
||||
}
|
||||
|
||||
void EditorClient::destroy()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
LUMIX_DELETE(m_impl);
|
||||
m_impl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void EditorClient::onMessage(const uint8_t* data, int size)
|
||||
{
|
||||
if(m_impl)
|
||||
{
|
||||
m_impl->onMessage(data, size);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorClientImpl::onMessage(const uint8_t* data, int size)
|
||||
{
|
||||
Blob stream;
|
||||
stream.create(data, size);
|
||||
int32_t message_type;
|
||||
stream.read(message_type);
|
||||
switch(message_type)
|
||||
{
|
||||
case ServerMessageType::ENTITY_POSITION:
|
||||
{
|
||||
EntityPositionEvent msg;
|
||||
msg.read(stream);
|
||||
m_entity_position_changed.invoke(msg);
|
||||
}
|
||||
break;
|
||||
case ServerMessageType::ENTITY_SELECTED:
|
||||
{
|
||||
EntitySelectedEvent msg;
|
||||
msg.read(stream);
|
||||
m_entity_selected.invoke(msg);
|
||||
}
|
||||
break;
|
||||
case ServerMessageType::PROPERTY_LIST:
|
||||
{
|
||||
PropertyListEvent msg;
|
||||
msg.read(stream);
|
||||
m_property_list_received.invoke(msg);
|
||||
}
|
||||
break;
|
||||
case ServerMessageType::LOG_MESSAGE:
|
||||
{
|
||||
LogEvent msg;
|
||||
msg.read(stream);
|
||||
m_message_logged.invoke(msg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EditorClient::PropertyListCallback& EditorClient::propertyListReceived()
|
||||
{
|
||||
return m_impl->m_property_list_received;
|
||||
}
|
||||
|
||||
|
||||
EditorClient::EntitySelectedCallback& EditorClient::entitySelected()
|
||||
{
|
||||
return m_impl->m_entity_selected;
|
||||
}
|
||||
|
||||
EditorClient::EntityPositionCallback& EditorClient::entityPositionReceived()
|
||||
{
|
||||
return m_impl->m_entity_position_changed;
|
||||
}
|
||||
|
||||
void EditorClientImpl::sendMessage(uint32_t type, const void* data, int32_t size)
|
||||
{
|
||||
Blob stream;
|
||||
stream.write(&type, sizeof(type));
|
||||
if (data)
|
||||
{
|
||||
stream.write(data, size);
|
||||
}
|
||||
m_server.onMessage(stream.getBuffer(), stream.getBufferSize());
|
||||
}
|
||||
|
||||
|
||||
const char* EditorClient::getBasePath() const
|
||||
{
|
||||
return m_impl->m_base_path.c_str();
|
||||
}
|
||||
|
||||
|
||||
void EditorClient::lookAtSelected()
|
||||
{
|
||||
m_impl->sendMessage((uint32_t)ClientMessageType::LOOK_AT_SELECTED, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
void EditorClient::addComponent(uint32_t type)
|
||||
{
|
||||
m_impl->sendMessage((uint32_t)ClientMessageType::ADD_COMPONENT, &type, sizeof(type));
|
||||
}
|
||||
|
||||
void EditorClient::toggleGameMode()
|
||||
{
|
||||
m_impl->sendMessage((uint32_t)ClientMessageType::TOGGLE_GAME_MODE, NULL, 0);
|
||||
}
|
||||
|
||||
void EditorClient::addEntity()
|
||||
{
|
||||
m_impl->sendMessage((uint32_t)ClientMessageType::ADD_ENTITY, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
void EditorClient::mouseDown(int x, int y, int button)
|
||||
{
|
||||
int data[3] = {x, y, button};
|
||||
m_impl->sendMessage(ClientMessageType::POINTER_DOWN, data, 12);
|
||||
}
|
||||
|
||||
|
||||
void EditorClient::mouseUp(int x, int y, int button)
|
||||
{
|
||||
int data[3] = {x, y, button};
|
||||
m_impl->sendMessage(ClientMessageType::POINTER_UP, data, 12);
|
||||
}
|
||||
|
||||
|
||||
void EditorClient::mouseMove(int x, int y, int dx, int dy, int flags)
|
||||
{
|
||||
int data[] = {x, y, dx, dy, flags};
|
||||
m_impl->sendMessage(ClientMessageType::POINTER_MOVE, data, 20);
|
||||
|
||||
}
|
||||
|
||||
void EditorClient::loadUniverse(const char* path)
|
||||
{
|
||||
m_impl->sendMessage(ClientMessageType::LOAD, path, (int32_t)strlen(path)+1);
|
||||
}
|
||||
|
||||
void EditorClient::setWireframe(bool is_wireframe)
|
||||
{
|
||||
int32_t data = is_wireframe;
|
||||
m_impl->sendMessage(ClientMessageType::SET_WIREFRAME, &data, sizeof(data));
|
||||
}
|
||||
|
||||
void EditorClient::setEntityPosition(int32_t entity, const Vec3& position)
|
||||
{
|
||||
uint8_t data[sizeof(entity) + sizeof(position)];
|
||||
*(int32_t*)data = entity;
|
||||
*(Vec3*)(data + sizeof(entity)) = position;
|
||||
m_impl->sendMessage(ClientMessageType::SET_POSITION, data, sizeof(entity) + sizeof(position));
|
||||
}
|
||||
|
||||
void EditorClient::saveUniverse(const char* path)
|
||||
{
|
||||
m_impl->sendMessage(ClientMessageType::SAVE, path, (int32_t)strlen(path)+1);
|
||||
}
|
||||
|
||||
void EditorClient::navigate(float forward, float right, float speed)
|
||||
{
|
||||
uint8_t data[12];
|
||||
*(float*)data = forward;
|
||||
*(float*)(data + 4) = right;
|
||||
*(float*)(data + 8) = speed;
|
||||
m_impl->sendMessage(ClientMessageType::MOVE_CAMERA, data, 12);
|
||||
}
|
||||
|
||||
|
||||
void EditorClient::setComponentProperty(const char* component, const char* property, const void* value, int32_t length)
|
||||
{
|
||||
static Blob stream;
|
||||
stream.clearBuffer();
|
||||
uint32_t tmp = crc32(component);
|
||||
stream.write(&tmp, sizeof(tmp));
|
||||
tmp = crc32(property);
|
||||
stream.write(&tmp, sizeof(tmp));
|
||||
stream.write(&length, sizeof(length));
|
||||
stream.write(value, length);
|
||||
m_impl->sendMessage(ClientMessageType::PROPERTY_SET, stream.getBuffer(), stream.getBufferSize());
|
||||
}
|
||||
|
||||
|
||||
void EditorClient::requestProperties(uint32_t type_crc)
|
||||
{
|
||||
m_impl->sendMessage(ClientMessageType::GET_PROPERTIES, &type_crc, sizeof(type_crc));
|
||||
}
|
||||
|
||||
|
||||
} // ~namespace Lumix
|
|
@ -1,54 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
#include "core/lumix.h"
|
||||
#include "core/delegate_list.h"
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
class EditorServer;
|
||||
struct Entity;
|
||||
struct EntityPositionEvent;
|
||||
struct EntitySelectedEvent;
|
||||
struct PropertyListEvent;
|
||||
struct ServerMessage;
|
||||
struct Vec3;
|
||||
|
||||
class LUMIX_ENGINE_API EditorClient
|
||||
{
|
||||
public:
|
||||
typedef DelegateList<void(PropertyListEvent&)> PropertyListCallback;
|
||||
typedef DelegateList<void(EntitySelectedEvent&)> EntitySelectedCallback;
|
||||
typedef DelegateList<void(EntityPositionEvent&)> EntityPositionCallback;
|
||||
|
||||
public:
|
||||
EditorClient() { m_impl = NULL; }
|
||||
|
||||
bool create(const char* base_path, EditorServer& server);
|
||||
void destroy();
|
||||
void onMessage(const uint8_t* data, int size);
|
||||
void addEntity();
|
||||
void toggleGameMode();
|
||||
void lookAtSelected();
|
||||
void addComponent(uint32_t type);
|
||||
void mouseDown(int x, int y, int button);
|
||||
void mouseUp(int x, int y, int button);
|
||||
void mouseMove(int x, int y, int dx, int dy, int flags);
|
||||
void requestProperties(uint32_t type_crc);
|
||||
void setComponentProperty(const char* component, const char* property, const void* value, int32_t length);
|
||||
void navigate(float forward, float right, float speed);
|
||||
void loadUniverse(const char* path);
|
||||
void saveUniverse(const char* path);
|
||||
void setEntityPosition(int32_t entity, const Vec3& position);
|
||||
void setWireframe(bool is_wireframe);
|
||||
const char* getBasePath() const;
|
||||
PropertyListCallback& propertyListReceived();
|
||||
EntitySelectedCallback& entitySelected();
|
||||
EntityPositionCallback& entityPositionReceived();
|
||||
|
||||
private:
|
||||
struct EditorClientImpl* m_impl;
|
||||
};
|
||||
|
||||
} // ~namespace Lumix
|
File diff suppressed because it is too large
Load diff
|
@ -1,54 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/lumix.h"
|
||||
#include "core/delegate_list.h"
|
||||
#include "editor/property_descriptor.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
|
||||
class EditorClient;
|
||||
class Engine;
|
||||
class IPlugin;
|
||||
class IRenderDevice;
|
||||
namespace FS
|
||||
{
|
||||
class TCPFileServer;
|
||||
}
|
||||
|
||||
class LUMIX_ENGINE_API EditorServer
|
||||
{
|
||||
public:
|
||||
enum class MouseFlags : int
|
||||
{
|
||||
ALT = 1,
|
||||
CONTROL = 2
|
||||
};
|
||||
|
||||
public:
|
||||
EditorServer() { m_impl = 0; }
|
||||
|
||||
bool create(const char* base_path, EditorClient& client);
|
||||
void destroy();
|
||||
void onMessage(const uint8_t* data, int32_t size);
|
||||
void tick();
|
||||
void registerCreator(uint32_t type, IPlugin& creator);
|
||||
void registerProperty(const char* component_type, IPropertyDescriptor* descriptor);
|
||||
Engine& getEngine();
|
||||
void render(IRenderDevice& render_device);
|
||||
void renderIcons(IRenderDevice& render_device);
|
||||
Component getEditCamera() const;
|
||||
class Gizmo& getGizmo();
|
||||
class FS::TCPFileServer& getTCPFileServer();
|
||||
void setEditViewRenderDevice(IRenderDevice& render_device);
|
||||
DelegateList<void ()>& universeCreated();
|
||||
DelegateList<void ()>& universeDestroyed();
|
||||
|
||||
private:
|
||||
struct EditorServerImpl* m_impl;
|
||||
};
|
||||
|
||||
|
||||
}
|
211
src/editor/entity_template_system.cpp
Normal file
211
src/editor/entity_template_system.cpp
Normal file
|
@ -0,0 +1,211 @@
|
|||
#include "entity_template_system.h"
|
||||
#include "core/array.h"
|
||||
#include "core/crc32.h"
|
||||
#include "core/iserializer.h"
|
||||
#include "core/map.h"
|
||||
#include "core/string.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "engine/engine.h"
|
||||
#include "universe/entity.h"
|
||||
#include "universe/universe.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
|
||||
class EntityTemplateSystemImpl : public EntityTemplateSystem
|
||||
{
|
||||
public:
|
||||
EntityTemplateSystemImpl(WorldEditor& editor)
|
||||
: m_editor(editor)
|
||||
{
|
||||
m_universe = editor.getEngine().getUniverse();
|
||||
editor.universeCreated().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseCreated>(this);
|
||||
editor.universeDestroyed().bind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseDestroyed>(this);
|
||||
}
|
||||
|
||||
|
||||
~EntityTemplateSystemImpl()
|
||||
{
|
||||
m_editor.universeCreated().unbind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseCreated>(this);
|
||||
m_editor.universeDestroyed().unbind<EntityTemplateSystemImpl, &EntityTemplateSystemImpl::onUniverseDestroyed>(this);
|
||||
}
|
||||
|
||||
|
||||
void onUniverseCreated()
|
||||
{
|
||||
m_instances.clear();
|
||||
m_template_names.clear();
|
||||
m_universe = m_editor.getEngine().getUniverse();
|
||||
}
|
||||
|
||||
|
||||
void onUniverseDestroyed()
|
||||
{
|
||||
m_instances.clear();
|
||||
m_template_names.clear();
|
||||
m_universe = NULL;
|
||||
}
|
||||
|
||||
|
||||
virtual void createTemplateFromEntity(const char* name, const Entity& entity) override
|
||||
{
|
||||
uint32_t name_hash = crc32(name);
|
||||
if (m_instances.find(name_hash) == m_instances.end())
|
||||
{
|
||||
m_template_names.push(string(name));
|
||||
m_instances[name_hash].push(entity);
|
||||
m_updated.invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual uint32_t getTemplate(const Entity& entity) override
|
||||
{
|
||||
for (auto iter = m_instances.begin(), end = m_instances.end(); iter != end; ++iter)
|
||||
{
|
||||
Array<Entity>& entities = iter.second();
|
||||
for (int i = 0, c = entities.size(); i < c; ++i)
|
||||
{
|
||||
if (entities[i] == entity)
|
||||
{
|
||||
return iter.first();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
virtual const Array<Entity>& getInstances(uint32_t template_name_hash) override
|
||||
{
|
||||
return m_instances[template_name_hash];
|
||||
}
|
||||
|
||||
|
||||
virtual Entity createInstance(const char* name) override
|
||||
{
|
||||
uint32_t name_hash = crc32(name);
|
||||
Map<uint32_t, Array<Entity> >::iterator iter = m_instances.find(name_hash);
|
||||
if (iter == m_instances.end())
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void serialize(ISerializer& serializer) override
|
||||
{
|
||||
serializer.serialize("templates_count", (int32_t)m_template_names.size());
|
||||
serializer.beginArray("template_names");
|
||||
for (int i = 0, c = m_template_names.size(); i < c; ++i)
|
||||
{
|
||||
serializer.serializeArrayItem(m_template_names[i].c_str());
|
||||
}
|
||||
serializer.endArray();
|
||||
serializer.serialize("instance_count", (int32_t)m_instances.size());
|
||||
serializer.beginArray("instances");
|
||||
for (auto i = m_instances.begin(), end = m_instances.end(); i != end; ++i)
|
||||
{
|
||||
serializer.serializeArrayItem(i.first());
|
||||
serializer.serializeArrayItem((int32_t)i.second().size());
|
||||
for (int j = 0, c = i.second().size(); j < c; ++j)
|
||||
{
|
||||
serializer.serializeArrayItem(i.second()[j].index);
|
||||
}
|
||||
}
|
||||
serializer.endArray();
|
||||
|
||||
}
|
||||
|
||||
|
||||
virtual void deserialize(ISerializer& serializer) override
|
||||
{
|
||||
m_template_names.clear();
|
||||
m_instances.clear();
|
||||
int32_t count;
|
||||
serializer.deserialize("templates_count", count);
|
||||
serializer.deserializeArrayBegin("template_names");
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
const int MAX_NAME_LENGTH = 50;
|
||||
char name[MAX_NAME_LENGTH];
|
||||
serializer.deserializeArrayItem(name, MAX_NAME_LENGTH);
|
||||
m_template_names.push(string(name));
|
||||
}
|
||||
serializer.deserializeArrayEnd();
|
||||
serializer.deserialize("instance_count", count);
|
||||
serializer.deserializeArrayBegin("instances");
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
uint32_t hash;
|
||||
serializer.deserializeArrayItem(hash);
|
||||
int32_t instances_per_template;
|
||||
serializer.deserializeArrayItem(instances_per_template);
|
||||
m_instances.insert(hash, Array<Entity>());
|
||||
Array<Entity>& entities = m_instances[hash];
|
||||
for (int j = 0; j < instances_per_template; ++j)
|
||||
{
|
||||
int32_t entity_index;
|
||||
serializer.deserializeArrayItem(entity_index);
|
||||
entities.push(Entity(m_universe, entity_index));
|
||||
}
|
||||
}
|
||||
serializer.deserializeArrayEnd();
|
||||
m_updated.invoke();
|
||||
}
|
||||
|
||||
|
||||
virtual Array<string>& getTemplateNames() override
|
||||
{
|
||||
return m_template_names;
|
||||
}
|
||||
|
||||
|
||||
virtual DelegateList<void()>& updated() override
|
||||
{
|
||||
return m_updated;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Map<uint32_t, Array<Entity> > m_instances;
|
||||
Array<string> m_template_names;
|
||||
Universe* m_universe;
|
||||
WorldEditor& m_editor;
|
||||
DelegateList<void()> m_updated;
|
||||
|
||||
}; // class EntityTemplateSystemImpl
|
||||
|
||||
|
||||
EntityTemplateSystem* EntityTemplateSystem::create(WorldEditor& editor)
|
||||
{
|
||||
return LUMIX_NEW(EntityTemplateSystemImpl)(editor);
|
||||
}
|
||||
|
||||
|
||||
void EntityTemplateSystem::destroy(EntityTemplateSystem* system)
|
||||
{
|
||||
LUMIX_DELETE(system);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Lumix
|
35
src/editor/entity_template_system.h
Normal file
35
src/editor/entity_template_system.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
#include "core/lumix.h"
|
||||
#include "core/delegate_list.h"
|
||||
#include "core/string.h"
|
||||
#include "universe/entity.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
class ISerializer;
|
||||
class WorldEditor;
|
||||
|
||||
class LUMIX_ENGINE_API EntityTemplateSystem
|
||||
{
|
||||
public:
|
||||
static EntityTemplateSystem* create(WorldEditor& editor);
|
||||
static void destroy(EntityTemplateSystem* system);
|
||||
|
||||
virtual ~EntityTemplateSystem() {}
|
||||
virtual void serialize(ISerializer& serializer) = 0;
|
||||
virtual void deserialize(ISerializer& serializer) = 0;
|
||||
virtual void createTemplateFromEntity(const char* name, const Entity& entity) = 0;
|
||||
virtual uint32_t getTemplate(const Entity& entity) = 0;
|
||||
virtual const Array<Entity>& getInstances(uint32_t template_name_hash) = 0;
|
||||
virtual class Array<string>& getTemplateNames() = 0;
|
||||
virtual Entity createInstance(const char* name) = 0;
|
||||
|
||||
virtual DelegateList<void()>& updated() = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Lumix
|
|
@ -7,6 +7,7 @@
|
|||
#include "core/resource_manager.h"
|
||||
#include "core/resource_manager_base.h"
|
||||
#include "editor/gizmo.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "engine/engine.h"
|
||||
#include "graphics/irender_device.h"
|
||||
#include "graphics/model.h"
|
||||
|
@ -18,7 +19,8 @@ namespace Lumix
|
|||
{
|
||||
|
||||
|
||||
Gizmo::Gizmo()
|
||||
Gizmo::Gizmo(WorldEditor& editor)
|
||||
: m_editor(editor)
|
||||
{
|
||||
m_model = NULL;
|
||||
m_selected_entity.index = -1;
|
||||
|
@ -178,8 +180,9 @@ void Gizmo::transform(Component camera, TransformOperation operation, int x, int
|
|||
{
|
||||
angle = (relx + rely) / 100.0f;
|
||||
}
|
||||
m_selected_entity.setRotation(m_selected_entity.getRotation() * Quat(axis, angle));
|
||||
m_selected_entity.setPosition(pos);
|
||||
Quat new_rot = m_selected_entity.getRotation() * Quat(axis, angle);
|
||||
new_rot.normalize();
|
||||
m_editor.setEntityPositionAndRotaion(m_selected_entity, pos, new_rot);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -188,7 +191,7 @@ void Gizmo::transform(Component camera, TransformOperation operation, int x, int
|
|||
m_transform_point = intersection;
|
||||
Vec3 pos = m_selected_entity.getPosition();
|
||||
pos += delta;
|
||||
m_selected_entity.setPosition(pos);
|
||||
m_editor.setEntityPosition(m_selected_entity, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ class IRenderDevice;
|
|||
struct Matrix;
|
||||
class Renderer;
|
||||
class Universe;
|
||||
class WorldEditor;
|
||||
|
||||
|
||||
class LUMIX_ENGINE_API Gizmo
|
||||
|
@ -73,7 +74,7 @@ class LUMIX_ENGINE_API Gizmo
|
|||
};
|
||||
|
||||
public:
|
||||
Gizmo();
|
||||
Gizmo(WorldEditor& editor);
|
||||
~Gizmo();
|
||||
|
||||
void create(Renderer& renderer);
|
||||
|
@ -93,6 +94,7 @@ class LUMIX_ENGINE_API Gizmo
|
|||
Vec3 getMousePlaneIntersection(Component camera, int x, int y);
|
||||
|
||||
private:
|
||||
WorldEditor& m_editor;
|
||||
Renderer* m_renderer;
|
||||
Entity m_selected_entity;
|
||||
Universe* m_universe;
|
||||
|
|
18
src/editor/ieditor_command.h
Normal file
18
src/editor/ieditor_command.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
|
||||
class IEditorCommand
|
||||
{
|
||||
public:
|
||||
virtual void execute() = 0;
|
||||
virtual void undo() = 0;
|
||||
virtual uint32_t getType() = 0;
|
||||
virtual bool merge(IEditorCommand& command) = 0;
|
||||
};
|
||||
|
||||
|
||||
} // namespace Lumix
|
|
@ -89,8 +89,7 @@ class PropertyDescriptor : public IPropertyDescriptor
|
|||
template <class S>
|
||||
void PropertyDescriptor<S>::set(Component cmp, Blob& stream) const
|
||||
{
|
||||
int len;
|
||||
stream.read(&len, sizeof(len));
|
||||
int len = stream.getBufferSize();
|
||||
switch(m_type)
|
||||
{
|
||||
case DECIMAL:
|
||||
|
@ -151,7 +150,6 @@ void PropertyDescriptor<S>::get(Component cmp, Blob& stream) const
|
|||
string value;
|
||||
(static_cast<S*>(cmp.system)->*m_getter)(cmp, value);
|
||||
len = value.length() + 1;
|
||||
stream.write(&len, sizeof(len));
|
||||
stream.write(value.c_str(), len);
|
||||
}
|
||||
break;
|
||||
|
@ -160,7 +158,6 @@ void PropertyDescriptor<S>::get(Component cmp, Blob& stream) const
|
|||
float f;
|
||||
(static_cast<S*>(cmp.system)->*m_decimal_getter)(cmp, f);
|
||||
len = sizeof(f);
|
||||
stream.write(&len, sizeof(len));
|
||||
stream.write(&f, len);
|
||||
}
|
||||
break;
|
||||
|
@ -169,7 +166,6 @@ void PropertyDescriptor<S>::get(Component cmp, Blob& stream) const
|
|||
int32_t i;
|
||||
(static_cast<S*>(cmp.system)->*m_integer_getter)(cmp, i);
|
||||
len = sizeof(i);
|
||||
stream.write(&len, sizeof(len));
|
||||
stream.write(&i, len);
|
||||
}
|
||||
break;
|
||||
|
@ -178,7 +174,6 @@ void PropertyDescriptor<S>::get(Component cmp, Blob& stream) const
|
|||
bool b;
|
||||
(static_cast<S*>(cmp.system)->*m_bool_getter)(cmp, b);
|
||||
len = sizeof(b);
|
||||
stream.write(&len, sizeof(len));
|
||||
stream.write(&b, len);
|
||||
}
|
||||
break;
|
||||
|
@ -187,7 +182,6 @@ void PropertyDescriptor<S>::get(Component cmp, Blob& stream) const
|
|||
Vec3 v;
|
||||
(static_cast<S*>(cmp.system)->*m_vec3_getter)(cmp, v);
|
||||
len = sizeof(v);
|
||||
stream.write(&len, sizeof(len));
|
||||
stream.write(&v, len);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
#include "server_message_types.h"
|
||||
#include "core/blob.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
|
||||
void EntityPositionEvent::read(Blob& stream)
|
||||
{
|
||||
stream.read(&index, sizeof(index));
|
||||
stream.read(&x, sizeof(x));
|
||||
stream.read(&y, sizeof(y));
|
||||
stream.read(&z, sizeof(z));
|
||||
}
|
||||
|
||||
|
||||
void EntitySelectedEvent::read(Blob& stream)
|
||||
{
|
||||
stream.read(&index, sizeof(index));
|
||||
int32_t count;
|
||||
stream.read(&count, sizeof(count));
|
||||
components.resize(count);
|
||||
for(int i = 0; i < count; ++i)
|
||||
{
|
||||
stream.read(&components[i], sizeof(components[i]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LogEvent::read(Blob& stream)
|
||||
{
|
||||
stream.read(&type, sizeof(type));
|
||||
int32_t len;
|
||||
stream.read(&len, sizeof(len));
|
||||
char tmp[255];
|
||||
if(len < 255)
|
||||
{
|
||||
stream.read(tmp, len);
|
||||
tmp[len] = 0;
|
||||
}
|
||||
system = tmp;
|
||||
stream.read(&len, sizeof(len));
|
||||
if(len < 255)
|
||||
{
|
||||
stream.read(tmp, len);
|
||||
tmp[len] = 0;
|
||||
message = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* buf = LUMIX_NEW_ARRAY(char, len+1);
|
||||
stream.read(buf, len);
|
||||
buf[len] = 0;
|
||||
message = buf;
|
||||
LUMIX_DELETE_ARRAY(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PropertyListEvent::read(Blob& stream)
|
||||
{
|
||||
int32_t count;
|
||||
stream.read(&count, sizeof(count));
|
||||
properties.resize(count);
|
||||
stream.read(&type_hash, sizeof(type_hash));
|
||||
for(int i = 0; i < count; ++i)
|
||||
{
|
||||
stream.read(&properties[i].name_hash, sizeof(properties[i].name_hash));
|
||||
stream.read(&properties[i].data_size, sizeof(properties[i].data_size));
|
||||
properties[i].data = LUMIX_NEW_ARRAY(uint8_t, properties[i].data_size);
|
||||
stream.read(properties[i].data, properties[i].data_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // ~namespace Lumix
|
|
@ -1,76 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
#include "core/map.h"
|
||||
#include "core/array.h"
|
||||
#include "core/string.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
|
||||
class Blob;
|
||||
|
||||
|
||||
struct ServerMessageType
|
||||
{
|
||||
enum Value
|
||||
{
|
||||
ENTITY_SELECTED = 1,
|
||||
PROPERTY_LIST = 2,
|
||||
ENTITY_POSITION = 3,
|
||||
LOG_MESSAGE = 4,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
struct LUMIX_ENGINE_API EntityPositionEvent
|
||||
{
|
||||
void read(Blob& stream);
|
||||
|
||||
int32_t index;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
|
||||
|
||||
struct LUMIX_ENGINE_API EntitySelectedEvent
|
||||
{
|
||||
void read(Blob& stream);
|
||||
|
||||
int32_t index;
|
||||
Array<uint32_t> components;
|
||||
};
|
||||
|
||||
|
||||
struct LUMIX_ENGINE_API LogEvent
|
||||
{
|
||||
void read(Blob& stream);
|
||||
|
||||
int32_t type;
|
||||
string message;
|
||||
string system;
|
||||
};
|
||||
|
||||
|
||||
struct LUMIX_ENGINE_API PropertyListEvent
|
||||
{
|
||||
struct Property
|
||||
{
|
||||
Property() { data = NULL; }
|
||||
~Property() { LUMIX_DELETE_ARRAY(data); }
|
||||
uint32_t name_hash;
|
||||
void* data;
|
||||
int32_t data_size;
|
||||
};
|
||||
|
||||
void read(Blob& stream);
|
||||
|
||||
uint32_t type_hash;
|
||||
Array<Property> properties;
|
||||
};
|
||||
|
||||
|
||||
} // ~namespace Lumix
|
1457
src/editor/world_editor.cpp
Normal file
1457
src/editor/world_editor.cpp
Normal file
File diff suppressed because it is too large
Load diff
106
src/editor/world_editor.h
Normal file
106
src/editor/world_editor.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
#pragma once
|
||||
|
||||
#include "core/lumix.h"
|
||||
#include "core/delegate_list.h"
|
||||
#include "editor/property_descriptor.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
class Engine;
|
||||
class EntityTemplateSystem;
|
||||
class IPlugin;
|
||||
class IRenderDevice;
|
||||
class Path;
|
||||
class RayCastModelHit;
|
||||
namespace FS
|
||||
{
|
||||
class TCPFileServer;
|
||||
}
|
||||
|
||||
struct MouseButton
|
||||
{
|
||||
enum Value
|
||||
{
|
||||
LEFT,
|
||||
MIDDLE,
|
||||
RIGHT
|
||||
};
|
||||
};
|
||||
|
||||
class LUMIX_ENGINE_API WorldEditor
|
||||
{
|
||||
public:
|
||||
enum class MouseFlags : int
|
||||
{
|
||||
ALT = 1,
|
||||
CONTROL = 2
|
||||
};
|
||||
|
||||
class Plugin
|
||||
{
|
||||
public:
|
||||
virtual ~Plugin() {}
|
||||
|
||||
virtual void tick() = 0;
|
||||
virtual bool onEntityMouseDown(const RayCastModelHit& hit, int x, int y) = 0;
|
||||
virtual void onMouseMove(int x, int y, int rel_x, int rel_y, int mouse_flags) = 0;
|
||||
virtual void onMouseUp(int x, int y, MouseButton::Value button) = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
static WorldEditor* create(const char* base_path);
|
||||
static void destroy(WorldEditor* server);
|
||||
|
||||
virtual void tick() = 0;
|
||||
virtual void registerCreator(uint32_t type, IPlugin& creator) = 0;
|
||||
virtual void registerProperty(const char* component_type, IPropertyDescriptor* descriptor) = 0;
|
||||
virtual Engine& getEngine() = 0;
|
||||
virtual void render(IRenderDevice& render_device) = 0;
|
||||
virtual void renderIcons(IRenderDevice& render_device) = 0;
|
||||
virtual Component getEditCamera() const = 0;
|
||||
virtual class Gizmo& getGizmo() = 0;
|
||||
virtual class FS::TCPFileServer& getTCPFileServer() = 0;
|
||||
virtual void setEditViewRenderDevice(IRenderDevice& render_device) = 0;
|
||||
virtual void undo() = 0;
|
||||
virtual void redo() = 0;
|
||||
virtual void loadUniverse(const Path& path) = 0;
|
||||
virtual void saveUniverse(const Path& path) = 0;
|
||||
virtual void newUniverse() = 0;
|
||||
virtual Path getUniversePath() const = 0;
|
||||
virtual void addComponent(uint32_t type_crc) = 0;
|
||||
virtual void cloneComponent(const Component& src, Entity& entity) = 0;
|
||||
virtual void removeComponent(const Component& crc) = 0;
|
||||
virtual Entity addEntity() = 0;
|
||||
virtual void selectEntity(Entity e) = 0;
|
||||
virtual Entity addEntityAt(int camera_x, int camera_y) = 0;
|
||||
virtual void setEntityPosition(const Entity& entity, const Vec3& position) = 0;
|
||||
virtual void setEntityPositionAndRotaion(const Entity& entity, const Vec3& position, const Quat& rotation) = 0;
|
||||
virtual void snapToTerrain() = 0;
|
||||
virtual void toggleGameMode() = 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 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 onMouseUp(int x, int y, MouseButton::Value button) = 0;
|
||||
virtual float getMouseX() const = 0;
|
||||
virtual float getMouseY() const = 0;
|
||||
virtual void setWireframe(bool is_wireframe) = 0;
|
||||
virtual void lookAtSelected() = 0;
|
||||
virtual const char* getBasePath() = 0;
|
||||
virtual Entity getSelectedEntity() const = 0;
|
||||
virtual const IPropertyDescriptor& getPropertyDescriptor(uint32_t type, uint32_t name_hash) = 0;
|
||||
virtual DelegateList<void(Entity&)>& entitySelected() = 0;
|
||||
virtual DelegateList<void()>& universeCreated() = 0;
|
||||
virtual DelegateList<void()>& universeDestroyed() = 0;
|
||||
virtual void addPlugin(Plugin* plugin) = 0;
|
||||
virtual void getRelativePath(char* relative_path, int max_length, const Path& source) = 0;
|
||||
virtual EntityTemplateSystem& getEntityTemplateSystem() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~WorldEditor() {}
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -56,7 +56,7 @@ namespace Lumix
|
|||
// CullingSystem* m_culling_system;
|
||||
|
||||
string m_base_path;
|
||||
EditorServer* m_editor_server;
|
||||
WorldEditor* m_editor_server;
|
||||
PluginManager m_plugin_manager;
|
||||
Universe* m_universe;
|
||||
RenderScene* m_render_scene;
|
||||
|
@ -113,7 +113,7 @@ namespace Lumix
|
|||
{
|
||||
return false;
|
||||
}
|
||||
AnimationSystem* anim_system = LUMIX_NEW(AnimationSystem)();
|
||||
AnimationSystem* anim_system = AnimationSystem::createInstance();
|
||||
if(!anim_system->create(owner))
|
||||
{
|
||||
LUMIX_DELETE(anim_system);
|
||||
|
@ -128,7 +128,7 @@ namespace Lumix
|
|||
}
|
||||
|
||||
|
||||
bool Engine::create(const char* base_path, FS::FileSystem* file_system, EditorServer* editor_server)
|
||||
bool Engine::create(const char* base_path, FS::FileSystem* file_system, WorldEditor* editor_server)
|
||||
{
|
||||
g_log_info.getCallback().bind<showLogInVS>();
|
||||
g_log_warning.getCallback().bind<showLogInVS>();
|
||||
|
@ -222,7 +222,7 @@ namespace Lumix
|
|||
}
|
||||
}
|
||||
|
||||
EditorServer* Engine::getEditorServer() const
|
||||
WorldEditor* Engine::getWorldEditor() const
|
||||
{
|
||||
return m_impl->m_editor_server;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Lumix
|
|||
class FileSystem;
|
||||
}
|
||||
|
||||
class WorldEditor;
|
||||
namespace MTJD
|
||||
{
|
||||
class Manager;
|
||||
|
@ -31,13 +32,13 @@ namespace Lumix
|
|||
Engine() { m_impl = NULL; }
|
||||
~Engine() { ASSERT(m_impl == NULL); }
|
||||
|
||||
bool create(const char* base_path, FS::FileSystem* fs, EditorServer* editor_server);
|
||||
bool create(const char* base_path, FS::FileSystem* fs, WorldEditor* editor_server);
|
||||
void destroy();
|
||||
|
||||
Universe* createUniverse();
|
||||
void destroyUniverse();
|
||||
|
||||
EditorServer* getEditorServer() const;
|
||||
WorldEditor* getWorldEditor() const;
|
||||
FS::FileSystem& getFileSystem();
|
||||
Renderer& getRenderer();
|
||||
InputSystem& getInputSystem();
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace Lumix
|
|||
virtual void deserialize(ISerializer&) {}
|
||||
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 void sendMessage(const char*) {};
|
||||
};
|
||||
|
|
|
@ -28,8 +28,8 @@ FrameBuffer::FrameBuffer(int width, int height, int render_buffers, const char*
|
|||
|
||||
glBindTexture(GL_TEXTURE_2D, m_textures[DEPTH]);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[DEPTH], 0);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "graphics/geometry.h"
|
||||
#include "core/profiler.h"
|
||||
#include "graphics/gl_ext.h"
|
||||
#include "graphics/shader.h"
|
||||
|
||||
|
@ -34,11 +35,16 @@ void VertexDef::parse(const char* data, int size)
|
|||
break;
|
||||
case 'i':
|
||||
++i;
|
||||
if(data[i] == '4')
|
||||
if (data[i] == '4')
|
||||
{
|
||||
m_attributes[index] = VertexAttributeDef::INT4;
|
||||
m_vertex_size += 4 * sizeof(int);
|
||||
}
|
||||
else if (data[i] == '1')
|
||||
{
|
||||
m_attributes[index] = VertexAttributeDef::INT1;
|
||||
m_vertex_size += sizeof(int);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(false);
|
||||
|
@ -83,6 +89,9 @@ int VertexDef::getPositionOffset() const
|
|||
case VertexAttributeDef::INT4:
|
||||
offset += 4 * sizeof(int);
|
||||
break;
|
||||
case VertexAttributeDef::INT1:
|
||||
offset += sizeof(int);
|
||||
break;
|
||||
case VertexAttributeDef::POSITION:
|
||||
return offset;
|
||||
break;
|
||||
|
@ -103,6 +112,7 @@ int VertexDef::getPositionOffset() const
|
|||
|
||||
void VertexDef::begin(Shader& shader)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
int offset = 0;
|
||||
int shader_attrib_idx = 0;
|
||||
for(int i = 0; i < m_attribute_count; ++i)
|
||||
|
@ -142,6 +152,12 @@ void VertexDef::begin(Shader& shader)
|
|||
offset += sizeof(GLint) * 4;
|
||||
++shader_attrib_idx;
|
||||
break;
|
||||
case VertexAttributeDef::INT1:
|
||||
glEnableVertexAttribArray(shader.getAttribId(shader_attrib_idx));
|
||||
glVertexAttribPointer(shader.getAttribId(shader_attrib_idx), 1, GL_INT, GL_FALSE, m_vertex_size, (GLvoid*)offset);
|
||||
offset += sizeof(GLint) * 1;
|
||||
++shader_attrib_idx;
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
break;
|
||||
|
@ -153,6 +169,7 @@ void VertexDef::begin(Shader& shader)
|
|||
|
||||
void VertexDef::end(Shader& shader)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
int shader_attrib_idx = 0;
|
||||
for(int i = 0; i < m_attribute_count; ++i)
|
||||
{
|
||||
|
@ -167,6 +184,7 @@ void VertexDef::end(Shader& shader)
|
|||
case VertexAttributeDef::TEXTURE_COORDS:
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
break;
|
||||
case VertexAttributeDef::INT1:
|
||||
case VertexAttributeDef::INT4:
|
||||
case VertexAttributeDef::FLOAT4:
|
||||
case VertexAttributeDef::FLOAT2:
|
||||
|
@ -199,6 +217,7 @@ 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);
|
||||
|
@ -221,6 +240,48 @@ Geometry::~Geometry()
|
|||
}
|
||||
|
||||
|
||||
void Geometry::copy(const Geometry& source, int times, VertexCallback& vertex_callback, IndexCallback& index_callback)
|
||||
{
|
||||
ASSERT(!source.m_indices.empty());
|
||||
m_vertex_definition = source.m_vertex_definition;
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, source.m_id);
|
||||
uint8_t* data = (uint8_t*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
|
||||
Array<uint8_t> data_copy;
|
||||
int vertex_size = m_vertex_definition.getVertexSize();
|
||||
int one_size = vertex_size * source.getVertices().size();
|
||||
data_copy.resize(one_size * times);
|
||||
for (int i = 0; i < times; ++i)
|
||||
{
|
||||
memcpy(&data_copy[i * one_size], data, one_size);
|
||||
}
|
||||
vertex_callback.invoke(data_copy);
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, source.m_indices_id);
|
||||
data = (uint8_t*)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY);
|
||||
Array<int> indices_data_copy;
|
||||
int indices_count = source.getIndices().size();
|
||||
indices_data_copy.resize(indices_count * times);
|
||||
for (int i = 0; i < times; ++i)
|
||||
{
|
||||
memcpy(&indices_data_copy[i * indices_count], data, sizeof(int) * indices_count);
|
||||
}
|
||||
index_callback.invoke(indices_data_copy);
|
||||
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_id);
|
||||
glBufferData(GL_ARRAY_BUFFER, data_copy.size() * sizeof(data_copy[0]), &data_copy[0], GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indices_id);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_data_copy.size() * sizeof(indices_data_copy[0]), &indices_data_copy[0], GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
|
||||
void Geometry::copy(const uint8_t* data, int size, const Array<int32_t>& indices, VertexDef vertex_definition)
|
||||
{
|
||||
m_vertex_definition = vertex_definition;
|
||||
|
@ -236,7 +297,6 @@ void Geometry::copy(const uint8_t* data, int size, const Array<int32_t>& indices
|
|||
{
|
||||
m_indices[i] = indices[i];
|
||||
}
|
||||
m_indices_count = indices.size();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_id);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "core/array.h"
|
||||
#include "core/delegate.h"
|
||||
#include "core/vec3.h"
|
||||
#include "graphics/gl_ext.h"
|
||||
|
||||
|
@ -18,6 +19,7 @@ struct VertexAttributeDef
|
|||
FLOAT4,
|
||||
FLOAT2,
|
||||
INT4,
|
||||
INT1,
|
||||
POSITION,
|
||||
NORMAL,
|
||||
TEXTURE_COORDS,
|
||||
|
@ -34,6 +36,7 @@ struct VertexDef
|
|||
int getPositionOffset() const;
|
||||
void begin(Shader& shader);
|
||||
void end(Shader& shader);
|
||||
VertexAttributeDef::Type getAttributeType(int i) const { return i < m_attribute_count ? m_attributes[i] : VertexAttributeDef::NONE; }
|
||||
|
||||
private:
|
||||
VertexAttributeDef::Type m_attributes[16];
|
||||
|
@ -45,15 +48,21 @@ struct VertexDef
|
|||
|
||||
class Geometry
|
||||
{
|
||||
public:
|
||||
typedef Delegate<void(Array<uint8_t>&)> VertexCallback;
|
||||
typedef Delegate<void(Array<int>&)> IndexCallback;
|
||||
|
||||
public:
|
||||
Geometry();
|
||||
~Geometry();
|
||||
|
||||
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 draw(int start, int count, Shader& shader);
|
||||
const Array<Vec3>& getVertices() const { return m_vertices; }
|
||||
const Array<int32_t>& getIndices() const { return m_indices; }
|
||||
float getBoundingRadius() const;
|
||||
const VertexDef& getVertexDefinition() const { return m_vertex_definition; }
|
||||
|
||||
private:
|
||||
GLuint m_id;
|
||||
|
@ -61,7 +70,6 @@ class Geometry
|
|||
VertexDef m_vertex_definition;
|
||||
Array<Vec3> m_vertices;
|
||||
Array<int32_t> m_indices;
|
||||
int m_indices_count;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
#define GLEW_STATIC
|
||||
#include <gl/glew.h>
|
||||
#include <gl/GL.h>
|
||||
#include <gl/wglew.h>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/json_serializer.h"
|
||||
#include "core/log.h"
|
||||
#include "core/path_utils.h"
|
||||
#include "core/profiler.h"
|
||||
#include "core/resource_manager.h"
|
||||
#include "core/resource_manager_base.h"
|
||||
#include "core/timer.h"
|
||||
|
@ -48,6 +49,7 @@ void Material::apply(Renderer& renderer, PipelineInstance& pipeline)
|
|||
{
|
||||
m_textures[i]->apply(i);
|
||||
}
|
||||
renderer.enableAlphaToCoverage(m_is_alpha_to_coverage);
|
||||
renderer.enableZTest(m_is_z_test);
|
||||
for (int i = 0, c = m_uniforms.size(); i < c; ++i)
|
||||
{
|
||||
|
@ -226,6 +228,7 @@ void Material::setShader(Shader* shader)
|
|||
|
||||
void Material::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
if(success)
|
||||
{
|
||||
JsonSerializer serializer(*file, JsonSerializer::READ, m_path.c_str());
|
||||
|
@ -241,7 +244,7 @@ void Material::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
|||
{
|
||||
deserializeUniforms(serializer);
|
||||
}
|
||||
else if (strcmp(label, "texture") == 0 || strcmp(label, "heightmap") == 0)
|
||||
else if (strcmp(label, "texture") == 0 || strcmp(label, "heightmap") == 0 || strcmp(label, "splatmap") == 0)
|
||||
{
|
||||
serializer.deserialize(path, MAX_PATH);
|
||||
if (path[0] != '\0')
|
||||
|
@ -251,6 +254,7 @@ void Material::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
|||
texture_path += path;
|
||||
Texture* texture = static_cast<Texture*>(m_resource_manager.get(ResourceManager::TEXTURE)->load(texture_path.c_str()));
|
||||
bool is_heightmap = label[0] == 'h';
|
||||
bool is_splatmap = label[0] == 's';
|
||||
if (is_heightmap)
|
||||
{
|
||||
if (!m_textures.empty())
|
||||
|
@ -260,9 +264,12 @@ void Material::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
|||
fs.close(file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (is_heightmap || is_splatmap)
|
||||
{
|
||||
if (texture->isReady() && !texture->getData())
|
||||
{
|
||||
g_log_error.log("Renderer") << "Heightmap " << m_path.c_str() << " can not be used as an ordinary texture";
|
||||
g_log_error.log("Renderer") << (is_heightmap ? "Heightmap " : "Splatmap ") << m_path.c_str() << " can not be used as an ordinary texture";
|
||||
onFailure();
|
||||
fs.close(file);
|
||||
return;
|
||||
|
@ -273,6 +280,10 @@ void Material::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
|||
addDependency(*texture);
|
||||
}
|
||||
}
|
||||
else if (strcmp(label, "alpha_to_coverage") == 0)
|
||||
{
|
||||
serializer.deserialize(m_is_alpha_to_coverage);
|
||||
}
|
||||
else if (strcmp(label, "shader") == 0)
|
||||
{
|
||||
serializer.deserialize(path, MAX_PATH);
|
||||
|
|
|
@ -37,6 +37,8 @@ public:
|
|||
void enableZTest(bool enable) { m_is_z_test = enable; }
|
||||
bool isBackfaceCulling() const { return m_is_backface_culling; }
|
||||
void enableBackfaceCulling(bool enable) { m_is_backface_culling = enable; }
|
||||
bool isAlphaToCoverage() const { return m_is_alpha_to_coverage; }
|
||||
void enableAlphaToCoverage(bool enable) { m_is_alpha_to_coverage = enable; }
|
||||
|
||||
void setShader(Shader* shader);
|
||||
Shader* getShader() const { return m_shader; }
|
||||
|
@ -54,6 +56,7 @@ private:
|
|||
, m_is_z_test(true)
|
||||
, m_is_backface_culling(true)
|
||||
, m_depth_func(DepthFunc::LESS)
|
||||
, m_is_alpha_to_coverage(false)
|
||||
{ }
|
||||
|
||||
~Material();
|
||||
|
@ -94,6 +97,7 @@ private:
|
|||
Array<Uniform> m_uniforms;
|
||||
bool m_is_z_test;
|
||||
bool m_is_backface_culling;
|
||||
bool m_is_alpha_to_coverage;
|
||||
DepthFunc m_depth_func;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/fs/ifile.h"
|
||||
#include "core/log.h"
|
||||
#include "core/path_utils.h"
|
||||
#include "core/profiler.h"
|
||||
#include "core/resource_manager.h"
|
||||
#include "core/resource_manager_base.h"
|
||||
#include "core/vec3.h"
|
||||
|
@ -190,6 +191,7 @@ bool Model::parseBones(FS::IFile* file)
|
|||
file->read(tmp, len);
|
||||
tmp[len] = 0;
|
||||
b.name = tmp;
|
||||
m_bone_map.insert(crc32(b.name.c_str()), m_bones.size() - 1);
|
||||
file->read(&len, sizeof(len));
|
||||
if (len >= MAX_PATH)
|
||||
{
|
||||
|
@ -294,6 +296,7 @@ bool Model::parseMeshes(FS::IFile* file)
|
|||
|
||||
void Model::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
if(success)
|
||||
{
|
||||
VertexDef vertex_definition;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/array.h"
|
||||
#include "core/crc32.h"
|
||||
#include "core/delegate_list.h"
|
||||
#include "core/hash_map.h"
|
||||
#include "core/matrix.h"
|
||||
#include "core/quat.h"
|
||||
#include "core/string.h"
|
||||
|
@ -58,6 +59,8 @@ class Mesh
|
|||
class Model : public Resource
|
||||
{
|
||||
public:
|
||||
typedef HashMap<uint32_t, int> BoneMap;
|
||||
|
||||
struct Bone
|
||||
{
|
||||
string name;
|
||||
|
@ -83,6 +86,7 @@ class Model : public Resource
|
|||
int getMeshCount() const { return m_meshes.size(); }
|
||||
int getBoneCount() const { return m_bones.size(); }
|
||||
const Bone& getBone(int i) const { return m_bones[i]; }
|
||||
BoneMap::iterator getBoneIndex(uint32_t hash) { return m_bone_map.find(hash); }
|
||||
void getPose(Pose& pose);
|
||||
float getBoundingRadius() const { return m_bounding_radius; }
|
||||
RayCastModelHit castRay(const Vec3& origin, const Vec3& dir, const Matrix& model_transform, float scale);
|
||||
|
@ -103,6 +107,7 @@ class Model : public Resource
|
|||
Array<Mesh> m_meshes;
|
||||
Array<Bone> m_bones;
|
||||
float m_bounding_radius;
|
||||
BoneMap m_bone_map; // maps bone name hash to bone index in m_bones
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "core/json_serializer.h"
|
||||
#include "core/log.h"
|
||||
#include "core/map.h"
|
||||
#include "core/profiler.h"
|
||||
#include "core/resource_manager.h"
|
||||
#include "core/resource_manager_base.h"
|
||||
#include "core/string.h"
|
||||
|
@ -546,8 +547,38 @@ struct PipelineInstanceImpl : public PipelineInstance
|
|||
glEnd();
|
||||
}
|
||||
|
||||
void renderGrass(int64_t layer_mask)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
if (m_active_camera.isValid())
|
||||
{
|
||||
Material* last_material = NULL;
|
||||
m_grass_infos.clear();
|
||||
m_scene->getGrassInfos(m_grass_infos, layer_mask);
|
||||
for (int i = 0; i < m_grass_infos.size(); ++i)
|
||||
{
|
||||
Shader* shader = m_grass_infos[i].m_mesh->getMaterial()->getShader();
|
||||
if (m_grass_infos[i].m_mesh->getMaterial() != last_material)
|
||||
{
|
||||
m_grass_infos[i].m_mesh->getMaterial()->apply(*m_renderer, *this);
|
||||
shader->setUniform("shadowmap_matrix0", m_shadow_modelviewprojection[0]);
|
||||
shader->setUniform("shadowmap_matrix1", m_shadow_modelviewprojection[1]);
|
||||
shader->setUniform("shadowmap_matrix2", m_shadow_modelviewprojection[2]);
|
||||
shader->setUniform("shadowmap_matrix3", m_shadow_modelviewprojection[3]);
|
||||
shader->setUniform("light_dir", m_light_dir);
|
||||
last_material = m_grass_infos[i].m_mesh->getMaterial();
|
||||
}
|
||||
shader->setUniform("grass_matrices", m_grass_infos[i].m_matrices, m_grass_infos[i].m_matrix_count);
|
||||
|
||||
Mesh& mesh = *m_grass_infos[i].m_mesh;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void renderTerrains(int64_t layer_mask)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
if (m_active_camera.isValid())
|
||||
{
|
||||
m_terrain_infos.clear();
|
||||
|
@ -560,6 +591,7 @@ struct PipelineInstanceImpl : public PipelineInstance
|
|||
Matrix world_matrix;
|
||||
m_terrain_infos[i].m_entity.getMatrix(world_matrix);
|
||||
Shader* shader = m_terrain_infos[i].m_material->getShader();
|
||||
m_terrain_infos[i].m_material->apply(*m_renderer, *this);
|
||||
shader->setUniform("world_matrix", world_matrix);
|
||||
shader->setUniform("shadowmap_matrix0", m_shadow_modelviewprojection[0]);
|
||||
shader->setUniform("shadowmap_matrix1", m_shadow_modelviewprojection[1]);
|
||||
|
@ -580,20 +612,22 @@ struct PipelineInstanceImpl : public PipelineInstance
|
|||
|
||||
void renderModels(int64_t layer_mask)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
ASSERT(m_renderer != NULL);
|
||||
static Array<RenderableInfo> infos;
|
||||
infos.clear();
|
||||
m_scene->getRenderableInfos(infos, layer_mask);
|
||||
int count = infos.size();
|
||||
renderTerrains(layer_mask);
|
||||
|
||||
m_renderable_infos.clear();
|
||||
m_scene->getRenderableInfos(m_renderable_infos, layer_mask);
|
||||
int count = m_renderable_infos.size();
|
||||
Material* last_material = NULL;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
glPushMatrix();
|
||||
Matrix world_matrix = infos[i].m_model ? infos[i].m_model->getMatrix() : *infos[i].m_matrix;
|
||||
world_matrix.multiply3x3(infos[i].m_scale);
|
||||
Matrix world_matrix = m_renderable_infos[i].m_model ? m_renderable_infos[i].m_model->getMatrix() : *m_renderable_infos[i].m_matrix;
|
||||
world_matrix.multiply3x3(m_renderable_infos[i].m_scale);
|
||||
glMultMatrixf(&world_matrix.m11);
|
||||
|
||||
Mesh& mesh = *infos[i].m_mesh;
|
||||
Mesh& mesh = *m_renderable_infos[i].m_mesh;
|
||||
Material& material = *mesh.getMaterial();
|
||||
if (last_material != &material)
|
||||
{
|
||||
|
@ -607,12 +641,13 @@ struct PipelineInstanceImpl : public PipelineInstance
|
|||
last_material = &material;
|
||||
}
|
||||
static Matrix bone_mtx[64];
|
||||
if (infos[i].m_pose)
|
||||
if (m_renderable_infos[i].m_pose)
|
||||
{
|
||||
const Pose& pose = *infos[i].m_pose;
|
||||
const Model& model = *infos[i].m_model->getModel();
|
||||
const Pose& pose = *m_renderable_infos[i].m_pose;
|
||||
const Model& model = *m_renderable_infos[i].m_model->getModel();
|
||||
Vec3* poss = pose.getPositions();
|
||||
Quat* rots = pose.getRotations();
|
||||
ASSERT(pose.getCount() <= 64);
|
||||
for (int bone_index = 0, bone_count = pose.getCount(); bone_index < bone_count; ++bone_index)
|
||||
{
|
||||
rots[bone_index].toMatrix(bone_mtx[bone_index]);
|
||||
|
@ -622,11 +657,11 @@ struct PipelineInstanceImpl : public PipelineInstance
|
|||
material.getShader()->setUniform("bone_matrices", bone_mtx, pose.getCount());
|
||||
}
|
||||
|
||||
infos[i].m_geometry->draw(mesh.getStart(), mesh.getCount(), *material.getShader());
|
||||
m_renderable_infos[i].m_geometry->draw(mesh.getStart(), mesh.getCount(), *material.getShader());
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
renderTerrains(layer_mask);
|
||||
renderGrass(layer_mask);
|
||||
}
|
||||
|
||||
virtual void resize(int w, int h) override
|
||||
|
@ -673,6 +708,8 @@ struct PipelineInstanceImpl : public PipelineInstance
|
|||
Map<uint32_t, CustomCommandHandler> m_custom_commands_handlers;
|
||||
Component m_active_camera;
|
||||
Array<TerrainInfo> m_terrain_infos;
|
||||
Array<GrassInfo> m_grass_infos;
|
||||
Array<RenderableInfo> m_renderable_infos;
|
||||
|
||||
private:
|
||||
void operator=(const PipelineInstanceImpl&);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "core/matrix.h"
|
||||
#include "core/quat.h"
|
||||
#include "core/vec3.h"
|
||||
#include "graphics/model.h"
|
||||
|
||||
|
||||
namespace Lumix
|
||||
|
@ -13,6 +14,7 @@ Pose::Pose()
|
|||
m_positions = 0;
|
||||
m_rotations = 0;
|
||||
m_count = 0;
|
||||
m_is_absolute = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,6 +27,7 @@ Pose::~Pose()
|
|||
|
||||
void Pose::resize(int count)
|
||||
{
|
||||
m_is_absolute = false;
|
||||
LUMIX_DELETE_ARRAY(m_positions);
|
||||
LUMIX_DELETE_ARRAY(m_rotations);
|
||||
m_count = count;
|
||||
|
@ -40,6 +43,40 @@ void Pose::resize(int count)
|
|||
}
|
||||
}
|
||||
|
||||
void Pose::computeAbsolute(Model& model, int i, bool* valid)
|
||||
{
|
||||
if (!valid[i])
|
||||
{
|
||||
int parent = model.getBone(i).parent_idx;
|
||||
if (parent >= 0)
|
||||
{
|
||||
if (!valid[parent])
|
||||
{
|
||||
computeAbsolute(model, parent, valid);
|
||||
}
|
||||
m_positions[i] = m_rotations[parent] * m_positions[i] + m_positions[parent];
|
||||
m_rotations[i] = m_rotations[i] * m_rotations[parent];
|
||||
}
|
||||
valid[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Pose::computeAbsolute(Model& model)
|
||||
{
|
||||
/// TODO remove recursion
|
||||
if(!m_is_absolute)
|
||||
{
|
||||
ASSERT(m_count < 256);
|
||||
bool valid[256];
|
||||
memset(valid, 0, sizeof(bool) * m_count);
|
||||
for (int i = 0; i < m_count; ++i)
|
||||
{
|
||||
computeAbsolute(model, i, valid);
|
||||
}
|
||||
m_is_absolute = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Pose::setMatrices(Matrix* mtx) const
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Lumix
|
|||
|
||||
|
||||
struct Matrix;
|
||||
class Model;
|
||||
struct Quat;
|
||||
struct Vec3;
|
||||
|
||||
|
@ -24,12 +25,16 @@ class Pose
|
|||
int getCount() const { return m_count; }
|
||||
Vec3* getPositions() const { return m_positions; }
|
||||
Quat* getRotations() const { return m_rotations; }
|
||||
void computeAbsolute(Model& model);
|
||||
void setIsRelative() { m_is_absolute = false; }
|
||||
|
||||
private:
|
||||
Pose(const Pose&) {}
|
||||
void operator =(const Pose&) {}
|
||||
void computeAbsolute(Model& model, int i, bool* valid);
|
||||
|
||||
private:
|
||||
bool m_is_absolute;
|
||||
int32_t m_count;
|
||||
Vec3* m_positions;
|
||||
Quat* m_rotations;
|
||||
|
|
|
@ -8,14 +8,15 @@
|
|||
namespace Lumix
|
||||
{
|
||||
|
||||
struct RayCastModelHit
|
||||
class RayCastModelHit
|
||||
{
|
||||
bool m_is_hit;
|
||||
float m_t;
|
||||
Vec3 m_origin;
|
||||
Vec3 m_dir;
|
||||
class Mesh* m_mesh;
|
||||
Component m_component;
|
||||
public:
|
||||
bool m_is_hit;
|
||||
float m_t;
|
||||
Vec3 m_origin;
|
||||
Vec3 m_dir;
|
||||
class Mesh* m_mesh;
|
||||
Component m_component;
|
||||
};
|
||||
|
||||
} // ~ namespace Lumix
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,6 +42,15 @@ namespace Lumix
|
|||
float m_scale;
|
||||
};
|
||||
|
||||
struct GrassInfo
|
||||
{
|
||||
Geometry* m_geometry;
|
||||
Mesh* m_mesh;
|
||||
const Matrix* m_matrices;
|
||||
int m_matrix_count;
|
||||
int m_mesh_copy_count;
|
||||
};
|
||||
|
||||
struct DebugLine
|
||||
{
|
||||
Vec3 m_from;
|
||||
|
@ -59,7 +68,8 @@ namespace Lumix
|
|||
virtual void serialize(ISerializer& serializer) = 0;
|
||||
virtual void deserialize(ISerializer& serializer) = 0;
|
||||
virtual Component createComponent(uint32_t type, const Entity& entity) = 0;
|
||||
virtual RayCastModelHit castRay(const Vec3& origin, const Vec3& dir) = 0;
|
||||
virtual void destroyComponent(const Component& component) = 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 applyCamera(Component camera) = 0;
|
||||
virtual void update(float dt) = 0;
|
||||
|
@ -93,6 +103,8 @@ namespace Lumix
|
|||
virtual void setRenderablePath(Component cmp, const string& path) = 0;
|
||||
virtual void setRenderableScale(Component cmp, const float& scale) = 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 getTerrainInfos(Array<TerrainInfo>& infos, int64_t layer_mask) = 0;
|
||||
virtual void setTerrainMaterial(Component cmp, const string& path) = 0;
|
||||
virtual void getTerrainMaterial(Component cmp, string& path) = 0;
|
||||
|
@ -100,6 +112,9 @@ namespace Lumix
|
|||
virtual void getTerrainXZScale(Component cmp, float& scale) = 0;
|
||||
virtual void setTerrainYScale(Component cmp, const float& scale) = 0;
|
||||
virtual void getTerrainYScale(Component cmp, float& scale) = 0;
|
||||
virtual void setTerrainGrass(Component cmp, const string& path) = 0;
|
||||
virtual void getTerrainGrass(Component cmp, string& path) = 0;
|
||||
virtual void setTerrainBrush(Component cmp, const Vec3& position, float size) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~RenderScene() {}
|
||||
|
|
|
@ -26,9 +26,9 @@ namespace Lumix
|
|||
{
|
||||
|
||||
|
||||
static const uint32_t light_hash = crc32("light");
|
||||
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 RENDERABLE_HASH = crc32("renderable");
|
||||
static const uint32_t CAMERA_HASH = crc32("camera");
|
||||
|
||||
|
||||
struct RendererImpl : public Renderer
|
||||
|
@ -110,11 +110,33 @@ 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
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual void enableZTest(bool enable) override
|
||||
{
|
||||
if (enable)
|
||||
|
|
|
@ -35,6 +35,7 @@ class LUMIX_ENGINE_API Renderer : public IPlugin
|
|||
|
||||
virtual void render(IRenderDevice& device) = 0;
|
||||
virtual void renderGame() = 0;
|
||||
virtual void enableAlphaToCoverage(bool enable) = 0;
|
||||
virtual void enableZTest(bool enable) = 0;
|
||||
virtual void setRenderDevice(IRenderDevice& device) = 0;
|
||||
virtual void setEditorWireframe(bool is_wireframe) = 0;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/json_serializer.h"
|
||||
#include "core/log.h"
|
||||
#include "core/matrix.h"
|
||||
#include "core/profiler.h"
|
||||
#include "core/resource_manager.h"
|
||||
#include "core/resource_manager_base.h"
|
||||
#include "core/vec3.h"
|
||||
|
@ -39,6 +40,7 @@ void Shader::apply()
|
|||
|
||||
void Shader::setUniform(const char* name, int value)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
||||
if(loc >= 0)
|
||||
{
|
||||
|
@ -51,6 +53,7 @@ void Shader::setUniform(const char* name, int value)
|
|||
|
||||
void Shader::setUniform(const char* name, const Vec3& value)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
||||
if(loc >= 0)
|
||||
{
|
||||
|
@ -63,6 +66,7 @@ void Shader::setUniform(const char* name, const Vec3& value)
|
|||
|
||||
void Shader::setUniform(const char* name, GLfloat value)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
||||
if(loc >= 0)
|
||||
{
|
||||
|
@ -75,6 +79,7 @@ void Shader::setUniform(const char* name, GLfloat value)
|
|||
|
||||
void Shader::setUniform(const char* name, const Matrix& mtx)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
GLint loc = glGetUniformLocation(m_program_id, name);
|
||||
if(loc >= 0)
|
||||
{
|
||||
|
@ -86,6 +91,7 @@ void Shader::setUniform(const char* name, const Matrix& mtx)
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -140,7 +146,7 @@ void Shader::loaded(FS::IFile* file, bool success, FS::FileSystem& fs)
|
|||
}
|
||||
serializer.deserializeObjectEnd();
|
||||
|
||||
int32_t size = (int32_t)file->size() - file->pos() + 1;
|
||||
int32_t size = serializer.getRestOfFileSize();
|
||||
ShaderManager* manager = static_cast<ShaderManager*>(getResourceManager().get(ResourceManager::SHADER));
|
||||
char* buf = reinterpret_cast<char*>(manager->getBuffer(size + 1));
|
||||
serializer.deserializeRawString(buf, size);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "terrain.h"
|
||||
#include "core/iserializer.h"
|
||||
#include "core/log.h"
|
||||
#include "core/math_utils.h"
|
||||
#include "core/profiler.h"
|
||||
#include "core/resource_manager.h"
|
||||
|
@ -11,12 +12,14 @@
|
|||
#include "graphics/render_scene.h"
|
||||
#include "graphics/shader.h"
|
||||
#include "graphics/texture.h"
|
||||
#include <cfloat>
|
||||
|
||||
|
||||
namespace Lumix
|
||||
{
|
||||
|
||||
static const int GRID_SIZE = 16;
|
||||
static const int COPY_COUNT = 50;
|
||||
static const uint32_t TERRAIN_HASH = crc32("terrain");
|
||||
|
||||
struct Sample
|
||||
|
@ -144,7 +147,7 @@ namespace Lumix
|
|||
};
|
||||
|
||||
|
||||
Terrain::Terrain(const Entity& entity)
|
||||
Terrain::Terrain(const Entity& entity, RenderScene& scene)
|
||||
: m_mesh(NULL)
|
||||
, m_material(NULL)
|
||||
, m_root(NULL)
|
||||
|
@ -154,6 +157,12 @@ namespace Lumix
|
|||
, m_y_scale(1)
|
||||
, m_xz_scale(1)
|
||||
, m_entity(entity)
|
||||
, m_grass_geometry(NULL)
|
||||
, m_grass_mesh(NULL)
|
||||
, m_scene(scene)
|
||||
, m_grass_model(NULL)
|
||||
, m_brush_position(0, 0, 0)
|
||||
, m_brush_size(1)
|
||||
{
|
||||
generateGeometry();
|
||||
}
|
||||
|
@ -163,6 +172,213 @@ namespace Lumix
|
|||
setMaterial(NULL);
|
||||
LUMIX_DELETE(m_mesh);
|
||||
LUMIX_DELETE(m_root);
|
||||
if (m_grass_model)
|
||||
{
|
||||
m_grass_model->getResourceManager().get(ResourceManager::MODEL)->unload(*m_grass_model);
|
||||
m_grass_model->getObserverCb().unbind<Terrain, &Terrain::grassLoaded>(this);
|
||||
LUMIX_DELETE(m_grass_mesh);
|
||||
LUMIX_DELETE(m_grass_geometry);
|
||||
for (int i = 0; i < m_grass_quads.size(); ++i)
|
||||
{
|
||||
LUMIX_DELETE(m_grass_quads[i]);
|
||||
}
|
||||
for (int i = 0; i < m_free_grass_quads.size(); ++i)
|
||||
{
|
||||
LUMIX_DELETE(m_free_grass_quads[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Path Terrain::getGrassPath()
|
||||
{
|
||||
if (m_grass_model)
|
||||
{
|
||||
return m_grass_model->getPath();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
void Terrain::setGrassPath(const Path& path)
|
||||
{
|
||||
if (m_grass_model)
|
||||
{
|
||||
m_grass_model->getResourceManager().get(ResourceManager::MODEL)->unload(*m_grass_model);
|
||||
m_grass_model->getObserverCb().unbind<Terrain, &Terrain::grassLoaded>(this);
|
||||
m_grass_model = NULL;
|
||||
LUMIX_DELETE(m_grass_mesh);
|
||||
LUMIX_DELETE(m_grass_geometry);
|
||||
m_grass_mesh = NULL;
|
||||
m_grass_geometry = NULL;
|
||||
}
|
||||
if (path.isValid())
|
||||
{
|
||||
m_grass_model = static_cast<Model*>(m_scene.getEngine().getResourceManager().get(ResourceManager::MODEL)->load(path));
|
||||
m_grass_model->getObserverCb().bind<Terrain, &Terrain::grassLoaded>(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Terrain::updateGrass(const Vec3& camera_position)
|
||||
{
|
||||
PROFILE_FUNCTION();
|
||||
if (m_free_grass_quads.size() + m_grass_quads.size() < GRASS_QUADS_HEIGHT * GRASS_QUADS_WIDTH)
|
||||
{
|
||||
int new_count = GRASS_QUADS_HEIGHT * GRASS_QUADS_WIDTH - m_grass_quads.size();
|
||||
for (int i = 0; i < new_count; ++i)
|
||||
{
|
||||
m_free_grass_quads.push(LUMIX_NEW(GrassQuad));
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_last_camera_position - camera_position).length() > 1)
|
||||
{
|
||||
Matrix mtx = m_entity.getMatrix();
|
||||
Matrix inv_mtx = m_entity.getMatrix();
|
||||
inv_mtx.fastInverse();
|
||||
Vec3 local_camera_position = inv_mtx.multiplyPosition(camera_position);
|
||||
float cx = (int)(local_camera_position.x / (GRASS_QUAD_SIZE)) * (float)GRASS_QUAD_SIZE;
|
||||
float cz = (int)(local_camera_position.z / (GRASS_QUAD_SIZE)) * (float)GRASS_QUAD_SIZE;
|
||||
float from_quad_x = cx - (GRASS_QUADS_WIDTH >> 1) * GRASS_QUAD_SIZE;
|
||||
float from_quad_z = cz - (GRASS_QUADS_HEIGHT >> 1) * GRASS_QUAD_SIZE;
|
||||
float to_quad_x = cx + (GRASS_QUADS_WIDTH >> 1) * GRASS_QUAD_SIZE;
|
||||
float to_quad_z = cz + (GRASS_QUADS_WIDTH >> 1) * GRASS_QUAD_SIZE;
|
||||
|
||||
float old_bounds[4] = { FLT_MAX, FLT_MIN, FLT_MAX, FLT_MIN };
|
||||
for (int i = m_grass_quads.size() - 1; i >= 0; --i)
|
||||
{
|
||||
GrassQuad* quad = m_grass_quads[i];
|
||||
old_bounds[0] = Math::minValue(old_bounds[0], quad->m_x);
|
||||
old_bounds[1] = Math::maxValue(old_bounds[1], quad->m_x);
|
||||
old_bounds[2] = Math::minValue(old_bounds[2], quad->m_z);
|
||||
old_bounds[3] = Math::maxValue(old_bounds[3], quad->m_z);
|
||||
if (quad->m_x < from_quad_x || quad->m_x > to_quad_x || quad->m_z < from_quad_z || quad->m_z > to_quad_z)
|
||||
{
|
||||
m_free_grass_quads.push(m_grass_quads[i]);
|
||||
m_grass_quads.eraseFast(i);
|
||||
}
|
||||
}
|
||||
|
||||
from_quad_x = Math::maxValue(0.0f, from_quad_x);
|
||||
from_quad_z = Math::maxValue(0.0f, from_quad_z);
|
||||
|
||||
for (float quad_z = from_quad_z; quad_z <= to_quad_z; quad_z += GRASS_QUAD_SIZE)
|
||||
{
|
||||
for (float quad_x = from_quad_x; quad_x <= to_quad_x; quad_x += GRASS_QUAD_SIZE)
|
||||
{
|
||||
if (quad_x < old_bounds[0] || quad_x > old_bounds[1] || quad_z < old_bounds[2] || quad_z > old_bounds[3])
|
||||
{
|
||||
GrassQuad* quad = m_free_grass_quads.back();
|
||||
m_free_grass_quads.pop();
|
||||
m_grass_quads.push(quad);
|
||||
quad->m_matrices.resize(31 * 31);
|
||||
quad->m_x = quad_x;
|
||||
quad->m_z = quad_z;
|
||||
srand((int)quad_x + (int)quad_z * GRASS_QUADS_WIDTH);
|
||||
int index = 0;
|
||||
for (float dx = 0; dx < GRASS_QUAD_SIZE; dx += 0.333f)
|
||||
{
|
||||
for (float dz = 0; dz < GRASS_QUAD_SIZE; dz += 0.333f)
|
||||
{
|
||||
quad->m_matrices[index] = Matrix::IDENTITY;
|
||||
float x = quad_x + dx + (rand() % 100 - 50) / 100.0f;
|
||||
float z = quad_z + dz + (rand() % 100 - 50) / 100.0f;;
|
||||
quad->m_matrices[index].setTranslation(Vec3(x, getHeight(x / m_xz_scale, z / m_xz_scale), z));
|
||||
quad->m_matrices[index] = mtx * quad->m_matrices[index];
|
||||
++index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_last_camera_position = camera_position;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Terrain::grassVertexCopyCallback(Array<uint8_t>& data)
|
||||
{
|
||||
bool has_matrix_index_attribute = m_grass_model->getGeometry()->getVertexDefinition().getAttributeType(3) == VertexAttributeDef::INT1;
|
||||
if (has_matrix_index_attribute)
|
||||
{
|
||||
int vertex_size = m_grass_model->getGeometry()->getVertexDefinition().getVertexSize();
|
||||
int one_size = vertex_size * m_grass_model->getGeometry()->getVertices().size();
|
||||
const int i1_offset = 3 * sizeof(float) + 3 * sizeof(float) + 2 * sizeof(float);
|
||||
for (int i = 0; i < COPY_COUNT; ++i)
|
||||
{
|
||||
for (int j = 0; j < m_grass_model->getGeometry()->getVertices().size(); ++j)
|
||||
{
|
||||
data[i * one_size + j * vertex_size + i1_offset] = (uint8_t)i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_log_error.log("renderer") << "Mesh " << m_grass_model->getPath().c_str() << " is not a grass mesh - wrong format";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Terrain::grassIndexCopyCallback(Array<int>& data)
|
||||
{
|
||||
int indices_count = m_grass_model->getGeometry()->getIndices().size();
|
||||
int index_offset = m_grass_model->getGeometry()->getVertices().size();
|
||||
for (int i = 0; i < COPY_COUNT; ++i)
|
||||
{
|
||||
for (int j = 0, c = indices_count; j < c; ++j)
|
||||
{
|
||||
data[i * indices_count + j] += index_offset * i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Terrain::grassLoaded(Resource::State, Resource::State)
|
||||
{
|
||||
if (m_grass_model->isReady())
|
||||
{
|
||||
LUMIX_DELETE(m_grass_geometry);
|
||||
|
||||
m_grass_geometry = LUMIX_NEW(Geometry);
|
||||
Geometry::VertexCallback vertex_callback;
|
||||
Geometry::IndexCallback index_callback;
|
||||
vertex_callback.bind<Terrain, &Terrain::grassVertexCopyCallback>(this);
|
||||
index_callback.bind<Terrain, &Terrain::grassIndexCopyCallback>(this);
|
||||
m_grass_geometry->copy(*m_grass_model->getGeometry(), COPY_COUNT, vertex_callback, index_callback);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
for (int k = 0, kc = m_grass_quads[i]->m_matrices.size() / COPY_COUNT; k < kc; ++k)
|
||||
{
|
||||
GrassInfo& info = infos.pushEmpty();
|
||||
info.m_geometry = m_grass_geometry;
|
||||
info.m_matrices = &m_grass_quads[i]->m_matrices[COPY_COUNT * k];
|
||||
info.m_mesh = m_grass_mesh;
|
||||
info.m_matrix_count = COPY_COUNT;
|
||||
info.m_mesh_copy_count = COPY_COUNT;
|
||||
}
|
||||
if (m_grass_quads[i]->m_matrices.size() % COPY_COUNT != 0)
|
||||
{
|
||||
GrassInfo& info = infos.pushEmpty();
|
||||
info.m_geometry = 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_mesh = m_grass_mesh;
|
||||
info.m_matrix_count = m_grass_quads[i]->m_matrices.size() % COPY_COUNT;
|
||||
info.m_mesh_copy_count = COPY_COUNT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -202,6 +418,8 @@ namespace Lumix
|
|||
setMaterial(static_cast<Material*>(scene.getEngine().getResourceManager().get(ResourceManager::MATERIAL)->load(path)));
|
||||
serializer.deserializeArrayItem(m_xz_scale);
|
||||
serializer.deserializeArrayItem(m_y_scale);
|
||||
serializer.deserializeArrayItem(path, LUMIX_MAX_PATH);
|
||||
setGrassPath(path);
|
||||
universe.addComponent(m_entity, TERRAIN_HASH, &scene, index);
|
||||
}
|
||||
|
||||
|
@ -213,6 +431,7 @@ namespace Lumix
|
|||
serializer.serializeArrayItem(m_material->getPath().c_str());
|
||||
serializer.serializeArrayItem(m_xz_scale);
|
||||
serializer.serializeArrayItem(m_y_scale);
|
||||
serializer.serializeArrayItem(m_grass_model ? m_grass_model->getPath().c_str() : "");
|
||||
}
|
||||
|
||||
|
||||
|
@ -221,9 +440,37 @@ namespace Lumix
|
|||
if (m_root)
|
||||
{
|
||||
m_material->apply(renderer, pipeline);
|
||||
Matrix world_matrix;
|
||||
m_entity.getMatrix(world_matrix);
|
||||
world_matrix.fastInverse();
|
||||
Vec3 rel_cam_pos = world_matrix.multiplyPosition(camera_pos) / m_xz_scale;
|
||||
m_mesh->getMaterial()->getShader()->setUniform("brush_position", m_brush_position);
|
||||
m_mesh->getMaterial()->getShader()->setUniform("brush_size", m_brush_size);
|
||||
m_mesh->getMaterial()->getShader()->setUniform("map_size", m_root->m_size);
|
||||
m_mesh->getMaterial()->getShader()->setUniform("camera_pos", camera_pos);
|
||||
m_root->render(m_mesh, m_geometry, camera_pos, *pipeline.getScene());
|
||||
m_mesh->getMaterial()->getShader()->setUniform("camera_pos", rel_cam_pos);
|
||||
m_root->render(m_mesh, m_geometry, rel_cam_pos, *pipeline.getScene());
|
||||
}
|
||||
}
|
||||
|
||||
float Terrain::getHeight(float x, float z)
|
||||
{
|
||||
int int_x = (int)x;
|
||||
int int_z = (int)z;
|
||||
float dec_x = x - int_x;
|
||||
float dec_z = z - int_z;
|
||||
if (dec_x > dec_z)
|
||||
{
|
||||
float h0 = getHeight(int_x, int_z);
|
||||
float h1 = getHeight(int_x + 1, int_z);
|
||||
float h2 = getHeight(int_x + 1, int_z + 1);
|
||||
return h0 + (h1 - h0) * dec_x + (h2 - h1) * dec_z;
|
||||
}
|
||||
else
|
||||
{
|
||||
float h0 = getHeight(int_x, int_z);
|
||||
float h1 = getHeight(int_x + 1, int_z + 1);
|
||||
float h2 = getHeight(int_x, int_z + 1);
|
||||
return h0 + (h2 - h0) * dec_z + (h1 - h2) * dec_x;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,10 +478,10 @@ namespace Lumix
|
|||
float Terrain::getHeight(int x, int z)
|
||||
{
|
||||
Texture* t = m_material->getTexture(0);
|
||||
int idx = x + z * m_width;
|
||||
int idx = Math::clamp(x, 0, m_width) + Math::clamp(z, 0, m_height) * m_width;
|
||||
if (t->getBytesPerPixel() == 2)
|
||||
{
|
||||
return ((m_y_scale / (256.0f * 256.0f)) * ((uint16_t*)t->getData())[idx]);
|
||||
return ((m_y_scale / (256.0f * 256.0f - 1)) * ((uint16_t*)t->getData())[idx]);
|
||||
}
|
||||
else if(t->getBytesPerPixel() == 4)
|
||||
{
|
||||
|
@ -242,7 +489,7 @@ namespace Lumix
|
|||
}
|
||||
else
|
||||
{
|
||||
ASSERT(false); TODO("todo");
|
||||
ASSERT(false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -304,12 +551,11 @@ namespace Lumix
|
|||
if (Math::getRayAABBIntersection(rel_origin, rel_dir, m_root->m_min, size, start))
|
||||
{
|
||||
Vec3 p = start;
|
||||
while (p.x >= m_root->m_min.x && p.x <= m_root->m_min.x + m_root->m_size * m_xz_scale
|
||||
&& p.z >= m_root->m_min.z && p.z <= m_root->m_min.z + m_root->m_size * m_xz_scale)
|
||||
int hx = (int)(p.x / m_xz_scale);
|
||||
int hz = (int)(p.z / m_xz_scale);
|
||||
while (hx >= 0 && hz >= 0 && hx < m_width - 1 && hz < m_height - 1 && p.y > m_root->m_min.y && p.y < m_root->m_min.y + m_root->m_size)
|
||||
{
|
||||
float t;
|
||||
int hx = (int)(p.x / m_xz_scale);
|
||||
int hz = (int)(p.z / m_xz_scale);
|
||||
float x = hx * m_xz_scale;
|
||||
float z = hz * m_xz_scale;
|
||||
Vec3 p0(x, getHeight(hx, hz), z);
|
||||
|
@ -332,7 +578,9 @@ namespace Lumix
|
|||
hit.m_t = t;
|
||||
return hit;
|
||||
}
|
||||
p += dir;
|
||||
p += rel_dir;
|
||||
hx = (int)(p.x / m_xz_scale);
|
||||
hz = (int)(p.z / m_xz_scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,21 @@ struct TerrainQuad;
|
|||
class Terrain
|
||||
{
|
||||
public:
|
||||
Terrain(const Entity& entity);
|
||||
class GrassQuad
|
||||
{
|
||||
public:
|
||||
Array<Matrix> m_matrices;
|
||||
float m_x;
|
||||
float m_z;
|
||||
};
|
||||
|
||||
public:
|
||||
static const int GRASS_QUADS_WIDTH = 5;
|
||||
static const int GRASS_QUADS_HEIGHT = 5;
|
||||
static const int GRASS_QUAD_SIZE = 10;
|
||||
|
||||
public:
|
||||
Terrain(const Entity& entity, RenderScene& scene);
|
||||
~Terrain();
|
||||
|
||||
void render(Renderer& renderer, PipelineInstance& pipeline, const Vec3& camera_pos);
|
||||
|
@ -40,12 +54,21 @@ class Terrain
|
|||
float getYScale() const { return m_y_scale; }
|
||||
Entity getEntity() const { return m_entity; }
|
||||
Material* getMaterial() const { return m_material; }
|
||||
void setGrassPath(const Path& path);
|
||||
Path getGrassPath();
|
||||
void setMaterial(Material* material);
|
||||
void getGrassInfos(Array<GrassInfo>& infos, const Vec3& camera_position);
|
||||
void setBrush(const Vec3& position, float size) { m_brush_position = position; m_brush_size = size; }
|
||||
|
||||
private:
|
||||
void updateGrass(const Vec3& camera_position);
|
||||
void generateGeometry();
|
||||
void onMaterialLoaded(Resource::State, Resource::State new_state);
|
||||
float getHeight(int x, int z);
|
||||
float getHeight(float x, float z);
|
||||
void grassLoaded(Resource::State, Resource::State);
|
||||
void grassVertexCopyCallback(Array<uint8_t>& data);
|
||||
void grassIndexCopyCallback(Array<int>& data);
|
||||
|
||||
private:
|
||||
Mesh* m_mesh;
|
||||
|
@ -58,6 +81,15 @@ class Terrain
|
|||
float m_y_scale;
|
||||
Entity m_entity;
|
||||
Material* m_material;
|
||||
Geometry* m_grass_geometry;
|
||||
Mesh* m_grass_mesh;
|
||||
RenderScene& m_scene;
|
||||
Model* m_grass_model;
|
||||
Array<GrassQuad*> m_free_grass_quads;
|
||||
Array<GrassQuad*> m_grass_quads;
|
||||
Vec3 m_last_camera_position;
|
||||
Vec3 m_brush_position;
|
||||
float m_brush_size;
|
||||
};
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,14 +26,18 @@ class LUMIX_ENGINE_API Texture : public Resource
|
|||
int getHeight() const { return m_height; }
|
||||
int getBytesPerPixel() const { return m_BPP; }
|
||||
const uint8_t* getData() const { return m_data.empty() ? NULL : &m_data[0]; }
|
||||
uint8_t* getData() { return m_data.empty() ? NULL : &m_data[0]; }
|
||||
void addDataReference();
|
||||
void removeDataReference();
|
||||
|
||||
void onDataUpdated();
|
||||
void save();
|
||||
|
||||
private:
|
||||
void loaded(FS::IFile* file, bool success, FS::FileSystem& fs);
|
||||
bool loadDDS(FS::IFile& file);
|
||||
bool loadTGA(FS::IFile& file);
|
||||
bool loadRaw(FS::IFile& file);
|
||||
void saveTGA();
|
||||
|
||||
virtual void doUnload(void) override;
|
||||
virtual FS::ReadCallback getReadCallback() override;
|
||||
|
@ -45,6 +49,7 @@ class LUMIX_ENGINE_API Texture : public Resource
|
|||
int m_BPP;
|
||||
int m_data_reference;
|
||||
Array<uint8_t> m_data;
|
||||
bool m_is_cubemap;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -220,6 +220,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
|||
m_actors.push(actor);
|
||||
actor->m_source = "";
|
||||
actor->m_entity = entity;
|
||||
actor->m_physx_actor = NULL;
|
||||
|
||||
Component cmp = m_universe->addComponent(entity, MESH_ACTOR_HASH, this, m_actors.size() - 1);
|
||||
m_universe->componentCreated().invoke(cmp);
|
||||
|
@ -295,7 +296,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
|||
{
|
||||
bool is_dynamic = false;
|
||||
getIsDynamic(cmp, is_dynamic);
|
||||
if (m_actors[cmp.index]->m_source == str && is_dynamic == !m_actors[cmp.index]->m_physx_actor->isRigidStatic())
|
||||
if (m_actors[cmp.index]->m_source == str && (!m_actors[cmp.index]->m_physx_actor || is_dynamic == !m_actors[cmp.index]->m_physx_actor->isRigidStatic()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -308,7 +309,7 @@ struct PhysicsSceneImpl : public PhysicsScene
|
|||
cmp.entity.getMatrix(mtx);
|
||||
matrix2Transform(mtx, transform);
|
||||
|
||||
if (m_actors[cmp.index])
|
||||
if (m_actors[cmp.index] && m_actors[cmp.index]->m_physx_actor)
|
||||
{
|
||||
m_scene->removeActor(*m_actors[cmp.index]->m_physx_actor);
|
||||
m_actors[cmp.index]->m_physx_actor->release();
|
||||
|
@ -539,15 +540,16 @@ struct PhysicsSceneImpl : public PhysicsScene
|
|||
if (bytes_per_pixel == 2)
|
||||
{
|
||||
PROFILE_BLOCK("copyData");
|
||||
const uint16_t* data = (const uint16_t*)terrain->m_heightmap->getData();
|
||||
const uint16_t* LUMIX_RESTRICT data = (const uint16_t*)terrain->m_heightmap->getData();
|
||||
for (int j = 0; j < height; ++j)
|
||||
{
|
||||
int idx = j * width;
|
||||
for (int i = 0; i < width; ++i)
|
||||
{
|
||||
int idx = i + j * width;
|
||||
int idx2 = j + i * height;
|
||||
heights[idx].height = data[idx2];
|
||||
heights[idx].materialIndex0 = heights[idx].materialIndex1 = 0;
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -569,42 +571,45 @@ struct PhysicsSceneImpl : public PhysicsScene
|
|||
|
||||
//terrain->m_heightmap->removeDataReference();
|
||||
|
||||
physx::PxHeightFieldDesc hfDesc;
|
||||
hfDesc.format = physx::PxHeightFieldFormat::eS16_TM;
|
||||
hfDesc.nbColumns = width;
|
||||
hfDesc.nbRows = height;
|
||||
hfDesc.samples.data = &heights[0];
|
||||
hfDesc.samples.stride = sizeof(physx::PxHeightFieldSample);
|
||||
hfDesc.thickness = -1;
|
||||
{ // PROFILE_BLOCK scope
|
||||
PROFILE_BLOCK("PhysX");
|
||||
physx::PxHeightFieldDesc hfDesc;
|
||||
hfDesc.format = physx::PxHeightFieldFormat::eS16_TM;
|
||||
hfDesc.nbColumns = width;
|
||||
hfDesc.nbRows = height;
|
||||
hfDesc.samples.data = &heights[0];
|
||||
hfDesc.samples.stride = sizeof(physx::PxHeightFieldSample);
|
||||
hfDesc.thickness = -1;
|
||||
|
||||
physx::PxHeightField* heightfield = m_system->m_impl->m_physics->createHeightField(hfDesc);
|
||||
float height_scale = bytes_per_pixel == 2 ? 1 / (256 * 256.0f) : 1 / 255.0f;
|
||||
physx::PxHeightFieldGeometry hfGeom(heightfield, physx::PxMeshGeometryFlags(), height_scale * terrain->m_y_scale, terrain->m_xz_scale, terrain->m_xz_scale);
|
||||
if (terrain->m_actor)
|
||||
{
|
||||
physx::PxRigidActor* actor = terrain->m_actor;
|
||||
m_scene->removeActor(*actor);
|
||||
actor->release();
|
||||
terrain->m_actor = NULL;
|
||||
}
|
||||
physx::PxHeightField* heightfield = m_system->m_impl->m_physics->createHeightField(hfDesc);
|
||||
float height_scale = bytes_per_pixel == 2 ? 1 / (256 * 256.0f - 1) : 1 / 255.0f;
|
||||
physx::PxHeightFieldGeometry hfGeom(heightfield, physx::PxMeshGeometryFlags(), height_scale * terrain->m_y_scale, terrain->m_xz_scale, terrain->m_xz_scale);
|
||||
if (terrain->m_actor)
|
||||
{
|
||||
physx::PxRigidActor* actor = terrain->m_actor;
|
||||
m_scene->removeActor(*actor);
|
||||
actor->release();
|
||||
terrain->m_actor = NULL;
|
||||
}
|
||||
|
||||
physx::PxTransform transform;
|
||||
Matrix mtx;
|
||||
terrain->m_entity.getMatrix(mtx);
|
||||
matrix2Transform(mtx, transform);
|
||||
physx::PxTransform transform;
|
||||
Matrix mtx;
|
||||
terrain->m_entity.getMatrix(mtx);
|
||||
matrix2Transform(mtx, transform);
|
||||
|
||||
physx::PxRigidActor* actor;
|
||||
actor = PxCreateStatic(*m_system->m_impl->m_physics, transform, hfGeom, *m_default_material);
|
||||
if (actor)
|
||||
{
|
||||
actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, width <= 1024);
|
||||
actor->userData = (void*)terrain->m_entity.index;
|
||||
m_scene->addActor(*actor);
|
||||
terrain->m_actor = actor;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_log_error.log("PhysX") << "Could not create PhysX heightfield " << terrain->m_heightmap->getPath().c_str();
|
||||
physx::PxRigidActor* actor;
|
||||
actor = PxCreateStatic(*m_system->m_impl->m_physics, transform, hfGeom, *m_default_material);
|
||||
if (actor)
|
||||
{
|
||||
actor->setActorFlag(physx::PxActorFlag::eVISUALIZATION, width <= 1024);
|
||||
actor->userData = (void*)terrain->m_entity.index;
|
||||
m_scene->addActor(*actor);
|
||||
terrain->m_actor = actor;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_log_error.log("PhysX") << "Could not create PhysX heightfield " << terrain->m_heightmap->getPath().c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -984,12 +989,12 @@ PhysicsScene* PhysicsScene::create(PhysicsSystem& system, Universe& universe, En
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);
|
||||
/*impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);
|
||||
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eSCALE, 1.0);
|
||||
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eACTOR_AXES, 1.0f);
|
||||
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eCOLLISION_AABBS, 1.0f);
|
||||
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eWORLD_AXES, 1.0f);
|
||||
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eCONTACT_POINT, 1.0f);
|
||||
impl->m_scene->setVisualizationParameter(physx::PxVisualizationParameter::eCONTACT_POINT, 1.0f);*/
|
||||
impl->m_system = &system;
|
||||
impl->m_default_material = impl->m_system->m_impl->m_physics->createMaterial(0.5,0.5,0.5);
|
||||
return impl;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "cooking/PxCooking.h"
|
||||
#include "core/crc32.h"
|
||||
#include "core/log.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "editor/property_descriptor.h"
|
||||
#include "engine/engine.h"
|
||||
#include "physics/physics_scene.h"
|
||||
|
@ -68,6 +68,12 @@ void PhysicsSystem::sendMessage(const char* message)
|
|||
}
|
||||
|
||||
|
||||
void PhysicsSystem::destroyComponent(const Component& component)
|
||||
{
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
Component PhysicsSystem::createComponent(uint32_t component_type, const Entity& entity)
|
||||
{
|
||||
if (component_type == HEIGHTFIELD_HASH)
|
||||
|
@ -121,16 +127,16 @@ class AssertNullAllocator : public physx::PxAllocatorCallback
|
|||
|
||||
bool PhysicsSystem::create(Engine& engine)
|
||||
{
|
||||
engine.getEditorServer()->registerProperty("box_rigid_actor", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("dynamic"), &PhysicsScene::getIsDynamic, &PhysicsScene::setIsDynamic));
|
||||
engine.getEditorServer()->registerProperty("box_rigid_actor", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("size"), &PhysicsScene::getHalfExtents, &PhysicsScene::setHalfExtents));
|
||||
engine.getEditorServer()->registerProperty("mesh_rigid_actor", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("source"), &PhysicsScene::getShapeSource, &PhysicsScene::setShapeSource, IPropertyDescriptor::FILE));
|
||||
engine.getEditorServer()->registerProperty("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("heightmap"), &PhysicsScene::getHeightmap, &PhysicsScene::setHeightmap, IPropertyDescriptor::FILE));
|
||||
engine.getEditorServer()->registerProperty("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("xz_scale"), &PhysicsScene::getHeightmapXZScale, &PhysicsScene::setHeightmapXZScale));
|
||||
engine.getEditorServer()->registerProperty("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("y_scale"), &PhysicsScene::getHeightmapYScale, &PhysicsScene::setHeightmapYScale));
|
||||
engine.getEditorServer()->registerCreator(HEIGHTFIELD_HASH, *this);
|
||||
engine.getEditorServer()->registerCreator(BOX_ACTOR_HASH, *this);
|
||||
engine.getEditorServer()->registerCreator(MESH_ACTOR_HASH, *this);
|
||||
engine.getEditorServer()->registerCreator(CONTROLLER_HASH, *this);
|
||||
engine.getWorldEditor()->registerProperty("box_rigid_actor", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("dynamic"), &PhysicsScene::getIsDynamic, &PhysicsScene::setIsDynamic));
|
||||
engine.getWorldEditor()->registerProperty("box_rigid_actor", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("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("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("heightmap"), &PhysicsScene::getHeightmap, &PhysicsScene::setHeightmap, IPropertyDescriptor::FILE));
|
||||
engine.getWorldEditor()->registerProperty("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("xz_scale"), &PhysicsScene::getHeightmapXZScale, &PhysicsScene::setHeightmapXZScale));
|
||||
engine.getWorldEditor()->registerProperty("physical_heightfield", LUMIX_NEW(PropertyDescriptor<PhysicsScene>)(crc32("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->m_allocator = LUMIX_NEW(AssertNullAllocator)();
|
||||
|
|
|
@ -24,6 +24,7 @@ class LUMIX_PHYSICS_API PhysicsSystem : public IPlugin
|
|||
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 void sendMessage(const char* message) override;
|
||||
class PhysicsScene* getScene() const;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "core/json_serializer.h"
|
||||
#include "core/log.h"
|
||||
#include "core/array.h"
|
||||
#include "editor/editor_server.h"
|
||||
#include "editor/world_editor.h"
|
||||
#include "engine/engine.h"
|
||||
#include "universe/universe.h"
|
||||
#include "base_script.h"
|
||||
|
@ -263,8 +263,8 @@ namespace Lumix
|
|||
virtual bool create(Engine& engine) override
|
||||
{
|
||||
m_engine = &engine;
|
||||
engine.getEditorServer()->registerProperty("script", LUMIX_NEW(PropertyDescriptor<ScriptSystem>)(crc32("source"), &ScriptSystem::getScriptPath, &ScriptSystem::setScriptPath, IPropertyDescriptor::FILE));
|
||||
engine.getEditorServer()->registerCreator(SCRIPT_HASH, *this);
|
||||
engine.getWorldEditor()->registerProperty("script", LUMIX_NEW(PropertyDescriptor<ScriptSystem>)(crc32("source"), &ScriptSystem::getScriptPath, &ScriptSystem::setScriptPath, IPropertyDescriptor::FILE));
|
||||
engine.getWorldEditor()->registerCreator(SCRIPT_HASH, *this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -275,6 +275,12 @@ namespace Lumix
|
|||
}
|
||||
|
||||
|
||||
virtual void destroyComponent(const Component&) override
|
||||
{
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
|
||||
virtual Component createComponent(uint32_t type, const Entity& entity) override
|
||||
{
|
||||
if (type == SCRIPT_HASH)
|
||||
|
|
|
@ -34,18 +34,16 @@ Universe::Universe()
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Entity Universe::createEntity()
|
||||
{
|
||||
|
||||
if(m_free_slots.empty())
|
||||
{
|
||||
m_positions.push(Vec3(0, 0, 0));
|
||||
m_rotations.push(Quat(0, 0, 0, 1));
|
||||
m_component_list.pushEmpty();
|
||||
return Entity(this, m_positions.size() - 1);
|
||||
Entity e(this, m_positions.size() - 1);
|
||||
m_entity_created.invoke(e);
|
||||
return e;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -54,6 +52,7 @@ Entity Universe::createEntity()
|
|||
m_positions[e.index].set(0, 0, 0);
|
||||
m_rotations[e.index].set(0, 0, 0, 1);
|
||||
m_component_list[e.index].clear();
|
||||
m_entity_created.invoke(e);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,14 +44,14 @@ class LUMIX_ENGINE_API Universe final
|
|||
int getEntityCount() const { return m_positions.size(); }
|
||||
|
||||
DelegateList<void(Entity&)>& entityMoved() { return m_entity_moved; }
|
||||
DelegateList<void(Entity&)>& entityCreated() { return m_entity_created; }
|
||||
DelegateList<void(Entity&)>& entityDestroyed() { return m_entity_destroyed; }
|
||||
DelegateList<void(Component&)>& componentCreated() { return m_component_created; }
|
||||
DelegateList<void(Component&)>& componentDestroyed() { return m_component_destroyed; }
|
||||
DelegateList<void(const Component&)>& componentDestroyed() { return m_component_destroyed; }
|
||||
|
||||
void serialize(ISerializer& serializer);
|
||||
void deserialize(ISerializer& serializer);
|
||||
|
||||
|
||||
private:
|
||||
void onEvent(Event& event);
|
||||
|
||||
|
@ -61,9 +61,10 @@ class LUMIX_ENGINE_API Universe final
|
|||
Array<int> m_free_slots;
|
||||
ComponentList m_component_list;
|
||||
DelegateList<void(Entity&)> m_entity_moved;
|
||||
DelegateList<void(Entity&)> m_entity_created;
|
||||
DelegateList<void(Entity&)> m_entity_destroyed;
|
||||
DelegateList<void(Component&)> m_component_created;
|
||||
DelegateList<void(Component&)> m_component_destroyed;
|
||||
DelegateList<void(const Component&)> m_component_destroyed;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue