This commit is contained in:
Isuru Samarathunga
2025-10-09 19:28:54 +05:30
parent 1f9d5426b8
commit 96bad30f15
25 changed files with 813 additions and 69 deletions

View File

@ -1,4 +1,5 @@
set(SRC_FILES
"Src/Imp/CPP/UI.cpp"
"Src/Imp/CPP/Time.cpp"
"Src/Imp/CPP/Scene.cpp"
"Src/Imp/CPP/Random.cpp"
@ -14,7 +15,6 @@ set(SRC_FILES
"Src/Imp/CPP/Renderer/DebugDraw.cpp"
"Src/Imp/CPP/Renderer/Pipeline.cpp"
"Src/Imp/CPP/Renderer/Renderer.cpp"
"Src/Imp/CPP/Renderer/UIRenderer.cpp"
"Src/Imp/CPP/Renderer/GPUResourceManager.cpp"
"Src/Imp/CPP/Nodes/Node2D.cpp"

View File

@ -25,14 +25,13 @@ namespace ia::iae
VOID TextureComponent::SetTexture(IN Handle image)
{
const auto t = Engine::GetImageExtent(image);
m_texture = image;
m_textureExtent = {t.x, t.y};
}
VOID TextureComponent::Draw()
{
const auto t = Engine::GetImageExtent(m_texture);
m_textureExtent = {t.x, t.y};
m_drawnSize = m_node->GetScale() * m_textureExtent * m_scaleOffset;
Engine::SetRenderState_Texture(m_texture);

View File

@ -15,6 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <IAEngine/Engine.hpp>
#include <IAEngine/UI.hpp>
#include <Renderer/Renderer.hpp>
#include <IACore/File.hpp>
@ -26,6 +27,7 @@ EXTERN GameFunctionTable g_gameFunctions;
namespace ia::iae
{
EXTERN SDL_Window *g_windowHandle;
SIZE_T g_resourceNameCounter = 1;
BOOL Engine::IsDebugMode()
{
@ -38,8 +40,10 @@ namespace ia::iae
VOID Engine::ResizeDisplay(IN INT32 newWidth, IN INT32 newHeight)
{
Renderer::WaitForGPUIdle();
SDL_SetWindowSize(g_windowHandle, newWidth, newHeight);
Renderer::OnScreenResize(newWidth, newHeight);
UI::OnScreenResize(newWidth, newHeight);
g_gameFunctions.OnResize(newWidth, newHeight);
}
@ -62,4 +66,14 @@ namespace ia::iae
const auto data = File::ReadToString(path.c_str());
return Scene::Create(data);
}
Handle Engine::ResizeImage(IN CONST String &name, IN INT32 newWidth, IN INT32 newHeight)
{
return ResizeImage(GetImage(name), newWidth, newHeight);
}
String Engine::GetUniqueResourceName()
{
return BuildString("__res_", g_resourceNameCounter++);
}
} // namespace ia::iae

View File

@ -38,15 +38,17 @@ namespace ia::iae
VOID __Internal_Engine::Initialize()
{
const auto config = g_gameFunctions.GetConfigRequest();
IAE_LOG_INFO("Booting IAEngine for ", g_gameFunctions.GetName());
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_gameFunctions.GetName(), 800, 600, SDL_WINDOW_RESIZABLE)))
if (!(g_windowHandle = SDL_CreateWindow(g_gameFunctions.GetName(), config.ScreenWidth, config.ScreenHeight, SDL_WINDOW_RESIZABLE)))
THROW_UNKNOWN("Failed to create the SDL window: ", SDL_GetError());
SDL_SetWindowResizable(g_windowHandle, false);
//SDL_SetWindowResizable(g_windowHandle, false);
const auto gameVersion = g_gameFunctions.GetVersion();
SDL_SetAppMetadata(g_gameFunctions.GetName(), BuildString(gameVersion).c_str(),
@ -60,6 +62,7 @@ namespace ia::iae
InputManager::Initialize();
ResourceManager::Initialize();
WorldManager::Initialize();
UI::Initialize();
g_gameFunctions.OnInitialize();
}
@ -68,6 +71,7 @@ namespace ia::iae
{
g_gameFunctions.OnTerminate();
UI::Terminate();
WorldManager::Terminate();
ResourceManager::Terminate();
InputManager::Terminate();
@ -84,6 +88,7 @@ namespace ia::iae
VOID __Internal_Engine::Iterate()
{
UI::Update();
WorldManager::Update();
WorldManager::FixedUpdate();
g_gameFunctions.OnUpdate(Time::GetFrameDeltaTime());
@ -91,6 +96,7 @@ namespace ia::iae
Renderer::BeginFrame();
WorldManager::Draw();
UI::Draw();
Renderer::EndFrame();
}
@ -104,6 +110,7 @@ namespace ia::iae
}
InputManager::OnSDLEvent(event);
EventManager::OnSDLEvent(event);
UI::OnSDLEvent(event);
ImGui_ImplSDL3_ProcessEvent(event);
}
@ -115,6 +122,8 @@ namespace ia::iae
BOOL ValidateGameFunctionTable(IN GameFunctionTable gameFunctionTable)
{
if (!gameFunctionTable.GetConfigRequest)
return false;
if (!gameFunctionTable.OnInitialize)
return false;
if (!gameFunctionTable.OnTerminate)

View File

@ -138,6 +138,7 @@ namespace ia::iae
VOID GPUResourceManager::DestroyTexture(IN SDL_GPUTexture *handle)
{
if(!handle) return;
SDL_ReleaseGPUTexture(Renderer::GetDevice(), handle);
}

View File

@ -19,6 +19,7 @@
#include <Renderer/EmbeddedShader.hpp>
#include <Renderer/Renderer.hpp>
#include <ResourceManager.hpp>
#include <WorldManager.hpp>
#include <backends/imgui_impl_sdl3.h>
@ -231,6 +232,15 @@ namespace ia::iae
if (s_state.ActiveCamera)
s_state.ActiveCamera->SetViewport(newWidth, newHeight);
const auto activeScene = WorldManager::GetActiveScene();
if (activeScene)
{
const auto sceneExtent = activeScene->Extent();
s_state.SceneScaleFactor = {(FLOAT32) newWidth / (FLOAT32) sceneExtent.x,
(FLOAT32) newHeight / (FLOAT32) sceneExtent.y};
IAE_LOG_INFO("Updated Scene Scale Factor: (", s_state.SceneScaleFactor.x, ", ", s_state.SceneScaleFactor.y, ")");
}
}
SDL_GPUTextureFormat Renderer::GetRenderTargetFormat()
@ -266,7 +276,7 @@ namespace ia::iae
INT32 FlippedH{false};
INT32 FlippedV{false};
Vec2 TextureOffset{0.0f, 0.0f};
glm::vec4 ColorOverlay{1.0f, 1.0f, 1.0f, 1.0f};
Vec4 ColorOverlay{1.0f, 1.0f, 1.0f, 1.0f};
} s_fragmentUniform{};
#pragma pack(pop)
@ -289,6 +299,11 @@ namespace ia::iae
SDL_BindGPUIndexBuffer(s_state.ActiveRenderPass, &bufferBindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT);
SDL_DrawGPUIndexedPrimitives(s_state.ActiveRenderPass, handle->IndexCount, 1, 0, 0, 0);
}
VOID Renderer::WaitForGPUIdle()
{
SDL_WaitForGPUIdle(s_gpuDevice);
}
} // namespace ia::iae
namespace ia::iae
@ -352,7 +367,7 @@ namespace ia::iae
VOID Engine::SetRenderState_Texture(IN Handle image)
{
Renderer::s_state.ActiveTexture = (SDL_GPUTexture *) image;
Renderer::s_state.ActiveTexture = ResourceManager::GetTextureFromImage(image);
}
VOID Engine::SetRenderState_Transform(IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation, IN UINT8 layer,
@ -363,6 +378,9 @@ namespace ia::iae
if (Renderer::s_state.YSortingEnabled)
sortIndex += static_cast<INT16>(position.y);
position *= Renderer::s_state.SceneScaleFactor;
scale *= Renderer::s_state.SceneScaleFactor;
Renderer::s_state.ModelMatrix =
glm::translate(glm::mat4(1.0f), glm::vec3{position.x, position.y,
static_cast<FLOAT32>((layer << 13) | (sortIndex & 0x1FFF))});

View File

@ -1,24 +0,0 @@
// 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 <SDL3/SDL.h>
namespace ia::iae
{
}

View File

@ -18,6 +18,7 @@
#include <ResourceManager.hpp>
#include <AudioManager.hpp>
#include <Renderer/Renderer.hpp>
#include <Renderer/GPUResourceManager.hpp>
#define STB_IMAGE_IMPLEMENTATION
@ -27,18 +28,26 @@
namespace ia::iae
{
Vector<SDL_GPUTexture*> ResourceManager::s_imageHandles;
Map<String, Handle> ResourceManager::s_images;
Map<String, Handle> ResourceManager::s_sounds;
Map<Handle, UINT64> ResourceManager::s_imageExtents;
Map<Handle, UINT64> ResourceManager::s_nonScaledImageExtents;
VOID ResourceManager::Initialize()
{
{ // Set Texture Handle 0 to a pure white image
const auto data = new UINT8[100*100*4];
ia_memset(data, 0xFF, 100* 100* 4);
CreateImage(Engine::GetUniqueResourceName(), data, 100, 100);
delete[] data;
}
}
VOID ResourceManager::Terminate()
{
for (const auto &t : s_images)
GPUResourceManager::DestroyTexture((SDL_GPUTexture *) t->Value);
GPUResourceManager::DestroyTexture(s_imageHandles[t->Value]);
for (const auto &t : s_sounds)
AudioManager::DestoryAudio(t->Value);
}
@ -54,10 +63,13 @@ namespace ia::iae
Handle ResourceManager::CreateImage(IN CONST String &name, IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height)
{
const auto handle = (Handle) GPUResourceManager::CreateTexture(SDL_GPU_TEXTUREUSAGE_SAMPLER, width, height,
const auto texture = GPUResourceManager::CreateTexture(SDL_GPU_TEXTUREUSAGE_SAMPLER, width, height,
rgbaData, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM);
s_imageExtents[handle] = (((UINT64) width) << 32) | height;
s_imageHandles.pushBack(texture);
Handle handle = s_imageHandles.size() - 1;
s_images[name] = handle;
s_imageExtents[handle] = (((UINT64) width) << 32) | height;
s_nonScaledImageExtents[handle] = s_imageExtents[handle];
return handle;
}
@ -102,7 +114,8 @@ namespace ia::iae
VOID ResourceManager::DestroyImage(IN Handle image)
{
GPUResourceManager::DestroyTexture((SDL_GPUTexture *) image);
GPUResourceManager::DestroyTexture(s_imageHandles[image]);
s_imageHandles[image] = nullptr;
}
VOID ResourceManager::DestroySound(IN Handle sound)
@ -120,22 +133,37 @@ namespace ia::iae
{
const auto currentExtent = GetImageExtent(image);
const auto pixelData =
GPUResourceManager::GetTexturePixelData((SDL_GPUTexture *) image, currentExtent.x, currentExtent.y);
GPUResourceManager::DestroyTexture((SDL_GPUTexture*)image);
GPUResourceManager::GetTexturePixelData(s_imageHandles[image], currentExtent.x, currentExtent.y);
const auto newPixelData =
stbir_resize_uint8_linear(pixelData.data(), currentExtent.x, currentExtent.y, currentExtent.x * 4, nullptr,
newWidth, newHeight, newWidth * 4, stbir_pixel_layout::STBIR_RGBA);
const auto result = CreateImage(GetImageName(image), newPixelData, newWidth, newHeight);
const auto texture = GPUResourceManager::CreateTexture(SDL_GPU_TEXTUREUSAGE_SAMPLER, newWidth, newHeight,
newPixelData, SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM);
s_imageExtents[image] = (((UINT64) newWidth) << 32) | newHeight;
GPUResourceManager::DestroyTexture(s_imageHandles[image]);
s_imageHandles[image] = texture;
free(newPixelData);
return result;
return image;
}
Handle ResourceManager::CombineImages(IN CONST Vector<Handle> &images, IN INT32 unitWidth, IN INT32 unitHeight,
IN INT32 unitCountX, IN INT32 unitCountY)
{
return (Handle) GPUResourceManager::CombineTextures((SDL_GPUTexture **) images.data(), unitWidth, unitHeight,
Vector<SDL_GPUTexture*> textures;
for(const auto& t: images)
textures.pushBack(s_imageHandles[t]);
return (Handle) GPUResourceManager::CombineTextures(textures.data(), unitWidth, unitHeight,
unitCountX, unitCountY);
}
VOID ResourceManager::RescaleAllImages(IN FLOAT32 factorX, IN FLOAT32 factorY)
{
for(auto& t: s_images)
{
const auto p = s_nonScaledImageExtents[t->Value];
t->Value = ResizeImage(t->Value, ((INT32) (p >> 32)) * factorX, ((INT32) p) * factorY);
}
}
} // namespace ia::iae
namespace ia::iae
@ -185,6 +213,11 @@ namespace ia::iae
return ResourceManager::ResizeImage(image, newWidth, newHeight);
}
VOID Engine::RescaleAllImages(IN FLOAT32 factorX, IN FLOAT32 factorY)
{
ResourceManager::RescaleAllImages(factorX, factorY);
}
Handle Engine::CombineImages(IN CONST Vector<Handle> &images, IN INT32 unitWidth, IN INT32 unitHeight,
IN INT32 unitCountX, IN INT32 unitCountY)
{

View File

@ -21,13 +21,16 @@ namespace ia::iae
{
RefPtr<Scene> Scene::Create()
{
return MakeRefPtr<Scene>();
const auto scene = MakeRefPtr<Scene>();
scene->Extent() = Engine::GetDisplayExtent();
return scene;
}
RefPtr<Scene> Scene::Create(IN CONST String &sceneXML)
{
const auto scene = MakeRefPtr<Scene>();
scene->Extent() = Engine::GetDisplayExtent();
return scene;
}

465
Engine/Src/Imp/CPP/UI.cpp Normal file
View File

@ -0,0 +1,465 @@
// 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/UI.hpp>
#include <Renderer/Renderer.hpp>
#include <SDL3/SDL.h>
#include <RmlUi/Core.h>
#include <RmlUi/Debugger.h>
namespace ia::iae
{
Rml::Context *g_context{};
BOOL g_debuggerEnabled{false};
Rml::ElementDocument *g_document{};
class RmlUIRenderInterface : public Rml::RenderInterface
{
public:
Rml::CompiledGeometryHandle CompileGeometry(Rml::Span<const Rml::Vertex> vertices,
Rml::Span<const int> indices);
void RenderGeometry(Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation,
Rml::TextureHandle texture);
void ReleaseGeometry(Rml::CompiledGeometryHandle geometry);
Rml::TextureHandle LoadTexture(Rml::Vector2i &texture_dimensions, const Rml::String &source);
Rml::TextureHandle GenerateTexture(Rml::Span<const Rml::byte> source, Rml::Vector2i source_dimensions);
void ReleaseTexture(Rml::TextureHandle texture);
void EnableScissorRegion(bool enable);
void SetScissorRegion(Rml::Rectanglei region);
} g_rmlUIRenderInterface{};
class RmlEventListener : public Rml::EventListener
{
public:
RmlEventListener()
{
}
VOID ProcessEvent(IN Rml::Event &event)
{
}
} g_eventListener{};
/* Taken from https://github.com/mikke89/RmlUi/blob/master/Backends/RmlUi_Platform_SDL.cpp */
INT32 GetKeyModifierState()
{
SDL_Keymod sdl_mods = SDL_GetModState();
INT32 keymods = 0;
if (sdl_mods & SDL_KMOD_CTRL)
keymods |= Rml::Input::KM_CTRL;
if (sdl_mods & SDL_KMOD_SHIFT)
keymods |= Rml::Input::KM_SHIFT;
if (sdl_mods & SDL_KMOD_ALT)
keymods |= Rml::Input::KM_ALT;
if (sdl_mods & SDL_KMOD_NUM)
keymods |= Rml::Input::KM_NUMLOCK;
if (sdl_mods & SDL_KMOD_CAPS)
keymods |= Rml::Input::KM_CAPSLOCK;
return keymods;
}
/* Taken from https://github.com/mikke89/RmlUi/blob/master/Backends/RmlUi_Platform_SDL.cpp */
INT32 SDLMouseButtonToRml(IN INT32 button)
{
switch (button)
{
case SDL_BUTTON_LEFT:
return 0;
case SDL_BUTTON_RIGHT:
return 1;
case SDL_BUTTON_MIDDLE:
return 2;
default:
break;
}
return 3;
}
/* Taken from https://github.com/mikke89/RmlUi/blob/master/Backends/RmlUi_Platform_SDL.cpp */
Rml::Input::KeyIdentifier SDLKeyToRml(int sdlkey)
{
switch (sdlkey)
{
case SDLK_UNKNOWN:
return Rml::Input::KI_UNKNOWN;
case SDLK_ESCAPE:
return Rml::Input::KI_ESCAPE;
case SDLK_SPACE:
return Rml::Input::KI_SPACE;
case SDLK_0:
return Rml::Input::KI_0;
case SDLK_1:
return Rml::Input::KI_1;
case SDLK_2:
return Rml::Input::KI_2;
case SDLK_3:
return Rml::Input::KI_3;
case SDLK_4:
return Rml::Input::KI_4;
case SDLK_5:
return Rml::Input::KI_5;
case SDLK_6:
return Rml::Input::KI_6;
case SDLK_7:
return Rml::Input::KI_7;
case SDLK_8:
return Rml::Input::KI_8;
case SDLK_9:
return Rml::Input::KI_9;
case SDLK_A:
return Rml::Input::KI_A;
case SDLK_B:
return Rml::Input::KI_B;
case SDLK_C:
return Rml::Input::KI_C;
case SDLK_D:
return Rml::Input::KI_D;
case SDLK_E:
return Rml::Input::KI_E;
case SDLK_F:
return Rml::Input::KI_F;
case SDLK_G:
return Rml::Input::KI_G;
case SDLK_H:
return Rml::Input::KI_H;
case SDLK_I:
return Rml::Input::KI_I;
case SDLK_J:
return Rml::Input::KI_J;
case SDLK_K:
return Rml::Input::KI_K;
case SDLK_L:
return Rml::Input::KI_L;
case SDLK_M:
return Rml::Input::KI_M;
case SDLK_N:
return Rml::Input::KI_N;
case SDLK_O:
return Rml::Input::KI_O;
case SDLK_P:
return Rml::Input::KI_P;
case SDLK_Q:
return Rml::Input::KI_Q;
case SDLK_R:
return Rml::Input::KI_R;
case SDLK_S:
return Rml::Input::KI_S;
case SDLK_T:
return Rml::Input::KI_T;
case SDLK_U:
return Rml::Input::KI_U;
case SDLK_V:
return Rml::Input::KI_V;
case SDLK_W:
return Rml::Input::KI_W;
case SDLK_X:
return Rml::Input::KI_X;
case SDLK_Y:
return Rml::Input::KI_Y;
case SDLK_Z:
return Rml::Input::KI_Z;
case SDLK_SEMICOLON:
return Rml::Input::KI_OEM_1;
case SDLK_PLUS:
return Rml::Input::KI_OEM_PLUS;
case SDLK_COMMA:
return Rml::Input::KI_OEM_COMMA;
case SDLK_MINUS:
return Rml::Input::KI_OEM_MINUS;
case SDLK_PERIOD:
return Rml::Input::KI_OEM_PERIOD;
case SDLK_SLASH:
return Rml::Input::KI_OEM_2;
case SDLK_GRAVE:
return Rml::Input::KI_OEM_3;
case SDLK_LEFTBRACKET:
return Rml::Input::KI_OEM_4;
case SDLK_BACKSLASH:
return Rml::Input::KI_OEM_5;
case SDLK_RIGHTBRACKET:
return Rml::Input::KI_OEM_6;
case SDLK_DBLAPOSTROPHE:
return Rml::Input::KI_OEM_7;
case SDLK_KP_0:
return Rml::Input::KI_NUMPAD0;
case SDLK_KP_1:
return Rml::Input::KI_NUMPAD1;
case SDLK_KP_2:
return Rml::Input::KI_NUMPAD2;
case SDLK_KP_3:
return Rml::Input::KI_NUMPAD3;
case SDLK_KP_4:
return Rml::Input::KI_NUMPAD4;
case SDLK_KP_5:
return Rml::Input::KI_NUMPAD5;
case SDLK_KP_6:
return Rml::Input::KI_NUMPAD6;
case SDLK_KP_7:
return Rml::Input::KI_NUMPAD7;
case SDLK_KP_8:
return Rml::Input::KI_NUMPAD8;
case SDLK_KP_9:
return Rml::Input::KI_NUMPAD9;
case SDLK_KP_ENTER:
return Rml::Input::KI_NUMPADENTER;
case SDLK_KP_MULTIPLY:
return Rml::Input::KI_MULTIPLY;
case SDLK_KP_PLUS:
return Rml::Input::KI_ADD;
case SDLK_KP_MINUS:
return Rml::Input::KI_SUBTRACT;
case SDLK_KP_PERIOD:
return Rml::Input::KI_DECIMAL;
case SDLK_KP_DIVIDE:
return Rml::Input::KI_DIVIDE;
case SDLK_KP_EQUALS:
return Rml::Input::KI_OEM_NEC_EQUAL;
case SDLK_BACKSPACE:
return Rml::Input::KI_BACK;
case SDLK_TAB:
return Rml::Input::KI_TAB;
case SDLK_CLEAR:
return Rml::Input::KI_CLEAR;
case SDLK_RETURN:
return Rml::Input::KI_RETURN;
case SDLK_PAUSE:
return Rml::Input::KI_PAUSE;
case SDLK_CAPSLOCK:
return Rml::Input::KI_CAPITAL;
case SDLK_PAGEUP:
return Rml::Input::KI_PRIOR;
case SDLK_PAGEDOWN:
return Rml::Input::KI_NEXT;
case SDLK_END:
return Rml::Input::KI_END;
case SDLK_HOME:
return Rml::Input::KI_HOME;
case SDLK_LEFT:
return Rml::Input::KI_LEFT;
case SDLK_UP:
return Rml::Input::KI_UP;
case SDLK_RIGHT:
return Rml::Input::KI_RIGHT;
case SDLK_DOWN:
return Rml::Input::KI_DOWN;
case SDLK_INSERT:
return Rml::Input::KI_INSERT;
case SDLK_DELETE:
return Rml::Input::KI_DELETE;
case SDLK_HELP:
return Rml::Input::KI_HELP;
case SDLK_F1:
return Rml::Input::KI_F1;
case SDLK_F2:
return Rml::Input::KI_F2;
case SDLK_F3:
return Rml::Input::KI_F3;
case SDLK_F4:
return Rml::Input::KI_F4;
case SDLK_F5:
return Rml::Input::KI_F5;
case SDLK_F6:
return Rml::Input::KI_F6;
case SDLK_F7:
return Rml::Input::KI_F7;
case SDLK_F8:
return Rml::Input::KI_F8;
case SDLK_F9:
return Rml::Input::KI_F9;
case SDLK_F10:
return Rml::Input::KI_F10;
case SDLK_F11:
return Rml::Input::KI_F11;
case SDLK_F12:
return Rml::Input::KI_F12;
case SDLK_F13:
return Rml::Input::KI_F13;
case SDLK_F14:
return Rml::Input::KI_F14;
case SDLK_F15:
return Rml::Input::KI_F15;
case SDLK_NUMLOCKCLEAR:
return Rml::Input::KI_NUMLOCK;
case SDLK_SCROLLLOCK:
return Rml::Input::KI_SCROLL;
case SDLK_LSHIFT:
return Rml::Input::KI_LSHIFT;
case SDLK_RSHIFT:
return Rml::Input::KI_RSHIFT;
case SDLK_LCTRL:
return Rml::Input::KI_LCONTROL;
case SDLK_RCTRL:
return Rml::Input::KI_RCONTROL;
case SDLK_LALT:
return Rml::Input::KI_LMENU;
case SDLK_RALT:
return Rml::Input::KI_RMENU;
case SDLK_LGUI:
return Rml::Input::KI_LMETA;
case SDLK_RGUI:
return Rml::Input::KI_RMETA;
default:
break;
}
return Rml::Input::KI_UNKNOWN;
}
} // namespace ia::iae
namespace ia::iae
{
VOID UI::Initialize()
{
Rml::SetRenderInterface(&g_rmlUIRenderInterface);
Rml::Initialise();
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();
}
VOID UI::Terminate()
{
Rml::Shutdown();
}
VOID UI::Update()
{
if (Engine::WasInputKeyPressed(InputKey::F8))
Rml::Debugger::SetVisible(g_debuggerEnabled = !g_debuggerEnabled);
g_context->Update();
}
VOID UI::Draw()
{
g_context->Render();
}
VOID UI::OnSDLEvent(IN PVOID _event)
{
const auto keymods = GetKeyModifierState();
const auto event = (SDL_Event *) _event;
switch (event->type)
{
case SDL_EventType::SDL_EVENT_MOUSE_MOTION:
g_context->ProcessMouseMove(event->motion.x, event->motion.y, keymods);
break;
case SDL_EventType::SDL_EVENT_MOUSE_BUTTON_UP:
g_context->ProcessMouseButtonUp(SDLMouseButtonToRml(event->button.button), keymods);
break;
case SDL_EventType::SDL_EVENT_MOUSE_BUTTON_DOWN:
g_context->ProcessMouseButtonDown(SDLMouseButtonToRml(event->button.button), keymods);
break;
case SDL_EventType::SDL_EVENT_KEY_DOWN:
g_context->ProcessKeyDown(SDLKeyToRml(event->key.key), keymods);
break;
case SDL_EventType::SDL_EVENT_KEY_UP:
g_context->ProcessKeyUp(SDLKeyToRml(event->key.key), keymods);
break;
case SDL_EventType::SDL_EVENT_TEXT_INPUT:
g_context->ProcessTextInput(Rml::String(&event->text.text[0]));
break;
}
}
VOID UI::OnScreenResize(IN INT32 newWidth, IN INT32 newHeight)
{
}
VOID UI::AddFontFromFile(IN CONST String &path)
{
Rml::LoadFontFace(path.c_str());
}
VOID UI::SetHTML(IN CONST String &source)
{
g_document->SetInnerRML(
BuildString("<body style=\"display: block; width: 100%; height: 100%;\">", source, "</body>").c_str());
}
} // namespace ia::iae
namespace ia::iae
{
Rml::CompiledGeometryHandle RmlUIRenderInterface::CompileGeometry(Rml::Span<const Rml::Vertex> vertices,
Rml::Span<const int> indices)
{
Vector<GeometryVertex> _vertices;
Vector<INT32> _indices;
for (const auto &v : vertices)
_vertices.pushBack({Vec2{v.position.x, v.position.y}, Vec2{v.tex_coord.x, v.tex_coord.y},
Vec4{v.colour.red / 255.0f, v.colour.green / 255.0f, v.colour.blue / 255.0f,
v.colour.alpha / 255.0f}});
for (const auto &v : indices)
_indices.pushBack(v);
return (Rml::CompiledGeometryHandle) Engine::CreateGeometry(_vertices, _indices);
}
void RmlUIRenderInterface::RenderGeometry(Rml::CompiledGeometryHandle geometry, Rml::Vector2f translation,
Rml::TextureHandle texture)
{
Engine::SetRenderState_Texture((Handle) texture);
Engine::SetRenderState_FlippedH(false);
Engine::SetRenderState_FlippedV(false);
Engine::SetRenderState_ColorOverlay({255, 255, 255, 255});
Engine::SetRenderState_TextureOffset({0, 0});
Engine::SetRenderState_CameraRelative(false);
Engine::SetRenderState_Transform({translation.x, translation.y}, {1.0f, 1.0f}, 0, 0xFF, 0);
Engine::DrawGeometry((Handle) geometry);
}
void RmlUIRenderInterface::ReleaseGeometry(Rml::CompiledGeometryHandle geometry)
{
Engine::DestroyGeometry((Handle) geometry);
}
Rml::TextureHandle RmlUIRenderInterface::LoadTexture(Rml::Vector2i &texture_dimensions, const Rml::String &source)
{
return Engine::CreateImageFromFile(Engine::GetUniqueResourceName(), source.c_str(), texture_dimensions.x,
texture_dimensions.y);
}
Rml::TextureHandle RmlUIRenderInterface::GenerateTexture(Rml::Span<const Rml::byte> source,
Rml::Vector2i source_dimensions)
{
return Engine::CreateImage(Engine::GetUniqueResourceName(), (PCUINT8) source.data(), source_dimensions.x,
source_dimensions.y);
}
void RmlUIRenderInterface::ReleaseTexture(Rml::TextureHandle texture)
{
Engine::DestroyImage((Handle) texture);
}
void RmlUIRenderInterface::EnableScissorRegion(bool enable)
{
if (!enable)
Engine::SetRenderState_Scissor({});
}
void RmlUIRenderInterface::SetScissorRegion(Rml::Rectanglei region)
{
Engine::SetRenderState_Scissor({region.Left(), region.Top(), region.Right(), region.Bottom()});
}
} // namespace ia::iae

File diff suppressed because one or more lines are too long

View File

@ -45,6 +45,7 @@ namespace ia::iae
SDL_Rect Scissor{0, 0, 0, 0};
SDL_GPUTexture* ActiveTexture{nullptr};
SDL_GPUViewport ActiveViewport{};
Vec2 SceneScaleFactor{1.0f, 1.0f};
Mat4 ModelMatrix{1.0f};
@ -63,6 +64,8 @@ namespace ia::iae
STATIC VOID BeginFrame();
STATIC VOID EndFrame();
STATIC VOID WaitForGPUIdle();
STATIC VOID OnScreenResize(IN INT32 newWidth, IN INT32 newHeight);
public:

View File

@ -35,25 +35,34 @@ namespace ia::iae
STATIC VOID Initialize();
STATIC VOID Terminate();
STATIC Handle CreateImage(IN CONST String& name, IN PCUINT8 encodedData, IN SIZE_T encodedDataSize);
STATIC Handle CreateImage(IN CONST String& name, IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
STATIC Handle CreateSound(IN CONST String& name, IN PCUINT8 encodedData, IN SIZE_T encodedDataSize);
STATIC Handle GetImage(IN CONST String& name);
STATIC Handle GetSound(IN CONST String& name);
STATIC Handle CreateImage(IN CONST String &name, IN PCUINT8 encodedData, IN SIZE_T encodedDataSize);
STATIC Handle CreateImage(IN CONST String &name, IN PCUINT8 rgbaData, IN INT32 width, IN INT32 height);
STATIC Handle CreateSound(IN CONST String &name, IN PCUINT8 encodedData, IN SIZE_T encodedDataSize);
STATIC Handle GetImage(IN CONST String &name);
STATIC Handle GetSound(IN CONST String &name);
STATIC String GetImageName(IN Handle handle);
STATIC String GetSoundName(IN Handle handle);
STATIC VOID DestroyImage(IN Handle image);
STATIC VOID DestroySound(IN Handle sound);
STATIC IVec2 GetImageExtent(IN Handle image);
STATIC VOID RescaleAllImages(IN FLOAT32 factorX, IN FLOAT32 factorY);
STATIC Handle ResizeImage(IN Handle image, IN INT32 newWidth, IN INT32 newHeight);
STATIC Handle CombineImages(IN CONST Vector<Handle> &images, IN INT32 unitWidth, IN INT32 unitHeight,
IN INT32 unitCountX, IN INT32 unitCountY);
public:
STATIC SDL_GPUTexture *GetTextureFromImage(IN Handle image)
{
return s_imageHandles[image];
}
private:
STATIC Vector<SDL_GPUTexture *> s_imageHandles;
STATIC Map<String, Handle> s_images;
STATIC Map<String, Handle> s_sounds;
STATIC Map<Handle, UINT64> s_imageExtents;
STATIC Map<Handle, UINT64> s_nonScaledImageExtents;
};
} // namespace ia::iae

View File

@ -24,6 +24,7 @@
#include <IAEngine/Components/CameraComponent.hpp>
#include <IAEngine/Components/SoundEmitterComponent.hpp>
#include <IAEngine/UI.hpp>
#include <IAEngine/Scene.hpp>
namespace ia::iae
@ -82,6 +83,8 @@ namespace ia::iae
STATIC IAE_DLL_API VOID DestroySound(IN Handle sound);
STATIC IAE_DLL_API IVec2 GetImageExtent(IN Handle image);
STATIC IAE_DLL_API Handle ResizeImage(IN Handle image, IN INT32 newWidth, IN INT32 newHeight);
STATIC IAE_DLL_API Handle ResizeImage(IN CONST String& name, IN INT32 newWidth, IN INT32 newHeight);
STATIC IAE_DLL_API VOID RescaleAllImages(IN FLOAT32 factorX, IN FLOAT32 factorY);
STATIC IAE_DLL_API Handle CombineImages(IN CONST Vector<Handle> &images, IN INT32 unitWidth,
IN INT32 unitHeight, IN INT32 unitCountX, IN INT32 unitCountY);
@ -127,5 +130,6 @@ namespace ia::iae
// Engine Functions
STATIC IAE_DLL_API BOOL IsDebugMode();
STATIC IAE_DLL_API String GetUniqueResourceName();
};
} // namespace ia::iae

View File

@ -21,6 +21,12 @@
using namespace ia;
using namespace ia::iae;
struct GameRequestedConfig
{
INT32 ScreenWidth{};
INT32 ScreenHeight{};
};
#if defined(__BUILDING_IAENGINE_GAME) && (__BUILDING_IAENGINE_GAME)
#define GAME_LOG_TAG "[GAME]: "
@ -28,6 +34,7 @@ using namespace ia::iae;
#define GAME_LOG_WARN(...) ia::Logger::Warn(IAE_LOG_TAG, __VA_ARGS__)
#define GAME_LOG_ERROR(...) ia::Logger::Error(IAE_LOG_TAG, __VA_ARGS__)
C_DECL(IA_DLL_EXPORT GameRequestedConfig Game_GetConfigRequest());
C_DECL(IA_DLL_EXPORT VOID Game_OnInitialize());
C_DECL(IA_DLL_EXPORT VOID Game_OnTerminate());
C_DECL(IA_DLL_EXPORT VOID Game_OnDebugDraw());
@ -44,6 +51,8 @@ using namespace ia::iae;
struct GameFunctionTable
{
GameRequestedConfig(*GetConfigRequest)(){nullptr};
VOID (*OnInitialize)() {nullptr};
VOID (*OnTerminate)() {nullptr};
VOID (*OnDebugDraw)() {nullptr};

View File

@ -32,12 +32,18 @@ namespace ia::iae
IAE_DLL_API VOID RemoveNode(IN CONST String &name);
public:
IVec2& Extent()
{
return m_extent;
}
Color &BackgroundColor()
{
return m_backgroundColor;
}
private:
IVec2 m_extent{100, 100};
Color m_backgroundColor{0, 0, 0, 255};
Map<String, RefPtr<INode>> m_nodes;

View File

@ -20,5 +20,21 @@
namespace ia::iae
{
class UI
{
public:
STATIC IAE_DLL_API VOID AddFontFromFile(IN CONST String& path);
STATIC IAE_DLL_API VOID SetHTML(IN CONST String& source);
public:
STATIC VOID Initialize();
STATIC VOID Terminate();
STATIC VOID Update();
STATIC VOID Draw();
STATIC VOID OnSDLEvent(IN PVOID event);
STATIC VOID OnScreenResize(IN INT32 newWidth, IN INT32 newHeight);
};
}