private static void AMsubMenu() { CustomSubMenu.AddToggle("FLux Enabled", !Main.fluxObj?.Equals(null) ?? false, (action) => { Main.ToggleObject(); }, null); CustomSubMenu.AddRadialPuppet("HDRClamp", f => Main.flux_HDRClamp.Value = f, Main.flux_HDRClamp.Value, HDR); CustomSubMenu.AddRadialPuppet("Hue", f => Main.flux_Hue.Value = f, Main.flux_Hue.Value, Hue); CustomSubMenu.AddRadialPuppet("Colorize", f => Main.flux_Colorize.Value = f, Main.flux_Colorize.Value, Colorize); CustomSubMenu.AddRadialPuppet("Brightness", f => Main.flux_Brightness.Value = f, Main.flux_Brightness.Value, Bright); CustomSubMenu.AddRadialPuppet("Desat", f => Main.flux_Desat.Value = f, Main.flux_Desat.Value, Desat); StoredMenu(); CustomSubMenu.AddSubMenu("Extras", () => { CustomSubMenu.AddSubMenu($"\nReset", () => { CustomSubMenu.AddButton($"\n<size=30>Confirm Reset</size>", () => { Main.pauseOnValueChange = true; Main.flux_HDRClamp.Value = .222f; Main.flux_Hue.Value = .102f; Main.flux_Colorize.Value = .75f; Main.flux_Brightness.Value = .623f; Main.flux_Desat.Value = .255f; Main.pauseOnValueChange = false; Main.OnValueChange(0f, 0f); }, checkmark); }, reset); CustomSubMenu.AddButton($"*Rotary puppets max out at 97%\n*Slot names can be changed in Mod Settings", () => { }, null); CustomSubMenu.AddButton($"Uses:\nVRChat Flux Bloom Removal Shader\nrollthered.\nbooth.pm", () => { }, null); }, gears); }
public static void ActionMenuIntegration() { VRCActionMenuPage.AddSubMenu(ActionMenuPage.Main, "<color=#00a2ff>Tracking Rotator</color>", () => { CustomSubMenu.AddButton("Forward", () => Move(Main.Transform.right), Assets.Forward); //X+ CustomSubMenu.AddButton("Backward", () => Move(-Main.Transform.right), Assets.Backward); //X- CustomSubMenu.AddButton("Tilt Left", () => Move(Main.Transform.forward), Assets.TLeft); //Z+ CustomSubMenu.AddButton("Tilt Right", () => Move(-Main.Transform.forward), Assets.TRight); //Z- CustomSubMenu.AddButton("Left", () => Move(-Main.Transform.up), Assets.Left); //Y- CustomSubMenu.AddButton("Right", () => Move(Main.Transform.up), Assets.Right); //Y+ CustomSubMenu.AddSubMenu("Other", () => { CustomSubMenu.AddButton("Reset", () => CameraTransform.localRotation = OriginalRotation, Assets.Reset); CustomSubMenu.AddToggle("High precision", HighPrecision, b => HighPrecision = b, Assets.Hp); }, Assets.Other); }, Assets.Main); }
public override void OnApplicationStart() { /* Register settings */ Settings.RegisterConfig(); /* Load audio settings */ WorldAudio.LoadConfig(); /* Load avatar parameters */ Parameters.LoadConfig(); /* Load our custom UI elements */ UiExpansion.LoadUiObjects(); /* TODO: Consider switching to operator+ when everyone had to update the assembly unhollower */ /* The current solution might be prefereable so we are always first */ VRCAvatarManager.field_Private_Static_Action_3_Player_GameObject_VRC_AvatarDescriptor_0 += (Il2CppSystem.Action <Player, GameObject, VRC.SDKBase.VRC_AvatarDescriptor>)OnAvatarInstantiate; /* Register async, awaiting network manager */ MelonCoroutines.Start(RegisterJoinLeaveNotifier()); ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("Player List", PlayerList); ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("WorldCleanup", MainMenu); ExpansionKitApi.GetExpandedMenu(ExpandedMenu.UserQuickMenu).AddSimpleButton("Avatar Toggles", OnUserQuickMenu); /* Hook into setter for parameter properties */ unsafe { var param_prop_bool_set = (IntPtr)typeof(AvatarParameter).GetField("NativeMethodInfoPtr_Method_Public_Virtual_Final_New_set_Void_Boolean_0", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); MelonUtils.NativeHookAttach(param_prop_bool_set, new Action <IntPtr, bool>(Parameters.BoolPropertySetter).Method.MethodHandle.GetFunctionPointer()); Parameters._boolPropertySetterDelegate = Marshal.GetDelegateForFunctionPointer <Parameters.BoolPropertySetterDelegate>(*(IntPtr *)(void *)param_prop_bool_set); var param_prop_int_set = (IntPtr)typeof(AvatarParameter).GetField("NativeMethodInfoPtr_Method_Public_Virtual_Final_New_set_Void_Int32_0", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); MelonUtils.NativeHookAttach(param_prop_int_set, new Action <IntPtr, int>(Parameters.IntPropertySetter).Method.MethodHandle.GetFunctionPointer()); Parameters._intPropertySetterDelegate = Marshal.GetDelegateForFunctionPointer <Parameters.IntPropertySetterDelegate>(*(IntPtr *)(void *)param_prop_int_set); var param_prop_float_set = (IntPtr)typeof(AvatarParameter).GetField("NativeMethodInfoPtr_Method_Public_Virtual_Final_New_set_Void_Single_0", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null); MelonUtils.NativeHookAttach(param_prop_float_set, new Action <IntPtr, float>(Parameters.FloatPropertySetter).Method.MethodHandle.GetFunctionPointer()); Parameters._floatPropertySetterDelegate = Marshal.GetDelegateForFunctionPointer <Parameters.FloatPropertySetterDelegate>(*(IntPtr *)(void *)param_prop_float_set); } AMUtils.AddToModsFolder("Player Toggles", () => { /* Filter inactive avatar objects */ s_PlayerList = s_PlayerList.Where(o => o.Value).ToDictionary(o => o.Key, o => o.Value); /* Order by physical distance to camera */ var query = from player in s_PlayerList orderby Vector3.Distance(player.Value.transform.position, Camera.main.transform.position) select player; /* Only allow a max of 10 players there at once */ /* TODO: Consider adding multiple pages */ var remaining_count = 10; foreach (var entry in query) { var manager = entry.Value.GetComponentInParent <VRCAvatarManager>(); /* Ignore SDK2 & avatars w/o custom expressions */ if (!manager.HasCustomExpressions()) { continue; } var avatar_id = entry.Value.GetComponent <VRC.Core.PipelineManager>().blueprintId; var user_icon = s_Portraits[avatar_id].Get(); /* Source default expression icon */ var menu_icons = ActionMenuDriver.prop_ActionMenuDriver_0.field_Public_MenuIcons_0; var default_expression = menu_icons.defaultExpression; CustomSubMenu.AddSubMenu(entry.Key, () => { if (entry.Value == null || !entry.Value.active) { return; } var parameters = manager.GetAllAvatarParameters(); var filtered = Parameters.FilterDefaultParameters(parameters); var avatar_descriptor = manager.prop_VRCAvatarDescriptor_0; CustomSubMenu.AddToggle("Lock", filtered.Any(Parameters.IsLocked), (state) => { filtered.ForEach(state ? Parameters.Lock : Parameters.Unlock); }, icon: UiExpansion.LockClosedIcon); CustomSubMenu.AddButton("Save", () => Parameters.StoreParameters(manager), icon: UiExpansion.SaveIcon); AvatarParameter FindParameter(string name) { foreach (var parameter in parameters) { if (parameter.field_Private_String_0 == name) { return(parameter); } } return(null); } void ExpressionSubmenu(VRCExpressionsMenu expressions_menu) { if (entry.Value == null || !entry.Value.active) { return; } void FourAxisControl(VRCExpressionsMenu.Control control, Action <Vector2> callback) { CustomSubMenu.AddFourAxisPuppet( control.TruncatedName(), callback, icon: control.icon ?? default_expression, topButtonText: control.labels[0]?.TruncatedName() ?? "Up", rightButtonText: control.labels[1]?.TruncatedName() ?? "Right", downButtonText: control.labels[2]?.TruncatedName() ?? "Down", leftButtonText: control.labels[3]?.TruncatedName() ?? "Left"); } foreach (var control in expressions_menu.controls) { try { switch (control.type) { case VRCExpressionsMenu.Control.ControlType.Button: /* Note: Action Menu "Buttons" are actually Toggles */ /* that set on press and revert on release. */ /* TODO: Add proper implementation. */ case VRCExpressionsMenu.Control.ControlType.Toggle: { var param = FindParameter(control.parameter.name); var current_value = param.GetValue(); var default_value = avatar_descriptor.expressionParameters.FindParameter(control.parameter.name)?.defaultValue ?? 0f; var target_value = control.value; void SetIntFloat(bool state) => param.SetValue(state ? target_value : default_value); void SetBool(bool state) => param.SetValue(state ? 1f : 0f); CustomSubMenu.AddToggle( control.TruncatedName(), current_value == target_value, param.prop_ParameterType_0 == AvatarParameter.ParameterType.Bool ? SetBool : SetIntFloat, icon: control.icon ?? default_expression); break; } case VRCExpressionsMenu.Control.ControlType.SubMenu: { CustomSubMenu.AddSubMenu(control.TruncatedName(), () => ExpressionSubmenu(control.subMenu), icon: control.icon ?? default_expression); break; } case VRCExpressionsMenu.Control.ControlType.TwoAxisPuppet: { var horizontal = FindParameter(control.subParameters[0]?.name); var vertical = FindParameter(control.subParameters[1]?.name); FourAxisControl(control, (value) => { horizontal.SetFloatProperty(value.x); vertical.SetFloatProperty(value.y); }); break; } case VRCExpressionsMenu.Control.ControlType.FourAxisPuppet: { var up = FindParameter(control.subParameters[0]?.name); var down = FindParameter(control.subParameters[1]?.name); var left = FindParameter(control.subParameters[2]?.name); var right = FindParameter(control.subParameters[3]?.name); FourAxisControl(control, (value) => { up.SetFloatProperty(Math.Max(0, value.y)); down.SetFloatProperty(-Math.Min(0, value.y)); left.SetFloatProperty(Math.Max(0, value.x)); right.SetFloatProperty(-Math.Min(0, value.x)); }); break; } case VRCExpressionsMenu.Control.ControlType.RadialPuppet: { var param = FindParameter(control.subParameters[0]?.name); CustomSubMenu.AddRestrictedRadialPuppet(control.TruncatedName(), param.SetValue, startingValue: param.GetValue(), icon: control.icon ?? default_expression); break; } } } catch (Exception e) { MelonLogger.Error(e.StackTrace); } } } ExpressionSubmenu(avatar_descriptor.expressionsMenu); }, icon: user_icon); if (--remaining_count == 0) { break; } } }); MelonLogger.Msg(ConsoleColor.Green, "WorldCleanup ready!"); }
private static void MirrorMenu(string MirrorType, MelonPreferences_Entry <string> prefState, MelonPreferences_Entry <bool> prefPickup, MelonPreferences_Entry <float> prefDist, MelonPreferences_Entry <float> prefX, MelonPreferences_Entry <float> prefY, MelonPreferences_Entry <bool> prefPos, MelonPreferences_Entry <bool> prefTracking) { string MirrorScaleType = "MirrorScale" + (MirrorType == "PortableMirrorCeiling" ? "Z" : "Y"); float Scale = (MirrorType == "PortableMirrorMicro" ? .01f : .25f); CustomSubMenu.AddSubMenu("Mirror Type", () => { CustomSubMenu.AddButton("Full", () => { prefState.Value = "MirrorFull"; Main main = new Main(); main.OnPreferencesSaved(); }, MirrorFull); CustomSubMenu.AddButton("Optimized", () => { prefState.Value = "MirrorOpt"; Main main = new Main(); main.OnPreferencesSaved(); }, MirrorOpt); CustomSubMenu.AddButton("Cutout", () => { prefState.Value = "MirrorCutout"; Main main = new Main(); main.OnPreferencesSaved(); }, MirrorCut); CustomSubMenu.AddButton("Transparent", () => { prefState.Value = "MirrorTransparent"; Main main = new Main(); main.OnPreferencesSaved(); }, MirrorTrans); CustomSubMenu.AddButton("Cutout Solo", () => { prefState.Value = "MirrorCutoutSolo"; Main main = new Main(); main.OnPreferencesSaved(); }, MirrorCutSolo); CustomSubMenu.AddButton("Transparent Solo", () => { prefState.Value = "MirrorTransparentSolo"; Main main = new Main(); main.OnPreferencesSaved(); }, MirrorTransSolo); }, MirrorOptions); CustomSubMenu.AddToggle("Can Pickup", prefPickup.Value, (action) => { prefPickup.Value = !prefPickup.Value; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, Grab); CustomSubMenu.AddSubMenu("Location & Size", () => { if (MirrorType != "PortableMirrorMicro") { CustomSubMenu.AddButton($"Distance +\n{prefDist.Value.ToString("F2").TrimEnd('0')}", () => { prefDist.Value += Main._mirrorDistAdj; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, DistPlus); CustomSubMenu.AddButton($"Distance -\n{prefDist.Value.ToString("F2").TrimEnd('0')}", () => { prefDist.Value -= Main._mirrorDistAdj; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, DistMinus); } CustomSubMenu.AddButton("Larger", () => { prefX.Value += Scale; prefY.Value += Scale; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, SizePlus); CustomSubMenu.AddButton("Smaller", () => { if ((prefX.Value > Scale * (MirrorType == "PortableMirrorMicro" ? 2f : 1f)) && prefY.Value > Scale * (MirrorType == "PortableMirrorMicro" ? 2f : 1f)) { prefX.Value -= Scale; prefY.Value -= Scale; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); } }, SizeMinus); }, MirrorRuler); if (MirrorType == "PortableMirror" || MirrorType == "PortableMirrorTrans" || MirrorType == "PortableMirrorMicro") { CustomSubMenu.AddToggle("Pos&Rotation from View", prefPos.Value, (action) => { prefPos.Value = !prefPos.Value; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, PosfromView); } CustomSubMenu.AddToggle("Mirror follows you", prefTracking.Value, (action) => { prefTracking.Value = !prefTracking.Value; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, FollowsYou); }
private static void AMsubMenu() { CustomSubMenu.AddSubMenu("Portable Mirror", () => { CustomSubMenu.AddToggle("Enable", (Main._mirrorBase != null), (action) => { if (Utils.GetVRCPlayer() != null) { Main.ToggleMirror(); } AMUtils.RefreshActionMenu(); }, MirrorBase); MirrorMenu("PortableMirror", Main._base_MirrorState, Main._base_CanPickupMirror, Main._base_MirrorDistance, Main._base_MirrorScaleX, Main._base_MirrorScaleY, Main._base_PositionOnView, Main._base_AnchorToTracking); }, MirrorBase); CustomSubMenu.AddSubMenu("45 Mirror", () => { CustomSubMenu.AddToggle("Enable", (Main._mirror45 != null), (action) => { if (Utils.GetVRCPlayer() != null) { Main.ToggleMirror45(); } AMUtils.RefreshActionMenu(); }, Mirror45); MirrorMenu("PortableMirror45", Main._45_MirrorState, Main._45_CanPickupMirror, Main._45_MirrorDistance, Main._45_MirrorScaleX, Main._45_MirrorScaleY, Main.Spacer1, Main._45_AnchorToTracking); }, Mirror45); CustomSubMenu.AddSubMenu("Ceiling Mirror", () => { CustomSubMenu.AddToggle("Enable", (Main._mirrorCeiling != null), (action) => { if (Utils.GetVRCPlayer() != null) { Main.ToggleMirrorCeiling(); } AMUtils.RefreshActionMenu(); }, MirrorCeil); MirrorMenu("PortableMirrorCeiling", Main._ceil_MirrorState, Main._ceil_CanPickupMirror, Main._ceil_MirrorDistance, Main._ceil_MirrorScaleX, Main._ceil_MirrorScaleZ, Main.Spacer1, Main._ceil_AnchorToTracking); }, MirrorCeil); CustomSubMenu.AddSubMenu("Micro Mirror", () => { CustomSubMenu.AddToggle("Enable", (Main._mirrorMicro != null), (action) => { if (Utils.GetVRCPlayer() != null) { Main.ToggleMirrorMicro(); } AMUtils.RefreshActionMenu(); }, MirrorMicro); MirrorMenu("PortableMirrorMicro", Main._micro_MirrorState, Main._micro_CanPickupMirror, Main._base_MirrorDistance, Main._micro_MirrorScaleX, Main._micro_MirrorScaleY, Main._micro_PositionOnView, Main._micro_AnchorToTracking); }, MirrorMicro); CustomSubMenu.AddSubMenu("Transparent Mirror", () => { CustomSubMenu.AddToggle("Enable", (Main._mirrorTrans != null), (action) => { if (Utils.GetVRCPlayer() != null) { Main.ToggleMirrorTrans(); } AMUtils.RefreshActionMenu(); }, MirrorTrans); MirrorMenu("PortableMirrorTrans", Main._trans_MirrorState, Main._trans_CanPickupMirror, Main._trans_MirrorDistance, Main._trans_MirrorScaleX, Main._trans_MirrorScaleY, Main._trans_PositionOnView, Main._trans_AnchorToTracking); }, MirrorTrans); CustomSubMenu.AddSubMenu("Extras", () => { CustomSubMenu.AddButton($"Transparency:\n{Main.TransMirrorTrans.Value}", () => { Main.TransMirrorTrans.Value += .1f; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, TransPlus); CustomSubMenu.AddButton($"Transparency:\n{Main.TransMirrorTrans.Value}", () => { Main.TransMirrorTrans.Value -= .1f; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, TransMinus); CustomSubMenu.AddToggle("Mirrors Show In Camera", Main.MirrorsShowInCamera.Value, (action) => { Main.MirrorsShowInCamera.Value = !Main.MirrorsShowInCamera.Value; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, CameraMirror); CustomSubMenu.AddToggle("High Precision Adjust", Main._mirrorDistHighPrec, (action) => { Main._mirrorDistHighPrec = !Main._mirrorDistHighPrec; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, DistAdjIcon); CustomSubMenu.AddButton($"ColliderDepth:\n{Main.ColliderDepth.Value.ToString("F2").TrimEnd('0')}", () => { Main.ColliderDepth.Value += .1f; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, GrabDistPlus); CustomSubMenu.AddButton($"ColliderDepth:\n{Main.ColliderDepth.Value.ToString("F2").TrimEnd('0')}", () => { if (Main.ColliderDepth.Value > .1f) { Main.ColliderDepth.Value -= .1f; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); } }, GrabDistMinus); CustomSubMenu.AddToggle("Pickups snap to hand", Main.PickupToHand.Value, (action) => { Main.PickupToHand.Value = !Main.PickupToHand.Value; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, SnapToHand); CustomSubMenu.AddToggle("All Pickupable", Main._AllPickupable, (action) => { Main._AllPickupable = !Main._AllPickupable; Main._base_CanPickupMirror.Value = Main._AllPickupable; Main._45_CanPickupMirror.Value = Main._AllPickupable; Main._ceil_CanPickupMirror.Value = Main._AllPickupable; Main._micro_CanPickupMirror.Value = Main._AllPickupable; Main._trans_CanPickupMirror.Value = Main._AllPickupable; Main main = new Main(); main.OnPreferencesSaved(); AMUtils.RefreshActionMenu(); }, Grab); }, SettingsGear); }
public static PedalOption AddTogglePedalToSubMenu(string text, bool startingState, Action <bool> onToggle, Texture2D icon = null) { return(CustomSubMenu.AddToggle(text, startingState, onToggle, icon)); }