Compare commits

..

2 Commits

Author SHA1 Message Date
73d26b2f35 Fixes 2025-11-08 23:46:47 +05:30
042ff451b1 Fixes 2025-11-06 01:01:32 +05:30
42 changed files with 4349 additions and 533 deletions

View File

@ -1,4 +1,6 @@
add_subdirectory(Common/)
add_subdirectory(ConfigParser/)
add_subdirectory(RenderCore/) add_subdirectory(RenderCore/)
add_subdirectory(IAEngine/) add_subdirectory(IAEngine/)
add_subdirectory(CLI/) add_subdirectory(CLI/)

10
Src/Common/CMakeLists.txt Normal file
View File

@ -0,0 +1,10 @@
set(SRC_FILES
"imp/cpp/Common.cpp"
)
add_library(Common STATIC ${SRC_FILES})
target_include_directories(Common PUBLIC inc)
target_include_directories(Common PRIVATE imp/hpp)
target_link_libraries(Common PUBLIC IACore SDL3::SDL3 glm::glm pugixml::pugixml)

View File

View File

@ -0,0 +1,48 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IACore/Exception.hpp>
#include <IACore/Logger.hpp>
#include <IACore/Map.hpp>
#include <IACore/Memory.hpp>
#include <IACore/String.hpp>
#include <IACore/Vector.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glm/ext/scalar_constants.hpp>
#include <glm/mat4x4.hpp>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
namespace ia::iae
{
STATIC CONSTEXPR IA_VERSION_TYPE ENGINE_VERSION = IA_MAKE_VERSION(1, 0, 0);
using Handle = INT64;
STATIC CONSTEXPR Handle INVALID_HANDLE = -1;
using Vec2 = glm::vec2;
using Vec3 = glm::vec3;
using Vec4 = glm::vec4;
using IVec2 = glm::ivec2;
using IVec3 = glm::ivec3;
using IVec4 = glm::ivec4;
using Mat4 = glm::mat4;
} // namespace ia::iae

View File

@ -0,0 +1,10 @@
set(SRC_FILES
"imp/cpp/ConfigData.cpp"
)
add_library(ConfigData STATIC ${SRC_FILES})
target_include_directories(ConfigData PUBLIC inc)
target_include_directories(ConfigData PRIVATE imp/hpp)
target_link_libraries(ConfigData PUBLIC Common)

View File

@ -0,0 +1,83 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <ConfigData/ConfigData.hpp>
#include <IACore/File.hpp>
namespace ia::iae
{
ConfigData::ConfigData(IN pugi::xml_document &&document, IN CONST String &type, IN CONST String &name,
IN pugi::xml_node propertiesNode, IN Vector<pugi::xml_node> &&childNodes)
: m_document(IA_MOVE(document)), m_type(type), m_name(name), m_propertiesNode(propertiesNode),
m_childNodes(IA_MOVE(childNodes))
{
}
RefPtr<ConfigData> ConfigData::LoadFromFile(IN CONST String &path)
{
return LoadFromMemory(File::ReadToString(path));
}
RefPtr<ConfigData> ConfigData::LoadFromMemory(IN CONST String &data)
{
pugi::xml_document doc;
if (!doc.load_string(data.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 > ENGINE_VERSION)
{
CFG_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<pugi::xml_node> 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 MakeRefPtr<ConfigData>(IA_MOVE(doc), rootNode.name(), nameAttr ? nameAttr.as_string() : "",
propertiesNode, IA_MOVE(childNodes));
}
pugi::xml_node ConfigData::Property(IN CONST String &name)
{
return m_propertiesNode.child(name.c_str());
}
} // namespace ia::iae

View File

@ -0,0 +1,33 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <Common/Base.hpp>
#include <pugixml.hpp>
#define CFG_LOG_TAG "CFG"
#define CFG_LOG_INFO(...) ia::Logger::Info(CFG_LOG_TAG, __VA_ARGS__)
#define CFG_LOG_WARN(...) ia::Logger::Warn(CFG_LOG_TAG, __VA_ARGS__)
#define CFG_LOG_ERROR(...) ia::Logger::Error(CFG_LOG_TAG, __VA_ARGS__)
#define CFG_LOG_SUCCESS(...) ia::Logger::Success(CFG_LOG_TAG, __VA_ARGS__)
namespace ia::iae
{
} // namespace ia::iae

View File

@ -0,0 +1,59 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <ConfigData/Base.hpp>
namespace ia::iae
{
class ConfigData
{
public:
STATIC RefPtr<ConfigData> LoadFromFile(IN CONST String &path);
STATIC RefPtr<ConfigData> LoadFromMemory(IN CONST String &data);
public:
pugi::xml_node Property(IN CONST String &name);
public:
CONST String &Type() CONST
{
return m_type;
}
CONST String &Name() CONST
{
return m_name;
}
CONST Vector<pugi::xml_node> &Children() CONST
{
return m_childNodes;
}
private:
CONST String m_type;
CONST String m_name;
CONST pugi::xml_document m_document;
CONST pugi::xml_node m_propertiesNode;
CONST Vector<pugi::xml_node> m_childNodes;
public:
ConfigData(IN pugi::xml_document &&document, IN CONST String &type, IN CONST String &name,
IN pugi::xml_node propertiesNode, IN Vector<pugi::xml_node> &&childNodes);
};
} // namespace ia::iae

View File

@ -1,8 +1,12 @@
set(SRC_FILES set(SRC_FILES
"imp/cpp/UI.cpp" "imp/cpp/UI.cpp"
"imp/cpp/Main.cpp" "imp/cpp/Main.cpp"
"imp/cpp/Editor.cpp"
"imp/cpp/Project.cpp"
"imp/cpp/GamePreview.cpp" "imp/cpp/GamePreview.cpp"
"imp/cpp/View/AssetBrowser.cpp"
# imgui # imgui
"imp/cpp/Vendor/imgui/imgui.cpp" "imp/cpp/Vendor/imgui/imgui.cpp"
"imp/cpp/Vendor/imgui/imgui_draw.cpp" "imp/cpp/Vendor/imgui/imgui_draw.cpp"

File diff suppressed because one or more lines are too long

View File

@ -17,7 +17,7 @@
#include <GamePreview.hpp> #include <GamePreview.hpp>
#include <RenderCore/RenderCore.hpp> #include <RenderCore/RenderCore.hpp>
namespace ia::iae::editor namespace ia::iae
{ {
} }

View File

@ -14,9 +14,9 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <UI.hpp> #include <Editor.hpp>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
return ia::iae::editor::UI::Run(argc, (const char **) argv); return ia::iae::Editor::Instance().Run(argc, (const char **) argv);
} }

View File

@ -0,0 +1,38 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <Project.hpp>
#include <ConfigData/ConfigData.hpp>
#include <filesystem>
namespace ia::iae
{
RefPtr<Project> Project::Load(IN CONST String &directory)
{
const auto config = ConfigData::LoadFromFile(BuildString(directory, "/", "Project.iae"));
return MakeRefPtr<Project>(config->Name(), std::filesystem::canonical(directory.c_str()).string().c_str());
}
Project::Project(IN CONST String& name, IN CONST String& absolutePath):
m_projectName(name), m_projectAbsolutePath(absolutePath), m_assetDirectory(BuildString(absolutePath, "/Assets/"))
{
IA_ASSERT(std::filesystem::exists(m_assetDirectory.c_str()));
}
Project::~Project()
{
}
} // namespace ia::iae

View File

@ -20,23 +20,26 @@
#include <Vendor/imgui/backends/imgui_impl_sdl3.h> #include <Vendor/imgui/backends/imgui_impl_sdl3.h>
#include <Vendor/imgui/backends/imgui_impl_sdlgpu3.h> #include <Vendor/imgui/backends/imgui_impl_sdlgpu3.h>
#include <Vendor/imgui/imgui.h>
#include <UI.hpp> #include <UI.hpp>
namespace ia::iae::editor #include <View/AssetBrowser.hpp>
{
CONST IVec2 gamePreviewResolution = {800, 608};
IVec2 g_windowExtent{800, 600}; namespace ia::iae
RDC_Texture *g_gamePreviewTexture{}; {
EXTERN IVec2 g_windowExtent;
EXTERN RDC_Texture *g_gamePreviewTexture;
View_AssetBrowser g_assetBrowserView;
VOID UI::Initialize() VOID UI::Initialize()
{ {
g_assetBrowserView.Initialize();
} }
VOID UI::Terminate() VOID UI::Terminate()
{ {
g_assetBrowserView.Terminate();
} }
VOID UI::Update() VOID UI::Update()
@ -66,142 +69,19 @@ namespace ia::iae::editor
{ // Properties View { // Properties View
ImGui::Begin("Properties", nullptr, ImGui::Begin("Properties", nullptr,
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
ImGui::SetWindowSize({g_windowExtent.x / 2.0f - gamePreviewViewSize.x / 2.0f - 15.0f, gamePreviewViewSize.y + 35}); ImGui::SetWindowSize(
{g_windowExtent.x / 2.0f - gamePreviewViewSize.x / 2.0f - 15.0f, gamePreviewViewSize.y + 35});
ImGui::SetWindowPos({g_windowExtent.x - ImGui::GetWindowSize().x, 0.0f}); ImGui::SetWindowPos({g_windowExtent.x - ImGui::GetWindowSize().x, 0.0f});
ImGui::End(); ImGui::End();
} }
{ // Tileset View { // Asset Browser View
ImGui::Begin("Tilesets", nullptr, ImGui::Begin("Asset Browser", nullptr,
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse); ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse);
ImGui::SetWindowPos({0.0f, gamePreviewViewSize.y + 35}); ImGui::SetWindowPos({0.0f, gamePreviewViewSize.y + 35});
ImGui::SetWindowSize({(FLOAT32)g_windowExtent.x, (FLOAT32)g_windowExtent.y - gamePreviewViewSize.y - 35}); ImGui::SetWindowSize({(FLOAT32) g_windowExtent.x, (FLOAT32) g_windowExtent.y - gamePreviewViewSize.y - 35});
g_assetBrowserView.Render();
ImGui::End(); ImGui::End();
} }
} }
} // namespace ia::iae::editor } // namespace ia::iae::editor
namespace ia::iae
{
EXTERN Vec2 g_designViewport;
EXTERN SDL_Window *g_windowHandle;
} // namespace ia::iae
namespace ia::iae::editor
{
ImDrawData *g_imDrawData{};
INT32 UI::Run(IN INT32 argc, IN PCCHAR argv[])
{
INT32 frameCounter{0};
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD))
THROW_UNKNOWN("Failed to intialize SDL: ", SDL_GetError());
if (!(g_windowHandle = SDL_CreateWindow("IAEngine", g_windowExtent.x, g_windowExtent.y,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED)))
THROW_UNKNOWN("Failed to create the SDL window: ", SDL_GetError());
SDL_MaximizeWindow(g_windowHandle);
SDL_GetWindowSizeInPixels(g_windowHandle, &g_windowExtent.x, &g_windowExtent.y);
g_designViewport = gamePreviewResolution;
IAEngine::__Initialize();
g_gamePreviewTexture = new RDC_Texture(RDC_Texture::EType::SAMPLED, g_designViewport.x, g_designViewport.y);
const auto mainScale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
IMGUI_CHECKVERSION();
ImGui::CreateContext();
auto &imGUIIO = ImGui::GetIO();
imGUIIO.IniFilename = nullptr;
imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
ImGui::StyleColorsClassic();
ImGuiStyle &style = ImGui::GetStyle();
style.ScaleAllSizes(mainScale);
style.FontScaleDpi = mainScale;
ImGui_ImplSDLGPU3_InitInfo initInfo{.Device = RDC_Device::GetHandle(),
.ColorTargetFormat = RDC_Device::GetSwapchainTextureFormat(),
.PresentMode = SDL_GPU_PRESENTMODE_VSYNC};
ImGui_ImplSDL3_InitForSDLGPU(g_windowHandle);
ImGui_ImplSDLGPU3_Init(&initInfo);
Initialize();
SDL_Event event{};
while (true)
{
SDL_PollEvent(&event);
if (event.type == SDL_EVENT_QUIT)
break;
IAEngine::__ProcessEvent(&event);
IAEngine::__Update();
ImGui_ImplSDL3_ProcessEvent(&event);
Update();
frameCounter++;
if (frameCounter >= 60)
{
frameCounter = 0;
IAEngine::__FixedUpdate();
}
IAEngine::__RenderToTexture(g_gamePreviewTexture->GetHandle());
ImGui_ImplSDLGPU3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
Draw();
ImGui::Render();
STATIC SDL_GPURenderPass *ActiveRenderPass{};
STATIC SDL_GPUCommandBuffer *ActiveCommandBuffer{};
STATIC SDL_GPUColorTargetInfo ActiveColorTargetInfo{.clear_color = SDL_FColor{0.0f, 0.0f, 0.0f, 1.0f},
.load_op = SDL_GPU_LOADOP_CLEAR,
.store_op = SDL_GPU_STOREOP_STORE};
if (!(ActiveCommandBuffer = SDL_AcquireGPUCommandBuffer(RDC_Device::GetHandle())))
THROW_UNKNOWN("Failed to acquire SDL GPU command buffer: ", SDL_GetError());
g_imDrawData = ImGui::GetDrawData();
ImGui_ImplSDLGPU3_PrepareDrawData(g_imDrawData, ActiveCommandBuffer);
SDL_GPUTexture *swapChainTexture{};
if (!SDL_WaitAndAcquireGPUSwapchainTexture(ActiveCommandBuffer, g_windowHandle, &swapChainTexture, nullptr,
nullptr))
THROW_UNKNOWN("Failed to acquire SDL GPU Swapchain texture: ", SDL_GetError());
ActiveColorTargetInfo.texture = swapChainTexture;
ActiveColorTargetInfo.clear_color = SDL_FColor{0.3f, 0.3f, 0.3f, 1.0f};
ActiveRenderPass = SDL_BeginGPURenderPass(ActiveCommandBuffer, &ActiveColorTargetInfo, 1, nullptr);
ImGui_ImplSDLGPU3_RenderDrawData(g_imDrawData, ActiveCommandBuffer, ActiveRenderPass);
SDL_EndGPURenderPass(ActiveRenderPass);
SDL_SubmitGPUCommandBuffer(ActiveCommandBuffer);
RDC_Device::WaitForIdle();
}
Terminate();
ImGui_ImplSDL3_Shutdown();
ImGui_ImplSDLGPU3_Shutdown();
ImGui::DestroyContext();
delete g_gamePreviewTexture;
IAEngine::__Terminate();
SDL_DestroyWindow(g_windowHandle);
return 0;
}
} // namespace ia::iae::editor

