@@ -34,16 +34,17 @@ public partial class EventWindow : Panel
3434 private bool _isTypewriting ;
3535 private readonly long _typewriterResponseDelay = ClientConfiguration . Instance . TypewriterResponseDelay ;
3636
37- private Dialog ? _currentDialog ;
37+ private readonly Dialog _dialog ;
3838
39- public EventWindow ( Canvas gameCanvas ) : base ( gameCanvas , nameof ( EventWindow ) )
39+ private EventWindow ( Canvas gameCanvas , Dialog dialog ) : base ( gameCanvas , nameof ( EventWindow ) )
4040 {
41+ _dialog = dialog ;
4142 _defaultFont = GameContentManager . Current . GetFont ( name : "sourcesansproblack" , 12 ) ;
4243 _writer = Globals . Database . TypewriterBehavior == TypewriterBehavior . Off ? default : new Typewriter ( ) ;
4344
4445 Alignment = [ Alignments . Center ] ;
45- MinimumSize = new Point ( 520 , 240 ) ;
46- MaximumSize = new Point ( 800 , 600 ) ;
46+ MinimumSize = new Point ( 520 , 180 ) ;
47+ MaximumSize = new Point ( 720 , 520 ) ;
4748 Padding = new Padding ( 16 ) ;
4849
4950 _promptPanel = new Panel ( this , nameof ( _promptPanel ) )
@@ -86,6 +87,7 @@ public EventWindow(Canvas gameCanvas) : base(gameCanvas, nameof(EventWindow))
8687 {
8788 Dock = Pos . Left ,
8889 MaintainAspectRatio = true ,
90+ Margin = new Margin ( 8 , 8 , 0 , 8 ) ,
8991 MaximumSize = new Point ( 128 , 128 ) ,
9092 } ;
9193
@@ -108,6 +110,62 @@ public EventWindow(Canvas gameCanvas) : base(gameCanvas, nameof(EventWindow))
108110 } ;
109111
110112 _promptPanel . SizeToChildren ( recursive : true ) ;
113+
114+
115+ #region Configure and Display
116+
117+ if ( _dialog . Face is { } faceTextureName )
118+ {
119+ var faceTexture = Globals . ContentManager . GetTexture ( TextureType . Face , faceTextureName ) ;
120+ _faceImage . Texture = faceTexture ;
121+ if ( faceTexture is not null )
122+ {
123+ _faceImage . IsVisible = true ;
124+ _faceImage . SizeToContents ( ) ;
125+ }
126+ else
127+ {
128+ _faceImage . IsVisible = false ;
129+ }
130+ }
131+ else
132+ {
133+ _faceImage . Texture = null ;
134+ _faceImage . IsVisible = false ;
135+ }
136+
137+ var visibleOptions = _dialog . Options . Where ( option => ! string . IsNullOrEmpty ( option ) ) . ToArray ( ) ;
138+ if ( visibleOptions . Length < 1 )
139+ {
140+ visibleOptions = [ Strings . EventWindow . Continue ] ;
141+ }
142+
143+ for ( var optionIndex = 0 ; optionIndex < _optionButtons . Length ; ++ optionIndex )
144+ {
145+ var optionButton = _optionButtons [ optionIndex ] ;
146+ if ( optionIndex < visibleOptions . Length )
147+ {
148+ optionButton . Text = visibleOptions [ optionIndex ] ;
149+ optionButton . IsVisible = true ;
150+ }
151+ else
152+ {
153+ optionButton . IsVisible = false ;
154+ }
155+ }
156+
157+ // var optionLimit = Math.Max(1, visibleOptions.Length);
158+ // Name = $"EventDialogWindow_{optionLimit}Response{(optionLimit == 1 ? string.Empty : 's')}";
159+ // LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer?.GetResolutionString());
160+
161+ SkipRender ( ) ;
162+ ShowDialog ( ) ;
163+
164+ MakeModal ( dim : true ) ;
165+ BringToFront ( ) ;
166+ Interface . InputBlockingComponents . Add ( this ) ;
167+
168+ #endregion Configure and Display
111169 }
112170
113171 protected override void OnMouseClicked ( MouseButton mouseButton , Point mousePosition , bool userAction = true )
@@ -117,21 +175,18 @@ protected override void OnMouseClicked(MouseButton mouseButton, Point mousePosit
117175 SkipTypewriting ( ) ;
118176 }
119177
120- public void Update ( )
178+ public override void Dispose ( )
121179 {
122- if ( IsHidden )
123- {
124- _ = Interface . InputBlockingComponents . Remove ( this ) ;
125- }
180+ EnsureControlRestored ( ) ;
181+ base . Dispose ( ) ;
182+ }
126183
127- var availableDialog = Globals . EventDialogs . FirstOrDefault ( ) ;
128- if ( availableDialog == null )
129- {
130- return ;
131- }
184+ private static EventWindow ? _instance ;
132185
186+ private void Update ( )
187+ {
133188 // Handle typewriting
134- if ( _isTypewriting && ! IsHidden )
189+ if ( _isTypewriting && IsVisible )
135190 {
136191 var voiceIdx = Randomization . Next ( 0 , ClientConfiguration . Instance . TypewriterSounds . Count ) ;
137192
@@ -140,7 +195,7 @@ public void Update()
140195 for ( var optionIndex = 0 ; optionIndex < _optionButtons . Length ; ++ optionIndex )
141196 {
142197 var optionButton = _optionButtons [ optionIndex ] ;
143- var optionText = _currentDialog ? . Options [ optionIndex ] ;
198+ var optionText = _dialog ? . Options [ optionIndex ] ;
144199 optionButton . IsVisible = writerCompleted && ! string . IsNullOrEmpty ( optionText ) ;
145200 }
146201
@@ -163,82 +218,31 @@ public void Update()
163218 return ;
164219 }
165220
166- if ( _currentDialog != availableDialog )
167- {
168- _currentDialog = availableDialog ;
169-
170- if ( availableDialog . Face is { } faceTextureName )
171- {
172- var faceTexture = Globals . ContentManager . GetTexture ( TextureType . Face , faceTextureName ) ;
173- _faceImage . Texture = faceTexture ;
174- if ( faceTexture is not null )
175- {
176- _faceImage . IsVisible = true ;
177- _faceImage . SizeToContents ( ) ;
178- }
179- else
180- {
181- _faceImage . IsVisible = false ;
182- }
183- }
184- else
185- {
186- _faceImage . Texture = null ;
187- _faceImage . IsVisible = false ;
188- }
189-
190- var visibleOptions = availableDialog . Options . Where ( option => ! string . IsNullOrEmpty ( option ) ) . ToArray ( ) ;
191- if ( visibleOptions . Length < 1 )
192- {
193- visibleOptions = [ Strings . EventWindow . Continue ] ;
194- }
195-
196- for ( var optionIndex = 0 ; optionIndex < _optionButtons . Length ; ++ optionIndex )
197- {
198- var optionButton = _optionButtons [ optionIndex ] ;
199- if ( optionIndex < visibleOptions . Length )
200- {
201- optionButton . Text = visibleOptions [ optionIndex ] ;
202- optionButton . IsVisible = true ;
203- }
204- else
205- {
206- optionButton . IsVisible = false ;
207- }
208- }
209-
210- // Name = $"EventDialogWindow_{_optionCountLimit}Response{(_optionCountLimit == 1 ? string.Empty : 's')}";
211- // LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer?.GetResolutionString());
212-
213- ShowDialog ( ) ;
214-
215- Defer (
216- ( ) =>
217- {
218- SizeToChildren ( recursive : true ) ;
219-
220- _promptScroller . ScrollToTop ( ) ;
221- }
222- ) ;
221+ _isTypewriting = ClientConfiguration . Instance . TypewriterEnabled &&
222+ Globals . Database . TypewriterBehavior == TypewriterBehavior . Word ;
223+ }
223224
224- SkipRender ( ) ;
225- Show ( ) ;
226- MakeModal ( dim : true ) ;
227- Interface . InputBlockingComponents . Add ( this ) ;
225+ public static void ShowOrUpdateDialog ( Canvas canvas )
226+ {
227+ if ( _instance is { } instance )
228+ {
229+ instance . Update ( ) ;
230+ return ;
231+ }
228232
229- BringToFront ( ) ;
233+ var availableDialog = Globals . EventDialogs . FirstOrDefault ( ) ;
234+ if ( availableDialog == null )
235+ {
236+ return ;
230237 }
231238
232- _isTypewriting = ClientConfiguration . Instance . TypewriterEnabled &&
233- Globals . Database . TypewriterBehavior == TypewriterBehavior . Word ;
239+ _instance = new EventWindow ( canvas , availableDialog ) ;
234240 }
235241
236242 private void ShowDialog ( )
237243 {
238244 _promptLabel . ClearText ( ) ;
239- _promptLabel . Width = _promptScroller . Width - _promptScroller . VerticalScrollBar . Width ;
240-
241- _promptLabel . AddText ( _currentDialog ? . Prompt ?? string . Empty , _promptTemplateLabel ) ;
245+ _promptLabel . AddText ( _dialog ? . Prompt ?? string . Empty , _promptTemplateLabel ) ;
242246
243247 _ = _promptLabel . SizeToChildren ( ) ;
244248
@@ -252,7 +256,14 @@ private void ShowDialog()
252256 }
253257 }
254258
255- _promptScroller . ScrollToTop ( ) ;
259+ Defer (
260+ ( ) =>
261+ {
262+ SizeToChildren ( recursive : true ) ;
263+
264+ _promptScroller . ScrollToTop ( ) ;
265+ }
266+ ) ;
256267 }
257268
258269 public void CloseEventResponse ( EventResponseType response )
@@ -263,16 +274,39 @@ public void CloseEventResponse(EventResponseType response)
263274 return ;
264275 }
265276
266- if ( _currentDialog is not { ResponseSent : false } dialog )
277+ if ( _dialog is not { ResponseSent : false } dialog )
267278 {
268279 return ;
269280 }
270281
271282 PacketSender . SendEventResponse ( ( byte ) response , dialog ) ;
272283 dialog . ResponseSent = true ;
273284
285+ EnsureDestroyed ( ) ;
286+ }
287+
288+ private void EnsureControlRestored ( )
289+ {
290+ if ( _instance == this )
291+ {
292+ _instance = null ;
293+ }
294+ _ = Interface . InputBlockingComponents . Remove ( this ) ;
274295 RemoveModal ( ) ;
275- Hide ( ) ;
296+ }
297+
298+ private void EnsureDestroyed ( )
299+ {
300+ EnsureControlRestored ( ) ;
301+
302+ if ( Parent is { } parent )
303+ {
304+ parent . RemoveChild ( this , dispose : true ) ;
305+ }
306+ else
307+ {
308+ DelayedDelete ( ) ;
309+ }
276310 }
277311
278312 private void SkipTypewriting ( )
0 commit comments