This commit is contained in:
NotAKidoS 2023-05-09 03:46:58 -05:00
parent 26441f8b1e
commit c7b16abd4f
27 changed files with 591 additions and 91 deletions

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk"/>

View file

@ -0,0 +1,15 @@
using HarmonyLib;
using UnityEngine;
using static ABI_RC.Core.CVRTools;
namespace NAK.CameraFixes.HarmonyPatches;
class CVRCamControllerPatches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(CVRCamController), nameof(CVRCamController.Start))]
static void Postfix_CVRCamController_Start(ref CVRCamController __instance)
{
SetGameObjectLayerRecursive(__instance.gameObject, LayerMask.NameToLayer("UI Internal"));
}
}

28
CameraFixes/Main.cs Normal file
View file

@ -0,0 +1,28 @@
using ABI_RC.Core.IO;
using MelonLoader;
using UnityEngine;
namespace NAK.CameraFixes;
public class CameraFixes : MelonMod
{
internal static MelonLogger.Instance Logger;
public override void OnInitializeMelon()
{
Logger = LoggerInstance;
ApplyPatches(typeof(HarmonyPatches.CVRCamControllerPatches));
}
void ApplyPatches(Type type)
{
try
{
HarmonyInstance.PatchAll(type);
}
catch (Exception e)
{
Logger.Msg($"Failed while patching {type.Name}!");
Logger.Error(e);
}
}
}

View file

