Example #1
0
        private void DoWalkCycleOffsets(
            float armLength,
            ref Vector3 rightHand,
            ref Vector3 leftHand,
            ref List <float> shoulderAngle,
            ref List <float> handSwingAngle,
            ref JointLister shoulderPos,
            bool carrying,
            SimpleCurve cycleHandsSwingAngle,
            float offsetJoint)
        {
            // Has the pawn something in his hands?
            if (carrying)
            {
                return;
            }

            Rot4 rot = this.BodyFacing;

            // Basic values if pawn is carrying stuff
            float x  = 0;
            float x2 = -x;
            float y  = Offsets.YOffset_Behind;
            float y2 = y;
            float z;
            float z2;

            // Offsets for hands from the pawn center
            z = z2 = -armLength;

            if (rot.IsHorizontal)
            {
                x = x2 = 0f;
                if (rot == Rot4.East)
                {
                    y2 = -0.5f;
                }
                else
                {
                    y = -0.05f;
                }
            }
            else if (rot == Rot4.North)
            {
                y   = y2 = -0.02f;
                x  *= -1;
                x2 *= -1;
            }

            // Swing the hands, try complete the cycle
            if (this.CompAnimator.IsMoving)
            {
                WalkCycleDef walkCycle = this.CompAnimator.WalkCycle;
                float        percent   = this.CompAnimator.MovedPercent;
                if (rot.IsHorizontal)
                {
                    float lookie = rot == Rot4.West ? -1f : 1f;
                    float f      = lookie * offsetJoint;

                    shoulderAngle[0] = shoulderAngle[1] = lookie * walkCycle?.shoulderAngle ?? 0f;

                    shoulderPos.RightJoint.x += f;
                    shoulderPos.LeftJoint.x  += f;

                    handSwingAngle[0] = handSwingAngle[1] =
                        (rot == Rot4.West ? -1 : 1) * cycleHandsSwingAngle.Evaluate(percent);
                }
                else
                {
                    z  += cycleHandsSwingAngle.Evaluate(percent) / 500;
                    z2 -= cycleHandsSwingAngle.Evaluate(percent) / 500;

                    z  += walkCycle?.shoulderAngle / 800 ?? 0f;
                    z2 += walkCycle?.shoulderAngle / 800 ?? 0f;
                }
            }

            if (MainTabWindow_BaseAnimator.Panic || this.Pawn.Fleeing() || this.Pawn.IsBurning())
            {
                float offset = 1f + armLength;
                x  *= offset;
                z  *= offset;
                x2 *= offset;
                z2 *= offset;
                handSwingAngle[0] += 180f;
                handSwingAngle[1] += 180f;
                shoulderAngle[0]   = shoulderAngle[1] = 0f;
            }

            rightHand = new Vector3(x, y, z);
            leftHand  = new Vector3(x2, y2, z2);
        }
