Text Rendering

This commit is contained in:
Isuru Samarathunga
2025-10-20 23:39:54 +05:30
parent d4e93b047c
commit b10aacaee7
40 changed files with 1295 additions and 297 deletions

View File

@ -8,11 +8,13 @@ set(SRC_FILES
"Src/Imp/CPP/Physics.cpp"
"Src/Imp/CPP/InternalEngine.cpp"
"Src/Imp/CPP/FontManager.cpp"
"Src/Imp/CPP/InputManager.cpp"
"Src/Imp/CPP/ResourceManager.cpp"
"Src/Imp/CPP/SceneManager.cpp"
"Src/Imp/CPP/EventManager.cpp"
"Src/Imp/CPP/WorldManager.cpp"
"Src/Imp/CPP/AudioManager.cpp"
"Src/Imp/CPP/ResourceManager.cpp"
"Src/Imp/CPP/Renderer/DebugDraw.cpp"
"Src/Imp/CPP/Renderer/Pipeline.cpp"
@ -24,7 +26,17 @@ set(SRC_FILES
"Src/Imp/CPP/Nodes/SpriteNode.cpp"
"Src/Imp/CPP/Nodes/TextureNode.cpp"
"Src/Imp/CPP/Nodes/TileMapNode.cpp"
"Src/Imp/CPP/Nodes/UINode.cpp"
"Src/Imp/CPP/Nodes/UILabelNode.cpp"
"Src/Imp/CPP/Nodes/UITextNode.cpp"
"Src/Imp/CPP/Nodes/UIImageNode.cpp"
"Src/Imp/CPP/Nodes/UIButtonNode.cpp"
"Src/Imp/CPP/Components/UILabelComponent.cpp"
"Src/Imp/CPP/Components/UITextComponent.cpp"
"Src/Imp/CPP/Components/UIImageComponent.cpp"
"Src/Imp/CPP/Components/UIButtonComponent.cpp"
"Src/Imp/CPP/Components/CameraComponent.cpp"
"Src/Imp/CPP/Components/PhysicsComponent.cpp"
"Src/Imp/CPP/Components/SpriteComponent.cpp"
@ -51,4 +63,4 @@ target_include_directories(IAEngine PUBLIC Src/Inc)
target_include_directories(IAEngine PRIVATE Src/Imp/HPP)
target_link_libraries(IAEngine PUBLIC IACore)
target_link_libraries(IAEngine PRIVATE ZLIB::ZLIBSTATIC SDL3::SDL3 SDL3_mixer::SDL3_mixer RmlUi::RmlUi STB)
target_link_libraries(IAEngine PRIVATE ZLIB::ZLIBSTATIC SDL3::SDL3 SDL3_mixer::SDL3_mixer RmlUi::RmlUi STB Freetype::Freetype)

View File

@ -34,7 +34,7 @@ namespace ia::iae
m_viewport.w = height;
m_projectionMatrix =
glm::orthoLH(0.0f, (FLOAT32) width, (FLOAT32) height, 0.0f, Renderer::MIN_DEPTH, Renderer::MAX_DEPTH);
glm::orthoLH(0.0f, (FLOAT32) width, (FLOAT32) height, 0.0f, -1.0f, 1.0f);
}
CONST Mat4 *CameraComponent::GetViewMatrix()

View File

@ -0,0 +1,49 @@
// 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/Engine.hpp>
#include <IAEngine/Nodes/UINode.hpp>
#include <IAEngine/Components/UILabelComponent.hpp>
namespace ia::iae
{
UILabelComponent::UILabelComponent(IN UINode *node) : IUIComponent(node)
{
}
VOID UILabelComponent::Draw()
{
Engine::SetRenderState_Texture(0);
Engine::SetRenderState_FlippedH(false);
Engine::SetRenderState_FlippedV(false);
Engine::SetRenderState_ColorOverlay({0xFF, 0xFF, 0xFF, 0xFF});
Engine::SetRenderState_TextureOffset({});
Engine::SetRenderState_CameraRelative(false);
Engine::DrawText(m_label, m_node->GetPosition(), m_node->GetScale(), m_node->GetRotation(), 0xFF, 0);
}
VOID UILabelComponent::DebugDraw()
{
}
VOID UILabelComponent::Update()
{
}
VOID UILabelComponent::FixedUpdate()
{
}
} // namespace ia::iae

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 <FontManager.hpp>
#include <Renderer/GPUResourceManager.hpp>
#include <ft2build.h>
#include FT_FREETYPE_H
namespace ia::iae
{
Map<String, FontManager::Font> FontManager::s_fonts;
FT_Library g_freetype;
VOID FontManager::Initialize()
{
if (FT_Init_FreeType(&g_freetype))
THROW_UNKNOWN("Failed to initialize the FreeType font library");
LoadFont("Roboto", "Resources/Fonts/Roboto-Black.ttf");
}
VOID FontManager::Terminate()
{
for(const auto& f: s_fonts)
{
for(const auto& t: f->Value.Chars)
GPUResourceManager::DestroyTexture(t.Texture);
}
FT_Done_FreeType(g_freetype);
}
VOID FontManager::LoadFont(IN CONST String &name, IN CONST String &path)
{
STATIC Vector<UINT8> GLYPH_PIXEL_DATA;
Font result;
const auto fontSize = 16;
FT_Face face;
if (FT_New_Face(g_freetype, path.c_str(), 0, &face))
THROW_UNKNOWN("Failed to load the TrueType font '", path, "'");
FT_Set_Pixel_Sizes(face, 0, fontSize);
const auto charCount = static_cast<UINT8>(sizeof(result.Chars) / sizeof(result.Chars[0]));
for (UINT8 c = 0; c < charCount; c++)
{
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
THROW_UNKNOWN("Failed to load character '", (CHAR) c, "' of TrueType font '", path, "'");
const auto glyphSize = face->glyph->bitmap.pitch * face->glyph->bitmap.rows;
if(!glyphSize) continue;
GLYPH_PIXEL_DATA.clear();
GLYPH_PIXEL_DATA.resize(glyphSize << 2);
for(SIZE_T t = 0; t < glyphSize; t++)
{
const auto pi= t<<2;
const auto p = face->glyph->bitmap.buffer[t];
GLYPH_PIXEL_DATA[pi + 0] = p;
GLYPH_PIXEL_DATA[pi + 1] = p;
GLYPH_PIXEL_DATA[pi + 2] = p;
GLYPH_PIXEL_DATA[pi + 3] = p;
}
result.Chars[c] = {
IVec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
IVec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
static_cast<UINT32>(face->glyph->advance.x) >> 6,
GPUResourceManager::CreateTexture(SDL_GPU_TEXTUREUSAGE_SAMPLER | SDL_GPU_TEXTUREUSAGE_COLOR_TARGET, face->glyph->bitmap.width, face->glyph->bitmap.rows, GLYPH_PIXEL_DATA.data()),
};
}
FT_Done_Face(face);
s_fonts[name] = IA_MOVE(result);
}
} // namespace ia::iae

View File

@ -23,10 +23,18 @@ namespace ia::iae
BOOL InputManager::s_keys[256];
BOOL InputManager::s_prevKeys[256];
InputKey InputManager::s_axisInputs[4];
Vec2 InputManager::s_pointerPosition{};
Map<String, Handle> InputManager::s_actionNames;
Vector<Vector<InputKey>> InputManager::s_actions;
InputManager::KeyboardGamePadMapping InputManager::s_keyboardGamePadMapping{};
BOOL InputManager::s_buttonA{};
BOOL InputManager::s_buttonB{};
BOOL InputManager::s_buttonC{};
BOOL InputManager::s_buttonD{};
INT16 InputManager::s_verticalAxis{};
INT16 InputManager::s_horizontalAxis{};
BOOL InputManager::s_onScreenGamePadEnabled{};
BOOL InputManager::s_keyboardGamePadEnabled{};
VOID InputManager::Initialize()
{
@ -60,12 +68,6 @@ namespace ia::iae
}
}
Vec2 InputManager::GetAxis()
{
return Vec2{IsKeyDown(s_axisInputs[3]) + IsKeyDown(s_axisInputs[2]) * -1,
IsKeyDown(s_axisInputs[1]) + IsKeyDown(s_axisInputs[0]) * -1};
}
VOID InputManager::SwitchModeToText()
{
SDL_StartTextInput(g_windowHandle);
@ -96,202 +98,232 @@ namespace ia::iae
return s_prevKeys[(UINT8) key] && !s_keys[(UINT8) key];
}
BOOL InputManager::IsActionDown(IN Handle action)
VOID InputManager::SetupOnScreenGamePad()
{
const auto &t = s_actions[action];
for (const auto &k : t)
if (IsKeyDown(k))
return true;
return false;
s_onScreenGamePadEnabled = true;
}
BOOL InputManager::WasActionPressed(IN Handle action)
VOID InputManager::SetupKeyboardGamePad(IN CONST KeyboardGamePadMapping &mapping)
{
const auto &t = s_actions[action];
for (const auto &k : t)
if (WasKeyPressed(k))
return true;
return false;
s_keyboardGamePadEnabled = true;
s_keyboardGamePadMapping = mapping;
}
BOOL InputManager::WasActionReleased(IN Handle action)
BOOL InputManager::GetButtonA()
{
const auto &t = s_actions[action];
for (const auto &k : t)
if (WasKeyReleased(k))
return true;
return false;
return s_buttonA;
}
BOOL InputManager::IsActionDown(IN CONST String &action)
BOOL InputManager::GetButtonB()
{
return IsActionDown(s_actionNames[action]);
return s_buttonB;
}
BOOL InputManager::WasActionPressed(IN CONST String &action)
BOOL InputManager::GetButtonC()
{
return WasActionPressed(s_actionNames[action]);
return s_buttonC;
}
BOOL InputManager::WasActionReleased(IN CONST String &action)
BOOL InputManager::GetButtonD()
{
return WasActionReleased(s_actionNames[action]);
return s_buttonD;
}
Handle InputManager::BindAction(IN CONST String &name, IN InputKey key)
INT16 InputManager::GetVerticalAxis()
{
s_actions.pushBack({key});
const auto handle = s_actions.size() - 1;
s_actionNames[name] = handle;
return handle;
return s_verticalAxis;
}
VOID InputManager::BindAxis(IN InputKey upKey, IN InputKey downKey, IN InputKey leftKey, IN InputKey rightKey)
INT16 InputManager::GetHorizontalAxis()
{
s_axisInputs[0] = upKey;
s_axisInputs[1] = downKey;
s_axisInputs[2] = leftKey;
s_axisInputs[3] = rightKey;
return s_horizontalAxis;
}
VOID InputManager::SetKey(IN InputKey key, IN BOOL state)
IVec2 InputManager::GetDirectionalInput()
{
s_keys[(UINT8) key] = state;
return IVec2{GetHorizontalAxis(), GetVerticalAxis()};
}
VOID InputManager::SetAxis(IN BOOL up, IN BOOL down, IN BOOL left, IN BOOL right)
VOID InputManager::SetButtonA(IN BOOL value)
{
s_keys[(UINT8) s_axisInputs[0]] = up;
s_keys[(UINT8) s_axisInputs[1]] = down;
s_keys[(UINT8) s_axisInputs[2]] = left;
s_keys[(UINT8) s_axisInputs[3]] = right;
s_buttonA = value;
}
VOID InputManager::SetAxisUp(IN BOOL v)
VOID InputManager::SetButtonB(IN BOOL value)
{
s_keys[(UINT8) s_axisInputs[0]] = v;
s_buttonB = value;
}
VOID InputManager::SetAxisDown(IN BOOL v)
VOID InputManager::SetButtonC(IN BOOL value)
{
s_keys[(UINT8) s_axisInputs[1]] = v;
s_buttonC = value;
}
VOID InputManager::SetAxisLeft(IN BOOL v)
VOID InputManager::SetButtonD(IN BOOL value)
{
s_keys[(UINT8) s_axisInputs[2]] = v;
s_buttonD = value;
}
VOID InputManager::SetAxisRight(IN BOOL v)
VOID InputManager::SetVerticalAxis(IN INT16 value)
{
s_keys[(UINT8) s_axisInputs[3]] = v;
s_verticalAxis = value;
}
VOID InputManager::SetHorizontalAxis(IN INT16 value)
{
s_horizontalAxis = value;
}
VOID InputManager::Draw()
{
if (s_onScreenGamePadEnabled)
{
//Engine::SetRenderState_Texture(0);
//Engine::SetRenderState_FlippedH(false);
//Engine::SetRenderState_FlippedV(false);
//Engine::SetRenderState_ColorOverlay({0xFF, 0xFF, 0xFF, 0xFF});
//Engine::SetRenderState_TextureOffset({0, 0});
//Engine::SetRenderState_CameraRelative(false);
//Engine::SetRenderState_Transform({300.0f, 500.0f},
// {100.0f, 100.0f},
// 0);
//Engine::DrawGeometry(Engine::GetGeometry_Circle(), 0xFF, 0);
}
}
VOID InputManager::Update()
{
s_buttonA = false;
s_buttonB = false;
s_buttonC = false;
s_buttonD = false;
s_verticalAxis = 0;
s_horizontalAxis = 0;
if (s_onScreenGamePadEnabled)
{
}
if (s_keyboardGamePadEnabled)
{
s_buttonA |= IsKeyDown(s_keyboardGamePadMapping.ButtonA);
s_buttonB |= IsKeyDown(s_keyboardGamePadMapping.ButtonB);
s_buttonC |= IsKeyDown(s_keyboardGamePadMapping.ButtonC);
s_buttonD |= IsKeyDown(s_keyboardGamePadMapping.ButtonD);
s_verticalAxis +=
IsKeyDown(s_keyboardGamePadMapping.AxisDown) + IsKeyDown(s_keyboardGamePadMapping.AxisUp) * -1;
s_horizontalAxis +=
IsKeyDown(s_keyboardGamePadMapping.AxisRight) + IsKeyDown(s_keyboardGamePadMapping.AxisLeft) * -1;
}
}
} // namespace ia::iae
namespace ia::iae
{
Vec2 Engine::GetInputAxis()
{
return InputManager::GetAxis();
}
VOID Engine::SwitchInputModeToText()
VOID Engine::Input_SwitchModeToText()
{
InputManager::SwitchModeToText();
}
VOID Engine::SwitchInputModeToAction()
VOID Engine::Input_SwitchModeToAction()
{
InputManager::SwitchModeToAction();
}
Vec2 Engine::GetInputPointerPosition()
Vec2 Engine::Input_GetPointerPosition()
{
return InputManager::GetPointerPosition();
}
BOOL Engine::IsInputKeyDown(IN InputKey key)
BOOL Engine::Input_IsKeyDown(IN InputKey key)
{
return InputManager::IsKeyDown(key);
}
BOOL Engine::WasInputKeyPressed(IN InputKey key)
BOOL Engine::Input_WasKeyPressed(IN InputKey key)
{
return InputManager::WasKeyPressed(key);
}
BOOL Engine::WasInputKeyReleased(IN InputKey key)
BOOL Engine::Input_WasKeyReleased(IN InputKey key)
{
return InputManager::WasKeyReleased(key);
}
BOOL Engine::IsInputActionDown(IN Handle action)
VOID Engine::Input_SetupOnScreenGamePad()
{
return InputManager::IsActionDown(action);
InputManager::SetupOnScreenGamePad();
}
BOOL Engine::WasInputActionPressed(IN Handle action)
VOID Engine::Input_SetupKeyboardGamePad(IN InputKey axisLeft, IN InputKey axisRight, IN InputKey axisDown,
IN InputKey axisUp, IN InputKey buttonA, IN InputKey buttonB,
IN InputKey buttonC, IN InputKey buttonD)
{
return InputManager::WasActionPressed(action);
InputManager::SetupKeyboardGamePad({axisLeft, axisRight, axisDown, axisUp, buttonA, buttonB, buttonC, buttonD});
}
BOOL Engine::WasInputActionReleased(IN Handle action)
BOOL Engine::Input_GetButtonA()
{
return InputManager::WasActionReleased(action);
return InputManager::GetButtonA();
}
BOOL Engine::IsInputActionDown(IN CONST String &action)
BOOL Engine::Input_GetButtonB()
{
return InputManager::IsActionDown(action);
return InputManager::GetButtonB();
}
BOOL Engine::WasInputActionPressed(IN CONST String &action)
BOOL Engine::Input_GetButtonC()
{
return InputManager::WasActionPressed(action);
return InputManager::GetButtonC();
}
BOOL Engine::WasInputActionReleased(IN CONST String &action)
BOOL Engine::Input_GetButtonD()
{
return InputManager::WasActionReleased(action);
return InputManager::GetButtonD();
}
Handle Engine::BindInputAction(IN CONST String &name, IN InputKey key)
INT16 Engine::Input_GetVerticalAxis()
{
return InputManager::BindAction(name, key);
return InputManager::GetVerticalAxis();
}
VOID Engine::BindInputAxis(IN InputKey upKey, IN InputKey downKey, IN InputKey leftKey, IN InputKey rightKey)
INT16 Engine::Input_GetHorizontalAxis()
{
InputManager::BindAxis(upKey, downKey, leftKey, rightKey);
return InputManager::GetHorizontalAxis();
}
VOID Engine::SetKey(IN InputKey key, IN BOOL state)
IVec2 Engine::Input_GetDirectionalInput()
{
InputManager::SetKey(key, state);
return InputManager::GetDirectionalInput();
}
VOID Engine::SetAxis(IN BOOL up, IN BOOL down, IN BOOL left, IN BOOL right)
VOID Engine::Input_SetButtonA(IN BOOL value)
{
InputManager::SetAxis(up, down, left, right);
InputManager::SetButtonA(value);
}
VOID Engine::SetAxisUp(IN BOOL v)
VOID Engine::Input_SetButtonB(IN BOOL value)
{
InputManager::SetAxisUp(v);
InputManager::SetButtonB(value);
}
VOID Engine::SetAxisDown(IN BOOL v)
VOID Engine::Input_SetButtonC(IN BOOL value)
{
InputManager::SetAxisDown(v);
InputManager::SetButtonC(value);
}
VOID Engine::SetAxisLeft(IN BOOL v)
VOID Engine::Input_SetButtonD(IN BOOL value)
{
InputManager::SetAxisLeft(v);
InputManager::SetButtonD(value);
}
VOID Engine::SetAxisRight(IN BOOL v)
VOID Engine::Input_SetVerticalAxis(IN INT16 value)
{
InputManager::SetAxisRight(v);
InputManager::SetVerticalAxis(value);
}
VOID Engine::Input_SetHorizontalAxis(IN INT16 value)
{
InputManager::SetHorizontalAxis(value);
}
} // namespace ia::iae

