Last active
December 18, 2015 09:19
-
-
Save rc1/5760667 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| #include "ofMain.h" | |
| class ScreenStack; | |
| // Base Screen class for using with ScreenStack | |
| class Screen { | |
| friend class ScreenStack; | |
| public: | |
| Screen(): | |
| screenStack(0) | |
| {}; | |
| virtual ~Screen() {} | |
| // the stack that contains this screen | |
| ScreenStack *getScreenStack() { return screenStack; } | |
| /// App events | |
| virtual void update() {}; | |
| virtual void draw() = 0; | |
| virtual void exit() {}; | |
| /// Touch events | |
| virtual void touchDown(ofTouchEventArgs & touch) {}; | |
| virtual void touchMoved(ofTouchEventArgs & touch) {}; | |
| virtual void touchUp(ofTouchEventArgs & touch) {}; | |
| virtual void touchDoubleTap(ofTouchEventArgs & touch) {}; | |
| virtual void touchCancelled(ofTouchEventArgs & touch) {} | |
| /// Pop delegate methods (invoked by ScreenStack) | |
| // Can return false to block a pop request. I.e. return false, do a *getting popped* | |
| // animation, force a pop on the ScreenStack | |
| virtual bool allowPop() { return true; } | |
| virtual void willGetPopped() {}; | |
| virtual void didBecomeTopAfterPop() {}; | |
| /// Push delegate methods (invoked by ScreenStack) | |
| // Can return false to block a screen being pushed on top. I.e. return false, | |
| // do a *getting popped* animation, force a push on the ScreenStack with `otherScreenPtr` | |
| virtual bool allowScreenToBePushedOnTop(ofPtr<Screen>otherScreenPtr) { return true; } | |
| virtual void willGetScreenPushedOnTop(ofPtr<Screen>otherScreenPtr) {}; | |
| virtual void didGetPushedOnTop() {}; | |
| private: | |
| ScreenStack *screenStack; | |
| }; | |
| // Holds a stack of screens. | |
| // The top most screen will be the reciever of calls to update, draw, exit, touch. | |
| // The events can be auto subscribed via enableAppEvents, enableTouchEvents | |
| class ScreenStack { | |
| public: | |
| ScreenStack(): | |
| _hasEnabledAppEvents(false), | |
| _hasEnabledTouchEvents(false) | |
| {}; | |
| virtual ~ScreenStack() { | |
| if (_hasEnabledAppEvents) { | |
| disableAppEvents(); | |
| } | |
| if (_hasEnabledTouchEvents) { | |
| disableTouchEvents(); | |
| } | |
| }; | |
| /// Adding and removing screens | |
| void pushScreen(ofPtr<Screen> screenPtr, bool force=false) { | |
| if (screenPtr == 0) { | |
| ofLogError() << "Invald screen pushed to ScreenStack"; | |
| return; | |
| } | |
| // either force the push or ask the top most screen if it allows the push | |
| if ( force || screenPtrs.empty() || screenPtrs.top()->allowScreenToBePushedOnTop( screenPtr ) ) { | |
| // tell the top most screen it is getting something push on top | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->willGetScreenPushedOnTop( screenPtr ); | |
| } | |
| // give the screen a reference to its stack (this) | |
| screenPtr->screenStack = this; | |
| screenPtrs.push( screenPtr ); | |
| screenPtr->didGetPushedOnTop(); | |
| } | |
| }; | |
| void popScreen(bool force=false) { | |
| if ( force || screenPtrs.empty() || screenPtrs.top()->allowPop() ) { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->willGetPopped(); | |
| } | |
| screenPtrs.top()->screenStack = nil; | |
| screenPtrs.pop(); | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->didBecomeTopAfterPop(); | |
| } | |
| } | |
| }; | |
| /// Events | |
| // Draw events | |
| void update() { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->update(); | |
| } | |
| }; | |
| void draw() { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->draw(); | |
| } | |
| }; | |
| void exit() { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->exit(); | |
| } | |
| }; | |
| // Touch events | |
| void touchDown(ofTouchEventArgs & touch) { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->touchDown(touch); | |
| } | |
| }; | |
| void touchMoved(ofTouchEventArgs & touch) { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->touchMoved(touch); | |
| } | |
| }; | |
| void touchUp(ofTouchEventArgs & touch) { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->touchUp(touch); | |
| } | |
| }; | |
| void touchDoubleTap(ofTouchEventArgs & touch) { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->touchDoubleTap(touch); | |
| } | |
| }; | |
| void touchCancelled(ofTouchEventArgs & touch) { | |
| if ( !screenPtrs.empty() ) { | |
| screenPtrs.top()->touchCancelled(touch); | |
| } | |
| }; | |
| /// Auto enable / disable events listeners | |
| void enableAppEvents() { | |
| ofAddListener(ofEvents().update, this, &ScreenStack::onUpdate); | |
| ofAddListener(ofEvents().draw, this, &ScreenStack::onDraw); | |
| ofAddListener(ofEvents().exit, this, &ScreenStack::onExit); | |
| _hasEnabledAppEvents = true; | |
| }; | |
| void disableAppEvents() { | |
| ofRemoveListener(ofEvents().update, this, &ScreenStack::onUpdate); | |
| ofRemoveListener(ofEvents().draw, this, &ScreenStack::onDraw); | |
| ofRemoveListener(ofEvents().exit, this, &ScreenStack::onExit); | |
| _hasEnabledAppEvents = false; | |
| }; | |
| void onDraw(ofEventArgs &data) { draw(); } | |
| void onUpdate(ofEventArgs &data) { update(); } | |
| void onExit(ofEventArgs &data) { exit(); } | |
| void enableTouchEvents() { | |
| ofAddListener(ofEvents().touchDown, this, &ScreenStack::onTouchDown); | |
| ofAddListener(ofEvents().touchMoved, this, &ScreenStack::onTouchMoved); | |
| ofAddListener(ofEvents().touchUp, this, &ScreenStack::onTouchUp); | |
| ofAddListener(ofEvents().touchDoubleTap, this, &ScreenStack::onTouchDoubleTap); | |
| ofAddListener(ofEvents().touchCancelled, this, &ScreenStack::onTouchCancelled); | |
| _hasEnabledAppEvents = true; | |
| }; | |
| void disableTouchEvents() { | |
| ofRemoveListener(ofEvents().touchDown, this, &ScreenStack::onTouchDown); | |
| ofRemoveListener(ofEvents().touchMoved, this, &ScreenStack::onTouchMoved); | |
| ofRemoveListener(ofEvents().touchUp, this, &ScreenStack::onTouchUp); | |
| ofRemoveListener(ofEvents().touchDoubleTap, this, &ScreenStack::onTouchDoubleTap); | |
| ofRemoveListener(ofEvents().touchCancelled, this, &ScreenStack::onTouchCancelled); | |
| _hasEnabledAppEvents = false; | |
| }; | |
| void onTouchDown(ofTouchEventArgs & touch) { touchDown(touch); } | |
| void onTouchMoved(ofTouchEventArgs & touch) { touchMoved(touch); } | |
| void onTouchUp(ofTouchEventArgs & touch) { touchUp(touch); } | |
| void onTouchDoubleTap(ofTouchEventArgs & touch) { touchDoubleTap(touch); } | |
| void onTouchCancelled(ofTouchEventArgs & touch) { touchCancelled(touch); } | |
| private: | |
| stack< ofPtr<Screen> > screenPtrs; | |
| bool _hasEnabledAppEvents; | |
| bool _hasEnabledTouchEvents; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment