Refactored step 1: Core Architecture Setup
This commit is contained in:
208
src/core/ApplicationManager.cpp
Normal file
208
src/core/ApplicationManager.cpp
Normal file
@ -0,0 +1,208 @@
|
||||
#include "ApplicationManager.h"
|
||||
#include "StateManager.h"
|
||||
#include "../graphics/RenderManager.h"
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3_ttf/SDL_ttf.h>
|
||||
#include <iostream>
|
||||
|
||||
ApplicationManager::ApplicationManager() = default;
|
||||
|
||||
ApplicationManager::~ApplicationManager() {
|
||||
if (m_initialized) {
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
bool ApplicationManager::initialize(int argc, char* argv[]) {
|
||||
if (m_initialized) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "ApplicationManager already initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Initializing ApplicationManager...");
|
||||
|
||||
// Initialize SDL first
|
||||
if (!initializeSDL()) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize managers
|
||||
if (!initializeManagers()) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize managers");
|
||||
cleanupSDL();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize game systems
|
||||
if (!initializeGame()) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize game systems");
|
||||
cleanupManagers();
|
||||
cleanupSDL();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
m_running = true;
|
||||
m_lastFrameTime = SDL_GetTicks();
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "ApplicationManager initialized successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApplicationManager::run() {
|
||||
if (!m_initialized) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ApplicationManager not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Starting main application loop");
|
||||
|
||||
while (m_running) {
|
||||
// Calculate delta time
|
||||
uint64_t currentTime = SDL_GetTicks();
|
||||
float deltaTime = (currentTime - m_lastFrameTime) / 1000.0f;
|
||||
m_lastFrameTime = currentTime;
|
||||
|
||||
// Limit delta time to prevent spiral of death
|
||||
if (deltaTime > 0.05f) { // Cap at 20 FPS minimum
|
||||
deltaTime = 0.05f;
|
||||
}
|
||||
|
||||
// Main loop phases
|
||||
processEvents();
|
||||
|
||||
if (m_running) {
|
||||
update(deltaTime);
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Main application loop ended");
|
||||
}
|
||||
|
||||
void ApplicationManager::shutdown() {
|
||||
if (!m_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Shutting down ApplicationManager...");
|
||||
|
||||
m_running = false;
|
||||
|
||||
// Cleanup in reverse order of initialization
|
||||
cleanupManagers();
|
||||
cleanupSDL();
|
||||
|
||||
m_initialized = false;
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "ApplicationManager shutdown complete");
|
||||
}
|
||||
|
||||
bool ApplicationManager::initializeSDL() {
|
||||
// Initialize SDL subsystems
|
||||
int sdlResult = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
|
||||
if (sdlResult < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Init failed: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize SDL_ttf
|
||||
int ttfResult = TTF_Init();
|
||||
if (ttfResult < 0) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "TTF_Init failed: %s", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL initialized successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ApplicationManager::initializeManagers() {
|
||||
// Create and initialize RenderManager
|
||||
m_renderManager = std::make_unique<RenderManager>();
|
||||
if (!m_renderManager->initialize(m_windowWidth, m_windowHeight, m_windowTitle)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize RenderManager");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create StateManager (will be enhanced in next steps)
|
||||
m_stateManager = std::make_unique<StateManager>(AppState::Loading);
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Managers initialized successfully");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ApplicationManager::initializeGame() {
|
||||
// TODO: Initialize game-specific systems
|
||||
// For now, just set a basic loading state to test the window
|
||||
|
||||
// Initialize a basic test render handler
|
||||
m_stateManager->registerRenderHandler(AppState::Loading,
|
||||
[this](RenderManager& renderer) {
|
||||
// Simple test render - just clear screen and show a colored rectangle
|
||||
renderer.clear(20, 30, 40, 255);
|
||||
|
||||
SDL_FRect testRect = { 400, 300, 400, 200 };
|
||||
renderer.renderRect(testRect, 255, 100, 100, 255);
|
||||
});
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Game systems initialized");
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApplicationManager::processEvents() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if (event.type == SDL_EVENT_QUIT) {
|
||||
requestShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Route events through InputManager and StateManager
|
||||
// For now, handle basic window events
|
||||
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||
if (m_renderManager) {
|
||||
m_renderManager->handleWindowResize(event.window.data1, event.window.data2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationManager::update(float deltaTime) {
|
||||
// TODO: Update all game systems
|
||||
// This will include StateManager updates, game logic, etc.
|
||||
|
||||
if (m_stateManager) {
|
||||
m_stateManager->update(deltaTime);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationManager::render() {
|
||||
if (!m_renderManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_renderManager->beginFrame();
|
||||
|
||||
// Delegate rendering to StateManager
|
||||
if (m_stateManager) {
|
||||
m_stateManager->render(*m_renderManager);
|
||||
}
|
||||
|
||||
m_renderManager->endFrame();
|
||||
}
|
||||
|
||||
void ApplicationManager::cleanupManagers() {
|
||||
// Cleanup managers in reverse order
|
||||
m_stateManager.reset();
|
||||
m_renderManager.reset();
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Managers cleaned up");
|
||||
}
|
||||
|
||||
void ApplicationManager::cleanupSDL() {
|
||||
TTF_Quit();
|
||||
SDL_Quit();
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "SDL cleaned up");
|
||||
}
|
||||
75
src/core/ApplicationManager.h
Normal file
75
src/core/ApplicationManager.h
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
// Forward declarations
|
||||
class RenderManager;
|
||||
class InputManager;
|
||||
class StateManager;
|
||||
class AssetManager;
|
||||
class Game;
|
||||
class ScoreManager;
|
||||
class Starfield;
|
||||
class Starfield3D;
|
||||
class FontAtlas;
|
||||
class LineEffect;
|
||||
|
||||
/**
|
||||
* ApplicationManager - Central coordinator for the entire application lifecycle
|
||||
*
|
||||
* Responsibilities:
|
||||
* - Initialize and shutdown all subsystems
|
||||
* - Coordinate the main application loop
|
||||
* - Manage high-level application state
|
||||
* - Provide clean separation between main() and application logic
|
||||
*/
|
||||
class ApplicationManager {
|
||||
public:
|
||||
ApplicationManager();
|
||||
~ApplicationManager();
|
||||
|
||||
// Core lifecycle methods
|
||||
bool initialize(int argc, char* argv[]);
|
||||
void run();
|
||||
void shutdown();
|
||||
|
||||
// Application state
|
||||
bool isRunning() const { return m_running; }
|
||||
void requestShutdown() { m_running = false; }
|
||||
|
||||
// Access to managers (for now, will be replaced with dependency injection later)
|
||||
RenderManager* getRenderManager() const { return m_renderManager.get(); }
|
||||
StateManager* getStateManager() const { return m_stateManager.get(); }
|
||||
|
||||
private:
|
||||
// Initialization methods
|
||||
bool initializeSDL();
|
||||
bool initializeManagers();
|
||||
bool initializeGame();
|
||||
|
||||
// Main loop methods
|
||||
void processEvents();
|
||||
void update(float deltaTime);
|
||||
void render();
|
||||
|
||||
// Cleanup methods
|
||||
void cleanupManagers();
|
||||
void cleanupSDL();
|
||||
|
||||
// Core managers
|
||||
std::unique_ptr<RenderManager> m_renderManager;
|
||||
std::unique_ptr<StateManager> m_stateManager;
|
||||
|
||||
// Application state
|
||||
bool m_running = false;
|
||||
bool m_initialized = false;
|
||||
|
||||
// Timing
|
||||
uint64_t m_lastFrameTime = 0;
|
||||
|
||||
// Configuration
|
||||
int m_windowWidth = 1200;
|
||||
int m_windowHeight = 1000;
|
||||
std::string m_windowTitle = "Tetris (SDL3)";
|
||||
};
|
||||
@ -1,46 +1,202 @@
|
||||
#include "StateManager.h"
|
||||
#include "../graphics/RenderManager.h"
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
StateManager::StateManager(AppState initial)
|
||||
: currentState(initial)
|
||||
: m_currentState(initial)
|
||||
, m_previousState(initial)
|
||||
{
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "StateManager initialized with state: %s", getStateName(initial));
|
||||
}
|
||||
|
||||
void StateManager::registerHandler(AppState s, EventHandler h) {
|
||||
handlers[static_cast<int>(s)].push_back(std::move(h));
|
||||
void StateManager::registerEventHandler(AppState state, EventHandler handler) {
|
||||
if (!isValidState(state)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid state for event handler registration");
|
||||
return;
|
||||
}
|
||||
|
||||
m_eventHandlers[stateToInt(state)].push_back(std::move(handler));
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Event handler registered for state: %s", getStateName(state));
|
||||
}
|
||||
|
||||
void StateManager::registerOnEnter(AppState s, Hook h) {
|
||||
onEnter[static_cast<int>(s)].push_back(std::move(h));
|
||||
void StateManager::registerUpdateHandler(AppState state, UpdateHandler handler) {
|
||||
if (!isValidState(state)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid state for update handler registration");
|
||||
return;
|
||||
}
|
||||
|
||||
m_updateHandlers[stateToInt(state)].push_back(std::move(handler));
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Update handler registered for state: %s", getStateName(state));
|
||||
}
|
||||
|
||||
void StateManager::registerOnExit(AppState s, Hook h) {
|
||||
onExit[static_cast<int>(s)].push_back(std::move(h));
|
||||
void StateManager::registerRenderHandler(AppState state, RenderHandler handler) {
|
||||
if (!isValidState(state)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid state for render handler registration");
|
||||
return;
|
||||
}
|
||||
|
||||
m_renderHandlers[stateToInt(state)].push_back(std::move(handler));
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Render handler registered for state: %s", getStateName(state));
|
||||
}
|
||||
|
||||
// Overload accepting a no-arg function as handler (wraps it into an EventHandler)
|
||||
void StateManager::registerOnEnter(AppState state, Hook hook) {
|
||||
if (!isValidState(state)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid state for enter hook registration");
|
||||
return;
|
||||
}
|
||||
|
||||
m_onEnterHooks[stateToInt(state)].push_back(std::move(hook));
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Enter hook registered for state: %s", getStateName(state));
|
||||
}
|
||||
|
||||
void StateManager::registerOnExit(AppState state, Hook hook) {
|
||||
if (!isValidState(state)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid state for exit hook registration");
|
||||
return;
|
||||
}
|
||||
|
||||
m_onExitHooks[stateToInt(state)].push_back(std::move(hook));
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Exit hook registered for state: %s", getStateName(state));
|
||||
}
|
||||
|
||||
// Legacy compatibility: overload accepting a no-arg function as handler
|
||||
void StateManager::registerHandler(AppState s, std::function<void()> h) {
|
||||
EventHandler wrapper = [h = std::move(h)](const SDL_Event&) { h(); };
|
||||
registerHandler(s, std::move(wrapper));
|
||||
registerEventHandler(s, std::move(wrapper));
|
||||
}
|
||||
|
||||
void StateManager::setState(AppState s) {
|
||||
if (s == currentState) return;
|
||||
// call exit hooks for current
|
||||
auto it = onExit.find(static_cast<int>(currentState));
|
||||
if (it != onExit.end()) {
|
||||
for (auto &h : it->second) h();
|
||||
bool StateManager::setState(AppState newState) {
|
||||
if (!isValidState(newState)) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Attempted to set invalid state");
|
||||
return false;
|
||||
}
|
||||
currentState = s;
|
||||
auto it2 = onEnter.find(static_cast<int>(currentState));
|
||||
if (it2 != onEnter.end()) {
|
||||
for (auto &h : it2->second) h();
|
||||
|
||||
if (newState == m_currentState) {
|
||||
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Attempted to set same state: %s", getStateName(newState));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!canTransitionTo(newState)) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Invalid state transition from %s to %s",
|
||||
getStateName(m_currentState), getStateName(newState));
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "State transition: %s -> %s",
|
||||
getStateName(m_currentState), getStateName(newState));
|
||||
|
||||
// Execute exit hooks for current state
|
||||
executeExitHooks(m_currentState);
|
||||
|
||||
// Update state
|
||||
m_previousState = m_currentState;
|
||||
m_currentState = newState;
|
||||
|
||||
// Execute enter hooks for new state
|
||||
executeEnterHooks(m_currentState);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StateManager::handleEvent(const SDL_Event& event) {
|
||||
auto it = m_eventHandlers.find(stateToInt(m_currentState));
|
||||
if (it == m_eventHandlers.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& handler : it->second) {
|
||||
try {
|
||||
handler(event);
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Exception in event handler for state %s: %s",
|
||||
getStateName(m_currentState), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppState StateManager::getState() const { return currentState; }
|
||||
void StateManager::update(float deltaTime) {
|
||||
auto it = m_updateHandlers.find(stateToInt(m_currentState));
|
||||
if (it == m_updateHandlers.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
void StateManager::handleEvent(const SDL_Event& e) {
|
||||
auto it = handlers.find(static_cast<int>(currentState));
|
||||
if (it == handlers.end()) return;
|
||||
for (auto &h : it->second) h(e);
|
||||
for (auto& handler : it->second) {
|
||||
try {
|
||||
handler(deltaTime);
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Exception in update handler for state %s: %s",
|
||||
getStateName(m_currentState), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StateManager::render(RenderManager& renderer) {
|
||||
auto it = m_renderHandlers.find(stateToInt(m_currentState));
|
||||
if (it == m_renderHandlers.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& handler : it->second) {
|
||||
try {
|
||||
handler(renderer);
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Exception in render handler for state %s: %s",
|
||||
getStateName(m_currentState), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool StateManager::isValidState(AppState state) const {
|
||||
// All enum values are currently valid
|
||||
return static_cast<int>(state) >= static_cast<int>(AppState::Loading) &&
|
||||
static_cast<int>(state) <= static_cast<int>(AppState::GameOver);
|
||||
}
|
||||
|
||||
bool StateManager::canTransitionTo(AppState newState) const {
|
||||
// For now, allow all transitions. Can be enhanced later with state machine validation
|
||||
return isValidState(newState);
|
||||
}
|
||||
|
||||
const char* StateManager::getStateName(AppState state) const {
|
||||
switch (state) {
|
||||
case AppState::Loading: return "Loading";
|
||||
case AppState::Menu: return "Menu";
|
||||
case AppState::LevelSelector: return "LevelSelector";
|
||||
case AppState::Playing: return "Playing";
|
||||
case AppState::LevelSelect: return "LevelSelect";
|
||||
case AppState::GameOver: return "GameOver";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void StateManager::executeEnterHooks(AppState state) {
|
||||
auto it = m_onEnterHooks.find(stateToInt(state));
|
||||
if (it == m_onEnterHooks.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& hook : it->second) {
|
||||
try {
|
||||
hook();
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Exception in enter hook for state %s: %s",
|
||||
getStateName(state), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StateManager::executeExitHooks(AppState state) {
|
||||
auto it = m_onExitHooks.find(stateToInt(state));
|
||||
if (it == m_onExitHooks.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& hook : it->second) {
|
||||
try {
|
||||
hook();
|
||||
} catch (const std::exception& e) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Exception in exit hook for state %s: %s",
|
||||
getStateName(state), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,8 +3,12 @@
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
// Forward declarations
|
||||
class RenderManager;
|
||||
|
||||
// Application states used across the app
|
||||
enum class AppState {
|
||||
Loading,
|
||||
@ -15,28 +19,68 @@ enum class AppState {
|
||||
GameOver
|
||||
};
|
||||
|
||||
// State manager used by main to route events and lifecycle hooks
|
||||
/**
|
||||
* Enhanced StateManager - Manages application state transitions and lifecycle
|
||||
*
|
||||
* Improvements over original:
|
||||
* - Better error handling and validation
|
||||
* - Support for update and render cycles
|
||||
* - State transition validation
|
||||
* - Logging for debugging
|
||||
* - Cleaner API design
|
||||
*/
|
||||
class StateManager {
|
||||
public:
|
||||
using EventHandler = std::function<void(const SDL_Event&)>;
|
||||
using UpdateHandler = std::function<void(float deltaTime)>;
|
||||
using RenderHandler = std::function<void(RenderManager& renderer)>;
|
||||
using Hook = std::function<void()>;
|
||||
|
||||
StateManager(AppState initial);
|
||||
~StateManager() = default;
|
||||
|
||||
void registerHandler(AppState s, EventHandler h);
|
||||
void registerOnEnter(AppState s, Hook h);
|
||||
void registerOnExit(AppState s, Hook h);
|
||||
// State registration
|
||||
void registerEventHandler(AppState state, EventHandler handler);
|
||||
void registerUpdateHandler(AppState state, UpdateHandler handler);
|
||||
void registerRenderHandler(AppState state, RenderHandler handler);
|
||||
void registerOnEnter(AppState state, Hook hook);
|
||||
void registerOnExit(AppState state, Hook hook);
|
||||
|
||||
// Legacy compatibility
|
||||
void registerHandler(AppState s, EventHandler h) { registerEventHandler(s, std::move(h)); }
|
||||
void registerHandler(AppState s, std::function<void()> h); // overload used in some places
|
||||
|
||||
void setState(AppState s);
|
||||
AppState getState() const;
|
||||
// State management
|
||||
bool setState(AppState newState);
|
||||
AppState getState() const { return m_currentState; }
|
||||
AppState getPreviousState() const { return m_previousState; }
|
||||
|
||||
void handleEvent(const SDL_Event& e);
|
||||
// State operations
|
||||
void handleEvent(const SDL_Event& event);
|
||||
void update(float deltaTime);
|
||||
void render(RenderManager& renderer);
|
||||
|
||||
// Validation
|
||||
bool isValidState(AppState state) const;
|
||||
bool canTransitionTo(AppState newState) const;
|
||||
|
||||
// Utility
|
||||
const char* getStateName(AppState state) const;
|
||||
|
||||
private:
|
||||
AppState currentState;
|
||||
std::unordered_map<int, std::vector<EventHandler>> handlers;
|
||||
std::unordered_map<int, std::vector<Hook>> onEnter;
|
||||
std::unordered_map<int, std::vector<Hook>> onExit;
|
||||
// State data
|
||||
AppState m_currentState;
|
||||
AppState m_previousState;
|
||||
|
||||
// Handler storage
|
||||
std::unordered_map<int, std::vector<EventHandler>> m_eventHandlers;
|
||||
std::unordered_map<int, std::vector<UpdateHandler>> m_updateHandlers;
|
||||
std::unordered_map<int, std::vector<RenderHandler>> m_renderHandlers;
|
||||
std::unordered_map<int, std::vector<Hook>> m_onEnterHooks;
|
||||
std::unordered_map<int, std::vector<Hook>> m_onExitHooks;
|
||||
|
||||
// Helper methods
|
||||
void executeEnterHooks(AppState state);
|
||||
void executeExitHooks(AppState state);
|
||||
int stateToInt(AppState state) const { return static_cast<int>(state); }
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user