Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
OlympeEngine.cpp
Go to the documentation of this file.
1/*
2Olympe Engine V2 2025
3Nicolas Chereau
4nchereau@gmail.com
5
6Purpose:
7- Main application file for Olympe Engine V2 using SDL3.
8Notes:
9- This file implements the SDL_App* callbacks to initialize, run, and shutdown
10 the engine using SDL3's application framework.
11- GameEngine and its submanagers are initialized here: EventManager, InputsManager,
12 DataManager, VideoGame, etc.
13
14*/
15
16#define SDL_MAIN_USE_CALLBACKS 1 /* use the callbacks instead of main() */
17#include <SDL3/SDL.h>
18#include <SDL3/SDL_main.h>
19#include <SDL3/SDL_messagebox.h>
20#include "gameengine.h"
21#include "World.h"
24#include "system/MouseManager.h"
25#include "InputsManager.h"
26#include "GameState.h"
28#include "system/GameMenu.h"
29#include "DataManager.h"
30#include "system/system_utils.h"
31#include "PanelManager.h"
32#include "BlueprintEditor/BlueprintEditor.h"
36#include "third_party/imgui/imgui.h"
37#include "third_party/imgui/backends/imgui_impl_sdl3.h"
38#include "third_party/imgui/backends/imgui_impl_sdlrenderer3.h"
39
40// Avoid Win32 macro collisions: PostMessage is a Win32 macro expanding to PostMessageW/A
41#ifdef PostMessage
42#undef PostMessage
43#endif
44
45 /* We will use this renderer to draw into this window every frame. */
48const int TARGET_FPS = 100;
50
51// BlueprintEditor GUI instance
53
54// Behavior Tree Debug Window instance (global for access from AI systems)
55// Note: Using raw pointer for consistency with existing code. Cleaned up in SDL_AppQuit().
57
58// Animation Editor Window instance
60
61/* This function runs once at startup. */
63{
64 // Initialize the system logger first so all SYSTEM_LOG calls reach cout, cerr and olympe.log
66
67 SYSTEM_LOG << "----------- OLYMPE ENGINE V2 ------------" << endl;
68 SYSTEM_LOG << "System Initialization\n" << endl;
69
70 // Load configuration (JSON inside "olympe.ini"). Defaults used if not present.
71 // InitLogger() above enables cout, cerr, file, and panel by default; LoadOlympeConfig
72 // may then selectively disable channels via log_cout/log_cerr/log_file/log_panel keys.
73 LoadOlympeConfig("olympe.ini");
74
75 SDL_SetAppMetadata("Olympe Game Engine", "2.0", "com.googlesites.olympeengine");
76
77
79 SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
80 return SDL_APP_FAILURE;
81 }
82
84 SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
85 return SDL_APP_FAILURE;
86 }
88
89 // Create and initialize PanelManager (for debug panels)
90 //PanelManager::Get().Initialize();
91
92 // Initialize DataManager (load system resources if needed)
93 DataManager::Get().Initialize(); // DataManager must be initialized before GameEngine to enable loading resources during GameEngine init
94
95 //Olympe Engine and all managers singleton Initialization Here
96 GameEngine::renderer = renderer; // important: set main renderer for GameEngine before GetInstance
97 GameEngine::GetInstance(); // create the GameEngine itself
98 GameEngine::Get().Initialize(); // initialize all submanagers
99
100 // Attach panels/menu to main SDL window (Windows only)
101 //PanelManager::Get().AttachToSDLWindow(window);
102
103 // Initialize ImGui context BEFORE creating debug windows
104 // This ensures the main context exists when separate windows create their own contexts
105 ImGui::CreateContext();
106 ImGuiIO& io = ImGui::GetIO();
107 (void)io;
108
109 ImGui::StyleColorsDark();
112
113 // Initialize Blueprint Editor Backend
116
117 // Create Blueprint Editor GUI
120
121 // Create Behavior Tree Debug Window (now ImGui context exists)
124
125 // Create Animation Editor Window
127
128 SYSTEM_LOG << "Runtime Blueprint Panel initialized (toggle with F2; opens full Blueprint Editor from panel)" << endl;
129 SYSTEM_LOG << "BehaviorTree Debugger initialized (toggle with F10)" << endl;
130 SYSTEM_LOG << "Animation Editor initialized (toggle with F9)" << endl;
131
132 return SDL_APP_CONTINUE; /* carry on with the program! */
133}
134
135/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
137{
138 if (!event) return SDL_APP_CONTINUE;
139
140 // ===== Route events to Animation Editor separate window =====
141 if (animationEditorWindow != nullptr)
142 {
144 }
145
146 // ===== Route events to BT Debugger separate window =====
147 if (g_btDebugWindow != nullptr)
148 {
150 }
151
152 // ===== A) ImGui Event Processing for MAIN window =====
153 // Process ImGui events before game logic to enable panel interactivity
155
156 // Get ImGui IO to check if ImGui wants to capture input
157 ImGuiIO& io = ImGui::GetIO();
158
159 // Skip event propagation to game if ImGui wants to capture it
160 bool skipEventForGame = false;
161
162 // Check if ImGui wants to capture mouse events
163 if (io.WantCaptureMouse)
164 {
165 if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN ||
167 event->type == SDL_EVENT_MOUSE_MOTION ||
169 {
170 skipEventForGame = true;
171 }
172 }
173
174 // Check if ImGui wants to capture keyboard events
175 if (io.WantCaptureKeyboard)
176 {
177 if (event->type == SDL_EVENT_KEY_DOWN ||
178 event->type == SDL_EVENT_KEY_UP ||
180 {
181 skipEventForGame = true;
182 }
183 }
184
185 // Only propagate to game systems if ImGui doesn't want the event
186 if (!skipEventForGame)
187 {
189 }
190
191 switch (event->type)
192 {
194
195 // F2 toggles Tiled Level Loader menu
196 if (event->key.key == SDLK_F2)
197 {
199 SYSTEM_LOG << "Tiled Level Loader (F2) "
200 << (GameMenu::Get().IsF2MenuOpen() ? "opened" : "closed")
201 << endl;
202 return SDL_APP_CONTINUE; // Early return to avoid ESC dialog below
203 }
204
205 // F10 toggles Behavior Tree Debug Window
206 if (event->key.key == SDLK_F10)
207 {
208 if (g_btDebugWindow)
209 {
211 SYSTEM_LOG << "BT Runtime Debugger "
212 << (g_btDebugWindow->IsVisible() ? "opened" : "closed")
213 << endl;
214 }
215 return SDL_APP_CONTINUE;
216 }
217
218 // F9 toggles Animation Editor Window
219 if (event->key.key == SDLK_F9)
220 {
222 {
224 SYSTEM_LOG << "Animation Editor "
225 << (animationEditorWindow->IsOpen() ? "opened" : "closed")
226 << endl;
227 }
228 return SDL_APP_CONTINUE;
229 }
230
231 // F3 toggles Tiled Level Loader menu
232 if (event->key.key == SDLK_F3)
233 {
235 SYSTEM_LOG << "Tiled Level Loader Menu "
236 << (GameMenu::Get().IsF2MenuOpen() ? "opened" : "closed")
237 << endl;
238 return SDL_APP_CONTINUE;
239 }
240
241 if (event->key.key == SDLK_ESCAPE)
242 {
243 const SDL_MessageBoxButtonData buttons[] =
244 {
245 { /* .flags, .buttonid, .text */ 0, 0, "No" },
248 };
250 {
251 { /* .colors (.r, .g, .b) */
252 /* [SDL_MESSAGEBOX_COLOR_BACKGROUND] */
253 { 255, 0, 0 },
254 /* [SDL_MESSAGEBOX_COLOR_TEXT] */
255 { 0, 255, 0 },
256 /* [SDL_MESSAGEBOX_COLOR_BUTTON_BORDER] */
257 { 255, 255, 0 },
258 /* [SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND] */
259 { 0, 0, 255 },
260 /* [SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED] */
261 { 255, 0, 255 }
262 }
263 };
265 SDL_MESSAGEBOX_INFORMATION, /* .flags */
266 window, /* .window */
267 "Olympe Engine V2", /* .title */
268 "Do you want to exit Olympe Engine?", /* .message */
269 SDL_arraysize(buttons), /* .numbuttons */
270 buttons, /* .buttons */
271 &colorScheme /* .colorScheme */
272 };
273 int buttonid;
274
276 if (buttonid == 1)
277 {
278 // Clear input state before exiting
282 return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
283 }
284 }
285 break;
286 case SDL_EVENT_QUIT:
287 {
288 // Clear input state before exiting
292 return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
293 }
294 break;
295 default:
296 return SDL_APP_CONTINUE; /* carry on with the program! */
297 break;
298 }
299
300 return SDL_APP_CONTINUE; /* carry on with the program! */
301
302}
303
304/* This function runs once per frame, and is the heart of the program. */
306{
307 //-------------------------------------------------------------------
308 // PROCESSING PHASE -------------------------------------------------
309 //-------------------------------------------------------------------
310
311 // Calculate delta time
312 GameEngine::Get().Process(); // update fDt here for all managers
313
314 // Update Blueprint Editor backend if active
315 if (Olympe::BlueprintEditor::Get().IsActive())
316 {
318 }
319
320 // Process ECS systems
321 World::Get().Process(); // process all world objects/components
322
323 // If game state requests quit, end the application loop
325 {
326 // Clear input state before exiting
330 return SDL_APP_SUCCESS;
331 }
332
333 //-------------------------------------------------------------------
334 // RENDER PHASE -----------------------------------------------------
335 //-------------------------------------------------------------------
336
337 /* as you can see from this, rendering draws over whatever was drawn before it. */
338 SDL_SetRenderDrawColor(renderer, 120, 120, 120, SDL_ALPHA_OPAQUE); /* white, full alpha */
339 SDL_RenderClear(renderer); /* start with a blank canvas. */
340
341 // Render world once per viewport/player so each viewport gets its own draw pass
342 const auto& rects = ViewportManager::Get().GetViewRects();
343 const auto& players = ViewportManager::Get().GetPlayers();
344
345 if (rects.empty())
346 {
347 // fallback to previous single-render behavior
348 World::Get().Render();
349 }
350 else
351 {
352 // save current viewport to restore later
354 //SDL_RenderGetViewport(renderer, &prev);
355
356 for (size_t i = 0; i < rects.size(); ++i)
357 {
358 const auto& rf = rects[i];
359 SDL_Rect r = { (int)rf.x, (int)rf.y, (int)rf.w, (int)rf.h };
362
363 // Draw world for this viewport
364 World::Get().Render();
365
366 // Reset clip rect after each viewport
368 }
369
370 // restore previous viewport and ensure clip rect is cleared
373 }
374
375 // Render Blueprint Editor GUI if active
376 // NOTE: Requires ImGui to be initialized and integrated into main engine
377 // TODO: Add ImGui initialization in SDL_AppInit and ImGui NewFrame/Render calls here
378 if ((Olympe::BlueprintEditor::Get().IsActive() && blueprintEditorGUI) || GameMenu::Get().IsF2MenuOpen())
379 {
380 // ===== FIX: Synchronize ImGui DisplaySize with window size =====
381 // This fixes mouse coordinates in fullscreen mode
384
385 ImGuiIO& io = ImGui::GetIO();
386
387 // Update DisplaySize if window size changed
388 if (io.DisplaySize.x != (float)windowWidth || io.DisplaySize.y != (float)windowHeight)
389 {
390 io.DisplaySize = ImVec2((float)windowWidth, (float)windowHeight);
391
392 // Update framebuffer scale for High DPI support
395
396 if (windowWidth > 0 && windowHeight > 0)
397 {
398 io.DisplayFramebufferScale = ImVec2(
399 (float)displayWidth / windowWidth,
401 );
402 }
403 }
404
407 ImGui::NewFrame();
408
409 blueprintEditorGUI->Render(); // BeginMainMenuBar() est maintenant sûr
410
411 // Render Tiled Level Loader menu (F2)
413
414 // Render minimal runtime Blueprint panel (accessible via UI)
416
417 ImGui::Render();
418 ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer);
419 }
420
421 // Render Behavior Tree Debug Window (F10) - Independent separate window
422 // This is rendered outside the main ImGui frame as it has its own SDL window and ImGui context
423 if (g_btDebugWindow)
424 {
426 }
427
428 // Update Animation Editor (F9) - Independent separate window
430 {
432 }
433
434 SDL_RenderPresent(renderer); /* put it all on the screen! */
435
436 // Update FPS counter and set window title once per second
437 static int frameCount = 0;
438 static Uint64 fpsLastTime = 0;
439 static Uint64 frameStartTime = 0;
440 if (frameStartTime > 0)
441 {
442 // Temps �coul� depuis le d�but de la frame pr�c�dente
444
445 // Si la frame a pris moins de temps que le temps cible (16.666 ms)...
447 {
448 // ... alors nous "dormons" (bloquons) le thread pour le temps restant.
451 // Ce SDL_Delay garantit que chaque frame ne sera pas trait�e plus vite que TARGET_FPS.
452 }
453 }
455
456 frameCount++;
457 const Uint64 nowMs = SDL_GetTicks();
458 if (fpsLastTime == 0) fpsLastTime = nowMs;
460 if (elapsed >= 1000)
461 {
462 float fps = frameCount * 1000.0f / (float)elapsed;
463 char title[256];
464 snprintf(title, sizeof(title), "Olympe Engine 2.0 - FPS: %.f", fps);
465 if (window) SDL_SetWindowTitle(window, title);
466 frameCount = 0;
468 }
469
470 //-------------------------------------------------------------------
471 // END OF FRAME: Reset frame state for input managers
472 //-------------------------------------------------------------------
473 // Clear pressed/released state after all systems have processed input
477
478 return SDL_APP_CONTINUE; /* carry on with the program! */
479}
480
481/* This function runs once at shutdown. */
483{
484 /* SDL will clean up the window/renderer for us. */
485
486 // Cleanup Behavior Tree Debug Window
487 if (g_btDebugWindow)
488 {
489 // g_btDebugWindow->Shutdown(); // delete
490 delete g_btDebugWindow;
491 g_btDebugWindow = nullptr;
492 }
493
494 // Cleanup Animation Editor Window
496 {
498 animationEditorWindow = nullptr;
499 }
500
501 // Shutdown Blueprint Editor
503 {
504 // blueprintEditorGUI->Shutdown(); // Double delete
505 delete blueprintEditorGUI;
506 blueprintEditorGUI = nullptr;
507 }
508
509 //Olympe::BlueprintEditor::Get().Shutdown();
510
511 // Shutdown datamanager to ensure resources freed
513
514 SYSTEM_LOG << "----------- OLYMPE ENGINE V2 ------------" << endl;
515 SYSTEM_LOG << "System shutdown completed\n" << endl;
516}
517
Animation Editor window for creating and editing animation banks.
Runtime debugger for behavior tree visualization and inspection.
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
static Olympe::AnimationEditorWindow * animationEditorWindow
void SDL_AppQuit(void *appstate, SDL_AppResult result)
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
SDL_AppResult SDL_AppIterate(void *appstate)
const Uint32 FRAME_TARGET_TIME_MS
static SDL_Renderer * renderer
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
static Olympe::BlueprintEditorGUI * blueprintEditorGUI
static SDL_Window * window
Olympe::BehaviorTreeDebugWindow * g_btDebugWindow
const int TARGET_FPS
World and ECS Manager for Olympe Engine.
static DataManager & Get()
Definition DataManager.h:91
void Initialize()
void Shutdown()
void Process()
Process one frame.
static int screenWidth
Screen width in pixels.
Definition GameEngine.h:123
static float fDt
Delta time between frames in seconds.
Definition GameEngine.h:120
static int screenHeight
Screen height in pixels.
Definition GameEngine.h:126
static GameEngine & GetInstance()
Get singleton instance.
Definition GameEngine.h:56
static GameEngine & Get()
Get singleton instance (short form)
Definition GameEngine.h:66
void Initialize()
Initialize all engine subsystems.
static SDL_Renderer * renderer
Main SDL renderer.
Definition GameEngine.h:129
static GameMenu & Get()
Definition GameMenu.h:38
void ToggleF2Menu()
Definition GameMenu.cpp:95
bool IsF2MenuOpen() const
Definition GameMenu.h:62
void RenderRuntimeBlueprintPanel()
Definition GameMenu.cpp:117
void RenderF2Menu()
Definition GameMenu.cpp:255
static InputsManager & Get()
virtual void HandleEvent(const SDL_Event *ev)
static JoystickManager & Get()
static KeyboardManager & Get()
static MouseManager & Get()
Main animation editor window.
void Toggle()
Toggle window visibility.
bool IsOpen() const
Check if window is open.
void Update(float deltaTime)
Update and render the editor window (separate window)
void ProcessEvent(SDL_Event *event)
Process SDL events for the separate window.
Main debug window for behavior tree runtime visualization.
void Initialize()
Initialize the debug window.
void ToggleVisibility()
Toggle window visibility (creates/destroys separate window)
void Render()
Render the debug window (in separate SDL3 window)
bool IsVisible() const
Check if window is visible.
void ProcessEvent(SDL_Event *event)
Process SDL events for separate window.
BlueprintEditorGUI - Frontend UI for Blueprint Editor Renders ImGui interface and interacts with Blue...
static BlueprintEditor & Get()
void Update(float deltaTime)
static ViewportManager & Get()
const std::vector< SDL_FRect > & GetViewRects() const
const std::vector< short > & GetPlayers() const
void Process()
Definition World.h:257
static World & Get()
Get singleton instance (short form)
Definition World.h:232
void Render()
Definition World.h:271
GameState GetState()
Definition GameState.cpp:15
bool InitLogger(const std::string &filename="olympe.log")
void LoadOlympeConfig(const char *filename)
#define SYSTEM_LOG