From ebedefb6a78613dffa4f8d655ab80437db4f72ec Mon Sep 17 00:00:00 2001 From: Antoine Pilote Date: Tue, 10 Sep 2024 22:27:15 -0400 Subject: [PATCH] Added UI component, resource & system. Now renders on screen and live reloads --- Editor/src/ComponentsPanel/UIPanel.h | 51 ++++++++++ Editor/src/Windows/EditorSelectionPanel.cpp | 1 + Editor/src/Windows/EditorSelectionPanel.h | 2 + Editor/src/Windows/FileSystemUI.cpp | 5 +- Nuake/src/FileSystem/File.cpp | 5 + Nuake/src/FileSystem/FileTypes.h | 3 +- Nuake/src/Rendering/SceneRenderer.cpp | 100 +++++++++----------- Nuake/src/Rendering/SceneRenderer.h | 1 + Nuake/src/Resource/ResourceLoader.cpp | 8 ++ Nuake/src/Resource/ResourceLoader.h | 2 + Nuake/src/Resource/UI.cpp | 72 ++++++++++++++ Nuake/src/Resource/UI.h | 35 +++++++ Nuake/src/Scene/Components/UIComponent.cpp | 1 + Nuake/src/Scene/Components/UIComponent.h | 17 ++++ Nuake/src/Scene/Scene.cpp | 5 +- Nuake/src/Scene/Systems/UISystem.cpp | 70 ++++++++++++++ Nuake/src/Scene/Systems/UISystem.h | 28 ++++++ Nuake/src/UI/Nodes/Canvas.h | 2 +- Nuake/src/UI/Nodes/Node.cpp | 3 +- Nuake/src/UI/Parsers/CanvasParser.cpp | 18 +++- Nuake/src/UI/Parsers/CanvasParser.h | 3 +- 21 files changed, 366 insertions(+), 66 deletions(-) create mode 100644 Editor/src/ComponentsPanel/UIPanel.h create mode 100644 Nuake/src/Resource/UI.cpp create mode 100644 Nuake/src/Resource/UI.h create mode 100644 Nuake/src/Scene/Components/UIComponent.cpp create mode 100644 Nuake/src/Scene/Components/UIComponent.h create mode 100644 Nuake/src/Scene/Systems/UISystem.cpp create mode 100644 Nuake/src/Scene/Systems/UISystem.h diff --git a/Editor/src/ComponentsPanel/UIPanel.h b/Editor/src/ComponentsPanel/UIPanel.h new file mode 100644 index 00000000..05ce4496 --- /dev/null +++ b/Editor/src/ComponentsPanel/UIPanel.h @@ -0,0 +1,51 @@ +#pragma once +#include "ComponentPanel.h" + +#include "src/FileSystem/FileSystem.h" +#include +#include +#include + + +class UIPanel : ComponentPanel +{ +public: + UIPanel() = default; + ~UIPanel() = default; + + void Draw(Nuake::Entity entity) override + { + using namespace Nuake; + + if (!entity.HasComponent()) + return; + + auto& component = entity.GetComponent(); + BeginComponentTable(UI EMITTER, UIComponent); + { + { + ImGui::Text("HTML File"); + ImGui::TableNextColumn(); + + std::string path = component.UIFilePath; + ImGui::Button(component.UIFilePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)); + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_UIFile")) + { + char* file = (char*)payload->Data; + std::string fullPath = std::string(file, 256); + path = Nuake::FileSystem::AbsoluteToRelative(fullPath); + component.UIFilePath = path; + } + ImGui::EndDragDropTarget(); + } + + ImGui::TableNextColumn(); + + ComponentTableReset(component.UIFilePath, ""); + } + } + EndComponentTable(); + } +}; \ No newline at end of file diff --git a/Editor/src/Windows/EditorSelectionPanel.cpp b/Editor/src/Windows/EditorSelectionPanel.cpp index 1e7316dc..e4a438d8 100644 --- a/Editor/src/Windows/EditorSelectionPanel.cpp +++ b/Editor/src/Windows/EditorSelectionPanel.cpp @@ -138,6 +138,7 @@ void EditorSelectionPanel::DrawEntity(Nuake::Entity entity) mMeshColliderPanel.Draw(entity); mCharacterControllerPanel.Draw(entity); mNavMeshVolumePanel.Draw(entity); + mUiPanel.Draw(entity); using namespace Nuake; diff --git a/Editor/src/Windows/EditorSelectionPanel.h b/Editor/src/Windows/EditorSelectionPanel.h index e380af3b..82f3fb0c 100644 --- a/Editor/src/Windows/EditorSelectionPanel.h +++ b/Editor/src/Windows/EditorSelectionPanel.h @@ -25,6 +25,7 @@ #include "../ComponentsPanel/AudioEmitterPanel.h" #include "../ComponentsPanel/NetScriptPanel.h" #include "../ComponentsPanel/NavMeshVolumePanel.h" +#include "../ComponentsPanel/UIPanel.h" #include #include @@ -58,6 +59,7 @@ private: BonePanel mBonePanel; AudioEmitterPanel mAudioEmitterPanel; NavMeshVolumePanel mNavMeshVolumePanel; + UIPanel mUiPanel; Ref currentFile; Ref selectedResource; diff --git a/Editor/src/Windows/FileSystemUI.cpp b/Editor/src/Windows/FileSystemUI.cpp index bbe0bbd1..7304be65 100644 --- a/Editor/src/Windows/FileSystemUI.cpp +++ b/Editor/src/Windows/FileSystemUI.cpp @@ -270,7 +270,6 @@ namespace Nuake OS::OpenIn(file->GetAbsolutePath()); break; } - } Editor->Selection = EditorSelection(file); @@ -320,6 +319,10 @@ namespace Nuake { dragType = "_AudioFile"; } + else if (fileExtension == ".html") + { + dragType = "_UIFile"; + } ImGui::SetDragDropPayload(dragType.c_str(), (void*)(pathBuffer), sizeof(pathBuffer)); ImGui::Text(file->GetName().c_str()); diff --git a/Nuake/src/FileSystem/File.cpp b/Nuake/src/FileSystem/File.cpp index e25ee1be..24b8af9f 100644 --- a/Nuake/src/FileSystem/File.cpp +++ b/Nuake/src/FileSystem/File.cpp @@ -79,6 +79,11 @@ FileType File::GetFileType() const return FileType::Mesh; } + if (ext == ".html") + { + return FileType::UI; + } + return FileType::Unkown; } diff --git a/Nuake/src/FileSystem/FileTypes.h b/Nuake/src/FileSystem/FileTypes.h index cdfd667c..7632c650 100644 --- a/Nuake/src/FileSystem/FileTypes.h +++ b/Nuake/src/FileSystem/FileTypes.h @@ -17,6 +17,7 @@ namespace Nuake Map, Assembly, Solution, - Audio + Audio, + UI }; } diff --git a/Nuake/src/Rendering/SceneRenderer.cpp b/Nuake/src/Rendering/SceneRenderer.cpp index 53366233..9d770748 100644 --- a/Nuake/src/Rendering/SceneRenderer.cpp +++ b/Nuake/src/Rendering/SceneRenderer.cpp @@ -2,12 +2,16 @@ #include "src/Rendering/Shaders/ShaderManager.h" #include "src/Resource/Project.h" +#include "src/Resource/ResourceManager.h" +#include "src/Resource/UI.h" + #include "src/Scene/Components/BSPBrushComponent.h" #include "src/Scene/Components/ModelComponent.h" #include "src/Scene/Components/ParentComponent.h" #include "src/Scene/Components/ParticleEmitterComponent.h" #include "src/Scene/Components/SpriteComponent.h" #include +#include "src/Scene/Components/UIComponent.h" #include #include @@ -34,6 +38,9 @@ namespace Nuake mShadingBuffer->SetTexture(CreateRef(defaultResolution, GL_RGB, GL_RGB16F, GL_FLOAT)); mShadingBuffer->SetTexture(CreateRef(defaultResolution, GL_DEPTH_COMPONENT), GL_DEPTH_ATTACHMENT); // Depth + mTempFrameBuffer = CreateScope(false, defaultResolution); + mTempFrameBuffer->SetTexture(CreateRef(defaultResolution, GL_RGBA), GL_COLOR_ATTACHMENT0); + mToneMapBuffer = CreateScope(false, defaultResolution); mToneMapBuffer->SetTexture(CreateRef(defaultResolution, GL_RGB), GL_COLOR_ATTACHMENT0); @@ -141,6 +148,8 @@ namespace Nuake mGBuffer->QueueResize(framebufferResolution); GBufferPass(scene); + mTempFrameBuffer->QueueResize(framebuffer.GetSize()); + // SSAO const auto& sceneEnv = scene.GetEnvironment(); if (sceneEnv->SSAOEnabled) @@ -169,18 +178,6 @@ namespace Nuake DebugRendererPass(scene); -#ifdef AMD - framebuffer.Bind(); - { - RenderCommand::Clear(); - Shader* shader = ShaderManager::GetShader("Resources/Shaders/copy.shader"); - shader->Bind(); - - shader->SetUniform("u_Source", mShadingBuffer->GetTexture().get(), 0); - Renderer::DrawQuad(); - } - framebuffer.Unbind(); -#else Ref finalOutput = mShadingBuffer->GetTexture(); if (scene.GetEnvironment()->BloomEnabled) { @@ -207,10 +204,7 @@ namespace Nuake sceneEnv->mVolumetric->SetDepth(mGBuffer->GetTexture(GL_DEPTH_ATTACHMENT).get()); sceneEnv->mVolumetric->Draw(mProjection, mView, mCamPos, lightList); - //finalOutput = mVolumetric->GetFinalOutput().get(); - // combine - framebuffer.Bind(); { RenderCommand::Clear(); @@ -261,18 +255,6 @@ namespace Nuake RenderCommand::Clear(); Shader* shader = ShaderManager::GetShader("Resources/Shaders/outline.shader"); shader->Bind(); - - //mGBuffer->GetTexture(GL_COLOR_ATTACHMENT3)->Bind(0); - //mGBuffer->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(1); - //shader->SetUniforms( - //{ - // {"u_EntityID", mOutlineEntityID == -1 ? -1 : mOutlineEntityID + 1}, - // {"u_EntityTexture", 0}, - // {"u_OutlineColor", projectSettings.PrimaryColor}, - // {"u_Depth", 1}, - // {"u_Radius", projectSettings.OutlineRadius * projectSettings.ResolutionScale}, - //}); - shader->SetUniform("u_EntityID", mOutlineEntityID == -1 ? -1 : mOutlineEntityID + 1); shader->SetUniform("u_EntityTexture", mGBuffer->GetTexture(GL_COLOR_ATTACHMENT3).get(), 0); shader->SetUniform("u_OutlineColor", projectSettings.PrimaryColor); @@ -423,18 +405,6 @@ namespace Nuake } mVignetteBuffer->Unbind(); - //framebuffer.Bind(); - //{ - // RenderCommand::Clear(); - // Shader* shader = ShaderManager::GetShader("Resources/Shaders/add.shader"); - // shader->Bind(); - // - // shader->SetUniform("u_Source", mVignetteBuffer->GetTexture().get(), 0); - // shader->SetUniform("u_Source2", mOutlineBuffer->GetTexture().get(), 1); - // Renderer::DrawQuad(); - //} - //framebuffer.Unbind(); - framebuffer.Bind(); { RenderCommand::Clear(); @@ -445,29 +415,45 @@ namespace Nuake Renderer::DrawQuad(); } framebuffer.Unbind(); -#endif - + mTempFrameBuffer->Bind(); + { + RenderCommand::Clear(); + Shader* shader = ShaderManager::GetShader("Resources/Shaders/copy.shader"); + shader->Bind(); - + shader->SetUniform("u_Source", framebuffer.GetTexture().get(), 0); + Renderer::DrawQuad(); + } + mTempFrameBuffer->Unbind(); + + const auto uiView = scene.m_Registry.view(); + for (auto ui : uiView) + { + const UIComponent& uiComponent = uiView.get(ui); + if (!ResourceManager::IsResourceLoaded(uiComponent.UIResource)) + { + continue; + } + + // Fetch resource from resource manager using UUID + Ref uiResource = ResourceManager::GetResource(uiComponent.UIResource); + uiResource->Resize(framebuffer.GetSize()); + + // Copy UI onto final viewport + framebuffer.Bind(); + { + Shader* shader = ShaderManager::GetShader("Resources/Shaders/add.shader"); + shader->Bind(); + shader->SetUniform("u_Source", mTempFrameBuffer->GetTexture().get(), 0); + shader->SetUniform("u_Source2", uiResource->GetOutputTexture().get(), 1); + Renderer::DrawQuad(); + } + framebuffer.Unbind(); + } glDepthMask(true); - // Barrel distortion - //mVignetteBuffer->Bind(); - //{ - // RenderCommand::Clear(); - // Shader* shader = ShaderManager::GetShader("Resources/Shaders/vignette.shader"); - // shader->Bind(); - // - // shader->SetUniform("u_Intensity", sceneEnv->VignetteIntensity); - // shader->SetUniform("u_Extend", sceneEnv->VignetteExtend); - // shader->SetUniform("u_Source", mBarrelDistortionBuffer->GetTexture().get(), 0); - // Renderer::DrawQuad(); - //} - //mVignetteBuffer->Unbind(); - - RenderCommand::Enable(RendererEnum::DEPTH_TEST); Renderer::EndDraw(); } diff --git a/Nuake/src/Rendering/SceneRenderer.h b/Nuake/src/Rendering/SceneRenderer.h index 8170d058..8334aaa7 100644 --- a/Nuake/src/Rendering/SceneRenderer.h +++ b/Nuake/src/Rendering/SceneRenderer.h @@ -94,6 +94,7 @@ namespace Nuake Scope mDOFBuffer; Scope mOutlineBuffer; Scope mDisplayDepthBuffer; + Scope mTempFrameBuffer; // Shapes Ref mBoxGizmo; diff --git a/Nuake/src/Resource/ResourceLoader.cpp b/Nuake/src/Resource/ResourceLoader.cpp index 92988a4e..8186590e 100644 --- a/Nuake/src/Resource/ResourceLoader.cpp +++ b/Nuake/src/Resource/ResourceLoader.cpp @@ -5,6 +5,7 @@ #include "src/Resource/ResourceManager.h" #include "src/Rendering/Textures/Material.h" #include "src/Resource/Model.h" +#include "src/Resource/UI.h" using namespace Nuake; @@ -94,6 +95,13 @@ Ref ResourceLoader::LoadModel(const std::string& path) return model; } +Ref ResourceLoader::LoadUI(const std::string& path) +{ + auto uiResource = CreateRef(path); + uiResource->ID = UUID(); + return uiResource; +} + UUID ResourceLoader::ReadUUID(json j) { if (j.contains("UUID")) diff --git a/Nuake/src/Resource/ResourceLoader.h b/Nuake/src/Resource/ResourceLoader.h index e8f74c05..4e916a7b 100644 --- a/Nuake/src/Resource/ResourceLoader.h +++ b/Nuake/src/Resource/ResourceLoader.h @@ -7,6 +7,7 @@ namespace Nuake { class Material; class Model; + class UIResource; class ResourceLoader { @@ -21,6 +22,7 @@ namespace Nuake static Ref LoadMaterial(const std::string& path); static Ref LoadModel(const std::string& path); + static Ref LoadUI(const std::string& path); private: static UUID ReadUUID(json j); diff --git a/Nuake/src/Resource/UI.cpp b/Nuake/src/Resource/UI.cpp new file mode 100644 index 00000000..8c584144 --- /dev/null +++ b/Nuake/src/Resource/UI.cpp @@ -0,0 +1,72 @@ +#include "UI.h" +#include "Engine.h" +#include "src/FileSystem/FileSystem.h" +#include "src/Rendering/Buffers/Framebuffer.h" +#include "src/UI/NuakeUI.h" +#include "src/UI/Parsers/CanvasParser.h" +#include "src/UI/UIInputManager.h" + + +using namespace Nuake; +using namespace NuakeUI; + +MyInputManager* UIResource::inputManager = nullptr; + +UIResource::UIResource(const std::string& path) : + filePath(path) +{ + const Vector2 defaultSize = { 1280, 720 }; + framebuffer = CreateRef(true, defaultSize); + framebuffer->SetTexture(CreateRef(defaultSize, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE)); + + if (!inputManager) + { + inputManager = new MyInputManager(*Engine::GetCurrentWindow()); + } + + CanvasParser parser; + canvas = parser.Parse(FileSystem::RelativeToAbsolute(path)); + canvas->SetInputManager(inputManager); + canvas->ComputeLayout(defaultSize); +} + +void UIResource::Draw() +{ + framebuffer->Bind(); + { + RenderCommand::Clear(); + + if (canvas) + { + canvas->Draw(); + } + } + framebuffer->Unbind(); +} + +void UIResource::Resize(const Vector2& size) +{ + framebuffer->QueueResize(size); + canvas->ComputeLayout(size); +} + +void UIResource::Reload() +{ + if (!FileSystem::FileExists(filePath)) + { + return; + } + + CanvasParser parser; + canvas = parser.Parse(FileSystem::RelativeToAbsolute(filePath)); + if (canvas) + { + canvas->SetInputManager(inputManager); + canvas->ComputeLayout(framebuffer->GetSize()); + } +} + +Ref UIResource::GetOutputTexture() const +{ + return framebuffer->GetTexture(); +} diff --git a/Nuake/src/Resource/UI.h b/Nuake/src/Resource/UI.h new file mode 100644 index 00000000..1b5400a8 --- /dev/null +++ b/Nuake/src/Resource/UI.h @@ -0,0 +1,35 @@ +#pragma once +#include "Resource.h" +#include "src/Core/Core.h" +#include "src/Core/Maths.h" + +namespace NuakeUI +{ + class Canvas; +} + +namespace Nuake +{ + class FrameBuffer; + class MyInputManager; + class Texture; + + class UIResource : public Resource + { + public: + UIResource(const std::string& path); + ~UIResource() = default; + + void Draw(); + void Resize(const Vector2& size); + void Reload(); + + Ref GetOutputTexture() const; + + private: + Ref canvas; + Ref framebuffer; + static MyInputManager* inputManager; + std::string filePath; + }; +} \ No newline at end of file diff --git a/Nuake/src/Scene/Components/UIComponent.cpp b/Nuake/src/Scene/Components/UIComponent.cpp new file mode 100644 index 00000000..df02ef9a --- /dev/null +++ b/Nuake/src/Scene/Components/UIComponent.cpp @@ -0,0 +1 @@ +#include "UIComponent.h" \ No newline at end of file diff --git a/Nuake/src/Scene/Components/UIComponent.h b/Nuake/src/Scene/Components/UIComponent.h new file mode 100644 index 00000000..6be8711f --- /dev/null +++ b/Nuake/src/Scene/Components/UIComponent.h @@ -0,0 +1,17 @@ +#pragma once +#include "src/Core/Object/Object.h" +#include "src/Resource/UUID.h" + +namespace Nuake +{ + struct UIComponent + { + NUAKECOMPONENT(UIComponent, "UI Component"); + + UUID UIResource = UUID(0); + std::string CSharpUIController; + std::string UIFilePath; + bool IsWorldSpace; + // TODO: Z-Ordering + }; +} \ No newline at end of file diff --git a/Nuake/src/Scene/Scene.cpp b/Nuake/src/Scene/Scene.cpp index fe630935..2ae9bc3a 100644 --- a/Nuake/src/Scene/Scene.cpp +++ b/Nuake/src/Scene/Scene.cpp @@ -12,7 +12,8 @@ #include "src/Scene/Systems/QuakeMapBuilder.h" #include "src/Scene/Systems/ParticleSystem.h" #include "src/Scene/Systems/AnimationSystem.h" -#include +#include "src/Scene/Systems/AudioSystem.h" +#include "src/Scene/Systems/UISystem.h" #include "src/Rendering/SceneRenderer.h" #include "src/Rendering/Renderer.h" @@ -54,6 +55,7 @@ namespace Nuake // Adding systems - Order is important m_Systems.push_back(CreateRef(this)); + m_Systems.push_back(CreateRef(this)); m_Systems.push_back(CreateRef(this)); m_Systems.push_back(CreateRef(this)); m_Systems.push_back(CreateRef(this)); @@ -237,7 +239,6 @@ namespace Nuake } } - return false; } diff --git a/Nuake/src/Scene/Systems/UISystem.cpp b/Nuake/src/Scene/Systems/UISystem.cpp new file mode 100644 index 00000000..46f4a157 --- /dev/null +++ b/Nuake/src/Scene/Systems/UISystem.cpp @@ -0,0 +1,70 @@ +#include "UISystem.h" +#include "src/Resource/ResourceManager.h" +#include "src/Resource/ResourceLoader.h" +#include "src/Resource/UI.h" +#include "src/Scene/Scene.h" +#include "src/FileSystem/File.h" +#include "src/Scene/Components/UIComponent.h" +#include "src/FileSystem/FileSystem.h" + +namespace Nuake +{ + UISystem::UISystem(Scene* scene) + { + m_Scene = scene; + } + + bool UISystem::Init() + { + return true; + } + + void UISystem::Update(Timestep ts) + { + auto uiView = m_Scene->m_Registry.view(); + for (auto e : uiView) + { + auto& uiViewComponent = uiView.get(e); + const std::string& filePath = uiViewComponent.UIFilePath; + if (uiViewComponent.UIResource == 0) + { + if (filePath.empty() || !FileSystem::FileExists(filePath)) + { + continue; + } + + Ref uiResource = ResourceLoader::LoadUI(filePath); + uiViewComponent.UIResource = uiResource->ID; + uis[uiViewComponent.UIResource] = uiResource; + + ResourceManager::RegisterResource(uiResource); + } + else + { + if (FileSystem::FileExists(filePath)) + { + Ref file = FileSystem::GetFile(filePath); + if (file->GetHasBeenModified()) + { + uis[uiViewComponent.UIResource]->Reload(); + file->SetHasBeenModified(false); + } + + uis[uiViewComponent.UIResource]->Draw(); + } + } + } + } + + void UISystem::FixedUpdate(Timestep ts) + { + } + + void UISystem::EditorUpdate() + { + } + + void UISystem::Exit() + { + } +} diff --git a/Nuake/src/Scene/Systems/UISystem.h b/Nuake/src/Scene/Systems/UISystem.h new file mode 100644 index 00000000..bcda56f5 --- /dev/null +++ b/Nuake/src/Scene/Systems/UISystem.h @@ -0,0 +1,28 @@ +#pragma once +#include "src/Resource/UUID.h" +#include "src/Scene/Systems/System.h" +#include "src/Core/Maths.h" + + +namespace Nuake +{ + class UIResource; + + class UISystem : public System + { + public: + UISystem(Scene* scene); + bool Init() override; + + void Update(Timestep ts) override; + void EditorUpdate() override; + void FixedUpdate(Timestep ts) override; + + void Draw() override {} + + void Exit() override; + + private: + std::map> uis; + }; +} diff --git a/Nuake/src/UI/Nodes/Canvas.h b/Nuake/src/UI/Nodes/Canvas.h index 85ded963..e0af1086 100644 --- a/Nuake/src/UI/Nodes/Canvas.h +++ b/Nuake/src/UI/Nodes/Canvas.h @@ -10,7 +10,7 @@ namespace NuakeUI { class Canvas; - typedef std::shared_ptr CanvasPtr; + using CanvasPtr = std::shared_ptr; class Canvas { diff --git a/Nuake/src/UI/Nodes/Node.cpp b/Nuake/src/UI/Nodes/Node.cpp index 5d773606..a2734abf 100644 --- a/Nuake/src/UI/Nodes/Node.cpp +++ b/Nuake/src/UI/Nodes/Node.cpp @@ -1,5 +1,6 @@ #include "Node.h" #include "../Renderer.h" +#include "src/FileSystem/FileSystem.h" #include "NodeState.h" #include "../StringHelper.h" @@ -480,7 +481,7 @@ namespace NuakeUI } else { - auto texture = std::make_shared(value.string); + auto texture = CreateRef(value.string); ComputedStyle.BackgroundImage = texture; } } diff --git a/Nuake/src/UI/Parsers/CanvasParser.cpp b/Nuake/src/UI/Parsers/CanvasParser.cpp index e1a6eec9..24f3d992 100644 --- a/Nuake/src/UI/Parsers/CanvasParser.cpp +++ b/Nuake/src/UI/Parsers/CanvasParser.cpp @@ -11,6 +11,7 @@ #include #include +#include namespace NuakeUI { @@ -249,12 +250,25 @@ namespace NuakeUI } } - CanvasPtr CanvasParser::Parse(const std::string& path) + Ref CanvasParser::Parse(const std::string& path) { _parsingPath = path; tinyxml2::XMLDocument doc; - if (tinyxml2::XMLError error = doc.LoadFile(path.c_str())) + tinyxml2::XMLError error; + bool fileLoaded = false; + for (int i = 0; i < 5; ++i) { // Try 5 times + error = doc.LoadFile(path.c_str()); + if (error == tinyxml2::XML_SUCCESS) { + fileLoaded = true; + break; + } + else if (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Wait before retrying + } + } + + if (error) { doc.PrintError(); return nullptr; diff --git a/Nuake/src/UI/Parsers/CanvasParser.h b/Nuake/src/UI/Parsers/CanvasParser.h index 67e26ac7..7feb6c32 100644 --- a/Nuake/src/UI/Parsers/CanvasParser.h +++ b/Nuake/src/UI/Parsers/CanvasParser.h @@ -1,4 +1,5 @@ #pragma once +#include "src/Core/Core.h" #include "../Nodes/Canvas.h" #include @@ -31,7 +32,7 @@ namespace NuakeUI bool HasNodeType(const std::string& name) const; refNew GetNodeType(const std::string& name) const; - CanvasPtr Parse(const std::string& file); + Ref Parse(const std::string& file); private: void ScanFragment(tinyxml2::XMLElement* e, NodePtr node); void WriteValueFromString(std::variant& var, const std::string& str);