//    public void SetFromBody(EnableBody body, ReplayEventData data, float speed = 1.0f, bool usePositionData = false)
    /// <summary>
    /// Sets the Avatar's joints using EnableBody as relative-to-Tpose rotation data.
    /// </summary>
    /// <param name="body">T-pose offset rotation data</param>
    /// <param name="duration">How quickly to get to final pose</param>
    /// <param name="speed">Multiplier to duration</param>
    /// <param name="usePositionData">Whether to use or ignore joint positions (and only use orientations)</param>
    public void SetFromBody(EnableBody body, float duration, float speed = 1.0f, bool usePositionData = false, bool mirror = false)
    {
        Dictionary <string, EnableJoint> joints = body.Joints;

        //estimatedRootOffset = newEstimatedRootOffset;
        //print("SetFromBody: duration=" + duration + ", speed = " + speed);
        foreach (string jointName in joints.Keys)
        {
            //print ("======================SetFromBody jointName = " + jointName);
            //Transform bp = bodyDict[jointName];

            /*
             *          Transform bp;
             *          //lookup if JSON data is one of the joints we are tracking
             *          if (bodyDict.TryGetValue(jointName, out bp))
             *          {
             *          }
             *          else
             *          {
             *              continue;
             *          }
             */
            string jn = jointName;
            //print("jn=" + jn);
            if (mirror == true)
            {
                if (jointName.Contains("Left"))
                {
                    //print("replacing " + jn);
                    jn = jointName.Replace("Left", "Right");
                }
                else if (jointName.Contains("Right"))
                {
                    jn = jointName.Replace("Right", "Left");
                }
            }


            EnableJoint j = joints[jn];
            //if (j.orientation == null) {
            //	print ("NULL+++++++++++++++++++++");
            //}
            JointSet(j, jointName, duration / speed, usePositionData, mirror);
        }

        /*
         *      footPositionCurrent = (leftFootPosition.y < rightFootPosition.y ? leftFootPosition : rightFootPosition);
         *      leftFootDown = (leftFootPosition.y < rightFootPosition.y);
         *      int footDown = (leftFootDown ? 1 : 0);
         *      if (lastFootDown != footDown) {  //switched feet
         *              footPositionInit = (leftFootDown ? leftFootPosition : rightFootPosition) ;
         *              //print ("switched feet, leftdown=" + leftFootDown + ", l=" + leftFootPosition + ", r=" + rightFootPosition);
         *              if (lastFootDown == -1) {  //get offset to move foot position to startPosition
         *                      startOffset = startPosition - footPositionInit;
         *              }
         *              lastFootDown = footDown;
         *      }
         *      newEstimatedRootOffset = footPositionCurrent - footPositionInit ; //move body
         */
    }
    public void AddJoint(string name, Vector3 position, Quaternion orientation)
    {
        EnableJoint joint = new EnableJoint();

        joint.position    = position;
        joint.orientation = orientation;
        AddJoint(name, joint);
    }
    void SetFromBody(EnableBody body, ReplayEventData data)
    {
        Dictionary <string, EnableJoint> joints = body.Joints;

        foreach (string jointName in joints.Keys)
        {
            Transform   bp = bodyDict[jointName];
            EnableJoint j  = joints[jointName];
            bp.DOLocalRotate(j.orientation.eulerAngles, data.Duration);
            bp.DOMove(j.position, data.Duration);
        }
    }
    /// <summary>
    /// Set the Avatar's joint position and orientation
    /// </summary>
    /// <param name="aJoint">values to set the joint to</param>
    /// <param name="jointName">name of the avatar joint to set</param>
    /// <param name="duration">how long it takes joint to interpolate to new position</param>
    /// <param name="usePositionData">whether to set joints to positons (scale skeleton to bone lenghts)</param>
    void JointSet(EnableJoint aJoint, string jointName, float duration, bool usePositionData, bool mirror)
    {
        //        Transform bp = bodyDict[jointName];
        Quaternion targetRotation, offsetNodeRotation;

        offsetNodeRotation = Quaternion.identity;
        int boneInd;

        //        int boneInd = boneName2BoneIndex[jointName];
        if (!boneName2BoneIndex.TryGetValue(jointName, out boneInd))
        {
            print("JointSet : " + jointName + " not found!");
        }
        //print("JointSet : " + jointName + ", boneInd: " + boneInd);
        //       print("JointSet id= " + boneInd);
        Transform bp = bones[boneInd];  //bone on avatar to set

        if (bp == null)
        {
            //print("bone NULL: " + jointName);
            return;
        }
        // Kinect2AvatarRot(aJoint.orientation, bp);
        //bp.rotation = Quaternion.Slerp(bp.rotation, targetRotation, smoothFactor * Time.deltaTime);


        //    Quaternion targetRotation = bp.rotation;
        //    var boneInfo = m_BoneInfos[i];
        if (offsetNode != null)
        {
            offsetNodeRotation = offsetNode.transform.rotation;
        }
        var rot = aJoint.orientation;  //global orientation

        if (mirror == true)
        {
            //flip quaternion
            rot.y = -rot.y;
            rot.z = -rot.z;
            //			rot.y = -rot.y;
            //			rot.x = -rot.x;
            //			rot.x = -rot.x;
            //			rot.z = -rot.z;
        }

        rot = offsetNodeRotation * rot;  //since we set global rotations, all parent transforms are ignored unless offsetNode set

        if (globalData)
        {
            targetRotation = rot * initialRotations[boneInd];
            if (jointName == "aLeftShoulder")
            {
                print("SET ROTATIONS[" + jointName + "]bi=" + boneInd.ToString());
                print("SET ROTATIONS[" + jointName + "]targ=" + rot.eulerAngles);
                print("SET ROTATIONS[" + jointName + "]init=" + initialLocalRotations[boneInd].eulerAngles);
                print("SET ROTATIONS[" + jointName + "]Ltarg= " + targetRotation.eulerAngles);
                print("SET ROTATIONS[" + jointName + "]trans=" + bp.name);
            }
        }
        else
        {
            //targetRotation = rot * initialLocalRotations[boneInd];
            Quaternion iq2 = initialLocalRotations[boneInd];
            Quaternion lq2 = Quaternion.Inverse(iq2) * rot * iq2;
            targetRotation = iq2 * lq2;

            /*
             * if (jointName == "aLeftShoulder")
             * {
             *  print("SET LOCAL ROTATIONS[" + jointName + "]bi=" + boneInd.ToString());
             *  print("SET LOCAL ROTATIONS[" + jointName + "]targ=" + rot.eulerAngles);
             *  print("SET LOCAL ROTATIONS[" + jointName + "]init=" + initialLocalRotations[boneInd].eulerAngles);
             *  print("SET LOCAL ROTATIONS[" + jointName + "]Ltarg= " + targetRotation.eulerAngles);
             *  print("SET LOCAL ROTATIONS[" + jointName + "]trans=" + bp.name);
             * }*/
        }

        //        bp.localPosition = Vector3.Lerp(bp.localPosition, targetPosition , m_InterpolateMovement);
        //        bp.localRotation = Quaternion.Slerp(bp.localRotation, targetRotation, m_InterpolateRotation);
        if (globalData)
        {
            Vector3 ang       = targetRotation.eulerAngles;
            float   duration2 = duration * 1.5f; //hack... For some reason, tween is stopping well before next one starts without this hack
                                                 //print("duration2="+duration2);

            /*
             * if (jointName == "LeftShoulder")
             * {
             *  print("DORotate: ang=" + ang + ", duration = " + duration2);
             *  print("SET ROTATIONS[" + jointName + "]bi=" + boneInd.ToString());
             *  print("SET ROTATIONS[" + jointName + "]targ=" + rot.eulerAngles);
             *  print("SET ROTATIONS[" + jointName + "]init=" + initialLocalRotations[boneInd].eulerAngles);
             *  print("SET ROTATIONS[" + jointName + "]Ltarg= " + targetRotation.eulerAngles);
             *  print("SET ROTATIONS[" + jointName + "]trans=" + bp.name);
             * }*/
            //bp.transform.rotation = targetRotation;
            //            bp.DORotate(ang, duration2).OnComplete(tweenDone);
            bp.DOKill();  //kill any tweens still going (in case speed was increased or we jumped in time)
            bp.DORotate(ang, duration2).OnComplete(() => tweenDone(bp));
        }
        else
        {
            float m_InterpolateRotation = 0.5f;
            bp.localRotation = Quaternion.Slerp(bp.localRotation, targetRotation, m_InterpolateRotation);
        }
        Vector3 targetPosition, offsetNodePosition, offsetNodeScale;

        offsetNodePosition = Vector3.zero;
        if (offsetNode != null)
        {
            offsetNodePosition = offsetNode.transform.position;
            offsetNodeScale    = offsetNode.transform.localScale;
        }
        //bp.DOLocalMove(Kinect2AvatarPos(aJoint.position, rootToGround), duration);
        if (usePositionData || (jointName == "Hips"))
        {  //move body parts in global space if flag is set
            if (jointName == "Chest")
            {
                return;
            }
            if (false) // PJD  Check if ok to put this back!!! usePositionData)
            {
                targetPosition = aJoint.position + offsetNodePosition;
            }
            else
            {
                //firstPosition is a hack if no offset node is set for the figure not to move globally from where it is initially placed.
                if (!firstPositionSet)
                {
                    if (offsetNode != null)
                    {
                        firstPosition = Vector3.zero;
                        //print("+++++++++++++++FPSet1");
                    }
                    else
                    {
                        firstPosition = aJoint.position - bp.position;// aJoint.position;
                        //print("+++++++++++++++FPSet2");
                    }
                    firstPositionSet = true;
                    //print("+++++++++++++++FPSet");
                }

                //                targetPosition = aJoint.position - firstPosition + offsetNodePosition.Scale(offsetNodeScale);
                targetPosition = aJoint.position - firstPosition;
                //print("targ pos1=" + targetPosition);
                targetPosition = offsetNode.transform.TransformPoint(targetPosition);
                //print("targ pos2=" + targetPosition);
            }
            if (mirror)
            {
                targetPosition.x = -targetPosition.x;
            }
            bp.DOMove(targetPosition, duration); //move relative to spine base
        }
    }
 public void AddJoint(string name, EnableJoint aJoint)
 {
     jointDictionary.Add(name, aJoint);
 }