@ -0,0 +1,30 @@
using CameraFixes.Properties;
using MelonLoader;
using System.Reflection;
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyTitle(nameof(NAK.CameraFixes))]
[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
[assembly: AssemblyProduct(nameof(NAK.CameraFixes))]
[assembly: MelonInfo(
typeof(NAK.CameraFixes.CameraFixes),
nameof(NAK.CameraFixes),
AssemblyInfoParams.Version,
AssemblyInfoParams.Author,
downloadLink: "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/tree/main/CameraFixes"
)]
[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
[assembly: HarmonyDontPatchAll]
namespace CameraFixes.Properties;
internal static class AssemblyInfoParams
{
public const string Version = "1.0.0";
public const string Author = "NotAKidoS";
}

23
CameraFixes/format.json Normal file
View file

@ -0,0 +1,23 @@
{
"_id": 129,
"name": "CameraFixes",
"modversion": "1.0.0",
"gameversion": "2022r170",
"loaderversion": "0.5.7",
"modtype": "Mod",
"author": "NotAKidoS",
"description": "Prevents VRIK from using toe bones in VR & optionaly FBT.\n\nVRIK calculates weird center of mass when toes are mapped, so it is sometimes desired to unmap toes to prevent an avatars feet from resting far back.\n\nPlease see the README for relevant imagery detailing the problem.",
"searchtags": [
"toes",
"vrik",
"ik",
"feet"
],
"requirements": [
"None"
],
"downloadlink": "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/releases/download/r3/CameraFixes.dll",
"sourcelink": "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/tree/main/CameraFixes/",
"changelog": "- Initial Release\n- No double patching. Bad. Stinky. Dont do it.",
"embedcolor": "#ffc700"
}

View file

@ -89,45 +89,45 @@ public class DesktopVRSwitcher : MonoBehaviour
yield break;
}
//one frame after switch attempt
public void FailedVRModeSwitch(bool isVR)
{
if (_softVRSwitch) return;
//let tracked objects know a switch failed
VRModeSwitchTracker.FailVRModeSwitch(isVR);
}
//one frame before switch attempt
public void PreVRModeSwitch(bool isVR)
public void PreVRModeSwitch(bool enableVR)
{
if (_softVRSwitch) return;
//let tracked objects know we are attempting to switch
VRModeSwitchTracker.PreVRModeSwitch(isVR);
VRModeSwitchTracker.PreVRModeSwitch(enableVR);
}
//one frame after switch attempt
public void PostVRModeSwitch(bool isVR)
public void FailedVRModeSwitch(bool enableVR)
{
if (_softVRSwitch) return;
//let tracked objects know a switch failed
VRModeSwitchTracker.FailVRModeSwitch(enableVR);
}
//one frame after switch attempt
public void PostVRModeSwitch(bool enableVR)
{
if (_softVRSwitch) return;
//close the menus
TryCatchHell.CloseCohtmlMenus();
//the base of VR checks
TryCatchHell.SetCheckVR(isVR);
TryCatchHell.SetMetaPort(isVR);
TryCatchHell.SetCheckVR(enableVR);
TryCatchHell.SetMetaPort(enableVR);
//game basics for functional gameplay post switch
TryCatchHell.RepositionCohtmlHud(isVR);
TryCatchHell.UpdateHudOperations(isVR);
TryCatchHell.RepositionCohtmlHud(enableVR);
TryCatchHell.UpdateHudOperations(enableVR);
TryCatchHell.DisableMirrorCanvas();
TryCatchHell.SwitchActiveCameraRigs(isVR);
TryCatchHell.SwitchActiveCameraRigs(enableVR);
TryCatchHell.ResetCVRInputManager();
TryCatchHell.UpdateRichPresence();
TryCatchHell.UpdateGestureReconizerCam();
TryCatchHell.UpdateMenuCoreData(isVR);
TryCatchHell.UpdateMenuCoreData(enableVR);
//let tracked objects know we switched
VRModeSwitchTracker.PostVRModeSwitch(isVR);
VRModeSwitchTracker.PostVRModeSwitch(enableVR);
//reload avatar by default, optional for debugging
if (_reloadLocalAvatar)

View file

@ -20,7 +20,7 @@ public class CVRPickupObjectTracker : MonoBehaviour
VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch;
}
public void PostVRModeSwitch(bool isVR, Camera activeCamera)
public void PostVRModeSwitch(bool enableVR, Camera activeCamera)
{
if (pickupObject != null)
{

View file

@ -6,6 +6,7 @@ namespace NAK.DesktopVRSwitch.Patches;
public class CameraFacingObjectTracker : MonoBehaviour
{
public CameraFacingObject cameraFacingObject;
void Start()
{
cameraFacingObject = GetComponent<CameraFacingObject>();
@ -17,7 +18,7 @@ public class CameraFacingObjectTracker : MonoBehaviour
VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch;
}
public void PostVRModeSwitch(bool isVR, Camera activeCamera)
public void PostVRModeSwitch(bool enableVR, Camera activeCamera)
{
cameraFacingObject.m_Camera = activeCamera;
}

View file

@ -1,7 +1,6 @@
using ABI_RC.Systems.IK;
using ABI_RC.Systems.IK.SubSystems;
using ABI_RC.Systems.IK.TrackingModules;
using HarmonyLib;
using System.Reflection;
using UnityEngine;
namespace NAK.DesktopVRSwitch.Patches;
@ -9,53 +8,80 @@ namespace NAK.DesktopVRSwitch.Patches;
public class IKSystemTracker : MonoBehaviour
{
public IKSystem ikSystem;
public Traverse _traverseModules;
void Start()
{
ikSystem = GetComponent<IKSystem>();
_traverseModules = Traverse.Create(ikSystem).Field("_trackingModules");
VRModeSwitchTracker.OnPreVRModeSwitch += PreVRModeSwitch;
VRModeSwitchTracker.OnFailVRModeSwitch += FailedVRModeSwitch;
VRModeSwitchTracker.OnPostVRModeSwitch += PostVRModeSwitch;
}
void OnDestroy()
{
VRModeSwitchTracker.OnPreVRModeSwitch -= PreVRModeSwitch;
VRModeSwitchTracker.OnFailVRModeSwitch -= FailedVRModeSwitch;
VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch;
}
public void PostVRModeSwitch(bool isVR, Camera activeCamera)
public void PreVRModeSwitch(bool enableVR, Camera activeCamera)
{
var _trackingModules = _traverseModules.GetValue<List<TrackingModule>>();
SteamVRTrackingModule openVRTrackingModule = _trackingModules.FirstOrDefault(m => m is SteamVRTrackingModule) as SteamVRTrackingModule;
if (openVRTrackingModule != null)
{
if (isVR)
{
openVRTrackingModule.ModuleStart();
}
else
{
//why named destroy when it doesnt ?
openVRTrackingModule.ModuleDestroy();
}
}
else
{
var steamVRTrackingModule = CreateSteamVRTrackingModule();
ikSystem.AddTrackingModule(steamVRTrackingModule);
}
BodySystem.TrackingEnabled = false;
BodySystem.TrackingPositionWeight = 0f;
BodySystem.TrackingLocomotionEnabled = false;
if (IKSystem.vrik != null)
IKSystem.vrik.enabled = false;
}
public void FailedVRModeSwitch(bool enableVR, Camera activeCamera)
{
BodySystem.TrackingEnabled = true;
BodySystem.TrackingPositionWeight = 1f;
BodySystem.TrackingLocomotionEnabled = true;
if (IKSystem.vrik != null)
IKSystem.vrik.enabled = true;
}
public void PostVRModeSwitch(bool enableVR, Camera activeCamera)
{
if (IKSystem.vrik != null)
DestroyImmediate(IKSystem.vrik);
//make sure you are fully tracking
BodySystem.TrackingEnabled = true;
BodySystem.TrackingPositionWeight = 1f;
BodySystem.TrackingLocomotionEnabled = true;
BodySystem.isCalibratedAsFullBody = false;
BodySystem.isCalibrating = false;
BodySystem.isRecalibration = false;
//make it so you dont instantly end up in FBT from Desktop
IKSystem.firstAvatarLoaded = DesktopVRSwitch.EntryEnterCalibrationOnSwitch.Value;
//turn of finger tracking just in case user switched controllers
ikSystem.FingerSystem.controlActive = false;
//vrik should be deleted by avatar switch
SetupSteamVRTrackingModule(enableVR);
}
//thanks for marking the constructor as internal
private SteamVRTrackingModule CreateSteamVRTrackingModule()
void SetupSteamVRTrackingModule(bool enableVR)
{
var steamVRTrackingModuleType = typeof(SteamVRTrackingModule);
var constructor = steamVRTrackingModuleType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
var instance = constructor.Invoke(null);
return (SteamVRTrackingModule)instance;
var openVRModule = ikSystem._trackingModules.OfType<SteamVRTrackingModule>().FirstOrDefault();
if (openVRModule != null)
{
if (enableVR)
{
openVRModule.ModuleStart();
}
else
{
openVRModule.ModuleDestroy();
}
}
else if (enableVR)
{
var newVRModule = new SteamVRTrackingModule();
ikSystem.AddTrackingModule(newVRModule);
}
}
}

View file

@ -12,17 +12,17 @@ public class MovementSystemTracker : MonoBehaviour
void Start()
{
movementSystem = GetComponent<MovementSystem>();
VRModeSwitchTracker.OnPostVRModeSwitch += PreVRModeSwitch;
VRModeSwitchTracker.OnPreVRModeSwitch += PreVRModeSwitch;
VRModeSwitchTracker.OnPostVRModeSwitch += PostVRModeSwitch;
}
void OnDestroy()
{
VRModeSwitchTracker.OnPostVRModeSwitch -= PreVRModeSwitch;
VRModeSwitchTracker.OnPreVRModeSwitch -= PreVRModeSwitch;
VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch;
}
public void PreVRModeSwitch(bool isVR, Camera activeCamera)
public void PreVRModeSwitch(bool enableVR, Camera activeCamera)
{
//correct rotationPivot y position, so we dont teleport up/down
Vector3 position = movementSystem.rotationPivot.transform.position;
@ -34,15 +34,21 @@ public class MovementSystemTracker : MonoBehaviour
//I correct for this in lazy way, but i use rotationPivot instead of avatar root,
//so the user can still switch even if avatar is null (if it failed to load for example).
movementSystem.ChangeCrouch(false);
movementSystem.ChangeProne(false);
}
public void PostVRModeSwitch(bool isVR, Camera activeCamera)
public void PostVRModeSwitch(bool enableVR, Camera activeCamera)
{
//immediatly update camera to new camera transform
movementSystem.rotationPivot = activeCamera.transform;
//lazy way of correcting Desktop & VR offset issue (game does the maths)
movementSystem.TeleportToPosRot(preSwitchWorldPosition, preSwitchWorldRotation, false);
//recenter desktop collision to player object
if (!isVR) movementSystem.UpdateColliderCenter(movementSystem.transform.position);
if (!enableVR) movementSystem.UpdateColliderCenter(movementSystem.transform.position);
movementSystem.ChangeCrouch(false);
movementSystem.ChangeProne(false);
}
}

View file

@ -10,35 +10,35 @@ public class VRModeSwitchTracker
public static event UnityAction<bool, Camera> OnPostVRModeSwitch;
public static event UnityAction<bool, Camera> OnFailVRModeSwitch;
public static void PreVRModeSwitch(bool isVR)
public static void PreVRModeSwitch(bool enableVR)
{
TryCatchHell.TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg("Invoking VRModeSwitchTracker.OnPreVRModeSwitch.");
Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
VRModeSwitchTracker.OnPreVRModeSwitch?.Invoke(isVR, activeCamera);
VRModeSwitchTracker.OnPreVRModeSwitch?.Invoke(enableVR, activeCamera);
},
"Error while invoking VRModeSwitchTracker.OnPreVRModeSwitch. Did someone do a fucky?");
}
public static void PostVRModeSwitch(bool isVR)
public static void PostVRModeSwitch(bool enableVR)
{
TryCatchHell.TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg("Invoking VRModeSwitchTracker.OnPostVRModeSwitch.");
Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
VRModeSwitchTracker.OnPostVRModeSwitch?.Invoke(isVR, activeCamera);
VRModeSwitchTracker.OnPostVRModeSwitch?.Invoke(enableVR, activeCamera);
},
"Error while invoking VRModeSwitchTracker.OnPostVRModeSwitch. Did someone do a fucky?");
}
public static void FailVRModeSwitch(bool isVR)
public static void FailVRModeSwitch(bool enableVR)
{
TryCatchHell.TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg("Invoking VRModeSwitchTracker.OnFailVRModeSwitch.");
Camera activeCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
VRModeSwitchTracker.OnFailVRModeSwitch?.Invoke(isVR, activeCamera);
VRModeSwitchTracker.OnFailVRModeSwitch?.Invoke(enableVR, activeCamera);
},
"Error while invoking OnFailVRModeSwitch.OnPreVRModeSwitch. Did someone do a fucky?");
}

