Not working yet

This commit is contained in:
Alier 2025-05-15 19:37:34 +02:00
parent ddce1caaed
commit a65c2bc262
18 changed files with 50 additions and 592 deletions

View File

@ -35,7 +35,7 @@ namespace Deer {
ComponentScriptInstance() = default;
~ComponentScriptInstance();
void tick();
void tickExecution();
void start();
asIScriptObject* m_object;

View File

@ -18,6 +18,7 @@
#define DEER_MESH_EXTENSION ".dmesh"
#define DEER_SHADER_EXTENSION ".glsl"
#define DEER_SCRIPT_EXTENSION ".as"
#define DEER_BIN_PATH "bin"
#define DEER_TEMP_PATH "tmp"

View File

@ -148,7 +148,7 @@ namespace Deer {
glm::mat4 getWorldMatrix();
glm::mat4 getRelativeMatrix();
void tick();
void tickExecution();
inline bool isValid() const { return m_exists; }

View File

@ -10,6 +10,7 @@
#include <string>
#include <vector>
#include <array>
#include <stdint.h>
namespace Deer {
class Environment;
@ -18,16 +19,17 @@ namespace Deer {
// A scene is a 3d simulation with its environment and voxel world in case
// of initialized, here things can be simulated
namespace Scene {
// Resets all scene to 0 but conserving the memory making it much faster
// than creating another instance
// Clears all the assets and memory the Scene had conained
void clear();
// This is the cycle to execution
void beginExecution();
void tick();
// This is the cycle to execution of scripts and physics
void initExecution();
void tickExecution();
void endExecution();
bool getExecutingState();
uint32_t getCurrentExTick();
#ifdef DEER_RENDER
// This function renders with the default camera in the environment
void render();

61
Deer/Include/Deer/ScriptEngine.h Executable file → Normal file
View File

@ -1,47 +1,36 @@
#pragma once
#include <filesystem>
#include <stdint.h>
#include <string>
#include <unordered_map>
#include <vector>
#include "Deer/ComponentScript.h"
#include "Deer/Memory.h"
class asIScriptEngine;
class asIScriptModule;
class asIScriptContext;
class asIScriptFunction;
class asITypeInfo;
class asIScriptObject;
class asIScriptFunction;
namespace Deer {
class Entity;
class ComponentScript;
namespace ScriptEngine {
struct ComponentScript {
public:
ComponentScript(asITypeInfo* type);
using ComponentScriptMap = std::unordered_map<std::string, ComponentScript>;
void initialize();
void tick();
private:
asITypeInfo* scriptType;
asIScriptFunction* startFunction;
asIScriptFunction* updateFunction;
};
namespace ScriptEngine {
extern asIScriptContext* m_context;
extern bool m_isCompilationValid;
extern ComponentScriptMap m_componentScripts;
void loadScripts();
void unloadScripts();
void compileScriptEngine(const std::filesystem::path& scriptPath);
void shutdownScriptEngine();
void initializeExecution();
void tickExecution();
void endExecution();
void beginExecutionContext();
void endExecutionContext();
void clearComponentScripts();
inline asIScriptContext* getExecutionContext() { return m_context; }
inline bool isCompilationValid() { return m_isCompilationValid; }
inline ComponentScriptMap& getComponentScripts() {
return m_componentScripts;
}
inline ComponentScript& getComponentScript(
const std::string& scriptID) {
return m_componentScripts[scriptID];
}
Ref<ComponentScriptInstance> createComponentScriptInstance(
const std::string& scriptID, Entity& scriptEntity);
} // namespace ScriptEngine
} // namespace Deer
ComponentScript& getComponentScript(uint16_t);
ComponentScript& createComponentScript(const std::string& scriptName);
void destroyComponentScript(uint16_t);
}
}

View File

@ -94,7 +94,7 @@ namespace Deer {
RenderCommand::setClearColor({ 0.2f, 0.2f, 0.3f, 1.0f });
RenderCommand::clear();
Render::beginExecution();
Render::initExecution();
onRender(Timestep((float)targetRenderTime));
Render::endExecution();

View File

@ -12,7 +12,6 @@
#include "Deer/Voxels/VoxelWorldData.h"
#include "Deer/Enviroment.h"
#include "Deer/Scene/SceneData.h"
#ifdef DEER_RENDER
@ -26,6 +25,7 @@ namespace Deer {
void Scene::clear() {
environment.clear();
VoxelWorld::clear();
#ifdef DEER_RENDER
MeshManager::unloadAllModels();
ShaderManager::unloadAllShaders();
@ -37,33 +37,17 @@ namespace Deer {
return isExecuting;
}
void Scene::beginExecution() {
void Scene::initExecution() {
DEER_CORE_ASSERT(!isExecuting, "Deer scene is already executing");
isExecuting = true;
DEER_CORE_INFO("Executing Scene...");
ScriptEngine::beginExecutionContext();
// Instantiate all the scripts
auto view = environment.m_registry.view<ScriptComponent, TagComponent>();
for (auto& entID : view) {
auto& tagComponent = view.get<TagComponent>(entID);
auto& componentScript = view.get<ScriptComponent>(entID);
Entity& entity = environment.getEntity(tagComponent.entityUID);
componentScript.roeInstance =
ScriptEngine::createComponentScriptInstance(componentScript.scriptID, entity);
componentScript.roeInstance->start();
}
}
void Scene::tick() {
void Scene::tickExecution() {
// Update all scripts
auto view = environment.m_registry.view<ScriptComponent>();
for (auto& entID : view) {
auto& componentScript = view.get<ScriptComponent>(entID);
componentScript.roeInstance->tick();
componentScript.roeInstance->tickExecution();
}
}

View File

@ -1,41 +0,0 @@
#include "Deer/ComponentScript.h"
#include "angelscript.h"
#include "Deer/Log.h"
#include "Deer/ScriptEngine.h"
#include "angelscript.h"
namespace Deer {
ComponentScript::ComponentScript(asITypeInfo* typeInfo)
: m_typeInfo(typeInfo) {
m_scriptID = m_typeInfo->GetName();
m_attributes = extractAttributes(typeInfo);
}
ComponentScriptInstance::~ComponentScriptInstance() {
m_object->Release();
}
void ComponentScriptInstance::tick() {
if (!m_updateFunction)
return;
asIScriptContext* context = ScriptEngine::getExecutionContext();
context->Prepare(m_updateFunction);
context->SetObject(m_object);
context->Execute();
}
void ComponentScriptInstance::start() {
if (!m_startFuction)
return;
asIScriptContext* context = ScriptEngine::getExecutionContext();
context->Prepare(m_startFuction);
context->SetObject(m_object);
context->Execute();
}
}

View File

@ -1,24 +0,0 @@
#include "Deer/ComponentScript.h"
#include "Deer/Log.h"
#include "angelscript.h"
namespace Deer {
ScriptAttributeMap extractAttributes(asITypeInfo* typeInfo) {
ScriptAttributeMap m_attributes;
int atributes = typeInfo->GetPropertyCount();
for (int x = 0; x < atributes; x++) {
const char* name;
bool isPrivate;
int typeID;
int offset;
typeInfo->GetProperty(x, &name, &typeID, &isPrivate, nullptr, &offset);
ScriptAttribute attribute(name, typeID, isPrivate, offset, x);
m_attributes.insert({ std::string(name), attribute});
}
return m_attributes;
}
}

View File

@ -1,172 +0,0 @@
#include "Deer/ScriptEngine.h"
#include <filesystem>
#include "Deer/ComponentScript.h"
#include "Deer/Enviroment.h"
#include "Deer/Log.h"
#include "Deer/Scene.h"
#include "ScriptEngineFunctions.h"
#include "angelscript.h"
#include "scriptbuilder.h"
#include "scriptmath.h"
#include "scriptstdstring.h"
namespace fs = std::filesystem;
namespace Deer {
namespace ScriptEngine {
asIScriptEngine* m_scriptEngine;
asIScriptModule* m_scriptModule;
bool m_isCompilationValid = false;
asIScriptContext* m_context;
ComponentScriptMap m_componentScripts;
void loadModuleFolder(const std::filesystem::path& modulePath,
const char* moduleName);
void registerBaseComponents();
} // namespace ScriptEngine
void ScriptEngine::shutdownScriptEngine() { m_componentScripts.clear(); }
void ScriptEngine::beginExecutionContext() {
m_context = m_scriptEngine->CreateContext();
}
void ScriptEngine::endExecutionContext() { m_context->Release(); }
void ScriptEngine::compileScriptEngine(
const std::filesystem::path& modulePath) {
m_scriptEngine = asCreateScriptEngine();
m_isCompilationValid = true;
registerBaseComponents();
loadModuleFolder(modulePath, "Deer");
m_scriptModule = m_scriptEngine->GetModule("Deer");
asITypeInfo* m_deerScript =
m_scriptModule->GetTypeInfoByName("ComponentScript");
int classCount = m_scriptModule->GetObjectTypeCount();
for (int i = 0; i < classCount; i++) {
asITypeInfo* type = m_scriptModule->GetObjectTypeByIndex(i);
asITypeInfo* parent = type->GetBaseType();
std::string scriptID = type->GetName();
if (parent == m_deerScript) {
ComponentScript componentScript(type);
m_componentScripts.insert({scriptID, componentScript});
}
}
}
Ref<ComponentScriptInstance> ScriptEngine::createComponentScriptInstance(
const std::string& scriptID, Entity& scriptEntity) {
ComponentScript& script = getComponentScript(scriptID);
asITypeInfo* type = script.getTypeInfo();
ComponentScriptInstance* instance = new ComponentScriptInstance();
std::string factoryString(script.getName());
factoryString = factoryString + " @" + script.getName() + "()";
asIScriptFunction* function =
type->GetFactoryByDecl(factoryString.c_str());
if (!function) {
DEER_SCRIPT_ERROR("Function constructor not found for class {0}",
script.getName());
return nullptr;
}
int r = m_context->Prepare(function);
if (r < 0) {
DEER_SCRIPT_ERROR(
"Failed to prepare constructor context for class {0}",
script.getName());
return nullptr;
}
r = m_context->Execute();
if (r < 0) {
DEER_SCRIPT_ERROR("Failed to execute constructor for class {0}",
script.getName());
return nullptr;
}
asIScriptObject* obj =
*(asIScriptObject**)m_context->GetAddressOfReturnValue();
obj->AddRef();
int entityPosition = script.getAttribute("entity").internalID;
unsigned int* entityValue =
(unsigned int*)obj->GetAddressOfProperty(entityPosition);
*entityValue = scriptEntity.getId();
asIScriptFunction* updateFunction =
type->GetMethodByDecl("void update()");
asIScriptFunction* startFunction =
type->GetMethodByDecl("void start()");
instance->m_updateFunction = updateFunction;
instance->m_startFuction = startFunction;
instance->m_object = obj;
return Ref<ComponentScriptInstance>(instance);
}
void ScriptEngine::loadModuleFolder(const std::filesystem::path& modulePath,
const char* moduleName) {
CScriptBuilder builder;
int r = builder.StartNewModule(m_scriptEngine, moduleName);
DEER_SCRIPT_ASSERT(
r >= 0, "Unrecoverable error while starting a new module. {0}",
moduleName);
try {
DEER_CORE_TRACE("Loading Scripts ");
for (const auto& entry :
fs::recursive_directory_iterator(modulePath)) {
if (fs::is_regular_file(entry) &&
entry.path().extension() == ".as") {
r = builder.AddSectionFromFile(
entry.path().generic_string().c_str());
DEER_SCRIPT_ASSERT(r >= 0,
"Please correct the errors in the "
"script and try again. {0}",
entry.path().generic_string().c_str());
//DEER_CORE_TRACE(" {0}",
// entry.path().filename().string().c_str());
}
}
} catch (const fs::filesystem_error& e) {
DEER_CORE_ERROR("Error while loading scripts, error: {0}",
e.what());
}
r = builder.BuildModule();
if (r < 0) {
DEER_SCRIPT_INFO(
"Please correct the errors in the script and try again.");
m_isCompilationValid = false;
}
}
void ScriptEngine::registerBaseComponents() {
RegisterStdString(m_scriptEngine);
RegisterScriptMath(m_scriptEngine);
// Regist data types
registerEntity(m_scriptEngine);
registerVec3(m_scriptEngine);
// Regist functions
registerDeerFunctions(m_scriptEngine);
registerInputFunctions(m_scriptEngine);
registerEntityTransformFunctions(m_scriptEngine);
}
} // namespace Deer

View File

@ -1,249 +0,0 @@
#include "ScriptEngineFunctions.h"
#include "Deer/Enviroment.h"
#include "Deer/Log.h"
#include "Deer/Scene.h"
#include "Deer/ScriptEngine.h"
#include "DeerRender/Input.h"
#include "angelscript.h"
#include "glm/glm.hpp"
namespace Deer {
void messageCallback(const asSMessageInfo* msg, void* param) {
if (msg->type == asMSGTYPE_WARNING) {
DEER_SCRIPT_WARN("({0} {1}) : {2} {3}", msg->row, msg->col,
msg->message, msg->section);
} else if (msg->type == asMSGTYPE_ERROR) {
DEER_SCRIPT_ERROR("({0} {1}) : {2} {3}", msg->row, msg->col,
msg->message, msg->section);
} else if (msg->type == asMSGTYPE_INFORMATION) {
DEER_SCRIPT_INFO("({0} {1}) : {2} {3}", msg->row, msg->col,
msg->message, msg->section);
} else {
DEER_SCRIPT_WARN("({0} {1}) : {2} {3}", msg->row, msg->col,
msg->message, msg->section);
}
}
void print(std::string& msg) { DEER_SCRIPT_INFO(msg.c_str()); }
glm::vec3 getEntityPosition(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return glm::vec3();
}
Environment& m_environment = Scene::environment;
Entity& entt = m_environment.getEntity(entityUID);
return entt.getComponent<TransformComponent>().position;
}
void setEntityPosition(glm::vec3 position, uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return;
}
Environment& m_environment = Scene::environment;
Entity& entt = m_environment.getEntity(entityUID);
entt.getComponent<TransformComponent>().position = position;
}
glm::vec3 getEntityScale(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return glm::vec3();
}
Environment& m_environment = Scene::environment;
Entity& entt = m_environment.getEntity(entityUID);
return entt.getComponent<TransformComponent>().scale;
}
void setEntityScale(glm::vec3 scale, uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return;
}
Environment& m_environment = Scene::environment;
Entity& entt = m_environment.getEntity(entityUID);
entt.getComponent<TransformComponent>().scale = scale;
}
uint32_t getEntityParent(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) {
DEER_SCRIPT_ERROR("Entity is not invalid");
return 0;
}
Environment& m_environment = Scene::environment;
Entity& entt = m_environment.getEntity(entityUID);
return entt.getParentId();
}
bool isEntityValid(uint32_t& entityUID) {
if (entityUID == 0 || entityUID == 1) return false;
Environment& m_environment = Scene::environment;
Entity& entt = m_environment.getEntity(entityUID);
return entt.isValid();
}
void registerVec3(asIScriptEngine* engine) {
engine->RegisterObjectType("Vec3", sizeof(glm::vec3),
asOBJ_VALUE | asOBJ_POD |
asGetTypeTraits<glm::vec3>() |
asOBJ_APP_CLASS_ALLFLOATS);
engine->RegisterObjectBehaviour(
"Vec3", asBEHAVE_CONSTRUCT, "void f()",
asFUNCTIONPR([](void* memory) { new (memory) glm::vec3(); },
(void*), void),
asCALL_CDECL_OBJLAST);
engine->RegisterObjectBehaviour(
"Vec3", asBEHAVE_CONSTRUCT, "void f(float, float = 0, float = 0)",
asFUNCTIONPR([](float x, float y, float z,
void* memory) { new (memory) glm::vec3(x, y, z); },
(float, float, float, void*), void),
asCALL_CDECL_OBJLAST);
engine->RegisterObjectProperty("Vec3", "float x",
asOFFSET(glm::vec3, x));
engine->RegisterObjectProperty("Vec3", "float y",
asOFFSET(glm::vec3, y));
engine->RegisterObjectProperty("Vec3", "float z",
asOFFSET(glm::vec3, z));
engine->RegisterObjectMethod(
"Vec3", "Vec3 opAdd(const Vec3 &in) const",
asFUNCTIONPR([](const glm::vec3& a,
const glm::vec3& b) -> glm::vec3 { return a + b; },
(const glm::vec3&, const glm::vec3&), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opSub(const Vec3 &in) const",
asFUNCTIONPR(
[](const glm::vec3& a, const glm::vec3& b) { return a - b; },
(const glm::vec3&, const glm::vec3&), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opMul(float) const",
asFUNCTIONPR(
[](const glm::vec3& a, float scalar) { return a * scalar; },
(const glm::vec3&, float), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opDiv(float) const",
asFUNCTIONPR(
[](const glm::vec3& a, float scalar) { return a / scalar; },
(const glm::vec3&, float), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 normalize() const",
asFUNCTIONPR(glm::normalize, (const glm::vec3&), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "float getMagnitude() const",
asFUNCTIONPR(glm::length, (const glm::vec3&), float),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "Vec3 opNeg() const",
asFUNCTIONPR([](const glm::vec3& a) { return -a; },
(const glm::vec3&), glm::vec3),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod(
"Vec3", "bool opEquals(const Vec3 &in) const",
asFUNCTIONPR(
[](const glm::vec3& a, const glm::vec3& b) { return a == b; },
(const glm::vec3&, const glm::vec3&), bool),
asCALL_CDECL_OBJFIRST);
engine->RegisterObjectMethod("Vec3", "string opImplConv() const",
asFUNCTIONPR(
[](const glm::vec3& a) {
// Example string conversion using
// glm (you may need to format it)
char buffer[64];
snprintf(buffer, sizeof(buffer),
"(%.2f, %.2f, %.2f)", a.x,
a.y, a.z);
return std::string(buffer);
},
(const glm::vec3&), std::string),
asCALL_CDECL_OBJFIRST);
}
void registerEntity(asIScriptEngine* engine) {
engine->RegisterObjectType(
"Entity", sizeof(unsigned int),
asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE);
engine->RegisterObjectProperty("Entity", "uint uint32_t", 0);
engine->RegisterObjectMethod("Entity", "Entity getParent()",
asFUNCTION(Deer::getEntityParent),
asCALL_CDECL_OBJLAST);
engine->RegisterObjectMethod("Entity", "bool isValid()",
asFUNCTION(Deer::isEntityValid),
asCALL_CDECL_OBJLAST);
engine->RegisterGlobalFunction(
"Entity getEntity(uint)",
asFUNCTIONPR([](uint32_t id) { return id; }, (uint32_t), uint32_t),
asCALL_CDECL);
}
void registerDeerFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->SetMessageCallback(
asFUNCTION(Deer::messageCallback), 0, asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up angel script");
r = scriptEngine->RegisterGlobalFunction("void print(const string &in)",
asFUNCTION(Deer::print),
asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0,
"Error in seting up void print(const string &in)");
}
void registerInputFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->RegisterGlobalFunction(
"bool isKeyPressed(int)", asFUNCTION(Deer::Input::isKeyPressed),
asCALL_CDECL);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up bool isKeyPressed(int)");
}
void registerEntityTransformFunctions(asIScriptEngine* scriptEngine) {
int r = scriptEngine->RegisterObjectMethod(
"Entity", "Vec3 getPosition()", asFUNCTION(Deer::getEntityPosition),
asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up Vec3 getPosition()");
scriptEngine->RegisterObjectMethod("Entity", "void setPosition(Vec3)",
asFUNCTION(Deer::setEntityPosition),
asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up void setPosition(Vec3)");
r = scriptEngine->RegisterObjectMethod("Entity", "Vec3 getScale()",
asFUNCTION(Deer::getEntityScale),
asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up Vec3 getScale()");
scriptEngine->RegisterObjectMethod("Entity", "void setScale(Vec3)",
asFUNCTION(Deer::setEntityScale),
asCALL_CDECL_OBJLAST);
DEER_SCRIPT_ASSERT(r >= 0, "Error in seting up void setScale(Vec3)");
}
} // namespace Deer

View File

@ -1,32 +0,0 @@
#pragma once
#include <string>
#include "glm/glm.hpp"
struct asSMessageInfo;
class asIScriptEngine;
namespace Deer {
void messageCallback(const asSMessageInfo* msg, void* param);
void print(std::string& msg);
// Entity Transformations -------------
glm::vec3 getEntityPosition(uint32_t& entityUID);
void setEntityPosition(glm::vec3 position, uint32_t& entityUID);
glm::vec3 getEntityScale(uint32_t& entityUID);
void setEntityScale(glm::vec3 scale, uint32_t& entityUID);
// Entity Transformations -------------
// Entity Relationship ------------
uint32_t getEntityParent(uint32_t& entityUID);
bool isEntityValid(uint32_t& entityUID);
// Entity Relationship ------------
void registerVec3(asIScriptEngine* engine);
void registerEntity(asIScriptEngine* engine);
void registerDeerFunctions(asIScriptEngine* scriptEngine);
void registerInputFunctions(asIScriptEngine* scriptEngine);
void registerEntityTransformFunctions(asIScriptEngine* scriptEngine);
}

View File

@ -4,7 +4,7 @@
#include "DeerRender/Render/RenderAPI.h"
namespace Deer {
void Render::beginExecution() {
void Render::initExecution() {
}

View File

@ -6,7 +6,7 @@ namespace Deer {
class Render {
public:
static void beginExecution();
static void initExecution();
static void endExecution();
static void submit(VertexArray& vertexArray);

View File

@ -76,7 +76,7 @@ namespace Deer {
void DeerStudioApplication::onUpdate(Timestep delta) {
if (Scene::getExecutingState())
Scene::tick();
Scene::tickExecution();
if (VoxelWorld::isInitialized())
VoxelWorld::bakeNextChunk();

View File

@ -30,7 +30,7 @@ namespace Deer {
if (ScriptEngine::isCompilationValid() &&
ImGui::Button("Execute")) {
DataStore::exportRuntimeScene();
Scene::beginExecution();
Scene::initExecution();
}
} else {
if (ImGui::Button("Stop")) {
@ -78,7 +78,7 @@ namespace Deer {
if (ScriptEngine::isCompilationValid() &&
ImGui::Button("Execute")) {
DataStore::exportRuntimeScene();
Scene::beginExecution();
Scene::initExecution();
}
} else {
if (ImGui::Button("Stop")) {

View File

@ -36,7 +36,7 @@ DockId=0x00000004,0
Pos=377,24
Size=532,462
Collapsed=0
DockId=0x00000006,2
DockId=0x00000006,1
[Window][Scene Explorer]
Pos=0,389
@ -97,10 +97,10 @@ Collapsed=0
DockId=0x00000008,1
[Window][Test]
Pos=377,24
Size=532,462
Pos=911,24
Size=369,462
Collapsed=0
DockId=0x00000006,1
DockId=0x00000004,2
[Docking][Data]
DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,24 Size=1280,696 Split=Y
@ -109,7 +109,7 @@ DockSpace ID=0xA1672E74 Window=0x4647B76E Pos=0,24 Size=1280,696 Split=Y
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=909,338 Split=X Selected=0x13926F0B
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=375,446 Selected=0xE45B9F93
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=532,446 CentralNode=1 Selected=0x13926F0B
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=369,338 Selected=0xA35A27E3
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=369,338 Selected=0x44A6A033
DockNode ID=0x00000002 Parent=0x00000007 SizeRef=2560,331 Selected=0xCF339702
DockNode ID=0x00000008 Parent=0xA1672E74 SizeRef=1280,232 Selected=0xD962995A

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB