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

2
.vscode/launch.json vendored
View File

@ -8,7 +8,7 @@
"name": "(Windows) Launch", "name": "(Windows) Launch",
"type": "cppvsdbg", "type": "cppvsdbg",
"request": "launch", "request": "launch",
"program": "${workspaceFolder}/build/bin/Debug/IAERuntime.exe", "program": "${workspaceFolder}/build/bin/Debug/Editor.exe",
"args": [], "args": [],
"stopAtEntry": false, "stopAtEntry": false,
"cwd": "${workspaceFolder}/Samples/SpaceInvaders", "cwd": "${workspaceFolder}/Samples/SpaceInvaders",

71
.vscode/settings.json vendored
View File

@ -21,6 +21,75 @@
"array": "cpp", "array": "cpp",
"ranges": "cpp", "ranges": "cpp",
"span": "cpp", "span": "cpp",
"vector": "cpp" "vector": "cpp",
"xiosbase": "cpp",
"thread": "cpp",
"algorithm": "cpp",
"atomic": "cpp",
"bit": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"charconv": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"coroutine": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"deque": "cpp",
"exception": "cpp",
"forward_list": "cpp",
"fstream": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"map": "cpp",
"memory": "cpp",
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
"ostream": "cpp",
"queue": "cpp",
"ratio": "cpp",
"set": "cpp",
"shared_mutex": "cpp",
"source_location": "cpp",
"sstream": "cpp",
"stack": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"string": "cpp",
"tuple": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"utility": "cpp",
"valarray": "cpp",
"variant": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xlocbuf": "cpp",
"xlocmes": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xstddef": "cpp",
"xtree": "cpp"
} }
} }

View File

@ -0,0 +1,9 @@
set(SRC_FILES
"Src/Imp/CPP/Main.cpp"
)
add_executable(Editor ${SRC_FILES})
target_include_directories(Editor PRIVATE "Src/Imp/HPP")
target_link_libraries(Editor PUBLIC IAEngine)

View File

View File

@ -0,0 +1,93 @@
// 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/EngineLibraryInterface.hpp>
C_DECL(GameRequestedConfig GetConfigRequest())
{
return {1280, 720};
}
C_DECL(VOID OnInitialize())
{
}
C_DECL(VOID OnTerminate())
{
}
C_DECL(VOID OnDebugDraw())
{
}
C_DECL(VOID OnFixedUpdate())
{
}
C_DECL(VOID OnUpdate(IN FLOAT32 deltaTime))
{
}
C_DECL(VOID OnResize(IN INT32 newWidth, IN INT32 newHeight))
{
}
C_DECL(PCCHAR GetName())
{
return "IAEngine Editor";
}
C_DECL(UINT64 GetVersion())
{
return IA_MAKE_VERSION(1, 0, 0);
}
C_DECL(PCCHAR GetPackageName())
{
return "com.iasoft.iaengine.editor";
}
C_DECL(PCCHAR GetDeveloperName())
{
return "IASoft (PVT) LTD";
}
C_DECL(PCCHAR GetPublisherName())
{
return "IASoft (PVT) LTD";
}
int main(int argc, char* argv[])
{
GameFunctionTable functionTable{};
functionTable.GetConfigRequest = GetConfigRequest;
functionTable.GetDeveloperName = GetDeveloperName;
functionTable.GetName = GetName;
functionTable.GetPackageName = GetPackageName;
functionTable.GetPublisherName = GetPublisherName;
functionTable.GetVersion = GetVersion;
functionTable.OnDebugDraw = OnDebugDraw;
functionTable.OnFixedUpdate = OnFixedUpdate;
functionTable.OnInitialize = OnInitialize;
functionTable.OnResize = OnResize;
functionTable.OnTerminate = OnTerminate;
functionTable.OnUpdate = OnUpdate;
IAEngine_Run(functionTable);
return 0;
}

View File

View File

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

View File

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

View File

