From c762d1c0a50a45e6689697c830c584f7e8e69860 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 16 Jul 2012 01:10:03 +0200 Subject: [PATCH] Add a simple screen manager (kind of like activity stack) --- base/PCMain.cpp | 10 +++--- native.vcxproj | 2 ++ native.vcxproj.filters | 6 ++++ ui/CMakeLists.txt | 1 + ui/screen.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++ ui/screen.h | 62 ++++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 ui/screen.cpp create mode 100644 ui/screen.h diff --git a/base/PCMain.cpp b/base/PCMain.cpp index 4510d008e2..7540cf1d22 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -234,13 +234,11 @@ int main(int argc, char *argv[]) { bool nextFrameMD = 0; float t = 0; while (true) { - SDL_Event event; - input_state.accelerometer_valid = false; input_state.mouse_valid = true; int quitRequested = 0; - // input_state.mouse_down[1] = nextFrameMD; + SDL_Event event; while (SDL_PollEvent(&event)) { float mx = event.motion.x * dp_xscale; float my = event.motion.y * dp_yscale; @@ -289,7 +287,7 @@ int main(int argc, char *argv[]) { SDL_GL_SwapBuffers(); - // Simple framerate limiting + // Simple frame rate limiting while (time_now() < t + 1.0f/60.0f) { sleep_ms(0); time_update(); @@ -299,7 +297,8 @@ int main(int argc, char *argv[]) { framecount++; } // Faster exit, thanks to the OS. Remove this if you want to debug shutdown - exit(0); + // The speed difference is only really noticable on Linux. On Windows you do notice it though + // exit(0); NativeShutdownGraphics(); SDL_PauseAudio(1); @@ -307,5 +306,6 @@ int main(int argc, char *argv[]) { SDL_CloseAudio(); SDL_Quit(); net::Shutdown(); + exit(0); return 0; } diff --git a/native.vcxproj b/native.vcxproj index 0402ee4795..7c1069b6fd 100644 --- a/native.vcxproj +++ b/native.vcxproj @@ -148,6 +148,7 @@ + @@ -211,6 +212,7 @@ + diff --git a/native.vcxproj.filters b/native.vcxproj.filters index 61af2a0391..8bda8682a6 100644 --- a/native.vcxproj.filters +++ b/native.vcxproj.filters @@ -181,6 +181,9 @@ android + + ui + @@ -330,6 +333,9 @@ android + + ui + diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt index 9a98c118d9..4b6f2c5758 100644 --- a/ui/CMakeLists.txt +++ b/ui/CMakeLists.txt @@ -1,5 +1,6 @@ set(SRCS ui.cpp + screen.cpp ) set(SRCS ${SRCS}) diff --git a/ui/screen.cpp b/ui/screen.cpp new file mode 100644 index 0000000000..581c3eabd9 --- /dev/null +++ b/ui/screen.cpp @@ -0,0 +1,81 @@ +#include "base/logging.h" +#include "input/input_state.h" +#include "ui/screen.h" + +ScreenManager screenManager; + +Screen::Screen() { } +Screen::~Screen() { } + +ScreenManager::ScreenManager() { + currentScreen_=0; + nextScreen_=0; +} + +ScreenManager::~ScreenManager() { + delete currentScreen_; +} + +void ScreenManager::switchScreen(Screen *screen) { + // Note that if a dialog is found, this will be a silent background switch that + // will only become apparent if the dialog is closed. The previous screen will stick around + // until that switch. + if (nextScreen_ != 0) { + FLOG("WTF? Already had nextScreen_"); + } + nextScreen_ = screen; +} + +void ScreenManager::update(const InputState &input) { + if (dialog_.size()) { + dialog_.back()->update(input); + return; + } + + if (nextScreen_) { + Screen *temp = currentScreen_; + currentScreen_ = nextScreen_; + delete temp; + temp = 0; + nextScreen_ = 0; + } + if (currentScreen_) { + currentScreen_->update(input); + } +} + +void ScreenManager::render() { + if (dialog_.size()) { + dialog_.back()->render(); + } + if (currentScreen_) { + currentScreen_->render(); + } + else { + ELOG("No current screen!"); + } +} + +void ScreenManager::shutdown() { + if (nextScreen_) { + delete nextScreen_; + nextScreen_ = 0; + } + if (currentScreen_) { + delete currentScreen_; + currentScreen_ = 0; + } +} + +void ScreenManager::push(Screen *screen) { + dialog_.push_back(screen); +} + +void ScreenManager::pop() { + if (dialog_.size()) { + delete dialog_.back(); + dialog_.pop_back(); + } else { + ELOG("Can't push when no dialog is shown"); + } +} \ No newline at end of file diff --git a/ui/screen.h b/ui/screen.h new file mode 100644 index 0000000000..5dcd8a841b --- /dev/null +++ b/ui/screen.h @@ -0,0 +1,62 @@ +// Super basic screen manager. Let's you, well, switch between screens. Can also be used +// to pop one screen in front for a bit while keeping another one running, it's basically +// a native "activity stack". Well actually that part is still a TODO. +// +// Semantics +// +// switchScreen: When you call this, on a newed screen, the ScreenManager takes ownership. +// On the next update, it switches to the new screen and deletes the previous screen. +// +// TODO: A way to do smooth transitions between screens. Will probably involve screenshotting +// the previous screen and then animating it on top of the current screen with transparency +// and/or other similar effects. + +#pragma once + +#include +#include "base/display.h" + +struct InputState; + +class Screen { +public: + Screen(); + virtual ~Screen(); + virtual void update(const InputState &input) = 0; + virtual void render() {} + virtual void dialogFinished(const Screen &dialog) {} +}; + +class Transition { +public: + Transition() {} +}; + +class ScreenManager { +public: + ScreenManager(); + virtual ~ScreenManager(); + + void switchScreen(Screen *screen); + void update(const InputState &input); + void render(); + void shutdown(); + + // Push a dialog box in front. Currently 1-level only. + void push(Screen *screen); + + // Pops the dialog away. + void pop(); + +private: + // Base screen. These don't "stack" and you can move in any order between them. + Screen *currentScreen_; + Screen *nextScreen_; + + // Dialog stack. These are shown "on top" of base screens and back works as expected. + // Used for options, in-game menus and other things you expect to be able to back out from onto something. + std::list dialog_; +}; + +// Yeah, an old school non enforced singleton. Good enough. +extern ScreenManager screenManager;