Scene - m1keall1son/ofxMediaSystem GitHub Wiki
In ofxMediaSystem, the Scene brings everything together. A scene:
- is an
EventManagerthat triggers its own set of local events (see events page for more details) - has a map of Entities, controlling their creation and destruction
- has a
ComponentManager, with a pass-through interface for convenience in accessing it. - has a
SystemManagerto house local systems (see system page for more detail)
Scenes inherently don't have any statemachine-type logic embedded in them. Instead they provide three app functions:
- house all the data-structures related to an application state,
- house all the logic necessary for this application state (like a state-manchine knowing where to transition to next)
- manage a transition [in from the prev/out to the next] scene.
Scenes generally don't know about each other and are self-contained, all the entities in one scene are not shared with another. If there is a need to keep entities shared between application states, it would be an ofxMediaSystem best-practice for the user to sub-divide the scene into finer states adding events for this as necessary.
There are two methods for extending a scene to include business logic that are effectively the same:
//via the optional virtual interface, inheriting ms::Scene
class MyScene : public ms::Scene {
public:
MyScene():Scene("my scene name"){}
void init()override;
void postInit()override;
void transitionIn()override;
void transitionUpdate()override;
void transitionOut()override;
void update()override;
void draw()override;
void shutdown()override;
void reset()override;
void start()override;
void stop()override;
void transitionInComplete()override;
void transitionOutComplete()override;
...
};
auto scene = mSceneManager.createScene<MyScene>();
//or by using the event hooks
class MySceneOrOtherAppLogic {
public:
MyScene():Scene("my scene name"){}
ms::EventStatus onInit(const ms::IEventRef& event);
ms::EventStatus onStart(const ms::IEventRef& event);
ms::EventStatus onStop(const ms::IEventRef& event);
ms::EventStatus onUpdate(const ms::IEventRef& event);
...
};
auto myThing = MySceneOrOtherAppLogic();
//still have to crate a basic logicless scene
auto scene = mSceneManager.createScene<ms::Scene>("my scene");
//hook into whatever events you want to listen to...
scene.addDelegate<ms::Init>( EventDelegate::create<MySceneOrOtherAppLogic,&MySceneOrOtherAppLogic::onInit>(&myThing));
scene.addDelegate<ms::Start>( EventDelegate::create<MySceneOrOtherAppLogic,&MySceneOrOtherAppLogic::onStart>(&myThing));
scene.addDelegate<ms::Stop>( EventDelegate::create<MySceneOrOtherAppLogic,&MySceneOrOtherAppLogic::onStop>(&myThing));
scene.addDelegate<ms::Update>( EventDelegate::create<MySceneOrOtherAppLogic,&MySceneOrOtherAppLogic::onUpdate>(&myThing));
A possible use of multiple scenes is imagine one scene as a "splash" another scene as an initial "menu" and a third scene as an "interactive UI" etc.
A scene manager is the top-level object an oF application will interface will. In the most typical use-case, an oF application will have a ms::SceneManager and use it to construct/destroy scenes. The best practice is to create all scenes during ofApp::setup() prior to calling SceneManager::initScenes() to kick things off, there must be an initial ms::SceneChange event or the user must call SceneManager::changeSceneTo(someScene).
//typical use-case
//in ofApp.h
ms::SceneManager mSceneManager;
...
//in ofApp.cpp
void ofApp::setup(){
//create all scenes
auto first = mSceneManger.createScene<MyScene>(...);
mSceneManger.createScene<MyOtherScene>(...);
//etc.
...
try{
mSceneManager.initScenes();
}catch(const std::exception& e){
//do something
}
mSceneManager.changeSceneTo(first);
}
void ofApp::update(){
mSceneManager.update();
}
void ofApp::draw(){
mSceneManager.draw();
}Transitions are the only logical mechanism built-in to ms::Scene. Transitions have a direction ms::Scene::TransitionDir::TRANSITION_IN or ms::Scene::TransitionDir::TRANSITION_OUT. Each direction can have its own duration of transition independent of other scenes as well. This means that there's no guarantee that scenes will transition at the same speed or end at the same time unless the user defines it that way. NOTE: the default transition time is 0.f seconds. if the transition time is 0.f, then the functions relating to transitions transitionIn/Out() transitionIn/OutComplete() transitionUpdate() will be skipped! so only use logic there if you intend to set the duration larger than 0.f, otherwise, just use start() and stop().
During a transition, the scenes are "cross-faded" meaning that the two transitioning states will be active at the same time, updating and drawing. The current scene is always updated before the next scene and the current scene is also drawn before the next scene.