Custom event classes for patched methods

Update to LeapCSharp 6.15.0
This commit is contained in:
SDraw 2024-04-26 23:52:25 +03:00
parent 4b879d53d5
commit 85925a7072
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
76 changed files with 3443 additions and 2187 deletions

View file

@ -75,10 +75,17 @@ namespace ml_pam
m_enabled = Settings.Enabled;
Settings.EnabledChange += this.SetEnabled;
Settings.GrabOffsetChange += this.SetGrabOffset;
Settings.LeadingHandChange += this.OnLeadingHandChange;
Settings.HandsExtensionChange += this.OnHandsExtensionChange;
Settings.OnEnabledChanged.AddHandler(this.OnEnabledChanged);
Settings.OnGrabOffsetChanged.AddHandler(this.OnGrabOffsetChanged);
Settings.OnLeadingHandChanged.AddHandler(this.OnLeadingHandChanged);
Settings.OnHandsExtensionChanged.AddHandler(this.OnHandsExtensionChanged);
GameEvents.OnAvatarClear.AddHandler(this.OnAvatarClear);
GameEvents.OnAvatarSetup.AddHandler(this.OnAvatarSetup);
GameEvents.OnAvatarReuse.AddHandler(this.OnAvatarReuse);
GameEvents.OnPlayspaceScale.AddHandler(this.OnPlayspaceScale);
GameEvents.OnPickupGrab.AddHandler(this.OnPickupGrab);
GameEvents.OnPickupDrop.AddHandler(this.OnPickupDrop);
}
void OnDestroy()
@ -98,10 +105,17 @@ namespace ml_pam
m_pickup = null;
m_vrIK = null;
Settings.EnabledChange -= this.SetEnabled;
Settings.GrabOffsetChange -= this.SetGrabOffset;
Settings.LeadingHandChange -= this.OnLeadingHandChange;
Settings.HandsExtensionChange -= this.OnHandsExtensionChange;
Settings.OnEnabledChanged.RemoveHandler(this.OnEnabledChanged);
Settings.OnGrabOffsetChanged.RemoveHandler(this.OnGrabOffsetChanged);
Settings.OnLeadingHandChanged.RemoveHandler(this.OnLeadingHandChanged);
Settings.OnHandsExtensionChanged.RemoveHandler(this.OnHandsExtensionChanged);
GameEvents.OnAvatarClear.RemoveHandler(this.OnAvatarClear);
GameEvents.OnAvatarSetup.RemoveHandler(this.OnAvatarSetup);
GameEvents.OnAvatarReuse.RemoveHandler(this.OnAvatarReuse);
GameEvents.OnPlayspaceScale.RemoveHandler(this.OnPlayspaceScale);
GameEvents.OnPickupGrab.RemoveHandler(this.OnPickupGrab);
GameEvents.OnPickupDrop.RemoveHandler(this.OnPickupDrop);
}
void Update()
@ -221,7 +235,7 @@ namespace ml_pam
}
// Settings
void SetEnabled(bool p_state)
void OnEnabledChanged(bool p_state)
{
m_enabled = p_state;
@ -232,13 +246,13 @@ namespace ml_pam
if(m_rightHandState != HandState.Empty)
SetArmActive(Settings.LeadHand.Right, true);
OnHandsExtensionChange(Settings.HandsExtension);
OnHandsExtensionChanged(Settings.HandsExtension);
}
else
SetArmActive(Settings.LeadHand.Both, false, true);
}
void SetGrabOffset(float p_value)
void OnGrabOffsetChanged(float p_value)
{
if(m_leftTarget != null)
m_leftTarget.localPosition = new Vector3(c_offsetLimit * m_playspaceScale * -p_value, 0f, 0f);
@ -246,7 +260,7 @@ namespace ml_pam
m_rightTarget.localPosition = new Vector3(c_offsetLimit * m_playspaceScale * p_value, 0f, 0f);
}
void OnLeadingHandChange(Settings.LeadHand p_hand)
void OnLeadingHandChanged(Settings.LeadHand p_hand)
{
if(m_pickup != null)
{
@ -281,7 +295,7 @@ namespace ml_pam
}
}
void OnHandsExtensionChange(bool p_state)
void OnHandsExtensionChanged(bool p_state)
{
if(m_enabled)
{
@ -315,7 +329,7 @@ namespace ml_pam
}
// Game events
internal void OnAvatarClear()
void OnAvatarClear()
{
m_vrIK = null;
m_armIKLeft = null;
@ -323,7 +337,7 @@ namespace ml_pam
m_armLength = 0f;
}
internal void OnAvatarSetup()
void OnAvatarSetup()
{
m_inVR = Utils.IsInVR();
m_vrIK = PlayerSetup.Instance._animator.GetComponent<VRIK>();
@ -351,10 +365,10 @@ namespace ml_pam
SetupArmIK();
}
SetEnabled(m_enabled);
OnEnabledChanged(m_enabled);
}
internal void OnAvatarReinitialize()
void OnAvatarReuse()
{
// Old VRIK is destroyed by game
m_inVR = Utils.IsInVR();
@ -373,12 +387,12 @@ namespace ml_pam
else if(!m_inVR)
SetupArmIK();
SetEnabled(m_enabled);
OnEnabledChanged(m_enabled);
}
internal void OnPickupGrab(CVRPickupObject p_pickup, Vector3 p_hit)
void OnPickupGrab(CVRPickupObject p_pickup, Vector3 p_hit)
{
if(p_pickup.ControllerRay == ViewManager.Instance.desktopControllerRay)
if(p_pickup.IsGrabbedByMe && (p_pickup.ControllerRay == ViewManager.Instance.desktopControllerRay))
{
m_pickup = p_pickup;
@ -416,7 +430,7 @@ namespace ml_pam
}
}
internal void OnPickupDrop(CVRPickupObject p_pickup)
void OnPickupDrop(CVRPickupObject p_pickup)
{
if(m_pickup == p_pickup)
{
@ -440,10 +454,10 @@ namespace ml_pam
}
}
internal void OnPlayspaceScale(float p_relation)
void OnPlayspaceScale(float p_relation)
{
m_playspaceScale = p_relation;
SetGrabOffset(Settings.GrabOffset);
OnGrabOffsetChanged(Settings.GrabOffset);
}
// Arbitrary

