206 lines
10 KiB
C
206 lines
10 KiB
C
![]() |
/*
|
||
|
** Command & Conquer Generals Zero Hour(tm)
|
||
|
** Copyright 2025 Electronic Arts Inc.
|
||
|
**
|
||
|
** This program is free software: you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation, either version 3 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// (c) 2001-2003 Electronic Arts Inc. //
|
||
|
// //
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// FILE: Shell.h //////////////////////////////////////////////////////////////////////////////////
|
||
|
// Author: Colin Day, September 2001
|
||
|
// Description: Shell menu representations
|
||
|
//
|
||
|
// Using The Shell:
|
||
|
// ----------------
|
||
|
//
|
||
|
// The Shell makes use of the window layouts to represent screens. You can push and
|
||
|
// pop screens on the stack so that you don't have to keep track of how you got
|
||
|
// to which screen.
|
||
|
//
|
||
|
// Here is what happens when you push a layout on the shell stack:
|
||
|
// 1) The layout name is stored as a "pending push"
|
||
|
// 2) The top of the stack has the Shutdown() method run
|
||
|
// 3) The Shutdown() method (or other mechanisms like Update()) will call
|
||
|
// Shell::shutdownComplete() when the shutdown process for that layout is "complete"
|
||
|
// 4) Shell::shutdownComplete() sees the "pending push" in the shell
|
||
|
// 5) "Pending push" layout is then loaded from disk and the pending push state is cleared
|
||
|
// 6) The new layout is put on the top of the stack
|
||
|
// 7) The new layout Init() method is called
|
||
|
//
|
||
|
// Here is what happens when you pop the top of the stack
|
||
|
// 1) The stack sets a "pending pop" as in progress
|
||
|
// 2) The top layout of the stack has the Shutdown() method called
|
||
|
// 3) The Shutdown() method (or other mechanisms like Update()) will call
|
||
|
// Shell::shutdownComplete() when the shutdown process for that layout is "complete"
|
||
|
// 4) Shell::shutdownComplete() sees the "pending pop" in the shell
|
||
|
// 5) The "pending pop" layout is then destroyed and removed from the stack
|
||
|
// 6) The new top of the stack has the Init() method run
|
||
|
//
|
||
|
// Window Layouts and the Shell:
|
||
|
// -----------------------------
|
||
|
//
|
||
|
// Window Layouts in the shell need the following functions to work property, these
|
||
|
// can be assigned from the GUIEdit window layout tool:
|
||
|
//
|
||
|
// - Init() [OPTIONAL]
|
||
|
// This is called as a result of a push or pop operation (see above for more info)
|
||
|
// The window layout is loaded from disk and then this Init()
|
||
|
// method is run. All shell layout Init() methods should show
|
||
|
// the layout windows. At this point you could move windows
|
||
|
// to starting positions, set a state that the Update() method looks at to
|
||
|
// "animate" the windows to the desired positions.
|
||
|
//
|
||
|
// - Update() [OPTIONAL]
|
||
|
// This is called once at a rate of "shellUpdateDelay" for EVERY screen on the shell
|
||
|
// stack. It does not matter if the screen is on the top, or is hidden, or
|
||
|
// anything, this is always called. Each update is run starting with the screen
|
||
|
// at the top of the stack and progressing to the bottom of the stack.
|
||
|
// States could be set in the Init() or Shutdown() methods of the layout
|
||
|
// that the Update() looks at and reacts to appropriately if desired.
|
||
|
//
|
||
|
// - Shutdown() [REQUIRED]
|
||
|
// This is called when a layout is popped off the stack, or when a new layout
|
||
|
// is pushed on top of this one (see above for more detail on what happens
|
||
|
// during the push/pop process). You can switch into a "shutdown" state and
|
||
|
// animate the layout appropriately in the Update() method for the layout.
|
||
|
// When shutdown is actually complete you should hide the all windows in
|
||
|
// the layout and then you are REQUIRED to notify the shell by calling
|
||
|
// the Shell::shutdownComplete() method.
|
||
|
//
|
||
|
// Shutdown() is also required to be able to handle the paramater "immediatePop".
|
||
|
// If this paramater is TRUE it means that when control returns from the
|
||
|
// shutdown function that the layout will immediately be popped off the
|
||
|
// stack. We need to be able to handle this when in code we want to
|
||
|
// traverse back down the stack rapidly (like when we lose connection to
|
||
|
// an online service, we might pop all the way back to the login screen)
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#ifndef __SHELL_H_
|
||
|
#define __SHELL_H_
|
||
|
|
||
|
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
|
||
|
class WindowLayout;
|
||
|
class AnimateWindowManager;
|
||
|
class GameWindow;
|
||
|
class ShellMenuSchemeManager;
|
||
|
|
||
|
enum AnimTypes;
|
||
|
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
/** This is the interface to the shell system to load, display, and
|
||
|
* manage screen menu shell system layouts */
|
||
|
//-------------------------------------------------------------------------------------------------
|
||
|
class Shell : public SubsystemInterface
|
||
|
{
|
||
|
|
||
|
public:
|
||
|
|
||
|
Shell( void );
|
||
|
~Shell( void );
|
||
|
|
||
|
// Inhertited from subsystem ====================================================================
|
||
|
virtual void init( void );
|
||
|
virtual void reset( void );
|
||
|
virtual void update( void );
|
||
|
//===============================================================================================
|
||
|
|
||
|
void showShellMap(Bool useShellMap ); ///< access function to turn on and off the shell map
|
||
|
|
||
|
void hide( Bool hide ); ///< show/hide all shell layouts
|
||
|
|
||
|
// pseudo-stack operations for manipulating layouts
|
||
|
void push( AsciiString filename, Bool shutdownImmediate = FALSE ); ///< load new screen on top, optionally doing an immediate shutdown
|
||
|
void pop( void ); ///< pop top layout
|
||
|
void popImmediate( void ); ///< pop now, don't wait for shutdown
|
||
|
void showShell( Bool runInit = TRUE ); ///< init the top of stack
|
||
|
void hideShell( void ); ///< shutdown the top of stack
|
||
|
WindowLayout *top( void ); ///< return top layout
|
||
|
|
||
|
void shutdownComplete( WindowLayout *layout, Bool impendingPush = FALSE ); ///< layout has completed shutdown
|
||
|
|
||
|
WindowLayout *findScreenByFilename( AsciiString filename ); ///< find screen
|
||
|
inline Bool isShellActive( void ) { return m_isShellActive; } ///< Returns true if the shell is active
|
||
|
|
||
|
inline Int getScreenCount(void) { return m_screenCount; } ///< Return the current number of screens
|
||
|
|
||
|
void registerWithAnimateManager( GameWindow *win, AnimTypes animType, Bool needsToFinish, UnsignedInt delayMS = 0);
|
||
|
Bool isAnimFinished( void );
|
||
|
void reverseAnimatewindow( void );
|
||
|
Bool isAnimReversed( void );
|
||
|
|
||
|
void loadScheme( AsciiString name );
|
||
|
ShellMenuSchemeManager *getShellMenuSchemeManager( void ) { return m_schemeManager; }
|
||
|
|
||
|
WindowLayout *getSaveLoadMenuLayout( void ); ///< create if necessary and return layout for save load menu
|
||
|
WindowLayout *getPopupReplayLayout( void ); ///< create if necessary and return layout for replay save menu
|
||
|
WindowLayout *getOptionsLayout( Bool create ); ///< return layout for options menu, create if necessary and we are allowed to.
|
||
|
void destroyOptionsLayout( void ); ///< destroy the shell's options layout.
|
||
|
|
||
|
protected:
|
||
|
|
||
|
void linkScreen( WindowLayout *screen ); ///< link screen to list
|
||
|
void unlinkScreen( WindowLayout *screen ); ///< remove screen from list
|
||
|
|
||
|
void doPush( AsciiString layoutFile ); ///< workhorse for push action
|
||
|
void doPop( Bool impendingPush ); ///< workhorse for pop action
|
||
|
|
||
|
enum { MAX_SHELL_STACK = 16 }; ///< max simultaneous shell screens
|
||
|
WindowLayout *m_screenStack[ MAX_SHELL_STACK ]; ///< the screen layout stack
|
||
|
Int m_screenCount; ///< # of screens in screen stack
|
||
|
|
||
|
WindowLayout *m_background; ///< The Background layout if the 3d shell isn't running
|
||
|
Bool m_clearBackground; ///< Flag if we're going to clear the background or not
|
||
|
|
||
|
Bool m_pendingPush; ///< TRUE when a push is pending
|
||
|
Bool m_pendingPop; ///< TRUE when a pop is pending
|
||
|
AsciiString m_pendingPushName; ///< layout name to be pushed
|
||
|
Bool m_isShellActive; ///< TRUE when the shell is active
|
||
|
Bool m_shellMapOn; ///< TRUE when the shell map is on
|
||
|
AnimateWindowManager *m_animateWindowManager; ///< The animate Window Manager
|
||
|
ShellMenuSchemeManager *m_schemeManager; ///< The Shell Scheme Manager
|
||
|
|
||
|
//
|
||
|
// we keep a pointer to this layout so that we can simply just hide/unhide this
|
||
|
// window layout. Why you ask? Well, as the result of pressing a button to start
|
||
|
// a save game load a super large set of operations will happen as the game
|
||
|
// loads. One of those operations is the destruction of the menu, which although
|
||
|
// it just destroys the windows and puts them on a destroyed list, that destroyed
|
||
|
// list is also processed before we are out of our own window procedure.
|
||
|
// This is a prime example why it's easier to just deal with windows by hiding and
|
||
|
// un-hiding them rather than actually creating and destroying them.
|
||
|
//
|
||
|
WindowLayout *m_saveLoadMenuLayout; ///< save/load menu layout
|
||
|
WindowLayout *m_popupReplayLayout; ///< replay save menu layout
|
||
|
WindowLayout *m_optionsLayout; ///< options menu layout
|
||
|
|
||
|
}; // end class Shell
|
||
|
|
||
|
// INLINING ///////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// EXTERNALS //////////////////////////////////////////////////////////////////////////////////////
|
||
|
extern Shell *TheShell; ///< the shell external interface
|
||
|
|
||
|
#endif // __SHELL_H_
|
||
|
|