diff --git a/.gitignore b/.gitignore index f14bb3fa..69048e50 100644 --- a/.gitignore +++ b/.gitignore @@ -789,6 +789,8 @@ ASALocalRun/ # MFractors (Xamarin productivity tool) working folder .mfractor/ +./bin +./bin-int/ # Local History for Visual Studio .localhistory/ diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp index 5a728644..cf7a6533 100644 --- a/Editor/Editor.cpp +++ b/Editor/Editor.cpp @@ -86,15 +86,15 @@ public: void OnUpdate(Timestep ts) { - if (Input::IsKeyPress(GLFW_KEY_W)) + if (Input::IsKeyDown(GLFW_KEY_W)) velocity.z = 5.0f; - else if (Input::IsKeyPress(GLFW_KEY_S)) + else if (Input::IsKeyDown(GLFW_KEY_S)) velocity.z = -5.0f; else velocity.z = 0.0f; - if (Input::IsKeyPress(GLFW_KEY_A)) + if (Input::IsKeyDown(GLFW_KEY_A)) velocity.x = 5.0f; - else if (Input::IsKeyPress(GLFW_KEY_D)) + else if (Input::IsKeyDown(GLFW_KEY_D)) velocity.x = -5.0f; else velocity.x = 0.0f; @@ -159,16 +159,18 @@ int main() while (!Engine::GetCurrentWindow()->ShouldClose()) { + Engine::Tick(); + Engine::Draw(); - if (Input::IsKeyPress(GLFW_KEY_F8)) + if (Input::IsKeyPressed(GLFW_KEY_F8)) Engine::ExitPlayMode(); editor.Draw(); Engine::EndDraw(); - Engine::Tick(); + } Engine::Close(); diff --git a/Editor/resources/Interface/Testing.css b/Editor/resources/Interface/Testing.css index ef92915e..2eead7f5 100644 --- a/Editor/resources/Interface/Testing.css +++ b/Editor/resources/Interface/Testing.css @@ -1,6 +1,8 @@ -.button { - width: 100%; - height: 100%; + + +.hello{ + width: 400px; + height: 200px; } .screen{ @@ -8,20 +10,11 @@ width: 100%; justify-content: center; flex-direction: row; - align-content:flex-end; + align-content:flex-start; } -.container { - height: 50px; - width: 50%; - flex-direction: row; - justify-content: space-between; - align-content: center; - align-self:center; - padding: 8px; -} +.rect{ + height: 200px; + width: 200px; -.items{ - height: 30px; - width: 30px; } diff --git a/Editor/resources/Interface/Testing.interface b/Editor/resources/Interface/Testing.interface index c8a25d58..c12e00d1 100644 --- a/Editor/resources/Interface/Testing.interface +++ b/Editor/resources/Interface/Testing.interface @@ -1,23 +1,12 @@ - -

Hello world!

- - - - - - - - - - +

Hello, world

