You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h

211 lines
10 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/Component/Component.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/Interface/Interface.h>
#include <AzFramework/Physics/RagdollPhysicsBus.h>
#include <AzFramework/Physics/CharacterPhysicsDataBus.h>
#include <AzFramework/Physics/Common/PhysicsEvents.h>
#include <Integration/Assets/ActorAsset.h>
#include <Integration/ActorComponentBus.h>
#include <Integration/Rendering/RenderActorInstance.h>
#include <EMotionFX/Source/ActorBus.h>
#include <LmbrCentral/Animation/AttachmentComponentBus.h>
namespace EMotionFX
{
namespace Integration
{
class ActorComponent
: public AZ::Component
, private AZ::Data::AssetBus::Handler
, private AZ::TransformNotificationBus::MultiHandler
, private AZ::TickBus::Handler
, private ActorComponentRequestBus::Handler
, private ActorComponentNotificationBus::Handler
, private LmbrCentral::AttachmentComponentNotificationBus::Handler
, private AzFramework::CharacterPhysicsDataRequestBus::Handler
, private AzFramework::RagdollPhysicsNotificationBus::Handler
{
public:
AZ_COMPONENT(ActorComponent, "{BDC97E7F-A054-448B-A26F-EA2B5D78E377}");
friend class EditorActorComponent;
class BoundingBoxConfiguration
{
public:
AZ_TYPE_INFO(BoundingBoxConfiguration, "{EBCFF975-00A5-4578-85C7-59909F52067C}");
BoundingBoxConfiguration() = default;
EMotionFX::ActorInstance::EBoundsType m_boundsType = EMotionFX::ActorInstance::BOUNDS_STATIC_BASED;
float m_expandBy = 25.0f; ///< Expand the bounding volume by the given percentage.
bool m_autoUpdateBounds = true;
float m_updateTimeFrequency = 0.0f;
AZ::u32 m_updateItemFrequency = 1;
// Set the bounding box configuration of the given actor instance to the parameters given by 'this'. The actor instance must not be null (this is not checked).
void Set(ActorInstance* actorInstance) const;
// Set the bounding box configuration, then update the bounds of the actor instance
void SetAndUpdate(ActorInstance* actorInstance) const;
static void Reflect(AZ::ReflectContext* context);
AZ::Crc32 GetVisibilityAutoUpdate() const;
AZ::Crc32 GetVisibilityAutoUpdateSettings() const;
};
/**
* Configuration struct for procedural configuration of Actor Components.
*/
struct Configuration
{
AZ_TYPE_INFO(Configuration, "{053BFBC0-ABAA-4F4E-911F-5320F941E1A8}")
AZ::Data::Asset<ActorAsset> m_actorAsset{AZ::Data::AssetLoadBehavior::NoLoad}; ///< Selected actor asset.
ActorAsset::MaterialList m_materialPerLOD{}; ///< Material assignment per LOD.
AZ::EntityId m_attachmentTarget{}; ///< Target entity this actor should attach to.
size_t m_attachmentJointIndex = InvalidIndex; ///< Index of joint on target skeleton for actor attachments.
AttachmentType m_attachmentType = AttachmentType::None; ///< Type of attachment.
bool m_renderSkeleton = false; ///< Toggles debug rendering of the skeleton.
bool m_renderCharacter = true; ///< Toggles rendering of the character.
bool m_renderBounds = false; ///< Toggles rendering of the character bounds used for visibility testing.
SkinningMethod m_skinningMethod = SkinningMethod::DualQuat; ///< The skinning method for this actor
size_t m_lodLevel = 0;
// Force updating the joints when it is out of camera view. By
// default, joints level update (beside the root joint) on
// actor are disabled when the actor is out of view.
bool m_forceUpdateJointsOOV = false;
BoundingBoxConfiguration m_bboxConfig; ///< Configuration for bounding box type and updates
static void Reflect(AZ::ReflectContext* context);
};
ActorComponent(const Configuration* configuration = nullptr);
~ActorComponent() override;
//////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
void Activate() override;
void Deactivate() override;
//////////////////////////////////////////////////////////////////////////
// ActorComponentRequestBus::Handler
size_t GetNumJoints() const override;
size_t GetJointIndexByName(const char* name) const override;
AZ::Transform GetJointTransform(size_t jointIndex, Space space) const override;
void GetJointTransformComponents(size_t jointIndex, Space space, AZ::Vector3& outPosition, AZ::Quaternion& outRotation, AZ::Vector3& outScale) const override;
Physics::AnimationConfiguration* GetPhysicsConfig() const override;
ActorInstance* GetActorInstance() override { return m_actorInstance.get(); }
void AttachToEntity(AZ::EntityId targetEntityId, AttachmentType attachmentType) override;
void DetachFromEntity() override;
bool GetRenderCharacter() const override;
void SetRenderCharacter(bool enable) override;
bool GetRenderActorVisible() const override;
SkinningMethod GetSkinningMethod() const override;
void SetActorAsset(AZ::Data::Asset<ActorAsset> actorAsset) override;
//////////////////////////////////////////////////////////////////////////
// ActorComponentNotificationBus::Handler
void OnActorInstanceCreated(ActorInstance* actorInstance) override;
void OnActorInstanceDestroyed(ActorInstance* actorInstance) override;
//////////////////////////////////////////////////////////////////////////
// The entity has attached to the target.
void OnAttached(AZ::EntityId targetId) override;
// The entity is detaching from the target.
void OnDetached(AZ::EntityId targetId) override;
//////////////////////////////////////////////////////////////////////////
// AzFramework::CharacterPhysicsDataBus::Handler
bool GetRagdollConfiguration(Physics::RagdollConfiguration& config) const override;
Physics::RagdollState GetBindPose(const Physics::RagdollConfiguration& config) const override;
AZStd::string GetParentNodeName(const AZStd::string& childName) const override;
//////////////////////////////////////////////////////////////////////////
// AzFramework::RagdollPhysicsNotificationBus::Handler
void OnRagdollActivated() override;
void OnRagdollDeactivated() override;
//////////////////////////////////////////////////////////////////////////
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("EMotionFXActorService", 0xd6e8f48d));
provided.push_back(AZ_CRC("MeshService", 0x71d8a455));
provided.push_back(AZ_CRC("CharacterPhysicsDataService", 0x34757927));
provided.push_back(AZ_CRC("MaterialReceiverService", 0x0d1a6a74));
}
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("EMotionFXActorService", 0xd6e8f48d));
incompatible.push_back(AZ_CRC("MeshService", 0x71d8a455));
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
}
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
dependent.push_back(AZ_CRC("PhysicsService", 0xa7350d22));
}
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC("TransformService", 0x8ee22c50));
}
static void Reflect(AZ::ReflectContext* context);
// AZ::Data::AssetBus::Handler
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
bool IsPhysicsSceneSimulationFinishEventConnected() const;
AZ::Data::Asset<ActorAsset> GetActorAsset() const { return m_configuration.m_actorAsset; }
void SetRenderFlag(ActorRenderFlagBitset renderFlags);
private:
// AZ::TransformNotificationBus::MultiHandler
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
// AZ::TickBus::Handler
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
int GetTickOrder() override;
void CheckActorCreation();
void DestroyActor();
void CheckAttachToEntity();
Configuration m_configuration; ///< Component configuration.
/// Live state
ActorAsset::ActorInstancePtr m_attachmentTargetActor; ///< Target actor instance to attach to.
AZ::EntityId m_attachmentTargetEntityId; ///< Target actor entity ID
ActorAsset::ActorInstancePtr m_actorInstance; ///< Live actor instance.
AZStd::vector<AZ::EntityId> m_attachments;
AZStd::unique_ptr<RenderActorInstance> m_renderActorInstance;
ActorRenderFlagBitset m_debugRenderFlags; ///< Actor debug render flag
AzPhysics::SceneEvents::OnSceneSimulationFinishHandler m_sceneFinishSimHandler;
};
} //namespace Integration
} // namespace EMotionFX