@ -15,6 +15,7 @@
// 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 <IAEngine/Engine.hpp> #include <IAEngine/Engine.hpp>
#include <IAEngine/UI.hpp>
#include <Renderer/Renderer.hpp> #include <Renderer/Renderer.hpp>
#include <IACore/File.hpp> #include <IACore/File.hpp>
@ -26,6 +27,7 @@ EXTERN GameFunctionTable g_gameFunctions;
namespace ia::iae namespace ia::iae
{ {
EXTERN SDL_Window *g_windowHandle; EXTERN SDL_Window *g_windowHandle;
SIZE_T g_resourceNameCounter = 1;
BOOL Engine::IsDebugMode() BOOL Engine::IsDebugMode()
{ {
@ -38,8 +40,10 @@ namespace ia::iae
VOID Engine::ResizeDisplay(IN INT32 newWidth, IN INT32 newHeight) VOID Engine::ResizeDisplay(IN INT32 newWidth, IN INT32 newHeight)
{ {
Renderer::WaitForGPUIdle();
SDL_SetWindowSize(g_windowHandle, newWidth, newHeight); SDL_SetWindowSize(g_windowHandle, newWidth, newHeight);
Renderer::OnScreenResize(newWidth, newHeight); Renderer::OnScreenResize(newWidth, newHeight);
UI::OnScreenResize(newWidth, newHeight);
g_gameFunctions.OnResize(newWidth, newHeight); g_gameFunctions.OnResize(newWidth, newHeight);
} }
@ -62,4 +66,14 @@ namespace ia::iae
const auto data = File::ReadToString(path.c_str()); const auto data = File::ReadToString(path.c_str());
return Scene::Create(data); 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 } // namespace ia::iae

View File

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

View File

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

View File

@ -19,6 +19,7 @@
#include <Renderer/EmbeddedShader.hpp> #include <Renderer/EmbeddedShader.hpp>
#include <Renderer/Renderer.hpp> #include <Renderer/Renderer.hpp>
#include <ResourceManager.hpp>
#include <WorldManager.hpp> #include <WorldManager.hpp>
#include <backends/imgui_impl_sdl3.h> #include <backends/imgui_impl_sdl3.h>
@ -231,6 +232,15 @@ namespace ia::iae
if (s_state.ActiveCamera) if (s_state.ActiveCamera)
s_state.ActiveCamera->SetViewport(newWidth, newHeight); 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() SDL_GPUTextureFormat Renderer::GetRenderTargetFormat()
@ -266,7 +276,7 @@ namespace ia::iae
INT32 FlippedH{false}; INT32 FlippedH{false};
INT32 FlippedV{false}; INT32 FlippedV{false};
Vec2 TextureOffset{0.0f, 0.0f}; 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{}; } s_fragmentUniform{};
#pragma pack(pop) #pragma pack(pop)
@ -289,6 +299,11 @@ namespace ia::iae
SDL_BindGPUIndexBuffer(s_state.ActiveRenderPass, &bufferBindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT); SDL_BindGPUIndexBuffer(s_state.ActiveRenderPass, &bufferBindings[1], SDL_GPU_INDEXELEMENTSIZE_32BIT);
SDL_DrawGPUIndexedPrimitives(s_state.ActiveRenderPass, handle->IndexCount, 1, 0, 0, 0); SDL_DrawGPUIndexedPrimitives(s_state.ActiveRenderPass, handle->IndexCount, 1, 0, 0, 0);
} }
VOID Renderer::WaitForGPUIdle()
{
SDL_WaitForGPUIdle(s_gpuDevice);
}
} // namespace ia::iae } // namespace ia::iae
namespace ia::iae namespace ia::iae
@ -352,7 +367,7 @@ namespace ia::iae
VOID Engine::SetRenderState_Texture(IN Handle image) 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, 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) if (Renderer::s_state.YSortingEnabled)
sortIndex += static_cast<INT16>(position.y); sortIndex += static_cast<INT16>(position.y);
position *= Renderer::s_state.SceneScaleFactor;
scale *= Renderer::s_state.SceneScaleFactor;
Renderer::s_state.ModelMatrix = Renderer::s_state.ModelMatrix =
glm::translate(glm::mat4(1.0f), glm::vec3{position.x, position.y, glm::translate(glm::mat4(1.0f), glm::vec3{position.x, position.y,
static_cast<FLOAT32>((layer << 13) | (sortIndex & 0x1FFF))}); 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 <ResourceManager.hpp>
#include <AudioManager.hpp> #include <AudioManager.hpp>
#include <Renderer/Renderer.hpp>
#include <Renderer/GPUResourceManager.hpp> #include <Renderer/GPUResourceManager.hpp>
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
@ -27,18 +28,26 @@
namespace ia::iae namespace ia::iae
{ {
Vector<SDL_GPUTexture*> ResourceManager::s_imageHandles;
Map<String, Handle> ResourceManager::s_images; Map<String, Handle> ResourceManager::s_images;
Map<String, Handle> ResourceManager::s_sounds; Map<String, Handle> ResourceManager::s_sounds;
Map<Handle, UINT64> ResourceManager::s_imageExtents; Map<Handle, UINT64> ResourceManager::s_imageExtents;
Map<Handle, UINT64> ResourceManager::s_nonScaledImageExtents;
VOID ResourceManager::Initialize() 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() VOID ResourceManager::Terminate()
{ {
for (const auto &t : s_images) for (const auto &t : s_images)
GPUResourceManager::DestroyTexture((SDL_GPUTexture *) t->Value); GPUResourceManager::DestroyTexture(s_imageHandles[t->Value]);
for (const auto &t : s_sounds) for (const auto &t : s_sounds)
AudioManager::DestoryAudio(t->Value); 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) 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); 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_images[name] = handle;
s_imageExtents[handle] = (((UINT64) width) << 32) | height;
s_nonScaledImageExtents[handle] = s_imageExtents[handle];
return handle; return handle;
} }
@ -102,7 +114,8 @@ namespace ia::iae
VOID ResourceManager::DestroyImage(IN Handle image) 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) VOID ResourceManager::DestroySound(IN Handle sound)
@ -120,22 +133,37 @@ namespace ia::iae
{ {
const auto currentExtent = GetImageExtent(image); const auto currentExtent = GetImageExtent(image);
const auto pixelData = const auto pixelData =
GPUResourceManager::GetTexturePixelData((SDL_GPUTexture *) image, currentExtent.x, currentExtent.y); GPUResourceManager::GetTexturePixelData(s_imageHandles[image], currentExtent.x, currentExtent.y);
GPUResourceManager::DestroyTexture((SDL_GPUTexture*)image);
const auto newPixelData = const auto newPixelData =
stbir_resize_uint8_linear(pixelData.data(), currentExtent.x, currentExtent.y, currentExtent.x * 4, nullptr, stbir_resize_uint8_linear(pixelData.data(), currentExtent.x, currentExtent.y, currentExtent.x * 4, nullptr,
newWidth, newHeight, newWidth * 4, stbir_pixel_layout::STBIR_RGBA); 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); free(newPixelData);
return result; return image;
} }
Handle ResourceManager::CombineImages(IN CONST Vector<Handle> &images, IN INT32 unitWidth, IN INT32 unitHeight, Handle ResourceManager::CombineImages(IN CONST Vector<Handle> &images, IN INT32 unitWidth, IN INT32 unitHeight,
IN INT32 unitCountX, IN INT32 unitCountY) 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); 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
namespace ia::iae namespace ia::iae
@ -185,6 +213,11 @@ namespace ia::iae
return ResourceManager::ResizeImage(image, newWidth, newHeight); 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, Handle Engine::CombineImages(IN CONST Vector<Handle> &images, IN INT32 unitWidth, IN INT32 unitHeight,
IN INT32 unitCountX, IN INT32 unitCountY) IN INT32 unitCountX, IN INT32 unitCountY)
{ {

View File

@ -21,13 +21,16 @@ namespace ia::iae
{ {
RefPtr<Scene> Scene::Create() 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) RefPtr<Scene> Scene::Create(IN CONST String &sceneXML)
{ {
const auto scene = MakeRefPtr<Scene>(); const auto scene = MakeRefPtr<Scene>();
scene->Extent() = Engine::GetDisplayExtent();
return scene; 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_Rect Scissor{0, 0, 0, 0};
SDL_GPUTexture* ActiveTexture{nullptr}; SDL_GPUTexture* ActiveTexture{nullptr};
SDL_GPUViewport ActiveViewport{}; SDL_GPUViewport ActiveViewport{};
Vec2 SceneScaleFactor{1.0f, 1.0f};
Mat4 ModelMatrix{1.0f}; Mat4 ModelMatrix{1.0f};
@ -63,6 +64,8 @@ namespace ia::iae
STATIC VOID BeginFrame(); STATIC VOID BeginFrame();
STATIC VOID EndFrame(); STATIC VOID EndFrame();
STATIC VOID WaitForGPUIdle();
STATIC VOID OnScreenResize(IN INT32 newWidth, IN INT32 newHeight); STATIC VOID OnScreenResize(IN INT32 newWidth, IN INT32 newHeight);
public: public:

View File

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

View File

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

View File

@ -21,6 +21,12 @@
using namespace ia; using namespace ia;
using namespace ia::iae; using namespace ia::iae;
struct GameRequestedConfig
{
INT32 ScreenWidth{};
INT32 ScreenHeight{};
};
#if defined(__BUILDING_IAENGINE_GAME) && (__BUILDING_IAENGINE_GAME) #if defined(__BUILDING_IAENGINE_GAME) && (__BUILDING_IAENGINE_GAME)
#define GAME_LOG_TAG "[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_WARN(...) ia::Logger::Warn(IAE_LOG_TAG, __VA_ARGS__)
#define GAME_LOG_ERROR(...) ia::Logger::Error(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_OnInitialize());
C_DECL(IA_DLL_EXPORT VOID Game_OnTerminate()); C_DECL(IA_DLL_EXPORT VOID Game_OnTerminate());
C_DECL(IA_DLL_EXPORT VOID Game_OnDebugDraw()); C_DECL(IA_DLL_EXPORT VOID Game_OnDebugDraw());
@ -44,6 +51,8 @@ using namespace ia::iae;
struct GameFunctionTable struct GameFunctionTable
{ {
GameRequestedConfig(*GetConfigRequest)(){nullptr};
VOID (*OnInitialize)() {nullptr}; VOID (*OnInitialize)() {nullptr};
VOID (*OnTerminate)() {nullptr}; VOID (*OnTerminate)() {nullptr};
VOID (*OnDebugDraw)() {nullptr}; VOID (*OnDebugDraw)() {nullptr};

View File

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

View File

@ -20,5 +20,21 @@
namespace ia::iae 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);
};
} }

View File

@ -24,6 +24,7 @@ int main(int argc, char* argv[])
gameFunctionTable.OnResize = gameFunctionTable.OnResize =
(VOID (*)(IN INT32 newWidth, IN INT32 newHeight)) GetProcAddress(gameLib, "Game_OnResize"); (VOID (*)(IN INT32 newWidth, IN INT32 newHeight)) GetProcAddress(gameLib, "Game_OnResize");
gameFunctionTable.GetConfigRequest = (GameRequestedConfig (*)()) GetProcAddress(gameLib, "Game_GetConfigRequest");
gameFunctionTable.GetName = (PCCHAR (*)()) GetProcAddress(gameLib, "Game_GetName"); gameFunctionTable.GetName = (PCCHAR (*)()) GetProcAddress(gameLib, "Game_GetName");
gameFunctionTable.GetVersion = (UINT64 (*)()) GetProcAddress(gameLib, "Game_GetVersion"); gameFunctionTable.GetVersion = (UINT64 (*)()) GetProcAddress(gameLib, "Game_GetVersion");
gameFunctionTable.GetPackageName = (PCCHAR (*)()) GetProcAddress(gameLib, "Game_GetPackageName"); gameFunctionTable.GetPackageName = (PCCHAR (*)()) GetProcAddress(gameLib, "Game_GetPackageName");

View File

@ -19,24 +19,30 @@
RefPtr<Node2D> backgroundNode; RefPtr<Node2D> backgroundNode;
RefPtr<CameraNode> mainCamera; RefPtr<CameraNode> mainCamera;
TextureComponent *title;
C_DECL(IA_DLL_EXPORT GameRequestedConfig Game_GetConfigRequest())
{
return {600, 600};
}
C_DECL(IA_DLL_EXPORT VOID Game_OnInitialize()) C_DECL(IA_DLL_EXPORT VOID Game_OnInitialize())
{ {
Engine::ResizeDisplay(600, 600);
const auto displayExtent = Engine::GetDisplayExtent();
Engine::CreateImageFromFile("Background", "Resources/Sprites/bg.png", displayExtent.x, displayExtent.y);
Engine::CreateImageFromFile("Stars-A", "Resources/Sprites/Stars-A.png", displayExtent.x, displayExtent.y);
Engine::CreateImageFromFile("Stars-B", "Resources/Sprites/Stars-B.png", displayExtent.x, displayExtent.y);
mainCamera = MakeRefPtr<CameraNode>("MainCamera"); mainCamera = MakeRefPtr<CameraNode>("MainCamera");
Engine::SetActiveCamera(mainCamera->GetCameraComponent()); Engine::SetActiveCamera(mainCamera->GetCameraComponent());
backgroundNode = MakeRefPtr<Node2D>("BG"); Engine::CreateImageFromFile("Background", "Resources/Sprites/bg.png");
backgroundNode->AddComponent<TextureComponent>()->SetTexture(Engine::GetImage("Stars-A")); Engine::CreateImageFromFile("Stars-A", "Resources/Sprites/Stars-A.png");
//backgroundNode->AddComponent<TextureComponent>()->SetTexture(g_spriteBGStarsA); Engine::CreateImageFromFile("Stars-B", "Resources/Sprites/Stars-B.png");
//backgroundNode->GetTextureComponent()->SetTexture(g_spriteBG); Engine::CreateImageFromFile("Title", "Resources/UI/Title.png");
Engine::AddNodeToActiveScene(backgroundNode);
//UI::SetHTML("<img src=\"Resources/UI/Title.png\" style=\"width: 100%; height: 100%;\"></img>");
//backgroundNode = MakeRefPtr<Node2D>("BG");
//backgroundNode->AddComponent<TextureComponent>()->SetTexture(Engine::GetImage("Background"));
//title = backgroundNode->AddComponent<TextureComponent>();
//title->PositionOffset() = {150, 100};
//title->SetTexture(Engine::GetImage("Title"));
//Engine::AddNodeToActiveScene(backgroundNode);
} }
C_DECL(IA_DLL_EXPORT VOID Game_OnTerminate()) C_DECL(IA_DLL_EXPORT VOID Game_OnTerminate())
@ -57,11 +63,12 @@ C_DECL(IA_DLL_EXPORT VOID Game_OnUpdate(IN FLOAT32 deltaTime))
C_DECL(IA_DLL_EXPORT VOID Game_OnResize(IN INT32 newWidth, IN INT32 newHeight)) C_DECL(IA_DLL_EXPORT VOID Game_OnResize(IN INT32 newWidth, IN INT32 newHeight))
{ {
} }
C_DECL(IA_DLL_EXPORT PCCHAR Game_GetName()) C_DECL(IA_DLL_EXPORT PCCHAR Game_GetName())
{ {
return "Space Invaders"; return "Space Case";
} }
C_DECL(IA_DLL_EXPORT UINT64 Game_GetVersion()) C_DECL(IA_DLL_EXPORT UINT64 Game_GetVersion())
@ -71,7 +78,7 @@ C_DECL(IA_DLL_EXPORT UINT64 Game_GetVersion())
C_DECL(IA_DLL_EXPORT PCCHAR Game_GetPackageName()) C_DECL(IA_DLL_EXPORT PCCHAR Game_GetPackageName())
{ {
return "com.iasoft.iaenginesamples.spaceinvaders"; return "com.iasoft.spacecase";
} }
C_DECL(IA_DLL_EXPORT PCCHAR Game_GetDeveloperName()) C_DECL(IA_DLL_EXPORT PCCHAR Game_GetDeveloperName())