Example #2
0
        public override void DrawHands(Quaternion bodyQuat, Vector3 drawPos,
                                       bool portrait,
                                       Thing carriedThing = null, bool flip = false)
        {
            if (this.Pawn.Dead || this.Pawn.Downed)
            {
                return;
            }

            if (portrait && !HarmonyPatchesFS.AnimatorIsOpen())
            {
                return;
            }

            if (!this.CompAnimator.Props.bipedWithHands)
            {
                return;
            }

            // return if hands already drawn on carrything
            bool carrying = carriedThing != null;

            if (this.CarryStuff() && !carrying)
            {
                return;
            }


            if (carrying)
            {
                this.ApplyEquipmentWobble(ref drawPos);
                carriedThing.DrawAt(drawPos, flip);
            }

            BodyAnimDef body = this.CompAnimator.BodyAnim;

            Rot4 rot = this.BodyFacing;

            if (body == null)
            {
                return;
            }

            JointLister shoulperPos = this.GetJointPositions(JointType.Shoulder,
                                                             body.shoulderOffsets[rot.AsInt],
                                                             body.shoulderOffsets[Rot4.North.AsInt].x,
                                                             carrying, this.Pawn.ShowWeaponOpenly());

            List <float> handSwingAngle = new List <float> {
                0f, 0f
            };
            List <float> shoulderAngle = new List <float> {
                0f, 0f
            };
            Vector3      rightHand = Vector3.zero;
            Vector3      leftHand  = Vector3.zero;
            WalkCycleDef walkCycle = this.CompAnimator.WalkCycle;
            PoseCycleDef poseCycle = this.CompAnimator.PoseCycle;

            if (walkCycle != null)
            {
                float offsetJoint = walkCycle.ShoulderOffsetHorizontalX.Evaluate(this.CompAnimator.MovedPercent);

                this.DoWalkCycleOffsets(
                    body.armLength,
                    ref rightHand,
                    ref leftHand,
                    ref shoulderAngle,
                    ref handSwingAngle,
                    ref shoulperPos,
                    carrying,
                    walkCycle.HandsSwingAngle,
                    offsetJoint);
            }

            if (poseCycle != null)
            {
                this.DoPoseCycleOffsets(ref rightHand,
                                        ref shoulderAngle,
                                        ref handSwingAngle, poseCycle);
            }

            this.DoAttackAnimationHandOffsets(ref handSwingAngle, ref rightHand, false);

            this.GetBipedMesh(out Mesh handMeshRight, out Mesh handMeshLeft);

            Material matLeft  = this.LeftHandMat;
            Material matRight = this.RightHandMat;

            if (MainTabWindow_BaseAnimator.Colored)
            {
                matLeft  = this.CompAnimator.PawnBodyGraphic?.HandGraphicLeftCol?.MatSingle;
                matRight = this.CompAnimator.PawnBodyGraphic?.HandGraphicRightCol?.MatSingle;
            }
            else if (carriedThing == null)
            {
                switch (rot.AsInt)
                {
                case 1:
                    matLeft = this.LeftHandShadowMat;
                    break;

                case 3:
                    matRight = this.RightHandShadowMat;
                    break;
                }
            }

            bool drawLeft  = matLeft != null && this.CompAnimator.BodyStat.HandLeft != PartStatus.Missing;
            bool drawRight = matRight != null && this.CompAnimator.BodyStat.HandRight != PartStatus.Missing;

            if (drawLeft)
            {
                Quaternion quat;
                Vector3    position;
                bool       noTween = false;
                if (!this.CompAnimator.IsMoving && this.CompAnimator.HasLeftHandPosition)
                {
                    position = this.CompAnimator.SecondHandPosition;
                    quat     = this.CompAnimator.WeaponQuat;
                    noTween  = true;
                }
                else
                {
                    shoulperPos.LeftJoint = bodyQuat * shoulperPos.LeftJoint;
                    leftHand = bodyQuat * leftHand.RotatedBy(-handSwingAngle[0] - shoulderAngle[0]);

                    position = drawPos + shoulperPos.LeftJoint + leftHand;
                    quat     = bodyQuat * Quaternion.AngleAxis(-handSwingAngle[0], Vector3.up);
                }

                TweenThing handLeft = TweenThing.HandLeft;
                this.DrawTweenedHand(position, handMeshLeft, matLeft, quat, handLeft, portrait, noTween);
                //GenDraw.DrawMeshNowOrLater(
                //                           handMeshLeft, position,
                //                           quat,
                //                           matLeft,
                //                           portrait);
            }

            if (drawRight)
            {
                Quaternion quat;
                Vector3    position;
                bool       noTween = false;
                if (this.CompAnimator.FirstHandPosition != Vector3.zero)
                {
                    quat     = this.CompAnimator.WeaponQuat;
                    position = this.CompAnimator.FirstHandPosition;
                    noTween  = true;
                }
                else
                {
                    shoulperPos.RightJoint = bodyQuat * shoulperPos.RightJoint;
                    rightHand =
                        bodyQuat * rightHand.RotatedBy(handSwingAngle[1] - shoulderAngle[1]);

                    position = drawPos + shoulperPos.RightJoint + rightHand;
                    quat     = bodyQuat * Quaternion.AngleAxis(handSwingAngle[1], Vector3.up);
                }

                TweenThing handRight = TweenThing.HandRight;
                this.DrawTweenedHand(position, handMeshRight, matRight, quat, handRight, portrait, noTween);
                // GenDraw.DrawMeshNowOrLater(
                //                            handMeshRight, position,
                //                            quat,
                //                            matRight,
                //                            portrait);
            }

            if (MainTabWindow_BaseAnimator.Develop)
            {
                // for debug
                Material centerMat = GraphicDatabase.Get <Graphic_Single>(
                    "Hands/Human_Hand_dev",
                    ShaderDatabase.CutoutSkin,
                    Vector2.one,
                    Color.white).MatSingle;

                GenDraw.DrawMeshNowOrLater(
                    handMeshLeft,
                    drawPos + shoulperPos.LeftJoint + new Vector3(0, -0.301f, 0),
                    bodyQuat * Quaternion.AngleAxis(-shoulderAngle[0], Vector3.up),
                    centerMat,
                    portrait);

                GenDraw.DrawMeshNowOrLater(
                    handMeshRight,
                    drawPos + shoulperPos.RightJoint + new Vector3(0, 0.301f, 0),
                    bodyQuat * Quaternion.AngleAxis(-shoulderAngle[1], Vector3.up),
                    centerMat,
                    portrait);
            }
        }
