Fixes
This commit is contained in:
@ -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
|
||||
|
||||
Reference in New Issue
Block a user