From 58f2190199ae7de34d3850bc0924c93d213246b0 Mon Sep 17 00:00:00 2001 From: Isuru Samarathunga Date: Tue, 14 Oct 2025 01:50:56 +0530 Subject: [PATCH] Fixes --- .../Imp/CPP/Components/CameraComponent.cpp | 9 +- Engine/Src/Imp/CPP/Engine.cpp | 27 ++-- Engine/Src/Imp/CPP/Renderer/Renderer.cpp | 21 +-- Engine/Src/Imp/CPP/Scene.cpp | 133 +++++++++++++++++- Engine/Src/Imp/CPP/UI.cpp | 15 +- Engine/Src/Imp/CPP/Utils.cpp | 38 ++++- Engine/Src/Imp/CPP/WorldManager.cpp | 1 + Engine/Src/Inc/IAEngine/Base.hpp | 9 +- .../IAEngine/Components/CameraComponent.hpp | 7 +- Engine/Src/Inc/IAEngine/Engine.hpp | 2 +- Engine/Src/Inc/IAEngine/Scene.hpp | 39 ++++- Engine/Src/Inc/IAEngine/UI.hpp | 2 +- Engine/Src/Inc/IAEngine/Utils.hpp | 3 + 13 files changed, 261 insertions(+), 45 deletions(-) diff --git a/Engine/Src/Imp/CPP/Components/CameraComponent.cpp b/Engine/Src/Imp/CPP/Components/CameraComponent.cpp index 5d15d69..7249d18 100644 --- a/Engine/Src/Imp/CPP/Components/CameraComponent.cpp +++ b/Engine/Src/Imp/CPP/Components/CameraComponent.cpp @@ -36,6 +36,13 @@ namespace ia::iae glm::orthoLH(0.0f, (FLOAT32) width, (FLOAT32) height, 0.0f, Renderer::MIN_DEPTH, Renderer::MAX_DEPTH); } + CONST Mat4 *CameraComponent::GetViewMatrix() + { + const auto pos = m_node->GetPosition() + m_positionOffset; + m_viewMatrix = glm::lookAtLH(glm::vec3{pos, -2.0f}, {pos, 0.0f}, {0.0f, 1.0f, 0.0f}); + return &m_viewMatrix; + } + VOID CameraComponent::Draw() { } @@ -46,8 +53,6 @@ namespace ia::iae VOID CameraComponent::Update() { - const auto pos = m_node->GetPosition() + m_positionOffset; - m_viewMatrix = glm::lookAtLH(glm::vec3{pos, -2.0f}, {pos, 0.0f}, {0.0f, 1.0f, 0.0f}); } VOID CameraComponent::FixedUpdate() diff --git a/Engine/Src/Imp/CPP/Engine.cpp b/Engine/Src/Imp/CPP/Engine.cpp index a508d64..fbbf86b 100644 --- a/Engine/Src/Imp/CPP/Engine.cpp +++ b/Engine/Src/Imp/CPP/Engine.cpp @@ -38,11 +38,26 @@ namespace ia::iae #endif } + String Engine::ReadTextAsset(IN CONST String &path) + { + SDL_IOStream *f = SDL_IOFromFile(path.c_str(), "r"); + if (!f) + THROW_FILE_OPEN_READ(path); + Vector result; + SDL_SeekIO(f, 0, SDL_IO_SEEK_END); + result.resize(SDL_TellIO(f) + 1); + SDL_SeekIO(f, 0, SDL_IO_SEEK_SET); + SDL_ReadIO(f, result.data(), result.size()); + result.back() = '\0'; + SDL_CloseIO(f); + return result.data(); + } + Vector Engine::ReadBinaryAsset(IN CONST String &path) { - SDL_IOStream* f = SDL_IOFromFile(path.c_str(), "rb"); - if(!f) - THROW_FILE_OPEN_READ(path); + SDL_IOStream *f = SDL_IOFromFile(path.c_str(), "rb"); + if (!f) + THROW_FILE_OPEN_READ(path); Vector result; SDL_SeekIO(f, 0, SDL_IO_SEEK_END); result.resize(SDL_TellIO(f)); @@ -90,12 +105,6 @@ namespace ia::iae return CreateSound(name, data.data(), data.size()); } - RefPtr Engine::CreateSceneFromFile(IN CONST String &path) - { - const auto data = File::ReadToString(path.c_str()); - return Scene::Create(data); - } - Handle Engine::ResizeImage(IN CONST String &name, IN INT32 newWidth, IN INT32 newHeight) { return ResizeImage(GetImage(name), newWidth, newHeight); diff --git a/Engine/Src/Imp/CPP/Renderer/Renderer.cpp b/Engine/Src/Imp/CPP/Renderer/Renderer.cpp index 9869cff..e417390 100644 --- a/Engine/Src/Imp/CPP/Renderer/Renderer.cpp +++ b/Engine/Src/Imp/CPP/Renderer/Renderer.cpp @@ -27,6 +27,8 @@ namespace ia::iae { + STATIC Mat4 IdentityMatrix(1.0f); + EXTERN SDL_Window *g_windowHandle; INT32 Renderer::s_screenWidth{}; @@ -136,8 +138,6 @@ namespace ia::iae VOID Renderer::BeginFrame() { - STATIC Mat4 IdentityMatrix(1.0f); - if (!(s_state.ActiveCommandBuffer = SDL_AcquireGPUCommandBuffer(s_gpuDevice))) THROW_UNKNOWN("Failed to acquire SDL GPU command buffer: ", SDL_GetError()); @@ -152,10 +152,6 @@ namespace ia::iae SDL_PushGPUVertexUniformData( s_state.ActiveCommandBuffer, 0, s_state.ActiveCamera ? s_state.ActiveCamera->GetProjectionMatrix() : &IdentityMatrix, sizeof(Mat4)); - SDL_PushGPUVertexUniformData( - s_state.ActiveCommandBuffer, 1, - (s_state.ActiveCamera && s_state.CameraRelative) ? s_state.ActiveCamera->GetViewMatrix() : &IdentityMatrix, - sizeof(Mat4)); } VOID Renderer::EndFrame() @@ -236,9 +232,9 @@ namespace ia::iae const auto activeScene = WorldManager::GetActiveScene(); if (activeScene) { - const auto sceneExtent = activeScene->Extent(); - s_state.SceneScaleFactor = {(FLOAT32) newWidth / (FLOAT32) sceneExtent.x, - (FLOAT32) newHeight / (FLOAT32) sceneExtent.y}; + const auto sceneViewport = activeScene->Viewport(); + s_state.SceneScaleFactor = {(FLOAT32) newWidth / (FLOAT32) sceneViewport.x, + (FLOAT32) newHeight / (FLOAT32) sceneViewport.y}; IAE_LOG_INFO("Updated Scene Scale Factor: (", s_state.SceneScaleFactor.x, ", ", s_state.SceneScaleFactor.y, ")"); } @@ -282,6 +278,11 @@ namespace ia::iae #pragma pack(pop) + SDL_PushGPUVertexUniformData( + s_state.ActiveCommandBuffer, 1, + (s_state.ActiveCamera && s_state.CameraRelative) ? s_state.ActiveCamera->GetViewMatrix() : &IdentityMatrix, + sizeof(Mat4)); + s_fragmentUniform.ColorOverlay = s_state.ColorOverlay.GetAsFloatVec(); s_fragmentUniform.FlippedH = s_state.FlippedH; s_fragmentUniform.FlippedV = s_state.FlippedV; @@ -385,7 +386,7 @@ namespace ia::iae sortIndex += static_cast(position.y); position *= Renderer::s_state.SceneScaleFactor; - // scale *= Renderer::s_state.SceneScaleFactor; + scale *= Renderer::s_state.SceneScaleFactor; Renderer::s_state.ModelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3{position.x, position.y, diff --git a/Engine/Src/Imp/CPP/Scene.cpp b/Engine/Src/Imp/CPP/Scene.cpp index 9a50723..ad5b2b6 100644 --- a/Engine/Src/Imp/CPP/Scene.cpp +++ b/Engine/Src/Imp/CPP/Scene.cpp @@ -17,20 +17,138 @@ #include #include +#include + namespace ia::iae { + // ----------------------------------------------- + // getInnerXML and xml_string_writer were taken from https://stackoverflow.com/a/60337372 + struct xml_string_writer : pugi::xml_writer + { + std::string result; + + virtual void write(const void *data, size_t size) + { + result.append(static_cast(data), size); + } + }; + + const auto getInnerXML = [](pugi::xml_node target) { + xml_string_writer writer; + for (pugi::xml_node child = target.first_child(); child; child = child.next_sibling()) + child.print(writer, ""); + return writer.result; + }; + + // ----------------------------------------------- + RefPtr Scene::Create() { const auto scene = MakeRefPtr(); scene->Extent() = Engine::GetDisplayExtent(); + const auto cameraNode = MakeRefPtr("MainCamera"); + scene->AddNode(cameraNode); + scene->m_camera = cameraNode->GetCameraComponent(); return scene; } - RefPtr Scene::Create(IN CONST String &sceneXML) + RefPtr Scene::Create(IN CONST String &sceneXML, + IN std::function(IN CONST String &, IN Handle)> getCustomNode, + IN std::function getResource) { - const auto scene = MakeRefPtr(); - scene->Extent() = Engine::GetDisplayExtent(); - + const auto scene = Create(); + + pugi::xml_document doc; + doc.load_string(sceneXML.c_str()); + const auto sceneRoot = doc.child("Scene"); + + Map resources; + + // Process Resources + const auto resRoot = sceneRoot.child("Resources"); + if (!resRoot) + THROW_INVALID_DATA("Scene file is missing 'Resources' tag"); + { + for (const auto &t : resRoot.children()) + { + if (!strcmp(t.name(), "Image")) + { + resources[t.attribute("name").as_string()] = getResource( + ResourceType::IMAGE, t.attribute("path").as_string(), t.attribute("index").as_llong()); + } + else if (!strcmp(t.name(), "Audio")) + { + resources[t.attribute("name").as_string()] = + getResource(ResourceType::SOUND, t.attribute("path").as_string(), 0); + } + } + } + + // Process Properties + const auto propRoot = sceneRoot.child("Properties"); + if (!propRoot) + THROW_INVALID_DATA("Scene file is missing 'Properties' tag"); + { + auto t = propRoot.child("Extent"); + scene->Extent() = Vec2{t.attribute("width").as_float(), t.attribute("height").as_float()}; + + t = propRoot.child("Viewport"); + scene->Viewport() = Vec2{t.attribute("width").as_float(), t.attribute("height").as_float()}; + } + + // Process Nodes + const auto nodeRoot = sceneRoot.child("Nodes"); + if (!nodeRoot) + THROW_INVALID_DATA("Scene file is missing 'Nodes' tag"); + { + for (const auto &t : nodeRoot) + { + Node2D* n{}; + if (!strcmp(t.name(), "TextureNode")) + { + const auto node = MakeRefPtr(Engine::GetUniqueResourceName()); + node->GetTextureComponent()->SetTexture(resources[t.attribute("texture").as_string()]); + scene->AddNode(node); + n = node.get(); + } + else + { + Handle id{INVALID_HANDLE}; + const auto attrID = t.attribute("id"); + if(attrID) + id = (Handle)attrID.as_ullong(); + const auto node = getCustomNode(t.name(), id); + scene->AddNode(node); + n = node.get(); + } + + if(!n) continue; + if(t.attribute("X") && t.attribute("Y")) + { + n->SetLocalPosition({ + t.attribute("X").as_float(), + t.attribute("Y").as_float() + }); + } + } + } + + // Process UI + const auto uiRoot = sceneRoot.child("UI"); + if (!uiRoot) + THROW_INVALID_DATA("Scene file is missing 'UI' tag"); + { + scene->UIMarkupStyles() = getInnerXML(uiRoot.child("CSS")).c_str(); + auto html = String(getInnerXML(uiRoot.child("HTML")).c_str()); + html = + Utils::RegexReplaceGroups(html, "UIMarkup() = html; + } + return scene; } @@ -72,4 +190,11 @@ namespace ia::iae { m_nodes[name] = nullptr; } + + VOID Scene::OnActivate() + { + UI::SetMarkup(UIMarkup(), UIMarkupStyles()); + if(m_camera) + Engine::SetActiveCamera(m_camera); + } } // namespace ia::iae diff --git a/Engine/Src/Imp/CPP/UI.cpp b/Engine/Src/Imp/CPP/UI.cpp index 30e03af..93889e7 100644 --- a/Engine/Src/Imp/CPP/UI.cpp +++ b/Engine/Src/Imp/CPP/UI.cpp @@ -452,10 +452,11 @@ namespace ia::iae Rml::LoadFontFace(path.c_str()); } - VOID UI::SetHTML(IN CONST String &source) + VOID UI::SetMarkup(IN CONST String &markup, IN CONST String &styles) { + g_document->SetStyleSheetContainer(Rml::Factory::InstanceStyleSheetString(styles.c_str())); g_document->SetInnerRML( - BuildString("", source, "").c_str()); + BuildString("", markup, "").c_str()); } VOID UI::AddClickEvent(IN PCCHAR elementId, IN std::function callback) @@ -502,8 +503,14 @@ namespace ia::iae Rml::TextureHandle RmlUIRenderInterface::LoadTexture(Rml::Vector2i &texture_dimensions, const Rml::String &source) { - return Engine::CreateImageFromFile(Engine::GetUniqueResourceName(), source.c_str(), texture_dimensions.x, - texture_dimensions.y); + Handle result; + if (source.starts_with("$H$")) + result = (Handle) std::stoi(source.substr(3)); + else + result = Engine::CreateImageFromFile(Engine::GetUniqueResourceName(), source.c_str()); + const auto extent = Engine::GetImageExtent(result); + texture_dimensions = {extent.x, extent.y}; + return result; } Rml::TextureHandle RmlUIRenderInterface::GenerateTexture(Rml::Span source, diff --git a/Engine/Src/Imp/CPP/Utils.cpp b/Engine/Src/Imp/CPP/Utils.cpp index d0dad3b..21bc40d 100644 --- a/Engine/Src/Imp/CPP/Utils.cpp +++ b/Engine/Src/Imp/CPP/Utils.cpp @@ -18,13 +18,15 @@ #include +#include + namespace ia::iae { Vector Utils::Inflate(IN PCUINT8 data, IN SIZE_T dataSize) { STATIC UINT8 TMP_BUFFER[16384]; Vector result; - result.reserve(ia_min((SIZE_T)(dataSize * 3), sizeof(TMP_BUFFER))); + result.reserve(ia_min((SIZE_T) (dataSize * 3), sizeof(TMP_BUFFER))); z_stream stream; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; @@ -35,7 +37,8 @@ namespace ia::iae THROW_UNKNOWN("Inflate failed: init zlib inflate"); stream.avail_in = dataSize; stream.next_in = (Bytef *) data; - while (true) { + while (true) + { stream.avail_out = sizeof(TMP_BUFFER); stream.next_out = TMP_BUFFER; const auto r = inflate(&stream, Z_SYNC_FLUSH); @@ -58,4 +61,35 @@ namespace ia::iae result.resize(deflateBound); return result; } + + String Utils::RegexReplaceString(IN CONST String &input, IN CONST String &from, IN CONST String &to) + { + return std::regex_replace(input.c_str(), std::regex(from.c_str()), to.c_str()).c_str(); + } + + String Utils::RegexReplaceGroups(IN CONST String &input, IN CONST String &pattern, + IN std::function groupTransformer) + { + std::string text = input.c_str(); + + std::smatch match; + std::string result; + std::string::const_iterator search_start(text.cbegin()); + + SIZE_T t1 = 0, t2 = 0; + while (std::regex_search(search_start, text.cend(), match, std::regex(pattern.c_str()))) + { + for(SIZE_T i = 1; i < match.size(); i++) + { + result += text.substr(t1, match.position(i) - t1); + result += std::string(groupTransformer(i - 1, match.str(i).c_str()).c_str()); + t1 = match.position(i); + t2 = match.str(i).length(); + } + result += text.substr(match.suffix().first - text.begin() - 1); + search_start = match.suffix().first; + } + + return result.c_str(); + } } // namespace ia::iae \ No newline at end of file diff --git a/Engine/Src/Imp/CPP/WorldManager.cpp b/Engine/Src/Imp/CPP/WorldManager.cpp index 253f1fd..bbd6726 100644 --- a/Engine/Src/Imp/CPP/WorldManager.cpp +++ b/Engine/Src/Imp/CPP/WorldManager.cpp @@ -54,6 +54,7 @@ namespace ia::iae VOID WorldManager::ChangeActiveScene(IN RefPtr scene) { s_activeScene = scene; + scene->OnActivate(); } VOID WorldManager::AddNodeToActiveScene(IN RefPtr node) diff --git a/Engine/Src/Inc/IAEngine/Base.hpp b/Engine/Src/Inc/IAEngine/Base.hpp index edc9052..7c8de88 100644 --- a/Engine/Src/Inc/IAEngine/Base.hpp +++ b/Engine/Src/Inc/IAEngine/Base.hpp @@ -102,7 +102,8 @@ namespace ia::iae Vec4 Color{}; }; - enum class Direction : UINT8 { + enum class Direction : UINT8 + { NONE = 255, DOWN = 0, DOWN_LEFT, @@ -114,6 +115,12 @@ namespace ia::iae DOWN_RIGHT }; + enum class ResourceType + { + IMAGE, + SOUND, + }; + struct Color { UINT8 R{0xFF}; diff --git a/Engine/Src/Inc/IAEngine/Components/CameraComponent.hpp b/Engine/Src/Inc/IAEngine/Components/CameraComponent.hpp index fe9c044..bf63f80 100644 --- a/Engine/Src/Inc/IAEngine/Components/CameraComponent.hpp +++ b/Engine/Src/Inc/IAEngine/Components/CameraComponent.hpp @@ -45,10 +45,7 @@ namespace ia::iae return m_viewport; } - CONST Mat4 *GetViewMatrix() CONST - { - return &m_viewMatrix; - } + CONST Mat4 *GetViewMatrix(); CONST Mat4 *GetProjectionMatrix() CONST { @@ -57,8 +54,8 @@ namespace ia::iae private: Vec4 m_viewport{}; - Mat4 m_viewMatrix{1.0f}; Vec2 m_positionOffset{}; + Mat4 m_viewMatrix{1.0f}; Mat4 m_projectionMatrix{1.0f}; }; } // namespace ia::iae diff --git a/Engine/Src/Inc/IAEngine/Engine.hpp b/Engine/Src/Inc/IAEngine/Engine.hpp index a6e6543..ef664e7 100644 --- a/Engine/Src/Inc/IAEngine/Engine.hpp +++ b/Engine/Src/Inc/IAEngine/Engine.hpp @@ -93,7 +93,6 @@ namespace ia::iae STATIC CameraComponent *GetActiveCamera(); // Scene Functions - STATIC RefPtr CreateSceneFromFile(IN CONST String &path); STATIC Scene *GetActiveScene(); STATIC VOID ChangeActiveScene(IN RefPtr scene); STATIC VOID AddNodeToActiveScene(IN RefPtr node); @@ -118,6 +117,7 @@ namespace ia::iae STATIC VOID BindInputAxis(IN InputKey upKey, IN InputKey downKey, IN InputKey leftKey, IN InputKey rightKey); // Utility Functions + STATIC String ReadTextAsset(IN CONST String& path); STATIC Direction GetVectorPointingDirection(IN Vec2 v); STATIC Vector ReadBinaryAsset(IN CONST String& path); diff --git a/Engine/Src/Inc/IAEngine/Scene.hpp b/Engine/Src/Inc/IAEngine/Scene.hpp index d05950f..68c13a6 100644 --- a/Engine/Src/Inc/IAEngine/Scene.hpp +++ b/Engine/Src/Inc/IAEngine/Scene.hpp @@ -16,6 +16,7 @@ #pragma once +#include #include namespace ia::iae @@ -23,27 +24,48 @@ namespace ia::iae class Scene { public: - STATIC RefPtr Create(); - STATIC RefPtr Create(IN CONST String &sceneXML); + STATIC RefPtr Create(); + STATIC RefPtr Create( + IN CONST String &sceneXML, IN std::function(IN CONST String &, IN Handle)> getCustomNode, + IN std::function getResource); public: - VOID AddNode(IN RefPtr node); - INode *GetNode(IN CONST String &name); - VOID RemoveNode(IN CONST String &name); + VOID AddNode(IN RefPtr node); + INode *GetNode(IN CONST String &name); + VOID RemoveNode(IN CONST String &name); public: - IVec2& Extent() + String &UIMarkup() + { + return m_uiMarkup; + } + + String &UIMarkupStyles() + { + return m_uiMarkupStyles; + } + + IVec2 &Extent() { return m_extent; } + IVec2 &Viewport() + { + return m_viewport; + } + Color &BackgroundColor() { return m_backgroundColor; } private: + String m_uiMarkup{}; + String m_uiMarkupStyles{}; IVec2 m_extent{100, 100}; + IVec2 m_viewport{100, 100}; + CameraComponent *m_camera{}; Color m_backgroundColor{0, 0, 0, 255}; Map> m_nodes; @@ -53,5 +75,10 @@ namespace ia::iae VOID FixedUpdate(); VOID Update(); + + private: + VOID OnActivate(); + + friend class WorldManager; }; } // namespace ia::iae \ No newline at end of file diff --git a/Engine/Src/Inc/IAEngine/UI.hpp b/Engine/Src/Inc/IAEngine/UI.hpp index e84e864..16a07cb 100644 --- a/Engine/Src/Inc/IAEngine/UI.hpp +++ b/Engine/Src/Inc/IAEngine/UI.hpp @@ -25,7 +25,7 @@ namespace ia::iae public: STATIC VOID AddFontFromFile(IN CONST String &path); - STATIC VOID SetHTML(IN CONST String &source); + STATIC VOID SetMarkup(IN CONST String &markup, IN CONST String &styles); STATIC VOID AddClickEvent(IN PCCHAR elementId, IN std::function callback); diff --git a/Engine/Src/Inc/IAEngine/Utils.hpp b/Engine/Src/Inc/IAEngine/Utils.hpp index 61033d9..11f0882 100644 --- a/Engine/Src/Inc/IAEngine/Utils.hpp +++ b/Engine/Src/Inc/IAEngine/Utils.hpp @@ -25,5 +25,8 @@ namespace ia::iae public: STATIC Vector Inflate(IN PCUINT8 data, IN SIZE_T dataSize); STATIC Vector Deflate(IN PCUINT8 data, IN SIZE_T dataSize); + + STATIC String RegexReplaceString(IN CONST String& input, IN CONST String& from, IN CONST String& to); + STATIC String RegexReplaceGroups(IN CONST String& input, IN CONST String& pattern, IN std::function groupTransformer); }; } \ No newline at end of file