thirdperson, propundobutton, mirror clone test, you are a clone test, bettershadowclone test, nevermind, anotherlocaltestmod, and some changes to avatarscaling ???

This commit is contained in:
NotAKidoS 2024-04-10 17:25:21 -05:00
parent df45fb50d9
commit 9944ad7611
43 changed files with 1076 additions and 173 deletions

80
MirrorClone/Main.cs Normal file
View file

@ -0,0 +1,80 @@
using MelonLoader;
using System.Reflection;
using ABI_RC.Core.Player;
using ABI_RC.Core.Util;
using ABI_RC.Systems.IK;
using UnityEngine;
namespace NAK.BetterShadowClone;
public class MirrorCloneMod : MelonMod
{
internal static MelonLogger.Instance Logger;
public override void OnInitializeMelon()
{
Logger = LoggerInstance;
ModSettings.Initialize();
try
{
InitializePatches();
}
catch (Exception e)
{
Logger.Error(e);
}
}
#region Harmony Patches
private void InitializePatches()
{
HarmonyInstance.Patch(
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.Awake), BindingFlags.NonPublic | BindingFlags.Instance),
postfix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnPlayerSetup_Awake_Postfix), BindingFlags.NonPublic | BindingFlags.Static))
);
HarmonyInstance.Patch(
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)),
prefix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnPlayerSetup_SetupAvatar_Prefix), BindingFlags.NonPublic | BindingFlags.Static)),
postfix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnPlayerSetup_SetupAvatar_Postfix), BindingFlags.NonPublic | BindingFlags.Static))
);
HarmonyInstance.Patch(
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)),
prefix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnPlayerSetup_ClearAvatar_Prefix), BindingFlags.NonPublic | BindingFlags.Static))
);
HarmonyInstance.Patch(
typeof(IKSystem).GetMethod(nameof(IKSystem.OnPostSolverUpdateGeneral), BindingFlags.NonPublic | BindingFlags.Instance),
postfix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnIKSystem_OnPostSolverUpdateGeneral_Postfix), BindingFlags.NonPublic | BindingFlags.Static))
);
HarmonyInstance.Patch(
typeof(TransformHiderForMainCamera).GetMethod(nameof(TransformHiderForMainCamera.ProcessHierarchy)),
prefix: new HarmonyLib.HarmonyMethod(typeof(MirrorCloneMod).GetMethod(nameof(OnTransformHiderForMainCamera_ProcessHierarchy_Prefix), BindingFlags.NonPublic | BindingFlags.Static))
);
}
private static void OnPlayerSetup_Awake_Postfix()
=> MirrorCloneManager.OnPlayerSetupAwake();
private static void OnPlayerSetup_SetupAvatar_Prefix(GameObject inAvatar)
=> MirrorCloneManager.Instance.OnAvatarInitialized(inAvatar);
private static void OnPlayerSetup_SetupAvatar_Postfix()
=> MirrorCloneManager.Instance.OnAvatarConfigured();
private static void OnPlayerSetup_ClearAvatar_Prefix()
=> MirrorCloneManager.Instance.OnAvatarDestroyed();
private static void OnIKSystem_OnPostSolverUpdateGeneral_Postfix()
=> MirrorCloneManager.Instance.OnPostSolverUpdateGeneral();
private static void OnTransformHiderForMainCamera_ProcessHierarchy_Prefix(ref bool __runOriginal)
=> __runOriginal = !ModSettings.EntryEnabled.Value;
#endregion
}

View file

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

View file

