// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #include "SceneObject.h" #include "Tags.h" #include "Engine/Core/Types/Span.h" #include "Engine/Core/Math/Transform.h" #include "Engine/Core/Math/BoundingBox.h" #include "Engine/Core/Math/BoundingSphere.h" #include "Engine/Scripting/ScriptingObject.h" #include "Types.h" struct RenderView; struct RenderContext; struct RenderContextBatch; class GPUContext; class MemoryWriteStream; class PhysicsScene; class SceneRendering; class SceneRenderTask; /// /// Base class for all actor objects on the scene. /// API_CLASS(Abstract) class FLAXENGINE_API Actor : public SceneObject { DECLARE_SCENE_OBJECT(Actor); friend Level; friend PrefabManager; friend Scene; friend SceneRendering; friend Prefab; friend PrefabInstanceData; protected: uint16 _isActive : 1; uint16 _isActiveInHierarchy : 1; uint16 _isPrefabRoot : 1; uint16 _isEnabled : 1; uint16 _drawNoCulling : 1; uint16 _drawCategory : 4; byte _layer; StaticFlags _staticFlags; Transform _localTransform; Transform _transform; BoundingSphere _sphere; BoundingBox _box; String _name; Scene* _scene; PhysicsScene* _physicsScene; private: // Disable copying Actor(Actor const&) = delete; Actor& operator=(Actor const&) = delete; public: /// /// List with all child actors attached to the actor (readonly). All items are valid (not null). /// API_FIELD(ReadOnly) Array Children; /// /// List with all scripts attached to the actor (readonly). All items are valid (not null). /// API_FIELD(ReadOnly, Attributes="HideInEditor, NoAnimate, EditorOrder(-5), EditorDisplay(\"Scripts\", EditorDisplayAttribute.InlineStyle), Collection(ReadOnly = true, NotNullItems = true, CanReorderItems = false)") Array Scripts; /// /// The hide flags. /// API_FIELD(Attributes="HideInEditor, NoSerialize") HideFlags HideFlags; /// /// Actor tags collection. /// API_FIELD(Attributes="NoAnimate, EditorDisplay(\"General\"), EditorOrder(-68)") Array Tags; public: /// /// Gets the object layer (index). Can be used for selective rendering or ignoring raycasts. /// API_PROPERTY(Attributes="NoAnimate, EditorDisplay(\"General\"), EditorOrder(-69), CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.ActorLayerEditor\")") FORCE_INLINE int32 GetLayer() const { return _layer; } /// /// Gets the layer mask (with single bit set). /// FORCE_INLINE int32 GetLayerMask() const { return 1 << static_cast(_layer); } /// /// Sets the layer. /// /// The index of the layer. API_PROPERTY() void SetLayer(int32 layerIndex); /// /// Sets the layer recursively for all underlying children. /// /// The index of the layer. API_FUNCTION() void SetLayerRecursive(int32 layerIndex); /// /// Gets the name of the layer. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize, NoAnimate") const String& GetLayerName() const; /// /// Sets the name of the layer. /// API_PROPERTY() void SetLayerName(const StringView& value); /// /// Sets the name of the layer recursively for actor and for all underlying child actors. /// API_FUNCTION() void SetLayerNameRecursive(const StringView& value); /// /// Determines whether this actor has any tag assigned. /// API_FUNCTION() bool HasTag() const; /// /// Determines whether this actor has given tag assigned (exact match). /// /// The tag to check. API_FUNCTION() bool HasTag(const Tag& tag) const; /// /// Determines whether this actor has given tag assigned (exact match). /// /// The tag to check. API_FUNCTION() bool HasTag(const StringView& tag) const; /// /// Adds a tag to the actor /// /// The tag to add. API_FUNCTION() void AddTag(const Tag& tag); /// /// Adds a tag to the actor and for all underlying child actors. /// /// The tag to add. API_FUNCTION() void AddTagRecursive(const Tag& tag); /// /// Removes a tag to the actor /// /// The tag to remove. API_FUNCTION() void RemoveTag(const Tag& tag); /// /// Gets the name of the tag. /// [Deprecated in v1.5] /// API_PROPERTY(Attributes="HideInEditor, NoSerialize, NoAnimate") DEPRECATED("Use HasTag instead") const String& GetTag() const; /// /// Sets the name of the tag. /// [Deprecated in v1.5] /// API_PROPERTY() DEPRECATED("Use AddTag instead") void SetTag(const StringView& value); /// /// Gets the actor name. /// API_PROPERTY(Attributes="NoAnimate, EditorDisplay(\"General\"), EditorOrder(-100)") FORCE_INLINE const String& GetName() const { return _name; } /// /// Sets the actor name. /// /// The value to set. API_PROPERTY() void SetName(String&& value); /// /// Sets the actor name. /// /// The value to set. void SetName(const StringView& value); public: /// /// Gets the scene object which contains this actor. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE Scene* GetScene() const { return _scene; } /// /// Sets a actor parent. /// /// New parent /// Should actor world positions remain the same after parent change? /// True if can break prefab link on changing the parent. API_FUNCTION() void SetParent(Actor* value, bool worldPositionsStays, bool canBreakPrefabLink); /// /// Gets amount of child actors. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE int32 GetChildrenCount() const { return Children.Count(); } /// /// Gets the child actor at the given index. /// /// The child actor index. /// The child actor (always valid). API_FUNCTION() Actor* GetChild(int32 index) const; /// /// Gets the child actor with the given name. /// /// The child actor name. /// The child actor or null. API_FUNCTION() Actor* GetChild(const StringView& name) const; /// /// Gets the child actor of the given type. /// /// Type of the actor to search for. Includes any actors derived from the type. /// The child actor or null. API_FUNCTION() Actor* GetChild(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type) const; /// /// Gets the child actor of the given type. /// /// The child actor or null. template FORCE_INLINE T* GetChild() const { return (T*)GetChild(T::GetStaticClass()); } /// /// Finds the child actor of the given type or creates a new one. /// /// The child actor. template T* GetOrAddChild() { T* result = (T*)GetChild(T::GetStaticClass()); if (!result) { result = New(); result->SetParent(this, false, false); } return result; } /// /// Gets the child actors of the given type. /// /// Type of the actor to search for. Includes any actors derived from the type. /// The child actors. API_FUNCTION() Array GetChildren(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type) const; /// /// Gets the child actors of the given type. /// /// The child actors. template Array GetChildren() const { const MClass* type = T::GetStaticClass(); Array result; for (Actor* child : Children) if (IsSubClassOf(child, type)) result.Add((T*)child); return result; } /// /// Destroys the children. Calls Object.Destroy on every child actor and unlinks them for this actor. /// /// The time left to destroy object (in seconds). API_FUNCTION(Attributes="NoAnimate") void DestroyChildren(float timeLeft = 0.0f); public: /// /// Gets amount of scripts. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE int32 GetScriptsCount() const { return Scripts.Count(); } /// /// Gets the script at the given index. /// /// The script index. /// The script (always valid). API_FUNCTION() Script* GetScript(int32 index) const; /// /// Gets the script of the given type from this actor. /// /// Type of the script to search for. Includes any scripts derived from the type. /// The script or null. API_FUNCTION() Script* GetScript(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const; /// /// Gets the script of the given type from this actor. /// /// The script or null. template FORCE_INLINE T* GetScript() const { return (T*)GetScript(T::GetStaticClass()); } /// /// Gets the scripts of the given type from this actor. /// /// Type of the script to search for. Includes any scripts derived from the type. /// The scripts. API_FUNCTION() Array GetScripts(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const; /// /// Gets the scripts of the given type from this actor. /// /// The scripts. template Array GetScripts() const { const MClass* type = T::GetStaticClass(); Array result; for (Script* script : Scripts) if (IsSubClassOf(script, type)) result.Add((T*)script); return result; } /// /// Creates a new script of a specific type and adds it to the actor. /// /// The created script instance, null otherwise. template T* AddScript() { auto script = New(); script->SetParent(this); return script; } public: /// /// Gets value indicating if actor is active in the scene. /// API_PROPERTY(Attributes="EditorDisplay(\"General\"), DefaultValue(true), EditorOrder(-70)") FORCE_INLINE bool GetIsActive() const { return _isActive != 0; } /// /// Sets value indicating if actor is active in the scene. /// /// The value to set. API_PROPERTY() virtual void SetIsActive(bool value); /// /// Gets value indicating if actor is active in the scene graph. It must be active as well as that of all it's parents. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE bool IsActiveInHierarchy() const { return _isActiveInHierarchy != 0; } /// /// Gets value indicating if actor is in a scene. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE bool HasScene() const { return _scene != nullptr; } /// /// Returns true if object is fully static on the scene, otherwise false. /// FORCE_INLINE bool IsStatic() const { return _staticFlags == StaticFlags::FullyStatic; } /// /// Returns true if object has static transform. /// FORCE_INLINE bool IsTransformStatic() const { return (_staticFlags & StaticFlags::Transform) != StaticFlags::None; } /// /// Gets the actor static flags. /// API_PROPERTY(Attributes="NoAnimate, EditorDisplay(\"General\"), EditorOrder(-80), CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.ActorStaticFlagsEditor\")") FORCE_INLINE StaticFlags GetStaticFlags() const { return _staticFlags; } /// /// Sets the actor static flags. /// /// The value to set. API_PROPERTY() virtual void SetStaticFlags(StaticFlags value); /// /// Returns true if object has given flag(s) set. /// FORCE_INLINE bool HasStaticFlag(StaticFlags flag) const { return EnumHasAllFlags(_staticFlags, flag); } /// /// Adds the actor static flags. /// /// The flags to add. FORCE_INLINE void AddStaticFlags(StaticFlags flags) { SetStaticFlags(_staticFlags | flags); } /// /// Removes the actor static flags. /// /// The flags to remove. FORCE_INLINE void RemoveStaticFlags(StaticFlags flags) { SetStaticFlags(_staticFlags & ~flags); } /// /// Sets a single static flag to the desire value. /// /// The flag to change. /// The target value of the flag. FORCE_INLINE void SetStaticFlag(StaticFlags flag, bool value) { SetStaticFlags((_staticFlags & ~flag) | (value ? flag : StaticFlags::None)); } public: /// /// Gets the actor's world transformation. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE const Transform& GetTransform() const { return _transform; } /// /// Sets the actor's world transformation. /// /// The value to set. API_PROPERTY() void SetTransform(const Transform& value); /// /// Gets the actor's world transform position. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE Vector3 GetPosition() const { return _transform.Translation; } /// /// Sets the actor's world transform position. /// /// The value to set. API_PROPERTY() void SetPosition(const Vector3& value); /// /// Gets actor orientation in 3D space /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE Quaternion GetOrientation() const { return _transform.Orientation; } /// /// Sets actor orientation in 3D space. /// /// The value to set. API_PROPERTY() void SetOrientation(const Quaternion& value); /// /// Gets actor scale in 3D space. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE Float3 GetScale() const { return _transform.Scale; } /// /// Sets actor scale in 3D space /// /// The value to set. API_PROPERTY() void SetScale(const Float3& value); /// /// Gets actor rotation matrix. /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") Matrix GetRotation() const; /// /// Sets actor rotation matrix. /// /// The value to set. API_PROPERTY() void SetRotation(const Matrix& value); public: /// /// Gets the random per-instance value (normalized to range 0-1). /// API_PROPERTY() FORCE_INLINE float GetPerInstanceRandom() const { return _id.C * (1.0f / (float)MAX_uint32); } /// /// Gets actor direction vector (forward vector). /// API_PROPERTY(Attributes="HideInEditor, NoSerialize") FORCE_INLINE Float3 GetDirection() const { return Float3::Transform(Float3::Forward, GetOrientation()); } /// /// Sets actor direction vector (forward) /// /// The value to set. API_PROPERTY() void SetDirection(const Float3& value); public: /// /// Resets the actor local transform. /// void ResetLocalTransform(); /// /// Gets local transform of the actor in parent actor space. /// API_PROPERTY(Attributes="HideInEditor, NoAnimate") FORCE_INLINE Transform GetLocalTransform() const { return _localTransform; } /// /// Sets local transform of the actor in parent actor space. /// /// The value to set. API_PROPERTY() void SetLocalTransform(const Transform& value); /// /// Gets local position of the actor in parent actor space. /// API_PROPERTY(Attributes="EditorDisplay(\"Transform\", \"Position\"), VisibleIf(\"ShowTransform\"), DefaultValue(typeof(Vector3), \"0,0,0\"), EditorOrder(-30), NoSerialize, CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.ActorTransformEditor+PositionEditor\")") FORCE_INLINE Vector3 GetLocalPosition() const { return _localTransform.Translation; } /// /// Sets local position of the actor in parent actor space. /// /// The value to set. API_PROPERTY() void SetLocalPosition(const Vector3& value); /// /// Gets local rotation of the actor in parent actor space. /// /// Actor.LocalOrientation *= Quaternion.Euler(0, 10 * Time.DeltaTime, 0) API_PROPERTY(Attributes="EditorDisplay(\"Transform\", \"Rotation\"), VisibleIf(\"ShowTransform\"), DefaultValue(typeof(Quaternion), \"0,0,0,1\"), EditorOrder(-20), NoSerialize, CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.ActorTransformEditor+OrientationEditor\")") FORCE_INLINE Quaternion GetLocalOrientation() const { return _localTransform.Orientation; } /// /// Sets local rotation of the actor in parent actor space. /// /// The value to set. API_PROPERTY() void SetLocalOrientation(const Quaternion& value); /// /// Gets local scale vector of the actor in parent actor space. /// API_PROPERTY(Attributes="EditorDisplay(\"Transform\", \"Scale\"), VisibleIf(\"ShowTransform\"), DefaultValue(typeof(Float3), \"1,1,1\"), Limit(float.MinValue, float.MaxValue, 0.01f), EditorOrder(-10), NoSerialize, CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.ActorTransformEditor+ScaleEditor\")") FORCE_INLINE Float3 GetLocalScale() const { return _localTransform.Scale; } /// /// Sets local scale vector of the actor in parent actor space. /// /// The value to set. API_PROPERTY() void SetLocalScale(const Float3& value); /// /// Moves the actor (also can rotate it) in world space. /// /// The translation vector. API_FUNCTION() FORCE_INLINE void AddMovement(const Vector3& translation) { AddMovement(translation, Quaternion::Identity); } /// /// Moves the actor (also can rotate it) in world space. /// /// The translation vector. /// The rotation quaternion. API_FUNCTION() virtual void AddMovement(const Vector3& translation, const Quaternion& rotation); /// /// Gets the matrix that transforms a point from the world space to local space of the actor. /// /// The world to local matrix. API_FUNCTION() void GetWorldToLocalMatrix(API_PARAM(Out) Matrix& worldToLocal) const; /// /// Gets the matrix that transforms a point from the local space of the actor to world space. /// /// The world to local matrix. API_FUNCTION() void GetLocalToWorldMatrix(API_PARAM(Out) Matrix& localToWorld) const; public: /// /// Gets actor bounding sphere that defines 3D space intersecting with the actor (for determination of the visibility for actor). /// API_PROPERTY() FORCE_INLINE const BoundingSphere& GetSphere() const { return _sphere; } /// /// Gets actor bounding box that defines 3D space intersecting with the actor (for determination of the visibility for actor). /// API_PROPERTY() FORCE_INLINE const BoundingBox& GetBox() const { return _box; } /// /// Gets actor bounding box of the actor including all child actors (children included in recursive way) /// API_PROPERTY() BoundingBox GetBoxWithChildren() const; #if USE_EDITOR /// /// Gets actor bounding box (single actor, no children included) for editor tools. /// API_PROPERTY() virtual BoundingBox GetEditorBox() const; /// /// Gets actor bounding box of the actor including all child actors for editor tools. /// API_PROPERTY() BoundingBox GetEditorBoxChildren() const; #endif /// /// Returns true if actor has loaded content. /// API_PROPERTY() virtual bool HasContentLoaded() const; /// /// Calls UnregisterObject for all objects in the actor hierarchy. /// void UnregisterObjectHierarchy(); /// /// Calls Initialize for all objects in the actor hierarchy. /// void InitializeHierarchy(); public: /// /// Draws this actor. Called by Scene Rendering service. This call is more optimized than generic Draw (eg. geometry is rendered during all pass types but other actors are drawn only during GBufferFill pass). /// /// The rendering context. virtual void Draw(RenderContext& renderContext); /// /// Draws this actor. Called by Scene Rendering service. This call is more optimized than generic Draw (eg. geometry is rendered during all pass types but other actors are drawn only during GBufferFill pass). /// /// The rendering context batch (eg, main view and shadow projections). virtual void Draw(RenderContextBatch& renderContextBatch); #if USE_EDITOR /// /// Draws debug shapes for the actor and all child scripts. /// API_FUNCTION() virtual void OnDebugDraw(); /// /// Draws debug shapes for the selected actor and all child scripts. /// API_FUNCTION() virtual void OnDebugDrawSelected(); #endif public: /// /// Changes the script order. /// /// The script. /// The new index. void ChangeScriptOrder(Script* script, int32 newIndex); /// /// Gets the script by its identifier. /// /// The script identifier. /// The script or null. Script* GetScriptByID(const Guid& id) const; /// /// Gets a value indicating whether this actor is a prefab instance root object. /// API_PROPERTY() bool IsPrefabRoot() const; /// /// Gets the root of the prefab this actor is attached to. /// /// The root prefab object, or null if this actor is not a prefab. API_FUNCTION() Actor* GetPrefabRoot(); public: /// /// Tries to find the actor with the given name in this actor hierarchy (checks this actor and all children hierarchy). /// /// The name of the actor. /// Actor instance if found, null otherwise. API_FUNCTION() Actor* FindActor(const StringView& name) const; /// /// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy). /// /// Type of the actor to search for. Includes any actors derived from the type. /// Finds only a active actor. /// Actor instance if found, null otherwise. API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, bool activeOnly = false) const; /// /// Tries to find the actor of the given type and name in this actor hierarchy (checks this actor and all children hierarchy). /// /// Type of the actor to search for. Includes any actors derived from the type. /// The name of the actor. /// Actor instance if found, null otherwise. API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const StringView& name) const; /// /// Tries to find the actor of the given type and tag in this actor hierarchy. /// /// Type of the actor to search for. Includes any actors derived from the type. /// The tag of the actor to search for. /// Finds only an active actor. /// Actor instance if found, null otherwise. API_FUNCTION() Actor* FindActor(API_PARAM(Attributes="TypeReference(typeof(Actor))") const MClass* type, const Tag& tag, bool activeOnly = false) const; /// /// Tries to find the actor of the given type in this actor hierarchy (checks this actor and all children hierarchy). /// /// Actor instance if found, null otherwise. template FORCE_INLINE T* FindActor() const { return (T*)FindActor(T::GetStaticClass()); } /// /// Tries to find the actor of the given type and name in this actor hierarchy (checks this actor and all children hierarchy). /// /// The name of the actor. /// Actor instance if found, null otherwise. template FORCE_INLINE T* FindActor(const StringView& name) const { return (T*)FindActor(T::GetStaticClass(), name); } /// /// Tries to find the actor of the given type and tag in this actor hierarchy (checks this actor and all children hierarchy). /// /// The tag of the actor to search for. /// Actor instance if found, null otherwise. template FORCE_INLINE T* FindActor(const Tag& tag) const { return (T*)FindActor(T::GetStaticClass(), tag); } /// /// Tries to find the script of the given type in this actor hierarchy (checks this actor and all children hierarchy). /// /// Type of the actor to search for. Includes any actors derived from the type. /// Script instance if found, null otherwise. API_FUNCTION() Script* FindScript(API_PARAM(Attributes="TypeReference(typeof(Script))") const MClass* type) const; /// /// Tries to find the script of the given type in this actor hierarchy (checks this actor and all children hierarchy). /// /// Script instance if found, null otherwise. template FORCE_INLINE T* FindScript() const { return (T*)FindScript(T::GetStaticClass()); } /// /// Try to find actor in hierarchy structure. /// /// The actor to find. /// Found actor or null. API_FUNCTION() bool HasActorInHierarchy(Actor* a) const; /// /// Try to find actor in child actors structure. /// /// The actor to find. /// Found actor or null. API_FUNCTION() bool HasActorInChildren(Actor* a) const; /// /// Determines if there is an intersection between the current object and a Ray. /// /// The ray to test. /// When the method completes, contains the distance of the intersection (if any valid). /// When the method completes, contains the intersection surface normal vector (if any valid). /// True whether the two objects intersected, otherwise false. API_FUNCTION() virtual bool IntersectsItself(const Ray& ray, API_PARAM(Out) Real& distance, API_PARAM(Out) Vector3& normal); /// /// Determines if there is an intersection between the current object or any it's child and a ray. /// /// The ray to test. /// When the method completes, contains the distance of the intersection (if any valid). /// When the method completes, contains the intersection surface normal vector (if any valid). /// The target hit actor that is the closest to the ray. API_FUNCTION() Actor* Intersects(const Ray& ray, API_PARAM(Out) Real& distance, API_PARAM(Out) Vector3& normal); /// /// Rotates actor to orient it towards the specified world position. /// /// The world position to orient towards. API_FUNCTION() void LookAt(const Vector3& worldPos); /// /// Rotates actor to orient it towards the specified world position with upwards direction. /// /// The world position to orient towards. /// The up direction that Constrains y axis orientation to a plane this vector lies on. This rule might be broken if forward and up direction are nearly parallel. API_FUNCTION() void LookAt(const Vector3& worldPos, const Vector3& worldUp); /// /// Gets rotation of the actor oriented towards the specified world position. /// /// The world position to orient towards. API_FUNCTION() Quaternion LookingAt(const Vector3& worldPos) const; /// /// Gets rotation of the actor oriented towards the specified world position with upwards direction. /// /// The world position to orient towards. /// The up direction that constrains up axis orientation to a plane this vector lies on. This rule might be broken if forward and up direction are nearly parallel. API_FUNCTION() Quaternion LookingAt(const Vector3& worldPos, const Vector3& worldUp) const; public: /// /// Execute custom action on actors tree. /// /// Actor to call on every actor in the tree. Returns true if keep calling deeper. /// Custom arguments for the function template void TreeExecute(Function& action, Params ... args) { if (action(this, args...)) { for (int32 i = 0; i < Children.Count(); i++) Children.Get()[i]->TreeExecute(action, args...); } } /// /// Execute custom action on actor children tree. /// /// Actor to call on every actor in the tree. Returns true if keep calling deeper. /// Custom arguments for the function template void TreeExecuteChildren(Function& action, Params ... args) { for (int32 i = 0; i < Children.Count(); i++) Children.Get()[i]->TreeExecute(action, args...); } public: /// /// Performs actors serialization to the raw bytes. /// /// The actors to serialize. /// The output data stream. /// True if fails, otherwise false. static bool ToBytes(const Array& actors, MemoryWriteStream& output); /// /// Performs actors serialization to the raw bytes. /// /// The actors to serialize. /// The output data, empty if failed. API_FUNCTION() static Array ToBytes(const Array& actors); /// /// Performs actors deserialization from the raw bytes. /// /// The input data. /// The output actors. /// The custom serialization modifier. /// True if fails, otherwise false. static bool FromBytes(const Span& data, Array& output, ISerializeModifier* modifier); /// /// Performs actors deserialization from the raw bytes. /// /// The input data. /// The output actors. API_FUNCTION() static Array FromBytes(const Span& data); /// /// Performs actors deserialization from the raw bytes. /// /// The input data. /// The serialized objects Ids mapping. Can be used to convert the spawned objects ids and references to them. /// The output actors. API_FUNCTION() static Array FromBytes(const Span& data, const Dictionary& idsMapping); /// /// Tries the get serialized objects ids from the raw bytes. /// /// The data. /// The output array of serialized object ids. API_FUNCTION() static Array TryGetSerializedObjectsIds(const Span& data); /// /// Serializes the actor object to the Json string. Serialized are only this actor properties but no child actors nor scripts. Serializes references to the other objects in a proper way using IDs. /// /// The Json container with serialized actor data. API_FUNCTION() String ToJson(); /// /// Deserializes the actor object to the Json string. Deserialized are only this actor properties but no child actors nor scripts. /// /// The serialized actor data (state). API_FUNCTION() void FromJson(const StringAnsiView& json); public: /// /// Called when actor gets added to game systems. Occurs on BeginPlay event or when actor gets activated in hierarchy. Use this event to register object to other game system (eg. audio). /// API_FUNCTION() virtual void OnEnable(); /// /// Called when actor gets removed from game systems. Occurs on EndPlay event or when actor gets inactivated in hierarchy. Use this event to unregister object from other game system (eg. audio). /// API_FUNCTION() virtual void OnDisable(); /// /// Called when actor parent gets changed. /// virtual void OnParentChanged(); /// /// Called when actor transform gets changed. /// virtual void OnTransformChanged(); /// /// Called when actor active state gets changed. /// virtual void OnActiveChanged(); /// /// Called when actor active in tree state gets changed. /// virtual void OnActiveInTreeChanged(); /// /// Called when order in parent children array gets changed. /// virtual void OnOrderInParentChanged(); /// /// Called when actor static flag gets changed. /// virtual void OnStaticFlagsChanged(); /// /// Called when layer gets changed. /// virtual void OnLayerChanged(); /// /// Called when adding object to the game. /// API_FUNCTION(Attributes="NoAnimate") virtual void OnBeginPlay() { } /// /// Called when removing object from the game. /// API_FUNCTION(Attributes="NoAnimate") virtual void OnEndPlay() { } /// /// Gets the scene rendering object. /// /// The scene rendering interface. SceneRendering* GetSceneRendering() const; public: /// /// Set the physics world the controller is part of. /// API_PROPERTY(Attributes="HideInEditor") void SetPhysicsScene(PhysicsScene* scene); /// /// Get the physics world the controller is part of. /// API_PROPERTY(Attributes="HideInEditor") PhysicsScene* GetPhysicsScene() const; protected: virtual void OnPhysicsSceneChanged(PhysicsScene* previous) { } private: void SetSceneInHierarchy(Scene* scene); void OnEnableInHierarchy(); void OnDisableInHierarchy(); // Helper methods used by templates GetChildren/GetScripts to prevent including MClass/Script here static bool IsSubClassOf(const Actor* object, const MClass* klass); static bool IsSubClassOf(const Script* object, const MClass* klass); public: // [ScriptingObject] String ToString() const override; void OnDeleteObject() override; // [SceneObject] const Guid& GetSceneObjectId() const override; void SetParent(Actor* value, bool canBreakPrefabLink = true) override; int32 GetOrderInParent() const override; void SetOrderInParent(int32 index) override; void LinkPrefab(const Guid& prefabId, const Guid& prefabObjectId) override; void BreakPrefabLink() override; void Initialize() override; void BeginPlay(SceneBeginData* data) override; void EndPlay() override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; };