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 "Math/BsMatrix4.h" |
7 | #include "Math/BsVector3.h" |
8 | #include "Math/BsQuaternion.h" |
9 | #include "Reflection/BsRTTIType.h" |
10 | #include "Scene/BsGameObjectManager.h" |
11 | #include "Scene/BsGameObject.h" |
12 | #include "Scene/BsComponent.h" |
13 | #include "Scene/BsTransform.h" |
14 | |
15 | namespace bs |
16 | { |
17 | class SceneInstance; |
18 | |
19 | /** @addtogroup Scene |
20 | * @{ |
21 | */ |
22 | |
23 | /** Possible modifiers that can be applied to a SceneObject. */ |
24 | enum SceneObjectFlags |
25 | { |
26 | SOF_DontInstantiate = 0x01, /**< Object wont be in the main scene and its components won't receive updates. */ |
27 | SOF_DontSave = 0x02, /**< Object will be skipped when saving the scene hierarchy or a prefab. */ |
28 | SOF_Persistent = 0x04, /**< Object will remain in the scene even after scene clear, unless destroyed directly. |
29 | This only works with top-level objects. */ |
30 | SOF_Internal = 0x08 /**< Provides a hint to external systems that his object is used by engine internals. |
31 | For example, those systems might not want to display those objects together with the |
32 | user created ones. */ |
33 | }; |
34 | |
35 | /** |
36 | * An object in the scene graph. It has a transform object that allows it to be positioned, scaled and rotated. It can |
37 | * have other scene objects as children, and will have a scene object as a parent, in which case transform changes |
38 | * to the parent are reflected to the child scene objects (children are relative to the parent). |
39 | * |
40 | * Each scene object can have one or multiple Component%s attached to it, where the components inherit the scene |
41 | * object's transform, and receive updates about transform and hierarchy changes. |
42 | */ |
43 | class BS_CORE_EXPORT SceneObject : public GameObject |
44 | { |
45 | /** Flags that signify which part of the SceneObject needs updating. */ |
46 | enum DirtyFlags |
47 | { |
48 | LocalTfrmDirty = 0x01, |
49 | WorldTfrmDirty = 0x02 |
50 | }; |
51 | |
52 | friend class SceneManager; |
53 | friend class Prefab; |
54 | friend class PrefabDiff; |
55 | friend class PrefabUtility; |
56 | public: |
57 | ~SceneObject(); |
58 | |
59 | /** |
60 | * Creates a new SceneObject with the specified name. Object will be placed in the top of the scene hierarchy. |
61 | * |
62 | * @param[in] name Name of the scene object. |
63 | * @param[in] flags Optional flags that control object behavior. See SceneObjectFlags. |
64 | */ |
65 | static HSceneObject create(const String& name, UINT32 flags = 0); |
66 | |
67 | /** |
68 | * Destroys this object and any of its held components. |
69 | * |
70 | * @param[in] immediate If true, the object will be deallocated and become unusable right away. Otherwise the |
71 | * deallocation will be delayed to the end of frame (preferred method). |
72 | */ |
73 | void destroy(bool immediate = false); |
74 | |
75 | /** Returns a handle to this object. */ |
76 | HSceneObject getHandle() const { return mThisHandle; } |
77 | |
78 | /** |
79 | * Returns the UUID of the prefab this object is linked to, if any. |
80 | * |
81 | * @param[in] onlyDirect If true, this method will return prefab link only for the root object of the prefab |
82 | * instance. If false the parent objects will be searched for the prefab ID. |
83 | */ |
84 | UUID getPrefabLink(bool onlyDirect = false) const; |
85 | |
86 | /** |
87 | * Returns the root object of the prefab instance that this object belongs to, if any. Returns null if the object |
88 | * is not part of a prefab instance. |
89 | */ |
90 | HSceneObject getPrefabParent() const; |
91 | |
92 | /** |
93 | * Breaks the link between this prefab instance and its prefab. Object will retain all current values but will no |
94 | * longer be influenced by modifications to its parent prefab. |
95 | */ |
96 | void breakPrefabLink(); |
97 | |
98 | /** Checks if the scene object has a specific bit flag set. */ |
99 | bool hasFlag(UINT32 flag) const; |
100 | |
101 | public: // ***** INTERNAL ****** |
102 | /** @name Internal |
103 | * @{ |
104 | */ |
105 | |
106 | /** @copydoc GameObject::_setInstanceData */ |
107 | void _setInstanceData(GameObjectInstanceDataPtr& other) override; |
108 | |
109 | /** |
110 | * Register the scene object with the scene and activate all of its components. |
111 | * |
112 | * @param[in] prefabOnly If true, only objects within the current prefab will be instantiated. If false all child |
113 | * objects and components will. |
114 | */ |
115 | void _instantiate(bool prefabOnly = false); |
116 | |
117 | /** |
118 | * Clears the internally stored prefab diff. If this object is updated from prefab its instance specific changes |
119 | * will be lost. |
120 | */ |
121 | void _clearPrefabDiff() { mPrefabDiff = nullptr; } |
122 | |
123 | /** |
124 | * Returns the UUID of the prefab this object is linked to, if any. Unlike getPrefabLink() method this will not |
125 | * search parents, but instead return only the value assigned to this object. |
126 | */ |
127 | const UUID& _getPrefabLinkUUID() const { return mPrefabLinkUUID; } |
128 | |
129 | /** |
130 | * Allows you to change the prefab link UUID of this object. Normally this should be accompanied by reassigning the |
131 | * link IDs. |
132 | */ |
133 | void _setPrefabLinkUUID(const UUID& UUID) { mPrefabLinkUUID = UUID; } |
134 | |
135 | /** |
136 | * Returns a prefab diff object containing instance specific modifications of this object compared to its prefab |
137 | * reference, if any. |
138 | */ |
139 | const SPtr<PrefabDiff>& _getPrefabDiff() const { return mPrefabDiff; } |
140 | |
141 | /** Assigns a new prefab diff object. Caller must ensure the prefab diff was generated for this object. */ |
142 | void _setPrefabDiff(const SPtr<PrefabDiff>& diff) { mPrefabDiff = diff; } |
143 | |
144 | /** Recursively enables the provided set of flags on this object and all children. */ |
145 | void _setFlags(UINT32 flags); |
146 | |
147 | /** Recursively disables the provided set of flags on this object and all children. */ |
148 | void _unsetFlags(UINT32 flags); |
149 | |
150 | /** @} */ |
151 | |
152 | private: |
153 | SceneObject(const String& name, UINT32 flags); |
154 | |
155 | /** |
156 | * Creates a new SceneObject instance, registers it with the game object manager, creates and returns a handle to |
157 | * the new object. |
158 | * |
159 | * @note |
160 | * When creating objects with DontInstantiate flag it is the callers responsibility to manually destroy the object, |
161 | * otherwise it will leak. |
162 | */ |
163 | static HSceneObject createInternal(const String& name, UINT32 flags = 0); |
164 | |
165 | /** |
166 | * Creates a new SceneObject instance from an existing pointer, registers it with the game object manager, creates |
167 | * and returns a handle to the object. |
168 | * |
169 | * @param[in] soPtr Pointer to the scene object register and return a handle to. |
170 | */ |
171 | static HSceneObject createInternal(const SPtr<SceneObject>& soPtr); |
172 | |
173 | /** |
174 | * Destroys this object and any of its held components. |
175 | * |
176 | * @param[in] handle Game object handle to this object. |
177 | * @param[in] immediate If true, the object will be deallocated and become unusable right away. Otherwise the |
178 | * deallocation will be delayed to the end of frame (preferred method). |
179 | * |
180 | * @note Unlike destroy(), does not remove the object from its parent. |
181 | */ |
182 | void destroyInternal(GameObjectHandleBase& handle, bool immediate = false) override; |
183 | |
184 | /** Checks is the scene object instantiated and visible in the scene. */ |
185 | bool isInstantiated() const { return (mFlags & SOF_DontInstantiate) == 0; } |
186 | |
187 | private: |
188 | HSceneObject mThisHandle; |
189 | UUID mPrefabLinkUUID; |
190 | SPtr<PrefabDiff> mPrefabDiff; |
191 | UINT32 mPrefabHash = 0; |
192 | UINT32 mFlags; |
193 | |
194 | /************************************************************************/ |
195 | /* Transform */ |
196 | /************************************************************************/ |
197 | public: |
198 | /** Gets the transform object representing object's position/rotation/scale in world space. */ |
199 | const Transform& getTransform() const; |
200 | |
201 | /** Gets the transform object representing object's position/rotation/scale relative to its parent. */ |
202 | const Transform& getLocalTransform() const { return mLocalTfrm; } |
203 | |
204 | /** Sets the local position of the object. */ |
205 | void setPosition(const Vector3& position); |
206 | |
207 | /** Sets the world position of the object. */ |
208 | void setWorldPosition(const Vector3& position); |
209 | |
210 | /** Sets the local rotation of the object. */ |
211 | void setRotation(const Quaternion& rotation); |
212 | |
213 | /** Sets the world rotation of the object. */ |
214 | void setWorldRotation(const Quaternion& rotation); |
215 | |
216 | /** Sets the local scale of the object. */ |
217 | void setScale(const Vector3& scale); |
218 | |
219 | /** |
220 | * Sets the world scale of the object. |
221 | * |
222 | * @note This will not work properly if this object or any of its parents have non-affine transform matrices. |
223 | */ |
224 | void setWorldScale(const Vector3& scale); |
225 | |
226 | /** |
227 | * Orients the object so it is looking at the provided @p location (world space) where @p up is used for |
228 | * determining the location of the object's Y axis. |
229 | */ |
230 | void lookAt(const Vector3& location, const Vector3& up = Vector3::UNIT_Y); |
231 | |
232 | /** |
233 | * Gets the objects world transform matrix. |
234 | * |
235 | * @note Performance warning: This might involve updating the transforms if the transform is dirty. |
236 | */ |
237 | const Matrix4& getWorldMatrix() const; |
238 | |
239 | /** |
240 | * Gets the objects inverse world transform matrix. |
241 | * |
242 | * @note Performance warning: This might involve updating the transforms if the transform is dirty. |
243 | */ |
244 | Matrix4 getInvWorldMatrix() const; |
245 | |
246 | /** Gets the objects local transform matrix. */ |
247 | const Matrix4& getLocalMatrix() const; |
248 | |
249 | /** Moves the object's position by the vector offset provided along world axes. */ |
250 | void move(const Vector3& vec); |
251 | |
252 | /** Moves the object's position by the vector offset provided along it's own axes (relative to orientation). */ |
253 | void moveRelative(const Vector3& vec); |
254 | |
255 | /** |
256 | * Rotates the game object so it's forward axis faces the provided direction. |
257 | * |
258 | * @param[in] forwardDir The forward direction to face, in world space. |
259 | * |
260 | * @note Local forward axis is considered to be negative Z. |
261 | */ |
262 | void setForward(const Vector3& forwardDir); |
263 | |
264 | /** Rotate the object around an arbitrary axis. */ |
265 | void rotate(const Vector3& axis, const Radian& angle); |
266 | |
267 | /** Rotate the object around an arbitrary axis using a Quaternion. */ |
268 | void rotate(const Quaternion& q); |
269 | |
270 | /** |
271 | * Rotates around local Z axis. |
272 | * |
273 | * @param[in] angle Angle to rotate by. |
274 | */ |
275 | void roll(const Radian& angle); |
276 | |
277 | /** |
278 | * Rotates around Y axis. |
279 | * |
280 | * @param[in] angle Angle to rotate by. |
281 | */ |
282 | void yaw(const Radian& angle); |
283 | |
284 | /** |
285 | * Rotates around X axis |
286 | * |
287 | * @param[in] angle Angle to rotate by. |
288 | */ |
289 | void pitch(const Radian& angle); |
290 | |
291 | /** |
292 | * Forces any dirty transform matrices on this object to be updated. |
293 | * |
294 | * @note |
295 | * Normally this is done internally when retrieving a transform, but sometimes it is useful to update transforms |
296 | * manually. |
297 | */ |
298 | void updateTransformsIfDirty(); |
299 | |
300 | /** |
301 | * Returns a hash value that changes whenever a scene objects transform gets updated. It allows you to detect |
302 | * changes with the local or world transforms without directly comparing their values with some older state. |
303 | */ |
304 | UINT32 getTransformHash() const { return mDirtyHash; } |
305 | |
306 | private: |
307 | Transform mLocalTfrm; |
308 | mutable Transform mWorldTfrm; |
309 | |
310 | mutable Matrix4 mCachedLocalTfrm = Matrix4::IDENTITY; |
311 | mutable Matrix4 mCachedWorldTfrm = Matrix4::IDENTITY; |
312 | |
313 | mutable UINT32 mDirtyFlags = 0xFFFFFFFF; |
314 | mutable UINT32 mDirtyHash = 0; |
315 | |
316 | /** |
317 | * Notifies components and child scene object that a transform has been changed. |
318 | * |
319 | * @param flags Specifies in what way was the transform changed. |
320 | */ |
321 | void notifyTransformChanged(TransformChangedFlags flags) const; |
322 | |
323 | /** Updates the local transform. Normally just reconstructs the transform matrix from the position/rotation/scale. */ |
324 | void updateLocalTfrm() const; |
325 | |
326 | /** |
327 | * Updates the world transform. Reconstructs the local transform matrix and multiplies it with any parent transforms. |
328 | * |
329 | * @note If parent transforms are dirty they will be updated. |
330 | */ |
331 | void updateWorldTfrm() const; |
332 | |
333 | /** Checks if cached local transform needs updating. */ |
334 | bool isCachedLocalTfrmUpToDate() const { return (mDirtyFlags & DirtyFlags::LocalTfrmDirty) == 0; } |
335 | |
336 | /** Checks if cached world transform needs updating. */ |
337 | bool isCachedWorldTfrmUpToDate() const { return (mDirtyFlags & DirtyFlags::WorldTfrmDirty) == 0; } |
338 | |
339 | /************************************************************************/ |
340 | /* Hierarchy */ |
341 | /************************************************************************/ |
342 | public: |
343 | /** |
344 | * Changes the parent of this object. Also removes the object from the current parent, and assigns it to the new |
345 | * parent. |
346 | * |
347 | * @param[in] parent New parent. |
348 | * @param[in] keepWorldTransform Determines should the current transform be maintained even after the parent is |
349 | * changed (this means the local transform will be modified accordingly). |
350 | */ |
351 | void setParent(const HSceneObject& parent, bool keepWorldTransform = true); |
352 | |
353 | /** |
354 | * Gets the parent of this object. |
355 | * |
356 | * @return Parent object, or nullptr if this SceneObject is at root level. |
357 | */ |
358 | HSceneObject getParent() const { return mParent; } |
359 | |
360 | /** |
361 | * Gets a child of this item. |
362 | * |
363 | * @param[in] idx The zero based index of the child. |
364 | * @return SceneObject of the child. |
365 | */ |
366 | HSceneObject getChild(UINT32 idx) const; |
367 | |
368 | /** |
369 | * Find the index of the specified child. Don't persist this value as it may change whenever you add/remove children. |
370 | * |
371 | * @param[in] child The child to look for. |
372 | * @return The zero-based index of the found child, or -1 if no match was found. |
373 | */ |
374 | int indexOfChild(const HSceneObject& child) const; |
375 | |
376 | /** Gets the number of all child GameObjects. */ |
377 | UINT32 getNumChildren() const { return (UINT32)mChildren.size(); } |
378 | |
379 | /** Returns the scene this object is part of. Can be null if scene object hasn't been instantiated. */ |
380 | const SPtr<SceneInstance>& getScene() const; |
381 | |
382 | /** |
383 | * Searches the scene object hierarchy to find a child scene object using the provided path. |
384 | * |
385 | * @param[in] path Path to the property, where each element of the path is separated with "/" Path elements signify |
386 | * names of child scene objects (first one relative to this object). |
387 | */ |
388 | HSceneObject findPath(const String& path) const; |
389 | |
390 | /** |
391 | * Searches the child objects for an object matching the specified name. |
392 | * |
393 | * @param[in] name Name of the object to locate. |
394 | * @param[in] recursive If true all descendants of the scene object will be searched, otherwise only immediate |
395 | * children. |
396 | * @return First found scene object, or empty handle if none found. |
397 | */ |
398 | HSceneObject findChild(const String& name, bool recursive = true); |
399 | |
400 | /** |
401 | * Searches the child objects for objects matching the specified name. |
402 | * |
403 | * @param[in] name Name of the objects to locate. |
404 | * @param[in] recursive If true all descendants of the scene object will be searched, otherwise only immediate |
405 | * children. |
406 | * @return All scene objects matching the specified name. |
407 | */ |
408 | Vector<HSceneObject> findChildren(const String& name, bool recursive = true); |
409 | |
410 | /** |
411 | * Enables or disables this object. Disabled objects also implicitly disable all their child objects. No components |
412 | * on the disabled object are updated. |
413 | */ |
414 | void setActive(bool active); |
415 | |
416 | /** |
417 | * Returns whether or not an object is active. |
418 | * |
419 | * @param[in] self If true, the method will only check if this particular object was activated or deactivated |
420 | * directly via setActive. If false we we also check if any of the objects parents are inactive. |
421 | */ |
422 | bool getActive(bool self = false) const; |
423 | |
424 | /** |
425 | * Sets the mobility of a scene object. This is used primarily as a performance hint to engine systems. Objects |
426 | * with more restricted mobility will result in higher performance. Some mobility constraints will be enforced by |
427 | * the engine itself, while for others the caller must be sure not to break the promise he made when mobility was |
428 | * set. By default scene object's mobility is unrestricted. |
429 | */ |
430 | void setMobility(ObjectMobility mobility); |
431 | |
432 | /** |
433 | * Gets the mobility setting for this scene object. See setMobility(); |
434 | */ |
435 | ObjectMobility getMobility() const { return mMobility; } |
436 | |
437 | /** |
438 | * Makes a deep copy of this object. |
439 | * |
440 | * @param[in] instantiate If false, the cloned hierarchy will just be a memory copy, but will not be present |
441 | * in the scene or otherwise active until instantiate() is called. |
442 | * @param[in] preserveUUIDs If false, each cloned game object will be assigned a brand new UUID. Otherwise |
443 | * the UUID of the original game objects will be preserved. Note that two instantiated |
444 | * scene objects should never have the same UUID, so if preserving UUID's make sure |
445 | * the original is destroyed before instantiating. |
446 | */ |
447 | HSceneObject clone(bool instantiate = true, bool preserveUUIDs = false); |
448 | |
449 | private: |
450 | SPtr<SceneInstance> mParentScene; |
451 | HSceneObject mParent; |
452 | Vector<HSceneObject> mChildren; |
453 | bool mActiveSelf = true; |
454 | bool mActiveHierarchy = true; |
455 | ObjectMobility mMobility = ObjectMobility::Movable; |
456 | |
457 | /** |
458 | * Internal version of setParent() that allows you to set a null parent. |
459 | * |
460 | * @param[in] parent New parent. |
461 | * @param[in] keepWorldTransform Determines should the current transform be maintained even after the parent is |
462 | * changed (this means the local transform will be modified accordingly). |
463 | */ |
464 | void _setParent(const HSceneObject& parent, bool keepWorldTransform = true); |
465 | |
466 | /** Changes the owning scene of the scene object and all children. */ |
467 | void setScene(const SPtr<SceneInstance>& scene); |
468 | |
469 | /** |
470 | * Adds a child to the child array. This method doesn't check for null or duplicate values. |
471 | * |
472 | * @param[in] object New child. |
473 | */ |
474 | void addChild(const HSceneObject& object); |
475 | |
476 | /** |
477 | * Removes the child from the object. |
478 | * |
479 | * @param[in] object Child to remove. |
480 | */ |
481 | void removeChild(const HSceneObject& object); |
482 | |
483 | /** Changes the object active in hierarchy state, and triggers necessary events. */ |
484 | void setActiveHierarchy(bool active, bool triggerEvents = true); |
485 | |
486 | /************************************************************************/ |
487 | /* Component */ |
488 | /************************************************************************/ |
489 | public: |
490 | /** Constructs a new component of the specified type and adds it to the internal component list. */ |
491 | template<class T, class... Args> |
492 | GameObjectHandle<T> addComponent(Args &&... args) |
493 | { |
494 | static_assert((std::is_base_of<bs::Component, T>::value), |
495 | "Specified type is not a valid Component." ); |
496 | |
497 | SPtr<T> gameObject(new (bs_alloc<T>()) T(mThisHandle, |
498 | std::forward<Args>(args)...), |
499 | &bs_delete<T>, StdAlloc<T>()); |
500 | |
501 | const HComponent newComponent = |
502 | static_object_cast<Component>(GameObjectManager::instance().registerObject(gameObject)); |
503 | |
504 | addAndInitializeComponent(newComponent); |
505 | return static_object_cast<T>(newComponent); |
506 | } |
507 | |
508 | /** |
509 | * Constructs a new component of the specified type id and adds it to the internal component list. Component must |
510 | * have a parameterless constructor. |
511 | */ |
512 | HComponent addComponent(UINT32 typeId); |
513 | |
514 | /** |
515 | * Searches for a component with the specific type and returns the first one it finds. Will also return components |
516 | * derived from the type. |
517 | * |
518 | * @tparam T Type of the component. |
519 | * @return Component if found, nullptr otherwise. |
520 | * |
521 | * @note |
522 | * Don't call this too often as it is relatively slow. It is more efficient to call it once and store the result |
523 | * for further use. |
524 | */ |
525 | template <typename T> |
526 | GameObjectHandle<T> getComponent() |
527 | { |
528 | static_assert((std::is_base_of<bs::Component, T>::value), |
529 | "Specified type is not a valid Component." ); |
530 | |
531 | return static_object_cast<T>(getComponent(T::getRTTIStatic())); |
532 | } |
533 | |
534 | /** |
535 | * Returns all components with the specific type. Will also return components derived from the type. |
536 | * |
537 | * @tparam typename T Type of the component. |
538 | * @return Array of found components. |
539 | * |
540 | * @note |
541 | * Don't call this too often as it is relatively slow. It is more efficient to call it once and store the result |
542 | * for further use. |
543 | */ |
544 | template <typename T> |
545 | Vector<GameObjectHandle<T>> getComponents() |
546 | { |
547 | static_assert((std::is_base_of<bs::Component, T>::value), |
548 | "Specified type is not a valid Component." ); |
549 | |
550 | Vector<GameObjectHandle<T>> output; |
551 | |
552 | for (auto entry : mComponents) |
553 | { |
554 | if (entry->getRTTI()->isDerivedFrom(T::getRTTIStatic())) |
555 | output.push_back(static_object_cast<T>(entry)); |
556 | } |
557 | |
558 | return output; |
559 | } |
560 | |
561 | /** |
562 | * Checks if the current object contains the specified component or components derived from the provided type. |
563 | * |
564 | * @tparam typename T Type of the component. |
565 | * @return True if component exists on the object. |
566 | * |
567 | * @note Don't call this too often as it is relatively slow. |
568 | */ |
569 | template <typename T> |
570 | bool hasComponent() |
571 | { |
572 | static_assert((std::is_base_of<bs::Component, T>::value), |
573 | "Specified type is not a valid Component." ); |
574 | |
575 | for (auto entry : mComponents) |
576 | { |
577 | if (entry->getRTTI()->isDerivedFrom(T::getRTTIStatic())) |
578 | return true; |
579 | } |
580 | |
581 | return false; |
582 | } |
583 | |
584 | /** |
585 | * Searches for a component with the specified type and returns the first one it finds. Will also return components |
586 | * derived from the type. |
587 | * |
588 | * @param[in] type RTTI information for the type. |
589 | * @return Component if found, nullptr otherwise. |
590 | * |
591 | * @note |
592 | * Don't call this too often as it is relatively slow. It is more efficient to call it once and store the result |
593 | * for further use. |
594 | */ |
595 | HComponent getComponent(RTTITypeBase* type) const; |
596 | |
597 | /** |
598 | * Removes the component from this object, and deallocates it. |
599 | * |
600 | * @param[in] component The component to destroy. |
601 | * @param[in] immediate If true, the component will be deallocated and become unusable right away. Otherwise |
602 | * the deallocation will be delayed to the end of frame (preferred method). |
603 | */ |
604 | void destroyComponent(const HComponent component, bool immediate = false); |
605 | |
606 | /** |
607 | * Removes the component from this object, and deallocates it. |
608 | * |
609 | * @param[in] component The component to destroy. |
610 | * @param[in] immediate If true, the component will be deallocated and become unusable right away. Otherwise |
611 | * the deallocation will be delayed to the end of frame (preferred method). |
612 | */ |
613 | void destroyComponent(Component* component, bool immediate = false); |
614 | |
615 | /** Returns all components on this object. */ |
616 | const Vector<HComponent>& getComponents() const { return mComponents; } |
617 | |
618 | /** Creates an empty component with the default constructor. Primarily used for RTTI purposes. */ |
619 | template <typename T> |
620 | static SPtr<T> createEmptyComponent() |
621 | { |
622 | static_assert((std::is_base_of<bs::Component, T>::value), "Specified type is not a valid Component." ); |
623 | |
624 | T* rawPtr = new (bs_alloc<T>()) T(); |
625 | SPtr<T> gameObject(rawPtr, &bs_delete<T>, StdAlloc<T>()); |
626 | gameObject->mRTTIData = gameObject; |
627 | |
628 | return gameObject; |
629 | } |
630 | |
631 | public: // ***** INTERNAL ****** |
632 | /** @name Internal |
633 | * @{ |
634 | */ |
635 | |
636 | /** Returns a modifyable list of all components on this object. */ |
637 | Vector<HComponent>& _getComponents() { return mComponents; } |
638 | |
639 | /** @} */ |
640 | private: |
641 | /** Adds the component to the internal component array. */ |
642 | void addComponentInternal(const SPtr<Component>& component); |
643 | |
644 | /** Adds the component to the internal component array, and initializes it. */ |
645 | void addAndInitializeComponent(const HComponent& component); |
646 | |
647 | /** Adds the component to the internal component array, and initializes it. */ |
648 | void addAndInitializeComponent(const SPtr<Component>& component); |
649 | |
650 | Vector<HComponent> mComponents; |
651 | |
652 | /************************************************************************/ |
653 | /* RTTI */ |
654 | /************************************************************************/ |
655 | public: |
656 | friend class GameObjectRTTI; |
657 | friend class SceneObjectRTTI; |
658 | static RTTITypeBase* getRTTIStatic(); |
659 | RTTITypeBase* getRTTI() const override; |
660 | }; |
661 | |
662 | /** @} */ |
663 | } |