View File

@ -16,13 +16,14 @@
#include <AudioManager.hpp>
#include <EventManager.hpp>
#include <FontManager.hpp>
#include <InputManager.hpp>
#include <InternalEngine.hpp>
#include <Physics.hpp>
#include <Random.hpp>
#include <Renderer/Renderer.hpp>
#include <ResourceManager.hpp>
#include <Time.hpp>
#include <Physics.hpp>
#include <WorldManager.hpp>
#include <IAEngine/Engine.hpp>
@ -52,15 +53,14 @@ namespace ia::iae
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(g_gameName.c_str(), config->ScreenWidth, config->ScreenHeight,
if (!(g_windowHandle = SDL_CreateWindow(g_gameName.c_str(), config->WindowWidth, config->WindowHeight,
SDL_WINDOW_RESIZABLE)))
THROW_UNKNOWN("Failed to create the SDL window: ", SDL_GetError());
// SDL_SetWindowResizable(g_windowHandle, false);
const auto gameVersion = g_gameVersion;
SDL_SetAppMetadata(g_gameName.c_str(), IA_STRINGIFY_VERSION(gameVersion).c_str(),
g_gamePackageName.c_str());
SDL_SetAppMetadata(g_gameName.c_str(), IA_STRINGIFY_VERSION(gameVersion).c_str(), g_gamePackageName.c_str());
Time::Initialize();
Random::Initialize();
@ -70,12 +70,13 @@ namespace ia::iae
InputManager::Initialize();
ResourceManager::Initialize();
WorldManager::Initialize();
FontManager::Initialize();
UI::Initialize();
Physics::Initialize();
Game_OnInitialize();
Engine::ResizeDisplay(config->ScreenWidth, config->ScreenHeight);
Engine::ResizeDisplay(config->WindowWidth, config->WindowHeight);
}
VOID __Internal_Engine::Terminate()
@ -84,6 +85,7 @@ namespace ia::iae
Physics::Terminate();
UI::Terminate();
FontManager::Terminate();
WorldManager::Terminate();
ResourceManager::Terminate();
InputManager::Terminate();
@ -102,6 +104,7 @@ namespace ia::iae
{
UI::Update();
Physics::Update();
InputManager::Update();
WorldManager::Update();
WorldManager::FixedUpdate();
Game_OnUpdate(Time::GetFrameDeltaTime());
@ -110,6 +113,7 @@ namespace ia::iae
Renderer::BeginFrame();
WorldManager::Draw();
UI::Draw();
InputManager::Draw();
Renderer::EndFrame();
}
@ -132,7 +136,8 @@ namespace ia::iae
return (FLOAT32) m_value + ((FLOAT32) m_value * (Random::Get() * m_randomAdjustment) / 100.0f);
}
INT32 Run(IN CONST String& name, IN CONST String& packageName, IN CONST String& developerName, IN CONST String& publisherName, IN IA_VERSION_TYPE version)
INT32 Run(IN CONST String &name, IN CONST String &packageName, IN CONST String &developerName,
IN CONST String &publisherName, IN IA_VERSION_TYPE version)
{
g_gameName = name;
g_gameVersion = version;

View File

View File

@ -0,0 +1,25 @@
// 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/Engine.hpp>
#include <IAEngine/Nodes/UILabelNode.hpp>
namespace ia::iae
{
UILabelNode::UILabelNode(IN CONST String &name) : UINode(name), m_labelComponent(AddComponent<UILabelComponent>())
{
}
} // namespace ia::iae

View File

@ -0,0 +1,62 @@
// 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/Nodes/UINode.hpp>
namespace ia::iae
{
UINode::UINode(IN CONST String &name): INode(name)
{
}
UINode::~UINode()
{
for(auto& t: m_components)
delete t;
}
VOID UINode::Draw()
{
for(auto& t: m_components)
t->Draw();
for(auto& t: m_children)
t->Draw();
}
VOID UINode::DebugDraw()
{
for(auto& t: m_components)
t->DebugDraw();
for(auto& t: m_children)
t->DebugDraw();
}
VOID UINode::Update()
{
for(auto& t: m_components)
t->Update();
for(auto& t: m_children)
t->Update();
}
VOID UINode::FixedUpdate()
{
for(auto& t: m_components)
t->FixedUpdate();
for(auto& t: m_children)
t->FixedUpdate();
}
} // namespace ia::iae

View File

View File

@ -33,7 +33,7 @@ namespace ia::iae
VOID Physics::Update()
{
if(Engine::WasInputKeyPressed(InputKey::F6))
if(Engine::Input_WasKeyPressed(InputKey::F6))
g_physicsDebugDrawEnabled = !g_physicsDebugDrawEnabled;
}

View File

@ -67,7 +67,7 @@ namespace ia::iae
IN INT32 height, IN PCUINT8 rgbaData,
IN SDL_GPUTextureFormat format, IN BOOL generateMipmaps)
{
const auto mipLevels = generateMipmaps ? floor(log2(ia_max(width, height))) + 1 : 1;
const auto mipLevels = 1;//generateMipmaps ? ia_max((UINT32)(floor(log2(ia_max(width, height))) + 1), (UINT32)1) : (UINT32)1;
STATIC Vector<UINT8> TMP_COLOR_BUFFER;

View File

@ -19,6 +19,7 @@
#include <Renderer/EmbeddedShader.hpp>
#include <Renderer/Renderer.hpp>
#include <FontManager.hpp>
#include <ResourceManager.hpp>
#include <WorldManager.hpp>
@ -45,6 +46,7 @@ namespace ia::iae
Pipeline *Renderer::s_postprocessPipeline{};
Renderer::Geometry *Renderer::s_quadGeometry{};
Renderer::Geometry *Renderer::s_circleGeometry{};
Vector<Renderer::DrawEntry> Renderer::s_drawEntries;
@ -123,6 +125,125 @@ namespace ia::iae
{glm::vec3{0, 0, 0}, glm::vec2{0, 0}, glm::vec4{1.0f, 1.0f, 1.0f, 1.0f}},
},
{0, 1, 2, 2, 3, 0});
s_circleGeometry = CreateGeometry(
{
{{0.0000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.0000000f},
{0.5000000f, 0.5000000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 0 Center
{{1.0000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.0000000f},
{1.0000000f, 0.5000000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 1
{{0.9848078f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.1736482f},
{0.9924039f, 0.5868241f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 2
{{0.9396926f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.3420201f},
{0.9698463f, 0.6710101f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 3
{{0.8660254f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.5000000f},
{0.9330127f, 0.7500000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 4
{{0.7660444f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.6427876f},
{0.8830222f, 0.8213938f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 5
{{0.6427876f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.7660444f},
{0.8213938f, 0.8830222f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 6
{{0.5000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.8660254f},
{0.7500000f, 0.9330127f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 7
{{0.3420201f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.9396926f},
{0.6710101f, 0.9698463f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 8
{{0.1736482f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.9848078f},
{0.5868241f, 0.9924039f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 9
{{0.0000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 1.0000000f},
{0.5000000f, 1.0000000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 10
{{-0.1736482f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.9848078f},
{0.4131759f, 0.9924039f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 11
{{-0.3420201f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.9396926f},
{0.3289899f, 0.9698463f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 12
{{-0.5000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.8660254f},
{0.2500000f, 0.9330127f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 13
{{-0.6427876f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.7660444f},
{0.1786062f, 0.8830222f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 14
{{-0.7660444f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.6427876f},
{0.1169778f, 0.8213938f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 15
{{-0.8660254f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.5000000f},
{0.0669873f, 0.7500000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 16
{{-0.9396926f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.3420201f},
{0.0301537f, 0.6710101f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 17
{{-0.9848078f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.1736482f},
{0.0075961f, 0.5868241f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 18
{{-1.0000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * 0.0000000f},
{0.0000000f, 0.5000000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 19
{{-0.9848078f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.1736482f},
{0.0075961f, 0.4131759f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 20
{{-0.9396926f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.3420201f},
{0.0301537f, 0.3289899f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 21
{{-0.8660254f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.5000000f},
{0.0669873f, 0.2500000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 22
{{-0.7660444f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.6427876f},
{0.1169778f, 0.1786062f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 23
{{-0.6427876f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.7660444f},
{0.1786062f, 0.1169778f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 24
{{-0.5000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.8660254f},
{0.2500000f, 0.0669873f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 25
{{-0.3420201f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.9396926f},
{0.3289899f, 0.0301537f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 26
{{-0.1736482f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.9848078f},
{0.4131759f, 0.0075961f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 27
{{-0.0000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -1.0000000f},
{0.5000000f, 0.0000000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 28
{{0.1736482f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.9848078f},
{0.5868241f, 0.0075961f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 29
{{0.3420201f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.9396926f},
{0.6710101f, 0.0301537f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 30
{{0.5000000f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.8660254f},
{0.7500000f, 0.0669873f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 31
{{0.6427876f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.7660444f},
{0.8213938f, 0.1169778f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 32
{{0.7660444f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.6427876f},
{0.8830222f, 0.1786062f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 33
{{0.8660254f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.5000000f},
{0.9330127f, 0.2500000f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 34
{{0.9396926f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.3420201f},
{0.9698463f, 0.3289899f},
{1.0f, 1.0f, 1.0f, 1.0f}}, // 35
{{0.9848078f, (1.0f / Engine::GetDisplayAspectRatio()) * 0.75f * -0.1736482f},
{0.9924039f, 0.4131759f},
{1.0f, 1.0f, 1.0f, 1.0f}} // 36
},
{0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 9, 0, 9, 10,
0, 10, 11, 0, 11, 12, 0, 12, 13, 0, 13, 14, 0, 14, 15, 0, 15, 16, 0, 16, 17, 0, 17, 18, 0, 18, 19,
0, 19, 20, 0, 20, 21, 0, 21, 22, 0, 22, 23, 0, 23, 24, 0, 24, 25, 0, 25, 26, 0, 26, 27, 0, 27, 28,
0, 28, 29, 0, 29, 30, 0, 30, 31, 0, 31, 32, 0, 32, 33, 0, 33, 34, 0, 34, 35, 0, 35, 36, 0, 36, 1});
}
VOID Renderer::Terminate()
@ -130,6 +251,7 @@ namespace ia::iae
SDL_WaitForGPUIdle(s_gpuDevice);
DestroyGeometry(s_quadGeometry);
DestroyGeometry(s_circleGeometry);
DebugDraw::Terminate();
@ -321,6 +443,36 @@ namespace ia::iae
DrawEntry{.Layer = layer, .SortIndex = t, .DrawState = s_state, .GeometryHandle = handle});
}
VOID Renderer::DrawText(IN CONST String &text, IN Vec2 position, IN FLOAT32 scale, IN FLOAT32 rotation,
IN UINT8 layer, IN UINT16 sortIndex)
{
const auto &font = FontManager::GetFont("Roboto");
const auto t = (UINT16) (sortIndex + ((UINT16) s_state.PositionY * s_state.YSortingEnabled));
Vec3 p{};
Vec3 s{};
for (const auto &c : text)
{
if (!c)
break;
const auto glyph = font.Chars[(UINT8) c];
p = Vec3(position.x, position.y, 0.0f) +
Vec3(glyph.Bearing.x, glyph.Size.y - glyph.Bearing.y, 0.0f) * scale;
p.y += (16 - glyph.Size.y) * scale;
s = Vec3(scale * glyph.Size.x, scale * glyph.Size.y, 1.0f);
s_state.ActiveTexture = glyph.Texture;
s_state.PositionY = position.y;
s_state.ModelMatrix = glm::translate(glm::mat4(1.0f), p);
s_state.ModelMatrix = glm::rotate(s_state.ModelMatrix, rotation, glm::vec3(0.0f, 0.0f, 1.0f));
s_state.ModelMatrix = glm::scale(s_state.ModelMatrix, s);
s_drawEntries.pushBack(
DrawEntry{.Layer = layer, .SortIndex = t, .DrawState = s_state, .GeometryHandle = s_quadGeometry});
position.x += glyph.Advance * scale;
}
}
VOID Renderer::WaitForGPUIdle()
{
SDL_WaitForGPUIdle(s_gpuDevice);
@ -334,6 +486,11 @@ namespace ia::iae
return IVec2(Renderer::s_screenWidth, Renderer::s_screenHeight);
}
FLOAT32 Engine::GetDisplayAspectRatio()
{
return (FLOAT32) Renderer::s_screenHeight / (FLOAT32) Renderer::s_screenWidth;
}
VOID Engine::SetActiveCamera(IN CameraComponent *cameraComponent)
{
Renderer::s_activeCamera = cameraComponent;
@ -365,6 +522,12 @@ namespace ia::iae
Renderer::DrawGeometry((Renderer::Geometry *) handle, layer, sortIndex);
}
VOID Engine::DrawText(IN CONST String &text, IN Vec2 position, IN FLOAT32 scale, IN FLOAT32 rotation,
IN UINT8 layer, IN UINT16 sortIndex)
{
Renderer::DrawText(text, position, scale, rotation, layer, sortIndex);
}
VOID Engine::SetRenderState_Scissor(IN IVec4 rect)
{
Renderer::s_scissor = rect.z ? SDL_Rect{0, 0, Renderer::s_screenWidth, Renderer::s_screenHeight}
@ -431,4 +594,9 @@ namespace ia::iae
{
return (Handle) Renderer::s_quadGeometry;
}
Handle Engine::GetGeometry_Circle()
{
return (Handle) Renderer::s_circleGeometry;
}
} // namespace ia::iae

View File

@ -17,31 +17,13 @@
#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
Scene::Scene()
{
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>();
@ -52,106 +34,6 @@ namespace ia::iae
return scene;
}
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 = 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;
}
VOID Scene::Draw()
{
for (auto &t : m_nodes)

View File

@ -0,0 +1,160 @@
// 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/Engine.hpp>
#include <IAEngine/SceneManager.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;
};
// -----------------------------------------------
}
namespace ia::iae
{
SceneManager::SceneManager(IN std::function<RefPtr<Node2D>(IN CONST String &, IN CONST Vector<String>&)> getCustomNode,
IN std::function<Handle(IN ResourceType type, IN CONST String &, IN INT64)> getResource):
m_customNodeGetter(getCustomNode), m_resourceGetter(getResource)
{
}
SceneManager::~SceneManager()
{
for(const auto& t: m_scenes)
delete t->Value;
}
VOID SceneManager::SwitchTo(IN CONST String &name)
{
Engine::ChangeActiveScene(m_scenes[name]);
}
Scene *SceneManager::GetScene(IN CONST String &name)
{
return m_scenes[name];
}
VOID SceneManager::AddScene(IN Scene *scene, IN CONST String &name, IN CONST String &xml)
{
pugi::xml_document doc;
doc.load_string(xml.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()] = m_resourceGetter(
ResourceType::IMAGE, t.attribute("path").as_string(), t.attribute("index").as_llong());
}
else if (!strcmp(t.name(), "Audio"))
{
resources[t.attribute("name").as_string()] =
m_resourceGetter(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
{
const auto node = m_customNodeGetter(t.name(), String(t.attribute("id").as_string()).split(';'));
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;
}
m_scenes[name] = scene;
}
} // namespace ia::iae

View File

@ -391,16 +391,29 @@ namespace ia::iae
namespace ia::iae
{
INT64 UI::s_numericVariables[MAX_VARIABLE_COUNT];
std::string UI::s_stringVariables[MAX_VARIABLE_COUNT];
Rml::DataModelConstructor g_dataModel;
VOID UI::Initialize()
{
Rml::SetRenderInterface(&g_rmlUIRenderInterface);
Rml::Initialise();
Rml::LoadFontFace("Resources/Fonts/Roboto-Black.ttf");
const auto displayExtent = Engine::GetDisplayExtent();
g_context = Rml::CreateContext("main", Rml::Vector2i(displayExtent.x, displayExtent.y));
Rml::Debugger::Initialise(g_context);
Rml::Debugger::SetVisible(false);
g_document = g_context->CreateDocument();
g_dataModel = g_context->CreateDataModel("ui_data");
for (INT32 i = 0; i < MAX_VARIABLE_COUNT; i++)
g_dataModel.Bind(BuildString("NumVar", i).c_str(), &s_numericVariables[i]);
for (INT32 i = 0; i < MAX_VARIABLE_COUNT; i++)
g_dataModel.Bind(BuildString("StrVar", i).c_str(), &s_stringVariables[i]);
}
VOID UI::Terminate()
@ -410,7 +423,7 @@ namespace ia::iae
VOID UI::Update()
{
if (Engine::WasInputKeyPressed(InputKey::F8))
if (Engine::Input_WasKeyPressed(InputKey::F8))
Rml::Debugger::SetVisible(g_debuggerEnabled = !g_debuggerEnabled);
g_context->Update();
@ -483,7 +496,9 @@ namespace ia::iae
VOID UI::SetMarkup(IN CONST String &markup, IN CONST String &styles)
{
g_styleSheetContainer = Rml::Factory::InstanceStyleSheetString(styles.c_str());
g_markup = BuildString("<body style=\"display: block; width: 100vw; height: 100vh;\">", markup, "</body>");
g_markup = BuildString("<body><div style=\"font-family: Roboto; display: block; width: 100vw; height: 100vh;\" "
"data-model=\"ui_data\">",
markup, "</div></body>");
g_document->SetStyleSheetContainer(g_styleSheetContainer);
g_document->SetInnerRML(g_markup.c_str());
}
@ -512,6 +527,46 @@ namespace ia::iae
{
g_eventListener.AddPointerEnterListener(g_document->GetElementById(elementId), callback);
}
VOID UI::SetNumericVariable(IN UINT8 index, IN INT64 value)
{
s_numericVariables[index] = value;
}
VOID UI::SetStringVariable(IN UINT8 index, IN CONST String &value)
{
s_stringVariables[index] = value.c_str();
}
INT64 UI::GetNumericVariable(IN UINT8 index)
{
return s_numericVariables[index];
}
String UI::GetStringVariable(IN UINT8 index)
{
return s_stringVariables[index].c_str();
}
VOID UI::SetElementWidth(IN CONST String &elementId, IN INT32 value)
{
g_document->GetElementById(elementId.c_str())->SetProperty("width", BuildString(value, "px").c_str());
}
INT32 UI::GetElementWidth(IN CONST String &elementId)
{
return g_document->GetElementById(elementId.c_str())->GetClientWidth();
}
VOID UI::SetElementHeight(IN CONST String &elementId, IN INT32 value)
{
g_document->GetElementById(elementId.c_str())->SetProperty("height", BuildString(value, "px").c_str());
}
INT32 UI::GetElementHeight(IN CONST String &elementId)
{
return g_document->GetElementById(elementId.c_str())->GetClientHeight();
}
} // namespace ia::iae
namespace ia::iae
@ -540,7 +595,7 @@ namespace ia::iae
Engine::SetRenderState_ColorOverlay({255, 255, 255, 255});
Engine::SetRenderState_TextureOffset({0, 0});
Engine::SetRenderState_CameraRelative(false);
Engine::SetRenderState_TransformUI({translation.x, translation.y}, {1.0f, 1.0f}, 0);
Engine::SetRenderState_Transform({translation.x, translation.y}, {1.0f, 1.0f}, 0);
Engine::DrawGeometry((Handle) geometry, 0xFF, 0);
}

View File

@ -19,16 +19,18 @@
namespace ia::iae
{
RefPtr<Scene> WorldManager::s_activeScene{};
RefPtr<Scene> g_defaultScene;
Scene* WorldManager::s_activeScene{};
VOID WorldManager::Initialize()
{
s_activeScene = Scene::Create();
g_defaultScene = Scene::Create();
s_activeScene = g_defaultScene.get();
}
VOID WorldManager::Terminate()
{
s_activeScene.reset();
}
VOID WorldManager::Draw()
@ -51,7 +53,7 @@ namespace ia::iae
s_activeScene->FixedUpdate();
}
VOID WorldManager::ChangeActiveScene(IN RefPtr<Scene> scene)
VOID WorldManager::ChangeActiveScene(IN Scene* scene)
{
s_activeScene = scene;
scene->OnActivate();
@ -74,7 +76,7 @@ namespace ia::iae
Scene *WorldManager::GetActiveScene()
{
return s_activeScene.get();
return s_activeScene;
}
} // namespace ia::iae
@ -85,7 +87,7 @@ namespace ia::iae
return WorldManager::GetActiveScene();
}
VOID Engine::ChangeActiveScene(IN RefPtr<Scene> scene)
VOID Engine::ChangeActiveScene(IN Scene* scene)
{
WorldManager::ChangeActiveScene(scene);
}

View File

@ -0,0 +1,54 @@
// 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>
#include <SDL3/SDL.h>
namespace ia::iae
{
class FontManager
{
public:
struct Character
{
IVec2 Size;
IVec2 Bearing; // Offset from baseline to left/top of glyph
UINT32 Advance; // Horizontal offset to advance to next glyph
SDL_GPUTexture *Texture{};
};
struct Font
{
Character Chars[0x80];
};
public:
STATIC VOID Initialize();
STATIC VOID Terminate();
STATIC VOID LoadFont(IN CONST String &name, IN CONST String &path);
STATIC CONST Font &GetFont(IN CONST String &name)
{
return s_fonts[name];
}
private:
STATIC Map<String, Font> s_fonts;
};
} // namespace ia::iae

View File

@ -24,41 +24,70 @@ namespace ia::iae
{
class InputManager
{
public:
struct KeyboardGamePadMapping
{
IN InputKey AxisLeft;
IN InputKey AxisRight;
IN InputKey AxisDown;
IN InputKey AxisUp;
IN InputKey ButtonA;
IN InputKey ButtonB;
IN InputKey ButtonC;
IN InputKey ButtonD;
};
public:
STATIC VOID Initialize();
STATIC VOID Terminate();
STATIC VOID OnSDLEvent(IN SDL_Event *event);
STATIC Vec2 GetAxis();
STATIC VOID SwitchModeToText();
STATIC VOID SwitchModeToAction();
STATIC Vec2 GetPointerPosition();
STATIC BOOL IsKeyDown(IN InputKey key);
STATIC BOOL WasKeyPressed(IN InputKey key);
STATIC BOOL WasKeyReleased(IN InputKey key);
STATIC BOOL IsActionDown(IN Handle action);
STATIC BOOL WasActionPressed(IN Handle action);
STATIC BOOL WasActionReleased(IN Handle action);
STATIC BOOL IsActionDown(IN CONST String& action);
STATIC BOOL WasActionPressed(IN CONST String& action);
STATIC BOOL WasActionReleased(IN CONST String& action);
STATIC Handle BindAction(IN CONST String &name, IN InputKey key);
STATIC VOID BindAxis(IN InputKey upKey, IN InputKey downKey, IN InputKey leftKey, IN InputKey rightKey);
STATIC VOID SetAxisUp(IN BOOL v);
STATIC VOID SetAxisDown(IN BOOL v);
STATIC VOID SetAxisLeft(IN BOOL v);
STATIC VOID SetAxisRight(IN BOOL v);
STATIC VOID SetKey(IN InputKey key, IN BOOL state);
STATIC VOID SetAxis(IN BOOL up, IN BOOL down, IN BOOL left, IN BOOL right);
STATIC VOID SetupOnScreenGamePad();
STATIC VOID SetupKeyboardGamePad(IN CONST KeyboardGamePadMapping& mapping);
STATIC BOOL GetButtonA();
STATIC BOOL GetButtonB();
STATIC BOOL GetButtonC();
STATIC BOOL GetButtonD();
STATIC INT16 GetVerticalAxis();
STATIC INT16 GetHorizontalAxis();
STATIC IVec2 GetDirectionalInput();
STATIC VOID SetButtonA(IN BOOL value);
STATIC VOID SetButtonB(IN BOOL value);
STATIC VOID SetButtonC(IN BOOL value);
STATIC VOID SetButtonD(IN BOOL value);
STATIC VOID SetVerticalAxis(IN INT16 value);
STATIC VOID SetHorizontalAxis(IN INT16 value);
private:
STATIC BOOL s_buttonA;
STATIC BOOL s_buttonB;
STATIC BOOL s_buttonC;
STATIC BOOL s_buttonD;
STATIC INT16 s_verticalAxis;
STATIC INT16 s_horizontalAxis;
STATIC BOOL s_keys[256];
STATIC BOOL s_prevKeys[256];
STATIC Vec2 s_pointerPosition;
STATIC InputKey s_axisInputs[4];
STATIC Map<String, Handle> s_actionNames;
STATIC Vector<Vector<InputKey>> s_actions;
STATIC BOOL s_onScreenGamePadEnabled;
STATIC BOOL s_keyboardGamePadEnabled;
STATIC KeyboardGamePadMapping s_keyboardGamePadMapping;
private:
STATIC VOID Initialize();
STATIC VOID Terminate();
STATIC VOID Draw();
STATIC VOID Update();
STATIC VOID OnSDLEvent(IN SDL_Event *event);
friend class __Internal_Engine;
};
} // namespace ia::iae

View File

@ -71,6 +71,7 @@ namespace ia::iae
STATIC VOID DestroyGeometry(IN Geometry* handle);
STATIC VOID DrawGeometry(IN Geometry* handle, IN UINT8 layer, IN UINT16 sortIndex);
STATIC VOID DrawText(IN CONST String& text, IN Vec2 position, IN FLOAT32 scale, IN FLOAT32 rotation, IN UINT8 layer, IN UINT16 sortIndex);
STATIC SDL_GPUTextureFormat GetRenderTargetFormat();
@ -89,6 +90,7 @@ namespace ia::iae
STATIC Pipeline* s_geometryPipeline;
STATIC Pipeline* s_postprocessPipeline;
STATIC Geometry* s_quadGeometry;
STATIC Geometry* s_circleGeometry;
STATIC Vector<DrawEntry> s_drawEntries;
STATIC SDL_GPURenderPass* s_activeRenderPass;
STATIC SDL_GPUCommandBuffer* s_activeCommandBuffer;

View File

@ -37,12 +37,12 @@ namespace ia::iae
public:
STATIC Scene *GetActiveScene();
STATIC VOID ChangeActiveScene(IN RefPtr<Scene> scene);
STATIC VOID ChangeActiveScene(IN Scene* scene);
STATIC VOID AddNodeToActiveScene(IN RefPtr<INode> node);
STATIC INode *GetNodeFromActiveScene(IN CONST String &name);
STATIC VOID RemoveNodeFromActiveScene(IN CONST String &name);
private:
STATIC RefPtr<Scene> s_activeScene;
STATIC Scene* s_activeScene;
};
} // namespace ia::iae

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 <IAEngine/Base.hpp>
namespace ia::iae
{
class UINode;
class IUIComponent
{
public:
PURE_VIRTUAL(VOID Draw());
PURE_VIRTUAL(VOID DebugDraw());
PURE_VIRTUAL(VOID Update());
PURE_VIRTUAL(VOID FixedUpdate());
public:
IUIComponent(IN UINode *node) : m_node(node)
{
}
UINode *GetNode()
{
return m_node;
}
CONST UINode *GetNode() CONST
{
return m_node;
}
protected:
UINode *CONST m_node{};
};
}

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 <IAEngine/Components/IUIComponent.hpp>
namespace ia::iae
{
class UILabelComponent : public IUIComponent
{
public:
UILabelComponent(IN UINode* node);
String &Label()
{
return m_label;
}
CONST String &Label() CONST
{
return m_label;
}
public:
VOID Draw();
VOID DebugDraw();
VOID Update();
VOID FixedUpdate();
private:
String m_label{};
};
} // namespace ia::iae

View File

@ -44,11 +44,14 @@ namespace ia::iae
// Renderer Functions
STATIC Handle GetGeometry_Quad();
STATIC Handle GetGeometry_Circle();
STATIC Handle CreateGeometry(IN CONST Vector<GeometryVertex> &vertices, IN CONST Vector<INT32> &indices);
STATIC VOID DestroyGeometry(IN Handle geometry);
STATIC VOID DrawGeometry(IN Handle handle, IN UINT8 layer, IN UINT16 sortIndex);
STATIC IVec2 GetDisplayExtent();
STATIC FLOAT32 GetDisplayAspectRatio();
STATIC VOID ResizeDisplay(IN INT32 newWidth, IN INT32 newHeight);
STATIC VOID DrawText(IN CONST String& text, IN Vec2 position, IN FLOAT32 scale, IN FLOAT32 rotation, IN UINT8 layer, IN UINT16 sortIndex);
// Renderer State Functions
STATIC VOID SetRenderState_Scissor(IN IVec4 rect);
@ -96,33 +99,35 @@ namespace ia::iae
// Scene Functions
STATIC Scene *GetActiveScene();
STATIC VOID ChangeActiveScene(IN RefPtr<Scene> scene);
STATIC VOID ChangeActiveScene(IN Scene* scene);
STATIC VOID AddNodeToActiveScene(IN RefPtr<INode> node);
STATIC INode *GetNodeFromActiveScene(IN CONST String &name);
STATIC VOID RemoveNodeFromActiveScene(IN CONST String &name);
// Input Functions
STATIC Vec2 GetInputAxis();
STATIC VOID SwitchInputModeToText();
STATIC VOID SwitchInputModeToAction();
STATIC Vec2 GetInputPointerPosition();
STATIC BOOL IsInputKeyDown(IN InputKey key);
STATIC BOOL WasInputKeyPressed(IN InputKey key);
STATIC BOOL WasInputKeyReleased(IN InputKey key);
STATIC BOOL IsInputActionDown(IN Handle action);
STATIC BOOL WasInputActionPressed(IN Handle action);
STATIC BOOL WasInputActionReleased(IN Handle action);
STATIC BOOL IsInputActionDown(IN CONST String &action);
STATIC BOOL WasInputActionPressed(IN CONST String &action);
STATIC BOOL WasInputActionReleased(IN CONST String &action);
STATIC Handle BindInputAction(IN CONST String &name, IN InputKey key);
STATIC VOID BindInputAxis(IN InputKey upKey, IN InputKey downKey, IN InputKey leftKey, IN InputKey rightKey);
STATIC VOID SetAxisUp(IN BOOL v);
STATIC VOID SetAxisDown(IN BOOL v);
STATIC VOID SetAxisLeft(IN BOOL v);
STATIC VOID SetAxisRight(IN BOOL v);
STATIC VOID SetKey(IN InputKey key, IN BOOL state);
STATIC VOID SetAxis(IN BOOL up, IN BOOL down, IN BOOL left, IN BOOL right);
STATIC VOID Input_SwitchModeToText();
STATIC VOID Input_SwitchModeToAction();
STATIC Vec2 Input_GetPointerPosition();
STATIC BOOL Input_IsKeyDown(IN InputKey key);
STATIC BOOL Input_WasKeyPressed(IN InputKey key);
STATIC BOOL Input_WasKeyReleased(IN InputKey key);
STATIC VOID Input_SetupOnScreenGamePad();
STATIC VOID Input_SetupKeyboardGamePad(IN InputKey axisLeft, IN InputKey axisRight, IN InputKey axisDown,
IN InputKey axisUp, IN InputKey buttonA, IN InputKey buttonB,
IN InputKey buttonC, IN InputKey buttonD);
STATIC BOOL Input_GetButtonA();
STATIC BOOL Input_GetButtonB();
STATIC BOOL Input_GetButtonC();
STATIC BOOL Input_GetButtonD();
STATIC INT16 Input_GetVerticalAxis();
STATIC INT16 Input_GetHorizontalAxis();
STATIC IVec2 Input_GetDirectionalInput();
STATIC VOID Input_SetButtonA(IN BOOL value);
STATIC VOID Input_SetButtonB(IN BOOL value);
STATIC VOID Input_SetButtonC(IN BOOL value);
STATIC VOID Input_SetButtonD(IN BOOL value);
STATIC VOID Input_SetVerticalAxis(IN INT16 value);
STATIC VOID Input_SetHorizontalAxis(IN INT16 value);
// Utility Functions
STATIC String ReadTextAsset(IN CONST String& path);

View File

@ -23,8 +23,10 @@ using namespace ia::iae;
struct GameRequestedConfig
{
INT32 ScreenWidth{};
INT32 ScreenHeight{};
INT32 DesignWidth{};
INT32 DesignHeight{};
INT32 WindowWidth{};
INT32 WindowHeight{};
};
C_DECL(GameRequestedConfig* Game_GetConfigRequest());

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/>.
#pragma once
#include <IAEngine/Components/UILabelComponent.hpp>
#include <IAEngine/Nodes/UINode.hpp>
namespace ia::iae
{
class UILabelNode : public UINode
{
public:
UILabelNode(IN CONST String &name);
public:
UILabelComponent *GetLabelComponent()
{
return m_labelComponent;
}
protected:
UILabelComponent *CONST m_labelComponent{};
};
} // namespace ia::iae

View File

@ -17,8 +17,161 @@
#pragma once
#include <IAEngine/Nodes/INode.hpp>
#include <IAEngine/Components/IUIComponent.hpp>
namespace ia::iae
{
class UINode : public INode
{
public:
UINode(IN CONST String &name);
~UINode();
public:
template<typename _component_type> _component_type *AddComponent()
{
const auto t = new _component_type(this);
m_components.pushBack(t);
return t;
}
template<typename _component_type> _component_type *GetComponent()
{
for (auto &c : m_components)
{
_component_type *comp = dynamic_cast<_component_type *>(c);
if (comp)
return comp;
}
return nullptr;
}
template<typename _component_type> Vector<_component_type *> GetComponents()
{
Vector<_component_type *> result;
for (auto &c : m_components)
{
_component_type *comp = dynamic_cast<_component_type *>(c);
if (comp)
result.pushBack(comp);
}
return result;
}
VOID AddChild(IN RefPtr<UINode> node)
{
node->m_parent = this;
m_children.pushBack(node);
}
public:
VOID Translate(IN Vec2 v)
{
m_local.Position += v;
RecalculatePosition();
}
VOID Scale(IN FLOAT32 v)
{
m_local.Scale *= v;
RecalculateScale();
}
VOID Rotate(IN FLOAT32 v)
{
m_local.Rotation += v;
RecalculateRotation();
}
VOID SetLocalPosition(IN CONST Vec2 &v)
{
m_local.Position = v;
RecalculatePosition();
}
VOID SetLocalScale(IN CONST FLOAT32 &v)
{
m_local.Scale = v;
RecalculateScale();
}
VOID SetLocalRotation(IN FLOAT32 v)
{
m_local.Rotation = v;
RecalculateRotation();
}
public:
CONST Vec2 &GetPosition() CONST
{
return m_global.Position;
}
CONST FLOAT32 &GetScale() CONST
{
return m_global.Scale;
}
CONST FLOAT32 &GetRotation() CONST
{
return m_global.Rotation;
}
CONST Vec2 &GetLocalPosition() CONST
{
return m_local.Position;
}
CONST FLOAT32 &GetLocalScale() CONST
{
return m_local.Scale;
}
CONST FLOAT32 &GetLocalRotation() CONST
{
return m_local.Rotation;
}
protected:
VOID RecalculatePosition()
{
m_global.Position = (m_parent ? m_parent->GetPosition() : Vec2{}) + m_local.Position;
for (auto &c : m_children)
c->RecalculatePosition();
}
VOID RecalculateRotation()
{
m_global.Rotation = (m_parent ? m_parent->GetRotation() : 0) + m_local.Rotation;
for (auto &c : m_children)
c->RecalculateRotation();
}
VOID RecalculateScale()
{
m_global.Scale = (m_parent ? m_parent->GetScale() : 0.0f) + m_local.Scale;
for (auto &c : m_children)
c->RecalculateScale();
}
protected:
UINode* m_parent{};
Vector<IUIComponent *> m_components;
Vector<RefPtr<UINode>> m_children{};
private:
struct
{
FLOAT32 Rotation{0.0f};
Vec2 Position{0.0f, 0.0f};
FLOAT32 Scale{1.0f};
} m_local{}, m_global{};
public:
VOID Draw();
VOID DebugDraw();
VOID Update();
VOID FixedUpdate();
};
}

View File

@ -24,10 +24,8 @@ namespace ia::iae
class Scene
{
public:
Scene();
STATIC RefPtr<Scene> Create();
STATIC RefPtr<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);
public:
VOID AddNode(IN RefPtr<INode> node);
@ -70,11 +68,11 @@ namespace ia::iae
Map<String, RefPtr<INode>> m_nodes;
public:
VOID Draw();
VOID DebugDraw();
VOID FixedUpdate();
VOID Update();
VIRTUAL VOID Draw();
VIRTUAL VOID DebugDraw();
VIRTUAL VOID FixedUpdate();
VIRTUAL VOID Update();
private:
VOID OnActivate();

View File

@ -0,0 +1,50 @@
// 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>
namespace ia::iae
{
class SceneManager
{
public:
SceneManager(IN std::function<RefPtr<Node2D>(IN CONST String &, IN CONST Vector<String>&)> getCustomNode,
IN std::function<Handle(IN ResourceType type, IN CONST String &, IN INT64)> getResource);
~SceneManager();
VOID SwitchTo(IN CONST String &name);
Scene *GetScene(IN CONST String &name);
public:
template<typename SceneType> SceneType* AddScene(IN CONST String &name, IN CONST String &xml)
{
const auto t = (Scene*)new SceneType();
AddScene(t, name, xml);
return (SceneType*)t;
}
private:
VOID AddScene(IN Scene *scene, IN CONST String &name, IN CONST String &xml);
private:
Map<String, Scene *> m_scenes;
std::function<RefPtr<Node2D>(IN CONST String &, IN CONST Vector<String>&)> m_customNodeGetter;
std::function<Handle(IN ResourceType type, IN CONST String &, IN INT64)> m_resourceGetter;
};
} // namespace ia::iae

View File

@ -22,6 +22,9 @@ namespace ia::iae
{
class UI
{
public:
STATIC CONSTEXPR UINT8 MAX_VARIABLE_COUNT = 10;
public:
STATIC VOID AddFontFromFile(IN CONST String &path);
@ -33,6 +36,18 @@ namespace ia::iae
STATIC VOID AddPointerExitEvent(IN PCCHAR elementId, IN std::function<VOID()> callback);
STATIC VOID AddPointerEnterEvent(IN PCCHAR elementId, IN std::function<VOID()> callback);
STATIC VOID SetNumericVariable(IN UINT8 index, IN INT64 value);
STATIC VOID SetStringVariable(IN UINT8 index, IN CONST String &value);
STATIC INT64 GetNumericVariable(IN UINT8 index);
STATIC String GetStringVariable(IN UINT8 index);
STATIC INT32 GetElementWidth(IN CONST String &elementId);
STATIC VOID SetElementWidth(IN CONST String &elementId, IN INT32 value);
STATIC INT32 GetElementHeight(IN CONST String &elementId);
STATIC VOID SetElementHeight(IN CONST String &elementId, IN INT32 value);
public:
STATIC VOID Initialize();
STATIC VOID Terminate();
@ -42,5 +57,9 @@ namespace ia::iae
STATIC VOID OnSDLEvent(IN PVOID event);
STATIC VOID OnScreenResize(IN INT32 newWidth, IN INT32 newHeight);
private:
STATIC INT64 s_numericVariables[MAX_VARIABLE_COUNT];
STATIC std::string s_stringVariables[MAX_VARIABLE_COUNT];
};
} // namespace ia::iae