Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ endif ()
# -----------------------------------------------------------------------------
octarine_library(octarine_engine
Engine/EngineBootstrap.cpp
Engine/EngineRuntime.cpp
Engine/FrameLoop.cpp
Engine/SceneLoader.cpp
Game/Game.cpp
)
target_link_libraries(octarine_engine PUBLIC
Expand Down
81 changes: 81 additions & 0 deletions src/Engine/EngineRuntime.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include "Engine/EngineRuntime.h"

#include <SDL3/SDL.h>
#include <SDL3_ttf/SDL_ttf.h>

#include <string>

#include "General/Logger.h"

#ifdef OCTARINE_WITH_IMGUI
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlrenderer3.h"
#endif

bool EngineRuntime::InitSubsystems() {
constexpr auto SDL_INI = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD;

if (!SDL_Init(SDL_INI)) {
Logger::Error("SDL_Init Error: " + std::string(SDL_GetError()));
return false;
}

if (!TTF_Init()) {
Logger::Error("TTF_Init Error: " + std::string(SDL_GetError()));
return false;
}

return true;
}

bool EngineRuntime::CreateWindow(const std::string& title, int width, int height) {
SDL_CreateWindowAndRenderer(title.c_str(), width, height, SDL_WINDOW_RESIZABLE, &window_, &sdl_renderer_);

if (!window_) {
Logger::Error("SDL_CreateWindow Error: " + std::string(SDL_GetError()));
return false;
}

if (!sdl_renderer_) {
Logger::Error("SDL_CreateRenderer Error: " + std::string(SDL_GetError()));
return false;
}

return true;
}

#ifdef OCTARINE_WITH_IMGUI
void EngineRuntime::InitImGui(const char* iniPath) {
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.IniFilename = iniPath;

io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;

ImGui_ImplSDL3_InitForSDLRenderer(window_, sdl_renderer_);
ImGui_ImplSDLRenderer3_Init(sdl_renderer_);
}
#endif

void EngineRuntime::Shutdown() {
if (sdl_renderer_) {
#ifdef OCTARINE_WITH_IMGUI
ImGui_ImplSDLRenderer3_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
#endif
SDL_DestroyRenderer(sdl_renderer_);
sdl_renderer_ = nullptr;
}

if (window_) {
SDL_DestroyWindow(window_);
window_ = nullptr;
}

SDL_Quit();
}
53 changes: 53 additions & 0 deletions src/Engine/EngineRuntime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once

#include <SDL3/SDL.h>

#include <string>

class GameConfig;
class Renderer;

// Owns the platform/runtime lifecycle that Game::Initialize and Game::Destroy used to inline:
// SDL + TTF subsystem init, the window/renderer pair, the ImGui backend, and orderly teardown.
// It deliberately knows nothing about GameConfig loading, project resolution, or editor
// persistence — Game still drives those and feeds this the window title/size it derived. The
// off-screen scene render target stays owned by Renderer (Stage 7); Game sequences DestroyScene
// around Shutdown so the SDL renderer is still live when the scene target is freed.
class EngineRuntime {
public:
EngineRuntime() = default;

EngineRuntime(const EngineRuntime&) = delete;
EngineRuntime& operator=(const EngineRuntime&) = delete;
EngineRuntime(EngineRuntime&&) = delete;
EngineRuntime& operator=(EngineRuntime&&) = delete;

~EngineRuntime() = default;

// SDL_Init(video/audio/events/gamepad) + TTF_Init. Returns false (logging the SDL error) on
// failure so Game::Initialize can abort.
[[nodiscard]] bool InitSubsystems();

// Create the window + accelerated renderer (resizable). Returns false on failure; on success
// Window()/SdlRenderer() are non-null.
[[nodiscard]] bool CreateWindow(const std::string& title, int width, int height);

#ifdef OCTARINE_WITH_IMGUI
// Stand up the ImGui context + SDL3/SDLRenderer3 backends and the docking/nav config flags.
// `iniPath` becomes io.IniFilename (must outlive the context). Fonts/style are the caller's
// job afterwards (editor builds rebuild the editor font; player builds add the default).
void InitImGui(const char* iniPath);
#endif

// Tear down the ImGui backend (if built) and destroy the renderer, window, and SDL subsystems.
// Safe to call when CreateWindow was never reached (no-ops on null handles). Call AFTER the
// owner has released anything that needs a live SDL renderer (scene target, GPU textures).
void Shutdown();

[[nodiscard]] SDL_Window* Window() const { return window_; }
[[nodiscard]] SDL_Renderer* SdlRenderer() const { return sdl_renderer_; }

private:
SDL_Window* window_ = nullptr;
SDL_Renderer* sdl_renderer_ = nullptr;
};
Loading
Loading