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 SYSTEM_LOG << "----------- OLYMPE ENGINE V2 ------------" << endl;
65 SYSTEM_LOG << "System Initialization\n" << endl;
66
67 // Load configuration (JSON inside "olympe.ini"). Defaults used if not present.
68 LoadOlympeConfig("olympe.ini");
69
70 SDL_SetAppMetadata("Olympe Game Engine", "2.0", "com.googlesites.olympeengine");
71
72 // Initialize system logger so SYSTEM_LOG forwards to UI (if available)
74
75
77 SDL_Log("Couldn't initialize SDL: %s", SDL_GetError());
78 return SDL_APP_FAILURE;
79 }
80
82 SDL_Log("Couldn't create window/renderer: %s", SDL_GetError());
83 return SDL_APP_FAILURE;
84 }
86
87 // Create and initialize PanelManager (for debug panels)
89
90 // Initialize DataManager (load system resources if needed)
91 DataManager::Get().Initialize(); // DataManager must be initialized before GameEngine to enable loading resources during GameEngine init
92
93 //Olympe Engine and all managers singleton Initialization Here
94 GameEngine::renderer = renderer; // important: set main renderer for GameEngine before GetInstance
95 GameEngine::GetInstance(); // create the GameEngine itself
96 GameEngine::Get().Initialize(); // initialize all submanagers
97
98 // Attach panels/menu to main SDL window (Windows only)
100
101 // Initialize Blueprint Editor Backend
104
105 // Create Blueprint Editor GUI
108
109 // Create Behavior Tree Debug Window
112
113 // Create Animation Editor Window
115
116 SYSTEM_LOG << "BlueprintEditor initialized in Runtime mode (toggle with F2)" << endl;
117 SYSTEM_LOG << "BehaviorTree Debugger initialized (toggle with F10)" << endl;
118 SYSTEM_LOG << "Animation Editor initialized (toggle with F9)" << endl;
119
120 // Initialisation (à l'initialisation de l'application)
121 ImGui::CreateContext();
122 ImGuiIO& io = ImGui::GetIO();
123
124 ImGui::StyleColorsDark();
125 // Initialiser vos implémentations (ex. SDL + renderer)
128
129 return SDL_APP_CONTINUE; /* carry on with the program! */
130}
131
132/* This function runs when a new event (mouse input, keypresses, etc) occurs. */
134{
135 if (!event) return SDL_APP_CONTINUE;
136
137 // ===== Route events to Animation Editor separate window =====
138 if (animationEditorWindow != nullptr)
139 {
141 }
142
143 // ===== Route events to BT Debugger separate window =====
144 if (g_btDebugWindow != nullptr)
145 {
147 }
148
149 // ===== A) ImGui Event Processing for MAIN window =====
150 // Process ImGui events before game logic to enable panel interactivity
152
153 // Get ImGui IO to check if ImGui wants to capture input
154 ImGuiIO& io = ImGui::GetIO();
155
156 // Skip event propagation to game if ImGui wants to capture it
157 bool skipEventForGame = false;
158
159 // Check if ImGui wants to capture mouse events
160 if (io.WantCaptureMouse)
161 {
162 if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN ||
164 event->type == SDL_EVENT_MOUSE_MOTION ||
166 {
167 skipEventForGame = true;
168 }
169 }
170
171 // Check if ImGui wants to capture keyboard events
172 if (io.WantCaptureKeyboard)
173 {
174 if (event->type == SDL_EVENT_KEY_DOWN ||
175 event->type == SDL_EVENT_KEY_UP ||
177 {
178 skipEventForGame = true;
179 }
180 }
181
182 // Only propagate to game systems if ImGui doesn't want the event
183 if (!skipEventForGame)
184 {
186 }
187
188 switch (event->type)
189 {
191
192 // F2 toggles Blueprint Editor (always process, even if ImGui is capturing)
193 if (event->key.key == SDLK_F2)
194 {
196 SYSTEM_LOG << "BlueprintEditor "
197 << (Olympe::BlueprintEditor::Get().IsActive() ? "activated" : "deactivated")
198 << endl;
200 return SDL_APP_CONTINUE; // Early return to avoid ESC dialog below
201 }
202
203 // F10 toggles Behavior Tree Debug Window
204 if (event->key.key == SDLK_F10)
205 {
206 if (g_btDebugWindow)
207 {
209 SYSTEM_LOG << "BT Runtime Debugger "
210 << (g_btDebugWindow->IsVisible() ? "opened" : "closed")
211 << endl;
212 }
213 return SDL_APP_CONTINUE;
214 }
215
216 // F9 toggles Animation Editor Window
217 if (event->key.key == SDLK_F9)
218 {
220 {
222 SYSTEM_LOG << "Animation Editor "
223 << (animationEditorWindow->IsOpen() ? "opened" : "closed")
224 << endl;
225 }
226 return SDL_APP_CONTINUE;
227 }
228
229 // F3 toggles Tiled Level Loader menu
230 if (event->key.key == SDLK_F3)
231 {
233 SYSTEM_LOG << "Tiled Level Loader Menu "
234 << (GameMenu::Get().IsF2MenuOpen() ? "opened" : "closed")
235 << endl;
236 return SDL_APP_CONTINUE;
237 }
238
239 if (event->key.key == SDLK_ESCAPE)
240 {
241 const SDL_MessageBoxButtonData buttons[] =
242 {
243 { /* .flags, .buttonid, .text */ 0, 0, "No" },
246 };
248 {
249 { /* .colors (.r, .g, .b) */
250 /* [SDL_MESSAGEBOX_COLOR_BACKGROUND] */
251 { 255, 0, 0 },
252 /* [SDL_MESSAGEBOX_COLOR_TEXT] */
253 { 0, 255, 0 },
254 /* [SDL_MESSAGEBOX_COLOR_BUTTON_BORDER] */
255 { 255, 255, 0 },
256 /* [SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND] */
257 { 0, 0, 255 },
258 /* [SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED] */
259 { 255, 0, 255 }
260 }
261 };
263 SDL_MESSAGEBOX_INFORMATION, /* .flags */
264 window, /* .window */
265 "Olympe Engine V2", /* .title */
266 "Do you want to exit Olympe Engine?", /* .message */
267 SDL_arraysize(buttons), /* .numbuttons */
268 buttons, /* .buttons */
269 &colorScheme /* .colorScheme */
270 };
271 int buttonid;
272
274 if (buttonid == 1)
275 {
276 // Clear input state before exiting
280 return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
281 }
282 }
283 break;
284 case SDL_EVENT_QUIT:
285 {
286 // Clear input state before exiting
290 return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */
291 }
292 break;
293 default:
294 return SDL_APP_CONTINUE; /* carry on with the program! */
295 break;
296 }
297
298 return SDL_APP_CONTINUE; /* carry on with the program! */
299
300}
301
302/* This function runs once per frame, and is the heart of the program. */
304{
305 //-------------------------------------------------------------------
306 // PROCESSING PHASE -------------------------------------------------
307 //-------------------------------------------------------------------
308
309 // Calculate delta time
310 GameEngine::Get().Process(); // update fDt here for all managers
311
312 // Update Blueprint Editor backend if active
313 if (Olympe::BlueprintEditor::Get().IsActive())
314 {
316 }
317
318 // Process ECS systems
319 World::Get().Process(); // process all world objects/components
320
321 // If game state requests quit, end the application loop
323 {
324 // Clear input state before exiting
328 return SDL_APP_SUCCESS;
329 }
330
331 //-------------------------------------------------------------------
332 // RENDER PHASE -----------------------------------------------------
333 //-------------------------------------------------------------------
334
335 /* as you can see from this, rendering draws over whatever was drawn before it. */
336 SDL_SetRenderDrawColor(renderer, 120, 120, 120, SDL_ALPHA_OPAQUE); /* white, full alpha */
337 SDL_RenderClear(renderer); /* start with a blank canvas. */
338
339 // Render world once per viewport/player so each viewport gets its own draw pass
340 const auto& rects = ViewportManager::Get().GetViewRects();
341 const auto& players = ViewportManager::Get().GetPlayers();
342
343 if (rects.empty())
344 {
345 // fallback to previous single-render behavior
346 World::Get().Render();
347 }
348 else
349 {
350 // save current viewport to restore later
352 //SDL_RenderGetViewport(renderer, &prev);
353
354 for (size_t i = 0; i < rects.size(); ++i)
355 {
356 const auto& rf = rects[i];
357 SDL_Rect r = { (int)rf.x, (int)rf.y, (int)rf.w, (int)rf.h };
360
361 // Draw world for this viewport
362 World::Get().Render();
363
364 // Reset clip rect after each viewport
366 }
367
368 // restore previous viewport and ensure clip rect is cleared
371 }
372
373 // Render Blueprint Editor GUI if active
374 // NOTE: Requires ImGui to be initialized and integrated into main engine
375 // TODO: Add ImGui initialization in SDL_AppInit and ImGui NewFrame/Render calls here
377 {
378 // ===== FIX: Synchronize ImGui DisplaySize with window size =====
379 // This fixes mouse coordinates in fullscreen mode
382
383 ImGuiIO& io = ImGui::GetIO();
384
385 // Update DisplaySize if window size changed
386 if (io.DisplaySize.x != (float)windowWidth || io.DisplaySize.y != (float)windowHeight)
387 {
388 io.DisplaySize = ImVec2((float)windowWidth, (float)windowHeight);
389
390 // Update framebuffer scale for High DPI support
393
394 if (windowWidth > 0 && windowHeight > 0)
395 {
396 io.DisplayFramebufferScale = ImVec2(
397 (float)displayWidth / windowWidth,
399 );
400 }
401 }
402
405 ImGui::NewFrame();
406
407 blueprintEditorGUI->Render(); // BeginMainMenuBar() est maintenant sûr
408
409 // Render Behavior Tree Debug Window
410 if (g_btDebugWindow)
411 {
413 }
414
415 // Update Animation Editor (separate window)
417 {
419 }
420
421 // Render Tiled Level Loader menu (F3)
423
424 ImGui::Render();
425 ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), renderer);
426 }
427
428 SDL_RenderPresent(renderer); /* put it all on the screen! */
429
430 // Update FPS counter and set window title once per second
431 static int frameCount = 0;
432 static Uint64 fpsLastTime = 0;
433 static Uint64 frameStartTime = 0;
434 if (frameStartTime > 0)
435 {
436 // Temps �coul� depuis le d�but de la frame pr�c�dente
438
439 // Si la frame a pris moins de temps que le temps cible (16.666 ms)...
441 {
442 // ... alors nous "dormons" (bloquons) le thread pour le temps restant.
445 // Ce SDL_Delay garantit que chaque frame ne sera pas trait�e plus vite que TARGET_FPS.
446 }
447 }
449
450 frameCount++;
451 const Uint64 nowMs = SDL_GetTicks();
452 if (fpsLastTime == 0) fpsLastTime = nowMs;
454 if (elapsed >= 1000)
455 {
456 float fps = frameCount * 1000.0f / (float)elapsed;
457 char title[256];
458 snprintf(title, sizeof(title), "Olympe Engine 2.0 - FPS: %.f", fps);
459 if (window) SDL_SetWindowTitle(window, title);
460 frameCount = 0;
462 }
463
464 //-------------------------------------------------------------------
465 // END OF FRAME: Reset frame state for input managers
466 //-------------------------------------------------------------------
467 // Clear pressed/released state after all systems have processed input
471
472 return SDL_APP_CONTINUE; /* carry on with the program! */
473}
474
475/* This function runs once at shutdown. */
477{
478 /* SDL will clean up the window/renderer for us. */
479
480 // Cleanup Behavior Tree Debug Window
481 if (g_btDebugWindow)
482 {
483 // g_btDebugWindow->Shutdown(); // delete
484 delete g_btDebugWindow;
485 g_btDebugWindow = nullptr;
486 }
487
488 // Cleanup Animation Editor Window
490 {
492 animationEditorWindow = nullptr;
493 }
494
495 // Shutdown Blueprint Editor
497 {
498 // blueprintEditorGUI->Shutdown(); // Double delete
499 delete blueprintEditorGUI;
500 blueprintEditorGUI = nullptr;
501 }
502
504
505 // Shutdown datamanager to ensure resources freed
507
508 SYSTEM_LOG << "----------- OLYMPE ENGINE V2 ------------" << endl;
509 SYSTEM_LOG << "System shutdown completed\n" << endl;
510}
511
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:87
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
void SetF2MenuOpen(bool open)
Definition GameMenu.cpp:99
static GameMenu & Get()
Definition GameMenu.h:38
void ToggleF2Menu()
Definition GameMenu.cpp:94
bool IsF2MenuOpen() const
Definition GameMenu.h:62
void RenderF2Menu()
Definition GameMenu.cpp:200
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 PanelManager & Get()
void AttachToSDLWindow(SDL_Window *sdlWindow)
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