77using System . Runtime . InteropServices ;
88using System . Collections . Generic ;
99using System ;
10- using System . Linq ;
10+ using System . Text ;
11+ using UnityEngine . Pool ;
1112using UnityEngine . Scripting ;
1213
1314namespace UnityEditor
@@ -66,6 +67,11 @@ internal void __internalAwake()
6667 hideFlags = HideFlags . DontSave ;
6768 }
6869
70+ private void OnDestroy ( )
71+ {
72+ Internal_Destroy ( ) ;
73+ }
74+
6975 internal ShowMode showMode => ( ShowMode ) m_ShowMode ;
7076
7177 private string m_WindowID = null ;
@@ -225,60 +231,69 @@ public void SetMinMaxSizes(Vector2 min, Vector2 max)
225231 Internal_SetMinMaxSizes ( min , max ) ;
226232 }
227233
228- static internal bool InternalRequestCloseAll ( bool keepMainWindow )
234+ static internal bool CanCloseAll ( bool includeMainWindow )
229235 {
230- var unsaved = windows
231- . Where ( w => keepMainWindow || w . showMode != ShowMode . MainWindow )
232- . SelectMany ( w => w . m_UnsavedEditorWindows )
233- . ToList ( ) ;
236+ using ( var pooledObject = ListPool < EditorWindow > . Get ( out List < EditorWindow > unsaved ) )
237+ {
238+ foreach ( var window in windows )
239+ {
240+ if ( includeMainWindow || window . showMode != ShowMode . MainWindow )
241+ {
242+ unsaved . AddRange ( window . m_UnsavedEditorWindows ) ;
243+ }
244+ }
234245
235- if ( unsaved . Any ( ) )
236- return PrivateRequestClose ( unsaved ) ;
246+ if ( unsaved . Count > 0 )
247+ return AskToClose ( unsaved ) ;
237248
238- return true ;
249+ return true ;
250+ }
239251 }
240252
241- internal bool InternalRequestClose ( )
253+ private bool CanClose ( )
242254 {
243- if ( IsMainWindow ( ) )
244- {
245- var UnsavedWindows = windows . Where ( w => w != s_MainWindow ) . SelectMany ( w => w . m_UnsavedEditorWindows ) . ToList ( ) ;
246-
247- if ( UnsavedWindows . Any ( ) )
248- return PrivateRequestClose ( UnsavedWindows ) ;
249- }
250- if ( hasUnsavedChanges )
255+ if ( Application . isHumanControllingUs && hasUnsavedChanges )
251256 {
252- return PrivateRequestClose ( m_UnsavedEditorWindows ) ;
257+ return AskToClose ( m_UnsavedEditorWindows ) ;
253258 }
254259
255260 return true ;
256261 }
257262
258- internal bool InternalRequestClose ( EditorWindow dockedTab )
263+ internal static bool CanClose ( EditorWindow dockedTab )
259264 {
260- if ( dockedTab . hasUnsavedChanges )
265+ if ( Application . isHumanControllingUs && dockedTab . hasUnsavedChanges )
261266 {
262267 var unsaved = new List < EditorWindow > ( ) { dockedTab } ;
263- return PrivateRequestClose ( unsaved ) ;
268+ return AskToClose ( unsaved ) ;
264269 }
265270
266271 return true ;
267272 }
268273
269- internal bool InternalRequestCloseAllExcept ( EditorWindow editorWindow )
274+ internal bool CanCloseAllExcept ( EditorWindow editorWindow )
270275 {
271- var unsaved = m_UnsavedEditorWindows . Where ( w => w != editorWindow ) ;
276+ if ( ! Application . isHumanControllingUs )
277+ return true ;
272278
273- if ( unsaved . Any ( ) )
274- return PrivateRequestClose ( unsaved . ToList ( ) ) ;
279+ using ( var pooledObject = ListPool < EditorWindow > . Get ( out List < EditorWindow > unsaved ) )
280+ {
281+ foreach ( var w in m_UnsavedEditorWindows )
282+ {
283+ if ( w != editorWindow )
284+ unsaved . Add ( w ) ;
285+ }
286+
287+ if ( unsaved . Count > 0 )
288+ return AskToClose ( unsaved ) ;
289+ }
275290
276291 return true ;
277292 }
278293
279- internal static bool PrivateRequestClose ( List < EditorWindow > allUnsaved )
294+ private static bool AskToClose ( List < EditorWindow > allUnsaved )
280295 {
281- Debug . Assert ( allUnsaved . Count > 0 ) ;
296+ Debug . Assert ( Application . isHumanControllingUs && allUnsaved . Count > 0 ) ;
282297
283298 const int kSave = 0 ;
284299 const int kCancel = 1 ;
@@ -288,20 +303,28 @@ internal static bool PrivateRequestClose(List<EditorWindow> allUnsaved)
288303
289304 if ( allUnsaved . Count == 1 )
290305 {
291- var title = allUnsaved . First ( ) . titleContent . text ;
306+ var title = allUnsaved [ 0 ] . titleContent . text ;
292307
293308 option = EditorUtility . DisplayDialogComplex ( ( string . IsNullOrEmpty ( title ) ? "" : ( title + " - " ) ) + L10n . Tr ( "Unsaved Changes Detected" ) ,
294- allUnsaved . First ( ) . saveChangesMessage ,
309+ allUnsaved [ 0 ] . saveChangesMessage ,
295310 L10n . Tr ( "Save" ) ,
296311 L10n . Tr ( "Cancel" ) ,
297312 L10n . Tr ( "Discard" ) ) ;
298313 }
299314 else
300315 {
301- string unsavedChangesMessage = string . Join ( "\n " , allUnsaved . Select ( v => v . saveChangesMessage ) . ToArray ( ) ) ;
316+ var savedChangesBuilder = new StringBuilder ( ) ;
317+
318+ int last = allUnsaved . Count - 1 ;
319+ for ( int i = 0 ; i < last ; ++ i )
320+ {
321+ savedChangesBuilder . Append ( allUnsaved [ i ] . saveChangesMessage ) ;
322+ savedChangesBuilder . Append ( '\n ' ) ;
323+ }
324+ savedChangesBuilder . Append ( allUnsaved [ last ] ) ;
302325
303326 option = EditorUtility . DisplayDialogComplex ( L10n . Tr ( "Unsaved Changes Detected" ) ,
304- unsavedChangesMessage ,
327+ savedChangesBuilder . ToString ( ) ,
305328 L10n . Tr ( "Save All" ) ,
306329 L10n . Tr ( "Cancel" ) ,
307330 L10n . Tr ( "Discard All" ) ) ;
@@ -342,11 +365,17 @@ internal static bool PrivateRequestClose(List<EditorWindow> allUnsaved)
342365 }
343366 }
344367
345- internal void InternalCloseWindow ( )
368+ // Closes the Window _without prompting_
369+ public void Close ( )
346370 {
371+ // Because this is a UnityObject, DestroyImmediate _will_ nullify the this pointer.
372+ // This can guard against double-close
373+ if ( this == null )
374+ return ;
375+
347376 Save ( ) ;
348377
349- if ( m_ShowMode == ( int ) ShowMode . MainWindow && s_MainWindow == this )
378+ if ( s_MainWindow == this )
350379 s_MainWindow = null ;
351380
352381 if ( m_RootView )
@@ -358,6 +387,15 @@ internal void InternalCloseWindow()
358387 DestroyImmediate ( this , true ) ;
359388 }
360389
390+ [ RequiredByNativeCode ]
391+ private void RequestCloseSentByNativeCode ( )
392+ {
393+ if ( CanClose ( ) )
394+ {
395+ Close ( ) ;
396+ }
397+ }
398+
361399 [ RequiredByNativeCode ]
362400 internal bool IsMultiplayerClone ( )
363401 {
@@ -373,7 +411,7 @@ private static List<EditorWindow> FindUnsavedChanges(View view)
373411 switch ( v )
374412 {
375413 case DockArea dockArea :
376- foreach ( var windowClose in dockArea . m_Panes . OfType < EditorWindow > ( ) )
414+ foreach ( var windowClose in dockArea . m_Panes )
377415 if ( windowClose . hasUnsavedChanges )
378416 unsavedChanges . Add ( windowClose ) ;
379417 break ;
@@ -395,16 +433,6 @@ public void UnsavedStateChanged()
395433 hasUnsavedChanges = m_UnsavedEditorWindows . Count > 0 ;
396434 }
397435
398- public void Close ( )
399- {
400- Save ( ) ;
401-
402- // Guard against destroy window or window in the process of being destroyed.
403- if ( this && m_WindowPtr . m_IntPtr != IntPtr . Zero )
404- InternalClose ( ) ;
405- DestroyImmediate ( this , true ) ;
406- }
407-
408436 internal bool IsNotDocked ( )
409437 {
410438 return ( // hallelujah
@@ -433,7 +461,17 @@ internal string GetWindowID()
433461
434462 if ( rootView . children . Length > 0 )
435463 {
436- var dockArea = rootView . children . FirstOrDefault ( c => c is DockArea ) as DockArea ;
464+ DockArea dockArea = null ;
465+
466+ foreach ( var child in rootView . children )
467+ {
468+ if ( child is DockArea )
469+ {
470+ dockArea = ( DockArea ) child ;
471+ break ;
472+ }
473+ }
474+
437475 if ( dockArea && dockArea . m_Panes . Count > 0 )
438476 {
439477 return ( m_ShowMode == ( int ) ShowMode . Utility || m_ShowMode == ( int ) ShowMode . AuxWindow ) ? v . actualView . GetType ( ) . ToString ( )
@@ -642,6 +680,5 @@ internal Rect GetDropDownRect(Rect buttonRect, Vector2 minSize, Vector2 maxSize)
642680 {
643681 return PopupLocationHelper . GetDropDownRect ( buttonRect , minSize , maxSize , this ) ;
644682 }
645-
646683 }
647684} //namespace
0 commit comments