Example #3
0
        public override void DrawFeet(Quaternion bodyQuat, Quaternion footQuat, Vector3 rootLoc, bool portrait)
        {
            if (this.Pawn.Dead || this.Pawn.Downed)
            {
                return;
            }
            /// No feet while sitting at a table
            Job curJob = this.Pawn.CurJob;

            if (curJob != null)
            {
                if (curJob.def == JobDefOf.Ingest && !this.Pawn.Rotation.IsHorizontal)
                {
                    if (curJob.targetB.IsValid)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            Rot4    rotty  = new Rot4(i);
                            IntVec3 intVec = this.Pawn.Position + rotty.FacingCell;
                            if (intVec == curJob.targetB)
                            {
                                return;
                            }
                        }
                    }
                }
            }

            if (portrait && !HarmonyPatchesFS.AnimatorIsOpen())
            {
                return;
            }

            Quaternion drawQuat = this.CompAnimator.IsMoving ? footQuat : bodyQuat;

            Rot4 rot = this.BodyFacing;

            // Basic values
            BodyAnimDef body = this.CompAnimator.BodyAnim;

            if (body == null)
            {
                return;
            }

            JointLister groundPos = this.GetJointPositions(JointType.Hip,
                                                           body.hipOffsets[rot.AsInt],
                                                           body.hipOffsets[Rot4.North.AsInt].x);

            Vector3      rightFootCycle = Vector3.zero;
            Vector3      leftFootCycle  = Vector3.zero;
            float        footAngleRight = 0;
            float        footAngleLeft  = 0;
            float        offsetJoint    = 0;
            WalkCycleDef cycle          = this.CompAnimator.WalkCycle;

            if (cycle != null)
            {
                offsetJoint = cycle.HipOffsetHorizontalX.Evaluate(this.CompAnimator.MovedPercent);

                this.DoWalkCycleOffsets(
                    ref rightFootCycle,
                    ref leftFootCycle,
                    ref footAngleRight,
                    ref footAngleLeft,
                    ref offsetJoint,
                    cycle.FootPositionX,
                    cycle.FootPositionZ,
                    cycle.FootAngle);
            }

            this.GetBipedMesh(out Mesh footMeshRight, out Mesh footMeshLeft);

            Material matRight;
            Material matLeft;

            if (MainTabWindow_BaseAnimator.Colored)
            {
                matRight = this.CompAnimator.PawnBodyGraphic?.FootGraphicRightCol?.MatAt(rot);
                matLeft  = this.CompAnimator.PawnBodyGraphic?.FootGraphicLeftCol?.MatAt(rot);
            }
            else
            {
                Material rightFoot   = this.CompAnimator.PawnBodyGraphic?.FootGraphicRight?.MatAt(rot);
                Material leftFoot    = this.CompAnimator.PawnBodyGraphic?.FootGraphicLeft?.MatAt(rot);
                Material leftShadow  = this.CompAnimator.PawnBodyGraphic?.FootGraphicLeftShadow?.MatAt(rot);
                Material rightShadow = this.CompAnimator.PawnBodyGraphic?.FootGraphicRightShadow?.MatAt(rot);

                switch (rot.AsInt)
                {
                default:
                    matRight = this.Flasher.GetDamagedMat(rightFoot);
                    matLeft  = this.Flasher.GetDamagedMat(leftFoot);
                    break;

                case 1:
                    matRight = this.Flasher.GetDamagedMat(rightFoot);

                    matLeft = this.Flasher.GetDamagedMat(leftShadow);
                    break;

                case 3:

                    matRight = this.Flasher.GetDamagedMat(rightShadow);
                    matLeft  = this.Flasher.GetDamagedMat(leftFoot);
                    break;
                }
            }

            bool drawRight = matRight != null && this.CompAnimator.BodyStat.FootRight != PartStatus.Missing;

            bool drawLeft = matLeft != null && this.CompAnimator.BodyStat.FootLeft != PartStatus.Missing;

            groundPos.LeftJoint  = drawQuat * groundPos.LeftJoint;
            groundPos.RightJoint = drawQuat * groundPos.RightJoint;
            leftFootCycle        = drawQuat * leftFootCycle;
            rightFootCycle       = drawQuat * rightFootCycle;
            Vector3 ground = rootLoc + drawQuat * new Vector3(0, 0, OffsetGroundZ);

            if (drawLeft)
            {
                // TweenThing leftFoot = TweenThing.FootLeft;
                // PawnPartsTweener tweener = this.CompAnimator.PartTweener;
                // if (tweener != null)
                {
                    Vector3 position = ground + groundPos.LeftJoint + leftFootCycle;

                    // tweener.PartPositions[(int)leftFoot] = position;
                    // tweener.PreThingPosCalculation(leftFoot, spring: SpringTightness.Stff);

                    GenDraw.DrawMeshNowOrLater(
                        footMeshLeft,
                        position,                        // tweener.TweenedPartsPos[(int)leftFoot],
                        drawQuat * Quaternion.AngleAxis(footAngleLeft, Vector3.up),
                        matLeft,
                        portrait);
                }
            }

            if (drawRight)
            {
                // TweenThing rightFoot = TweenThing.FootRight;
                // PawnPartsTweener tweener = this.CompAnimator.PartTweener;
                // if (tweener != null)
                // {
                Vector3 position = ground + groundPos.RightJoint + rightFootCycle;

                // tweener.PartPositions[(int)rightFoot] = position;
                //     tweener.PreThingPosCalculation(rightFoot, spring: SpringTightness.Stff);
                GenDraw.DrawMeshNowOrLater(
                    footMeshRight,
                    position,                        // tweener.TweenedPartsPos[(int)rightFoot],
                    drawQuat * Quaternion.AngleAxis(footAngleRight, Vector3.up),
                    matRight,
                    portrait);

                // }
            }

            if (MainTabWindow_BaseAnimator.Develop)
            {
                // for debug
                Material centerMat = GraphicDatabase
                                     .Get <Graphic_Single>("Hands/Ground", ShaderDatabase.Transparent, Vector2.one,
                                                           Color.red).MatSingle;

                GenDraw.DrawMeshNowOrLater(
                    footMeshLeft,
                    ground + groundPos.LeftJoint +
                    new Vector3(offsetJoint, -0.301f, 0),
                    drawQuat * Quaternion.AngleAxis(0, Vector3.up),
                    centerMat,
                    portrait);

                GenDraw.DrawMeshNowOrLater(
                    footMeshRight,
                    ground + groundPos.RightJoint +
                    new Vector3(offsetJoint, 0.301f, 0),
                    drawQuat * Quaternion.AngleAxis(0, Vector3.up),
                    centerMat,
                    portrait);

                Material hipMat = GraphicDatabase
                                  .Get <Graphic_Single>("Hands/Human_Hand_dev", ShaderDatabase.Transparent, Vector2.one,
                                                        Color.blue).MatSingle;

                GenDraw.DrawMeshNowOrLater(
                    footMeshLeft,
                    groundPos.LeftJoint +
                    new Vector3(offsetJoint, -0.301f, 0),
                    drawQuat * Quaternion.AngleAxis(0, Vector3.up),
                    centerMat,
                    portrait);

                // UnityEngine.Graphics.DrawMesh(handsMesh, center + new Vector3(0, 0.301f, z),
                // Quaternion.AngleAxis(0, Vector3.up), centerMat, 0);
                // UnityEngine.Graphics.DrawMesh(handsMesh, center + new Vector3(0, 0.301f, z2),
                // Quaternion.AngleAxis(0, Vector3.up), centerMat, 0);
            }
        }
