public AvatarModule() : base(ExpandedMenu.AvatarMenu, FavCatMod.Database.AvatarFavorites, GetListsParent(), false, DateTime.Now < FavCatMod.NoMoreVisibleAvatarFavoritesAfter) { myCurrentAnnoyingMessage = CanPerformAdditiveActions ? "WillBeObsolete" : (CanShowExistingLists ? "CantAdd" : "NoFavorites"); MelonLogger.Log("Adding button to UI - Looking up for Change Button"); var foundAvatarPage = Resources.FindObjectsOfTypeAll <PageAvatar>()?.FirstOrDefault(p => p.transform.Find("Change Button") != null); if (foundAvatarPage == null) { throw new ApplicationException("No avatar page, can't initialize extended favorites"); } myPageAvatar = foundAvatarPage; ExpansionKitApi.GetExpandedMenu(ExpandedMenu.UserDetailsMenu).AddSimpleButton("Search known public avatars", DoSearchKnownAvatars); var expandEnforcer = new GameObject(ExpandEnforcerGameObjectName, new[] { Il2CppType.Of <RectTransform>(), Il2CppType.Of <LayoutElement>() }); expandEnforcer.transform.SetParent(GetListsParent(), false); var layoutElement = expandEnforcer.GetComponent <LayoutElement>(); layoutElement.minWidth = 1534; layoutElement.minHeight = 0; myPageAvatar.gameObject.AddComponent <EnableDisableListener>().OnEnabled += () => { if (FavCatSettings.DontShowAnnoyingMessage == myCurrentAnnoyingMessage || myHasShownAnnoyingMessageThisRun) { return; } myHasShownAnnoyingMessageThisRun = true; ShowAnnoyingMessage(); }; myInitialised = true; }
public AvatarModule() : base(ExpandedMenu.AvatarMenu, FavCatMod.Database.AvatarFavorites, GetListsParent()) { MelonLogger.Log("Adding button to UI - Looking up for Change Button"); var foundAvatarPage = Resources.FindObjectsOfTypeAll <PageAvatar>()?.FirstOrDefault(p => p.transform.Find("Change Button") != null); if (foundAvatarPage == null) { throw new ApplicationException("No avatar page, can't initialize extended favorites"); } myPageAvatar = foundAvatarPage; ExpansionKitApi.GetExpandedMenu(ExpandedMenu.UserDetailsMenu).AddSimpleButton("Search known public avatars", DoSearchKnownAvatars); var expandEnforcer = new GameObject(ExpandEnforcerGameObjectName, new[] { Il2CppType.Of <RectTransform>(), Il2CppType.Of <LayoutElement>() }); expandEnforcer.transform.SetParent(GetListsParent(), false); var layoutElement = expandEnforcer.GetComponent <LayoutElement>(); layoutElement.minWidth = 1534; layoutElement.minHeight = 0; myInitialised = true; }
public override void OnApplicationStart() { ICustomLayoutedMenu settingsPage = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu); settingsPage.AddSimpleButton("Unblock unpack queue", delegate { Utilities.UnblockUnPackQueue(); }); }
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 AddUixActions() { ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu).AddSimpleButton("More IKTweaks...", ShowIKTweaksMenu); }
public static void SetupUIX() { ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SafetyMenu).AddSimpleButton($"Load Custom Safety Settings", OpenLoadMenu); ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SafetyMenu).AddSimpleButton($"Save Custom Safety Settings", OpenSaveMenu); }
public PlayersModule() : base(ExpandedMenu.SocialMenu, FavCatMod.Database.PlayerFavorites, GetListsParent(), false) { ExpansionKitApi.GetExpandedMenu(ExpandedMenu.UserDetailsMenu).AddSimpleButton("Local Favorite", ShowFavMenu); PageUserInfo = GameObject.Find("UserInterface/MenuContent/Screens/UserInfo").GetComponent <PageUserInfo>(); }
public static void OnApplicationStart() { ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("Tracking Rotator", ShowRotationMenu); ExpansionKitApi.OnUiManagerInit += VRChat_OnUiManagerInit; }
public static void AddOpenButtonToUIX() { ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("Open User History", new Action(MenuManager.OpenUserHistoryMenu), new Action <GameObject>((gameObject) => { openButton = gameObject; gameObject.SetActive(Config.useUIX.Value); })); Config.useUIX.OnValueChanged += OnUseUIXChange; }
public static void Init() { ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu).AddSimpleButton("Optimize mirrors", OptimizeMirrors); ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu).AddSimpleButton("Beautify mirrors", BeautifyMirrors); }
public IEnumerator InitializeUI() { MelonLogger.Msg("Initializing DiscordMute UI..."); var parentObject = QuickMenu.Find("Container").Find("Window").transform; var originalMic = parentObject.Find("MicButton").gameObject; DiscordButton = UnityEngine.Object.Instantiate(originalMic, originalMic.transform); DiscordButton.name = "DiscordButton"; DiscordButton.transform.SetParent(parentObject); DiscordButton.SetActive(true); DiscordButton.transform.localPosition += new Vector3(30, 97, 0); MelonLogger.Msg("Initializing Bind Manager"); BindManager.Initialize(); void ShowBindManager() { BindManager.Show("Press your mute key in keyboard", new Action <List <Keys> >(selectedKeys => { string stringKeys = ""; if (selectedKeys.Count > 0) { stringKeys = string.Join(",", selectedKeys); } MelonPreferences.SetEntryValue("DiscordMute", nameof(MuteKey), stringKeys); MelonPreferences.Save(); }), null); } ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu).AddSimpleButton("Discord Bind", () => ShowBindManager()); UnityEngine.Object.Destroy(DiscordButton.GetComponent <MicToggle>()); UnityEngine.Object.Destroy(DiscordButton.GetComponent <Toggle>()); yield return(null); // Wait object destroy var tooltip = DiscordButton.GetComponent <UiToggleTooltip>(); tooltip.field_Public_String_0 = "Discord"; tooltip.field_Public_String_1 = "Discord"; var toggle = DiscordButton.AddComponent <Toggle>(); yield return(null); // Wait component toggle.onValueChanged.RemoveAllListeners(); toggle.isOn = true; toggle.onValueChanged.AddListener(new Action <bool>(value => { if (!string.IsNullOrEmpty(MuteKey)) { List <Keys> selectedKeys = new List <Keys>(); if (!string.IsNullOrEmpty(MuteKey)) { string[] stringKeys = MuteKey.Split(','); foreach (var stringKey in stringKeys) { selectedKeys.Add((Keys)Enum.Parse(typeof(Keys), stringKey)); } } // Hold and Release the selected keys foreach (var key in selectedKeys) { HoldKey(key); } foreach (var key in selectedKeys) { ReleaseKey(key); } } else { ShowBindManager(); } })); yield break; }
public override void VRChat_OnUiManagerInit() { BindManager.Initialize(); void ShowBindManager() { BindManager.Show("Press your mute key in keyboard", new Action <List <Keys> >(selectedKeys => { string stringKeys = ""; if (selectedKeys.Count > 0) { stringKeys = string.Join(",", selectedKeys); } MelonPreferences.SetEntryValue("DiscordMute", nameof(MuteKey), stringKeys); MelonPreferences.Save(); }), null); } ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu).AddSimpleButton("Discord Bind", () => ShowBindManager()); var originalMic = GameObject.Find("/UserInterface/QuickMenu/MicControls"); DiscordButton = GameObject.Instantiate(originalMic, originalMic.transform); DiscordButton.name = "Discord"; DiscordButton.SetActive(true); DiscordButton.transform.localPosition -= new Vector3(420, 7); DiscordButton.GetComponentInChildren <Text>().text = "Discord"; var button = DiscordButton.GetComponentInChildren <Button>(); button.onClick = new Button.ButtonClickedEvent(); button.onClick.AddListener(new Action(() => { bool isEnabled = !GameObject.Find("/UserInterface/QuickMenu/MicControls/Discord/MicButton/MicEnabled").activeSelf; GameObject.Find("/UserInterface/QuickMenu/MicControls/Discord/MicButton/MicEnabled").gameObject.SetActive(isEnabled); GameObject.Find("/UserInterface/QuickMenu/MicControls/Discord/MicButton/MicDisabled").gameObject.SetActive(!isEnabled); if (!string.IsNullOrEmpty(MuteKey)) { List <Keys> selectedKeys = new List <Keys>(); if (!string.IsNullOrEmpty(MuteKey)) { string[] stringKeys = MuteKey.Split(','); foreach (var stringKey in stringKeys) { selectedKeys.Add((Keys)Enum.Parse(typeof(Keys), stringKey)); } } // Hold and Release the selected keys foreach (var key in selectedKeys) { HoldKey(key); } foreach (var key in selectedKeys) { ReleaseKey(key); } } else { ShowBindManager(); } })); }
public static void SetupUI() { ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("Light Menu", () => LightTypeMenu()); }
public override void OnApplicationStart() { var category = MelonPreferences.CreateCategory("CameraMinus", "CameraMinus"); myUseCameraExpando = category.CreateEntry("UseCameraExpando", true, "Use Camera expando (instead of QM expando)"); myUnlimitCameraPickupDistance = category.CreateEntry("UnlimitCameraPickupDistance", true, "Longer camera pickup distance"); ExpansionKitApi.GetSettingsCategory("CameraMinus") .AddLabel("Disable and enable camera to update camera expando visibility"); IMenuToggle cameraGrabbableButton = null; IMenuToggle qmGrabbableButton = null; IMenuToggle cameraUiVisibleButton = null; IMenuToggle qmUiVisibleButton = null; void SetCameraGrabbable(bool grabbable) { var controller = UserCameraController.field_Internal_Static_UserCameraController_0; if (controller != null) { controller.transform.Find("ViewFinder").GetComponent <VRC_Pickup>().pickupable = grabbable; } cameraGrabbableButton !.Selected = qmGrabbableButton !.Selected = grabbable; } void SetUiVisible(bool visible) { var controller = UserCameraController.field_Internal_Static_UserCameraController_0; if (controller != null) { controller.transform.Find("ViewFinder/PhotoControls").gameObject.SetActive(visible); } cameraUiVisibleButton !.Selected = qmUiVisibleButton !.Selected = visible; } var cameraEnlargeButton = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.Camera).AddSimpleButton("Enlarge camera", Enlarge); var cameraShrinkButton = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.Camera).AddSimpleButton("Shrink camera", Shrink); cameraGrabbableButton = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.Camera).AddToggleButton("Grabbable", SetCameraGrabbable, () => true); cameraUiVisibleButton = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.Camera).AddToggleButton("UI visible", SetUiVisible, () => true); var qmEnlargeButton = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.CameraQuickMenu).AddSimpleButton("Enlarge camera", Enlarge); var qmShrinkButton = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.CameraQuickMenu).AddSimpleButton("Shrink camera", Shrink); qmGrabbableButton = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.CameraQuickMenu).AddToggleButton("Grabbable", SetCameraGrabbable, () => true); qmUiVisibleButton = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.CameraQuickMenu).AddToggleButton("UI visible", SetUiVisible, () => true); void UpdateButtonVisibility(bool value) { cameraEnlargeButton.SetVisible(value); cameraShrinkButton.SetVisible(value); cameraGrabbableButton.SetVisible(value); cameraUiVisibleButton.SetVisible(value); qmEnlargeButton.SetVisible(!value); qmShrinkButton.SetVisible(!value); qmGrabbableButton.SetVisible(!value); qmUiVisibleButton.SetVisible(!value); } myUseCameraExpando.OnValueChanged += (_, value) => { UpdateButtonVisibility(value); }; UpdateButtonVisibility(myUseCameraExpando.Value); myUnlimitCameraPickupDistance.OnValueChanged += (_, value) => { UpdateCameraPickupDistance(value); }; ExpansionKitApi.OnUiManagerInit += () => { UpdateCameraPickupDistance(myUnlimitCameraPickupDistance.Value); }; }