/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. // Description : Central manager for synchronized animations on multiple // animated characters/actors #ifndef CRYINCLUDE_CRYACTION_ICOOPERATIVEANIMATIONMANAGER_H #define CRYINCLUDE_CRYACTION_ICOOPERATIVEANIMATIONMANAGER_H #pragma once #include #include "IAnimatedCharacter.h" #include "IActorSystem.h" class CCooperativeAnimation; class SCharacterParams; struct SCooperativeAnimParams; struct IAnimatedCharacter; typedef DynArray TCharacterParams; /// Cooperative Animation Manager Common Interface struct ICooperativeAnimationManager { virtual ~ICooperativeAnimationManager(){} // update function for every frame // dt is the time passed since last frame virtual void Update(float dt) = 0; virtual void Reset() = 0; //! Start a new Cooperative animation //! Returns true if the animation was started //! If one of the specified actors is already part of a cooperative animation, //! the function will return false. virtual bool StartNewCooperativeAnimation(TCharacterParams& characterParams, const SCooperativeAnimParams& generalParams) = 0; //! Start a new Cooperative animation //! Returns true if the animation was started //! If one of the specified actors is already part of a cooperative animation, //! the function will return false. virtual bool StartNewCooperativeAnimation(SCharacterParams& params1, SCharacterParams& params2, const SCooperativeAnimParams& generalParams) = 0; //! This neat function allows to abuse the Cooperative Animation System for just a single //! character - taking advantage of the exact positioning virtual bool StartExactPositioningAnimation(const SCharacterParams& params, const SCooperativeAnimParams& generalParams) = 0; //! Stops all cooperative animations on this actor //! Returns true if there was at least one animation stopped, false otherwise. virtual bool StopCooperativeAnimationOnActor(IAnimatedCharacter* pActor) = 0; //! Same as above, but only stops cooperative animations that include both actors virtual bool StopCooperativeAnimationOnActor(IAnimatedCharacter* pActor1, IAnimatedCharacter* pActor2) = 0; virtual bool IsActorBusy(const IAnimatedCharacter* pActor, const CCooperativeAnimation* pIgnoreAnimation = NULL) const = 0; virtual bool IsActorBusy(const EntityId entID) const = 0; }; //! Determines what information is to be used as reference //! to align the actors for the animations enum EAlignmentRef { eAF_WildMatch = 0, //! the best location that involves the least movement will be picked eAF_FirstActor, //! the first actor will not move at all (but can be rotated), all others adjust to him eAF_FirstActorNoRot, //! the first actor will not move or rotate at all, all others adjust to him eAF_FirstActorPosition, //! the target pos and rot of the first actor is specified in general params, all others adjust to that eAF_Location, //! the reference location of the animation is specified in general params eAF_Max, }; // Default values const float animParamDefaultDistanceForSliding = 0.4f; const float animParamDefaultSlidingDuration = 0.15f; // this should ideally be the same value that is set in the AG for transition time const EAlignmentRef animParamDefaultAlignment = eAF_WildMatch; const QuatT animParamDefaultLoc = QuatT(IDENTITY); // END Default Values //! Parameters needed per character class SCharacterParams { friend class CCooperativeAnimation; public: IAnimatedCharacter* GetActor() const; bool IsActorValid() const; void SetStartDelay(float delay) { fStartDelay = delay; } void SetAllowHorizontalPhysics(bool bAllow) { bAllowHorizontalPhysics = bAllow; } QuatT GetTargetQuatT() { return qTarget; } SCharacterParams(IAnimatedCharacter* actor, const char* signalName, bool allowHPhysics = false, float slidingDuration = animParamDefaultSlidingDuration) : deltaLocatorMovement(IDENTITY) , collisionsDisabledWithFirstActor(0) , animationState(AS_Unrequested) , animFilepathCRC(0) { CRY_ASSERT_MESSAGE(actor != NULL, "Invalid parameter. The actor here may not be NULL"); CRY_ASSERT_MESSAGE(signalName != NULL, "Invalid parameter. The signal name cannot be NULL"); CRY_ASSERT_MESSAGE(strcmp(signalName, "") != 0, "Invalid parameter. The signal name cannot be empty"); CRY_ASSERT_MESSAGE(slidingDuration > 0.0f, "Invalid parameter. The sliding duration cannot be <= 0.0f"); bAnimationPlaying = false; bAllowHorizontalPhysics = allowHPhysics; entityId = actor->GetEntityId(); pActor = actor; fSlidingDuration = (slidingDuration > 0.0f) ? slidingDuration : animParamDefaultSlidingDuration; fSlidingTimer = 0.0f; fStartDelay = 0.0f; fStartDelayTimer = 0.0f; qTarget = QuatT(Vec3(ZERO), IDENTITY); qSlideOffset = QuatT(Vec3(ZERO), IDENTITY); currPos = QuatT(Vec3(ZERO), IDENTITY); sSignalName = signalName; } private: enum eAnimationState { AS_Unrequested, AS_NotReady, AS_Ready, }; SCharacterParams() {} // default constructor only available to CCooperativeAnimation // cached pointer to the actor mutable IAnimatedCharacter* pActor; // EntityId which owns the actor we need EntityId entityId; // time (in secs) this character has to slide into position while animation is already playing float fSlidingDuration; //! timer for when the character is moved over time (internal use in the CCooperativeAnim only) // Note: This a bit more complicated way of sliding is necessary to allow the character to move away // within the animation while still sliding, otherwise it locators have to be fixed in the animation // during the sliding duration and that constricts animators and is generally error-prone. float fSlidingTimer; // time (in secs) to delay starting this character's sliding and animation // Generally not needed, but useful for e.g. melee hit reactions, to start the animation of the character // being hit later than the one hitting float fStartDelay; //! timer for when the character animation should be started (internal use in the CCooperativeAnim only) float fStartDelayTimer; // name of the signal to the animation graph string sSignalName; // Target position and rotation of this character (internal use in the CCooperativeAnim only) QuatT qTarget; //! Value for the offset when sliding starts (internal use in the CCooperativeAnim only) // Needed because the animation will start to move the character away from his starting // position, so ::qTargetPos cannot be used as reference after the animation has started. // This relative offset will be applied over time. QuatT qSlideOffset; // Needed for internal sliding purposes QuatT currPos; //! Internal use only. Needed for the Play&Slide step, so locator movement is properly applied QuatT deltaLocatorMovement; //! Internal use only. Caches the FilePathCRC of the anim when using non-animgraph-based mode uint32 animFilepathCRC; // checking if the character has finished this coop action (he might already have started another) bool bAnimationPlaying; // if this is true, the animation will not clip into solid objects, but this can then affect // and falsify the relative positioning of the characters towards each other. bool bAllowHorizontalPhysics; //! Internal use only. For disabling collisions between first actor and the rest bool collisionsDisabledWithFirstActor; //! Internal use only. Reflects the state of the animation for this character when using non-animgraph-based mode uint8 animationState; }; //! General Parameters for the animation struct SCooperativeAnimParams { //! Set to true if the animations shall be started no matter what. //! This can mean interrupting other coopAnims, and can result in animation snapping. bool bForceStart; //! true if this is supposed to be a looping animation bool bLooping; //! true if we don't want to abort animation if one of the characters dies (useful for e.g. melee killing moves) bool bIgnoreCharacterDeath; //! Defines the way the characters are aligned to each other EAlignmentRef eAlignment; //! Position and orientation that animation is to be started from (eAlignment will determine it's specific meaning) QuatT qLocation; //! true to enable the terrain elevation check bool bPreventFallingThroughTerrain; // disables collisions between first actor and the others bool bNoCollisionsBetweenFirstActorAndRest; SCooperativeAnimParams(bool forceStart = false, bool looping = false, EAlignmentRef alignment = animParamDefaultAlignment, const QuatT& location = animParamDefaultLoc, bool _bPreventFallingThroughTerrain = true) : bForceStart(forceStart) , bLooping(looping) , bIgnoreCharacterDeath(false) , eAlignment(alignment) , qLocation(location) , bPreventFallingThroughTerrain(_bPreventFallingThroughTerrain) , bNoCollisionsBetweenFirstActorAndRest(false) { } }; ////////////////////////////////////////////////////////////////////////// ILINE IAnimatedCharacter* SCharacterParams::GetActor() const { return pActor; } ////////////////////////////////////////////////////////////////////////// ILINE bool SCharacterParams::IsActorValid() const { // No animated character or not Character instance makes an actor invalid return (pActor != NULL) && pActor->GetEntity() && (pActor->GetEntity()->GetCharacter(0) != NULL); } #endif // CRYINCLUDE_CRYACTION_ICOOPERATIVEANIMATIONMANAGER_H