View file

@ -7,14 +7,10 @@ namespace NAK.DesktopVRSwitch.Patches;
public class VRTrackerManagerTracker : MonoBehaviour
{
public VRTrackerManager vrTrackerManager;
public Traverse _hasCheckedForKnucklesTraverse;
public Traverse _posesTraverse;
void Start()
{
vrTrackerManager = GetComponent<VRTrackerManager>();
_posesTraverse = Traverse.Create(vrTrackerManager).Field("poses");
_hasCheckedForKnucklesTraverse = Traverse.Create(vrTrackerManager).Field("hasCheckedForKnuckles");
VRModeSwitchTracker.OnPostVRModeSwitch += PostVRModeSwitch;
}
void OnDestroy()
@ -22,14 +18,14 @@ public class VRTrackerManagerTracker : MonoBehaviour
VRModeSwitchTracker.OnPostVRModeSwitch -= PostVRModeSwitch;
}
public void PostVRModeSwitch(bool isVR, Camera activeCamera)
public void PostVRModeSwitch(bool enableVR, Camera activeCamera)
{
//force the VRTrackerManager to reset anything its stored
//this makes it get correct Left/Right hand if entering VR with different controllers
//or if you restarted SteamVR and controllers are now in swapped index
vrTrackerManager.poses = null;
vrTrackerManager.leftHand = null;
vrTrackerManager.rightHand = null;
_posesTraverse.SetValue(null);
_hasCheckedForKnucklesTraverse.SetValue(false);
vrTrackerManager.hasCheckedForKnuckles = false;
}
}

View file

@ -26,6 +26,6 @@ using System.Reflection;
namespace NAK.DesktopVRSwitch.Properties;
internal static class AssemblyInfoParams
{
public const string Version = "4.3.5";
public const string Version = "4.3.6";
public const string Author = "NotAKidoS";
}

View file

@ -5,7 +5,6 @@ using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
using ABI_RC.Core.UI;
using ABI_RC.Systems.Camera;
using HarmonyLib;
using UnityEngine;
namespace NAK.DesktopVRSwitch;
@ -36,45 +35,45 @@ internal class TryCatchHell
"Setting CheckVR hasVrDeviceLoaded failed.");
}
internal static void SetCheckVR(bool isVR)
internal static void SetCheckVR(bool enableVR)
{
TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg($"Setting CheckVR hasVrDeviceLoaded to {isVR}.");
CheckVR.Instance.hasVrDeviceLoaded = isVR;
DesktopVRSwitch.Logger.Msg($"Setting CheckVR hasVrDeviceLoaded to {enableVR}.");
CheckVR.Instance.hasVrDeviceLoaded = enableVR;
},
"Setting CheckVR hasVrDeviceLoaded failed.");
}
internal static void SetMetaPort(bool isVR)
internal static void SetMetaPort(bool enableVR)
{
TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg($"Setting MetaPort isUsingVr to {isVR}.");
MetaPort.Instance.isUsingVr = isVR;
DesktopVRSwitch.Logger.Msg($"Setting MetaPort isUsingVr to {enableVR}.");
MetaPort.Instance.isUsingVr = enableVR;
},
"Setting MetaPort isUsingVr failed.");
}
internal static void RepositionCohtmlHud(bool isVR)
internal static void RepositionCohtmlHud(bool enableVR)
{
TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg("Configuring new hud affinity for CohtmlHud.");
CohtmlHud.Instance.gameObject.transform.parent = isVR ? PlayerSetup.Instance.vrCamera.transform : PlayerSetup.Instance.desktopCamera.transform;
CohtmlHud.Instance.gameObject.transform.parent = enableVR ? PlayerSetup.Instance.vrCamera.transform : PlayerSetup.Instance.desktopCamera.transform;
CVRTools.ConfigureHudAffinity();
CohtmlHud.Instance.gameObject.transform.localScale = new Vector3(1.2f, 1f, 1.2f);
},
"Error parenting CohtmlHud to active camera.");
}
internal static void UpdateHudOperations(bool isVR)
internal static void UpdateHudOperations(bool enableVR)
{
TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg("Switching HudOperations worldLoadingItem & worldLoadStatus.");
HudOperations.Instance.worldLoadingItem = isVR ? HudOperations.Instance.worldLoadingItemVr : HudOperations.Instance.worldLoadingItemDesktop;
HudOperations.Instance.worldLoadStatus = isVR ? HudOperations.Instance.worldLoadStatusVr : HudOperations.Instance.worldLoadStatusDesktop;
HudOperations.Instance.worldLoadingItem = enableVR ? HudOperations.Instance.worldLoadingItemVr : HudOperations.Instance.worldLoadingItemDesktop;
HudOperations.Instance.worldLoadStatus = enableVR ? HudOperations.Instance.worldLoadStatusVr : HudOperations.Instance.worldLoadStatusDesktop;
},
"Failed switching HudOperations objects.");
}
@ -91,13 +90,13 @@ internal class TryCatchHell
"Failed to disable PortableCamera canvas mirroring.");
}
internal static void SwitchActiveCameraRigs(bool isVR)
internal static void SwitchActiveCameraRigs(bool enableVR)
{
TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg("Switching active PlayerSetup camera rigs. Updating Desktop camera FOV.");
PlayerSetup.Instance.desktopCameraRig.SetActive(!isVR);
PlayerSetup.Instance.vrCameraRig.SetActive(isVR);
PlayerSetup.Instance.desktopCameraRig.SetActive(!enableVR);
PlayerSetup.Instance.vrCameraRig.SetActive(enableVR);
CVR_DesktopCameraController.UpdateFov();
//uicamera has script that copies fov from desktop cam
//toggling the cameras on/off resets aspect ratio
@ -172,17 +171,17 @@ internal class TryCatchHell
TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg("Updating CVRGestureRecognizer _camera to active camera.");
Traverse.Create(CVRGestureRecognizer.Instance).Field("_camera").SetValue(PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>());
CVRGestureRecognizer.Instance._camera = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
},
"Failed to update CVRGestureRecognizer camera.");
}
internal static void UpdateMenuCoreData(bool isVR)
internal static void UpdateMenuCoreData(bool enableVR)
{
TryCatchWrapper(() =>
{
DesktopVRSwitch.Logger.Msg("Updating CVR_Menu_Data core data.");
CVR_MenuManager.Instance.coreData.core.inVr = isVR;
CVR_MenuManager.Instance.coreData.core.inVr = enableVR;
},
"Failed to update CVR_Menu_Data core data.");
}

