UI hot-reloads if child widgets or stylesheet gets updated

This commit is contained in:
antopilo
2024-09-13 19:14:46 -04:00
parent ee852f7f3d
commit 6e92674bba
8 changed files with 76 additions and 11 deletions

View File

@@ -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";
}

View File

@@ -18,6 +18,7 @@ namespace Nuake
Assembly,
Solution,
Audio,
UI
UI,
CSS
};
}

View File

@@ -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> file = FileSystem::GetFile(filePath);
if (file->GetHasBeenModified())
auto ui = ResourceManager::GetResource<UIResource>(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())

View File

@@ -1,10 +1,12 @@
#include "Canvas.h"
#include "src/UI/Renderer.h"
#include "src/FileSystem/File.h"
#include "Node.h"
#include <yoga/Yoga.h>
#include <yoga/YGConfig.h>
#include "../Renderer.h"
#include "Node.h"
namespace NuakeUI
{
@@ -188,4 +190,13 @@ namespace NuakeUI
return nodeCache[uuid];
}
void Canvas::AddSourceFile(Ref<File> file)
{
sourceFiles.push_back(file);
}
std::vector<Ref<File>> Canvas::GetSourceFiles() const
{
return sourceFiles;
}
}

View File

@@ -10,6 +10,11 @@
#include <memory>
namespace Nuake
{
class File;
}
namespace NuakeUI
{
class Canvas;
@@ -33,6 +38,7 @@ namespace NuakeUI
bool mDirty;
std::vector<Ref<Nuake::File>> sourceFiles;
public:
static CanvasPtr New();
@@ -65,5 +71,8 @@ namespace NuakeUI
}
Ref<Node> GetNodeByUUID(const UUID& uuid);
void AddSourceFile(Ref<Nuake::File> file);
std::vector<Ref<Nuake::File>> GetSourceFiles() const;
};
}

View File

@@ -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<Canvas> 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<Canvas> 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);
}
}

View File

@@ -17,6 +17,7 @@ namespace NuakeUI
class CanvasParser
{
private:
Ref<Canvas> currentParsingCanvas;
std::map<std::string, refNew> NodeTypes;
std::string _parsingPath;
std::vector<std::pair<std::pair<UUID, UUID>, std::string>> customWidgetIDs;

View File

@@ -11,11 +11,11 @@ using namespace NuakeUI;
std::shared_ptr<StyleSheet> 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();