diff --git a/Core/GameEngine/Include/GameClient/View.h b/Core/GameEngine/Include/GameClient/View.h index 16d7171755b..683fb39294c 100644 --- a/Core/GameEngine/Include/GameClient/View.h +++ b/Core/GameEngine/Include/GameClient/View.h @@ -331,5 +331,40 @@ class ViewLocation } }; +// TheSuperHackers @feature bobtista 31/01/2026 +// View that does nothing. Used for Headless Mode. +class ViewDummy : public View +{ +public: + virtual Drawable *pickDrawable( const ICoord2D *screen, Bool forceAttack, PickType pickType ) override + { + return nullptr; + } + virtual Int iterateDrawablesInRegion( IRegion2D *screenRegion, Bool (*callback)( Drawable *draw, void *userData ), void *userData ) override + { + return 0; + } + virtual void forceRedraw() override {} + virtual const Coord3D& get3DCameraPosition() const override + { + static Coord3D zero = {0,0,0}; + return zero; + } + virtual WorldToScreenReturn worldToScreenTriReturn(const Coord3D *w, ICoord2D *s ) override + { + return WTS_INVALID; + } + virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) override {} + virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) override {} + virtual void drawView( void ) override {} + virtual void updateView(void) override {} + virtual void stepView() override {} + virtual void setGuardBandBias( const Coord2D *gb ) override {} + virtual Bool isDoingScriptedCamera() override { return false; } + virtual void stopDoingScriptedCamera() override {} + + // Do not override View::xfer(). The base implementation must run to serialize valid view state for save file compatibility. +}; + // EXTERNALS ////////////////////////////////////////////////////////////////////////////////////// extern View *TheTacticalView; ///< the main tactical interface to the game world diff --git a/Generals/Code/GameEngine/Include/GameClient/InGameUI.h b/Generals/Code/GameEngine/Include/GameClient/InGameUI.h index a64ba0c95e9..54487f2f419 100644 --- a/Generals/Code/GameEngine/Include/GameClient/InGameUI.h +++ b/Generals/Code/GameEngine/Include/GameClient/InGameUI.h @@ -669,7 +669,7 @@ friend class Drawable; // for selection/deselection transactions void incrementSelectCount() { ++m_selectCount; } ///< Increase by one the running total of "selected" drawables void decrementSelectCount() { --m_selectCount; } ///< Decrease by one the running total of "selected" drawables - virtual View *createView() = 0; ///< Factory for Views + virtual View *createView(bool dummy = false) = 0; ///< Factory for Views void evaluateSoloNexus( Drawable *newlyAddedDrawable = nullptr ); /// expire a hint from of the specified type at the hint index diff --git a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp index a7c70a70f7b..2b4498bcec4 100644 --- a/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -1337,17 +1337,17 @@ void InGameUI::init() been moved to where all the other translators are attached in game client */ // create the tactical view - if (TheDisplay) + TheTacticalView = createView(TheGlobalData->m_headless); + if (TheTacticalView && TheDisplay) { - TheTacticalView = createView(); TheTacticalView->init(); TheDisplay->attachView( TheTacticalView ); // make the tactical display the full screen width and height TheTacticalView->setWidth( TheDisplay->getWidth() ); TheTacticalView->setHeight( TheDisplay->getHeight() ); + TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); } - TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); /** @todo this may be the wrong place to create the sidebar, but for now this is where it lives */ diff --git a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h index 02109bc27cd..cc84fe56c17 100644 --- a/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h +++ b/Generals/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h @@ -69,7 +69,12 @@ class W3DInGameUI : public InGameUI protected: /// factory for views - virtual View *createView() { return NEW W3DView; } + virtual View *createView(bool dummy) + { + if (dummy) + return NEW ViewDummy; + return NEW W3DView; + } virtual void drawSelectionRegion(); ///< draw the selection region on screen virtual void drawMoveHints( View *view ); ///< draw move hint visual feedback diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h b/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h index 2ed0c91abfd..a7f1d05866e 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/InGameUI.h @@ -689,7 +689,7 @@ friend class Drawable; // for selection/deselection transactions void incrementSelectCount() { ++m_selectCount; } ///< Increase by one the running total of "selected" drawables void decrementSelectCount() { --m_selectCount; } ///< Decrease by one the running total of "selected" drawables - virtual View *createView() = 0; ///< Factory for Views + virtual View *createView(bool dummy = false) = 0; ///< Factory for Views void evaluateSoloNexus( Drawable *newlyAddedDrawable = nullptr ); /// expire a hint from of the specified type at the hint index diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp index 3b852e3f676..f43748cba86 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp @@ -1367,17 +1367,17 @@ void InGameUI::init() been moved to where all the other translators are attached in game client */ // create the tactical view - if (TheDisplay) + TheTacticalView = createView(TheGlobalData->m_headless); + if (TheTacticalView && TheDisplay) { - TheTacticalView = createView(); TheTacticalView->init(); TheDisplay->attachView( TheTacticalView ); // make the tactical display the full screen width and height TheTacticalView->setWidth( TheDisplay->getWidth() ); TheTacticalView->setHeight( TheDisplay->getHeight() ); + TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); } - TheTacticalView->setDefaultView(0.0f, 0.0f, 1.0f); /** @todo this may be the wrong place to create the sidebar, but for now this is where it lives */ diff --git a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h b/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h index f239e05e1f9..9b7c49dfc4c 100644 --- a/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h +++ b/GeneralsMD/Code/GameEngineDevice/Include/W3DDevice/GameClient/W3DInGameUI.h @@ -69,7 +69,12 @@ class W3DInGameUI : public InGameUI protected: /// factory for views - virtual View *createView() { return NEW W3DView; } + virtual View *createView(bool dummy) + { + if (dummy) + return NEW ViewDummy; + return NEW W3DView; + } virtual void drawSelectionRegion(); ///< draw the selection region on screen virtual void drawMoveHints( View *view ); ///< draw move hint visual feedback