From 5581dfa8ad0ca34eb73de1dea0bbfd4c36279721 Mon Sep 17 00:00:00 2001 From: Arnau Alier Torres Date: Wed, 7 May 2025 19:24:32 +0200 Subject: [PATCH] Get Mesh component starts to workgit add .! --- Deer/Include/DeerRender/Components.h | 8 ++ Deer/Include/DeerRender/Mesh.h | 4 +- Deer/src/DeerRender/Mesh/MeshDataStore.cpp | 4 +- Deer/src/DeerRender/Mesh/MeshModelLoading.cpp | 51 ++++++++-- DeerStudio/src/DeerStudio/DeerStudio.cpp | 2 +- .../src/DeerStudio/EditorEngine/API/Entity.h | 16 ++++ .../DeerStudio/EditorEngine/API/Resource.h | 4 +- .../{API => API_Implementation}/Debug.cpp | 0 .../{API => API_Implementation}/Entity.cpp | 94 +++++++++++++++++++ .../Entity_Register.cpp | 60 ++++++++++++ .../{API => API_Implementation}/Layout.cpp | 0 .../{API => API_Implementation}/Math.cpp | 0 .../Math_Register.cpp | 0 .../{API => API_Implementation}/Menu.cpp | 0 .../{API => API_Implementation}/Resource.cpp | 11 ++- .../{API => API_Implementation}/UI.cpp | 0 .../EditorEngine/RegisterStructs.cpp | 1 + roe/editor/properties/components_render.as | 9 ++ roe/editor/properties/properties_pannel.as | 5 +- roe/editor/shader_explorer.as | 41 ++++++++ roe/imgui.ini | 8 +- 21 files changed, 301 insertions(+), 17 deletions(-) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/Debug.cpp (100%) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/Entity.cpp (57%) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/Entity_Register.cpp (77%) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/Layout.cpp (100%) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/Math.cpp (100%) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/Math_Register.cpp (100%) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/Menu.cpp (100%) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/Resource.cpp (96%) rename DeerStudio/src/DeerStudio/EditorEngine/{API => API_Implementation}/UI.cpp (100%) create mode 100644 roe/editor/shader_explorer.as diff --git a/Deer/Include/DeerRender/Components.h b/Deer/Include/DeerRender/Components.h index f273965..8c6cdf8 100755 --- a/Deer/Include/DeerRender/Components.h +++ b/Deer/Include/DeerRender/Components.h @@ -31,6 +31,14 @@ namespace Deer { return MeshManager::getModel(meshId); } + inline Path& getMeshName() { + return MeshManager::getModelName(meshId); + } + + inline bool hasMesh() { + return meshId != 0; + } + inline bool isActive() { return active; } diff --git a/Deer/Include/DeerRender/Mesh.h b/Deer/Include/DeerRender/Mesh.h index c0adaf7..73da33e 100644 --- a/Deer/Include/DeerRender/Mesh.h +++ b/Deer/Include/DeerRender/Mesh.h @@ -59,8 +59,10 @@ namespace Deer { }; namespace MeshManager { - uint16_t loadModel(const MeshData&); + uint16_t loadModel(const Path&); + uint16_t loadModel(const MeshData&, const Path&); VertexArray& getModel(uint16_t model_id); + Path& getModelName(uint16_t model_id); void unloadAllModels(); } diff --git a/Deer/src/DeerRender/Mesh/MeshDataStore.cpp b/Deer/src/DeerRender/Mesh/MeshDataStore.cpp index 7a3cfdc..f890a4f 100644 --- a/Deer/src/DeerRender/Mesh/MeshDataStore.cpp +++ b/Deer/src/DeerRender/Mesh/MeshDataStore.cpp @@ -8,7 +8,7 @@ namespace Deer { void DataStore::loadModel(MeshData& meshData, const Path& name) { Path realName; - realName = Path(DEER_MESH_PATH) / (name.string() + ".dmesh"); + realName = Path(DEER_MESH_PATH) / (name.string() + DEER_MESH_EXTENSION); uint32_t size; uint8_t* data = DataStore::readFile(realName, &size); @@ -28,7 +28,7 @@ namespace Deer { void DataStore::saveModel(const MeshData& meshData, const Path& name) { Path realName; - realName = Path(DEER_MESH_PATH) / (name.string() + ".dmesh"); + realName = Path(DEER_MESH_PATH) / (name.string() + DEER_MESH_EXTENSION); std::stringstream output; { diff --git a/Deer/src/DeerRender/Mesh/MeshModelLoading.cpp b/Deer/src/DeerRender/Mesh/MeshModelLoading.cpp index 154f39b..931cc74 100644 --- a/Deer/src/DeerRender/Mesh/MeshModelLoading.cpp +++ b/Deer/src/DeerRender/Mesh/MeshModelLoading.cpp @@ -3,30 +3,57 @@ namespace Deer { namespace MeshManager { + struct MeshManagerContainer { + Path mesh_name; + VertexArray* mesh_data = nullptr; + }; + size_t minModelId = 0; - VertexArray* meshes[SCENE_MAX_MESH_COUNT]{}; + MeshManagerContainer meshes[SCENE_MAX_MESH_COUNT]{}; + std::unordered_map mesh_name_id; + VertexArray* loadModelToGPU(const MeshData& data); } void MeshManager::unloadAllModels() { - for (uint16_t i = 0; i < minModelId; i++) { - delete meshes[i]; - meshes[i] = nullptr; + for (uint16_t i = 1; i < minModelId; i++) { + delete meshes[i].mesh_data; + meshes[i].mesh_data = nullptr; } + mesh_name_id.clear(); - minModelId = 0; + mesh_name_id["NULL"] = 0; + meshes[0].mesh_data = nullptr; + meshes[0].mesh_name = "NULL"; + minModelId = 1; } - uint16_t MeshManager::loadModel(const MeshData& meshData) { + uint16_t MeshManager::loadModel(const Path& name) { + if (mesh_name_id.contains(name)) + return mesh_name_id[name]; + + MeshData meshData; + DataStore::loadModel(meshData, name); + + return loadModel(meshData, name); + } + + uint16_t MeshManager::loadModel(const MeshData& meshData, const Path& name) { if (minModelId >= SCENE_MAX_MESH_COUNT) { DEER_CORE_ERROR("Max model loaded into a scene"); - return -1; + return 0; } + if (mesh_name_id.contains(name)) { + DEER_CORE_ERROR("Mesh with name {0} already exists", name.string().c_str()); + return 0; + } + uint16_t modelId = minModelId; minModelId++; - meshes[modelId] = loadModelToGPU(meshData); + meshes[modelId].mesh_data = loadModelToGPU(meshData); + meshes[modelId].mesh_name = name; return modelId; } @@ -34,7 +61,13 @@ namespace Deer { VertexArray& MeshManager::getModel(uint16_t model_id) { DEER_CORE_ASSERT(model_id >= 0 && model_id < minModelId, "Invalid model id, id is not loaded"); - return *meshes[model_id]; + return *meshes[model_id].mesh_data; + } + + Path& MeshManager::getModelName(uint16_t model_id) { + DEER_CORE_ASSERT(model_id >= 0 && model_id < minModelId, "Invalid model id, id is not loaded"); + + return meshes[model_id].mesh_name; } VertexArray* MeshManager::loadModelToGPU(const MeshData& data) { diff --git a/DeerStudio/src/DeerStudio/DeerStudio.cpp b/DeerStudio/src/DeerStudio/DeerStudio.cpp index 536ca5e..a9b8a4a 100755 --- a/DeerStudio/src/DeerStudio/DeerStudio.cpp +++ b/DeerStudio/src/DeerStudio/DeerStudio.cpp @@ -66,7 +66,7 @@ namespace Deer { ShaderData shaderData; DataStore::loadShader(shaderData, "shader"); - renderComponent.setMesh(MeshManager::loadModel(meshData)); + renderComponent.setMesh(MeshManager::loadModel(meshData, "SIMPLE MESH")); shaderComponent.setShader(ShaderManager::loadShader(shaderData)); return 0; diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Entity.h b/DeerStudio/src/DeerStudio/EditorEngine/API/Entity.h index 71a25d6..d41d28b 100644 --- a/DeerStudio/src/DeerStudio/EditorEngine/API/Entity.h +++ b/DeerStudio/src/DeerStudio/EditorEngine/API/Entity.h @@ -46,6 +46,11 @@ namespace Deer { bool isDescendantOf(EntityStruct parent); bool opEquals(const EntityStruct& other); + //COMPONENTS + EntityStruct getMeshComponent(); + bool hasMeshComponent(); + void removeMeshComponent(); + // This function can be adapted to get a specific transform since the data is the same EntityStruct getSelf(); }; @@ -65,6 +70,17 @@ namespace Deer { void setRotation(glm::vec3); }; + struct MeshComponentStruct : EntityStruct { + bool check_self(); + + bool isActive(); + bool hasMesh(); + void clear(); + + std::string getMesh(); + void setMesh(std::string&); + }; + EntityStruct getRoot(); void constructEntityStruct(int id, void* memory); void copyEntityStruct(int id, void* memory); diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Resource.h b/DeerStudio/src/DeerStudio/EditorEngine/API/Resource.h index da650cb..cf5831f 100644 --- a/DeerStudio/src/DeerStudio/EditorEngine/API/Resource.h +++ b/DeerStudio/src/DeerStudio/EditorEngine/API/Resource.h @@ -6,7 +6,8 @@ namespace Deer { namespace EditorEngine { enum ResourceType : uint32_t { NOTHING = 0, - MESH = 1 + MESH = 1, + SHADER = 2, }; // Returns the count of meshes in the dir relative to the mesh root dir @@ -23,6 +24,7 @@ namespace Deer { // Returns the name of the subDir in the dir relative to the mesh root dir std::string getDirNameById(ResourceType, std::string& dir, int i); + // INTERNAL const char* getResourcePath(ResourceType); const char* getResourceExtension(ResourceType); const char* getResourceName(ResourceType); diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Debug.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Debug.cpp similarity index 100% rename from DeerStudio/src/DeerStudio/EditorEngine/API/Debug.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Debug.cpp diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Entity.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Entity.cpp similarity index 57% rename from DeerStudio/src/DeerStudio/EditorEngine/API/Entity.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Entity.cpp index 29b3654..2707694 100644 --- a/DeerStudio/src/DeerStudio/EditorEngine/API/Entity.cpp +++ b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Entity.cpp @@ -137,5 +137,99 @@ namespace Deer { return EntityStruct(newEnt.getId()); } + EntityStruct EntityStruct::getMeshComponent() { + Entity& self = GET_ENTITY(entityId); + + if (!self.hasComponent()) { + self.addComponent(); + } + + return *this; + } + + bool EntityStruct::hasMeshComponent() { + Entity& self = GET_ENTITY(entityId); + + return self.hasComponent(); + } + + void EntityStruct::removeMeshComponent() { + Entity& self = GET_ENTITY(entityId); + + if (self.hasComponent()) { + self.removeComponent(); + } + } + + bool MeshComponentStruct::isActive() { + Entity& self = GET_ENTITY(entityId); + + if (!self.hasComponent()) { + DEER_UI_ENGINE_ERROR("Entity {0} has no component Mesh Component", entityId); + + if (currentDockPanelExecution) + currentDockPanelExecution->invalidate(); + return false; + } + + return self.getComponent().isActive(); + } + + bool MeshComponentStruct::hasMesh() { + Entity& self = GET_ENTITY(entityId); + + if (!self.hasComponent()) { + DEER_UI_ENGINE_ERROR("Entity {0} has no component Mesh Component", entityId); + + if (currentDockPanelExecution) + currentDockPanelExecution->invalidate(); + return false; + } + + return self.getComponent().hasMesh(); + } + + void MeshComponentStruct::clear() { + Entity& self = GET_ENTITY(entityId); + + if (!self.hasComponent()) { + DEER_UI_ENGINE_ERROR("Entity {0} has no component Mesh Component", entityId); + + if (currentDockPanelExecution) + currentDockPanelExecution->invalidate(); + return; + } + + return self.removeComponent(); + } + + std::string MeshComponentStruct::getMesh() { + Entity& self = GET_ENTITY(entityId); + + if (!self.hasComponent()) { + DEER_UI_ENGINE_ERROR("Entity {0} has no component Mesh Component", entityId); + + if (currentDockPanelExecution) + currentDockPanelExecution->invalidate(); + return "NULL"; + } + + return self.getComponent().getMeshName(); + } + + void MeshComponentStruct::setMesh(std::string& name) { + Entity& self = GET_ENTITY(entityId); + + if (!self.hasComponent()) { + DEER_UI_ENGINE_ERROR("Entity {0} has no component Mesh Component", entityId); + + if (currentDockPanelExecution) + currentDockPanelExecution->invalidate(); + return; + } + + uint16_t meshId = MeshManager::loadModel(name); + self.getComponent().setMesh(meshId); + } } } \ No newline at end of file diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Entity_Register.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Entity_Register.cpp similarity index 77% rename from DeerStudio/src/DeerStudio/EditorEngine/API/Entity_Register.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Entity_Register.cpp index 3048d74..d135591 100644 --- a/DeerStudio/src/DeerStudio/EditorEngine/API/Entity_Register.cpp +++ b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Entity_Register.cpp @@ -25,6 +25,8 @@ namespace Deer { AS_CHECK(scriptEngine->RegisterObjectType("TransformComponent", sizeof(EntityStruct), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits() | asOBJ_APP_CLASS_ALLINTS)); + AS_CHECK(scriptEngine->RegisterObjectType("MeshComponent", sizeof(EntityStruct), + asOBJ_VALUE | asOBJ_POD | asGetTypeTraits() | asOBJ_APP_CLASS_ALLINTS)); } void registerEntityFunctions() { @@ -120,6 +122,28 @@ namespace Deer { asCALL_THISCALL )); + + AS_CHECK(scriptEngine->RegisterObjectMethod( + "Entity", + "MeshComponent getMeshComponent()", + asMETHOD(EntityStruct, getMeshComponent), + asCALL_THISCALL + )); + + AS_CHECK(scriptEngine->RegisterObjectMethod( + "Entity", + "bool hasMeshComponent()", + asMETHOD(EntityStruct, hasMeshComponent), + asCALL_THISCALL + )); + + AS_CHECK(scriptEngine->RegisterObjectMethod( + "Entity", + "void removeMeshComponent()", + asMETHOD(EntityStruct, removeMeshComponent), + asCALL_THISCALL + )); + AS_CHECK(scriptEngine->RegisterGlobalFunction( "Entity getRoot()", asFUNCTION(getRoot), @@ -140,6 +164,7 @@ namespace Deer { asMETHOD(EntityChildArrayStruct, getChild), asCALL_THISCALL )); + // TRANSFORM COMPONENT AS_CHECK(scriptEngine->RegisterObjectMethod( @@ -183,6 +208,41 @@ namespace Deer { asMETHOD(TransformComponentStruct, setRotation), asCALL_THISCALL )); + + AS_CHECK(scriptEngine->RegisterObjectMethod( + "MeshComponent", + "bool get_isActive() const property", + asMETHOD(MeshComponentStruct, isActive), + asCALL_THISCALL + )); + + AS_CHECK(scriptEngine->RegisterObjectMethod( + "MeshComponent", + "bool get_hasMesh() const property", + asMETHOD(MeshComponentStruct, hasMesh), + asCALL_THISCALL + )); + + AS_CHECK(scriptEngine->RegisterObjectMethod( + "MeshComponent", + "void clear()", + asMETHOD(MeshComponentStruct, clear), + asCALL_THISCALL + )); + + AS_CHECK(scriptEngine->RegisterObjectMethod( + "MeshComponent", + "string getMesh()", + asMETHOD(MeshComponentStruct, getMesh), + asCALL_THISCALL + )); + + AS_CHECK(scriptEngine->RegisterObjectMethod( + "MeshComponent", + "void setMesh(string&in)", + asMETHOD(MeshComponentStruct, setMesh), + asCALL_THISCALL + )); } void registerTransformComponent() { diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Layout.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Layout.cpp similarity index 100% rename from DeerStudio/src/DeerStudio/EditorEngine/API/Layout.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Layout.cpp diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Math.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Math.cpp similarity index 100% rename from DeerStudio/src/DeerStudio/EditorEngine/API/Math.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Math.cpp diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Math_Register.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Math_Register.cpp similarity index 100% rename from DeerStudio/src/DeerStudio/EditorEngine/API/Math_Register.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Math_Register.cpp diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Menu.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Menu.cpp similarity index 100% rename from DeerStudio/src/DeerStudio/EditorEngine/API/Menu.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Menu.cpp diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/Resource.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Resource.cpp similarity index 96% rename from DeerStudio/src/DeerStudio/EditorEngine/API/Resource.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Resource.cpp index ca94dfc..1433d9a 100644 --- a/DeerStudio/src/DeerStudio/EditorEngine/API/Resource.cpp +++ b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/Resource.cpp @@ -15,6 +15,9 @@ namespace Deer { case ResourceType::MESH : return DEER_MESH_PATH; + + case ResourceType::SHADER : + return DEER_SHADER_PATH; } return nullptr; @@ -27,7 +30,10 @@ namespace Deer { return nullptr; case ResourceType::MESH : - return ".dmesh"; + return DEER_MESH_EXTENSION; + + case ResourceType::SHADER : + return DEER_SHADER_EXTENSION; } return nullptr; @@ -41,6 +47,9 @@ namespace Deer { case ResourceType::MESH : return "Mesh"; + + case ResourceType::SHADER : + return "Shader"; } return nullptr; diff --git a/DeerStudio/src/DeerStudio/EditorEngine/API/UI.cpp b/DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/UI.cpp similarity index 100% rename from DeerStudio/src/DeerStudio/EditorEngine/API/UI.cpp rename to DeerStudio/src/DeerStudio/EditorEngine/API_Implementation/UI.cpp diff --git a/DeerStudio/src/DeerStudio/EditorEngine/RegisterStructs.cpp b/DeerStudio/src/DeerStudio/EditorEngine/RegisterStructs.cpp index f567e2c..612e283 100644 --- a/DeerStudio/src/DeerStudio/EditorEngine/RegisterStructs.cpp +++ b/DeerStudio/src/DeerStudio/EditorEngine/RegisterStructs.cpp @@ -11,6 +11,7 @@ namespace Deer { void registerResourceTypeEnum() { AS_RET_CHECK(scriptEngine->RegisterEnum("ResourceType")); AS_CHECK(scriptEngine->RegisterEnumValue("ResourceType", "Mesh", (int)ResourceType::MESH)); + AS_CHECK(scriptEngine->RegisterEnumValue("ResourceType", "Shader", (int)ResourceType::SHADER)); } void registerEditorEngineStructs() { diff --git a/roe/editor/properties/components_render.as b/roe/editor/properties/components_render.as index 98c3e98..153aaa2 100644 --- a/roe/editor/properties/components_render.as +++ b/roe/editor/properties/components_render.as @@ -10,4 +10,13 @@ void renderTransformComponent(any@ data) { transform.position = magicSlider3("Posiiton", position, 0.1); transform.scale = magicSlider3("Scale", scale, 0.1); transform.rotation = magicSlider3("Rotation", rotation, 0.1); +} + +void renderMeshComponent(any@ data) { + Entity entity; + data.retrieve(entity); + + MeshComponent meshComponent = entity.getMeshComponent(); + + text(meshComponent.getMesh()); } \ No newline at end of file diff --git a/roe/editor/properties/properties_pannel.as b/roe/editor/properties/properties_pannel.as index 30ed583..98915d5 100644 --- a/roe/editor/properties/properties_pannel.as +++ b/roe/editor/properties/properties_pannel.as @@ -28,7 +28,10 @@ class PropertiesPannel : DockPanel { space(); componentNode("Transform Component", any(entity), renderTransformComponent); - componentNode("Transform Component 2", any(entity), renderTransformComponent); + + if (entity.hasMeshComponent()) { + componentNode("Mesh Component", any(entity), renderMeshComponent); + } space(); diff --git a/roe/editor/shader_explorer.as b/roe/editor/shader_explorer.as new file mode 100644 index 0000000..ab1f466 --- /dev/null +++ b/roe/editor/shader_explorer.as @@ -0,0 +1,41 @@ +class ShaderExplorer : DockPanel { + string currentPath = ""; + + void onRender() { + setupAutomaticColumns(128); + + // To avoid problems we will cache the current path + const string cache_currentPath = currentPath; + if (cache_currentPath != "") { + drawIconCentered("folder", 64); + if (isItemClicked(0) and isMouseDoubleClicked(0)) { + currentPath = ""; + } + textCenter(cache_currentPath + "/.."); + nextColumn(); + } + + ResourceType resourceType = ResourceType::Shader; + int dirCount = getDirCount(resourceType, cache_currentPath); + for (int i = 0; i < dirCount; i++) { + drawIconCentered("folder", 64); + + if (isItemClicked(0) and isMouseDoubleClicked(0)) { + print(getDirPathById(resourceType, cache_currentPath, i)); + currentPath = getDirPathById(resourceType, cache_currentPath, i); + } + + textCenter(getDirNameById(resourceType, cache_currentPath, i)); + nextColumn(); + } + + int meshCount = getResourceCount(resourceType, cache_currentPath); + for (int i = 0; i < meshCount; i++) { + drawIconCentered("file", 64); + + textCenter(getResourceNameById(resourceType, cache_currentPath, i)); + nextColumn(); + } + endColumns(); + } +} \ No newline at end of file diff --git a/roe/imgui.ini b/roe/imgui.ini index 3b55db0..5d229d0 100644 --- a/roe/imgui.ini +++ b/roe/imgui.ini @@ -90,6 +90,12 @@ Size=338,429 Collapsed=0 DockId=0x00000004,1 +[Window][ShaderExplorer] +Pos=0,500 +Size=1280,220 +Collapsed=0 +DockId=0x00000008,1 + [Docking][Data] DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,24 Size=1280,696 Split=Y DockNode ID=0x00000007 Parent=0xA1672E74 SizeRef=1280,474 Split=Y @@ -97,7 +103,7 @@ DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,24 Size=1280,696 Split=Y DockNode ID=0x00000003 Parent=0x00000001 SizeRef=878,338 Split=X Selected=0x13926F0B DockNode ID=0x00000005 Parent=0x00000003 SizeRef=256,446 Selected=0xE45B9F93 DockNode ID=0x00000006 Parent=0x00000003 SizeRef=620,446 CentralNode=1 Selected=0x13926F0B - DockNode ID=0x00000004 Parent=0x00000001 SizeRef=400,338 Selected=0x2A2C795E + DockNode ID=0x00000004 Parent=0x00000001 SizeRef=400,338 Selected=0xA35A27E3 DockNode ID=0x00000002 Parent=0x00000007 SizeRef=2560,331 Selected=0xCF339702 DockNode ID=0x00000008 Parent=0xA1672E74 SizeRef=1280,220 Selected=0xD962995A