386 lines
10 KiB
C++
386 lines
10 KiB
C++
![]() |
/*
|
||
|
** 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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// (c) 2001-2003 Electronic Arts Inc. //
|
||
|
// //
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// FILE: Display.cpp //////////////////////////////////////////////////////////
|
||
|
// The implementation of the Display class
|
||
|
// Author: Michael S. Booth, March 2001
|
||
|
|
||
|
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||
|
|
||
|
#include "GameClient/Display.h"
|
||
|
#include "GameClient/Mouse.h"
|
||
|
#include "GameClient/VideoPlayer.h"
|
||
|
#include "GameClient/DisplayStringManager.h"
|
||
|
#include "GameClient/GameText.h"
|
||
|
#include "GameClient/GlobalLanguage.h"
|
||
|
//#include "GameLogic/ScriptEngine.h"
|
||
|
//#include "GameLogic/GameLogic.h"
|
||
|
|
||
|
/// The Display singleton instance.
|
||
|
Display *TheDisplay = NULL;
|
||
|
|
||
|
|
||
|
Display::Display()
|
||
|
{
|
||
|
m_viewList = NULL;
|
||
|
m_width = 0;
|
||
|
m_height = 0;
|
||
|
m_bitDepth = 0;
|
||
|
m_windowed = FALSE;
|
||
|
m_videoBuffer = NULL;
|
||
|
m_videoStream = NULL;
|
||
|
m_debugDisplayCallback = NULL;
|
||
|
m_debugDisplayUserData = NULL;
|
||
|
m_debugDisplay = NULL;
|
||
|
m_letterBoxFadeLevel = 0;
|
||
|
m_letterBoxEnabled = FALSE;
|
||
|
m_cinematicText = AsciiString::TheEmptyString;
|
||
|
m_cinematicFont = NULL;
|
||
|
m_cinematicTextFrames = 0;
|
||
|
m_movieHoldTime = -1;
|
||
|
m_copyrightHoldTime = -1;
|
||
|
m_elapsedMovieTime = 0;
|
||
|
m_elapsedCopywriteTime = 0;
|
||
|
m_copyrightDisplayString = NULL;
|
||
|
|
||
|
// Added by Sadullah Nader
|
||
|
// Initializations missing and needed
|
||
|
m_currentlyPlayingMovie.clear();
|
||
|
m_letterBoxFadeStartTime = 0;
|
||
|
// End Add
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Destructor for the Display. Destroy all views attached to it.
|
||
|
*/
|
||
|
Display::~Display()
|
||
|
{
|
||
|
|
||
|
stopMovie();
|
||
|
// delete all our views if present
|
||
|
deleteViews();
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete all views in the Display
|
||
|
*/
|
||
|
void Display::deleteViews( void )
|
||
|
{
|
||
|
View *v, *next;
|
||
|
|
||
|
for( v = m_viewList; v; v = next )
|
||
|
{
|
||
|
next = v->getNextView();
|
||
|
delete v;
|
||
|
}
|
||
|
m_viewList = NULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Attach the given view to the world
|
||
|
* @todo Rethink the "attachView" notion...
|
||
|
*/
|
||
|
void Display::attachView( View *view )
|
||
|
{
|
||
|
// prepend to head of list
|
||
|
m_viewList = view->prependViewToList( m_viewList );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Render all views of the world
|
||
|
*/
|
||
|
void Display::drawViews( void )
|
||
|
{
|
||
|
|
||
|
for( View *v = m_viewList; v; v = v->getNextView() )
|
||
|
v->drawView();
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Updates all views of the world. This forces state variables
|
||
|
to refresh without actually drawing anything.
|
||
|
*/
|
||
|
void Display::updateViews( void )
|
||
|
{
|
||
|
|
||
|
for( View *v = m_viewList; v; v = v->getNextView() )
|
||
|
v->updateView();
|
||
|
|
||
|
}
|
||
|
|
||
|
/// Redraw the entire display
|
||
|
void Display::draw( void )
|
||
|
{
|
||
|
// redraw all views
|
||
|
drawViews();
|
||
|
|
||
|
// redraw the in-game user interface
|
||
|
/// @todo Switch between in-game and shell interfaces
|
||
|
|
||
|
}
|
||
|
|
||
|
/** Sets screen resolution/mode*/
|
||
|
Bool Display::setDisplayMode( UnsignedInt xres, UnsignedInt yres, UnsignedInt bitdepth, Bool windowed )
|
||
|
{
|
||
|
//Get old values
|
||
|
UnsignedInt oldDisplayHeight=getHeight();
|
||
|
UnsignedInt oldDisplayWidth=getWidth();
|
||
|
Int oldViewWidth=TheTacticalView->getWidth();
|
||
|
Int oldViewHeight=TheTacticalView->getHeight();
|
||
|
Int oldViewOriginX,oldViewOriginY;
|
||
|
TheTacticalView->getOrigin(&oldViewOriginX,&oldViewOriginY);
|
||
|
|
||
|
setWidth(xres);
|
||
|
setHeight(yres);
|
||
|
|
||
|
//Adjust view to match previous proportions
|
||
|
TheTacticalView->setWidth((Real)oldViewWidth/(Real)oldDisplayWidth*(Real)xres);
|
||
|
TheTacticalView->setHeight((Real)oldViewHeight/(Real)oldDisplayHeight*(Real)yres);
|
||
|
TheTacticalView->setOrigin((Real)oldViewOriginX/(Real)oldDisplayWidth*(Real)xres,
|
||
|
(Real)oldViewOriginY/(Real)oldDisplayHeight*(Real)yres);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// Display::setWidth ==========================================================
|
||
|
/** Set the width of the display */
|
||
|
//=============================================================================
|
||
|
void Display::setWidth( UnsignedInt width )
|
||
|
{
|
||
|
|
||
|
// set the new width
|
||
|
m_width = width;
|
||
|
|
||
|
// set the new mouse limits
|
||
|
if( TheMouse )
|
||
|
TheMouse->setMouseLimits();
|
||
|
|
||
|
} // end setWidth
|
||
|
|
||
|
// Display::setHeight =========================================================
|
||
|
/** Set the height of the display */
|
||
|
//=============================================================================
|
||
|
void Display::setHeight( UnsignedInt height )
|
||
|
{
|
||
|
|
||
|
// se the new height
|
||
|
m_height = height;
|
||
|
|
||
|
// set the new mouse limits
|
||
|
if( TheMouse )
|
||
|
TheMouse->setMouseLimits();
|
||
|
|
||
|
} // end setHeight
|
||
|
|
||
|
//============================================================================
|
||
|
// Display::playLogoMovie
|
||
|
// minMovieLength is in milliseconds
|
||
|
// minCopyrightLength
|
||
|
//============================================================================
|
||
|
|
||
|
void Display::playLogoMovie( AsciiString movieName, Int minMovieLength, Int minCopyrightLength )
|
||
|
{
|
||
|
|
||
|
stopMovie();
|
||
|
|
||
|
m_videoStream = TheVideoPlayer->open( movieName );
|
||
|
|
||
|
if ( m_videoStream == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_currentlyPlayingMovie = movieName;
|
||
|
m_movieHoldTime = minMovieLength;
|
||
|
m_copyrightHoldTime = minCopyrightLength;
|
||
|
m_elapsedMovieTime = timeGetTime(); // we're using time get time becuase legal want's actual "Seconds"
|
||
|
|
||
|
m_videoBuffer = createVideoBuffer();
|
||
|
if ( m_videoBuffer == NULL ||
|
||
|
!m_videoBuffer->allocate( m_videoStream->width(),
|
||
|
m_videoStream->height())
|
||
|
)
|
||
|
{
|
||
|
stopMovie();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
// Display::playMovie
|
||
|
//============================================================================
|
||
|
|
||
|
void Display::playMovie( AsciiString movieName)
|
||
|
{
|
||
|
|
||
|
stopMovie();
|
||
|
|
||
|
|
||
|
|
||
|
m_videoStream = TheVideoPlayer->open( movieName );
|
||
|
|
||
|
if ( m_videoStream == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_currentlyPlayingMovie = movieName;
|
||
|
|
||
|
m_videoBuffer = createVideoBuffer();
|
||
|
if ( m_videoBuffer == NULL ||
|
||
|
!m_videoBuffer->allocate( m_videoStream->width(),
|
||
|
m_videoStream->height())
|
||
|
)
|
||
|
{
|
||
|
stopMovie();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
// Display::stopMovie
|
||
|
//============================================================================
|
||
|
|
||
|
void Display::stopMovie( void )
|
||
|
{
|
||
|
delete m_videoBuffer;
|
||
|
m_videoBuffer = NULL;
|
||
|
|
||
|
if ( m_videoStream )
|
||
|
{
|
||
|
m_videoStream->close();
|
||
|
m_videoStream = NULL;
|
||
|
}
|
||
|
|
||
|
if (!m_currentlyPlayingMovie.isEmpty()) {
|
||
|
//TheScriptEngine->notifyOfCompletedVideo(m_currentlyPlayingMovie); // Removing this sync-error cause MDC
|
||
|
m_currentlyPlayingMovie = AsciiString::TheEmptyString;
|
||
|
}
|
||
|
if(m_copyrightDisplayString)
|
||
|
{
|
||
|
TheDisplayStringManager->freeDisplayString(m_copyrightDisplayString);
|
||
|
m_copyrightDisplayString = NULL;
|
||
|
}
|
||
|
m_copyrightHoldTime = -1;
|
||
|
m_movieHoldTime = -1;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
// Display::update
|
||
|
//============================================================================
|
||
|
|
||
|
void Display::update( void )
|
||
|
{
|
||
|
if ( m_videoStream && m_videoBuffer )
|
||
|
{
|
||
|
if ( m_videoStream->isFrameReady())
|
||
|
{
|
||
|
m_videoStream->frameDecompress();
|
||
|
m_videoStream->frameRender( m_videoBuffer );
|
||
|
if( m_videoStream->frameIndex() != m_videoStream->frameCount() - 1)
|
||
|
m_videoStream->frameNext();
|
||
|
else if( m_copyrightHoldTime >= 0 ||m_movieHoldTime >= 0 )
|
||
|
{
|
||
|
if( m_elapsedCopywriteTime == 0 && m_elapsedCopywriteTime >= 0)
|
||
|
{
|
||
|
//display the copyrighttext;
|
||
|
if(m_copyrightDisplayString)
|
||
|
m_copyrightDisplayString->deleteInstance();
|
||
|
m_copyrightDisplayString = TheDisplayStringManager->newDisplayString();
|
||
|
m_copyrightDisplayString->setText(TheGameText->fetch("GUI:EACopyright"));
|
||
|
if (TheGlobalLanguageData && TheGlobalLanguageData->m_copyrightFont.name.isNotEmpty())
|
||
|
{ FontDesc *fontdesc=&TheGlobalLanguageData->m_copyrightFont;
|
||
|
m_copyrightDisplayString->setFont(TheFontLibrary->getFont(fontdesc->name,
|
||
|
TheGlobalLanguageData->adjustFontSize(fontdesc->size),
|
||
|
fontdesc->bold));
|
||
|
}
|
||
|
else
|
||
|
m_copyrightDisplayString->setFont(TheFontLibrary->getFont("Courier",
|
||
|
TheGlobalLanguageData->adjustFontSize(12), TRUE));
|
||
|
m_elapsedCopywriteTime = timeGetTime();
|
||
|
}
|
||
|
if(m_movieHoldTime + m_elapsedMovieTime < timeGetTime() &&
|
||
|
m_copyrightHoldTime + m_elapsedCopywriteTime < timeGetTime())
|
||
|
{
|
||
|
m_movieHoldTime = -1;
|
||
|
m_elapsedMovieTime = 0;
|
||
|
m_elapsedCopywriteTime = 0;
|
||
|
m_copyrightHoldTime = -1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
stopMovie();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
// Display::reset
|
||
|
//============================================================================
|
||
|
|
||
|
void Display::reset()
|
||
|
{
|
||
|
//Remove letterbox border that may have been enabled by a script
|
||
|
m_letterBoxFadeLevel = 0;
|
||
|
m_letterBoxEnabled = FALSE;
|
||
|
stopMovie();
|
||
|
|
||
|
// Reset all views that need resetting
|
||
|
for( View *v = m_viewList; v; v = v->getNextView() )
|
||
|
v->reset();
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
// Display::isMoviePlaying
|
||
|
//============================================================================
|
||
|
|
||
|
Bool Display::isMoviePlaying(void)
|
||
|
{
|
||
|
return m_videoStream != NULL && m_videoBuffer != NULL;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
// Display::setDebugDisplayCallback
|
||
|
//============================================================================
|
||
|
|
||
|
void Display::setDebugDisplayCallback( DebugDisplayCallback *callback, void *userData )
|
||
|
{
|
||
|
m_debugDisplayCallback = callback;
|
||
|
m_debugDisplayUserData = userData;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
// Display::getDebugDisplayCallback
|
||
|
//============================================================================
|
||
|
|
||
|
Display::DebugDisplayCallback *Display::getDebugDisplayCallback()
|
||
|
{
|
||
|
return m_debugDisplayCallback;
|
||
|
}
|