Files
IAEngine/Src/Editor/imp/cpp/Editor.cpp
Isuru Samarathunga 9d6f525b81 Fixes
2025-11-11 09:24:14 +05:30

189 lines
7.0 KiB
C++

// 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 <Editor.hpp>
#include <IAEngine/IAEngine.hpp>
#include <RenderCore/RenderCore.hpp>
#include <SDL3/SDL.h>
#include <Vendor/imgui/backends/imgui_impl_sdl3.h>
#include <Vendor/imgui/backends/imgui_impl_sdlgpu3.h>
#include <UI/UI.hpp>
#include <UI/View/Asset.hpp>
#include <LogoIcon.hpp>
namespace ia::iae
{
EXTERN UINT8 DATA_TTF_FONTAWESOME7FREESOLID900[];
EXTERN SIZE_T SIZE_TTF_FONTAWESOME7FREESOLID900;
EXTERN SDL_Window *g_windowHandle;
Editor Editor::s_instance{};
ImDrawData *g_imDrawData{};
IVec2 g_windowExtent{800, 600};
VOID Editor::LoadProject(IN CONST String &directory)
{
m_activeProject = Project::Load(directory);
}
VOID Editor::OpenAsset(IN Path path)
{
UI::GetAssetView()->Open(path);
UI::FocusAssetView();
}
INT32 Editor::Run(IN INT32 argc, IN PCCHAR argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD))
THROW_UNKNOWN("Failed to intialize SDL: ", SDL_GetError());
if (!(g_windowHandle = SDL_CreateWindow("IAEngine", g_windowExtent.x, g_windowExtent.y, SDL_WINDOW_RESIZABLE)))
THROW_UNKNOWN("Failed to create the SDL window: ", SDL_GetError());
LoadProject(".");
SDL_SetWindowPosition(g_windowHandle, m_activeProject->WindowPosition().x, m_activeProject->WindowPosition().y);
SDL_MaximizeWindow(g_windowHandle);
SDL_GetWindowSizeInPixels(g_windowHandle, &g_windowExtent.x, &g_windowExtent.y);
SDL_Surface *iconSurface = SDL_CreateSurface(LOGO_ICON_WIDTH, LOGO_ICON_HEIGHT, SDL_PIXELFORMAT_RGBA32);
if (iconSurface)
{
for (UINT32 i = 0; i < LOGO_ICON_WIDTH * LOGO_ICON_HEIGHT * 4; i += 4)
{
STATIC UINT32 p{0xFFFFFFFF};
const auto pixel = ((PUINT8) &p);
const auto pixels = (PUINT8) iconSurface->pixels;
LOGO_ICON_GET_PIXEL(LOGO_ICON_DATA, pixel);
pixels[i + 0] = pixel[0];
pixels[i + 1] = pixel[1];
pixels[i + 2] = pixel[2];
pixels[i + 3] = 0xFF;
}
SDL_SetWindowIcon(g_windowHandle, iconSurface);
SDL_DestroySurface(iconSurface);
}
SDL_SetWindowTitle(g_windowHandle, BuildString("IAEngine - ", m_activeProject->Name()).c_str());
RDC::Initialize(g_windowExtent, g_windowHandle, true);
const auto mainScale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
IMGUI_CHECKVERSION();
ImGui::CreateContext();
auto &imGUIIO = ImGui::GetIO();
imGUIIO.IniFilename = nullptr;
imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
imGUIIO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
ImGuiStyle &style = ImGui::GetStyle();
style.ScaleAllSizes(mainScale);
style.FontScaleDpi = mainScale;
ImGui_ImplSDLGPU3_InitInfo initInfo{.Device = RDC_Device::GetHandle(),
.ColorTargetFormat = RDC_Device::GetSwapchainTextureFormat(),
.PresentMode = SDL_GPU_PRESENTMODE_VSYNC};
ImGui_ImplSDL3_InitForSDLGPU(g_windowHandle);
ImGui_ImplSDLGPU3_Init(&initInfo);
ImFontConfig fontConfig;
fontConfig.MergeMode = true;
fontConfig.PixelSnapH = true;
fontConfig.FontDataOwnedByAtlas = false;
fontConfig.GlyphOffset.y = 1.5f;
fontConfig.SizePixels = 12.0f;
static const ImWchar icon_ranges[] = {ICON_MIN_FA, ICON_MAX_FA, 0};
imGUIIO.Fonts->AddFontDefault();
imGUIIO.Fonts->AddFontFromMemoryTTF((PVOID) DATA_TTF_FONTAWESOME7FREESOLID900,
SIZE_TTF_FONTAWESOME7FREESOLID900, 0.0f, &fontConfig, icon_ranges);
imGUIIO.Fonts->Build();
UI::Initialize();
SDL_Event event{};
while (true)
{
SDL_PollEvent(&event);
if (event.type == SDL_EVENT_QUIT)
break;
UI::ProcessEvent(&event);
UI::Update();
ImGui_ImplSDL3_ProcessEvent(&event);
ImGui_ImplSDLGPU3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
UI::Draw();
ImGui::Render();
STATIC SDL_GPURenderPass *ActiveRenderPass{};
STATIC SDL_GPUCommandBuffer *ActiveCommandBuffer{};
STATIC SDL_GPUColorTargetInfo ActiveColorTargetInfo{.clear_color = SDL_FColor{0.0f, 0.0f, 0.0f, 1.0f},
.load_op = SDL_GPU_LOADOP_CLEAR,
.store_op = SDL_GPU_STOREOP_STORE};
if (!(ActiveCommandBuffer = SDL_AcquireGPUCommandBuffer(RDC_Device::GetHandle())))
THROW_UNKNOWN("Failed to acquire SDL GPU command buffer: ", SDL_GetError());
g_imDrawData = ImGui::GetDrawData();
ImGui_ImplSDLGPU3_PrepareDrawData(g_imDrawData, ActiveCommandBuffer);
SDL_GPUTexture *swapChainTexture{};
if (!SDL_WaitAndAcquireGPUSwapchainTexture(ActiveCommandBuffer, g_windowHandle, &swapChainTexture, nullptr,
nullptr))
THROW_UNKNOWN("Failed to acquire SDL GPU Swapchain texture: ", SDL_GetError());
ActiveColorTargetInfo.texture = swapChainTexture;
ActiveColorTargetInfo.clear_color = SDL_FColor{0.3f, 0.3f, 0.3f, 1.0f};
ActiveRenderPass = SDL_BeginGPURenderPass(ActiveCommandBuffer, &ActiveColorTargetInfo, 1, nullptr);
ImGui_ImplSDLGPU3_RenderDrawData(g_imDrawData, ActiveCommandBuffer, ActiveRenderPass);
SDL_EndGPURenderPass(ActiveRenderPass);
SDL_SubmitGPUCommandBuffer(ActiveCommandBuffer);
RDC_Device::WaitForIdle();
}
IVec2 currentWindowPosition{};
SDL_GetWindowPosition(g_windowHandle, &currentWindowPosition.x, &currentWindowPosition.y);
m_activeProject->WindowPosition() = currentWindowPosition;
m_activeProject->Update();
UI::Terminate();
ImGui_ImplSDL3_Shutdown();
ImGui_ImplSDLGPU3_Shutdown();
ImGui::DestroyContext();
SDL_DestroyWindow(g_windowHandle);
return 0;
}
} // namespace ia::iae