1+ using System ;
2+ using System . Collections . Generic ;
3+ using ReMod . Core . Unity ;
4+ using ReMod . Core . VRChat ;
5+ using TMPro ;
6+ using UnityEngine ;
7+ using UnityEngine . UI ;
8+ using VRC . UI . Elements ;
9+ using VRC . UI . Elements . Controls ;
10+ using ListBinding = MonoBehaviourPublicTrGaBoObAcObDi2GaBoUnique ; //DataModel.dll
11+ using Object = Il2CppSystem . Object ;
12+
13+ namespace ReMod . Core . UI . QuickMenu
14+ {
15+ public class ReRadioTogglePage : UiElement
16+ {
17+ private static GameObject _menuPrefab ;
18+
19+ private static GameObject MenuPrefab
20+ {
21+ get
22+ {
23+ if ( _menuPrefab == null )
24+ {
25+ _menuPrefab = QuickMenuEx . Instance . field_Public_Transform_0 . Find ( "Window/QMParent/Menu_ChangeAudioInputDevice" ) . gameObject ;
26+ }
27+ return _menuPrefab ;
28+ }
29+ }
30+
31+ private static int SiblingIndex => QuickMenuEx . Instance . field_Public_Transform_0 . Find ( "Window/QMParent/Modal_AddMessage" ) . GetSiblingIndex ( ) ;
32+
33+ public event Action OnOpen ;
34+ public event Action OnClose ;
35+ public event Action < Object > OnSelect ;
36+
37+ public string TitleText
38+ {
39+ set => _titleText . text = value ;
40+ }
41+
42+ private TextMeshProUGUI _titleText ;
43+ private ListBinding ListBinding ;
44+ private GameObject RadioButtonPrefab ;
45+ private RadioButtonSelectorGroup RadioButtonSelectorGroup ;
46+ private Dictionary < string , Tuple < string , Object , Action > > _radioElementSource = new ( ) ;
47+ private bool _isUpdated ;
48+
49+ private readonly bool _isRoot ;
50+
51+ private readonly Transform _container ;
52+
53+ public UIPage UiPage { get ; }
54+
55+ public ReRadioTogglePage ( string name ) : base ( MenuPrefab , QuickMenuEx . MenuParent , $ "Menu_{ name } ", false )
56+ {
57+ var headerTransform = RectTransform . GetChild ( 0 ) ;
58+
59+ _titleText = headerTransform . GetComponentInChildren < TextMeshProUGUI > ( ) ;
60+ _titleText . text = name ;
61+ _titleText . richText = true ;
62+
63+ _container = RectTransform . GetComponentInChildren < ScrollRect > ( ) . content ;
64+
65+ var inputMenu = RectTransform . GetComponent < AudioInputDeviceMenu > ( ) ;
66+ RadioButtonPrefab = inputMenu . field_Public_GameObject_0 ;
67+ ListBinding = inputMenu . field_Public_MonoBehaviourPublicTrGaBoObAcObDi2GaBoUnique_0 ;
68+ RadioButtonSelectorGroup = ListBinding . gameObject . GetComponent < RadioButtonSelectorGroup > ( ) ;
69+
70+ ListBinding . field_Private_Dictionary_2_Object_GameObject_0 = new Il2CppSystem . Collections . Generic . Dictionary < Object , GameObject > ( ) ;
71+
72+ //Get rid of the AudioInputDeviceMenu component
73+ UnityEngine . Object . DestroyImmediate ( inputMenu ) ;
74+
75+ // Set up UIPage
76+ UiPage = GameObject . GetComponent < UIPage > ( ) ;
77+ UiPage . field_Public_String_0 = $ "QuickMenuReMod{ GetCleanName ( name ) } ";
78+ UiPage . field_Private_Boolean_1 = true ;
79+ UiPage . field_Protected_MenuStateController_0 = QuickMenuEx . MenuStateCtrl ;
80+ UiPage . field_Private_List_1_UIPage_0 = new Il2CppSystem . Collections . Generic . List < UIPage > ( ) ;
81+ UiPage . field_Private_List_1_UIPage_0 . Add ( UiPage ) ;
82+
83+ QuickMenuEx . MenuStateCtrl . field_Private_Dictionary_2_String_UIPage_0 . Add ( UiPage . field_Public_String_0 , UiPage ) ;
84+
85+ EnableDisableListener . RegisterSafe ( ) ;
86+ var listener = GameObject . AddComponent < EnableDisableListener > ( ) ;
87+ listener . OnEnableEvent += ( ) => OnOpen ? . Invoke ( ) ;
88+ listener . OnDisableEvent += ( ) => OnClose ? . Invoke ( ) ;
89+ }
90+
91+ public void Open ( )
92+ {
93+ QuickMenuEx . MenuStateCtrl . PushPage ( UiPage . field_Public_String_0 ) ;
94+
95+ if ( ! _isUpdated )
96+ return ;
97+
98+ _isUpdated = false ;
99+
100+ foreach ( var element in ListBinding . field_Private_Dictionary_2_Object_GameObject_0 )
101+ UnityEngine . Object . DestroyImmediate ( element . value ) ;
102+ ListBinding . field_Private_Dictionary_2_Object_GameObject_0 . Clear ( ) ;
103+
104+ foreach ( var newElement in _radioElementSource )
105+ {
106+ var radioButton = UnityEngine . Object . Instantiate ( RadioButtonPrefab , ListBinding . gameObject . transform ) ;
107+ radioButton . active = true ;
108+ var radioButtonSelector = radioButton . GetComponent < RadioButtonSelector > ( ) ;
109+ radioButtonSelector . field_Public_TextMeshProUGUI_0 = radioButtonSelector . GetComponentInChildren < TextMeshProUGUI > ( ) ;
110+ radioButtonSelector . field_Private_Button_0 = radioButtonSelector . GetComponent < Button > ( ) ;
111+ UnityEngine . Object . DestroyImmediate ( radioButtonSelector . GetComponent < AudioDeviceButton > ( ) ) ;
112+ radioButtonSelector . field_Private_Button_0 . onClick . AddListener ( new Action ( ( ) => OnSelect ? . Invoke ( newElement . Value . Item2 ) ) ) ;
113+ if ( newElement . Value . Item3 != null )
114+ radioButtonSelector . field_Private_Button_0 . onClick . AddListener ( newElement . Value . Item3 ) ;
115+ radioButtonSelector . field_Public_String_0 = newElement . Value . Item1 ;
116+ radioButtonSelector . SetTitle ( newElement . Key , newElement . Value . Item1 ) ;
117+ radioButtonSelector . prop_RadioButtonSelectorGroup_0 = RadioButtonSelectorGroup ;
118+ ListBinding . field_Private_Dictionary_2_Object_GameObject_0 . Add ( newElement . Key , radioButton ) ;
119+ }
120+ }
121+
122+ /// <summary>
123+ /// Adds a item to the radio element source
124+ /// </summary>
125+ /// <param name="name">Name that will appear on radio toggle</param>
126+ /// <param name="obj">Object to be send in OnSelect event</param>
127+ /// <param name="onClick">OnClick when the toggle is selected in menu</param>
128+ public void AddItem ( string name , Object obj , Action onClick = null )
129+ {
130+ _radioElementSource . Add ( $ "{ _radioElementSource . Count } _{ name } ", new Tuple < string , Object , Action > ( name , obj , onClick ) ) ;
131+ _isUpdated = true ;
132+ }
133+
134+ public void ClearItems ( )
135+ {
136+ _radioElementSource . Clear ( ) ;
137+ _isUpdated = true ;
138+ }
139+ }
140+ }
0 commit comments