diff --git a/Makefile.common b/Makefile.common index c73a30594..abd6c087a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -2,7 +2,7 @@ CXX=g++ CXXFLAGS=-Wall -g -O2 LDFLAGS= -SRC_SOURCES=AudioManager.cpp InputConfig.cpp Log.cpp FolderData.cpp Font.cpp GameData.cpp GuiComponent.cpp InputManager.cpp main.cpp MathExp.cpp Renderer.cpp Renderer_draw_gl.cpp Renderer_init.cpp Sound.cpp SystemData.cpp XMLReader.cpp components/GuiAnimation.cpp components/GuiBox.cpp components/GuiFastSelect.cpp components/GuiGameList.cpp components/GuiImage.cpp components/GuiInputConfig.cpp components/GuiMenu.cpp components/GuiTheme.cpp pugiXML/pugixml.cpp +SRC_SOURCES=AudioManager.cpp InputConfig.cpp Log.cpp FolderData.cpp Font.cpp GameData.cpp Gui.cpp InputManager.cpp main.cpp MathExp.cpp Renderer_draw_gl.cpp Renderer_init.cpp Sound.cpp SystemData.cpp XMLReader.cpp components/GuiAnimation.cpp components/GuiBox.cpp components/GuiFastSelect.cpp components/GuiGameList.cpp components/GuiImage.cpp components/GuiInputConfig.cpp components/GuiMenu.cpp components/GuiTheme.cpp pugiXML/pugixml.cpp SOURCES=$(addprefix src/,$(SRC_SOURCES)) OBJECTS=$(SOURCES:.cpp=.o) DEPS=$(SOURCES:.cpp=.d) diff --git a/src/Gui.cpp b/src/Gui.cpp new file mode 100644 index 000000000..a51730dc9 --- /dev/null +++ b/src/Gui.cpp @@ -0,0 +1,11 @@ +#include "Gui.h" +#include "Window.h" + +Gui::Gui(Window* window) : mWindow(window) +{ +} + +Gui::~Gui() +{ + mWindow->removeGui(this); +} diff --git a/src/Gui.h b/src/Gui.h new file mode 100644 index 000000000..8b4d0d7c8 --- /dev/null +++ b/src/Gui.h @@ -0,0 +1,21 @@ +#ifndef _GUI_H_ +#define _GUI_H_ + +#include "InputConfig.h" + +class Window; + +class Gui +{ +public: + Gui(Window* window); + virtual ~Gui(); + + virtual void input(InputConfig* config, Input input) = 0; + virtual void update(int deltaTime) = 0; + virtual void render() = 0; +protected: + Window* mWindow; +}; + +#endif \ No newline at end of file diff --git a/src/GuiComponent.cpp b/src/GuiComponent.cpp deleted file mode 100644 index 1013f91db..000000000 --- a/src/GuiComponent.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "GuiComponent.h" -#include "Renderer.h" -#include -#include "Log.h" - -std::vector GuiComponent::sComponentVector; - -GuiComponent::GuiComponent() -{ - sComponentVector.push_back(this); - - mOffsetX = 0; - mOffsetY = 0; - mOpacity = 255; -} - -GuiComponent::~GuiComponent() -{ - for(unsigned int i = 0; i < sComponentVector.size(); i++) - { - if(sComponentVector.at(i) == this) - { - sComponentVector.erase(sComponentVector.begin() + i); - } - } -} - -void GuiComponent::addChild(GuiComponent* comp) -{ - mChildren.push_back(comp); -} - -void GuiComponent::removeChild(GuiComponent* comp) -{ - for(unsigned int i = 0; i < mChildren.size(); i++) - { - if(mChildren.at(i) == comp) - { - mChildren.erase(mChildren.begin() + i); - return; - } - } - - LOG(LogError) << "Error - tried to remove GuiComponent child, but couldn't find it!"; -} - -void GuiComponent::clearChildren() -{ - mChildren.clear(); -} - -void GuiComponent::processTicks(int deltaTime) -{ - for(unsigned int i = 0; i < sComponentVector.size(); i++) - { - sComponentVector.at(i)->onTick(deltaTime); - } -} - -void GuiComponent::render() -{ - onRender(); - - for(unsigned int i = 0; i < mChildren.size(); i++) - { - mChildren.at(i)->render(); - } -} - -void GuiComponent::pause() -{ - onPause(); - - for(unsigned int i = 0; i < mChildren.size(); i++) - mChildren.at(i)->pause(); -} - -void GuiComponent::resume() -{ - onResume(); - - for(unsigned int i = 0; i < mChildren.size(); i++) - mChildren.at(i)->resume(); -} - -void GuiComponent::init() -{ - onInit(); - - for(unsigned int i = 0; i < mChildren.size(); i++) - { - mChildren.at(i)->init(); - } -} - -void GuiComponent::deinit() -{ - onDeinit(); - - for(unsigned int i = 0; i < mChildren.size(); i++) - { - mChildren.at(i)->deinit(); - } -} - -void GuiComponent::setOffsetX(int val) { mOffsetX = val; } -void GuiComponent::setOffsetY(int val) { mOffsetY = val; } -void GuiComponent::setOffset(int x, int y) { mOffsetX = x; mOffsetY = y; } -int GuiComponent::getOffsetX() { return mOffsetX; } -int GuiComponent::getOffsetY() { return mOffsetY; } - -void GuiComponent::setOpacity(unsigned char opacity) { mOpacity = opacity; } -unsigned char GuiComponent::getOpacity() { return mOpacity; } diff --git a/src/GuiComponent.h b/src/GuiComponent.h deleted file mode 100644 index 0594c508e..000000000 --- a/src/GuiComponent.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _GUICOMPONENT_H_ -#define _GUICOMPONENT_H_ - -#include -#include "Renderer.h" -#include "InputManager.h" - -/* -The GuiComponent class is what everything that is rendered, updated by time (ticking), or takes input is subclassed from. -GuiComponents have a list of child GuiComponents. Rendering, ticking, pausing/resuming, init/deinit, are all automatically sent to children. -You can rely on the parent getting called first - this way, you can control what order components are rendered in. -You can also manually call the render/pause/resume/init/deinit methods if you so desire (e.g. want a child to render *before* its parent). - -To make a GuiComponent render/take input, you must register with the Renderer or InputManager respectively (Renderer::registerComponent(comp) or InputManager::registerComponent(comp)). -All components are automatically ticked every frame, just add an onTick(int deltaTime) method. -onInput calls arrive before onRender calls. -*/ - -class GuiComponent -{ -public: - GuiComponent(); - virtual ~GuiComponent(); - - void render(); - virtual void onRender() { }; - virtual void onTick(int deltaTime) { }; - - void pause(); - void resume(); - virtual void onPause() { }; - virtual void onResume() { }; - - void init(); - void deinit(); - virtual void onInit() { }; - virtual void onDeinit() { }; - - virtual void onInput(InputManager::InputButton button, bool keyDown) { }; - - void addChild(GuiComponent* comp); - void removeChild(GuiComponent* comp); - void clearChildren(); - unsigned int getChildCount() { return mChildren.size(); } - GuiComponent* getChild(unsigned int i) { return mChildren.at(i); } - - - int getOffsetX(); - int getOffsetY(); - void setOffsetX(int val); - void setOffsetY(int val); - void setOffset(int x, int y); - - unsigned char getOpacity(); - void setOpacity(unsigned char opacity); - - static void processTicks(int deltaTime); - -private: - int mOffsetX, mOffsetY; - - unsigned char mOpacity; - - static std::vector sComponentVector; - std::vector mChildren; -}; - -#endif diff --git a/src/InputManager.cpp b/src/InputManager.cpp index c347757ef..0086475c8 100644 --- a/src/InputManager.cpp +++ b/src/InputManager.cpp @@ -1,311 +1,151 @@ #include "InputManager.h" -#include "GuiComponent.h" +#include "InputConfig.h" +#include "Window.h" #include -#include -#include -#include "Log.h" -std::vector InputManager::inputVector; -SDL_Event* InputManager::lastEvent = NULL; - -std::map InputManager::joystickButtonMap, InputManager::joystickAxisPosMap, InputManager::joystickAxisNegMap; -std::map InputManager::axisState; -InputManager::InputButton InputManager::hatState = InputManager::UNKNOWN; -std::string InputManager::joystickName = ""; - -int InputManager::deadzone = 28000; - -void InputManager::registerComponent(GuiComponent* comp) +InputManager::InputManager(Window* window) : mWindow(window) { - inputVector.push_back(comp); + mJoysticks = NULL; + mKeyboardInputConfig = NULL; + mNumJoysticks = 0; + mNumPlayers = 0; } -void InputManager::unregisterComponent(GuiComponent* comp) +InputManager::~InputManager() { - for(unsigned int i = 0; i < inputVector.size(); i++) - { - if(inputVector.at(i) == comp) - { - inputVector.erase(inputVector.begin() + i); - break; - } - } + deinit(); } -InputManager::InputButton InputManager::processEvent(SDL_Event* event) +void InputManager::init() { - bool keyDown = false; - InputButton button = UNKNOWN; + if(mJoysticks != NULL) + deinit(); - lastEvent = event; + SDL_InitSubSystem(SDL_INIT_JOYSTICK); - //keyboard events - if(event->type == SDL_KEYDOWN || event->type == SDL_KEYUP) + mNumJoysticks = SDL_NumJoysticks(); + mJoysticks = new SDL_Joystick*[mNumJoysticks]; + mInputConfigs = new InputConfig*[mNumJoysticks]; + mPrevAxisValues = new std::map[mNumJoysticks]; + + for(int i = 0; i < mNumJoysticks; i++) { - if(event->key.state == SDL_PRESSED) - keyDown = true; + mJoysticks[i] = SDL_JoystickOpen(i); + mInputConfigs[i] = new InputConfig(i); - //get InputButton from the event - switch(event->key.keysym.sym) + for(int k = 0; k < SDL_JoystickNumAxes(mJoysticks[i]); k++) { - case SDLK_LEFT: - button = LEFT; - break; - case SDLK_RIGHT: - button = RIGHT; - break; - case SDLK_UP: - button = UP; - break; - case SDLK_DOWN: - button = DOWN; - break; - case SDLK_PAGEUP: - button = PAGEUP; - break; - case SDLK_RIGHTBRACKET: - button = PAGEUP; - break; - case SDLK_PAGEDOWN: - button = PAGEDOWN; - break; - case SDLK_LEFTBRACKET: - button = PAGEDOWN; - break; - case SDLK_RETURN: - button = BUTTON1; - break; - case SDLK_ESCAPE: - button = BUTTON2; - break; - case SDLK_F1: - button = MENU; - break; - case SDLK_F2: - button = SELECT; - break; - - default: - button = UNKNOWN; - break; - } - - //catch emergency quit event - if(event->key.keysym.sym == SDLK_F4 && keyDown) - { - //I have no idea if SDL will delete this event, but we're quitting, so I don't think it really matters - SDL_Event* quit = new SDL_Event(); - quit->type = SDL_QUIT; - SDL_PushEvent(quit); - LOG(LogInfo) << "Pushing quit event."; - } - }else{ - if(event->type == SDL_JOYBUTTONDOWN || event->type == SDL_JOYBUTTONUP) //joystick button events - { - if(event->type == SDL_JOYBUTTONDOWN) //defaults to false, so no else - keyDown = true; - - button = joystickButtonMap[event->jbutton.button]; - }else{ - if(event->type == SDL_JOYHATMOTION) - { - int hat = event->jhat.value; - - if(hat == 0) //centered - { - //we need to send a keyUp event for the last hat - //keyDown is already false - button = hatState; - }else{ - keyDown = true; - } - - if(hat & SDL_HAT_LEFT) - button = LEFT; - if(hat & SDL_HAT_RIGHT) - button = RIGHT; - - if(hat & SDL_HAT_UP) - button = UP; - if(hat & SDL_HAT_DOWN) - button = DOWN; - - if(button == hatState && keyDown) - { - //ignore this hat event since the user most likely just made it a diagonal (but it still is using the old direction) - button = UNKNOWN; - }else{ - if(hatState != UNKNOWN && keyDown) - { - //this will occur if the user went down -> downLeft -> Left or similar - button = hatState; - keyDown = false; - hatState = UNKNOWN; - processEvent(event); - }else{ - if(!keyDown) - hatState = UNKNOWN; - else - hatState = button; - } - } - - }else{ - if(event->type == SDL_JOYAXISMOTION) - { - int axis = event->jaxis.axis; - int value = event->jaxis.value; - - //if this axis was previously not centered, it can only keyUp - if(axisState[axis] != 0) - { - if(abs(value) < deadzone) //if it has indeed centered - { - if(axisState[axis] > 0) - button = joystickAxisPosMap[axis]; - else - button = joystickAxisNegMap[axis]; - axisState[axis] = 0; - } - }else{ - if(value > deadzone) - { - //axisPos keyDown - axisState[axis] = 1; - keyDown = true; - button = joystickAxisPosMap[axis]; - }else if(value < -deadzone) - { - axisState[axis] = -1; - keyDown = true; - button = joystickAxisNegMap[axis]; - } - } - } - } + mPrevAxisValues[i][k] = 0; } } - for(unsigned int i = 0; i < inputVector.size(); i++) - { - inputVector.at(i)->onInput(button, keyDown); - } - - return button; -} - -void InputManager::loadConfig() -{ - LOG(LogDebug) << "Loading input config..."; - - //clear any old config - joystickButtonMap.clear(); - joystickAxisPosMap.clear(); - joystickAxisNegMap.clear(); - - std::string path = getConfigPath(); - - std::ifstream file(path.c_str()); - - joystickName = ""; - - while(file.good()) - { - std::string line; - std::getline(file, line); - - //skip blank lines and comments - if(line.empty() || line[0] == *"#") - continue; - - - //I know I could probably just read from the file stream directly, but I feel it would be harder to catch errors in a readable way - std::istringstream stream(line); - - std::string token[3]; - int tokNum = 0; - - while(std::getline(stream, token[tokNum], ' ')) - { - tokNum++; - - //JOYNAME can have spaces - if(tokNum == 1 && token[0] == "JOYNAME") - { - std::getline(stream, token[1]); - break; - } - - if(tokNum >= 3) - break; - } - - - if(token[0] == "BUTTON") - { - joystickButtonMap[atoi(token[1].c_str())] = (InputButton)atoi(token[2].c_str()); - }else if(token[0] == "AXISPOS") - { - joystickAxisPosMap[atoi(token[1].c_str())] = (InputButton)atoi(token[2].c_str()); - }else if(token[0] == "AXISNEG") - { - joystickAxisNegMap[atoi(token[1].c_str())] = (InputButton)atoi(token[2].c_str()); - }else if(token[0] == "JOYNAME") - { - joystickName = token[1]; - }else{ - LOG(LogWarning) << "Invalid input type - " << token[0]; - return; - } - - } - - LOG(LogDebug) << "Finished loading input config"; - - openJoystick(); -} - -void InputManager::openJoystick() -{ - //if any joystick is plugged in - if(SDL_NumJoysticks() > 0) - { - if(!joystickName.empty()) - { - LOG(LogDebug) << " attempting to open joystick of name \"" << joystickName << "\""; - - bool found = false; - for(int i = 0; i < SDL_NumJoysticks(); i++) - { - if(strcmp(SDL_JoystickName(i), joystickName.c_str()) == 0) - { - LOG(LogDebug) << " found, opening joystick " << joystickName << " at " << i; - - SDL_JoystickOpen(i); - found = true; - break; - } - } - - if(!found) - { - LOG(LogWarning) << " could not find named joystick! You could try manually removing the joystick name entry in the input config file."; - } - }else{ - LOG(LogDebug) << " opening first joystick (no name saved)"; - - SDL_JoystickOpen(0); //if we don't have a specific joystick in mind, take the first - } - }else{ - LOG(LogDebug) << " no joysticks detected by SDL_NumJoysticks(), so no joystick opened"; - } + mKeyboardInputConfig = new InputConfig(DEVICE_KEYBOARD); SDL_JoystickEventState(SDL_ENABLE); } -std::string InputManager::getConfigPath() +void InputManager::deinit() { - std::string home = getenv("HOME"); - home += "/.emulationstation/es_input.cfg"; - return home; + SDL_JoystickEventState(SDL_DISABLE); + + if(!SDL_WasInit(SDL_INIT_JOYSTICK)) + return; + + if(mJoysticks != NULL) + { + for(int i = 0; i < mNumJoysticks; i++) + { + SDL_JoystickClose(mJoysticks[i]); + delete mInputConfigs[i]; + } + + delete mKeyboardInputConfig; + + delete[] mJoysticks; + delete[] mInputConfigs; + delete[] mPrevAxisValues; + mJoysticks = NULL; + mKeyboardInputConfig = NULL; + mInputConfigs = NULL; + } + + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); +} + +int InputManager::getNumJoysticks() { return mNumJoysticks; } + +int InputManager::getNumPlayers() { return mNumPlayers; } +void InputManager::setNumPlayers(int num) { mNumPlayers = num; } + +InputConfig* InputManager::getInputConfigByDevice(int device) +{ + if(device == DEVICE_KEYBOARD) + return mKeyboardInputConfig; + else + return mInputConfigs[device]; +} + +InputConfig* InputManager::getInputConfigByPlayer(int player) +{ + if(mKeyboardInputConfig->getPlayerNum() == player) + return mKeyboardInputConfig; + + for(int i = 0; i < mNumJoysticks; i++) + { + if(mInputConfigs[i]->getPlayerNum() == player) + return mInputConfigs[i]; + } + + std::cout << "Could not find input config for player number " << player << "!\n"; + return NULL; +} + +void InputManager::parseEvent(const SDL_Event& ev) +{ + switch(ev.type) + { + case SDL_JOYAXISMOTION: + //if it switched boundaries + if((abs(ev.jaxis.value) > DEADZONE) != (abs(mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis]) > DEADZONE)) + { + int normValue; + if(abs(ev.jaxis.value) <= DEADZONE) + normValue = 0; + else + if(ev.jaxis.value > 0) + normValue = 1; + else + normValue = -1; + + mWindow->input(getInputConfigByDevice(ev.jaxis.which), Input(ev.jaxis.which, TYPE_AXIS, ev.jaxis.axis, normValue, false)); + } + + mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis] = ev.jaxis.value; + break; + + case SDL_JOYBUTTONDOWN: + case SDL_JOYBUTTONUP: + mWindow->input(getInputConfigByDevice(ev.jbutton.which), Input(ev.jbutton.which, TYPE_BUTTON, ev.jbutton.button, ev.jbutton.state == SDL_PRESSED, false)); + break; + + case SDL_JOYHATMOTION: + mWindow->input(getInputConfigByDevice(ev.jhat.which), Input(ev.jhat.which, TYPE_HAT, ev.jhat.hat, ev.jhat.value, false)); + break; + + case SDL_KEYDOWN: + if(ev.key.keysym.sym == SDLK_F4) + { + SDL_Event* quit = new SDL_Event(); + quit->type = SDL_QUIT; + SDL_PushEvent(quit); + return; + } + + mWindow->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, ev.key.keysym.sym, 1, false)); + break; + + case SDL_KEYUP: + mWindow->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, ev.key.keysym.sym, 0, false)); + break; + } } diff --git a/src/InputManager.h b/src/InputManager.h index 4e91ff939..274bf355b 100644 --- a/src/InputManager.h +++ b/src/InputManager.h @@ -1,37 +1,46 @@ #ifndef _INPUTMANAGER_H_ #define _INPUTMANAGER_H_ +#include #include -#include #include -#include -class GuiComponent; +class InputConfig; +class Window; -//The InputManager takes native system input and abstracts it into InputButtons. -//GuiComponents can be registered to receive onInput() events. -namespace InputManager { - void registerComponent(GuiComponent* comp); - void unregisterComponent(GuiComponent* comp); +//you should only ever instantiate one of these, by the way +class InputManager +{ +public: + InputManager(Window* window); + ~InputManager(); - void loadConfig(); - void openJoystick(); + void init(); + void deinit(); - //enum for identifying input, regardless of configuration - enum InputButton { UNKNOWN, UP, DOWN, LEFT, RIGHT, BUTTON1, BUTTON2, MENU, SELECT, PAGEUP, PAGEDOWN}; + void setNumPlayers(int num); + int getNumPlayers(); - InputButton processEvent(SDL_Event* event); + int getNumJoysticks(); - extern std::vector inputVector; - extern SDL_Event* lastEvent; //mostly for GuiInputConfig - extern int deadzone; - std::string getConfigPath(); + void parseEvent(const SDL_Event& ev); - extern std::map joystickButtonMap; - extern std::map joystickAxisPosMap, joystickAxisNegMap; - extern std::map axisState; - extern InputButton hatState; - extern std::string joystickName; -} + InputConfig* getInputConfigByPlayer(int player); + +private: + static const int DEADZONE = 23000; + + Window* mWindow; + + //non-InputManager classes shouldn't use this, as you can easily miss the keyboard + InputConfig* getInputConfigByDevice(int device); + + int mNumJoysticks; + int mNumPlayers; + SDL_Joystick** mJoysticks; + InputConfig** mInputConfigs; + InputConfig* mKeyboardInputConfig; + std::map* mPrevAxisValues; +}; #endif diff --git a/src/Renderer.cpp b/src/Renderer.cpp deleted file mode 100644 index 909f5ad4f..000000000 --- a/src/Renderer.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include "Renderer.h" -#include "GuiComponent.h" - -std::vector renderVector; - -void Renderer::registerComponent(GuiComponent* comp) -{ - renderVector.push_back(comp); -} - -void Renderer::unregisterComponent(GuiComponent* comp) -{ - for(unsigned int i = 0; i < renderVector.size(); i++) - { - if(renderVector.at(i) == comp) - { - renderVector.erase(renderVector.begin() + i); - break; - } - } -} - -void Renderer::deleteAll() -{ - for(unsigned int i = 0; i < renderVector.size(); i++) - { - delete renderVector.at(i); - } - renderVector.clear(); -} - -void Renderer::render() -{ - for(unsigned int i = 0; i < renderVector.size(); i++) - { - renderVector.at(i)->render(); - } -} - -void Renderer::onInit() -{ - for(unsigned int i = 0; i < renderVector.size(); i++) - { - renderVector.at(i)->init(); - } -} - -void Renderer::onDeinit() -{ - for(unsigned int i = 0; i < renderVector.size(); i++) - { - renderVector.at(i)->deinit(); - } -} diff --git a/src/Window.cpp b/src/Window.cpp new file mode 100644 index 000000000..4efcdd5dd --- /dev/null +++ b/src/Window.cpp @@ -0,0 +1,70 @@ +#include "Window.h" +#include + +Window::Window() +{ + mInputManager = new InputManager(this); +} + +Window::~Window() +{ + delete mInputManager; +} + +void Window::pushGui(Gui* gui) +{ + mGuiStack.push_back(gui); +} + +void Window::removeGui(Gui* gui) +{ + for(unsigned int i = 0; i < mGuiStack.size(); i++) + { + if(mGuiStack.at(i) == gui) + { + mGuiStack.erase(mGuiStack.begin() + i); + break; + } + } +} + +Gui* Window::peekGui() +{ + if(mGuiStack.size() == 0) + return NULL; + + return mGuiStack.at(mGuiStack.size() - 1); +} + +void Window::render() +{ + if(mGuiStack.size() == 0) + std::cout << "guistack empty\n"; + + for(unsigned int i = 0; i < mGuiStack.size(); i++) + { + mGuiStack.at(i)->render(); + } +} + +void Window::input(InputConfig* config, Input input) +{ + if(peekGui()) + this->peekGui()->input(config, input); +} + +void Window::update(int deltaTime) +{ + if(peekGui()) + peekGui()->update(deltaTime); +} + +InputManager* Window::getInputManager() +{ + return mInputManager; +} + +asIScriptEngine* Window::getScriptEngine() +{ + return mScriptEngine; +} diff --git a/src/Window.h b/src/Window.h new file mode 100644 index 000000000..c54358f8e --- /dev/null +++ b/src/Window.h @@ -0,0 +1,29 @@ +#ifndef _WINDOW_H_ +#define _WINDOW_H_ + +#include "Gui.h" +#include "InputManager.h" +#include + +class Window +{ +public: + Window(); + ~Window(); + + void pushGui(Gui* gui); + void removeGui(Gui* gui); + Gui* peekGui(); + + void input(InputConfig* config, Input input); + void update(int deltaTime); + void render(); + + InputManager* getInputManager(); + +private: + InputManager* mInputManager; + std::vector mGuiStack; +}; + +#endif