View file

@ -1,5 +1,10 @@
<Project>
<!-- Hack! MelonLoader is locking the Mod files, this way I can build and output the mod dll with the game running -->
<Target Name="DeleteOutputDLLIfExists" BeforeTargets="BeforeBuild">
<Exec Command="if exist &quot;$(OutputPath)$(TargetName).dll&quot; del /F /Q &quot;$(OutputPath)$(TargetName).dll&quot;" />
</Target>
<PropertyGroup>
<!-- Put your Chillout vr path in a new environnment variable CVRPATH in Windows -->
<OutputPath>$(CVRPATH)\Mods\</OutputPath>

View file

@ -0,0 +1,68 @@
using UnityEngine;
using RootMotion.FinalIK;
namespace NAK.InteractionTest;
public class AutoArmIK : MonoBehaviour
{
public bool calibrateOnStart = true;
public Transform leftHand, rightHand;
Animator animator;
ArmIK leftArmIK, rightArmIK;
void Start()
{
if (calibrateOnStart) CalibrateArmIK();
}
public void CalibrateArmIK()
{
animator = GetComponent<Animator>();
if (animator == null)
{
Debug.LogError("Animator component not found on the avatar.");
return;
}
leftArmIK = gameObject.AddComponent<ArmIK>();
leftArmIK.solver.isLeft = true;
rightArmIK = gameObject.AddComponent<ArmIK>();
rightArmIK.solver.isLeft = false;
CreateHandTarget(HumanBodyBones.LeftHand, ref leftHand);
CreateHandTarget(HumanBodyBones.RightHand, ref rightHand);
leftArmIK.solver.arm.target = leftHand;
rightArmIK.solver.arm.target = rightHand;
SetArmIKChain(leftArmIK, HumanBodyBones.LeftShoulder, HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand);
SetArmIKChain(rightArmIK, HumanBodyBones.RightShoulder, HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand);
leftArmIK.solver.IKPositionWeight = 1f;
rightArmIK.solver.IKPositionWeight = 1f;
}
private void CreateHandTarget(HumanBodyBones bone, ref Transform handTarget)
{
var boneTransform = animator.GetBoneTransform(bone);
var handGO = new GameObject($"{boneTransform.name} Target");
handTarget = handGO.transform;
handTarget.position = boneTransform.position;
Vector3 sourceYWorld = boneTransform.TransformDirection(Vector3.up);
handTarget.rotation = Quaternion.LookRotation(boneTransform.forward, sourceYWorld);
}
private void SetArmIKChain(ArmIK armIK, HumanBodyBones shoulder, HumanBodyBones upperArm, HumanBodyBones lowerArm, HumanBodyBones hand)
{
armIK.solver.SetChain(
animator.GetBoneTransform(HumanBodyBones.Chest),
animator.GetBoneTransform(shoulder),
animator.GetBoneTransform(upperArm),
animator.GetBoneTransform(lowerArm),
animator.GetBoneTransform(hand),
animator.transform
);
}
}

