//Calld by GroundedAnimatedAbilityModule to move a capsuletransform along the path
    public void ApplyMotion(CapsuleTransform a_Transform, float a_Time)
    {
        if (m_CurrentPathNode == null)
        {
            return;
        }
        if (m_CurrentIndex == 0)
        {
            m_CurrentPathNode.ApplyEntireMovement(a_Transform);
            return;
        }
        if (m_CurrentPathNode.m_Duration == 0)
        {
            m_CurrentPathNode.ApplyEntireMovement(a_Transform);
        }
        else
        {
            float factor = Mathf.Clamp01(a_Time / m_CurrentPathNode.m_Duration);

            CapsuleMovementPathNode newPoint = new CapsuleMovementPathNode();
            newPoint.InterpolationBetweenTwoNodes(m_PathNodes[m_CurrentIndex - 1], m_CurrentPathNode, factor);

            newPoint.ApplyEntireMovement(a_Transform);
        }
    }
 public void InterpolationBetweenTwoNodes(CapsuleMovementPathNode a_PathNode1, CapsuleMovementPathNode a_PathNode2, float a_Factor)
 {
     a_Factor      = Mathf.Clamp01(a_Factor);
     m_Position    = Vector3.Lerp(a_PathNode1.m_Position, a_PathNode2.m_Position, a_Factor);
     m_UpDirection = Vector3.Lerp(a_PathNode1.m_UpDirection, a_PathNode2.m_UpDirection, a_Factor).normalized;
     m_Length      = Mathf.Lerp(a_PathNode1.m_Length, a_PathNode2.m_Length, a_Factor);
 }
 public void CopyFromPathNode(CapsuleMovementPathNode a_PathNode)
 {
     m_Position     = a_PathNode.m_Position;
     m_UpDirection  = a_PathNode.m_UpDirection;
     m_Length       = a_PathNode.m_Length;
     m_Duration     = a_PathNode.m_Duration;
     m_RotateMethod = a_PathNode.m_RotateMethod;
     m_ResizeMethod = a_PathNode.m_ResizeMethod;
 }
    //Creation functions for the path
    public CapsuleMovementPathNode CreateFirstNode(CapsuleTransform a_Transform)
    {
        CapsuleMovementPathNode node = new CapsuleMovementPathNode();

        node.CopyFromTransform(a_Transform);
        AddNode(node);
        m_CurrentPathNode = node;
        m_CurrentIndex    = 0;
        return(node);
    }
 public void IncrementCurrentNode()
 {
     m_CurrentIndex++;
     if (m_CurrentIndex < m_PathNodes.Count)
     {
         m_CurrentPathNode = m_PathNodes[m_CurrentIndex];
     }
     else
     {
         m_CurrentPathNode = null;
     }
 }
    public CapsuleMovementPathNode DuplicateAndAddLastNode()
    {
        if (m_PathNodes.Count == 0)
        {
            Debug.Log("Path is empty!");
            return(new CapsuleMovementPathNode());
        }
        CapsuleMovementPathNode node = new CapsuleMovementPathNode();

        node.CopyFromPathNode(m_PathNodes[m_PathNodes.Count - 1]);
        AddNode(node);
        return(node);
    }
    protected override void GeneratePath()
    {
        CEdgeCastInfo info = m_ControlledCollider.GetEdgeCastInfo();

        m_Path.Clear();
        CapsuleTransform copy = m_ControlledCollider.GetCapsuleTransformCopy();

        //First node is in edgehang alignment, moving away from the edge mildly
        CapsuleMovementPathNode newNode = m_Path.CreateFirstNode(copy);
        Vector3 upCenter = info.GetProposedHeadPoint();

        upCenter += m_ControlledCollider.GetEdgeCastInfo().GetWallNormal() * 0.03f;
        copy.SetUpCenter(upCenter);
        copy.Rotate(info.GetUpDirection(), RotateMethod.FromTop);
        newNode = m_Path.DuplicateAndAddLastNode();
        newNode.CopyFromTransform(copy);

        //Second node moves up along local up, until the bottom can slide over the edge
        newNode            = m_Path.DuplicateAndAddLastNode();
        newNode.m_Duration = m_MoveUpTime;
        float contactDot  = Vector3.Dot(info.GetEdgeNormal(), info.GetEdgePoint());
        float bottomDot   = Vector3.Dot(info.GetEdgeNormal(), copy.GetDownCenter()) - m_ControlledCollider.GetRadius() - m_MoveUpMargin;
        float normalDot   = Vector3.Dot(info.GetEdgeNormal(), copy.GetUpDirection());
        float rawDistance = contactDot - bottomDot;
        float distance    = rawDistance / normalDot;

        newNode.m_Position += copy.GetUpDirection() * distance;
        newNode.ApplyEntireMovement(copy);
        //Third node snaps the capsule to the "upright" position for the ground it's going to stand on
        newNode                = m_Path.DuplicateAndAddLastNode();
        newNode.m_Duration     = 0.0f;
        newNode.m_UpDirection  = (m_CharacterController.GetAlignsToGround()) ? info.GetEdgeNormal() : Vector3.up;
        newNode.m_RotateMethod = RotateMethod.FromBottom;
        newNode.ApplyEntireMovement(copy);
        newNode.m_Position = copy.GetPosition();
        //Final node moves the capsule over the ground
        newNode            = m_Path.DuplicateAndAddLastNode();
        newNode.m_Duration = m_MoveSideTime;
        Vector3 direction = CState.GetDirectionAlongNormal(-info.GetWallNormal(), info.GetEdgeNormal());

        newNode.m_Position += direction * m_MoveSideDistance;
        newNode.ApplyEntireMovement(copy);
    }
 void AddNode(CapsuleMovementPathNode a_Node)
 {
     m_PathNodes.Add(a_Node);
 }
 public void Clear()
 {
     m_PathNodes.Clear();
     m_CurrentPathNode = null;
     m_CurrentIndex    = 0;
 }