Example #1
0
        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;
        }
Example #2
0
        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;
        }
Example #3
0
        public override void OnApplicationStart()
        {
            ICustomLayoutedMenu settingsPage = ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu);

            settingsPage.AddSimpleButton("Unblock unpack queue", delegate { Utilities.UnblockUnPackQueue(); });
        }
Example #4
0
        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!");
        }
Example #5
0
 private static void AddUixActions()
 {
     ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu).AddSimpleButton("More IKTweaks...", ShowIKTweaksMenu);
 }
Example #6
0
 public static void SetupUIX()
 {
     ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SafetyMenu).AddSimpleButton($"Load Custom Safety Settings", OpenLoadMenu);
     ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SafetyMenu).AddSimpleButton($"Save Custom Safety Settings", OpenSaveMenu);
 }
Example #7
0
        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>();
        }
Example #8
0
 public static void OnApplicationStart()
 {
     ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("Tracking Rotator", ShowRotationMenu);
     ExpansionKitApi.OnUiManagerInit += VRChat_OnUiManagerInit;
 }
Example #9
0
 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;
 }
Example #10
0
 public static void Init()
 {
     ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu).AddSimpleButton("Optimize mirrors", OptimizeMirrors);
     ExpansionKitApi.GetExpandedMenu(ExpandedMenu.SettingsMenu).AddSimpleButton("Beautify mirrors", BeautifyMirrors);
 }
Example #11
0
        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;
        }
Example #12
0
        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();
                }
            }));
        }
Example #13
0
 public static void SetupUI()
 {
     ExpansionKitApi.GetExpandedMenu(ExpandedMenu.QuickMenu).AddSimpleButton("Light Menu", () => LightTypeMenu());
 }
Example #14
0
        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);
            };
        }