From 6e92674bba4bdda49115ce3fdad157b494840db1 Mon Sep 17 00:00:00 2001 From: antopilo Date: Fri, 13 Sep 2024 19:14:46 -0400 Subject: [PATCH] UI hot-reloads if child widgets or stylesheet gets updated --- Nuake/src/FileSystem/File.cpp | 15 +++++++++++++++ Nuake/src/FileSystem/FileTypes.h | 3 ++- Nuake/src/Scene/Systems/UISystem.cpp | 17 ++++++++++++++--- Nuake/src/UI/Nodes/Canvas.cpp | 17 ++++++++++++++--- Nuake/src/UI/Nodes/Canvas.h | 9 +++++++++ Nuake/src/UI/Parsers/CanvasParser.cpp | 21 +++++++++++++++++++-- Nuake/src/UI/Parsers/CanvasParser.h | 1 + Nuake/src/UI/Parsers/StyleSheetParser.cpp | 4 ++-- 8 files changed, 76 insertions(+), 11 deletions(-) diff --git a/Nuake/src/FileSystem/File.cpp b/Nuake/src/FileSystem/File.cpp index 24b8af9f..ae8fa4b7 100644 --- a/Nuake/src/FileSystem/File.cpp +++ b/Nuake/src/FileSystem/File.cpp @@ -84,6 +84,11 @@ FileType File::GetFileType() const return FileType::UI; } + if (ext == ".css") + { + return FileType::CSS; + } + return FileType::Unkown; } @@ -140,6 +145,16 @@ std::string File::GetFileTypeAsString() const return "C# Script"; } + if (ext == ".html") + { + return "UI Layout"; + } + + if (ext == ".css") + { + return "StyleSheet"; + } + return "File"; } diff --git a/Nuake/src/FileSystem/FileTypes.h b/Nuake/src/FileSystem/FileTypes.h index 7632c650..d9e7eb94 100644 --- a/Nuake/src/FileSystem/FileTypes.h +++ b/Nuake/src/FileSystem/FileTypes.h @@ -18,6 +18,7 @@ namespace Nuake Assembly, Solution, Audio, - UI + UI, + CSS }; } diff --git a/Nuake/src/Scene/Systems/UISystem.cpp b/Nuake/src/Scene/Systems/UISystem.cpp index 6c328038..a36af23b 100644 --- a/Nuake/src/Scene/Systems/UISystem.cpp +++ b/Nuake/src/Scene/Systems/UISystem.cpp @@ -5,6 +5,7 @@ #include "src/Resource/ResourceLoader.h" #include "src/Resource/UI.h" #include "src/Scene/Scene.h" +#include "src/UI/Nodes/Canvas.h" #include "src/FileSystem/File.h" #include "src/Scene/Components/UIComponent.h" #include "src/FileSystem/FileSystem.h" @@ -45,11 +46,21 @@ namespace Nuake { if (FileSystem::FileExists(filePath)) { - Ref file = FileSystem::GetFile(filePath); - if (file->GetHasBeenModified()) + auto ui = ResourceManager::GetResource(uiViewComponent.UIResource); + bool sourceHasChanged = false; + for (auto& fileAssociated : ui->GetCanvas()->GetSourceFiles()) + { + // Re-fetching the file object because the Scan might have invalided the pointer. + if (FileSystem::GetFile(fileAssociated->GetRelativePath())->GetHasBeenModified()) + { + sourceHasChanged = true; + FileSystem::GetFile(fileAssociated->GetRelativePath())->SetHasBeenModified(false); + } + } + + if (sourceHasChanged) { uis[uiViewComponent.UIResource]->Reload(); - file->SetHasBeenModified(false); } if (Engine::IsPlayMode()) diff --git a/Nuake/src/UI/Nodes/Canvas.cpp b/Nuake/src/UI/Nodes/Canvas.cpp index d9a23056..5380075e 100644 --- a/Nuake/src/UI/Nodes/Canvas.cpp +++ b/Nuake/src/UI/Nodes/Canvas.cpp @@ -1,10 +1,12 @@ #include "Canvas.h" + +#include "src/UI/Renderer.h" +#include "src/FileSystem/File.h" +#include "Node.h" + #include #include -#include "../Renderer.h" - -#include "Node.h" namespace NuakeUI { @@ -188,4 +190,13 @@ namespace NuakeUI return nodeCache[uuid]; } + void Canvas::AddSourceFile(Ref file) + { + sourceFiles.push_back(file); + } + + std::vector> Canvas::GetSourceFiles() const + { + return sourceFiles; + } } diff --git a/Nuake/src/UI/Nodes/Canvas.h b/Nuake/src/UI/Nodes/Canvas.h index 109f898a..6ac470ca 100644 --- a/Nuake/src/UI/Nodes/Canvas.h +++ b/Nuake/src/UI/Nodes/Canvas.h @@ -10,6 +10,11 @@ #include +namespace Nuake +{ + class File; +} + namespace NuakeUI { class Canvas; @@ -33,6 +38,7 @@ namespace NuakeUI bool mDirty; + std::vector> sourceFiles; public: static CanvasPtr New(); @@ -65,5 +71,8 @@ namespace NuakeUI } Ref GetNodeByUUID(const UUID& uuid); + + void AddSourceFile(Ref file); + std::vector> GetSourceFiles() const; }; } \ No newline at end of file diff --git a/Nuake/src/UI/Parsers/CanvasParser.cpp b/Nuake/src/UI/Parsers/CanvasParser.cpp index 5b75499a..ad2318e9 100644 --- a/Nuake/src/UI/Parsers/CanvasParser.cpp +++ b/Nuake/src/UI/Parsers/CanvasParser.cpp @@ -240,9 +240,23 @@ bool CanvasParser::ScanCustomWidgets(tinyxml2::XMLElement* e, NodePtr node) return false; } + currentParsingCanvas->AddSourceFile(FileSystem::GetFile(customWidget.htmlPath)); + // Parse load HTML file now const std::string& absoluteFilePath = FileSystem::RelativeToAbsolute(customWidget.htmlPath); + + // This is a workaround in case the file is locked by a code editor, retry 5 times. tinyxml2::XMLDocument doc; + tinyxml2::XMLError error; + int attempt = 0; + error = doc.LoadFile(absoluteFilePath.c_str()); + while (error && attempt < 5) + { + error = doc.LoadFile(absoluteFilePath.c_str()); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + attempt++; + } + if (tinyxml2::XMLError error = doc.LoadFile(absoluteFilePath.c_str())) { doc.PrintError(); @@ -308,6 +322,8 @@ Ref CanvasParser::Parse(CanvasPtr canvas, const std::string& path) _parsingPath = path; + currentParsingCanvas = canvas; + tinyxml2::XMLDocument doc; tinyxml2::XMLError error; bool fileLoaded = false; @@ -340,10 +356,11 @@ Ref CanvasParser::Parse(CanvasPtr canvas, const std::string& path) auto styleSheet = firstNode->FindAttribute("stylesheet"); if (styleSheet) { - std::string relativePath = path + "/../" + styleSheet->Value(); - if (FileSystem::FileExists(relativePath, true)) + std::string relativePath = styleSheet->Value(); + if (FileSystem::FileExists(relativePath)) { auto styleSheet = StyleSheetParser::Get().Parse(relativePath); + currentParsingCanvas->AddSourceFile(FileSystem::GetFile(relativePath)); canvas->SetStyleSheet(styleSheet); } } diff --git a/Nuake/src/UI/Parsers/CanvasParser.h b/Nuake/src/UI/Parsers/CanvasParser.h index a849536b..1fbadc94 100644 --- a/Nuake/src/UI/Parsers/CanvasParser.h +++ b/Nuake/src/UI/Parsers/CanvasParser.h @@ -17,6 +17,7 @@ namespace NuakeUI class CanvasParser { private: + Ref currentParsingCanvas; std::map NodeTypes; std::string _parsingPath; std::vector, std::string>> customWidgetIDs; diff --git a/Nuake/src/UI/Parsers/StyleSheetParser.cpp b/Nuake/src/UI/Parsers/StyleSheetParser.cpp index 98512e0a..940bcb68 100644 --- a/Nuake/src/UI/Parsers/StyleSheetParser.cpp +++ b/Nuake/src/UI/Parsers/StyleSheetParser.cpp @@ -11,11 +11,11 @@ using namespace NuakeUI; std::shared_ptr StyleSheetParser::Parse(const std::string& path) { - assert(FileSystem::FileExists(path, true)); + assert(FileSystem::FileExists(path)); _parsingPath = path; - std::string fileContent = FileSystem::ReadFile(path, true); + std::string fileContent = FileSystem::ReadFile(path); auto data = katana_parse(fileContent.c_str(), fileContent.length(), KatanaParserModeStylesheet); auto styleSheet = StyleSheet::New();