@ -0,0 +1,247 @@
using ABI_RC.Core;
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
using ABI_RC.Systems.IK;
using ABI.CCK.Components;
using UnityEngine;
using UnityEngine.Rendering;
namespace NAK.BetterShadowClone;
public class MirrorCloneManager : MonoBehaviour
{
#region Static Instance
public static MirrorCloneManager Instance { get; private set; }
#endregion
private bool _isAvatarConfigured;
private GameObject _avatar;
private GameObject _mirrorClone;
private GameObject _initializationTarget;
private CVRAnimatorManager _animatorManager;
private Animator _mirrorAnimator;
#region Unity Events
private void Awake()
{
if (Instance != null
&& Instance != this)
{
DestroyImmediate(this);
return;
}
Instance = this;
MirrorCloneMod.Logger.Msg("Mirror Clone Manager initialized.");
_animatorManager = PlayerSetup.Instance.animatorManager;
// Create initialization target (so no components are initialized before we're ready)
_initializationTarget = new GameObject(nameof(MirrorCloneManager) + " Initialization Target");
_initializationTarget.transform.SetParent(transform);
_initializationTarget.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
_initializationTarget.transform.localScale = Vector3.one;
_initializationTarget.SetActive(false);
}
private void OnDestroy()
{
if (Instance == this)
Instance = null;
}
#endregion
#region Game Events
public static void OnPlayerSetupAwake()
{
if (Instance != null)
return;
GameObject manager = new (nameof(MirrorCloneManager), typeof(MirrorCloneManager));
DontDestroyOnLoad(manager);
}
public void OnAvatarInitialized(GameObject avatar)
{
if (!ModSettings.EntryEnabled.Value)
return;
if (avatar == null
|| _isAvatarConfigured)
return;
_isAvatarConfigured = true;
_avatar = avatar;
_mirrorClone = InstantiateMirrorCopy(_avatar);
}
public void OnAvatarConfigured()
{
if (!_isAvatarConfigured)
return;
Animator baseAnimator = _avatar.GetComponent<Animator>();
if (!_mirrorClone.TryGetComponent(out _mirrorAnimator))
_mirrorAnimator = gameObject.AddComponent<Animator>();
_mirrorAnimator.runtimeAnimatorController = baseAnimator.runtimeAnimatorController;
_animatorManager._copyAnimator = _mirrorAnimator; // thank you for existing
var cameras = PlayerSetup.Instance.GetComponentsInChildren<Camera>(true);
foreach (var camera in cameras)
{
// hide PlayerClone layer from all cameras
camera.cullingMask &= ~(1 << CVRLayers.PlayerClone);
}
var mirrors = Resources.FindObjectsOfTypeAll<CVRMirror>();
foreach (CVRMirror mirror in mirrors)
{
// hide PlayerLocal layer from all mirrors
mirror.m_ReflectLayers &= ~(1 << CVRLayers.PlayerLocal);
}
// scale avatar head bone to 0 0 0
Transform headBone = baseAnimator.GetBoneTransform(HumanBodyBones.Head);
headBone.localScale = Vector3.zero;
CleanupAvatar();
CleanupMirrorClone();
SetupHumanPoseHandler();
_initializationTarget.SetActive(true);
}
public void OnAvatarDestroyed()
{
if (!_isAvatarConfigured)
return;
_avatar = null;
_mirrorAnimator = null;
if (_mirrorClone != null)
Destroy(_mirrorClone);
_initializationTarget.SetActive(false);
_isAvatarConfigured = false;
}
public void OnPostSolverUpdateGeneral()
{
if (!_isAvatarConfigured)
return;
StealTransforms();
}
#endregion
#region Private Methods
private GameObject InstantiateMirrorCopy(GameObject original)
{
GameObject clone = Instantiate(original, _initializationTarget.transform);
clone.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
clone.name = original.name + " (Mirror Clone)";
clone.SetLayerRecursive(CVRLayers.PlayerClone);
return clone;
}
private void CleanupAvatar()
{
// set local avatar mesh to shadow off
var avatarMeshes = _avatar.GetComponentsInChildren<SkinnedMeshRenderer>(true);
foreach (SkinnedMeshRenderer avatarMesh in avatarMeshes)
{
avatarMesh.shadowCastingMode = ShadowCastingMode.Off;
avatarMesh.forceMatrixRecalculationPerRender = false;
}
}
private void CleanupMirrorClone()
{
// destroy unneeded components
// only keep Animator
var components = _mirrorClone.GetComponentsInChildren<Component>(true);
foreach (Component component in components)
{
if (component == null)
continue;
// skip basic unity components
if (component is Animator
or Transform
or SkinnedMeshRenderer
or MeshRenderer
or MeshFilter)
continue;
// skip basic CVR components
if (component is CVRAvatar or CVRAssetInfo)
{
(component as MonoBehaviour).enabled = false;
continue;
}
Destroy(component);
}
}
#endregion
#region Job System
private HumanPoseHandler _humanPoseHandler;
private Transform _hipTransform;
private void SetupHumanPoseHandler()
{
_hipTransform = _mirrorAnimator.GetBoneTransform(HumanBodyBones.Hips);
_humanPoseHandler?.Dispose();
_humanPoseHandler = new HumanPoseHandler(_mirrorAnimator.avatar, _mirrorAnimator.transform);
}
private void StealTransforms()
{
// copy transforms from avatar to mirror clone
// var avatarTransforms = _avatar.GetComponentsInChildren<Transform>(true);
// var mirrorCloneTransforms = _mirrorClone.GetComponentsInChildren<Transform>(true);
// for (int i = 0; i < avatarTransforms.Length; i++)
// {
// Transform avatarTransform = avatarTransforms[i];
// Transform mirrorCloneTransform = mirrorCloneTransforms[i];
//
// mirrorCloneTransform.SetLocalPositionAndRotation(
// avatarTransform.localPosition,
// avatarTransform.localRotation);
// }
if (!IKSystem.Instance.IsAvatarCalibrated())
return;
IKSystem.Instance._humanPoseHandler.GetHumanPose(ref IKSystem.Instance._humanPose);
_humanPoseHandler.SetHumanPose(ref IKSystem.Instance._humanPose);
if (!MetaPort.Instance.isUsingVr)
_mirrorAnimator.transform.SetPositionAndRotation(PlayerSetup.Instance.GetPlayerPosition(), PlayerSetup.Instance.GetPlayerRotation());
else
_mirrorAnimator.transform.SetPositionAndRotation(_avatar.transform.position, _avatar.transform.rotation);
_hipTransform.SetPositionAndRotation(IKSystem.Instance._hipTransform.position, IKSystem.Instance._hipTransform.rotation);
}
#endregion
}

