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); } }
private void DrawTweenedHand(Vector3 position, Mesh handsMesh, Material material, Quaternion quat, TweenThing tweenThing, bool portrait, bool noTween) { if (position == Vector3.zero || handsMesh == null || material == null || quat == null || tweenThing == null) { return; } if (!this.Pawn.Downed || !this.Pawn.Dead) { if (!HarmonyPatchesFS.AnimatorIsOpen() && Find.TickManager.TicksGame == this.CompAnimator.LastPosUpdate[(int)tweenThing] || HarmonyPatchesFS.AnimatorIsOpen() && MainTabWindow_BaseAnimator.Pawn != this.Pawn) { position = this.CompAnimator.LastPosition[(int)tweenThing]; } else { if (this.Pawn.pather.MovedRecently(5)) { noTween = true; } this.CompAnimator.LastPosUpdate[(int)tweenThing] = Find.TickManager.TicksGame; Vector3Tween tween = this.CompAnimator.Vector3Tweens[(int)tweenThing]; switch (tween.State) { case TweenState.Running: if (noTween || this.CompAnimator.IsMoving) { tween.Stop(StopBehavior.ForceComplete); } position = tween.CurrentValue; break; case TweenState.Paused: break; case TweenState.Stopped: if (noTween || (this.CompAnimator.IsMoving)) { break; } ScaleFunc scaleFunc = ScaleFuncs.SineEaseOut; Vector3 start = this.CompAnimator.LastPosition[(int)tweenThing]; float distance = Vector3.Distance(start, position); float duration = Mathf.Abs(distance * 50f); if (start != Vector3.zero && duration > 12f) { start.y = position.y; tween.Start(start, position, duration, scaleFunc); position = start; } break; } this.CompAnimator.LastPosition[(int)tweenThing] = position; } } // tweener.PreThingPosCalculation(tweenThing, noTween); GenDraw.DrawMeshNowOrLater( handsMesh, position, quat, material, portrait); }