jubilant-funicular
ScreenManager.cpp
1 #include <queue>
2 
3 #include <GL/glew.h>
4 
5 #ifdef NTA_USE_IMGUI
6  #include <imgui/imgui.h>
7  #include <imgui/imgui_impl_sdl.h>
8  #include <imgui/imgui_impl_opengl3.h>
9 #endif
10 
11 #include "nta/ScreenManager.h"
12 #include "nta/WindowManager.h"
13 #include "nta/CallbackManager.h"
14 #include "nta/Logger.h"
15 #include "nta/utils.h"
16 
17 namespace nta {
18  std::mutex ScreenManager::m_window_creation_lock;
19  std::mutex ScreenManager::m_event_lock;
20  ScreenManager::ScreenManager(crstring title, float maxFPS, int width, int height) : m_input(CreateInputManagerKey()) {
21  std::lock_guard<std::mutex> g(m_window_creation_lock);
22  m_window = WindowManager::getWindow(title, width, height);
23  m_limiter.setMaxFPS(maxFPS);
24  }
26  if (!m_screens.empty()) destroy();
27  }
30  return utils::in_range<int>(m_currScreen, 0, m_screens.size()-1) ? m_screens[m_currScreen] : nullptr;
31  }
32  float ScreenManager::getFPS() const {
33  return m_limiter.getFPS();
34  }
36  const utils::Path& glsl_fldr,
37  const utils::Path& font_fldr) {
39  m_context_data.setGLSLFolder(glsl_fldr);
40  m_context_data.setFontFolder(font_fldr);
41  }
42  void ScreenManager::addScreen(Screen* newScreen, int escIndex, int xIndex, crstring title) {
43  Logger::writeToLog("Adding screen " + utils::to_string(m_screens.size()) +
44  " (\"" + newScreen->getName() + "\") to ScreenManager...");
46  m_currScreen = m_screens.empty() ? 0 : m_currScreen;
47  newScreen->setManager(this, SetManagerKey());
48  newScreen->setIndices(m_screens.size(), escIndex, xIndex, SetIndicesKey());
49  newScreen->setWindow((title == "") ? m_window->getTitle() : title, SetWindowKey());
50  newScreen->init();
51  m_screens.push_back(newScreen);
52  check_error();
54  Logger::writeToLog("Added screen");
55  }
56  void ScreenManager::switchScreen(int newIndex) {
57  if (utils::in_range<int>(newIndex, 0, m_screens.size()-1)) {
58  Logger::writeToLog("Switching from screen " + utils::to_string(m_currScreen) +
59  " (\"" + getCurrScreen()->getName() + "\") to screen " +
60  utils::to_string(newIndex) + " (\"" + m_screens[newIndex]->getName() +
61  "\")...");
64  Logger::writeToLog("called offFocus");
65  check_error();
66  ScreenSwitchInfo info(getCurrScreen()->getSwitchData(), m_currScreen);
67  m_currScreen = newIndex;
68  getCurrScreen()->onFocus(info);
69  Logger::writeToLog("called onFocus");
70  check_error();
72  Logger::writeToLog("Switched screen");
73  } else if (newIndex == -1) {
74  Logger::writeToLog("Exiting ScreenManager...");
76  m_currScreen = -1;
77  }
78  }
79  bool ScreenManager::owns_event(const SDL_Event& event) const {
80  switch(event.type) {
81  case SDL_WINDOWEVENT: return m_window->getID() == event.window.windowID;
82  case SDL_KEYDOWN: case SDL_KEYUP: return m_window->hasKeyboardFocus();
83  case SDL_MOUSEMOTION: case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: case SDL_MOUSEWHEEL: return m_window->hasMouseFocus();
84  }
85  return true;
86  }
88  //SDL_PumpEvents();
89  std::lock_guard<std::mutex> g(m_event_lock);
90 
91  if (m_window->hasKeyboardFocus()) {
93  }
94  if (m_window->hasMouseFocus()) {
95  m_input.setMouseWheelMotion(MouseWheelMotion::STATIONARY);
96  }
97 
98  std::queue<SDL_Event> skipped_events;
99 
100  SDL_Event e;
101  while (SDL_PollEvent(&e)) {
102  if (!owns_event(e)) {
103  skipped_events.push(e);
104  continue;
105  }
106 
107  switch(e.type) {
108  case SDL_WINDOWEVENT: {
109  switch(e.window.event) {
110  case SDL_WINDOWEVENT_RESIZED:
111  glViewport(0, 0, e.window.data1, e.window.data2);
112  m_window->setDimensions(e.window.data1, e.window.data2);
113  break;
114  case SDL_WINDOWEVENT_ENTER:
115  Window::setMouseFocus(e.window.windowID);
116  break;
117  case SDL_WINDOWEVENT_FOCUS_GAINED:
118  Window::setKeyboardFocus(e.window.windowID);
119  break;
120  case SDL_WINDOWEVENT_CLOSE:
121  getCurrScreen()->close();
122  break;
123  }
124  } break;
125  }
126 
127  m_input.update(e);
128  #ifdef NTA_USE_IMGUI
129  ImGui_ImplSDL2_ProcessEvent(&e);
130  #endif
131  }
132  while (!skipped_events.empty()) {
133  SDL_PushEvent(&skipped_events.front());
134  skipped_events.pop();
135  }
136 
137  if (m_input.justPressed(SDLK_ESCAPE)) {
138  getCurrScreen()->esc();
139  }
140  }
141  void ScreenManager::run(void* initFocusData) {
142  Logger::writeToLog("Running ScreenManager...");
143  Screen* currScreen = nullptr;
144  if (m_currScreen != -1) {
145  getCurrScreen()->onFocus(ScreenSwitchInfo(initFocusData));
146  }
147  while (m_currScreen != -1) {
148  currScreen = getCurrScreen();
149  // This while loop used to be neat
150  while (currScreen->getState() == ScreenState::RUNNING) {
151  m_limiter.begin();
153  update_input();
154  currScreen->update();
155  #ifdef NTA_USE_IMGUI
156  ImGui_ImplOpenGL3_NewFrame();
157  ImGui_ImplSDL2_NewFrame(m_window->getSDLWindow(GetSDLWindowKey()));
158  ImGui::NewFrame();
159  #endif
160  currScreen->render();
161  check_error();
163  m_limiter.end();
164  }
165  switch(currScreen->getState()) {
166  case ScreenState::SWITCH: switchScreen(currScreen->getNextIndex()); break;
167  case ScreenState::SWITCH_ESC: switchScreen(currScreen->getEscIndex()); break;
168  case ScreenState::SWITCH_X: switchScreen(currScreen->getXIndex()); break;
169  case ScreenState::NONE: Logger::writeErrorToLog("state of screen " +
171  " is NONE",
172  IMPOSSIBLE_BEHAVIOR); break;
173  default: break; // should never happen
174  }
175  }
176  Logger::writeToLog("Exited ScreenManager");
177  }
179  Logger::writeToLog("Destroying ScreenManager...");
180  Logger::indent();
181  for (auto screen : m_screens) {
182  Logger::writeToLog("Destroying Screen \"" + screen->getName() + "\"...");
183  Logger::indent();
184  delete screen;
186  Logger::writeToLog("Destroyed Screen");
187  }
188  m_screens.clear();
190  // Not sure how I feel about this
191  WindowManager::destroyWindow(m_window->getTitle());
193  Logger::writeToLog("Destroyed ScreenManager");
194  }
195 }
nta::Screen::getName
std::string getName() const
gets name of screen
Definition: Screen.cpp:19
nta::Window::setDimensions
void setDimensions(int width, int height)
updates the window's stored dimensions
Definition: Window.cpp:65
nta::ScreenManager::run
void run(void *initFocusData=nullptr)
Definition: ScreenManager.cpp:141
nta::Screen::setManager
void setManager(ScreenManager *manager, SetManagerKey key)
Sets the manager of this screen.
Definition: Screen.cpp:37
nta::Screen::setWindow
void setWindow(crstring title, SetWindowKey key)
sets the window to associate with this screen
Definition: Screen.cpp:45
nta::SetManagerKey
Key unlocking the setManager() "private" function of class Screen.
Definition: Screen.h:12
nta::ContextData::setFontFolder
void setFontFolder(const utils::Path &fldr)
Sets the font folder.
Definition: ContextData.h:61
nta::ScreenManager::addScreen
void addScreen(Screen *newScreen, int escIndex=-1, int xIndex=-1, crstring title="")
adds a screen and sets some of its properties
Definition: ScreenManager.cpp:42
nta::Screen::render
virtual void render()=0
renders screen
nta::ScreenSwitchInfo
Info passed to Screen::onFocus.
Definition: Screen.h:33
nta::ContextData::destroy
void destroy()
Deletes all data (does not reset folder paths)
Definition: ContextData.cpp:65
nta::ContextData::setGLSLFolder
void setGLSLFolder(const utils::Path &fldr)
Sets the shader folder.
Definition: ContextData.h:59
nta::ScreenManager::m_currScreen
int m_currScreen
the index of the currently active screen
Definition: ScreenManager.h:36
nta::ScreenManager::~ScreenManager
~ScreenManager()
basic destructor
Definition: ScreenManager.cpp:25
nta::ScreenManager::setResourceFolders
void setResourceFolders(const utils::Path &tex_fldr, const utils::Path &glsl_fldr, const utils::Path &font_fldr)
Sets the location of textures, shaders, and fonts.
Definition: ScreenManager.cpp:35
nta::InputManager::update
void update(SDL_Event &event)
updates internal state
Definition: InputManager.cpp:38
nta::Screen::setIndices
void setIndices(int index, int escIndex, int xIndex, SetIndicesKey key)
sets various screen indices
Definition: Screen.cpp:40
nta::Screen::offFocus
virtual void offFocus()
called when the screen is no longer active
Definition: Screen.cpp:51
nta::Logger::writeToLog
static void writeToLog(crstring entry)
writes an entry in the log
Definition: Logger.cpp:17
nta::ScreenManager::m_event_lock
static std::mutex m_event_lock
Lock for access the event queue.
Definition: ScreenManager.h:23
nta::ScreenManager::m_limiter
FPSLimiter m_limiter
used to cap the FPS
Definition: ScreenManager.h:32
nta::Screen::onFocus
virtual void onFocus(const ScreenSwitchInfo &info)
called when the screen becomes active
Definition: Screen.cpp:48
nta::ScreenManager::destroy
void destroy()
destroys screens
Definition: ScreenManager.cpp:178
utils::Path
A (case-sensitive) Path in a file system.
Definition: Path.h:16
nta::Logger::unindent
static void unindent(size_t tab_size=TAB_SIZE)
unindents entries
Definition: Logger.cpp:46
nta::CallbackManager::increment_frame
static void increment_frame()
Informs CallbackManager that a frame has passed.
Definition: CallbackManager.cpp:123
nta::InputManager::updatePrev
void updatePrev()
updates the state of m_prevKeyMap
Definition: InputManager.cpp:56
nta::ScreenManager::ScreenManager
ScreenManager(crstring title, float maxFPS, int width=640, int height=480)
sets the max fps and the window to use
Definition: ScreenManager.cpp:20
nta::GetSDLWindowKey
Key for unlocking the GetSDLWindow() "private" function of class Window.
Definition: Window.h:23
nta::ScreenManager::m_screens
std::vector< Screen * > m_screens
the screens
Definition: ScreenManager.h:26
nta::Screen::getState
ScreenState getState() const
returns state of screen
Definition: Screen.cpp:16
nta::Window::getID
WindowID getID() const
return the window's id
Definition: Window.h:56
nta::Window::getSDLWindow
SDL_Window * getSDLWindow(GetSDLWindowKey key) const
returns the underlying window
Definition: Window.cpp:30
nta
Definition: Animation2D.h:6
nta::FPSLimiter::getFPS
float getFPS() const
gets most recently calculated fps
Definition: FPSLimiter.cpp:13
nta::SetWindowKey
Key unlocking the setWindow() "private" function of class Screen.
Definition: Screen.h:26
nta::ContextData::setTextureFolder
void setTextureFolder(const utils::Path &fldr)
Sets the texture folder.
Definition: ContextData.h:57
nta::ScreenManager::getCurrScreen
Screen * getCurrScreen() const
returns the active screen
Definition: ScreenManager.cpp:28
nta::ScreenManager::owns_event
bool owns_event(const SDL_Event &event) const
Definition: ScreenManager.cpp:79
nta::Window::getTitle
std::string getTitle() const
returns the window's title
Definition: Window.cpp:52
nta::ScreenManager::update_input
void update_input()
Updates the state of m_input.
Definition: ScreenManager.cpp:87
nta::Screen
Represents a game screen.
Definition: Screen.h:47
nta::InputManager::setMouseWheelMotion
void setMouseWheelMotion(const MouseWheelMotion &motion)
tells InputManager how the wheel is rolling
Definition: InputManager.cpp:35
nta::CreateInputManagerKey
Key unlocking the InputManager constructor.
Definition: InputManager.h:11
nta::Screen::init
virtual void init()=0
initializes the screen
nta::SetIndicesKey
Key unlocking the setIndices() "private" function of class Screen.
Definition: Screen.h:19
nta::ScreenManager::m_context_data
ContextData m_context_data
GLTextures and GLSLPrograms and whatnot.
Definition: ScreenManager.h:28
nta::ScreenManager::m_window
Window * m_window
the main window used by the manager
Definition: ScreenManager.h:34
nta::ScreenManager::m_input
InputManager m_input
Keeps track of all input received in this window.
Definition: ScreenManager.h:30
nta::InputManager::justPressed
bool justPressed(key_type key) const
returns whether or not the key was just pressed this frame
Definition: InputManager.cpp:17
nta::FPSLimiter::end
long double end()
ends fps calculations, delaying if necessary to cap fps
Definition: FPSLimiter.cpp:16
nta::Screen::update
virtual void update()=0
updates screen
nta::WindowManager::getWindow
static Window * getWindow(crstring windowTitle, int width=640, int height=480, int flags=0)
Gets a Window with specified title, width, height, and flags.
Definition: WindowManager.cpp:6
nta::FPSLimiter::setMaxFPS
void setMaxFPS(float maxFPS)
sets maximum allowed fps
Definition: FPSLimiter.cpp:10
nta::ScreenManager::switchScreen
void switchScreen(int newIndex)
switches the to a new screen
Definition: ScreenManager.cpp:56
nta::Timer::begin
virtual void begin()
begins timer
Definition: Timer.cpp:8
nta::utils::to_string
std::string to_string(const T &input, std::size_t precision=0)
converts input to a std::string
Definition: utils.h:36
nta::Logger::writeErrorToLog
static Error writeErrorToLog(crstring error, ErrorType type=OTHER)
writes entry in log and then notifies ErrorManager
Definition: Logger.cpp:31
nta::Screen::getEscIndex
int getEscIndex() const
gets various screen indices
Definition: Screen.cpp:22
nta::ErrorManager::handle_errors
static void handle_errors()
Handles all outstanding errors.
Definition: Errors.cpp:16
nta::Logger::indent
static void indent(size_t tab_size=TAB_SIZE)
indents entries
Definition: Logger.cpp:43
nta::ScreenManager::getFPS
float getFPS() const
returns the current fps
Definition: ScreenManager.cpp:32
nta::check_error
bool check_error()
Checks for and logs errors.
Definition: MyEngine.cpp:84