diff --git a/Editor/resources/Scripts/Math.wren b/Editor/resources/Scripts/Math.wren index 7daa24ef..533ebbb5 100644 --- a/Editor/resources/Scripts/Math.wren +++ b/Editor/resources/Scripts/Math.wren @@ -3,6 +3,52 @@ class Math { } class Vector3 { + + x {_x} + y {_y} + z {_z} + x=(value) { + _x = value + } + y=(value) { + _y = value + } + z=(value) { + _z = value + } + + mul(other) { + if(other is Vector3) { + return Vector3.new(_x * other.x, + _y * other.y, + _z * other.z) + } else { + return Vector3.new(_x * other, _y * other, _z * other) + } + } + + *(other) { + if(other is Vector3) { + return Vector3.new(_x * other.x, + _y * other.y, + _z * other.z) + } else if(other is Num) { + return Vector3.new(_x * other, _y * other, _z * other) + } + } + + +(other) { + if(other is Vector3) { + return Vector3.new(_x + other.x, + _y + other.y, + _z + other.z) + } else if(other is Num) { + return Vector3.new(_x + other, + _y + other, + _z + other) + } + } + construct new(x, y, z) { _x = x _y = y diff --git a/Editor/resources/Scripts/Scene.wren b/Editor/resources/Scripts/Scene.wren index c6c0d099..4f6b5f36 100644 --- a/Editor/resources/Scripts/Scene.wren +++ b/Editor/resources/Scripts/Scene.wren @@ -1,4 +1,5 @@ import "Scripts/Engine" for Engine +import "Scripts/Math" for Vector3 class Scene { foreign static GetEntityID(name) @@ -11,35 +12,50 @@ class Scene { } foreign static EntityHasComponent(id, name) + static EntityGetComponent(id, component) { + if(this.EntityHasComponent(id, component) == false) { + Engine.Log("Tried getting a non-existent component of type: %(component) on entity with id: %(id)") + return + } - // Component specific private setter and getter. - foreign static GetLightIntensity_(e) - foreign static SetLightIntensity_(e, intensity) + if (component == "Light") { + return Light.new(id) + } else if (component == "CharacterController") { + return CharacterController.new(id) + } else if (component == "Camera") { + return Camera.new(id) + } + } - /* - // Transform - foreign static SetTranslation_(e, x, y, z) - foreign static SetRotation_(e, x, y, z) - foreign static SetScale_(e, x, y, z) - - // Character controller - foreign static SetVelocity(e, x, y, z) - foreign static SetStepHeight(e, x, y, z) - foreign static IsOnGround(e) - */ - // Light + // + // Components // - /* - foreign static SetLightIsVolumetric_(e, bool) - foreign static SetLightSyncDirectionWithSky_(e, bool) - foreign static SetLightColor_(e, r, g, b) + // Transform + //foreign static SetTranslation_(e, x, y, z) + //foreign static SetRotation_(e, x, y, z) + //foreign static SetScale_(e, x, y, z) + + // Light + foreign static GetLightIntensity_(e) // returns a float + foreign static SetLightIntensity_(e, intensity) + //foreign static SetLightIsVolumetric_(e, bool) + //foreign static SetLightSyncDirectionWithSky_(e, bool) + //foreign static SetLightColor_(e, r, g, b) + //foreign static GetLightColor_(e) // Camera - foreign static SetCameraFov_(e, fov) - foreign static SetCameraType(e, type) foreign static SetCameraDirection_(e, x, y, z) - */ + foreign static GetCameraDirection_(e) // returns a list x,y,z + foreign static GetCameraRight_(e) // returns a list x,y,z + //foreign static SetcameraFov(e, fov) + //foreign static GetCameraFov(e) // returns a float + + // Character controller + foreign static MoveAndSlide_(e, x, y, z) + //foreign static IsOnGround_(e) + + } class Entity { @@ -52,14 +68,7 @@ class Entity { } GetComponent(component) { - if(this.HasComponent(component) == false) { - Engine.Log("Tried getting a non-existent component of type: %(component) on entity with id: %(_entityId)") - return - } - - if (component == "Light") { - return Light.new(_entityId) - } + return Scene.EntityGetComponent(_entityId, component) } // Foreign engine functions @@ -110,17 +119,37 @@ class Light { SetColor(color) { this.SetColor_(_entityId, color.r, color.g, color.b, color.a) + }*/ + +} + +class CharacterController { + construct new(id) { + _entityId = id } - SetDirection(direction) { - var normalized = direction.Normalize() - this.SetDirection_(_entityId, normalized.x, normalized.y, normalized.z) + MoveAndSlide(vel) { + Scene.MoveAndSlide_(_entityId, vel.x, vel.y, vel.z) } - - foreign static SetType_(id, type) - foreign static SetColor_(id, r, g, b) - - foreign static SetDirection_(id, x, y, z) - */ - -} \ No newline at end of file +} + +class Camera { + construct new(id) { + _entityId = id + } + + SetDirection(dir) { + Scene.SetCameraDirection_(_entityId, dir.x, dir.y, dir.z) + } + + GetDirection() { + var dir = Scene.GetCameraDirection_(_entityId) + return Vector3.new(dir[0], dir[1], dir[2]) + } + + GetRight() { + var dir = Scene.GetCameraRight_(_entityId) + return Vector3.new(dir[0], dir[1], dir[2]) + } + +} diff --git a/Editor/resources/Scripts/ScriptableEntity.wren b/Editor/resources/Scripts/ScriptableEntity.wren new file mode 100644 index 00000000..0049e912 --- /dev/null +++ b/Editor/resources/Scripts/ScriptableEntity.wren @@ -0,0 +1,15 @@ +import "Scripts/Scene" for Scene + +class ScriptableEntity { + SetEntityId(id) { + _EntityID = id + } + + GetComponent(component) { + return Scene.EntityGetComponent(_EntityID, component) + } + + HasComponent(component) { + return Scene.EntityHasComponent(_EntityID, component) + } +} \ No newline at end of file diff --git a/Editor/src/EditorInterface.cpp b/Editor/src/EditorInterface.cpp index dc84726b..275cd48e 100644 --- a/Editor/src/EditorInterface.cpp +++ b/Editor/src/EditorInterface.cpp @@ -19,6 +19,7 @@ #include "src/Resource/Project.h" #include #include +#include Ref userInterface; ImFont* normalFont; ImFont* EditorInterface::bigIconFont; @@ -80,7 +81,7 @@ void EditorInterface::DrawViewport() glm::vec2 viewportPanelSize = glm::vec2(regionAvail.x, regionAvail.y); if(Engine::GetCurrentWindow()->GetFrameBuffer()->GetSize() != viewportPanelSize) - Engine::GetCurrentWindow()->GetFrameBuffer()->UpdateSize(viewportPanelSize); + Engine::GetCurrentWindow()->GetFrameBuffer()->QueueResize(viewportPanelSize); Ref texture = Engine::GetCurrentWindow()->GetFrameBuffer()->GetTexture(); ImGui::Image((void*)texture->GetID(), regionAvail, ImVec2(0, 1), ImVec2(1, 0)); @@ -321,16 +322,22 @@ void EditorInterface::DrawEntityPropreties() } if (ImGui::BeginPopup("add_component_popup")) { - if (ImGui::MenuItem("Lua script") && !m_SelectedEntity.HasComponent()) - m_SelectedEntity.AddComponent(); - if (ImGui::MenuItem("Light Component") && !m_SelectedEntity.HasComponent()) - m_SelectedEntity.AddComponent(); - if (ImGui::MenuItem("Mesh Component") && !m_SelectedEntity.HasComponent()) - m_SelectedEntity.AddComponent(); + if (ImGui::MenuItem("Wren Script") && !m_SelectedEntity.HasComponent()) + m_SelectedEntity.AddComponent(); + ImGui::Separator(); if (ImGui::MenuItem("Camera Component") && !m_SelectedEntity.HasComponent()) m_SelectedEntity.AddComponent(); + ImGui::Separator(); + if (ImGui::MenuItem("Light Component") && !m_SelectedEntity.HasComponent()) + m_SelectedEntity.AddComponent(); + ImGui::Separator(); + if (ImGui::MenuItem("Mesh Component") && !m_SelectedEntity.HasComponent()) + m_SelectedEntity.AddComponent(); if (ImGui::MenuItem("Quake map Component") && !m_SelectedEntity.HasComponent()) m_SelectedEntity.AddComponent(); + ImGui::Separator(); + if (ImGui::MenuItem("Character controller") && !m_SelectedEntity.HasComponent()) + m_SelectedEntity.AddComponent(); if (ImGui::MenuItem("Rigidbody Component") && !m_SelectedEntity.HasComponent()) { m_SelectedEntity.AddComponent(); @@ -377,32 +384,43 @@ void EditorInterface::DrawEntityPropreties() } - if (m_SelectedEntity.HasComponent()) { + if (m_SelectedEntity.HasComponent()) { std::string icon = ICON_FA_FILE; - if (ImGui::CollapsingHeader((icon + " " + "Lua script").c_str(), ImGuiTreeNodeFlags_DefaultOpen)) + if (ImGui::CollapsingHeader((icon + " " + "Wren Script").c_str(), ImGuiTreeNodeFlags_DefaultOpen)) { - auto& component = m_SelectedEntity.GetComponent(); + auto& component = m_SelectedEntity.GetComponent(); + + // Path std::string path = component.Script; - - char pathBuffer[256]; + memset(pathBuffer, 0, sizeof(pathBuffer)); std::strncpy(pathBuffer, path.c_str(), sizeof(pathBuffer)); + if (ImGui::InputText("##ScriptPath", pathBuffer, sizeof(pathBuffer))) - { - path = std::string(pathBuffer); - } + path = FileSystem::AbsoluteToRelative(std::string(pathBuffer)); + ImGui::SameLine(); + if (ImGui::Button("Browse")) - { - path = FileDialog::OpenFile(".map"); - } + path = FileSystem::AbsoluteToRelative(FileDialog::OpenFile(".wren")); component.Script = path; + // Class + std::string module = component.Class; + + char classBuffer[256]; + + memset(classBuffer, 0, sizeof(classBuffer)); + std::strncpy(classBuffer, module.c_str(), sizeof(classBuffer)); + + if (ImGui::InputText("##ScriptModule", classBuffer, sizeof(classBuffer))) + module = std::string(classBuffer); + + component.Class = module; ImGui::Separator(); } - } if (m_SelectedEntity.HasComponent()) { @@ -416,6 +434,18 @@ void EditorInterface::DrawEntityPropreties() } + if (m_SelectedEntity.HasComponent()) + { + if (ImGui::CollapsingHeader("Character controller", ImGuiTreeNodeFlags_DefaultOpen)) + { + auto& c = m_SelectedEntity.GetComponent(); + ImGui::InputFloat("Height", &c.Height); + ImGui::InputFloat("Radius", &c.Radius); + ImGui::InputFloat("Mass", &c.Mass); + ImGui::Separator(); + } + } + if (m_SelectedEntity.HasComponent()) { std::string icon = ICON_FA_TREE; @@ -907,17 +937,26 @@ void OpenProject() Engine::LoadProject(project); // Create new interface named test. - userInterface = UI::UserInterface::New("test"); + //userInterface = UI::UserInterface::New("test"); // Set current interface running. - Engine::GetCurrentScene()->AddInterface(userInterface); - + //Engine::GetCurrentScene()->AddInterface(userInterface); } void OpenScene() { + // Parse the project and load it. + std::string projectPath = FileDialog::OpenFile(".scene"); + Ref scene = Scene::New(); + if (!scene->Deserialize(FileSystem::ReadFile(projectPath, true))) { + Logger::Log("Error failed loading scene: " + projectPath); + return; + } + + scene->Path = FileSystem::AbsoluteToRelative(projectPath); + Engine::LoadScene(scene); } void EditorInterface::DrawInit() @@ -981,6 +1020,10 @@ void EditorInterface::Draw() m_IsEntitySelected = false; } ImGui::Separator(); + if (ImGui::MenuItem("Set current scene as default")) { + Engine::GetProject()->DefaultScene = Engine::GetCurrentScene(); + } + ImGui::Separator(); if (ImGui::MenuItem("Open scene...", "CTRL+O")) { OpenScene(); diff --git a/Nuake/Engine.cpp b/Nuake/Engine.cpp index 23c1ccca..7ac8358b 100644 --- a/Nuake/Engine.cpp +++ b/Nuake/Engine.cpp @@ -24,8 +24,6 @@ void Engine::Init() PhysicsManager::Get()->Init(); Logger::Log("Physics initialized"); - ScriptingEngine::Init(); - Logger::Log("Scripting engine initialized"); CurrentWindow = Window::Get(); Logger::Log("Window initialized"); diff --git a/Nuake/src/Rendering/Camera.h b/Nuake/src/Rendering/Camera.h index 6c6a6699..d0bd67fe 100644 --- a/Nuake/src/Rendering/Camera.h +++ b/Nuake/src/Rendering/Camera.h @@ -16,12 +16,13 @@ class Camera : public ISerializable private: CAMERA_TYPE m_Type; - float AspectRatio = 16.0f / 9.0f; + Vector3 Rotation = { 0.0f, 0.0f, 0.0f }; Vector3 Scale = { 1.0f, 1.0f, 1.0f }; Matrix4 m_Perspective; public: + float AspectRatio = 16.0f / 9.0f; // TODO: remove duplicate direction and have a proper api. Vector3 up = Vector3(0.0f, 1.0f, 0.0f); Vector3 cameraFront = Vector3(0.0f, 0.0f, 1.0f); diff --git a/Nuake/src/Rendering/Framebuffer.cpp b/Nuake/src/Rendering/Framebuffer.cpp index 9ad7c9b9..3bc90757 100644 --- a/Nuake/src/Rendering/Framebuffer.cpp +++ b/Nuake/src/Rendering/Framebuffer.cpp @@ -55,6 +55,9 @@ void FrameBuffer::SetTexture(Ref texture, GLenum attachment) void FrameBuffer::Bind() { + if (ResizeQueued) + UpdateSize(m_Size); + glBindFramebuffer(GL_FRAMEBUFFER, m_FramebufferID); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, m_Size.x, m_Size.y); @@ -65,6 +68,12 @@ void FrameBuffer::Unbind() glBindFramebuffer(GL_FRAMEBUFFER, 0); } +void FrameBuffer::QueueResize(Vector2 size) +{ + ResizeQueued = true; + m_Size = size; +} + void FrameBuffer::UpdateSize(Vector2 size) { m_Size = size; diff --git a/Nuake/src/Rendering/Framebuffer.h b/Nuake/src/Rendering/Framebuffer.h index a4ee0abf..9c058e19 100644 --- a/Nuake/src/Rendering/Framebuffer.h +++ b/Nuake/src/Rendering/Framebuffer.h @@ -11,7 +11,8 @@ private: unsigned int m_RenderBuffer; Vector2 m_Size; - + bool ResizeQueued = false; + std::map> m_Textures; Ref m_Texture; @@ -27,6 +28,7 @@ public: void Bind(); void Unbind(); + void QueueResize(Vector2 size); Vector2 GetSize() const { return m_Size; } void UpdateSize(Vector2 size); diff --git a/Nuake/src/Rendering/Shaders/Shader.cpp b/Nuake/src/Rendering/Shaders/Shader.cpp index 4179b18c..7ccb8c41 100644 --- a/Nuake/src/Rendering/Shaders/Shader.cpp +++ b/Nuake/src/Rendering/Shaders/Shader.cpp @@ -125,7 +125,7 @@ int Shader::FindUniformLocation(std::string uniform) { if (addr == -1) std::cout << "Warning: uniform '" << uniform << "' doesn't exists!" << std::endl; else { - std::cout << "Info: uniform '" << uniform << "' registered." << std::endl; + //std::cout << "Info: uniform '" << uniform << "' registered." << std::endl; UniformCache[uniform] = addr; } diff --git a/Nuake/src/Resource/Project.cpp b/Nuake/src/Resource/Project.cpp index 6a9433d4..5b27f535 100644 --- a/Nuake/src/Resource/Project.cpp +++ b/Nuake/src/Resource/Project.cpp @@ -33,11 +33,8 @@ void Project::Save() void Project::SaveAs(const std::string FullPath) { - // Serialize the scene. - BEGIN_SERIALIZE(); - SERIALIZE_VAL(Name); - SERIALIZE_VAL(Description); + json j = Serialize(); // Dump. std::string serialized_string = j.dump(); diff --git a/Nuake/src/Scene/Entities/Components/InterfaceComponent.h b/Nuake/src/Scene/Entities/Components/InterfaceComponent.h new file mode 100644 index 00000000..00390d5f --- /dev/null +++ b/Nuake/src/Scene/Entities/Components/InterfaceComponent.h @@ -0,0 +1,8 @@ +#pragma once +#include "../Core/Core.h" +#include + +class InterfaceComponent +{ + Ref Interface; +}; \ No newline at end of file diff --git a/Nuake/src/Scene/Entities/Components/WrenScriptComponent.h b/Nuake/src/Scene/Entities/Components/WrenScriptComponent.h new file mode 100644 index 00000000..0dab3666 --- /dev/null +++ b/Nuake/src/Scene/Entities/Components/WrenScriptComponent.h @@ -0,0 +1,31 @@ +#pragma once +#include "../Scripting/WrenScript.h" + +class WrenScriptComponent +{ +public: + std::string Script; + std::string Class; + + Ref WrenScript; + + json Serialize() + { + BEGIN_SERIALIZE(); + SERIALIZE_VAL(Script); + SERIALIZE_VAL(Class); + END_SERIALIZE(); + } + + bool Deserialize(std::string str) + { + BEGIN_DESERIALIZE(); + if (j.contains("Script")) + Script = j["Script"]; + if (j.contains("Class")) + Class = j["Class"]; + + + return true; + } +}; \ No newline at end of file diff --git a/Nuake/src/Scene/Entities/Entity.cpp b/Nuake/src/Scene/Entities/Entity.cpp index 69937b51..895851ba 100644 --- a/Nuake/src/Scene/Entities/Entity.cpp +++ b/Nuake/src/Scene/Entities/Entity.cpp @@ -8,6 +8,7 @@ #include "Components/QuakeMap.h" #include "Components/LightComponent.h" #include "Components/QuakeMap.h" +#include void Entity::AddChild(Entity ent) { if ((int)m_EntityHandle != ent.GetHandle()) @@ -31,6 +32,8 @@ json Entity::Serialize() SERIALIZE_OBJECT_REF_LBL("QuakeMapComponent", GetComponent()); if (HasComponent()) SERIALIZE_OBJECT_REF_LBL("LightComponent", GetComponent()); + if (HasComponent()) + SERIALIZE_OBJECT_REF_LBL("WrenScriptComponent", GetComponent()); END_SERIALIZE(); } @@ -43,6 +46,7 @@ bool Entity::Deserialize(const std::string& str) DESERIALIZE_COMPONENT(CameraComponent); DESERIALIZE_COMPONENT(QuakeMapComponent); DESERIALIZE_COMPONENT(LightComponent); + DESERIALIZE_COMPONENT(WrenScriptComponent); return true; } diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index d1f3a962..1cfacf9d 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -13,7 +13,7 @@ #include "../Scene/Entities/Components/LuaScriptComponent.h" #include #include - +#include "../Scene/Entities/Components/WrenScriptComponent.h" Ref Scene::New() { return CreateRef(); @@ -44,6 +44,8 @@ bool Scene::SetName(std::string& newName) void Scene::OnInit() { + ScriptingEngine::Init(); + // Create physic world. auto view = m_Registry.view(); for (auto e : view) @@ -98,10 +100,19 @@ void Scene::OnInit() // Instanciate scripts. { - m_Registry.view().each([=](auto entity, auto& nsc) + auto entities = m_Registry.view(); + for (auto& e : entities) { + WrenScriptComponent& wren = entities.get(e); + if (wren.Script != "" && wren.Class != "") + wren.WrenScript = CreateRef(wren.Script, wren.Class, true); - }); + if (wren.WrenScript != nullptr) + { + wren.WrenScript->SetScriptableEntityID((int)e); + wren.WrenScript->CallInit(); + } + } } } @@ -110,12 +121,21 @@ void Scene::OnExit() PhysicsManager::Get()->Reset(); // destroy scripts. + auto entities = m_Registry.view(); + for (auto& e : entities) { - m_Registry.view().each([=](auto entity, auto& nsc) + WrenScriptComponent& wren = entities.get(e); + + if (wren.WrenScript != nullptr) { - nsc.Instance->OnDestroy(); - }); + wren.WrenScript->CallExit(); + + + } + } + + ScriptingEngine::Close(); } // update entities and some components. @@ -129,6 +149,16 @@ void Scene::Update(Timestep ts) }); } + // destroy scripts. + auto entities = m_Registry.view(); + for (auto& e : entities) + { + WrenScriptComponent& wren = entities.get(e); + + if (wren.WrenScript != nullptr) + wren.WrenScript->CallUpdate(ts); + } + // Update rigidbodies PhysicsManager::Get()->Step(ts); @@ -618,12 +648,14 @@ bool Scene::SaveAs(const std::string& path) return true; } + void Scene::ReloadInterfaces() { for (auto& i : m_Interfaces) i->Reload(); } + void Scene::AddInterface(Ref interface) { this->m_Interfaces.push_back(interface); @@ -643,7 +675,6 @@ json Scene::Serialize() } - bool Scene::Deserialize(const std::string& str) { if (str == "") @@ -675,5 +706,6 @@ bool Scene::Deserialize(const std::string& str) } } } + return true; } diff --git a/Nuake/src/Scripting/Modules/MathModule.h b/Nuake/src/Scripting/Modules/MathModule.h index f4eff0f1..2cd0d862 100644 --- a/Nuake/src/Scripting/Modules/MathModule.h +++ b/Nuake/src/Scripting/Modules/MathModule.h @@ -27,9 +27,9 @@ namespace ScriptAPI static void Sqrt(WrenVM* vm) { - float x = wrenGetSlotDouble(vm, 0); - float y = wrenGetSlotDouble(vm, 0); - float z = wrenGetSlotDouble(vm, 0); + float x = wrenGetSlotDouble(vm, 1); + float y = wrenGetSlotDouble(vm, 2); + float z = wrenGetSlotDouble(vm, 3); float result = glm::sqrt((x * x) + (y * y) + (z * z)); wrenSetSlotDouble(vm, 0, result); } diff --git a/Nuake/src/Scripting/Modules/SceneModule.h b/Nuake/src/Scripting/Modules/SceneModule.h index a2352946..2832f3d7 100644 --- a/Nuake/src/Scripting/Modules/SceneModule.h +++ b/Nuake/src/Scripting/Modules/SceneModule.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace ScriptAPI { @@ -30,6 +31,10 @@ namespace ScriptAPI RegisterMethod("EntityHasComponent(_,_)", (void*)EntityHasComponent); RegisterMethod("SetLightIntensity_(_,_)", (void*)SetLightIntensity); RegisterMethod("GetLightIntensity_(_)", (void*)GetLightIntensity); + RegisterMethod("SetCameraDirection_(_,_,_,_)", (void*)SetCameraDirection); + RegisterMethod("GetCameraDirection_(_)", (void*)GetCameraDirection); + RegisterMethod("GetCameraRight_(_)", (void*)GetCameraRight); + RegisterMethod("MoveAndSlide_(_,_,_,_)", (void*)MoveAndSlide); } static void GetEntity(WrenVM* vm) @@ -99,7 +104,73 @@ namespace ScriptAPI static void SetCameraDirection(WrenVM* vm) { + int handle = wrenGetSlotDouble(vm, 1); + float x = wrenGetSlotDouble(vm, 2); + float y = wrenGetSlotDouble(vm, 3); + float z = wrenGetSlotDouble(vm, 4); + Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get()); + auto& cam = ent.GetComponent(); + cam.CameraInstance->SetDirection(Vector3(x, y, z)); } + + static void GetCameraDirection(WrenVM* vm) + { + int handle = wrenGetSlotDouble(vm, 1); + Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get()); + + auto& cam = ent.GetComponent(); + + Vector3 dir = cam.CameraInstance->GetDirection(); + + wrenEnsureSlots(vm, 4); + + // set the slots + // Fill the list + wrenSetSlotNewList(vm, 0); + wrenSetSlotDouble(vm, 1, dir.x); + wrenSetSlotDouble(vm, 2, dir.y); + wrenSetSlotDouble(vm, 3, dir.z); + + wrenInsertInList(vm, 0, -1, 1); + wrenInsertInList(vm, 0, -1, 2); + wrenInsertInList(vm, 0, -1, 3); + } + + static void GetCameraRight(WrenVM* vm) + { + int handle = wrenGetSlotDouble(vm, 1); + Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get()); + + auto& cam = ent.GetComponent(); + + Vector3 right = cam.CameraInstance->cameraRight; + + // set the slots + wrenSetSlotDouble(vm, 1, right.x); + wrenSetSlotDouble(vm, 2, right.y); + wrenSetSlotDouble(vm, 3, right.z); + + // Fill the list + wrenSetSlotNewList(vm, 0); + wrenInsertInList(vm, 0, 0, 1); + wrenInsertInList(vm, 0, 1, 2); + wrenInsertInList(vm, 0, 2, 3); + } + + + + static void MoveAndSlide(WrenVM* vm) + { + int handle = wrenGetSlotDouble(vm, 1); + float x = wrenGetSlotDouble(vm, 2); + float y = wrenGetSlotDouble(vm, 3); + float z = wrenGetSlotDouble(vm, 4); + + Entity ent = Entity((entt::entity)handle, Engine::GetCurrentScene().get()); + auto& characterController = ent.GetComponent(); + characterController.CharacterController->MoveAndSlide(Vector3(x, y, z)); + } + }; } \ No newline at end of file diff --git a/Nuake/src/Scripting/ScriptingEngine.cpp b/Nuake/src/Scripting/ScriptingEngine.cpp index 2b38247c..bac7d86d 100644 --- a/Nuake/src/Scripting/ScriptingEngine.cpp +++ b/Nuake/src/Scripting/ScriptingEngine.cpp @@ -40,11 +40,25 @@ void writeFn(WrenVM* vm, const char* text) { printf("%s", text); } +bool hasEnding(std::string const& fullString, std::string const& ending) { + if (fullString.length() >= ending.length()) { + return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending)); + } + else { + return false; + } +} WrenLoadModuleResult myLoadModule(WrenVM* vm, const char* name) { WrenLoadModuleResult result = { 0 }; - std::string str = FileSystem::ReadFile("resources/" + std::string(name) + ".wren", true); + + std::string path = "resources/" + std::string(name); + if(!hasEnding(path, ".wren")) + path += ".wren"; + + std::string str = FileSystem::ReadFile(path, true); char* c = strcpy(new char[str.length() + 1], str.c_str()); + result.source = c; return result; } diff --git a/Nuake/src/Scripting/WrenScript.cpp b/Nuake/src/Scripting/WrenScript.cpp index 27200976..1ddcf480 100644 --- a/Nuake/src/Scripting/WrenScript.cpp +++ b/Nuake/src/Scripting/WrenScript.cpp @@ -1,20 +1,36 @@ #include "WrenScript.h" #include "../Core/FileSystem.h" #include -WrenScript::WrenScript(const std::string& path, const std::string& mod) -{ +WrenScript::WrenScript(const std::string& path, const std::string& mod, bool isEntity) +{ WrenVM* vm = ScriptingEngine::GetWrenVM(); - + // Import statement + std::string source = "import \"" + path + "\" for " + mod; + + // Import file as module + wrenInterpret(vm, "main", source.c_str()); + + // Get handle to class wrenEnsureSlots(vm, 1); wrenGetVariable(vm, "main", mod.c_str(), 0); + WrenHandle* classHandle = wrenGetSlotHandle(vm, 0); + // Call the constructor + WrenHandle* constructHandle = wrenMakeCallHandle(vm, "new()"); + wrenCall(vm, constructHandle); + + // Retreive value of constructor this->m_Instance = wrenGetSlotHandle(vm, 0); + // Create handles to the instance methods. this->m_OnInitHandle = wrenMakeCallHandle(vm, "init()"); this->m_OnUpdateHandle = wrenMakeCallHandle(vm, "update(_)"); this->m_OnExitHandle = wrenMakeCallHandle(vm, "exit()"); + + if (isEntity) + this->m_SetEntityIDHandle = wrenMakeCallHandle(vm, "SetEntityId(_)"); } void WrenScript::CallInit() @@ -26,7 +42,6 @@ void WrenScript::CallInit() void WrenScript::CallUpdate(float timestep) { - WrenVM* vm = ScriptingEngine::GetWrenVM(); wrenEnsureSlots(vm, 2); wrenSetSlotHandle(vm, 0, this->m_Instance); @@ -37,6 +52,7 @@ void WrenScript::CallUpdate(float timestep) void WrenScript::CallExit() { WrenVM* vm = ScriptingEngine::GetWrenVM(); + wrenEnsureSlots(vm, 1); wrenSetSlotHandle(vm, 0, this->m_Instance); WrenInterpretResult result = wrenCall(vm, this->m_OnExitHandle); } @@ -56,7 +72,16 @@ void WrenScript::CallMethod(const std::string& signature) // 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); } + +void WrenScript::SetScriptableEntityID(int id) +{ + WrenVM* vm = ScriptingEngine::GetWrenVM(); + wrenSetSlotHandle(vm, 0, this->m_Instance); + wrenSetSlotDouble(vm, 1, id); + WrenInterpretResult result = wrenCall(vm, this->m_SetEntityIDHandle); +} diff --git a/Nuake/src/Scripting/WrenScript.h b/Nuake/src/Scripting/WrenScript.h index 4e5a5987..2ddad9b3 100644 --- a/Nuake/src/Scripting/WrenScript.h +++ b/Nuake/src/Scripting/WrenScript.h @@ -12,8 +12,9 @@ public: WrenHandle* m_OnInitHandle; WrenHandle* m_OnUpdateHandle; WrenHandle* m_OnExitHandle; + WrenHandle* m_SetEntityIDHandle; - WrenScript(const std::string& path, const std::string& mod); + WrenScript(const std::string& path, const std::string& mod, bool isEntity = false); void CallInit(); void CallUpdate(float timestep); @@ -21,4 +22,6 @@ public: void RegisterMethod(const std::string& signature); void CallMethod(const std::string& signature); + + void SetScriptableEntityID(int id); }; \ No newline at end of file diff --git a/Nuake/src/UI/InterfaceParser.cpp b/Nuake/src/UI/InterfaceParser.cpp index 35fa8105..c2ed807f 100644 --- a/Nuake/src/UI/InterfaceParser.cpp +++ b/Nuake/src/UI/InterfaceParser.cpp @@ -1,5 +1,5 @@ #include "InterfaceParser.h" - +#include "Styling/Stylesheet.h" Ref InterfaceParser::Root = CreateRef(); void InterfaceParser::Iterate(const pugi::xml_node& xml_node, Ref node, int depth) @@ -271,6 +271,11 @@ Ref InterfaceParser::CreateCanvas(const pugi::xml_node& xml_node) std::string module = s[1]; node->Script = ScriptingEngine::RegisterScript(path, module); } + if (name == "stylesheet") + { + std::string path = a.value(); + node->StyleSheet = UI::StyleSheet::New(path); + } } return node; diff --git a/Nuake/src/UI/Nodes/Canvas.h b/Nuake/src/UI/Nodes/Canvas.h index ecf43074..9e57c690 100644 --- a/Nuake/src/UI/Nodes/Canvas.h +++ b/Nuake/src/UI/Nodes/Canvas.h @@ -3,6 +3,8 @@ #include "../Core/Core.h" #include "../Scripting/WrenScript.h" #include +#include "../Styling/Stylesheet.h" + // Base container for UI. class Canvas : public Node { @@ -11,5 +13,7 @@ private: public: Ref Script; + Ref StyleSheet; + Canvas(); }; \ No newline at end of file diff --git a/Nuake/src/UI/Styling/Stylesheet.h b/Nuake/src/UI/Styling/Stylesheet.h index 5f6767f0..eee6f17b 100644 --- a/Nuake/src/UI/Styling/Stylesheet.h +++ b/Nuake/src/UI/Styling/Stylesheet.h @@ -1,18 +1,14 @@ #pragma once +#include "katana-parser/katana.h" #include "../Core/FileSystem.h" #include "../Core/Logger.h" #include "../Core/Core.h" -#include "Style.h" - -#include "katana-parser/katana.h" -#include -#include +#include "../Nodes/Node.h" #include #include -#include -#include - +#include +#include namespace UI { class StyleSheet @@ -24,7 +20,20 @@ namespace UI public: std::string Path; static Ref New(const std::string& path); + 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; + } void AddStyleGroup(std::string selector, Ref group) { Styles[selector] = group; @@ -90,7 +99,7 @@ namespace UI std::smatch match_value; Layout::LayoutVec4 result; - std::vector splits = InterfaceParser::split(value, ' '); + std::vector splits = Split(value, ' '); int idx = 0; for (auto& s : splits) { diff --git a/Nuake/src/UI/UserInterface.cpp b/Nuake/src/UI/UserInterface.cpp index 7ae18768..44e5ed97 100644 --- a/Nuake/src/UI/UserInterface.cpp +++ b/Nuake/src/UI/UserInterface.cpp @@ -14,11 +14,8 @@ namespace UI m_Name = name; font = FontLoader::LoadFont("resources/Fonts/RobotoMono-Regular.ttf"); - - m_Stylesheet = StyleSheet::New("/Interface\\Testing.css"); - Root = InterfaceParser::Parse("resources/Interface/Testing.interface"); - + if (!Root) { Logger::Log("Failed to generate interface structure"); @@ -38,7 +35,6 @@ namespace UI void UserInterface::Reload() { - m_Stylesheet = StyleSheet::New("/Interface\\Testing.css"); Root = InterfaceParser::Parse("resources/Interface/Testing.interface"); if (!Root) { @@ -67,8 +63,8 @@ namespace UI Root->YogaNode = yoga_root; for (auto& g : Root->GetGroups()) - if (m_Stylesheet->HasStyleGroup(g)) - Root->ApplyStyle(m_Stylesheet->GetStyleGroup(g)); + if (Root->StyleSheet->HasStyleGroup(g)) + Root->ApplyStyle(Root->StyleSheet->GetStyleGroup(g)); Root->SetYogaLayout(); CreateYogaLayoutRecursive(Root, yoga_root); } @@ -85,8 +81,8 @@ namespace UI n->YogaNode = newYogaNode; for (auto& g : n->GetGroups()) - if (m_Stylesheet->HasStyleGroup(g)) - n->ApplyStyle(m_Stylesheet->GetStyleGroup(g)); + if (Root->StyleSheet->HasStyleGroup(g)) + n->ApplyStyle(Root->StyleSheet->GetStyleGroup(g)); n->SetYogaLayout(); YGNodeInsertChild(yoga_node, newYogaNode, index); diff --git a/Nuake/src/UI/UserInterface.h b/Nuake/src/UI/UserInterface.h index f01160f6..e0851f12 100644 --- a/Nuake/src/UI/UserInterface.h +++ b/Nuake/src/UI/UserInterface.h @@ -16,7 +16,6 @@ namespace UI Ref m_Framebuffer; // Texture of the interface. std::string m_Name; Ref Root; - Ref m_Stylesheet; YGConfigRef yoga_config; YGNodeRef yoga_root; public: diff --git a/Nuake/src/Window.cpp b/Nuake/src/Window.cpp index 11aeb4e7..510aee47 100644 --- a/Nuake/src/Window.cpp +++ b/Nuake/src/Window.cpp @@ -232,6 +232,8 @@ void Window::Draw() Ref cam = m_Scene->GetCurrentCamera(); if (!cam) return; + Vector2 size = m_Framebuffer->GetSize(); + cam->AspectRatio = size.x / size.y; Renderer::BeginDraw(cam); {