diff --git a/Samples/RPG/Resources/Scenes/GameMap.xml b/Samples/RPG/Resources/Scenes/GameMap.xml index 1c597bf..05b5b9f 100644 --- a/Samples/RPG/Resources/Scenes/GameMap.xml +++ b/Samples/RPG/Resources/Scenes/GameMap.xml @@ -25,7 +25,83 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/RPG/Src/imp/cpp/Game.cpp b/Samples/RPG/Src/imp/cpp/Game.cpp index ae7927b..bb8d73b 100644 --- a/Samples/RPG/Src/imp/cpp/Game.cpp +++ b/Samples/RPG/Src/imp/cpp/Game.cpp @@ -75,7 +75,7 @@ namespace ia::iae::rpg VOID OnUpdate(IN FLOAT32 deltaTime) { - //IAEngine::DrawSprite(g_playerSpriteSheet, 2, 0, {100.0f, 100.0f}, {1.0f, 1.0f}, 0.0f); + //IAEngine::DrawSprite(0, 2, 0, {100.0f, 100.0f}, {1.0f, 1.0f}, 0.0f); } VOID OnResize(IN INT32 newWidth, IN INT32 newHeight) diff --git a/Src/IAEngine/imp/cpp/GameData.cpp b/Src/IAEngine/imp/cpp/GameData.cpp index 78e8abc..a92d421 100644 --- a/Src/IAEngine/imp/cpp/GameData.cpp +++ b/Src/IAEngine/imp/cpp/GameData.cpp @@ -19,8 +19,81 @@ #include +#include + namespace ia::iae { + class XMLData + { + public: + STATIC XMLData *Load(IN CONST String &path); + + CONST String Type; + CONST String Name; + CONST pugi::xml_node PropertiesNode; + CONST Vector ChildNodes; + + private: + CONST pugi::xml_document m_document; + + XMLData(IN pugi::xml_document &&document, IN CONST String &type, IN CONST String &name, + IN pugi::xml_node propertiesNode, IN CONST Vector &childNodes); + }; + + XMLData::XMLData(IN pugi::xml_document &&document, IN CONST String &type, IN CONST String &name, + IN pugi::xml_node propertiesNode, IN CONST Vector &childNodes) + : m_document(IA_MOVE(document)), Type(type), Name(name), PropertiesNode(propertiesNode), ChildNodes(childNodes) + { + } + + XMLData *XMLData::Load(IN CONST String &path) + { + pugi::xml_document doc; + if (!doc.load_file(path.c_str())) + return nullptr; + + if (std::distance(doc.children().begin(), doc.children().end()) != 1) + return nullptr; + const auto rootNode = *doc.children().begin(); + + // Verify Engine Version + { + const auto engineInfoNode = rootNode.child("IAEngine"); + if (!engineInfoNode) + return nullptr; + const auto engineVersionNode = engineInfoNode.child("EngineVersion"); + if (!engineVersionNode) + return nullptr; + const auto engineVersion = IA_PARSE_VERSION_STRING(engineVersionNode.text().as_string()); + if (engineVersion > IAEngine::ENGINE_VERSION) + { + IAE_LOG_WARN("XML data file was created with a newer version of IAEngine, skipping.."); + return nullptr; + } + } + + const auto propertiesNode = rootNode.child("Properties"); + if (!propertiesNode) + return nullptr; + + Vector childNodes; + for (auto &c : rootNode.children()) + { + if ((!strcmp(c.name(), "Properties")) || (!strcmp(c.name(), "IAEngine"))) + continue; + childNodes.pushBack(c); + } + + const auto nameAttr = rootNode.attribute("name"); + return new XMLData(IA_MOVE(doc), rootNode.name(), nameAttr ? nameAttr.as_string() : "", propertiesNode, + childNodes); + } +} // namespace ia::iae + +namespace ia::iae +{ + RefPtr g_entryScene{}; + VOID GameData::Initialize() { if (!LoadResourceData()) @@ -41,17 +114,155 @@ namespace ia::iae BOOL GameData::LoadSceneData() { + for (const auto &entry : std::filesystem::directory_iterator("Resources/Scenes/")) + { + const auto scene = ParseScene(entry.path().string().c_str()); + if (!scene) + { + IAE_LOG_WARN("Failed to load the scene \"", entry.path().string().c_str(), "\", skipping.."); + continue; + } + } return true; } BOOL GameData::LoadResourceData() { - + auto xml = XMLData::Load("Resources/Resources.xml"); + if (!xml) + return false; + + pugi::xml_node entriesNode{}; + for (const auto &node : xml->ChildNodes) + { + if (!strcmp(node.name(), "Entries")) + { + entriesNode = node; + break; + } + } + if (!entriesNode) + return false; + + for (const auto &entry : entriesNode.children()) + { + if (!strcmp(entry.name(), "Sprite")) + { + } + else if (!strcmp(entry.name(), "SpriteSheet")) + { + } + else if (!strcmp(entry.name(), "TileSheet")) + { + IAEngine::AssignResourceName( + IAEngine::CreateTileSheet(BuildString("Resources/", entry.attribute("path").as_string()), + entry.attribute("tileWidth").as_int(), + entry.attribute("tileHeight").as_int()), + entry.attribute("name").as_string()); + } + else + THROW_INVALID_DATA(); + } + + delete xml; return true; } + RefPtr GameData::ParseScene(IN CONST String &path) + { + const auto xml = XMLData::Load(path); + if (!xml) + return nullptr; + + const auto extentNode = xml->PropertiesNode.child("Extent"); + if (!extentNode) + return nullptr; + + const auto extent = IVec2{extentNode.attribute("width").as_int(), extentNode.attribute("height").as_int()}; + RefPtr scene = MakeRefPtr(extent); + + for (const auto &child : xml->ChildNodes) + { + if (!strcmp(child.name(), "Resources")) + { + for (const auto &r : child.children()) + scene->AddReferencedResources(IAEngine::GetResourceByName(r.attribute("name").as_string())); + } + else if (!strcmp(child.name(), "Nodes")) + { + } + else if (!strcmp(child.name(), "Grid")) + { + ParseSceneGrid(scene.get(), &child); + } + else + THROW_INVALID_DATA(); + } + + IAEngine::AssignResourceName(IAEngine::AddScene(scene), xml->Name); + + if (!g_entryScene) + g_entryScene = scene; + + return scene; + } + + VOID GameData::ParseSceneGrid(IN Scene *scene, IN PCVOID _gridNode) + { + const auto gridNode = *static_cast(_gridNode); + + const auto parseHexColor = [](IN PCCHAR hex) -> Vec4 + { + Vec4 result{1.0f, 1.0f, 1.0f, 1.0f}; + if((hex[0] != '#') || (strlen(hex) != 9))return result; + THROW_NOT_IMPLEMENTED(); + return result; + }; + + INT32 tileCursorX{}, tileCursorY{}; + const auto processCell = [&](IN pugi::xml_node cellNode) { + if B_UNLIKELY (tileCursorY >= scene->GetGridSize().y) + return; + + auto& cell = scene->GetGridCell(tileCursorX, tileCursorY); + cell.TileSheetTexture = IAEngine::GetResourceByName(cellNode.attribute("tileSheet").as_string()); + cell.TileIndex.x = cellNode.attribute("tileX").as_int(); + cell.TileIndex.y = cellNode.attribute("tileY").as_int(); + cell.CollisionMask = cellNode.attribute("collisionMask").as_ullong(); + //cell.ColorOverlay = parseHexColor(cellNode.attribute("colorOverlay").as_string()); + + tileCursorX++; + if (tileCursorX >= scene->GetGridSize().x) + { + tileCursorX = 0; + tileCursorY++; + } + }; + + scene->SetupGrid({gridNode.attribute("tileWidth").as_int(), gridNode.attribute("tileHeight").as_int()}); + + for (const auto &t : gridNode.children()) + { + if (!strcmp(t.name(), "Cell")) + { + processCell(t); + } + else if (!strcmp(t.name(), "Repeat")) + { + const auto count = t.attribute("times").as_int(); + for (INT32 i = 0; i < count; i++) + { + for (const auto &cellNode : t) + processCell(cellNode); + } + } + else + THROW_INVALID_DATA(); + } + } + RefPtr GameData::GetEntryScene() { - return nullptr; + return g_entryScene; } } // namespace ia::iae diff --git a/Src/IAEngine/imp/cpp/IAEngine.cpp b/Src/IAEngine/imp/cpp/IAEngine.cpp index 3e59a4b..286b8f1 100644 --- a/Src/IAEngine/imp/cpp/IAEngine.cpp +++ b/Src/IAEngine/imp/cpp/IAEngine.cpp @@ -15,9 +15,9 @@ // along with this program. If not, see . #include +#include #include #include -#include #define STB_IMAGE_IMPLEMENTATION #include @@ -32,7 +32,8 @@ namespace ia::iae TEXTURE, SPRITE_SHEET, - SOUND + SOUND, + SCENE }; EType Type{EType::INVALID}; @@ -48,6 +49,11 @@ namespace ia::iae Vector FrameCounts; }; + struct Resource_Scene : public Resource + { + RefPtr SceneRef; + }; + RefPtr g_activeScene; Vector g_resources; Map g_resourceNames; @@ -146,9 +152,17 @@ namespace ia::iae { Renderer::Initialize(IVec2{g_designViewport.x, g_designViewport.y}); + { // Add default texture to resources + const auto t = new Resource_Texture(); + t->Type = Resource::EType::TEXTURE; + t->Texture = 0; + g_resources.pushBack(t); + } + GameData::Initialize(); - ChangeActiveScene(GameData::GetEntryScene() ? GameData::GetEntryScene() : CreateScene({g_designViewport.x, g_designViewport.y})); + ChangeActiveScene(GameData::GetEntryScene() ? GameData::GetEntryScene() + : CreateScene({g_designViewport.x, g_designViewport.y})); Game_OnInitialize(); } @@ -203,6 +217,8 @@ namespace ia::iae { INT32 w, h, n; auto pixels = stbi_load(path, &w, &h, &n, STBI_rgb_alpha); + if (!pixels) + THROW_INVALID_DATA(path); const auto t = Renderer::CreateTexture(pixels, w, h, tileWidth == -1 ? 1 : w / tileWidth, tileHeight == -1 ? 1 : h / tileHeight); stbi_image_free(pixels); @@ -280,6 +296,10 @@ namespace ia::iae case Resource::EType::SOUND: break; + + case Resource::EType::SCENE: + static_cast(g_resources[resource])->SceneRef.reset(); + break; } delete g_resources[resource]; g_resources[resource] = nullptr; @@ -307,6 +327,7 @@ namespace ia::iae { switch (g_resources[handle]->Type) { + case Resource::EType::SCENE: case Resource::EType::INVALID: break; @@ -367,4 +388,18 @@ namespace ia::iae g_activeScene = scene; LoadResources(scene->GetReferencedResources()); } + + VOID IAEngine::ChangeActiveScene(IN Handle scene) + { + ChangeActiveScene(static_cast(g_resources[scene])->SceneRef); + } + + Handle IAEngine::AddScene(IN RefPtr scene) + { + const auto t = new Resource_Scene(); + t->Type = Resource::EType::SCENE; + t->SceneRef = scene; + g_resources.pushBack(t); + return (Handle) g_resources.size() - 1; + } } // namespace ia::iae \ No newline at end of file diff --git a/Src/IAEngine/imp/cpp/Scene.cpp b/Src/IAEngine/imp/cpp/Scene.cpp index ec654e5..5e4bb27 100644 --- a/Src/IAEngine/imp/cpp/Scene.cpp +++ b/Src/IAEngine/imp/cpp/Scene.cpp @@ -14,8 +14,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#include #include +#include namespace ia::iae { @@ -36,11 +36,22 @@ namespace ia::iae VOID Scene::OnDraw() { - for(const auto& cell: m_gridCells) + INT32 tileCursorX{}, tileCursorY{}; + for (const auto &cell : m_gridCells) { - IAEngine::DrawTile(cell.TileSheetTexture, cell.TileIndex.x, cell.TileIndex.y, { - - }, {1.0f, 1.0f}, 0.0f); + if (cell.TileSheetTexture) + IAEngine::DrawTile(cell.TileSheetTexture, cell.TileIndex.x, cell.TileIndex.y, + { + tileCursorX * m_gridCellSize.x, + tileCursorY * m_gridCellSize.y + }, + {1.0f, 1.0f}, 0.0f); + tileCursorX++; + if (tileCursorX >= GetGridSize().x) + { + tileCursorX = 0; + tileCursorY++; + } } } diff --git a/Src/IAEngine/imp/hpp/GameData.hpp b/Src/IAEngine/imp/hpp/GameData.hpp index fe5e5e9..8645422 100644 --- a/Src/IAEngine/imp/hpp/GameData.hpp +++ b/Src/IAEngine/imp/hpp/GameData.hpp @@ -29,6 +29,9 @@ namespace ia::iae STATIC BOOL LoadSceneData(); STATIC BOOL LoadResourceData(); + STATIC RefPtr ParseScene(IN CONST String& path); + STATIC VOID ParseSceneGrid(IN Scene* scene, IN PCVOID gridNode); + private: STATIC VOID Initialize(); STATIC VOID Terminate(); diff --git a/Src/IAEngine/inc/IAEngine/IAEngine.hpp b/Src/IAEngine/inc/IAEngine/IAEngine.hpp index 82c45ef..7f68b02 100644 --- a/Src/IAEngine/inc/IAEngine/IAEngine.hpp +++ b/Src/IAEngine/inc/IAEngine/IAEngine.hpp @@ -22,6 +22,9 @@ namespace ia::iae { class IAEngine { + public: + STATIC CONSTEXPR IA_VERSION_TYPE ENGINE_VERSION = IA_MAKE_VERSION(1, 0, 0); + public: STATIC Handle CreateSprite(IN CONST String &path); STATIC Handle CreateSprite(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height); @@ -43,6 +46,8 @@ namespace ia::iae public: STATIC RefPtr GetActiveScene(); STATIC RefPtr CreateScene(IN IVec2 extent); + STATIC VOID ChangeActiveScene(IN Handle scene); + STATIC Handle AddScene(IN RefPtr scene); STATIC VOID ChangeActiveScene(IN RefPtr scene); public: diff --git a/Src/IAEngine/inc/IAEngine/Scene.hpp b/Src/IAEngine/inc/IAEngine/Scene.hpp index 874a508..c0baf88 100644 --- a/Src/IAEngine/inc/IAEngine/Scene.hpp +++ b/Src/IAEngine/inc/IAEngine/Scene.hpp @@ -41,7 +41,26 @@ namespace ia::iae INLINE GridCell &GetGridCell(IN INT32 x, IN INT32 y); INLINE VOID AddReferencedResources(IN Handle resource); - INLINE CONST Vector &GetReferencedResources() CONST; + public: + CONST Vector &GetReferencedResources() CONST + { + return m_referencedResources; + } + + CONST IVec2 &GetGridSize() CONST + { + return m_gridSize; + } + + CONST IVec2 &GetExtent() CONST + { + return m_extent; + } + + CONST IVec2 &GetGridCellSize() CONST + { + return m_gridCellSize; + } private: IVec2 m_gridSize{}; @@ -69,9 +88,4 @@ namespace ia::iae { m_referencedResources.pushBack(resource); } - - CONST Vector &Scene::GetReferencedResources() CONST - { - return m_referencedResources; - } } // namespace ia::iae diff --git a/Vendor/IACore b/Vendor/IACore index 2498e7d..cdc4413 160000 --- a/Vendor/IACore +++ b/Vendor/IACore @@ -1 +1 @@ -Subproject commit 2498e7d6e3f5712b28f2c0cdc267b929e6de09b9 +Subproject commit cdc44137e8fe70209f3b2fa048586d36d1e703b7