+ +
diff --git a/Editor/resources/Scenes/level.scene b/Editor/resources/Scenes/level.scene new file mode 100644 index 00000000..fbddfefa --- /dev/null +++ b/Editor/resources/Scenes/level.scene @@ -0,0 +1,62 @@ +{ + "Entities": [ + { + "GetComponent()": { + "Name": "Camera" + }, + "GetComponent()": { + "HasParent": false, + "Type": "ParentComponent" + }, + "GetComponent()": { + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + }, + "Translation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Type": "TransformComponent" + } + } + ], + "Name": "", + "m_Environement": { + "AmbientColor": { + "w": 1.0141871010880041e-38, + "x": 4.489836626909252e+21, + "y": 7.618957098799247e+31, + "z": 1.0141871010880041e-38 + }, + "ProceduralSkybox": { + "AtmosphereRadius": 6380000.0, + "MieScattering": { + "x": 1.9999999494757503e-05, + "y": 1.9999999494757503e-05, + "z": 1.9999999494757503e-05 + }, + "RayleighScattering": { + "x": 5.80000005356851e-06, + "y": 1.3500000022759195e-05, + "z": 3.310000101919286e-05 + }, + "SunDirection": { + "x": 0.20000000298023224, + "y": 0.9591699838638306, + "z": 0.20000000298023224 + }, + "SunIntensity": 100.0, + "SurfaceRadius": 6360000.0 + }, + "VolumetricFog": 0.949999988079071, + "VolumetricStepCount": 100.0 + } +} \ No newline at end of file diff --git a/Editor/resources/Scenes/test.scene b/Editor/resources/Scenes/test.scene new file mode 100644 index 00000000..e2584be9 --- /dev/null +++ b/Editor/resources/Scenes/test.scene @@ -0,0 +1,108 @@ +{ + "Entities": [ + { + "NameComponent": { + "Name": "Trenchbroom map" + }, + "ParentComponent": { + "HasParent": false + }, + "QuakeMapComponent": { + "HasCollisions": false, + "Path": "C:\\Dev\\Nuake\\Editor\\resources\\Maps\\texture_test.map" + }, + "TransformComponent": { + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + }, + "Translation": { + "x": 9.199999809265137, + "y": 5.599999904632568, + "z": 0.0 + }, + "Type": "TransformComponent" + } + }, + { + "LightComponent": { + "CastShadows": true, + "Color": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + }, + "Direction": { + "x": 0.20000000298023224, + "y": 0.9591699838638306, + "z": 0.20000000298023224 + }, + "IsVolumetric": false, + "Strength": 10.0, + "SyncDirectionWithSky": true, + "Type": 0 + }, + "NameComponent": { + "Name": "Light" + }, + "ParentComponent": { + "HasParent": false + }, + "TransformComponent": { + "Rotation": { + "x": 0.0, + "y": -0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + }, + "Translation": { + "x": 7.035792350769043, + "y": 5.795107364654541, + "z": -0.9431453943252563 + }, + "Type": "TransformComponent" + } + } + ], + "Name": "", + "m_Environement": { + "AmbientColor": { + "w": 0.0, + "x": null, + "y": 0.0, + "z": 0.0 + }, + "ProceduralSkybox": { + "AtmosphereRadius": 6380000.0, + "MieScattering": { + "x": 1.9999999494757503e-05, + "y": 1.9999999494757503e-05, + "z": 1.9999999494757503e-05 + }, + "RayleighScattering": { + "x": 5.80000005356851e-06, + "y": 1.3500000022759195e-05, + "z": 3.310000101919286e-05 + }, + "SunDirection": { + "x": 0.20000000298023224, + "y": 0.9591699838638306, + "z": 0.20000000298023224 + }, + "SunIntensity": 100.0, + "SurfaceRadius": 6360000.0 + }, + "VolumetricFog": 0.949999988079071, + "VolumetricStepCount": 100.0 + } +} \ No newline at end of file diff --git a/Editor/resources/Scenes/test.scene.scene b/Editor/resources/Scenes/test.scene.scene new file mode 100644 index 00000000..0f285f04 --- /dev/null +++ b/Editor/resources/Scenes/test.scene.scene @@ -0,0 +1,70 @@ +{ + "Entities": [ + { + "CameraComponent": { + "CameraInstance": { + "AspectRatio": 1.7777777910232544, + "Exposure": 1.0, + "Fov": 88.0, + "Speed": 1.0, + "m_Type": 1 + } + }, + "NameComponent": { + "Name": "Camera" + }, + "ParentComponent": { + "HasParent": false + }, + "TransformComponent": { + "Rotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Scale": { + "x": 1.0, + "y": 1.0, + "z": 1.0 + }, + "Translation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "Type": "TransformComponent" + } + } + ], + "Name": "", + "m_Environement": { + "AmbientColor": { + "w": 9.275544859982045e-39, + "x": 1.0193902624158886e-38, + "y": 8.449025394560124e-39, + "z": 9.275544859982045e-39 + }, + "ProceduralSkybox": { + "AtmosphereRadius": 6380000.0, + "MieScattering": { + "x": 1.9999999494757503e-05, + "y": 1.9999999494757503e-05, + "z": 1.9999999494757503e-05 + }, + "RayleighScattering": { + "x": 5.80000005356851e-06, + "y": 1.3500000022759195e-05, + "z": 3.310000101919286e-05 + }, + "SunDirection": { + "x": 0.20000000298023224, + "y": 0.9591699838638306, + "z": 0.20000000298023224 + }, + "SunIntensity": 100.0, + "SurfaceRadius": 6360000.0 + }, + "VolumetricFog": 0.949999988079071, + "VolumetricStepCount": 100.0 + } +} \ No newline at end of file diff --git a/Editor/resources/Scripts/Engine.wren b/Editor/resources/Scripts/Engine.wren new file mode 100644 index 00000000..4ccbd944 --- /dev/null +++ b/Editor/resources/Scripts/Engine.wren @@ -0,0 +1,15 @@ +class Engine { + foreign static Log(msg) +} + +class Vector3 { + construct new(x, y, z) { + _x = x + _y = y + _z = z + } +} + +class Entity { + foreign GetComponent(type) +} \ No newline at end of file diff --git a/Editor/resources/Scripts/test.wren b/Editor/resources/Scripts/test.wren new file mode 100644 index 00000000..fc35bfea --- /dev/null +++ b/Editor/resources/Scripts/test.wren @@ -0,0 +1,18 @@ +import "Scripts/Engine" for Engine +class Test { + init() { + System.print("hello init") + } + + update(t) { + System.print("hello update %(t)") + } + + exit() { + System.print("hello exit ") + } + + static hello() { + Engine.Log("Hello from foreign") + } +} \ No newline at end of file diff --git a/Editor/src/EditorInterface.cpp b/Editor/src/EditorInterface.cpp index 49559889..dc84726b 100644 --- a/Editor/src/EditorInterface.cpp +++ b/Editor/src/EditorInterface.cpp @@ -675,10 +675,10 @@ void EditorInterface::DrawDirectoryExplorer() } } - ImGui::EndTable(); + } - + ImGui::EndTable(); } ImGui::End(); } diff --git a/Nuake/Engine.cpp b/Nuake/Engine.cpp index 93fadfb0..23c1ccca 100644 --- a/Nuake/Engine.cpp +++ b/Nuake/Engine.cpp @@ -1,6 +1,8 @@ #include "Engine.h" #include "src/Core/Physics/PhysicsManager.h" #include + +#include "../Core/Input.h" #include "src/Core/FileSystem.h" #include "src/Scripting/ScriptingEngine.h" @@ -47,9 +49,11 @@ void Engine::Tick() // Play mode update vs editor update. if (Engine::IsPlayMode) - GetCurrentScene()->Update(timestep); + CurrentWindow->Update(timestep); else GetCurrentScene()->EditorUpdate(timestep); + + Input::Update(); } void Engine::EnterPlayMode() diff --git a/Nuake/src/Core/FileSystem.cpp b/Nuake/src/Core/FileSystem.cpp index 3bdce5b4..eadf4f07 100644 --- a/Nuake/src/Core/FileSystem.cpp +++ b/Nuake/src/Core/FileSystem.cpp @@ -124,7 +124,7 @@ std::string FileSystem::ReadFile(const std::string& path, bool absolute) // Use a while loop together with the getline() function to read the file line by line while (getline(MyReadFile, fileContent)) { - allFile.append(fileContent); + allFile.append(fileContent + "\n"); } // Close the file diff --git a/Nuake/src/Core/Input.cpp b/Nuake/src/Core/Input.cpp index 7655a32a..043920e2 100644 --- a/Nuake/src/Core/Input.cpp +++ b/Nuake/src/Core/Input.cpp @@ -3,39 +3,70 @@ #include Input* Input::s_Instance; -// TODO: Key press, and release system. +std::map Input::m_Keys = std::map(); +bool Input::m_MouseButtons[5] = { false, false, false, false, false }; +#pragma region Keys +// Only true if the key is currently being pressed +bool Input::IsKeyDown(int keycode) +{ + auto window = Window::Get()->GetHandle(); + int state = glfwGetKey(window, keycode); + bool result = state == GLFW_PRESS; + + m_Keys[keycode] = state; + + return result; +} + +// Only true if the key is pressed for the first frame. no repeat. bool Input::IsKeyPressed(int keycode) { auto window = Window::Get()->GetHandle(); - int state = glfwGetKey(window, keycode); + bool result = state == GLFW_PRESS; - return state == GLFW_PRESS || state == GLFW_REPEAT; + // First time pressed? + if (m_Keys.find(keycode) == m_Keys.end() || m_Keys[keycode] == false) + { + if (result) + m_Keys[keycode] = true; + + return result; + } + + return false; } -bool Input::IsKeyPress(int keycode) -{ - auto window = Window::Get()->GetHandle(); - int state = glfwGetKey(window, keycode); - return state == GLFW_PRESS; -} bool Input::IsKeyReleased(int keycode) { auto window = Window::Get()->GetHandle(); int state = glfwGetKey(window, keycode); - return state == GLFW_RELEASE; -} + bool result = state == GLFW_RELEASE; + // First time pressed? + if (m_Keys.find(keycode) == m_Keys.end()) + return result; + + if (result && m_Keys[keycode] == true) + { + return true; + } + + + return false; +} +#pragma endregion + +#pragma region Mouse + +// Visibility void Input::HideMouse() { auto window = Window::Get()->GetHandle(); glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); } - - -// TODO: Rename bool Input::IsMouseHidden() { auto window = Window::Get()->GetHandle(); return glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED; @@ -46,7 +77,9 @@ void Input::ShowMouse() { glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } -bool Input::IsMouseButtonPressed(int button) + +// Action +bool Input::IsMouseButtonDown(int button) { auto window = Window::Get()->GetHandle(); auto state = glfwGetMouseButton(window, button); @@ -54,6 +87,29 @@ bool Input::IsMouseButtonPressed(int button) return state == GLFW_PRESS; } +bool Input::IsMouseButtonPressed(int button) +{ + auto window = Window::Get()->GetHandle(); + auto state = glfwGetMouseButton(window, button); + + if (m_MouseButtons[button] == false && state == GLFW_PRESS) + { + m_MouseButtons[button] = true; + return true; + } + + return false; +} + +bool Input::IsMouseButtonReleased(int button) +{ + auto window = Window::Get()->GetHandle(); + auto state = glfwGetMouseButton(window, button); + + return state == GLFW_RELEASE && m_MouseButtons[button] == true; +} + +// Position float Input::GetMouseX() { auto window = Window::Get()->GetHandle(); @@ -74,15 +130,16 @@ float Input::GetMouseY() return (float)ypos; } -std::pair Input::GetMousePosition() +Vector2 Input::GetMousePosition() { auto window = Window::Get()->GetHandle(); double xpos, ypos; glfwGetCursorPos(window, &xpos, &ypos); - return { (float)xpos, (float)ypos }; + return Vector2(xpos, ypos); } +#pragma endregion bool Input::Init() { @@ -91,4 +148,20 @@ bool Input::Init() return false; } +void Input::Update() +{ + // Reset all input to false. + for (auto& k : m_Keys) + { + if(!IsKeyDown(k.first)) + k.second = false; + } + + for (int i = 0; i < 5; i++) + { + if(!IsMouseButtonDown(i)) + m_MouseButtons[i] = false; + } +} + diff --git a/Nuake/src/Core/Input.h b/Nuake/src/Core/Input.h index 382b6d86..d3dd7c50 100644 --- a/Nuake/src/Core/Input.h +++ b/Nuake/src/Core/Input.h @@ -1,25 +1,31 @@ #pragma once #include - - +#include "../Core/Maths.h" +#include class Input { +private: + static bool m_MouseButtons[5]; + static std::map m_Keys; public: static bool IsKeyPressed(int keycode); - static bool IsKeyPress(int keycode); + static bool IsKeyDown(int keycode); static bool IsKeyReleased(int keycode); - static bool IsMouseButtonPressed(int button); - + static void HideMouse(); static void ShowMouse(); static bool IsMouseHidden(); + static bool IsMouseButtonPressed(int button); + static bool IsMouseButtonDown(int button); + static bool IsMouseButtonReleased(int button); static float GetMouseX(); static float GetMouseY(); - static std::pair GetMousePosition(); + static Vector2 GetMousePosition(); static bool Init(); + static void Update(); Input* Get() { return s_Instance; } diff --git a/Nuake/src/Rendering/Renderer2D.cpp b/Nuake/src/Rendering/Renderer2D.cpp index d9018ddd..61eaae8a 100644 --- a/Nuake/src/Rendering/Renderer2D.cpp +++ b/Nuake/src/Rendering/Renderer2D.cpp @@ -76,25 +76,33 @@ void Renderer2D::DrawString(const std::string& str, TextStyle style, Matrix4 mod style.font->FontAtlas->Bind(5); TextShader->SetUniform1i("msdf", 5); + + float lineHeight = 0.0f; for (char const& c : str) { Char& letter = style.font->GetChar((int)c); - Matrix4 mat = Matrix4(1.0f); - mat = glm::translate(model, Vector3(advance, (letter.PlaneBounds.top * style.fontSize), 0.f)); + if (letter.PlaneBounds.top - letter.PlaneBounds.bottom > lineHeight) + lineHeight = letter.PlaneBounds.top - letter.PlaneBounds.bottom ; + } + + lineHeight *= style.fontSize; + + for (char const& c : str) { + Char& letter = style.font->GetChar((int)c); + Matrix4 mat = glm::translate(model, Vector3(advance, -(letter.PlaneBounds.top) + (lineHeight), 0.f)); float scaleX = letter.PlaneBounds.right - letter.PlaneBounds.left; float scaleY = letter.PlaneBounds.top - letter.PlaneBounds.bottom; - mat = glm::scale(mat, Vector3(scaleX * style.fontSize, scaleY * style.fontSize, 0.f)); - + mat = glm::scale(mat, Vector3(scaleX, scaleY, 0.f)); TextShader->SetUniform2f("texPos", letter.AtlasBounds.Pos.x, letter.AtlasBounds.Pos.y); TextShader->SetUniform2f("texScale", letter.AtlasBounds.Size.x, letter.AtlasBounds.Size.y); TextShader->SetUniformMat4f("model", mat); //TextShader->SetUniform4f("bgColor", 0, 0, 1, 1); - TextShader->SetUniform4f("bgColor", 0.f, 0.f, 0.f, 0.f); + TextShader->SetUniform4f("bgColor", 1.f, 0.f, 0.f, 0.f); TextShader->SetUniform4f("fgColor", 1.f, 1.f, 1.f, 1.f); //TextShader->SetUniform1f("pxRange", 32); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 6); - advance += letter.Advance * style.fontSize; + advance += letter.Advance; } } diff --git a/Nuake/src/Scene/EditorCamera.cpp b/Nuake/src/Scene/EditorCamera.cpp index 9969bd0c..a13d2062 100644 --- a/Nuake/src/Scene/EditorCamera.cpp +++ b/Nuake/src/Scene/EditorCamera.cpp @@ -22,9 +22,9 @@ void EditorCamera::Update(Timestep ts) Input::HideMouse(); // Should probably not have speed binding in here. - if (Input::IsKeyPress(GLFW_KEY_UP)) + if (Input::IsKeyDown(GLFW_KEY_UP)) Speed += 0.1f; - else if (Input::IsKeyPress(GLFW_KEY_DOWN)) + else if (Input::IsKeyDown(GLFW_KEY_DOWN)) Speed -= 0.1f; if (Speed < 0) diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index 1f570469..d1f3a962 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -145,7 +145,6 @@ void Scene::Update(Timestep ts) } - } @@ -155,14 +154,13 @@ void Scene::EditorUpdate(Timestep ts) for (auto i : m_Interfaces) { - //i->Calculate(1280,720); + i->Update(ts); } } void Scene::DrawShadows() { - auto modelView = m_Registry.view(); auto quakeView = m_Registry.view(); auto view = m_Registry.view(); @@ -363,14 +361,10 @@ void Scene::EditorDraw() glDisable(GL_DEPTH_TEST); Ref env = GetEnvironment(); - //if (env->ProceduralSkybox) - //{ - // env->ProceduralSkybox->Draw(m_EditorCamera); - //} - - - - + if (env->ProceduralSkybox) + { + env->ProceduralSkybox->Draw(m_EditorCamera); + } Renderer::m_Shader->Bind(); env->Push(); @@ -406,7 +400,7 @@ void Scene::EditorDraw() Renderer::m_Shader->Bind(); Renderer::m_Shader->SetUniform1i("u_ShowNormal", 0); - /*if (m_EditorCamera) + if (m_EditorCamera) { Renderer::m_Shader->SetUniform1f("u_Exposure", m_EditorCamera->Exposure); @@ -518,9 +512,7 @@ void Scene::EditorDraw() t.Scale = (box.Radius * 2.f) * transform.Scale; Renderer::DrawSphere(t, glm::vec4(0.0f, 0.0f, 0.9f, 0.2f)); } - }*/ - - + } } std::vector Scene::GetAllEntities() { diff --git a/Nuake/src/Scripting/Modules/EngineModule.h b/Nuake/src/Scripting/Modules/EngineModule.h new file mode 100644 index 00000000..ae5664cd --- /dev/null +++ b/Nuake/src/Scripting/Modules/EngineModule.h @@ -0,0 +1,38 @@ +#pragma once +#include "wren.h" +#include +#include +#include "ScriptModule.h" +#include +#include + +namespace ScriptAPI +{ + class EngineModule : public ScriptModule + { + std::string ModuleName = "Engine"; + std::string WrenAPI = "class Engine { \n" + "foreign static Log(msg) \n" + "}" + ""; + + std::string GetModuleName() override + { + return "Engine"; + } + + void RegisterModule(WrenVM* vm) override + { + RegisterMethod("Log(_)", (void*)Log); + WrenInterpretResult result = wrenInterpret(vm, "main", WrenAPI.c_str()); + } + + static void Log(WrenVM* vm) + { + std::string msg = wrenGetSlotString(vm, 1); + Logger::Log(msg); + } + }; + + +} \ No newline at end of file diff --git a/Nuake/src/Scripting/Modules/ScriptModule.h b/Nuake/src/Scripting/Modules/ScriptModule.h new file mode 100644 index 00000000..e8a380d6 --- /dev/null +++ b/Nuake/src/Scripting/Modules/ScriptModule.h @@ -0,0 +1,27 @@ +#pragma once +#include +#include +struct WrenVM; +class ScriptModule +{ +private: + std::map Methods = std::map(); + + std::string WrenAPI; +public: + std::string ModuleName; + virtual void RegisterModule(WrenVM*) = 0; + virtual std::string GetModuleName() = 0; + + void RegisterMethod(const std::string& signature, void* ptr) + { + Methods[signature] = ptr; + } + + void* GetMethodPointer(const std::string& signature) + { + return Methods[signature]; + } + + +}; \ No newline at end of file diff --git a/Nuake/src/Scripting/ScriptLoader.cpp b/Nuake/src/Scripting/ScriptLoader.cpp index d14b0f62..e8ef5a64 100644 --- a/Nuake/src/Scripting/ScriptLoader.cpp +++ b/Nuake/src/Scripting/ScriptLoader.cpp @@ -9,17 +9,7 @@ bool ScriptLoader::RegisterScript(ScriptableEntity* script) bool ScriptLoader::LoadModule(const std::string& path) { - HMODULE loadedLib = LoadLibraryA(path.c_str()); - if (!loadedLib) { - printf("Failed to load library\n"); - return false; - } - - printf("Library loaded\n"); - - ScriptModuleRegister* functionPointer = (ScriptModuleRegister*)GetProcAddress(loadedLib, "Register"); - - functionPointer(); + return true; diff --git a/Nuake/src/Scripting/ScriptLoader.h b/Nuake/src/Scripting/ScriptLoader.h index a226feb1..cbabad8f 100644 --- a/Nuake/src/Scripting/ScriptLoader.h +++ b/Nuake/src/Scripting/ScriptLoader.h @@ -1,6 +1,5 @@ #pragma once -#include "ScriptModule.h" #include #include #include "../Scene/Entities/ScriptableEntity.h" diff --git a/Nuake/src/Scripting/ScriptModule.h b/Nuake/src/Scripting/ScriptModule.h deleted file mode 100644 index 642b0688..00000000 --- a/Nuake/src/Scripting/ScriptModule.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -class ScriptModule -{ -public: - virtual void Register(); -}; diff --git a/Nuake/src/Scripting/ScriptingAPI/HelloWorld.cpp b/Nuake/src/Scripting/ScriptingAPI/HelloWorld.cpp deleted file mode 100644 index 192d5517..00000000 --- a/Nuake/src/Scripting/ScriptingAPI/HelloWorld.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "HelloWorld.h" - - - -int ScriptingAPI::HelloWorld(lua_State* L) -{ - - - return 1; // Successful -} diff --git a/Nuake/src/Scripting/ScriptingAPI/HelloWorld.h b/Nuake/src/Scripting/ScriptingAPI/HelloWorld.h deleted file mode 100644 index c550d2ff..00000000 --- a/Nuake/src/Scripting/ScriptingAPI/HelloWorld.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -struct lua_State; -namespace ScriptingAPI -{ - int HelloWorld(lua_State* L); -} \ No newline at end of file diff --git a/Nuake/src/Scripting/ScriptingEngine.cpp b/Nuake/src/Scripting/ScriptingEngine.cpp index 1165dd51..c88a0535 100644 --- a/Nuake/src/Scripting/ScriptingEngine.cpp +++ b/Nuake/src/Scripting/ScriptingEngine.cpp @@ -1,77 +1,112 @@ #include "ScriptingEngine.h" -#include -#include -#include +#include "WrenScript.h" +#include "../Core/FileSystem.h" +#include +#include +WrenVM* ScriptingEngine::m_WrenVM; -inline void my_panic(sol::optional maybe_msg) { - std::cerr << "Lua script error detected!" << std::endl; - if (maybe_msg) { - const std::string& msg = maybe_msg.value(); - std::cerr << "\terror message: " << msg << std::endl; - } + +std::map> ScriptingEngine::m_Scripts; + +std::map> ScriptingEngine::Modules; + +void errorFn(WrenVM* vm, WrenErrorType errorType, + const char* module, const int line, + const char* msg) +{ + switch (errorType) + { + case WREN_ERROR_COMPILE: + { + printf("[%s line %d] [Error] %s\n", module, line, msg); + } break; + case WREN_ERROR_STACK_TRACE: + { + printf("[%s line %d] in %s\n", module, line, msg); + } break; + case WREN_ERROR_RUNTIME: + { + printf("[Runtime Error] %s\n", msg); + } break; + } } -sol::state ScriptingEngine::lua = sol::state(sol::c_call); + +void writeFn(WrenVM* vm, const char* text) { + printf("%s", text); +} + + +WrenLoadModuleResult myLoadModule(WrenVM* vm, const char* name) { + WrenLoadModuleResult result = { 0 }; + std::string str = FileSystem::ReadFile("resources/" + std::string(name) + ".wren", true); + char* c = strcpy(new char[str.length() + 1], str.c_str()); + result.source = c; + return result; +} + +Ref ScriptingEngine::RegisterScript(const std::string& path, const std::string& mod) +{ + std::string query = "import \"" + path + "\" for " + mod; + wrenInterpret(m_WrenVM, "main", query.c_str()); + return CreateRef(path, mod); +} + +void ScriptingEngine::RegisterModule(Ref scriptModule) +{ + Modules[scriptModule->GetModuleName()] = scriptModule; + scriptModule->RegisterModule(m_WrenVM); +} + + +void ScriptingEngine::InitScript(Ref script) +{ + script->CallInit(); +} + +void ScriptingEngine::UpdateScript(Ref script, Timestep timestep) +{ + script->CallUpdate(timestep); +} + +void ScriptingEngine::ExitScript(Ref script) +{ + script->CallExit(); +} void ScriptingEngine::Init() { - lua.open_libraries(sol::lib::base, sol::lib::package); + m_Scripts = std::map>(); + WrenConfiguration config; + wrenInitConfiguration(&config); + config.loadModuleFn = &myLoadModule; + config.errorFn = &errorFn; + config.writeFn = &writeFn; + config.bindForeignMethodFn = &bindForeignMethod; + m_WrenVM = wrenNewVM(&config); + + Ref engineModule = CreateRef(); + RegisterModule(engineModule); } -void ScriptingEngine::RunFile(const std::string& path) -{ - -} - -void ScriptingEngine::RunCode(const std::string& code) -{ - lua.script(code); - bool isfullscreen = lua["config"]["fullscreen"]; - sol::table config = lua["config"]; - float x = lua["config"]["resolution"]["x"]; - return; - -} - -void ScriptingEngine::UpdateScript(const std::string& path) -{ - std::string fileContent; - std::string allFile = ""; - // Read from the text file - std::ifstream MyReadFile("resources/Scripts/test.lua"); - - // Use a while loop together with the getline() function to read the file line by line - while (getline(MyReadFile, fileContent)) { - allFile.append(fileContent); - } - - // Close the file - MyReadFile.close(); - - try { - auto bad_code_result = lua.script(allFile); - // it did not work - if (!bad_code_result.valid()) - { - printf(std::to_string((int)(bad_code_result.status())).c_str()); - return; - } - - int result = lua["update"](); - } - catch (int e) - { - - } - - - - - return; -} void ScriptingEngine::Close() { + wrenFreeVM(m_WrenVM); +} -} \ No newline at end of file +WrenForeignMethodFn ScriptingEngine::bindForeignMethod(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature) +{ + if (Modules.find(className) != Modules.end()) + { + Ref mod = Modules[className]; + void* ptr = mod->GetMethodPointer(signature); + return (WrenForeignMethodFn)ptr; + } +} + +WrenVM* ScriptingEngine::GetWrenVM() +{ + return m_WrenVM; +} diff --git a/Nuake/src/Scripting/ScriptingEngine.h b/Nuake/src/Scripting/ScriptingEngine.h index 515f18f3..5e4414ad 100644 --- a/Nuake/src/Scripting/ScriptingEngine.h +++ b/Nuake/src/Scripting/ScriptingEngine.h @@ -1,26 +1,36 @@ #pragma once #include -#include "sol/forward.hpp" #include #include +#include "src/Core/Core.h" +#include "src/Vendors/wren/src/include/wren.hpp" +#include +class WrenScript; +class ScriptModule; class ScriptingEngine { private: - static sol::state lua; - static std::map m_Scripts; - + static WrenVM* m_WrenVM; + static std::map> m_Scripts; + static std::map> Modules; public: + static Ref RegisterScript(const std::string& path, const std::string& mod); + static void RegisterModule(Ref module); + static void RegisterMethod(void* method, const std::string& module, const std::string& signature); + static void InitScript(Ref script); + static void UpdateScript(Ref script, Timestep timestep); + static void ExitScript(Ref script); static void Init(); - - static void RegisterScript(std::string path); - - static void InitScript(std::string path); - static void UpdateScript(std::string path); - static void ExitScript(std::string path); - - static void RunFile(const std::string& path); - static void UpdateScript(const std::string& path); static void RunCode(const std::string& code); static void Close(); + + static WrenForeignMethodFn bindForeignMethod( + WrenVM* vm, + const char* module, + const char* className, + bool isStatic, + const char* signature); + + static WrenVM* GetWrenVM(); }; \ No newline at end of file diff --git a/Nuake/src/Scripting/WrenScript.cpp b/Nuake/src/Scripting/WrenScript.cpp new file mode 100644 index 00000000..27200976 --- /dev/null +++ b/Nuake/src/Scripting/WrenScript.cpp @@ -0,0 +1,62 @@ +#include "WrenScript.h" +#include "../Core/FileSystem.h" +#include +WrenScript::WrenScript(const std::string& path, const std::string& mod) +{ + + WrenVM* vm = ScriptingEngine::GetWrenVM(); + + + wrenEnsureSlots(vm, 1); + wrenGetVariable(vm, "main", mod.c_str(), 0); + + this->m_Instance = wrenGetSlotHandle(vm, 0); + + this->m_OnInitHandle = wrenMakeCallHandle(vm, "init()"); + this->m_OnUpdateHandle = wrenMakeCallHandle(vm, "update(_)"); + this->m_OnExitHandle = wrenMakeCallHandle(vm, "exit()"); +} + +void WrenScript::CallInit() +{ + WrenVM* vm = ScriptingEngine::GetWrenVM(); + wrenSetSlotHandle(vm, 0, this->m_Instance); + WrenInterpretResult result = wrenCall(vm, this->m_OnInitHandle); +} + +void WrenScript::CallUpdate(float timestep) +{ + + WrenVM* vm = ScriptingEngine::GetWrenVM(); + wrenEnsureSlots(vm, 2); + wrenSetSlotHandle(vm, 0, this->m_Instance); + wrenSetSlotDouble(vm, 1, timestep); + WrenInterpretResult result = wrenCall(vm, this->m_OnUpdateHandle); +} + +void WrenScript::CallExit() +{ + WrenVM* vm = ScriptingEngine::GetWrenVM(); + wrenSetSlotHandle(vm, 0, this->m_Instance); + WrenInterpretResult result = wrenCall(vm, this->m_OnExitHandle); +} + +void WrenScript::RegisterMethod(const std::string& signature) +{ + WrenVM* vm = ScriptingEngine::GetWrenVM(); + WrenHandle* handle = wrenMakeCallHandle(vm, signature.c_str()); + methods.emplace(signature, handle); +} + +void WrenScript::CallMethod(const std::string& signature) +{ + WrenVM* vm = ScriptingEngine::GetWrenVM(); + + + // Not found. maybe try to register it? + if (methods.find(signature) == methods.end()) + return; + wrenSetSlotHandle(vm, 0, this->m_Instance); + WrenHandle* handle = methods[signature]; + WrenInterpretResult result = wrenCall(vm, handle); +} diff --git a/Nuake/src/Scripting/WrenScript.h b/Nuake/src/Scripting/WrenScript.h new file mode 100644 index 00000000..4e5a5987 --- /dev/null +++ b/Nuake/src/Scripting/WrenScript.h @@ -0,0 +1,24 @@ +#pragma once +#include "ScriptingEngine.h" +#include +#include + +class WrenHandle; +class WrenScript +{ +public: + std::map methods; + WrenHandle* m_Instance; + WrenHandle* m_OnInitHandle; + WrenHandle* m_OnUpdateHandle; + WrenHandle* m_OnExitHandle; + + WrenScript(const std::string& path, const std::string& mod); + + void CallInit(); + void CallUpdate(float timestep); + void CallExit(); + + void RegisterMethod(const std::string& signature); + void CallMethod(const std::string& signature); +}; \ No newline at end of file diff --git a/Nuake/src/UI/InterfaceParser.cpp b/Nuake/src/UI/InterfaceParser.cpp index 545bad35..35fa8105 100644 --- a/Nuake/src/UI/InterfaceParser.cpp +++ b/Nuake/src/UI/InterfaceParser.cpp @@ -2,28 +2,276 @@ Ref InterfaceParser::Root = CreateRef(); -void InterfaceParser::Iterate(const pugi::xml_node& xml_node, Ref node) +void InterfaceParser::Iterate(const pugi::xml_node& xml_node, Ref node, int depth) { + int currentDepth = depth + 1; for (auto& e : xml_node.children()) { std::string type = e.name(); + Ref newNode; + if (type == "Canvas") - { - Ref canvas = CreateCanvas(e); - node->Childrens.push_back(canvas); - Iterate(e, canvas); - } + newNode = CreateCanvas(e); else if (type == "Rect") - { - Ref newNode = CreateNode(e); - node->Childrens.push_back(newNode); - Iterate(e, newNode); - } + newNode = CreateNode(e); else if (type == "p") + newNode = CreateTextNode(e); + else + continue; + newNode->Depth = currentDepth; + node->Childrens.push_back(newNode); + Iterate(e, newNode, currentDepth); + } +} + +Ref InterfaceParser::Parse(const std::string path) +{ + pugi::xml_document doc; + pugi::xml_parse_result result = doc.load_file(path.c_str()); + std::string name = doc.first_child().name(); + if (name != "Canvas") + { + Logger::Log("InterfaceParser error: First child should be a canvas - " + path); + return nullptr; + } + + Root = CreateCanvas(doc.first_child()); + Root->Depth = 0; + Iterate(doc.first_child(), Root, 0); + return Root; +} + +Ref InterfaceParser::CreateTextNode(const pugi::xml_node& xml_node) +{ + Ref node = CreateRef(); + node->content = xml_node.text().as_string(); + node->Type = NodeType::Text; + TextStyle style{ + FontManager::GetFont("resources/Fonts/RobotoMono-Regular.ttf"), + 2.0, + Color(255, 255, 255, 255) + }; + + node->SetTextStyle(style); + for (auto& a : xml_node.attributes()) + { + std::string name = a.name(); + if (name == "groups") { - Ref textnode = CreateTextNode(e); - node->Childrens.push_back(textnode); - Iterate(e, textnode); + for (auto& g : split(a.value(), ' ')) + { + node->AddGroup(g); + } + } + if (name == "height") + node->Height = GetUnit(a.value()); + if (name == "width") + node->Width = GetUnit(a.value()); + if (name == "margin") + node->Margin = GetVec4Unit(a.value()); + if (name == "padding") + node->Padding = GetVec4Unit(a.value()); + if (name == "border") + node->Border = GetVec4Unit(a.value()); + if (name == "position") + node->Position = GetVec4Unit(a.value()); + if (name == "color") + node->BackgroundColor = GetColor(a.value()); + } + return node; +} + +Ref InterfaceParser::CreateNode(const pugi::xml_node& xml_node) +{ + Ref node = CreateRef(); + + node->Root = Root; + for (auto& a : xml_node.attributes()) + { + std::string name = a.name(); + if (name == "groups") + { + for (auto& g : split(a.value(), ' ')) + { + node->AddGroup(g); + } + } + if (name == "height") + node->Height = GetUnit(a.value()); + if (name == "width") + node->Width = GetUnit(a.value()); + if (name == "margin") + node->Margin = GetVec4Unit(a.value()); + if (name == "padding") + node->Padding = GetVec4Unit(a.value()); + if (name == "border") + node->Border = GetVec4Unit(a.value()); + if (name == "position") + node->Position = GetVec4Unit(a.value()); + if (name == "color") + node->BackgroundColor = GetColor(a.value()); + if (name == "onclick") + { + std::string signature = a.value(); + Root->Script->RegisterMethod(a.value()); + node->OnClickSignature = a.value(); } } + + return node; +} + +Layout::LayoutUnit InterfaceParser::GetUnit(const std::string& value) +{ + std::regex only_number("[0-9]+"); + std::regex not_number("[^0-9]+"); + + // is percentage + std::smatch match_value; + if (std::regex_search(value.begin(), value.end(), match_value, only_number)) + { + std::smatch match_type; + if (std::regex_search(value.begin(), value.end(), match_type, not_number)) + { + float value = std::stof(match_value[0]); + + if (match_type[0] == "%") + { + return Layout::LayoutUnit{ + value, + Layout::Unit::PERCENT + }; + } + else if (match_type[0] == "px") + { + return Layout::LayoutUnit{ + value, + Layout::Unit::PIXEL + }; + } + } + } +} + +std::vector InterfaceParser::split(std::string const& str, const char delim) +{ + std::vector result; + size_t start; + size_t end = 0; + + while ((start = str.find_first_not_of(delim, end)) != std::string::npos) + { + end = str.find(delim, start); + result.push_back(str.substr(start, end - start)); + } + + return result; +} + +Layout::LayoutVec4 InterfaceParser::GetVec4Unit(const std::string& value) +{ + std::regex regex("[0-9]+[^ ]+"); + std::smatch match_value; + Layout::LayoutVec4 result; + + std::vector splits = split(value, ' '); + int idx = 0; + for (auto& s : splits) + { + if (std::regex_search(value.begin(), value.end(), match_value, regex)) + { + if (idx == 0) + { + result.Left = GetUnit(s); + } + else if (idx == 1) + { + result.Right = GetUnit(s); + } + else if (idx == 2) + { + result.Top = GetUnit(s); + } + else + { + result.Bottom = GetUnit(s); + } + idx++; + } + } + return result; +} + +Color InterfaceParser::GetColor(const std::string& value) +{ + std::regex regex("[0-9]+[^ ]+"); + std::smatch match_value; + Color result; + + std::vector splits = split(value, ' '); + int idx = 0; + for (auto& s : splits) + { + if (std::regex_search(value.begin(), value.end(), match_value, regex)) + { + if (idx == 0) + { + result.r = std::stof(s); + } + else if (idx == 1) + { + result.g = std::stof(s); + } + else if (idx == 2) + { + result.b = std::stof(s); + } + else + { + result.a = std::stof(s); + } + idx++; + } + } + return result; +} + +Ref InterfaceParser::CreateCanvas(const pugi::xml_node& xml_node) +{ + Ref node = CreateRef(); + node->Root = Root; + for (auto& a : xml_node.attributes()) + { + std::string name = a.name(); + if (name == "groups") + { + for (auto& g : split(a.value(), ' ')) + { + node->AddGroup(g); + } + } + if (name == "height") + node->Height = GetUnit(a.value()); + if (name == "width") + node->Width = GetUnit(a.value()); + if (name == "margin") + node->Margin = GetVec4Unit(a.value()); + if (name == "padding") + node->Padding = GetVec4Unit(a.value()); + if (name == "border") + node->Border = GetVec4Unit(a.value()); + if (name == "position") + node->Position = GetVec4Unit(a.value()); + if (name == "color") + node->BackgroundColor = GetColor(a.value()); + if (name == "script") + { + auto s = split(a.value(), ' '); + std::string path = s[0]; + std::string module = s[1]; + node->Script = ScriptingEngine::RegisterScript(path, module); + } + } + + return node; } \ No newline at end of file diff --git a/Nuake/src/UI/InterfaceParser.h b/Nuake/src/UI/InterfaceParser.h index 2a0c2e71..d63c5328 100644 --- a/Nuake/src/UI/InterfaceParser.h +++ b/Nuake/src/UI/InterfaceParser.h @@ -8,229 +8,23 @@ #include #include "Nodes/TextNode.h" #include "Font/FontManager.h" +#include "../Scripting/ScriptingEngine.h" class InterfaceParser { - static Ref Root; - private: - + static Ref Root; public: - static Ref Parse(const std::string path) - { - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(path.c_str()); + static Ref Parse(const std::string path); - std::string name = doc.first_child().name(); - if (name != "Canvas") - { - Logger::Log("InterfaceParser error: First child should be a canvas - " + path); - return nullptr; - } - - Root = CreateCanvas(doc.first_child()); + static void Iterate(const pugi::xml_node& xml_node, Ref node, int depth); - Iterate(doc.first_child(), Root); - return Root; - } + static Ref CreateNode(const pugi::xml_node& xml_node); + static Ref CreateCanvas(const pugi::xml_node& xml_node); + static Ref CreateTextNode(const pugi::xml_node& xml_node); + static std::vector split(std::string const& str, const char delim); - - static void Iterate(const pugi::xml_node& xml_node, Ref node); - - static Ref CreateTextNode(const pugi::xml_node& xml_node) - { - Ref node = CreateRef(); - node->content = xml_node.text().as_string(); - - TextStyle style{ - FontManager::GetFont("resources/Fonts/OpenSans-Regular.ttf"), - 2.0, - Color(255, 255, 255, 255) - }; - - node->SetTextStyle(style); - return node; - } - - static Ref CreateNode(const pugi::xml_node& xml_node) - { - Ref node = CreateRef(); - for (auto& a : xml_node.attributes()) - { - std::string name = a.name(); - if (name == "groups") - { - for (auto& g : split(a.value(), ' ')) - { - node->AddGroup(g); - } - } - if (name == "height") - node->Height = GetUnit(a.value()); - if (name == "width") - node->Width = GetUnit(a.value()); - if (name == "margin") - node->Margin = GetVec4Unit(a.value()); - if (name == "padding") - node->Padding = GetVec4Unit(a.value()); - if (name == "border") - node->Border = GetVec4Unit(a.value()); - if (name == "position") - node->Position = GetVec4Unit(a.value()); - if (name == "color") - node->BackgroundColor = GetColor(a.value()); - } - - return node; - } - - static Layout::LayoutUnit GetUnit(const std::string& value) - { - std::regex only_number("[0-9]+"); - std::regex not_number("[^0-9]+"); - - // is percentage - std::smatch match_value; - if (std::regex_search(value.begin(), value.end(), match_value, only_number)) - { - std::smatch match_type; - if (std::regex_search(value.begin(), value.end(), match_type, not_number)) - { - float value = std::stof(match_value[0]); - - if (match_type[0] == "%") - { - return Layout::LayoutUnit{ - value, - Layout::Unit::PERCENT - }; - } - else if (match_type[0] == "px") - { - return Layout::LayoutUnit{ - value, - Layout::Unit::PIXEL - }; - } - } - } - } - - static std::vector split(std::string const& str, const char delim) - { - std::vector result; - size_t start; - size_t end = 0; - - while ((start = str.find_first_not_of(delim, end)) != std::string::npos) - { - end = str.find(delim, start); - result.push_back(str.substr(start, end - start)); - } - - return result; - } - - static Layout::LayoutVec4 GetVec4Unit(const std::string& value) - { - std::regex regex("[0-9]+[^ ]+"); - std::smatch match_value; - Layout::LayoutVec4 result; - - std::vector splits = split(value, ' '); - int idx = 0; - for (auto& s : splits) - { - if (std::regex_search(value.begin(), value.end(), match_value, regex)) - { - if (idx == 0) - { - result.Left = GetUnit(s); - } - else if (idx == 1) - { - result.Right = GetUnit(s); - } - else if (idx == 2) - { - result.Top = GetUnit(s); - } - else - { - result.Bottom = GetUnit(s); - } - idx++; - } - } - return result; - } - - static Color GetColor(const std::string& value) - { - std::regex regex("[0-9]+[^ ]+"); - std::smatch match_value; - Color result; - - std::vector splits = split(value, ' '); - int idx = 0; - for (auto& s : splits) - { - if (std::regex_search(value.begin(), value.end(), match_value, regex)) - { - if (idx == 0) - { - result.r = std::stof(s); - } - else if (idx == 1) - { - result.g = std::stof(s); - } - else if (idx == 2) - { - result.b = std::stof(s); - } - else - { - result.a = std::stof(s); - } - idx++; - } - } - return result; - } - - - static Ref CreateCanvas(const pugi::xml_node& xml_node) - { - Ref node = CreateRef(); - for (auto& a : xml_node.attributes()) - { - std::string name = a.name(); - if (name == "groups") - { - for (auto& g : split(a.value(), ' ')) - { - node->AddGroup(g); - } - } - if (name == "height") - node->Height = GetUnit(a.value()); - if (name == "width") - node->Width = GetUnit(a.value()); - if (name == "margin") - node->Margin = GetVec4Unit(a.value()); - if (name == "padding") - node->Padding = GetVec4Unit(a.value()); - if (name == "border") - node->Border = GetVec4Unit(a.value()); - if (name == "position") - node->Position = GetVec4Unit(a.value()); - if (name == "color") - node->BackgroundColor = GetColor(a.value()); - - } - - return node; - - } + static Layout::LayoutUnit GetUnit(const std::string& value); + static Layout::LayoutVec4 GetVec4Unit(const std::string& value); + static Color GetColor(const std::string& value); }; \ No newline at end of file diff --git a/Nuake/src/UI/Nodes/Canvas.h b/Nuake/src/UI/Nodes/Canvas.h index 9b83700d..ecf43074 100644 --- a/Nuake/src/UI/Nodes/Canvas.h +++ b/Nuake/src/UI/Nodes/Canvas.h @@ -1,5 +1,8 @@ #pragma once #include "Node.h" +#include "../Core/Core.h" +#include "../Scripting/WrenScript.h" +#include // Base container for UI. class Canvas : public Node { @@ -7,7 +10,6 @@ private: // Script here public: + Ref Script; Canvas(); - - }; \ No newline at end of file diff --git a/Nuake/src/UI/Nodes/Node.cpp b/Nuake/src/UI/Nodes/Node.cpp index 202db3c2..daf4bfd0 100644 --- a/Nuake/src/UI/Nodes/Node.cpp +++ b/Nuake/src/UI/Nodes/Node.cpp @@ -1,5 +1,24 @@ #include "Node.h" +Node::Node() +{ + Childrens = std::vector>(); + Groups = std::vector(); + PositionType = Layout::PositionType::RELATIVE; + Position = Layout::LayoutVec4(); + Height = MaxHeight = MinHeight = Layout::LayoutUnit(); + Margin = Padding = Border = Layout::LayoutVec4(); + Direction = Layout::LayoutDirection::LTR; + FlexDirection = Layout::FlexDirection::ROW; + FlexWrap = Layout::FlexWrap::WRAP; + FlexGrow = 0.f; + FlexShrink = 1.f; + FlexBasis = 10.f; + AspectRatio = 1.f; + AlignItems = Layout::AlignItems::AUTO; + AlignSelf = Layout::AlignItems::AUTO; +} + void Node::ApplyStyle(Ref stylegroup) { for (auto& s : stylegroup->GetProps()) @@ -90,21 +109,33 @@ void Node::ApplyStyle(Ref stylegroup) } } -Node::Node() +bool Node::IsPositionInside(Vector2 position) { - Childrens = std::vector>(); - Groups = std::vector(); - PositionType = Layout::PositionType::RELATIVE; - Position = Layout::LayoutVec4(); - Height = MaxHeight = MinHeight = Layout::LayoutUnit(); - Margin = Padding = Border = Layout::LayoutVec4(); - Direction = Layout::LayoutDirection::LTR; - FlexDirection = Layout::FlexDirection::ROW; - FlexWrap = Layout::FlexWrap::WRAP; - FlexGrow = 0.f; - FlexShrink = 1.f; - FlexBasis = 10.f; - AspectRatio = 1.f; - AlignItems = Layout::AlignItems::AUTO; - AlignSelf = Layout::AlignItems::AUTO; + float width = YGNodeLayoutGetWidth(YogaNode); + float height = YGNodeLayoutGetHeight(YogaNode); + float padding = YGNodeLayoutGetPadding(YogaNode, YGEdgeLeft); + float left = YGNodeLayoutGetLeft(YogaNode); //+ offset.x; + float top = YGNodeLayoutGetTop(YogaNode);// +offset.y; + + float parentLeft = 0.0f; + float parentTop = 0.0f; + auto parent = YGNodeGetParent(YogaNode); + if (parent) + { + parentLeft = YGNodeLayoutGetLeft(YGNodeGetParent(YogaNode)); + parentTop = YGNodeLayoutGetTop(YGNodeGetParent(YogaNode)); + float parentPaddingTop = YGNodeLayoutGetPadding(parent, YGEdgeTop); + float parentPaddingLeft = YGNodeLayoutGetPadding(parent, YGEdgeTop); + // Overflow hidden. + float parentwidth = YGNodeLayoutGetWidth(parent); + if (parentwidth - YGNodeLayoutGetMargin(YogaNode, YGEdgeLeft) < width) + width = parentwidth - parentPaddingLeft; + float parentHeight = YGNodeLayoutGetHeight(parent); + if (parentHeight < height) + height = parentHeight - parentPaddingTop; + } + + left += parentLeft; + top += parentTop; + return position.x > left && position.x < left + width && position.y > top && position.y < top + height; } \ No newline at end of file diff --git a/Nuake/src/UI/Nodes/Node.h b/Nuake/src/UI/Nodes/Node.h index cc22b0b9..b658d2fe 100644 --- a/Nuake/src/UI/Nodes/Node.h +++ b/Nuake/src/UI/Nodes/Node.h @@ -65,47 +65,56 @@ namespace Layout } +enum class NodeType +{ + Normal, + Text +}; + // Base UI node. class Node { public: - Ref Parent; - YGNodeRef YogaNode; + int Depth; + Ref Root; + Ref Parent; + std::vector Groups; std::vector> Childrens = std::vector>(); - void ApplyStyle(Ref stylegroup); + std::string OnClickSignature = ""; + + NodeType Type = NodeType::Normal; + + YGNodeRef YogaNode; + Ref