View file

@ -0,0 +1,40 @@
using ABI_RC.Core;
using System.Text;
using UnityEngine;
namespace NAK.InteractionTest;
internal class GrabbableAvatar : MonoBehaviour
{
private static readonly HumanBodyBones[][] boneSequences = new[]
{
new[] { HumanBodyBones.Hips, HumanBodyBones.Spine, HumanBodyBones.Chest, HumanBodyBones.Neck, HumanBodyBones.Head },
new[] { HumanBodyBones.LeftUpperLeg, HumanBodyBones.LeftLowerLeg, HumanBodyBones.LeftFoot },
new[] { HumanBodyBones.RightUpperLeg, HumanBodyBones.RightLowerLeg, HumanBodyBones.RightFoot },
new[] { HumanBodyBones.LeftUpperArm, HumanBodyBones.LeftLowerArm, HumanBodyBones.LeftHand },
new[] { HumanBodyBones.RightUpperArm, HumanBodyBones.RightLowerArm, HumanBodyBones.RightHand }
};
private void Start()
{
var animator = GetComponent<Animator>();
for (int seqIndex = 0; seqIndex < boneSequences.Length; seqIndex++)
{
var boneSequence = boneSequences[seqIndex];
for (int i = 0; i < boneSequence.Length - 1; i++)
{
var fromBone = animator.GetBoneTransform(boneSequence[i]);
var toBone = animator.GetBoneTransform(boneSequence[i + 1]);
var colliderName = new StringBuilder(fromBone.name)
.Append("_to_")
.Append(toBone.name)
.ToString();
CVRTools.GenerateBoneCollider(fromBone, toBone, 1f, colliderName);
}
}
}
}

View file