Example #4
0
        protected JointLister GetJointPositions(JointType jointType, Vector3 offsets,
                                                float jointWidth,
                                                bool carrying = false, bool armed = false)
        {
            Rot4        rot    = this.BodyFacing;
            JointLister joints = new JointLister
            {
                jointType = jointType
            };
            float leftX  = offsets.x;
            float rightX = offsets.x;
            float leftZ  = offsets.z;
            float rightZ = offsets.z;

            float offsetY = Offsets.YOffset_HandsFeetOver;
            float leftY   = offsetY;

            bool offsetsCarrying = false;

            switch (jointType)
            {
            case JointType.Shoulder:
                offsetY = armed ? -Offsets.YOffset_HandsFeet : Offsets.YOffset_HandsFeetOver;
                leftY   = this.CompAnimator.IsMoving ? Offsets.YOffset_HandsFeetOver : offsetY;
                if (carrying)
                {
                    offsetsCarrying = true;
                }
                break;
            }

            float rightY = offsetY;

            if (offsetsCarrying)
            {
                leftX  = -jointWidth / 2;
                rightX = jointWidth / 2;
                leftZ  = -0.025f;
                rightZ = -leftZ;
            }
            else if (rot.IsHorizontal)
            {
                float offsetX = jointWidth * 0.1f;
                float offsetZ = jointWidth * 0.2f;

                if (rot == Rot4.East)
                {
                    leftY  = -Offsets.YOffset_Behind;
                    leftZ += +offsetZ;
                }
                else
                {
                    rightY  = -Offsets.YOffset_Behind;
                    rightZ += offsetZ;
                }

                leftX  += offsetX;
                rightX -= offsetX;
            }
            else
            {
                leftX = -rightX;
            }

            if (rot == Rot4.North)
            {
                leftY = rightY = -Offsets.YOffset_Behind;
                // leftX *= -1;
                // rightX *= -1;
            }

            joints.RightJoint = new Vector3(rightX, rightY, rightZ);
            joints.LeftJoint  = new Vector3(leftX, leftY, leftZ);

            return(joints);
        }
        protected virtual void DrawFrontPaws(Quaternion bodyQuat, Quaternion footQuat, Vector3 rootLoc, bool portrait)
        {
            if (!this.CompAnimator.Props.quadruped)
            {
                return;
            }


            // Basic values
            BodyAnimDef body = this.CompAnimator.BodyAnim;

            Rot4 rot = this.BodyFacing;

            if (body == null)
            {
                return;
            }

            JointLister jointPositions = this.GetJointPositions(JointType.Shoulder,
                                                                body.shoulderOffsets[rot.AsInt],
                                                                body.shoulderOffsets[Rot4.North.AsInt].x);

            Vector3 rightFootAnim  = Vector3.zero;
            Vector3 leftFootAnim   = Vector3.zero;
            float   footAngleRight = 0f;

            float footAngleLeft = 0f;
            float offsetJoint   = 0;

            WalkCycleDef cycle = this.CompAnimator.WalkCycle;

            if (cycle != null)
            {
                offsetJoint = cycle.ShoulderOffsetHorizontalX.Evaluate(this.CompAnimator.MovedPercent);

                // Center = drawpos of carryThing
                this.DoWalkCycleOffsets(
                    ref rightFootAnim,
                    ref leftFootAnim,
                    ref footAngleRight,
                    ref footAngleLeft,
                    ref offsetJoint,
                    cycle.FrontPawPositionX,
                    cycle.FrontPawPositionZ,
                    cycle.FrontPawAngle);
            }

            this.GetBipedMesh(out Mesh footMeshRight, out Mesh footMeshLeft);

            Material matLeft;

            Material matRight;

            if (MainTabWindow_BaseAnimator.Colored)
            {
                matRight = this.CompAnimator.PawnBodyGraphic?.FrontPawGraphicRightCol?.MatAt(rot);
                matLeft  = this.CompAnimator.PawnBodyGraphic?.FrontPawGraphicLeftCol?.MatAt(rot);
            }
            else
            {
                switch (rot.AsInt)
                {
                default:
                    matRight = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic?.FrontPawGraphicRight
                                                          ?.MatAt(rot));
                    matLeft = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic?.FrontPawGraphicLeft
                                                         ?.MatAt(rot));
                    break;

                case 1:
                    matRight = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic?.FrontPawGraphicRight
                                                          ?.MatAt(rot));
                    matLeft = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic
                                                         ?.FrontPawGraphicLeftShadow?.MatAt(rot));
                    break;

                case 3:
                    matRight = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic
                                                          ?.FrontPawGraphicRightShadow?.MatAt(rot));
                    matLeft = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic?.FrontPawGraphicLeft
                                                         ?.MatAt(rot));
                    break;
                }
            }


            Quaternion drawQuat = this.CompAnimator.IsMoving ? footQuat : bodyQuat;
            Vector3    ground   = rootLoc + drawQuat * new Vector3(0, 0, OffsetGroundZ);

            if (matLeft != null)
            {
                if (this.CompAnimator.BodyStat.FootLeft != PartStatus.Missing)
                {
                    GenDraw.DrawMeshNowOrLater(
                        footMeshLeft,
                        ground + jointPositions.LeftJoint + leftFootAnim,
                        drawQuat * Quaternion.AngleAxis(footAngleLeft, Vector3.up),
                        matLeft,
                        portrait);
                }
            }

            if (matRight != null)
            {
                if (this.CompAnimator.BodyStat.FootRight != PartStatus.Missing)
                {
                    GenDraw.DrawMeshNowOrLater(
                        footMeshRight,
                        ground + jointPositions.RightJoint +
                        rightFootAnim,
                        drawQuat * Quaternion.AngleAxis(footAngleRight, Vector3.up),
                        matRight,
                        portrait);
                }
            }

            if (MainTabWindow_BaseAnimator.Develop)
            {
                // for debug
                Material centerMat = GraphicDatabase
                                     .Get <Graphic_Single>("Hands/Ground", ShaderDatabase.Transparent, Vector2.one,
                                                           Color.cyan).MatSingle;

                GenDraw.DrawMeshNowOrLater(
                    footMeshLeft,
                    ground + jointPositions.LeftJoint +
                    new Vector3(offsetJoint, 0.301f, 0),
                    drawQuat * Quaternion.AngleAxis(0, Vector3.up),
                    centerMat,
                    portrait);

                GenDraw.DrawMeshNowOrLater(
                    footMeshRight,
                    ground + jointPositions.RightJoint +
                    new Vector3(offsetJoint, 0.301f, 0),
                    drawQuat * Quaternion.AngleAxis(0, Vector3.up),
                    centerMat,
                    portrait);

                // UnityEngine.Graphics.DrawMesh(handsMesh, center + new Vector3(0, 0.301f, z),
                // Quaternion.AngleAxis(0, Vector3.up), centerMat, 0);
                // UnityEngine.Graphics.DrawMesh(handsMesh, center + new Vector3(0, 0.301f, z2),
                // Quaternion.AngleAxis(0, Vector3.up), centerMat, 0);
            }
        }
