BVB Source Codes

CRYENGINE Show PlayCGANode.cpp Source code

Return Download CRYENGINE: download PlayCGANode.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "CryAction.h"
  5. #include "IAnimatedCharacter.h"
  6. #include "IMovementController.h"
  7.  
  8. #include <IActorSystem.h>
  9. #include <IAnimatedCharacter.h>
  10. #include <GameObjects/GameObject.h>
  11. #include <CryAnimation/ICryAnimation.h>
  12. #include <ICooperativeAnimationManager.h>
  13. #include <CryFlowGraph/IFlowBaseNode.h>
  14.  
  15. class CPlayCGA_Node : public CFlowBaseNode<eNCT_Instanced>
  16. {
  17.         IEntity* m_pEntity;
  18. public:
  19.         CPlayCGA_Node(SActivationInfo* pActInfo) : m_pEntity(0)
  20.         {
  21.         };
  22.  
  23.         IFlowNodePtr Clone(SActivationInfo* pActInfo)
  24.         {
  25.                 return new CPlayCGA_Node(pActInfo);
  26.         }
  27.  
  28.         virtual void GetMemoryUsage(ICrySizer* s) const
  29.         {
  30.                 s->Add(*this);
  31.         }
  32.  
  33.         virtual void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  34.         {
  35.                 // TODO: what to do on load?
  36.                 // sequence might have played, or should we replay from start or trigger done or ???
  37.                 // we set the entity to our best knowledge
  38.                 if (ser.IsReading())
  39.                         m_pEntity = pActInfo->pEntity;
  40.         }
  41.  
  42.         virtual void GetConfiguration(SFlowNodeConfig& config)
  43.         {
  44.                 static const SInputPortConfig in_config[] = {
  45.                         InputPortConfig<string>("CGA_File",           _HELP("CGA Filename")),
  46.                         InputPortConfig<string>("anim_CGA_Animation", _HELP("CGA Animation name")),
  47.                         InputPortConfig<bool>("Trigger",              _HELP("Starts the animation")),
  48.                         { 0 }
  49.                 };
  50.                 static const SOutputPortConfig out_config[] = {
  51.                         OutputPortConfig<bool>("Done", _HELP("Set to TRUE when animation is finished")),
  52.                         { 0 }
  53.                 };
  54.                 config.sDescription = _HELP("Plays a CGA Animation");
  55.                 config.nFlags |= EFLN_TARGET_ENTITY;
  56.                 config.pInputPorts = in_config;
  57.                 config.pOutputPorts = out_config;
  58.                 config.SetCategory(EFLN_APPROVED);
  59.         }
  60.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  61.         {
  62.                 switch (event)
  63.                 {
  64.                 case eFE_Activate:
  65.                         {
  66.  
  67.                                 m_pEntity = pActInfo->pEntity;
  68.                                 if (m_pEntity != NULL)
  69.                                 {
  70.                                         if (IsPortActive(pActInfo, 0))
  71.                                         {
  72.                                                 m_pEntity->LoadCharacter(0, GetPortString(pActInfo, 0));
  73.                                         }
  74.                                         if (!IsPortActive(pActInfo, 2)) break;
  75.                                         ICharacterInstance* pCharacter = m_pEntity->GetCharacter(0);
  76.                                         if (pCharacter != NULL)
  77.                                         {
  78.                                                 CryCharAnimationParams params;
  79.                                                 pCharacter->GetISkeletonAnim()->StartAnimation(GetPortString(pActInfo, 1), params);
  80.                                                 //pCharacter->SetFlags(pCharacter->GetFlags() | CS_FLAG_UPDATE_ALWAYS); doesn't seem to matter
  81.                                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  82.                                                 ActivateOutput(pActInfo, 0, false);
  83.                                         }
  84.                                         else CryLogAlways("PlayCGA - Get/LoadCharacter failed");
  85.                                 }
  86.                                 else CryLogAlways("PlayCGA - Invalid entity pointer");
  87.                                 break;
  88.                         }
  89.  
  90.                 case eFE_Initialize:
  91.                         m_pEntity = pActInfo->pEntity;
  92.                         if (m_pEntity)
  93.                         {
  94.                                 m_pEntity->LoadCharacter(0, GetPortString(pActInfo, 0));
  95.                         }
  96.                         break;
  97.  
  98.                 case eFE_Update:
  99.                         {
  100.                                 if (m_pEntity != NULL)
  101.                                 {
  102.                                         ICharacterInstance* pCharacter = m_pEntity->GetCharacter(0);
  103.                                         //CryLogAlways("Using deprecated AnimAnimation node in animation graph (entity %s)", data.pEntity->GetName());
  104.                                         /*if(pCharacter->GetCurrentAnimation(0) == -1)
  105.                                            {
  106.                                            ActivateOutput(pActInfo, 0, true);
  107.                                            pActInfo->pGraph->SetRegularlyUpdated( pActInfo->myID, false );
  108.                                            }*/
  109.  
  110.                                         QuatT offset(m_pEntity->GetSlotLocalTM(0, false));
  111.                                         QuatT renderLocation(m_pEntity->GetSlotWorldTM(0));
  112.                                         QuatTS animLocation = renderLocation * offset; // TODO: This might be wrong.
  113.                                         float fDistance = (GetISystem()->GetViewCamera().GetPosition() - animLocation.t).GetLength();
  114.  
  115.                                         SAnimationProcessParams params;
  116.                                         params.locationAnimation = renderLocation;
  117.                                         params.bOnRender = 0;
  118.                                         params.zoomAdjustedDistanceFromCamera = fDistance;
  119.                                         pCharacter->StartAnimationProcessing(params);
  120.                                 }
  121.                                 break;
  122.                         }
  123.                 }
  124.                 ;
  125.         };
  126. };
  127.  
  128. class CAnimationBoneInfo_Node
  129.         : public CFlowBaseNode<eNCT_Singleton>
  130. {
  131.         enum EInputPorts
  132.         {
  133.                 eInputPort_BoneName = 0,
  134.                 eInputPort_BoneId,
  135.                 eInputPort_Enabled,
  136.                 eInputPort_Get
  137.         };
  138.  
  139.         enum EOutputPorts
  140.         {
  141.                 eOutputPort_LocalPosition = 0,
  142.                 eOutputPort_LocalRotation,
  143.                 eOutputPort_WorldPosition,
  144.                 eOutputPort_WorldRotation
  145.         };
  146.  
  147. public:
  148.         CAnimationBoneInfo_Node(SActivationInfo* pActInfo)
  149.         {
  150.         }
  151.  
  152.         virtual void GetMemoryUsage(ICrySizer* s) const
  153.         {
  154.                 s->Add(*this);
  155.         }
  156.  
  157.         virtual void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  158.         {
  159.                 if (ser.IsReading())
  160.                         OnChange(pActInfo);
  161.         }
  162.  
  163.         virtual void GetConfiguration(SFlowNodeConfig& config)
  164.         {
  165.                 static const SInputPortConfig in_config[] = {
  166.                         InputPortConfig<string>("bone_BoneName", _HELP("Name of Bone to get info for")),
  167.                         InputPortConfig<int>("BoneId", INVALID_JOINT_ID, _HELP("Id of the bone to get info for (used only if BoneName is left empty)")),
  168.                         InputPortConfig<bool>("Enabled", true, _HELP("Enable / Disable automatic per frame updates")),
  169.                         InputPortConfig_Void("Get", _HELP("Retrieve the bone info just once")),
  170.                         { 0 }
  171.                 };
  172.                 static const SOutputPortConfig out_config[] = {
  173.                         OutputPortConfig<Vec3>("LocalPos", _HELP("Position of bone in Local Space")),
  174.                         OutputPortConfig<Vec3>("LocalRot", _HELP("Rotation of bone in Local Space")),
  175.                         OutputPortConfig<Vec3>("WorldPos", _HELP("Position of bone in World Space")),
  176.                         OutputPortConfig<Vec3>("WorldRot", _HELP("Rotation of bone in World Space")),
  177.                         { 0 }
  178.                 };
  179.                 config.sDescription = _HELP("Outputs information of the bone [BoneName] of the character of the attached entity");
  180.                 config.nFlags |= EFLN_TARGET_ENTITY;
  181.                 config.pInputPorts = in_config;
  182.                 config.pOutputPorts = out_config;
  183.                 config.SetCategory(EFLN_APPROVED);
  184.         }
  185.  
  186.         static int32 GetDesiredJointId(SActivationInfo* pActInfo, ICharacterInstance* pCharacter)
  187.         {
  188.                 int32 result = INVALID_JOINT_ID;
  189.  
  190.                 const IDefaultSkeleton& defaultSkeleton = pCharacter->GetIDefaultSkeleton();
  191.                 const string& boneName = GetPortString(pActInfo, eInputPort_BoneName);
  192.  
  193.                 if (!boneName.empty())
  194.                 {
  195.                         result = defaultSkeleton.GetJointIDByName(boneName.c_str());
  196.                         if (result == INVALID_JOINT_ID)
  197.                         {
  198.                                 CryLogAlways("[flow] Animations:BoneInfo: Cannot find bone '%s' in character 0 of entity '%s'", boneName.c_str(), pActInfo->pEntity->GetName());
  199.                         }
  200.                 }
  201.                 else
  202.                 {
  203.                         result = GetPortInt(pActInfo, eInputPort_BoneId);
  204.                         if (result >= static_cast<int32>(defaultSkeleton.GetJointCount()))
  205.                         {
  206.                                 result = INVALID_JOINT_ID;
  207.                         }
  208.                 }
  209.  
  210.                 return result;
  211.         }
  212.  
  213.         void OnChange(SActivationInfo* pActInfo)
  214.         {
  215.                 struct UpdateChanger
  216.                 {
  217.                         UpdateChanger(SActivationInfo* const pActivationInfo, const bool bUpdate) : pActivationInfo(pActivationInfo), bUpdate(bUpdate) {}
  218.                         ~UpdateChanger() { pActivationInfo->pGraph->SetRegularlyUpdated(pActivationInfo->myID, bUpdate); }
  219.                         SActivationInfo* pActivationInfo;
  220.                         bool             bUpdate;
  221.                 };
  222.  
  223.                 UpdateChanger updateChanger(pActInfo, false);
  224.  
  225.                 if (IEntity* pEntity = pActInfo->pEntity)
  226.                 {
  227.                         if (ICharacterInstance* pCharacter = pEntity->GetCharacter(0))
  228.                         {
  229.                                 int32 jointId = GetDesiredJointId(pActInfo, pCharacter);
  230.                                 const bool bEnabled = GetPortBool(pActInfo, eInputPort_Enabled);
  231.                                 updateChanger.bUpdate = (jointId != INVALID_JOINT_ID) && bEnabled;
  232.                         }
  233.                 }
  234.         }
  235.  
  236.         void GetJointInfo(SActivationInfo* pActInfo)
  237.         {
  238.                 if (IEntity* pEntity = pActInfo->pEntity)
  239.                 {
  240.                         if (ICharacterInstance* pCharacter = pEntity->GetCharacter(0))
  241.                         {
  242.                                 const IDefaultSkeleton& rIDefaultSkeleton = pCharacter->GetIDefaultSkeleton();
  243.                                 const int32 jointID = rIDefaultSkeleton.GetJointIDByName(GetPortString(pActInfo, 0).c_str());
  244.                                 if (jointID < 0)
  245.                                 {
  246.                                         CryLogAlways("[flow] Animations:BoneInfo Cannot find bone '%s' in character 0 of entity '%s'", GetPortString(pActInfo, 0).c_str(), pEntity->GetName());
  247.                                         return;
  248.                                 }
  249.                                 const ISkeletonPose* const pISkeletonPose = pCharacter->GetISkeletonPose();
  250.                                 Matrix34 mat = Matrix34(pISkeletonPose->GetAbsJointByID(jointID));
  251.                                 ActivateOutput(pActInfo, eOutputPort_LocalPosition, mat.GetTranslation());
  252.  
  253.                                 mat.OrthonormalizeFast();
  254.                                 const Ang3 angles = Ang3::GetAnglesXYZ(Matrix33(Quat(mat)));
  255.                                 ActivateOutput(pActInfo, eOutputPort_LocalRotation, Vec3(RAD2DEG(angles)));
  256.  
  257.                                 Matrix34 matWorld = pEntity->GetSlotWorldTM(0) * mat;
  258.                                 ActivateOutput(pActInfo, eOutputPort_WorldPosition, matWorld.GetTranslation());
  259.  
  260.                                 matWorld.OrthonormalizeFast();
  261.                                 const Ang3 anglesWorld = Ang3::GetAnglesXYZ(Matrix33(Quat(matWorld)));
  262.                                 ActivateOutput(pActInfo, eOutputPort_WorldRotation, Vec3(RAD2DEG(anglesWorld)));
  263.                         }
  264.                 }
  265.         }
  266.  
  267.         void OnUpdate(SActivationInfo* pActInfo)
  268.         {
  269.                 GetJointInfo(pActInfo);
  270.         }
  271.  
  272.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  273.         {
  274.                 switch (event)
  275.                 {
  276.                 case eFE_Activate:
  277.                         {
  278.                                 OnChange(pActInfo);
  279.                                 const bool enabled = GetPortBool(pActInfo, eInputPort_Enabled);
  280.                                 if (!enabled && IsPortActive(pActInfo, eInputPort_Get))
  281.                                 {
  282.                                         GetJointInfo(pActInfo);
  283.                                 }
  284.                         }
  285.                         break;
  286.  
  287.                 case eFE_Initialize:
  288.                         OnChange(pActInfo);
  289.                         break;
  290.  
  291.                 case eFE_Update:
  292.                         OnUpdate(pActInfo);
  293.                         break;
  294.                 }
  295.         }
  296. };
  297.  
  298. //////////////////////////////////////////////////////////////////////////
  299. class CPlayAnimation_Node : public CFlowBaseNode<eNCT_Instanced>
  300. {
  301.         uint32 m_token;
  302.         uint32 m_layer;
  303.  
  304.         bool   m_firedAlmostDone;
  305.         bool   m_bForcedActivate;
  306.         bool   m_bForcedUpdateActivate;
  307.         bool   m_manualAnimationControlledMovement;
  308.         bool   m_bLooping;
  309.  
  310.         float  m_almostDonePercentage;
  311.         float  m_playbackSpeedMultiplier;
  312.  
  313. public:
  314.  
  315.         enum EInputs
  316.         {
  317.                 IN_START,
  318.                 IN_STOP,
  319.                 IN_ANIMATION,
  320.                 IN_BLEND_TIME,
  321.                 IN_LAYER,
  322.                 IN_LOOP,
  323.                 IN_REPEAT_LAST_FRAME,
  324.                 IN_FORCE_UPDATE,
  325.                 IN_PAUSE_ANIM_GRAPH,
  326.                 IN_CONTROL_MOVEMENT,
  327.                 IN_ALMOST_DONE_PERCENTAGE,
  328.                 IN_PLAYBACK_SPEED_MULTIPLIER,
  329.         };
  330.  
  331.         enum EOutputs
  332.         {
  333.                 OUT_DONE,
  334.                 OUT_ALMOST_DONE,
  335.         };
  336.  
  337.         CPlayAnimation_Node(SActivationInfo* pActInfo)
  338.         {
  339.                 m_firedAlmostDone = false;
  340.                 m_bForcedActivate = false;
  341.                 m_bForcedUpdateActivate = false;
  342.                 m_bLooping = false;
  343.                 m_manualAnimationControlledMovement = false;
  344.                 m_token = 0;
  345.                 m_layer = 0;
  346.                 m_almostDonePercentage = 0.85f;
  347.                 m_playbackSpeedMultiplier = 1.0f;
  348.         };
  349.  
  350.         ~CPlayAnimation_Node()
  351.         {
  352.         }
  353.  
  354.         IFlowNodePtr Clone(SActivationInfo* pActInfo)
  355.         {
  356.                 return new CPlayAnimation_Node(pActInfo);
  357.         }
  358.  
  359.         virtual void GetMemoryUsage(ICrySizer* s) const
  360.         {
  361.                 s->Add(*this);
  362.         }
  363.  
  364.         virtual void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  365.         {
  366.                 ser.Value("m_token", m_token);
  367.                 ser.Value("m_firedAlmostDone", m_firedAlmostDone);
  368.                 ser.Value("m_bLooping", m_bLooping);
  369.                 ser.Value("m_bForcedActivate", m_bForcedActivate);
  370.                 ser.Value("m_bForcedUpdateActivate", m_bForcedUpdateActivate);
  371.                 ser.Value("m_manualAnimationControlledMovement", m_manualAnimationControlledMovement);
  372.                 ser.Value("m_layer", m_layer);
  373.                 ser.Value("m_almostDonePercentage", m_almostDonePercentage);
  374.                 ser.Value("m_playbackSpeedMultiplier", m_playbackSpeedMultiplier);
  375.         }
  376.  
  377.         virtual void GetConfiguration(SFlowNodeConfig& config)
  378.         {
  379.                 static const SInputPortConfig in_config[] = {
  380.                         InputPortConfig_Void("Start", _HELP("Starts the animation")),
  381.                         InputPortConfig_Void("Stop", _HELP("Stops the animation")),
  382.                         InputPortConfig<string>("anim_Animation", _HELP("Animation name"), 0, _UICONFIG("ref_entity=entityId")),
  383.                         InputPortConfig<float>("BlendInTime", 0.2f, _HELP("Blend in time")),
  384.                         InputPortConfig<int>("Layer", _HELP("Layer in which to play the animation (0-15).\nFullbody Animations should be played in layer 0.")),
  385.                         InputPortConfig<bool>("Loop", _HELP("When True animation will loop and will never stop")),
  386.                         InputPortConfig<bool>("StayOnLastFrame", _HELP("When True animation will not reset to the first frame after it finished. Ignored when 'Loop' is true.")),
  387.                         InputPortConfig<bool>("ForceUpdate", false, _HELP("When True animation will play even if not visible")),
  388.                         InputPortConfig<bool>("PauseAnimGraph", false, _HELP("Deprecated, this input has no effect")),
  389.                         InputPortConfig<bool>("ControlMovement", false, _HELP("When True this animation will control the entities movement")),
  390.                         InputPortConfig<float>("AlmostDonePercentage", m_almostDonePercentage, _HELP("Normalised percentage of animation progress at which Almost Done output will trigger, values between 0.05 & 0.95")),
  391.                         InputPortConfig<float>("PlaybackSpeedMultiplier", m_playbackSpeedMultiplier, _HELP("Speed multiplier at which to play the animation")),
  392.                         { 0 }
  393.                 };
  394.  
  395.                 static const SOutputPortConfig out_config[] = {
  396.                         OutputPortConfig_Void("Done",       _HELP("Send an event when animation is finished")),
  397.                         OutputPortConfig_Void("AlmostDone", _HELP("Send an event when animation is almost finished - can be used to enhance blending to a different PlayAnimation node.")),
  398.                         { 0 }
  399.                 };
  400.  
  401.                 config.sDescription = _HELP("Plays an Animation on this character's skeleton.");
  402.                 config.nFlags |= EFLN_TARGET_ENTITY | EFLN_AISEQUENCE_SUPPORTED;
  403.                 config.pInputPorts = in_config;
  404.                 config.pOutputPorts = out_config;
  405.                 config.SetCategory(EFLN_APPROVED);
  406.         }
  407.  
  408.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  409.         {
  410.                 switch (event)
  411.                 {
  412.                 case eFE_Activate:
  413.                         {
  414.                                 if (IsPortActive(pActInfo, IN_START))
  415.                                 {
  416.                                         StartAnimation(pActInfo);
  417.                                 }
  418.                                 else if (IsPortActive(pActInfo, IN_STOP))
  419.                                 {
  420.                                         StopAnimation(pActInfo);
  421.                                 }
  422.                         }
  423.                         break;
  424.  
  425.                 case eFE_Update:
  426.                         {
  427.                                 Update(pActInfo);
  428.                         }
  429.                         break;
  430.                 }
  431.                 ;
  432.         };
  433.  
  434. private:
  435.  
  436.         uint32 ChooseToken(ICharacterInstance* pCharacter) const
  437.         {
  438.                 ISkeletonAnim* pSkel = pCharacter->GetISkeletonAnim();
  439.                 uint32 maxToken = 0;
  440.                 for (int i = 0; i < pSkel->GetNumAnimsInFIFO(m_layer); i++)
  441.                         maxToken = max(pSkel->GetAnimFromFIFO(m_layer, i).GetUserToken(), maxToken);
  442.                 if (!maxToken) // choose a (hopefully safe default)
  443.                         maxToken = 0xffff0000;
  444.                 else
  445.                         maxToken += 10000;
  446.                 return maxToken;
  447.         }
  448.  
  449.         void StartAnimation(SActivationInfo* pActInfo)
  450.         {
  451.                 ICharacterInstance* pCharacterInstance = (pActInfo->pEntity != NULL) ? pActInfo->pEntity->GetCharacter(0) : NULL;
  452.                 if (pCharacterInstance)
  453.                 {
  454.                         CryCharAnimationParams aparams;
  455.                         aparams.m_fTransTime = GetPortFloat(pActInfo, IN_BLEND_TIME);
  456.  
  457.                         m_almostDonePercentage = clamp_tpl(GetPortFloat(pActInfo, IN_ALMOST_DONE_PERCENTAGE), 0.05f, 0.95f);
  458.  
  459.                         m_bLooping = GetPortBool(pActInfo, IN_LOOP);
  460.                         if (m_bLooping)
  461.                                 aparams.m_nFlags |= CA_LOOP_ANIMATION;
  462.  
  463.                         m_playbackSpeedMultiplier = GetPortFloat(pActInfo, IN_PLAYBACK_SPEED_MULTIPLIER);
  464.                         aparams.m_fPlaybackSpeed = m_playbackSpeedMultiplier;
  465.  
  466.                         m_playbackSpeedMultiplier = GetPortFloat(pActInfo, IN_PLAYBACK_SPEED_MULTIPLIER);
  467.                         aparams.m_fPlaybackSpeed = m_playbackSpeedMultiplier;
  468.  
  469.                         m_bForcedActivate = false;
  470.                         m_bForcedUpdateActivate = false;
  471.                         if (GetPortBool(pActInfo, IN_FORCE_UPDATE))
  472.                         {
  473.                                 aparams.m_nFlags |= CA_FORCE_SKELETON_UPDATE;
  474.                                 if (pActInfo->pEntity->IsActive() == false)
  475.                                 {
  476.                                         m_bForcedActivate = true;
  477.                                         pActInfo->pEntity->Activate(true); // maybe unforce update as well
  478.                                 }
  479.  
  480.                                 m_bForcedUpdateActivate = true;
  481.                                 SetForceUpdate(pActInfo->pEntity->GetId(), true);
  482.                         }
  483.  
  484.                         const bool animationMovementControl = GetPortBool(pActInfo, IN_CONTROL_MOVEMENT);
  485.                         const string& animation = GetPortString(pActInfo, IN_ANIMATION);
  486.  
  487.                         m_layer = GetPortInt(pActInfo, IN_LAYER);
  488.                         m_layer = CLAMP(m_layer, 0, 15);          // safety checking on the layer number
  489.  
  490.                         aparams.m_nLayerID = m_layer;
  491.                         aparams.m_nUserToken = ChooseToken(pCharacterInstance);
  492.                         aparams.m_nFlags |= (animationMovementControl && (m_layer == 0)) ? CA_FULL_ROOT_PRIORITY : 0;
  493.  
  494.                         ISkeletonAnim* pISkeletonAnim = pCharacterInstance->GetISkeletonAnim();
  495.                         const bool bStarted = pISkeletonAnim->StartAnimation(animation, aparams);
  496.  
  497.                         IScriptTable* pEntityScript = pActInfo->pEntity->GetScriptTable();
  498.                         const char* pFuncName = "OnFlowGraphAnimationStart";
  499.                         if (pEntityScript && pEntityScript->HaveValue(pFuncName))
  500.                                 Script::CallMethod(pEntityScript, pFuncName, animation.c_str(), m_layer, GetPortBool(pActInfo, IN_LOOP));
  501.  
  502.                         if (bStarted)
  503.                         {
  504.                                 m_token = aparams.m_nUserToken;
  505.                         }
  506.                         else
  507.                         {
  508.                                 //make sure game logic continues nevertheless
  509.                                 ActivateOutput(pActInfo, OUT_ALMOST_DONE, SFlowSystemVoid());
  510.                                 ActivateOutput(pActInfo, OUT_DONE, SFlowSystemVoid());
  511.                         }
  512.  
  513.                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  514.                         m_firedAlmostDone = false;
  515.  
  516.                         if (animationMovementControl)
  517.                         {
  518.                                 bool needsManualUpdate = (m_layer == 0);
  519.                                 if (IGameObject* pGameObject = CCryAction::GetCryAction()->GetGameObject(pActInfo->pEntity->GetId()))
  520.                                 {
  521.                                         if (IAnimatedCharacter* pAnimatedCharacter = static_cast<IAnimatedCharacter*>(pGameObject->QueryExtension("AnimatedCharacter")))
  522.                                         {
  523.                                                 needsManualUpdate = false;
  524.                                         }
  525.                                 }
  526.  
  527.                                 if (needsManualUpdate)
  528.                                 {
  529.                                         pISkeletonAnim->SetAnimationDrivenMotion(1);
  530.                                         m_manualAnimationControlledMovement = true;
  531.                                 }
  532.                         }
  533.                 }
  534.         }
  535.  
  536.         void StopAnimation(SActivationInfo* pActInfo)
  537.         {
  538.                 if (pActInfo->pEntity)
  539.                 {
  540.                         if (m_bForcedActivate)
  541.                         {
  542.                                 pActInfo->pEntity->Activate(false);
  543.                                 m_bForcedActivate = false;
  544.                         }
  545.  
  546.                         if (m_bForcedUpdateActivate)
  547.                         {
  548.                                 m_bForcedUpdateActivate = false;
  549.                                 SetForceUpdate(pActInfo->pEntity->GetId(), false);
  550.                         }
  551.  
  552.                         ICharacterInstance* pCharacterInstance = pActInfo->pEntity->GetCharacter(0);
  553.                         if (pCharacterInstance != NULL)
  554.                         {
  555.                                 ISkeletonAnim* pSkeletonAnimation = pCharacterInstance->GetISkeletonAnim();
  556.                                 for (int i = 0; i < pSkeletonAnimation->GetNumAnimsInFIFO(m_layer); i++)
  557.                                 {
  558.                                         CAnimation& anim = pSkeletonAnimation->GetAnimFromFIFO(m_layer, i);
  559.                                         if (anim.HasUserToken(m_token))
  560.                                         {
  561.                                                 anim.ClearActivated(); // so removal will always work, maybe add a new method to IS
  562.                                                 pSkeletonAnimation->RemoveAnimFromFIFO(m_layer, i);
  563.                                                 break;
  564.                                         }
  565.                                 }
  566.                         }
  567.  
  568.                         IScriptTable* pEntityScript = pActInfo->pEntity->GetScriptTable();
  569.                         const char* pFuncName = "OnFlowGraphAnimationStop";
  570.                         if (pEntityScript && pEntityScript->HaveValue(pFuncName))
  571.                                 Script::CallMethod(pEntityScript, pFuncName);
  572.                 }
  573.         }
  574.  
  575.         void Update(SActivationInfo* pActInfo)
  576.         {
  577.                 bool tokenFound = false;
  578.                 bool almostDone = false;
  579.                 bool isAlmostDoneConnected = false;
  580.  
  581.                 QuatT relativeAnimationMovement(IDENTITY, ZERO);
  582.                 ICharacterInstance* pCharacterInstance = m_token && pActInfo->pEntity ? pActInfo->pEntity->GetCharacter(0) : NULL;
  583.                 ISkeletonAnim* pSkeletonAnimation = NULL;
  584.                 if (pCharacterInstance)
  585.                 {
  586.                         pSkeletonAnimation = pCharacterInstance->GetISkeletonAnim();
  587.                         for (int i = 0; i < pSkeletonAnimation->GetNumAnimsInFIFO(m_layer); i++)
  588.                         {
  589.                                 const CAnimation& animation = pSkeletonAnimation->GetAnimFromFIFO(m_layer, i);
  590.                                 if (animation.HasUserToken(m_token))
  591.                                 {
  592.                                         tokenFound = true;
  593.                                         const float animationTime = pSkeletonAnimation->GetAnimationNormalizedTime(&animation);
  594.                                         almostDone = animationTime > m_almostDonePercentage;
  595.                                         if (m_bLooping && !almostDone)
  596.                                         {
  597.                                                 m_firedAlmostDone = false;
  598.                                         }
  599.                                 }
  600.                         }
  601.                         relativeAnimationMovement = pSkeletonAnimation->GetRelMovement();
  602.                 }
  603.  
  604.                 if (almostDone && !m_firedAlmostDone)
  605.                 {
  606.                         ActivateOutput(pActInfo, OUT_ALMOST_DONE, SFlowSystemVoid());
  607.                         isAlmostDoneConnected = IsOutputConnected(pActInfo, OUT_ALMOST_DONE);
  608.                         m_firedAlmostDone = true;
  609.                 }
  610.                 else if (!tokenFound)
  611.                 {
  612.                         ActivateOutput(pActInfo, OUT_DONE, SFlowSystemVoid());
  613.  
  614.                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  615.  
  616.                         m_firedAlmostDone = false;
  617.  
  618.                         if (pActInfo->pEntity != NULL)
  619.                         {
  620.                                 if (m_bForcedActivate)
  621.                                 {
  622.                                         pActInfo->pEntity->Activate(false);
  623.                                         m_bForcedActivate = false;
  624.                                 }
  625.  
  626.                                 if (m_bForcedUpdateActivate)
  627.                                 {
  628.                                         m_bForcedUpdateActivate = false;
  629.                                         SetForceUpdate(pActInfo->pEntity->GetId(), false);
  630.                                 }
  631.  
  632.                                 if (m_manualAnimationControlledMovement)
  633.                                 {
  634.                                         if (pSkeletonAnimation != NULL)
  635.                                         {
  636.                                                 pSkeletonAnimation->SetAnimationDrivenMotion(0);
  637.                                         }
  638.                                         m_manualAnimationControlledMovement = false;
  639.                                 }
  640.  
  641.                                 IScriptTable* pEntityScript = pActInfo->pEntity->GetScriptTable();
  642.                                 const char* pFuncName = "OnFlowGraphAnimationEnd";
  643.                                 if (pEntityScript && pEntityScript->HaveValue(pFuncName))
  644.                                         Script::CallMethod(pEntityScript, pFuncName);
  645.                         }
  646.                 }
  647.  
  648.                 // Update entity position if animation is running and controlled movement active.
  649.                 // If AlmostDone was triggered and AlmostDone output is connected, we assume that
  650.                 // a new animation was triggered.
  651.                 // There are situations when this assumption might fail and movement is not updated
  652.                 // properly, to get this fixed the controlled movement needs to happen outside of this
  653.                 // FG Node
  654.                 if (tokenFound && !isAlmostDoneConnected && m_manualAnimationControlledMovement && pActInfo->pEntity)
  655.                 {
  656.                         QuatT newWorldLocation = QuatT(pActInfo->pEntity->GetWorldTM()) * relativeAnimationMovement;
  657.                         newWorldLocation.q.Normalize();
  658.                         pActInfo->pEntity->SetWorldTM(Matrix34(newWorldLocation));
  659.                 }
  660.         }
  661.  
  662.         void SetForceUpdate(EntityId entityId, bool bEnable)
  663.         {
  664.                 IGameFramework* const pGameFramework = gEnv->pGameFramework;
  665.                 IGameObject* const pGameObject = pGameFramework ? pGameFramework->GetGameObject(entityId) : nullptr;
  666.                 if (pGameObject)
  667.                 {
  668.                         pGameObject->ForceUpdate(bEnable);
  669.                 }
  670.         }
  671. };
  672.  
  673.  
  674. //////////////////////////////////////////////////////////////////////////
  675. class CIsAnimPlaying_Node : public CFlowBaseNode<eNCT_Singleton>
  676. {
  677. public:
  678.         enum EInputs
  679.         {
  680.                 IN_CHECK,
  681.                 IN_CHECK_EACH_FRAME,
  682.                 IN_ANIMATION,
  683.                 IN_LAYER,
  684.         };
  685.  
  686.         enum EOutputs
  687.         {
  688.                 OUT_IS_PLAYING,
  689.                 OUT_IS_NOT_PLAYING,
  690.                 OUT_IS_TOP_OF_STACK,
  691.         };
  692.  
  693.         CIsAnimPlaying_Node(SActivationInfo* pActInfo)   {}
  694.  
  695.         ~CIsAnimPlaying_Node() {}
  696.  
  697.         virtual void GetMemoryUsage(ICrySizer* s) const
  698.         {
  699.                 s->Add(*this);
  700.         }
  701.  
  702.         virtual void Serialize(SActivationInfo* pActInfo, TSerialize ser) {}
  703.  
  704.         virtual void GetConfiguration(SFlowNodeConfig& config)
  705.         {
  706.                 static const SInputPortConfig in_config[] = {
  707.                         InputPortConfig_Void("Check",             _HELP("Test now once whether this animation is playing")),
  708.                         InputPortConfig<bool>("CheckAlways",      _HELP("If true, will check each frame whether the anim is playing (costs processing time)")),
  709.                         InputPortConfig<string>("anim_Animation", _HELP("Animation name"),                                                                     0,   _UICONFIG("ref_entity=entityId")),
  710.                         InputPortConfig<int>("Layer",             _HELP("Which layer should this anim be playing on"),                                         0),
  711.                         { 0 }
  712.                 };
  713.                 static const SOutputPortConfig out_config[] = {
  714.                         OutputPortConfig_Void("Playing",    _HELP("Triggers if animation was found on the layer")),
  715.                         OutputPortConfig_Void("NotPlaying", _HELP("Triggers if animation was not found on the layer")),
  716.                         OutputPortConfig_Void("TopOfStack", _HELP("Triggers when animation was found and it is top of the stack (meaning, not currently blending out)")),
  717.                         { 0 }
  718.                 };
  719.                 config.sDescription = _HELP("Checks whether a specific Animation is playing");
  720.                 config.nFlags |= EFLN_TARGET_ENTITY;
  721.                 config.pInputPorts = in_config;
  722.                 config.pOutputPorts = out_config;
  723.                 config.SetCategory(EFLN_APPROVED);
  724.         }
  725.  
  726.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  727.         {
  728.                 switch (event)
  729.                 {
  730.                 case eFE_Activate:
  731.                         {
  732.                                 if (!pActInfo->pEntity)
  733.                                         return;
  734.  
  735.                                 if (IsPortActive(pActInfo, IN_CHECK))
  736.                                 {
  737.                                         PerformAnimCheck(pActInfo);
  738.                                 }
  739.  
  740.                                 bool checkEachFrame = GetPortBool(pActInfo, IN_CHECK_EACH_FRAME);
  741.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, checkEachFrame);
  742.  
  743.                                 break;
  744.                         }
  745.  
  746.                 case eFE_Update:
  747.                         {
  748.                                 if (!pActInfo->pEntity)
  749.                                         return;
  750.  
  751.                                 PerformAnimCheck(pActInfo);
  752.  
  753.                                 bool checkEachFrame = GetPortBool(pActInfo, IN_CHECK_EACH_FRAME);
  754.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, checkEachFrame);
  755.                         }
  756.                         break;
  757.  
  758.                 case eFE_Initialize:
  759.                         {
  760.                                 bool checkEachFrame = GetPortBool(pActInfo, IN_CHECK_EACH_FRAME);
  761.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, checkEachFrame);
  762.                         }
  763.                         break;
  764.  
  765.                 }
  766.                 ;
  767.         };
  768.  
  769. private:
  770.  
  771.         void PerformAnimCheck(SActivationInfo* pActInfo)
  772.         {
  773.                 ICharacterInstance* pCharacter = pActInfo->pEntity->GetCharacter(0);
  774.                 const string& animName = GetPortString(pActInfo, IN_ANIMATION);
  775.  
  776.                 if (pCharacter && !animName.empty())
  777.                 {
  778.                         int animLayer = GetPortInt(pActInfo, IN_LAYER);
  779.  
  780.                         ISkeletonAnim* pISkeletonAnim = pCharacter->GetISkeletonAnim();
  781.  
  782.                         int animID = pCharacter->GetIAnimationSet()->GetAnimIDByName(animName.c_str());
  783.  
  784.                         int numAnims = pISkeletonAnim->GetNumAnimsInFIFO(animLayer);
  785.                         for (int i = 0; i < numAnims; ++i)
  786.                         {
  787.                                 const CAnimation& anim = pISkeletonAnim->GetAnimFromFIFO(animLayer, i);
  788.                                 int32 animInLayerID = anim.GetAnimationId();
  789.                                 if (animInLayerID == animID)
  790.                                 {
  791.                                         ActivateOutput(pActInfo, OUT_IS_PLAYING, SFlowSystemVoid());
  792.  
  793.                                         // animation is playing, but is it also the top of the stack? (FIFO - last one in)
  794.                                         // this is done this way because in theory the animation could be in the FIFO several times
  795.                                         // so DO NOT optimize this to just check whether i == numAnims - 1 please
  796.                                         const CAnimation& topAnim = pISkeletonAnim->GetAnimFromFIFO(animLayer, numAnims - 1);
  797.                                         int32 topAnimId = topAnim.GetAnimationId();
  798.                                         if (topAnimId == animID)
  799.                                         {
  800.                                                 ActivateOutput(pActInfo, OUT_IS_TOP_OF_STACK, SFlowSystemVoid());
  801.                                         }
  802.  
  803.                                         return;
  804.                                 }
  805.                         }
  806.  
  807.                 }
  808.  
  809.                 // else it's apparently all false
  810.                 ActivateOutput(pActInfo, OUT_IS_NOT_PLAYING, SFlowSystemVoid());
  811.         }
  812. };
  813.  
  814. //////////////////////////////////////////////////////////////////////////
  815. class CFlowNode_LookAt : public CFlowBaseNode<eNCT_Singleton>
  816. {
  817. public:
  818.         enum EInputs
  819.         {
  820.                 IN_START,
  821.                 IN_STOP,
  822.                 IN_FOV,
  823.                 IN_BLEND,
  824.                 IN_TARGET,
  825.                 IN_TARGET_POS,
  826.                 IN_PLAYER,
  827.         };
  828.         CFlowNode_LookAt(SActivationInfo* pActInfo) {}
  829.         ~CFlowNode_LookAt() {};
  830.  
  831.         virtual void GetMemoryUsage(ICrySizer* s) const
  832.         {
  833.                 s->Add(*this);
  834.         }
  835.  
  836.         virtual void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  837.         {
  838.         }
  839.  
  840.         virtual void GetConfiguration(SFlowNodeConfig& config)
  841.         {
  842.                 static const SInputPortConfig in_config[] = {
  843.                         InputPortConfig_AnyType("Start",      _HELP("Starts Look at ")),
  844.                         InputPortConfig_AnyType("Stop",       _HELP("Stops Look at")),
  845.                         InputPortConfig<float>("FieldOfView", 90,                       _HELP("LookAt Field of view (Degrees)")),
  846.                         InputPortConfig<float>("Blending",    1,                        _HELP("Blending with animation value")),
  847.                         InputPortConfig<EntityId>("Target",   (EntityId)0,              _HELP("Look at target entity")),
  848.                         InputPortConfig<Vec3>("TargetPos",    Vec3(0,                   0,                                       0),_HELP("Look at target position")),
  849.                         InputPortConfig<bool>("LookAtPlayer", false,                    _HELP("When true looks at player")),
  850.                         { 0 }
  851.                 };
  852.                 config.sDescription = _HELP("Activates character Look At IK");
  853.                 config.nFlags |= EFLN_TARGET_ENTITY;
  854.                 config.pInputPorts = in_config;
  855.                 config.pOutputPorts = 0;
  856.                 config.SetCategory(EFLN_ADVANCED);
  857.         }
  858.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  859.         {
  860.                 Vec3 vTarget(0, 0, 0);
  861.                 float fFov = 0;
  862.                 ICharacterInstance* pCharacter = 0;
  863.                 if (pActInfo->pEntity && pActInfo->pInputPorts)
  864.                 {
  865.                         pCharacter = pActInfo->pEntity->GetCharacter(0);
  866.                         if (pCharacter)
  867.                         {
  868.                                 // Update look IK on the character.
  869.                                 if (!GetPortBool(pActInfo, IN_PLAYER))
  870.                                 {
  871.                                         vTarget = GetPortVec3(pActInfo, IN_TARGET_POS);
  872.                                         IEntity* pEntity = gEnv->pEntitySystem->GetEntity((EntityId)GetPortEntityId(pActInfo, IN_TARGET));
  873.                                         if (pEntity)
  874.                                                 vTarget = pEntity->GetWorldPos();
  875.                                 }
  876.                                 else if (IActor* pActor = CCryAction::GetCryAction()->GetClientActor())
  877.                                 {
  878.                                         if (IMovementController* pMoveController = pActor->GetMovementController())
  879.                                         {
  880.                                                 SMovementState movementState;
  881.                                                 pMoveController->GetMovementState(movementState);
  882.                                                 vTarget = movementState.eyePosition + GetPortVec3(pActInfo, IN_TARGET_POS);
  883.                                         }
  884.                                 }
  885.                                 fFov = GetPortFloat(pActInfo, IN_FOV);
  886.                                 GetPortFloat(pActInfo, IN_BLEND);
  887.                         }
  888.                 }
  889.                 /*
  890.                     float lookIKBlends[5];
  891.                     lookIKBlends[0] = 0.00f * fBlend;
  892.                     lookIKBlends[1] = 0.00f * fBlend;
  893.                     lookIKBlends[2] = 0.00f * fBlend;
  894.                     lookIKBlends[3] = 0.10f * fBlend;
  895.                     lookIKBlends[4] = 0.60f * fBlend;
  896.                  */
  897.                 switch (event)
  898.                 {
  899.                 case eFE_Update:
  900.                         if (pActInfo->pEntity && pCharacter)
  901.                         {
  902.                                 CGameObject* pGameObject = (CGameObject*)pActInfo->pEntity->GetProxy(ENTITY_PROXY_USER);
  903.                                 IMovementController* pMC = pGameObject ? pGameObject->GetMovementController() : NULL;
  904.                                 if (pMC)
  905.                                 {
  906.                                         CMovementRequest mc;
  907.                                         mc.SetLookStyle(LOOKSTYLE_DEFAULT);
  908.                                         mc.SetLookTarget(vTarget);
  909.                                         pMC->RequestMovement(mc);
  910.                                 }
  911.                                 else
  912.                                 {
  913.                                         IAnimationPoseBlenderDir* pIPoseBlenderLook = pCharacter->GetISkeletonPose()->GetIPoseBlenderLook();
  914.                                         if (pIPoseBlenderLook)
  915.                                         {
  916.                                                 pIPoseBlenderLook->SetState(1);
  917.                                                 pIPoseBlenderLook->SetFadeoutAngle(DEG2RAD(fFov));
  918.                                                 pIPoseBlenderLook->SetTarget(vTarget);
  919.                                         }
  920.                                 }
  921.                         }
  922.                         break;
  923.  
  924.                 case eFE_Activate:
  925.                         if (pActInfo->pEntity)
  926.                         {
  927.                                 if (IsPortActive(pActInfo, IN_START))
  928.                                 {
  929.                                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  930.                                 }
  931.                                 if (IsPortActive(pActInfo, IN_STOP))
  932.                                 {
  933.                                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  934.                                         if (pCharacter)
  935.                                         {
  936.                                                 // Turns off look ik.
  937.                                                 CGameObject* pGameObject = (CGameObject*)pActInfo->pEntity->GetProxy(ENTITY_PROXY_USER);
  938.                                                 IMovementController* pMC = pGameObject ? pGameObject->GetMovementController() : NULL;
  939.                                                 if (pMC)
  940.                                                 {
  941.                                                         CMovementRequest mc;
  942.                                                         mc.ClearLookTarget();
  943.                                                         pMC->RequestMovement(mc);
  944.                                                 }
  945.                                                 else
  946.                                                 {
  947.                                                         IAnimationPoseBlenderDir* poseBlenderLook = pCharacter->GetISkeletonPose()->GetIPoseBlenderLook();
  948.                                                         if (poseBlenderLook)
  949.                                                         {
  950.                                                                 poseBlenderLook->SetState(0);
  951.                                                                 poseBlenderLook->SetTarget(vTarget);
  952.                                                                 poseBlenderLook->SetFadeoutAngle(DEG2RAD(fFov));
  953.                                                         }
  954.                                                 }
  955.                                         }
  956.                                 }
  957.                         }
  958.                         break;
  959.  
  960.                 case eFE_Initialize:
  961.                         break;
  962.                 }
  963.                 ;
  964.         };
  965. };
  966.  
  967. #ifdef INCLUDE_ANIMATIONGRAPH
  968. class CFlowNode_AGControl : public CFlowBaseNode<eNCT_Singleton>
  969. {
  970. public:
  971.         enum EInputs
  972.         {
  973.                 IN_AG_PAUSE = 0
  974.         };
  975.  
  976.         CFlowNode_AGControl(SActivationInfo* pActInfo)
  977.         {
  978.         }
  979.  
  980.         virtual void GetMemoryUsage(ICrySizer* s) const
  981.         {
  982.                 s->Add(*this);
  983.         }
  984.  
  985.         virtual void GetConfiguration(SFlowNodeConfig& config)
  986.         {
  987.                 static const SInputPortConfig inputs[] = {
  988.                         InputPortConfig<bool>("Pause", false, _HELP("Pauses AnimationGraph updates of the attached entity"), _HELP("Pause")),
  989.                         { 0 }
  990.                 };
  991.                 config.pInputPorts = inputs;
  992.                 config.nFlags |= EFLN_TARGET_ENTITY;
  993.                 config.sDescription = _HELP("Controls the AnimationGraph of the attached entity");
  994.                 config.SetCategory(EFLN_ADVANCED);
  995.         }
  996.  
  997.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  998.         {
  999.                 switch (event)
  1000.                 {
  1001.                 case eFE_Activate:
  1002.                         if (IsPortActive(pActInfo, IN_AG_PAUSE))
  1003.                         {
  1004.                                 if (pActInfo->pEntity)
  1005.                                 {
  1006.                                         IAnimationGraphState* pCurState = GetCurAGState(pActInfo->pEntity);
  1007.                                         if (pCurState)
  1008.                                         {
  1009.                                                 pCurState->Pause(GetPortBool(pActInfo, IN_AG_PAUSE), eAGP_FlowGraph);
  1010.                                         }
  1011.                                 }
  1012.                         }
  1013.                         break;
  1014.                 }
  1015.         }
  1016. };
  1017.  
  1018. class CFlowNode_AGSetInput : public CFlowBaseNode<eNCT_Singleton>
  1019. {
  1020. public:
  1021.         CFlowNode_AGSetInput(SActivationInfo* pActInfo)
  1022.         {
  1023.         }
  1024.  
  1025.         virtual void GetMemoryUsage(ICrySizer* s) const
  1026.         {
  1027.                 s->Add(*this);
  1028.         }
  1029.  
  1030.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1031.         {
  1032.                 static const SInputPortConfig inputs[] = {
  1033.                         InputPortConfig<SFlowSystemVoid>("In", _HELP("Causes the node to set its value"), _HELP("In")),
  1034.                         InputPortConfig<string>("Input",       "Signal",                                  _HELP("Input"), _HELP("Input")),
  1035.                         InputPortConfig<string>("Value",       "none" _HELP("Value"),                     _HELP("Value")),
  1036.                         { 0 }
  1037.                 };
  1038.                 static const SOutputPortConfig out_config[] = {
  1039.                         OutputPortConfig_AnyType("Done", _HELP("Send an event when the input is set")),
  1040.                         { 0 }
  1041.                 };
  1042.                 config.pInputPorts = inputs;
  1043.                 config.pOutputPorts = out_config;
  1044.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1045.                 config.sDescription = _HELP("Controls the AnimationGraph of the attached entity");
  1046.                 config.SetCategory(EFLN_ADVANCED);
  1047.         }
  1048.  
  1049.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1050.         {
  1051.                 switch (event)
  1052.                 {
  1053.                 case eFE_Activate:
  1054.                         if (IsPortActive(pActInfo, 0))
  1055.                         {
  1056.                                 if (pActInfo->pEntity)
  1057.                                 {
  1058.                                         IAnimationGraphState* pCurState = GetCurAGState(pActInfo->pEntity);
  1059.                                         if (pCurState)
  1060.                                         {
  1061.                                                 pCurState->SetInput(GetPortString(pActInfo, 1).c_str(), GetPortString(pActInfo, 2).c_str());
  1062.                                         }
  1063.                                 }
  1064.                         }
  1065.                         ActivateOutput(pActInfo, 0, SFlowSystemVoid());
  1066.                         break;
  1067.                 }
  1068.         }
  1069. };
  1070.  
  1071. class CFlowNode_AGLockInput : public CFlowBaseNode<eNCT_Singleton>
  1072. {
  1073. public:
  1074.         CFlowNode_AGLockInput(SActivationInfo* pActInfo)
  1075.         {
  1076.         }
  1077.  
  1078.         virtual void GetMemoryUsage(ICrySizer* s) const
  1079.         {
  1080.                 s->Add(*this);
  1081.         }
  1082.  
  1083.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1084.         {
  1085.                 static const SInputPortConfig inputs[] = {
  1086.                         InputPortConfig<SFlowSystemVoid>("Lock",   _HELP("Causes the node to set its value"), _HELP("Lock")),
  1087.                         InputPortConfig<SFlowSystemVoid>("Unlock", _HELP("Causes the node to set its value"), _HELP("Unlock")),
  1088.                         InputPortConfig<string>("Input",           "InstantZDelta",                           _HELP("Input"),  _HELP("Input")),
  1089.                         { 0 }
  1090.                 };
  1091.                 static const SOutputPortConfig out_config[] = {
  1092.                         OutputPortConfig_AnyType("Done", _HELP("Send an event when animation is finished")),
  1093.                         { 0 }
  1094.                 };
  1095.                 config.pInputPorts = inputs;
  1096.                 config.pOutputPorts = out_config;
  1097.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1098.                 config.sDescription = _HELP("Controls the AnimationGraph of the attached entity");
  1099.                 config.SetCategory(EFLN_ADVANCED);
  1100.         }
  1101.  
  1102.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1103.         {
  1104.                 switch (event)
  1105.                 {
  1106.                 case eFE_Activate:
  1107.                         int action = int(IsPortActive(pActInfo, 0)) - int(IsPortActive(pActInfo, 1));
  1108.                         IAnimationGraphState* pState = GetCurAGState(pActInfo->pEntity);
  1109.                         if (!pState)
  1110.                         {
  1111.                                 CRY_ASSERT(pState);
  1112.                                 return;
  1113.                         }
  1114.                         IAnimationGraphState::InputID id = pState->GetInputId(GetPortString(pActInfo, 2));
  1115.                         bool lock = false;
  1116.                         switch (action)
  1117.                         {
  1118.                         case 0:
  1119.                                 break;
  1120.                         case 1:
  1121.                                 lock = true;
  1122.                         case -1:
  1123.                                 pState->LockInput(id, lock);
  1124.                                 break;
  1125.                         default:
  1126.                                 CRY_ASSERT(false);
  1127.                         }
  1128.                         ActivateOutput(pActInfo, 0, SFlowSystemVoid());
  1129.                         break;
  1130.                 }
  1131.         }
  1132. };
  1133.  
  1134. class CFlowNode_AGOutput : public CFlowBaseNode<eNCT_Instanced>, public IAnimationGraphStateListener
  1135. {
  1136. public:
  1137.         CFlowNode_AGOutput(EntityId id = 0) : m_currentEntity(0)
  1138.         {
  1139.                 SetEntity(id);
  1140.         }
  1141.         ~CFlowNode_AGOutput() { SetEntity(0); }
  1142.         CFlowNode_AGOutput(const CFlowNode_AGOutput& output) : m_currentEntity(0)
  1143.         {
  1144.                 SetEntity(m_currentEntity);
  1145.         }
  1146.  
  1147.         virtual void Serialize(SActivationInfo*, TSerialize ser)
  1148.         {
  1149.                 ser.Value("entity", this, &CFlowNode_AGOutput::GetEntity, &CFlowNode_AGOutput::SetEntity);
  1150.         }
  1151.  
  1152.         virtual void GetMemoryUsage(ICrySizer* s) const
  1153.         {
  1154.                 s->Add(*this);
  1155.         }
  1156.  
  1157.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1158.         {
  1159.                 switch (event)
  1160.                 {
  1161.                 case eFE_SetEntityId:
  1162.                         if (pActInfo->pEntity)
  1163.                                 SetEntity(pActInfo->pEntity->GetId());
  1164.                         break;
  1165.                 }
  1166.         }
  1167.  
  1168.         void     QueryComplete(TAnimationGraphQueryID queryID, bool succeeded) {}
  1169.  
  1170.         EntityId GetEntity() const                                             { return m_currentEntity; }
  1171.  
  1172. private:
  1173.         EntityId m_currentEntity;
  1174.  
  1175.         void SetEntity(EntityId id)
  1176.         {
  1177.                 IEntitySystem* pES = gEnv->pEntitySystem;
  1178.                 if (IEntity* pCurEntity = pES->GetEntity(m_currentEntity))
  1179.                         if (IAnimationGraphState* pState = GetCurAGState(pCurEntity))
  1180.                                 pState->RemoveListener(this);
  1181.                 m_currentEntity = id;
  1182.                 if (IEntity* pCurEntity = pES->GetEntity(m_currentEntity))
  1183.                         if (IAnimationGraphState* pState = GetCurAGState(pCurEntity))
  1184.                                 pState->AddListener("agoutput", this);
  1185.         }
  1186. };
  1187.  
  1188. class CFlowNode_AGWatchOutput : public CFlowNode_AGOutput
  1189. {
  1190. public:
  1191.         CFlowNode_AGWatchOutput(SActivationInfo* pActInfo, EntityId id = 0) : CFlowNode_AGOutput(id), m_actInfo(*pActInfo)
  1192.         {
  1193.         }
  1194.  
  1195.         IFlowNodePtr Clone(SActivationInfo* pActInfo)
  1196.         {
  1197.                 return new CFlowNode_AGWatchOutput(pActInfo, GetEntity());
  1198.         }
  1199.  
  1200.         virtual void GetMemoryUsage(ICrySizer* s) const
  1201.         {
  1202.                 s->Add(*this);
  1203.         }
  1204.  
  1205.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1206.         {
  1207.                 static const SInputPortConfig inputs[] = {
  1208.                         InputPortConfig<string>("Name", _HELP("Name of the output"), _HELP("Name")),
  1209.                         { 0 }
  1210.                 };
  1211.                 static const SOutputPortConfig out_config[] = {
  1212.                         OutputPortConfig<string>("Value", _HELP("Output a string whenever the animation graph output is set")),
  1213.                         { 0 }
  1214.                 };
  1215.                 config.pInputPorts = inputs;
  1216.                 config.pOutputPorts = out_config;
  1217.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1218.                 config.sDescription = _HELP("Controls the AnimationGraph of the attached entity");
  1219.                 config.SetCategory(EFLN_ADVANCED);
  1220.         }
  1221.  
  1222.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1223.         {
  1224.                 CFlowNode_AGOutput::ProcessEvent(event, pActInfo);
  1225.  
  1226.                 switch (event)
  1227.                 {
  1228.                 case eFE_Initialize:
  1229.                         m_actInfo = *pActInfo;
  1230.  
  1231.                         const char* value = "";
  1232.                         if (IAnimationGraphState* pState = GetCurAGState(pActInfo->pEntity))
  1233.                                 value = pState->QueryOutput(GetPortString(pActInfo, 0));
  1234.                         ActivateOutput(pActInfo, 0, string(value));
  1235.                         break;
  1236.                 }
  1237.         }
  1238.  
  1239.         void SetOutput(const char* output, const char* value)
  1240.         {
  1241.                 if (m_actInfo.pGraph)
  1242.                         if (GetPortString(&m_actInfo, 0) == output)
  1243.                                 ActivateOutput(&m_actInfo, 0, string(value));
  1244.         }
  1245.         void DestroyedState(IAnimationGraphState*) {}
  1246.  
  1247. private:
  1248.         SActivationInfo m_actInfo;
  1249. };
  1250.  
  1251. class CFlowNode_AGCheckOutput : public CFlowNode_AGOutput
  1252. {
  1253. public:
  1254.         CFlowNode_AGCheckOutput(SActivationInfo* pActInfo, EntityId id = 0) : CFlowNode_AGOutput(id), m_actInfo(*pActInfo)
  1255.         {
  1256.         }
  1257.  
  1258.         IFlowNodePtr Clone(SActivationInfo* pActInfo)
  1259.         {
  1260.                 return new CFlowNode_AGCheckOutput(pActInfo, GetEntity());
  1261.         }
  1262.  
  1263.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1264.         {
  1265.                 static const SInputPortConfig inputs[] = {
  1266.                         InputPortConfig<string>("Name",       _HELP("Name of the output"), _HELP("Name")),
  1267.                         InputPortConfig<string>("CheckValue", _HELP("Name of the output"), _HELP("CheckValue")),
  1268.                         { 0 }
  1269.                 };
  1270.                 static const SOutputPortConfig out_config[] = {
  1271.                         OutputPortConfig_AnyType("OnEqual",    _HELP("Output a string whenever the animation graph output is set")),
  1272.                         OutputPortConfig_AnyType("OnNotEqual", _HELP("Output a string whenever the animation graph output is set")),
  1273.                         OutputPortConfig<bool>("Equal",        _HELP("Output a string whenever the animation graph output is set")),
  1274.                         { 0 }
  1275.                 };
  1276.                 config.pInputPorts = inputs;
  1277.                 config.pOutputPorts = out_config;
  1278.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1279.                 config.sDescription = _HELP("Controls the AnimationGraph of the attached entity");
  1280.                 config.SetCategory(EFLN_ADVANCED);
  1281.         }
  1282.  
  1283.         virtual void GetMemoryUsage(ICrySizer* s) const
  1284.         {
  1285.                 s->Add(*this);
  1286.         }
  1287.  
  1288.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1289.         {
  1290.                 CRY_ASSERT(pActInfo);
  1291.                 CFlowNode_AGOutput::ProcessEvent(event, pActInfo);
  1292.  
  1293.                 switch (event)
  1294.                 {
  1295.                 case eFE_Initialize:
  1296.                         m_actInfo = *pActInfo;
  1297.  
  1298.                 case eFE_Update:
  1299.                         {
  1300.                                 const char* value = "";
  1301.                                 if (IAnimationGraphState* pState = GetCurAGState(pActInfo->pEntity))
  1302.                                         value = pState->QueryOutput(GetPortString(pActInfo, 0));
  1303.                                 bool same = false;
  1304.                                 if (value != NULL)
  1305.                                         same = (GetPortString(pActInfo, 1) == value);
  1306.                                 ActivateOutput(pActInfo, !same, SFlowSystemVoid());
  1307.                                 ActivateOutput(pActInfo, 2, same);
  1308.                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, false);
  1309.                         }
  1310.                         break;
  1311.                 }
  1312.         }
  1313.         void DestroyedState(IAnimationGraphState*) {}
  1314.  
  1315.         void SetOutput(const char* output, const char* value)
  1316.         {
  1317.                 if (m_actInfo.pGraph)
  1318.                         m_actInfo.pGraph->SetRegularlyUpdated(m_actInfo.myID, true);
  1319.         }
  1320.  
  1321. private:
  1322.         SActivationInfo m_actInfo;
  1323. };
  1324.  
  1325. class CFlowNode_AGReset : public CFlowBaseNode<eNCT_Singleton>
  1326. {
  1327. public:
  1328.         CFlowNode_AGReset(SActivationInfo* pActInfo)
  1329.         {
  1330.         }
  1331.  
  1332.         virtual void GetMemoryUsage(ICrySizer* s) const
  1333.         {
  1334.                 s->Add(*this);
  1335.         }
  1336.  
  1337.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1338.         {
  1339.                 static const SInputPortConfig inputs[] = {
  1340.                         InputPortConfig<SFlowSystemVoid>("Reset", _HELP("Causes the animation graph to lose its state"), _HELP("Reset")),
  1341.                         { 0 }
  1342.                 };
  1343.                 static const SOutputPortConfig out_config[] = {
  1344.                         OutputPortConfig_AnyType("Done", _HELP("Send an event when animation is finished")),
  1345.                         { 0 }
  1346.                 };
  1347.                 config.pInputPorts = inputs;
  1348.                 config.pOutputPorts = out_config;
  1349.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1350.                 config.sDescription = _HELP("Controls the AnimationGraph of the attached entity");
  1351.                 config.SetCategory(EFLN_ADVANCED);
  1352.         }
  1353.  
  1354.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1355.         {
  1356.                 switch (event)
  1357.                 {
  1358.                 case eFE_Activate:
  1359.                         IAnimationGraphState* pState = GetCurAGState(pActInfo->pEntity);
  1360.                         if (!pState)
  1361.                                 return;
  1362.                         pState->Reset();
  1363.                         ActivateOutput(pActInfo, 0, SFlowSystemVoid());
  1364.                         break;
  1365.                 }
  1366.         }
  1367. };
  1368. #endif // INCLUDE_ANIMATIONGRAPH
  1369.  
  1370. class CFlowNode_StopAnimation : public CFlowBaseNode<eNCT_Singleton>
  1371. {
  1372. public:
  1373.         CFlowNode_StopAnimation(SActivationInfo* pActInfo)
  1374.         {
  1375.         }
  1376.  
  1377.         virtual void GetMemoryUsage(ICrySizer* s) const
  1378.         {
  1379.                 s->Add(*this);
  1380.         }
  1381.  
  1382.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1383.         {
  1384.                 static const SInputPortConfig inputs[] = {
  1385.                         InputPortConfig<SFlowSystemVoid>("Stop", _HELP("Stops animation playing"), _HELP("Stop!")),
  1386.                         { 0 }
  1387.                 };
  1388.                 static const SOutputPortConfig out_config[] = {
  1389.                         OutputPortConfig_AnyType("Done", _HELP("Send an event when animation is finished")),
  1390.                         { 0 }
  1391.                 };
  1392.                 config.pInputPorts = inputs;
  1393.                 config.pOutputPorts = out_config;
  1394.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1395.                 config.sDescription = _HELP("Controls the AnimationGraph of the attached entity");
  1396.                 config.SetCategory(EFLN_APPROVED);
  1397.         }
  1398.  
  1399.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1400.         {
  1401.                 switch (event)
  1402.                 {
  1403.                 case eFE_Activate:
  1404.                         if (pActInfo->pEntity)
  1405.                                 if (ICharacterInstance* pCharacter = pActInfo->pEntity->GetCharacter(0))
  1406.                                         pCharacter->GetISkeletonAnim()->StopAnimationsAllLayers();
  1407.                         ActivateOutput(pActInfo, 0, SFlowSystemVoid());
  1408.                         break;
  1409.                 }
  1410.         }
  1411. };
  1412.  
  1413. class CFlowNode_NoAiming : public CFlowBaseNode<eNCT_Singleton>
  1414. {
  1415. public:
  1416.         CFlowNode_NoAiming(SActivationInfo* pActInfo)
  1417.         {
  1418.         }
  1419.  
  1420.         virtual void GetMemoryUsage(ICrySizer* s) const
  1421.         {
  1422.                 s->Add(*this);
  1423.         }
  1424.  
  1425.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1426.         {
  1427.                 static const SInputPortConfig inputs[] = {
  1428.                         InputPortConfig<SFlowSystemVoid>("Enable", _HELP("Stops animation playing"), _HELP("Dont Aim!")),
  1429.                         { 0 }
  1430.                 };
  1431.                 static const SOutputPortConfig out_config[] = {
  1432.                         OutputPortConfig_AnyType("Done", _HELP("Send an event when animation is finished")),
  1433.                         { 0 }
  1434.                 };
  1435.                 config.pInputPorts = inputs;
  1436.                 config.pOutputPorts = out_config;
  1437.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1438.                 config.sDescription = _HELP("Controls the AnimationGraph of the attached entity");
  1439.                 config.SetCategory(EFLN_ADVANCED);
  1440.         }
  1441.  
  1442.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1443.         {
  1444.                 switch (event)
  1445.                 {
  1446.                 case eFE_Activate:
  1447.                         if (pActInfo->pEntity)
  1448.                                 if (CGameObject* pGameObject = (CGameObject*)pActInfo->pEntity->GetProxy(ENTITY_PROXY_USER))
  1449.                                         if (IMovementController* pMC = pGameObject->GetMovementController())
  1450.                                         {
  1451.                                                 CMovementRequest mc;
  1452.                                                 mc.SetNoAiming();
  1453.                                                 pMC->RequestMovement(mc);
  1454.                                         }
  1455.                         ActivateOutput(pActInfo, 0, SFlowSystemVoid());
  1456.                         break;
  1457.                 }
  1458.         }
  1459. };
  1460.  
  1461. // TODO: post VS2 we need to make a general system for this
  1462. class CFlowNode_SynchronizeTwoAnimations : public CFlowBaseNode<eNCT_Singleton>
  1463. {
  1464. public:
  1465.         CFlowNode_SynchronizeTwoAnimations(SActivationInfo* pActInfo)
  1466.         {
  1467.         }
  1468.  
  1469.         virtual void GetMemoryUsage(ICrySizer* s) const
  1470.         {
  1471.                 s->Add(*this);
  1472.         }
  1473.  
  1474.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1475.         {
  1476.                 static const SInputPortConfig inputs[] = {
  1477.                         InputPortConfig<EntityId>("Entity1",            _HELP("Entity1")),
  1478.                         InputPortConfig<EntityId>("Entity2",            _HELP("Entity2")),
  1479.                         InputPortConfig<string>("anim_Animation1",      _HELP("Animation1"),0,                                _UICONFIG("ref_entity=Entity1")),
  1480.                         InputPortConfig<string>("anim_Animation2",      _HELP("Animation2"),0,                                _UICONFIG("ref_entity=Entity2")),
  1481.                         InputPortConfig<float>("ResyncTime",            0.2f,               _HELP("ResyncTime")),
  1482.                         InputPortConfig<float>("MaxPercentSpeedChange", 10,                 _HELP("MaxPercentSpeedChange")),
  1483.                         { 0 }
  1484.                 };
  1485.                 config.pInputPorts = inputs;
  1486.                 config.sDescription = _HELP("Synchronize two animations on two entities");
  1487.                 config.SetCategory(EFLN_ADVANCED);
  1488.         }
  1489.  
  1490.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1491.         {
  1492.                 switch (event)
  1493.                 {
  1494.                 case eFE_Initialize:
  1495.                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  1496.                         break;
  1497.                 case eFE_Update:
  1498.                         Update(pActInfo);
  1499.                         break;
  1500.                 }
  1501.         }
  1502.  
  1503. private:
  1504.         void Update(SActivationInfo* pActInfo)
  1505.         {
  1506.                 IEntity* pEnt1 = gEnv->pEntitySystem->GetEntity(GetPortEntityId(pActInfo, 0));
  1507.                 IEntity* pEnt2 = gEnv->pEntitySystem->GetEntity(GetPortEntityId(pActInfo, 1));
  1508.                 if (!pEnt1 || !pEnt2)
  1509.                         return;
  1510.                 ICharacterInstance* pChar1 = pEnt1->GetCharacter(0);
  1511.                 ICharacterInstance* pChar2 = pEnt2->GetCharacter(0);
  1512.                 if (!pChar1 || !pChar2)
  1513.                         return;
  1514.                 ISkeletonAnim* pSkel1 = pChar1->GetISkeletonAnim();
  1515.                 ISkeletonAnim* pSkel2 = pChar2->GetISkeletonAnim();
  1516.                 if (pSkel1->GetNumAnimsInFIFO(0) == 0 || pSkel2->GetNumAnimsInFIFO(0) == 0)
  1517.                         return;
  1518.                 CAnimation* pAnim1 = &pSkel1->GetAnimFromFIFO(0, 0);
  1519.                 CAnimation* pAnim2 = &pSkel2->GetAnimFromFIFO(0, 0);
  1520.                 if (pAnim1->GetAnimationId() != pChar1->GetIAnimationSet()->GetAnimIDByName(GetPortString(pActInfo, 2)))
  1521.                         return;
  1522.                 if (pAnim2->GetAnimationId() != pChar2->GetIAnimationSet()->GetAnimIDByName(GetPortString(pActInfo, 3)))
  1523.                         return;
  1524.  
  1525.                 float tm1 = pSkel1->GetAnimationNormalizedTime(pAnim1);
  1526.                 float tm2 = pSkel2->GetAnimationNormalizedTime(pAnim2);
  1527.                 if (tm2 < tm1)
  1528.                 {
  1529.                         std::swap(pAnim1, pAnim2);
  1530.                         std::swap(tm1, tm2);
  1531.                 }
  1532.  
  1533.                 if (tm2 - 0.5f > tm1)
  1534.                 {
  1535.                         tm1 += 1.0f;
  1536.                         std::swap(pAnim1, pAnim2);
  1537.                         std::swap(tm1, tm2);
  1538.                 }
  1539.                 float catchupTime = GetPortFloat(pActInfo, 4);
  1540.                 float gamma = (tm2 - tm1) / catchupTime;
  1541.                 float pb2 = (-gamma + sqrtf(gamma * gamma + 4.0f)) / 2.0f;
  1542.                 float pb1 = 1.0f / pb2;
  1543.                 float maxPB = GetPortFloat(pActInfo, 5) / 100.0f + 1.0f;
  1544.                 float minPB = 1.0f / maxPB;
  1545.                 pb2 = clamp_tpl(pb2, minPB, maxPB);
  1546.                 pb1 = clamp_tpl(pb1, minPB, maxPB);
  1547.                 pAnim1->SetPlaybackScale(pb1);
  1548.                 pAnim2->SetPlaybackScale(pb2);
  1549.         }
  1550. };
  1551.  
  1552. // TODO: post VS2 we use events for this
  1553. class CFlowNode_TriggerOnKeyTime : public CFlowBaseNode<eNCT_Instanced>
  1554. {
  1555. public:
  1556.         CFlowNode_TriggerOnKeyTime(SActivationInfo* pActInfo, bool state = false) : m_state(state)
  1557.         {
  1558.         }
  1559.  
  1560.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1561.         {
  1562.                 static const SInputPortConfig inputs[] = {
  1563.                         InputPortConfig<string>("anim_Animation", _HELP("Animation1")),
  1564.                         InputPortConfig<float>("TriggerTime",     0.2f,                _HELP("TriggerTime")),
  1565.                         { 0 }
  1566.                 };
  1567.                 static const SOutputPortConfig out_config[] = {
  1568.                         OutputPortConfig_AnyType("Trigger", _HELP("Send an event when animation is finished")),
  1569.                         { 0 }
  1570.                 };
  1571.                 config.pInputPorts = inputs;
  1572.                 config.pOutputPorts = out_config;
  1573.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1574.                 config.sDescription = _HELP("Synchronize two animations on two entities");
  1575.                 config.SetCategory(EFLN_ADVANCED);
  1576.         }
  1577.  
  1578.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1579.         {
  1580.                 switch (event)
  1581.                 {
  1582.                 case eFE_Initialize:
  1583.                         pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  1584.                         break;
  1585.                 case eFE_Update:
  1586.                         Update(pActInfo);
  1587.                         break;
  1588.                 }
  1589.         }
  1590.  
  1591.         virtual IFlowNodePtr Clone(SActivationInfo* pInfo)
  1592.         {
  1593.                 return new CFlowNode_TriggerOnKeyTime(pInfo, m_state);
  1594.         }
  1595.  
  1596.         virtual void Serialize(SActivationInfo*, TSerialize ser)
  1597.         {
  1598.                 ser.Value("state", m_state);
  1599.         }
  1600.  
  1601.         virtual void GetMemoryUsage(ICrySizer* s) const
  1602.         {
  1603.                 s->Add(*this);
  1604.         }
  1605.  
  1606. private:
  1607.         void Update(SActivationInfo* pActInfo)
  1608.         {
  1609.                 if (!pActInfo->pEntity)
  1610.                 {
  1611.                         m_state = false;
  1612.                         return;
  1613.                 }
  1614.                 ICharacterInstance* pChar = pActInfo->pEntity->GetCharacter(0);
  1615.                 if (!pChar)
  1616.                 {
  1617.                         m_state = false;
  1618.                         return;
  1619.                 }
  1620.                 ISkeletonAnim* pSkel = pChar->GetISkeletonAnim();
  1621.                 if (pSkel->GetNumAnimsInFIFO(0) < 1)
  1622.                 {
  1623.                         m_state = false;
  1624.                         return;
  1625.                 }
  1626.                 const CAnimation& anim = pSkel->GetAnimFromFIFO(0, 0);
  1627.                 if (anim.GetAnimationId() != pChar->GetIAnimationSet()->GetAnimIDByName(GetPortString(pActInfo, 0)))
  1628.                 {
  1629.                         m_state = false;
  1630.                         return;
  1631.                 }
  1632.                 float triggerTime = GetPortFloat(pActInfo, 1);
  1633.                 const float animTime = pSkel->GetAnimationNormalizedTime(&anim);
  1634.                 if (animTime < triggerTime)
  1635.                 {
  1636.                         m_state = false;
  1637.                 }
  1638.                 else if (animTime > triggerTime + 0.5f)
  1639.                 {
  1640.                         m_state = false;
  1641.                 }
  1642.                 else if (!m_state)
  1643.                 {
  1644.                         ActivateOutput(pActInfo, 0, SFlowSystemVoid());
  1645.                         m_state = true;
  1646.                 }
  1647.         }
  1648.  
  1649.         bool m_state;
  1650. };
  1651.  
  1652. class CFlowNode_AttachmentControl : public CFlowBaseNode<eNCT_Instanced>
  1653. {
  1654. public:
  1655.         CFlowNode_AttachmentControl(SActivationInfo* pActInfo)
  1656.                 : m_bHide(false)
  1657.         {
  1658.         }
  1659.  
  1660.         virtual IFlowNodePtr Clone(SActivationInfo* pActInfo) { return new CFlowNode_AttachmentControl(pActInfo); }
  1661.  
  1662.         enum INPUTS
  1663.         {
  1664.                 EIP_Attachment = 0,
  1665.                 EIP_Show,
  1666.                 EIP_Hide
  1667.         };
  1668.  
  1669.         enum OUTPUTS
  1670.         {
  1671.                 EOP_Shown = 0,
  1672.                 EOP_Hidden
  1673.         };
  1674.  
  1675.         virtual void GetConfiguration(SFlowNodeConfig& config)
  1676.         {
  1677.                 static const SInputPortConfig inputs[] = {
  1678.                         InputPortConfig<string>("Attachment", _HELP("Attachment"),           0, _UICONFIG("dt=attachment,ref_entity=entityId")),
  1679.                         InputPortConfig_Void("Show",          _HELP("Show the attachment")),
  1680.                         InputPortConfig_Void("Hide",          _HELP("Hide the attachment")),
  1681.                         { 0 }
  1682.                 };
  1683.                 static const SOutputPortConfig out_config[] = {
  1684.                         OutputPortConfig_Void("Shown",  _HELP("Triggered when Shown")),
  1685.                         OutputPortConfig_Void("Hidden", _HELP("Triggered when Hidden")),
  1686.                         { 0 }
  1687.                 };
  1688.                 config.pInputPorts = inputs;
  1689.                 config.pOutputPorts = out_config;
  1690.                 config.nFlags |= EFLN_TARGET_ENTITY;
  1691.                 config.sDescription = _HELP("[CUTSCENE ONLY] Show/Hide Character Attachments.");
  1692.                 config.SetCategory(EFLN_ADVANCED);
  1693.         }
  1694.  
  1695.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1696.         {
  1697.                 if (event == eFE_Initialize)
  1698.                 {
  1699.                         IAttachment* pAttachment = GetAttachment(pActInfo);
  1700.                         if (!pAttachment)
  1701.                                 return;
  1702.                         m_bHide = pAttachment->IsAttachmentHidden() != 0;
  1703.                 }
  1704.                 else if (event == eFE_Activate)
  1705.                 {
  1706.                         IAttachment* pAttachment = GetAttachment(pActInfo);
  1707.                         if (!pAttachment)
  1708.                                 return;
  1709.                         const bool bHide = IsPortActive(pActInfo, EIP_Hide);
  1710.                         const bool bShow = IsPortActive(pActInfo, EIP_Show);
  1711.                         if (bHide || bShow)
  1712.                         {
  1713.                                 pAttachment->HideAttachment(bHide);
  1714.                                 ActivateOutput(pActInfo, bHide ? EOP_Hidden : EOP_Shown, true);
  1715.                                 m_bHide = bHide;
  1716.                         }
  1717.                 }
  1718.         }
  1719.  
  1720.         IAttachment* GetAttachment(SActivationInfo* pActInfo)
  1721.         {
  1722.                 if (pActInfo->pEntity == 0)
  1723.                         return NULL;
  1724.  
  1725.                 ICharacterInstance* pChar = pActInfo->pEntity->GetCharacter(0);
  1726.                 if (pChar == 0)
  1727.                         return NULL;
  1728.  
  1729.                 IAttachmentManager* pAttMgr = pChar->GetIAttachmentManager();
  1730.                 if (pAttMgr == 0)
  1731.                         return NULL;
  1732.  
  1733.                 const string& attachment = GetPortString(pActInfo, EIP_Attachment);
  1734.                 IAttachment* pAttachment = pAttMgr->GetInterfaceByName(attachment.c_str());
  1735.                 return pAttachment;
  1736.         }
  1737.  
  1738.         virtual void GetMemoryUsage(ICrySizer* s) const
  1739.         {
  1740.                 s->Add(*this);
  1741.         }
  1742.  
  1743.         virtual void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  1744.         {
  1745.                 IAttachment* pAttachment = GetAttachment(pActInfo);
  1746.                 if (!pAttachment)
  1747.                         return;
  1748.  
  1749.                 ser.BeginGroup("FG_AttachmentControl");
  1750.                 if (ser.IsWriting())
  1751.                         m_bHide = pAttachment->IsAttachmentHidden() != 0;
  1752.  
  1753.                 ser.Value("bHide", m_bHide);
  1754.  
  1755.                 ser.EndGroup();
  1756.  
  1757.                 if (ser.IsReading())
  1758.                         pAttachment->HideAttachment(m_bHide);
  1759.         }
  1760.  
  1761. private:
  1762.         bool m_bHide;
  1763. };
  1764.  
  1765. //////////////////////////////////////////////////////////////////////////
  1766. // Start a cooperative animation
  1767. class CFlowNode_CooperativeAnimation : public CFlowBaseNode<eNCT_Instanced>
  1768. {
  1769. public:
  1770.         enum EInputs
  1771.         {
  1772.                 eIN_START,
  1773.                 eIN_STOP,
  1774.                 eIN_LOOP,
  1775.                 eIN_FORCESTART,
  1776.                 eIN_ADJUST_TO_TERRAIN,
  1777.                 eIN_IGNORE_CHARACTERS_DEATH,
  1778.                 //eIN_VERTICALCORRECTION,
  1779.                 eIN_FIRST_ACTOR_DOESNT_COLLIDE,
  1780.                 eIN_LOCATION,
  1781.                 eIN_ROTATION,
  1782.                 eIN_ALIGNMENTTYPE,
  1783.                 eIN_TARGET_ENTITY01,
  1784.                 eIN_SIGNALNAME01,
  1785.                 eIN_SLIDETIME01,
  1786.                 eIN_ALLOWHPHYSICS01,
  1787.                 eIN_TARGET_ENTITY02,
  1788.                 eIN_SIGNALNAME02,
  1789.                 eIN_SLIDETIME02,
  1790.                 eIN_ALLOWHPHYSICS02,
  1791.                 eIN_TARGET_ENTITY03,
  1792.                 eIN_SIGNALNAME03,
  1793.                 eIN_SLIDETIME03,
  1794.                 eIN_ALLOWHPHYSICS03,
  1795.                 eIN_TARGET_ENTITY04,
  1796.                 eIN_SIGNALNAME04,
  1797.                 eIN_SLIDETIME04,
  1798.                 eIN_ALLOWHPHYSICS04,
  1799.         };
  1800.  
  1801.         enum EOutputs
  1802.         {
  1803.                 eOUT_FINISHED01,
  1804.                 eOUT_FINISHED02,
  1805.                 eOUT_FINISHED03,
  1806.                 eOUT_FINISHED04,
  1807.                 eOUT_FINISHEDALL,
  1808.         };
  1809.  
  1810.         CFlowNode_CooperativeAnimation(SActivationInfo* pActInfo)
  1811.         {
  1812.                 m_bRunning = false;
  1813.                 Reset();
  1814.         }
  1815.  
  1816.         virtual IFlowNodePtr Clone(SActivationInfo* pActInfo) { return new CFlowNode_CooperativeAnimation(pActInfo); }
  1817.  
  1818.         void                 GetConfiguration(SFlowNodeConfig& config)
  1819.         {
  1820.                 // declare input ports //_UICONFIG("enum_int:NoChange=0,Hide=-1,Show=1")
  1821.                 static const SInputPortConfig in_ports[] =
  1822.                 {
  1823.                         InputPortConfig_Void("Start",                  _HELP("Starts the Cooperative Animation")),
  1824.                         InputPortConfig_Void("Stop",                   _HELP("Interrupts and Stops the animations (only needed in looping animations)")),
  1825.                         InputPortConfig<bool>("Loop",                  false,                                                                            _HELP("Loop Animation (runs until stopped) (0=no loop, 1=loop)"),                                                                                                                                                                                                                                                                                                                                "Looping",   0),
  1826.                         InputPortConfig<bool>("ForceStart",            true,                                                                             _HELP("Force Start Animation (safer)")),
  1827.                         InputPortConfig<bool>("AdjustToTerrain",       true,                                                                             _HELP("Make sure the characters are on terrain level (usually safer, but could cause problems on animations played in underground passages within the terrain)")),
  1828.                         InputPortConfig<bool>("IgnoreCharactersDeath", true,                                                                             _HELP("If false and any of the characters dies, it will stop the animation on all the characters involved")),
  1829.                         //InputPortConfig<bool>( "VerticalCorrection", 1, _HELP("Tilts the characters on uneven ground to match slope" )),
  1830.                         InputPortConfig<bool>("NoCollisionBetween",    true,                                                                             _HELP("If true, the first actor won't collide with the other actors involved on this action")),
  1831.                         InputPortConfig<Vec3>("Location",              _HELP("Starts the animation at a specific position (needs alignment type)")),
  1832.                         InputPortConfig<Vec3>("Rotation",              _HELP("Starts the animation at a specific rotation (needs alignment type)")),
  1833.                         InputPortConfig<int>("Alignment",              0,                                                                                _HELP("Alignment Type\nWildMatch: moves both characters the least amount\nFirstActor: first actor can be rotated but not moved\nFirstActorNoRot: first actor can neither be moved nor rotated\nFirstActorPosition: Slides the characters so the first one is at the in Location specified position\nLocation: moves both character until the reference point of the animation is at Location"),  0,           _UICONFIG("enum_int:WildMatch=0,FirstActor=1,FirstActorNoRot=2,FirstActorPosition=3,Location=4")),
  1834.                         InputPortConfig<EntityId>("Entity_01",         _HELP("First Actor"),                                                             "Entity_01",                                                                                                                                                                                                                                                                                                                                                                                     0),
  1835.                         InputPortConfig<string>("AnimationName_01",    _HELP("Animation Name")),
  1836.                         InputPortConfig<float>("SlideDuration_01",     0.2f,                                                                             _HELP("Time in seconds to slide this entity into position")),
  1837.                         InputPortConfig<bool>("HorizPhysics1",         false,                                                                            _HELP("Prohibits this character from being pushed through walls etc (safer)"),                                                                                                                                                                                                                                                                                                                   "HPhysics1", 0),
  1838.                         InputPortConfig<EntityId>("Entity_02",         _HELP("Second Actor"),                                                            "Entity_02",                                                                                                                                                                                                                                                                                                                                                                                     0),
  1839.                         InputPortConfig<string>("AnimationName_02",    _HELP("Animation Name")),
  1840.                         InputPortConfig<float>("SlideDuration_02",     0.2f,                                                                             _HELP("Time in seconds to slide this entity into position")),
  1841.                         InputPortConfig<bool>("HorizPhysics2",         false,                                                                            _HELP("Prohibits this character from being pushed through walls etc (safer)"),                                                                                                                                                                                                                                                                                                                   "HPhysics2", 0),
  1842.                         InputPortConfig<EntityId>("Entity_03",         _HELP("Third Actor"),                                                             "Entity_03",                                                                                                                                                                                                                                                                                                                                                                                     0),
  1843.                         InputPortConfig<string>("AnimationName_03",    _HELP("Animation Name")),
  1844.                         InputPortConfig<float>("SlideDuration_03",     0.2f,                                                                             _HELP("Time in seconds to slide this entity into position")),
  1845.                         InputPortConfig<bool>("HorizPhysics3",         false,                                                                            _HELP("Prohibits this character from being pushed through walls etc (safer)"),                                                                                                                                                                                                                                                                                                                   "HPhysics3", 0),
  1846.                         InputPortConfig<EntityId>("Entity_04",         _HELP("Fourth Actor"),                                                            "Entity_04",                                                                                                                                                                                                                                                                                                                                                                                     0),
  1847.                         InputPortConfig<string>("AnimationName_04",    _HELP("Animation Name")),
  1848.                         InputPortConfig<float>("SlideDuration_04",     0.2f,                                                                             _HELP("Time in seconds to slide this entity into position")),
  1849.                         InputPortConfig<bool>("HorizPhysics4",         false,                                                                            _HELP("Prohibits this character from being pushed through walls etc (safer)"),                                                                                                                                                                                                                                                                                                                   "HPhysics4", 0),
  1850.  
  1851.                         { 0 }
  1852.                 };
  1853.                 static const SOutputPortConfig out_config[] = {
  1854.                         OutputPortConfig_Void("Finished_01", _HELP("Activates when the first actor is done.")),
  1855.                         OutputPortConfig_Void("Finished_02", _HELP("Activates when the second actor is done.")),
  1856.                         OutputPortConfig_Void("Finished_03", _HELP("Activates when the third actor is done.")),
  1857.                         OutputPortConfig_Void("Finished_04", _HELP("Activates when the fourth actor is done.")),
  1858.                         OutputPortConfig_Void("Done",        _HELP("Activates when all actors are done.")),
  1859.                         { 0 }
  1860.                 };
  1861.  
  1862.                 //config.nFlags |= EFLN_TARGET_ENTITY;
  1863.                 config.pInputPorts = in_ports;
  1864.                 config.pOutputPorts = out_config;
  1865.                 config.sDescription = _HELP("Starts a cooperative animation for two characters (including alignment)");
  1866.                 config.SetCategory(EFLN_APPROVED);
  1867.         }
  1868.  
  1869.         void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  1870.         {
  1871.                 switch (event)
  1872.                 {
  1873.                 case eFE_Activate:
  1874.                         {
  1875.                                 // Get input port values
  1876.                                 EntityId iEntityID_01 = GetPortEntityId(pActInfo, eIN_TARGET_ENTITY01);
  1877.                                 EntityId iEntityID_02 = GetPortEntityId(pActInfo, eIN_TARGET_ENTITY02);
  1878.                                 EntityId iEntityID_03 = GetPortEntityId(pActInfo, eIN_TARGET_ENTITY03);
  1879.                                 EntityId iEntityID_04 = GetPortEntityId(pActInfo, eIN_TARGET_ENTITY04);
  1880.  
  1881.                                 if (IsPortActive(pActInfo, eIN_START))
  1882.                                 {
  1883.                                         if (m_bRunning)
  1884.                                         {
  1885.                                                 // if the coop animation is already running, do nothing
  1886.                                                 UpdateOutputs(pActInfo);
  1887.                                         }
  1888.  
  1889.                                         if (!m_bRunning)
  1890.                                         {
  1891.                                                 // start coop animation
  1892.  
  1893.                                                 // get the actors for both entities
  1894.                                                 IActor* pActor01 = reinterpret_cast<IActor*>(gEnv->pGameFramework->GetIActorSystem()->GetActor(iEntityID_01));
  1895.                                                 IActor* pActor02 = reinterpret_cast<IActor*>(gEnv->pGameFramework->GetIActorSystem()->GetActor(iEntityID_02));
  1896.                                                 IActor* pActor03 = reinterpret_cast<IActor*>(gEnv->pGameFramework->GetIActorSystem()->GetActor(iEntityID_03));
  1897.                                                 IActor* pActor04 = reinterpret_cast<IActor*>(gEnv->pGameFramework->GetIActorSystem()->GetActor(iEntityID_04));
  1898.                                                 CRY_ASSERT(pActor01);
  1899.                                                 if (!pActor01)
  1900.                                                         return;
  1901.                                                 //CRY_ASSERT(pActor02); // only one actor is really mandatory
  1902.  
  1903.                                                 // get the animation signal name
  1904.                                                 const string& sAnimName1 = GetPortString(pActInfo, eIN_SIGNALNAME01);
  1905.                                                 const string& sAnimName2 = GetPortString(pActInfo, eIN_SIGNALNAME02);
  1906.                                                 const string& sAnimName3 = GetPortString(pActInfo, eIN_SIGNALNAME03);
  1907.                                                 const string& sAnimName4 = GetPortString(pActInfo, eIN_SIGNALNAME04);
  1908.  
  1909.                                                 // get the rest of the parameters
  1910.                                                 Vec3 vLocation = GetPortVec3(pActInfo, eIN_LOCATION);
  1911.                                                 Vec3 vTemp = GetPortVec3(pActInfo, eIN_ROTATION);
  1912.                                                 Ang3 qRotation(vTemp.x, vTemp.y, vTemp.z);
  1913.                                                 bool bForceStart = GetPortBool(pActInfo, eIN_FORCESTART);
  1914.                                                 bool bLooping = GetPortBool(pActInfo, eIN_LOOP);
  1915.                                                 EAlignmentRef eAlignment = static_cast<EAlignmentRef>(GetPortInt(pActInfo, eIN_ALIGNMENTTYPE));
  1916.                                                 static_assert(eAF_Max == 5, "Array size changed, code might need to be updated!");
  1917.  
  1918.                                                 bool onlyOneChar = false;
  1919.                                                 if (!pActor02 && !pActor03 && !pActor04)
  1920.                                                 {
  1921.                                                         if (eAlignment == eAF_FirstActorPosition)
  1922.                                                         {
  1923.                                                                 // this is an exact positioning animation for only one Character
  1924.                                                                 onlyOneChar = true;
  1925.                                                         }
  1926.                                                         else
  1927.                                                                 return;
  1928.                                                 }
  1929.  
  1930.                                                 QuatT qtLocation;
  1931.                                                 qtLocation.t = vLocation;
  1932.                                                 qtLocation.q.SetIdentity();
  1933.                                                 //qtLocation.q.NormalizeSafe();
  1934.                                                 if (!vTemp.IsZero())
  1935.                                                 {
  1936.                                                         qtLocation.q.SetRotationXYZ(qRotation);
  1937.                                                         qtLocation.q.NormalizeSafe();
  1938.                                                 }
  1939.  
  1940.                                                 // Get sliding times
  1941.                                                 float slideTime01 = GetPortFloat(pActInfo, eIN_SLIDETIME01);
  1942.                                                 float slideTime02 = GetPortFloat(pActInfo, eIN_SLIDETIME02);
  1943.                                                 float slideTime03 = GetPortFloat(pActInfo, eIN_SLIDETIME03);
  1944.                                                 float slideTime04 = GetPortFloat(pActInfo, eIN_SLIDETIME04);
  1945.  
  1946.                                                 // Get physics settings
  1947.                                                 bool allowHPhysics01 = GetPortBool(pActInfo, eIN_ALLOWHPHYSICS01);
  1948.                                                 bool allowHPhysics02 = GetPortBool(pActInfo, eIN_ALLOWHPHYSICS02);
  1949.                                                 bool allowHPhysics03 = GetPortBool(pActInfo, eIN_ALLOWHPHYSICS03);
  1950.                                                 bool allowHPhysics04 = GetPortBool(pActInfo, eIN_ALLOWHPHYSICS04);
  1951.  
  1952.                                                 SCooperativeAnimParams generalParams(bForceStart, bLooping, eAlignment, qtLocation);
  1953.                                                 generalParams.bPreventFallingThroughTerrain = GetPortBool(pActInfo, eIN_ADJUST_TO_TERRAIN);
  1954.                                                 generalParams.bIgnoreCharacterDeath = GetPortBool(pActInfo, eIN_IGNORE_CHARACTERS_DEATH);
  1955.                                                 generalParams.bNoCollisionsBetweenFirstActorAndRest = GetPortBool(pActInfo, eIN_FIRST_ACTOR_DOESNT_COLLIDE);
  1956.  
  1957.                                                 SCharacterParams charParams1(pActor01->GetAnimatedCharacter(), sAnimName1.c_str(), allowHPhysics01, slideTime01);
  1958.                                                 charParams1.SetAllowHorizontalPhysics(false);
  1959.                                                 if (!onlyOneChar)
  1960.                                                 {
  1961.                                                         TCharacterParams characterParams;
  1962.                                                         characterParams.push_back(charParams1);
  1963.  
  1964.                                                         if (pActor02)
  1965.                                                         {
  1966.                                                                 SCharacterParams charParams2(pActor02->GetAnimatedCharacter(), sAnimName2.c_str(), allowHPhysics02, slideTime02);
  1967.                                                                 charParams2.SetAllowHorizontalPhysics(false);
  1968.                                                                 characterParams.push_back(charParams2);
  1969.                                                         }
  1970.                                                         if (pActor03)
  1971.                                                         {
  1972.                                                                 SCharacterParams charParams3(pActor03->GetAnimatedCharacter(), sAnimName3.c_str(), allowHPhysics03, slideTime03);
  1973.                                                                 charParams3.SetAllowHorizontalPhysics(false);
  1974.                                                                 characterParams.push_back(charParams3);
  1975.                                                         }
  1976.                                                         if (pActor04)
  1977.                                                         {
  1978.                                                                 SCharacterParams charParams4(pActor04->GetAnimatedCharacter(), sAnimName4.c_str(), allowHPhysics04, slideTime04);
  1979.                                                                 charParams4.SetAllowHorizontalPhysics(false);
  1980.                                                                 characterParams.push_back(charParams4);
  1981.                                                         }
  1982.  
  1983.                                                         m_bRunning = gEnv->pGameFramework->GetICooperativeAnimationManager()->StartNewCooperativeAnimation(characterParams, generalParams);
  1984.                                                 }
  1985.                                                 else
  1986.                                                 {
  1987.                                                         m_bRunning = gEnv->pGameFramework->GetICooperativeAnimationManager()->StartExactPositioningAnimation(charParams1, generalParams);
  1988.                                                 }
  1989.  
  1990.                                                 m_bStarted = true;
  1991.  
  1992.                                                 // make sure I get updated regulary
  1993.                                                 pActInfo->pGraph->SetRegularlyUpdated(pActInfo->myID, true);
  1994.  
  1995.                                                 if (m_bRunning)
  1996.                                                 {
  1997.                                                         m_iEntityID_01 = iEntityID_01;
  1998.                                                         m_iEntityID_02 = iEntityID_02;
  1999.                                                         m_iEntityID_03 = iEntityID_03;
  2000.                                                         m_iEntityID_04 = iEntityID_04;
  2001.                                                 }
  2002.                                                 else
  2003.                                                 {
  2004.                                                         // starting failed
  2005.                                                 }
  2006.                                         }
  2007.                                 }
  2008.                                 else if (IsPortActive(pActInfo, eIN_STOP))
  2009.                                 {
  2010.                                         if (m_bRunning)
  2011.                                         {
  2012.                                                 // Stop running cooperative animation on these two characters
  2013.                                                 StopAnimations(pActInfo);
  2014.                                         }
  2015.  
  2016.                                         m_bRunning = false;
  2017.                                         Reset();
  2018.                                 }
  2019.                         }
  2020.                         break;
  2021.                 case eFE_Update:
  2022.                         {
  2023.                                 UpdateOutputs(pActInfo);
  2024.                         }
  2025.                         break;
  2026.                 }
  2027.         }
  2028.  
  2029.         void UpdateOutputs(SActivationInfo* pActInfo)
  2030.         {
  2031.                 // Update the Outputs of whether this action has finished or not
  2032.                 bool bActor1Busy = gEnv->pGameFramework->GetICooperativeAnimationManager()->IsActorBusy(m_iEntityID_01);
  2033.                 bool bActor2Busy = gEnv->pGameFramework->GetICooperativeAnimationManager()->IsActorBusy(m_iEntityID_02);
  2034.                 bool bActor3Busy = gEnv->pGameFramework->GetICooperativeAnimationManager()->IsActorBusy(m_iEntityID_03);
  2035.                 bool bActor4Busy = gEnv->pGameFramework->GetICooperativeAnimationManager()->IsActorBusy(m_iEntityID_04);
  2036.  
  2037.                 if (m_bStarted)
  2038.                 {
  2039.                         bool bFinishedAll = false;
  2040.  
  2041.                         if (!bActor1Busy)
  2042.                         {
  2043.                                 bFinishedAll = true;
  2044.  
  2045.                                 ActivateOutput(pActInfo, eOUT_FINISHED01, !bActor1Busy && m_bRunning);
  2046.                         }
  2047.  
  2048.                         if (!bActor2Busy && m_iEntityID_02)
  2049.                         {
  2050.                                 ActivateOutput(pActInfo, eOUT_FINISHED02, !bActor2Busy && m_bRunning);
  2051.                         }
  2052.                         else
  2053.                                 bFinishedAll = bFinishedAll && (m_iEntityID_02 == 0);
  2054.  
  2055.                         if (!bActor3Busy && m_iEntityID_03)
  2056.                         {
  2057.                                 ActivateOutput(pActInfo, eOUT_FINISHED03, !bActor3Busy && m_bRunning);
  2058.                         }
  2059.                         else
  2060.                                 bFinishedAll = bFinishedAll && (m_iEntityID_03 == 0);
  2061.  
  2062.                         if (!bActor4Busy && m_iEntityID_04)
  2063.                         {
  2064.                                 ActivateOutput(pActInfo, eOUT_FINISHED04, !bActor4Busy && m_bRunning);
  2065.                         }
  2066.                         else
  2067.                                 bFinishedAll = bFinishedAll && (m_iEntityID_04 == 0);
  2068.  
  2069.                         if (bFinishedAll)
  2070.                         {
  2071.                                 ActivateOutput(pActInfo, eOUT_FINISHEDALL, bFinishedAll && m_bRunning);
  2072.                         }
  2073.                 }
  2074.  
  2075.                 m_bRunning = bActor1Busy || bActor2Busy;
  2076.  
  2077.                 if (!m_bRunning)
  2078.                         Reset();
  2079.         }
  2080.  
  2081.         void StopAnimations(SActivationInfo* pActInfo)
  2082.         {
  2083.                 // stop coop animation for all actors
  2084.                 IActor* pActor01 = /*static_cast<CActor*>*/ (gEnv->pGameFramework->GetIActorSystem()->GetActor(m_iEntityID_01));
  2085.                 CRY_ASSERT(pActor01);
  2086.  
  2087.                 gEnv->pGameFramework->GetICooperativeAnimationManager()->StopCooperativeAnimationOnActor(pActor01->GetAnimatedCharacter());
  2088.  
  2089.                 ActivateOutput(pActInfo, eOUT_FINISHED01, true);
  2090.                 ActivateOutput(pActInfo, eOUT_FINISHED02, true);
  2091.                 ActivateOutput(pActInfo, eOUT_FINISHED03, true);
  2092.                 ActivateOutput(pActInfo, eOUT_FINISHED04, true);
  2093.                 ActivateOutput(pActInfo, eOUT_FINISHEDALL, true);
  2094.  
  2095.                 Reset();
  2096.         }
  2097.  
  2098.         void Reset()
  2099.         {
  2100.                 m_bRunning = false;
  2101.                 m_bStarted = false;
  2102.         }
  2103.  
  2104.         virtual void GetMemoryUsage(ICrySizer* s)  const
  2105.         {
  2106.                 s->Add(*this);
  2107.         }
  2108.  
  2109. private:
  2110.  
  2111.         bool     m_bRunning;
  2112.         bool     m_bStarted;
  2113.         EntityId m_iEntityID_01;
  2114.         EntityId m_iEntityID_02;
  2115.         EntityId m_iEntityID_03;
  2116.         EntityId m_iEntityID_04;
  2117. };
  2118.  
  2119. REGISTER_FLOW_NODE("Animations:PlayCGA", CPlayCGA_Node);
  2120. REGISTER_FLOW_NODE("Animations:BoneInfo", CAnimationBoneInfo_Node);
  2121. REGISTER_FLOW_NODE("Animations:PlayAnimation", CPlayAnimation_Node);
  2122. REGISTER_FLOW_NODE("Animations:CheckAnimPlaying", CIsAnimPlaying_Node);
  2123. REGISTER_FLOW_NODE("Animations:CooperativeAnimation", CFlowNode_CooperativeAnimation);
  2124. REGISTER_FLOW_NODE("Animations:LookAt", CFlowNode_LookAt);
  2125. #ifdef INCLUDE_ANIMATIONGRAPH
  2126. REGISTER_FLOW_NODE("Animations:AnimGraphControl", CFlowNode_AGControl);
  2127. REGISTER_FLOW_NODE("Animations:AnimGraphSetInput", CFlowNode_AGSetInput);
  2128. REGISTER_FLOW_NODE("Animations:AnimGraphLockInput", CFlowNode_AGLockInput);
  2129. REGISTER_FLOW_NODE("Animations:AnimGraphWatchOutput", CFlowNode_AGWatchOutput);
  2130. REGISTER_FLOW_NODE("Animations:AnimGraphCheckOutput", CFlowNode_AGCheckOutput);
  2131. REGISTER_FLOW_NODE("Animations:AnimGraphReset", CFlowNode_AGReset);
  2132. #endif
  2133. REGISTER_FLOW_NODE("Animations:StopAnimation", CFlowNode_StopAnimation);
  2134. REGISTER_FLOW_NODE("Animations:NoAiming", CFlowNode_NoAiming);
  2135. REGISTER_FLOW_NODE("Animations:SynchronizeTwoAnimations", CFlowNode_SynchronizeTwoAnimations);
  2136. REGISTER_FLOW_NODE("Animations:TriggerOnKeyTime", CFlowNode_TriggerOnKeyTime);
  2137. REGISTER_FLOW_NODE("Animations:AttachmentControl", CFlowNode_AttachmentControl);
  2138.  
downloadPlayCGANode.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top