@ -0,0 +1,108 @@
using UnityEngine;
using RootMotion.FinalIK;
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
namespace NAK.InteractionTest;
internal class GrabbingAvatar : MonoBehaviour
{
VRIK m_vrik;
private bool m_isGrabbingLeft = false;
private bool m_isGrabbingRight = false;
private Transform m_grabbedTransform = null;
private Vector3 m_localOffset;
private Quaternion m_localRotation;
public float m_grabRadius = 0.1f;
public LayerMask m_grabLayerMask;
void Start()
{
m_vrik = GetComponent<VRIK>();
}
void Update()
{
bool isGrabLeft = CVRInputManager.Instance.gripLeftValue >= 0.5f;
bool isGrabRight = CVRInputManager.Instance.gripRightValue >= 0.5f;
if (isGrabLeft && !m_isGrabbingLeft)
{
m_isGrabbingLeft = true;
OnGrab(Hand.Left);
}
else if (!isGrabLeft && m_isGrabbingLeft)
{
m_isGrabbingLeft = false;
OnRelease(Hand.Left);
}
if (isGrabRight && !m_isGrabbingRight)
{
m_isGrabbingRight = true;
OnGrab(Hand.Right);
}
else if (!isGrabRight && m_isGrabbingRight)
{
m_isGrabbingRight = false;
OnRelease(Hand.Right);
}
if (m_isGrabbingLeft)
{
UpdateGrabbedHand(Hand.Left);
}
if (m_isGrabbingRight)
{
UpdateGrabbedHand(Hand.Right);
}
}
void OnGrab(Hand hand)
{
// Find the closest grabbable object using a sphere cast
Collider[] colliders = Physics.OverlapSphere(transform.position, m_grabRadius, m_grabLayerMask);
if (colliders.Length > 0)
{
Collider closestCollider = colliders[0];
float closestDistance = float.MaxValue;
foreach (Collider collider in colliders)
{
float distance = (collider.transform.position - transform.position).magnitude;
if (distance < closestDistance)
{
closestCollider = collider;
closestDistance = distance;
}
}
// Cache the grabbed transform and local position/rotation offset
m_grabbedTransform = closestCollider.transform;
m_localOffset = transform.InverseTransformVector(m_grabbedTransform.position - transform.position);
m_localRotation = Quaternion.Inverse(transform.rotation) * m_grabbedTransform.rotation;
}
}
void OnRelease(Hand hand)
{
// Reset the grabbed transform and local position/rotation offset
m_grabbedTransform = null;
m_localOffset = Vector3.zero;
m_localRotation = Quaternion.identity;
}
void UpdateGrabbedHand(Hand hand)
{
}
}
public enum Hand
{
Left,
Right
}

View file

@ -0,0 +1,24 @@
using HarmonyLib;
using ABI_RC.Core.Player;
namespace NAK.InteractionTest.HarmonyPatches;
class PuppetMasterPatches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(PuppetMaster), nameof(PuppetMaster.AvatarInstantiated))]
static void Postfix_PuppetMaster_SetupAvatar(ref PuppetMaster __instance)
{
__instance.avatarObject.AddComponent<AutoArmIK>();
}
}
class PlayerSetupPatches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerSetup), nameof(PlayerSetup.SetupAvatar))]
static void Postfix_PlayerSetup_SetupAvatar(ref PlayerSetup __instance)
{
}
}

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<Reference Include="ml_prm">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\ChilloutVR\Mods\ml_prm.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

26
InteractionTest/Main.cs Normal file
View file

@ -0,0 +1,26 @@
using MelonLoader;
namespace NAK.InteractionTest;
public class InteractionTest : MelonMod
{
internal static MelonLogger.Instance Logger;
public override void OnInitializeMelon()
{
ApplyPatches(typeof(HarmonyPatches.PuppetMasterPatches));
ApplyPatches(typeof(HarmonyPatches.PlayerSetupPatches));
}
void ApplyPatches(Type type)
{
try
{
HarmonyInstance.PatchAll(type);
}
catch (Exception e)
{
LoggerInstance.Msg($"Failed while patching {type.Name}!");
LoggerInstance.Error(e);
}
}
}

View file