View File

@ -0,0 +1,97 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <View/AssetBrowser.hpp>
namespace ia::iae
{
VOID View_AssetBrowser::Initialize()
{
if (!std::filesystem::exists("Assets"))
THROW_INVALID_DATA("Not a valid IAEngine project directory");
m_assetDirectoryPath = std::filesystem::current_path() / "Assets/";
ChangeCurrentOpenDirectory(m_assetDirectoryPath);
FillFileEntries(m_assetDirectoryPath, m_assetDirectoryFiles);
}
VOID View_AssetBrowser::Terminate()
{
}
VOID View_AssetBrowser::Render()
{
PreRender();
if (ImGui::BeginTable("root", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingStretchProp))
{
ImGui::TableSetupColumn("Navigation", ImGuiTableColumnFlags_WidthStretch, 0.25f);
ImGui::TableSetupColumn("Asset Browser", ImGuiTableColumnFlags_WidthStretch, 0.75f);
ImGui::TableNextColumn();
if (ImGui::BeginChild("Navigation", ImVec2(0, -FLT_MIN)))
{
for (const auto &t : m_assetDirectoryFiles)
{
ImGui::Text("%s %s", t.Icon, t.Name.c_str());
}
}
ImGui::EndChild();
ImGui::TableNextColumn();
if (ImGui::BeginChild("Asset Browser", ImVec2(0, -FLT_MIN)))
{
}
ImGui::EndChild();
ImGui::EndTable();
}
PostRender();
}
VOID View_AssetBrowser::ChangeCurrentOpenDirectory(IN CONST std::filesystem::path &path)
{
m_currentOpenDirectoryPath = path;
std::filesystem::current_path(m_currentOpenDirectoryPath);
FillFileEntries(m_currentOpenDirectoryPath, m_currentOpenDirectoryFiles);
}
VOID View_AssetBrowser::FillFileEntries(IN CONST std::filesystem::path &path, IN Vector<FileEntry> &fileEntries)
{
for (const auto &t : std::filesystem::directory_iterator(path))
{
if (!t.is_directory())
continue;
fileEntries.pushBack(
{.Icon = ICON_FA_FOLDER, .Name = t.path().filename().string().c_str(), .IsDirectory = true});
}
for (const auto &t : std::filesystem::directory_iterator(path))
{
if (t.is_directory())
continue;
fileEntries.pushBack({.Icon = GetFileEntryIcon(t.path().extension().string().c_str()),
.Name = t.path().filename().string().c_str(),
.IsDirectory = false});
}
}
PCCHAR View_AssetBrowser::GetFileEntryIcon(IN PCCHAR extension)
{
if(!strcmp(extension, ".xml"))
return ICON_FA_CODE;
return "";
}
} // namespace ia::iae::editor

View File

@ -18,7 +18,10 @@
#include <IAEngine/Base.hpp> #include <IAEngine/Base.hpp>
namespace ia::iae::editor #include <Vendor/imgui/imgui.h>
#include <Vendor/IconsFontAwesome7.h>
namespace ia::iae
{ {
} }

View File

@ -0,0 +1,48 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <Project.hpp>
namespace ia::iae
{
class Editor
{
STATIC Editor s_instance;
public:
STATIC Editor &Instance()
{
return s_instance;
}
public:
VOID LoadProject(IN CONST String &directory);
public:
CONST Project *GetActiveProject() CONST
{
return m_activeProject.get();
}
public:
INT32 Run(IN INT32 argc, IN PCCHAR argv[]);
private:
RefPtr<Project> m_activeProject{};
};
} // namespace ia::iae

