// 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 . #include #include #include #include #include #include #include #include #include #include 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}; Map g_assetNameMap; SIZE_T g_uniqueNameCounter{0}; String generate_unique_asset_name() { return BuildString("Asset_", g_uniqueNameCounter++); } VOID Editor::LoadProject(IN CONST String &directory) { m_activeProject = Project::Load(directory); } VOID Editor::OpenFile(IN Path path) { const auto assetName = AssetManager::GetAssetName(path.string().c_str()); if (assetName.size()) { UI::GetAssetView()->Open(assetName); UI::OpenAssetView(); } else { UI::GetFilePreviewView()->Open(path); UI::OpenFilePreviewView(); } } VOID Editor::MarkAsAsset(IN Path path) { const auto assetName = generate_unique_asset_name(); AssetManager::AssignAssetName(AssetManager::LoadTexture(path.string().c_str()), assetName); UI::CloseFilePreviewView(); UI::GetAssetView()->Open(assetName); UI::OpenAssetView(); } VOID Editor::RemoveFromAssets(IN CONST String &assetName) { } 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, ¤tWindowPosition.x, ¤tWindowPosition.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