/* ** Command & Conquer Generals(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 . */ //////////////////////////////////////////////////////////////////////////////// // // // (c) 2001-2003 Electronic Arts Inc. // // // //////////////////////////////////////////////////////////////////////////////// // FILE: SubsystemInterface.h ///////////////////////////////////////////////////////////////////// // Author: Colin Day, October 2001 // Description: Framework for subsystems singletons of the game engine /////////////////////////////////////////////////////////////////////////////////////////////////// #pragma once #ifndef __SUBSYSTEMINTERFACE_H_ #define __SUBSYSTEMINTERFACE_H_ #include "Common/INI.h" #include "Common/STLTypedefs.h" class Xfer; //------------------------------------------------------------------------------------------------- /** This is the abstract base class from which all game engine subsytems should derive from. * In order to provide consistent behaviors across all these systems, any implementation * must obey the rules defined in here * * Nothing about the subsystems is automatic, this interface does not wrap up automated * functions, it is only here to provide a basic interface and rules for behavior * all subsystems */ class SubsystemInterface { public: //----------------------------------------------------------------------------------------------- /** - Constructors should initialize any data to a valid state. That DOES NOT mean * the data has default values (something done in the init() method), only that * nothing is left pointing to garbage, un-initialized memory. In most cases * this probably means just setting members to zero or NULL. */ SubsystemInterface(); //----------------------------------------------------------------------------------------------- /** - Free any resources allocated for this class. * * - DO NOT throw exceptions during any destruction ever, and do not call other * methods that have the possibility of throwing exceptions. Try to keep it * simple and keep as much work actually inside the destructor as possible. */ virtual ~SubsystemInterface(); //----------------------------------------------------------------------------------------------- /** - Assign any default values to data required for the class * * - Allocate any memory and resources needed throughout the lifetime of the class */ virtual void init() = 0; //----------------------------------------------------------------------------------------------- /** - Called for all subsystems after all other Subsystems are inited. * (allows for initializing inter-system dependencies) */ virtual void postProcessLoad() { } //----------------------------------------------------------------------------------------------- /** - Any system should be able to reset all data and go back to an empty state * that is ready to accept a completely new set of data. Reset() can expect * to be used in the context of resetting the engine in order to start or * load a new game. * * - Do NOT free and re-allocate resources needed, where possible reorganize and * re-initialize the resources already allocated. * * - After a reset, the system does not need to be in EXACTLY the same state as a * fresh instantiation. If there are persistent state information for the * system make sure you maintain it while restoring or re-initializing other * transient parts. */ virtual void reset() = 0; //----------------------------------------------------------------------------------------------- /** - Update methods are the place to do system per frame processing. You * should call the system update once each time through the game loop * to service the system. * * - Note that currently the GameClient and GameLogic will be updating * at different rates where the logic is running real time, and the * client will adjust how many loops can be done during one server * time slice in order to improve performance on low end machines. */ virtual void update() = 0; virtual void draw( void ){DEBUG_CRASH(("Shouldn't call base class. jba."));} #ifdef DUMP_PERF_STATS void UPDATE(void); void DRAW(void); Real getUpdateTime(void) {return m_curUpdateTime;} Real getDrawTime(void) {return m_curDrawTime;} static Real getTotalTime(void) {return s_msConsumed;} static void clearTotalTime(void) {s_msConsumed = 0;} protected: static Real s_msConsumed; Real m_startTimeConsumed; Real m_curUpdateTime; Real m_startDrawTimeConsumed; Real m_curDrawTime; #else inline void UPDATE(void) {update();} inline void DRAW(void) {draw();} #endif protected: AsciiString m_name; public: AsciiString getName(void) {return m_name;} void setName(AsciiString name) {m_name = name;} }; // end SubsystemInterface //------------------------------------------------------------------------------------------------- class SubsystemInterfaceList { public: SubsystemInterfaceList(); ~SubsystemInterfaceList(); void initSubsystem(SubsystemInterface* sys, const char* path1, const char* path2, const char* dirpath, Xfer *pXfer, AsciiString name=""); void addSubsystem(SubsystemInterface* sys); void removeSubsystem(SubsystemInterface* sys); void postProcessLoadAll(); void resetAll(); void shutdownAll(); #ifdef DUMP_PERF_STATS AsciiString dumpTimesForAll(); #endif private: typedef std::vector SubsystemList; SubsystemList m_subsystems; SubsystemList m_allSubsystems; }; extern SubsystemInterfaceList* TheSubsystemList; #endif // __SUBSYSTEMINTERFACE_H_