@ -0,0 +1,30 @@
using MelonLoader;
using NAK.InteractionTest.Properties;
using System.Reflection;
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyTitle(nameof(NAK.InteractionTest))]
[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
[assembly: AssemblyProduct(nameof(NAK.InteractionTest))]
[assembly: MelonInfo(
typeof(NAK.InteractionTest.InteractionTest),
nameof(NAK.InteractionTest),
AssemblyInfoParams.Version,
AssemblyInfoParams.Author,
downloadLink: "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/tree/main/AvatarScale"
)]
[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
[assembly: MelonAdditionalDependencies("PlayerRagdollMod")]
namespace NAK.InteractionTest.Properties;
internal static class AssemblyInfoParams
{
public const string Version = "1.0.0";
public const string Author = "NotAKidoS";
}

16
InteractionTest/README.md Normal file
View file

@ -0,0 +1,16 @@
# InteractionTest
Makes "AvatarScale" parameter persistant across avatars.
Combined with AvatarScaleTool, this allows for crossa consistant scale when switching between avatars.
---
Here is the block of text where I tell you this mod is not affiliated or endorsed by ABI.
https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games
> This mod is an independent creation and is not affiliated with, supported by or approved by Alpha Blend Interactive.
> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use.
> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive.

View file

@ -0,0 +1,23 @@
{
"_id": 126,
"name": "AvatarScale",
"modversion": "1.0.5",
"gameversion": "2022r170",
"loaderversion": "0.5.7",
"modtype": "Mod",
"author": "NotAKidoS",
"description": "Fixes two issues with the Avatar Advanced Settings buffers when loading remote avatars. In simple terms, it means 'fewer wardrobe malfunctions'.\n\nEmpty buffer (all 0/false) will no longer be applied on load.\nReceived AAS data is ignored until the wearer has loaded into the expected avatar.\n(The avatar will sit in its default state until the wearer has loaded and started syncing correct AAS)\nAAS will no longer be sent while switching avatar.\n\nPlease view the GitHub README for links to relevant feedback posts.",
"searchtags": [
"aas",
"sync",
"naked",
"buffer"
],
"requirements": [
"None"
],
"downloadlink": "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/releases/download/r3/AvatarScale.dll",
"sourcelink": "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/tree/main/AvatarScale/",
"changelog": "",
"embedcolor": "9b59b6"
}

View file

@ -49,6 +49,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvatarScaleMod", "AvatarSca
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Nevermind", "Nevermind\Nevermind.csproj", "{0432AB34-549E-4E36-8C92-6B9991800D67}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "InteractionTest", "InteractionTest\InteractionTest.csproj", "{55B6B84B-8D92-4703-B456-04A56FA069D9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CameraFixes", "CameraFixes\CameraFixes.csproj", "{3090F446-1122-4EF1-B9D9-6ACE724C87DF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IKAdjustments", "IKAdjustments\IKAdjustments.csproj", "{CCD510BF-1A32-441F-B52B-8A937BF75CE3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -147,6 +153,18 @@ Global
{0432AB34-549E-4E36-8C92-6B9991800D67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0432AB34-549E-4E36-8C92-6B9991800D67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0432AB34-549E-4E36-8C92-6B9991800D67}.Release|Any CPU.Build.0 = Release|Any CPU
{55B6B84B-8D92-4703-B456-04A56FA069D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55B6B84B-8D92-4703-B456-04A56FA069D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55B6B84B-8D92-4703-B456-04A56FA069D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55B6B84B-8D92-4703-B456-04A56FA069D9}.Release|Any CPU.Build.0 = Release|Any CPU
{3090F446-1122-4EF1-B9D9-6ACE724C87DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3090F446-1122-4EF1-B9D9-6ACE724C87DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3090F446-1122-4EF1-B9D9-6ACE724C87DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3090F446-1122-4EF1-B9D9-6ACE724C87DF}.Release|Any CPU.Build.0 = Release|Any CPU
{CCD510BF-1A32-441F-B52B-8A937BF75CE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CCD510BF-1A32-441F-B52B-8A937BF75CE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CCD510BF-1A32-441F-B52B-8A937BF75CE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CCD510BF-1A32-441F-B52B-8A937BF75CE3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -77,9 +77,17 @@ internal static class CameraLogic
// Copy basic settings
ourCamComponent.farClipPlane = playerCamComponent.farClipPlane;
ourCamComponent.nearClipPlane = playerCamComponent.nearClipPlane;
ourCamComponent.cullingMask = playerCamComponent.cullingMask;
ourCamComponent.depthTextureMode = playerCamComponent.depthTextureMode;
// We cant copy this because we set it to 0
ourCamComponent.cullingMask &= -32769;
ourCamComponent.cullingMask |= 256;
ourCamComponent.cullingMask |= 512;
ourCamComponent.cullingMask |= 32;
ourCamComponent.cullingMask &= -4097;
ourCamComponent.cullingMask |= 1024;
ourCamComponent.cullingMask |= 8192;
// Copy post processing if added
PostProcessLayer ppLayerPlayerCam = playerCamComponent.GetComponent<PostProcessLayer>();
PostProcessLayer ppLayerThirdPerson = ourCamComponent.AddComponentIfMissing<PostProcessLayer>();