This commit is contained in:
Isuru Samarathunga
2025-10-14 01:50:56 +05:30
parent 13e8c538c7
commit 58f2190199
13 changed files with 261 additions and 45 deletions

View File

@ -17,20 +17,138 @@
#include <IAEngine/Engine.hpp>
#include <IAEngine/Scene.hpp>
#include <IAEngine/pugixml/pugixml.hpp>
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<const char *>(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> Scene::Create()
{
const auto scene = MakeRefPtr<Scene>();
scene->Extent() = Engine::GetDisplayExtent();
const auto cameraNode = MakeRefPtr<CameraNode>("MainCamera");
scene->AddNode(cameraNode);
scene->m_camera = cameraNode->GetCameraComponent();
return scene;
}
RefPtr<Scene> Scene::Create(IN CONST String &sceneXML)
RefPtr<Scene> Scene::Create(IN CONST String &sceneXML,
IN std::function<RefPtr<Node2D>(IN CONST String &, IN Handle)> getCustomNode,
IN std::function<Handle(IN ResourceType type, IN CONST String &, IN INT64)> getResource)
{
const auto scene = MakeRefPtr<Scene>();
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<String, Handle> 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<TextureNode>(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, "<img(.*?)src=\"(.*?)\"", [&](IN INT32 index, IN CONST String &match) {
if(index == 1)
return BuildString("$H$", resources[match]);
return match;
});
scene->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