3232
3333#include " Common/RandomValue.h"
3434#include " GameClient/Shell.h"
35+ #include " GameClient/InGameUI.h"
36+ #include " GameClient/GUICallbacks.h"
3537#include " GameClient/WindowLayout.h"
3638#include " GameClient/GameWindowManager.h"
3739#include " GameClient/GameWindowTransitions.h"
@@ -85,6 +87,7 @@ void Shell::construct()
8587 m_popupReplayLayout = nullptr ;
8688 m_optionsLayout = nullptr ;
8789 m_screenCount = 0 ;
90+ m_isRecreatingLayouts = FALSE ;
8891}
8992
9093// -------------------------------------------------------------------------------------------------
@@ -113,28 +116,30 @@ void Shell::deconstruct()
113116 // delete the save/load menu if present
114117 if ( m_saveLoadMenuLayout )
115118 {
116-
117119 m_saveLoadMenuLayout->destroyWindows ();
118120 deleteInstance (m_saveLoadMenuLayout);
119121 m_saveLoadMenuLayout = nullptr ;
120122
123+ extern WindowLayout *saveLoadMenuLayout;
124+ saveLoadMenuLayout = nullptr ;
121125 }
122126
123127 // delete the replay save menu if present
124128 if ( m_popupReplayLayout )
125129 {
126-
127130 m_popupReplayLayout->destroyWindows ();
128131 deleteInstance (m_popupReplayLayout);
129132 m_popupReplayLayout = nullptr ;
130-
131133 }
132134
133135 // delete the options menu if present.
134136 if (m_optionsLayout != nullptr ) {
135137 m_optionsLayout->destroyWindows ();
136138 deleteInstance (m_optionsLayout);
137139 m_optionsLayout = nullptr ;
140+
141+ extern WindowLayout *OptionsLayout;
142+ OptionsLayout = nullptr ;
138143 }
139144}
140145
@@ -231,7 +236,22 @@ namespace
231236// -------------------------------------------------------------------------------------------------
232237void Shell::recreateWindowLayouts ()
233238{
234- // collect state of the current shell
239+ // 1. Query the states of Quit Menu, Options Layout, and Save/Load Layout BEFORE deconstruction
240+ Bool wasQuitVisible = TheInGameUI ? TheInGameUI->isQuitMenuVisible () : FALSE ;
241+ Bool wasOptionsVisible = (m_optionsLayout != nullptr && !m_optionsLayout->isHidden ());
242+ Bool wasSaveLoadVisible = (m_saveLoadMenuLayout != nullptr && !m_saveLoadMenuLayout->isHidden ());
243+
244+ // Preserve shell active status and shell map state
245+ Bool wasShellActive = m_isShellActive;
246+ Bool wasShellMapOn = m_shellMapOn;
247+
248+ // If the quit menu was visible, we MUST destroy it cleanly so its static layouts are freed
249+ if (wasQuitVisible)
250+ {
251+ destroyQuitMenu ();
252+ }
253+
254+ // collect state of the current shell
235255 const Int screenCount = getScreenCount ();
236256 std::vector<ScreenInfo> screenStackInfos;
237257
@@ -247,21 +267,75 @@ void Shell::recreateWindowLayouts()
247267 }
248268 }
249269
270+ m_isRecreatingLayouts = TRUE ;
271+
250272 // reconstruct the shell now
251273 deconstruct ();
252274 construct ();
253275 init ();
254276
277+ m_isShellActive = wasShellActive;
278+ m_shellMapOn = wasShellMapOn;
279+
255280 // restore the screen stack
256281 Int screenIndex = 0 ;
257282 for (; screenIndex < screenCount; ++screenIndex)
258283 {
259284 const ScreenInfo& screenInfo = screenStackInfos[screenIndex];
260- push (screenInfo.filename );
285+
286+ WindowLayout *newScreen = TheWindowManager->winCreateLayout ( screenInfo.filename );
287+ DEBUG_ASSERTCRASH ( newScreen != nullptr , (" Shell unable to load pending push layout" ) );
288+
289+ linkScreen ( newScreen );
290+
291+ if (TheIMEManager)
292+ TheIMEManager->detach ();
293+
294+ if (!screenInfo.isHidden )
295+ {
296+ newScreen->runInit ( nullptr );
297+ newScreen->bringForward ();
298+ }
299+
300+ newScreen->hide (screenInfo.isHidden );
301+ }
261302
262- WindowLayout* layout = getScreenLayout (screenIndex);
263- layout->hide (screenInfo.isHidden );
303+ // 3. Restore the standalone layouts if they were visible
304+ if (wasQuitVisible)
305+ {
306+ // ToggleQuitMenu will reload the .wnd layout and cleanly recreate the Quit Menu at the new resolution
307+ ToggleQuitMenu ();
264308 }
309+
310+ if (wasOptionsVisible)
311+ {
312+ WindowLayout *optLayout = getOptionsLayout (TRUE );
313+ if (optLayout)
314+ {
315+ optLayout->runInit ();
316+ optLayout->hide (FALSE );
317+ optLayout->bringForward ();
318+
319+ extern WindowLayout *OptionsLayout;
320+ OptionsLayout = optLayout;
321+ }
322+ }
323+
324+ if (wasSaveLoadVisible)
325+ {
326+ WindowLayout *slLayout = getSaveLoadMenuLayout ();
327+ if (slLayout)
328+ {
329+ slLayout->runInit ();
330+ slLayout->hide (FALSE );
331+ slLayout->bringForward ();
332+
333+ extern WindowLayout *saveLoadMenuLayout;
334+ saveLoadMenuLayout = slLayout;
335+ }
336+ }
337+
338+ m_isRecreatingLayouts = FALSE ;
265339}
266340
267341// -------------------------------------------------------------------------------------------------
@@ -445,8 +519,11 @@ void Shell::popImmediate()
445519 m_pendingPop = FALSE ;
446520
447521 // run the shutdown
448- Bool immediatePop = TRUE ;
449- screen->runShutdown ( &immediatePop );
522+ if (!m_isRecreatingLayouts)
523+ {
524+ Bool immediatePop = TRUE ;
525+ screen->runShutdown ( &immediatePop );
526+ }
450527
451528 // pop the screen of the stack
452529 doPop ( FALSE );
@@ -702,7 +779,7 @@ void Shell::doPop( Bool impendingPush )
702779
703780 // run the init for the new top of the stack if present
704781 WindowLayout *newTop = top ();
705- if ( newTop && !impendingPush )
782+ if ( newTop && !impendingPush && !m_isRecreatingLayouts )
706783 {
707784 newTop->runInit ( nullptr );
708785 // newTop->bringForward();
0 commit comments