//======== (C) Copyright 1999, 2000 Valve, L.L.C. All rights reserved. ======== // // The copyright to the contents herein is the property of Valve, L.L.C. // The contents may be used and/or copied only with the written permission of // Valve, L.L.C., or in accordance with the terms and conditions stipulated in // the agreement/contract under which the contents have been supplied. // // Purpose: Defines a group of app systems that all have the same lifetime // that need to be connected/initialized, etc. in a well-defined order // // $Revision: $ // $NoKeywords: $ //============================================================================= #ifndef IAPPSYSTEMGROUP_H #define IAPPSYSTEMGROUP_H #ifdef _WIN32 #pragma once #endif #include "tier1/interface.h" #include "tier1/utlvector.h" #include "tier1/utldict.h" #include "tier1/UtlStringMap.h" #include "iappsystem.h" //----------------------------------------------------------------------------- // forward declarations //----------------------------------------------------------------------------- class IAppSystem; class CSysModule; class IBaseInterface; class IFileSystem; //----------------------------------------------------------------------------- // Handle to a DLL //----------------------------------------------------------------------------- typedef int AppModule_t; enum { APP_MODULE_INVALID = (AppModule_t)~0 }; //----------------------------------------------------------------------------- // NOTE: The following methods must be implemented in your application // although they can be empty implementations if you like... //----------------------------------------------------------------------------- abstract_class IAppSystemGroup { public: // An installed application creation function, you should tell the group // the DLLs and the singleton interfaces you want to instantiate. // Return false if there's any problems and the app will abort virtual bool Create( ) = 0; // Allow the application to do some work after AppSystems are connected but // they are all Initialized. // Return false if there's any problems and the app will abort virtual bool PreInit() = 0; // Allow the application to do some work after AppSystems are initialized but // before main is run // Return false if there's any problems and the app will abort virtual bool PostInit() = 0; // Main loop implemented by the application virtual int Main( ) = 0; // Allow the application to do some work after all AppSystems are shut down virtual void PreShutdown() = 0; // Allow the application to do some work after all AppSystems are shut down virtual void PostShutdown() = 0; // Call an installed application destroy function, occurring after all modules // are unloaded virtual void Destroy() = 0; }; //----------------------------------------------------------------------------- // This class represents a group of app systems that all have the same lifetime // that need to be connected/initialized, etc. in a well-defined order //----------------------------------------------------------------------------- class CAppSystemGroup : public IAppSystemGroup { public: // Used to determine where we exited out from the system enum AppSystemGroupStage_t { CREATION = 0, DEPENDENCIES, CONNECTION, PREINITIALIZATION, INITIALIZATION, POSTINITIALIZATION, RUNNING, PRESHUTDOWN, SHUTDOWN, POSTSHUTDOWN, DISCONNECTION, DESTRUCTION, APPSYSTEM_GROUP_STAGE_COUNT, NONE, // This means no error }; public: // constructor CAppSystemGroup( CAppSystemGroup *pParentAppSystem = NULL ); // Runs the app system group. // First, modules are loaded, next they are connected, followed by initialization // Then Main() is run // Then modules are shut down, disconnected, and unloaded int Run( ); // Use this version in cases where you can't control the main loop and // expect to be ticked virtual int Startup(); virtual void Shutdown(); // Default implementations... virtual bool PostInit() { return true; } virtual void PreShutdown() { } // Returns the stage at which the app system group ran into an error AppSystemGroupStage_t GetCurrentStage() const; int ReloadModule( const char * pDLLName ); protected: // These methods are meant to be called by derived classes of CAppSystemGroup // Methods to load + unload DLLs AppModule_t LoadModule( const char *pDLLName ); AppModule_t LoadModule( CreateInterfaceFn factory ); // Method to add various global singleton systems IAppSystem *AddSystem( AppModule_t module, const char *pInterfaceName ); void AddSystem( IAppSystem *pAppSystem, const char *pInterfaceName ); // Simpler method of doing the LoadModule/AddSystem thing. // Make sure the last AppSystemInfo has a NULL module name bool AddSystems( AppSystemInfo_t *pSystems ); // Adds a factory to the system so other stuff can query it. Triggers a connect systems void AddNonAppSystemFactory( CreateInterfaceFn fn ); // Removes a factory, triggers a disconnect call if it succeeds void RemoveNonAppSystemFactory( CreateInterfaceFn fn ); // Causes the systems to reconnect to an interface void ReconnectSystems( const char *pInterfaceName ); // Method to look up a particular named system... void *FindSystem( const char *pInterfaceName ); // Creates the app window (windowed app only) virtual void *CreateAppWindow( void *hInstance, const char *pTitle, bool bWindowed, int w, int h, bool bResizing ); void SetAppWindowTitle( void* hWnd, const char *pTitle ); // Gets at a class factory for the topmost appsystem group in an appsystem stack static CreateInterfaceFn GetFactory(); private: struct Module_t { CSysModule *m_pModule; CreateInterfaceFn m_Factory; char *m_pModuleName; }; typedef CUtlStringMap< CUtlSymbolTable > LibraryDependencies_t; int OnStartup(); void OnShutdown(); void UnloadAllModules( ); void RemoveAllSystems(); // Method to load all dependent systems bool LoadDependentSystems(); // Method to connect/disconnect all systems bool ConnectSystems( ); void DisconnectSystems(); // Method to initialize/shutdown all systems InitReturnVal_t InitSystems(); void ShutdownSystems(); // Gets at the parent appsystem group CAppSystemGroup *GetParent(); // Loads a module the standard way virtual CSysModule *LoadModuleDLL( const char *pDLLName ); void ComputeDependencies( LibraryDependencies_t &depend ); void SortDependentLibraries( LibraryDependencies_t &depend ); const char *FindSystemName( int nIndex ); static bool SortLessFunc( const int &left, const int &right ); void ReportStartupFailure( int nErrorStage, int nSysIndex ); CUtlVector m_Modules; CUtlVector m_Systems; CUtlVector m_NonAppSystemFactories; CUtlDict m_SystemDict; CAppSystemGroup *m_pParentAppSystem; AppSystemGroupStage_t m_nCurrentStage; static LibraryDependencies_t *sm_pSortDependencies; friend void *AppSystemCreateInterfaceFn(const char *pName, int *pReturnCode); friend class CSteamAppSystemGroup; }; //----------------------------------------------------------------------------- // This class represents a group of app systems that are loaded through steam //----------------------------------------------------------------------------- class CSteamAppSystemGroup : public CAppSystemGroup { public: CSteamAppSystemGroup( IFileSystem *pFileSystem = NULL, CAppSystemGroup *pParentAppSystem = NULL ); // Used by CSteamApplication to set up necessary pointers if we can't do it in the constructor void Setup( IFileSystem *pFileSystem, CAppSystemGroup *pParentAppSystem ); protected: // Sets up the search paths bool SetupSearchPaths( const char *pStartingDir, bool bOnlyUseStartingDir, bool bIsTool ); // Returns the game info path. Only works if you've called SetupSearchPaths first const char *GetGameInfoPath() const; private: virtual CSysModule *LoadModuleDLL( const char *pDLLName ); IFileSystem *m_pFileSystem; char m_pGameInfoPath[ MAX_PATH ]; }; //----------------------------------------------------------------------------- // Helper empty decorator implementation of an IAppSystemGroup //----------------------------------------------------------------------------- template< class CBaseClass > class CDefaultAppSystemGroup : public CBaseClass { public: virtual bool Create( ) { return true; } virtual bool PreInit() { return true; } virtual bool PostInit() { return true; } virtual void PreShutdown() { } virtual void PostShutdown() {} virtual void Destroy() {} }; //----------------------------------------------------------------------------- // Special helper for game info directory suggestion //----------------------------------------------------------------------------- class CFSSteamSetupInfo; // Forward declaration // // SuggestGameInfoDirFn_t // Game info suggestion function. // Provided by the application to possibly detect the suggested game info // directory and initialize all the game-info-related systems appropriately. // Parameters: // pFsSteamSetupInfo steam file system setup information if available. // pchPathBuffer buffer to hold game info directory path on return. // nBufferLength length of the provided buffer to hold game info directory path. // pbBubbleDirectories should contain "true" on return to bubble the directories up searching for game info file. // Return values: // Returns "true" if the game info directory path suggestion is available and // was successfully copied into the provided buffer. // Returns "false" otherwise, interpreted that no suggestion will be used. // typedef bool ( * SuggestGameInfoDirFn_t ) ( CFSSteamSetupInfo const *pFsSteamSetupInfo, char *pchPathBuffer, int nBufferLength, bool *pbBubbleDirectories ); // // SetSuggestGameInfoDirFn // Installs the supplied game info directory suggestion function. // Parameters: // pfnNewFn the new game info directory suggestion function. // Returns: // The previously installed suggestion function or NULL if none was installed before. // This function never fails. // SuggestGameInfoDirFn_t SetSuggestGameInfoDirFn( SuggestGameInfoDirFn_t pfnNewFn ); #endif // APPSYSTEMGROUP_H