View File

@ -18,7 +18,7 @@
#include <Base.hpp> #include <Base.hpp>
namespace ia::iae::editor namespace ia::iae
{ {
class GamePreview class GamePreview
{ {

View File

@ -0,0 +1,48 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <Base.hpp>
namespace ia::iae
{
class Project
{
public:
STATIC RefPtr<Project> Load(IN CONST String &directory);
public:
CONST String &Name() CONST
{
return m_projectName;
}
CONST String &AssetDirectory() CONST
{
return m_assetDirectory;
}
private:
CONST String m_projectName;
CONST String m_assetDirectory;
CONST String m_projectAbsolutePath;
public:
Project(IN CONST String &name, IN CONST String &absolutePath);
~Project();
};
} // namespace ia::iae

View File

@ -18,14 +18,13 @@
#include <Base.hpp> #include <Base.hpp>
namespace ia::iae::editor namespace ia::iae
{ {
CONST IVec2 gamePreviewResolution = {800, 608};
class UI class UI
{ {
public: public:
STATIC INT32 Run(IN INT32 argc, IN PCCHAR argv[]);
private:
STATIC VOID Initialize(); STATIC VOID Initialize();
STATIC VOID Terminate(); STATIC VOID Terminate();
STATIC VOID Update(); STATIC VOID Update();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <View/IView.hpp>
#include <filesystem>
namespace ia::iae
{
class View_AssetBrowser : public IView
{
struct FileEntry
{
PCCHAR Icon{""};
String Name{};
BOOL IsDirectory{};
};
public:
VOID Initialize();
VOID Terminate();
VOID Render();
private:
VOID ChangeCurrentOpenDirectory(IN CONST std::filesystem::path &path);
VOID FillFileEntries(IN CONST std::filesystem::path &path, IN Vector<FileEntry> &fileEntries);
PCCHAR GetFileEntryIcon(IN PCCHAR extension);
private:
Vector<FileEntry> m_assetDirectoryFiles;
std::filesystem::path m_assetDirectoryPath{};
Vector<FileEntry> m_currentOpenDirectoryFiles;
std::filesystem::path m_currentOpenDirectoryPath{};
};
} // namespace ia::iae::editor

View File

@ -0,0 +1,46 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <Base.hpp>
namespace ia::iae
{
class IView
{
public:
PURE_VIRTUAL(VOID Initialize());
PURE_VIRTUAL(VOID Terminate());
PURE_VIRTUAL(VOID Render());
protected:
INLINE VOID PreRender();
INLINE VOID PostRender();
protected:
ImVec2 m_extent{};
};
VOID IView::PreRender()
{
m_extent = ImGui::GetWindowSize();
}
VOID IView::PostRender()
{
}
} // namespace ia::iae::editor

View File

@ -3,6 +3,7 @@ set(SRC_FILES
"imp/cpp/Scene.cpp" "imp/cpp/Scene.cpp"
"imp/cpp/GameData.cpp" "imp/cpp/GameData.cpp"
"imp/cpp/AssetManager.cpp"
#"imp/cpp/EmbeddedResources.cpp" #"imp/cpp/EmbeddedResources.cpp"
) )
@ -11,5 +12,5 @@ add_library(IAEngine STATIC ${SRC_FILES})
target_include_directories(IAEngine PUBLIC inc) target_include_directories(IAEngine PUBLIC inc)
target_include_directories(IAEngine PRIVATE imp/hpp) target_include_directories(IAEngine PRIVATE imp/hpp)
target_link_libraries(IAEngine PUBLIC RenderCore pugixml::pugixml) target_link_libraries(IAEngine PUBLIC RenderCore ConfigData)
target_link_libraries(IAEngine PRIVATE ZLIB::ZLIBSTATIC SDL3_mixer::SDL3_mixer) target_link_libraries(IAEngine PRIVATE ZLIB::ZLIBSTATIC SDL3_mixer::SDL3_mixer)

View File

@ -0,0 +1,272 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/AssetManager.hpp>
#include <IAEngine/IAEngine.hpp>
#include <SDL3/SDL_iostream.h>
#define STB_IMAGE_IMPLEMENTATION
#include <Vendor/stb/stb_image.h>
#include <RenderCore/RenderCore.hpp>
#include <IACore/DynamicLib.hpp>
namespace ia::iae
{
Handle CreateTextureFromFile(IN PCCHAR path, IN INT32 tileWidth = -1, IN INT32 tileHeight = -1)
{
const auto data = IAEngine::GetAssetManager()->ReadBinaryAsset(path);
INT32 w, h, n;
auto pixels = stbi_load_from_memory(data.data(), data.size(), &w, &h, &n, STBI_rgb_alpha);
if (!pixels)
THROW_INVALID_DATA(path);
const auto t =
RDC::CreateImage(pixels, w, h, tileWidth == -1 ? 1 : w / tileWidth, tileHeight == -1 ? 1 : h / tileHeight);
stbi_image_free(pixels);
return t;
}
VOID AssetManager::Initialize()
{
}
VOID AssetManager::Terminate()
{
for (SIZE_T i = 0; i < m_assets.size(); i++)
DestroyAsset(m_assets[i]);
}
VOID AssetManager::SetAssetDirectory(IN CONST String &path)
{
m_assetDirectory = path;
}
String AssetManager::ReadTextAsset(IN CONST String &path)
{
const auto t = BuildString(m_assetDirectory, "/", path);
SDL_IOStream *f = SDL_IOFromFile(t.c_str(), "r");
if (!f)
THROW_FILE_OPEN_READ(t);
Vector<CHAR> result;
SDL_SeekIO(f, 0, SDL_IO_SEEK_END);
result.resize(SDL_TellIO(f) + 1);
SDL_SeekIO(f, 0, SDL_IO_SEEK_SET);
SDL_ReadIO(f, result.data(), result.size());
result.back() = '\0';
SDL_CloseIO(f);
return result.data();
}
Vector<UINT8> AssetManager::ReadBinaryAsset(IN CONST String &path)
{
const auto t = BuildString(m_assetDirectory, "/", path);
SDL_IOStream *f = SDL_IOFromFile(t.c_str(), "rb");
if (!f)
THROW_FILE_OPEN_READ(t);
Vector<UINT8> result;
SDL_SeekIO(f, 0, SDL_IO_SEEK_END);
result.resize(SDL_TellIO(f));
SDL_SeekIO(f, 0, SDL_IO_SEEK_SET);
SDL_ReadIO(f, result.data(), result.size());
SDL_CloseIO(f);
return result;
}
Asset_Plugin *AssetManager::LoadPlugin(IN CONST String &path)
{
auto lib = DynamicLib::Load(BuildString(m_assetDirectory, "/Plugins"), path);
auto t = new Asset_Plugin();
t->OnInitialize = lib.GetFunction<VOID (*)()>("Plugin_OnInitialize");
t->OnTerminate = lib.GetFunction<VOID (*)()>("Plugin_OnTerminate");
t->OnDebugDraw = lib.GetFunction<VOID (*)()>("Plugin_OnDebugDraw");
t->OnFixedUpdate = lib.GetFunction<VOID (*)()>("Plugin_OnFixedUpdate");
t->OnUpdate = lib.GetFunction<VOID (*)(IN FLOAT32 deltaTime)>("Plugin_OnUpdate");
return t;
}
Asset_Sprite *AssetManager::CreateSprite(IN CONST String &path)
{
const auto t = new Asset_Sprite();
t->m_texture = CreateTextureFromFile(path.c_str());
m_assets.pushBack(t);
return t;
}
Asset_Sprite *AssetManager::CreateSprite(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
{
const auto t = new Asset_Sprite();
t->m_texture = RDC::CreateImage(rgbaData, width, height);
m_assets.pushBack(t);
return t;
}
Asset_SpriteSheet *AssetManager::CreateSpriteSheet(IN CONST Vector<Vector<Handle>> &animations)
{
THROW_NOT_IMPLEMENTED();
return nullptr;
}
Asset_SpriteSheet *AssetManager::CreateSpriteSheet(IN CONST String &path, IN INT32 spriteWidth,
IN INT32 spriteHeight, IN CONST Vector<INT32> &frameCounts)
{
const auto t = new Asset_SpriteSheet();
t->m_frameCounts = frameCounts;
t->m_texture = CreateTextureFromFile(path.c_str(), spriteWidth, spriteHeight);
m_assets.pushBack(t);
return t;
}
Asset_TileSheet *AssetManager::CreateTileSheet(IN CONST String &path, IN INT32 tileWidth, IN INT32 tileHeight)
{
const auto t = new Asset_TileSheet();
t->m_texture = CreateTextureFromFile(path.c_str(), tileWidth, tileHeight);
m_assets.pushBack(t);
return t;
}
Asset_TileSheet *AssetManager::CreateTileSheet(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height,
IN INT32 tileWidth, IN INT32 tileHeight)
{
const auto t = new Asset_TileSheet();
t->m_texture = RDC::CreateImage(rgbaData, width, height, width / tileWidth, height / tileHeight);
m_assets.pushBack(t);
return t;
}
VOID AssetManager::DestroyAsset(IN IAsset *asset)
{
asset->Destroy();
delete asset;
for (auto &t : m_assets)
if (t == asset)
t = nullptr;
for (auto &t : m_assetNames)
if (t->Value == asset)
t->Value = nullptr;
}
IAsset *AssetManager::GetAssetByName(IN CONST String &name)
{
return m_assetNames[name];
}
VOID AssetManager::AssignAssetName(IN IAsset *asset, IN CONST String &name)
{
m_assetNames[name] = asset;
}
Asset_Scene *AssetManager::CreateScene(IN IVec2 extent)
{
const auto t = new Asset_Scene();
t->m_scene.SetExtent(extent);
m_assets.pushBack(t);
return t;
}
} // namespace ia::iae
namespace ia::iae
{
IAsset::IAsset(IN EAssetType type) : m_type(type)
{
}
IAsset::~IAsset()
{
}
VOID Asset_Sprite::Compile()
{
}
VOID Asset_Sprite::Destroy()
{
}
VOID Asset_SpriteSheet::Compile()
{
}
VOID Asset_SpriteSheet::Destroy()
{
}
VOID Asset_Scene::Compile()
{
}
VOID Asset_Scene::Destroy()
{
}
VOID Asset_Plugin::Compile()
{
}
VOID Asset_Plugin::Destroy()
{
}
} // namespace ia::iae
#include <zlib.h>
namespace ia::iae
{
Vector<UINT8> AssetManager::Inflate(IN PCUINT8 data, IN SIZE_T dataSize)
{
STATIC UINT8 TMP_BUFFER[16384];
Vector<UINT8> result;
result.reserve(dataSize * 3);
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = 0;
stream.next_in = Z_NULL;
if (inflateInit(&stream) != Z_OK)
THROW_UNKNOWN("Inflate failed: init zlib inflate");
stream.avail_in = dataSize;
stream.next_in = (Bytef *) data;
while (true)
{
stream.avail_out = sizeof(TMP_BUFFER);
stream.next_out = TMP_BUFFER;
const auto r = inflate(&stream, Z_SYNC_FLUSH);
result.insert(result.end(), sizeof(TMP_BUFFER) - stream.avail_out, TMP_BUFFER);
if (r == Z_STREAM_END)
break;
else if (r != Z_OK)
THROW_INVALID_DATA("Inflate failed: zlib inflation");
}
inflateEnd(&stream);
return result;
}
Vector<UINT8> AssetManager::Deflate(IN PCUINT8 data, IN SIZE_T dataSize)
{
Vector<UINT8> result;
auto deflateBound = compressBound(dataSize);
result.resize(deflateBound);
compress(result.data(), &deflateBound, data, dataSize);
result.resize(deflateBound);
return result;
}
} // namespace ia::iae

File diff suppressed because one or more lines are too long

View File

@ -17,88 +17,19 @@
#include <GameData.hpp> #include <GameData.hpp>
#include <IAEngine/IAEngine.hpp> #include <IAEngine/IAEngine.hpp>
#include <pugixml.hpp> #include <ConfigData/ConfigData.hpp>
#include <filesystem> #include <filesystem>
namespace ia::iae namespace ia::iae
{ {
class XMLData Asset_Scene* g_entryScene{};
{
public:
STATIC XMLData *Load(IN CONST String &path);
CONST String Type;
CONST String Name;
CONST pugi::xml_node PropertiesNode;
CONST Vector<pugi::xml_node> 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<pugi::xml_node> &childNodes);
};
XMLData::XMLData(IN pugi::xml_document &&document, IN CONST String &type, IN CONST String &name,
IN pugi::xml_node propertiesNode, IN CONST Vector<pugi::xml_node> &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<pugi::xml_node> 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<Scene> g_entryScene{};
VOID GameData::Initialize() VOID GameData::Initialize()
{ {
if (!LoadResourceData()) if (!LoadAssetData())
{ {
IAE_LOG_WARN("Couldn't load \"Resources.XML\", skipping.."); IAE_LOG_WARN("Couldn't load \"Assets.XML\", skipping..");
return; return;
} }
if (!LoadSceneData()) if (!LoadSceneData())
@ -114,7 +45,7 @@ namespace ia::iae
BOOL GameData::LoadSceneData() BOOL GameData::LoadSceneData()
{ {
for (const auto &entry : std::filesystem::directory_iterator("Resources/Scenes/")) for (const auto &entry : std::filesystem::directory_iterator("Assets/Scenes/"))
{ {
const auto scene = ParseScene(entry.path().string().c_str()); const auto scene = ParseScene(entry.path().string().c_str());
if (!scene) if (!scene)
@ -126,14 +57,14 @@ namespace ia::iae
return true; return true;
} }
BOOL GameData::LoadResourceData() BOOL GameData::LoadAssetData()
{ {
auto xml = XMLData::Load("Resources/Resources.xml"); auto xml = ConfigData::LoadFromFile("Assets/Assets.xml");
if (!xml) if (!xml)
return false; return false;
pugi::xml_node entriesNode{}; pugi::xml_node entriesNode{};
for (const auto &node : xml->ChildNodes) for (const auto &node : xml->Children())
{ {
if (!strcmp(node.name(), "Entries")) if (!strcmp(node.name(), "Entries"))
{ {
@ -154,8 +85,8 @@ namespace ia::iae
} }
else if (!strcmp(entry.name(), "TileSheet")) else if (!strcmp(entry.name(), "TileSheet"))
{ {
IAEngine::AssignResourceName( IAEngine::GetAssetManager()->AssignAssetName(
IAEngine::CreateTileSheet(BuildString("Resources/", entry.attribute("path").as_string()), IAEngine::GetAssetManager()->CreateTileSheet(entry.attribute("path").as_string(),
entry.attribute("tileWidth").as_int(), entry.attribute("tileWidth").as_int(),
entry.attribute("tileHeight").as_int()), entry.attribute("tileHeight").as_int()),
entry.attribute("name").as_string()); entry.attribute("name").as_string());
@ -164,42 +95,41 @@ namespace ia::iae
THROW_INVALID_DATA(); THROW_INVALID_DATA();
} }
delete xml;
return true; return true;
} }
RefPtr<Scene> GameData::ParseScene(IN CONST String &path) Asset_Scene* GameData::ParseScene(IN CONST String &path)
{ {
const auto xml = XMLData::Load(path); const auto xml = ConfigData::LoadFromFile(path);
if (!xml) if (!xml)
return nullptr; return nullptr;
const auto extentNode = xml->PropertiesNode.child("Extent"); const auto extentNode = xml->Property("Extent");
if (!extentNode) if (!extentNode)
return nullptr; return nullptr;
const auto extent = IVec2{extentNode.attribute("width").as_int(), extentNode.attribute("height").as_int()}; const auto extent = IVec2{extentNode.attribute("width").as_int(), extentNode.attribute("height").as_int()};
RefPtr<Scene> scene = MakeRefPtr<Scene>(extent); auto scene = IAEngine::GetAssetManager()->CreateScene(extent);
for (const auto &child : xml->ChildNodes) for (const auto &child : xml->Children())
{ {
if (!strcmp(child.name(), "Resources")) if (!strcmp(child.name(), "Assets"))
{ {
for (const auto &r : child.children()) for (const auto &r : child.children())
scene->AddReferencedResources(IAEngine::GetResourceByName(r.attribute("name").as_string())); scene->GetScene().AddReferencedResources(IAEngine::GetAssetManager()->GetAssetByName<IAsset>(r.attribute("name").as_string()));
} }
else if (!strcmp(child.name(), "Nodes")) else if (!strcmp(child.name(), "Nodes"))
{ {
} }
else if (!strcmp(child.name(), "Grid")) else if (!strcmp(child.name(), "Grid"))
{ {
ParseSceneGrid(scene.get(), &child); ParseSceneGrid(&scene->GetScene(), &child);
} }
else else
THROW_INVALID_DATA(); THROW_INVALID_DATA();
} }
IAEngine::AssignResourceName(IAEngine::AddScene(scene), xml->Name); IAEngine::GetAssetManager()->AssignAssetName(scene, xml->Name());
if (!g_entryScene) if (!g_entryScene)
g_entryScene = scene; g_entryScene = scene;
@ -225,7 +155,7 @@ namespace ia::iae
return; return;
auto& cell = scene->GetGridCell(tileCursorX, tileCursorY); auto& cell = scene->GetGridCell(tileCursorX, tileCursorY);
cell.TileSheetTexture = IAEngine::GetResourceByName(cellNode.attribute("tileSheet").as_string()); cell.TileSheet = IAEngine::GetAssetManager()->GetAssetByName<Asset_TileSheet>(cellNode.attribute("tileSheet").as_string());
cell.TileIndex.x = cellNode.attribute("tileX").as_int(); cell.TileIndex.x = cellNode.attribute("tileX").as_int();
cell.TileIndex.y = cellNode.attribute("tileY").as_int(); cell.TileIndex.y = cellNode.attribute("tileY").as_int();
cell.CollisionMask = cellNode.attribute("collisionMask").as_ullong(); cell.CollisionMask = cellNode.attribute("collisionMask").as_ullong();
@ -261,7 +191,7 @@ namespace ia::iae
} }
} }
RefPtr<Scene> GameData::GetEntryScene() Asset_Scene* GameData::GetEntryScene()
{ {
return g_entryScene; return g_entryScene;
} }

View File

@ -18,50 +18,12 @@
#include <GameData.hpp> #include <GameData.hpp>
#include <IAEngine/LibInterface.hpp> #include <IAEngine/LibInterface.hpp>
#define STB_IMAGE_IMPLEMENTATION
#include <Vendor/stb/stb_image.h>
#include <RenderCore/RenderCore.hpp> #include <RenderCore/RenderCore.hpp>
namespace ia::iae namespace ia::iae
{ {
struct Resource Asset_Scene *g_activeScene{};
{
enum class EType
{
INVALID,
TEXTURE,
SPRITE_SHEET,
SOUND,
SCENE
};
EType Type{EType::INVALID};
};
struct Resource_Texture : public Resource
{
Handle Texture;
};
struct Resource_SpriteSheet : public Resource_Texture
{
Vector<INT32> FrameCounts;
};
struct Resource_Scene : public Resource
{
RefPtr<Scene> SceneRef;
};
RefPtr<Scene> g_activeScene;
Vector<Resource *> g_resources;
Map<String, Handle> g_resourceNames;
} // namespace ia::iae
namespace ia::iae
{
String g_gameName; String g_gameName;
String g_gamePackageName; String g_gamePackageName;
String g_gameDeveloperName; String g_gameDeveloperName;
@ -71,6 +33,11 @@ namespace ia::iae
Vec2 g_designViewport; Vec2 g_designViewport;
SDL_Window *g_windowHandle{}; SDL_Window *g_windowHandle{};
Vector<Asset_Plugin *> g_plugins;
AssetManager* g_assetManager{};
AssetManager* g_defaultAssetManager{};
#if defined(__IA_DEBUG) && __IA_DEBUG #if defined(__IA_DEBUG) && __IA_DEBUG
BOOL g_isDebugMode = true; BOOL g_isDebugMode = true;
#else #else
@ -156,267 +123,155 @@ namespace ia::iae
RDC::Initialize(IVec2{g_designViewport.x, g_designViewport.y}, g_windowHandle, g_isDebugMode); RDC::Initialize(IVec2{g_designViewport.x, g_designViewport.y}, g_windowHandle, g_isDebugMode);
g_defaultAssetManager = new AssetManager();
g_assetManager = g_defaultAssetManager;
GameData::Initialize(); GameData::Initialize();
ChangeActiveScene(GameData::GetEntryScene() ? GameData::GetEntryScene() ChangeActiveScene(GameData::GetEntryScene()
: CreateScene({g_designViewport.x, g_designViewport.y})); ? GameData::GetEntryScene()
: g_assetManager->CreateScene({g_designViewport.x, g_designViewport.y}));
Game_OnInitialize(); Game_OnInitialize();
for (auto &p : g_plugins)
p->OnInitialize();
} }
VOID IAEngine::__InitializeHeadless() VOID IAEngine::__InitializeHeadless()
{ {
g_isHeadlessMode = true; g_isHeadlessMode = true;
if(!g_designViewport.x || !g_designViewport.y) if (!g_designViewport.x || !g_designViewport.y)
g_designViewport = {800, 600}; g_designViewport = {800, 600};
g_defaultAssetManager = new AssetManager();
g_assetManager = g_defaultAssetManager;
GameData::Initialize(); GameData::Initialize();
ChangeActiveScene(GameData::GetEntryScene() ? GameData::GetEntryScene() ChangeActiveScene(GameData::GetEntryScene()
: CreateScene({g_designViewport.x, g_designViewport.y})); ? GameData::GetEntryScene()
: g_assetManager->CreateScene({g_designViewport.x, g_designViewport.y}));
Game_OnInitialize(); Game_OnInitialize();
for (auto &p : g_plugins)
p->OnInitialize();
} }
VOID IAEngine::__Terminate() VOID IAEngine::__Terminate()
{ {
for (auto &p : g_plugins)
p->OnTerminate();
Game_OnTerminate(); Game_OnTerminate();
GameData::Terminate(); GameData::Terminate();
RDC::Terminate(); delete g_defaultAssetManager;
for (SIZE_T i = 0; i < g_resources.size(); i++) RDC::Terminate();
DestroyResource(i);
} }
VOID IAEngine::__RenderToWindow() VOID IAEngine::__RenderToWindow()
{ {
g_activeScene->OnDraw(); g_activeScene->GetScene().OnDraw();
RDC::RenderToWindow(); RDC::RenderToWindow();
g_activeScene->OnDebugDraw(); g_activeScene->GetScene().OnDebugDraw();
Game_OnDebugDraw(); Game_OnDebugDraw();
for (auto &p : g_plugins)
p->OnDebugDraw();
} }
VOID IAEngine::__RenderToTexture(IN PVOID textureHandle) VOID IAEngine::__RenderToTexture(IN PVOID textureHandle)
{ {
g_activeScene->OnDraw(); g_activeScene->GetScene().OnDraw();
RDC::RenderToTexture((SDL_GPUTexture *) textureHandle); RDC::RenderToTexture((SDL_GPUTexture *) textureHandle);
g_activeScene->OnDebugDraw(); g_activeScene->GetScene().OnDebugDraw();
Game_OnDebugDraw(); Game_OnDebugDraw();
for (auto &p : g_plugins)
p->OnDebugDraw();
} }
VOID IAEngine::__Update() VOID IAEngine::__Update()
{ {
FLOAT32 deltaTime = 0; FLOAT32 deltaTime = 0;
g_activeScene->OnUpdate(deltaTime); g_activeScene->GetScene().OnUpdate(deltaTime);
Game_OnUpdate(deltaTime); Game_OnUpdate(deltaTime);
for (auto &p : g_plugins)
p->OnUpdate(deltaTime);
} }
VOID IAEngine::__FixedUpdate() VOID IAEngine::__FixedUpdate()
{ {
g_activeScene->OnFixedUpdate(); g_activeScene->GetScene().OnFixedUpdate();
Game_OnFixedUpdate(); Game_OnFixedUpdate();
for (auto &p : g_plugins)
p->OnFixedUpdate();
} }
VOID IAEngine::__ProcessEvent(IN PVOID _event) VOID IAEngine::__ProcessEvent(IN PVOID _event)
{ {
const auto event = (SDL_Event *) _event; const auto event = (SDL_Event *) _event;
} }
} // namespace ia::iae
namespace ia::iae VOID IAEngine::AddPlugin(IN Asset_Plugin *plugin)
{
Handle CreateTextureFromFile(IN PCCHAR path, IN INT32 tileWidth = -1, IN INT32 tileHeight = -1)
{ {
INT32 w, h, n; g_plugins.pushBack(plugin);
auto pixels = stbi_load(path, &w, &h, &n, STBI_rgb_alpha);
if (!pixels)
THROW_INVALID_DATA(path);
const auto t =
RDC::CreateImage(pixels, w, h, tileWidth == -1 ? 1 : w / tileWidth, tileHeight == -1 ? 1 : h / tileHeight);
stbi_image_free(pixels);
return t;
} }
Handle IAEngine::CreateSprite(IN CONST String &path) AssetManager* IAEngine::GetAssetManager()
{ {
const auto t = new Resource_Texture(); return g_assetManager;
t->Type = Resource::EType::TEXTURE;
t->Texture = CreateTextureFromFile(path.c_str());
g_resources.pushBack(t);
return (Handle) g_resources.size() - 1;
} }
Handle IAEngine::CreateSprite(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height) VOID IAEngine::SetAssetManager(IN AssetManager *instance)
{ {
const auto t = new Resource_Texture(); g_assetManager = instance;
t->Type = Resource::EType::TEXTURE;
t->Texture = RDC::CreateImage(rgbaData, width, height);
g_resources.pushBack(t);
return (Handle) g_resources.size() - 1;
}
Handle IAEngine::CreateSpriteSheet(IN CONST Vector<Vector<Handle>> &animations)
{
THROW_NOT_IMPLEMENTED();
return INVALID_HANDLE;
}
Handle IAEngine::CreateSpriteSheet(IN CONST String &path, IN INT32 spriteWidth, IN INT32 spriteHeight,
IN CONST Vector<INT32> &frameCounts)
{
const auto t = new Resource_SpriteSheet();
t->Type = Resource::EType::SPRITE_SHEET;
t->FrameCounts = frameCounts;
t->Texture = CreateTextureFromFile(path.c_str(), spriteWidth, spriteHeight);
g_resources.pushBack(t);
return (Handle) g_resources.size() - 1;
}
Handle IAEngine::CreateTileSheet(IN CONST String &path, IN INT32 tileWidth, IN INT32 tileHeight)
{
const auto t = new Resource_Texture();
t->Type = Resource::EType::TEXTURE;
t->Texture = CreateTextureFromFile(path.c_str(), tileWidth, tileHeight);
g_resources.pushBack(t);
return (Handle) g_resources.size() - 1;
}
Handle IAEngine::CreateTileSheet(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height, IN INT32 tileWidth,
IN INT32 tileHeight)
{
const auto t = new Resource_Texture();
t->Type = Resource::EType::TEXTURE;
t->Texture = RDC::CreateImage(rgbaData, width, height, width / tileWidth, height / tileHeight);
g_resources.pushBack(t);
return (Handle) g_resources.size() - 1;
}
VOID IAEngine::DestroyResource(IN Handle resource)
{
if (!g_resources[resource])
return;
switch (g_resources[resource]->Type)
{
case Resource::EType::INVALID:
break;
case Resource::EType::TEXTURE:
case Resource::EType::SPRITE_SHEET:
RDC::DestroyImage(static_cast<Resource_Texture *>(g_resources[resource])->Texture);
break;
case Resource::EType::SOUND:
break;
case Resource::EType::SCENE:
static_cast<Resource_Scene *>(g_resources[resource])->SceneRef.reset();
break;
}
delete g_resources[resource];
g_resources[resource] = nullptr;
for (auto &t : g_resourceNames)
if (t->Value == resource)
t->Value = INVALID_HANDLE;
}
Handle IAEngine::GetResourceByName(IN CONST String &name)
{
return g_resourceNames[name];
}
VOID IAEngine::AssignResourceName(IN Handle resource, IN CONST String &name)
{
g_resourceNames[name] = resource;
}
VOID IAEngine::LoadResources(IN CONST Vector<Handle> &resources)
{
Vector<Handle> atlasTextures;
for (const auto &handle : resources)
{
switch (g_resources[handle]->Type)
{
case Resource::EType::SCENE:
case Resource::EType::INVALID:
break;
case Resource::EType::TEXTURE:
case Resource::EType::SPRITE_SHEET:
atlasTextures.pushBack(static_cast<Resource_Texture *>(g_resources[handle])->Texture);
break;
case Resource::EType::SOUND:
break;
}
}
RDC::CompileTextures(atlasTextures);
} }
} // namespace ia::iae } // namespace ia::iae
namespace ia::iae namespace ia::iae
{ {
VOID IAEngine::DrawTile(IN Handle tileSheet, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position, VOID IAEngine::DrawTile(IN Asset_TileSheet *tileSheet, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position,
IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset) IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset)
{ {
const auto t = static_cast<Resource_Texture *>(g_resources[tileSheet]); RDC::DrawSpriteTopLeft(tileSheet->GetTexture(), tileIndexX, tileIndexY, position, scale, rotation, flipH, flipV,
RDC::DrawSpriteTopLeft(t->Texture, tileIndexX, tileIndexY, position, scale, rotation, flipH, flipV, uvOffset);
}
VOID IAEngine::DrawSprite(IN Handle sprite, IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH,
IN BOOL flipV, IN Vec2 uvOffset)
{
const auto t = static_cast<Resource_Texture *>(g_resources[sprite]);
RDC::DrawSpriteTopLeft(t->Texture, 0, 0, position, scale, rotation, flipH, flipV, uvOffset);
}
VOID IAEngine::DrawSprite(IN Handle spriteSheet, IN INT32 animationIndex, IN INT32 frameIndex, IN Vec2 position,
IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset)
{
const auto t = static_cast<Resource_SpriteSheet *>(g_resources[spriteSheet]);
RDC::DrawSpriteTopLeft(t->Texture, frameIndex, animationIndex, position, scale, rotation, flipH, flipV,
uvOffset); uvOffset);
} }
VOID IAEngine::DrawSprite(IN Asset_Sprite *sprite, IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation,
IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset)
{
RDC::DrawSpriteTopLeft(sprite->GetTexture(), 0, 0, position, scale, rotation, flipH, flipV, uvOffset);
}
VOID IAEngine::DrawSprite(IN Asset_SpriteSheet *spriteSheet, IN INT32 animationIndex, IN INT32 frameIndex,
IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV,
IN Vec2 uvOffset)
{
RDC::DrawSpriteTopLeft(spriteSheet->GetTexture(), frameIndex, animationIndex, position, scale, rotation, flipH,
flipV, uvOffset);
}
} // namespace ia::iae } // namespace ia::iae
namespace ia::iae namespace ia::iae
{ {
RefPtr<Scene> IAEngine::GetActiveScene() Asset_Scene *IAEngine::GetActiveScene()
{ {
return g_activeScene; return g_activeScene;
} }
RefPtr<Scene> IAEngine::CreateScene(IN IVec2 extent) VOID IAEngine::ChangeActiveScene(IN Asset_Scene *scene)
{
return MakeRefPtr<Scene>(extent);
}
VOID IAEngine::ChangeActiveScene(IN RefPtr<Scene> scene)
{ {
g_activeScene = scene; g_activeScene = scene;
LoadResources(scene->GetReferencedResources());
}
VOID IAEngine::ChangeActiveScene(IN Handle scene)
{
ChangeActiveScene(static_cast<Resource_Scene *>(g_resources[scene])->SceneRef);
}
Handle IAEngine::AddScene(IN RefPtr<Scene> 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 } // namespace ia::iae

View File

@ -18,6 +18,10 @@
namespace ia::iae namespace ia::iae
{ {
Scene::Scene()
{
}
Scene::Scene(IN IVec2 extent) : m_extent(extent) Scene::Scene(IN IVec2 extent) : m_extent(extent)
{ {
} }
@ -26,6 +30,11 @@ namespace ia::iae
{ {
} }
VOID Scene::SetExtent(IN IVec2 extent)
{
m_extent = extent;
}
VOID Scene::SetupGrid(IN IVec2 gridCellSize) VOID Scene::SetupGrid(IN IVec2 gridCellSize)
{ {
m_gridCellSize = gridCellSize; m_gridCellSize = gridCellSize;
@ -38,13 +47,10 @@ namespace ia::iae
INT32 tileCursorX{}, tileCursorY{}; INT32 tileCursorX{}, tileCursorY{};
for (const auto &cell : m_gridCells) for (const auto &cell : m_gridCells)
{ {
if (cell.TileSheetTexture) if (cell.TileSheet)
IAEngine::DrawTile(cell.TileSheetTexture, cell.TileIndex.x, cell.TileIndex.y, IAEngine::DrawTile(cell.TileSheet, cell.TileIndex.x, cell.TileIndex.y,
{ {tileCursorX * m_gridCellSize.x, tileCursorY * m_gridCellSize.y}, {1.0f, 1.0f},
tileCursorX * m_gridCellSize.x, 0.0f);
tileCursorY * m_gridCellSize.y
},
{1.0f, 1.0f}, 0.0f);
tileCursorX++; tileCursorX++;
if (tileCursorX >= GetGridSize().x) if (tileCursorX >= GetGridSize().x)
{ {
@ -64,6 +70,6 @@ namespace ia::iae
VOID Scene::OnUpdate(IN FLOAT32 deltaTime) VOID Scene::OnUpdate(IN FLOAT32 deltaTime)
{ {
//Renderer::SetCameraPosition(m_cameraPosition); // Renderer::SetCameraPosition(m_cameraPosition);
} }
} // namespace ia::iae } // namespace ia::iae

View File

@ -0,0 +1,34 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IAEngine/Base.hpp>
namespace ia::iae
{
class EmbeddedResources
{
public:
STATIC VOID Initialize();
STATIC VOID Terminate();
STATIC CONST Vector<UINT8>& GetResource(IN CONST String& name);
private:
STATIC Map<String, Vector<UINT8>> s_resources;
};
}

View File

@ -16,20 +16,20 @@
#pragma once #pragma once
#include <IAEngine/Scene.hpp> #include <IAEngine/AssetManager.hpp>
namespace ia::iae namespace ia::iae
{ {
class GameData class GameData
{ {
public: public:
STATIC RefPtr<Scene> GetEntryScene(); STATIC Asset_Scene* GetEntryScene();
private: private:
STATIC BOOL LoadSceneData(); STATIC BOOL LoadSceneData();
STATIC BOOL LoadResourceData(); STATIC BOOL LoadAssetData();
STATIC RefPtr<Scene> ParseScene(IN CONST String& path); STATIC Asset_Scene* ParseScene(IN CONST String& path);
STATIC VOID ParseSceneGrid(IN Scene* scene, IN PCVOID gridNode); STATIC VOID ParseSceneGrid(IN Scene* scene, IN PCVOID gridNode);
private: private:

View File

@ -0,0 +1,222 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IAEngine/Scene.hpp>
#include <IACore/StreamReader.hpp>
namespace ia::iae
{
enum class EAssetType
{
INVALID,
SCENE,
SOUND,
SPRITE,
TILESHEET,
SPRITESHEET,
PLUGIN,
PACKAGE
};
class IAsset
{
public:
IAsset(IN EAssetType type);
VIRTUAL ~IAsset();
PURE_VIRTUAL(VOID Compile());
PURE_VIRTUAL(VOID Destroy());
protected:
CONST EAssetType m_type;
};
class Asset_Sprite : public IAsset
{
public:
Asset_Sprite() : IAsset(EAssetType::SPRITE)
{
}
Asset_Sprite(IN EAssetType type) : IAsset(type)
{
}
VOID Compile();
VOID Destroy();
INLINE Handle GetTexture();
protected:
Handle m_texture;
friend class AssetManager;
};
class Asset_TileSheet : public Asset_Sprite
{
public:
Asset_TileSheet() : Asset_Sprite(EAssetType::TILESHEET)
{
}
};
class Asset_SpriteSheet : public Asset_Sprite
{
public:
Asset_SpriteSheet() : Asset_Sprite(EAssetType::SPRITESHEET)
{
}
VOID Compile();
VOID Destroy();
INLINE CONST Vector<INT32> &GetFrameCounts() CONST;
protected:
Vector<INT32> m_frameCounts;
friend class AssetManager;
};
class Asset_Scene : public IAsset
{
public:
Asset_Scene() : IAsset(EAssetType::SCENE)
{
}
VOID Compile();
VOID Destroy();
public:
INLINE Scene &GetScene();
protected:
Scene m_scene;
friend class AssetManager;
};
class Asset_Plugin : public IAsset
{
public:
Asset_Plugin() : IAsset(EAssetType::PLUGIN)
{
}
VOID Compile();
VOID Destroy();
public:
VOID (*OnInitialize)();
VOID (*OnTerminate)();
VOID (*OnDebugDraw)();
VOID (*OnFixedUpdate)();
VOID (*OnUpdate)(IN FLOAT32 deltaTime);
};
class IAsset_Package : public IAsset
{
public:
struct AssetRef
{
String Path;
Handle RefHandle{INVALID_HANDLE};
EAssetType Type{EAssetType::INVALID};
};
public:
PURE_VIRTUAL(Vector<AssetRef>::const_iterator ListAssets());
PURE_VIRTUAL(RefPtr<IStreamReader> GetAssetData(IN Handle refHandle));
};
class AssetManager
{
public:
VIRTUAL VOID SetAssetDirectory(IN CONST String &path);
String ReadTextAsset(IN CONST String &path);
Vector<UINT8> ReadBinaryAsset(IN CONST String &path);
public:
VIRTUAL Asset_Plugin *LoadPlugin(IN CONST String &path);
VIRTUAL Asset_Sprite *CreateSprite(IN CONST String &path);
VIRTUAL Asset_Sprite *CreateSprite(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
VIRTUAL Asset_SpriteSheet *CreateSpriteSheet(IN CONST Vector<Vector<Handle>> &animations);
VIRTUAL Asset_SpriteSheet *CreateSpriteSheet(IN CONST String &path, IN INT32 spriteWidth, IN INT32 spriteHeight,
IN CONST Vector<INT32> &frameCounts);
VIRTUAL Asset_TileSheet *CreateTileSheet(IN CONST String &path, IN INT32 tileWidth, IN INT32 tileHeight);
VIRTUAL Asset_TileSheet *CreateTileSheet(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height,
IN INT32 tileWidth, IN INT32 tileHeight);
VIRTUAL Asset_Scene *CreateScene(IN IVec2 extent);
VIRTUAL VOID DestroyAsset(IN IAsset *asset);
VIRTUAL VOID AssignAssetName(IN IAsset *asset, IN CONST String &name);
template<typename AssetType>
requires std::is_base_of<IAsset, AssetType>::value
AssetType *GetAssetByName(IN CONST String &name);
public:
STATIC Vector<UINT8> Inflate(IN PCUINT8 data, IN SIZE_T dataSize);
STATIC Vector<UINT8> Deflate(IN PCUINT8 data, IN SIZE_T dataSize);
protected:
String m_assetDirectory;
Vector<IAsset *> m_assets;
Map<String, IAsset *> m_assetNames;
protected:
VIRTUAL IAsset *GetAssetByName(IN CONST String &name);
private:
VOID Initialize();
VOID Terminate();
friend class IAEngine;
};
template<typename AssetType>
requires std::is_base_of<IAsset, AssetType>::value
AssetType *AssetManager::GetAssetByName(IN CONST String &name)
{
return (AssetType *) GetAssetByName(name);
}
Handle Asset_Sprite::GetTexture()
{
return m_texture;
}
Scene &Asset_Scene::GetScene()
{
return m_scene;
}
CONST Vector<INT32> &Asset_SpriteSheet::GetFrameCounts() CONST
{
return m_frameCounts;
}
} // namespace ia::iae

View File

@ -16,51 +16,33 @@
#pragma once #pragma once
#include <IAEngine/Scene.hpp> #include <IAEngine/AssetManager.hpp>
namespace ia::iae namespace ia::iae
{ {
class IAEngine class IAEngine
{ {
public: public:
STATIC CONSTEXPR IA_VERSION_TYPE ENGINE_VERSION = IA_MAKE_VERSION(1, 0, 0); STATIC VOID AddPlugin(IN Asset_Plugin *plugin);
STATIC AssetManager *GetAssetManager();
STATIC VOID SetAssetManager(IN AssetManager *instance);
public: public:
STATIC Handle CreateSprite(IN CONST String &path); STATIC Asset_Scene *GetActiveScene();
STATIC Handle CreateSprite(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height); STATIC VOID ChangeActiveScene(IN Asset_Scene *scene);
STATIC Handle CreateSpriteSheet(IN CONST Vector<Vector<Handle>> &animations);
STATIC Handle CreateSpriteSheet(IN CONST String &path, IN INT32 spriteWidth, IN INT32 spriteHeight,
IN CONST Vector<INT32> &frameCounts);
STATIC Handle CreateTileSheet(IN CONST String &path, IN INT32 tileWidth, IN INT32 tileHeight);
STATIC Handle CreateTileSheet(IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height, IN INT32 tileWidth,
IN INT32 tileHeight);
STATIC VOID DestroyResource(IN Handle resource);
STATIC Handle GetResourceByName(IN CONST String &name);
STATIC VOID AssignResourceName(IN Handle resource, IN CONST String &name);
STATIC VOID LoadResources(IN CONST Vector<Handle> &resources);
public: public:
STATIC RefPtr<Scene> GetActiveScene(); STATIC VOID DrawTile(IN Asset_TileSheet *tileSheet, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position,
STATIC RefPtr<Scene> CreateScene(IN IVec2 extent);
STATIC VOID ChangeActiveScene(IN Handle scene);
STATIC Handle AddScene(IN RefPtr<Scene> scene);
STATIC VOID ChangeActiveScene(IN RefPtr<Scene> scene);
public:
STATIC VOID DrawTile(IN Handle tileSheet, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position,
IN Vec2 scale = {1.0f, 1.0f}, IN FLOAT32 rotation = 0.0f, IN BOOL flipH = false, IN Vec2 scale = {1.0f, 1.0f}, IN FLOAT32 rotation = 0.0f, IN BOOL flipH = false,
IN BOOL flipV = false, IN Vec2 uvOffset = {}); IN BOOL flipV = false, IN Vec2 uvOffset = {});
STATIC VOID DrawSprite(IN Handle sprite, IN Vec2 position, IN Vec2 scale = {1.0f, 1.0f}, STATIC VOID DrawSprite(IN Asset_Sprite *sprite, IN Vec2 position, IN Vec2 scale = {1.0f, 1.0f},
IN FLOAT32 rotation = 0.0f, IN BOOL flipH = false, IN BOOL flipV = false, IN FLOAT32 rotation = 0.0f, IN BOOL flipH = false, IN BOOL flipV = false,
IN Vec2 uvOffset = {}); IN Vec2 uvOffset = {});
STATIC VOID DrawSprite(IN Handle spriteSheet, IN INT32 animationIndex, IN INT32 frameIndex, IN Vec2 position, STATIC VOID DrawSprite(IN Asset_SpriteSheet *spriteSheet, IN INT32 animationIndex, IN INT32 frameIndex,
IN Vec2 scale = {1.0f, 1.0f}, IN FLOAT32 rotation = 0.0f, IN BOOL flipH = false, IN Vec2 position, IN Vec2 scale = {1.0f, 1.0f}, IN FLOAT32 rotation = 0.0f,
IN BOOL flipV = false, IN Vec2 uvOffset = {}); IN BOOL flipH = false, IN BOOL flipV = false, IN Vec2 uvOffset = {});
public: public:
STATIC VOID __Initialize(); STATIC VOID __Initialize();

View File

@ -0,0 +1,55 @@
// IAEngine: 2D Game Engine by IA
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#pragma once
#include <IAEngine/LibInterface.hpp>
#if defined(_WIN32) || defined(WIN32)
#define IAE_DLL_EXPORT __declspec(dllexport)
#else
#define IAE_DLL_EXPORT
#endif
IAE_DLL_EXPORT C_DECL(VOID Plugin_OnInitialize());
IAE_DLL_EXPORT C_DECL(VOID Plugin_OnTerminate());
IAE_DLL_EXPORT C_DECL(VOID Plugin_OnDebugDraw());
IAE_DLL_EXPORT C_DECL(VOID Plugin_OnFixedUpdate());
IAE_DLL_EXPORT C_DECL(VOID Plugin_OnUpdate(IN FLOAT32 deltaTime));
#define IAE_PLUGIN(name) \
C_DECL(GameRequestedConfig *Game_GetConfigRequest()) \
{ \
return nullptr; \
} \
C_DECL(VOID Game_OnInitialize()) \
{ \
} \
C_DECL(VOID Game_OnTerminate()) \
{ \
} \
C_DECL(VOID Game_OnDebugDraw()) \
{ \
} \
C_DECL(VOID Game_OnFixedUpdate()) \
{ \
} \
C_DECL(VOID Game_OnUpdate(IN FLOAT32 deltaTime)) \
{ \
} \
C_DECL(VOID Game_OnResize(IN INT32 newWidth, IN INT32 newHeight)) \
{ \
}

View File

@ -25,24 +25,27 @@ namespace ia::iae
IVec2 TileIndex; IVec2 TileIndex;
PVOID UserData{}; PVOID UserData{};
Vec4 ColorOverlay; Vec4 ColorOverlay;
Handle TileSheetTexture{};
UINT64 CollisionMask{}; UINT64 CollisionMask{};
class Asset_TileSheet* TileSheet{};
}; };
class Scene class Scene
{ {
public: public:
Scene();
Scene(IN IVec2 extent); Scene(IN IVec2 extent);
~Scene(); ~Scene();
VOID SetExtent(IN IVec2 extent);
VOID SetupGrid(IN IVec2 gridCellSize); VOID SetupGrid(IN IVec2 gridCellSize);
public: public:
INLINE GridCell &GetGridCell(IN INT32 x, IN INT32 y); INLINE GridCell &GetGridCell(IN INT32 x, IN INT32 y);
INLINE VOID AddReferencedResources(IN Handle resource); INLINE VOID AddReferencedResources(IN class IAsset* resource);
public: public:
CONST Vector<Handle> &GetReferencedResources() CONST CONST Vector<class IAsset*> &GetReferencedResources() CONST
{ {
return m_referencedResources; return m_referencedResources;
} }
@ -63,12 +66,12 @@ namespace ia::iae
} }
private: private:
IVec2 m_extent{};
IVec2 m_gridSize{}; IVec2 m_gridSize{};
CONST IVec2 m_extent;
IVec2 m_gridCellSize{}; IVec2 m_gridCellSize{};
Vec2 m_cameraPosition{}; Vec2 m_cameraPosition{};
Vector<GridCell> m_gridCells; Vector<GridCell> m_gridCells;
Vector<Handle> m_referencedResources; Vector<class IAsset*> m_referencedResources;
private: private:
VOID OnDraw(); VOID OnDraw();
@ -84,7 +87,7 @@ namespace ia::iae
return m_gridCells[x + (y * m_gridSize.x)]; return m_gridCells[x + (y * m_gridSize.x)];
} }
VOID Scene::AddReferencedResources(IN Handle resource) VOID Scene::AddReferencedResources(IN class IAsset* resource)
{ {
m_referencedResources.pushBack(resource); m_referencedResources.pushBack(resource);
} }

View File

@ -13,4 +13,4 @@ add_library(RenderCore STATIC ${SRC_FILES})
target_include_directories(RenderCore PUBLIC inc) target_include_directories(RenderCore PUBLIC inc)
target_include_directories(RenderCore PRIVATE imp/hpp) target_include_directories(RenderCore PRIVATE imp/hpp)
target_link_libraries(RenderCore PUBLIC IACore SDL3::SDL3 glm::glm) target_link_libraries(RenderCore PUBLIC Common)

View File

@ -141,7 +141,7 @@ namespace ia::iae
{ {
STATIC SDL_GPURenderPass *ActiveRenderPass{}; STATIC SDL_GPURenderPass *ActiveRenderPass{};
STATIC SDL_GPUCommandBuffer *ActiveCommandBuffer{}; STATIC SDL_GPUCommandBuffer *ActiveCommandBuffer{};
STATIC SDL_GPUColorTargetInfo ActiveColorTargetInfo{.clear_color = SDL_FColor{0.0f, 0.0f, 0.0f, 1.0f}, STATIC SDL_GPUColorTargetInfo ActiveColorTargetInfo{.clear_color = SDL_FColor{0.39f, 0.58f, 0.92f, 1.0f},
.load_op = SDL_GPU_LOADOP_CLEAR, .load_op = SDL_GPU_LOADOP_CLEAR,
.store_op = SDL_GPU_STOREOP_STORE}; .store_op = SDL_GPU_STOREOP_STORE};
@ -170,7 +170,7 @@ namespace ia::iae
{ {
STATIC SDL_GPURenderPass *ActiveRenderPass{}; STATIC SDL_GPURenderPass *ActiveRenderPass{};
STATIC SDL_GPUCommandBuffer *ActiveCommandBuffer{}; STATIC SDL_GPUCommandBuffer *ActiveCommandBuffer{};
STATIC SDL_GPUColorTargetInfo ActiveColorTargetInfo{.clear_color = SDL_FColor{0.0f, 0.0f, 0.0f, 1.0f}, STATIC SDL_GPUColorTargetInfo ActiveColorTargetInfo{.clear_color = SDL_FColor{0.39f, 0.58f, 0.92f, 1.0f},
.load_op = SDL_GPU_LOADOP_CLEAR, .load_op = SDL_GPU_LOADOP_CLEAR,
.store_op = SDL_GPU_STOREOP_STORE}; .store_op = SDL_GPU_STOREOP_STORE};
@ -226,7 +226,7 @@ namespace ia::iae
VOID RDC::DrawLine(IN Vec2 start, IN Vec2 end, IN Vec4 color) VOID RDC::DrawLine(IN Vec2 start, IN Vec2 end, IN Vec4 color)
{ {
s_primitiveInstances[s_primitiveInstanceCount++] = {start, color}; s_primitiveInstances[s_primitiveInstanceCount++] = {start, color};
s_primitiveInstances[s_primitiveInstanceCount++] = { end, color }; s_primitiveInstances[s_primitiveInstanceCount++] = {end, color};
} }
VOID RDC::DrawRect(IN Vec2 start, IN Vec2 end, IN Vec4 color) VOID RDC::DrawRect(IN Vec2 start, IN Vec2 end, IN Vec4 color)
@ -236,7 +236,7 @@ namespace ia::iae
s_primitiveInstances[s_primitiveInstanceCount++] = {Vec2{end.x, start.y}, color}; s_primitiveInstances[s_primitiveInstanceCount++] = {Vec2{end.x, start.y}, color};
s_primitiveInstances[s_primitiveInstanceCount++] = {end, color}; s_primitiveInstances[s_primitiveInstanceCount++] = {end, color};
s_primitiveInstances[s_primitiveInstanceCount++] = {end, color}; s_primitiveInstances[s_primitiveInstanceCount++] = {end, color};
s_primitiveInstances[s_primitiveInstanceCount++] = {Vec2{start.x, end.y}, color}; s_primitiveInstances[s_primitiveInstanceCount++] = {Vec2{start.x, end.y}, color};
@ -289,6 +289,8 @@ namespace ia::iae
VOID RDC::CompileTextures(IN CONST Vector<Handle> &images) VOID RDC::CompileTextures(IN CONST Vector<Handle> &images)
{ {
if (!images.size())
return;
delete s_dynamicSpriteAtlas; delete s_dynamicSpriteAtlas;
s_dynamicSpriteAtlas = new RDC_TextureAtlas(images); s_dynamicSpriteAtlas = new RDC_TextureAtlas(images);
} }

View File

@ -16,20 +16,7 @@
#pragma once #pragma once
#include <IACore/Exception.hpp> #include <Common/Base.hpp>
#include <IACore/Logger.hpp>
#include <IACore/Map.hpp>
#include <IACore/Memory.hpp>
#include <IACore/String.hpp>
#include <IACore/Vector.hpp>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <glm/ext/scalar_constants.hpp>
#include <glm/mat4x4.hpp>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#define RDC_LOG_TAG "RDC" #define RDC_LOG_TAG "RDC"
@ -40,17 +27,6 @@
namespace ia::iae namespace ia::iae
{ {
using Handle = INT64;
STATIC CONSTEXPR Handle INVALID_HANDLE = -1;
using Vec2 = glm::vec2;
using Vec3 = glm::vec3;
using Vec4 = glm::vec4;
using IVec2 = glm::ivec2;
using IVec3 = glm::ivec3;
using IVec4 = glm::ivec4;
using Mat4 = glm::mat4;
struct ImageData struct ImageData
{ {
PUINT8 Pixels{}; PUINT8 Pixels{};

View File

@ -20,7 +20,7 @@ import os
import sys import sys
def main(args: list[str]): def main(args: list[str]):
os.system("cmake -S. -B./Build/Windows -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DBUILD_SAMPLES=ON") os.system("cmake -S. -B./Build/Windows -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Debug -DBUILD_SAMPLES=OFF")
os.system("cmake --build ./Build/Windows") os.system("cmake --build ./Build/Windows")
main(sys.argv) main(sys.argv)

2
Vendor/IACore vendored