1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Utility/BsModule.h"
7#include "Scene/BsGameObject.h"
8
9namespace bs
10{
11 class LightProbeVolume;
12 class PhysicsScene;
13
14 /** @addtogroup Scene-Internal
15 * @{
16 */
17
18 /** Information about a scene actor and the scene object it has been bound to. */
19 struct BoundActorData
20 {
21 BoundActorData() = default;
22 BoundActorData(const SPtr<SceneActor>& actor, const HSceneObject& so)
23 :actor(actor), so(so)
24 { }
25
26 SPtr<SceneActor> actor;
27 HSceneObject so;
28 };
29
30 /** Possible states components can be in. Controls which component callbacks are triggered. */
31 enum class ComponentState
32 {
33 Running, /**< All components callbacks are being triggered normally. */
34 Paused, /**< All component callbacks except update are being triggered normally. */
35 Stopped /**< No component callbacks are being triggered. */
36 };
37
38 /** Contains information about an instantiated scene. */
39 class BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Scene) SceneInstance
40 {
41 struct ConstructPrivately {};
42 public:
43 SceneInstance(ConstructPrivately dummy, const String& name, const HSceneObject& root,
44 const SPtr<PhysicsScene>& physicsScene);
45
46 /** Name of the scene. */
47 BS_SCRIPT_EXPORT(n:Name,pr:getter)
48 const String& getName() const { return mName; }
49
50 /** Root object of the scene. */
51 BS_SCRIPT_EXPORT(n:Root,pr:getter)
52 const HSceneObject& getRoot() const { return mRoot; }
53
54 /** Checks is the scene currently active. IF inactive the scene properties aside from the name are undefined. */
55 BS_SCRIPT_EXPORT(n:IsActive,pr:getter)
56 bool isActive() const { return mIsActive; }
57
58 /**
59 * Physical representation of the scene, as assigned by the physics sub-system. Exact implementation depends on the
60 * physics plugin used.
61 */
62 BS_SCRIPT_EXPORT(n:Physics,pr:getter)
63 const SPtr<PhysicsScene>& getPhysicsScene() const { return mPhysicsScene; }
64 private:
65 friend class SceneManager;
66
67 String mName;
68 HSceneObject mRoot;
69 bool mIsActive = true;
70 SPtr<PhysicsScene> mPhysicsScene;
71 };
72
73 /**
74 * Keeps track of all active SceneObject%s and their components. Keeps track of component state and triggers their
75 * events. Updates the transforms of objects as SceneObject%s move.
76 */
77 class BS_CORE_EXPORT SceneManager : public Module<SceneManager>
78 {
79 public:
80 SceneManager();
81 ~SceneManager();
82
83 /** Returns the object that represents the main scene. */
84 const SPtr<SceneInstance>& getMainScene() const { return mMainScene; }
85
86 /**
87 * Destroys all scene objects in the scene.
88 *
89 * @param[in] forceAll If true, then even the persistent objects will be unloaded.
90 */
91 void clearScene(bool forceAll = false);
92
93 /**
94 * Instantiates a new scene and makes it active. All non-persistent objects that are part of the current scene will
95 * be destroyed.
96 */
97 void loadScene(const HPrefab& scene);
98
99 /**
100 * Saves all the currently active scene objects into a brand new prefab which can then be saved to disk, loaded back
101 * and provided to setScene() for loading.
102 */
103 HPrefab saveScene() const;
104
105 /**
106 * Changes the component state that globally determines which component callbacks are activated. Only affects
107 * components that don't have the ComponentFlag::AlwaysRun flag set.
108 */
109 void setComponentState(ComponentState state);
110
111 /** Checks are the components currently in the Running state. */
112 bool isRunning() const { return mComponentState == ComponentState::Running; }
113
114 /**
115 * Returns a list of all components of the specified type currently in the scene.
116 *
117 * @tparam T Type of the component to search for.
118 *
119 * @param[in] activeOnly If true only active components are returned, otherwise all components are returned.
120 * @return A list of all matching components in the scene.
121 */
122 template<class T>
123 Vector<GameObjectHandle<T>> findComponents(bool activeOnly = true);
124
125 /** Returns all cameras in the scene. */
126 const UnorderedMap<Camera*, SPtr<Camera>>& getAllCameras() const { return mCameras; }
127
128 /**
129 * Returns the camera in the scene marked as main. Main camera controls the final render surface that is displayed
130 * to the user. If there are multiple main cameras, the first one found returned.
131 */
132 SPtr<Camera> getMainCamera() const;
133
134 /**
135 * Sets the render target that the main camera in the scene (if any) will render its view to. This generally means
136 * the main game window when running standalone, or the Game viewport when running in editor.
137 */
138 void setMainRenderTarget(const SPtr<RenderTarget>& rt);
139
140 /** Changes the root scene object. Any persistent objects will remain in the scene, now parented to the new root. */
141 void _setRootNode(const HSceneObject& root);
142
143 /**
144 * Binds a scene actor with a scene object. Every frame the scene object's transform will be monitored for
145 * changes and those changes will be automatically transfered to the actor.
146 */
147 void _bindActor(const SPtr<SceneActor>& actor, const HSceneObject& so);
148
149 /** Unbinds an actor that was previously bound using bindActor(). */
150 void _unbindActor(const SPtr<SceneActor>& actor);
151
152 /** Returns a scene object bound to the provided actor, if any. */
153 HSceneObject _getActorSO(const SPtr<SceneActor>& actor) const;
154
155 /** Notifies the scene manager that a new camera was created. */
156 void _registerCamera(const SPtr<Camera>& camera);
157
158 /** Notifies the scene manager that a camera was removed. */
159 void _unregisterCamera(const SPtr<Camera>& camera);
160
161 /** Notifies the scene manager that a camera either became the main camera, or has stopped being main camera. */
162 void _notifyMainCameraStateChanged(const SPtr<Camera>& camera);
163
164 /** Called every frame. Calls update methods on all scene objects and their components. */
165 void _update();
166
167 /** Called at fixed time internals. Calls the fixed update method on all active components. */
168 void _fixedUpdate();
169
170 /** Updates dirty transforms on any core objects that may be tied with scene objects. */
171 void _updateCoreObjectTransforms();
172
173 /** Notifies the manager that a new component has just been created. The manager triggers necessary callbacks. */
174 void _notifyComponentCreated(const HComponent& component, bool parentActive);
175
176 /**
177 * Notifies the manager that a scene object the component belongs to was activated. The manager triggers necessary
178 * callbacks.
179 */
180 void _notifyComponentActivated(const HComponent& component, bool triggerEvent);
181
182 /**
183 * Notifies the manager that a scene object the component belongs to was deactivated. The manager triggers necessary
184 * callbacks.
185 */
186 void _notifyComponentDeactivated(const HComponent& component, bool triggerEvent);
187
188 /** Notifies the manager that a component is about to be destroyed. The manager triggers necessary callbacks. */
189 void _notifyComponentDestroyed(const HComponent& component, bool immediate);
190
191 protected:
192 /** Types of events that represent component state changes relevant to the scene manager. */
193 enum class ComponentStateEventType
194 {
195 Created, Activated, Deactivated, Destroyed
196 };
197
198 /** Describes a single component state change. */
199 struct ComponentStateChange
200 {
201 ComponentStateChange(HComponent obj, ComponentStateEventType type)
202 :obj(std::move(obj)), type(type)
203 { }
204
205 HComponent obj;
206 ComponentStateEventType type;
207 };
208
209 friend class SceneObject;
210
211 /**
212 * Register a new node in the scene manager, on the top-most level of the hierarchy.
213 *
214 * @param[in] node Node you wish to add. It's your responsibility not to add duplicate or null nodes. This
215 * method won't check.
216 *
217 * @note
218 * After you add a node in the scene manager, it takes ownership of its memory and is responsible for releasing it.
219 * Do NOT add nodes that have already been added (if you just want to change their parent). Normally this
220 * method will only be called by SceneObject.
221 */
222 void registerNewSO(const HSceneObject& node);
223
224 /** Callback that is triggered when the main render target size is changed. */
225 void onMainRenderTargetResized();
226
227 /**
228 * Adds a component to the specified state list. Caller is expected to first remove the component from any
229 * existing state lists.
230 */
231 void addToStateList(const HComponent& component, UINT32 listType);
232
233 /** Removes a component from its current scene manager state list (if any). */
234 void removeFromStateList(const HComponent& component);
235
236 /** Iterates over components that had their state modified and moves them to the appropriate state lists. */
237 void processStateChanges();
238
239 /**
240 * Encodes an index and a type into a single 32-bit integer. Top 2 bits represent the type, while the rest represent
241 * the index.
242 */
243 static UINT32 encodeComponentId(UINT32 idx, UINT32 type);
244
245 /** Decodes an id encoded with encodeComponentId(). */
246 static void decodeComponentId(UINT32 id, UINT32& idx, UINT32& type);
247
248 /** Checks does the specified component type match the provided RTTI id. */
249 static bool isComponentOfType(const HComponent& component, UINT32 rttiId);
250
251 protected:
252 SPtr<SceneInstance> mMainScene;
253
254 UnorderedMap<SceneActor*, BoundActorData> mBoundActors;
255 UnorderedMap<Camera*, SPtr<Camera>> mCameras;
256 Vector<SPtr<Camera>> mMainCameras;
257
258 Vector<HComponent> mActiveComponents;
259 Vector<HComponent> mInactiveComponents;
260 Vector<HComponent> mUninitializedComponents;
261
262 std::array<Vector<HComponent>*, 3> mComponentsPerState =
263 { { &mActiveComponents, &mInactiveComponents, &mUninitializedComponents } };
264
265 SPtr<RenderTarget> mMainRT;
266 HEvent mMainRTResizedConn;
267
268 ComponentState mComponentState = ComponentState::Running;
269 bool mDisableStateChange = false;
270 Vector<ComponentStateChange> mStateChanges;
271 };
272
273 /** Provides easy access to the SceneManager. */
274 BS_CORE_EXPORT SceneManager& gSceneManager();
275
276 template<class T>
277 Vector<GameObjectHandle<T>> SceneManager::findComponents(bool activeOnly)
278 {
279 UINT32 rttiId = T::getRTTIStatic()->getRTTIId();
280
281 Vector<GameObjectHandle<T>> output;
282 for(auto& entry : mActiveComponents)
283 {
284 if (isComponentOfType(entry, rttiId))
285 output.push_back(static_object_cast<T>(entry));
286 }
287
288 if(!activeOnly)
289 {
290 for(auto& entry : mInactiveComponents)
291 {
292 if (isComponentOfType(entry, rttiId))
293 output.push_back(static_object_cast<T>(entry));
294 }
295
296 for(auto& entry : mUninitializedComponents)
297 {
298 if (isComponentOfType(entry, rttiId))
299 output.push_back(static_object_cast<T>(entry));
300 }
301 }
302
303 return output;
304 }
305
306 /** @} */
307}
308