159
ml_pam/GameEvents.cs Normal file
View file

@ -0,0 +1,159 @@
using ABI.CCK.Components;
using ABI_RC.Core.Player;
using ABI_RC.Systems.IK;
using System;
using System.Reflection;
using UnityEngine;
namespace ml_pam
{
static class GameEvents
{
internal class GameEvent
{
event Action m_action;
public void AddHandler(Action p_listener) => m_action += p_listener;
public void RemoveHandler(Action p_listener) => m_action -= p_listener;
public void Invoke() => m_action?.Invoke();
}
internal class GameEvent<T1>
{
event Action<T1> m_action;
public void AddHandler(Action<T1> p_listener) => m_action += p_listener;
public void RemoveHandler(Action<T1> p_listener) => m_action -= p_listener;
public void Invoke(T1 p_obj) => m_action?.Invoke(p_obj);
}
internal class GameEvent<T1, T2>
{
event Action<T1, T2> m_action;
public void AddHandler(Action<T1, T2> p_listener) => m_action += p_listener;
public void RemoveHandler(Action<T1, T2> p_listener) => m_action -= p_listener;
public void Invoke(T1 p_objA, T2 p_objB) => m_action?.Invoke(p_objA, p_objB);
}
public static readonly GameEvent OnAvatarSetup = new GameEvent();
public static readonly GameEvent OnAvatarClear = new GameEvent();
public static readonly GameEvent OnAvatarReuse = new GameEvent();
public static readonly GameEvent<float> OnPlayspaceScale = new GameEvent<float>();
public static readonly GameEvent<CVRPickupObject, Vector3> OnPickupGrab = new GameEvent<CVRPickupObject, Vector3>();
public static readonly GameEvent<CVRPickupObject> OnPickupDrop = new GameEvent<CVRPickupObject>();
internal static void Init(HarmonyLib.Harmony p_instance)
{
try
{
p_instance.Patch(
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)),
null,
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
p_instance.Patch(
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)),
null,
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
p_instance.Patch(
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
null,
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnAvatarReinitialize_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
p_instance.Patch(
typeof(PlayerSetup).GetMethod("SetPlaySpaceScale", BindingFlags.NonPublic | BindingFlags.Instance),
null,
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnPlayspaceScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
p_instance.Patch(
typeof(CVRPickupObject).GetMethod("OnGrab", BindingFlags.Instance | BindingFlags.NonPublic),
null,
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnCVRPickupObjectGrab_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
p_instance.Patch(
typeof(CVRPickupObject).GetMethod("OnDrop", BindingFlags.Instance | BindingFlags.NonPublic),
null,
new HarmonyLib.HarmonyMethod(typeof(GameEvents).GetMethod(nameof(OnCVRPickupObjectDrop_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnAvatarClear_Postfix()
{
try
{
OnAvatarClear.Invoke();
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnSetupAvatar_Postfix()
{
try
{
OnAvatarSetup.Invoke();
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnAvatarReinitialize_Postfix()
{
try
{
OnAvatarReuse.Invoke();
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnPlayspaceScale_Postfix(float ____avatarScaleRelation)
{
try
{
OnPlayspaceScale.Invoke(____avatarScaleRelation);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnCVRPickupObjectGrab_Postfix(ref CVRPickupObject __instance, Vector3 __0)
{
try
{
OnPickupGrab.Invoke(__instance, __0);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnCVRPickupObjectDrop_Postfix(ref CVRPickupObject __instance)
{
try
{
OnPickupDrop.Invoke(__instance);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
}
}

View file

@ -1,56 +1,15 @@
using ABI.CCK.Components;
using ABI_RC.Core.InteractionSystem;
using ABI_RC.Core.Player;
using ABI_RC.Systems.IK;
using System;
using System.Reflection;
using UnityEngine;
using ABI_RC.Core.Player;
namespace ml_pam
{
public class PickupArmMovement : MelonLoader.MelonMod
{
static PickupArmMovement ms_instance = null;
ArmMover m_localMover = null;
public override void OnInitializeMelon()
{
if(ms_instance == null)
ms_instance = this;
Settings.Init();
HarmonyInstance.Patch(
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)),
null,
new HarmonyLib.HarmonyMethod(typeof(PickupArmMovement).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.NonPublic | BindingFlags.Static))
);
HarmonyInstance.Patch(
typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)),
null,
new HarmonyLib.HarmonyMethod(typeof(PickupArmMovement).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
HarmonyInstance.Patch(
typeof(IKSystem).GetMethod(nameof(IKSystem.ReinitializeAvatar), BindingFlags.Instance | BindingFlags.Public),
null,
new HarmonyLib.HarmonyMethod(typeof(PickupArmMovement).GetMethod(nameof(OnAvatarReinitialize_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
HarmonyInstance.Patch(
typeof(CVRPickupObject).GetMethod("OnGrab", BindingFlags.Instance | BindingFlags.NonPublic),
null,
new HarmonyLib.HarmonyMethod(typeof(PickupArmMovement).GetMethod(nameof(OnCVRPickupObjectGrab_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
HarmonyInstance.Patch(
typeof(CVRPickupObject).GetMethod("OnDrop", BindingFlags.Instance | BindingFlags.NonPublic),
null,
new HarmonyLib.HarmonyMethod(typeof(PickupArmMovement).GetMethod(nameof(OnCVRPickupObjectDrop_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
HarmonyInstance.Patch(
typeof(PlayerSetup).GetMethod("SetPlaySpaceScale", BindingFlags.NonPublic | BindingFlags.Instance),
null,
new HarmonyLib.HarmonyMethod(typeof(PickupArmMovement).GetMethod(nameof(OnPlayspaceScale_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
);
GameEvents.Init(HarmonyInstance);
MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer());
}
@ -65,96 +24,9 @@ namespace ml_pam
public override void OnDeinitializeMelon()
{
if(ms_instance == this)
ms_instance = null;
if(m_localMover != null)
UnityEngine.Object.Destroy(m_localMover);
m_localMover = null;
}
static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear();
void OnAvatarClear()
{
try
{
if(m_localMover != null)
m_localMover.OnAvatarClear();
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar();
void OnSetupAvatar()
{
try
{
if(m_localMover != null)
m_localMover.OnAvatarSetup();
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnAvatarReinitialize_Postfix() => ms_instance?.OnAvatarReinitialize();
void OnAvatarReinitialize()
{
try
{
if(m_localMover != null)
m_localMover.OnAvatarReinitialize();
}
catch(System.Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnCVRPickupObjectGrab_Postfix(ref CVRPickupObject __instance, Vector3 __0) => ms_instance?.OnCVRPickupObjectGrab(__instance, __0);
void OnCVRPickupObjectGrab(CVRPickupObject p_pickup, Vector3 p_hit)
{
try
{
if(p_pickup.IsGrabbedByMe && (m_localMover != null))
m_localMover.OnPickupGrab(p_pickup, p_hit);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnCVRPickupObjectDrop_Postfix(ref CVRPickupObject __instance) => ms_instance?.OnCVRPickupObjectDrop(__instance);
void OnCVRPickupObjectDrop(CVRPickupObject p_pickup)
{
try
{
if(m_localMover != null)
m_localMover.OnPickupDrop(p_pickup);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnPlayspaceScale_Postfix(float ____avatarScaleRelation) => ms_instance?.OnPlayspaceScale(____avatarScaleRelation);
void OnPlayspaceScale(float p_relation)
{
try
{
if(m_localMover != null)
m_localMover.OnPlayspaceScale(p_relation);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
}
}

View file

@ -1,4 +1,4 @@
[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.1.1", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.1.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
[assembly: MelonLoader.MelonPriority(1)]
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]

View file

@ -6,6 +6,14 @@ namespace ml_pam
{
static class Settings
{
internal class SettingEvent<T>
{
event Action<T> m_action;
public void AddHandler(Action<T> p_listener) => m_action += p_listener;
public void RemoveHandler(Action<T> p_listener) => m_action -= p_listener;
public void Invoke(T p_value) => m_action?.Invoke(p_value);
}
public enum ModSetting
{
Enabled = 0,
@ -28,10 +36,10 @@ namespace ml_pam
static MelonLoader.MelonPreferences_Category ms_category = null;
static List<MelonLoader.MelonPreferences_Entry> ms_entries = null;
public static event Action<bool> EnabledChange;
public static event Action<float> GrabOffsetChange;
public static event Action<LeadHand> LeadingHandChange;
public static event Action<bool> HandsExtensionChange;
public static readonly SettingEvent<bool> OnEnabledChanged = new SettingEvent<bool>();
public static readonly SettingEvent<float> OnGrabOffsetChanged = new SettingEvent<float>();
public static readonly SettingEvent<LeadHand> OnLeadingHandChanged = new SettingEvent<LeadHand>();
public static readonly SettingEvent<bool> OnHandsExtensionChanged = new SettingEvent<bool>();
internal static void Init()
{
@ -79,61 +87,83 @@ namespace ml_pam
static void OnToggleUpdate(string p_name, string p_value)
{
if(Enum.TryParse(p_name, out ModSetting l_setting))
try
{
switch(l_setting)
if(Enum.TryParse(p_name, out ModSetting l_setting))
{
case ModSetting.Enabled:
switch(l_setting)
{
Enabled = bool.Parse(p_value);
EnabledChange?.Invoke(Enabled);
case ModSetting.Enabled:
{
Enabled = bool.Parse(p_value);
OnEnabledChanged.Invoke(Enabled);
}
break;
case ModSetting.HandsExtension:
{
HandsExtension = bool.Parse(p_value);
OnHandsExtensionChanged.Invoke(HandsExtension);
}
break;
}
break;
case ModSetting.HandsExtension:
{
HandsExtension = bool.Parse(p_value);
HandsExtensionChange?.Invoke(HandsExtension);
} break;
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
}
ms_entries[(int)l_setting].BoxedValue = bool.Parse(p_value);
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnSliderUpdate(string p_name, string p_value)
{
if(Enum.TryParse(p_name, out ModSetting l_setting))
try
{
switch(l_setting)
if(Enum.TryParse(p_name, out ModSetting l_setting))
{
case ModSetting.GrabOffset:
switch(l_setting)
{
GrabOffset = int.Parse(p_value) * 0.01f;
GrabOffsetChange?.Invoke(GrabOffset);
case ModSetting.GrabOffset:
{
GrabOffset = int.Parse(p_value) * 0.01f;
OnGrabOffsetChanged.Invoke(GrabOffset);
}
break;
}
break;
}
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value);
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value);
}
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
static void OnDropdownUpdate(string p_name, string p_value)
{
if(Enum.TryParse(p_name, out ModSetting l_setting))
try
{
switch(l_setting)
if(Enum.TryParse(p_name, out ModSetting l_setting))
{
case ModSetting.LeadHand:
switch(l_setting)
{
LeadingHand = (LeadHand)int.Parse(p_value);
LeadingHandChange?.Invoke(LeadingHand);
case ModSetting.LeadHand:
{
LeadingHand = (LeadHand)int.Parse(p_value);
OnLeadingHandChanged.Invoke(LeadingHand);
}
break;
}
break;
}
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value);
ms_entries[(int)l_setting].BoxedValue = int.Parse(p_value);
}
}
catch(Exception e)
{
MelonLoader.MelonLogger.Error(e);
}
}
}

View file

@ -4,7 +4,7 @@
<TargetFramework>netstandard2.1</TargetFramework>
<Platforms>x64</Platforms>
<PackageId>PickupArmMovement</PackageId>
<Version>1.1.1</Version>
<Version>1.1.2</Version>
<Authors>SDraw</Authors>
<Company>None</Company>
<Product>PickupArmMovement</Product>