diff --git a/ActionMenuApi/ActionMenuApi.cs b/ActionMenuApi/ActionMenuApi.cs index 42a9df9..16c27f0 100644 --- a/ActionMenuApi/ActionMenuApi.cs +++ b/ActionMenuApi/ActionMenuApi.cs @@ -1,7 +1,7 @@ using ActionMenuApi.Managers; using MelonLoader; #pragma warning disable 1591 -[assembly: MelonInfo(typeof(ActionMenuApi.ActionMenuApi), "ActionMenuApi", "0.1.2", "gompo", "https://github.com/gompocp/ActionMenuApi/releases")] +[assembly: MelonInfo(typeof(ActionMenuApi.ActionMenuApi), "ActionMenuApi", "0.2.0", "gompo", "https://github.com/gompocp/ActionMenuApi/releases")] [assembly: MelonGame("VRChat", "VRChat")] namespace ActionMenuApi diff --git a/ActionMenuApi/Api/CustomSubMenu.cs b/ActionMenuApi/Api/CustomSubMenu.cs index ad4b842..3369b58 100644 --- a/ActionMenuApi/Api/CustomSubMenu.cs +++ b/ActionMenuApi/Api/CustomSubMenu.cs @@ -11,6 +11,9 @@ namespace ActionMenuApi.Api { + /// <summary> + /// Class for adding buttons,toggles,radial puppets inside of a custom submenu + /// </summary> public static class CustomSubMenu { /// <summary> @@ -18,8 +21,8 @@ public static class CustomSubMenu /// </summary> /// <param name="text">Button text</param> /// <param name="triggerEvent">Button click action</param> - /// <param name="locked">The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <returns> PedalOption Instance (Note: 1. can be null if both action menus are open 2. The gameobject that it is attached to is destroyed when you change page on the action menu)</returns> public static PedalOption AddButton(string text, Action triggerEvent, Texture2D icon = null, bool locked = false) { @@ -39,9 +42,9 @@ public static PedalOption AddButton(string text, Action triggerEvent, Texture2D /// </summary> /// <param name="text">Button text</param> /// <param name="onUpdate">Calls action with a float between 0 - 1 depending on the current value of the radial puppet</param> - /// <param name="locked">The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="startingValue">(optional) Starting value for radial puppet 0-1</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <returns> PedalOption Instance (Note: the gameobject that it is attached to is destroyed when you change page on the action menu</returns> public static PedalOption AddRadialPuppet(string text, Action<float> onUpdate, float startingValue = 0, Texture2D icon = null, bool locked = false) { @@ -72,8 +75,8 @@ public static PedalOption AddRadialPuppet(string text, Action<float> onUpdate, f /// </summary> /// <param name="text">Button text</param> /// <param name="onUpdate">Calls action with a Vector2 with x and y being between -1 and 1 depending on the current value of the four axis puppet</param> - /// <param name="locked">The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="topButtonText">(optional) Top Button Button text On Four Axis Puppet</param> /// <param name="rightButtonText">(optional) Right Button Button text On Four Axis Puppet</param> /// <param name="downButtonText">(optional) Bottom Button Button text On Four Axis Puppet</param> @@ -107,8 +110,8 @@ public static PedalOption AddFourAxisPuppet(string text, Action<Vector2> onUpdat /// </summary> /// <param name="text">Button text</param> /// <param name="openFunc">Function called when page opened. Add your methods calls to other AMAPI methods such AddRadialPedalToSubMenu to add buttons to the submenu it creates when clicked</param> - /// <param name="locked">The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="closeFunc">(optional) Function called when page closes</param> /// <returns> PedalOption Instance (Note: the gameobject that it is attached to is destroyed when you change page on the action menu</returns> public static PedalOption AddSubMenu(string text, Action openFunc, Texture2D icon = null, bool locked = false, Action closeFunc = null) @@ -135,12 +138,11 @@ public static PedalOption AddSubMenu(string text, Action openFunc, Texture2D ico /// <param name="text">Button text</param> /// <param name="startingState">Starting value of the toggle pedal everytime the pedal is created</param> /// <param name="onToggle">Calls action with a bool depending on the current value of the toggle</param> - /// <param name="locked">The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <returns> PedalOption Instance (Note: the gameobject that it is attached to is destroyed when you change page on the action menu</returns> public static PedalOption AddToggle(string text, bool startingState, Action<bool> onToggle, Texture2D icon = null, bool locked = false) { - ActionMenuOpener actionMenuOpener = Utilities.GetActionMenuOpener(); if (actionMenuOpener == null) return null; PedalOption pedalOption = actionMenuOpener.GetActionMenu().AddOption(); diff --git a/ActionMenuApi/Api/VRCActionMenuPage.cs b/ActionMenuApi/Api/VRCActionMenuPage.cs index 483faf9..3dbe724 100644 --- a/ActionMenuApi/Api/VRCActionMenuPage.cs +++ b/ActionMenuApi/Api/VRCActionMenuPage.cs @@ -15,6 +15,7 @@ public static class VRCActionMenuPage /// <param name="text">Button text</param> /// <param name="triggerEvent">Button click action</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="insertion">(optional) Determines whether or not the button is added before or after VRChat's buttons for the target page</param> public static PedalButton AddButton(ActionMenuPage pageType, string text, Action triggerEvent, Texture2D icon = null, bool locked = false, Insertion insertion = Insertion.Post) { @@ -22,7 +23,7 @@ public static PedalButton AddButton(ActionMenuPage pageType, string text, Action AddPedalToList(pageType, pedal, insertion); return pedal; } - + /// <summary> /// Add a radial puppet button pedal to a specific ActionMenu page /// </summary> @@ -31,6 +32,7 @@ public static PedalButton AddButton(ActionMenuPage pageType, string text, Action /// <param name="onUpdate">Calls action with a float between 0 - 1 depending on the current value of the radial puppet</param> /// <param name="startingValue">(optional) Starting value for radial puppet 0-1</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="insertion">(optional) Determines whether or not the button is added before or after VRChat's buttons for the target page</param> public static PedalRadial AddRadialPuppet(ActionMenuPage pageType, string text, Action<float> onUpdate, float startingValue = 0, Texture2D icon = null, bool locked = false, Insertion insertion = Insertion.Post) { @@ -38,7 +40,7 @@ public static PedalRadial AddRadialPuppet(ActionMenuPage pageType, string text, AddPedalToList(pageType, pedal, insertion); return pedal; } - + /// <summary> /// Add a four axis puppet button pedal to a specific ActionMenu page /// </summary> @@ -47,6 +49,7 @@ public static PedalRadial AddRadialPuppet(ActionMenuPage pageType, string text, /// <param name="onUpdate">Calls action with a Vector2 with x and y being between -1 and 1 depending on the current value of the four axis puppet</param> /// <param name="icon">(optional) The Button Icon</param> /// <param name="insertion">(optional) Determines whether or not the button is added before or after VRChat's buttons for the target page</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="topButtonText">(optional) Top Button Button text On Four Axis Puppet</param> /// <param name="rightButtonText">(optional) Right Button Button text On Four Axis Puppet</param> /// <param name="downButtonText">(optional) Bottom Button Button text On Four Axis Puppet</param> @@ -58,7 +61,7 @@ public static PedalFourAxis AddFourAxisPuppet(ActionMenuPage pageType, string te AddPedalToList(pageType, pedal, insertion); return pedal; } - + /// <summary> /// Add a submenu to an ActionMenu page /// </summary> @@ -66,6 +69,7 @@ public static PedalFourAxis AddFourAxisPuppet(ActionMenuPage pageType, string te /// <param name="text">Button text</param> /// <param name="openFunc">Function called when page opened. Add your methods calls to other AMAPI methods such AddRadialPedalToSubMenu to add buttons to the submenu it creates when clicked</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="closeFunc">(optional) Function called when page closes</param> /// <param name="insertion">(optional) Determines whether or not the button is added before or after VRChat's buttons for the target page</param> public static PedalSubMenu AddSubMenu(ActionMenuPage pageType, string text, Action openFunc, Texture2D icon = null, bool locked = false, Action closeFunc = null, Insertion insertion = Insertion.Post) @@ -74,7 +78,7 @@ public static PedalSubMenu AddSubMenu(ActionMenuPage pageType, string text, Acti AddPedalToList(pageType, pedal, insertion); return pedal; } - + /// <summary> /// Add a toggle button pedal to an ActionMenu page /// </summary> @@ -83,6 +87,7 @@ public static PedalSubMenu AddSubMenu(ActionMenuPage pageType, string text, Acti /// <param name="startingState">Starting value of the toggle pedal everytime the pedal is created</param> /// <param name="onToggle">Calls action with a bool depending on the current value of the toggle</param> /// <param name="icon">(optional) The Button Icon</param> + /// <param name="locked">(optional)The starting state for the lockable pedal, true = locked, false = unlocked</param> /// <param name="insertion">(optional) Determines whether or not the button is added before or after VRChat's buttons for the target page</param> public static PedalToggle AddToggle(ActionMenuPage pageType, string text, bool startingState, Action<bool> onToggle, Texture2D icon = null, bool locked = false, Insertion insertion = Insertion.Post) { @@ -93,7 +98,7 @@ public static PedalToggle AddToggle(ActionMenuPage pageType, string text, bool s internal static void AddPedalToList(ActionMenuPage pageType, PedalStruct customPedal, Insertion insertion) { - Logger.Log($"Adding: {pageType.ToString()}, Text: {customPedal.text}, Locked: {customPedal.locked}"); + Logger.Log($"Adding to page: {pageType.ToString()}, Text: {customPedal.text}, Locked: {customPedal.locked}"); switch (pageType) { case ActionMenuPage.SDK2Expression: diff --git a/ActionMenuApi/Stuff/Utilities.cs b/ActionMenuApi/Stuff/Utilities.cs index c8c620d..e5fe732 100644 --- a/ActionMenuApi/Stuff/Utilities.cs +++ b/ActionMenuApi/Stuff/Utilities.cs @@ -67,8 +67,8 @@ public static void AddPedalsInList(List<PedalStruct> list, ActionMenu instance) PedalOption pedalOption = instance.AddOption(); pedalOption.SetText(pedalStruct.text); pedalOption.SetIcon(pedalStruct.icon); - pedalOption.SetPedalTriggerEvent( - DelegateSupport.ConvertDelegate<PedalOptionTriggerEvent>(pedalStruct.triggerEvent)); + if(!pedalStruct.locked) pedalOption.SetPedalTriggerEvent(DelegateSupport.ConvertDelegate<PedalOptionTriggerEvent>(pedalStruct.triggerEvent)); + else ResourcesManager.AddLockChildIcon(pedalOption.GetActionButton().gameObject.GetChild("Inner")); //Additional setup for pedals switch (pedalStruct.Type) { diff --git a/ActionMenuTestMod/ActionMenuTestMod.cs b/ActionMenuTestMod/ActionMenuTestMod.cs index 511bbb5..7cecbab 100644 --- a/ActionMenuTestMod/ActionMenuTestMod.cs +++ b/ActionMenuTestMod/ActionMenuTestMod.cs @@ -2,6 +2,7 @@ using System.Reflection; using ActionMenuApi; using ActionMenuApi.Api; +using ActionMenuApi.Pedals; using ActionMenuApi.Types; using MelonLoader; using UnhollowerRuntimeLib; @@ -51,18 +52,19 @@ public override void OnApplicationStart() buttonIcon = iconsAssetBundle.LoadAsset_Internal("Assets/Resources/Icons/cloud-data-download.png", Il2CppType.Of<Texture2D>()).Cast<Texture2D>(); buttonIcon.hideFlags |= HideFlags.DontUnloadUnusedAsset; - AMAPI.AddButtonPedalToMenu(ActionMenuPageType.Main, "Button",() => MelonLogger.Msg("Pressed Button"), buttonIcon); + VRCActionMenuPage.AddButton(ActionMenuPage.Main, "Button",() => MelonLogger.Msg("Pressed Button"), buttonIcon); - AMAPI.AddTogglePedalToMenu(ActionMenuPageType.Config, "Toggle", testBool, b => testBool = b); + PedalSubMenu subMenu = VRCActionMenuPage.AddSubMenu(ActionMenuPage.Config, "Toggle", () => { }, null, true); + subMenu.locked = true; - AMAPI.AddModFolder( + AMUtils.AddToModsFolder( "Test Stuff", delegate { - AMAPI.AddTogglePedalToSubMenu("Risky Functions", !riskyFunctionsAllowed, (b) => + CustomSubMenu.AddToggle("Risky Functions", !riskyFunctionsAllowed, (b) => { riskyFunctionsAllowed = !b; - AMUtils.RefreshActionMenu(); + AMUtils.RefreshActionMenu(); //Refresh menu to update the locked state of the pedal }); //No properties here are saved because I'm lazy af CustomSubMenu.AddToggle("Enable Hax", false, b => { }, null,riskyFunctionsAllowed); @@ -76,8 +78,29 @@ public override void OnApplicationStart() }, subMenuIcon ); + + //Purely for backwards compatibility testing + AMUtils.AddToModsFolder( + "New Cube Stuff", + delegate + { + CustomSubMenu.AddFourAxisPuppet("Reposition cube X/Y", (v) => RePositionCubeXY(v), toggleIcon); + CustomSubMenu.AddFourAxisPuppet("Reposition cube Z/Y", RePositionCubeZY, toggleIcon); + CustomSubMenu.AddFourAxisPuppet("Reposition cube X/Z", RePositionCubeXZ, toggleIcon); + CustomSubMenu.AddRadialPuppet("X",RotateCubeX, x,radialIcon); //Rotation a bit borked + CustomSubMenu.AddToggle("Test Toggle", testBool2, (b) => testBool2 = b); + CustomSubMenu.AddRadialPuppet("Y",RotateCubeY, y,radialIcon); + CustomSubMenu.AddRadialPuppet("Z",RotateCubeZ, z,radialIcon); + CustomSubMenu.AddButton("Spawn Cube", CreateCube, buttonIcon); + CustomSubMenu.AddButton("Tp Cube To Player",() => _controllingGameObject.transform.localPosition = VRCPlayer.field_Internal_Static_VRCPlayer_0.transform.localPosition, buttonIcon); + }, + subMenuIcon, + true + ); + + //Purely for backwards compatibility testing don't use yourself AMAPI.AddModFolder( - "Cube Stuff", + "Old Cube Stuff", delegate { AMAPI.AddFourAxisPedalToSubMenu("Reposition cube X/Y", (v) => RePositionCubeXY(v), toggleIcon); @@ -88,7 +111,7 @@ public override void OnApplicationStart() AMAPI.AddRadialPedalToSubMenu("Y",RotateCubeY, y,radialIcon); AMAPI.AddRadialPedalToSubMenu("Z",RotateCubeZ, z,radialIcon); AMAPI.AddButtonPedalToSubMenu("Spawn Cube", CreateCube, buttonIcon); - AMAPI.AddButtonPedalToSubMenu("Tp Cube To Player",() => controllingGameObject.transform.localPosition = VRCPlayer.field_Internal_Static_VRCPlayer_0.transform.localPosition, buttonIcon); + AMAPI.AddButtonPedalToSubMenu("Tp Cube To Player",() => _controllingGameObject.transform.localPosition = VRCPlayer.field_Internal_Static_VRCPlayer_0.transform.localPosition, buttonIcon); }, subMenuIcon ); @@ -108,50 +131,51 @@ public override void OnUpdate() private static void CreateCube() { - controllingGameObject = GameObject.CreatePrimitive(PrimitiveType.Cube); - controllingGameObject.GetComponent<Collider>().enabled = false; - x = controllingGameObject.transform.eulerAngles.x*360; - y = controllingGameObject.transform.eulerAngles.y*360; - z = controllingGameObject.transform.eulerAngles.z*360; + _controllingGameObject = GameObject.CreatePrimitive(PrimitiveType.Cube); + _controllingGameObject.GetComponent<Collider>().enabled = false; + var eulerAngles = _controllingGameObject.transform.eulerAngles; + x = eulerAngles.x*360; + y = eulerAngles.y*360; + z = eulerAngles.z*360; } private static void RePositionCubeXY(Vector3 v) { - controllingGameObject.transform.localPosition += v/25; + _controllingGameObject.transform.localPosition += v/25; } private static void RePositionCubeZY(Vector2 v) { - controllingGameObject.transform.localPosition += new Vector3(0, v.y/25, v.x/25); + _controllingGameObject.transform.localPosition += new Vector3(0, v.y/25, v.x/25); } private static void RePositionCubeXZ(Vector2 v) { - controllingGameObject.transform.localPosition += new Vector3(v.x/25, 0, v.y/25); + _controllingGameObject.transform.localPosition += new Vector3(v.x/25, 0, v.y/25); } private static void RotateCubeX(float rotation) { //This is the incorrect way of rotating the gameobject and it breaks from 90-270 as quaternions and euler angle conversions are a bit fucky - Vector3 old = controllingGameObject.transform.eulerAngles; - controllingGameObject.transform.eulerAngles = new Vector3((rotation)*360, old.y, old.z); + Vector3 old = _controllingGameObject.transform.eulerAngles; + _controllingGameObject.transform.eulerAngles = new Vector3((rotation)*360, old.y, old.z); x = rotation; } private static void RotateCubeY(float rotation) { - Vector3 old = controllingGameObject.transform.eulerAngles; + Vector3 old = _controllingGameObject.transform.eulerAngles; //MelonLogger.Msg($"Old Angles: {old.ToString()}"); - controllingGameObject.transform.eulerAngles = new Vector3(old.x, (rotation)*360, old.z); + _controllingGameObject.transform.eulerAngles = new Vector3(old.x, (rotation)*360, old.z); y = rotation; } private static void RotateCubeZ(float rotation) { - Vector3 old = controllingGameObject.transform.eulerAngles; + Vector3 old = _controllingGameObject.transform.eulerAngles; //MelonLogger.Msg($"Old Angles: {old.ToString()}"); - controllingGameObject.transform.eulerAngles = new Vector3(old.x, old.y, (rotation)*360); + _controllingGameObject.transform.eulerAngles = new Vector3(old.x, old.y, (rotation)*360); z = rotation; } - private static GameObject controllingGameObject; + private static GameObject _controllingGameObject; } } \ No newline at end of file