private static bool LateUpdatePrefix(FullBodyBipedIK __instance) { IKTweaksMod.ProcessIKLateUpdateQueue(); if (IkTweaksSettings.FullBodyVrIk && LastCalibrationWasInCustomIk && LastInitializedController.field_Private_FullBodyBipedIK_0 == __instance) { Update(); if (LastInitializedVRIK != null) { LastInitializedVRIK.LateUpdate_ManualDrive(); } return(false); } return(true); }
private static async Task CalibrateCore(GameObject avatarRoot) { var avatarId = avatarRoot.GetComponent <PipelineManager>().blueprintId; if (IkTweaksSettings.CalibrateStorePerAvatar && HasSavedCalibration(avatarId)) { await ApplyStoredCalibration(avatarRoot, avatarId); return; } await ManualCalibrateCoro(avatarRoot); await IKTweaksMod.AwaitVeryLateUpdate(); if (!avatarRoot) { return; } await ApplyStoredCalibration(avatarRoot, avatarId); }
private static async Task ManualCalibrateCoro(GameObject avatarRoot) { var animator = avatarRoot.GetComponent <Animator>(); var hips = animator.GetBoneTransform(HumanBodyBones.Hips); var head = animator.GetBoneTransform(HumanBodyBones.Head); var avatarId = avatarRoot.GetComponent <PipelineManager>().blueprintId; var avatarRootTransform = avatarRoot.transform; var nativeMuscles = (Il2CppStructArray <float>)TPoseMuscles; var dummyMuscles = new Il2CppStructArray <float>(nativeMuscles.Count); var poseHandler = new HumanPoseHandler(animator.avatar, animator.transform); var forwardDirection = avatarRootTransform.parent; var hipsRelativeToForwardDirection = Quaternion.Inverse(forwardDirection.rotation) * hips.rotation; MelonDebug.Msg($"Calibrating for avatar ID {avatarId}"); var oldHipPos = hips.position; var oldHipRot = hips.rotation; await IKTweaksMod.AwaitVeryLateUpdate(); if (!avatarRoot) { MelonDebug.Msg("Avatar root was destroyed, cancelling calibration"); return; } var headTarget = FullBodyHandling.LastInitializedController.field_Private_FBBIKHeadEffector_0.transform; var headsetTracker = headTarget.parent; SetTrackerVisibility(true); var preClickHeadPos = Vector3.zero; var preClickHeadRot = Quaternion.identity; var mirrorCloneRoot = forwardDirection.Find("_AvatarMirrorClone"); HumanPoseHandler mirrorClonePoseHandler = null; Transform mirrorHips = null; if (mirrorCloneRoot != null) { mirrorClonePoseHandler = new HumanPoseHandler(animator.avatar, mirrorCloneRoot); var mirrorCloneAnimator = mirrorCloneRoot.GetComponent <Animator>(); if (mirrorCloneAnimator != null) { mirrorHips = mirrorCloneAnimator.GetBoneTransform(HumanBodyBones.Hips); } } var willUniversallyCalibrate = false; while (true) { await IKTweaksMod.AwaitIKLateUpdate(); if (avatarRoot == null) { break; } poseHandler.GetHumanPose(out var humanBodyPose, out var humanBodyRot, dummyMuscles); poseHandler.SetHumanPose(ref humanBodyPose, ref humanBodyRot, nativeMuscles); mirrorClonePoseHandler?.SetHumanPose(ref humanBodyPose, ref humanBodyRot, nativeMuscles); var trigger1 = Input.GetAxisRaw("Oculus_CrossPlatform_PrimaryIndexTrigger"); var trigger2 = Input.GetAxisRaw("Oculus_CrossPlatform_SecondaryIndexTrigger"); if (IkTweaksSettings.CalibrateUseUniversal && UniversalData.Count >= 4) { MoveTrackersToStoredPositions(); willUniversallyCalibrate = true; } if (IkTweaksSettings.CalibrateHalfFreeze && trigger1 + trigger2 > 0.75f) { hips.position = oldHipPos; hips.rotation = oldHipRot; if (mirrorHips != null) { mirrorHips.position = oldHipPos; mirrorHips.rotation = oldHipRot; } } else if (IkTweaksSettings.CalibrateFollowHead || willUniversallyCalibrate) { hips.rotation = forwardDirection.rotation * hipsRelativeToForwardDirection; var delta = headTarget.position - head.position; hips.position += delta; if (mirrorHips != null) { mirrorHips.position = hips.position; } oldHipPos = hips.position; oldHipRot = hips.rotation; preClickHeadPos = headsetTracker.position; preClickHeadRot = headsetTracker.rotation; } else { // legacy calibration hips.position = oldHipPos; hips.rotation = oldHipRot; if (mirrorHips != null) { mirrorHips.position = oldHipPos; mirrorHips.rotation = oldHipRot; } preClickHeadPos = headsetTracker.position; preClickHeadRot = headsetTracker.rotation; } if (trigger1 + trigger2 > 1.75f || willUniversallyCalibrate) { break; } } SetTrackerVisibility(false); if (avatarRoot == null) { return; } var steamVrControllerManager = GetControllerManager(); var possibleTrackers = new List <Transform>(steamVrControllerManager.field_Public_ArrayOf_GameObject_0 .Where(it => it != steamVrControllerManager.field_Public_GameObject_1 && it != steamVrControllerManager.field_Public_GameObject_0 && it != null) .Select(it => it.transform)); (Transform Tracker, Transform Bone)? GetTracker(HumanBodyBones bone, HumanBodyBones fallback = HumanBodyBones.Hips) { var boneTransform = animator.GetBoneTransform(bone) ?? animator.GetBoneTransform(fallback); var bonePosition = boneTransform.position; var bestTracker = -1; var bestDistance = float.PositiveInfinity; for (var index = 0; index < possibleTrackers.Count; index++) { var possibleTracker = possibleTrackers[index]; var steamVRTrackedObject = possibleTracker.GetComponent <SteamVR_TrackedObject>(); if (steamVRTrackedObject.field_Public_EnumNPublicSealedvaNoHmDe18DeDeDeDeDeUnique_0 == SteamVR_TrackedObject.EnumNPublicSealedvaNoHmDe18DeDeDeDeDeUnique.None) { continue; } var distance = Vector3.Distance(possibleTracker.position, bonePosition); if (distance < bestDistance) { bestDistance = distance; bestTracker = index; } } if (bestTracker == -1) { MelonLogger.Log($"Null target for bone {bone}"); return(null); } var result = possibleTrackers[bestTracker] !; possibleTrackers.RemoveAt(bestTracker); return(result, boneTransform); } void StoreData(CalibrationPoint point, (Transform tracker, Transform bone)?pair) { if (pair == null) { return; } var tracker = pair.Value.tracker; var bone = pair.Value.bone; var serial = GetTrackerSerial((int)tracker.GetComponent <SteamVR_TrackedObject>().field_Public_EnumNPublicSealedvaNoHmDe18DeDeDeDeDeUnique_0); var trackerRelativeData = new CalibrationData(GetLocalPosition(tracker, bone), GetLocalRotation(tracker, bone), serial); Save(avatarId, point, trackerRelativeData); if (!willUniversallyCalibrate) { var avatarSpaceData = new CalibrationData(GetLocalPosition(tracker.parent, tracker), GetLocalRotation(tracker.parent, tracker), serial); UniversalData[point] = avatarSpaceData; } } void StoreHand(Vector3 angles, HumanBodyBones handBone, CalibrationPoint point) { var handRotation = animator.GetBoneTransform(handBone).rotation; var bodyRotation = animator.transform.rotation; var storedData = new CalibrationData(Vector3.zero, Quaternion.Euler(angles) * Quaternion.Inverse(bodyRotation) * handRotation, point.ToString()); Save(avatarId, point, storedData); } void StoreBendGoal(CalibrationPoint point, (Transform tracker, Transform bone)?pair, Vector3 offset, ref float weight) { weight = 0f; if (pair == null) { return; } var tracker = pair.Value.tracker; var bone = pair.Value.bone; var serial = GetTrackerSerial((int)tracker.GetComponent <SteamVR_TrackedObject>().field_Public_EnumNPublicSealedvaNoHmDe18DeDeDeDeDeUnique_0); var trackerRelativeData = new CalibrationData(tracker.InverseTransformPoint(bone.position + offset), Quaternion.identity, serial); Save(avatarId, point, trackerRelativeData); if (!willUniversallyCalibrate) { var avatarSpaceData = new CalibrationData(GetLocalPosition(tracker.parent, tracker), GetLocalRotation(tracker.parent, tracker), serial); UniversalData[point] = avatarSpaceData; } weight = 1f; } var hipsTracker = GetTracker(HumanBodyBones.Hips); var leftFootTracker = GetTracker(IkTweaksSettings.MapToes ? HumanBodyBones.LeftToes : HumanBodyBones.LeftFoot, HumanBodyBones.LeftFoot); var rightFootTracker = GetTracker(IkTweaksSettings.MapToes ? HumanBodyBones.RightToes : HumanBodyBones.RightFoot, HumanBodyBones.RightFoot); StoreData(CalibrationPoint.Hip, hipsTracker); StoreData(CalibrationPoint.LeftFoot, leftFootTracker); StoreData(CalibrationPoint.RightFoot, rightFootTracker); var leftLowerLegPosition = animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg).position; var rightLowerLegPosition = animator.GetBoneTransform(HumanBodyBones.RightLowerLeg).position; var avatarForward = Vector3.Cross(rightLowerLegPosition - leftLowerLegPosition, Vector3.up).normalized; if (IkTweaksSettings.UseElbowTrackers) { var leftElbowTracker = GetTracker(HumanBodyBones.LeftLowerArm); var rightElbowTracker = GetTracker(HumanBodyBones.RightLowerArm); StoreBendGoal(CalibrationPoint.LeftElbow, leftElbowTracker, avatarForward * -0.1f, ref FullBodyHandling.LeftElbowWeight); StoreBendGoal(CalibrationPoint.RightElbow, rightElbowTracker, avatarForward * -0.1f, ref FullBodyHandling.RightElbowWeight); } if (IkTweaksSettings.UseKneeTrackers) { var leftKneeTracker = GetTracker(HumanBodyBones.LeftLowerLeg); var rightKneeTracker = GetTracker(HumanBodyBones.RightLowerLeg); StoreBendGoal(CalibrationPoint.LeftKnee, leftKneeTracker, avatarForward * 0.1f, ref FullBodyHandling.LeftKneeWeight); StoreBendGoal(CalibrationPoint.RightKnee, rightKneeTracker, avatarForward * 0.1f, ref FullBodyHandling.RightKneeWeight); } if (IkTweaksSettings.UseChestTracker) { var chestTracker = GetTracker(HumanBodyBones.UpperChest, HumanBodyBones.Chest); StoreBendGoal(CalibrationPoint.Chest, chestTracker, avatarForward * .5f, ref FullBodyHandling.ChestWeight); } StoreHand(new Vector3(15, 90 + 10, 0), HumanBodyBones.LeftHand, CalibrationPoint.LeftHand); StoreHand(new Vector3(15, -90 - 10, 0), HumanBodyBones.RightHand, CalibrationPoint.RightHand); if (!willUniversallyCalibrate) { var trackerParent = hipsTracker.Value.Tracker.parent; UniversalData[CalibrationPoint.Head] = new CalibrationData( GetLocalPosition(trackerParent, preClickHeadPos), GetLocalRotation(trackerParent, preClickHeadRot), "HEAD"); } }