Example #6
0
        public override void DrawFeet(Vector3 rootLoc, bool portrait)
        {
            if (portrait && !this.CompAnimator.AnimatorOpen)
            {
                return;
            }

            int   legsCount = 4;
            float legSpan   = 1f;


            Vector3 ground = rootLoc;

            ground.z += OffsetGround;

            Rot4 rot = this.BodyFacing;

            // Basic values
            BodyAnimDef body      = this.CompAnimator.BodyAnim;
            JointLister groundPos = this.GetJointPositions(
                body.hipOffsets[rot.AsInt],
                body.hipOffsets[Rot4.North.AsInt].x);

            WalkCycleDef cycle          = this.CompAnimator.WalkCycle;
            Vector3      rightFootAnim  = Vector3.zero;
            Vector3      leftFootAnim   = Vector3.zero;
            float        footAngleRight = 0;
            float        footAngleLeft  = 0;
            float        offsetJoint    = 0;

            if (cycle != null)
            {
                offsetJoint = cycle.HipOffsetHorizontalX.Evaluate(this.MovedPercent);

                this.DoWalkCycleOffsets(
                    ref rightFootAnim,
                    ref leftFootAnim,
                    ref footAngleRight,
                    ref footAngleLeft,
                    ref offsetJoint,
                    cycle.FootPositionX,
                    cycle.FootPositionZ,
                    cycle.FootAngle);
            }
            this.GetMeshesFoot(out Mesh footMeshRight, out Mesh footMeshLeft);

            float bodyAngle = 0f;

            Pawn pawn = this.Pawn;

            if (pawn.Downed || pawn.Dead)
            {
                bodyAngle = pawn.Drawer.renderer.wiggler.downedAngle;
            }

            Material matRight;

            Material matLeft;

            if (!MainTabWindow_Animator.Colored)
            {
                switch (rot.AsInt)
                {
                default:
                    matRight = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic?.FootGraphicRight
                                                          ?.MatAt(rot));
                    matLeft = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic?.FootGraphicLeft
                                                         ?.MatAt(rot));
                    break;

                case 1:
                    matRight = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic?.FootGraphicRight
                                                          ?.MatAt(rot));
                    matLeft = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic
                                                         ?.FootGraphicLeftShadow
                                                         ?.MatAt(rot));
                    break;

                case 3:
                    matRight = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic
                                                          ?.FootGraphicRightShadow
                                                          ?.MatAt(rot));
                    matLeft = this.Flasher.GetDamagedMat(this.CompAnimator.PawnBodyGraphic?.FootGraphicLeft
                                                         ?.MatAt(rot));
                    break;
                }
            }
            else
            {
                matRight = this.CompAnimator.PawnBodyGraphic?.FootGraphicRightCol?.MatAt(rot);
                matLeft  = this.CompAnimator.PawnBodyGraphic?.FootGraphicLeftCol?.MatAt(rot);
            }

            bool drawRight = matRight != null && this.CompAnimator.BodyStat.FootRight != PartStatus.Missing;

            bool drawLeft = matLeft != null && this.CompAnimator.BodyStat.FootLeft != PartStatus.Missing;

            if (drawLeft)
            {
                GenDraw.DrawMeshNowOrLater(
                    footMeshLeft,
                    (ground + groundPos.LeftJoint + leftFootAnim)
                    .RotatedBy(bodyAngle),
                    Quaternion.AngleAxis(bodyAngle + footAngleLeft, Vector3.up),
                    matLeft,
                    portrait);
            }

            if (drawRight)
            {
                GenDraw.DrawMeshNowOrLater(
                    footMeshRight,
                    (ground + groundPos.RightJoint + rightFootAnim)
                    .RotatedBy(bodyAngle),
                    Quaternion.AngleAxis(bodyAngle + footAngleRight, Vector3.up),
                    matRight,
                    portrait);
            }

            if (MainTabWindow_Animator.Develop)
            {
                // for debug
                Material centerMat = GraphicDatabase
                                     .Get <Graphic_Single>("Hands/Ground", ShaderDatabase.Transparent, Vector2.one,
                                                           Color.red).MatSingle;

                GenDraw.DrawMeshNowOrLater(
                    footMeshLeft,
                    ground.RotatedBy(bodyAngle) + groundPos.LeftJoint +
                    new Vector3(offsetJoint, -0.301f, 0),
                    Quaternion.AngleAxis(0, Vector3.up),
                    centerMat,
                    portrait);

                GenDraw.DrawMeshNowOrLater(
                    footMeshRight,
                    ground.RotatedBy(bodyAngle) + groundPos.RightJoint +
                    new Vector3(offsetJoint, 0.301f, 0),
                    Quaternion.AngleAxis(0, Vector3.up),
                    centerMat,
                    portrait);

                // UnityEngine.Graphics.DrawMesh(handsMesh, center + new Vector3(0, 0.301f, z),
                // Quaternion.AngleAxis(0, Vector3.up), centerMat, 0);
                // UnityEngine.Graphics.DrawMesh(handsMesh, center + new Vector3(0, 0.301f, z2),
                // Quaternion.AngleAxis(0, Vector3.up), centerMat, 0);
            }
        }