public override void OnApplicationStart() { IkTweaksSettings.RegisterSettings(); BundleHolder.Init(); ClassInjector.RegisterTypeInIl2Cpp <VRIK_New>(); ClassInjector.RegisterTypeInIl2Cpp <TwistRelaxer_New>(); VrIkHandling.HookVrIkInit(harmonyInstance); FullBodyHandling.HookFullBodyController(harmonyInstance); Camera.onPreRender = Delegate.Combine(Camera.onPreRender, (Camera.CameraCallback)OnVeryLateUpdate).Cast <Camera.CameraCallback>(); if (MelonHandler.Mods.Any(it => it.Info.Name == "UI Expansion Kit" && !it.Info.Version.StartsWith("0.1."))) { AddUixActions(); } }
private static async Task ApplyStoredCalibration(GameObject avatarRoot, string avatarId) { // await IKTweaksMod.AwaitLateUpdate(); var dummyMuscles = new Il2CppStructArray <float>(HumanTrait.MuscleCount); // Enforce mostly-bike-pose for IK setup - otherwise animations can break knee bend angles and the like // Some avatars apparently have inverted knees in T-pose, so bike pose is preferred here var animator = avatarRoot.GetComponent <Animator>(); var poseHandler = new HumanPoseHandler(animator.avatar, avatarRoot.transform); poseHandler.GetHumanPose(out var position, out var rotation, dummyMuscles); rotation = Quaternion.identity; for (var i = 0; i < FullBodyHandling.ourBoneResetMasks.Length; i++) { if (FullBodyHandling.ourBoneResetMasks[i] != FullBodyHandling.BoneResetMask.Never) { dummyMuscles[i] = 0; } } poseHandler.SetHumanPose(ref position, ref rotation, dummyMuscles); FullBodyHandling.PreSetupVrIk(avatarRoot); var vrik = FullBodyHandling.SetupVrIk(FullBodyHandling.LastInitializedController, avatarRoot); foreach (var target in ourTargets) { Object.DestroyImmediate(target); } var steamVrControllerManager = GetControllerManager(); var newTargets = new List <GameObject>(); var datas = SavedAvatars[avatarId]; Transform?GetTarget(CalibrationPoint point) { if (!datas.TryGetValue(point, out var data)) { return(null); } var bestTracker = FindTracker(data.TrackerSerial, steamVrControllerManager); if (bestTracker == null) { MelonLogger.Log($"Null target for tracker {data.TrackerSerial}"); return(null); } MelonLogger.Log($"Found tracker with serial {data.TrackerSerial} for point {point}"); var result = bestTracker; var newTarget = new GameObject("CustomIkTarget-For-" + data.TrackerSerial + "-" + point); newTargets.Add(newTarget); var targetTransform = newTarget.transform; targetTransform.SetParent(result); targetTransform.localPosition = data.LocalPosition; targetTransform.localRotation = data.LocalRotation; return(targetTransform); } Transform MakeHandTarget(Quaternion localRotation, Transform parent) { var targetGo = new GameObject("CustomIkHandTarget"); var targetTransform = targetGo.transform; targetTransform.SetParent(parent, false); targetTransform.localRotation = localRotation; newTargets.Add(targetGo); return(targetTransform); } var hips = GetTarget(CalibrationPoint.Hip); var leftFoot = GetTarget(CalibrationPoint.LeftFoot); var rightFoot = GetTarget(CalibrationPoint.RightFoot); vrik.solver.leftArm.target = MakeHandTarget(datas[CalibrationPoint.LeftHand].LocalRotation, FullBodyHandling.LastInitializedController.field_Private_FullBodyBipedIK_0.solver.leftHandEffector.target); vrik.solver.rightArm.target = MakeHandTarget(datas[CalibrationPoint.RightHand].LocalRotation, FullBodyHandling.LastInitializedController.field_Private_FullBodyBipedIK_0.solver.rightHandEffector.target); vrik.solver.leftLeg.bendGoal = GetTarget(CalibrationPoint.LeftKnee); vrik.solver.rightLeg.bendGoal = GetTarget(CalibrationPoint.RightKnee); vrik.solver.leftArm.bendGoal = GetTarget(CalibrationPoint.LeftElbow); vrik.solver.rightArm.bendGoal = GetTarget(CalibrationPoint.RightElbow); vrik.solver.spine.chestGoal = GetTarget(CalibrationPoint.Chest); ourTargets = newTargets.ToArray(); vrik.solver.spine.pelvisTarget = hips; vrik.solver.leftLeg.target = leftFoot; vrik.solver.rightLeg.target = rightFoot; MelonLogger.Log("Applied stored calibration"); }