Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        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");
            }
        }