Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
parent
2e338c00cb
commit
3d0ee53a05
6072 changed files with 2283311 additions and 0 deletions
883
Generals/Code/GameEngine/Source/GameClient/System/Anim2D.cpp
Normal file
883
Generals/Code/GameEngine/Source/GameClient/System/Anim2D.cpp
Normal file
|
@ -0,0 +1,883 @@
|
|||
/*
|
||||
** 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: Anim2D.cpp ///////////////////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, July 2002
|
||||
// Desc: A collection of 2D images to make animation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
#define DEFINE_ANIM_2D_MODE_NAMES
|
||||
#include "Common/RandomValue.h"
|
||||
#include "Common/Xfer.h"
|
||||
#include "GameClient/Anim2D.h"
|
||||
#include "GameClient/Display.h"
|
||||
#include "GameClient/Image.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// GLOBAL /////////////////////////////////////////////////////////////////////////////////////////
|
||||
Anim2DCollection *TheAnim2DCollection = NULL;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Anim2DTemplate::Anim2DTemplate( AsciiString name )
|
||||
{
|
||||
|
||||
m_name = name;
|
||||
m_images = NULL;
|
||||
m_numFrames = NUM_FRAMES_INVALID;
|
||||
m_framesBetweenUpdates = 0;
|
||||
m_animMode = ANIM_2D_LOOP;
|
||||
m_randomizeStartFrame = FALSE;
|
||||
m_nextTemplate = NULL;
|
||||
|
||||
} // end Anim2DTemplate
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Anim2DTemplate::~Anim2DTemplate( void )
|
||||
{
|
||||
|
||||
// delete the images
|
||||
if( m_images )
|
||||
delete [] m_images;
|
||||
|
||||
} // end ~Anim2DTemplate
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Field parse table for 2D animation templates */
|
||||
// ---------i---------------------------------------------------------------------------------------
|
||||
const FieldParse Anim2DTemplate::s_anim2DFieldParseTable[] =
|
||||
{
|
||||
|
||||
{ "NumberImages", Anim2DTemplate::parseNumImages, NULL, 0 },
|
||||
{ "Image", Anim2DTemplate::parseImage, NULL, 0 },
|
||||
{ "ImageSequence", Anim2DTemplate::parseImageSequence, NULL, 0 },
|
||||
{ "AnimationMode", INI::parseIndexList, Anim2DModeNames, offsetof( Anim2DTemplate, m_animMode ) },
|
||||
{ "AnimationDelay", INI::parseDurationUnsignedShort, NULL, offsetof( Anim2DTemplate, m_framesBetweenUpdates ) },
|
||||
{ "RandomizeStartFrame", INI::parseBool, NULL, offsetof( Anim2DTemplate, m_randomizeStartFrame ) },
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Parse the number of images we will have in this animation and allocate the array for them */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2DTemplate::parseNumImages( INI *ini, void *instance, void *store, const void *userData )
|
||||
{
|
||||
|
||||
// parse the integer data from the file
|
||||
UnsignedInt numFrames;
|
||||
ini->parseUnsignedInt( ini, instance, &numFrames, userData );
|
||||
|
||||
// get the template we are to store into
|
||||
Anim2DTemplate *animTemplate = (Anim2DTemplate *)instance;
|
||||
|
||||
// animations must have a minimum # of frames
|
||||
Int minimumFrames = 1;
|
||||
if( numFrames < minimumFrames )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "Anim2DTemplate::parseNumImages - Invalid animation '%s', animations must have '%d' or more frames defined\n",
|
||||
animTemplate->getName().str(), minimumFrames ));
|
||||
throw INI_INVALID_DATA;
|
||||
|
||||
} // end if
|
||||
|
||||
// allocate the image array
|
||||
animTemplate->allocateImages( (UnsignedShort)numFrames );
|
||||
|
||||
} // end parseNumImages
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Allocate the image array for an animation template and store the number of frames we have */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2DTemplate::allocateImages( UnsignedShort numFrames )
|
||||
{
|
||||
|
||||
// store the number of frames
|
||||
m_numFrames = numFrames;
|
||||
|
||||
// allocate an array to hold the image pointers
|
||||
m_images = NEW const Image *[ m_numFrames ]; // pool[]ify
|
||||
|
||||
// set all the images to NULL;
|
||||
for( Int i = 0; i < m_numFrames; ++i )
|
||||
m_images[ i ] = NULL;
|
||||
|
||||
} // end allocateImages
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Parsing a single image definition for an animation */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2DTemplate::parseImage( INI *ini, void *instance, void *store, const void *userData )
|
||||
{
|
||||
|
||||
// parse the image name from the file and store as an image pointer
|
||||
const Image *image;
|
||||
ini->parseMappedImage( ini, instance, &image, userData );
|
||||
|
||||
// sanity
|
||||
if( image == NULL )
|
||||
{
|
||||
|
||||
//We don't care if we're in the builder
|
||||
//DEBUG_CRASH(( "Anim2DTemplate::parseImage - Image not found\n" ));
|
||||
//throw INI_INVALID_DATA;
|
||||
|
||||
} // end if
|
||||
|
||||
//
|
||||
// assign the image to the animation template list of images ... note since we've pre-allocated
|
||||
// the array of images and the index an image is loaded into depends on its order specified
|
||||
// in INI, we need to get the number of images currently loaded into this animation template
|
||||
// so that we can put it at the next free image spot ... and then tell the animation
|
||||
// template we've loaded one more
|
||||
//
|
||||
Anim2DTemplate *animTemplate = (Anim2DTemplate *)instance;
|
||||
animTemplate->storeImage( image );
|
||||
|
||||
} // end parseImage
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** This will parse the image sequence of an animation. You can use this as a shortcut to
|
||||
* specifying a series of images for an animation instead of having to specify them all
|
||||
* individually. Image names will be assumed to start with an appended "000" to the end
|
||||
* end of the first image name and incremented up to the number of images for the
|
||||
* animation. NOTE: That the number images *must* have already been specified before
|
||||
* we can parse this entry so we know how many images to allocate and look for */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/*static*/ void Anim2DTemplate::parseImageSequence( INI *ini, void *instance,
|
||||
void *store, const void *userData )
|
||||
{
|
||||
|
||||
// get the animation template
|
||||
Anim2DTemplate *animTemplate = (Anim2DTemplate *)instance;
|
||||
|
||||
//
|
||||
// before we can read, allocate, and find all the images for the sequence ... we must
|
||||
// know how many total images are in this animation. Verify that now
|
||||
//
|
||||
if( animTemplate->getNumFrames() == NUM_FRAMES_INVALID )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "Anim2DTemplate::parseImageSequence - You must specify the number of animation frames for animation '%s' *BEFORE* specifying the image sequence name\n",
|
||||
animTemplate->getName().str() ));
|
||||
throw INI_INVALID_DATA;
|
||||
|
||||
} // end if
|
||||
|
||||
//
|
||||
// the image storage has already been allocated, all we have to do now is count from
|
||||
// 0 to numImages - 1 and add those images to the template
|
||||
//
|
||||
AsciiString imageBaseName = ini->getNextAsciiString();
|
||||
AsciiString imageName;
|
||||
const Image *image;
|
||||
for( Int i = 0; i < animTemplate->getNumFrames(); ++i )
|
||||
{
|
||||
|
||||
// construct this name
|
||||
imageName.format( "%s%03d", imageBaseName.str(), i );
|
||||
|
||||
// search for this image
|
||||
image = TheMappedImageCollection->findImageByName( imageName );
|
||||
|
||||
// sanity
|
||||
if( image == NULL )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "Anim2DTemplate::parseImageSequence - Image '%s' not found for animation '%s'. Check the number of images specified in INI and also make sure all the actual images exist.\n",
|
||||
imageName.str(), animTemplate->getName().str() ));
|
||||
throw INI_INVALID_DATA;
|
||||
|
||||
} // end if
|
||||
|
||||
// store the image in the next free frame
|
||||
animTemplate->storeImage( image );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end parseImageSequence
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Store the image at the next open image slot for the animation */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2DTemplate::storeImage( const Image *image )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( image == NULL )
|
||||
return;
|
||||
|
||||
// search through the image list and store at the next free spot
|
||||
for( Int i = 0; i < m_numFrames; ++i )
|
||||
{
|
||||
|
||||
if( m_images[ i ] == NULL )
|
||||
{
|
||||
|
||||
m_images[ i ] = image;
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
} // end for i
|
||||
|
||||
// if we got here we tried to store an image in an array that was too small
|
||||
DEBUG_CRASH(( "Anim2DTemplate::storeImage - Unable to store image '%s' into animation '%s' because the animation is setup to only support '%d' image frames\n",
|
||||
image->getName().str(), getName().str(), m_numFrames ));
|
||||
throw INI_INVALID_DATA;
|
||||
|
||||
} // end storeImage
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Return the Image* for the frame number requested */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const Image* Anim2DTemplate::getFrame( UnsignedShort frameNumber ) const
|
||||
{
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( m_images != NULL,
|
||||
("Anim2DTemplate::getFrame - Image data is NULL for animation '%s'\n",
|
||||
getName().str()) );
|
||||
|
||||
// sanity
|
||||
if( frameNumber < 0 || frameNumber >= m_numFrames )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "Anim2DTemplate::getFrame - Illegal frame number '%d' for animation '%s'\n",
|
||||
frameNumber, getName().str() ));
|
||||
return NULL;
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// return the image frame
|
||||
return m_images[ frameNumber ];
|
||||
|
||||
} // end else
|
||||
|
||||
} // end getFrame
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Anim2D::Anim2D( Anim2DTemplate *animTemplate, Anim2DCollection *collectionSystem )
|
||||
{
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( animTemplate != NULL, ("Anim2D::Anim2D - NULL template\n") );
|
||||
|
||||
//Added By Sadullah Nader
|
||||
//Initialization
|
||||
|
||||
m_currentFrame = 0;
|
||||
|
||||
//
|
||||
|
||||
// set the template
|
||||
m_template = animTemplate;
|
||||
|
||||
// initialize members
|
||||
m_status = ANIM_2D_STATUS_NONE;
|
||||
m_alpha = 1.0f;
|
||||
|
||||
// set the initial frame for the animation based on the type of animation mode or randomize
|
||||
if( m_template->isRandomizedStartFrame() )
|
||||
randomizeCurrentFrame();
|
||||
else
|
||||
reset();
|
||||
|
||||
m_minFrame = 0;
|
||||
m_maxFrame = m_template->getNumFrames() - 1;
|
||||
m_framesBetweenUpdates = m_template->getNumFramesBetweenUpdates();
|
||||
|
||||
//added by Sadullah Nader
|
||||
// initializing pointers to NULL, and clearing Frame counters before
|
||||
// we register ourselves to the System
|
||||
m_collectionSystemNext = NULL;
|
||||
m_collectionSystemPrev = NULL;
|
||||
|
||||
m_lastUpdateFrame = 0;
|
||||
|
||||
// if a system is present, register ourselves with that system
|
||||
m_collectionSystem = collectionSystem;
|
||||
if( m_collectionSystem )
|
||||
m_collectionSystem->registerAnimation( this );
|
||||
|
||||
|
||||
} // end Anim2D
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Anim2D::~Anim2D( void )
|
||||
{
|
||||
|
||||
// if we were registered with a system, un-register ourselves
|
||||
if( m_collectionSystem )
|
||||
m_collectionSystem->unRegisterAnimation( this );
|
||||
|
||||
} // end ~Anim2D
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Set the current animation frame */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::setCurrentFrame( UnsignedShort frame )
|
||||
{
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( m_template != NULL, ("Anim2D::reset - No template for animation\n") );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( TheGameLogic != NULL,
|
||||
("Anim2D::setCurrentFrame - TheGameLogic must exist to use animation instances (%s)\n",
|
||||
m_template->getName().str()) );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( frame >= 0 && frame < m_template->getNumFrames(),
|
||||
("Anim2D::setCurrentFrame - Illegal frame number '%d' in animation\n",
|
||||
frame, m_template->getName().str()) );
|
||||
|
||||
// set the frame
|
||||
m_currentFrame = frame;
|
||||
|
||||
// record the frame of this update to our current frame
|
||||
m_lastUpdateFrame = TheGameLogic->getFrame();
|
||||
|
||||
} // end setCurrentFrame
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Randomize the current frame */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::randomizeCurrentFrame( void )
|
||||
{
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( m_template != NULL, ("Anim2D::reset - No template for animation\n") );
|
||||
|
||||
// set the current frame to a random frame
|
||||
setCurrentFrame( GameClientRandomValue( 0, m_template->getNumFrames() - 1 ) );
|
||||
|
||||
} // end randomizeCurrentFrame
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Reset this animation instance to the "start" of the animation */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::reset( void )
|
||||
{
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( m_template != NULL, ("Anim2D::reset - No template for animation\n") );
|
||||
|
||||
switch( m_template->getAnimMode() )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case ANIM_2D_ONCE:
|
||||
case ANIM_2D_LOOP:
|
||||
case ANIM_2D_PING_PONG:
|
||||
setCurrentFrame( m_minFrame );
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case ANIM_2D_ONCE_BACKWARDS:
|
||||
case ANIM_2D_LOOP_BACKWARDS:
|
||||
case ANIM_2D_PING_PONG_BACKWARDS:
|
||||
setCurrentFrame( m_maxFrame );
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
default:
|
||||
DEBUG_CRASH(( "Anim2D::reset - Unknown animation mode '%d' for '%s'\n",
|
||||
m_template->getAnimMode(), m_template->getName().str() ));
|
||||
break;
|
||||
|
||||
} // end switch, animation mode
|
||||
|
||||
} // end reset
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** This is called after we are drawn ... if sufficient time has passed since our last
|
||||
* frame update we will update our current frame */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::tryNextFrame( void )
|
||||
{
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( TheGameLogic != NULL,
|
||||
("Anim2D::tryNextFrame - TheGameLogic must exist to use animation instances (%s)\n",
|
||||
m_template->getName().str()) );
|
||||
|
||||
// how many frames have passed since our last update
|
||||
if( TheGameLogic->getFrame() - m_lastUpdateFrame >= m_framesBetweenUpdates )
|
||||
{
|
||||
|
||||
switch( m_template->getAnimMode() )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
case ANIM_2D_ONCE:
|
||||
{
|
||||
|
||||
if( m_currentFrame < m_maxFrame )
|
||||
setCurrentFrame( m_currentFrame + 1 );
|
||||
else
|
||||
setStatus( ANIM_2D_STATUS_COMPLETE );
|
||||
break;
|
||||
|
||||
} // end once
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
case ANIM_2D_ONCE_BACKWARDS:
|
||||
{
|
||||
|
||||
if( m_currentFrame > m_minFrame )
|
||||
setCurrentFrame( m_currentFrame - 1 );
|
||||
else
|
||||
setStatus( ANIM_2D_STATUS_COMPLETE );
|
||||
break;
|
||||
|
||||
} // end once backwards
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
case ANIM_2D_LOOP:
|
||||
{
|
||||
|
||||
if( m_currentFrame == m_maxFrame )
|
||||
setCurrentFrame( m_minFrame );
|
||||
else
|
||||
setCurrentFrame( m_currentFrame + 1 );
|
||||
break;
|
||||
|
||||
} // end loop
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
case ANIM_2D_LOOP_BACKWARDS:
|
||||
{
|
||||
|
||||
if( m_currentFrame > m_minFrame )
|
||||
setCurrentFrame( m_currentFrame - 1 );
|
||||
else
|
||||
setCurrentFrame( m_maxFrame );
|
||||
break;
|
||||
|
||||
} // end loop backwards
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
case ANIM_2D_PING_PONG:
|
||||
case ANIM_2D_PING_PONG_BACKWARDS:
|
||||
{
|
||||
|
||||
if( BitTest( m_status, ANIM_2D_STATUS_REVERSED ) )
|
||||
{
|
||||
//
|
||||
// decrement frame, unless we're at frame 0 in which case we
|
||||
// increment and reverse directions
|
||||
//
|
||||
if( m_currentFrame == m_minFrame )
|
||||
{
|
||||
|
||||
setCurrentFrame( m_currentFrame + 1 );
|
||||
clearStatus( ANIM_2D_STATUS_REVERSED );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
setCurrentFrame( m_currentFrame - 1 );
|
||||
|
||||
} // end else
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
//
|
||||
// increment frame, unless we're at the end in which case we decrement
|
||||
// and reverse directions
|
||||
//
|
||||
if( m_currentFrame == m_maxFrame )
|
||||
{
|
||||
|
||||
setCurrentFrame( m_currentFrame - 1 );
|
||||
setStatus( ANIM_2D_STATUS_REVERSED );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
setCurrentFrame( m_currentFrame + 1 );
|
||||
|
||||
} // end else
|
||||
|
||||
} // end else
|
||||
|
||||
break;
|
||||
|
||||
} // end ping pong / ping pong backwards
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
default:
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "Anim2D::tryNextFrame - Unknown animation mode '%d' for '%s'\n",
|
||||
m_template->getAnimMode(), m_template->getName().str() ));
|
||||
break;
|
||||
|
||||
} // end default
|
||||
|
||||
} // end switch
|
||||
|
||||
} // end if
|
||||
|
||||
} // end tryNextFrame
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Set status bit */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::setStatus( UnsignedByte statusBits )
|
||||
{
|
||||
|
||||
// set the bits
|
||||
BitSet( m_status, statusBits );
|
||||
|
||||
} // end setStatus
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Clear status bit */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::clearStatus( UnsignedByte statusBits )
|
||||
{
|
||||
|
||||
// clear bits
|
||||
BitClear( m_status, statusBits );
|
||||
|
||||
} // end clearStatus
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Return the "natural" width of the image for our current frame */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
UnsignedInt Anim2D::getCurrentFrameWidth( void ) const
|
||||
{
|
||||
const Image *currentFrameImage = m_template->getFrame( m_currentFrame );
|
||||
|
||||
if( currentFrameImage )
|
||||
return currentFrameImage->getImageWidth();
|
||||
|
||||
return 0;
|
||||
|
||||
} // end getCurrentFrameWidth
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Return the "natural" height of the image for our current frame */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
UnsignedInt Anim2D::getCurrentFrameHeight( void ) const
|
||||
{
|
||||
const Image *currentFrameImage = m_template->getFrame( m_currentFrame );
|
||||
|
||||
if( currentFrameImage )
|
||||
return currentFrameImage->getImageHeight();
|
||||
|
||||
return 0;
|
||||
|
||||
} // end getCurrentFrameHeight
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Draw an Anim2D using the natural width and height of the image data */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::draw( Int x, Int y )
|
||||
{
|
||||
|
||||
// get the current image
|
||||
const Image *image = m_template->getFrame( m_currentFrame );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( image != NULL, ("Anim2D::draw - Image not found for frame '%d' on animation '%s'\n",
|
||||
m_currentFrame, m_template->getName().str()) );
|
||||
|
||||
// get the natural width and height of this image
|
||||
const ICoord2D *imageSize = image->getImageSize();
|
||||
|
||||
// draw the image
|
||||
Color color = GameMakeColor( 255, 255, 255, 255 * m_alpha );
|
||||
TheDisplay->drawImage( image, x, y, x + imageSize->x, y + imageSize->y, color );
|
||||
|
||||
//
|
||||
// see if it's time for us to go to the next frame in the sequence, we do not update
|
||||
// frame numbers for animation instances that are registered with a system as the
|
||||
// system will update them during its update phase
|
||||
//
|
||||
if( m_collectionSystem == NULL && BitTest( m_status, ANIM_2D_STATUS_FROZEN ) == FALSE )
|
||||
tryNextFrame();
|
||||
|
||||
} // end draw
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Drawing an Anim2D using a forced width and height */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::draw( Int x, Int y, Int width, Int height )
|
||||
{
|
||||
|
||||
// get the current image
|
||||
const Image *image = m_template->getFrame( m_currentFrame );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( image != NULL, ("Anim2D::draw - Image not found for frame '%d' on animation '%s'\n",
|
||||
m_currentFrame, m_template->getName().str()) );
|
||||
|
||||
|
||||
// draw image to the display
|
||||
Color color = GameMakeColor( 255, 255, 255, 255 * m_alpha );
|
||||
TheDisplay->drawImage( image, x, y, x + width, y + height, color );
|
||||
|
||||
//
|
||||
// see if it's time for us to go to the next frame in the sequence, we do not update
|
||||
// frame numbers for animation instances that are registered with a system as the
|
||||
// system will update them during its update phase
|
||||
//
|
||||
if( m_collectionSystem == NULL && BitTest( m_status, ANIM_2D_STATUS_FROZEN ) == FALSE )
|
||||
tryNextFrame();
|
||||
|
||||
} // end draw
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer Method
|
||||
* Version Info:
|
||||
* 1: Initial version */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2D::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
// current frame
|
||||
xfer->xferUnsignedShort( &m_currentFrame );
|
||||
|
||||
// last update frame
|
||||
xfer->xferUnsignedInt( &m_lastUpdateFrame );
|
||||
|
||||
// status
|
||||
xfer->xferUnsignedByte( &m_status );
|
||||
|
||||
// min frame
|
||||
xfer->xferUnsignedShort( &m_minFrame );
|
||||
|
||||
// max frame
|
||||
xfer->xferUnsignedShort( &m_maxFrame );
|
||||
|
||||
// frames between updates
|
||||
xfer->xferUnsignedInt( &m_framesBetweenUpdates );
|
||||
|
||||
// alpha
|
||||
xfer->xferReal( &m_alpha );
|
||||
|
||||
} // end xfer
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Anim2DCollection::Anim2DCollection( void )
|
||||
{
|
||||
|
||||
m_templateList = NULL;
|
||||
m_instanceList = NULL;
|
||||
} // end Anim2DCollection
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Anim2DCollection::~Anim2DCollection( void )
|
||||
{
|
||||
|
||||
// there should not be any animation instances registered with us since we're being destroyed
|
||||
DEBUG_ASSERTCRASH( m_instanceList == NULL, ("Anim2DCollection - instance list is not NULL\n") );
|
||||
|
||||
// delete all the templates
|
||||
Anim2DTemplate *nextTemplate;
|
||||
while( m_templateList )
|
||||
{
|
||||
|
||||
// get next template
|
||||
nextTemplate = m_templateList->friend_getNextTemplate();
|
||||
|
||||
// delete this template
|
||||
m_templateList->deleteInstance();
|
||||
|
||||
// set the head of our list to the next template
|
||||
m_templateList = nextTemplate;
|
||||
|
||||
} // end while
|
||||
|
||||
} // end ~Anim2DCollection
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Initialize 2D animation collection */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2DCollection::init( void )
|
||||
{
|
||||
INI ini;
|
||||
|
||||
ini.load( "Data\\INI\\Animation2D.ini", INI_LOAD_OVERWRITE, NULL );
|
||||
|
||||
} // end init
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** System update phase */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2DCollection::update( void )
|
||||
{
|
||||
Anim2D *anim;
|
||||
|
||||
// go through all our animations
|
||||
for( anim = m_instanceList; anim; anim = anim->m_collectionSystemNext )
|
||||
{
|
||||
|
||||
// try to update the frame
|
||||
if( BitTest( anim->getStatus(), ANIM_2D_STATUS_FROZEN ) == FALSE )
|
||||
anim->tryNextFrame();
|
||||
|
||||
} // end for, anim
|
||||
|
||||
} // end update
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Search the template list for a template with a matching name */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Anim2DTemplate *Anim2DCollection::findTemplate( const AsciiString& name )
|
||||
{
|
||||
|
||||
// search the list
|
||||
for( Anim2DTemplate *animTemplate = m_templateList;
|
||||
animTemplate;
|
||||
animTemplate = animTemplate->friend_getNextTemplate() )
|
||||
{
|
||||
|
||||
if( animTemplate->getName() == name )
|
||||
return animTemplate;
|
||||
|
||||
} // end for
|
||||
|
||||
return NULL; // template not found
|
||||
|
||||
} // end findTemplate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Anim2DTemplate* Anim2DCollection::getNextTemplate( Anim2DTemplate *animTemplate ) const
|
||||
{
|
||||
if( animTemplate )
|
||||
{
|
||||
return animTemplate->friend_getNextTemplate();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Allocate a new template, assign name, and link to our internal list */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Anim2DTemplate *Anim2DCollection::newTemplate( const AsciiString& name )
|
||||
{
|
||||
|
||||
// allocate a new template
|
||||
Anim2DTemplate *animTemplate = newInstance(Anim2DTemplate)( name );
|
||||
|
||||
// link to our template list
|
||||
animTemplate->friend_setNextTemplate( m_templateList );
|
||||
m_templateList = animTemplate;
|
||||
|
||||
// return the new template
|
||||
return animTemplate;
|
||||
|
||||
} // end newTemplate
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Register animation instance with us. When an animation instance is registered it can
|
||||
* be updated even when it's not drawn */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2DCollection::registerAnimation( Anim2D *anim )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( anim == NULL )
|
||||
return;
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( anim->m_collectionSystemNext == NULL &&
|
||||
anim->m_collectionSystemPrev == NULL,
|
||||
("Registering animation instance, instance '%s' is already in a system\n",
|
||||
anim->getAnimTemplate()->getName().str()) );
|
||||
|
||||
// tie to our list
|
||||
anim->m_collectionSystemPrev = NULL;
|
||||
anim->m_collectionSystemNext = m_instanceList;
|
||||
if( m_instanceList )
|
||||
m_instanceList->m_collectionSystemPrev = anim;
|
||||
m_instanceList = anim;
|
||||
|
||||
} // end registerAnimation
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Anim2DCollection::unRegisterAnimation( Anim2D *anim )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( anim == NULL )
|
||||
return;
|
||||
|
||||
// if animation is not registered with us do nothing
|
||||
if( anim->m_collectionSystem != this )
|
||||
return;
|
||||
|
||||
// unlink from our instnace list
|
||||
if( anim->m_collectionSystemNext )
|
||||
anim->m_collectionSystemNext->m_collectionSystemPrev = anim->m_collectionSystemPrev;
|
||||
if( anim->m_collectionSystemPrev )
|
||||
anim->m_collectionSystemPrev->m_collectionSystemNext = anim->m_collectionSystemNext;
|
||||
else
|
||||
m_instanceList = anim->m_collectionSystemNext;
|
||||
|
||||
} // end unRegisterAnimation
|
||||
|
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
** 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: CampaignManager.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Jul 2002
|
||||
//
|
||||
// Filename: CampaignManager.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: The flow of the campaigns are stored up in here!
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/INI.h"
|
||||
#include "Common/Xfer.h"
|
||||
#include "GameClient/CampaignManager.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
CampaignManager *TheCampaignManager = NULL;
|
||||
|
||||
const FieldParse CampaignManager::m_campaignFieldParseTable[] =
|
||||
{
|
||||
|
||||
{ "Mission", CampaignManager::parseMissionPart, NULL, NULL },
|
||||
{ "FirstMission", INI::parseAsciiString, NULL, offsetof( Campaign, m_firstMission ) },
|
||||
{ "CampaignNameLabel", INI::parseAsciiString, NULL, offsetof( Campaign, m_campaignNameLabel ) },
|
||||
{ "FinalVictoryMovie", INI::parseAsciiString, NULL, offsetof( Campaign, m_finalMovieName ) },
|
||||
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void INI::parseCampaignDefinition( INI *ini )
|
||||
{
|
||||
AsciiString name;
|
||||
Campaign *campaign;
|
||||
|
||||
// read the name
|
||||
const char* c = ini->getNextToken();
|
||||
name.set( c );
|
||||
|
||||
// find existing item if present
|
||||
DEBUG_ASSERTCRASH( TheCampaignManager, ("parseCampaignDefinition: Unable to Get TheCampaignManager\n") );
|
||||
if( !TheCampaignManager )
|
||||
return;
|
||||
|
||||
// If we have a previously allocated Campaign
|
||||
campaign = TheCampaignManager->newCampaign( name );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( campaign, ("parseCampaignDefinition: Unable to allocate campaign '%s'\n", name.str()) );
|
||||
|
||||
// parse the ini definition
|
||||
ini->initFromINI( campaign, TheCampaignManager->getFieldParse() );
|
||||
|
||||
} // end parseCampaignDefinition
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Campaign::Campaign( void )
|
||||
{
|
||||
m_missions.clear();
|
||||
m_firstMission.clear();
|
||||
m_name.clear();
|
||||
m_finalMovieName.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Campaign::~Campaign( void )
|
||||
{
|
||||
MissionListIt it = m_missions.begin();
|
||||
while(it != m_missions.end())
|
||||
{
|
||||
Mission *mission = *it;
|
||||
it = m_missions.erase( it );
|
||||
if(mission)
|
||||
mission->deleteInstance();
|
||||
}
|
||||
}
|
||||
|
||||
AsciiString Campaign::getFinalVictoryMovie( void )
|
||||
{
|
||||
return m_finalMovieName;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Mission *Campaign::newMission( AsciiString name )
|
||||
{
|
||||
MissionListIt it;
|
||||
it = m_missions.begin();
|
||||
name.toLower();
|
||||
while(it != m_missions.end())
|
||||
{
|
||||
Mission *mission = *it;
|
||||
if(mission->m_name.compare(name) == 0)
|
||||
{
|
||||
m_missions.erase( it );
|
||||
mission->deleteInstance();
|
||||
break;
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
Mission *newMission = newInstance(Mission);
|
||||
newMission->m_name.set(name);
|
||||
m_missions.push_back(newMission);
|
||||
return newMission;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Mission *Campaign::getMission( AsciiString missionName )
|
||||
{
|
||||
if(missionName.isEmpty())
|
||||
return NULL;
|
||||
MissionListIt it;
|
||||
it = m_missions.begin();
|
||||
// we've reached the end of the campaign
|
||||
while(it != m_missions.end())
|
||||
{
|
||||
Mission *mission = *it;
|
||||
if(mission->m_name.compare(missionName) == 0)
|
||||
return mission;
|
||||
++it;
|
||||
}
|
||||
DEBUG_ASSERTCRASH(FALSE, ("getMission couldn't find %s", missionName.str()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Mission *Campaign::getNextMission( Mission *current)
|
||||
{
|
||||
AsciiString name;
|
||||
//if passed a Null pointer, load the first mission
|
||||
if(!current)
|
||||
{
|
||||
name = m_firstMission;
|
||||
}
|
||||
else
|
||||
name = current->m_nextMission;
|
||||
name.toLower();
|
||||
MissionListIt it;
|
||||
it = m_missions.begin();
|
||||
// we've reached the end of the campaign
|
||||
if(name.isEmpty())
|
||||
return NULL;
|
||||
while(it != m_missions.end())
|
||||
{
|
||||
Mission *mission = *it;
|
||||
if(mission->m_name.compare(name) == 0)
|
||||
return mission;
|
||||
++it;
|
||||
}
|
||||
// DEBUG_ASSERTCRASH(FALSE, ("GetNextMission couldn't find %s", current->m_nextMission.str()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CampaignManager::CampaignManager( void )
|
||||
{
|
||||
m_campaignList.clear();
|
||||
m_currentCampaign = NULL;
|
||||
m_currentMission = NULL;
|
||||
m_victorious = FALSE;
|
||||
m_currentRankPoints = 0;
|
||||
m_difficulty = DIFFICULTY_NORMAL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CampaignManager::~CampaignManager( void )
|
||||
{
|
||||
m_currentCampaign = NULL;
|
||||
m_currentMission = NULL;
|
||||
|
||||
CampaignListIt it = m_campaignList.begin();
|
||||
|
||||
while(it != m_campaignList.end())
|
||||
{
|
||||
Campaign *campaign = *it;
|
||||
it = m_campaignList.erase( it );
|
||||
if(campaign)
|
||||
campaign->deleteInstance();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CampaignManager::init( void )
|
||||
{
|
||||
INI ini;
|
||||
// Read from INI all the CampaignManager
|
||||
ini.load( AsciiString( "Data\\INI\\Campaign.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Campaign *CampaignManager::getCurrentCampaign( void )
|
||||
{
|
||||
return m_currentCampaign;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Mission *CampaignManager::getCurrentMission( void )
|
||||
{
|
||||
return m_currentMission;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Mission *CampaignManager::gotoNextMission( void )
|
||||
{
|
||||
if (!m_currentCampaign || !m_currentMission)
|
||||
return NULL;
|
||||
m_currentMission = m_currentCampaign->getNextMission(m_currentMission);
|
||||
return m_currentMission;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CampaignManager::setCampaignAndMission( AsciiString campaign, AsciiString mission )
|
||||
{
|
||||
if(mission.isEmpty())
|
||||
{
|
||||
setCampaign(campaign);
|
||||
return;
|
||||
}
|
||||
CampaignListIt it;
|
||||
it = m_campaignList.begin();
|
||||
campaign.toLower();
|
||||
while ( it != m_campaignList.end())
|
||||
{
|
||||
Campaign *camp = *it;
|
||||
if(camp->m_name.compare(campaign) == 0)
|
||||
{
|
||||
m_currentCampaign = camp;
|
||||
m_currentMission = camp->getMission( mission );
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CampaignManager::setCampaign( AsciiString campaign )
|
||||
{
|
||||
CampaignListIt it;
|
||||
it = m_campaignList.begin();
|
||||
campaign.toLower();
|
||||
while ( it != m_campaignList.end())
|
||||
{
|
||||
Campaign *camp = *it;
|
||||
if(camp->m_name.compare(campaign) == 0)
|
||||
{
|
||||
m_currentCampaign = camp;
|
||||
m_currentMission = camp->getNextMission( NULL );
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
// could not find the mission. we are resetting the missions to nothing.
|
||||
m_currentCampaign = NULL;
|
||||
m_currentMission = NULL;
|
||||
m_currentRankPoints = 0;
|
||||
m_difficulty = DIFFICULTY_NORMAL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
AsciiString CampaignManager::getCurrentMap( void )
|
||||
{
|
||||
if(!m_currentMission)
|
||||
return AsciiString::TheEmptyString;
|
||||
|
||||
return m_currentMission->m_mapName;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Return the 0 based mission number */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Int CampaignManager::getCurrentMissionNumber( void )
|
||||
{
|
||||
Int number = INVALID_MISSION_NUMBER;
|
||||
|
||||
if( m_currentCampaign )
|
||||
{
|
||||
Campaign::MissionListIt it;
|
||||
|
||||
for( it = m_currentCampaign->m_missions.begin();
|
||||
it != m_currentCampaign->m_missions.end();
|
||||
++it )
|
||||
{
|
||||
|
||||
number++;
|
||||
if( *it == m_currentMission )
|
||||
return number;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return number;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void CampaignManager::parseMissionPart( INI* ini, void *instance, void *store, const void *userData )
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "Map", INI::parseAsciiString, NULL, offsetof( Mission, m_mapName ) },
|
||||
{ "NextMission", INI::parseAsciiString, NULL, offsetof( Mission, m_nextMission ) },
|
||||
{ "IntroMovie", INI::parseAsciiString, NULL, offsetof( Mission, m_movieLabel ) },
|
||||
{ "ObjectiveLine0", INI::parseAsciiString, NULL, offsetof( Mission, m_missionObjectivesLabel[0] ) },
|
||||
{ "ObjectiveLine1", INI::parseAsciiString, NULL, offsetof( Mission, m_missionObjectivesLabel[1] ) },
|
||||
{ "ObjectiveLine2", INI::parseAsciiString, NULL, offsetof( Mission, m_missionObjectivesLabel[2] ) },
|
||||
{ "ObjectiveLine3", INI::parseAsciiString, NULL, offsetof( Mission, m_missionObjectivesLabel[3] ) },
|
||||
{ "ObjectiveLine4", INI::parseAsciiString, NULL, offsetof( Mission, m_missionObjectivesLabel[4] ) },
|
||||
{ "BriefingVoice", INI::parseAudioEventRTS, NULL, offsetof( Mission, m_briefingVoice ) },
|
||||
{ "UnitNames0", INI::parseAsciiString, NULL, offsetof( Mission, m_unitNames[0] ) },
|
||||
{ "UnitNames1", INI::parseAsciiString, NULL, offsetof( Mission, m_unitNames[1] ) },
|
||||
{ "UnitNames2", INI::parseAsciiString, NULL, offsetof( Mission, m_unitNames[2] ) },
|
||||
{ "LocationNameLabel",INI::parseAsciiString, NULL, offsetof( Mission, m_locationNameLabel ) },
|
||||
{ "VoiceLength", INI::parseInt , NULL, offsetof( Mission, m_voiceLength ) },
|
||||
|
||||
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
};
|
||||
AsciiString name;
|
||||
const char* c = ini->getNextToken();
|
||||
name.set( c );
|
||||
|
||||
Mission *mission = ((Campaign*)instance)->newMission(name );
|
||||
ini->initFromINI(mission, myFieldParse);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Campaign *CampaignManager::newCampaign(AsciiString name)
|
||||
{
|
||||
CampaignListIt it;
|
||||
it = m_campaignList.begin();
|
||||
name.toLower();
|
||||
while(it != m_campaignList.end())
|
||||
{
|
||||
Campaign *campaign = *it;
|
||||
if(campaign->m_name.compare(name) == 0)
|
||||
{
|
||||
m_campaignList.erase( it );
|
||||
campaign->deleteInstance();
|
||||
break;
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
Campaign *newCampaign = newInstance(Campaign);
|
||||
newCampaign->m_name.set(name);
|
||||
m_campaignList.push_back(newCampaign);
|
||||
return newCampaign;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer method
|
||||
* Version Info
|
||||
* 1: Initial version
|
||||
* 2: Added RankPoints Saving*/
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void CampaignManager::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
const XferVersion currentVersion = 3;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
// current campaign
|
||||
AsciiString currentCampaign;
|
||||
if( m_currentCampaign )
|
||||
currentCampaign = m_currentCampaign->m_name;
|
||||
xfer->xferAsciiString( ¤tCampaign );
|
||||
|
||||
// current mission
|
||||
AsciiString currentMission;
|
||||
if( m_currentMission )
|
||||
currentMission = m_currentMission->m_name;
|
||||
xfer->xferAsciiString( ¤tMission );
|
||||
|
||||
// version 2 and above has rank points!
|
||||
if(version >= 2)
|
||||
xfer->xferInt( &m_currentRankPoints );
|
||||
|
||||
if(version >= 3)
|
||||
xfer->xferUser( &m_difficulty, sizeof(m_difficulty) );
|
||||
|
||||
// when loading, need to set the current campaign and mission
|
||||
if( xfer->getXferMode() == XFER_LOAD )
|
||||
setCampaignAndMission( currentCampaign, currentMission );
|
||||
|
||||
} // end xfer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Mission::Mission( void )
|
||||
{
|
||||
m_voiceLength = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
Mission::~Mission( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
** 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. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: Generals
|
||||
//
|
||||
// Module: Debug
|
||||
//
|
||||
// File name: AudiDebugDisplay.cpp
|
||||
//
|
||||
// Created: 11/13/01 TR
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Includes
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/DebugDisplay.h"
|
||||
#include "Common/GameAudio.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Externals
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Defines
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private Types
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private Data
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static DebugDisplayInterface *debugDisplay;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Public Data
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private Prototypes
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private Functions
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
static void printFunc( char *text )
|
||||
{
|
||||
debugDisplay->printf( text );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Public Functions
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//============================================================================
|
||||
// AudioDebugDisplay
|
||||
//============================================================================
|
||||
|
||||
#if defined(_DEBUG) || defined(_INTERNAL)
|
||||
void AudioDebugDisplay ( DebugDisplayInterface *dd, void *, FILE *fp = NULL )
|
||||
{
|
||||
TheAudio->audioDebugDisplay( dd, NULL, fp );
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
/*
|
||||
** 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. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: Generals
|
||||
//
|
||||
// Module: Debug
|
||||
//
|
||||
// File name: DebugDisplay.cpp
|
||||
//
|
||||
// Created: 11/13/01 TR
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Includes
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/DebugDisplay.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Externals
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Defines
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private Types
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private Data
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Public Data
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private Prototypes
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Private Functions
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Public Functions
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::DebugDisplay
|
||||
//============================================================================
|
||||
|
||||
DebugDisplay::DebugDisplay()
|
||||
: m_width(0),
|
||||
m_height(0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::reset
|
||||
//============================================================================
|
||||
|
||||
void DebugDisplay::reset( void )
|
||||
{
|
||||
setCursorPos( 0, 0 );
|
||||
setTextColor( WHITE );
|
||||
setRightMargin( 0 );
|
||||
setLeftMargin( getWidth() );
|
||||
}
|
||||
//============================================================================
|
||||
// DebugDisplay::setCursorPos
|
||||
//============================================================================
|
||||
|
||||
void DebugDisplay::setCursorPos( Int x, Int y )
|
||||
{
|
||||
m_xPos = x;
|
||||
m_yPos = y;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::getCursorXPos
|
||||
//============================================================================
|
||||
|
||||
Int DebugDisplay::getCursorXPos( void )
|
||||
{
|
||||
return m_xPos;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::getCursorYPos
|
||||
//============================================================================
|
||||
|
||||
Int DebugDisplay::getCursorYPos( void )
|
||||
{
|
||||
return m_yPos;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::getWidth
|
||||
//============================================================================
|
||||
|
||||
Int DebugDisplay::getWidth( void )
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::getHeight
|
||||
//============================================================================
|
||||
|
||||
Int DebugDisplay::getHeight( void )
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::setTextColor
|
||||
//============================================================================
|
||||
|
||||
void DebugDisplay::setTextColor( Color color )
|
||||
{
|
||||
m_textColor = color;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::setRightMargin
|
||||
//============================================================================
|
||||
|
||||
void DebugDisplay::setRightMargin( Int rightPos )
|
||||
{
|
||||
m_rightMargin = rightPos;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::setLeftMargin
|
||||
//============================================================================
|
||||
|
||||
void DebugDisplay::setLeftMargin( Int leftPos )
|
||||
{
|
||||
m_leftMargin = leftPos;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// DebugDisplay::printf
|
||||
//============================================================================
|
||||
|
||||
void DebugDisplay::printf( Char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int result;
|
||||
static char text[5*1024];
|
||||
|
||||
va_start( args, format );
|
||||
result = vsprintf( text, format, args );
|
||||
va_end( args );
|
||||
|
||||
if ( result < 0 )
|
||||
{
|
||||
// error while printing string
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_ASSERTCRASH( result < sizeof(text), ("text overflow in DebugDisplay::printf() - string too long"));
|
||||
|
||||
// find every line and print it
|
||||
Char *ptr = text;;
|
||||
Char *lineStart = ptr;
|
||||
Int lineLen = 0;
|
||||
Char ch;
|
||||
|
||||
while ( (ch = *ptr++) != 0 )
|
||||
{
|
||||
switch ( ch )
|
||||
{
|
||||
case '\n':
|
||||
{
|
||||
if ( lineLen > 0 )
|
||||
{
|
||||
*(ptr -1) = 0; // replace '/n' with null
|
||||
drawText( m_rightMargin + m_xPos, m_yPos, lineStart );
|
||||
lineLen = 0;
|
||||
}
|
||||
lineStart = ptr;
|
||||
m_yPos++;
|
||||
m_xPos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
lineLen++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( lineLen > 0 )
|
||||
{
|
||||
drawText( m_rightMargin + m_xPos, m_yPos, lineStart );
|
||||
m_xPos += lineLen;
|
||||
}
|
||||
}
|
342
Generals/Code/GameEngine/Source/GameClient/System/Image.cpp
Normal file
342
Generals/Code/GameEngine/Source/GameClient/System/Image.cpp
Normal file
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
** 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: Image.cpp ////////////////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, June 2001
|
||||
// Desc: High level representation of images, this is currently being
|
||||
// written so we have a way to refer to images in the windows
|
||||
// GUI, this system should be replaced with something that can
|
||||
// handle real image management or written to accomodate
|
||||
// all parts of the engine that need images.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#define DEFINE_IMAGE_STATUS_NAMES
|
||||
#include "Lib/BaseType.h"
|
||||
#include "Common/Debug.h"
|
||||
#include "Common/INI.h"
|
||||
#include "Common/GlobalData.h"
|
||||
#include "GameClient/Image.h"
|
||||
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
const FieldParse Image::m_imageFieldParseTable[] =
|
||||
{
|
||||
|
||||
{ "Texture", INI::parseAsciiString, NULL, offsetof( Image, m_filename ) },
|
||||
{ "TextureWidth", INI::parseInt, NULL, offsetof( Image, m_textureSize.x ) },
|
||||
{ "TextureHeight", INI::parseInt, NULL, offsetof( Image, m_textureSize.y ) },
|
||||
{ "Coords", Image::parseImageCoords, NULL, offsetof( Image, m_UVCoords ) },
|
||||
{ "Status", Image::parseImageStatus, NULL, offsetof( Image, m_status ) },
|
||||
|
||||
{ NULL, NULL, NULL, 0 }
|
||||
|
||||
};
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Parse an image coordinates in the form of
|
||||
*
|
||||
* COORDS = Left:AAA Top:BBB Right:CCC Bottom:DDD */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Image::parseImageCoords( INI* ini, void *instance, void *store, const void* /*userData*/ )
|
||||
{
|
||||
Int left = INI::scanInt(ini->getNextSubToken("Left"));
|
||||
Int top = INI::scanInt(ini->getNextSubToken("Top"));
|
||||
Int right = INI::scanInt(ini->getNextSubToken("Right"));
|
||||
Int bottom = INI::scanInt(ini->getNextSubToken("Bottom"));
|
||||
|
||||
// get the image we're storing in
|
||||
Image *theImage = (Image *)instance;
|
||||
|
||||
//
|
||||
// store the UV coords based on what we've read in and the texture size
|
||||
// defined for this image
|
||||
//
|
||||
Region2D uvCoords;
|
||||
|
||||
uvCoords.lo.x = (Real)left;
|
||||
uvCoords.lo.y = (Real)top;
|
||||
uvCoords.hi.x = (Real)right;
|
||||
uvCoords.hi.y = (Real)bottom;
|
||||
|
||||
// adjust the coords by texture size
|
||||
const ICoord2D *textureSize = theImage->getTextureSize();
|
||||
if( textureSize->x )
|
||||
{
|
||||
uvCoords.lo.x /= (Real)textureSize->x;
|
||||
uvCoords.hi.x /= (Real)textureSize->x;
|
||||
} // end if
|
||||
if( textureSize->y )
|
||||
{
|
||||
uvCoords.lo.y /= (Real)textureSize->y;
|
||||
uvCoords.hi.y /= (Real)textureSize->y;
|
||||
} // end if
|
||||
|
||||
// store the uv coords
|
||||
theImage->setUV( &uvCoords );
|
||||
|
||||
// compute the image size based on the coords we read and store
|
||||
ICoord2D imageSize;
|
||||
imageSize.x = right - left;
|
||||
imageSize.y = bottom - top;
|
||||
theImage->setImageSize( &imageSize );
|
||||
|
||||
} // end parseImageCoord
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Parse the image status line */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Image::parseImageStatus( INI* ini, void *instance, void *store, const void* /*userData*/)
|
||||
{
|
||||
// use existing INI parsing for the bit strings
|
||||
INI::parseBitString32(ini, instance, store, imageStatusNames);
|
||||
|
||||
//
|
||||
// if we are rotated 90 degrees clockwise we need to swap our width and height as
|
||||
// they were computed from the page location rect, which was for the rotated image
|
||||
// (see ImagePacker tool for more details)
|
||||
//
|
||||
UnsignedInt *theStatusBits = (UnsignedInt *)store;
|
||||
if( BitTest( *theStatusBits, IMAGE_STATUS_ROTATED_90_CLOCKWISE ) )
|
||||
{
|
||||
Image *theImage = (Image *)instance;
|
||||
ICoord2D imageSize;
|
||||
|
||||
imageSize.x = theImage->getImageHeight(); // note it's height not width
|
||||
imageSize.y = theImage->getImageWidth(); // note it's width not height
|
||||
theImage->setImageSize( &imageSize );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end parseImageStatus
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
|
||||
ImageCollection *TheMappedImageCollection = NULL; ///< mapped images
|
||||
|
||||
// PUBLIC FUNCTIONS////////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Image::Image( void )
|
||||
{
|
||||
|
||||
m_name.clear();
|
||||
m_filename.clear();
|
||||
m_textureSize.x = 0;
|
||||
m_textureSize.y = 0;
|
||||
m_UVCoords.lo.x = 0.0f;
|
||||
m_UVCoords.lo.y = 0.0f;
|
||||
m_UVCoords.hi.x = 1.0f;
|
||||
m_UVCoords.hi.y = 1.0f;
|
||||
m_imageSize.x = 0;
|
||||
m_imageSize.y = 0;
|
||||
m_rawTextureData = NULL;
|
||||
m_status = IMAGE_STATUS_NONE;
|
||||
m_next = NULL;
|
||||
|
||||
} // end Image
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Image::~Image( void )
|
||||
{
|
||||
|
||||
} // end ~Image
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Set a status bit into the existing status, return the previous status
|
||||
* bit collection from before the set */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
UnsignedInt Image::setStatus( UnsignedInt bit )
|
||||
{
|
||||
UnsignedInt prevStatus = m_status;
|
||||
|
||||
BitSet( m_status, bit );
|
||||
return prevStatus;
|
||||
|
||||
} // end setStatus
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Clear a status bit from the existing status, return the previous
|
||||
* status bit collection from before the clear */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
UnsignedInt Image::clearStatus( UnsignedInt bit )
|
||||
{
|
||||
UnsignedInt prevStatus = m_status;
|
||||
|
||||
BitClear( m_status, bit );
|
||||
return prevStatus;
|
||||
|
||||
} // end clearStatus
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ImageCollection::ImageCollection( void )
|
||||
{
|
||||
|
||||
m_imageList = NULL;
|
||||
|
||||
} // end ImageCollection
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
ImageCollection::~ImageCollection( void )
|
||||
{
|
||||
Image *image, *next;
|
||||
|
||||
// delete the images
|
||||
image = m_imageList;
|
||||
while( image )
|
||||
{
|
||||
|
||||
next = image->m_next;
|
||||
image->deleteInstance();
|
||||
image = next;
|
||||
|
||||
} // end while
|
||||
m_imageList = NULL;
|
||||
|
||||
} // end ~ImageCollection
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Return the next image in the collection */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Image *ImageCollection::nextImage( Image *image )
|
||||
{
|
||||
|
||||
if( image )
|
||||
return image->m_next;
|
||||
|
||||
return NULL;
|
||||
|
||||
} // end nextImage
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Allocate a new image, tie to the image list and return it */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Image *ImageCollection::newImage( void )
|
||||
{
|
||||
Image *image = newInstance(Image);
|
||||
|
||||
// attach to collection list
|
||||
image->m_next = m_imageList;
|
||||
m_imageList = image;
|
||||
|
||||
return image;
|
||||
|
||||
} // end newImage
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Find an image given the image name */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const Image *ImageCollection::findImageByName( const AsciiString& name )
|
||||
{
|
||||
Image *image;
|
||||
|
||||
/** @todo this needs to be more intelligent if this image collection
|
||||
becomes a real system we use a lot */
|
||||
|
||||
// search the images
|
||||
image = m_imageList;
|
||||
while( image )
|
||||
{
|
||||
|
||||
//
|
||||
// want to do a case insensitive compare here cause image INI files are
|
||||
// autogenerated from filenames using the image packer tool
|
||||
//
|
||||
if( image->getName().compareNoCase( name.str() ) == 0 )
|
||||
return image;
|
||||
image = image->m_next;
|
||||
|
||||
} // end while
|
||||
|
||||
// not found
|
||||
return NULL;
|
||||
|
||||
} // end findImageByName
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Find image given image filename */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const Image *ImageCollection::findImageByFilename( const AsciiString& filename )
|
||||
{
|
||||
Image *image;
|
||||
|
||||
/** @todo this needs to be more intelligent if this image collection
|
||||
becomes a real system we use a lot */
|
||||
|
||||
// search the images
|
||||
image = m_imageList;
|
||||
while( image )
|
||||
{
|
||||
|
||||
if( image->getFilename() == filename )
|
||||
return image;
|
||||
image = image->m_next;
|
||||
|
||||
} // end while
|
||||
|
||||
// not found
|
||||
return NULL;
|
||||
|
||||
} // end findImageByFilename
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Load this image collection with all the images specified in the INI files
|
||||
* for the proper texture size directory */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ImageCollection::load( Int textureSize )
|
||||
{
|
||||
char buffer[ _MAX_PATH ];
|
||||
INI ini;
|
||||
// first load in the user created mapped image files if we have them.
|
||||
WIN32_FIND_DATA findData;
|
||||
AsciiString userDataPath;
|
||||
if(TheGlobalData)
|
||||
{
|
||||
userDataPath.format("%sINI\\MappedImages\\*.ini",TheGlobalData->getPath_UserData().str());
|
||||
if(FindFirstFile(userDataPath.str(), &findData) !=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
userDataPath.format("%sINI\\MappedImages",TheGlobalData->getPath_UserData().str());
|
||||
ini.loadDirectory(userDataPath, TRUE, INI_LOAD_OVERWRITE, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// construct path to the mapped images folder of the correct texture size
|
||||
sprintf( buffer, "Data\\INI\\MappedImages\\TextureSize_%d", textureSize );
|
||||
|
||||
// load all the ine files in that directory
|
||||
|
||||
ini.loadDirectory( AsciiString( buffer ), TRUE, INI_LOAD_OVERWRITE, NULL );
|
||||
|
||||
ini.loadDirectory("Data\\INI\\MappedImages\\HandCreated", TRUE, INI_LOAD_OVERWRITE, NULL );
|
||||
|
||||
|
||||
} // end load
|
3509
Generals/Code/GameEngine/Source/GameClient/System/ParticleSys.cpp
Normal file
3509
Generals/Code/GameEngine/Source/GameClient/System/ParticleSys.cpp
Normal file
File diff suppressed because it is too large
Load diff
204
Generals/Code/GameEngine/Source/GameClient/System/RayEffect.cpp
Normal file
204
Generals/Code/GameEngine/Source/GameClient/System/RayEffect.cpp
Normal file
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
** 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: RayEffect.cpp ////////////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, May 2001
|
||||
// Desc: Ray effect system manager
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/RayEffect.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
|
||||
class RayEffectSystem *TheRayEffects = NULL;
|
||||
|
||||
// PRIVATE METHODS ////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Find an effect entry given a drawable */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
RayEffectData *RayEffectSystem::findEntry( const Drawable *draw )
|
||||
{
|
||||
Int i;
|
||||
RayEffectData *effectData = NULL;
|
||||
|
||||
// find the matching effect data entry
|
||||
for( i = 0; i < MAX_RAY_EFFECTS; i++ )
|
||||
{
|
||||
|
||||
if( m_effectData[ i ].draw == draw )
|
||||
{
|
||||
|
||||
effectData = &m_effectData[ i ];
|
||||
break; // exit for i
|
||||
|
||||
} // end if
|
||||
|
||||
} // end for i
|
||||
|
||||
return effectData;
|
||||
|
||||
} // end findEntry
|
||||
|
||||
// PUBLIC METHODS /////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
RayEffectSystem::RayEffectSystem( void )
|
||||
{
|
||||
|
||||
init();
|
||||
|
||||
} // end RayEffectSystem
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
RayEffectSystem::~RayEffectSystem( void )
|
||||
{
|
||||
|
||||
} // end ~RayEffectSystem
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** initialize the system */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void RayEffectSystem::init( void )
|
||||
{
|
||||
Int i;
|
||||
|
||||
for( i = 0; i < MAX_RAY_EFFECTS; i++ )
|
||||
{
|
||||
|
||||
m_effectData[ i ].draw = NULL;
|
||||
m_effectData[ i ].startLoc.zero();
|
||||
m_effectData[ i ].endLoc.zero();
|
||||
|
||||
} // end for i
|
||||
|
||||
} // end init
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Reset */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void RayEffectSystem::reset( void )
|
||||
{
|
||||
|
||||
// nothing dynamic going on here, just initialize it
|
||||
init();
|
||||
|
||||
} // end reset
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** add a ray effect entry for this drawable */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void RayEffectSystem::addRayEffect( const Drawable *draw,
|
||||
const Coord3D *startLoc,
|
||||
const Coord3D *endLoc )
|
||||
{
|
||||
Int i;
|
||||
RayEffectData *effectData = NULL;
|
||||
|
||||
// sanity
|
||||
if( draw == NULL || startLoc == NULL || endLoc == NULL )
|
||||
return;
|
||||
|
||||
/** @todo this should be more intelligent and should not be limited
|
||||
to any kind of max ray effects, this is all a temporary hack system for
|
||||
the demo anyway right now though */
|
||||
|
||||
// search for a free effect slot
|
||||
for( i = 0; i < MAX_RAY_EFFECTS; i++ )
|
||||
{
|
||||
|
||||
if( m_effectData[ i ].draw == NULL )
|
||||
{
|
||||
|
||||
effectData = &m_effectData[ i ];
|
||||
break; // exit for
|
||||
|
||||
} // end if
|
||||
|
||||
} // end for i
|
||||
|
||||
// if no free slots we can't do it
|
||||
if( effectData == NULL )
|
||||
return;
|
||||
|
||||
// add the data to the entry
|
||||
effectData->draw = draw;
|
||||
effectData->startLoc = *startLoc;
|
||||
effectData->endLoc = *endLoc;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** given a drawable, remove its effect from the system */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void RayEffectSystem::deleteRayEffect( const Drawable *draw )
|
||||
{
|
||||
RayEffectData *effectData = NULL;
|
||||
|
||||
// sanity
|
||||
if( draw == NULL )
|
||||
return;
|
||||
|
||||
// find the effect entry
|
||||
effectData = findEntry( draw );
|
||||
if( effectData )
|
||||
{
|
||||
|
||||
// remove the data for this entry
|
||||
effectData->draw = NULL;
|
||||
|
||||
} // end if
|
||||
|
||||
} // end deleteRayEffect
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** given a drawable, if it is in the ray effect system list retrieve
|
||||
* the ray effect data for its entry */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void RayEffectSystem::getRayEffectData( const Drawable *draw,
|
||||
RayEffectData *effectData )
|
||||
{
|
||||
RayEffectData *entry = NULL;
|
||||
|
||||
// sanity
|
||||
if( draw == NULL || effectData == NULL )
|
||||
return;
|
||||
|
||||
// find the effect data entry
|
||||
entry = findEntry( draw );
|
||||
if( entry )
|
||||
{
|
||||
|
||||
// data has been found, copy to parameter
|
||||
*effectData = *entry;
|
||||
|
||||
} // end effectData
|
||||
|
||||
} // end getRayEffectData
|
||||
|
Reference in a new issue