1+ using PlayEveryWare . EpicOnlineServices . Editor . Utility ;
2+ using System ;
3+ using System . Threading . Tasks ;
4+ using UnityEditor ;
5+ using UnityEngine ;
6+
7+ namespace PlayEveryWare . EpicOnlineServices . Editor . Windows
8+ {
9+ public sealed class ClientCredentialsEncryptionKeyWindow : ModalInputWindow < string >
10+ {
11+ public ClientCredentialsEncryptionKeyWindow ( ) : base ( 600f , 50f )
12+ {
13+ }
14+
15+ public static void Show (
16+ string input ,
17+ Action < string > onSubmitCallback ,
18+ string windowTitle = "Client Credentials Encryption Key" ,
19+ string inputPrompt = "Enter the encryption key for these client credentials here:" )
20+ {
21+ ScheduleShow < ClientCredentialsEncryptionKeyWindow > (
22+ input ,
23+ onSubmitCallback ,
24+ EOSClientCredentials . IsEncryptionKeyValid ,
25+ windowTitle ,
26+ inputPrompt ,
27+ "Invalid encryption key. Encryption key must be 64 characters long and contain only alphanumeric characters." ) ;
28+ }
29+
30+ protected override void RenderModalContents ( )
31+ {
32+ GUILayout . BeginHorizontal ( ) ;
33+
34+ _input = GUILayout . TextField ( _input , GUILayout . Width ( GUIEditorUtility . MeasureLabelWidth ( 64 ) ) , GUILayout . Height ( 20 ) ) ;
35+
36+ GUILayout . Space ( 5f ) ;
37+
38+ if ( GUILayout . Button (
39+ new GUIContent ( EditorGUIUtility . IconContent ( "Refresh" ) . image ,
40+ "Click here to generate a new encryption key." ) , GUILayout . Height ( 20 ) , GUILayout . Width ( 50 ) ) )
41+ {
42+ _input = EOSClientCredentials . GenerateEncryptionKey ( ) ;
43+ }
44+ GUILayout . EndHorizontal ( ) ;
45+ }
46+ }
47+
48+ public abstract class ModalInputWindow < TInputType > : EOSEditorWindow
49+ {
50+ protected TInputType _input ;
51+ private string _inputPrompt ;
52+ private string _errorPrompt ;
53+ private Action < TInputType > _onSubmit ;
54+ private Func < TInputType , bool > _validateFunction ;
55+ private bool _showError ;
56+
57+ // Keep a reference to prevent focus loss
58+ private static ModalInputWindow < TInputType > s_currentWindow ;
59+
60+ protected ModalInputWindow ( float width , float height ) : base ( "" , height , width , false )
61+ {
62+ }
63+
64+ /// <summary>
65+ /// Helper to schedule the showing of the modal window.
66+ /// </summary>
67+ protected static void ScheduleShow < TWindowType > (
68+ TInputType input ,
69+ Action < TInputType > onSubmitCallback ,
70+ Func < TInputType , bool > validateFunction ,
71+ string windowTitle ,
72+ string inputPrompt ,
73+ string errorPrompt
74+ ) where TWindowType : ModalInputWindow < TInputType >
75+ {
76+ void ShowAndUnsubscribe ( )
77+ {
78+ // Unsubscribe first to ensure it runs only once
79+ EditorApplication . update -= ShowAndUnsubscribe ;
80+
81+ // Open the modal window
82+ ShowWindow < TWindowType > ( input , onSubmitCallback , validateFunction , windowTitle , inputPrompt , errorPrompt ) ;
83+ }
84+
85+ // Subscribe the delegate to execute on the next frame
86+ EditorApplication . update += ShowAndUnsubscribe ;
87+ }
88+
89+ public static void ShowWindow < TWindowType > (
90+ TInputType input ,
91+ Action < TInputType > onSubmitCallback ,
92+ Func < TInputType , bool > validateFunction ,
93+ string windowTitle ,
94+ string inputPrompt ,
95+ string errorPrompt ) where TWindowType : ModalInputWindow < TInputType >
96+ {
97+ if ( s_currentWindow != null )
98+ {
99+ s_currentWindow . Focus ( ) ;
100+ return ;
101+ }
102+
103+ ModalInputWindow < TInputType > window = CreateInstance < TWindowType > ( ) ;
104+ window . _input = input ;
105+ window . WindowTitle = windowTitle ;
106+ window . _inputPrompt = inputPrompt ;
107+ window . _onSubmit = onSubmitCallback ;
108+ window . _validateFunction = validateFunction ;
109+ window . _errorPrompt = errorPrompt ;
110+
111+ // Center the modal window relative to the parent window
112+ if ( focusedWindow != null )
113+ {
114+ Rect parentRect = focusedWindow . position ;
115+ float width = 300f ; // Width of the modal window
116+ float height = 150f ; // Height of the modal window
117+ window . position = new Rect (
118+ parentRect . x + ( parentRect . width - width ) / 2 ,
119+ parentRect . y + ( parentRect . height - height ) / 2 ,
120+ width ,
121+ height
122+ ) ;
123+ }
124+ else
125+ {
126+ // Default size and position if no parent is specified
127+ window . position = new Rect ( Screen . width / 2 - 150 , Screen . height / 2 - 75 , 300 , 150 ) ;
128+ }
129+
130+ window . ShowModalUtility ( ) ; // Makes it modal-like
131+ window . SetIsEmbedded ( false ) ;
132+
133+ s_currentWindow = window ;
134+ }
135+
136+ private void OnLostFocus ( )
137+ {
138+ // Refocus if the window loses focus
139+ Focus ( ) ;
140+ }
141+
142+ protected new void OnEnable ( )
143+ {
144+ // Overridden to remove base functionality.
145+ }
146+
147+ protected new void OnDisable ( )
148+ {
149+ // Overridden to remove base functionality.
150+ }
151+
152+ protected override void OnDestroy ( )
153+ {
154+ s_currentWindow = null ;
155+ base . OnDestroy ( ) ;
156+ }
157+
158+ protected abstract void RenderModalContents ( ) ;
159+
160+ protected override void RenderWindow ( )
161+ {
162+ bool shouldClose = false ;
163+
164+ EditorGUILayout . LabelField ( _inputPrompt , GUILayout . Width (
165+ GUIEditorUtility . MeasureLabelWidth ( _inputPrompt ) )
166+ ) ;
167+
168+ if ( _showError )
169+ {
170+ EditorGUILayout . HelpBox ( _errorPrompt , MessageType . Warning ) ;
171+ }
172+
173+ RenderModalContents ( ) ;
174+
175+ EditorGUILayout . Space ( ) ;
176+
177+ GUILayout . BeginHorizontal ( ) ;
178+ if ( GUILayout . Button ( "Save" ) )
179+ {
180+ if ( _validateFunction ( _input ) )
181+ {
182+ _onSubmit ? . Invoke ( _input ) ;
183+ shouldClose = true ;
184+ }
185+ else
186+ {
187+ _showError = true ;
188+ }
189+ }
190+
191+ GUI . SetNextControlName ( "CancelButton" ) ;
192+ if ( GUILayout . Button ( "Cancel" ) )
193+ {
194+ shouldClose = true ;
195+ }
196+ GUILayout . EndHorizontal ( ) ;
197+
198+ if ( shouldClose )
199+ {
200+ Close ( ) ;
201+ }
202+
203+ // Force focus back to the window
204+ if ( s_currentWindow != this )
205+ {
206+ Focus ( ) ;
207+ s_currentWindow = this ;
208+ }
209+ }
210+ }
211+ }
0 commit comments