View file

@ -0,0 +1,31 @@
using MelonLoader;
using UnityEngine;
namespace NAK.BetterShadowClone;
public static class ModSettings
{
#region Melon Prefs
private const string SettingsCategory = nameof(MirrorCloneMod);
private static readonly MelonPreferences_Category Category =
MelonPreferences.CreateCategory(SettingsCategory);
internal static readonly MelonPreferences_Entry<bool> EntryEnabled =
Category.CreateEntry("Enabled", true,
description: "Enable Mirror Clone.");
#endregion
internal static void Initialize()
{
foreach (MelonPreferences_Entry setting in Category.Entries)
setting.OnEntryValueChangedUntyped.Subscribe(OnSettingsChanged);
}
internal static void OnSettingsChanged(object oldValue = null, object newValue = null)
{
}
}

View file

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

16
MirrorClone/README.md Normal file
View file

@ -0,0 +1,16 @@
# EzCurls
A mod that allows you to tune your finger curls to your liking. Supposedly can help with VR sign language, as raw finger curls are not that great for quick and precise gestures.
The settings are not too coherent, it is mostly a bunch of things thrown at the wall, but it works for me. I hope it works for you too.
---
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.

23
MirrorClone/format.json Normal file
View file

@ -0,0 +1,23 @@
{
"_id": -1,
"name": "EzCurls",
"modversion": "1.0.0",
"gameversion": "2023r173",
"loaderversion": "0.6.1",
"modtype": "Mod",
"author": "NotAKidoS",
"description": "A mod that allows you to tune your finger curls to your liking. Supposedly can help with VR sign language, as raw finger curls are not that great for quick and precise gestures.\n\nThe settings are not too coherent, it is mostly a bunch of things thrown at the wall, but it works for me. I hope it works for you too.",
"searchtags": [
"curls",
"fingers",
"index",
"knuckles"
],
"requirements": [
"UIExpansionKit"
],
"downloadlink": "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/releases/download/r24/EzCurls.dll",
"sourcelink": "https://github.com/NotAKidOnSteam/NAK_CVR_Mods/tree/main/EzCurls/",
"changelog": "- Initial CVRMG release",
"embedcolor": "7d7d7d"
}