mirror of
https://github.com/electronicarts/CnC_Generals_Zero_Hour.git
synced 2025-12-16 23:51:41 -05:00
Initial commit of Command & Conquer Generals and Command & Conquer Generals Zero Hour source code.
This commit is contained in:
117
Generals/Code/GameEngine/Source/GameClient/Color.cpp
Normal file
117
Generals/Code/GameEngine/Source/GameClient/Color.cpp
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
** 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: Color.cpp ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: Color.cpp
|
||||
//
|
||||
// Created: Colin Day, July 2001
|
||||
//
|
||||
// Desc: Management of color representations
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/Color.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GameMakeColor ==============================================================
|
||||
/** Create a color representation given red, green, blue, and
|
||||
* alpha components
|
||||
*
|
||||
* NOTE: pure solid white (255, 255, 255, 255) will translate
|
||||
* intoa -1 which is GAME_COLOR_UNDEFINED
|
||||
*/
|
||||
//=============================================================================
|
||||
|
||||
// GameGetColorComponents =====================================================
|
||||
/** Get the RGB color comonents of a color */
|
||||
//=============================================================================
|
||||
void GameGetColorComponents( Color color,
|
||||
UnsignedByte *red,
|
||||
UnsignedByte *green,
|
||||
UnsignedByte *blue,
|
||||
UnsignedByte *alpha )
|
||||
{
|
||||
|
||||
*alpha = (color & 0xFF000000) >> 24;
|
||||
*red = (color & 0x00FF0000) >> 16;
|
||||
*green = (color & 0x0000FF00) >> 8;
|
||||
*blue = (color & 0x000000FF);
|
||||
|
||||
} // end GameGetColorComponents
|
||||
|
||||
void GameGetColorComponentsReal( Color color, Real *red, Real *green, Real *blue, Real *alpha )
|
||||
{
|
||||
*alpha = ((color & 0xFF000000) >> 24) / 255.0f;
|
||||
*red = ((color & 0x00FF0000) >> 16) / 255.0f;
|
||||
*green = ((color & 0x0000FF00) >> 8) / 255.0f;
|
||||
*blue = (color & 0x000000FF) / 255.0f;
|
||||
}
|
||||
|
||||
|
||||
Color GameDarkenColor( Color color, Int percent )
|
||||
{
|
||||
// if they try to go to dark, just return their old color
|
||||
if(percent >= 90 || percent <= 0)
|
||||
return color;
|
||||
|
||||
UnsignedByte r, g, b, a;
|
||||
GameGetColorComponents(color,&r,&g,&b,&a);
|
||||
r -= (r * percent / 100);
|
||||
g -= (g * percent / 100);
|
||||
b -= (b * percent / 100);
|
||||
|
||||
return GameMakeColor(r,g,b,a);
|
||||
}// end GameDarkenColor
|
||||
490
Generals/Code/GameEngine/Source/GameClient/Credits.cpp
Normal file
490
Generals/Code/GameEngine/Source/GameClient/Credits.cpp
Normal file
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
** 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: Credits.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Dec 2002
|
||||
//
|
||||
// Filename: Credits.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: This is where all the credit texts is going to be held.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "Common/INI.h"
|
||||
#include "GameClient/Credits.h"
|
||||
#include "GameClient/DisplayStringManager.h"
|
||||
#include "GameClient/Display.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GlobalLanguage.h"
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
CreditsManager *TheCredits = NULL;
|
||||
|
||||
const FieldParse CreditsManager::m_creditsFieldParseTable[] =
|
||||
{
|
||||
|
||||
{ "ScrollRate", INI::parseInt, NULL, offsetof( CreditsManager, m_scrollRate ) },
|
||||
{ "ScrollRateEveryFrames", INI::parseInt, NULL, offsetof( CreditsManager, m_scrollRatePerFrames ) },
|
||||
{ "ScrollDown", INI::parseBool, NULL, offsetof( CreditsManager, m_scrollDown ) },
|
||||
{ "TitleColor", INI::parseColorInt, NULL, offsetof( CreditsManager, m_titleColor ) },
|
||||
{ "MinorTitleColor", INI::parseColorInt, NULL, offsetof( CreditsManager, m_positionColor ) },
|
||||
{ "NormalColor", INI::parseColorInt, NULL, offsetof( CreditsManager, m_normalColor ) },
|
||||
{ "Style", INI::parseLookupList, CreditStyleNames, offsetof( CreditsManager, m_currentStyle ) },
|
||||
{ "Blank", CreditsManager::parseBlank, NULL, NULL },
|
||||
{ "Text", CreditsManager::parseText, NULL, NULL },
|
||||
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void INI::parseCredits( INI *ini )
|
||||
{
|
||||
// find existing item if present
|
||||
DEBUG_ASSERTCRASH( TheCredits, ("parseCredits: TheCredits has not been ininialized yet.\n") );
|
||||
if( !TheCredits )
|
||||
return;
|
||||
|
||||
// parse the ini definition
|
||||
ini->initFromINI( TheCredits, TheCredits->getFieldParse() );
|
||||
|
||||
} // end parseCommandButtonDefinition
|
||||
|
||||
|
||||
CreditsLine::CreditsLine()
|
||||
{
|
||||
m_useSecond = FALSE;
|
||||
m_done = FALSE;
|
||||
m_style = CREDIT_STYLE_BLANK;
|
||||
m_displayString = NULL;
|
||||
m_secondDisplayString = NULL;
|
||||
}
|
||||
|
||||
CreditsLine::~CreditsLine()
|
||||
{
|
||||
if(m_displayString)
|
||||
TheDisplayStringManager->freeDisplayString(m_displayString);
|
||||
if(m_secondDisplayString)
|
||||
TheDisplayStringManager->freeDisplayString(m_secondDisplayString);
|
||||
|
||||
m_displayString = NULL;
|
||||
m_secondDisplayString = NULL;
|
||||
}
|
||||
|
||||
|
||||
CreditsManager::CreditsManager(void)
|
||||
{
|
||||
m_scrollRate = 1; // in pixels
|
||||
m_scrollRatePerFrames = 1;
|
||||
m_scrollDown = TRUE; // if TRUE text will come from the top to the bottom if False, it will go from the bottom up
|
||||
m_framesSinceStarted = 0;
|
||||
m_titleColor = m_positionColor = m_normalColor = GameMakeColor(255,255,255,255);
|
||||
|
||||
m_currentStyle = CREDIT_STYLE_NORMAL;
|
||||
m_isFinished = FALSE;
|
||||
m_normalFontHeight = 10;
|
||||
}
|
||||
|
||||
CreditsManager::~CreditsManager(void)
|
||||
{
|
||||
|
||||
m_displayedCreditLineList.clear();
|
||||
CreditsLineList::iterator it =m_creditLineList.begin();
|
||||
while (it != m_creditLineList.end())
|
||||
{
|
||||
CreditsLine *cLine = *it;
|
||||
delete cLine;
|
||||
it = m_creditLineList.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void CreditsManager::init(void )
|
||||
{
|
||||
m_isFinished = FALSE;
|
||||
m_creditLineListIt = m_creditLineList.begin();
|
||||
m_framesSinceStarted = 0;
|
||||
}
|
||||
|
||||
void CreditsManager::load(void )
|
||||
{
|
||||
INI ini;
|
||||
// Read from INI all the ControlBarSchemes
|
||||
ini.load( AsciiString( "Data\\INI\\Credits.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||||
|
||||
if(m_scrollRatePerFrames <=0)
|
||||
m_scrollRatePerFrames = 1;
|
||||
if(m_scrollRate <=0)
|
||||
m_scrollRate = 1;
|
||||
|
||||
GameFont *font = TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsNormalFont.name,
|
||||
TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsNormalFont.size),
|
||||
TheGlobalLanguageData->m_creditsNormalFont.bold);
|
||||
|
||||
m_normalFontHeight = font->height;
|
||||
}
|
||||
|
||||
void CreditsManager::reset( void )
|
||||
{
|
||||
m_displayedCreditLineList.clear();
|
||||
m_isFinished = FALSE;
|
||||
m_creditLineListIt = m_creditLineList.begin();
|
||||
m_framesSinceStarted = 0;
|
||||
|
||||
}
|
||||
|
||||
void CreditsManager::update( void )
|
||||
{
|
||||
if(m_isFinished)
|
||||
return;
|
||||
m_framesSinceStarted++;
|
||||
|
||||
if(m_framesSinceStarted%m_scrollRatePerFrames != 0)
|
||||
return;
|
||||
|
||||
|
||||
Int y = 0;
|
||||
Int yTest = 0;
|
||||
Int lastHeight = 0;
|
||||
Int start = m_scrollDown? 0:TheDisplay->getHeight();
|
||||
Int end =m_scrollDown? TheDisplay->getHeight():0;
|
||||
Int offsetStartMultiplyer = m_scrollDown? -1:0; // if we're scrolling from the top, we need to subtract the height
|
||||
Int offsetEndMultiplyer = m_scrollDown? 0:1;
|
||||
Int directionMultiplyer = m_scrollDown? 1:-1;
|
||||
CreditsLineList::iterator drawIt = m_displayedCreditLineList.begin();
|
||||
while (drawIt != m_displayedCreditLineList.end())
|
||||
{
|
||||
CreditsLine *cLine = *drawIt;
|
||||
y = cLine->m_pos.y = cLine->m_pos.y + (m_scrollRate * directionMultiplyer);
|
||||
lastHeight = cLine->m_height;
|
||||
yTest = y + ((lastHeight + CREDIT_SPACE_OFFSET) * offsetEndMultiplyer);
|
||||
if(((m_scrollDown && (yTest > end)) || (!m_scrollDown && (yTest < end))))
|
||||
{
|
||||
TheDisplayStringManager->freeDisplayString(cLine->m_displayString);
|
||||
TheDisplayStringManager->freeDisplayString(cLine->m_secondDisplayString);
|
||||
cLine->m_displayString = NULL;
|
||||
cLine->m_secondDisplayString = NULL;
|
||||
drawIt = m_displayedCreditLineList.erase(drawIt);
|
||||
}
|
||||
else
|
||||
drawIt++;
|
||||
}
|
||||
|
||||
y= y + ((lastHeight + CREDIT_SPACE_OFFSET) * offsetStartMultiplyer);
|
||||
|
||||
// is it time to add a new string?
|
||||
if(!((m_scrollDown && (yTest >= start)) || (!m_scrollDown && (yTest <= start))))
|
||||
return;
|
||||
|
||||
if(m_displayedCreditLineList.size() == 0 && m_creditLineListIt == m_creditLineList.end())
|
||||
m_isFinished = TRUE;
|
||||
|
||||
if(m_creditLineListIt == m_creditLineList.end())
|
||||
return;
|
||||
|
||||
CreditsLine *cLine = *m_creditLineListIt;
|
||||
ICoord2D pos;
|
||||
switch (cLine->m_style)
|
||||
{
|
||||
case CREDIT_STYLE_TITLE:
|
||||
{
|
||||
cLine->m_color = m_titleColor;
|
||||
|
||||
if(TheGlobalLanguageData&& !cLine->m_text.isEmpty())
|
||||
{
|
||||
DisplayString *ds = TheDisplayStringManager->newDisplayString();
|
||||
if(!ds)
|
||||
return;
|
||||
ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsTitleFont.name,
|
||||
TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsTitleFont.size),
|
||||
TheGlobalLanguageData->m_creditsTitleFont.bold));
|
||||
ds->setText(cLine->m_text);
|
||||
ds->getSize(&pos.x,&pos.y);
|
||||
cLine->m_height = pos.y;
|
||||
cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
|
||||
cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplyer);
|
||||
cLine->m_displayString = ds;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CREDIT_STYLE_POSITION:
|
||||
{
|
||||
cLine->m_color = m_positionColor;
|
||||
|
||||
if(TheGlobalLanguageData && !cLine->m_text.isEmpty())
|
||||
{
|
||||
DisplayString *ds = TheDisplayStringManager->newDisplayString();
|
||||
if(!ds)
|
||||
return;
|
||||
ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsPositionFont.name,
|
||||
TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsPositionFont.size),
|
||||
TheGlobalLanguageData->m_creditsPositionFont.bold));
|
||||
ds->setText(cLine->m_text);
|
||||
ds->getSize(&pos.x,&pos.y);
|
||||
cLine->m_height = pos.y;
|
||||
cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
|
||||
cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplyer);
|
||||
cLine->m_displayString = ds;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CREDIT_STYLE_NORMAL:
|
||||
{
|
||||
cLine->m_color = m_normalColor;
|
||||
|
||||
if(TheGlobalLanguageData && !cLine->m_text.isEmpty())
|
||||
{
|
||||
DisplayString *ds = TheDisplayStringManager->newDisplayString();
|
||||
if(!ds)
|
||||
return;
|
||||
ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsNormalFont.name,
|
||||
TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsNormalFont.size),
|
||||
TheGlobalLanguageData->m_creditsNormalFont.bold));
|
||||
ds->setText(cLine->m_text);
|
||||
ds->getSize(&pos.x,&pos.y);
|
||||
cLine->m_height = pos.y;
|
||||
cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
|
||||
cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplyer);
|
||||
cLine->m_displayString = ds;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CREDIT_STYLE_COLUMN:
|
||||
{
|
||||
cLine->m_color = m_normalColor;
|
||||
|
||||
if(TheGlobalLanguageData && !cLine->m_text.isEmpty())
|
||||
{
|
||||
DisplayString *ds = TheDisplayStringManager->newDisplayString();
|
||||
if(!ds)
|
||||
return;
|
||||
ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsNormalFont.name,
|
||||
TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsNormalFont.size),
|
||||
TheGlobalLanguageData->m_creditsNormalFont.bold));
|
||||
ds->setText(cLine->m_text);
|
||||
ds->getSize(&pos.x,&pos.y);
|
||||
cLine->m_height = pos.y;
|
||||
cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
|
||||
cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplyer);
|
||||
cLine->m_displayString = ds;
|
||||
}
|
||||
if(TheGlobalLanguageData && !cLine->m_secondText.isEmpty())
|
||||
{
|
||||
DisplayString *ds = TheDisplayStringManager->newDisplayString();
|
||||
if(!ds)
|
||||
return;
|
||||
ds->setFont(TheFontLibrary->getFont(TheGlobalLanguageData->m_creditsNormalFont.name,
|
||||
TheGlobalLanguageData->adjustFontSize(TheGlobalLanguageData->m_creditsNormalFont.size),
|
||||
TheGlobalLanguageData->m_creditsNormalFont.bold));
|
||||
ds->setText(cLine->m_secondText);
|
||||
ds->getSize(&pos.x,&pos.y);
|
||||
cLine->m_height = pos.y;
|
||||
cLine->m_pos.x = TheDisplay->getWidth()/2 - pos.x/2 ;
|
||||
cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplyer);
|
||||
cLine->m_secondDisplayString = ds;
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CREDIT_STYLE_BLANK:
|
||||
{
|
||||
cLine->m_height = m_normalFontHeight;
|
||||
cLine->m_pos.y = start + (cLine->m_height * offsetStartMultiplyer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
m_displayedCreditLineList.push_back(cLine);
|
||||
|
||||
if(m_creditLineListIt != m_creditLineList.end())
|
||||
m_creditLineListIt++;
|
||||
|
||||
}
|
||||
|
||||
void CreditsManager::draw( void )
|
||||
{
|
||||
CreditsLineList::iterator drawIt = m_displayedCreditLineList.begin();
|
||||
while (drawIt != m_displayedCreditLineList.end())
|
||||
{
|
||||
CreditsLine *cLine = *drawIt;
|
||||
Int heightChunk = TheDisplay->getHeight()/3;
|
||||
Real perc = 0.0f;
|
||||
if(cLine->m_pos.y < heightChunk || cLine->m_pos.y > heightChunk * 2)
|
||||
{
|
||||
// adjust the color
|
||||
if( cLine->m_pos.y < 0 || cLine->m_pos.y > TheDisplay->getHeight())
|
||||
perc = 0.0f;
|
||||
else if( cLine->m_pos.y < heightChunk)
|
||||
perc = INT_TO_REAL(cLine->m_pos.y) / heightChunk;
|
||||
else
|
||||
perc = 1 - INT_TO_REAL(cLine->m_pos.y - 2*heightChunk) / heightChunk;
|
||||
}
|
||||
else
|
||||
perc = 1.0f;
|
||||
UnsignedByte r,g,b,a;
|
||||
GameGetColorComponents(cLine->m_color, &r, &g, &b, &a);
|
||||
Int color = GameMakeColor( r,g,b, a * perc);
|
||||
Int bColor= GameMakeColor( 0,0,0, a * perc);
|
||||
|
||||
switch (cLine->m_style) {
|
||||
case CREDIT_STYLE_TITLE:
|
||||
case CREDIT_STYLE_POSITION:
|
||||
case CREDIT_STYLE_NORMAL:
|
||||
{
|
||||
if(cLine->m_displayString)
|
||||
cLine->m_displayString->draw(cLine->m_pos.x,cLine->m_pos.y,color, bColor, 1,1 );
|
||||
}
|
||||
break;
|
||||
case CREDIT_STYLE_COLUMN:
|
||||
{
|
||||
Int chunk = TheDisplay->getWidth()/3;
|
||||
ICoord2D pos;
|
||||
if(cLine->m_displayString)
|
||||
{
|
||||
cLine->m_displayString->getSize(&pos.x, &pos.y);
|
||||
cLine->m_displayString->draw(chunk - (pos.x/2),cLine->m_pos.y,color, bColor, 1,1 );
|
||||
}
|
||||
if(cLine->m_secondDisplayString)
|
||||
{
|
||||
cLine->m_secondDisplayString->getSize(&pos.x, &pos.y);
|
||||
cLine->m_secondDisplayString->draw(2*chunk - (pos.x/2),cLine->m_pos.y,color, bColor, 1,1 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
drawIt++;
|
||||
}
|
||||
}
|
||||
void CreditsManager::addBlank( void )
|
||||
{
|
||||
CreditsLine *cLine = new CreditsLine;
|
||||
cLine->m_style = CREDIT_STYLE_BLANK;
|
||||
m_creditLineList.push_back(cLine);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CreditsManager::parseBlank( INI* ini, void *instance, void *store, const void *userData )
|
||||
{
|
||||
CreditsManager *cManager = (CreditsManager *)instance;
|
||||
cManager->addBlank();
|
||||
}
|
||||
|
||||
void CreditsManager::parseText( INI* ini, void *instance, void *store, const void *userData )
|
||||
{
|
||||
|
||||
AsciiString asciiString = ini->getNextQuotedAsciiString();
|
||||
CreditsManager *cManager = (CreditsManager *)instance;
|
||||
cManager->addText(asciiString);
|
||||
}
|
||||
void CreditsManager::addText( AsciiString text )
|
||||
{
|
||||
CreditsLine *cLine = new CreditsLine;
|
||||
|
||||
switch (m_currentStyle)
|
||||
{
|
||||
case CREDIT_STYLE_TITLE:
|
||||
case CREDIT_STYLE_POSITION:
|
||||
case CREDIT_STYLE_NORMAL:
|
||||
{
|
||||
cLine->m_text = getUnicodeString(text);
|
||||
cLine->m_style = m_currentStyle;
|
||||
m_creditLineList.push_back(cLine);
|
||||
}
|
||||
break;
|
||||
case CREDIT_STYLE_COLUMN:
|
||||
{
|
||||
CreditsLineList::reverse_iterator rIt = m_creditLineList.rbegin();
|
||||
CreditsLine *rcLine = *rIt;
|
||||
if(rIt == m_creditLineList.rend() || rcLine->m_style != CREDIT_STYLE_COLUMN
|
||||
|| (rcLine->m_style == CREDIT_STYLE_COLUMN && rcLine->m_done == TRUE))
|
||||
{
|
||||
cLine->m_text = getUnicodeString(text);
|
||||
cLine->m_style = CREDIT_STYLE_COLUMN;
|
||||
cLine->m_useSecond = TRUE;
|
||||
m_creditLineList.push_back(cLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
rcLine->m_secondText = getUnicodeString(text);
|
||||
rcLine->m_done = TRUE;
|
||||
delete cLine;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
DEBUG_ASSERTCRASH( FALSE, ("CreditsManager::addText we tried to add a credit text with the wrong style before it. Style is %d\n", m_currentStyle) );
|
||||
delete cLine;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
UnicodeString CreditsManager::getUnicodeString(AsciiString str)
|
||||
{
|
||||
UnicodeString uStr;
|
||||
if(str.compare("<BLANK>") == 0)
|
||||
return UnicodeString::TheEmptyString;
|
||||
|
||||
if(str.find(':'))
|
||||
uStr = TheGameText->fetch(str);
|
||||
else
|
||||
uStr.translate(str);
|
||||
|
||||
return uStr;
|
||||
}
|
||||
385
Generals/Code/GameEngine/Source/GameClient/Display.cpp
Normal file
385
Generals/Code/GameEngine/Source/GameClient/Display.cpp
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
** 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;
|
||||
}
|
||||
147
Generals/Code/GameEngine/Source/GameClient/DisplayString.cpp
Normal file
147
Generals/Code/GameEngine/Source/GameClient/DisplayString.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
** 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: DisplayString.cpp ////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: DisplayString.cpp
|
||||
//
|
||||
// Created: Colin Day, July 2001
|
||||
//
|
||||
// Desc: Contstuct for holding double byte game string data and being
|
||||
// able to draw that text to the screen.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Debug.h"
|
||||
#include "Common/Language.h"
|
||||
#include "GameClient/DisplayString.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// DisplayString::DisplayString ===============================================
|
||||
/** */
|
||||
//=============================================================================
|
||||
DisplayString::DisplayString( void )
|
||||
{
|
||||
// m_textString = ""; // not necessary, done by default
|
||||
m_font = NULL;
|
||||
|
||||
m_next = NULL;
|
||||
m_prev = NULL;
|
||||
|
||||
} // end DisplayString
|
||||
|
||||
// DisplayString::~DisplayString ==============================================
|
||||
/** */
|
||||
//=============================================================================
|
||||
DisplayString::~DisplayString( void )
|
||||
{
|
||||
|
||||
// free any data
|
||||
reset();
|
||||
|
||||
} // end ~DisplayString
|
||||
|
||||
// DisplayString::setText =====================================================
|
||||
/** Copy the text to this instance */
|
||||
//=============================================================================
|
||||
void DisplayString::setText( UnicodeString text )
|
||||
{
|
||||
if (text == m_textString)
|
||||
return;
|
||||
|
||||
m_textString = text;
|
||||
|
||||
// our text has now changed
|
||||
notifyTextChanged();
|
||||
|
||||
} // end setText
|
||||
|
||||
// DisplayString::reset =======================================================
|
||||
/** Free and reset all the data for this string, effectively making this
|
||||
* instance like brand new */
|
||||
//=============================================================================
|
||||
void DisplayString::reset( void )
|
||||
{
|
||||
|
||||
m_textString.clear();
|
||||
|
||||
// no font
|
||||
m_font = NULL;
|
||||
|
||||
} // end reset
|
||||
|
||||
// DisplayString::removeLastChar ==============================================
|
||||
/** Remove the last character from the string text */
|
||||
//=============================================================================
|
||||
void DisplayString::removeLastChar( void )
|
||||
{
|
||||
m_textString.removeLastChar();
|
||||
|
||||
// our text has now changed
|
||||
notifyTextChanged();
|
||||
|
||||
} // end removeLastChar
|
||||
|
||||
// DisplayString::appendChar ==================================================
|
||||
/** Append character to the end of the string */
|
||||
//=============================================================================
|
||||
void DisplayString::appendChar( WideChar c )
|
||||
{
|
||||
m_textString.concat(c);
|
||||
|
||||
// text has now changed
|
||||
notifyTextChanged();
|
||||
|
||||
} // end appendchar
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
** 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: DisplayStringManager.cpp /////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, July 2001
|
||||
// Desc: Access for creating game managed display strings
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/DisplayStringManager.h"
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
|
||||
DisplayStringManager *TheDisplayStringManager = NULL;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DisplayStringManager::DisplayStringManager( void )
|
||||
{
|
||||
|
||||
m_stringList = NULL;
|
||||
m_currentCheckpoint = NULL;
|
||||
|
||||
} // end DisplayStringManager
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
DisplayStringManager::~DisplayStringManager( void )
|
||||
{
|
||||
|
||||
//
|
||||
// we only keep track of the strings, we do NOT de-allocate them, our
|
||||
// list better be cleaned out before we destroy ourselves
|
||||
//
|
||||
assert( m_stringList == NULL );
|
||||
|
||||
} // end ~DisplayStringManager
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Link a display string to the master list */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DisplayStringManager::link( DisplayString *string )
|
||||
{
|
||||
|
||||
assert( string );
|
||||
assert( string->m_next == NULL );
|
||||
assert( string->m_prev == NULL );
|
||||
|
||||
string->m_next = m_stringList;
|
||||
if( m_stringList )
|
||||
m_stringList->m_prev = string;
|
||||
|
||||
m_stringList = string;
|
||||
|
||||
} // end link
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Unlink a display string from the master list */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DisplayStringManager::unLink( DisplayString *string )
|
||||
{
|
||||
|
||||
assert( string );
|
||||
assert( m_stringList );
|
||||
|
||||
if( string->m_next )
|
||||
string->m_next->m_prev = string->m_prev;
|
||||
if( string->m_prev )
|
||||
string->m_prev->m_next = string->m_next;
|
||||
else
|
||||
{
|
||||
|
||||
assert( string == m_stringList );
|
||||
m_stringList = string->m_next;
|
||||
|
||||
} // end else
|
||||
|
||||
} // end unLink
|
||||
55
Generals/Code/GameEngine/Source/GameClient/DrawGroupInfo.cpp
Normal file
55
Generals/Code/GameEngine/Source/GameClient/DrawGroupInfo.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
** 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. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// DrawGroupInfo.cpp //////////////////////////////////////////////////////////////////////////////
|
||||
// Author: John McDonald, October 2002
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/DrawGroupInfo.h"
|
||||
|
||||
// Useful defaults.
|
||||
|
||||
DrawGroupInfo::DrawGroupInfo()
|
||||
{
|
||||
m_fontName = "Arial";
|
||||
m_fontSize = 10;
|
||||
m_fontIsBold = FALSE;
|
||||
|
||||
m_usePlayerColor = TRUE;
|
||||
m_colorForText = GameMakeColor(255, 255, 255, 255);
|
||||
m_colorForTextDropShadow = GameMakeColor(0, 0, 0, 255);
|
||||
|
||||
m_dropShadowOffsetX = -1;
|
||||
m_dropShadowOffsetY = -1;
|
||||
|
||||
m_percentOffsetX = -0.05f;
|
||||
m_usingPixelOffsetX = FALSE;
|
||||
|
||||
m_pixelOffsetY = -10;
|
||||
m_usingPixelOffsetY = TRUE;
|
||||
}
|
||||
|
||||
DrawGroupInfo *TheDrawGroupInfo = NULL;
|
||||
4893
Generals/Code/GameEngine/Source/GameClient/Drawable.cpp
Normal file
4893
Generals/Code/GameEngine/Source/GameClient/Drawable.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
** 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. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
** 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: AnimatedParticleSysBoneClientUpdate.cpp //////////////////////////////////////////////////////////////////
|
||||
// Author: Mark Lorenzen, October 2002
|
||||
// Desc: client update module to translate particle systems with animation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/Module/AnimatedParticleSysBoneClientUpdate.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/ThingFactory.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/RandomValue.h"
|
||||
#include "Common/DrawModule.h"
|
||||
#include "Common/PerfTimer.h"
|
||||
#include "Common/Xfer.h"
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/ScriptEngine.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
AnimatedParticleSysBoneClientUpdate::AnimatedParticleSysBoneClientUpdate( Thing *thing, const ModuleData* moduleData ) :
|
||||
ClientUpdateModule( thing, moduleData )
|
||||
{
|
||||
m_life = 0;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
AnimatedParticleSysBoneClientUpdate::~AnimatedParticleSysBoneClientUpdate( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** The client update callback. */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void AnimatedParticleSysBoneClientUpdate::clientUpdate( void )
|
||||
{
|
||||
//THIS IS HAPPENING CLIENT-SIDE
|
||||
// I CAN DO WHAT I NEED HERE AND NOT HAVE TO BE LOGIC SYNC-SAFE
|
||||
|
||||
|
||||
++m_life;
|
||||
|
||||
Drawable *draw = getDrawable();
|
||||
if (draw)
|
||||
{
|
||||
|
||||
for (DrawModule** dm = draw->getDrawModules(); *dm; ++dm)
|
||||
{
|
||||
ObjectDrawInterface* di = (*dm)->getObjectDrawInterface();
|
||||
if (di)
|
||||
{
|
||||
if (di->updateBonesForClientParticleSystems())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** CRC */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void AnimatedParticleSysBoneClientUpdate::crc( Xfer *xfer )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::crc( xfer );
|
||||
|
||||
} // end crc
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer method
|
||||
* Version Info:
|
||||
* 1: Initial version */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void AnimatedParticleSysBoneClientUpdate::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::xfer( xfer );
|
||||
|
||||
|
||||
} // end xfer
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Load post process */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void AnimatedParticleSysBoneClientUpdate::loadPostProcess( void )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::loadPostProcess();
|
||||
|
||||
} // end loadPostProcess
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
** 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: BeaconClientUpdate.cpp //////////////////////////////////////////////////////////////////
|
||||
// Author: Matthew D. Campbell, August 2002
|
||||
// Desc: Beacon client update module
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine
|
||||
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/ParticleSys.h"
|
||||
#include "GameClient/Module/BeaconClientUpdate.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/Radar.h"
|
||||
#include "Common/Xfer.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
BeaconClientUpdateModuleData::BeaconClientUpdateModuleData() :
|
||||
m_framesBetweenRadarPulses(30),
|
||||
m_radarPulseDuration(15)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
BeaconClientUpdateModuleData::~BeaconClientUpdateModuleData()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void BeaconClientUpdateModuleData::buildFieldParse(MultiIniFieldParse& p)
|
||||
{
|
||||
ClientUpdateModuleData::buildFieldParse(p);
|
||||
|
||||
static const FieldParse dataFieldParse[] =
|
||||
{
|
||||
{ "RadarPulseFrequency", INI::parseDurationUnsignedInt, NULL, offsetof(BeaconClientUpdateModuleData, m_framesBetweenRadarPulses) },
|
||||
{ "RadarPulseDuration", INI::parseDurationUnsignedInt, NULL, offsetof(BeaconClientUpdateModuleData, m_radarPulseDuration) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
p.add(dataFieldParse);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
BeaconClientUpdate::BeaconClientUpdate( Thing *thing, const ModuleData* moduleData ) :
|
||||
ClientUpdateModule( thing, moduleData ),
|
||||
m_particleSystemID(INVALID_PARTICLE_SYSTEM_ID),
|
||||
m_lastRadarPulse(TheGameLogic->getFrame())
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
BeaconClientUpdate::~BeaconClientUpdate( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static ParticleSystem* createParticleSystem( Drawable *draw )
|
||||
{
|
||||
ParticleSystem *system = NULL;
|
||||
if (draw)
|
||||
{
|
||||
Object *obj = draw->getObject();
|
||||
if (obj)
|
||||
{
|
||||
AsciiString templateName;
|
||||
templateName.format("BeaconSmoke%6.6X", (0xffffff & obj->getIndicatorColor()));
|
||||
const ParticleSystemTemplate *particleTemplate = TheParticleSystemManager->findTemplate( templateName );
|
||||
|
||||
DEBUG_ASSERTCRASH(particleTemplate, ("Could not find particle system %s\n", templateName.str()));
|
||||
|
||||
if (particleTemplate)
|
||||
{
|
||||
system = TheParticleSystemManager->createParticleSystem( particleTemplate );
|
||||
if (system)
|
||||
system->attachToDrawable( draw );
|
||||
}
|
||||
else// This is a failsafe... if someone has monkeyed with the particle system names, or the MP house colors
|
||||
{// THis this will whip up a new particle system to match the house color provided
|
||||
templateName.format("BeaconSmokeFFFFFF");
|
||||
const ParticleSystemTemplate *failsafeTemplate = TheParticleSystemManager->findTemplate( templateName );
|
||||
DEBUG_ASSERTCRASH(failsafeTemplate, ("Doh, this is bad \n I Could not even find the white particle system to make a failsafe system out of."));
|
||||
if (failsafeTemplate)
|
||||
{
|
||||
system = TheParticleSystemManager->createParticleSystem( failsafeTemplate );
|
||||
if (system)
|
||||
{
|
||||
system->attachToDrawable( draw );
|
||||
system->tintAllColors( obj->getIndicatorColor() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return system;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void BeaconClientUpdate::hideBeacon( void )
|
||||
{
|
||||
Drawable *draw = getDrawable();
|
||||
if (draw)
|
||||
{
|
||||
draw->setDrawableHidden( true );
|
||||
draw->setShadowsEnabled( false );
|
||||
}
|
||||
|
||||
ParticleSystem *system;
|
||||
if (draw && m_particleSystemID == INVALID_PARTICLE_SYSTEM_ID)
|
||||
{
|
||||
system = createParticleSystem( draw );
|
||||
if (system)
|
||||
m_particleSystemID = system->getSystemID();
|
||||
}
|
||||
|
||||
// clean up particle system
|
||||
if (m_particleSystemID != INVALID_PARTICLE_SYSTEM_ID)
|
||||
{
|
||||
ParticleSystem *system = TheParticleSystemManager->findParticleSystem( m_particleSystemID );
|
||||
|
||||
if( system )
|
||||
system->stop();
|
||||
|
||||
} // end if
|
||||
|
||||
// DEBUG_LOG(("in hideBeacon(): draw=%d, m_particleSystemID=%d\n", draw, m_particleSystemID));
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** The client update callback. */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void BeaconClientUpdate::clientUpdate( void )
|
||||
{
|
||||
Drawable *draw = getDrawable();
|
||||
if (!draw)
|
||||
return;
|
||||
|
||||
if (m_particleSystemID == INVALID_PARTICLE_SYSTEM_ID)
|
||||
{
|
||||
ParticleSystem *system = createParticleSystem( draw );
|
||||
if( system )
|
||||
m_particleSystemID = system->getSystemID();
|
||||
}
|
||||
|
||||
if (!draw->isDrawableEffectivelyHidden())
|
||||
{
|
||||
BeaconClientUpdateModuleData *moduleData = (BeaconClientUpdateModuleData *)getModuleData();
|
||||
if (TheGameLogic->getFrame() > m_lastRadarPulse + moduleData->m_framesBetweenRadarPulses)
|
||||
{
|
||||
TheRadar->createEvent( draw->getPosition(), RADAR_EVENT_BEACON_PULSE, moduleData->m_radarPulseDuration * SECONDS_PER_LOGICFRAME_REAL );
|
||||
m_lastRadarPulse = TheGameLogic->getFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** CRC */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BeaconClientUpdate::crc( Xfer *xfer )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::crc( xfer );
|
||||
|
||||
} // end crc
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer method
|
||||
* Version Info:
|
||||
* 1: Initial version */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BeaconClientUpdate::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::xfer( xfer );
|
||||
|
||||
// particle system ID
|
||||
xfer->xferUser( &m_particleSystemID, sizeof( ParticleSystemID ) );
|
||||
|
||||
// last radar pulse
|
||||
xfer->xferUnsignedInt( &m_lastRadarPulse );
|
||||
|
||||
} // end xfer
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Load post process */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void BeaconClientUpdate::loadPostProcess( void )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::loadPostProcess();
|
||||
|
||||
} // end loadPostProcess
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
** 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: SwayClientUpdate.cpp //////////////////////////////////////////////////////////////////
|
||||
// Author: Matthew D. Campbell, May 2002
|
||||
// Desc: Tree sway client update module
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/Module/SwayClientUpdate.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/ThingFactory.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/RandomValue.h"
|
||||
#include "Common/PerfTimer.h"
|
||||
#include "Common/Xfer.h"
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/ScriptEngine.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
SwayClientUpdate::SwayClientUpdate( Thing *thing, const ModuleData* moduleData ) :
|
||||
ClientUpdateModule( thing, moduleData ),
|
||||
m_curDelta(0),
|
||||
m_curValue(0),
|
||||
m_curAngle(0),
|
||||
m_curAngleLimit(0),
|
||||
m_leanAngle(0),
|
||||
m_swaying(true),
|
||||
m_unused(false),
|
||||
m_curVersion(-1) // so that we never match the first time
|
||||
{
|
||||
|
||||
// don't do updateSway here; wait till the first time we go thru our update loop.
|
||||
//updateSway();
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
SwayClientUpdate::~SwayClientUpdate( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
// Update the sway parameters.
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SwayClientUpdate::updateSway()
|
||||
{
|
||||
const BreezeInfo& info = TheScriptEngine->getBreezeInfo();
|
||||
if (info.m_randomness == 0.0f)
|
||||
{
|
||||
m_curValue = 0;
|
||||
}
|
||||
Real delta = info.m_randomness * 0.5f;
|
||||
m_curAngleLimit = info.m_intensity * GameClientRandomValueReal(1.0f-delta, 1.0f+delta);
|
||||
m_curDelta = 2*PI/info.m_breezePeriod * GameClientRandomValueReal(1.0f-delta, 1.0f+delta);
|
||||
m_leanAngle = info.m_lean * GameClientRandomValueReal(1.0f-delta, 1.0f+delta);
|
||||
m_curVersion = info.m_breezeVersion;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** The client update callback. */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SwayClientUpdate::clientUpdate( void )
|
||||
{
|
||||
if( !m_swaying )
|
||||
return;
|
||||
|
||||
Drawable *draw = getDrawable();
|
||||
|
||||
// if breeze changes, always process the full update, even if not visible,
|
||||
// so that things offscreen won't 'pop' when first viewed
|
||||
const BreezeInfo& info = TheScriptEngine->getBreezeInfo();
|
||||
if (info.m_breezeVersion != m_curVersion)
|
||||
{
|
||||
updateSway();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, only update visible drawables
|
||||
if (!draw || !draw->isVisible())
|
||||
return;
|
||||
}
|
||||
|
||||
m_curValue += m_curDelta;
|
||||
if (m_curValue > 2*PI)
|
||||
m_curValue -= 2*PI;
|
||||
Real cosine = Cos(m_curValue);
|
||||
|
||||
Real targetAngle = cosine * m_curAngleLimit + m_leanAngle;
|
||||
Real deltaAngle = targetAngle - m_curAngle;
|
||||
|
||||
Matrix3D xfrm = *draw->getInstanceMatrix();
|
||||
xfrm.In_Place_Pre_Rotate_X(-deltaAngle * info.m_directionVec.x);
|
||||
xfrm.In_Place_Pre_Rotate_Y(deltaAngle * info.m_directionVec.y);
|
||||
draw->setInstanceMatrix(&xfrm);
|
||||
|
||||
m_curAngle = targetAngle;
|
||||
|
||||
// burned things don't sway.
|
||||
Object* obj = draw->getObject();
|
||||
if (obj && (obj->getStatusBits() & OBJECT_STATUS_BURNED) != 0)
|
||||
stopSway();
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** CRC */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SwayClientUpdate::crc( Xfer *xfer )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::crc( xfer );
|
||||
|
||||
} // end crc
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Xfer method
|
||||
* Version Info:
|
||||
* 1: Initial version */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SwayClientUpdate::xfer( Xfer *xfer )
|
||||
{
|
||||
|
||||
// version
|
||||
XferVersion currentVersion = 1;
|
||||
XferVersion version = currentVersion;
|
||||
xfer->xferVersion( &version, currentVersion );
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::xfer( xfer );
|
||||
|
||||
// cur value
|
||||
xfer->xferReal( &m_curValue );
|
||||
|
||||
// cur angle
|
||||
xfer->xferReal( &m_curAngle );
|
||||
|
||||
// cur delta
|
||||
xfer->xferReal( &m_curDelta );
|
||||
|
||||
// cur angle limit
|
||||
xfer->xferReal( &m_curAngleLimit );
|
||||
|
||||
// lean angle
|
||||
xfer->xferReal( &m_leanAngle );
|
||||
|
||||
// cur version
|
||||
xfer->xferShort( &m_curVersion );
|
||||
|
||||
// swaying
|
||||
xfer->xferBool( &m_swaying );
|
||||
|
||||
} // end xfer
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Load post process */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SwayClientUpdate::loadPostProcess( void )
|
||||
{
|
||||
|
||||
// extend base class
|
||||
ClientUpdateModule::loadPostProcess();
|
||||
|
||||
updateSway();
|
||||
|
||||
} // end loadPostProcess
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
** 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/>.
|
||||
*/
|
||||
|
||||
// DrawableManager.cpp
|
||||
// Message stream translator
|
||||
// Author: Michael S. Booth, March 2001
|
||||
|
||||
465
Generals/Code/GameEngine/Source/GameClient/Eva.cpp
Normal file
465
Generals/Code/GameEngine/Source/GameClient/Eva.cpp
Normal file
@@ -0,0 +1,465 @@
|
||||
/*
|
||||
** 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. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GameClient/Eva.cpp /////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
#include "GameClient/Eva.h"
|
||||
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const char *TheEvaMessageNames[] =
|
||||
{
|
||||
"LOWPOWER",
|
||||
"INSUFFICIENTFUNDS",
|
||||
"SUPERWEAPONDETECTED_PARTICLECANNON",
|
||||
"SUPERWEAPONDETECTED_NUKE",
|
||||
"SUPERWEAPONDETECTED_SCUDSTORM",
|
||||
"SUPERWEAPONLAUNCHED_PARTICLECANNON",
|
||||
"SUPERWEAPONLAUNCHED_NUKE",
|
||||
"SUPERWEAPONLAUNCHED_SCUDSTORM",
|
||||
"BUILDINGLOST",
|
||||
"BASEUNDERATTACK",
|
||||
"ALLYUNDERATTACK",
|
||||
"BEACONDETECTED",
|
||||
"UNITLOST",
|
||||
"GENERALLEVELUP",
|
||||
"VEHICLESTOLEN",
|
||||
"BUILDINGSTOLEN",
|
||||
"CASHSTOLEN",
|
||||
"UPGRADECOMPLETE",
|
||||
"BUILDINGBEINGSTOLEN",
|
||||
"EVA_INVALID",
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------ INI::parseEvaEvent
|
||||
void INI::parseEvaEvent( INI* ini )
|
||||
{
|
||||
AsciiString name;
|
||||
|
||||
// read the name
|
||||
const char* c = ini->getNextToken();
|
||||
name.set( c );
|
||||
|
||||
EvaCheckInfo *check = TheEva->newEvaCheckInfo( name );
|
||||
if (!check) {
|
||||
// could be null because it already exists.
|
||||
return;
|
||||
}
|
||||
|
||||
// parse the ini definition
|
||||
ini->initFromINI( check, check->getFieldParse() );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------- EvaSideSounds
|
||||
static void parseSideSoundsList( INI *ini, void *instance, void *store, const void* userData )
|
||||
{
|
||||
std::vector<EvaSideSounds> *sounds = (std::vector<EvaSideSounds>*) store;
|
||||
EvaSideSounds newSounds;
|
||||
|
||||
ini->initFromINI( &newSounds, newSounds.getFieldParse() );
|
||||
|
||||
// This could be made more efficient, but to be honest, it shouldn't be that slow.
|
||||
sounds->push_back(newSounds);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------- EvaSideSounds
|
||||
const FieldParse EvaSideSounds::s_evaSideSounds[] =
|
||||
{
|
||||
{ "Side", INI::parseAsciiString, NULL, offsetof( EvaSideSounds, m_side) },
|
||||
{ "Sounds", INI::parseSoundsList, NULL, offsetof( EvaSideSounds, m_soundNames) },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------ EvaCheckInfo
|
||||
EvaCheckInfo::EvaCheckInfo() :
|
||||
m_message(EVA_COUNT),
|
||||
m_priority(0), // lowest of all priorities
|
||||
m_framesBetweenChecks(900), // 30 seconds at 30 fps
|
||||
m_framesToExpire(150) // 5 seconds at 30 fps
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const FieldParse EvaCheckInfo::s_evaEventInfo[] =
|
||||
{
|
||||
{ "Priority", INI::parseUnsignedInt, NULL, offsetof( EvaCheckInfo, m_priority ) },
|
||||
{ "TimeBetweenChecksMS", INI::parseDurationUnsignedInt, NULL, offsetof( EvaCheckInfo, m_framesBetweenChecks ) },
|
||||
{ "ExpirationTimeMS", INI::parseDurationUnsignedInt, NULL, offsetof( EvaCheckInfo, m_framesToExpire) },
|
||||
{ "SideSounds", parseSideSoundsList, NULL, offsetof( EvaCheckInfo, m_evaSideSounds ) },
|
||||
{ 0, 0, 0, 0 },
|
||||
|
||||
};
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const ShouldPlayFunc Eva::s_shouldPlayFuncs[] =
|
||||
{
|
||||
Eva::shouldPlayLowPower,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
Eva::shouldPlayGenericHandler,
|
||||
NULL,
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
EvaCheck::EvaCheck() :
|
||||
m_evaInfo(NULL),
|
||||
m_triggeredOnFrame(TRIGGEREDON_NOT),
|
||||
m_timeForNextCheck(NEXT_CHECK_NOW),
|
||||
m_alreadyPlayed(FALSE)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Eva::Eva() :
|
||||
m_localPlayer(NULL),
|
||||
m_previousBuildingCount(0),
|
||||
m_previousUnitCount(0),
|
||||
m_enabled(TRUE)
|
||||
{
|
||||
|
||||
for (Int i = 0; i < EVA_COUNT; ++i) {
|
||||
m_shouldPlay[i] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Eva::~Eva()
|
||||
{
|
||||
EvaCheckInfoPtrVecIt it;
|
||||
for (it = m_allCheckInfos.begin(); it != m_allCheckInfos.end(); ++it) {
|
||||
if (*it)
|
||||
(*it)->deleteInstance();
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Eva::init()
|
||||
{
|
||||
// parse the INI here, etc.
|
||||
INI ini;
|
||||
ini.load( AsciiString( "Data\\INI\\Eva.ini" ), INI_LOAD_OVERWRITE, NULL);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Eva::reset()
|
||||
{
|
||||
m_previousUnitCount = 0;
|
||||
m_previousBuildingCount = 0;
|
||||
|
||||
// remove all pending counters, etc, here.
|
||||
EvaCheckVecIt it;
|
||||
for (it = m_checks.begin(); it != m_checks.end(); /* empty */) {
|
||||
it = m_checks.erase(it);
|
||||
}
|
||||
|
||||
// remove all things flagged as "need to play"
|
||||
for (Int i = 0; i < EVA_COUNT; ++i) {
|
||||
m_shouldPlay[i] = FALSE;
|
||||
}
|
||||
|
||||
// If we were previously disabled, re-enable ourselves.
|
||||
m_enabled = TRUE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Eva::update()
|
||||
{
|
||||
if (!m_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_localPlayer = ThePlayerList->getLocalPlayer();
|
||||
UnsignedInt frame = TheGameLogic->getFrame();
|
||||
|
||||
// Don't update for the first few frames. This way, we don't have to deal with our initial power
|
||||
// being 0, etc.
|
||||
if (frame < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Int mesg = (Int)EVA_FIRST; mesg < (Int)EVA_COUNT; ++mesg) {
|
||||
if (isTimeForCheck((EvaMessage)mesg, frame)) {
|
||||
if (messageShouldPlay((EvaMessage)mesg, frame)) {
|
||||
playMessage((EvaMessage)mesg, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processPlayingMessages(frame);
|
||||
m_localPlayer = NULL;
|
||||
|
||||
// Reset all of the flags that have been set to true that haven't actually been probed, because
|
||||
// they will need to trigger again to be valid messages.
|
||||
for (Int i = EVA_FIRST; i < EVA_COUNT; ++i) {
|
||||
m_shouldPlay[i] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
EvaMessage Eva::nameToMessage(const AsciiString& name)
|
||||
{
|
||||
for (Int i = EVA_FIRST; i < EVA_COUNT; ++i) {
|
||||
if (name.compareNoCase(TheEvaMessageNames[i]) == 0) {
|
||||
return (EvaMessage) i;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_CRASH(("Invalid requested Eva message translation :%s: jkmcd", name.str()));
|
||||
return EVA_COUNT;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
AsciiString Eva::messageToName(EvaMessage message)
|
||||
{
|
||||
if (message >= EVA_FIRST && message < EVA_COUNT)
|
||||
return TheEvaMessageNames[message];
|
||||
|
||||
DEBUG_CRASH(("Invalid requested Eva message translation. jkmcd"));
|
||||
return AsciiString::TheEmptyString;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
EvaCheckInfo *Eva::newEvaCheckInfo(AsciiString name)
|
||||
{
|
||||
EvaMessage mesg = nameToMessage(name);
|
||||
|
||||
// Only return a new one if there isn't an existing one.
|
||||
EvaCheckInfoPtrVecIt it;
|
||||
for (it = m_allCheckInfos.begin(); it != m_allCheckInfos.end(); ++it) {
|
||||
if (*it && (*it)->m_message == mesg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EvaCheckInfo *checkInfo = newInstance(EvaCheckInfo);
|
||||
m_allCheckInfos.push_back(checkInfo);
|
||||
checkInfo->m_message = mesg;
|
||||
return checkInfo;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const EvaCheckInfo *Eva::getEvaCheckInfo(AsciiString name)
|
||||
{
|
||||
EvaMessage mesg = nameToMessage(name);
|
||||
|
||||
// Only return a new one if there isn't an existing one.
|
||||
EvaCheckInfoPtrVecIt it;
|
||||
for (it = m_allCheckInfos.begin(); it != m_allCheckInfos.end(); ++it) {
|
||||
if (*it && (*it)->m_message == mesg)
|
||||
return *it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Eva::setShouldPlay(EvaMessage messageToPlay)
|
||||
{
|
||||
m_shouldPlay[messageToPlay] = TRUE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Eva::setEvaEnabled(Bool enabled)
|
||||
{
|
||||
// clear out any waiting messages.
|
||||
for (Int i = EVA_FIRST; i < EVA_COUNT; ++i) {
|
||||
m_shouldPlay[i] = FALSE;
|
||||
}
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Bool Eva::isTimeForCheck(EvaMessage messageToTest, UnsignedInt currentFrame) const
|
||||
{
|
||||
EvaCheckVec::const_iterator it;
|
||||
for (it = m_checks.begin(); it != m_checks.end(); ++it) {
|
||||
if (it->m_evaInfo->m_message == messageToTest) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Bool Eva::messageShouldPlay(EvaMessage messageToTest, UnsignedInt currentFrame) const
|
||||
{
|
||||
if (m_localPlayer == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_messageBeingTested = messageToTest;
|
||||
return s_shouldPlayFuncs[messageToTest](m_localPlayer);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Bool Eva::shouldPlayLowPower( Player *localPlayer )
|
||||
{
|
||||
|
||||
// @todo make eva sensitive to whether player can do anything about it...
|
||||
// "Low power, Low power, Low power, yadda yadda yadda..."
|
||||
//const ThingTemplate *chinaReactorTemplate = findTemplate(;
|
||||
//const ThingTemplate *americanReactorTemplate;
|
||||
//if ( chinaReactorTemplate && americanReactorTemplate )
|
||||
//{
|
||||
// if ( ! (localPlayer->canBuild(chinaReactorTemplate) || localPlayer->canBuild(americanReactorTemplate)) )
|
||||
// return FALSE
|
||||
//}
|
||||
|
||||
|
||||
return !localPlayer->getEnergy()->hasSufficientPower();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Bool Eva::shouldPlayGenericHandler( Player * )
|
||||
{
|
||||
if (TheEva->m_shouldPlay[TheEva->m_messageBeingTested]) {
|
||||
TheEva->m_shouldPlay[TheEva->m_messageBeingTested] = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Eva::playMessage(EvaMessage messageToTest, UnsignedInt currentFrame)
|
||||
{
|
||||
EvaCheck check;
|
||||
check.m_evaInfo = getEvaCheckInfo(Eva::messageToName(messageToTest));
|
||||
if (!check.m_evaInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
check.m_timeForNextCheck = currentFrame + check.m_evaInfo->m_framesBetweenChecks;
|
||||
check.m_triggeredOnFrame = currentFrame;
|
||||
check.m_alreadyPlayed = FALSE;
|
||||
|
||||
m_checks.push_back(check);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Eva::processPlayingMessages(UnsignedInt currentFrame)
|
||||
{
|
||||
// First pass, remove all the objects that can check after this frame.
|
||||
EvaCheckVecIt it;
|
||||
for (it = m_checks.begin(); it != m_checks.end(); /* empty */) {
|
||||
// These are requests that will be available next frame because they've played.
|
||||
if (it->m_timeForNextCheck <= currentFrame + 1 && it->m_alreadyPlayed) {
|
||||
it = m_checks.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
// These are requests that never got a chance to play and have since expired.
|
||||
if (it->m_triggeredOnFrame + it->m_evaInfo->m_framesToExpire <= currentFrame && !it->m_alreadyPlayed) {
|
||||
it = m_checks.erase(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
// It's possible, although unlikely, that we removed everything in the list.
|
||||
if (m_checks.begin() == m_checks.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're currently playing some audio, we're done.
|
||||
if (m_evaSpeech.isCurrentlyPlaying()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Okay. No one is currently playing anything, so lets find an event and trigger it.
|
||||
EvaCheckVecIt storedIt = m_checks.end();
|
||||
|
||||
UnsignedInt highestPriority = 0;
|
||||
for (it = m_checks.begin(); it != m_checks.end(); ++it) {
|
||||
if (it->m_evaInfo->m_priority > highestPriority && !it->m_alreadyPlayed) {
|
||||
storedIt = it;
|
||||
highestPriority = it->m_evaInfo->m_priority;
|
||||
}
|
||||
}
|
||||
|
||||
// There wasn't anything waiting to play.
|
||||
if (storedIt == m_checks.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We've got a winner!
|
||||
AsciiString side = ThePlayerList->getLocalPlayer()->getSide();
|
||||
Int numSides = storedIt->m_evaInfo->m_evaSideSounds.size();
|
||||
|
||||
for (Int i = 0; i < numSides; ++i) {
|
||||
if (side.compareNoCase(storedIt->m_evaInfo->m_evaSideSounds[i].m_side) == 0) {
|
||||
// Its this one.
|
||||
if (storedIt->m_evaInfo->m_evaSideSounds[i].m_soundNames.size() > 0) {
|
||||
Int soundToPlay = GameClientRandomValue(0, storedIt->m_evaInfo->m_evaSideSounds[i].m_soundNames.size() - 1);
|
||||
m_evaSpeech.setEventName(storedIt->m_evaInfo->m_evaSideSounds[i].m_soundNames[soundToPlay]);
|
||||
} else {
|
||||
// clear it.
|
||||
m_evaSpeech.setEventName(AsciiString::TheEmptyString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the entry
|
||||
storedIt->m_alreadyPlayed = true;
|
||||
storedIt->m_timeForNextCheck = currentFrame + storedIt->m_evaInfo->m_framesBetweenChecks;
|
||||
|
||||
// Now that we correctly filter messages, we need to set the player index for who should hear the
|
||||
// sound to the local player.
|
||||
m_evaSpeech.setPlayerIndex(m_localPlayer->getPlayerIndex());
|
||||
|
||||
m_evaSpeech.setPlayingHandle(TheAudio->addAudioEvent(&m_evaSpeech));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Eva *TheEva = NULL;
|
||||
|
||||
877
Generals/Code/GameEngine/Source/GameClient/FXList.cpp
Normal file
877
Generals/Code/GameEngine/Source/GameClient/FXList.cpp
Normal file
@@ -0,0 +1,877 @@
|
||||
/*
|
||||
** 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: FXList.cpp ///////////////////////////////////////////////////////////////////////////////
|
||||
// Author: Steven Johnson, December 2001
|
||||
// Desc: FXList descriptions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/FXList.h"
|
||||
|
||||
#include "Common/DrawModule.h"
|
||||
#include "Common/GameAudio.h"
|
||||
#include "Common/INI.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/RandomValue.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/ThingFactory.h"
|
||||
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/TerrainLogic.h"
|
||||
#include "GameClient/Display.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/ParticleSys.h"
|
||||
#include "GameLogic/PartitionManager.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
FXListStore *TheFXListStore = NULL; ///< the FXList store definition
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static void adjustVector(Coord3D *vec, const Matrix3D* mtx)
|
||||
{
|
||||
if (mtx)
|
||||
{
|
||||
Vector3 vectmp;
|
||||
vectmp.X = vec->x;
|
||||
vectmp.Y = vec->y;
|
||||
vectmp.Z = vec->z;
|
||||
vectmp = mtx->Rotate_Vector(vectmp);
|
||||
vec->x = vectmp.X;
|
||||
vec->y = vectmp.Y;
|
||||
vec->z = vectmp.Z;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE CLASSES ///////////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FXNugget::doFXObj(const Object* primary, const Object* secondary) const
|
||||
{
|
||||
const Coord3D* p = primary ? primary->getPosition() : NULL;
|
||||
const Matrix3D* mtx = primary ? primary->getTransformMatrix() : NULL;
|
||||
const Real speed = 0.0f; // yes, that's right -- NOT the object's speed.
|
||||
const Coord3D* s = secondary ? secondary->getPosition() : NULL;
|
||||
doFXPos(p, mtx, speed, s);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
class SoundFXNugget : public FXNugget
|
||||
{
|
||||
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(SoundFXNugget, "SoundFXNugget")
|
||||
|
||||
public:
|
||||
|
||||
virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
|
||||
{
|
||||
AudioEventRTS sound(m_soundName);
|
||||
|
||||
if (primary)
|
||||
{
|
||||
sound.setPosition(primary);
|
||||
}
|
||||
|
||||
TheAudio->addAudioEvent(&sound);
|
||||
}
|
||||
|
||||
virtual void doFXObj(const Object* primary, const Object* secondary = NULL) const
|
||||
{
|
||||
AudioEventRTS sound(m_soundName);
|
||||
if (primary)
|
||||
{
|
||||
sound.setPlayerIndex(primary->getControllingPlayer()->getPlayerIndex());
|
||||
sound.setPosition(primary->getPosition());
|
||||
}
|
||||
|
||||
TheAudio->addAudioEvent(&sound);
|
||||
}
|
||||
|
||||
|
||||
static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "Name", INI::parseAsciiString, NULL, offsetof( SoundFXNugget, m_soundName ) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
SoundFXNugget* nugget = newInstance(SoundFXNugget);
|
||||
ini->initFromINI(nugget, myFieldParse);
|
||||
((FXList*)instance)->addFXNugget(nugget);
|
||||
}
|
||||
|
||||
private:
|
||||
AsciiString m_soundName;
|
||||
};
|
||||
EMPTY_DTOR(SoundFXNugget)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static Real calcDist(const Coord3D& src, const Coord3D& dst)
|
||||
{
|
||||
Real dx = dst.x - src.x;
|
||||
Real dy = dst.y - src.y;
|
||||
Real dz = dst.z - src.z;
|
||||
return sqrt(dx*dx + dy*dy + dz*dz);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
class TracerFXNugget : public FXNugget
|
||||
{
|
||||
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TracerFXNugget, "TracerFXNugget")
|
||||
public:
|
||||
|
||||
TracerFXNugget()
|
||||
{
|
||||
m_tracerName.set("GenericTracer");
|
||||
m_boneName.clear();
|
||||
m_speed = 0.0f; // means "use passed-in speed"
|
||||
m_decayAt = 1.0f;
|
||||
m_length = 10.0f;
|
||||
m_width = 1.0f;
|
||||
m_color.red = m_color.green = m_color.blue = 1.0f;
|
||||
m_probability = 1.0f;
|
||||
}
|
||||
|
||||
virtual void doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx, const Real primarySpeed, const Coord3D *secondary, const Real /*overrideRadius*/ ) const
|
||||
{
|
||||
if (m_probability <= GameClientRandomValueReal(0, 1))
|
||||
return;
|
||||
|
||||
if (primary && secondary)
|
||||
{
|
||||
Drawable *tracer = TheThingFactory->newDrawable(TheThingFactory->findTemplate(m_tracerName));
|
||||
if(!tracer)
|
||||
return;
|
||||
|
||||
//Kris -- Redid this section Sept 18, 2002
|
||||
//Calculate tracer orientations to face from primary to secondary position. This
|
||||
//should be the direction that the projectile is being fired towards. It doesn't make
|
||||
//sense that the old stuff made use of the muzzle fx bone orientation (because it's a
|
||||
//subobject). It had other problems because of elevation variations the tracers would
|
||||
//stay on the ground.
|
||||
//tracer->setTransformMatrix(primaryMtx);
|
||||
Matrix3D tracerMtx;
|
||||
Vector3 pos( primary->x, primary->y, primary->z );
|
||||
Vector3 dir( secondary->x - primary->x, secondary->y - primary->y, secondary->z - primary->z );
|
||||
dir.Normalize(); //This is fantastically crucial for calling buildTransformMatrix!!!!!
|
||||
tracerMtx.buildTransformMatrix( pos, dir );
|
||||
tracer->setTransformMatrix( &tracerMtx );
|
||||
tracer->setPosition(primary);
|
||||
|
||||
Real speed = m_speed;
|
||||
if (speed == 0.0f)
|
||||
{
|
||||
speed = primarySpeed;
|
||||
}
|
||||
|
||||
TracerDrawInterface* tdi = NULL;
|
||||
for (DrawModule** d = tracer->getDrawModules(); *d; ++d)
|
||||
{
|
||||
if ((tdi = (*d)->getTracerDrawInterface()) != NULL)
|
||||
{
|
||||
tdi->setTracerParms(speed, m_length, m_width, m_color, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// estimate how long it will take us to get to the destination
|
||||
Real dist = calcDist(*primary, *secondary) - m_length;
|
||||
Real frames = (dist >= 0.0f && speed >= 0.0f) ? (dist / speed) : 1;
|
||||
Int framesAdjusted = REAL_TO_INT_CEIL(frames * m_decayAt);
|
||||
tracer->setExpirationDate(TheGameLogic->getFrame() + framesAdjusted);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary and secondary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "TracerName", INI::parseAsciiString, NULL, offsetof( TracerFXNugget, m_tracerName ) },
|
||||
{ "BoneName", INI::parseAsciiString, NULL, offsetof( TracerFXNugget, m_boneName ) },
|
||||
{ "Speed", INI::parseVelocityReal, NULL, offsetof( TracerFXNugget, m_speed ) },
|
||||
{ "DecayAt", INI::parseReal, NULL, offsetof( TracerFXNugget, m_decayAt ) },
|
||||
{ "Length", INI::parseReal, NULL, offsetof( TracerFXNugget, m_length ) },
|
||||
{ "Width", INI::parseReal, NULL, offsetof( TracerFXNugget, m_width ) },
|
||||
{ "Color", INI::parseRGBColor, NULL, offsetof( TracerFXNugget, m_color ) },
|
||||
{ "Probability", INI::parseReal, NULL, offsetof( TracerFXNugget, m_probability ) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
TracerFXNugget* nugget = newInstance( TracerFXNugget );
|
||||
ini->initFromINI(nugget, myFieldParse);
|
||||
((FXList*)instance)->addFXNugget(nugget);
|
||||
}
|
||||
|
||||
private:
|
||||
AsciiString m_tracerName;
|
||||
AsciiString m_boneName;
|
||||
Real m_speed;
|
||||
Real m_decayAt;
|
||||
Real m_length;
|
||||
Real m_width;
|
||||
RGBColor m_color;
|
||||
Real m_probability;
|
||||
};
|
||||
EMPTY_DTOR(TracerFXNugget)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
class RayEffectFXNugget : public FXNugget
|
||||
{
|
||||
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(RayEffectFXNugget, "RayEffectFXNugget")
|
||||
public:
|
||||
|
||||
RayEffectFXNugget()
|
||||
{
|
||||
m_templateName.clear();
|
||||
m_primaryOffset.x = m_primaryOffset.y = m_primaryOffset.z = 0;
|
||||
m_secondaryOffset.x = m_secondaryOffset.y = m_secondaryOffset.z = 0;
|
||||
}
|
||||
|
||||
virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * secondary, const Real /*overrideRadius*/ ) const
|
||||
{
|
||||
const ThingTemplate* tmpl = TheThingFactory->findTemplate(m_templateName);
|
||||
DEBUG_ASSERTCRASH(tmpl, ("RayEffect %s not found\n",m_templateName.str()));
|
||||
if (primary && secondary && tmpl)
|
||||
{
|
||||
Coord3D sourcePos = *primary;
|
||||
sourcePos.x += m_primaryOffset.x;
|
||||
sourcePos.y += m_primaryOffset.y;
|
||||
sourcePos.z += m_primaryOffset.z;
|
||||
|
||||
Coord3D targetPos = *secondary;
|
||||
targetPos.x += m_secondaryOffset.x;
|
||||
targetPos.y += m_secondaryOffset.y;
|
||||
targetPos.z += m_secondaryOffset.z;
|
||||
|
||||
TheGameClient->createRayEffectByTemplate(&sourcePos, &targetPos, tmpl);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary AND secondary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "Name", INI::parseAsciiString, NULL, offsetof( RayEffectFXNugget, m_templateName ) },
|
||||
{ "PrimaryOffset", INI::parseCoord3D, NULL, offsetof( RayEffectFXNugget, m_primaryOffset ) },
|
||||
{ "SecondaryOffset", INI::parseCoord3D, NULL, offsetof( RayEffectFXNugget, m_secondaryOffset ) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
RayEffectFXNugget* nugget = newInstance( RayEffectFXNugget );
|
||||
ini->initFromINI(nugget, myFieldParse);
|
||||
((FXList*)instance)->addFXNugget(nugget);
|
||||
}
|
||||
|
||||
private:
|
||||
AsciiString m_templateName;
|
||||
Coord3D m_primaryOffset;
|
||||
Coord3D m_secondaryOffset;
|
||||
};
|
||||
EMPTY_DTOR(RayEffectFXNugget)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
class LightPulseFXNugget : public FXNugget
|
||||
{
|
||||
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(LightPulseFXNugget, "LightPulseFXNugget")
|
||||
public:
|
||||
|
||||
LightPulseFXNugget() : m_radius(0), m_increaseFrames(0), m_decreaseFrames(0), m_boundingCirclePct(0)
|
||||
{
|
||||
m_color.red = m_color.green = m_color.blue = 0;
|
||||
}
|
||||
|
||||
virtual void doFXObj(const Object* primary, const Object* /*secondary*/) const
|
||||
{
|
||||
if (primary)
|
||||
{
|
||||
Real radius = m_radius;
|
||||
|
||||
if (m_boundingCirclePct > 0)
|
||||
radius = (primary->getGeometryInfo().getBoundingCircleRadius() * m_boundingCirclePct);
|
||||
|
||||
TheDisplay->createLightPulse(primary->getPosition(), &m_color, 1, radius, m_increaseFrames, m_decreaseFrames);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
|
||||
{
|
||||
if (primary)
|
||||
{
|
||||
TheDisplay->createLightPulse(primary, &m_color, 1, m_radius, m_increaseFrames, m_decreaseFrames);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "Color", INI::parseRGBColor, NULL, offsetof( LightPulseFXNugget, m_color ) },
|
||||
{ "Radius", INI::parseReal, NULL, offsetof( LightPulseFXNugget, m_radius ) },
|
||||
{ "RadiusAsPercentOfObjectSize", INI::parsePercentToReal, NULL, offsetof( LightPulseFXNugget, m_boundingCirclePct ) },
|
||||
{ "IncreaseTime", INI::parseDurationUnsignedInt, NULL, offsetof( LightPulseFXNugget, m_increaseFrames ) },
|
||||
{ "DecreaseTime", INI::parseDurationUnsignedInt, NULL, offsetof( LightPulseFXNugget, m_decreaseFrames ) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
LightPulseFXNugget* nugget = newInstance( LightPulseFXNugget );
|
||||
ini->initFromINI(nugget, myFieldParse);
|
||||
((FXList*)instance)->addFXNugget(nugget);
|
||||
}
|
||||
|
||||
private:
|
||||
RGBColor m_color;
|
||||
Real m_radius;
|
||||
Real m_boundingCirclePct;
|
||||
UnsignedInt m_increaseFrames;
|
||||
UnsignedInt m_decreaseFrames;
|
||||
};
|
||||
EMPTY_DTOR(LightPulseFXNugget)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
class ViewShakeFXNugget : public FXNugget
|
||||
{
|
||||
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ViewShakeFXNugget, "ViewShakeFXNugget")
|
||||
public:
|
||||
|
||||
ViewShakeFXNugget() : m_shake(View::SHAKE_NORMAL)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
|
||||
{
|
||||
if (primary)
|
||||
{
|
||||
if (TheTacticalView)
|
||||
TheTacticalView->shake(primary, m_shake);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "Type", parseShakeType, NULL, offsetof( ViewShakeFXNugget, m_shake ) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
ViewShakeFXNugget* nugget = newInstance( ViewShakeFXNugget );
|
||||
ini->initFromINI(nugget, myFieldParse);
|
||||
((FXList*)instance)->addFXNugget(nugget);
|
||||
}
|
||||
|
||||
protected:
|
||||
static void parseShakeType( INI* ini, void *instance, void *store, const void* /*userData*/ )
|
||||
{
|
||||
static const LookupListRec shakeTypeNames[] =
|
||||
{
|
||||
{ "SUBTLE", View::SHAKE_SUBTLE },
|
||||
{ "NORMAL", View::SHAKE_NORMAL },
|
||||
{ "STRONG", View::SHAKE_STRONG },
|
||||
{ "SEVERE", View::SHAKE_SEVERE },
|
||||
{ "CINE_EXTREME", View::SHAKE_CINE_EXTREME },
|
||||
{ "CINE_INSANE", View::SHAKE_CINE_INSANE },
|
||||
{ 0, 0 }
|
||||
};
|
||||
*(Int *)store = INI::scanLookupList(ini->getNextToken(), shakeTypeNames);
|
||||
}
|
||||
|
||||
private:
|
||||
View::CameraShakeType m_shake;
|
||||
|
||||
};
|
||||
EMPTY_DTOR(ViewShakeFXNugget)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
class TerrainScorchFXNugget : public FXNugget
|
||||
{
|
||||
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TerrainScorchFXNugget, "TerrainScorchFXNugget")
|
||||
public:
|
||||
|
||||
TerrainScorchFXNugget() : m_scorch(-1), m_radius(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void doFXPos(const Coord3D *primary, const Matrix3D* /*primaryMtx*/, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
|
||||
{
|
||||
if (primary)
|
||||
{
|
||||
Int scorch = m_scorch;
|
||||
if (scorch < 0)
|
||||
{
|
||||
scorch = GameClientRandomValue( SCORCH_1, SCORCH_4 );
|
||||
}
|
||||
TheGameClient->addScorch(primary, m_radius, (Scorches)scorch);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "Type", parseScorchType, NULL, offsetof( TerrainScorchFXNugget, m_scorch ) },
|
||||
{ "Radius", INI::parseReal, NULL, offsetof( TerrainScorchFXNugget, m_radius ) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
TerrainScorchFXNugget* nugget = newInstance( TerrainScorchFXNugget );
|
||||
ini->initFromINI(nugget, myFieldParse);
|
||||
((FXList*)instance)->addFXNugget(nugget);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
static void parseScorchType( INI* ini, void *instance, void *store, const void* /*userData*/ )
|
||||
{
|
||||
static const LookupListRec scorchTypeNames[] =
|
||||
{
|
||||
{ "SCORCH_1", SCORCH_1 },
|
||||
{ "SCORCH_2", SCORCH_2 },
|
||||
{ "SCORCH_3", SCORCH_3 },
|
||||
{ "SCORCH_4", SCORCH_4 },
|
||||
{ "SHADOW_SCORCH", SHADOW_SCORCH },
|
||||
{ "RANDOM", -1 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
*(Int *)store = INI::scanLookupList(ini->getNextToken(), scorchTypeNames);
|
||||
}
|
||||
|
||||
private:
|
||||
Int m_scorch;
|
||||
Real m_radius;
|
||||
};
|
||||
EMPTY_DTOR(TerrainScorchFXNugget)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
class ParticleSystemFXNugget : public FXNugget
|
||||
{
|
||||
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(ParticleSystemFXNugget, "ParticleSystemFXNugget")
|
||||
public:
|
||||
|
||||
ParticleSystemFXNugget()
|
||||
{
|
||||
m_name.clear();
|
||||
m_count = 1;
|
||||
m_radius.setRange(0, 0, GameClientRandomVariable::CONSTANT);
|
||||
m_height.setRange(0, 0, GameClientRandomVariable::CONSTANT);
|
||||
// -1 means "don't mess with it, just accept the particle-system's defaults"
|
||||
m_delay.setRange(-1, -1, GameClientRandomVariable::CONSTANT);
|
||||
m_offset.x = m_offset.y = m_offset.z = 0;
|
||||
m_orientToObject = false;
|
||||
m_attachToObject = false;
|
||||
m_createAtGroundHeight = FALSE;
|
||||
m_useCallersRadius = FALSE;
|
||||
m_rotateX = m_rotateY = m_rotateZ = 0;
|
||||
}
|
||||
|
||||
virtual void doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real overrideRadius ) const
|
||||
{
|
||||
if (primary)
|
||||
{
|
||||
reallyDoFX(primary, primaryMtx, NULL, overrideRadius);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void doFXObj(const Object* primary, const Object* secondary) const
|
||||
{
|
||||
if (primary)
|
||||
{
|
||||
|
||||
if (m_ricochet && secondary)
|
||||
{
|
||||
// HERE WE MUST BUILD A MATRIX WHICH WILL ORIENT THE NEW PARTICLE SYSTEM TO FACE AWAY FROM THE SECONDARY OBJECT
|
||||
// THE RESULT SHOULD LOOK LIKE THE DIRECTION OF THE "ATTACK" IS CARRIED THROUGH LIKE A RICOCHET
|
||||
Real deltaX = primary->getPosition()->x - secondary->getPosition()->x;
|
||||
Real deltaY = primary->getPosition()->y - secondary->getPosition()->y;
|
||||
Real aimingAngle = atan2(deltaY, deltaX);
|
||||
Matrix3D aimingMatrix(1);
|
||||
aimingMatrix.Rotate_Z( aimingAngle );
|
||||
|
||||
reallyDoFX(primary->getPosition(), &aimingMatrix, primary, 0.0f);
|
||||
}
|
||||
else
|
||||
// if we have an object, then adjust the offset and direction by the object's transformation
|
||||
// matrix, so that (say) an offset of +10 in the z axis "follows" the orientation of the object.
|
||||
reallyDoFX(primary->getPosition(), primary->getTransformMatrix(), primary, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "Name", INI::parseAsciiString, NULL, offsetof( ParticleSystemFXNugget, m_name ) },
|
||||
{ "Count", INI::parseInt, NULL, offsetof( ParticleSystemFXNugget, m_count ) },
|
||||
{ "Offset", INI::parseCoord3D, NULL, offsetof( ParticleSystemFXNugget, m_offset ) },
|
||||
{ "Radius", INI::parseGameClientRandomVariable, NULL, offsetof( ParticleSystemFXNugget, m_radius ) },
|
||||
{ "Height", INI::parseGameClientRandomVariable, NULL, offsetof( ParticleSystemFXNugget, m_height ) },
|
||||
{ "InitialDelay", INI::parseGameClientRandomVariable, NULL, offsetof( ParticleSystemFXNugget, m_delay ) },
|
||||
{ "RotateX", INI::parseAngleReal, NULL, offsetof( ParticleSystemFXNugget, m_rotateX ) },
|
||||
{ "RotateY", INI::parseAngleReal, NULL, offsetof( ParticleSystemFXNugget, m_rotateY ) },
|
||||
{ "RotateZ", INI::parseAngleReal, NULL, offsetof( ParticleSystemFXNugget, m_rotateZ ) },
|
||||
{ "OrientToObject", INI::parseBool, NULL, offsetof( ParticleSystemFXNugget, m_orientToObject ) },
|
||||
{ "Ricochet", INI::parseBool, NULL, offsetof( ParticleSystemFXNugget, m_ricochet ) },
|
||||
{ "AttachToObject", INI::parseBool, NULL, offsetof( ParticleSystemFXNugget, m_attachToObject ) },
|
||||
{ "CreateAtGroundHeight", INI::parseBool, NULL, offsetof( ParticleSystemFXNugget, m_createAtGroundHeight ) },
|
||||
{ "UseCallersRadius", INI::parseBool, NULL, offsetof( ParticleSystemFXNugget, m_useCallersRadius ) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
ParticleSystemFXNugget* nugget = newInstance( ParticleSystemFXNugget );
|
||||
ini->initFromINI(nugget, myFieldParse);
|
||||
((FXList*)instance)->addFXNugget(nugget);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void reallyDoFX(const Coord3D *primary, const Matrix3D* mtx, const Object* thingToAttachTo, Real overrideRadius ) const
|
||||
{
|
||||
Coord3D offset = m_offset;
|
||||
if (mtx)
|
||||
{
|
||||
adjustVector(&offset, mtx);
|
||||
}
|
||||
|
||||
const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate(m_name);
|
||||
DEBUG_ASSERTCRASH(tmp, ("ParticleSystem %s not found\n",m_name.str()));
|
||||
if (tmp)
|
||||
{
|
||||
for (Int i = 0; i < m_count; i++ )
|
||||
{
|
||||
ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp);
|
||||
if (sys)
|
||||
{
|
||||
Coord3D newPos;
|
||||
Real radius = m_radius.getValue();
|
||||
Real angle = GameClientRandomValueReal( 0.0f, 2.0f * PI );
|
||||
|
||||
newPos.x = primary->x + offset.x + radius * cos(angle);
|
||||
newPos.y = primary->y + offset.y + radius * sin(angle);
|
||||
if( m_createAtGroundHeight && TheTerrainLogic )
|
||||
{
|
||||
//old way:
|
||||
//newPos.z = TheTerrainLogic->getGrsoundHeight( newPos.x, newPos.y ) + 1;// The plus one prevents scissoring with terrain
|
||||
|
||||
//new way: now we allow bridges in the GroundHeight.
|
||||
PathfindLayerEnum layer = TheTerrainLogic->getLayerForDestination(&newPos);
|
||||
newPos.z = TheTerrainLogic->getLayerHeight( newPos.x, newPos.y, layer );
|
||||
}
|
||||
else
|
||||
newPos.z = primary->z + offset.z + m_height.getValue();
|
||||
|
||||
|
||||
if (m_orientToObject && mtx)
|
||||
{
|
||||
sys->setLocalTransform(mtx);
|
||||
}
|
||||
if (m_rotateX != 0.0f)
|
||||
sys->rotateLocalTransformX(m_rotateX);
|
||||
if (m_rotateY != 0.0f)
|
||||
sys->rotateLocalTransformY(m_rotateY);
|
||||
if (m_rotateZ != 0.0f)
|
||||
sys->rotateLocalTransformZ(m_rotateZ);
|
||||
|
||||
if (m_attachToObject && thingToAttachTo)
|
||||
sys->attachToObject(thingToAttachTo);
|
||||
else
|
||||
sys->setPosition( &newPos );
|
||||
|
||||
Real delayInMsec = m_delay.getValue();
|
||||
if (delayInMsec >= 0.0f)
|
||||
{
|
||||
UnsignedInt delayInFrames = REAL_TO_INT_CEIL(ConvertDurationFromMsecsToFrames(delayInMsec));
|
||||
sys->setInitialDelay(delayInFrames);
|
||||
}
|
||||
|
||||
if( m_useCallersRadius && overrideRadius )
|
||||
{
|
||||
ParticleSystemInfo::EmissionVolumeType type = sys->getEmisionVolumeType();
|
||||
|
||||
if( type == ParticleSystemInfo::EmissionVolumeType::SPHERE )
|
||||
sys->setEmissionVolumeSphereRadius( overrideRadius );
|
||||
else if( type == ParticleSystemInfo::EmissionVolumeType::CYLINDER )
|
||||
sys->setEmissionVolumeCylinderRadius( overrideRadius );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
AsciiString m_name;
|
||||
Int m_count;
|
||||
Coord3D m_offset;
|
||||
GameClientRandomVariable m_radius;
|
||||
GameClientRandomVariable m_height;
|
||||
GameClientRandomVariable m_delay;
|
||||
Real m_rotateX, m_rotateY, m_rotateZ;
|
||||
Bool m_orientToObject;
|
||||
Bool m_attachToObject;
|
||||
Bool m_createAtGroundHeight;
|
||||
Bool m_useCallersRadius;
|
||||
Bool m_ricochet;
|
||||
};
|
||||
EMPTY_DTOR(ParticleSystemFXNugget)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
class FXListAtBonePosFXNugget : public FXNugget
|
||||
{
|
||||
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(FXListAtBonePosFXNugget, "FXListAtBonePosFXNugget")
|
||||
public:
|
||||
|
||||
FXListAtBonePosFXNugget()
|
||||
{
|
||||
m_fx = NULL;
|
||||
m_boneName.clear();
|
||||
m_orientToBone = true;
|
||||
}
|
||||
|
||||
virtual void doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx, const Real /*primarySpeed*/, const Coord3D * /*secondary*/, const Real /*overrideRadius*/ ) const
|
||||
{
|
||||
DEBUG_CRASH(("You must use the object form for this effect"));
|
||||
}
|
||||
|
||||
virtual void doFXObj(const Object* primary, const Object* /*secondary*/) const
|
||||
{
|
||||
if (primary)
|
||||
{
|
||||
// first, try the unadorned name.
|
||||
doFxAtBones(primary, 0);
|
||||
|
||||
// then, try the 01,02,03...etc names.
|
||||
doFxAtBones(primary, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(("You must have a primary source for this effect"));
|
||||
}
|
||||
}
|
||||
|
||||
static void parse(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "FX", INI::parseFXList, NULL, offsetof( FXListAtBonePosFXNugget, m_fx ) },
|
||||
{ "BoneName", INI::parseAsciiString, NULL, offsetof( FXListAtBonePosFXNugget, m_boneName ) },
|
||||
{ "OrientToBone", INI::parseBool, NULL, offsetof( FXListAtBonePosFXNugget, m_orientToBone ) },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
FXListAtBonePosFXNugget* nugget = newInstance( FXListAtBonePosFXNugget );
|
||||
ini->initFromINI(nugget, myFieldParse);
|
||||
((FXList*)instance)->addFXNugget(nugget);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void doFxAtBones(const Object* obj, Int start) const
|
||||
{
|
||||
Coord3D bonePos[MAX_BONE_POINTS];
|
||||
Matrix3D boneMtx[MAX_BONE_POINTS];
|
||||
|
||||
Drawable* draw = obj->getDrawable();
|
||||
if (draw)
|
||||
{
|
||||
// yes, BONEPOS_CURRENT_CLIENT_ONLY -- this is client-only, so should be safe to do.
|
||||
Int count = draw->getCurrentClientBonePositions(m_boneName.str(), start, bonePos, boneMtx, MAX_BONE_POINTS);
|
||||
for (Int i = 0; i < count; ++i)
|
||||
{
|
||||
Coord3D p;
|
||||
Matrix3D m;
|
||||
obj->convertBonePosToWorldPos(&bonePos[i], &boneMtx[i], &p, &m);
|
||||
FXList::doFXPos(m_fx, &p, &m, 0.0f, NULL, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
enum { MAX_BONE_POINTS = 40 };
|
||||
|
||||
const FXList* m_fx;
|
||||
AsciiString m_boneName;
|
||||
Bool m_orientToBone;
|
||||
};
|
||||
EMPTY_DTOR(FXListAtBonePosFXNugget)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
static const FieldParse TheFXListFieldParse[] =
|
||||
{
|
||||
{ "Sound", SoundFXNugget::parse, 0, 0},
|
||||
{ "RayEffect", RayEffectFXNugget::parse, 0, 0},
|
||||
{ "Tracer", TracerFXNugget::parse, 0, 0},
|
||||
{ "LightPulse", LightPulseFXNugget::parse, 0, 0},
|
||||
{ "ViewShake", ViewShakeFXNugget::parse, 0, 0},
|
||||
{ "TerrainScorch", TerrainScorchFXNugget::parse, 0, 0},
|
||||
{ "ParticleSystem", ParticleSystemFXNugget::parse, 0, 0},
|
||||
{ "FXListAtBonePos", FXListAtBonePosFXNugget::parse, 0, 0},
|
||||
{ NULL, NULL, 0, 0 } // keep this last
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
FXList::FXList()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
FXList::~FXList()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FXList::clear()
|
||||
{
|
||||
for (FXNuggetList::iterator it = m_nuggets.begin(); it != m_nuggets.end(); ++it)
|
||||
{
|
||||
if (*it)
|
||||
(*it)->deleteInstance();
|
||||
}
|
||||
m_nuggets.clear();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FXList::doFXPos(const Coord3D *primary, const Matrix3D* primaryMtx, const Real primarySpeed, const Coord3D *secondary, const Real overrideRadius ) const
|
||||
{
|
||||
if (ThePartitionManager->getShroudStatusForPlayer(ThePlayerList->getLocalPlayer()->getPlayerIndex(), primary) != CELLSHROUD_CLEAR)
|
||||
return;
|
||||
|
||||
for (FXNuggetList::const_iterator it = m_nuggets.begin(); it != m_nuggets.end(); ++it)
|
||||
{
|
||||
(*it)->doFXPos(primary, primaryMtx, primarySpeed, secondary, overrideRadius);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FXList::doFXObj(const Object* primary, const Object* secondary) const
|
||||
{
|
||||
if (primary && primary->getShroudedStatus(ThePlayerList->getLocalPlayer()->getPlayerIndex()) > OBJECTSHROUD_PARTIAL_CLEAR)
|
||||
return; //the primary object is fogged or shrouded so don't bother with the effect.
|
||||
|
||||
for (FXNuggetList::const_iterator it = m_nuggets.begin(); it != m_nuggets.end(); ++it)
|
||||
{
|
||||
|
||||
// HERE THE PRIMARY IS THE GUY RECEIVING THE FX, AND SECONDARY MIGHT BE THE GUY DEALING IT
|
||||
(*it)->doFXObj(primary, secondary);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
FXListStore::FXListStore()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
FXListStore::~FXListStore()
|
||||
{
|
||||
m_fxmap.clear();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
const FXList *FXListStore::findFXList(const char* name) const
|
||||
{
|
||||
if (stricmp(name, "None") == 0)
|
||||
return NULL;
|
||||
|
||||
FXListMap::const_iterator it = m_fxmap.find(NAMEKEY(name));
|
||||
if (it != m_fxmap.end())
|
||||
{
|
||||
return &(*it).second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/*static */ void FXListStore::parseFXListDefinition(INI *ini)
|
||||
{
|
||||
// read the FXList name
|
||||
const char *c = ini->getNextToken();
|
||||
NameKeyType key = TheNameKeyGenerator->nameToKey(c);
|
||||
FXList& fxl = TheFXListStore->m_fxmap[key];
|
||||
fxl.clear();
|
||||
ini->initFromINI(&fxl, TheFXListFieldParse);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/*static*/ void INI::parseFXListDefinition(INI *ini)
|
||||
{
|
||||
FXListStore::parseFXListDefinition(ini);
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
/*
|
||||
** 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: AnimateWindowManager.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Mar 2002
|
||||
//
|
||||
// Filename: AnimateWindowManager.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: This will contain the logic behind the different animations that
|
||||
// can happen to a window.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Display.h"
|
||||
#include "GameClient/ProcessAnimateWindow.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// AnimateWindow PUBLIC FUNCTIONS /////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
AnimateWindow::AnimateWindow( void )
|
||||
{
|
||||
m_delay = 0;
|
||||
m_startPos.x = m_startPos.y = 0;
|
||||
m_endPos.x = m_endPos.y = 0;
|
||||
m_curPos.x = m_curPos.y = 0;
|
||||
m_win = NULL;
|
||||
m_animType = WIN_ANIMATION_NONE;
|
||||
|
||||
m_restPos.x = m_restPos.y = 0;
|
||||
m_vel.x = m_vel.y = 0.0f;
|
||||
m_needsToFinish = FALSE;
|
||||
m_isFinished = FALSE;
|
||||
m_endTime = 0;
|
||||
m_startTime = 0;
|
||||
}
|
||||
AnimateWindow::~AnimateWindow( void )
|
||||
{
|
||||
m_win = NULL;
|
||||
}
|
||||
|
||||
void AnimateWindow::setAnimData( ICoord2D startPos, ICoord2D endPos,
|
||||
ICoord2D curPos, ICoord2D restPos,
|
||||
Coord2D vel, UnsignedInt startTime,
|
||||
UnsignedInt endTime )
|
||||
|
||||
{
|
||||
m_startPos = startPos;
|
||||
m_endPos = endPos;
|
||||
m_curPos = curPos;
|
||||
m_restPos = restPos;
|
||||
m_vel = vel;
|
||||
m_startTime = startTime;
|
||||
m_endTime = endTime;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void clearWinList(AnimateWindowList &winList)
|
||||
{
|
||||
AnimateWindow *win = NULL;
|
||||
while (!winList.empty())
|
||||
{
|
||||
win = *(winList.begin());
|
||||
winList.pop_front();
|
||||
if (win)
|
||||
win->deleteInstance();
|
||||
win = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
AnimateWindowManager::AnimateWindowManager( void )
|
||||
{
|
||||
// we don't allocate many of these, so no MemoryPools used
|
||||
m_slideFromRight = NEW ProcessAnimateWindowSlideFromRight;
|
||||
m_slideFromRightFast = NEW ProcessAnimateWindowSlideFromRightFast;
|
||||
m_slideFromLeft = NEW ProcessAnimateWindowSlideFromLeft;
|
||||
m_slideFromTop = NEW ProcessAnimateWindowSlideFromTop;
|
||||
m_slideFromTopFast = NEW ProcessAnimateWindowSlideFromTopFast;
|
||||
m_slideFromBottom = NEW ProcessAnimateWindowSlideFromBottom;
|
||||
m_spiral = NEW ProcessAnimateWindowSpiral;
|
||||
m_slideFromBottomTimed = NEW ProcessAnimateWindowSlideFromBottomTimed;
|
||||
m_winList.clear();
|
||||
m_needsUpdate = FALSE;
|
||||
m_reverse = FALSE;
|
||||
m_winMustFinishList.clear();
|
||||
}
|
||||
AnimateWindowManager::~AnimateWindowManager( void )
|
||||
{
|
||||
if(m_slideFromRight)
|
||||
delete m_slideFromRight;
|
||||
if(m_slideFromRightFast)
|
||||
delete m_slideFromRightFast;
|
||||
if(m_slideFromLeft)
|
||||
delete m_slideFromLeft;
|
||||
if(m_slideFromTop)
|
||||
delete m_slideFromTop;
|
||||
if(m_slideFromTopFast)
|
||||
delete m_slideFromTopFast;
|
||||
if(m_slideFromBottom)
|
||||
delete m_slideFromBottom;
|
||||
if(m_spiral)
|
||||
delete m_spiral;
|
||||
if (m_slideFromBottomTimed)
|
||||
delete m_slideFromBottomTimed;
|
||||
|
||||
m_slideFromRight = NULL;
|
||||
resetToRestPosition( );
|
||||
clearWinList(m_winList);
|
||||
clearWinList(m_winMustFinishList);
|
||||
}
|
||||
|
||||
|
||||
void AnimateWindowManager::init( void )
|
||||
{
|
||||
clearWinList(m_winList);
|
||||
clearWinList(m_winMustFinishList);
|
||||
m_needsUpdate = FALSE;
|
||||
m_reverse = FALSE;
|
||||
}
|
||||
|
||||
void AnimateWindowManager::reset( void )
|
||||
{
|
||||
resetToRestPosition();
|
||||
clearWinList(m_winList);
|
||||
clearWinList(m_winMustFinishList);
|
||||
m_needsUpdate = FALSE;
|
||||
m_reverse = FALSE;
|
||||
}
|
||||
|
||||
void AnimateWindowManager::update( void )
|
||||
{
|
||||
|
||||
ProcessAnimateWindow *processAnim = NULL;
|
||||
|
||||
// if we need to update the windows that need to finish, update that list
|
||||
if(m_needsUpdate)
|
||||
{
|
||||
AnimateWindowList::iterator it = m_winMustFinishList.begin();
|
||||
m_needsUpdate = FALSE;
|
||||
|
||||
while (it != m_winMustFinishList.end())
|
||||
{
|
||||
AnimateWindow *animWin = *it;
|
||||
if (!animWin)
|
||||
{
|
||||
DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List"));
|
||||
return;
|
||||
}
|
||||
processAnim = getProcessAnimate( animWin->getAnimType() );
|
||||
if(processAnim)
|
||||
{
|
||||
if(m_reverse)
|
||||
{
|
||||
if(!processAnim->reverseAnimateWindow(animWin))
|
||||
m_needsUpdate = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!processAnim->updateAnimateWindow(animWin))
|
||||
m_needsUpdate = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
it ++;
|
||||
}
|
||||
}
|
||||
|
||||
AnimateWindowList::iterator it = m_winList.begin();
|
||||
|
||||
while (it != m_winList.end())
|
||||
{
|
||||
AnimateWindow *animWin = *it;
|
||||
if (!animWin)
|
||||
{
|
||||
DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List"));
|
||||
return;
|
||||
}
|
||||
processAnim = getProcessAnimate( animWin->getAnimType() );
|
||||
if(m_reverse)
|
||||
{
|
||||
if(processAnim)
|
||||
processAnim->reverseAnimateWindow(animWin);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(processAnim)
|
||||
processAnim->updateAnimateWindow(animWin);
|
||||
}
|
||||
it ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AnimateWindowManager::registerGameWindow(GameWindow *win, AnimTypes animType, Bool needsToFinish, UnsignedInt ms, UnsignedInt delayMs)
|
||||
{
|
||||
if(!win)
|
||||
{
|
||||
DEBUG_CRASH(("Win was NULL as it was passed into registerGameWindow... not good indeed"));
|
||||
return;
|
||||
}
|
||||
if(animType <= WIN_ANIMATION_NONE || animType >= WIN_ANIMATION_COUNT )
|
||||
{
|
||||
DEBUG_CRASH(("an Invalid WIN_ANIMATION type was passed into registerGameWindow... please fix me "));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new AnimateWindow class and fill in it's data.
|
||||
AnimateWindow *animWin = newInstance(AnimateWindow);
|
||||
animWin->setGameWindow(win);
|
||||
animWin->setAnimType(animType);
|
||||
animWin->setNeedsToFinish(needsToFinish);
|
||||
animWin->setDelay(delayMs);
|
||||
|
||||
// Run the window through the processAnim's init function.
|
||||
ProcessAnimateWindow *processAnim = getProcessAnimate( animType );
|
||||
if(processAnim)
|
||||
{
|
||||
processAnim->setMaxDuration(ms);
|
||||
processAnim->initAnimateWindow( animWin );
|
||||
}
|
||||
|
||||
// Add the Window to the proper list
|
||||
if(needsToFinish)
|
||||
{
|
||||
m_winMustFinishList.push_back(animWin);
|
||||
m_needsUpdate = TRUE;
|
||||
}
|
||||
else
|
||||
m_winList.push_back(animWin);
|
||||
}
|
||||
|
||||
ProcessAnimateWindow *AnimateWindowManager::getProcessAnimate( AnimTypes animType )
|
||||
{
|
||||
switch (animType) {
|
||||
case WIN_ANIMATION_SLIDE_RIGHT:
|
||||
{
|
||||
return m_slideFromRight;
|
||||
}
|
||||
case WIN_ANIMATION_SLIDE_RIGHT_FAST:
|
||||
{
|
||||
return m_slideFromRightFast;
|
||||
}
|
||||
case WIN_ANIMATION_SLIDE_LEFT:
|
||||
{
|
||||
return m_slideFromLeft;
|
||||
}
|
||||
case WIN_ANIMATION_SLIDE_TOP:
|
||||
{
|
||||
return m_slideFromTop;
|
||||
}
|
||||
case WIN_ANIMATION_SLIDE_BOTTOM:
|
||||
{
|
||||
return m_slideFromBottom;
|
||||
}
|
||||
case WIN_ANIMATION_SPIRAL:
|
||||
{
|
||||
return m_spiral;
|
||||
}
|
||||
case WIN_ANIMATION_SLIDE_BOTTOM_TIMED:
|
||||
{
|
||||
return m_slideFromBottomTimed;
|
||||
}
|
||||
case WIN_ANIMATION_SLIDE_TOP_FAST:
|
||||
{
|
||||
return m_slideFromTopFast;
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimateWindowManager::reverseAnimateWindow( void )
|
||||
{
|
||||
|
||||
m_reverse = TRUE;
|
||||
m_needsUpdate = TRUE;
|
||||
ProcessAnimateWindow *processAnim = NULL;
|
||||
|
||||
UnsignedInt maxDelay = 0;
|
||||
AnimateWindowList::iterator it = m_winMustFinishList.begin();
|
||||
while (it != m_winMustFinishList.end())
|
||||
{
|
||||
AnimateWindow *animWin = *it;
|
||||
if (!animWin)
|
||||
{
|
||||
DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List"));
|
||||
return;
|
||||
}
|
||||
if(animWin->getDelay() > maxDelay)
|
||||
maxDelay = animWin->getDelay();
|
||||
it ++;
|
||||
}
|
||||
|
||||
it = m_winMustFinishList.begin();
|
||||
while (it != m_winMustFinishList.end())
|
||||
{
|
||||
AnimateWindow *animWin = *it;
|
||||
if (!animWin)
|
||||
{
|
||||
DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List"));
|
||||
return;
|
||||
}
|
||||
// Run the window through the processAnim's init function.
|
||||
processAnim = getProcessAnimate( animWin->getAnimType() );
|
||||
if(processAnim)
|
||||
{
|
||||
processAnim->initReverseAnimateWindow( animWin, maxDelay );
|
||||
}
|
||||
|
||||
animWin->setFinished(FALSE);
|
||||
it ++;
|
||||
}
|
||||
|
||||
it = m_winList.begin();
|
||||
|
||||
while (it != m_winList.end())
|
||||
{
|
||||
AnimateWindow *animWin = *it;
|
||||
if (!animWin)
|
||||
{
|
||||
DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List"));
|
||||
return;
|
||||
}
|
||||
processAnim = getProcessAnimate( animWin->getAnimType() );
|
||||
|
||||
if(processAnim)
|
||||
processAnim->initReverseAnimateWindow(animWin);
|
||||
animWin->setFinished(FALSE);
|
||||
it ++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AnimateWindowManager::resetToRestPosition( void )
|
||||
{
|
||||
|
||||
m_reverse = TRUE;
|
||||
m_needsUpdate = TRUE;
|
||||
|
||||
AnimateWindowList::iterator it = m_winMustFinishList.begin();
|
||||
while (it != m_winMustFinishList.end())
|
||||
{
|
||||
AnimateWindow *animWin = *it;
|
||||
if (!animWin)
|
||||
{
|
||||
DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List"));
|
||||
return;
|
||||
}
|
||||
ICoord2D restPos = animWin->getRestPos();
|
||||
GameWindow *win = animWin->getGameWindow();
|
||||
if(win)
|
||||
win->winSetPosition(restPos.x, restPos.y);
|
||||
it ++;
|
||||
}
|
||||
it = m_winList.begin();
|
||||
while (it != m_winList.end())
|
||||
{
|
||||
AnimateWindow *animWin = *it;
|
||||
if (!animWin)
|
||||
{
|
||||
DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List"));
|
||||
return;
|
||||
}
|
||||
ICoord2D restPos = animWin->getRestPos();
|
||||
GameWindow *win = animWin->getGameWindow();
|
||||
if(win)
|
||||
win->winSetPosition(restPos.x, restPos.y);
|
||||
it ++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
** 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: ControlBarBeacon.cpp /////////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, March 2002
|
||||
// Desc: Methods specific to the control bar beacon display
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameLogic/Object.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::populateBeacon( Object *beacon )
|
||||
{
|
||||
|
||||
// set the portrait for the thing being constructed
|
||||
setPortraitByObject( beacon );
|
||||
|
||||
static NameKeyType textID = NAMEKEY("ControlBar.wnd:EditBeaconText");
|
||||
static NameKeyType staticTextID = NAMEKEY("ControlBar.wnd:StaticTextBeaconLabel");
|
||||
static NameKeyType clearButtonID = NAMEKEY("ControlBar.wnd:ButtonClearBeaconText");
|
||||
|
||||
GameWindow *textEntryWin = TheWindowManager->winGetWindowFromId(NULL, textID);
|
||||
GameWindow *staticTextWin = TheWindowManager->winGetWindowFromId(NULL, staticTextID);
|
||||
GameWindow *buttonWin = TheWindowManager->winGetWindowFromId(NULL, clearButtonID);
|
||||
|
||||
if (beacon->isLocallyControlled())
|
||||
{
|
||||
if (textEntryWin)
|
||||
{
|
||||
textEntryWin->winHide(FALSE);
|
||||
GadgetTextEntrySetText( textEntryWin, beacon->getDrawable()->getCaptionText() );
|
||||
TheWindowManager->winSetFocus( textEntryWin );
|
||||
}
|
||||
|
||||
if (staticTextWin)
|
||||
staticTextWin->winHide(FALSE);
|
||||
|
||||
if (buttonWin)
|
||||
buttonWin->winHide(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (textEntryWin)
|
||||
textEntryWin->winHide(TRUE);
|
||||
|
||||
if (staticTextWin)
|
||||
staticTextWin->winHide(TRUE);
|
||||
|
||||
if (buttonWin)
|
||||
buttonWin->winHide(TRUE);
|
||||
}
|
||||
} // end populateBeacon
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::updateContextBeacon( void )
|
||||
{
|
||||
|
||||
} // end updateContextBeacon
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType BeaconWindowInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
if (msg == GWM_CHAR && mData1 == KEY_ESC)
|
||||
{
|
||||
TheInGameUI->deselectAllDrawables(TRUE); // there should only be one beacon and nothing else selected
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end InGameChatInput
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,733 @@
|
||||
/*
|
||||
** 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: ControlBarCommandProcessing.cpp //////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, March 2002
|
||||
// Desc: This file contain just the method responsible for processing the actual command
|
||||
// clicks from the window controls in the UI
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/BuildAssistant.h"
|
||||
#include "Common/Money.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/Science.h"
|
||||
#include "Common/SpecialPower.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/Upgrade.h"
|
||||
#include "Common/PlayerTemplate.h"
|
||||
|
||||
#include "GameClient/CommandXlat.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/Eva.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/GadgetPushButton.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/Module/ProductionUpdate.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Process a button transition message from the window system that should be for one of
|
||||
* our GUI commands */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CBCommandStatus ControlBar::processCommandTransitionUI( GameWindow *control, GadgetGameMessage gadgetMessage )
|
||||
{
|
||||
// sanity, we won't process messages if we have no source object
|
||||
if( m_currContext != CB_CONTEXT_MULTI_SELECT &&
|
||||
(m_currentSelectedDrawable == NULL ||
|
||||
m_currentSelectedDrawable->getObject() == NULL) )
|
||||
{
|
||||
|
||||
if( m_currContext != CB_CONTEXT_NONE &&
|
||||
m_currContext != CB_CONTEXT_OBSERVER_INFO &&
|
||||
m_currContext != CB_CONTEXT_OBSERVER_LIST)
|
||||
switchToContext( CB_CONTEXT_NONE, NULL );
|
||||
return CBC_COMMAND_NOT_USED;
|
||||
|
||||
} // end if
|
||||
|
||||
return CBC_COMMAND_USED;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Process a button selected message from the window system that should be for one of
|
||||
* our GUI commands */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CBCommandStatus ControlBar::processCommandUI( GameWindow *control,
|
||||
GadgetGameMessage gadgetMessage )
|
||||
{
|
||||
// get the command pointer from the control user data we put in the button
|
||||
const CommandButton *commandButton = (const CommandButton *)GadgetButtonGetData(control);
|
||||
|
||||
// sanity, we won't process messages if we have no source object,
|
||||
// unless we're CB_CONTEXT_PURCHASE_SCIENCE or GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER
|
||||
if( m_currContext != CB_CONTEXT_MULTI_SELECT &&
|
||||
commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE &&
|
||||
commandButton->getCommandType() != GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER &&
|
||||
(m_currentSelectedDrawable == NULL ||
|
||||
m_currentSelectedDrawable->getObject() == NULL) )
|
||||
{
|
||||
|
||||
if( m_currContext != CB_CONTEXT_NONE )
|
||||
switchToContext( CB_CONTEXT_NONE, NULL );
|
||||
return CBC_COMMAND_NOT_USED;
|
||||
|
||||
} // end if
|
||||
|
||||
// sanity
|
||||
if( control == NULL )
|
||||
return CBC_COMMAND_NOT_USED;
|
||||
|
||||
// the context sensitive gui only is only made of buttons ... sanity
|
||||
if( control->winGetInputFunc() != GadgetPushButtonInput )
|
||||
return CBC_COMMAND_NOT_USED;
|
||||
|
||||
|
||||
if( commandButton == NULL )
|
||||
return CBC_COMMAND_NOT_USED;
|
||||
|
||||
// if the button is flashing, tell it to stop flashing
|
||||
commandButton->setFlashCount(0);
|
||||
TheControlBar->setFlash( FALSE );
|
||||
|
||||
if( commandButton->getCommandType() != GUI_COMMAND_EXIT_CONTAINER )
|
||||
{
|
||||
GadgetButtonSetEnabledImage( control, commandButton->getButtonImage() );
|
||||
}
|
||||
|
||||
//
|
||||
// get the object that is driving the context sensitive UI if we're not in a multi
|
||||
// select context
|
||||
//
|
||||
Object *obj = NULL;
|
||||
if( m_currContext != CB_CONTEXT_MULTI_SELECT &&
|
||||
commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE &&
|
||||
commandButton->getCommandType() != GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER)
|
||||
obj = m_currentSelectedDrawable->getObject();
|
||||
|
||||
//@todo Kris -- Special case code so convoy trucks can detonate nuke trucks -- if other things need this,
|
||||
//rethink it.
|
||||
if( obj && BitTest( commandButton->getOptions(), SINGLE_USE_COMMAND ) )
|
||||
{
|
||||
/** @todo Added obj check because Single Use and Multi Select crash when used together, but with this check
|
||||
* they just won't work. When the "rethinking" occurs, this can get fixed. Right now it is unused.
|
||||
* Convoy Truck needs Multi Select so Single Use is turned off, and noone else has it.
|
||||
*/
|
||||
|
||||
//Make sure the command button is marked as used if it's a single use command. That way
|
||||
//we can never press the button again. This was added specifically for nuke convoy trucks.
|
||||
//When you click to detonate the nuke, it takes a few seconds to detonate in order to play
|
||||
//a sound. But we want to disable the button after the first click.
|
||||
obj->markSingleUseCommandUsed(); //Yeah, an object can only use one single use command...
|
||||
}
|
||||
|
||||
TheInGameUI->placeBuildAvailable( NULL, NULL );
|
||||
|
||||
//Play any available unit specific sound for button
|
||||
Player *player = ThePlayerList->getLocalPlayer();
|
||||
if( player )
|
||||
{
|
||||
AudioEventRTS sound = *commandButton->getUnitSpecificSound();
|
||||
sound.setPlayerIndex( player->getPlayerIndex() );
|
||||
TheAudio->addAudioEvent( &sound );
|
||||
}
|
||||
|
||||
if( BitTest( commandButton->getOptions(), COMMAND_OPTION_NEED_TARGET ) )
|
||||
{
|
||||
if (commandButton->getOptions() & USES_MINE_CLEARING_WEAPONSET)
|
||||
{
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_SET_MINE_CLEARING_DETAIL );
|
||||
}
|
||||
|
||||
//June 06, 2002 -- Major change
|
||||
//I've added support for specific context sensitive commands which need targets just like
|
||||
//other options may need. When we need a target, the user must move the cursor to a position
|
||||
//where he wants the GUI command to take place. Older commands such as napalm strikes or daisy
|
||||
//cutter drops simply needed the user to click anywhere he desired.
|
||||
//
|
||||
//Now, we have new commands that will only work when the user clicks on valid targets to interact
|
||||
//with. For example, the terrorist can jack a car and convert it into a carbomb, but he has to
|
||||
//click on a valid car. In this case the doCommandOrHint code will determine if the mode is valid
|
||||
//or not and the cursor modes will be set appropriately.
|
||||
TheInGameUI->setGUICommand( commandButton );
|
||||
}
|
||||
else switch( commandButton->getCommandType() )
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_DOZER_CONSTRUCT:
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( m_currentSelectedDrawable == NULL )
|
||||
break;
|
||||
|
||||
//Kris: September 27, 2002
|
||||
//Make sure we have enough CASH to build it WHEN we click the button to build it,
|
||||
//before actually previewing the purchase, otherwise, cancel altogether.
|
||||
const ThingTemplate *whatToBuild = commandButton->getThingTemplate();
|
||||
CanMakeType cmt = TheBuildAssistant->canMakeUnit( obj, whatToBuild );
|
||||
if (cmt == CANMAKE_NO_MONEY)
|
||||
{
|
||||
TheEva->setShouldPlay(EVA_InsufficientFunds);
|
||||
TheInGameUI->message( "GUI:NotEnoughMoneyToBuild" );
|
||||
break;
|
||||
}
|
||||
else if (cmt == CANMAKE_QUEUE_FULL)
|
||||
{
|
||||
TheInGameUI->message( "GUI:ProductionQueueFull" );
|
||||
break;
|
||||
}
|
||||
else if (cmt == CANMAKE_PARKING_PLACES_FULL)
|
||||
{
|
||||
TheInGameUI->message( "GUI:ParkingPlacesFull" );
|
||||
break;
|
||||
}
|
||||
else if( cmt == CANMAKE_MAXED_OUT_FOR_PLAYER )
|
||||
{
|
||||
TheInGameUI->message( "GUI:UnitMaxedOut" );
|
||||
break;
|
||||
}
|
||||
|
||||
// tell the UI that we want to build something so we get a building at the cursor
|
||||
TheInGameUI->placeBuildAvailable( commandButton->getThingTemplate(), m_currentSelectedDrawable );
|
||||
|
||||
break;
|
||||
|
||||
} // end dozer construct
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_DOZER_CONSTRUCT_CANCEL:
|
||||
{
|
||||
|
||||
// get the object we have selected
|
||||
Object *building = obj;
|
||||
if( building == NULL )
|
||||
break;
|
||||
|
||||
// sanity check, the building must be under our control to cancel construction
|
||||
if( building->getControllingPlayer() != ThePlayerList->getLocalPlayer() )
|
||||
break;
|
||||
|
||||
// do the message
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_DOZER_CANCEL_CONSTRUCT );
|
||||
|
||||
break;
|
||||
|
||||
} // end cancel dozer construction
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_UNIT_BUILD:
|
||||
{
|
||||
const ThingTemplate *whatToBuild = commandButton->getThingTemplate();
|
||||
|
||||
// get the "factory" object that is going to make the thing
|
||||
Object *factory = obj;
|
||||
if( factory == NULL )
|
||||
break;
|
||||
|
||||
// sanity, we must have something to build
|
||||
DEBUG_ASSERTCRASH( whatToBuild, ("Undefined BUILD command for object '%s'\n",
|
||||
commandButton->getThingTemplate()->getName().str()) );
|
||||
|
||||
CanMakeType cmt = TheBuildAssistant->canMakeUnit(factory, whatToBuild);
|
||||
|
||||
if (cmt == CANMAKE_NO_MONEY)
|
||||
{
|
||||
TheEva->setShouldPlay(EVA_InsufficientFunds);
|
||||
TheInGameUI->message( "GUI:NotEnoughMoneyToBuild" );
|
||||
break;
|
||||
}
|
||||
else if (cmt == CANMAKE_QUEUE_FULL)
|
||||
{
|
||||
TheInGameUI->message( "GUI:ProductionQueueFull" );
|
||||
break;
|
||||
}
|
||||
else if (cmt == CANMAKE_PARKING_PLACES_FULL)
|
||||
{
|
||||
TheInGameUI->message( "GUI:ParkingPlacesFull" );
|
||||
break;
|
||||
}
|
||||
else if( cmt == CANMAKE_MAXED_OUT_FOR_PLAYER )
|
||||
{
|
||||
TheInGameUI->message( "GUI:UnitMaxedOut" );
|
||||
break;
|
||||
}
|
||||
else if (cmt != CANMAKE_OK)
|
||||
{
|
||||
DEBUG_ASSERTCRASH( 0, ("Cannot create '%s' because the factory object '%s' returns false for canMakeUnit\n",
|
||||
whatToBuild->getName().str(),
|
||||
factory->getTemplate()->getName().str()) );
|
||||
break;
|
||||
}
|
||||
|
||||
// get the production interface from the factory object
|
||||
ProductionUpdateInterface *pu = factory->getProductionUpdateInterface();
|
||||
|
||||
// sanity, we can't build things if we can't produce units
|
||||
if( pu == NULL )
|
||||
{
|
||||
|
||||
DEBUG_ASSERTCRASH( 0, ("Cannot create '%s' because the factory object '%s' is not capable of producting units\n",
|
||||
whatToBuild->getName().str(),
|
||||
factory->getTemplate()->getName().str()) );
|
||||
break;
|
||||
|
||||
} // end if
|
||||
|
||||
// get a new production id to assign to this
|
||||
ProductionID productionID = pu->requestUniqueUnitID();
|
||||
|
||||
// create a message to build this thing
|
||||
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_QUEUE_UNIT_CREATE );
|
||||
msg->appendIntegerArgument( whatToBuild->getTemplateID() );
|
||||
msg->appendIntegerArgument( productionID );
|
||||
|
||||
break;
|
||||
|
||||
} // end build unit
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_CANCEL_UNIT_BUILD:
|
||||
{
|
||||
Int i;
|
||||
|
||||
// find out which index (i) in the queue represents the button clicked
|
||||
for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ )
|
||||
if( m_queueData[ i ].control == control )
|
||||
break;
|
||||
|
||||
// sanity, control not found
|
||||
if( i == MAX_BUILD_QUEUE_BUTTONS )
|
||||
{
|
||||
|
||||
DEBUG_ASSERTCRASH( 0, ("Control not found in build queue data\n") );
|
||||
break;
|
||||
|
||||
} // end if
|
||||
|
||||
// sanity
|
||||
if( m_queueData[ i ].type != PRODUCTION_UNIT )
|
||||
break;
|
||||
|
||||
// the the production ID to cancel
|
||||
ProductionID productionIDToCancel = m_queueData[ i ].productionID;
|
||||
|
||||
// get the object that is the producer
|
||||
Object *producer = obj;
|
||||
if( producer == NULL )
|
||||
break;
|
||||
|
||||
// sanity, we must control the producer ... if this isn't true they might be hacking the game
|
||||
if( producer->getControllingPlayer() != ThePlayerList->getLocalPlayer() )
|
||||
break;
|
||||
|
||||
// send a message to cancel that particular production entry
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_CANCEL_UNIT_CREATE );
|
||||
msg->appendIntegerArgument( productionIDToCancel );
|
||||
|
||||
break;
|
||||
|
||||
} // end cancel unit build
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_PLAYER_UPGRADE:
|
||||
{
|
||||
const UpgradeTemplate *upgradeT = commandButton->getUpgradeTemplate();
|
||||
DEBUG_ASSERTCRASH( upgradeT, ("Undefined upgrade '%s' in player upgrade command\n", "UNKNOWN") );
|
||||
|
||||
// sanity
|
||||
if( obj == NULL || upgradeT == NULL )
|
||||
break;
|
||||
|
||||
// make sure the player can really make this
|
||||
if( TheUpgradeCenter->canAffordUpgrade( ThePlayerList->getLocalPlayer(), upgradeT, TRUE ) == FALSE )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ProductionUpdateInterface* pu = obj ? obj->getProductionUpdateInterface() : NULL;
|
||||
if (pu != NULL)
|
||||
{
|
||||
CanMakeType cmt = pu->canQueueUpgrade(upgradeT);
|
||||
if (cmt == CANMAKE_QUEUE_FULL)
|
||||
{
|
||||
TheInGameUI->message( "GUI:ProductionQueueFull" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// send the message
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_QUEUE_UPGRADE );
|
||||
msg->appendObjectIDArgument( obj->getID() );
|
||||
msg->appendIntegerArgument( upgradeT->getUpgradeNameKey() );
|
||||
|
||||
break;
|
||||
|
||||
} // command player upgrade
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_OBJECT_UPGRADE:
|
||||
{
|
||||
const UpgradeTemplate *upgradeT = commandButton->getUpgradeTemplate();
|
||||
DEBUG_ASSERTCRASH( upgradeT, ("Undefined upgrade '%s' in object upgrade command\n", "UNKNOWN") );
|
||||
// sanity
|
||||
if( upgradeT == NULL )
|
||||
break;
|
||||
|
||||
//Make sure the player can really make this
|
||||
if( TheUpgradeCenter->canAffordUpgrade( ThePlayerList->getLocalPlayer(), upgradeT, TRUE ) == FALSE )
|
||||
{
|
||||
//Kris: Disabled because we can get a valid reason for not being able to afford the upgrade!
|
||||
//TheInGameUI->message( "upgrade unsupported in commandprocessing." );
|
||||
break;
|
||||
}
|
||||
|
||||
ProductionUpdateInterface* pu = obj ? obj->getProductionUpdateInterface() : NULL;
|
||||
if (pu != NULL)
|
||||
{
|
||||
CanMakeType cmt = pu->canQueueUpgrade(upgradeT);
|
||||
if (cmt == CANMAKE_QUEUE_FULL)
|
||||
{
|
||||
TheInGameUI->message( "GUI:ProductionQueueFull" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ObjectID objID = INVALID_ID;
|
||||
if (obj)
|
||||
objID = obj->getID();
|
||||
|
||||
// make sure that the this object can actually build the upgrade
|
||||
if( obj && (obj->hasUpgrade( upgradeT ) == TRUE || obj->affectedByUpgrade( upgradeT ) == FALSE) )
|
||||
break;
|
||||
|
||||
// send the message
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_QUEUE_UPGRADE );
|
||||
msg->appendObjectIDArgument( objID );
|
||||
msg->appendIntegerArgument( upgradeT->getUpgradeNameKey() );
|
||||
|
||||
break;
|
||||
|
||||
} // end object upgrade
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_CANCEL_UPGRADE:
|
||||
{
|
||||
Int i;
|
||||
|
||||
// find out which index (i) in the queue represents the button clicked
|
||||
for( i = 0; i < MAX_BUILD_QUEUE_BUTTONS; i++ )
|
||||
if( m_queueData[ i ].control == control )
|
||||
break;
|
||||
|
||||
// sanity, control not found
|
||||
if( i == MAX_BUILD_QUEUE_BUTTONS )
|
||||
{
|
||||
|
||||
DEBUG_ASSERTCRASH( 0, ("Control not found in build queue data\n") );
|
||||
break;
|
||||
|
||||
} // end if
|
||||
|
||||
// sanity
|
||||
if( m_queueData[ i ].type != PRODUCTION_UPGRADE )
|
||||
break;
|
||||
|
||||
// get the upgrade to cancel
|
||||
const UpgradeTemplate *upgradeT = m_queueData[ i ].upgradeToResearch;
|
||||
|
||||
// get producer object (the thing driving our UI)
|
||||
Object *producer = obj;
|
||||
|
||||
// sanity
|
||||
if( upgradeT == NULL || producer == NULL )
|
||||
break;
|
||||
|
||||
// send the message
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_CANCEL_UPGRADE );
|
||||
msg->appendIntegerArgument( upgradeT->getUpgradeNameKey() );
|
||||
|
||||
break;
|
||||
|
||||
} // end cancel upgrade
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_ATTACK_MOVE:
|
||||
TheMessageStream->appendMessage(GameMessage::MSG_META_TOGGLE_ATTACKMOVE);
|
||||
break;
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_STOP:
|
||||
{
|
||||
// This message always works on the currently selected team
|
||||
TheMessageStream->appendMessage(GameMessage::MSG_DO_STOP);
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_WAYPOINTS:
|
||||
break;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_EXIT_CONTAINER:
|
||||
{
|
||||
Int i;
|
||||
ObjectID objID;
|
||||
|
||||
//
|
||||
// find the object ID that wants to exit by scanning through the transport data and looking
|
||||
// for the matching control button
|
||||
//
|
||||
for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
|
||||
if( m_containData[ i ].control == control )
|
||||
objID = m_containData[ i ].objectID;
|
||||
|
||||
// get the actual object
|
||||
Object *objWantingExit = TheGameLogic->findObjectByID( objID );
|
||||
|
||||
// if object is not found remove inventory entry and exit
|
||||
if( objWantingExit == NULL )
|
||||
{
|
||||
|
||||
//
|
||||
// remove from inventory data to avoid future matches ... the inventory update
|
||||
// cycle of the UI will repopulate any buttons as the contents of objects
|
||||
// change so this is only an edge case that will be visually corrected next frame
|
||||
//
|
||||
m_containData[ i ].control = NULL;
|
||||
m_containData[ i ].objectID = INVALID_ID;
|
||||
break; // exit case
|
||||
|
||||
} // end if
|
||||
|
||||
// send message to exit
|
||||
GameMessage *exitMsg = TheMessageStream->appendMessage( GameMessage::MSG_EXIT );
|
||||
exitMsg->appendObjectIDArgument( objWantingExit->getID() ); // 0 is the thing inside coming out
|
||||
|
||||
break;
|
||||
|
||||
} // end transport exit
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_EVACUATE:
|
||||
{
|
||||
// Cancel GUI command mode.
|
||||
TheInGameUI->setGUICommand( NULL );
|
||||
|
||||
if (BitTest(commandButton->getOptions(), NEED_TARGET_POS) == FALSE) {
|
||||
pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_EVACUATE );
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_EVACUATE );
|
||||
}
|
||||
|
||||
break;
|
||||
} // end evacuate
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_EXECUTE_RAILED_TRANSPORT:
|
||||
{
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_EXECUTE_RAILED_TRANSPORT );
|
||||
break;
|
||||
} // end execute railed transport
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_HACK_INTERNET:
|
||||
{
|
||||
pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_INTERNET_HACK );
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_INTERNET_HACK );
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_SET_RALLY_POINT:
|
||||
{
|
||||
break;
|
||||
|
||||
} // end set rally point
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_SELL:
|
||||
{
|
||||
|
||||
// command needs no additional data, send the message
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_SELL );
|
||||
break;
|
||||
|
||||
} // end sell
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_TOGGLE_OVERCHARGE:
|
||||
{
|
||||
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_TOGGLE_OVERCHARGE );
|
||||
break;
|
||||
|
||||
} // end overcharge
|
||||
|
||||
#ifdef ALLOW_SURRENDER
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_POW_RETURN_TO_PRISON:
|
||||
{
|
||||
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_RETURN_TO_PRISON );
|
||||
break;
|
||||
|
||||
} // end return to prison
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_BEACON_DELETE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end delete beacon
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_GUARD:
|
||||
case GUI_COMMAND_GUARD_WITHOUT_PURSUIT:
|
||||
case GUI_COMMAND_GUARD_FLYING_UNITS_ONLY:
|
||||
case GUI_COMMAND_COMBATDROP:
|
||||
{
|
||||
DEBUG_CRASH(("hmm, should never occur"));
|
||||
}
|
||||
break;
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_SWITCH_WEAPON:
|
||||
{
|
||||
// command needs no additional data, send the message
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_SWITCH_WEAPONS );
|
||||
|
||||
//Play mode change acknowledgement
|
||||
PickAndPlayInfo info;
|
||||
WeaponSlotType slot = commandButton->getWeaponSlot();
|
||||
info.m_weaponSlot = &slot;
|
||||
pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_SWITCH_WEAPONS, &info );
|
||||
|
||||
msg->appendIntegerArgument( commandButton->getWeaponSlot() );
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_FIRE_WEAPON:
|
||||
{
|
||||
// command needs no additional data, send the message
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_WEAPON );
|
||||
msg->appendIntegerArgument( commandButton->getWeaponSlot() );
|
||||
msg->appendIntegerArgument( commandButton->getMaxShotsToFire() );
|
||||
|
||||
break;
|
||||
|
||||
} // end fire weapon
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER:
|
||||
{
|
||||
Object* cmdCenter = ThePlayerList->getLocalPlayer()->findNaturalCommandCenter();
|
||||
if (cmdCenter == NULL)
|
||||
break;
|
||||
|
||||
// command needs no additional data, send the message
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_SPECIAL_POWER );
|
||||
msg->appendIntegerArgument( commandButton->getSpecialPowerTemplate()->getID() );
|
||||
msg->appendIntegerArgument( commandButton->getOptions() );
|
||||
msg->appendObjectIDArgument( cmdCenter->getID() );
|
||||
break;
|
||||
|
||||
} // end special weapon
|
||||
|
||||
case GUI_COMMAND_SPECIAL_POWER:
|
||||
{
|
||||
// command needs no additional data, send the message
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_SPECIAL_POWER );
|
||||
msg->appendIntegerArgument( commandButton->getSpecialPowerTemplate()->getID() );
|
||||
msg->appendIntegerArgument( commandButton->getOptions() );
|
||||
msg->appendObjectIDArgument( INVALID_ID ); // no specific source
|
||||
break;
|
||||
|
||||
} // end special weapon
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GUI_COMMAND_PURCHASE_SCIENCE:
|
||||
{
|
||||
|
||||
// loop through all the sciences on the button and select the one we don't have
|
||||
|
||||
ScienceType st = SCIENCE_INVALID;
|
||||
Player *player = ThePlayerList->getLocalPlayer();
|
||||
for(Int i = 0; i < commandButton->getScienceVec().size(); ++i)
|
||||
{
|
||||
st = commandButton->getScienceVec()[ i ];
|
||||
if(!player->hasScience(st) && TheScienceStore->playerHasPrereqsForScience(player, st) && TheScienceStore->getSciencePurchaseCost(st) <= player->getSciencePurchasePoints())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( st == SCIENCE_INVALID)
|
||||
{
|
||||
switchToContext( CB_CONTEXT_NONE, NULL );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_PURCHASE_SCIENCE );
|
||||
msg->appendIntegerArgument( st );
|
||||
|
||||
markUIDirty();
|
||||
|
||||
break;
|
||||
|
||||
} // end pick specialized science
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
|
||||
DEBUG_ASSERTCRASH( 0, ("Unknown command '%d'\n", commandButton->getCommandType()) );
|
||||
return CBC_COMMAND_NOT_USED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return CBC_COMMAND_USED;
|
||||
|
||||
} // end processCommandUI
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
** 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: ControlBarMultiSelect.cpp ////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, March 2002
|
||||
// Desc: Context sensitive GUI for when you select mutiple objects. What we do is show
|
||||
// the commands that you can use between them all
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/GadgetPushButton.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameLogic/Object.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Reset the common command data */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::resetCommonCommandData( void )
|
||||
{
|
||||
Int i;
|
||||
|
||||
for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
|
||||
{
|
||||
m_commonCommands[ i ] = NULL;
|
||||
//Clear out any remnant overlays.
|
||||
GadgetButtonDrawOverlayImage( m_commandWindows[ i ], NULL );
|
||||
}
|
||||
|
||||
} // end resetCommonCommandData
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** add the common commands of this drawable to the common command set */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::addCommonCommands( Drawable *draw, Bool firstDrawable )
|
||||
{
|
||||
Int i;
|
||||
const CommandButton *command;
|
||||
|
||||
// sanity
|
||||
if( draw == NULL )
|
||||
return;
|
||||
|
||||
Object* obj = draw->getObject();
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
if (obj->isKindOf(KINDOF_IGNORED_IN_GUI)) // ignore these guys
|
||||
return;
|
||||
|
||||
// get the command set of this drawable
|
||||
const CommandSet *commandSet = findCommandSet( obj->getCommandSetString() );
|
||||
if( commandSet == NULL )
|
||||
{
|
||||
|
||||
//
|
||||
// if there is no command set for this drawable, none of the selected drawables
|
||||
// can possibly have matching commands so we'll get rid of them all
|
||||
//
|
||||
for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
|
||||
{
|
||||
|
||||
m_commonCommands[ i ] = NULL;
|
||||
m_commandWindows[ i ]->winHide( TRUE );
|
||||
// After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images
|
||||
// removed from multiplayer branch
|
||||
//showCommandMarkers();
|
||||
|
||||
} // end for i
|
||||
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
|
||||
//
|
||||
// easy case, if we're adding the first drawable we simply just add any of the commands
|
||||
// in its set that can be multi-select commands to the common command set
|
||||
//
|
||||
if( firstDrawable == TRUE )
|
||||
{
|
||||
|
||||
// just add each command that is classified as a common command
|
||||
for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
|
||||
{
|
||||
|
||||
// get command
|
||||
command = commandSet->getCommandButton(i);
|
||||
|
||||
// add if present and can be used in a multi select
|
||||
if( command && BitTest( command->getOptions(), OK_FOR_MULTI_SELECT ) == TRUE )
|
||||
{
|
||||
|
||||
// put it in the common command set
|
||||
m_commonCommands[ i ] = command;
|
||||
|
||||
// show and enable this control
|
||||
m_commandWindows[ i ]->winHide( FALSE );
|
||||
m_commandWindows[ i ]->winEnable( TRUE );
|
||||
|
||||
// set the command into the control
|
||||
setControlCommand( m_commandWindows[ i ], command );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end for i
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// go through each command one by one
|
||||
for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
|
||||
{
|
||||
|
||||
// get the command
|
||||
command = commandSet->getCommandButton(i);
|
||||
|
||||
Bool attackMove = (command && command->getCommandType() == GUI_COMMAND_ATTACK_MOVE) ||
|
||||
(m_commonCommands[ i ] && m_commonCommands[ i ]->getCommandType() == GUI_COMMAND_ATTACK_MOVE);
|
||||
|
||||
// Kris: When any units have attack move, they all get it. This is to allow
|
||||
// combat units to be selected with the odd dozer or pilot and still retain that ability.
|
||||
if( attackMove && !m_commonCommands[ i ] )
|
||||
{
|
||||
// put it in the common command set
|
||||
m_commonCommands[ i ] = command;
|
||||
|
||||
// show and enable this control
|
||||
m_commandWindows[ i ]->winHide( FALSE );
|
||||
m_commandWindows[ i ]->winEnable( TRUE );
|
||||
|
||||
// set the command into the control
|
||||
setControlCommand( m_commandWindows[ i ], command );
|
||||
}
|
||||
else if( command != m_commonCommands[ i ] && !attackMove )
|
||||
{
|
||||
//
|
||||
// if this command does not match the command that is in the common command set then
|
||||
// *neither* this command OR the command in the common command set are really common
|
||||
// commands, so we will remove the one that has been stored in the common set
|
||||
//
|
||||
|
||||
// remove the common command
|
||||
m_commonCommands[ i ] = NULL;
|
||||
|
||||
//
|
||||
// hide the window control cause it should have been made visible from a command
|
||||
// that was placed in this common 'slot' earlier
|
||||
//
|
||||
m_commandWindows[ i ]->winHide( TRUE );
|
||||
}
|
||||
|
||||
} // end if
|
||||
|
||||
} // end else
|
||||
|
||||
// After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images
|
||||
// removed from multiplayer branch
|
||||
//showCommandMarkers();
|
||||
|
||||
} // end addCommonCommands
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Populate the visible command bar with commands that are common to all the objects
|
||||
* that are selected in the UI */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::populateMultiSelect( void )
|
||||
{
|
||||
Drawable *draw;
|
||||
Bool firstDrawable = TRUE;
|
||||
Bool portraitSet = FALSE;
|
||||
const Image *portrait = NULL;
|
||||
Object *portraitObj = NULL;
|
||||
|
||||
// first reset the common command data
|
||||
resetCommonCommandData();
|
||||
|
||||
// by default, hide all the controls in the command section
|
||||
for( Int i = 0; i < MAX_COMMANDS_PER_SET; i++ )
|
||||
m_commandWindows[ i ]->winHide( TRUE );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( TheInGameUI->getSelectCount() > 1,
|
||||
("populateMultiSelect: Can't populate multiselect context cause there are only '%d' things selected\n",
|
||||
TheInGameUI->getSelectCount()) );
|
||||
|
||||
// get the list of drawable IDs from the in game UI
|
||||
const DrawableList *selectedDrawables = TheInGameUI->getAllSelectedDrawables();
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( selectedDrawables->empty() == FALSE, ("populateMultiSelect: Drawable list is empty\n") );
|
||||
|
||||
// loop through all the selected drawables
|
||||
for( DrawableListCIt it = selectedDrawables->begin();
|
||||
it != selectedDrawables->end(); ++it )
|
||||
{
|
||||
|
||||
// get the drawable
|
||||
draw = *it;
|
||||
|
||||
|
||||
if (draw->getObject()->isKindOf(KINDOF_IGNORED_IN_GUI)) // ignore these guys
|
||||
continue;
|
||||
|
||||
|
||||
//
|
||||
// add command for this drawable, note that we also sanity check to make sure the
|
||||
// drawable has an object as all interesting drawables that we can select should
|
||||
// actually have an object underneath it so that we can do interesting things with
|
||||
// it ... otherwise we should have never selected it.
|
||||
// NOTE that we're not considering objects that are currently in the process of
|
||||
// being sold as those objects can't be issued anymore commands
|
||||
//
|
||||
if( draw && draw->getObject() &&
|
||||
BitTest( draw->getObject()->getStatusBits(), OBJECT_STATUS_SOLD ) == FALSE )
|
||||
{
|
||||
|
||||
// add the common commands of this drawable to the common command set
|
||||
addCommonCommands( draw, firstDrawable );
|
||||
|
||||
// not adding the first drawble anymore
|
||||
firstDrawable = FALSE;
|
||||
|
||||
//
|
||||
// keep track of the portrait images, if all units selected have the same portrait
|
||||
// we will display it in the right HUD, otherwise we won't
|
||||
//
|
||||
if( portraitSet == FALSE )
|
||||
{
|
||||
|
||||
portrait = draw->getTemplate()->getSelectedPortraitImage();
|
||||
portraitObj = draw->getObject();
|
||||
portraitSet = TRUE;
|
||||
|
||||
} // end if
|
||||
else if( draw->getTemplate()->getSelectedPortraitImage() != portrait )
|
||||
portrait = NULL;
|
||||
|
||||
} // end if
|
||||
|
||||
} // end for, drawble id iterator
|
||||
|
||||
// set the portrait image
|
||||
setPortraitByObject( portraitObj );
|
||||
|
||||
} // end populateMultiSelect
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Update logic for the multi select context sensitive GUI */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::updateContextMultiSelect( void )
|
||||
{
|
||||
Drawable *draw;
|
||||
Object *obj;
|
||||
const CommandButton *command;
|
||||
GameWindow *win;
|
||||
Int objectsThatCanDoCommand[ MAX_COMMANDS_PER_SET ];
|
||||
Int i;
|
||||
|
||||
// zero the array that counts how many objects can do each command
|
||||
memset( objectsThatCanDoCommand, 0, sizeof( objectsThatCanDoCommand ) );
|
||||
|
||||
// santiy
|
||||
DEBUG_ASSERTCRASH( TheInGameUI->getSelectCount() > 1,
|
||||
("updateContextMultiSelect: TheInGameUI only has '%d' things selected\n",
|
||||
TheInGameUI->getSelectCount()) );
|
||||
|
||||
// get the list of drawable IDs from the in game UI
|
||||
const DrawableList *selectedDrawables = TheInGameUI->getAllSelectedDrawables();
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( selectedDrawables->empty() == FALSE, ("populateMultiSelect: Drawable list is empty\n") );
|
||||
|
||||
// loop through all the selected drawable IDs
|
||||
for( DrawableListCIt it = selectedDrawables->begin();
|
||||
it != selectedDrawables->end(); ++it )
|
||||
{
|
||||
|
||||
// get the drawable from the ID
|
||||
draw = *it;
|
||||
|
||||
if (draw->getObject()->isKindOf(KINDOF_IGNORED_IN_GUI)) // ignore these guys
|
||||
continue;
|
||||
|
||||
|
||||
// get the object
|
||||
obj = draw->getObject();
|
||||
|
||||
// sanity
|
||||
if( obj == NULL )
|
||||
continue;
|
||||
|
||||
// for each of the visible command windows make sure the object can execute the command
|
||||
for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
|
||||
{
|
||||
|
||||
// get the control window
|
||||
win = m_commandWindows[ i ];
|
||||
|
||||
// don't consider hidden windows
|
||||
if( win->winIsHidden() == TRUE )
|
||||
continue;
|
||||
|
||||
// get the command
|
||||
command = (const CommandButton *)GadgetButtonGetData(win);
|
||||
if( command == NULL )
|
||||
continue;
|
||||
|
||||
// can we do the command
|
||||
CommandAvailability availability = getCommandAvailability( command, obj, win );
|
||||
|
||||
win->winClearStatus( WIN_STATUS_NOT_READY );
|
||||
win->winClearStatus( WIN_STATUS_ALWAYS_COLOR );
|
||||
|
||||
// enable/disable the window control
|
||||
switch( availability )
|
||||
{
|
||||
case COMMAND_HIDDEN:
|
||||
win->winHide( TRUE );
|
||||
break;
|
||||
case COMMAND_RESTRICTED:
|
||||
win->winEnable( FALSE );
|
||||
break;
|
||||
case COMMAND_NOT_READY:
|
||||
win->winEnable( FALSE );
|
||||
win->winSetStatus( WIN_STATUS_NOT_READY );
|
||||
break;
|
||||
case COMMAND_CANT_AFFORD:
|
||||
win->winEnable( FALSE );
|
||||
win->winSetStatus( WIN_STATUS_ALWAYS_COLOR );
|
||||
break;
|
||||
default:
|
||||
win->winEnable( TRUE );
|
||||
break;
|
||||
}
|
||||
|
||||
//If button is a CHECK_LIKE, then update it's status now.
|
||||
if( BitTest( command->getOptions(), CHECK_LIKE ) )
|
||||
{
|
||||
GadgetCheckLikeButtonSetVisualCheck( win, availability == COMMAND_ACTIVE );
|
||||
}
|
||||
|
||||
if( availability == COMMAND_AVAILABLE || availability == COMMAND_ACTIVE )
|
||||
objectsThatCanDoCommand[ i ]++;
|
||||
|
||||
} // end for i
|
||||
|
||||
} // end for, selected drawables
|
||||
|
||||
//
|
||||
// for each command, if any objects can do the command we enable the window, otherwise
|
||||
// we disable it
|
||||
//
|
||||
for( i = 0; i < MAX_COMMANDS_PER_SET; i++ )
|
||||
{
|
||||
|
||||
// don't consider hidden commands
|
||||
if( m_commandWindows[ i ]->winIsHidden() == TRUE )
|
||||
continue;
|
||||
|
||||
// don't consider slots that don't have commands
|
||||
if( m_commonCommands[ i ] == NULL )
|
||||
continue;
|
||||
|
||||
// check the count of objects that can do the command and enable/disable the control,
|
||||
if( objectsThatCanDoCommand[ i ] > 0 )
|
||||
m_commandWindows[ i ]->winEnable( TRUE );
|
||||
else
|
||||
m_commandWindows[ i ]->winEnable( FALSE );
|
||||
|
||||
} // end for i
|
||||
|
||||
// After Every change to the m_commandWIndows, we need to show fill in the missing blanks with the images
|
||||
// removed from multiplayer branch
|
||||
//showCommandMarkers();
|
||||
|
||||
|
||||
} // end updateContextMultiSelect
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
** 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: ControlBarOCLTimer.cpp //////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, March 2002
|
||||
// Desc: Methods specific to the control bar OCL Timer context
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/Module/OCLUpdate.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GadgetProgressBar.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::updateOCLTimerTextDisplay( UnsignedInt totalSeconds, Real percent )
|
||||
{
|
||||
UnicodeString text;
|
||||
static UnsignedInt descID = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:OCLTimerStaticText" );
|
||||
GameWindow *descWindow = TheWindowManager->winGetWindowFromId( NULL, descID );
|
||||
|
||||
static UnsignedInt barID = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:OCLTimerProgressBar" );
|
||||
GameWindow *barWindow = TheWindowManager->winGetWindowFromId( NULL, barID );
|
||||
|
||||
// santiy
|
||||
DEBUG_ASSERTCRASH( descWindow, ("Under construction window not found\n") );
|
||||
|
||||
Int minutes = totalSeconds / 60;
|
||||
Int seconds = totalSeconds - (minutes * 60);
|
||||
|
||||
// format the message
|
||||
if( seconds < 10 )
|
||||
text.format( TheGameText->fetch( "CONTROLBAR:OCLTimerDescWithPadding" ), minutes, seconds );
|
||||
else
|
||||
text.format( TheGameText->fetch( "CONTROLBAR:OCLTimerDesc" ), minutes, seconds );
|
||||
|
||||
GadgetStaticTextSetText( descWindow, text );
|
||||
GadgetProgressBarSetProgress(barWindow, (percent * 100));
|
||||
|
||||
// record this as the last time displayed
|
||||
m_displayedOCLTimerSeconds = totalSeconds;
|
||||
|
||||
} // end updateOCLTimerTextDisplay
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Populate the interface for an OCL Timer context. */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::populateOCLTimer( Object *creatorObject )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( creatorObject == NULL )
|
||||
return;
|
||||
|
||||
// get our parent window
|
||||
GameWindow *parent = m_contextParent[ CP_OCL_TIMER ];
|
||||
|
||||
// set the sell button
|
||||
/// @todo srj -- remove hard-coding here, please
|
||||
const CommandButton *commandButton = findCommandButton( "Command_Sell" );
|
||||
NameKeyType id;
|
||||
id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:OCLTimerSellButton" );
|
||||
GameWindow *win = TheWindowManager->winGetWindowFromId( parent, id );
|
||||
setControlCommand( win, commandButton );
|
||||
win->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
|
||||
|
||||
|
||||
// set the text percent and bar of our timer we are displaying
|
||||
updateContextOCLTimer( );
|
||||
|
||||
// set the portrait for the thing being constructed
|
||||
setPortraitByObject( creatorObject );
|
||||
|
||||
} // end populateUnderConstruction
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::updateContextOCLTimer( void )
|
||||
{
|
||||
Object *obj = m_currentSelectedDrawable->getObject();
|
||||
|
||||
static const NameKeyType key_OCLUpdate = NAMEKEY( "OCLUpdate" );
|
||||
OCLUpdate *update = (OCLUpdate*)obj->findUpdateModule( key_OCLUpdate );
|
||||
|
||||
UnsignedInt frames = update->getRemainingFrames();
|
||||
UnsignedInt seconds = frames / LOGICFRAMES_PER_SECOND;
|
||||
|
||||
Real percent = update->getCountdownPercent();
|
||||
|
||||
// if the time has changed since what was last shown to the user update the text
|
||||
if( m_displayedOCLTimerSeconds != seconds )
|
||||
updateOCLTimerTextDisplay( seconds, percent );
|
||||
|
||||
} // end updatecontextUnderConstruction
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
** 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: ControlBarObserver.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Aug 2002
|
||||
//
|
||||
// Filename: ControlBarObserver.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: All things related to the Observer Control bar, are in here.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerTemplate.h"
|
||||
#include "Common/KindOf.h"
|
||||
#include "Common/Recorder.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetPushButton.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameNetwork/NetworkDefs.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
enum { MAX_BUTTONS = 8};
|
||||
static NameKeyType buttonPlayerID[MAX_BUTTONS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID };
|
||||
static NameKeyType staticTextPlayerID[MAX_BUTTONS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID };
|
||||
static GameWindow *ObserverPlayerInfoWindow = NULL;
|
||||
static GameWindow *ObserverPlayerListWindow = NULL;
|
||||
|
||||
static GameWindow *buttonPlayer[MAX_BUTTONS] = {NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL };
|
||||
static GameWindow *staticTextPlayer[MAX_BUTTONS] = {NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL };
|
||||
|
||||
|
||||
static NameKeyType buttonCancelID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *winFlag = NULL;
|
||||
static GameWindow *winGeneralPortrait = NULL;
|
||||
static GameWindow *staticTextNumberOfUnits = NULL;
|
||||
static GameWindow *staticTextNumberOfBuildings = NULL;
|
||||
static GameWindow *staticTextNumberOfUnitsKilled = NULL;
|
||||
static GameWindow *staticTextNumberOfUnitsLost = NULL;
|
||||
static GameWindow *staticTextPlayerName = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void ControlBar::initObserverControls( void )
|
||||
{
|
||||
ObserverPlayerInfoWindow = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ObserverPlayerInfoWindow"));
|
||||
ObserverPlayerListWindow = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ObserverPlayerListWindow"));
|
||||
|
||||
for (Int i = 0; i < MAX_BUTTONS; i++)
|
||||
{
|
||||
AsciiString tmpString;
|
||||
tmpString.format("ControlBar.wnd:ButtonPlayer%d", i);
|
||||
buttonPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString );
|
||||
buttonPlayer[i] = TheWindowManager->winGetWindowFromId( ObserverPlayerListWindow, buttonPlayerID[i] );
|
||||
tmpString.format("ControlBar.wnd:StaticTextPlayer%d", i);
|
||||
staticTextPlayerID[i] = TheNameKeyGenerator->nameToKey( tmpString );
|
||||
staticTextPlayer[i] = TheWindowManager->winGetWindowFromId( ObserverPlayerListWindow, staticTextPlayerID[i] );
|
||||
}
|
||||
|
||||
staticTextNumberOfUnits = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnits"));
|
||||
staticTextNumberOfBuildings = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfBuildings"));
|
||||
staticTextNumberOfUnitsKilled = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnitsKilled"));
|
||||
staticTextNumberOfUnitsLost = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextNumberOfUnitsLost"));
|
||||
staticTextPlayerName = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:StaticTextPlayerName"));
|
||||
winFlag = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:WinFlag"));
|
||||
winGeneralPortrait = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ControlBar.wnd:WinGeneralPortrait"));
|
||||
|
||||
buttonCancelID = TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonCancel");
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** System callback for the ControlBarObserverSystem */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType ControlBarObserverSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
static NameKeyType buttonCommunicator = NAMEKEY_INVALID;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_MOUSE_ENTERING:
|
||||
case GBM_MOUSE_LEAVING:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
case GBM_SELECTED_RIGHT:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == buttonCancelID)
|
||||
{
|
||||
TheControlBar->setObserverLookAtPlayer(NULL);
|
||||
ObserverPlayerInfoWindow->winHide(TRUE);
|
||||
ObserverPlayerListWindow->winHide(FALSE);
|
||||
TheControlBar->populateObserverList();
|
||||
|
||||
}
|
||||
for(Int i = 0; i <MAX_BUTTONS; ++i)
|
||||
{
|
||||
if( controlID == buttonPlayerID[i])
|
||||
{
|
||||
ObserverPlayerInfoWindow->winHide(FALSE);
|
||||
ObserverPlayerListWindow->winHide(TRUE);
|
||||
TheControlBar->setObserverLookAtPlayer((Player *) GadgetButtonGetData( buttonPlayer[i]));
|
||||
if(TheControlBar->getObserverLookAtPlayer())
|
||||
TheControlBar->populateObserverInfoWindow();
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
// if( controlID == buttonCommunicator && TheGameLogic->getGameMode() == GAME_INTERNET )
|
||||
/*
|
||||
{
|
||||
popupCommunicatorLayout = TheWindowManager->winCreateLayout( AsciiString( "Menus/PopupCommunicator.wnd" ) );
|
||||
popupCommunicatorLayout->runInit();
|
||||
popupCommunicatorLayout->hide( FALSE );
|
||||
popupCommunicatorLayout->bringForward();
|
||||
}
|
||||
*/
|
||||
|
||||
break;
|
||||
|
||||
} // end button selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end ControlBarSystem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControlBar::populateObserverList( void )
|
||||
{
|
||||
Int currentButton = 0, i;
|
||||
if(TheRecorder->isMultiplayer())
|
||||
{
|
||||
|
||||
for (i = 0; i < MAX_SLOTS; ++i)
|
||||
{
|
||||
AsciiString name;
|
||||
name.format("player%d", i);
|
||||
Player *p = ThePlayerList->findPlayerWithNameKey(TheNameKeyGenerator->nameToKey(name));
|
||||
if(p)
|
||||
{
|
||||
if(p->isPlayerObserver())
|
||||
continue;
|
||||
DEBUG_ASSERTCRASH(currentButton < MAX_BUTTONS, ("ControlBar::populateObserverList trying to populate more buttons then we have"));
|
||||
GadgetButtonSetData(buttonPlayer[currentButton], (void *)p);
|
||||
GadgetButtonSetEnabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getEnabledImage() );
|
||||
//GadgetButtonSetHiliteImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getHiliteImage() );
|
||||
//GadgetButtonSetHiliteSelectedImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getPushedImage() );
|
||||
//GadgetButtonSetDisabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getDisabledImage() );
|
||||
buttonPlayer[currentButton]->winSetTooltip(p->getPlayerDisplayName());
|
||||
buttonPlayer[currentButton]->winHide(FALSE);
|
||||
buttonPlayer[currentButton]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
|
||||
|
||||
const GameSlot *slot = TheGameInfo->getConstSlot(currentButton);
|
||||
Color playerColor = p->getPlayerColor();
|
||||
Color backColor = GameMakeColor(0, 0, 0, 255);
|
||||
staticTextPlayer[currentButton]->winSetEnabledTextColors( playerColor, backColor );
|
||||
staticTextPlayer[currentButton]->winHide(FALSE);
|
||||
AsciiString teamStr;
|
||||
teamStr.format("Team:%d", slot->getTeamNumber() + 1);
|
||||
if (slot->isAI() && slot->getTeamNumber() == -1)
|
||||
teamStr = "Team:AI";
|
||||
|
||||
UnicodeString text;
|
||||
text.format(TheGameText->fetch("CONTROLBAR:ObsPlayerLabel"), p->getPlayerDisplayName().str(),
|
||||
TheGameText->fetch(teamStr).str());
|
||||
|
||||
GadgetStaticTextSetText(staticTextPlayer[currentButton], text );
|
||||
|
||||
++currentButton;
|
||||
}
|
||||
}
|
||||
for(currentButton; currentButton<MAX_BUTTONS; ++currentButton)
|
||||
{
|
||||
buttonPlayer[currentButton]->winHide(TRUE);
|
||||
staticTextPlayer[currentButton]->winHide(TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i =0; i < MAX_PLAYER_COUNT; ++i)
|
||||
{
|
||||
Player *p = ThePlayerList->getNthPlayer(i);
|
||||
if(p && !p->isPlayerObserver() && p->getPlayerType() == PLAYER_HUMAN)
|
||||
{
|
||||
DEBUG_ASSERTCRASH(currentButton < MAX_BUTTONS, ("ControlBar::populateObserverList trying to populate more buttons then we have"));
|
||||
GadgetButtonSetData(buttonPlayer[currentButton], (void *)p);
|
||||
GadgetButtonSetEnabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getEnabledImage() );
|
||||
//GadgetButtonSetHiliteImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getHiliteImage() );
|
||||
//GadgetButtonSetHiliteSelectedImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getPushedImage() );
|
||||
//GadgetButtonSetDisabledImage( buttonPlayer[currentButton], p->getPlayerTemplate()->getDisabledImage() );
|
||||
buttonPlayer[currentButton]->winSetTooltip(p->getPlayerDisplayName());
|
||||
buttonPlayer[currentButton]->winHide(FALSE);
|
||||
buttonPlayer[currentButton]->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
|
||||
|
||||
Color playerColor = p->getPlayerColor();
|
||||
Color backColor = GameMakeColor(0, 0, 0, 255);
|
||||
staticTextPlayer[currentButton]->winSetEnabledTextColors( playerColor, backColor );
|
||||
staticTextPlayer[currentButton]->winHide(FALSE);
|
||||
GadgetStaticTextSetText(staticTextPlayer[currentButton], p->getPlayerDisplayName());
|
||||
|
||||
++currentButton;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for(currentButton; currentButton<MAX_BUTTONS; ++currentButton)
|
||||
{
|
||||
buttonPlayer[currentButton]->winHide(TRUE);
|
||||
staticTextPlayer[currentButton]->winHide(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ControlBar::populateObserverInfoWindow ( void )
|
||||
{
|
||||
if(ObserverPlayerInfoWindow->winIsHidden())
|
||||
return;
|
||||
|
||||
if( !m_observerLookAtPlayer )
|
||||
{
|
||||
ObserverPlayerInfoWindow->winHide(TRUE);
|
||||
ObserverPlayerListWindow->winHide(FALSE);
|
||||
populateObserverList();
|
||||
return;
|
||||
}
|
||||
|
||||
UnicodeString uString;
|
||||
KindOfMaskType mask,clearmask;
|
||||
mask.set(KINDOF_SCORE);
|
||||
clearmask.set(KINDOF_STRUCTURE);
|
||||
|
||||
uString.format(L"%d",m_observerLookAtPlayer->countObjects(mask,clearmask));
|
||||
GadgetStaticTextSetText(staticTextNumberOfUnits, uString);
|
||||
|
||||
Int numBuildings = 0;
|
||||
mask.clear();
|
||||
mask.set(KINDOF_SCORE);
|
||||
mask.set(KINDOF_STRUCTURE);
|
||||
clearmask.clear();
|
||||
numBuildings = m_observerLookAtPlayer->countObjects(mask,clearmask);
|
||||
mask.clear();
|
||||
mask.set(KINDOF_SCORE_CREATE);
|
||||
mask.set(KINDOF_STRUCTURE);
|
||||
numBuildings += m_observerLookAtPlayer->countObjects(mask,clearmask);
|
||||
mask.clear();
|
||||
mask.set(KINDOF_SCORE_DESTROY);
|
||||
mask.set(KINDOF_STRUCTURE);
|
||||
numBuildings += m_observerLookAtPlayer->countObjects(mask,clearmask);
|
||||
uString.format(L"%d",numBuildings);
|
||||
GadgetStaticTextSetText(staticTextNumberOfBuildings, uString);
|
||||
uString.format(L"%d",m_observerLookAtPlayer->getScoreKeeper()->getTotalUnitsDestroyed());
|
||||
GadgetStaticTextSetText(staticTextNumberOfUnitsKilled, uString);
|
||||
uString.format(L"%d",m_observerLookAtPlayer->getScoreKeeper()->getTotalUnitsLost());
|
||||
GadgetStaticTextSetText(staticTextNumberOfUnitsLost, uString);
|
||||
GadgetStaticTextSetText(staticTextPlayerName, m_observerLookAtPlayer->getPlayerDisplayName());
|
||||
Color color = m_observerLookAtPlayer->getPlayerColor();
|
||||
staticTextPlayerName->winSetEnabledTextColors(color, GameMakeColor(0,0,0,255));
|
||||
winFlag->winSetEnabledImage(0, m_observerLookAtPlayer->getPlayerTemplate()->getFlagWaterMarkImage());
|
||||
winGeneralPortrait->winHide(FALSE);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
** 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: ControlBarPrintPositions.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Sep 2002
|
||||
//
|
||||
// Filename: ControlBarPrintPositions.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: Convience function for degayifying the whole squished control bar
|
||||
// process
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
#include <stdio.h>
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
void PrintInfoRecursive( GameWindow *win, FILE *fp)
|
||||
{
|
||||
if(!win)
|
||||
return;
|
||||
ICoord2D pos, size;
|
||||
win->winGetSize(&size.x, &size.y);
|
||||
win->winGetPosition(&pos.x, &pos.y);
|
||||
fprintf(fp, "ControlBarResizer %s\n",win->winGetInstanceData()->m_decoratedNameString.str());
|
||||
fprintf(fp, " AltPosition = X:%d Y:%d\n",pos.x, pos.y);
|
||||
fprintf(fp, " AltSize = X:%d Y:%d\n",size.x, size.y);
|
||||
fprintf(fp, "END\n\n");
|
||||
|
||||
PrintInfoRecursive(win->winGetChild(),fp);
|
||||
PrintInfoRecursive(win->winGetNext(),fp);
|
||||
|
||||
}
|
||||
|
||||
void PrintOffsetsFromControlBarParent( void )
|
||||
{
|
||||
GameWindow *controlBarParent = TheWindowManager->winGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ControlBarParent" ));
|
||||
if(!controlBarParent)
|
||||
return;
|
||||
|
||||
WindowLayout *layout = TheWindowManager->winCreateLayout("controlBarHidden.wnd");
|
||||
if(!layout)
|
||||
return;
|
||||
FILE *fp = fopen("ControlBarEasier.txt", "w");
|
||||
if(!fp)
|
||||
return;
|
||||
|
||||
PrintInfoRecursive(layout->getFirstWindow(), fp);
|
||||
|
||||
fclose(fp);
|
||||
layout->destroyWindows();
|
||||
layout->deleteInstance();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
** 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: ControlBarResizer.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Sep 2002
|
||||
//
|
||||
// Filename: ControlBarResizer.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: We want a "squished" control bar, this is the methods that will do it
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/ControlBarResizer.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/Display.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const FieldParse ControlBarResizer::m_controlBarResizerParseTable[] =
|
||||
{
|
||||
{ "AltPosition", INI::parseICoord2D, NULL, offsetof( ResizerWindow, m_altPos ) },
|
||||
{ "AltSize", INI::parseICoord2D, NULL, offsetof( ResizerWindow, m_altSize ) },
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ResizerWindow::ResizerWindow(void)
|
||||
{
|
||||
m_defaultPos.x = m_defaultPos.y = 0;
|
||||
m_defaultSize.x = m_defaultSize.y = 0;
|
||||
m_altSize.x = m_altSize.y = 0;
|
||||
m_altPos.x = m_altPos.y = 0;
|
||||
}
|
||||
|
||||
ControlBarResizer::ControlBarResizer( void )
|
||||
{
|
||||
|
||||
}
|
||||
ControlBarResizer::~ControlBarResizer( void )
|
||||
{
|
||||
ResizerWindowList::iterator it = m_resizerWindowsList.begin();
|
||||
while (it != m_resizerWindowsList.end())
|
||||
{
|
||||
ResizerWindow *rWin = *it;
|
||||
if( !rWin )
|
||||
{
|
||||
it = m_resizerWindowsList.erase(it);
|
||||
continue;
|
||||
}
|
||||
delete rWin;
|
||||
it = m_resizerWindowsList.erase(it);
|
||||
}
|
||||
m_resizerWindowsList.clear();
|
||||
}
|
||||
|
||||
void ControlBarResizer::init( void )
|
||||
{
|
||||
INI ini;
|
||||
// Read from INI all the ControlBarSchemes
|
||||
ini.load( AsciiString( "Data\\INI\\ControlBarResizer.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||||
|
||||
}
|
||||
|
||||
|
||||
ResizerWindow *ControlBarResizer::findResizerWindow( AsciiString name )
|
||||
{
|
||||
ResizerWindowList::iterator it = m_resizerWindowsList.begin();
|
||||
|
||||
while (it != m_resizerWindowsList.end())
|
||||
{
|
||||
ResizerWindow *rWin = *it;
|
||||
if( !rWin )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::findResizerWindow"));
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
// find the scheme that best matches our resolution
|
||||
if(rWin->m_name.compare(name) == 0)
|
||||
{
|
||||
return rWin;
|
||||
}
|
||||
it ++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ResizerWindow *ControlBarResizer::newResizerWindow( AsciiString name )
|
||||
{
|
||||
ResizerWindow *newRwin = NEW ResizerWindow;
|
||||
if(!newRwin)
|
||||
return NULL;
|
||||
|
||||
newRwin->m_name = name;
|
||||
GameWindow *win = NULL;
|
||||
win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey(name));
|
||||
if( !win )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(win,("ControlBarResizer::newResizerWindow could not find window %s Are you sure that window is loaded yet?", name.str()) );
|
||||
delete newRwin;
|
||||
return NULL;
|
||||
}
|
||||
win->winGetPosition(&newRwin->m_defaultPos.x,&newRwin->m_defaultPos.y);
|
||||
win->winGetSize(&newRwin->m_defaultSize.x,&newRwin->m_defaultSize.y);
|
||||
m_resizerWindowsList.push_back(newRwin);
|
||||
return newRwin;
|
||||
}
|
||||
void ControlBarResizer::sizeWindowsDefault( void )
|
||||
{
|
||||
ResizerWindowList::iterator it = m_resizerWindowsList.begin();
|
||||
GameWindow *win = NULL;
|
||||
while (it != m_resizerWindowsList.end())
|
||||
{
|
||||
ResizerWindow *rWin = *it;
|
||||
if( !rWin )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey(rWin->m_name));
|
||||
if(!win)
|
||||
{
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
win->winSetPosition(rWin->m_defaultPos.x, rWin->m_defaultPos.y);
|
||||
win->winSetSize(rWin->m_defaultSize.x, rWin->m_defaultSize.y);
|
||||
DEBUG_LOG(("sizeWindowsDefault:%s pos X:%d pos Y: %d size X:%d sizeY: %d",rWin->m_name.str(),rWin->m_defaultPos.x, rWin->m_defaultPos.y,rWin->m_defaultSize.x, rWin->m_defaultSize.y ));
|
||||
it ++;
|
||||
}
|
||||
}
|
||||
void ControlBarResizer::sizeWindowsAlt( void )
|
||||
{
|
||||
ResizerWindowList::iterator it = m_resizerWindowsList.begin();
|
||||
GameWindow *win = NULL;
|
||||
Real x = (Real)TheDisplay->getWidth() / 800;
|
||||
Real y = (Real)TheDisplay->getHeight() / 600;
|
||||
while (it != m_resizerWindowsList.end())
|
||||
{
|
||||
ResizerWindow *rWin = *it;
|
||||
if( !rWin )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(FALSE,("There's no resizerWindow in ControlBarResizer::sizeWindowsDefault"));
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey(rWin->m_name));
|
||||
if(!win)
|
||||
{
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
win->winSetPosition(rWin->m_altPos.x * x, rWin->m_altPos.y * y);
|
||||
if(rWin->m_altSize.x >0 || rWin->m_altSize.y > 0)
|
||||
win->winSetSize(rWin->m_altSize.x *x, rWin->m_altSize.y *y);
|
||||
DEBUG_LOG(("sizeWindowsAlt:%s pos X:%d pos Y: %d size X:%d sizeY: %d",rWin->m_name.str(), rWin->m_altPos.x*x, rWin->m_altPos.y*y,rWin->m_altSize.x*x, rWin->m_altSize.y *y));
|
||||
it ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void INI::parseControlBarResizerDefinition( INI* ini )
|
||||
{
|
||||
// AsciiString name;
|
||||
// ResizerWindow *rWin = NULL;
|
||||
//
|
||||
// // read the name
|
||||
// const char* c = ini->getNextToken();
|
||||
// name.set( c );
|
||||
//
|
||||
//// ControlBarResizer *resizer = TheControlBar->getControlBarResizer();
|
||||
// if( !resizer )
|
||||
// {
|
||||
// //We don't need it if we're in the builder... which doesn't have this.
|
||||
// return;
|
||||
// }
|
||||
// rWin = resizer->findResizerWindow( name );
|
||||
// if( rWin == NULL )
|
||||
// {
|
||||
//
|
||||
// // image not found, create a new one
|
||||
// rWin = resizer->newResizerWindow(name);
|
||||
// DEBUG_ASSERTCRASH( rWin, ("parseControlBarResizerDefinition: unable to allocate ResizerWindow for '%s'\n",
|
||||
// name.str()) );
|
||||
//
|
||||
// } // end if
|
||||
//
|
||||
// // parse the ini definition
|
||||
// ini->initFromINI( rWin, resizer->getFieldParse());
|
||||
//
|
||||
} // end parseMappedImage
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
** 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: ControlBarStructureInventory.cpp /////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, March 2002
|
||||
// Desc: Methods specific to the control bar garrison display
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/Module/OpenContain.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetPushButton.h"
|
||||
#include "GameClient/Hotkey.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
#define STOP_ID 10
|
||||
#define EVACUATE_ID 11
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
struct PopulateButtonInfo
|
||||
{
|
||||
Object *source;
|
||||
Int buttonIndex;
|
||||
ControlBar* self;
|
||||
GameWindow** inventoryButtons;
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::populateButtonProc( Object *obj, void *userData )
|
||||
{
|
||||
PopulateButtonInfo* info = (PopulateButtonInfo*)userData;
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( info->buttonIndex < MAX_STRUCTURE_INVENTORY_BUTTONS,
|
||||
("Too many objects inside '%s' for the inventory buttons to hold",
|
||||
info->source->getTemplate()->getName().str()) );
|
||||
|
||||
// put object in inventory data
|
||||
info->self->m_containData[ info->buttonIndex ].control = info->inventoryButtons[ info->buttonIndex ];
|
||||
info->self->m_containData[ info->buttonIndex ].objectID = obj->getID();
|
||||
|
||||
// set the UI button that will allow us to press it and cause the object to exit the container
|
||||
const Image *image;
|
||||
image = obj->getTemplate()->getButtonImage();
|
||||
GadgetButtonSetEnabledImage( info->inventoryButtons[ info->buttonIndex ], image );
|
||||
|
||||
//Show the auto-contained object's veterancy symbol!
|
||||
image = calculateVeterancyOverlayForObject( obj );
|
||||
GadgetButtonDrawOverlayImage( info->inventoryButtons[ info->buttonIndex ], image );
|
||||
|
||||
// Enable the button
|
||||
info->inventoryButtons[ info->buttonIndex ]->winEnable( TRUE );
|
||||
|
||||
// move to the next button index
|
||||
info->buttonIndex++;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::populateStructureInventory( Object *building )
|
||||
{
|
||||
Int i;
|
||||
|
||||
// reset the inventory data
|
||||
resetContainData();
|
||||
|
||||
// reset hotkeys -- seeing it only is reset in switching contexts. This is a special case
|
||||
// because we are building the hotkeys on the fly sort of... and it changes as guys enter
|
||||
// and leave. Taking this call out will cause multiple hotkeys to be added.
|
||||
if(TheHotKeyManager)
|
||||
TheHotKeyManager->reset();
|
||||
|
||||
// get the contain module of the object
|
||||
ContainModuleInterface *contain = building->getContain();
|
||||
DEBUG_ASSERTCRASH( contain, ("Object in structure inventory does not contain a Contain Module\n") );
|
||||
if (!contain)
|
||||
return;
|
||||
|
||||
/// @todo srj -- remove hard-coding here, please
|
||||
const CommandButton *evacuateCommand = findCommandButton( "Command_Evacuate" );
|
||||
setControlCommand( m_commandWindows[ EVACUATE_ID ], evacuateCommand );
|
||||
m_commandWindows[ EVACUATE_ID ]->winEnable( FALSE );
|
||||
|
||||
/// @todo srj -- remove hard-coding here, please
|
||||
const CommandButton *stopCommand = findCommandButton( "Command_Stop" );
|
||||
setControlCommand( m_commandWindows[ STOP_ID ], stopCommand );
|
||||
m_commandWindows[ STOP_ID ]->winEnable( FALSE );
|
||||
|
||||
// get the inventory exit command to assign into the button
|
||||
/// @todo srj -- remove hard-coding here, please
|
||||
const CommandButton *exitCommand = findCommandButton( "Command_StructureExit" );
|
||||
|
||||
// get window handles for each of the inventory buttons
|
||||
AsciiString windowName;
|
||||
for( i = 0; i < MAX_STRUCTURE_INVENTORY_BUTTONS; i++ )
|
||||
{
|
||||
// show the window
|
||||
m_commandWindows[ i ]->winHide( FALSE );
|
||||
|
||||
//
|
||||
// disable the button for now, it will be enabled if there is something there
|
||||
// for its contents
|
||||
//
|
||||
m_commandWindows[ i ]->winEnable( FALSE );
|
||||
m_commandWindows[ i ]->winSetStatus( WIN_STATUS_ALWAYS_COLOR );
|
||||
m_commandWindows[ i ]->winClearStatus( WIN_STATUS_NOT_READY );
|
||||
|
||||
// set an inventory command into the game window UI element
|
||||
setControlCommand( m_commandWindows[ i ], exitCommand );
|
||||
|
||||
// Clear any veterancy icon incase the unit leaves!
|
||||
GadgetButtonDrawOverlayImage( m_commandWindows[ i ], NULL );
|
||||
//
|
||||
// if the structure can hold a lesser amount inside it than what the GUI displays
|
||||
// we will completely hide the buttons that can't contain anything
|
||||
//
|
||||
if( i + 1 > contain->getContainMax() )
|
||||
m_commandWindows[ i ]->winHide( TRUE );
|
||||
|
||||
|
||||
} // end for i
|
||||
|
||||
// show the window
|
||||
m_commandWindows[ EVACUATE_ID ]->winHide( FALSE );
|
||||
m_commandWindows[ STOP_ID ]->winHide( FALSE );
|
||||
|
||||
// if there is at least one item in there enable the evacuate and stop buttons
|
||||
if( contain->getContainCount() != 0 )
|
||||
{
|
||||
m_commandWindows[ EVACUATE_ID ]->winEnable( TRUE );
|
||||
m_commandWindows[ STOP_ID ]->winEnable( TRUE );
|
||||
}
|
||||
|
||||
//
|
||||
// iterate each of the objects inside the container and put them in a button, note
|
||||
// we're iterating in reverse order here
|
||||
//
|
||||
PopulateButtonInfo info;
|
||||
info.source = building;
|
||||
info.buttonIndex = 0;
|
||||
info.self = this;
|
||||
info.inventoryButtons = m_commandWindows;
|
||||
contain->iterateContained(populateButtonProc, &info, FALSE );
|
||||
|
||||
//
|
||||
// save how many items were contained by the object at this time so that we can update
|
||||
// it if they change in the future while selected
|
||||
//
|
||||
m_lastRecordedInventoryCount = contain->getContainCount();
|
||||
|
||||
} // end populateStructureInventory
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::updateContextStructureInventory( void )
|
||||
{
|
||||
Object *source = m_currentSelectedDrawable->getObject();
|
||||
|
||||
//
|
||||
// we're visible, so there is something selected. It is possible that we had a building
|
||||
// selected that can be garrisoned, and while it was selected the enemy occupied it.
|
||||
// in that case we want to unselect the building so that we can't see the contents
|
||||
//
|
||||
Player *localPlayer = ThePlayerList->getLocalPlayer();
|
||||
if( source->isLocallyControlled() == FALSE &&
|
||||
localPlayer->getRelationship( source->getTeam() ) != NEUTRAL )
|
||||
{
|
||||
Drawable *draw = source->getDrawable();
|
||||
|
||||
if( draw )
|
||||
TheInGameUI->deselectDrawable( draw );
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
//
|
||||
// if the object being displayed in the interface has a different count than we last knew
|
||||
// about we need to repopulate the buttons of the interface
|
||||
//
|
||||
ContainModuleInterface *contain = source->getContain();
|
||||
DEBUG_ASSERTCRASH( contain, ("No contain module defined for object in the iventory bar\n") );
|
||||
if (!contain)
|
||||
return;
|
||||
|
||||
if( m_lastRecordedInventoryCount != contain->getContainCount() )
|
||||
populateStructureInventory( source );
|
||||
|
||||
} // end updateContextStructureInventory
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
** 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: ControlBarUnderConstruction.cpp //////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, March 2002
|
||||
// Desc: Methods specific to the control bar under construction context
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
|
||||
#include "GameLogic/Object.h"
|
||||
#include "GameLogic/Module/UpdateModule.h"
|
||||
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::updateConstructionTextDisplay( Object *obj )
|
||||
{
|
||||
UnicodeString text;
|
||||
static UnsignedInt descID = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:UnderConstructionDesc" );
|
||||
GameWindow *descWindow = TheWindowManager->winGetWindowFromId( NULL, descID );
|
||||
|
||||
// santiy
|
||||
DEBUG_ASSERTCRASH( descWindow, ("Under construction window not found\n") );
|
||||
|
||||
// format the message
|
||||
text.format( TheGameText->fetch( "CONTROLBAR:UnderConstructionDesc" ),
|
||||
obj->getConstructionPercent() );
|
||||
GadgetStaticTextSetText( descWindow, text );
|
||||
|
||||
// record this as the last percentage displayed
|
||||
m_displayedConstructPercent = obj->getConstructionPercent();
|
||||
|
||||
} // end updateConstructionTextDisplay
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Populate the interface for an under construction context. */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::populateUnderConstruction( Object *objectUnderConstruction )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( objectUnderConstruction == NULL )
|
||||
return;
|
||||
|
||||
// get our parent window
|
||||
GameWindow *parent = m_contextParent[ CP_UNDER_CONSTRUCTION ];
|
||||
|
||||
// set the cancel construction button
|
||||
/// @todo srj -- remove hard-coding here, please
|
||||
const CommandButton *commandButton = findCommandButton( "Command_CancelConstruction" );
|
||||
NameKeyType id;
|
||||
id = TheNameKeyGenerator->nameToKey( "ControlBar.wnd:ButtonCancelConstruction" );
|
||||
GameWindow *win = TheWindowManager->winGetWindowFromId( parent, id );
|
||||
|
||||
setControlCommand( win, commandButton );
|
||||
win->winSetStatus( WIN_STATUS_USE_OVERLAY_STATES );
|
||||
|
||||
// set the text description of what is building
|
||||
updateConstructionTextDisplay( objectUnderConstruction );
|
||||
|
||||
// set the portrait for the thing being constructed
|
||||
setPortraitByObject( objectUnderConstruction );
|
||||
|
||||
// and show the rally point, if it should have one,
|
||||
ExitInterface *exit = objectUnderConstruction->getObjectExitInterface();
|
||||
if( exit )
|
||||
showRallyPoint( exit->getRallyPoint() );
|
||||
|
||||
|
||||
} // end populateUnderConstruction
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ControlBar::updateContextUnderConstruction( void )
|
||||
{
|
||||
Object *obj = m_currentSelectedDrawable->getObject();
|
||||
|
||||
// if the object is no longer under construction switch to a new appropriate context
|
||||
if( BitTest( obj->getStatusBits(), OBJECT_STATUS_UNDER_CONSTRUCTION ) == FALSE )
|
||||
{
|
||||
|
||||
evaluateContextUI();
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// if the construction percent has changed since what was last shown to the user update the text
|
||||
if( m_displayedConstructPercent != obj->getConstructionPercent() )
|
||||
updateConstructionTextDisplay( obj );
|
||||
|
||||
} // end updatecontextUnderConstruction
|
||||
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
** 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. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/DisconnectMenu.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameNetwork/GameInfo.h"
|
||||
#include "GameNetwork/NetworkInterface.h"
|
||||
|
||||
char *DisconnectMenu::m_playerNameTextControlNames[] = {
|
||||
"DisconnectScreen.wnd:StaticPlayer1Name",
|
||||
"DisconnectScreen.wnd:StaticPlayer2Name",
|
||||
"DisconnectScreen.wnd:StaticPlayer3Name",
|
||||
"DisconnectScreen.wnd:StaticPlayer4Name",
|
||||
"DisconnectScreen.wnd:StaticPlayer5Name",
|
||||
"DisconnectScreen.wnd:StaticPlayer6Name",
|
||||
"DisconnectScreen.wnd:StaticPlayer7Name",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *DisconnectMenu::m_playerTimeoutTextControlNames[] = {
|
||||
"DisconnectScreen.wnd:StaticPlayer1Timeout",
|
||||
"DisconnectScreen.wnd:StaticPlayer2Timeout",
|
||||
"DisconnectScreen.wnd:StaticPlayer3Timeout",
|
||||
"DisconnectScreen.wnd:StaticPlayer4Timeout",
|
||||
"DisconnectScreen.wnd:StaticPlayer5Timeout",
|
||||
"DisconnectScreen.wnd:StaticPlayer6Timeout",
|
||||
"DisconnectScreen.wnd:StaticPlayer7Timeout",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *DisconnectMenu::m_playerVoteButtonControlNames[] = {
|
||||
"DisconnectScreen.wnd:ButtonKickPlayer1",
|
||||
"DisconnectScreen.wnd:ButtonKickPlayer2",
|
||||
"DisconnectScreen.wnd:ButtonKickPlayer3",
|
||||
"DisconnectScreen.wnd:ButtonKickPlayer4",
|
||||
"DisconnectScreen.wnd:ButtonKickPlayer5",
|
||||
"DisconnectScreen.wnd:ButtonKickPlayer6",
|
||||
"DisconnectScreen.wnd:ButtonKickPlayer7",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *DisconnectMenu::m_playerVoteCountControlNames[] = {
|
||||
"DisconnectScreen.wnd:StaticPlayer1Votes",
|
||||
"DisconnectScreen.wnd:StaticPlayer2Votes",
|
||||
"DisconnectScreen.wnd:StaticPlayer3Votes",
|
||||
"DisconnectScreen.wnd:StaticPlayer4Votes",
|
||||
"DisconnectScreen.wnd:StaticPlayer5Votes",
|
||||
"DisconnectScreen.wnd:StaticPlayer6Votes",
|
||||
"DisconnectScreen.wnd:StaticPlayer7Votes",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *DisconnectMenu::m_packetRouterTimeoutControlName = "DisconnectScreen.wnd:StaticPacketRouterTimeout";
|
||||
char *DisconnectMenu::m_packetRouterTimeoutLabelControlName = "DisconnectScreen.wnd:StaticPacketRouterTimeoutLabel";
|
||||
char *DisconnectMenu::m_textDisplayControlName = "DisconnectScreen.wnd:ListboxTextDisplay";
|
||||
|
||||
static const Color chatNormalColor = GameMakeColor(255,0,0,255);
|
||||
|
||||
DisconnectMenu *TheDisconnectMenu = NULL;
|
||||
|
||||
DisconnectMenu::DisconnectMenu() {
|
||||
m_disconnectManager = NULL;
|
||||
}
|
||||
|
||||
DisconnectMenu::~DisconnectMenu() {
|
||||
}
|
||||
|
||||
void DisconnectMenu::init() {
|
||||
m_disconnectManager = NULL;
|
||||
HideDisconnectWindow();
|
||||
m_menuState = DISCONNECTMENUSTATETYPE_SCREENOFF;
|
||||
}
|
||||
|
||||
void DisconnectMenu::attachDisconnectManager(DisconnectManager *disconnectManager) {
|
||||
m_disconnectManager = disconnectManager;
|
||||
}
|
||||
|
||||
void DisconnectMenu::showScreen() {
|
||||
HideDiplomacy();
|
||||
HideInGameChat();
|
||||
HideQuitMenu();
|
||||
ShowDisconnectWindow();
|
||||
m_menuState = DISCONNECTMENUSTATETYPE_SCREENON;
|
||||
}
|
||||
|
||||
void DisconnectMenu::hideScreen() {
|
||||
HideDisconnectWindow();
|
||||
m_menuState = DISCONNECTMENUSTATETYPE_SCREENOFF;
|
||||
}
|
||||
|
||||
void DisconnectMenu::setPlayerName(Int playerNum, UnicodeString name) {
|
||||
NameKeyType id = TheNameKeyGenerator->nameToKey(m_playerNameTextControlNames[playerNum]);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (control != NULL) {
|
||||
if (name.getLength() > 0) {
|
||||
GadgetStaticTextSetText(control, name);
|
||||
// showPlayerControls(playerNum);
|
||||
}
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_playerTimeoutTextControlNames[playerNum]);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (control != NULL) {
|
||||
if (name.getLength() > 0) {
|
||||
GadgetStaticTextSetText(control, UnicodeString(L""));
|
||||
}
|
||||
}
|
||||
|
||||
if (name.getLength() > 0) {
|
||||
showPlayerControls(playerNum);
|
||||
} else {
|
||||
hidePlayerControls(playerNum);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::setPlayerTimeoutTime(Int playerNum, time_t newTime) {
|
||||
NameKeyType id = TheNameKeyGenerator->nameToKey(m_playerTimeoutTextControlNames[playerNum]);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
char str[33]; // itoa uses a max of 33 bytes.
|
||||
itoa(newTime, str, 10);
|
||||
AsciiString asciiNum;
|
||||
asciiNum.set(str);
|
||||
UnicodeString uninum;
|
||||
uninum.translate(asciiNum);
|
||||
if (control != NULL) {
|
||||
GadgetStaticTextSetText(control, uninum);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::showPlayerControls(Int slot) {
|
||||
NameKeyType id = TheNameKeyGenerator->nameToKey(m_playerNameTextControlNames[slot]);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
if (control != NULL) {
|
||||
control->winHide(FALSE);
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_playerTimeoutTextControlNames[slot]);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
if (control != NULL) {
|
||||
control->winHide(FALSE);
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_playerVoteButtonControlNames[slot]);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
if (control != NULL) {
|
||||
control->winHide(FALSE);
|
||||
// Disallow voting for 2-player games. Cheating punk.
|
||||
if ( TheGameInfo && TheGameInfo->getNumPlayers() < 3 )
|
||||
{
|
||||
control->winEnable(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
control->winEnable(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_playerVoteCountControlNames[slot]);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
if (control != NULL) {
|
||||
control->winHide(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::hidePlayerControls(Int slot) {
|
||||
NameKeyType id = TheNameKeyGenerator->nameToKey(m_playerNameTextControlNames[slot]);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
if (control != NULL) {
|
||||
control->winHide(TRUE);
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_playerTimeoutTextControlNames[slot]);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
if (control != NULL) {
|
||||
control->winHide(TRUE);
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_playerVoteButtonControlNames[slot]);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
if (control != NULL) {
|
||||
control->winHide(TRUE);
|
||||
// Disallow voting for 2-player games. Cheating punk.
|
||||
if ( TheGameInfo && TheGameInfo->getNumPlayers() < 3 )
|
||||
{
|
||||
control->winEnable(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
control->winEnable(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_playerVoteCountControlNames[slot]);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
if (control != NULL) {
|
||||
control->winHide(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::showPacketRouterTimeout() {
|
||||
NameKeyType id = TheNameKeyGenerator->nameToKey(m_packetRouterTimeoutLabelControlName);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (control != NULL) {
|
||||
control->winHide(FALSE);
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_packetRouterTimeoutControlName);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (control != NULL) {
|
||||
GadgetStaticTextSetText(control, UnicodeString(L"")); // start it off with a blank string.
|
||||
control->winHide(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::hidePacketRouterTimeout() {
|
||||
NameKeyType id = TheNameKeyGenerator->nameToKey(m_packetRouterTimeoutLabelControlName);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (control != NULL) {
|
||||
control->winHide(TRUE);
|
||||
}
|
||||
|
||||
id = TheNameKeyGenerator->nameToKey(m_packetRouterTimeoutControlName);
|
||||
control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (control != NULL) {
|
||||
control->winHide(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::setPacketRouterTimeoutTime(time_t newTime) {
|
||||
NameKeyType id = TheNameKeyGenerator->nameToKey(m_packetRouterTimeoutControlName);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
char str[33]; // itoa uses a max of 33 bytes.
|
||||
itoa(newTime, str, 10);
|
||||
AsciiString asciiNum;
|
||||
asciiNum.set(str);
|
||||
UnicodeString uninum;
|
||||
uninum.translate(asciiNum);
|
||||
if (control != NULL) {
|
||||
GadgetStaticTextSetText(control, uninum);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::sendChat(UnicodeString text) {
|
||||
TheNetwork->sendDisconnectChat(text);
|
||||
}
|
||||
|
||||
void DisconnectMenu::showChat(UnicodeString text) {
|
||||
NameKeyType displayID = TheNameKeyGenerator->nameToKey(m_textDisplayControlName);
|
||||
GameWindow *displayControl = TheWindowManager->winGetWindowFromId(NULL, displayID);
|
||||
|
||||
if (displayControl != NULL) {
|
||||
GadgetListBoxAddEntryText(displayControl, text, chatNormalColor, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::quitGame() {
|
||||
TheNetwork->quitGame();
|
||||
}
|
||||
|
||||
void DisconnectMenu::removePlayer(Int slot, UnicodeString playerName) {
|
||||
hidePlayerControls(slot);
|
||||
|
||||
NameKeyType displayID = TheNameKeyGenerator->nameToKey(m_textDisplayControlName);
|
||||
GameWindow *displayControl = TheWindowManager->winGetWindowFromId(NULL, displayID);
|
||||
|
||||
UnicodeString text;
|
||||
// UnicodeString name;
|
||||
// name.translate(playerName);
|
||||
text.format(TheGameText->fetch("Network:PlayerLeftGame"), playerName.str());
|
||||
|
||||
if (displayControl != NULL) {
|
||||
GadgetListBoxAddEntryText(displayControl, text, chatNormalColor, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void DisconnectMenu::voteForPlayer(Int slot) {
|
||||
DEBUG_LOG(("Casting vote for disconnect slot %d\n", slot));
|
||||
TheNetwork->voteForPlayerDisconnect(slot); // Do this next.
|
||||
}
|
||||
|
||||
void DisconnectMenu::updateVotes(Int slot, Int votes) {
|
||||
NameKeyType id = TheNameKeyGenerator->nameToKey(m_playerVoteCountControlNames[slot]);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (control != NULL) {
|
||||
char votestr[16];
|
||||
itoa(votes, votestr, 10);
|
||||
AsciiString asciivotes;
|
||||
asciivotes.set(votestr);
|
||||
UnicodeString unistr;
|
||||
unistr.translate(asciivotes);
|
||||
|
||||
GadgetStaticTextSetText(control, unistr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
** 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. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// EstablishConnectionsMenu.cpp /////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/EstablishConnectionsMenu.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GameText.h"
|
||||
|
||||
EstablishConnectionsMenu *TheEstablishConnectionsMenu = NULL;
|
||||
|
||||
char *EstablishConnectionsMenu::m_playerReadyControlNames[] = {
|
||||
"EstablishConnectionsScreen.wnd:ButtonAccept1",
|
||||
"EstablishConnectionsScreen.wnd:ButtonAccept2",
|
||||
"EstablishConnectionsScreen.wnd:ButtonAccept3",
|
||||
"EstablishConnectionsScreen.wnd:ButtonAccept4",
|
||||
"EstablishConnectionsScreen.wnd:ButtonAccept5",
|
||||
"EstablishConnectionsScreen.wnd:ButtonAccept6",
|
||||
"EstablishConnectionsScreen.wnd:ButtonAccept7",
|
||||
NULL};
|
||||
|
||||
char *EstablishConnectionsMenu::m_playerNameControlNames[] = {
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer1Name",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer2Name",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer3Name",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer4Name",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer5Name",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer6Name",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer7Name",
|
||||
NULL
|
||||
};
|
||||
|
||||
char *EstablishConnectionsMenu::m_playerStatusControlNames[] = {
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer1Status",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer2Status",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer3Status",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer4Status",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer5Status",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer6Status",
|
||||
"EstablishConnectionsScreen.wnd:StaticPlayer7Status",
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
Constructor
|
||||
*/
|
||||
EstablishConnectionsMenu::EstablishConnectionsMenu() {
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
EstablishConnectionsMenu::~EstablishConnectionsMenu() {
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the menu
|
||||
*/
|
||||
void EstablishConnectionsMenu::initMenu() {
|
||||
ShowEstablishConnectionsWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
Close down the menu
|
||||
*/
|
||||
void EstablishConnectionsMenu::endMenu() {
|
||||
HideEstablishConnectionsWindow();
|
||||
}
|
||||
|
||||
/**
|
||||
Abort the game gracefully...ok, as gracefully as possible considering
|
||||
the game was supposed to be started and now for some reason we have to
|
||||
stop it. Its really sad that this game isn't going to be played
|
||||
considering how difficult it is to even get a game going in the first
|
||||
place, especially one with more than two players.
|
||||
*/
|
||||
void EstablishConnectionsMenu::abortGame() {
|
||||
}
|
||||
|
||||
// the slot number passed in is the index we are to use for the menu.
|
||||
void EstablishConnectionsMenu::setPlayerName(Int slot, UnicodeString name) {
|
||||
NameKeyType controlID = TheNameKeyGenerator->nameToKey(m_playerNameControlNames[slot]);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, controlID);
|
||||
|
||||
if (control == NULL) {
|
||||
DEBUG_ASSERTCRASH(control != NULL, ("player name control for slot %d is NULL", slot));
|
||||
return;
|
||||
}
|
||||
GadgetStaticTextSetText(control, name);
|
||||
}
|
||||
|
||||
void EstablishConnectionsMenu::setPlayerStatus(Int slot, NATConnectionState state) {
|
||||
NameKeyType controlID = TheNameKeyGenerator->nameToKey(m_playerStatusControlNames[slot]);
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId(NULL, controlID);
|
||||
|
||||
if (control == NULL) {
|
||||
DEBUG_ASSERTCRASH(control != NULL, ("player status control for slot %d is NULL", slot));
|
||||
return;
|
||||
}
|
||||
// if (state == NATCONNECTIONSTATE_NETGEARDELAY) {
|
||||
// GadgetStaticTextSetText(control, TheGameText->fetch("GUI:NetgearDelay"));
|
||||
if (state == NATCONNECTIONSTATE_WAITINGFORMANGLERRESPONSE) {
|
||||
GadgetStaticTextSetText(control, TheGameText->fetch("GUI:WaitingForManglerResponse"));
|
||||
} else if (state == NATCONNECTIONSTATE_WAITINGFORMANGLEDPORT) {
|
||||
GadgetStaticTextSetText(control, TheGameText->fetch("GUI:WaitingForMangledPort"));
|
||||
} else if (state == NATCONNECTIONSTATE_WAITINGFORRESPONSE) {
|
||||
GadgetStaticTextSetText(control, TheGameText->fetch("GUI:WaitingForResponse"));
|
||||
} else if (state == NATCONNECTIONSTATE_DONE) {
|
||||
GadgetStaticTextSetText(control, TheGameText->fetch("GUI:ConnectionDone"));
|
||||
} else if (state == NATCONNECTIONSTATE_FAILED) {
|
||||
GadgetStaticTextSetText(control, TheGameText->fetch("GUI:ConnectionFailed"));
|
||||
} else if (state == NATCONNECTIONSTATE_WAITINGTOBEGIN) {
|
||||
GadgetStaticTextSetText(control, TheGameText->fetch("GUI:WaitingToBeginConnection"));
|
||||
} else {
|
||||
GadgetStaticTextSetText(control, TheGameText->fetch("GUI:UnknownConnectionState"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,622 @@
|
||||
/*
|
||||
** 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: ControlBarCallback.cpp ///////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day - October 2001
|
||||
// Desc: GUI Control bar at the bottom of the screen that houses the
|
||||
// the build buttons, radar etc.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "Common/ThingFactory.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/Radar.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/Drawable.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/LanguageFilter.h"
|
||||
#include "GameClient/CommandXlat.h"
|
||||
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/ScriptEngine.h"
|
||||
|
||||
//external declarations of the Gadgets the callbacks can use
|
||||
WindowLayout *popupCommunicatorLayout = NULL;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Input procedure for the left HUD */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType LeftHUDInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
// get player
|
||||
Player *player = ThePlayerList->getLocalPlayer();
|
||||
|
||||
//
|
||||
// if the player doesn't have a radar, or the radar is hidden, and the radar is not being
|
||||
// forced to on, we just eat input over the radar window
|
||||
//
|
||||
if( !TheRadar->isRadarForced() && (TheRadar->isRadarHidden() || !player->hasRadar()) )
|
||||
return MSG_HANDLED;
|
||||
|
||||
// If the middle mouse button is depressed, then just let the message fall all the
|
||||
// way back to the usual middle mouse button processing.
|
||||
// jkmcd
|
||||
if( TheMouse->getMouseStatus()->middleState == MBS_Down )
|
||||
return MSG_IGNORED;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
/** @todo
|
||||
This is wrong. The radar should be in the message stream, and eat all messages and propagate them
|
||||
as a new message with the coords converted to world coords and the message flagged as being from
|
||||
the radar. This would let all of the normal processing occur, and allow individual commands to easily
|
||||
reject being used on the radar.
|
||||
*/
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_NONE:
|
||||
case GWM_MOUSE_ENTERING:
|
||||
case GWM_MOUSE_LEAVING:
|
||||
{
|
||||
|
||||
//
|
||||
// consider changing the mouse cursor if we are not in the process of firing
|
||||
// targeted "superweapons" which we can use the radar itself to fire
|
||||
//
|
||||
Bool targeting = FALSE;
|
||||
const CommandButton *command = TheInGameUI->getGUICommand();
|
||||
if( command
|
||||
&& (command->getCommandType() == GUI_COMMAND_SPECIAL_POWER || command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER)
|
||||
&& BitTest( command->getOptions(), NEED_TARGET_POS ) )
|
||||
targeting = TRUE;
|
||||
|
||||
if( targeting == FALSE )
|
||||
{
|
||||
const DrawableList *drawableList = TheInGameUI->getAllSelectedLocalDrawables();
|
||||
Mouse::MouseCursor cur = Mouse::ARROW;
|
||||
|
||||
if (!(drawableList->empty() || msg == GWM_MOUSE_LEAVING))
|
||||
{
|
||||
if (command && command->getCommandType() == GUI_COMMAND_ATTACK_MOVE)
|
||||
{
|
||||
cur = Mouse::ATTACKMOVETO;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = Mouse::MOVETO;
|
||||
}
|
||||
}
|
||||
|
||||
// Groovy
|
||||
TheMouse->setCursor(cur);
|
||||
|
||||
} // end if
|
||||
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_MOUSE_POS:
|
||||
{
|
||||
|
||||
// get mouse position
|
||||
ICoord2D mouse;
|
||||
mouse.x = mData1 & 0xFFFF;
|
||||
mouse.y = mData1 >> 16;
|
||||
|
||||
// get window screen position
|
||||
ICoord2D screenPos;
|
||||
window->winGetScreenPosition( &screenPos.x, &screenPos.y );
|
||||
|
||||
// set mouse position to be relative to this window
|
||||
mouse.x -= screenPos.x;
|
||||
mouse.y -= screenPos.y;
|
||||
|
||||
// is the mouse in the radar window
|
||||
ICoord2D radar;
|
||||
if( (TheRadar->isRadarHidden() == FALSE || TheRadar->isRadarForced()) &&
|
||||
TheRadar->localPixelToRadar( &mouse, &radar ) )
|
||||
{
|
||||
|
||||
/*
|
||||
//
|
||||
// this is an example piece of code to find the object under the pixel position
|
||||
// of the radar ... should we in the future wish to allow commands to be executed
|
||||
// on objects throught he radar. note tho that this is extremely hard to do because
|
||||
// the pixels on the radar are very small and it's hard to do accurate targeting
|
||||
//
|
||||
|
||||
Object *obj = TheRadar->objectUnderRadarPixel( &mouse );
|
||||
UnicodeString msg;
|
||||
if( obj )
|
||||
msg.format( L"Object under mouse on radar '%S'(%d)",
|
||||
obj->getTemplate()->getName().str(), obj->getID() );
|
||||
else
|
||||
msg.format( L"Mouse (%d,%d) in Radar window L(%d,%d)", mouse.x, mouse.y, radar.x, radar.y );
|
||||
TheInGameUI->message( msg );
|
||||
*/
|
||||
|
||||
// keep the cursor for any context commands
|
||||
const CommandButton *command = TheInGameUI->getGUICommand();
|
||||
if( command
|
||||
&& (command->getCommandType() == GUI_COMMAND_SPECIAL_POWER || command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER)
|
||||
&& BitTest( command->getOptions(), NEED_TARGET_POS ) )
|
||||
{
|
||||
Int index = TheMouse->getCursorIndex( command->getCursorName() );
|
||||
|
||||
if( index != Mouse::INVALID_MOUSE_CURSOR )
|
||||
TheMouse->setCursor( (Mouse::MouseCursor)index );
|
||||
else
|
||||
TheMouse->setCursor( Mouse::CROSS );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
// Else we are not super targeting, so we have to try to refresh the move cursor.
|
||||
// We can't just do this on Enter and Exit, because hotkeys allow state to change
|
||||
// while we are in the radar.
|
||||
const DrawableList *drawableList = TheInGameUI->getAllSelectedLocalDrawables();
|
||||
Mouse::MouseCursor cur = Mouse::ARROW;
|
||||
|
||||
if (!(drawableList->empty() || msg == GWM_MOUSE_LEAVING))
|
||||
{
|
||||
if (command && command->getCommandType() == GUI_COMMAND_ATTACK_MOVE)
|
||||
{
|
||||
cur = Mouse::ATTACKMOVETO;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur = Mouse::MOVETO;
|
||||
}
|
||||
}
|
||||
|
||||
// Groovy
|
||||
TheMouse->setCursor(cur);
|
||||
}
|
||||
|
||||
} // end if
|
||||
|
||||
break;
|
||||
|
||||
} // end case mouse position
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_RIGHT_UP:// Here to eat
|
||||
case GWM_LEFT_UP:// Here to eat
|
||||
break;
|
||||
|
||||
case GWM_RIGHT_DOWN:
|
||||
case GWM_LEFT_DOWN:
|
||||
{
|
||||
ICoord2D mouse;
|
||||
ICoord2D radar;
|
||||
ICoord2D size;
|
||||
ICoord2D screenPos;
|
||||
Coord3D world;
|
||||
|
||||
// get window size
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
|
||||
// get mouse position
|
||||
mouse.x = mData1 & 0xFFFF;
|
||||
mouse.y = mData1 >> 16;
|
||||
|
||||
// get window screen position
|
||||
window->winGetScreenPosition( &screenPos.x, &screenPos.y );
|
||||
|
||||
// set mouse position to be relative to this window
|
||||
mouse.x -= screenPos.x;
|
||||
mouse.y -= screenPos.y;
|
||||
|
||||
//
|
||||
// translate mouse position to radar position ... we know that the mouse
|
||||
// location given to us here is relative to the HUD window, which is
|
||||
// completely drawn with the radar ... so it's just a translation from
|
||||
// our window size we're drawing into to the radar cell size
|
||||
//
|
||||
if( (TheRadar->isRadarHidden() == FALSE || TheRadar->isRadarForced()) &&
|
||||
TheRadar->localPixelToRadar( &mouse, &radar ) &&
|
||||
TheRadar->radarToWorld( &radar, &world ) )
|
||||
{
|
||||
|
||||
// No drawables, or a right click automatically means its a look at.
|
||||
// Having drawables and being in attack move mode means that we should attack move.
|
||||
// Having drawables and not being in attack move mode means that we should move.
|
||||
|
||||
const DrawableList *drawableList = TheInGameUI->getAllSelectedLocalDrawables(); // locally-owned only
|
||||
|
||||
|
||||
// see if the user wants to move the tactical view
|
||||
if ( drawableList->empty()
|
||||
|| (! TheGlobalData->m_useAlternateMouse && msg == GWM_RIGHT_DOWN)
|
||||
|| (TheGlobalData->m_useAlternateMouse && msg == GWM_LEFT_DOWN) )
|
||||
{
|
||||
TheTacticalView->lookAt( &world );
|
||||
break;
|
||||
}
|
||||
|
||||
// evaluate any special powers that can be executed from the radar
|
||||
const CommandButton *command = TheInGameUI->getGUICommand();
|
||||
if( command
|
||||
&& (command->getCommandType() == GUI_COMMAND_SPECIAL_POWER || command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_COMMAND_CENTER)
|
||||
&& BitTest( command->getOptions(), NEED_TARGET_POS )
|
||||
)
|
||||
{
|
||||
|
||||
// do the command
|
||||
TheGameClient->evaluateContextCommand( NULL, &world, CommandTranslator::DO_COMMAND );
|
||||
|
||||
} // end if
|
||||
else if( command && command->getCommandType() == GUI_COMMAND_ATTACK_MOVE)
|
||||
{
|
||||
// Attack move has changed from a modifier to a command, so it moves up here.
|
||||
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_ATTACKMOVETO );
|
||||
msg->appendLocationArgument( world );
|
||||
|
||||
// Play the unit voice response
|
||||
pickAndPlayUnitVoiceResponse(TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_DO_ATTACKMOVETO);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMessage *newMsg = NULL;
|
||||
|
||||
// Do the superweapon stuff here, before issuing these other messages
|
||||
|
||||
// GS Leaving commented out to show that isInAttackMoveToMode is NEVER SET. It's a command now, not a modifier.
|
||||
// if (TheInGameUI->isInAttackMoveToMode())
|
||||
// {
|
||||
// newMsg = TheMessageStream->appendMessage(GameMessage::MSG_DO_ATTACKMOVETO);
|
||||
// newMsg->appendLocationArgument(world);
|
||||
// // Play the unit voice response
|
||||
// pickAndPlayUnitVoiceResponse(drawableList, GameMessage::MSG_DO_ATTACKMOVETO);
|
||||
// break;
|
||||
// }
|
||||
|
||||
newMsg = TheMessageStream->appendMessage(GameMessage::MSG_DO_MOVETO);
|
||||
newMsg->appendLocationArgument(world);
|
||||
// Play the unit voice response
|
||||
pickAndPlayUnitVoiceResponse(drawableList, GameMessage::MSG_DO_MOVETO);
|
||||
|
||||
} // end else
|
||||
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
|
||||
} // end left down
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
TheInGameUI->clearAttackMoveToMode();
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end LeftHUDInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Input procedure for the control bar */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType ControlBarInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end ControlBarInput
|
||||
void ToggleQuitMenu(void);
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** System callback for the control bar parent */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType ControlBarSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
static NameKeyType buttonCommunicator = NAMEKEY_INVALID;
|
||||
if(TheScriptEngine && TheScriptEngine->isGameEnding())
|
||||
return MSG_IGNORED;
|
||||
switch( msg )
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
// get ids for our children controls
|
||||
buttonCommunicator = TheNameKeyGenerator->nameToKey( AsciiString("ControlBar.wnd:PopupCommunicator") );
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_MOUSE_ENTERING:
|
||||
case GBM_MOUSE_LEAVING:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
|
||||
TheControlBar->processContextSensitiveButtonTransition( control, (GadgetGameMessage)msg);
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
case GBM_SELECTED_RIGHT:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
static NameKeyType beaconPlacementButtonID = NAMEKEY("ControlBar.wnd:ButtonPlaceBeacon");
|
||||
static NameKeyType beaconDeleteButtonID = NAMEKEY("ControlBar.wnd:ButtonDeleteBeacon");
|
||||
static NameKeyType beaconClearTextButtonID = NAMEKEY("ControlBar.wnd:ButtonClearBeaconText");
|
||||
static NameKeyType beaconGeneralButtonID = NAMEKEY("ControlBar.wnd:ButtonGeneral");
|
||||
// static NameKeyType buttonSmallID = NAMEKEY("ControlBar.wnd:ButtonSmall");
|
||||
// static NameKeyType buttonMediumID = NAMEKEY("ControlBar.wnd:ButtonMedium");
|
||||
static NameKeyType buttonLargeID = NAMEKEY("ControlBar.wnd:ButtonLarge");
|
||||
static NameKeyType buttonOptions = NAMEKEY("ControlBar.wnd:ButtonOptions");
|
||||
static NameKeyType buttonIdleWorker = NAMEKEY("ControlBar.wnd:ButtonIdleWorker");
|
||||
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == buttonCommunicator )
|
||||
{
|
||||
ToggleDiplomacy(FALSE);
|
||||
}
|
||||
else if( controlID == beaconPlacementButtonID && TheGameLogic->isInMultiplayerGame() &&
|
||||
ThePlayerList->getLocalPlayer()->isPlayerActive())
|
||||
{
|
||||
const CommandButton *commandButton = TheControlBar->findCommandButton( "Command_PlaceBeacon" );
|
||||
TheInGameUI->setGUICommand( commandButton );
|
||||
}
|
||||
else if( controlID == beaconDeleteButtonID && TheGameLogic->isInMultiplayerGame() )
|
||||
{
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_REMOVE_BEACON );
|
||||
}
|
||||
else if( controlID == beaconClearTextButtonID && TheGameLogic->isInMultiplayerGame() )
|
||||
{
|
||||
static NameKeyType textID = NAMEKEY("ControlBar.wnd:EditBeaconText");
|
||||
GameWindow *win = TheWindowManager->winGetWindowFromId(NULL, textID);
|
||||
if (win)
|
||||
{
|
||||
GadgetTextEntrySetText( win, UnicodeString::TheEmptyString );
|
||||
}
|
||||
}
|
||||
else if( controlID == beaconGeneralButtonID)
|
||||
{
|
||||
HideQuitMenu( );
|
||||
TheControlBar->togglePurchaseScience();
|
||||
}
|
||||
//else if( controlID == buttonSmallID)
|
||||
// {
|
||||
// TheControlBar->switchControlBarStage( CONTROL_BAR_STAGE_LOW );
|
||||
// }
|
||||
// else if( controlID == buttonMediumID)
|
||||
// {
|
||||
// TheControlBar->switchControlBarStage( CONTROL_BAR_STAGE_SQUISHED );
|
||||
// }
|
||||
|
||||
else if( controlID == buttonLargeID)
|
||||
{
|
||||
TheControlBar->toggleControlBarStage();
|
||||
}
|
||||
else if( controlID == buttonOptions)
|
||||
{
|
||||
ToggleQuitMenu();
|
||||
}
|
||||
else if( controlID == buttonIdleWorker)
|
||||
{
|
||||
HideQuitMenu( );
|
||||
TheInGameUI->selectNextIdleWorker();
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// all buttons from all the context sensitive user interface windows are part of the
|
||||
// control bar, send the button processing that way
|
||||
//
|
||||
TheControlBar->processContextSensitiveButtonClick( control, (GadgetGameMessage)msg );
|
||||
}
|
||||
break;
|
||||
|
||||
} // end button selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
static NameKeyType textID = NAMEKEY("ControlBar.wnd:EditBeaconText");
|
||||
if (controlID == textID)
|
||||
{
|
||||
// set beacon text
|
||||
if (TheInGameUI->getSelectCount() == 1)
|
||||
{
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_SET_BEACON_TEXT );
|
||||
UnicodeString newText = GadgetTextEntryGetText( control );
|
||||
TheLanguageFilter->filterLine(newText);
|
||||
const WideChar * c = newText.str();
|
||||
while ( c && *c )
|
||||
{
|
||||
msg->appendWideCharArgument( *c++ );
|
||||
}
|
||||
msg->appendWideCharArgument( L'\0' ); // trailing NULL
|
||||
}
|
||||
}
|
||||
break;
|
||||
} // end edit done
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end ControlBarSystem
|
||||
|
||||
extern void showReplayControls( void );
|
||||
extern void hideReplayControls( void );
|
||||
extern void toggleReplayControls( void );
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Force the control bar to be shown */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ShowControlBar( Bool immediate )
|
||||
{
|
||||
showReplayControls();
|
||||
if(TheControlBar)
|
||||
TheControlBar->showSpecialPowerShortcut();
|
||||
if (TheWindowManager)
|
||||
{
|
||||
Int id = (Int)TheNameKeyGenerator->nameToKey(AsciiString("ControlBar.wnd:ControlBarParent"));
|
||||
GameWindow *window = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (window)
|
||||
{
|
||||
TheControlBar->switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT);
|
||||
TheTacticalView->setHeight((Int)(TheDisplay->getHeight() * 0.80f));
|
||||
if (TheControlBar->m_animateWindowManager && !immediate)
|
||||
{
|
||||
TheControlBar->m_animateWindowManager->reset();
|
||||
//TheControlBar->m_animateWindowManager->registerGameWindow(window, WIN_ANIMATION_SLIDE_BOTTOM_TIMED, TRUE, 1000, 0);
|
||||
TheControlBar->m_animateWindowManager->registerGameWindow(window, WIN_ANIMATION_SLIDE_BOTTOM, TRUE, 500, 0);
|
||||
TheControlBar->animateSpecialPowerShortcut(TRUE);
|
||||
}
|
||||
window->winHide(FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// We want to get everything recalced since this is a major state change.
|
||||
if(TheControlBar)
|
||||
TheControlBar->markUIDirty();
|
||||
|
||||
}// void ShowControlBar(void)
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Force the control bar to be hidden */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void HideControlBar( Bool immediate )
|
||||
{
|
||||
hideReplayControls();
|
||||
if(TheControlBar)
|
||||
TheControlBar->hideSpecialPowerShortcut();
|
||||
if (TheWindowManager)
|
||||
{
|
||||
Int id = (Int)TheNameKeyGenerator->nameToKey(AsciiString("ControlBar.wnd:ControlBarParent"));
|
||||
GameWindow *window = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (window)
|
||||
{
|
||||
#ifdef SLIDE_LETTERBOX
|
||||
TheTacticalView->setHeight((Int)(TheDisplay->getHeight() * 0.80f));
|
||||
#else
|
||||
TheTacticalView->setHeight(TheDisplay->getHeight());
|
||||
#endif
|
||||
}
|
||||
if (immediate)
|
||||
{
|
||||
window->winHide(TRUE);
|
||||
if(TheControlBar)
|
||||
TheControlBar->hideSpecialPowerShortcut();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
TheControlBar->m_animateWindowManager->reverseAnimateWindow();
|
||||
TheControlBar->animateSpecialPowerShortcut(FALSE);
|
||||
}
|
||||
|
||||
//Always get rid of the purchase science screen!
|
||||
if( TheControlBar )
|
||||
{
|
||||
TheControlBar->hidePurchaseScience();
|
||||
}
|
||||
}
|
||||
}//void HideControlBar( void )
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Toggle the control bar on or off */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ToggleControlBar( Bool immediate )
|
||||
{
|
||||
toggleReplayControls();
|
||||
|
||||
if (TheWindowManager)
|
||||
{
|
||||
Int id = (Int)TheNameKeyGenerator->nameToKey(AsciiString("ControlBar.wnd:ControlBarParent"));
|
||||
GameWindow *window = TheWindowManager->winGetWindowFromId(NULL, id);
|
||||
|
||||
if (window)
|
||||
{
|
||||
if (window->winIsHidden())
|
||||
{
|
||||
if(TheControlBar)
|
||||
TheControlBar->showSpecialPowerShortcut();
|
||||
|
||||
//now hidden, we're making it visible again so shrink viewport under the window
|
||||
TheTacticalView->setHeight((Int)(TheDisplay->getHeight() * 0.80f));
|
||||
window->winHide(!window->winIsHidden());
|
||||
TheControlBar->switchControlBarStage(CONTROL_BAR_STAGE_DEFAULT);
|
||||
if (TheControlBar->m_animateWindowManager && !immediate)
|
||||
{
|
||||
TheControlBar->m_animateWindowManager->reset();
|
||||
//TheControlBar->m_animateWindowManager->registerGameWindow(window, WIN_ANIMATION_SLIDE_BOTTOM_TIMED, FALSE, 500, 0);
|
||||
TheControlBar->m_animateWindowManager->registerGameWindow(window, WIN_ANIMATION_SLIDE_BOTTOM, TRUE, 500, 0);
|
||||
TheControlBar->animateSpecialPowerShortcut(TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(TheControlBar)
|
||||
TheControlBar->hideSpecialPowerShortcut();
|
||||
TheTacticalView->setHeight(TheDisplay->getHeight());
|
||||
window->winHide(!window->winIsHidden());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}// end void ToggleControlBar( void )
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Resize the control bar */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
** 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: ControlBarPopupDescription.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Sep 2002
|
||||
//
|
||||
// Filename: ControlBarPopupDescription.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/BuildAssistant.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/ProductionPrerequisite.h"
|
||||
#include "Common/ThingTemplate.h"
|
||||
#include "Common/Upgrade.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/DisconnectMenu.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GadgetPushButton.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameClient/Controlbar.h"
|
||||
#include "GameClient/DisplayStringManager.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/Module/OverchargeBehavior.h"
|
||||
#include "GameLogic/Module/ProductionUpdate.h"
|
||||
#include "GameLogic/ScriptEngine.h"
|
||||
|
||||
#include "GameNetwork/NetworkInterface.h"
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
static WindowLayout *theLayout = NULL;
|
||||
static GameWindow *theWindow = NULL;
|
||||
static AnimateWindowManager *theAnimateWindowManager = NULL;
|
||||
static GameWindow *prevWindow = NULL;
|
||||
static Bool useAnimation = FALSE;
|
||||
void ControlBarPopupDescriptionUpdateFunc( WindowLayout *layout, void *param )
|
||||
{
|
||||
if(TheScriptEngine->isGameEnding())
|
||||
TheControlBar->hideBuildTooltipLayout();
|
||||
|
||||
if(theAnimateWindowManager && !TheControlBar->getShowBuildTooltipLayout() && !theAnimateWindowManager->isReversed())
|
||||
theAnimateWindowManager->reverseAnimateWindow();
|
||||
else if(!TheControlBar->getShowBuildTooltipLayout() && (!TheGlobalData->m_animateWindows || !useAnimation))
|
||||
TheControlBar->deleteBuildTooltipLayout();
|
||||
|
||||
|
||||
if ( useAnimation && theAnimateWindowManager && TheGlobalData->m_animateWindows)
|
||||
{
|
||||
Bool wasFinished = theAnimateWindowManager->isFinished();
|
||||
theAnimateWindowManager->update();
|
||||
if (theAnimateWindowManager && theAnimateWindowManager->isFinished() && !wasFinished && theAnimateWindowManager->isReversed())
|
||||
{
|
||||
delete theAnimateWindowManager;
|
||||
theAnimateWindowManager = NULL;
|
||||
TheControlBar->deleteBuildTooltipLayout();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
void ControlBar::showBuildTooltipLayout( GameWindow *cmdButton )
|
||||
{
|
||||
if (TheInGameUI->areTooltipsDisabled() || TheScriptEngine->isGameEnding())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Bool passedWaitTime = FALSE;
|
||||
static Bool isInitialized = FALSE;
|
||||
static UnsignedInt beginWaitTime;
|
||||
if(prevWindow == cmdButton)
|
||||
{
|
||||
m_showBuildToolTipLayout = TRUE;
|
||||
if(!isInitialized && beginWaitTime + cmdButton->getTooltipDelay() < timeGetTime())
|
||||
{
|
||||
//DEBUG_LOG(("%d beginwaittime, %d tooltipdelay, %dtimegettime\n", beginWaitTime, cmdButton->getTooltipDelay(), timeGetTime()));
|
||||
passedWaitTime = TRUE;
|
||||
}
|
||||
|
||||
if(!passedWaitTime)
|
||||
return;
|
||||
}
|
||||
else if( !m_buildToolTipLayout->isHidden() )
|
||||
{
|
||||
if(useAnimation && TheGlobalData->m_animateWindows && !theAnimateWindowManager->isReversed())
|
||||
theAnimateWindowManager->reverseAnimateWindow();
|
||||
else if( useAnimation && TheGlobalData->m_animateWindows && theAnimateWindowManager->isReversed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_buildToolTipLayout->destroyWindows();
|
||||
// m_buildToolTipLayout->deleteInstance();
|
||||
// m_buildToolTipLayout = NULL;
|
||||
m_buildToolTipLayout->hide(TRUE);
|
||||
prevWindow = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// will only get here the firsttime through the function through this window
|
||||
if(!passedWaitTime)
|
||||
{
|
||||
prevWindow = cmdButton;
|
||||
beginWaitTime = timeGetTime();
|
||||
isInitialized = FALSE;
|
||||
return;
|
||||
}
|
||||
isInitialized = TRUE;
|
||||
|
||||
if(!cmdButton)
|
||||
return;
|
||||
if(BitTest(cmdButton->winGetStyle(), GWS_PUSH_BUTTON))
|
||||
{
|
||||
const CommandButton *commandButton = (const CommandButton *)GadgetButtonGetData(cmdButton);
|
||||
|
||||
if(!commandButton)
|
||||
return;
|
||||
|
||||
// note that, in this branch, ENABLE_SOLO_PLAY is ***NEVER*** defined...
|
||||
// this is so that we have a multiplayer build that cannot possibly be hacked
|
||||
// to work as a solo game!
|
||||
#if !defined(_PLAYTEST)
|
||||
if (TheGameLogic->isInReplayGame())
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (TheInGameUI->isQuitMenuVisible())
|
||||
return;
|
||||
|
||||
if (TheDisconnectMenu && TheDisconnectMenu->isScreenVisible())
|
||||
return;
|
||||
|
||||
// if (m_buildToolTipLayout)
|
||||
// {
|
||||
// m_buildToolTipLayout->destroyWindows();
|
||||
// m_buildToolTipLayout->deleteInstance();
|
||||
//
|
||||
// }
|
||||
|
||||
m_showBuildToolTipLayout = TRUE;
|
||||
// m_buildToolTipLayout = TheWindowManager->winCreateLayout( "ControlBarPopupDescription.wnd" );
|
||||
// m_buildToolTipLayout->setUpdate(ControlBarPopupDescriptionUpdateFunc);
|
||||
|
||||
populateBuildTooltipLayout(commandButton);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're a generic window
|
||||
if(!BitTest(cmdButton->winGetStyle(), GWS_USER_WINDOW) && !BitTest(cmdButton->winGetStyle(), GWS_STATIC_TEXT))
|
||||
return;
|
||||
populateBuildTooltipLayout(NULL, cmdButton);
|
||||
}
|
||||
m_buildToolTipLayout->hide(FALSE);
|
||||
|
||||
if (useAnimation && TheGlobalData->m_animateWindows)
|
||||
{
|
||||
theAnimateWindowManager = NEW AnimateWindowManager;
|
||||
theAnimateWindowManager->reset();
|
||||
theAnimateWindowManager->registerGameWindow( m_buildToolTipLayout->getFirstWindow(), WIN_ANIMATION_SLIDE_RIGHT_FAST, TRUE, 200 );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ControlBar::repopulateBuildTooltipLayout( void )
|
||||
{
|
||||
if(!prevWindow || !m_buildToolTipLayout)
|
||||
return;
|
||||
if(!BitTest(prevWindow->winGetStyle(), GWS_PUSH_BUTTON))
|
||||
return;
|
||||
const CommandButton *commandButton = (const CommandButton *)GadgetButtonGetData(prevWindow);
|
||||
populateBuildTooltipLayout(commandButton);
|
||||
}
|
||||
|
||||
void ControlBar::populateBuildTooltipLayout( const CommandButton *commandButton, GameWindow *tooltipWin)
|
||||
{
|
||||
if(!m_buildToolTipLayout)
|
||||
return;
|
||||
|
||||
Player *player = ThePlayerList->getLocalPlayer();
|
||||
UnicodeString name, cost, descrip;
|
||||
UnicodeString requires = UnicodeString::TheEmptyString, requiresList;
|
||||
Bool firstRequirement = true;
|
||||
const ProductionPrerequisite *prereq;
|
||||
Bool fireScienceButton = false;
|
||||
|
||||
if(commandButton)
|
||||
{
|
||||
const ThingTemplate *thingTemplate = commandButton->getThingTemplate();
|
||||
const UpgradeTemplate *upgradeTemplate = commandButton->getUpgradeTemplate();
|
||||
|
||||
ScienceType st = SCIENCE_INVALID;
|
||||
if(commandButton->getScienceVec().size() > 1)
|
||||
{
|
||||
for(Int j = 0; j < commandButton->getScienceVec().size(); ++j)
|
||||
{
|
||||
st = commandButton->getScienceVec()[ j ];
|
||||
|
||||
if( commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE )
|
||||
{
|
||||
if( !player->hasScience( st ) && j > 0 )
|
||||
{
|
||||
//If we're not looking at a command button that purchases a science, then
|
||||
//it means we are looking at a command button that can USE the science. This
|
||||
//means we want to get the description for the previous science -- the one
|
||||
//we can use, not purchase!
|
||||
st = commandButton->getScienceVec()[ j - 1 ];
|
||||
}
|
||||
|
||||
//Now that we got the science for the button that executes the science, we need
|
||||
//to generate a simpler help text!
|
||||
fireScienceButton = true;
|
||||
|
||||
break;
|
||||
}
|
||||
else if( !player->hasScience( st ) )
|
||||
{
|
||||
//Purchase science case. The first science we run into that we don't have, that's the
|
||||
//one we'll want to show!
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(commandButton->getScienceVec().size() == 1 )
|
||||
{
|
||||
st = commandButton->getScienceVec()[ 0 ];
|
||||
}
|
||||
|
||||
if( commandButton->getDescriptionLabel().isNotEmpty() )
|
||||
{
|
||||
descrip = TheGameText->fetch(commandButton->getDescriptionLabel());
|
||||
|
||||
Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
|
||||
Object *selectedObject = draw ? draw->getObject() : NULL;
|
||||
if( selectedObject )
|
||||
{
|
||||
//Special case: Append status of overcharge on China power plant.
|
||||
if( commandButton->getCommandType() == GUI_COMMAND_TOGGLE_OVERCHARGE )
|
||||
{
|
||||
{
|
||||
OverchargeBehaviorInterface *obi;
|
||||
for( BehaviorModule **bmi = selectedObject->getBehaviorModules(); *bmi; ++bmi )
|
||||
{
|
||||
obi = (*bmi)->getOverchargeBehaviorInterface();
|
||||
if( obi )
|
||||
{
|
||||
descrip.concat( L"\n" );
|
||||
if( obi->isOverchargeActive() )
|
||||
descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipNukeReactorOverChargeIsOn" ) );
|
||||
else
|
||||
descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipNukeReactorOverChargeIsOff" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
} //End overcharge special case
|
||||
|
||||
//Special case: When building units, the CanMakeType determines reasons for not being able to buy stuff.
|
||||
else if( thingTemplate )
|
||||
{
|
||||
CanMakeType makeType = TheBuildAssistant->canMakeUnit( selectedObject, commandButton->getThingTemplate() );
|
||||
switch( makeType )
|
||||
{
|
||||
case CANMAKE_NO_MONEY:
|
||||
descrip.concat( L"\n\n" );
|
||||
descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipNotEnoughMoneyToBuild" ) );
|
||||
break;
|
||||
case CANMAKE_QUEUE_FULL:
|
||||
descrip.concat( L"\n\n" );
|
||||
descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotPurchaseBecauseQueueFull" ) );
|
||||
break;
|
||||
case CANMAKE_PARKING_PLACES_FULL:
|
||||
descrip.concat( L"\n\n" );
|
||||
descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotBuildUnitBecauseParkingFull" ) );
|
||||
break;
|
||||
case CANMAKE_MAXED_OUT_FOR_PLAYER:
|
||||
descrip.concat( L"\n\n" );
|
||||
descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotBuildUnitBecauseMaximumNumber" ) );
|
||||
break;
|
||||
//case CANMAKE_NO_PREREQ:
|
||||
// descrip.concat( L"\n\n" );
|
||||
// descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotBuildDueToPrerequisites" ) );
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
//Special case: When building upgrades
|
||||
else if( upgradeTemplate && !player->hasUpgradeInProduction( upgradeTemplate ) )
|
||||
{
|
||||
if( commandButton->getCommandType() == GUI_COMMAND_PLAYER_UPGRADE ||
|
||||
commandButton->getCommandType() == GUI_COMMAND_OBJECT_UPGRADE )
|
||||
{
|
||||
ProductionUpdateInterface *pui = selectedObject->getProductionUpdateInterface();
|
||||
if( pui && pui->getProductionCount() == MAX_BUILD_QUEUE_BUTTONS )
|
||||
{
|
||||
descrip.concat( L"\n\n" );
|
||||
descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipCannotPurchaseBecauseQueueFull" ) );
|
||||
}
|
||||
else if( !TheUpgradeCenter->canAffordUpgrade( ThePlayerList->getLocalPlayer(), upgradeTemplate, FALSE ) )
|
||||
{
|
||||
descrip.concat( L"\n\n" );
|
||||
descrip.concat( TheGameText->fetch( "TOOLTIP:TooltipNotEnoughMoneyToBuild" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
name = TheGameText->fetch(commandButton->getTextLabel().str());
|
||||
|
||||
if( thingTemplate && commandButton->getCommandType() != GUI_COMMAND_PURCHASE_SCIENCE )
|
||||
{
|
||||
//We are either looking at building a unit or a structure that may or may not have any
|
||||
//prerequisites.
|
||||
|
||||
//Format the cost only when we have to pay for it.
|
||||
cost.format(TheGameText->fetch("TOOLTIP:Cost"), thingTemplate->calcCostToBuild(player));
|
||||
|
||||
// ask each prerequisite to give us a list of the non satisfied prerequisites
|
||||
for( Int i=0; i<thingTemplate->getPrereqCount(); i++ )
|
||||
{
|
||||
prereq = thingTemplate->getNthPrereq(i);
|
||||
requiresList = prereq->getRequiresList(player);
|
||||
|
||||
if( requiresList != UnicodeString::TheEmptyString )
|
||||
{
|
||||
// make sure to put in 'returns' to space things correctly
|
||||
if (firstRequirement)
|
||||
firstRequirement = false;
|
||||
else
|
||||
requires.concat(L", ");
|
||||
}
|
||||
requires.concat(requiresList);
|
||||
}
|
||||
if( !requires.isEmpty() )
|
||||
{
|
||||
UnicodeString requireFormat = TheGameText->fetch("CONTROLBAR:Requirements");
|
||||
requires.format(requireFormat.str(), requires.str());
|
||||
if(!descrip.isEmpty())
|
||||
descrip.concat(L"\n");
|
||||
descrip.concat(requires);
|
||||
|
||||
}
|
||||
}
|
||||
else if( upgradeTemplate )
|
||||
{
|
||||
//We are looking at an upgrade purchase icon. Maybe we already purchased it?
|
||||
|
||||
Bool hasUpgradeAlready = false;
|
||||
Bool hasConflictingUpgrade = false;
|
||||
Bool playerUpgradeButton = commandButton->getCommandType() == GUI_COMMAND_PLAYER_UPGRADE;
|
||||
Bool objectUpgradeButton = commandButton->getCommandType() == GUI_COMMAND_OBJECT_UPGRADE;
|
||||
|
||||
//Check if the local player has the specified upgrade
|
||||
hasUpgradeAlready = player->hasUpgradeComplete( upgradeTemplate );
|
||||
|
||||
if( !hasUpgradeAlready )
|
||||
{
|
||||
//Check if the first selected object has the specified upgrade.
|
||||
Drawable *draw = TheInGameUI->getFirstSelectedDrawable();
|
||||
if( draw )
|
||||
{
|
||||
Object *object = draw->getObject();
|
||||
if( object )
|
||||
{
|
||||
hasUpgradeAlready = object->hasUpgrade( upgradeTemplate );
|
||||
if( objectUpgradeButton )
|
||||
{
|
||||
hasConflictingUpgrade = !object->affectedByUpgrade( upgradeTemplate );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if( hasConflictingUpgrade && !hasUpgradeAlready )
|
||||
{
|
||||
if( commandButton->getConflictingLabel().isNotEmpty() )
|
||||
{
|
||||
descrip = TheGameText->fetch( commandButton->getConflictingLabel() );
|
||||
}
|
||||
else
|
||||
{
|
||||
descrip = TheGameText->fetch( "TOOLTIP:HasConflictingUpgradeDefault" );
|
||||
}
|
||||
}
|
||||
else if( hasUpgradeAlready && ( playerUpgradeButton || objectUpgradeButton ) )
|
||||
{
|
||||
//See if we can fetch the "already upgraded" text for this upgrade. If not.... use the default "fill me in".
|
||||
if( commandButton->getPurchasedLabel().isNotEmpty() )
|
||||
{
|
||||
descrip = TheGameText->fetch( commandButton->getPurchasedLabel() );
|
||||
}
|
||||
else
|
||||
{
|
||||
descrip = TheGameText->fetch( "TOOLTIP:AlreadyUpgradedDefault" );
|
||||
}
|
||||
}
|
||||
else if( !hasUpgradeAlready )
|
||||
{
|
||||
//Determine the cost of the upgrade.
|
||||
cost.format(TheGameText->fetch("TOOLTIP:Cost"),upgradeTemplate->calcCostToBuild(player));
|
||||
}
|
||||
}
|
||||
else if( st != SCIENCE_INVALID && !fireScienceButton )
|
||||
{
|
||||
TheScienceStore->getNameAndDescription(st, name, descrip);
|
||||
cost.format(TheGameText->fetch("TOOLTIP:ScienceCost"),TheScienceStore->getSciencePurchaseCost(st));
|
||||
// ask each prerequisite to give us a list of the non satisfied prerequisites
|
||||
|
||||
if( thingTemplate )
|
||||
{
|
||||
for( Int i=0; i<thingTemplate->getPrereqCount(); i++ )
|
||||
{
|
||||
prereq = thingTemplate->getNthPrereq(i);
|
||||
requiresList = prereq->getRequiresList(player);
|
||||
|
||||
if( requiresList != UnicodeString::TheEmptyString )
|
||||
{
|
||||
// make sure to put in 'returns' to space things correctly
|
||||
if (firstRequirement)
|
||||
firstRequirement = false;
|
||||
else
|
||||
requires.concat(L", ");
|
||||
}
|
||||
requires.concat(requiresList);
|
||||
}
|
||||
if( !requires.isEmpty() )
|
||||
{
|
||||
UnicodeString requireFormat = TheGameText->fetch("CONTROLBAR:Requirements");
|
||||
requires.format(requireFormat.str(), requires.str());
|
||||
if(!descrip.isEmpty())
|
||||
descrip.concat(L"\n");
|
||||
descrip.concat(requires);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if(tooltipWin)
|
||||
{
|
||||
|
||||
if( tooltipWin == TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBar.wnd:MoneyDisplay")))
|
||||
{
|
||||
name = TheGameText->fetch("CONTROLBAR:Money");
|
||||
descrip = TheGameText->fetch("CONTROLBAR:MoneyDescription");
|
||||
}
|
||||
else if(tooltipWin == TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBar.wnd:PowerWindow")) )
|
||||
{
|
||||
name = TheGameText->fetch("CONTROLBAR:Power");
|
||||
descrip = TheGameText->fetch("CONTROLBAR:PowerDescription");
|
||||
|
||||
Player *playerToDisplay = NULL;
|
||||
if(TheControlBar->isObserverControlBarOn())
|
||||
playerToDisplay = TheControlBar->getObserverLookAtPlayer();
|
||||
else
|
||||
playerToDisplay = ThePlayerList->getLocalPlayer();
|
||||
|
||||
if( playerToDisplay && playerToDisplay->getEnergy() )
|
||||
{
|
||||
Energy *energy = playerToDisplay->getEnergy();
|
||||
descrip.format(descrip, energy->getProduction(), energy->getConsumption());
|
||||
}
|
||||
else
|
||||
{
|
||||
descrip.format(descrip, 0, 0);
|
||||
}
|
||||
}
|
||||
else if(tooltipWin == TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBar.wnd:GeneralsExp")) )
|
||||
{
|
||||
name = TheGameText->fetch("CONTROLBAR:GeneralsExp");
|
||||
descrip = TheGameText->fetch("CONTROLBAR:GeneralsExpDescription");
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_ASSERTCRASH(FALSE, ("ControlBar::populateBuildTooltipLayout We attempted to call the popup tooltip on a game window that has yet to be hand coded in as this fuction was/is designed for only buttons but has been hacked to work with GameWindows."));
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
GameWindow *win = TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBarPopupDescription.wnd:StaticTextName"));
|
||||
if(win)
|
||||
{
|
||||
GadgetStaticTextSetText(win, name);
|
||||
}
|
||||
win = TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBarPopupDescription.wnd:StaticTextCost"));
|
||||
if(win)
|
||||
{
|
||||
GadgetStaticTextSetText(win, cost);
|
||||
}
|
||||
win = TheWindowManager->winGetWindowFromId(m_buildToolTipLayout->getFirstWindow(), TheNameKeyGenerator->nameToKey("ControlBarPopupDescription.wnd:StaticTextDescription"));
|
||||
if(win)
|
||||
{
|
||||
|
||||
static NameKeyType winNamekey = TheNameKeyGenerator->nameToKey( AsciiString( "ControlBar.wnd:BackgroundMarker" ) );
|
||||
static ICoord2D lastOffset = { 0, 0 };
|
||||
|
||||
ICoord2D size, newSize, pos;
|
||||
Int diffSize;
|
||||
|
||||
DisplayString *tempDString = TheDisplayStringManager->newDisplayString();
|
||||
win->winGetSize(&size.x, &size.y);
|
||||
tempDString->setFont(win->winGetFont());
|
||||
tempDString->setWordWrap(size.x - 10);
|
||||
tempDString->setText(descrip);
|
||||
tempDString->getSize(&newSize.x, &newSize.y);
|
||||
TheDisplayStringManager->freeDisplayString(tempDString);
|
||||
tempDString = NULL;
|
||||
diffSize = newSize.y - size.y;
|
||||
GameWindow *parent = m_buildToolTipLayout->getFirstWindow();
|
||||
if(!parent)
|
||||
return;
|
||||
|
||||
parent->winGetSize(&size.x, &size.y);
|
||||
if(size.y + diffSize < 102) {
|
||||
diffSize = 102 - size.y;
|
||||
}
|
||||
|
||||
parent->winSetSize(size.x, size.y + diffSize);
|
||||
parent->winGetPosition(&pos.x, &pos.y);
|
||||
// if(size.y + diffSize < 102)
|
||||
// {
|
||||
//
|
||||
// parent->winSetPosition(pos.x, pos.y - (102 - (newSize.y + size.y + diffSize) ));
|
||||
// }
|
||||
// else
|
||||
|
||||
// heightChange = controlBarPos.y - m_defaultControlBarPosition.y;
|
||||
|
||||
GameWindow *marker = TheWindowManager->winGetWindowFromId(NULL,winNamekey);
|
||||
static ICoord2D basePos;
|
||||
if(!marker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
TheControlBar->getBackgroundMarkerPos(&basePos.x, &basePos.y);
|
||||
ICoord2D curPos, offset;
|
||||
marker->winGetScreenPosition(&curPos.x,&curPos.y);
|
||||
|
||||
offset.x = curPos.x - basePos.x;
|
||||
offset.y = curPos.y - basePos.y;
|
||||
|
||||
parent->winSetPosition(pos.x, (pos.y - diffSize) + (offset.y - lastOffset.y));
|
||||
|
||||
lastOffset.x = offset.x;
|
||||
lastOffset.y = offset.y;
|
||||
|
||||
win->winGetSize(&size.x, &size.y);
|
||||
win->winSetSize(size.x, size.y + diffSize);
|
||||
|
||||
GadgetStaticTextSetText(win, descrip);
|
||||
}
|
||||
m_buildToolTipLayout->hide(FALSE);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ControlBar::hideBuildTooltipLayout()
|
||||
{
|
||||
if(theAnimateWindowManager && theAnimateWindowManager->isReversed())
|
||||
return;
|
||||
if(useAnimation && theAnimateWindowManager && TheGlobalData->m_animateWindows)
|
||||
theAnimateWindowManager->reverseAnimateWindow();
|
||||
else
|
||||
deleteBuildTooltipLayout();
|
||||
|
||||
}
|
||||
|
||||
void ControlBar::deleteBuildTooltipLayout( void )
|
||||
{
|
||||
m_showBuildToolTipLayout = FALSE;
|
||||
prevWindow= NULL;
|
||||
m_buildToolTipLayout->hide(TRUE);
|
||||
// if(!m_buildToolTipLayout)
|
||||
// return;
|
||||
//
|
||||
// m_buildToolTipLayout->destroyWindows();
|
||||
// m_buildToolTipLayout->deleteInstance();
|
||||
// m_buildToolTipLayout = NULL;
|
||||
if(theAnimateWindowManager)
|
||||
delete theAnimateWindowManager;
|
||||
theAnimateWindowManager = NULL;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,602 @@
|
||||
/*
|
||||
** 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: Diplomacy.cpp ///////////////////////////////////////////////////////////////////////
|
||||
// Author: Matthew D. Campbell - August 2002
|
||||
// Desc: GUI callbacks for the diplomacy menu
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/MultiplayerSettings.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/PlayerTemplate.h"
|
||||
#include "Common/Recorder.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/Diplomacy.h"
|
||||
#include "GameClient/DisconnectMenu.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetCheckBox.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GadgetRadioButton.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/VictoryConditions.h"
|
||||
#include "GameNetwork/GameInfo.h"
|
||||
#include "GameNetwork/NetworkInterface.h"
|
||||
#include "GameNetwork/GameSpy/BuddyDefs.h"
|
||||
#include "GameNetwork/GameSpy/peerDefs.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
static NameKeyType staticTextPlayerID[MAX_SLOTS];
|
||||
static NameKeyType staticTextSideID[MAX_SLOTS];
|
||||
static NameKeyType staticTextTeamID[MAX_SLOTS];
|
||||
static NameKeyType staticTextStatusID[MAX_SLOTS];
|
||||
static NameKeyType buttonMuteID[MAX_SLOTS];
|
||||
static NameKeyType buttonUnMuteID[MAX_SLOTS];
|
||||
static NameKeyType radioButtonInGameID = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonBuddiesID = NAMEKEY_INVALID;
|
||||
static GameWindow *radioButtonInGame = NULL;
|
||||
static GameWindow *radioButtonBuddies = NULL;
|
||||
static NameKeyType winInGameID = NAMEKEY_INVALID;
|
||||
static NameKeyType winBuddiesID = NAMEKEY_INVALID;
|
||||
static NameKeyType winSoloID = NAMEKEY_INVALID;
|
||||
static GameWindow *winInGame = NULL;
|
||||
static GameWindow *winBuddies = NULL;
|
||||
static GameWindow *winSolo = NULL;
|
||||
static GameWindow *staticTextPlayer[MAX_SLOTS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
static GameWindow *staticTextSide[MAX_SLOTS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
static GameWindow *staticTextTeam[MAX_SLOTS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
static GameWindow *staticTextStatus[MAX_SLOTS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
static GameWindow *buttonMute[MAX_SLOTS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
static GameWindow *buttonUnMute[MAX_SLOTS] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
static Int slotNumInRow[MAX_SLOTS];
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
static WindowLayout *theLayout = NULL;
|
||||
static GameWindow *theWindow = NULL;
|
||||
static AnimateWindowManager *theAnimateWindowManager = NULL;
|
||||
WindowMsgHandledType BuddyControlSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2);
|
||||
void InitBuddyControls(Int type);
|
||||
void updateBuddyInfo( void );
|
||||
static void grabWindowPointers( void )
|
||||
{
|
||||
for (Int i=0; i<MAX_SLOTS; ++i)
|
||||
{
|
||||
AsciiString temp;
|
||||
temp.format("Diplomacy.wnd:StaticTextPlayer%d", i);
|
||||
staticTextPlayerID[i] = NAMEKEY(temp);
|
||||
temp.format("Diplomacy.wnd:StaticTextSide%d", i);
|
||||
staticTextSideID[i] = NAMEKEY(temp);
|
||||
temp.format("Diplomacy.wnd:StaticTextTeam%d", i);
|
||||
staticTextTeamID[i] = NAMEKEY(temp);
|
||||
temp.format("Diplomacy.wnd:StaticTextStatus%d", i);
|
||||
staticTextStatusID[i] = NAMEKEY(temp);
|
||||
temp.format("Diplomacy.wnd:ButtonMute%d", i);
|
||||
buttonMuteID[i] = NAMEKEY(temp);
|
||||
temp.format("Diplomacy.wnd:ButtonUnMute%d", i);
|
||||
buttonUnMuteID[i] = NAMEKEY(temp);
|
||||
|
||||
staticTextPlayer[i] = TheWindowManager->winGetWindowFromId(theWindow, staticTextPlayerID[i]);
|
||||
staticTextSide[i] = TheWindowManager->winGetWindowFromId(theWindow, staticTextSideID[i]);
|
||||
staticTextTeam[i] = TheWindowManager->winGetWindowFromId(theWindow, staticTextTeamID[i]);
|
||||
staticTextStatus[i] = TheWindowManager->winGetWindowFromId(theWindow, staticTextStatusID[i]);
|
||||
buttonMute[i] = TheWindowManager->winGetWindowFromId(theWindow, buttonMuteID[i]);
|
||||
buttonUnMute[i] = TheWindowManager->winGetWindowFromId(theWindow, buttonUnMuteID[i]);
|
||||
|
||||
slotNumInRow[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void releaseWindowPointers( void )
|
||||
{
|
||||
for (Int i=0; i<MAX_SLOTS; ++i)
|
||||
{
|
||||
staticTextPlayer[i] = NULL;
|
||||
staticTextSide[i] = NULL;
|
||||
staticTextTeam[i] = NULL;
|
||||
staticTextStatus[i] = NULL;
|
||||
buttonMute[i] = NULL;
|
||||
buttonUnMute[i] = NULL;
|
||||
|
||||
slotNumInRow[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
static void updateFunc( WindowLayout *layout, void *param )
|
||||
{
|
||||
if (theAnimateWindowManager && TheGlobalData->m_animateWindows)
|
||||
{
|
||||
Bool wasFinished = theAnimateWindowManager->isFinished();
|
||||
theAnimateWindowManager->update();
|
||||
if (theAnimateWindowManager->isFinished() && !wasFinished && theAnimateWindowManager->isReversed())
|
||||
theWindow->winHide( TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static BriefingList theBriefingList;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
BriefingList* GetBriefingTextList(void)
|
||||
{
|
||||
return &theBriefingList;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void UpdateDiplomacyBriefingText(AsciiString newText, Bool clear)
|
||||
{
|
||||
GameWindow *listboxSolo = TheWindowManager->winGetWindowFromId(theWindow, NAMEKEY("Diplomacy.wnd:ListboxSolo"));
|
||||
|
||||
if (clear)
|
||||
{
|
||||
theBriefingList.clear();
|
||||
if (listboxSolo)
|
||||
GadgetListBoxReset(listboxSolo);
|
||||
}
|
||||
|
||||
if (newText.isEmpty())
|
||||
return;
|
||||
|
||||
if (std::find(theBriefingList.begin(), theBriefingList.end(), newText) != theBriefingList.end())
|
||||
return;
|
||||
|
||||
theBriefingList.push_back(newText);
|
||||
if (!listboxSolo)
|
||||
return;
|
||||
|
||||
UnicodeString translated = TheGameText->fetch(newText);
|
||||
|
||||
Int numEntries = GadgetListBoxGetNumEntries(listboxSolo);
|
||||
GadgetListBoxAddEntryText(listboxSolo, translated, TheInGameUI->getMessageColor(numEntries%2), -1);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ShowDiplomacy( Bool immediate )
|
||||
{
|
||||
if (!TheInGameUI->getInputEnabled() || TheGameLogic->isIntroMoviePlaying() ||
|
||||
TheGameLogic->isLoadingGame())
|
||||
return;
|
||||
|
||||
|
||||
if (TheInGameUI->isQuitMenuVisible())
|
||||
return;
|
||||
|
||||
if (TheDisconnectMenu && TheDisconnectMenu->isScreenVisible())
|
||||
return;
|
||||
|
||||
if (theWindow)
|
||||
{
|
||||
theWindow->winHide(FALSE);
|
||||
theWindow->winEnable(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
theLayout = TheWindowManager->winCreateLayout( "Diplomacy.wnd" );
|
||||
theWindow = theLayout->getFirstWindow();
|
||||
theLayout->setUpdate(updateFunc);
|
||||
theAnimateWindowManager = NEW AnimateWindowManager;
|
||||
radioButtonInGameID = TheNameKeyGenerator->nameToKey("Diplomacy.wnd:RadioButtonInGame");
|
||||
radioButtonBuddiesID = TheNameKeyGenerator->nameToKey("Diplomacy.wnd:RadioButtonBuddies");
|
||||
radioButtonInGame = TheWindowManager->winGetWindowFromId(NULL, radioButtonInGameID);
|
||||
radioButtonBuddies = TheWindowManager->winGetWindowFromId(NULL, radioButtonBuddiesID);
|
||||
winInGameID = TheNameKeyGenerator->nameToKey("Diplomacy.wnd:InGameParent");
|
||||
winBuddiesID = TheNameKeyGenerator->nameToKey("Diplomacy.wnd:BuddiesParent");
|
||||
winSoloID = TheNameKeyGenerator->nameToKey("Diplomacy.wnd:SoloParent");
|
||||
winInGame = TheWindowManager->winGetWindowFromId(NULL, winInGameID);
|
||||
winBuddies = TheWindowManager->winGetWindowFromId(NULL, winBuddiesID);
|
||||
winSolo = TheWindowManager->winGetWindowFromId(NULL, winSoloID);
|
||||
|
||||
if (!TheRecorder->isMultiplayer())
|
||||
{
|
||||
GameWindow *listboxSolo = TheWindowManager->winGetWindowFromId(theWindow, NAMEKEY("Diplomacy.wnd:ListboxSolo"));
|
||||
if (listboxSolo)
|
||||
{
|
||||
for (BriefingList::iterator it = theBriefingList.begin(); it != theBriefingList.end(); ++it)
|
||||
{
|
||||
UnicodeString translated = TheGameText->fetch(*it);
|
||||
Int numEntries = GadgetListBoxGetNumEntries(listboxSolo);
|
||||
GadgetListBoxAddEntryText(listboxSolo, translated, TheInGameUI->getMessageColor(numEntries%2), -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
theLayout->hide(FALSE);
|
||||
|
||||
radioButtonInGame->winHide(TRUE);
|
||||
radioButtonBuddies->winHide(TRUE);
|
||||
GadgetRadioSetSelection(radioButtonInGame, FALSE);
|
||||
if (TheRecorder->isMultiplayer())
|
||||
{
|
||||
winInGame->winHide(FALSE);
|
||||
winBuddies->winHide(TRUE);
|
||||
winSolo->winHide(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
winInGame->winHide(TRUE);
|
||||
winBuddies->winHide(TRUE);
|
||||
winSolo->winHide(FALSE);
|
||||
}
|
||||
|
||||
theAnimateWindowManager->reset();
|
||||
if (!immediate && TheGlobalData->m_animateWindows)
|
||||
theAnimateWindowManager->registerGameWindow( theWindow, WIN_ANIMATION_SLIDE_TOP, TRUE, 200 );
|
||||
|
||||
TheInGameUI->registerWindowLayout(theLayout);
|
||||
grabWindowPointers();
|
||||
PopulateInGameDiplomacyPopup();
|
||||
|
||||
if(TheGameSpyInfo && TheGameSpyInfo->getLocalProfileID() != 0)
|
||||
{
|
||||
radioButtonInGame->winHide(FALSE);
|
||||
radioButtonBuddies->winHide(FALSE);
|
||||
InitBuddyControls(1);
|
||||
PopulateOldBuddyMessages();
|
||||
updateBuddyInfo();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ResetDiplomacy( void )
|
||||
{
|
||||
if(theLayout)
|
||||
{
|
||||
TheInGameUI->unregisterWindowLayout(theLayout);
|
||||
theLayout->destroyWindows();
|
||||
theLayout->deleteInstance();
|
||||
InitBuddyControls(-1);
|
||||
}
|
||||
theLayout = NULL;
|
||||
theWindow = NULL;
|
||||
if (theAnimateWindowManager)
|
||||
delete theAnimateWindowManager;
|
||||
theAnimateWindowManager = NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void HideDiplomacy( Bool immediate )
|
||||
{
|
||||
releaseWindowPointers();
|
||||
if (theWindow)
|
||||
{
|
||||
if (immediate || !TheGlobalData->m_animateWindows)
|
||||
{
|
||||
theWindow->winHide(TRUE);
|
||||
theWindow->winEnable(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (theAnimateWindowManager->isFinished())
|
||||
theAnimateWindowManager->reverseAnimateWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ToggleDiplomacy( Bool immediate )
|
||||
{
|
||||
// If we bring this up, let's hide the quit menu
|
||||
HideQuitMenu();
|
||||
|
||||
if (theWindow)
|
||||
{
|
||||
Bool show = theWindow->winIsHidden();
|
||||
if (show)
|
||||
ShowDiplomacy( immediate );
|
||||
else
|
||||
HideDiplomacy( immediate );
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowDiplomacy( immediate );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType DiplomacyInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
// UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
HideDiplomacy();
|
||||
return MSG_HANDLED;
|
||||
//return MSG_IGNORED;
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end char
|
||||
|
||||
}
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end DiplomacyInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType DiplomacySystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
if(BuddyControlSystem(window, msg, mData1, mData2) == MSG_HANDLED)
|
||||
{
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
switch( msg )
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GGM_FOCUS_CHANGE:
|
||||
{
|
||||
// Bool focus = (Bool) mData1;
|
||||
//if (focus)
|
||||
//TheWindowManager->winSetGrabWindow( chatTextEntry );
|
||||
break;
|
||||
} // end focus change
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're given the opportunity to take the keyboard focus we must say we don't want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = FALSE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
NameKeyType controlID = (NameKeyType)control->winGetWindowId();
|
||||
static NameKeyType buttonHideID = NAMEKEY( "Diplomacy.wnd:ButtonHide" );
|
||||
if (controlID == buttonHideID)
|
||||
{
|
||||
HideDiplomacy( FALSE );
|
||||
}
|
||||
else if( controlID == radioButtonInGameID)
|
||||
{
|
||||
winInGame->winHide(FALSE);
|
||||
winBuddies->winHide(TRUE);
|
||||
}
|
||||
else if( controlID == radioButtonBuddiesID)
|
||||
{
|
||||
winInGame->winHide(TRUE);
|
||||
winBuddies->winHide(FALSE);
|
||||
}
|
||||
|
||||
for (Int i=0; i<MAX_SLOTS; ++i)
|
||||
{
|
||||
if (controlID == buttonMuteID[i] && slotNumInRow[i] >= 0)
|
||||
{
|
||||
TheGameInfo->getSlot(slotNumInRow[i])->mute(TRUE);
|
||||
PopulateInGameDiplomacyPopup();
|
||||
break;
|
||||
}
|
||||
if (controlID == buttonUnMuteID[i] && slotNumInRow[i] >= 0)
|
||||
{
|
||||
TheGameInfo->getSlot(slotNumInRow[i])->mute(FALSE);
|
||||
PopulateInGameDiplomacyPopup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
} // end button selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end DiplomacySystem
|
||||
|
||||
void PopulateInGameDiplomacyPopup( void )
|
||||
{
|
||||
if (!TheGameInfo)
|
||||
return;
|
||||
|
||||
Int rowNum = 0;
|
||||
for (Int slotNum=0; slotNum<MAX_SLOTS; ++slotNum)
|
||||
{
|
||||
const GameSlot *slot = TheGameInfo->getConstSlot(slotNum);
|
||||
if (slot && slot->isOccupied())
|
||||
{
|
||||
Bool isInGame = false;
|
||||
// Note - for skirmish, TheNetwork == NULL. jba.
|
||||
if (TheNetwork && TheNetwork->isPlayerConnected(slotNum)) {
|
||||
isInGame = true;
|
||||
} else if ((TheNetwork == NULL) && slot->isHuman()) {
|
||||
// this is a skirmish game and it is the human player.
|
||||
isInGame = true;
|
||||
}
|
||||
if (slot->isAI())
|
||||
isInGame = true;
|
||||
AsciiString playerName;
|
||||
playerName.format("player%d", slotNum);
|
||||
Player *player = ThePlayerList->findPlayerWithNameKey(NAMEKEY(playerName));
|
||||
Bool isAlive = !TheVictoryConditions->hasSinglePlayerBeenDefeated(player);
|
||||
Bool isObserver = player->isPlayerObserver();
|
||||
|
||||
if (slot->isHuman() && TheGameInfo->getLocalSlotNum() != slotNum && isInGame)
|
||||
{
|
||||
// show mute button
|
||||
if (buttonMute[rowNum])
|
||||
{
|
||||
buttonMute[rowNum]->winHide(slot->isMuted());
|
||||
}
|
||||
if (buttonUnMute[rowNum])
|
||||
{
|
||||
buttonUnMute[rowNum]->winHide(!slot->isMuted());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// can't mute self, AI players, or MIA humans
|
||||
if (buttonMute[rowNum])
|
||||
buttonMute[rowNum]->winHide(TRUE);
|
||||
if (buttonUnMute[rowNum])
|
||||
buttonUnMute[rowNum]->winHide(TRUE);
|
||||
}
|
||||
|
||||
Color playerColor = TheMultiplayerSettings->getColor(slot->getApparentColor())->getColor();
|
||||
Color backColor = GameMakeColor(0, 0, 0, 255);
|
||||
Color aliveColor = GameMakeColor(0, 255, 0, 255);
|
||||
Color deadColor = GameMakeColor(255, 0, 0, 255);
|
||||
Color observerInGameColor = GameMakeColor(255, 255, 255, 255);
|
||||
Color goneColor = GameMakeColor(196, 0, 0, 255);
|
||||
Color observerGoneColor = GameMakeColor(196, 196, 196, 255);
|
||||
|
||||
if (staticTextPlayer[rowNum])
|
||||
{
|
||||
staticTextPlayer[rowNum]->winSetEnabledTextColors( playerColor, backColor );
|
||||
GadgetStaticTextSetText(staticTextPlayer[rowNum], slot->getName());
|
||||
}
|
||||
if (staticTextSide[rowNum])
|
||||
{
|
||||
staticTextSide[rowNum]->winSetEnabledTextColors( playerColor, backColor );
|
||||
GadgetStaticTextSetText(staticTextSide[rowNum], slot->getApparentPlayerTemplateDisplayName() );
|
||||
}
|
||||
if (staticTextTeam[rowNum])
|
||||
{
|
||||
staticTextTeam[rowNum]->winSetEnabledTextColors( playerColor, backColor );
|
||||
AsciiString teamStr;
|
||||
teamStr.format("Team:%d", slot->getTeamNumber() + 1);
|
||||
if (slot->isAI() && slot->getTeamNumber() == -1)
|
||||
teamStr = "Team:AI";
|
||||
GadgetStaticTextSetText(staticTextTeam[rowNum], TheGameText->fetch(teamStr) );
|
||||
}
|
||||
if (staticTextStatus[rowNum])
|
||||
{
|
||||
staticTextStatus[rowNum]->winHide(FALSE);
|
||||
if (isInGame)
|
||||
{
|
||||
if (isAlive)
|
||||
{
|
||||
staticTextStatus[rowNum]->winSetEnabledTextColors( aliveColor, backColor );
|
||||
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerAlive"));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isObserver)
|
||||
{
|
||||
staticTextStatus[rowNum]->winSetEnabledTextColors( observerInGameColor, backColor );
|
||||
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerObserver"));
|
||||
}
|
||||
else
|
||||
{
|
||||
staticTextStatus[rowNum]->winSetEnabledTextColors( deadColor, backColor );
|
||||
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerDead"));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not in game
|
||||
if (isObserver)
|
||||
{
|
||||
staticTextStatus[rowNum]->winSetEnabledTextColors( observerGoneColor, backColor );
|
||||
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerObserverGone"));
|
||||
}
|
||||
else
|
||||
{
|
||||
staticTextStatus[rowNum]->winSetEnabledTextColors( goneColor, backColor );
|
||||
GadgetStaticTextSetText(staticTextStatus[rowNum], TheGameText->fetch("GUI:PlayerGone"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
slotNumInRow[rowNum++] = slotNum;
|
||||
}
|
||||
}
|
||||
|
||||
while (rowNum < MAX_SLOTS)
|
||||
{
|
||||
slotNumInRow[rowNum] = -1;
|
||||
if (staticTextPlayer[rowNum])
|
||||
staticTextPlayer[rowNum]->winHide(TRUE);
|
||||
if (staticTextSide[rowNum])
|
||||
staticTextSide[rowNum]->winHide(TRUE);
|
||||
if (staticTextTeam[rowNum])
|
||||
staticTextTeam[rowNum]->winHide(TRUE);
|
||||
if (staticTextStatus[rowNum])
|
||||
staticTextStatus[rowNum]->winHide(TRUE);
|
||||
if (buttonMute[rowNum])
|
||||
buttonMute[rowNum]->winHide(TRUE);
|
||||
if (buttonUnMute[rowNum])
|
||||
buttonUnMute[rowNum]->winHide(TRUE);
|
||||
|
||||
++rowNum;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
** 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: ExtendedMessageBox.cpp ///////////////////////////////////////////////////////////////////
|
||||
// Author: Matt Campbell, January 2003
|
||||
// Description: We go quiet in 1 day, gold in 15. Poor time to rewrite message boxes, so
|
||||
// we get this file instead. Phooey.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/ExtendedMessageBox.h"
|
||||
|
||||
WindowMsgHandledType ExtendedMessageBoxSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 );
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Create an extended Modal Message Box */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static GameWindow *gogoExMessageBox(Int x, Int y, Int width, Int height, UnsignedShort buttonFlags,
|
||||
UnicodeString titleString, UnicodeString bodyString, void *userData,
|
||||
MessageBoxFunc yesCallback,
|
||||
MessageBoxFunc noCallback,
|
||||
MessageBoxFunc okCallback,
|
||||
MessageBoxFunc cancelCallback )
|
||||
{
|
||||
// first check to make sure we have some buttons to display
|
||||
if(buttonFlags == 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GameWindow *parent = TheWindowManager->winCreateFromScript( AsciiString("Menus/MessageBox.wnd") );
|
||||
TheWindowManager->winSetModal( parent );
|
||||
TheWindowManager->winSetFocus( NULL ); // make sure we lose focus from other windows even if we refuse focus ourselves
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
|
||||
// If the user wants the size to be different then the default
|
||||
float ratioX, ratioY = 1;
|
||||
|
||||
if( width > 0 && height > 0 )
|
||||
{
|
||||
ICoord2D temp;
|
||||
//First grab the percent increase/decrease compaired to the default size
|
||||
parent->winGetSize( &temp.x, &temp.y);
|
||||
ratioX = (float)width / (float)temp.x;
|
||||
ratioY = (float)height / (float)temp.y;
|
||||
//Set the window's new size
|
||||
parent->winSetSize( width, height);
|
||||
|
||||
//Resize/reposition all the children windows based off the ratio
|
||||
GameWindow *child;
|
||||
for( child = parent->winGetChild(); child; child = child->winGetNext() )
|
||||
{
|
||||
child->winGetSize(&temp.x, &temp.y);
|
||||
temp.x =Int(temp.x * ratioX);
|
||||
temp.y =Int(temp.y * ratioY);
|
||||
child->winSetSize(temp.x, temp.y);
|
||||
|
||||
child->winGetPosition(&temp.x, &temp.y);
|
||||
temp.x =Int(temp.x * ratioX);
|
||||
temp.y =Int(temp.y * ratioY);
|
||||
child->winSetPosition(temp.x, temp.y);
|
||||
}
|
||||
}
|
||||
|
||||
// If the user wants to position the message box somewhere other then default
|
||||
if( x >= 0 && y >= 0)
|
||||
parent->winSetPosition(x, y);
|
||||
|
||||
// Reposition the buttons
|
||||
Int buttonX[3], buttonY[3];
|
||||
|
||||
//In the layout, buttonOk will be in the first button position
|
||||
NameKeyType buttonOkID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonOk" ) );
|
||||
GameWindow *buttonOk = TheWindowManager->winGetWindowFromId(parent, buttonOkID);
|
||||
buttonOk->winGetPosition(&buttonX[0], &buttonY[0]);
|
||||
|
||||
NameKeyType buttonYesID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonYes" ) );
|
||||
GameWindow *buttonYes = TheWindowManager->winGetWindowFromId(parent, buttonYesID);
|
||||
//buttonNo in the second position
|
||||
NameKeyType buttonNoID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonNo" ) );
|
||||
GameWindow *buttonNo = TheWindowManager->winGetWindowFromId(parent, buttonNoID);
|
||||
buttonNo->winGetPosition(&buttonX[1], &buttonY[1]);
|
||||
|
||||
//and buttonCancel in the third
|
||||
NameKeyType buttonCancelID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonCancel" ) );
|
||||
GameWindow *buttonCancel = TheWindowManager->winGetWindowFromId(parent, buttonCancelID);
|
||||
buttonCancel->winGetPosition(&buttonX[2], &buttonY[2]);
|
||||
|
||||
//we shouldn't have button OK and Yes on the same dialog
|
||||
if((buttonFlags & (MSG_BOX_OK | MSG_BOX_YES)) == (MSG_BOX_OK | MSG_BOX_YES) )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(false, ("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No."));
|
||||
}
|
||||
|
||||
//Position the OK button if we have one
|
||||
if( (buttonFlags & MSG_BOX_OK) == MSG_BOX_OK)
|
||||
{
|
||||
buttonOk->winSetPosition(buttonX[0], buttonY[0]);
|
||||
buttonOk->winHide(FALSE);
|
||||
}
|
||||
else if( (buttonFlags & MSG_BOX_YES) == MSG_BOX_YES)
|
||||
{
|
||||
//Position the Yes if we have one
|
||||
buttonYes->winSetPosition(buttonX[0], buttonY[0]);
|
||||
buttonYes->winHide(FALSE);
|
||||
}
|
||||
|
||||
if((buttonFlags & (MSG_BOX_NO | MSG_BOX_CANCEL)) == (MSG_BOX_NO | MSG_BOX_CANCEL) )
|
||||
{
|
||||
//If we have both the No and Cancel button, then the no should go in the middle position
|
||||
buttonNo->winSetPosition(buttonX[1], buttonY[1]);
|
||||
buttonCancel->winSetPosition(buttonX[2], buttonY[2]);
|
||||
buttonNo->winHide(FALSE);
|
||||
buttonCancel->winHide(FALSE);
|
||||
}
|
||||
else if( (buttonFlags & MSG_BOX_NO) == MSG_BOX_NO)
|
||||
{
|
||||
//if we just have the no button, then position it in the right most spot
|
||||
buttonNo->winSetPosition(buttonX[2], buttonY[2]);
|
||||
buttonNo->winHide(FALSE);
|
||||
}
|
||||
else if( (buttonFlags & MSG_BOX_CANCEL) == MSG_BOX_CANCEL)
|
||||
{
|
||||
//else if we just have the Cancel button, well, it should always go in the right spot
|
||||
buttonCancel->winSetPosition(buttonX[2], buttonY[2]);
|
||||
buttonCancel->winHide(FALSE);
|
||||
}
|
||||
|
||||
// Fill the text into the text boxes
|
||||
NameKeyType staticTextTitleID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:StaticTextTitle" ) );
|
||||
GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId(parent, staticTextTitleID);
|
||||
GadgetStaticTextSetText(staticTextTitle,titleString);
|
||||
|
||||
NameKeyType staticTextMessageID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:StaticTextMessage" ) );
|
||||
GameWindow *staticTextMessage = TheWindowManager->winGetWindowFromId(parent, staticTextMessageID);
|
||||
GadgetStaticTextSetText(staticTextMessage,bodyString);
|
||||
|
||||
// create a structure that will pass the functions to
|
||||
WindowExMessageBoxData *MsgBoxCallbacks = NEW WindowExMessageBoxData;
|
||||
MsgBoxCallbacks->cancelCallback = cancelCallback;
|
||||
MsgBoxCallbacks->noCallback = noCallback;
|
||||
MsgBoxCallbacks->okCallback = okCallback;
|
||||
MsgBoxCallbacks->yesCallback = yesCallback;
|
||||
MsgBoxCallbacks->userData = userData;
|
||||
//pass the structure to the dialog
|
||||
parent->winSetUserData( MsgBoxCallbacks );
|
||||
|
||||
parent->winSetSystemFunc(ExtendedMessageBoxSystem);
|
||||
|
||||
//make sure the dialog is showing and bring it to the top
|
||||
parent->winHide(FALSE);
|
||||
parent->winBringToTop();
|
||||
|
||||
return parent;
|
||||
}// gogoExMessageBox
|
||||
|
||||
GameWindow *ExMessageBoxYesNo (UnicodeString titleString,UnicodeString bodyString, void *userData,
|
||||
MessageBoxFunc yesCallback, MessageBoxFunc noCallback)
|
||||
{
|
||||
return gogoExMessageBox(-1,-1,-1,-1,MSG_BOX_NO | MSG_BOX_YES , titleString, bodyString, userData, yesCallback, noCallback, NULL, NULL);
|
||||
}
|
||||
|
||||
GameWindow *ExMessageBoxYesNoCancel (UnicodeString titleString,UnicodeString bodyString, void *userData,
|
||||
MessageBoxFunc yesCallback, MessageBoxFunc noCallback, MessageBoxFunc cancelCallback)
|
||||
{
|
||||
return gogoExMessageBox(-1,-1,-1,-1,MSG_BOX_NO | MSG_BOX_YES | MSG_BOX_CANCEL , titleString, bodyString, userData, yesCallback, noCallback, NULL, cancelCallback);
|
||||
}
|
||||
|
||||
GameWindow *ExMessageBoxOkCancel (UnicodeString titleString,UnicodeString bodyString, void *userData,
|
||||
MessageBoxFunc okCallback, MessageBoxFunc cancelCallback)
|
||||
{
|
||||
return gogoExMessageBox(-1,-1,-1,-1,MSG_BOX_OK | MSG_BOX_CANCEL , titleString, bodyString, userData, NULL, NULL, okCallback, cancelCallback);
|
||||
}
|
||||
|
||||
GameWindow *ExMessageBoxOk (UnicodeString titleString,UnicodeString bodyString, void *userData,
|
||||
MessageBoxFunc okCallback)
|
||||
{
|
||||
return gogoExMessageBox(-1,-1,-1,-1,MSG_BOX_OK, titleString, bodyString, userData, NULL, NULL, okCallback, NULL);
|
||||
}
|
||||
|
||||
GameWindow *ExMessageBoxCancel (UnicodeString titleString,UnicodeString bodyString, void *userData,
|
||||
MessageBoxFunc cancelCallback)
|
||||
{
|
||||
return gogoExMessageBox(-1,-1,-1,-1, MSG_BOX_CANCEL, titleString, bodyString, userData, NULL, NULL, NULL, cancelCallback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Message Box window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType ExtendedMessageBoxSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
delete (WindowExMessageBoxData *)window->winGetUserData();
|
||||
window->winSetUserData( NULL );
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
static NameKeyType buttonOkID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonOk" ) );
|
||||
static NameKeyType buttonYesID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonYes" ) );
|
||||
static NameKeyType buttonNoID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonNo" ) );
|
||||
static NameKeyType buttonCancelID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonCancel" ) );
|
||||
WindowExMessageBoxData *MsgBoxCallbacks = (WindowExMessageBoxData *)window->winGetUserData();
|
||||
|
||||
MessageBoxReturnType ret = MB_RETURN_CLOSE;
|
||||
|
||||
if( controlID == buttonOkID )
|
||||
{
|
||||
if (MsgBoxCallbacks->okCallback)
|
||||
ret = MsgBoxCallbacks->okCallback(MsgBoxCallbacks->userData);
|
||||
} // end if
|
||||
else if( controlID == buttonYesID )
|
||||
{
|
||||
if (MsgBoxCallbacks->yesCallback)
|
||||
ret = MsgBoxCallbacks->yesCallback(MsgBoxCallbacks->userData);
|
||||
} // end else if
|
||||
else if( controlID == buttonNoID )
|
||||
{
|
||||
if (MsgBoxCallbacks->noCallback)
|
||||
ret = MsgBoxCallbacks->noCallback(MsgBoxCallbacks->userData);
|
||||
} // end else if
|
||||
else if( controlID == buttonCancelID )
|
||||
{
|
||||
if (MsgBoxCallbacks->cancelCallback)
|
||||
ret = MsgBoxCallbacks->cancelCallback(MsgBoxCallbacks->userData);
|
||||
} // end else if
|
||||
|
||||
if (ret == MB_RETURN_CLOSE)
|
||||
TheWindowManager->winDestroy(window);
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end ExtendedMessageBoxSystem
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
** 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: GeneralsExpPoints.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Oct 2002
|
||||
//
|
||||
// Filename: GeneralsExpPoints.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: File used to populate/update/show/hide the generals exp screen
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType GeneralsExpPointsInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_MOUSE_ENTERING:
|
||||
//Get rid of any building placement mode!
|
||||
if( TheInGameUI )
|
||||
{
|
||||
TheInGameUI->placeBuildAvailable( NULL, NULL );
|
||||
}
|
||||
break;
|
||||
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
// UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
TheControlBar->hidePurchaseScience();
|
||||
return MSG_HANDLED;
|
||||
//return MSG_IGNORED;
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end char
|
||||
|
||||
}
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end DiplomacyInput
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
WindowMsgHandledType GeneralsExpPointsSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GGM_FOCUS_CHANGE:
|
||||
{
|
||||
// Bool focus = (Bool) mData1;
|
||||
//if (focus)
|
||||
//TheWindowManager->winSetGrabWindow( chatTextEntry );
|
||||
break;
|
||||
} // end focus change
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're given the opportunity to take the keyboard focus we must say we don't want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = FALSE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
NameKeyType controlID = (NameKeyType)control->winGetWindowId();
|
||||
static NameKeyType buttonExitID = NAMEKEY( "GeneralsExpPoints.wnd:ButtonExit" );
|
||||
if (controlID == buttonExitID)
|
||||
{
|
||||
TheControlBar->hidePurchaseScience();
|
||||
}
|
||||
else
|
||||
TheControlBar->processContextSensitiveButtonClick( control, (GadgetGameMessage)msg );
|
||||
break;
|
||||
|
||||
} // end button selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GeneralsExpPointsSystem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
** 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: IMECandidate.cpp /////////////////////////////////////////////////////////////////////////
|
||||
// Author: TR November 2001
|
||||
// Desc: IME Candidate window callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/IMEManager.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/DisplayString.h"
|
||||
#include "GameClient/DisplayStringManager.h"
|
||||
|
||||
|
||||
Int IMECandidateWindowLineSpacing = 2;
|
||||
|
||||
static DisplayString *Dstring = NULL;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Input procedure for the candidate window */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType IMECandidateWindowInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end IMECandidateInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** System callback for the IME Candidate widnow */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType IMECandidateWindowSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
case GWM_CREATE:
|
||||
if ( Dstring == NULL )
|
||||
{
|
||||
Dstring = TheDisplayStringManager->newDisplayString();
|
||||
}
|
||||
break;
|
||||
|
||||
case GWM_DESTROY:
|
||||
|
||||
if ( Dstring != NULL )
|
||||
{
|
||||
TheDisplayStringManager->freeDisplayString( Dstring );
|
||||
Dstring = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end IMECandidateWidnowSystem
|
||||
|
||||
// IMECandidateDraw ================================================================
|
||||
/** Draw function for the IME candidate window */
|
||||
//=============================================================================
|
||||
void IMECandidateTextAreaDraw( GameWindow *window, WinInstanceData *instData )
|
||||
{
|
||||
// set up for rendering
|
||||
ICoord2D origin, size, start, end;
|
||||
Color textColor,
|
||||
textBorder,
|
||||
textSelectColor,
|
||||
textSelectBorder;
|
||||
IRegion2D textRegion;
|
||||
Color black = GameMakeColor( 0, 0, 0, 255);
|
||||
|
||||
// get window position and size
|
||||
window->winGetScreenPosition( &origin.x, &origin.y );
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
|
||||
// get a nice region from the positions
|
||||
textRegion.lo.x = origin.x;
|
||||
textRegion.lo.y = origin.y;
|
||||
textRegion.hi.x = origin.x + size.x;
|
||||
textRegion.hi.y = origin.y + size.y;
|
||||
|
||||
// get the right colors for drawing
|
||||
if( BitTest( window->winGetStatus(), WIN_STATUS_ENABLED ) == FALSE )
|
||||
{
|
||||
|
||||
textSelectColor = window->winGetDisabledTextColor();
|
||||
textSelectBorder = window->winGetDisabledTextBorderColor();
|
||||
textColor = window->winGetDisabledTextColor();
|
||||
textBorder = window->winGetDisabledTextBorderColor();
|
||||
|
||||
} // end if, disabled
|
||||
else if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
|
||||
{
|
||||
|
||||
textColor = window->winGetEnabledTextColor();
|
||||
textBorder = window->winGetEnabledTextBorderColor();
|
||||
textSelectColor = window->winGetHiliteTextColor();
|
||||
textSelectBorder = window->winGetHiliteTextBorderColor();
|
||||
|
||||
} // end else if, hilited
|
||||
else
|
||||
{
|
||||
|
||||
textSelectColor = window->winGetHiliteTextColor();
|
||||
textSelectBorder = window->winGetHiliteTextBorderColor();
|
||||
textColor = window->winGetEnabledTextColor();
|
||||
textBorder = window->winGetEnabledTextBorderColor();
|
||||
|
||||
} // end else, just enabled
|
||||
|
||||
|
||||
{
|
||||
Real borderWidth = 1.0f;
|
||||
|
||||
start.x = origin.x;
|
||||
start.y = origin.y;
|
||||
end.x = start.x + size.x;
|
||||
end.y = start.y + size.y;
|
||||
TheWindowManager->winOpenRect( black, borderWidth,
|
||||
start.x, start.y, end.x, end.y );
|
||||
}
|
||||
|
||||
if ( Dstring == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IMEManagerInterface *ime = (IMEManagerInterface*)window->winGetUserData();
|
||||
|
||||
if ( ime == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameFont *font = window->winGetFont() ;
|
||||
Int height;
|
||||
|
||||
// set the font
|
||||
Dstring->setFont( font );
|
||||
|
||||
// cacl line height
|
||||
height = font->height + IMECandidateWindowLineSpacing;
|
||||
|
||||
// set the clip region
|
||||
Dstring->setClipRegion( &textRegion );
|
||||
|
||||
Int first = ime->getCandidatePageStart();
|
||||
Int total = ime->getCandidateCount();
|
||||
Int pageSize = ime->getCandidatePageSize();
|
||||
Int selected = ime->getSelectedCandidateIndex();
|
||||
|
||||
Int count = pageSize;
|
||||
|
||||
if ( count + first > total )
|
||||
{
|
||||
count = total - first;
|
||||
}
|
||||
|
||||
selected = selected - first;
|
||||
UnicodeString number;
|
||||
|
||||
// calulate the widest number text
|
||||
Int width;
|
||||
Dstring->setText(UnicodeString(L"00:"));
|
||||
width = Dstring->getWidth();
|
||||
|
||||
// calc y start pos
|
||||
Int y = origin.y;
|
||||
Int leftEdge = origin.x + 10 + width;
|
||||
|
||||
for ( Int i = 0; i < count; i++, y+= height )
|
||||
{
|
||||
UnicodeString *candidate = ime->getCandidate( first + i );
|
||||
Int tcolor, bcolor;
|
||||
|
||||
if ( i == selected )
|
||||
{
|
||||
tcolor = textSelectColor;
|
||||
bcolor = textSelectBorder;
|
||||
}
|
||||
else
|
||||
{
|
||||
tcolor = textColor;
|
||||
bcolor = textBorder;
|
||||
}
|
||||
|
||||
// draw number tab first
|
||||
number.format( L"%d:", i + ime->getIndexBase());
|
||||
Dstring->setText( number );
|
||||
width = Dstring->getWidth();
|
||||
Dstring->draw( leftEdge - width, y, tcolor, black);
|
||||
|
||||
// draw candidate
|
||||
Dstring->setText( *candidate );
|
||||
Dstring->draw( leftEdge, y, tcolor, black );
|
||||
}
|
||||
}
|
||||
|
||||
// IMECandidateDraw ================================================================
|
||||
/** Draw function for the IME candidate window */
|
||||
//=============================================================================
|
||||
void IMECandidateMainDraw( GameWindow *window, WinInstanceData *instData )
|
||||
{
|
||||
// set up for rendering
|
||||
ICoord2D origin, size, start, end;
|
||||
Color backColor,
|
||||
backBorder;
|
||||
Real borderWidth = 1.0f;
|
||||
|
||||
// get window position and size
|
||||
window->winGetScreenPosition( &origin.x, &origin.y );
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
|
||||
// get the right colors for drawing
|
||||
if( BitTest( window->winGetStatus(), WIN_STATUS_ENABLED ) == FALSE )
|
||||
{
|
||||
|
||||
backColor = window->winGetDisabledColor( 0 );
|
||||
backBorder = window->winGetDisabledBorderColor( 0 );
|
||||
|
||||
} // end if, disabled
|
||||
else if( BitTest( instData->getState(), WIN_STATE_HILITED ) )
|
||||
{
|
||||
|
||||
backColor = window->winGetHiliteColor( 0 );
|
||||
backBorder = window->winGetHiliteBorderColor( 0 );
|
||||
|
||||
} // end else if, hilited
|
||||
else
|
||||
{
|
||||
|
||||
backColor = window->winGetEnabledColor( 0 );
|
||||
backBorder = window->winGetEnabledBorderColor( 0 );
|
||||
|
||||
} // end else, just enabled
|
||||
|
||||
// draw the back border
|
||||
if( backBorder != WIN_COLOR_UNDEFINED )
|
||||
{
|
||||
|
||||
start.x = origin.x;
|
||||
start.y = origin.y;
|
||||
end.x = start.x + size.x;
|
||||
end.y = start.y + size.y;
|
||||
TheWindowManager->winOpenRect( backBorder, borderWidth,
|
||||
start.x, start.y, end.x, end.y );
|
||||
} // end if
|
||||
|
||||
// draw the filled back
|
||||
if( backColor != WIN_COLOR_UNDEFINED )
|
||||
{
|
||||
|
||||
start.x = origin.x + 1;
|
||||
start.y = origin.y + 1;
|
||||
end.x = start.x + size.x - 2;
|
||||
end.y = start.y + size.y - 2;
|
||||
TheWindowManager->winFillRect( backColor, 0, start.x, start.y, end.x, end.y );
|
||||
|
||||
} // end if
|
||||
}
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
** 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: InGameChat.cpp ///////////////////////////////////////////////////////////////////////
|
||||
// Author: Matthew D. Campbell - June 2002
|
||||
// Desc: GUI callbacks for the in-game chat entry
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "GameClient/DisconnectMenu.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameClient/LanguageFilter.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameNetwork/GameInfo.h"
|
||||
#include "GameNetwork/NetworkInterface.h"
|
||||
|
||||
static GameWindow *chatWindow = NULL;
|
||||
static GameWindow *chatTextEntry = NULL;
|
||||
static GameWindow *chatTypeStaticText = NULL;
|
||||
static UnicodeString s_savedChat;
|
||||
static InGameChatType inGameChatType;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ShowInGameChat( Bool immediate )
|
||||
{
|
||||
#if !defined(_PLAYTEST)
|
||||
if (TheGameLogic->isInReplayGame())
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (TheInGameUI->isQuitMenuVisible())
|
||||
return;
|
||||
|
||||
if (TheDisconnectMenu && TheDisconnectMenu->isScreenVisible())
|
||||
return;
|
||||
|
||||
if (chatWindow)
|
||||
{
|
||||
chatWindow->winHide(FALSE);
|
||||
chatWindow->winEnable(TRUE);
|
||||
chatTextEntry->winHide(FALSE);
|
||||
chatTextEntry->winEnable(TRUE);
|
||||
GadgetTextEntrySetText( chatTextEntry, s_savedChat );
|
||||
s_savedChat.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
chatWindow = TheWindowManager->winCreateFromScript( AsciiString("InGameChat.wnd") );
|
||||
|
||||
static NameKeyType textEntryChatID = TheNameKeyGenerator->nameToKey( "InGameChat.wnd:TextEntryChat" );
|
||||
chatTextEntry = TheWindowManager->winGetWindowFromId( NULL, textEntryChatID );
|
||||
GadgetTextEntrySetText( chatTextEntry, UnicodeString::TheEmptyString );
|
||||
|
||||
static NameKeyType chatTypeStaticTextID = TheNameKeyGenerator->nameToKey( "InGameChat.wnd:StaticTextChatType" );
|
||||
chatTypeStaticText = TheWindowManager->winGetWindowFromId( NULL, chatTypeStaticTextID );
|
||||
}
|
||||
TheWindowManager->winSetFocus( chatTextEntry );
|
||||
SetInGameChatType( INGAME_CHAT_EVERYONE );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ResetInGameChat( void )
|
||||
{
|
||||
if(chatWindow)
|
||||
TheWindowManager->winDestroy( chatWindow );
|
||||
chatWindow = NULL;
|
||||
chatTextEntry = NULL;
|
||||
chatTypeStaticText = NULL;
|
||||
s_savedChat.clear();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void HideInGameChat( Bool immediate )
|
||||
{
|
||||
if (chatWindow)
|
||||
{
|
||||
s_savedChat = GadgetTextEntryGetText( chatTextEntry );
|
||||
chatWindow->winHide(TRUE);
|
||||
chatWindow->winEnable(FALSE);
|
||||
chatTextEntry->winHide(TRUE);
|
||||
chatTextEntry->winEnable(FALSE);
|
||||
TheWindowManager->winSetFocus( NULL );
|
||||
}
|
||||
TheWindowManager->winSetFocus( NULL );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SetInGameChatType( InGameChatType chatType )
|
||||
{
|
||||
inGameChatType = chatType;
|
||||
if (chatTypeStaticText)
|
||||
{
|
||||
switch (inGameChatType)
|
||||
{
|
||||
case INGAME_CHAT_EVERYONE:
|
||||
if (ThePlayerList->getLocalPlayer()->isPlayerActive())
|
||||
GadgetStaticTextSetText( chatTypeStaticText, TheGameText->fetch("Chat:Everyone") );
|
||||
else
|
||||
GadgetStaticTextSetText( chatTypeStaticText, TheGameText->fetch("Chat:Observers") );
|
||||
break;
|
||||
case INGAME_CHAT_ALLIES:
|
||||
GadgetStaticTextSetText( chatTypeStaticText, TheGameText->fetch("Chat:Allies") );
|
||||
break;
|
||||
case INGAME_CHAT_PLAYERS:
|
||||
GadgetStaticTextSetText( chatTypeStaticText, TheGameText->fetch("Chat:Players") );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Bool IsInGameChatActive() {
|
||||
if (chatWindow != NULL) {
|
||||
if (chatWindow->winIsHidden() == FALSE) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Slash commands -------------------------------------------------------------------------
|
||||
extern "C" {
|
||||
int getQR2HostingStatus(void);
|
||||
}
|
||||
extern int isThreadHosting;
|
||||
|
||||
Bool handleInGameSlashCommands(UnicodeString uText)
|
||||
{
|
||||
AsciiString message;
|
||||
message.translate(uText);
|
||||
|
||||
if (message.getCharAt(0) != '/')
|
||||
{
|
||||
return FALSE; // not a slash command
|
||||
}
|
||||
|
||||
AsciiString remainder = message.str() + 1;
|
||||
AsciiString token;
|
||||
remainder.nextToken(&token);
|
||||
token.toLower();
|
||||
|
||||
if (token == "host")
|
||||
{
|
||||
UnicodeString s;
|
||||
s.format(L"Hosting qr2:%d thread:%d", getQR2HostingStatus(), isThreadHosting);
|
||||
TheInGameUI->message(s);
|
||||
return TRUE; // was a slash command
|
||||
}
|
||||
|
||||
return FALSE; // not a slash command
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void ToggleInGameChat( Bool immediate )
|
||||
{
|
||||
static Bool justHid = false;
|
||||
if (justHid)
|
||||
{
|
||||
justHid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
#if !defined(_PLAYTEST)
|
||||
if (TheGameLogic->isInReplayGame())
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!TheGameInfo->isMultiPlayer() && TheGlobalData->m_netMinPlayers)
|
||||
return;
|
||||
|
||||
if (chatWindow)
|
||||
{
|
||||
Bool show = chatWindow->winIsHidden();
|
||||
if (show)
|
||||
ShowInGameChat( immediate );
|
||||
else
|
||||
{
|
||||
if (chatTextEntry)
|
||||
{
|
||||
// Send what is there, clear it out, and hide the window
|
||||
UnicodeString msg = GadgetTextEntryGetText( chatTextEntry );
|
||||
msg.trim();
|
||||
if (!msg.isEmpty() && !handleInGameSlashCommands(msg))
|
||||
{
|
||||
const Player *localPlayer = ThePlayerList->getLocalPlayer();
|
||||
AsciiString playerName;
|
||||
Int playerMask = 0;
|
||||
|
||||
for (Int i=0; i<MAX_SLOTS; ++i)
|
||||
{
|
||||
playerName.format("player%d", i);
|
||||
const Player *player = ThePlayerList->findPlayerWithNameKey( TheNameKeyGenerator->nameToKey( playerName ) );
|
||||
if (player && localPlayer)
|
||||
{
|
||||
switch (inGameChatType)
|
||||
{
|
||||
case INGAME_CHAT_EVERYONE:
|
||||
if (!TheGameInfo->getConstSlot(i)->isMuted())
|
||||
playerMask |= (1<<i);
|
||||
break;
|
||||
case INGAME_CHAT_ALLIES:
|
||||
if ( (player->getRelationship(localPlayer->getDefaultTeam()) == ALLIES &&
|
||||
localPlayer->getRelationship(player->getDefaultTeam()) == ALLIES) || player==localPlayer )
|
||||
playerMask |= (1<<i);
|
||||
break;
|
||||
case INGAME_CHAT_PLAYERS:
|
||||
if ( player == localPlayer )
|
||||
playerMask |= (1<<i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
TheLanguageFilter->filterLine(msg);
|
||||
TheNetwork->sendChat(msg, playerMask);
|
||||
}
|
||||
GadgetTextEntrySetText( chatTextEntry, UnicodeString::TheEmptyString );
|
||||
HideInGameChat( immediate );
|
||||
justHid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowInGameChat( immediate );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType InGameChatInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
// UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
HideInGameChat();
|
||||
return MSG_HANDLED;
|
||||
//return MSG_IGNORED;
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end char
|
||||
|
||||
}
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end InGameChatInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType InGameChatSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GGM_FOCUS_CHANGE:
|
||||
{
|
||||
// Bool focus = (Bool) mData1;
|
||||
//if (focus)
|
||||
//TheWindowManager->winSetGrabWindow( chatTextEntry );
|
||||
break;
|
||||
} // end focus change
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
ToggleInGameChat();
|
||||
//HideInGameChat();
|
||||
|
||||
break;
|
||||
|
||||
} // end button selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
static NameKeyType buttonClearID = TheNameKeyGenerator->nameToKey( AsciiString( "InGameChat.wnd:ButtonClear" ) );
|
||||
if (control && control->winGetWindowId() == buttonClearID)
|
||||
{
|
||||
if (chatTextEntry)
|
||||
GadgetTextEntrySetText( chatTextEntry, UnicodeString::TheEmptyString );
|
||||
s_savedChat.clear();
|
||||
}
|
||||
break;
|
||||
|
||||
} // end button selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end InGameChatSystem
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
** 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: InGamePopupMessage.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Jul 2002
|
||||
//
|
||||
// Filename: InGamePopupMessage.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: Init, input, and system for the in game message popup
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/Version.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameClient/DisplayStringManager.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static NameKeyType parentID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextMessageID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOkID = NAMEKEY_INVALID;
|
||||
|
||||
|
||||
static GameWindow *parent = NULL;
|
||||
static GameWindow *staticTextMessage = NULL;
|
||||
static GameWindow *buttonOk = NULL;
|
||||
|
||||
|
||||
static Bool pause = FALSE;
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the InGamePopupMessageInit menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void InGamePopupMessageInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
parentID = TheNameKeyGenerator->nameToKey(AsciiString("InGamePopupMessage.wnd:InGamePopupMessageParent"));
|
||||
parent = TheWindowManager->winGetWindowFromId(NULL, parentID);
|
||||
|
||||
staticTextMessageID = TheNameKeyGenerator->nameToKey(AsciiString("InGamePopupMessage.wnd:StaticTextMessage"));
|
||||
staticTextMessage = TheWindowManager->winGetWindowFromId(parent, staticTextMessageID);
|
||||
buttonOkID = TheNameKeyGenerator->nameToKey(AsciiString("InGamePopupMessage.wnd:ButtonOk"));
|
||||
buttonOk = TheWindowManager->winGetWindowFromId(parent, buttonOkID);
|
||||
|
||||
PopupMessageData *pMData = TheInGameUI->getPopupMessageData();
|
||||
|
||||
if(!pMData)
|
||||
{
|
||||
DEBUG_ASSERTCRASH(pMData, ("We're in InGamePopupMessage without a pointer to pMData\n") );
|
||||
///< @todo: add a call to the close this bitch method when I implement it CLH
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayString *tempString = TheDisplayStringManager->newDisplayString();
|
||||
tempString->setText(pMData->message);
|
||||
tempString->setFont(staticTextMessage->winGetFont());
|
||||
tempString->setWordWrap(pMData->width - 14);
|
||||
Int width, height;
|
||||
tempString->getSize(&width, &height);
|
||||
TheDisplayStringManager->freeDisplayString(tempString);
|
||||
|
||||
GadgetStaticTextSetText(staticTextMessage, pMData->message);
|
||||
// set the positions/sizes
|
||||
Int widthOk, heightOk;
|
||||
buttonOk->winGetSize(&widthOk, &heightOk);
|
||||
parent->winSetPosition( pMData->x, pMData->y);
|
||||
parent->winSetSize( pMData->width, height + 7 + 2 + 2 + heightOk + 2 );
|
||||
staticTextMessage->winSetPosition( 2, 2);
|
||||
staticTextMessage->winSetSize( pMData->width - 4, height + 7);
|
||||
buttonOk->winSetPosition(pMData->width - widthOk - 2, height + 7 + 2 + 2);
|
||||
staticTextMessage->winSetEnabledTextColors(pMData->textColor, 0);
|
||||
pause = pMData->pause;
|
||||
if(pMData->pause)
|
||||
TheWindowManager->winSetModal( parent );
|
||||
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
|
||||
parent->winHide(FALSE);
|
||||
parent->winBringToTop();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** InGamePopupMessageInput callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType InGamePopupMessageInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
// if (buttonPushed)
|
||||
// break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ENTER:
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonOk, buttonOkID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
return MSG_IGNORED;
|
||||
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** InGamePopupMessageSystem callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType InGamePopupMessageSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonOkID )
|
||||
{
|
||||
if(!pause)
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_INGAME_POPUP_MESSAGE );
|
||||
else
|
||||
TheInGameUI->clearPopupMessageData();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
** 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: CreditsMenu.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Dec 2002
|
||||
//
|
||||
// Filename: CreditsMenu.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: The credits screen...yay
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma message("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "Common/GameAudio.h"
|
||||
#include "Common/AudioEventRTS.h"
|
||||
#include "Common/AudioHandleSpecialValues.h"
|
||||
|
||||
#include "GameClient/Credits.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
static NameKeyType parentMainMenuID = NAMEKEY_INVALID;
|
||||
|
||||
// window pointers --------------------------------------------------------------------------------
|
||||
static GameWindow *parentMainMenu = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the single player menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CreditsMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
TheShell->showShellMap(FALSE);
|
||||
if(TheCredits)
|
||||
delete TheCredits;
|
||||
TheCredits = new CreditsManager;
|
||||
TheCredits->load();
|
||||
TheCredits->init();
|
||||
|
||||
parentMainMenuID = TheNameKeyGenerator->nameToKey( AsciiString("CreditsMenu.wnd:ParentCreditsWindow") );
|
||||
parentMainMenu = TheWindowManager->winGetWindowFromId( NULL, parentMainMenuID );
|
||||
|
||||
|
||||
// show menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// set keyboard focus to main parent
|
||||
TheWindowManager->winSetFocus( parentMainMenu );
|
||||
|
||||
|
||||
|
||||
TheAudio->removeAudioEvent( AHSV_StopTheMusicFade );
|
||||
AudioEventRTS event( AsciiString( "Credits" ) );
|
||||
event.setShouldFade( TRUE );
|
||||
TheAudio->addAudioEvent( &event );
|
||||
|
||||
|
||||
} // end CreditsMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CreditsMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
TheCredits->reset();
|
||||
delete TheCredits;
|
||||
TheCredits = NULL;
|
||||
TheShell->showShellMap(TRUE);
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
TheAudio->removeAudioEvent( AHSV_StopTheMusicFade );
|
||||
|
||||
} // end CreditsMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CreditsMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
if(TheCredits)
|
||||
{
|
||||
TheWindowManager->winSetFocus( parentMainMenu );
|
||||
TheCredits->update();
|
||||
if(TheCredits->isFinished())
|
||||
TheShell->pop();
|
||||
}
|
||||
else
|
||||
TheShell->pop();
|
||||
|
||||
} // end CreditsMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Replay menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType CreditsMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
|
||||
TheShell->pop();
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end CreditsMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType CreditsMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
|
||||
break;
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
} // end CreditsMenuSystem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
** 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: DifficultySelect.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Nov 2002
|
||||
//
|
||||
// Filename: DifficultySelect.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: The popup campaign difficulty select
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "Common/UserPreferences.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetPushButton.h"
|
||||
#include "GameClient/GadgetRadioButton.h"
|
||||
#include "GameClient/CampaignManager.h"
|
||||
|
||||
#include "GameLogic/ScriptEngine.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
static GameDifficulty s_AIDiff = DIFFICULTY_NORMAL;
|
||||
static NameKeyType buttonOkID = NAMEKEY_INVALID;
|
||||
static GameWindow * buttonOk = NULL;
|
||||
static NameKeyType buttonCancelID = NAMEKEY_INVALID;
|
||||
static GameWindow * buttonCancel = NULL;
|
||||
static NameKeyType radioButtonEasyAIID = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonMediumAIID = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonHardAIID = NAMEKEY_INVALID;
|
||||
static GameWindow * radioButtonEasyAI = NULL;
|
||||
static GameWindow * radioButtonMediumAI = NULL;
|
||||
static GameWindow * radioButtonHardAI = NULL;
|
||||
|
||||
void setupGameStart(AsciiString mapName, GameDifficulty diff);
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
static void SetDifficultyRadioButton( void )
|
||||
{
|
||||
OptionPreferences pref;
|
||||
if (!TheScriptEngine)
|
||||
{
|
||||
s_AIDiff = DIFFICULTY_NORMAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pref.getCampaignDifficulty())
|
||||
{
|
||||
case DIFFICULTY_EASY:
|
||||
{
|
||||
GadgetRadioSetSelection(radioButtonEasyAI, FALSE);
|
||||
s_AIDiff = DIFFICULTY_EASY;
|
||||
break;
|
||||
}
|
||||
case DIFFICULTY_NORMAL:
|
||||
{
|
||||
GadgetRadioSetSelection(radioButtonMediumAI, FALSE);
|
||||
s_AIDiff = DIFFICULTY_NORMAL;
|
||||
break;
|
||||
}
|
||||
case DIFFICULTY_HARD:
|
||||
{
|
||||
GadgetRadioSetSelection(radioButtonHardAI, FALSE);
|
||||
s_AIDiff = DIFFICULTY_HARD;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DEBUG_CRASH(("unrecognized difficulty level in the script engine"));
|
||||
}
|
||||
|
||||
}
|
||||
} // if (TheScriptEngine)
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DifficultySelectInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
AsciiString parentName( "DifficultySelect.wnd:DifficultySelectParent" );
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
|
||||
buttonOkID = TheNameKeyGenerator->nameToKey( "DifficultySelect.wnd:ButtonOk" );
|
||||
buttonOk = TheWindowManager->winGetWindowFromId( parent, buttonOkID );
|
||||
buttonCancelID = TheNameKeyGenerator->nameToKey( "DifficultySelect.wnd:ButtonCancel" );
|
||||
buttonCancel = TheWindowManager->winGetWindowFromId( parent, buttonCancelID );
|
||||
radioButtonEasyAIID = TheNameKeyGenerator->nameToKey( AsciiString("DifficultySelect.wnd:RadioButtonEasy") );
|
||||
radioButtonEasyAI = TheWindowManager->winGetWindowFromId( parent, radioButtonEasyAIID );
|
||||
radioButtonMediumAIID = TheNameKeyGenerator->nameToKey( AsciiString("DifficultySelect.wnd:RadioButtonMedium") );
|
||||
radioButtonMediumAI = TheWindowManager->winGetWindowFromId( parent, radioButtonMediumAIID );
|
||||
radioButtonHardAIID = TheNameKeyGenerator->nameToKey( AsciiString("DifficultySelect.wnd:RadioButtonHard") );
|
||||
radioButtonHardAI = TheWindowManager->winGetWindowFromId( parent, radioButtonHardAIID );
|
||||
|
||||
s_AIDiff = DIFFICULTY_NORMAL;
|
||||
SetDifficultyRadioButton();
|
||||
// set keyboard focus to main parent
|
||||
// AsciiString parentName( "SkirmishMapSelectMenu.wnd:SkrimishMapSelectMenuParent" );
|
||||
// NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
// parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
//
|
||||
// TheWindowManager->winSetFocus( parent );
|
||||
//
|
||||
parent->winBringToTop();
|
||||
TheWindowManager->winSetModal(parent);
|
||||
|
||||
} // end SkirmishMapSelectMenuInit
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Map select menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType DifficultySelectInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
// switch( msg )
|
||||
// {
|
||||
//
|
||||
// // --------------------------------------------------------------------------------------------
|
||||
// case GWM_CHAR:
|
||||
// {
|
||||
// UnsignedByte key = mData1;
|
||||
// UnsignedByte state = mData2;
|
||||
//
|
||||
// switch( key )
|
||||
// {
|
||||
//
|
||||
// // ----------------------------------------------------------------------------------------
|
||||
// case KEY_ESC:
|
||||
// {
|
||||
//
|
||||
// //
|
||||
// // send a simulated selected event to the parent window of the
|
||||
// // back/exit button
|
||||
// //
|
||||
// if( BitTest( state, KEY_STATE_UP ) )
|
||||
// {
|
||||
// AsciiString buttonName( "SkirmishMapSelectMenu.wnd:ButtonBack" );
|
||||
// NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
|
||||
// GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
|
||||
//
|
||||
// TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
// (WindowMsgData)button, buttonID );
|
||||
//
|
||||
// } // end if
|
||||
//
|
||||
// // don't let key fall through anywhere else
|
||||
// return MSG_HANDLED;
|
||||
//
|
||||
// } // end escape
|
||||
//
|
||||
// } // end switch( key )
|
||||
//
|
||||
// } // end char
|
||||
//
|
||||
// } // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end SkirmishMapSelectMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType DifficultySelectSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
// this isn't fixed yet
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == buttonOkID )
|
||||
{
|
||||
OptionPreferences pref;
|
||||
pref.setCampaignDifficulty(s_AIDiff);
|
||||
pref.write();
|
||||
//TheScriptEngine->setGlobalDifficulty(s_AIDiff); // CANNOT DO THIS! REPLAYS WILL BREAK!
|
||||
WindowLayout *layout = window->winGetLayout();
|
||||
layout->destroyWindows();
|
||||
layout->deleteInstance();
|
||||
setupGameStart(TheCampaignManager->getCurrentMap(), s_AIDiff);
|
||||
// start the game
|
||||
}
|
||||
else if ( controlID == buttonCancelID )
|
||||
{
|
||||
TheCampaignManager->setCampaign( AsciiString::TheEmptyString );
|
||||
TheWindowManager->winUnsetModal(window);
|
||||
WindowLayout *layout = window->winGetLayout();
|
||||
layout->destroyWindows();
|
||||
layout->deleteInstance();
|
||||
|
||||
}
|
||||
else if ( controlID == radioButtonEasyAIID )
|
||||
{
|
||||
s_AIDiff = DIFFICULTY_EASY;
|
||||
}
|
||||
else if ( controlID == radioButtonMediumAIID )
|
||||
{
|
||||
s_AIDiff = DIFFICULTY_NORMAL;
|
||||
}
|
||||
else if ( controlID == radioButtonHardAIID )
|
||||
{
|
||||
s_AIDiff = DIFFICULTY_HARD;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
** 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: DisconnectControls.cpp ///////////////////////////////////////////////////////////////////////
|
||||
// Author: Bryan Cleveland - March 2001
|
||||
// Desc: GUI menu for network disconnects
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
#include "GameClient/DisconnectMenu.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameNetwork/GameInfo.h"
|
||||
|
||||
// Private Data -----------------------------
|
||||
static WindowLayout *disconnectMenuLayout;
|
||||
|
||||
static NameKeyType textEntryID = NAMEKEY_INVALID;
|
||||
static NameKeyType textDisplayID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *textEntryWindow = NULL;
|
||||
static GameWindow *textDisplayWindow = NULL;
|
||||
|
||||
static NameKeyType buttonQuitID = NAMEKEY_INVALID;
|
||||
static GameWindow *buttonQuitWindow = NULL;
|
||||
|
||||
static NameKeyType buttonVotePlayer1ID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonVotePlayer2ID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonVotePlayer3ID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonVotePlayer4ID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonVotePlayer5ID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonVotePlayer6ID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonVotePlayer7ID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *buttonVotePlayer1Window = NULL;
|
||||
static GameWindow *buttonVotePlayer2Window = NULL;
|
||||
static GameWindow *buttonVotePlayer3Window = NULL;
|
||||
static GameWindow *buttonVotePlayer4Window = NULL;
|
||||
static GameWindow *buttonVotePlayer5Window = NULL;
|
||||
static GameWindow *buttonVotePlayer6Window = NULL;
|
||||
static GameWindow *buttonVotePlayer7Window = NULL;
|
||||
|
||||
static void InitDisconnectWindow( void ) {
|
||||
textEntryID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:TextEntry"));
|
||||
textDisplayID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ListboxTextDisplay"));
|
||||
|
||||
textEntryWindow = TheWindowManager->winGetWindowFromId(NULL, textEntryID);
|
||||
textDisplayWindow = TheWindowManager->winGetWindowFromId(NULL, textDisplayID);
|
||||
|
||||
if (textEntryWindow != NULL) {
|
||||
GadgetTextEntrySetText(textEntryWindow, UnicodeString::TheEmptyString);
|
||||
TheWindowManager->winSetFocus(textEntryWindow);
|
||||
}
|
||||
|
||||
buttonQuitID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ButtonQuitGame"));
|
||||
buttonQuitWindow = TheWindowManager->winGetWindowFromId(NULL, buttonQuitID);
|
||||
|
||||
buttonVotePlayer1ID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ButtonKickPlayer1"));
|
||||
buttonVotePlayer2ID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ButtonKickPlayer2"));
|
||||
buttonVotePlayer3ID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ButtonKickPlayer3"));
|
||||
buttonVotePlayer4ID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ButtonKickPlayer4"));
|
||||
buttonVotePlayer5ID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ButtonKickPlayer5"));
|
||||
buttonVotePlayer6ID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ButtonKickPlayer6"));
|
||||
buttonVotePlayer7ID = TheNameKeyGenerator->nameToKey( AsciiString("DisconnectScreen.wnd:ButtonKickPlayer7"));
|
||||
|
||||
buttonVotePlayer1Window = TheWindowManager->winGetWindowFromId(NULL, buttonVotePlayer1ID);
|
||||
buttonVotePlayer2Window = TheWindowManager->winGetWindowFromId(NULL, buttonVotePlayer2ID);
|
||||
buttonVotePlayer3Window = TheWindowManager->winGetWindowFromId(NULL, buttonVotePlayer3ID);
|
||||
buttonVotePlayer4Window = TheWindowManager->winGetWindowFromId(NULL, buttonVotePlayer4ID);
|
||||
buttonVotePlayer5Window = TheWindowManager->winGetWindowFromId(NULL, buttonVotePlayer5ID);
|
||||
buttonVotePlayer6Window = TheWindowManager->winGetWindowFromId(NULL, buttonVotePlayer6ID);
|
||||
buttonVotePlayer7Window = TheWindowManager->winGetWindowFromId(NULL, buttonVotePlayer7ID);
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
/** Show the Disconnect Screen */
|
||||
//------------------------------------------------------
|
||||
void ShowDisconnectWindow( void )
|
||||
{
|
||||
|
||||
// load the quit menu from the layout file if needed
|
||||
if( disconnectMenuLayout == NULL )
|
||||
{
|
||||
|
||||
// load layout from disk
|
||||
disconnectMenuLayout = TheWindowManager->winCreateLayout( "Menus/DisconnectScreen.wnd" );
|
||||
|
||||
// init it
|
||||
InitDisconnectWindow();
|
||||
|
||||
// show it
|
||||
disconnectMenuLayout->hide( FALSE );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
disconnectMenuLayout->hide( FALSE );
|
||||
|
||||
} // end else
|
||||
|
||||
// Disallow voting for 2-player games. Cheating punk.
|
||||
if ( TheGameInfo && TheGameInfo->getNumPlayers() < 3 )
|
||||
{
|
||||
buttonVotePlayer1Window->winEnable(FALSE);
|
||||
buttonVotePlayer2Window->winEnable(FALSE);
|
||||
buttonVotePlayer3Window->winEnable(FALSE);
|
||||
buttonVotePlayer4Window->winEnable(FALSE);
|
||||
buttonVotePlayer5Window->winEnable(FALSE);
|
||||
buttonVotePlayer6Window->winEnable(FALSE);
|
||||
buttonVotePlayer7Window->winEnable(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonVotePlayer1Window->winEnable(TRUE);
|
||||
buttonVotePlayer2Window->winEnable(TRUE);
|
||||
buttonVotePlayer3Window->winEnable(TRUE);
|
||||
buttonVotePlayer4Window->winEnable(TRUE);
|
||||
buttonVotePlayer5Window->winEnable(TRUE);
|
||||
buttonVotePlayer6Window->winEnable(TRUE);
|
||||
buttonVotePlayer7Window->winEnable(TRUE);
|
||||
}
|
||||
buttonQuitWindow->winEnable(TRUE);
|
||||
disconnectMenuLayout->bringForward();
|
||||
|
||||
GadgetListBoxReset(textDisplayWindow);
|
||||
GadgetListBoxAddEntryText(textDisplayWindow, TheGameText->fetch("GUI:InternetDisconnectionMenuBody1"),
|
||||
GameMakeColor(255,255,255,255), -1);
|
||||
|
||||
} // end ToggleQuitMenu
|
||||
|
||||
//------------------------------------------------------
|
||||
/** Hide the Disconnect Screen */
|
||||
//------------------------------------------------------
|
||||
void HideDisconnectWindow( void )
|
||||
{
|
||||
|
||||
// load the quit menu from the layout file if needed
|
||||
if( disconnectMenuLayout == NULL )
|
||||
{
|
||||
|
||||
// load layout from disk
|
||||
disconnectMenuLayout = TheWindowManager->winCreateLayout( "Menus/DisconnectScreen.wnd" );
|
||||
|
||||
// init it
|
||||
InitDisconnectWindow();
|
||||
|
||||
// show it
|
||||
disconnectMenuLayout->hide( TRUE );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
disconnectMenuLayout->hide( TRUE );
|
||||
|
||||
} // end else
|
||||
|
||||
} // end ToggleQuitMenu
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Input callback for the control bar parent */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType DisconnectControlInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end DisconnectControlInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** System callback for the control bar parent */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType DisconnectControlSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
|
||||
GameWindow *control = (GameWindow *) mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if (controlID == buttonQuitID) {
|
||||
TheDisconnectMenu->quitGame();
|
||||
buttonQuitWindow->winEnable(FALSE);
|
||||
} else if (controlID == buttonVotePlayer1ID) {
|
||||
TheDisconnectMenu->voteForPlayer(0);
|
||||
buttonVotePlayer1Window->winEnable(FALSE);
|
||||
} else if (controlID == buttonVotePlayer2ID) {
|
||||
TheDisconnectMenu->voteForPlayer(1);
|
||||
buttonVotePlayer2Window->winEnable(FALSE);
|
||||
} else if (controlID == buttonVotePlayer3ID) {
|
||||
TheDisconnectMenu->voteForPlayer(2);
|
||||
buttonVotePlayer3Window->winEnable(FALSE);
|
||||
} else if (controlID == buttonVotePlayer4ID) {
|
||||
TheDisconnectMenu->voteForPlayer(3);
|
||||
buttonVotePlayer4Window->winEnable(FALSE);
|
||||
} else if (controlID == buttonVotePlayer5ID) {
|
||||
TheDisconnectMenu->voteForPlayer(4);
|
||||
buttonVotePlayer5Window->winEnable(FALSE);
|
||||
} else if (controlID == buttonVotePlayer6ID) {
|
||||
TheDisconnectMenu->voteForPlayer(5);
|
||||
buttonVotePlayer6Window->winEnable(FALSE);
|
||||
} else if (controlID == buttonVotePlayer7ID) {
|
||||
TheDisconnectMenu->voteForPlayer(6);
|
||||
buttonVotePlayer7Window->winEnable(FALSE);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end button selected
|
||||
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
// DEBUG_LOG(("DisconnectControlSystem - got GEM_EDIT_DONE.\n"));
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
// Take the user's input and echo it into the chat window as well as
|
||||
// send it to the other clients on the lan
|
||||
if ( controlID == textEntryID )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
// DEBUG_LOG(("DisconnectControlSystem - GEM_EDIT_DONE was from the text entry control.\n"));
|
||||
|
||||
// read the user's input
|
||||
txtInput.set(GadgetTextEntryGetText( textEntryWindow ));
|
||||
// Clear the text entry line
|
||||
GadgetTextEntrySetText(textEntryWindow, UnicodeString::TheEmptyString);
|
||||
// Clean up the text (remove leading/trailing chars, etc)
|
||||
txtInput.trim();
|
||||
// Echo the user's input to the chat window
|
||||
if (!txtInput.isEmpty()) {
|
||||
// DEBUG_LOG(("DisconnectControlSystem - sending string %ls\n", txtInput.str()));
|
||||
TheDisconnectMenu->sendChat(txtInput);
|
||||
}
|
||||
|
||||
}// if ( controlID == textEntryChatID )
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end ControlBarSystem
|
||||
|
||||
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
** 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: DownloadMenu.cpp /////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: DownloadMenu.cpp
|
||||
//
|
||||
// Created: Matthew D. Campbell, July 2002
|
||||
//
|
||||
// Desc: the Patch Download window control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GadgetProgressBar.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/MessageBox.h"
|
||||
|
||||
#include "GameLogic/GameLogic.h"
|
||||
|
||||
#include "GameNetwork/DownloadManager.h"
|
||||
#include "GameNetwork/GameSpy/MainMenuUtils.h"
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static NameKeyType buttonCancelID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextSizeID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextTimeID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextFileID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextStatusID = NAMEKEY_INVALID;
|
||||
static NameKeyType progressBarMunkeeID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow * staticTextSize = NULL;
|
||||
static GameWindow * staticTextTime = NULL;
|
||||
static GameWindow * staticTextFile = NULL;
|
||||
static GameWindow * staticTextStatus = NULL;
|
||||
static GameWindow * progressBarMunkee = NULL;
|
||||
|
||||
static GameWindow *parent = NULL;
|
||||
|
||||
static void closeDownloadWindow( void )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(parent, ("No Parent"));
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
WindowLayout *menuLayout = parent->winGetLayout();
|
||||
menuLayout->runShutdown();
|
||||
menuLayout->destroyWindows();
|
||||
menuLayout->deleteInstance();
|
||||
menuLayout = NULL;
|
||||
|
||||
GameWindow *mainWin = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("MainMenu.wnd:MainMenuParent") );
|
||||
if (mainWin)
|
||||
TheWindowManager->winSetFocus( mainWin );
|
||||
}
|
||||
|
||||
static void errorCallback( void )
|
||||
{
|
||||
HandleCanceledDownload();
|
||||
closeDownloadWindow();
|
||||
}
|
||||
|
||||
static void successQuitCallback( void )
|
||||
{
|
||||
TheGameEngine->setQuitting( TRUE );
|
||||
closeDownloadWindow();
|
||||
|
||||
// Clean up game data. No crashy-crash for you!
|
||||
if (TheGameLogic->isInGame())
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_GAME_DATA );
|
||||
}
|
||||
|
||||
static void successNoQuitCallback( void )
|
||||
{
|
||||
HandleCanceledDownload();
|
||||
closeDownloadWindow();
|
||||
}
|
||||
|
||||
class DownloadManagerMunkee : public DownloadManager
|
||||
{
|
||||
public:
|
||||
DownloadManagerMunkee() {m_shouldQuitOnSuccess = true; m_shouldQuitOnSuccess = false;}
|
||||
virtual HRESULT OnError( Int error );
|
||||
virtual HRESULT OnEnd();
|
||||
virtual HRESULT OnProgressUpdate( Int bytesread, Int totalsize, Int timetaken, Int timeleft );
|
||||
virtual HRESULT OnStatusUpdate( Int status );
|
||||
virtual HRESULT downloadFile( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume );
|
||||
|
||||
private:
|
||||
Bool m_shouldQuitOnSuccess;
|
||||
};
|
||||
|
||||
HRESULT DownloadManagerMunkee::downloadFile( AsciiString server, AsciiString username, AsciiString password, AsciiString file, AsciiString localfile, AsciiString regkey, Bool tryResume )
|
||||
{
|
||||
// see if we'll need to restart
|
||||
if (strstr(localfile.str(), "patches\\") != NULL)
|
||||
{
|
||||
m_shouldQuitOnSuccess = true;
|
||||
}
|
||||
|
||||
if (staticTextFile)
|
||||
{
|
||||
AsciiString bob = file;
|
||||
|
||||
// just get the filename, not the pathname
|
||||
const char *tmp = bob.reverseFind('/');
|
||||
if (tmp)
|
||||
bob = tmp+1;
|
||||
tmp = bob.reverseFind('\\');
|
||||
if (tmp)
|
||||
bob = tmp+1;
|
||||
|
||||
UnicodeString fileString;
|
||||
fileString.translate(bob);
|
||||
GadgetStaticTextSetText(staticTextFile, fileString);
|
||||
}
|
||||
|
||||
password.format("-%s", password.str());
|
||||
return DownloadManager::downloadFile( server, username, password, file, localfile, regkey, tryResume );
|
||||
}
|
||||
HRESULT DownloadManagerMunkee::OnError( Int error )
|
||||
{
|
||||
HRESULT ret = DownloadManager::OnError( error );
|
||||
|
||||
MessageBoxOk(TheGameText->fetch("GUI:DownloadErrorTitle"), getErrorString(), errorCallback);
|
||||
return ret;
|
||||
}
|
||||
HRESULT DownloadManagerMunkee::OnEnd()
|
||||
{
|
||||
HRESULT ret = DownloadManager::OnEnd();
|
||||
|
||||
if (isFileQueuedForDownload())
|
||||
{
|
||||
return downloadNextQueuedFile();
|
||||
}
|
||||
if (m_shouldQuitOnSuccess)
|
||||
MessageBoxOk(TheGameText->fetch("GUI:DownloadSuccessTitle"), TheGameText->fetch("GUI:DownloadSuccessMustQuit"), successQuitCallback);
|
||||
else
|
||||
MessageBoxOk(TheGameText->fetch("GUI:DownloadSuccessTitle"), TheGameText->fetch("GUI:DownloadSuccess"), successNoQuitCallback);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static time_t lastUpdate = 0;
|
||||
static Int timeLeft = 0;
|
||||
HRESULT DownloadManagerMunkee::OnProgressUpdate( Int bytesread, Int totalsize, Int timetaken, Int timeleft )
|
||||
{
|
||||
HRESULT ret = DownloadManager::OnProgressUpdate( bytesread, totalsize, timetaken, timeleft );
|
||||
|
||||
if (progressBarMunkee)
|
||||
{
|
||||
Int percent = bytesread * 100 / totalsize;
|
||||
GadgetProgressBarSetProgress( progressBarMunkee, percent );
|
||||
}
|
||||
|
||||
if (staticTextSize)
|
||||
{
|
||||
UnicodeString sizeString;
|
||||
sizeString.format(TheGameText->fetch("GUI:DownloadBytesRatio"), bytesread, totalsize);
|
||||
GadgetStaticTextSetText(staticTextSize, sizeString);
|
||||
}
|
||||
timeLeft = timeleft;
|
||||
if (staticTextTime && GadgetStaticTextGetText(staticTextTime).isEmpty()) // only update immediately the first time
|
||||
{
|
||||
lastUpdate = time(NULL);
|
||||
UnicodeString timeString;
|
||||
if (timeleft)
|
||||
{
|
||||
DEBUG_ASSERTCRASH(timeleft > 0, ("Time left is negative!"));
|
||||
timeleft = max(1, timeleft);
|
||||
Int takenHour, takenMin, takenSec;
|
||||
takenHour = timeleft / 60 / 60;
|
||||
takenMin = timeleft / 60;
|
||||
takenSec = timeleft % 60;
|
||||
timeString.format(TheGameText->fetch("GUI:DownloadTimeLeft"), takenHour, takenMin, takenSec);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeString = TheGameText->fetch("GUI:DownloadUnknownTime");
|
||||
}
|
||||
GadgetStaticTextSetText(staticTextTime, timeString);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
HRESULT DownloadManagerMunkee::OnStatusUpdate( Int status )
|
||||
{
|
||||
HRESULT ret = DownloadManager::OnStatusUpdate( status );
|
||||
|
||||
if (staticTextStatus)
|
||||
{
|
||||
GadgetStaticTextSetText(staticTextStatus, getStatusString());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DownloadMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
//set keyboard focus to main parent and set modal
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey("DownloadMenu.wnd:ParentDownload");
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
|
||||
// get ids for our children controls
|
||||
buttonCancelID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:ButtonCancel" );
|
||||
staticTextSizeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextSize" );
|
||||
staticTextTimeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextTime" );
|
||||
staticTextFileID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextFile" );
|
||||
staticTextStatusID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:StaticTextStatus" );
|
||||
progressBarMunkeeID = TheNameKeyGenerator->nameToKey( "DownloadMenu.wnd:ProgressBarMunkee" );
|
||||
|
||||
staticTextSize = TheWindowManager->winGetWindowFromId( parent, staticTextSizeID );
|
||||
staticTextTime = TheWindowManager->winGetWindowFromId( parent, staticTextTimeID );
|
||||
staticTextFile = TheWindowManager->winGetWindowFromId( parent, staticTextFileID );
|
||||
staticTextStatus = TheWindowManager->winGetWindowFromId( parent, staticTextStatusID );
|
||||
progressBarMunkee = TheWindowManager->winGetWindowFromId( parent, progressBarMunkeeID );
|
||||
|
||||
DEBUG_ASSERTCRASH(!TheDownloadManager, ("Download manager already exists"));
|
||||
if (TheDownloadManager)
|
||||
{
|
||||
delete TheDownloadManager;
|
||||
}
|
||||
TheDownloadManager = NEW DownloadManagerMunkee;
|
||||
|
||||
} // end DownloadMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DownloadMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(TheDownloadManager, ("No download manager"));
|
||||
if (TheDownloadManager)
|
||||
{
|
||||
delete TheDownloadManager;
|
||||
TheDownloadManager = NULL;
|
||||
}
|
||||
|
||||
staticTextSize = NULL;
|
||||
staticTextTime = NULL;
|
||||
staticTextFile = NULL;
|
||||
staticTextStatus = NULL;
|
||||
progressBarMunkee = NULL;
|
||||
parent = NULL;
|
||||
|
||||
} // end DownloadMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void DownloadMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
if (staticTextTime && !GadgetStaticTextGetText(staticTextTime).isEmpty())
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
if (now <= lastUpdate)
|
||||
return;
|
||||
|
||||
lastUpdate = now;
|
||||
|
||||
UnicodeString timeString;
|
||||
if (timeLeft)
|
||||
{
|
||||
DEBUG_ASSERTCRASH(timeLeft > 0, ("Time left is negative!"));
|
||||
timeLeft = max(1, timeLeft);
|
||||
Int takenHour, takenMin, takenSec;
|
||||
takenHour = timeLeft / 60 / 60;
|
||||
takenMin = timeLeft / 60;
|
||||
takenSec = timeLeft % 60;
|
||||
timeString.format(TheGameText->fetch("GUI:DownloadTimeLeft"), takenHour, takenMin, takenSec);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeString = TheGameText->fetch("GUI:DownloadUnknownTime");
|
||||
}
|
||||
GadgetStaticTextSetText(staticTextTime, timeString);
|
||||
}
|
||||
|
||||
} // end DownloadMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType DownloadMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
AsciiString buttonName( "DownloadMenu.wnd:ButtonCancel" );
|
||||
NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end DownloadMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType DownloadMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonCancelID )
|
||||
{
|
||||
HandleCanceledDownload();
|
||||
closeDownloadWindow();
|
||||
} // end if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end DownloadMenuSystem
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
** 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. //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///// EstablishConnectionsWindow.cpp /////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/EstablishConnectionsMenu.h"
|
||||
#include "GameNetwork/GUIUtil.h"
|
||||
#include "GameNetwork/GameSpy/StagingRoomGameInfo.h"
|
||||
|
||||
static WindowLayout *establishConnectionsLayout;
|
||||
|
||||
static NameKeyType buttonQuitID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer1NameID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer2NameID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer3NameID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer4NameID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer5NameID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer6NameID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer7NameID = NAMEKEY_INVALID;
|
||||
|
||||
static NameKeyType staticPlayer1StatusID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer2StatusID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer3StatusID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer4StatusID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer5StatusID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer6StatusID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticPlayer7StatusID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *buttonQuitWindow = NULL;
|
||||
static GameWindow *staticPlayer1Name = NULL;
|
||||
static GameWindow *staticPlayer2Name = NULL;
|
||||
static GameWindow *staticPlayer3Name = NULL;
|
||||
static GameWindow *staticPlayer4Name = NULL;
|
||||
static GameWindow *staticPlayer5Name = NULL;
|
||||
static GameWindow *staticPlayer6Name = NULL;
|
||||
static GameWindow *staticPlayer7Name = NULL;
|
||||
|
||||
static GameWindow *staticPlayer1Status = NULL;
|
||||
static GameWindow *staticPlayer2Status = NULL;
|
||||
static GameWindow *staticPlayer3Status = NULL;
|
||||
static GameWindow *staticPlayer4Status = NULL;
|
||||
static GameWindow *staticPlayer5Status = NULL;
|
||||
static GameWindow *staticPlayer6Status = NULL;
|
||||
static GameWindow *staticPlayer7Status = NULL;
|
||||
|
||||
static const char *layoutFilename = "GameSpyGameOptionsMenu.wnd";
|
||||
static const char *parentName = "GameSpyGameOptionsMenuParent";
|
||||
static const char *gadgetsToHide[] =
|
||||
{
|
||||
"MapWindow",
|
||||
"StaticTextGameName",
|
||||
"StaticTextTeam",
|
||||
"StaticTextFaction",
|
||||
"StaticTextColor",
|
||||
"StaticTextPlayers",
|
||||
"TextEntryMapDisplay",
|
||||
"ButtonSelectMap",
|
||||
"ButtonStart",
|
||||
"StaticTextMapPreview",
|
||||
NULL // keep this last
|
||||
};
|
||||
static const char *perPlayerGadgetsToHide[] =
|
||||
{
|
||||
"ComboBoxTeam",
|
||||
"ComboBoxColor",
|
||||
"ComboBoxPlayerTemplate",
|
||||
"ComboBoxPlayer",
|
||||
"ButtonAccept",
|
||||
"GenericPing",
|
||||
//"ButtonStartPosition",
|
||||
NULL // keep this last
|
||||
};
|
||||
|
||||
static const char *qmlayoutFilename = "WOLQuickMatchMenu.wnd";
|
||||
static const char *qmparentName = "WOLQuickMatchMenuParent";
|
||||
static const char *qmgadgetsToHide[] =
|
||||
{
|
||||
"StaticTextTitle",
|
||||
"ButtonBack",
|
||||
"ButtonOptions",
|
||||
"ButtonBuddies",
|
||||
"ButtonWiden",
|
||||
"ButtonStop",
|
||||
"ButtonStart",
|
||||
NULL // keep this last
|
||||
};
|
||||
static const char *qmperPlayerGadgetsToHide[] =
|
||||
{
|
||||
//"ButtonStartPosition",
|
||||
NULL // keep this last
|
||||
};
|
||||
|
||||
static void showGameSpyGameOptionsUnderlyingGUIElements( Bool show )
|
||||
{
|
||||
ShowUnderlyingGUIElements( show, layoutFilename, parentName, gadgetsToHide, perPlayerGadgetsToHide );
|
||||
|
||||
}
|
||||
static void showGameSpyQMUnderlyingGUIElements( Bool show )
|
||||
{
|
||||
ShowUnderlyingGUIElements( show, qmlayoutFilename, qmparentName, qmgadgetsToHide, qmperPlayerGadgetsToHide );
|
||||
}
|
||||
|
||||
static void InitEstablishConnectionsDialog( void ) {
|
||||
buttonQuitID = TheNameKeyGenerator->nameToKey( AsciiString("EstablishConnectionsScreen.wnd:ButtonQuit") );
|
||||
buttonQuitWindow = TheWindowManager->winGetWindowFromId(NULL, buttonQuitID);
|
||||
}
|
||||
|
||||
void ShowEstablishConnectionsWindow( void ) {
|
||||
if (establishConnectionsLayout == NULL) {
|
||||
establishConnectionsLayout = TheWindowManager->winCreateLayout( "Menus/EstablishConnectionsScreen.wnd" );
|
||||
InitEstablishConnectionsDialog();
|
||||
}
|
||||
establishConnectionsLayout->hide(FALSE);
|
||||
TheWindowManager->winSetFocus(establishConnectionsLayout->getFirstWindow());
|
||||
if (!TheGameSpyGame->isQMGame())
|
||||
{
|
||||
showGameSpyGameOptionsUnderlyingGUIElements(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
showGameSpyQMUnderlyingGUIElements(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void HideEstablishConnectionsWindow( void ) {
|
||||
if (establishConnectionsLayout == NULL) {
|
||||
// establishConnectionsLayout = TheWindowManager->winCreateLayout( "Menus/EstablishConnectionsScreen.wnd" );
|
||||
// InitEstablishConnectionsDialog();
|
||||
return;
|
||||
}
|
||||
// establishConnectionsLayout->hide(TRUE);
|
||||
// establishConnectionsLayout->hide(TRUE);
|
||||
// TheWindowManager->winDestroy(establishConnectionsLayout);
|
||||
establishConnectionsLayout->destroyWindows();
|
||||
establishConnectionsLayout->deleteInstance();
|
||||
establishConnectionsLayout = NULL;
|
||||
if (!TheGameSpyGame->isQMGame())
|
||||
{
|
||||
showGameSpyGameOptionsUnderlyingGUIElements(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
showGameSpyQMUnderlyingGUIElements(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
WindowMsgHandledType EstablishConnectionsControlInput(GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2) {
|
||||
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
|
||||
WindowMsgHandledType EstablishConnectionsControlSystem(GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2) {
|
||||
|
||||
switch (msg) {
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if (controlID == buttonQuitID) {
|
||||
TheEstablishConnectionsMenu->abortGame();
|
||||
}
|
||||
break;
|
||||
}
|
||||
} // end switch
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
** 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: GameInfoWindow.cpp ////////////////////////////////////////////////////////////////////////
|
||||
// Author: Chris Huybregts, Feb 2002
|
||||
// Description: Game Info window callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/MapUtil.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GameInfoWindow.h"
|
||||
#include "Common/MultiplayerSettings.h"
|
||||
#include "Common/PlayerTemplate.h"
|
||||
#include "GameNetwork/GameInfo.h"
|
||||
#include "GameNetwork/LANAPI.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
static GameWindow *parent = NULL;
|
||||
static GameWindow *staticTextGameName = NULL;
|
||||
static GameWindow *staticTextMapName = NULL;
|
||||
static GameWindow *listBoxPlayers = NULL;
|
||||
static GameWindow *winCrates = NULL;
|
||||
static GameWindow *winSuperWeapons = NULL;
|
||||
static GameWindow *winFreeForAll = NULL;
|
||||
|
||||
static NameKeyType parentID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextGameNameID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextMapNameID = NAMEKEY_INVALID;
|
||||
static NameKeyType listBoxPlayersID = NAMEKEY_INVALID;
|
||||
static NameKeyType winCratesID = NAMEKEY_INVALID;
|
||||
static NameKeyType winSuperWeaponsID = NAMEKEY_INVALID;
|
||||
static NameKeyType winFreeForAllID = NAMEKEY_INVALID;
|
||||
|
||||
static WindowLayout *gameInfoWindowLayout = NULL;
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CreateLANGameInfoWindow( GameWindow *sizeAndPosWin )
|
||||
{
|
||||
if( !gameInfoWindowLayout )
|
||||
gameInfoWindowLayout = TheWindowManager->winCreateLayout( AsciiString( "Menus/GameInfoWindow.wnd" ) );
|
||||
|
||||
gameInfoWindowLayout->runInit();
|
||||
gameInfoWindowLayout->bringForward();
|
||||
gameInfoWindowLayout->hide( TRUE );
|
||||
|
||||
if( !parent || !sizeAndPosWin )
|
||||
return;
|
||||
Int x, y, width, height;
|
||||
sizeAndPosWin->winGetScreenPosition(&x,&y);
|
||||
parent->winSetPosition(x,y);
|
||||
|
||||
sizeAndPosWin->winGetSize( &width, &height );
|
||||
parent->winSetSize(width, height);
|
||||
|
||||
}
|
||||
|
||||
void DestroyGameInfoWindow(void)
|
||||
{
|
||||
if (gameInfoWindowLayout)
|
||||
{
|
||||
gameInfoWindowLayout->destroyWindows();
|
||||
gameInfoWindowLayout->deleteInstance();
|
||||
gameInfoWindowLayout = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void RefreshGameInfoWindow(GameInfo *gameInfo, UnicodeString gameName)
|
||||
{
|
||||
static const Image *randomIcon = TheMappedImageCollection->findImageByName("GameinfoRANDOM");
|
||||
static const Image *observerIcon = TheMappedImageCollection->findImageByName("GameinfoOBSRVR");
|
||||
if(!gameInfoWindowLayout || !gameInfo )
|
||||
return;
|
||||
|
||||
parent->winHide( FALSE );
|
||||
parent->winBringToTop();
|
||||
|
||||
// Set the game name
|
||||
GadgetStaticTextSetText(staticTextGameName, ((LANGameInfo *)gameInfo)->getPlayerName(0));
|
||||
// set the map name
|
||||
UnicodeString map;
|
||||
AsciiString asciiMap = gameInfo->getMap();
|
||||
asciiMap.toLower();
|
||||
std::map<AsciiString, MapMetaData>::iterator it = TheMapCache->find(asciiMap);
|
||||
if (it != TheMapCache->end())
|
||||
{
|
||||
map = it->second.m_displayName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// can happen if the map will have to be transferred... so use the leaf name (srj)
|
||||
const char *noPath = gameInfo->getMap().reverseFind('\\');
|
||||
if (noPath)
|
||||
{
|
||||
++noPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
noPath = gameInfo->getMap().str();
|
||||
}
|
||||
map.translate(noPath);
|
||||
}
|
||||
GadgetStaticTextSetText(staticTextMapName,map);
|
||||
|
||||
// fill in the player list
|
||||
|
||||
GadgetListBoxReset(listBoxPlayers);
|
||||
|
||||
Int numColors = TheMultiplayerSettings->getNumColors();
|
||||
Color white = GameMakeColor(255,255,255,255);
|
||||
// Color grey = GameMakeColor(188,188,188,255);
|
||||
for (Int i = 0; i < MAX_SLOTS; i ++)
|
||||
{
|
||||
Color playerColor = white;
|
||||
Int color = -1;
|
||||
Int addedRow;
|
||||
GameSlot *slot = gameInfo->getSlot(i);
|
||||
if(!slot || (slot->isOccupied() == FALSE))
|
||||
continue;
|
||||
color = slot->getColor();
|
||||
if(color > -1 && color < numColors)
|
||||
{
|
||||
MultiplayerColorDefinition *def = TheMultiplayerSettings->getColor(color);
|
||||
playerColor = def->getColor();
|
||||
}
|
||||
if(slot->isAI())
|
||||
{
|
||||
switch(slot->getState())
|
||||
{
|
||||
case SLOT_EASY_AI:
|
||||
{
|
||||
addedRow = GadgetListBoxAddEntryText(listBoxPlayers,TheGameText->fetch("GUI:EasyAI"),playerColor,-1, 1);
|
||||
break;
|
||||
}
|
||||
case SLOT_MED_AI:
|
||||
{
|
||||
addedRow = GadgetListBoxAddEntryText(listBoxPlayers,TheGameText->fetch("GUI:MediumAI"),playerColor,-1, 1);
|
||||
break;
|
||||
}
|
||||
case SLOT_BRUTAL_AI:
|
||||
{
|
||||
addedRow = GadgetListBoxAddEntryText(listBoxPlayers,TheGameText->fetch("GUI:HardAI"),playerColor,-1, 1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(slot->isHuman())
|
||||
{
|
||||
addedRow = GadgetListBoxAddEntryText(listBoxPlayers, slot->getName(),playerColor,-1,1);
|
||||
}
|
||||
Int playerTemplate = slot->getPlayerTemplate();
|
||||
if(playerTemplate == PLAYERTEMPLATE_OBSERVER)
|
||||
{
|
||||
GadgetListBoxAddEntryImage(listBoxPlayers, observerIcon,addedRow, 0, 22,25);
|
||||
}
|
||||
else if(playerTemplate < 0 || playerTemplate >= ThePlayerTemplateStore->getPlayerTemplateCount())
|
||||
{
|
||||
///< @todo: When we get art that shows player's side, then we'll actually draw the art instead of putting in text
|
||||
GadgetListBoxAddEntryImage(listBoxPlayers, randomIcon,addedRow, 0, 22,25);
|
||||
//GadgetListBoxAddEntryText(listBoxPlayers,TheGameText->fetch("GUI:???"),playerColor,addedRow, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const PlayerTemplate *fact = ThePlayerTemplateStore->getNthPlayerTemplate(playerTemplate);
|
||||
GadgetListBoxAddEntryImage(listBoxPlayers, fact->getSideIconImage(),addedRow, 0, 22,25);
|
||||
//GadgetListBoxAddEntryText(listBoxPlayers,fact->getDisplayName(),playerColor,addedRow, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void HideGameInfoWindow(Bool hide)
|
||||
{
|
||||
if(!parent)
|
||||
return;
|
||||
parent->winHide(hide);
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the GameInfoWindow */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void GameInfoWindowInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
parentID = TheNameKeyGenerator->nameToKey( "GameInfoWindow.wnd:ParentGameInfo" );
|
||||
staticTextGameNameID = TheNameKeyGenerator->nameToKey( "GameInfoWindow.wnd:StaticTextGameName" );
|
||||
staticTextMapNameID = TheNameKeyGenerator->nameToKey( "GameInfoWindow.wnd:StaticTextMapName" );
|
||||
listBoxPlayersID = TheNameKeyGenerator->nameToKey( "GameInfoWindow.wnd:ListBoxPlayers" );
|
||||
winCratesID = TheNameKeyGenerator->nameToKey( "GameInfoWindow.wnd:WinCrates" );
|
||||
winSuperWeaponsID = TheNameKeyGenerator->nameToKey( "GameInfoWindow.wnd:WinSuperWeapons" );
|
||||
winFreeForAllID = TheNameKeyGenerator->nameToKey( "GameInfoWindow.wnd:WinFreeForAll" );
|
||||
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
staticTextGameName = TheWindowManager->winGetWindowFromId( parent, staticTextGameNameID );
|
||||
staticTextMapName = TheWindowManager->winGetWindowFromId( parent, staticTextMapNameID );
|
||||
listBoxPlayers = TheWindowManager->winGetWindowFromId( parent, listBoxPlayersID );
|
||||
winCrates = TheWindowManager->winGetWindowFromId( parent, winCratesID );
|
||||
winSuperWeapons = TheWindowManager->winGetWindowFromId( parent, winSuperWeaponsID );
|
||||
winFreeForAll = TheWindowManager->winGetWindowFromId( parent, winFreeForAllID );
|
||||
|
||||
GadgetStaticTextSetText(staticTextGameName,UnicodeString.TheEmptyString);
|
||||
GadgetStaticTextSetText(staticTextMapName,UnicodeString.TheEmptyString);
|
||||
GadgetListBoxReset(listBoxPlayers);
|
||||
|
||||
} // end MapSelectMenuInit
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** GameInfo window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType GameInfoWindowSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
// might use these later
|
||||
// GameWindow *control = (GameWindow *)mData1;
|
||||
// Int controlID = control->winGetWindowId();
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end MapSelectMenuSystem
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,876 @@
|
||||
/*
|
||||
** 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: LanLobbyMenu.cpp
|
||||
// Author: Chris Huybregts, October 2001
|
||||
// Description: Lan Lobby Menu
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Lib/BaseType.h"
|
||||
#include "Common/CRC.h"
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/MultiplayerSettings.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerTemplate.h"
|
||||
#include "Common/QuotedPrintable.h"
|
||||
#include "Common/UserPreferences.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/MapUtil.h"
|
||||
#include "GameClient/Mouse.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/ShellHooks.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameInfoWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/MessageBox.h"
|
||||
#include "GameClient/GameWindowTransitions.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameNetwork/IPEnumeration.h"
|
||||
#include "GameNetwork/LANAPICallbacks.h"
|
||||
#include "GameNetwork/LANGameInfo.h"
|
||||
|
||||
Bool LANisShuttingDown = false;
|
||||
Bool LANbuttonPushed = false;
|
||||
Bool LANSocketErrorDetected = FALSE;
|
||||
char *LANnextScreen = NULL;
|
||||
|
||||
static Int initialGadgetDelay = 2;
|
||||
static Bool justEntered = FALSE;
|
||||
|
||||
|
||||
|
||||
LANPreferences::LANPreferences( void )
|
||||
{
|
||||
// note, the superclass will put this in the right dir automatically, this is just a leaf name
|
||||
load("Network.ini");
|
||||
}
|
||||
|
||||
LANPreferences::~LANPreferences()
|
||||
{
|
||||
}
|
||||
|
||||
UnicodeString LANPreferences::getUserName(void)
|
||||
{
|
||||
UnicodeString ret;
|
||||
LANPreferences::const_iterator it = find("UserName");
|
||||
if (it == end())
|
||||
{
|
||||
IPEnumeration IPs;
|
||||
ret.translate(IPs.getMachineName());
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = QuotedPrintableToUnicodeString(it->second);
|
||||
ret.trim();
|
||||
if (ret.isEmpty())
|
||||
{
|
||||
IPEnumeration IPs;
|
||||
ret.translate(IPs.getMachineName());
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Int LANPreferences::getPreferredColor(void)
|
||||
{
|
||||
Int ret;
|
||||
LANPreferences::const_iterator it = find("Color");
|
||||
if (it == end())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = atoi(it->second.str());
|
||||
if (ret < -1 || ret >= TheMultiplayerSettings->getNumColors())
|
||||
ret = -1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Int LANPreferences::getPreferredFaction(void)
|
||||
{
|
||||
Int ret;
|
||||
LANPreferences::const_iterator it = find("PlayerTemplate");
|
||||
if (it == end())
|
||||
{
|
||||
return PLAYERTEMPLATE_RANDOM;
|
||||
}
|
||||
|
||||
ret = atoi(it->second.str());
|
||||
if (ret == PLAYERTEMPLATE_OBSERVER || ret < PLAYERTEMPLATE_MIN || ret >= ThePlayerTemplateStore->getPlayerTemplateCount())
|
||||
ret = PLAYERTEMPLATE_RANDOM;
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
const PlayerTemplate *fac = ThePlayerTemplateStore->getNthPlayerTemplate(ret);
|
||||
if (!fac)
|
||||
ret = PLAYERTEMPLATE_RANDOM;
|
||||
else if (fac->getStartingBuilding().isEmpty())
|
||||
ret = PLAYERTEMPLATE_RANDOM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool LANPreferences::usesSystemMapDir(void)
|
||||
{
|
||||
OptionPreferences::const_iterator it = find("UseSystemMapDir");
|
||||
if (it == end())
|
||||
return TRUE;
|
||||
|
||||
if (stricmp(it->second.str(), "yes") == 0) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
AsciiString LANPreferences::getPreferredMap(void)
|
||||
{
|
||||
AsciiString ret;
|
||||
LANPreferences::const_iterator it = find("Map");
|
||||
if (it == end())
|
||||
{
|
||||
ret = getDefaultMap(TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = QuotedPrintableToAsciiString(it->second);
|
||||
ret.trim();
|
||||
if (ret.isEmpty() || !isValidMap(ret, TRUE))
|
||||
{
|
||||
ret = getDefaultMap(TRUE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Int LANPreferences::getNumRemoteIPs(void)
|
||||
{
|
||||
Int ret;
|
||||
LANPreferences::const_iterator it = find("NumRemoteIPs");
|
||||
if (it == end())
|
||||
{
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = atoi(it->second.str());
|
||||
return ret;
|
||||
}
|
||||
|
||||
UnicodeString LANPreferences::getRemoteIPEntry(Int i)
|
||||
{
|
||||
UnicodeString ret;
|
||||
AsciiString key;
|
||||
key.format("RemoteIP%d", i);
|
||||
|
||||
AsciiString ipstr;
|
||||
AsciiString asciientry;
|
||||
|
||||
LANPreferences::const_iterator it = find(key.str());
|
||||
if (it == end())
|
||||
{
|
||||
asciientry = "";
|
||||
return ret;
|
||||
}
|
||||
|
||||
asciientry = it->second;
|
||||
|
||||
asciientry.nextToken(&ipstr, ":");
|
||||
asciientry.set(asciientry.str() + 1); // skip the ':'
|
||||
|
||||
ret.translate(ipstr);
|
||||
if (asciientry.getLength() > 0)
|
||||
{
|
||||
ret.concat(L"(");
|
||||
ret.concat(QuotedPrintableToUnicodeString(asciientry));
|
||||
ret.concat(L")");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// window ids ------------------------------------------------------------------------------
|
||||
static NameKeyType parentLanLobbyID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonBackID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonClearID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonHostID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonJoinID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonDirectConnectID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonEmoteID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticToolTipID = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryPlayerNameID = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryChatID = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxPlayersID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextGameInfoID = NAMEKEY_INVALID;
|
||||
|
||||
|
||||
// Window Pointers ------------------------------------------------------------------------
|
||||
static GameWindow *parentLanLobby = NULL;
|
||||
static GameWindow *buttonBack = NULL;
|
||||
static GameWindow *buttonClear = NULL;
|
||||
static GameWindow *buttonHost = NULL;
|
||||
static GameWindow *buttonJoin = NULL;
|
||||
static GameWindow *buttonDirectConnect = NULL;
|
||||
static GameWindow *buttonEmote = NULL;
|
||||
static GameWindow *staticToolTip = NULL;
|
||||
static GameWindow *textEntryPlayerName = NULL;
|
||||
static GameWindow *textEntryChat = NULL;
|
||||
static GameWindow *staticTextGameInfo = NULL;
|
||||
|
||||
//external declarations of the Gadgets the callbacks can use
|
||||
NameKeyType listboxChatWindowID = NAMEKEY_INVALID;
|
||||
GameWindow *listboxChatWindow = NULL;
|
||||
GameWindow *listboxPlayers = NULL;
|
||||
NameKeyType listboxGamesID = NAMEKEY_INVALID;
|
||||
GameWindow *listboxGames = NULL;
|
||||
|
||||
// hack to disable framerate limiter in LAN games
|
||||
//static Bool shellmapOn;
|
||||
static Bool useFpsLimit;
|
||||
static UnicodeString defaultName;
|
||||
|
||||
static void playerTooltip(GameWindow *window,
|
||||
WinInstanceData *instData,
|
||||
UnsignedInt mouse)
|
||||
{
|
||||
Int x, y, row, col;
|
||||
x = LOLONGTOSHORT(mouse);
|
||||
y = HILONGTOSHORT(mouse);
|
||||
|
||||
GadgetListBoxGetEntryBasedOnXY(window, x, y, row, col);
|
||||
|
||||
if (row == -1 || col == -1)
|
||||
{
|
||||
//TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:LobbyPlayers") );
|
||||
return;
|
||||
}
|
||||
|
||||
UnsignedInt playerIP = (UnsignedInt)GadgetListBoxGetItemData( window, row, col );
|
||||
LANPlayer *player = TheLAN->LookupPlayer(playerIP);
|
||||
if (!player)
|
||||
{
|
||||
DEBUG_CRASH(("No player info in listbox!"));
|
||||
//TheMouse->setCursorTooltip( TheGameText->fetch("TOOLTIP:LobbyPlayers") );
|
||||
return;
|
||||
}
|
||||
UnicodeString tooltip;
|
||||
tooltip.format(TheGameText->fetch("TOOLTIP:LANPlayer"), player->getName().str(), player->getLogin().str(), player->getHost().str());
|
||||
TheMouse->setCursorTooltip( tooltip );
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the Lan Lobby Menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void LanLobbyMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
LANnextScreen = NULL;
|
||||
LANbuttonPushed = false;
|
||||
LANisShuttingDown = false;
|
||||
|
||||
// get the ids for our controls
|
||||
parentLanLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:LanLobbyMenuParent" ) );
|
||||
buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ButtonBack" ) );
|
||||
buttonClearID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ButtonClear" ) );
|
||||
buttonHostID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ButtonHost" ) );
|
||||
buttonJoinID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ButtonJoin" ) );
|
||||
buttonDirectConnectID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ButtonDirectConnect" ) );
|
||||
buttonEmoteID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ButtonEmote" ) );
|
||||
staticToolTipID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:StaticToolTip" ) );
|
||||
textEntryPlayerNameID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:TextEntryPlayerName" ) );
|
||||
textEntryChatID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:TextEntryChat" ) );
|
||||
listboxPlayersID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ListboxPlayers" ) );
|
||||
listboxChatWindowID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ListboxChatWindowLanLobby" ) );
|
||||
listboxGamesID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:ListboxGames" ) );
|
||||
staticTextGameInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "LanLobbyMenu.wnd:StaticTextGameInfo" ) );
|
||||
|
||||
|
||||
// Get pointers to the window buttons
|
||||
parentLanLobby = TheWindowManager->winGetWindowFromId( NULL, parentLanLobbyID );
|
||||
buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID);
|
||||
buttonClear = TheWindowManager->winGetWindowFromId( NULL, buttonClearID);
|
||||
buttonHost = TheWindowManager->winGetWindowFromId( NULL, buttonHostID );
|
||||
buttonJoin = TheWindowManager->winGetWindowFromId( NULL, buttonJoinID );
|
||||
buttonDirectConnect = TheWindowManager->winGetWindowFromId( NULL, buttonDirectConnectID );
|
||||
buttonEmote = TheWindowManager->winGetWindowFromId( NULL,buttonEmoteID );
|
||||
staticToolTip = TheWindowManager->winGetWindowFromId( NULL, staticToolTipID );
|
||||
textEntryPlayerName = TheWindowManager->winGetWindowFromId( NULL, textEntryPlayerNameID );
|
||||
textEntryChat = TheWindowManager->winGetWindowFromId( NULL, textEntryChatID );
|
||||
listboxPlayers = TheWindowManager->winGetWindowFromId( NULL, listboxPlayersID );
|
||||
listboxChatWindow = TheWindowManager->winGetWindowFromId( NULL, listboxChatWindowID );
|
||||
listboxGames = TheWindowManager->winGetWindowFromId( NULL, listboxGamesID );
|
||||
staticTextGameInfo = TheWindowManager->winGetWindowFromId( NULL, staticTextGameInfoID );
|
||||
listboxPlayers->winSetTooltipFunc(playerTooltip);
|
||||
|
||||
// Show Menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// Init LAN API Singleton
|
||||
if (!TheLAN)
|
||||
{
|
||||
TheLAN = NEW LANAPI(); /// @todo clh delete TheLAN and
|
||||
useFpsLimit = TheGlobalData->m_useFpsLimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
TheWritableGlobalData->m_useFpsLimit = useFpsLimit;
|
||||
TheLAN->reset();
|
||||
}
|
||||
|
||||
// Choose an IP address, then initialize the LAN singleton
|
||||
UnsignedInt IP = TheGlobalData->m_defaultIP;
|
||||
IPEnumeration IPs;
|
||||
|
||||
if (!IP)
|
||||
{
|
||||
EnumeratedIP *IPlist = IPs.getAddresses();
|
||||
/*
|
||||
while (IPlist && IPlist->getNext())
|
||||
{
|
||||
IPlist = IPlist->getNext();
|
||||
}
|
||||
*/
|
||||
DEBUG_ASSERTCRASH(IPlist, ("No IP addresses found!"));
|
||||
if (!IPlist)
|
||||
{
|
||||
/// @todo: display error and exit lan lobby if no IPs are found
|
||||
}
|
||||
|
||||
//UnicodeString str;
|
||||
//str.format(L"Local IP chosen: %hs", IPlist->getIPstring().str());
|
||||
//GadgetListBoxAddEntryText(listboxChatWindow, str, chatSystemColor, -1, 0);
|
||||
IP = IPlist->getIP();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
UnicodeString str;
|
||||
str.format(L"Default local IP: %d.%d.%d.%d",
|
||||
(IP >> 24),
|
||||
(IP >> 16) & 0xFF,
|
||||
(IP >> 8) & 0xFF,
|
||||
IP & 0xFF);
|
||||
GadgetListBoxAddEntryText(listboxChatWindow, str, chatSystemColor, -1, 0);
|
||||
*/
|
||||
}
|
||||
|
||||
// TheLAN->init() sets us to be in a LAN menu screen automatically.
|
||||
TheLAN->init();
|
||||
if (TheLAN->SetLocalIP(IP) == FALSE) {
|
||||
LANSocketErrorDetected = TRUE;
|
||||
}
|
||||
|
||||
//Initialize the gadgets on the window
|
||||
//UnicodeString txtInput;
|
||||
//txtInput.translate(IPs.getMachineName());
|
||||
LANPreferences prefs;
|
||||
defaultName = prefs.getUserName();
|
||||
while (defaultName.getLength() > g_lanPlayerNameLength)
|
||||
defaultName.removeLastChar();
|
||||
GadgetTextEntrySetText( textEntryPlayerName, defaultName);
|
||||
// Clear the text entry line
|
||||
GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString);
|
||||
|
||||
GadgetListBoxReset(listboxPlayers);
|
||||
GadgetListBoxReset(listboxGames);
|
||||
|
||||
while (defaultName.getLength() > g_lanPlayerNameLength)
|
||||
defaultName.removeLastChar();
|
||||
TheLAN->RequestSetName(defaultName);
|
||||
TheLAN->RequestLocations();
|
||||
|
||||
/*
|
||||
UnicodeString unicodeChat;
|
||||
|
||||
unicodeChat = L"Local IP list:";
|
||||
GadgetListBoxAddEntryText(listboxChatWindow, unicodeChat, chatSystemColor, -1, 0);
|
||||
|
||||
IPlist = IPs.getAddresses();
|
||||
while (IPlist)
|
||||
{
|
||||
unicodeChat.translate(IPlist->getIPstring());
|
||||
GadgetListBoxAddEntryText(listboxChatWindow, unicodeChat, chatSystemColor, -1, 0);
|
||||
IPlist = IPlist->getNext();
|
||||
}
|
||||
*/
|
||||
|
||||
// Set Keyboard to Main Parent
|
||||
//TheWindowManager->winSetFocus( parentLanLobby );
|
||||
TheWindowManager->winSetFocus( textEntryChat );
|
||||
CreateLANGameInfoWindow(staticTextGameInfo);
|
||||
|
||||
//TheShell->showShellMap(FALSE);
|
||||
//shellmapOn = FALSE;
|
||||
// coming out of a game, re-load the shell map
|
||||
TheShell->showShellMap(TRUE);
|
||||
|
||||
// check for MOTD
|
||||
TheLAN->checkMOTD();
|
||||
layout->hide(FALSE);
|
||||
layout->bringForward();
|
||||
|
||||
justEntered = TRUE;
|
||||
initialGadgetDelay = 2;
|
||||
GameWindow *win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("LanLobbyMenu.wnd:GadgetParent"));
|
||||
if(win)
|
||||
win->winHide(TRUE);
|
||||
|
||||
|
||||
// animate controls
|
||||
//TheShell->registerWithAnimateManager(parentLanLobby, WIN_ANIMATION_SLIDE_TOP, TRUE);
|
||||
// TheShell->registerWithAnimateManager(buttonHost, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600);
|
||||
// TheShell->registerWithAnimateManager(buttonJoin, WIN_ANIMATION_SLIDE_LEFT, TRUE, 400);
|
||||
// TheShell->registerWithAnimateManager(buttonDirectConnect, WIN_ANIMATION_SLIDE_LEFT, TRUE, 200);
|
||||
// //TheShell->registerWithAnimateManager(buttonOptions, WIN_ANIMATION_SLIDE_LEFT, TRUE, 1);
|
||||
// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_RIGHT, TRUE, 1);
|
||||
|
||||
} // GameLobbyMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** This is called when a shutdown is complete for this menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static void shutdownComplete( WindowLayout *layout )
|
||||
{
|
||||
|
||||
LANisShuttingDown = false;
|
||||
|
||||
// hide the layout
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout, (LANnextScreen != NULL) );
|
||||
|
||||
if (LANnextScreen != NULL)
|
||||
{
|
||||
TheShell->push(LANnextScreen);
|
||||
}
|
||||
|
||||
LANnextScreen = NULL;
|
||||
|
||||
} // end if
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Lan Lobby menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void LanLobbyMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
LANPreferences prefs;
|
||||
prefs["UserName"] = UnicodeStringToQuotedPrintable(GadgetTextEntryGetText( textEntryPlayerName ));
|
||||
prefs.write();
|
||||
|
||||
DestroyGameInfoWindow();
|
||||
// hide menu
|
||||
//layout->hide( TRUE );
|
||||
|
||||
TheLAN->RequestLobbyLeave( true );
|
||||
|
||||
// Reset the LAN singleton
|
||||
//TheLAN->reset();
|
||||
|
||||
// our shutdown is complete
|
||||
//TheShell->shutdownComplete( layout );
|
||||
TheWritableGlobalData->m_useFpsLimit = useFpsLimit;
|
||||
|
||||
LANisShuttingDown = true;
|
||||
|
||||
// if we are shutting down for an immediate pop, skip the animations
|
||||
Bool popImmediate = *(Bool *)userData;
|
||||
|
||||
LANSocketErrorDetected = FALSE;
|
||||
|
||||
if( popImmediate )
|
||||
{
|
||||
|
||||
shutdownComplete( layout );
|
||||
return;
|
||||
|
||||
} //end if
|
||||
|
||||
TheShell->reverseAnimatewindow();
|
||||
TheTransitionHandler->reverse("LanLobbyFade");
|
||||
//if( shellmapOn)
|
||||
// TheShell->showShellMap(TRUE);
|
||||
} // LanLobbyMenuShutdown
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Lan Lobby menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void LanLobbyMenuUpdate( WindowLayout * layout, void *userData)
|
||||
{
|
||||
if (TheGameLogic->isInShellGame() && TheGameLogic->getFrame() == 1)
|
||||
{
|
||||
SignalUIInteraction(SHELL_SCRIPT_HOOK_LAN_ENTERED_FROM_GAME);
|
||||
}
|
||||
|
||||
if(justEntered)
|
||||
{
|
||||
if(initialGadgetDelay == 1)
|
||||
{
|
||||
TheTransitionHandler->setGroup("LanLobbyFade");
|
||||
initialGadgetDelay = 2;
|
||||
justEntered = FALSE;
|
||||
}
|
||||
else
|
||||
initialGadgetDelay--;
|
||||
}
|
||||
|
||||
if(LANisShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished())
|
||||
shutdownComplete(layout);
|
||||
|
||||
if (TheShell->isAnimFinished() && !LANbuttonPushed && TheLAN)
|
||||
TheLAN->update();
|
||||
|
||||
if (LANSocketErrorDetected == TRUE) {
|
||||
LANSocketErrorDetected = FALSE;
|
||||
DEBUG_LOG(("SOCKET ERROR! BAILING!\n"));
|
||||
MessageBoxOk(TheGameText->fetch("GUI:NetworkError"), TheGameText->fetch("GUI:SocketError"), NULL);
|
||||
|
||||
// we have a socket problem, back out to the main menu.
|
||||
TheWindowManager->winSendSystemMsg(buttonBack->winGetParent(), GBM_SELECTED,
|
||||
(WindowMsgData)buttonBack, buttonBackID);
|
||||
}
|
||||
|
||||
|
||||
}// LanLobbyMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Lan Lobby menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType LanLobbyMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
if (LANbuttonPushed)
|
||||
break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonBack, buttonBackID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}// LanLobbyMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Lan Lobby menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType LanLobbyMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
SignalUIInteraction(SHELL_SCRIPT_HOOK_LAN_OPENED);
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
SignalUIInteraction(SHELL_SCRIPT_HOOK_LAN_CLOSED);
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
case GLM_DOUBLE_CLICKED:
|
||||
{
|
||||
if (LANbuttonPushed)
|
||||
break;
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxGamesID )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
|
||||
if (rowSelected >= 0)
|
||||
{
|
||||
LANGameInfo * theGame = TheLAN->LookupGameByListOffset(rowSelected);
|
||||
if (theGame)
|
||||
{
|
||||
TheLAN->RequestGameJoin(theGame);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GLM_SELECTED:
|
||||
{
|
||||
if (LANbuttonPushed)
|
||||
break;
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxGamesID )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
if( rowSelected < 0 )
|
||||
{
|
||||
HideGameInfoWindow(TRUE);
|
||||
break;
|
||||
}
|
||||
LANGameInfo * theGame = TheLAN->LookupGameByListOffset(rowSelected);
|
||||
if (theGame)
|
||||
RefreshGameInfoWindow(theGame, theGame->getName());
|
||||
else
|
||||
HideGameInfoWindow(TRUE);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
if (LANbuttonPushed)
|
||||
break;
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == buttonBackID )
|
||||
{
|
||||
//shellmapOn = TRUE;
|
||||
LANbuttonPushed = true;
|
||||
DEBUG_LOG(("Back was hit - popping to main menu\n"));
|
||||
TheShell->pop();
|
||||
delete TheLAN;
|
||||
TheLAN = NULL;
|
||||
//TheTransitionHandler->reverse("LanLobbyFade");
|
||||
|
||||
} //if ( controlID == buttonBack )
|
||||
else if ( controlID == buttonHostID )
|
||||
{
|
||||
TheLAN->RequestGameCreate( UnicodeString(L""), FALSE);
|
||||
|
||||
}//else if ( controlID == buttonHostID )
|
||||
else if ( controlID == buttonClearID )
|
||||
{
|
||||
GadgetTextEntrySetText(textEntryPlayerName, UnicodeString::TheEmptyString);
|
||||
TheWindowManager->winSendSystemMsg( window,
|
||||
GEM_UPDATE_TEXT,
|
||||
(WindowMsgData)textEntryPlayerName,
|
||||
0 );
|
||||
|
||||
}
|
||||
else if ( controlID == buttonJoinID )
|
||||
{
|
||||
|
||||
//TheShell->push( AsciiString("Menus/LanGameOptionsMenu.wnd") );
|
||||
|
||||
int rowSelected = -1;
|
||||
GadgetListBoxGetSelected( listboxGames, &rowSelected );
|
||||
|
||||
if (rowSelected >= 0)
|
||||
{
|
||||
LANGameInfo * theGame = TheLAN->LookupGameByListOffset(rowSelected);
|
||||
if (theGame)
|
||||
{
|
||||
TheLAN->RequestGameJoin(theGame);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GadgetListBoxAddEntryText(listboxChatWindow, TheGameText->fetch("LAN:ErrorNoGameSelected") , chatSystemColor, -1, 0);
|
||||
}
|
||||
|
||||
} //else if ( controlID == buttonJoinID )
|
||||
else if ( controlID == buttonEmoteID )
|
||||
{
|
||||
// read the user's input
|
||||
txtInput.set(GadgetTextEntryGetText( textEntryChat ));
|
||||
// Clear the text entry line
|
||||
GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString);
|
||||
// Clean up the text (remove leading/trailing chars, etc)
|
||||
txtInput.trim();
|
||||
// Echo the user's input to the chat window
|
||||
if (!txtInput.isEmpty()) {
|
||||
// TheLAN->RequestChat(txtInput, LANAPIInterface::LANCHAT_EMOTE);
|
||||
TheLAN->RequestChat(txtInput, LANAPIInterface::LANCHAT_NORMAL);
|
||||
}
|
||||
} //if ( controlID == buttonEmote )
|
||||
else if (controlID == buttonDirectConnectID)
|
||||
{
|
||||
TheLAN->RequestLobbyLeave( false );
|
||||
TheShell->push(AsciiString("Menus/NetworkDirectConnect.wnd"));
|
||||
}
|
||||
|
||||
break;
|
||||
}// case GBM_SELECTED:
|
||||
|
||||
case GEM_UPDATE_TEXT:
|
||||
{
|
||||
if (LANbuttonPushed)
|
||||
break;
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == textEntryPlayerNameID )
|
||||
{
|
||||
// grab the user's name
|
||||
txtInput.set(GadgetTextEntryGetText( textEntryPlayerName ));
|
||||
|
||||
// Clean up the text (remove leading/trailing chars, etc)
|
||||
const WideChar *c = txtInput.str();
|
||||
while (c && (iswspace(*c)))
|
||||
c++;
|
||||
|
||||
if (c)
|
||||
txtInput = UnicodeString(c);
|
||||
else
|
||||
txtInput = UnicodeString::TheEmptyString;
|
||||
|
||||
while (txtInput.getLength() > g_lanPlayerNameLength)
|
||||
txtInput.removeLastChar();
|
||||
|
||||
if (!txtInput.isEmpty() && txtInput.getCharAt(txtInput.getLength()-1) == L',')
|
||||
txtInput.removeLastChar(); // we use , for strtok's so we can't allow them in names. :(
|
||||
|
||||
if (!txtInput.isEmpty() && txtInput.getCharAt(txtInput.getLength()-1) == L':')
|
||||
txtInput.removeLastChar(); // we use : for strtok's so we can't allow them in names. :(
|
||||
|
||||
if (!txtInput.isEmpty() && txtInput.getCharAt(txtInput.getLength()-1) == L';')
|
||||
txtInput.removeLastChar(); // we use ; for strtok's so we can't allow them in names. :(
|
||||
|
||||
// send it over the network
|
||||
if (!txtInput.isEmpty())
|
||||
TheLAN->RequestSetName(txtInput);
|
||||
else
|
||||
{
|
||||
TheLAN->RequestSetName(defaultName);
|
||||
}
|
||||
|
||||
// Put the whitespace-free version in the box
|
||||
GadgetTextEntrySetText( textEntryPlayerName, txtInput );
|
||||
|
||||
}// if ( controlID == textEntryPlayerNameID )
|
||||
break;
|
||||
}//case GEM_UPDATE_TEXT:
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
if (LANbuttonPushed)
|
||||
break;
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
// Take the user's input and echo it into the chat window as well as
|
||||
// send it to the other clients on the lan
|
||||
if ( controlID == textEntryChatID )
|
||||
{
|
||||
|
||||
// read the user's input
|
||||
txtInput.set(GadgetTextEntryGetText( textEntryChat ));
|
||||
// Clear the text entry line
|
||||
GadgetTextEntrySetText(textEntryChat, UnicodeString::TheEmptyString);
|
||||
// Clean up the text (remove leading/trailing chars, etc)
|
||||
while (!txtInput.isEmpty() && iswspace(txtInput.getCharAt(0)))
|
||||
txtInput = UnicodeString(txtInput.str()+1);
|
||||
|
||||
// Echo the user's input to the chat window
|
||||
if (!txtInput.isEmpty())
|
||||
TheLAN->RequestChat(txtInput, LANAPIInterface::LANCHAT_NORMAL);
|
||||
|
||||
}// if ( controlID == textEntryChatID )
|
||||
/*
|
||||
else if ( controlID == textEntryPlayerNameID )
|
||||
{
|
||||
// grab the user's name
|
||||
txtInput.set(GadgetTextEntryGetText( textEntryPlayerName ));
|
||||
|
||||
// Clean up the text (remove leading/trailing chars, etc)
|
||||
txtInput.trim();
|
||||
|
||||
// send it over the network
|
||||
if (!txtInput.isEmpty())
|
||||
TheLAN->RequestSetName(txtInput);
|
||||
|
||||
// Put the whitespace-free version in the box
|
||||
GadgetTextEntrySetText( textEntryPlayerName, txtInput );
|
||||
|
||||
}// if ( controlID == textEntryPlayerNameID )
|
||||
*/
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
}// LanLobbyMenuSystem
|
||||
@@ -0,0 +1,460 @@
|
||||
/*
|
||||
** 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: LanMapSelectMenu.cpp ////////////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, October 2001
|
||||
// Description: MapSelect menu window callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "Common/UserPreferences.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetRadioButton.h"
|
||||
#include "GameNetwork/LANAPICallbacks.h"
|
||||
#include "GameClient/MapUtil.h"
|
||||
#include "GameNetwork/GUIUtil.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static NameKeyType buttonBack = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOK = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxMap = NAMEKEY_INVALID;
|
||||
static NameKeyType winMapPreviewID = NAMEKEY_INVALID;
|
||||
static GameWindow *parent = NULL;
|
||||
static GameWindow *mapList = NULL;
|
||||
static GameWindow *winMapPreview = NULL;
|
||||
static NameKeyType radioButtonSystemMapsID = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonUserMapsID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL };
|
||||
static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID };
|
||||
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
void positionStartSpots( AsciiString mapName, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow);
|
||||
static const char *layoutFilename = "LanGameOptionsMenu.wnd";
|
||||
static const char *parentName = "LanGameOptionsMenuParent";
|
||||
static const char *gadgetsToHide[] =
|
||||
{
|
||||
"MapWindow",
|
||||
//"StaticTextTitle",
|
||||
"StaticTextTeam",
|
||||
"StaticTextFaction",
|
||||
"StaticTextColor",
|
||||
"TextEntryMapDisplay",
|
||||
"ButtonSelectMap",
|
||||
"ButtonStart",
|
||||
"StaticTextMapPreview",
|
||||
|
||||
NULL // keep this last
|
||||
};
|
||||
static const char *perPlayerGadgetsToHide[] =
|
||||
{
|
||||
"ComboBoxTeam",
|
||||
"ComboBoxColor",
|
||||
"ComboBoxPlayerTemplate",
|
||||
NULL // keep this last
|
||||
};
|
||||
|
||||
static void showLANGameOptionsUnderlyingGUIElements( Bool show )
|
||||
{
|
||||
ShowUnderlyingGUIElements( show, layoutFilename, parentName, gadgetsToHide, perPlayerGadgetsToHide );
|
||||
GameWindow *win = TheWindowManager->winGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey("LanGameOptionsMenu.wnd:ButtonBack") );
|
||||
if(win)
|
||||
win->winEnable( show );
|
||||
|
||||
}
|
||||
|
||||
static void NullifyControls()
|
||||
{
|
||||
mapList = NULL;
|
||||
winMapPreview = NULL;
|
||||
parent = NULL;
|
||||
for (Int i=0; i<MAX_SLOTS; ++i)
|
||||
{
|
||||
buttonMapStartPosition[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the MapSelect menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void LanMapSelectMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
showLANGameOptionsUnderlyingGUIElements(FALSE);
|
||||
|
||||
// set keyboard focus to main parent
|
||||
AsciiString parentName( "LanMapSelectMenu.wnd:LanMapSelectMenuParent" );
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
|
||||
LANPreferences pref;
|
||||
Bool usesSystemMapDir = pref.usesSystemMapDir();
|
||||
|
||||
const MapMetaData *mmd = TheMapCache->findMap(TheLAN->GetMyGame()->getMap());
|
||||
if (mmd)
|
||||
{
|
||||
usesSystemMapDir = mmd->m_isOfficial;
|
||||
}
|
||||
|
||||
|
||||
buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("LanMapSelectMenu.wnd:ButtonBack") );
|
||||
buttonOK = TheNameKeyGenerator->nameToKey( AsciiString("LanMapSelectMenu.wnd:ButtonOK") );
|
||||
listboxMap = TheNameKeyGenerator->nameToKey( AsciiString("LanMapSelectMenu.wnd:ListboxMap") );
|
||||
winMapPreviewID = TheNameKeyGenerator->nameToKey( AsciiString("LanMapSelectMenu.wnd:WinMapPreview") );
|
||||
|
||||
radioButtonSystemMapsID = TheNameKeyGenerator->nameToKey( "LanMapSelectMenu.wnd:RadioButtonSystemMaps" );
|
||||
radioButtonUserMapsID = TheNameKeyGenerator->nameToKey( "LanMapSelectMenu.wnd:RadioButtonUserMaps" );
|
||||
GameWindow *radioButtonSystemMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonSystemMapsID );
|
||||
GameWindow *radioButtonUserMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonUserMapsID );
|
||||
winMapPreview = TheWindowManager->winGetWindowFromId(parent, winMapPreviewID);
|
||||
if (usesSystemMapDir)
|
||||
GadgetRadioSetSelection( radioButtonSystemMaps, FALSE );
|
||||
else
|
||||
GadgetRadioSetSelection( radioButtonUserMaps, FALSE );
|
||||
|
||||
AsciiString tmpString;
|
||||
for (Int i = 0; i < MAX_SLOTS; i++)
|
||||
{
|
||||
tmpString.format("LanMapSelectMenu.wnd:ButtonMapStartPosition%d", i);
|
||||
buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString );
|
||||
buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( winMapPreview, buttonMapStartPositionID[i] );
|
||||
DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i ));
|
||||
buttonMapStartPosition[i]->winHide(TRUE);
|
||||
buttonMapStartPosition[i]->winEnable(FALSE);
|
||||
}
|
||||
|
||||
// get the listbox window
|
||||
AsciiString listString( "LanMapSelectMenu.wnd:ListboxMap" );
|
||||
NameKeyType mapListID = TheNameKeyGenerator->nameToKey( listString );
|
||||
mapList = TheWindowManager->winGetWindowFromId( parent, mapListID );
|
||||
if( mapList )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, usesSystemMapDir, TRUE, TheLAN->GetMyGame()->getMap() );
|
||||
}
|
||||
} // end LanMapSelectMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void LanMapSelectMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
NullifyControls();
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
} // end LanMapSelectMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void LanMapSelectMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
} // end LanMapSelectMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Map select menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType LanMapSelectMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
AsciiString buttonName( "LanMapSelectMenu.wnd:ButtonBack" );
|
||||
NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end LanMapSelectMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType LanMapSelectMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
GameWindow *mapWindow = NULL;
|
||||
if (listboxMap != NULL)
|
||||
{
|
||||
mapWindow = TheWindowManager->winGetWindowFromId( parent, listboxMap );
|
||||
}
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
NullifyControls();
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GLM_DOUBLE_CLICKED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxMap )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
|
||||
if (rowSelected >= 0)
|
||||
{
|
||||
GadgetListBoxSetSelected( control, rowSelected );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonOK );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonOK );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == radioButtonSystemMapsID )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, TRUE, TRUE, TheLAN->GetMyGame()->getMap() );
|
||||
LANPreferences pref;
|
||||
pref["UseSystemMapDir"] = "yes";
|
||||
pref.write();
|
||||
}
|
||||
else if ( controlID == radioButtonUserMapsID )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, FALSE, TRUE, TheLAN->GetMyGame()->getMap() );
|
||||
LANPreferences pref;
|
||||
pref["UseSystemMapDir"] = "no";
|
||||
pref.write();
|
||||
}
|
||||
else if ( controlID == buttonBack )
|
||||
{
|
||||
|
||||
mapSelectLayout->destroyWindows();
|
||||
mapSelectLayout->deleteInstance();
|
||||
mapSelectLayout = NULL;
|
||||
// set the controls to NULL since they've been destroyed.
|
||||
NullifyControls();
|
||||
showLANGameOptionsUnderlyingGUIElements(TRUE);
|
||||
PostToLanGameOptions( MAP_BACK );
|
||||
} // end if
|
||||
else if ( controlID == buttonOK )
|
||||
{
|
||||
Int selected = -1;
|
||||
UnicodeString map;
|
||||
|
||||
// get the selected index
|
||||
if (mapWindow != NULL)
|
||||
{
|
||||
GadgetListBoxGetSelected( mapWindow, &selected );
|
||||
}
|
||||
|
||||
if( selected != -1 )
|
||||
{
|
||||
// get text of the map to load
|
||||
map = GadgetListBoxGetText( mapWindow, selected, 0 );
|
||||
|
||||
// set the map name in the global data map name
|
||||
AsciiString asciiMap;
|
||||
const char *mapFname = (const char *)GadgetListBoxGetItemData( mapWindow, selected );
|
||||
DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
|
||||
if (mapFname)
|
||||
asciiMap = mapFname;
|
||||
else
|
||||
asciiMap.translate( map );
|
||||
TheLAN->GetMyGame()->setMap( asciiMap );
|
||||
asciiMap.toLower();
|
||||
std::map<AsciiString, MapMetaData>::iterator it = TheMapCache->find(asciiMap);
|
||||
if (it != TheMapCache->end())
|
||||
{
|
||||
TheLAN->GetMyGame()->getSlot(0)->setMapAvailability(true);
|
||||
TheLAN->GetMyGame()->setMapCRC( it->second.m_CRC );
|
||||
TheLAN->GetMyGame()->setMapSize( it->second.m_filesize );
|
||||
|
||||
TheLAN->GetMyGame()->resetStartSpots();
|
||||
TheLAN->GetMyGame()->adjustSlotsForMap(); // BGC- adjust the slots for the new map.
|
||||
}
|
||||
|
||||
|
||||
mapSelectLayout->destroyWindows();
|
||||
mapSelectLayout->deleteInstance();
|
||||
mapSelectLayout = NULL;
|
||||
|
||||
// set the controls to NULL since they've been destroyed.
|
||||
NullifyControls();
|
||||
|
||||
showLANGameOptionsUnderlyingGUIElements(TRUE);
|
||||
PostToLanGameOptions(SEND_GAME_OPTS);
|
||||
|
||||
} // end if
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
case GLM_SELECTED:
|
||||
{
|
||||
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxMap )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
if( rowSelected < 0 )
|
||||
{
|
||||
positionStartSpots( AsciiString::TheEmptyString, buttonMapStartPosition, winMapPreview);
|
||||
// winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
|
||||
break;
|
||||
}
|
||||
winMapPreview->winSetStatus(WIN_STATUS_IMAGE);
|
||||
UnicodeString map;
|
||||
// get text of the map to load
|
||||
map = GadgetListBoxGetText( mapWindow, rowSelected, 0 );
|
||||
|
||||
// set the map name in the global data map name
|
||||
AsciiString asciiMap;
|
||||
const char *mapFname = (const char *)GadgetListBoxGetItemData( mapWindow, rowSelected );
|
||||
DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
|
||||
if (mapFname)
|
||||
asciiMap = mapFname;
|
||||
else
|
||||
asciiMap.translate( map );
|
||||
asciiMap.toLower();
|
||||
Image *image = getMapPreviewImage(asciiMap);
|
||||
winMapPreview->winSetUserData((void *)TheMapCache->findMap(asciiMap));
|
||||
if(image)
|
||||
{
|
||||
winMapPreview->winSetEnabledImage(0, image);
|
||||
}
|
||||
else
|
||||
{
|
||||
winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
|
||||
}
|
||||
positionStartSpots( asciiMap, buttonMapStartPosition, winMapPreview);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end LanMapSelectMenuSystem
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,478 @@
|
||||
/*
|
||||
** 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: MapSelectMenu.cpp ////////////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, October 2001
|
||||
// Description: MapSelect menu window callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "Common/RandomValue.h"
|
||||
#include "Common/UserPreferences.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/ScriptEngine.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/CampaignManager.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetRadioButton.h"
|
||||
#include "GameClient/MapUtil.h"
|
||||
#include "GameClient/Mouse.h"
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
static NameKeyType radioButtonSystemMapsID = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonUserMapsID = NAMEKEY_INVALID;
|
||||
static GameWindow *mapList = NULL;
|
||||
|
||||
static Bool showSoloMaps = true;
|
||||
static Bool isShuttingDown = false;
|
||||
static Bool startGame = false;
|
||||
static Bool buttonPushed = false;
|
||||
static GameDifficulty s_AIDiff = DIFFICULTY_NORMAL;
|
||||
static void setupGameStart(AsciiString mapName)
|
||||
{
|
||||
startGame = true;
|
||||
TheWritableGlobalData->m_pendingFile = mapName;
|
||||
TheShell->reverseAnimatewindow();
|
||||
}
|
||||
|
||||
static void doGameStart( void )
|
||||
{
|
||||
#if !defined(_PLAYTEST)
|
||||
startGame = false;
|
||||
|
||||
if (TheGameLogic->isInGame())
|
||||
TheGameLogic->clearGameData();
|
||||
//TheScriptEngine->setGlobalDifficulty(s_AIDiff); // CANNOT DO THIS! REPLAYS WILL BREAK!!!
|
||||
// send a message to the logic for a new game
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
|
||||
msg->appendIntegerArgument(GAME_SINGLE_PLAYER);
|
||||
msg->appendIntegerArgument(s_AIDiff);
|
||||
msg->appendIntegerArgument(0);
|
||||
|
||||
/// @todo: when Campaign & skirmish are separated, make campaign have fixed seed and skirmish random.
|
||||
InitRandom(0);
|
||||
/*
|
||||
if (TheGlobalData->m_fixedSeed >= 0)
|
||||
InitGameLogicRandom(TheGlobalData->m_fixedSeed);
|
||||
else
|
||||
InitGameLogicRandom(GameClientRandomValue(0, INT_MAX - 1));
|
||||
*/
|
||||
|
||||
isShuttingDown = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** This is called when a shutdown is complete for this menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static void shutdownComplete( WindowLayout *layout )
|
||||
{
|
||||
|
||||
isShuttingDown = false;
|
||||
|
||||
// hide the layout
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // end if
|
||||
|
||||
void SetDifficultyRadioButton( void )
|
||||
{
|
||||
AsciiString parentName( "MapSelectMenu.wnd:MapSelectMenuParent" );
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
|
||||
if (!TheScriptEngine)
|
||||
{
|
||||
s_AIDiff = DIFFICULTY_EASY;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (TheScriptEngine->getGlobalDifficulty())
|
||||
{
|
||||
case DIFFICULTY_EASY:
|
||||
{
|
||||
NameKeyType radioButtonEasyAIID = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:RadioButtonEasyAI") );
|
||||
GameWindow *radioButtonEasyAI = TheWindowManager->winGetWindowFromId( parent, radioButtonEasyAIID );
|
||||
GadgetRadioSetSelection(radioButtonEasyAI, FALSE);
|
||||
s_AIDiff = DIFFICULTY_EASY;
|
||||
break;
|
||||
}
|
||||
case DIFFICULTY_NORMAL:
|
||||
{
|
||||
NameKeyType radioButtonMediumAIID = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:RadioButtonMediumAI") );
|
||||
GameWindow *radioButtonMediumAI = TheWindowManager->winGetWindowFromId( parent, radioButtonMediumAIID );
|
||||
GadgetRadioSetSelection(radioButtonMediumAI, FALSE);
|
||||
s_AIDiff = DIFFICULTY_NORMAL;
|
||||
break;
|
||||
}
|
||||
case DIFFICULTY_HARD:
|
||||
{
|
||||
NameKeyType radioButtonHardAIID = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:RadioButtonHardAI") );
|
||||
GameWindow *radioButtonHardAI = TheWindowManager->winGetWindowFromId( parent, radioButtonHardAIID );
|
||||
GadgetRadioSetSelection(radioButtonHardAI, FALSE);
|
||||
s_AIDiff = DIFFICULTY_HARD;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
DEBUG_CRASH(("unrecognized difficulty level in the script engine"));
|
||||
}
|
||||
|
||||
}
|
||||
} // if (TheScriptEngine)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the MapSelect menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void MapSelectMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
showSoloMaps = true;
|
||||
buttonPushed = false;
|
||||
isShuttingDown = false;
|
||||
startGame = false;
|
||||
TheShell->showShellMap(TRUE);
|
||||
// show menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
OptionPreferences pref;
|
||||
Bool usesSystemMapDir = pref.usesSystemMapDir();
|
||||
|
||||
// get the listbox window
|
||||
AsciiString listString( "MapSelectMenu.wnd:ListboxMap" );
|
||||
NameKeyType mapListID = TheNameKeyGenerator->nameToKey( listString );
|
||||
mapList = TheWindowManager->winGetWindowFromId( NULL, mapListID );
|
||||
if( mapList )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, usesSystemMapDir, !showSoloMaps );
|
||||
}
|
||||
|
||||
|
||||
// set keyboard focus to main parent
|
||||
AsciiString parentName( "MapSelectMenu.wnd:MapSelectMenuParent" );
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
|
||||
NameKeyType buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:ButtonBack") );
|
||||
GameWindow *buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID );
|
||||
|
||||
NameKeyType buttonOKID = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:ButtonOK") );
|
||||
GameWindow *buttonOK = TheWindowManager->winGetWindowFromId( NULL, buttonOKID );
|
||||
|
||||
|
||||
TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_RIGHT, TRUE,0);
|
||||
TheShell->registerWithAnimateManager(buttonOK, WIN_ANIMATION_SLIDE_LEFT, TRUE, 0);
|
||||
|
||||
SetDifficultyRadioButton();
|
||||
|
||||
radioButtonSystemMapsID = TheNameKeyGenerator->nameToKey( "MapSelectMenu.wnd:RadioButtonSystemMaps" );
|
||||
radioButtonUserMapsID = TheNameKeyGenerator->nameToKey( "MapSelectMenu.wnd:RadioButtonUserMaps" );
|
||||
GameWindow *radioButtonSystemMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonSystemMapsID );
|
||||
GameWindow *radioButtonUserMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonUserMapsID );
|
||||
if (usesSystemMapDir)
|
||||
GadgetRadioSetSelection( radioButtonSystemMaps, FALSE );
|
||||
else
|
||||
GadgetRadioSetSelection( radioButtonUserMaps, FALSE );
|
||||
} // end MapSelectMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void MapSelectMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
if (!startGame)
|
||||
isShuttingDown = true;
|
||||
|
||||
// if we are shutting down for an immediate pop, skip the animations
|
||||
Bool popImmediate = *(Bool *)userData;
|
||||
if( popImmediate )
|
||||
{
|
||||
|
||||
shutdownComplete( layout );
|
||||
return;
|
||||
|
||||
} //end if
|
||||
|
||||
if (!startGame)
|
||||
TheShell->reverseAnimatewindow();
|
||||
|
||||
} // end MapSelectMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void MapSelectMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
if (startGame && TheShell->isAnimFinished())
|
||||
doGameStart();
|
||||
|
||||
// We'll only be successful if we've requested to
|
||||
if(isShuttingDown && TheShell->isAnimFinished())
|
||||
shutdownComplete(layout);
|
||||
|
||||
|
||||
} // end MapSelectMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Map select menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType MapSelectMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
AsciiString buttonName( "MapSelectMenu.wnd:ButtonBack" );
|
||||
NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end MapSelectMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType MapSelectMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
static NameKeyType buttonBack = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOK = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxMap = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonEasyAI = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonMediumAI = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonHardAI = NAMEKEY_INVALID;
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
// get ids for our children controls
|
||||
buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:ButtonBack") );
|
||||
buttonOK = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:ButtonOK") );
|
||||
listboxMap = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:ListboxMap") );
|
||||
radioButtonEasyAI = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:RadioButtonEasyAI") );
|
||||
radioButtonMediumAI = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:RadioButtonMediumAI") );
|
||||
radioButtonHardAI = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:RadioButtonHardAI") );
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
static NameKeyType singlePlayerID = NAMEKEY("MapSelectMenu.wnd:ButtonSinglePlayer");
|
||||
static NameKeyType multiplayerID = NAMEKEY("MapSelectMenu.wnd:ButtonMultiplayer");
|
||||
if ( controlID == singlePlayerID )
|
||||
{
|
||||
showSoloMaps = true;
|
||||
OptionPreferences pref;
|
||||
populateMapListbox( mapList, pref.usesSystemMapDir(), !showSoloMaps );
|
||||
}
|
||||
else if ( controlID == multiplayerID )
|
||||
{
|
||||
showSoloMaps = false;
|
||||
OptionPreferences pref;
|
||||
populateMapListbox( mapList, pref.usesSystemMapDir(), !showSoloMaps );
|
||||
}
|
||||
else if ( controlID == radioButtonSystemMapsID )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, TRUE, !showSoloMaps );
|
||||
OptionPreferences pref;
|
||||
pref["UseSystemMapDir"] = "yes";
|
||||
pref.write();
|
||||
}
|
||||
else if ( controlID == radioButtonUserMapsID )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, FALSE, !showSoloMaps );
|
||||
OptionPreferences pref;
|
||||
pref["UseSystemMapDir"] = "no";
|
||||
pref.write();
|
||||
}
|
||||
else if( controlID == buttonBack )
|
||||
{
|
||||
|
||||
// go back one screen
|
||||
TheShell->pop();
|
||||
buttonPushed = true;
|
||||
|
||||
} // end if
|
||||
else if( controlID == buttonOK )
|
||||
{
|
||||
|
||||
Int selected;
|
||||
UnicodeString map;
|
||||
GameWindow *mapWindow = TheWindowManager->winGetWindowFromId( NULL, listboxMap );
|
||||
|
||||
// get the selected index
|
||||
GadgetListBoxGetSelected( mapWindow, &selected );
|
||||
|
||||
if( selected != -1 )
|
||||
{
|
||||
buttonPushed = true;
|
||||
// reset the campaign manager to empty
|
||||
if( TheCampaignManager )
|
||||
TheCampaignManager->setCampaign( AsciiString( "" ) );
|
||||
// get text of the map to load
|
||||
const char *mapFname = (const char *)GadgetListBoxGetItemData( mapWindow, selected );
|
||||
DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
|
||||
if (mapFname)
|
||||
setupGameStart(mapFname);
|
||||
} // end if
|
||||
|
||||
} // end else if
|
||||
else if( controlID == radioButtonEasyAI)
|
||||
{
|
||||
s_AIDiff = DIFFICULTY_EASY;
|
||||
}
|
||||
else if( controlID == radioButtonMediumAI)
|
||||
{
|
||||
s_AIDiff = DIFFICULTY_NORMAL;
|
||||
}
|
||||
else if( controlID == radioButtonHardAI)
|
||||
{
|
||||
s_AIDiff = DIFFICULTY_HARD;
|
||||
}
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
case GLM_DOUBLE_CLICKED:
|
||||
{
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxMap )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
|
||||
if (rowSelected >= 0)
|
||||
{
|
||||
//buttonPushed = true;
|
||||
GadgetListBoxSetSelected( control, rowSelected );
|
||||
NameKeyType buttonOKID = TheNameKeyGenerator->nameToKey( AsciiString("MapSelectMenu.wnd:ButtonOK") );
|
||||
GameWindow *buttonOK = TheWindowManager->winGetWindowFromId( NULL, buttonOKID );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonOK, buttonOKID );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end MapSelectMenuSystem
|
||||
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
** 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: NetworkDirectConnect.cpp
|
||||
// Author: Bryan Cleveland, November 2001
|
||||
// Description: Lan Lobby Menu
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameSpy/peer/peer.h"
|
||||
|
||||
#include "Common/QuotedPrintable.h"
|
||||
#include "Common/UserPreferences.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetComboBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/GameWindowTransitions.h"
|
||||
|
||||
#include "GameNetwork/IPEnumeration.h"
|
||||
#include "GameNetwork/LANAPI.h"
|
||||
#include "GameNetwork/LANAPICallbacks.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// window ids ------------------------------------------------------------------------------
|
||||
|
||||
// Window Pointers ------------------------------------------------------------------------
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern Bool LANbuttonPushed;
|
||||
extern Bool LANisShuttingDown;
|
||||
|
||||
static Bool isShuttingDown = false;
|
||||
static Bool buttonPushed = false;
|
||||
|
||||
static NameKeyType buttonBackID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonHostID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonJoinID = NAMEKEY_INVALID;
|
||||
static NameKeyType editPlayerNameID = NAMEKEY_INVALID;
|
||||
static NameKeyType comboboxRemoteIPID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticLocalIPID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *buttonBack = NULL;
|
||||
static GameWindow *buttonHost = NULL;
|
||||
static GameWindow *buttonJoin = NULL;
|
||||
static GameWindow *editPlayerName = NULL;
|
||||
static GameWindow *comboboxRemoteIP = NULL;
|
||||
static GameWindow *staticLocalIP = NULL;
|
||||
|
||||
void PopulateRemoteIPComboBox()
|
||||
{
|
||||
LANPreferences userprefs;
|
||||
GadgetComboBoxReset(comboboxRemoteIP);
|
||||
|
||||
Int numRemoteIPs = userprefs.getNumRemoteIPs();
|
||||
Color white = GameMakeColor(255,255,255,255);
|
||||
|
||||
for (Int i = 0; i < numRemoteIPs; ++i)
|
||||
{
|
||||
UnicodeString entry;
|
||||
entry = userprefs.getRemoteIPEntry(i);
|
||||
GadgetComboBoxAddEntry(comboboxRemoteIP, entry, white);
|
||||
}
|
||||
|
||||
if (numRemoteIPs > 0)
|
||||
{
|
||||
GadgetComboBoxSetSelectedPos(comboboxRemoteIP, 0, TRUE);
|
||||
}
|
||||
userprefs.write();
|
||||
}
|
||||
|
||||
void UpdateRemoteIPList()
|
||||
{
|
||||
Int n1[4], n2[4];
|
||||
LANPreferences prefs;
|
||||
Int numEntries = GadgetComboBoxGetLength(comboboxRemoteIP);
|
||||
Int currentSelection = -1;
|
||||
GadgetComboBoxGetSelectedPos(comboboxRemoteIP, ¤tSelection);
|
||||
UnicodeString unisel = GadgetComboBoxGetText(comboboxRemoteIP);
|
||||
AsciiString sel;
|
||||
sel.translate(unisel);
|
||||
|
||||
// UnicodeString newEntry = prefs.getRemoteIPEntry(0);
|
||||
UnicodeString newEntry = unisel;
|
||||
UnicodeString newIP;
|
||||
newEntry.nextToken(&newIP, UnicodeString(L":"));
|
||||
Int numFields = swscanf(newIP.str(), L"%d.%d.%d.%d", &(n1[0]), &(n1[1]), &(n1[2]), &(n1[3]));
|
||||
|
||||
if (numFields != 4) {
|
||||
// this is not a properly formatted IP, don't change a thing.
|
||||
return;
|
||||
}
|
||||
|
||||
prefs["RemoteIP0"] = sel;
|
||||
|
||||
Int currentINIEntry = 1;
|
||||
|
||||
for (Int i = 0; i < numEntries; ++i)
|
||||
{
|
||||
if (i != currentSelection)
|
||||
{
|
||||
GadgetComboBoxSetSelectedPos(comboboxRemoteIP, i, FALSE);
|
||||
UnicodeString uni;
|
||||
uni = GadgetComboBoxGetText(comboboxRemoteIP);
|
||||
AsciiString ascii;
|
||||
ascii.translate(uni);
|
||||
|
||||
// prevent more than one copy of an IP address from being put in the list.
|
||||
if (currentSelection == -1)
|
||||
{
|
||||
UnicodeString oldEntry = uni;
|
||||
UnicodeString oldIP;
|
||||
oldEntry.nextToken(&oldIP, UnicodeString(L":"));
|
||||
|
||||
swscanf(oldIP.str(), L"%d.%d.%d.%d", &(n2[0]), &(n2[1]), &(n2[2]), &(n2[3]));
|
||||
|
||||
Bool isEqual = TRUE;
|
||||
for (Int i = 0; (i < 4) && (isEqual == TRUE); ++i) {
|
||||
if (n1[i] != n2[i]) {
|
||||
isEqual = FALSE;
|
||||
}
|
||||
}
|
||||
// check to see if this is a duplicate or if this is not a properly formatted IP address.
|
||||
if (isEqual == TRUE)
|
||||
{
|
||||
--numEntries;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
AsciiString temp;
|
||||
temp.format("RemoteIP%d", currentINIEntry);
|
||||
++currentINIEntry;
|
||||
prefs[temp.str()] = ascii;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentSelection == -1)
|
||||
{
|
||||
++numEntries;
|
||||
}
|
||||
|
||||
AsciiString numRemoteIPs;
|
||||
numRemoteIPs.format("%d", numEntries);
|
||||
|
||||
prefs["NumRemoteIPs"] = numRemoteIPs;
|
||||
|
||||
prefs.write();
|
||||
}
|
||||
|
||||
void HostDirectConnectGame()
|
||||
{
|
||||
// Init LAN API Singleton
|
||||
DEBUG_ASSERTCRASH(TheLAN != NULL, ("TheLAN is NULL!"));
|
||||
if (!TheLAN)
|
||||
{
|
||||
TheLAN = NEW LANAPI();
|
||||
}
|
||||
|
||||
UnsignedInt localIP = TheLAN->GetLocalIP();
|
||||
UnicodeString localIPString;
|
||||
localIPString.format(L"%d.%d.%d.%d", localIP >> 24, (localIP & 0xff0000) >> 16, (localIP & 0xff00) >> 8, localIP & 0xff);
|
||||
|
||||
UnicodeString name;
|
||||
name = GadgetTextEntryGetText(editPlayerName);
|
||||
|
||||
LANPreferences prefs;
|
||||
prefs["UserName"] = UnicodeStringToQuotedPrintable(name);
|
||||
prefs.write();
|
||||
|
||||
while (name.getLength() > g_lanPlayerNameLength)
|
||||
name.removeLastChar();
|
||||
TheLAN->RequestSetName(name);
|
||||
TheLAN->RequestGameCreate(localIPString, TRUE);
|
||||
}
|
||||
|
||||
void JoinDirectConnectGame()
|
||||
{
|
||||
// Init LAN API Singleton
|
||||
|
||||
if (!TheLAN)
|
||||
{
|
||||
TheLAN = NEW LANAPI();
|
||||
}
|
||||
|
||||
UnsignedInt ipaddress = 0;
|
||||
UnicodeString ipunistring = GadgetComboBoxGetText(comboboxRemoteIP);
|
||||
AsciiString asciientry;
|
||||
asciientry.translate(ipunistring);
|
||||
|
||||
AsciiString ipstring;
|
||||
asciientry.nextToken(&ipstring, "(");
|
||||
|
||||
char ipstr[16];
|
||||
strcpy(ipstr, ipstring.str());
|
||||
|
||||
Int ip1, ip2, ip3, ip4;
|
||||
sscanf(ipstr, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
|
||||
|
||||
DEBUG_LOG(("JoinDirectConnectGame - joining at %d.%d.%d.%d\n", ip1, ip2, ip3, ip4));
|
||||
|
||||
ipaddress = (ip1 << 24) + (ip2 << 16) + (ip3 << 8) + ip4;
|
||||
// ipaddress = htonl(ipaddress);
|
||||
|
||||
UnicodeString name;
|
||||
name = GadgetTextEntryGetText(editPlayerName);
|
||||
|
||||
LANPreferences prefs;
|
||||
prefs["UserName"] = UnicodeStringToQuotedPrintable(name);
|
||||
prefs.write();
|
||||
|
||||
UpdateRemoteIPList();
|
||||
PopulateRemoteIPComboBox();
|
||||
|
||||
while (name.getLength() > g_lanPlayerNameLength)
|
||||
name.removeLastChar();
|
||||
TheLAN->RequestSetName(name);
|
||||
|
||||
TheLAN->RequestGameJoinDirectConnect(ipaddress);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the WOL Welcome Menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void NetworkDirectConnectInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
LANbuttonPushed = false;
|
||||
LANisShuttingDown = false;
|
||||
|
||||
if (TheLAN == NULL)
|
||||
{
|
||||
TheLAN = NEW LANAPI();
|
||||
TheLAN->init();
|
||||
}
|
||||
TheLAN->reset();
|
||||
|
||||
buttonPushed = false;
|
||||
isShuttingDown = false;
|
||||
TheShell->showShellMap(TRUE);
|
||||
buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonBack" ) );
|
||||
buttonHostID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonHost" ) );
|
||||
buttonJoinID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ButtonJoin" ) );
|
||||
editPlayerNameID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:EditPlayerName" ) );
|
||||
comboboxRemoteIPID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:ComboboxRemoteIP" ) );
|
||||
staticLocalIPID = TheNameKeyGenerator->nameToKey( AsciiString( "NetworkDirectConnect.wnd:StaticLocalIP" ) );
|
||||
|
||||
buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID);
|
||||
buttonHost = TheWindowManager->winGetWindowFromId( NULL, buttonHostID);
|
||||
buttonJoin = TheWindowManager->winGetWindowFromId( NULL, buttonJoinID);
|
||||
editPlayerName = TheWindowManager->winGetWindowFromId( NULL, editPlayerNameID);
|
||||
comboboxRemoteIP = TheWindowManager->winGetWindowFromId( NULL, comboboxRemoteIPID);
|
||||
staticLocalIP = TheWindowManager->winGetWindowFromId( NULL, staticLocalIPID);
|
||||
|
||||
// // animate controls
|
||||
// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_LEFT, TRUE, 800);
|
||||
// TheShell->registerWithAnimateManager(buttonHost, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600);
|
||||
// TheShell->registerWithAnimateManager(buttonJoin, WIN_ANIMATION_SLIDE_LEFT, TRUE, 200);
|
||||
//
|
||||
LANPreferences userprefs;
|
||||
UnicodeString name;
|
||||
name = userprefs.getUserName();
|
||||
|
||||
if (name.getLength() == 0)
|
||||
{
|
||||
name = TheGameText->fetch("GUI:Player");
|
||||
}
|
||||
|
||||
GadgetTextEntrySetText(editPlayerName, name);
|
||||
|
||||
PopulateRemoteIPComboBox();
|
||||
|
||||
UnicodeString ipstr;
|
||||
|
||||
delete TheLAN;
|
||||
TheLAN = NULL;
|
||||
|
||||
if (TheLAN == NULL) {
|
||||
// DEBUG_ASSERTCRASH(TheLAN != NULL, ("TheLAN is null initializing the direct connect screen."));
|
||||
TheLAN = NEW LANAPI();
|
||||
|
||||
OptionPreferences prefs;
|
||||
UnsignedInt IP = prefs.getOnlineIPAddress();
|
||||
|
||||
IPEnumeration IPs;
|
||||
|
||||
// if (!IP)
|
||||
// {
|
||||
EnumeratedIP *IPlist = IPs.getAddresses();
|
||||
DEBUG_ASSERTCRASH(IPlist, ("No IP addresses found!"));
|
||||
if (!IPlist)
|
||||
{
|
||||
/// @todo: display error and exit lan lobby if no IPs are found
|
||||
}
|
||||
|
||||
Bool foundIP = FALSE;
|
||||
EnumeratedIP *tempIP = IPlist;
|
||||
while ((tempIP != NULL) && (foundIP == FALSE)) {
|
||||
if (IP == tempIP->getIP()) {
|
||||
foundIP = TRUE;
|
||||
}
|
||||
tempIP = tempIP->getNext();
|
||||
}
|
||||
|
||||
if (foundIP == FALSE) {
|
||||
// The IP that we had no longer exists, we need to pick a new one.
|
||||
IP = IPlist->getIP();
|
||||
}
|
||||
|
||||
// IP = IPlist->getIP();
|
||||
// }
|
||||
TheLAN->init();
|
||||
TheLAN->SetLocalIP(IP);
|
||||
}
|
||||
|
||||
UnsignedInt ip = TheLAN->GetLocalIP();
|
||||
ipstr.format(L"%d.%d.%d.%d", ip >> 24, (ip & 0xff0000) >> 16, (ip & 0xff00) >> 8, ip & 0xff);
|
||||
GadgetStaticTextSetText(staticLocalIP, ipstr);
|
||||
|
||||
TheLAN->RequestLobbyLeave(true);
|
||||
layout->hide(FALSE);
|
||||
layout->bringForward();
|
||||
TheTransitionHandler->setGroup("NetworkDirectConnectFade");
|
||||
|
||||
|
||||
} // NetworkDirectConnectInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** This is called when a shutdown is complete for this menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static void shutdownComplete( WindowLayout *layout )
|
||||
{
|
||||
|
||||
isShuttingDown = false;
|
||||
|
||||
// hide the layout
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // end if
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Welcome Menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void NetworkDirectConnectShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
isShuttingDown = true;
|
||||
|
||||
// if we are shutting down for an immediate pop, skip the animations
|
||||
Bool popImmediate = *(Bool *)userData;
|
||||
if( popImmediate )
|
||||
{
|
||||
|
||||
shutdownComplete( layout );
|
||||
return;
|
||||
|
||||
} //end if
|
||||
|
||||
TheShell->reverseAnimatewindow();
|
||||
|
||||
TheTransitionHandler->reverse("NetworkDirectConnectFade");
|
||||
} // NetworkDirectConnectShutdown
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Welcome Menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void NetworkDirectConnectUpdate( WindowLayout * layout, void *userData)
|
||||
{
|
||||
// We'll only be successful if we've requested to
|
||||
if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished())
|
||||
shutdownComplete(layout);
|
||||
}// NetworkDirectConnectUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Welcome Menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType NetworkDirectConnectInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonBack, buttonBackID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}// NetworkDirectConnectInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Welcome Menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType NetworkDirectConnectSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == buttonBackID )
|
||||
{
|
||||
UnicodeString name;
|
||||
name = GadgetTextEntryGetText(editPlayerName);
|
||||
|
||||
LANPreferences prefs;
|
||||
prefs["UserName"] = UnicodeStringToQuotedPrintable(name);
|
||||
prefs.write();
|
||||
|
||||
while (name.getLength() > g_lanPlayerNameLength)
|
||||
name.removeLastChar();
|
||||
TheLAN->RequestSetName(name);
|
||||
|
||||
buttonPushed = true;
|
||||
LANbuttonPushed = true;
|
||||
TheShell->pop();
|
||||
} //if ( controlID == buttonBack )
|
||||
else if (controlID == buttonHostID)
|
||||
{
|
||||
HostDirectConnectGame();
|
||||
}
|
||||
else if (controlID == buttonJoinID)
|
||||
{
|
||||
JoinDirectConnectGame();
|
||||
}
|
||||
break;
|
||||
}// case GBM_SELECTED:
|
||||
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
}// NetworkDirectConnectSystem
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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: PopupCommunicator.cpp /////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: PopupCommunicator.cpp
|
||||
//
|
||||
// Created: Chris Brue, July 2002
|
||||
//
|
||||
// Desc: Electronic Arts instant messaging system
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static NameKeyType buttonOkID = NAMEKEY_INVALID;
|
||||
static GameWindow *buttonOk = NULL;
|
||||
static GameWindow *parent = NULL;
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the Popup Communicator */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupCommunicatorInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
//set keyboard focus to main parent and set modal
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey("PopupCommunicator.wnd:PopupCommunicator");
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
TheWindowManager->winSetModal( parent );
|
||||
|
||||
// get ids for our children controls
|
||||
buttonOkID = TheNameKeyGenerator->nameToKey( AsciiString("PopupCommunicator.wnd:ButtonOk") );
|
||||
buttonOk = TheWindowManager->winGetWindowFromId( parent, buttonOkID );
|
||||
|
||||
} // end PopupCommunicatorInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Popup Communicator shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupCommunicatorShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
} // end PopupCommunicatorShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Popup Communicator update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupcommunicatorUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
} // end PopupCommunicatorUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Popup Communicator input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupCommunicatorInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonOk, buttonOkID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end PopupCommunicatorInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Popup Communicator window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupCommunicatorSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonOkID )
|
||||
{
|
||||
WindowLayout *popupCommunicatorLayout = window->winGetLayout();
|
||||
popupCommunicatorLayout->destroyWindows();
|
||||
popupCommunicatorLayout->deleteInstance();
|
||||
popupCommunicatorLayout = NULL;
|
||||
} // end if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
** 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: PopupHostGame.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Jul 2002
|
||||
//
|
||||
// Filename: PopupHostGame.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: Contains the Callbacks for the Host Game Popus
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "Common/Version.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GadgetCheckBox.h"
|
||||
#include "GameClient/GadgetComboBox.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameNetwork/GameSpy/GSConfig.h"
|
||||
#include "GameNetwork/GameSpy/Peerdefs.h"
|
||||
#include "GameNetwork/GameSpy/PeerThread.h"
|
||||
#include "GameNetwork/GameSpyOverlay.h"
|
||||
|
||||
#include "GameNetwork/GameSpy/LadderDefs.h"
|
||||
#include "Common/CustomMatchPreferences.h"
|
||||
#include "Common/LadderPreferences.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static NameKeyType parentPopupID = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryGameNameID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonCreateGameID = NAMEKEY_INVALID;
|
||||
static NameKeyType checkBoxAllowObserversID = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryGameDescriptionID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonCancelID = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryLadderPasswordID = NAMEKEY_INVALID;
|
||||
static NameKeyType comboBoxLadderNameID = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryGamePasswordID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *parentPopup = NULL;
|
||||
static GameWindow *textEntryGameName = NULL;
|
||||
static GameWindow *buttonCreateGame = NULL;
|
||||
static GameWindow *checkBoxAllowObservers = NULL;
|
||||
static GameWindow *textEntryGameDescription = NULL;
|
||||
static GameWindow *buttonCancel = NULL;
|
||||
static GameWindow *comboBoxLadderName = NULL;
|
||||
static GameWindow *textEntryLadderPassword = NULL;
|
||||
static GameWindow *textEntryGamePassword = NULL;
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
void createGame( void );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Ladders --------------------------------------------------------------------------------
|
||||
|
||||
static bool isPopulatingLadderBox = false;
|
||||
|
||||
void CustomMatchHideHostPopup(Bool hide)
|
||||
{
|
||||
if (!parentPopup)
|
||||
return;
|
||||
|
||||
parentPopup->winHide( hide );
|
||||
}
|
||||
|
||||
void HandleCustomLadderSelection(Int ladderID)
|
||||
{
|
||||
if (!parentPopup)
|
||||
return;
|
||||
|
||||
CustomMatchPreferences pref;
|
||||
|
||||
if (ladderID == 0)
|
||||
{
|
||||
pref.setLastLadder(AsciiString::TheEmptyString, 0);
|
||||
pref.write();
|
||||
return;
|
||||
}
|
||||
|
||||
const LadderInfo *info = TheLadderList->findLadderByIndex(ladderID);
|
||||
if (!info)
|
||||
{
|
||||
pref.setLastLadder(AsciiString::TheEmptyString, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pref.setLastLadder(info->address, info->port);
|
||||
}
|
||||
|
||||
pref.write();
|
||||
}
|
||||
|
||||
void PopulateCustomLadderListBox( GameWindow *win )
|
||||
{
|
||||
if (!parentPopup || !win)
|
||||
return;
|
||||
|
||||
isPopulatingLadderBox = true;
|
||||
|
||||
CustomMatchPreferences pref;
|
||||
|
||||
Color specialColor = GameSpyColor[GSCOLOR_MAP_SELECTED];
|
||||
Color normalColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED];
|
||||
Color favoriteColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED];
|
||||
Color localColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED];
|
||||
Int index;
|
||||
GadgetListBoxReset( win );
|
||||
|
||||
std::set<const LadderInfo *> usedLadders;
|
||||
|
||||
// start with "No Ladder"
|
||||
index = GadgetListBoxAddEntryText( win, TheGameText->fetch("GUI:NoLadder"), normalColor, -1 );
|
||||
GadgetListBoxSetItemData( win, 0, index );
|
||||
|
||||
// add the last ladder
|
||||
Int selectedPos = 0;
|
||||
AsciiString lastLadderAddr = pref.getLastLadderAddr();
|
||||
UnsignedShort lastLadderPort = pref.getLastLadderPort();
|
||||
const LadderInfo *info = TheLadderList->findLadder( lastLadderAddr, lastLadderPort );
|
||||
if (info && info->index > 0 && info->validCustom)
|
||||
{
|
||||
usedLadders.insert(info);
|
||||
index = GadgetListBoxAddEntryText( win, info->name, favoriteColor, -1 );
|
||||
GadgetListBoxSetItemData( win, (void *)(info->index), index );
|
||||
selectedPos = index;
|
||||
}
|
||||
|
||||
// our recent ladders
|
||||
LadderPreferences ladPref;
|
||||
ladPref.loadProfile( TheGameSpyInfo->getLocalProfileID() );
|
||||
const LadderPrefMap recentLadders = ladPref.getRecentLadders();
|
||||
for (LadderPrefMap::const_iterator cit = recentLadders.begin(); cit != recentLadders.end(); ++cit)
|
||||
{
|
||||
AsciiString addr = cit->second.address;
|
||||
UnsignedShort port = cit->second.port;
|
||||
if (addr == lastLadderAddr && port == lastLadderPort)
|
||||
continue;
|
||||
const LadderInfo *info = TheLadderList->findLadder( addr, port );
|
||||
if (info && info->index > 0 && info->validCustom && usedLadders.find(info) == usedLadders.end())
|
||||
{
|
||||
usedLadders.insert(info);
|
||||
index = GadgetListBoxAddEntryText( win, info->name, favoriteColor, -1 );
|
||||
GadgetListBoxSetItemData( win, (void *)(info->index), index );
|
||||
}
|
||||
}
|
||||
|
||||
// local ladders
|
||||
const LadderInfoList *lil = TheLadderList->getLocalLadders();
|
||||
LadderInfoList::const_iterator lit;
|
||||
for (lit = lil->begin(); lit != lil->end(); ++lit)
|
||||
{
|
||||
const LadderInfo *info = *lit;
|
||||
if (info && info->index < 0 && info->validCustom && usedLadders.find(info) == usedLadders.end())
|
||||
{
|
||||
usedLadders.insert(info);
|
||||
index = GadgetListBoxAddEntryText( win, info->name, localColor, -1 );
|
||||
GadgetListBoxSetItemData( win, (void *)(info->index), index );
|
||||
}
|
||||
}
|
||||
|
||||
// special ladders
|
||||
lil = TheLadderList->getSpecialLadders();
|
||||
for (lit = lil->begin(); lit != lil->end(); ++lit)
|
||||
{
|
||||
const LadderInfo *info = *lit;
|
||||
if (info && info->index > 0 && info->validCustom && usedLadders.find(info) == usedLadders.end())
|
||||
{
|
||||
usedLadders.insert(info);
|
||||
index = GadgetListBoxAddEntryText( win, info->name, specialColor, -1 );
|
||||
GadgetListBoxSetItemData( win, (void *)(info->index), index );
|
||||
}
|
||||
}
|
||||
|
||||
// standard ladders
|
||||
lil = TheLadderList->getStandardLadders();
|
||||
for (lit = lil->begin(); lit != lil->end(); ++lit)
|
||||
{
|
||||
const LadderInfo *info = *lit;
|
||||
if (info && info->index > 0 && info->validCustom && usedLadders.find(info) == usedLadders.end())
|
||||
{
|
||||
usedLadders.insert(info);
|
||||
index = GadgetListBoxAddEntryText( win, info->name, normalColor, -1 );
|
||||
GadgetListBoxSetItemData( win, (void *)(info->index), index );
|
||||
}
|
||||
}
|
||||
|
||||
GadgetListBoxSetSelected( win, selectedPos );
|
||||
isPopulatingLadderBox = false;
|
||||
}
|
||||
|
||||
void PopulateCustomLadderComboBox( void )
|
||||
{
|
||||
if (!parentPopup || !comboBoxLadderName)
|
||||
return;
|
||||
|
||||
isPopulatingLadderBox = true;
|
||||
|
||||
CustomMatchPreferences pref;
|
||||
AsciiString userPrefFilename;
|
||||
Int localProfile = TheGameSpyInfo->getLocalProfileID();
|
||||
userPrefFilename.format("GeneralsOnline\\CustomPref%d.ini", localProfile);
|
||||
pref.load(userPrefFilename);
|
||||
|
||||
std::set<const LadderInfo *> usedLadders;
|
||||
|
||||
Color specialColor = GameSpyColor[GSCOLOR_MAP_SELECTED];
|
||||
Color normalColor = GameSpyColor[GSCOLOR_MAP_UNSELECTED];
|
||||
Int index;
|
||||
GadgetComboBoxReset( comboBoxLadderName );
|
||||
index = GadgetComboBoxAddEntry( comboBoxLadderName, TheGameText->fetch("GUI:NoLadder"), normalColor );
|
||||
GadgetComboBoxSetItemData( comboBoxLadderName, index, 0 );
|
||||
|
||||
Int selectedPos = 0;
|
||||
AsciiString lastLadderAddr = pref.getLastLadderAddr();
|
||||
UnsignedShort lastLadderPort = pref.getLastLadderPort();
|
||||
const LadderInfo *info = TheLadderList->findLadder( lastLadderAddr, lastLadderPort );
|
||||
if (info && info->validCustom)
|
||||
{
|
||||
usedLadders.insert(info);
|
||||
index = GadgetComboBoxAddEntry( comboBoxLadderName, info->name, specialColor );
|
||||
GadgetComboBoxSetItemData( comboBoxLadderName, index, (void *)(info->index) );
|
||||
selectedPos = index;
|
||||
}
|
||||
|
||||
LadderPreferences ladPref;
|
||||
ladPref.loadProfile( localProfile );
|
||||
const LadderPrefMap recentLadders = ladPref.getRecentLadders();
|
||||
for (LadderPrefMap::const_iterator cit = recentLadders.begin(); cit != recentLadders.end(); ++cit)
|
||||
{
|
||||
AsciiString addr = cit->second.address;
|
||||
UnsignedShort port = cit->second.port;
|
||||
if (addr == lastLadderAddr && port == lastLadderPort)
|
||||
continue;
|
||||
const LadderInfo *info = TheLadderList->findLadder( addr, port );
|
||||
if (info && info->validCustom && usedLadders.find(info) == usedLadders.end())
|
||||
{
|
||||
usedLadders.insert(info);
|
||||
index = GadgetComboBoxAddEntry( comboBoxLadderName, info->name, normalColor );
|
||||
GadgetComboBoxSetItemData( comboBoxLadderName, index, (void *)(info->index) );
|
||||
}
|
||||
}
|
||||
|
||||
index = GadgetComboBoxAddEntry( comboBoxLadderName, TheGameText->fetch("GUI:ChooseLadder"), normalColor );
|
||||
GadgetComboBoxSetItemData( comboBoxLadderName, index, (void *)-1 );
|
||||
|
||||
GadgetComboBoxSetSelectedPos( comboBoxLadderName, selectedPos );
|
||||
isPopulatingLadderBox = false;
|
||||
}
|
||||
|
||||
// Window Functions -----------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the PopupHostGameInit menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupHostGameInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parentPopupID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:ParentHostPopUp"));
|
||||
parentPopup = TheWindowManager->winGetWindowFromId(NULL, parentPopupID);
|
||||
|
||||
textEntryGameNameID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:TextEntryGameName"));
|
||||
textEntryGameName = TheWindowManager->winGetWindowFromId(parentPopup, textEntryGameNameID);
|
||||
UnicodeString name;
|
||||
name.translate(TheGameSpyInfo->getLocalName());
|
||||
GadgetTextEntrySetText(textEntryGameName, name);
|
||||
|
||||
textEntryGameDescriptionID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:TextEntryGameDescription"));
|
||||
textEntryGameDescription = TheWindowManager->winGetWindowFromId(parentPopup, textEntryGameDescriptionID);
|
||||
GadgetTextEntrySetText(textEntryGameDescription, UnicodeString::TheEmptyString);
|
||||
|
||||
textEntryLadderPasswordID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:TextEntryLadderPassword"));
|
||||
textEntryLadderPassword = TheWindowManager->winGetWindowFromId(parentPopup, textEntryLadderPasswordID);
|
||||
GadgetTextEntrySetText(textEntryLadderPassword, UnicodeString::TheEmptyString);
|
||||
|
||||
textEntryGamePasswordID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:TextEntryGamePassword"));
|
||||
textEntryGamePassword = TheWindowManager->winGetWindowFromId(parentPopup, textEntryGamePasswordID);
|
||||
GadgetTextEntrySetText(textEntryGamePassword, UnicodeString::TheEmptyString);
|
||||
|
||||
buttonCreateGameID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:ButtonCreateGame"));
|
||||
buttonCreateGame = TheWindowManager->winGetWindowFromId(parentPopup, buttonCreateGameID);
|
||||
|
||||
buttonCancelID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:ButtonCancel"));
|
||||
buttonCancel = TheWindowManager->winGetWindowFromId(parentPopup, buttonCancelID);
|
||||
|
||||
checkBoxAllowObserversID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:CheckBoxAllowObservers"));
|
||||
checkBoxAllowObservers = TheWindowManager->winGetWindowFromId(parentPopup, checkBoxAllowObserversID);
|
||||
CustomMatchPreferences customPref;
|
||||
// disabling observers for Multiplayer test
|
||||
#ifndef _PLAYTEST
|
||||
GadgetCheckBoxSetChecked(checkBoxAllowObservers, customPref.allowsObservers());
|
||||
#else
|
||||
if (checkBoxAllowObservers)
|
||||
{
|
||||
GadgetCheckBoxSetChecked(checkBoxAllowObservers, FALSE);
|
||||
checkBoxAllowObservers->winEnable(FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
comboBoxLadderNameID = TheNameKeyGenerator->nameToKey(AsciiString("PopupHostGame.wnd:ComboBoxLadderName"));
|
||||
comboBoxLadderName = TheWindowManager->winGetWindowFromId(parentPopup, comboBoxLadderNameID);
|
||||
if (comboBoxLadderName)
|
||||
GadgetComboBoxReset(comboBoxLadderName);
|
||||
PopulateCustomLadderComboBox();
|
||||
|
||||
TheWindowManager->winSetFocus( parentPopup );
|
||||
TheWindowManager->winSetModal( parentPopup );
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** PopupHostGameInput callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupHostGameInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
// if (buttonPushed)
|
||||
// break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonCancel, buttonCancelID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** PopupHostGameSystem callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupHostGameSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
parentPopup = NULL;
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GEM_UPDATE_TEXT:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == textEntryGameNameID )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
// grab the game's name
|
||||
txtInput.set(GadgetTextEntryGetText( textEntryGameName ));
|
||||
|
||||
// Clean up the text (remove leading/trailing chars, etc)
|
||||
const WideChar *c = txtInput.str();
|
||||
while (c && (iswspace(*c)))
|
||||
c++;
|
||||
|
||||
if (c)
|
||||
txtInput = UnicodeString(c);
|
||||
else
|
||||
txtInput = UnicodeString::TheEmptyString;
|
||||
|
||||
// Put the whitespace-free version in the box
|
||||
GadgetTextEntrySetText( textEntryGameName, txtInput );
|
||||
|
||||
}// if ( controlID == textEntryPlayerNameID )
|
||||
break;
|
||||
}//case GEM_UPDATE_TEXT:
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GCM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
Int pos = -1;
|
||||
GadgetComboBoxGetSelectedPos(control, &pos);
|
||||
|
||||
if (controlID == comboBoxLadderNameID && !isPopulatingLadderBox)
|
||||
{
|
||||
if (pos >= 0)
|
||||
{
|
||||
Int ladderID = (Int)GadgetComboBoxGetItemData(control, pos);
|
||||
if (ladderID < 0)
|
||||
{
|
||||
// "Choose a ladder" selected - open overlay
|
||||
PopulateCustomLadderComboBox(); // this restores the non-"Choose a ladder" selection
|
||||
GameSpyOpenOverlay( GSOVERLAY_LADDERSELECT );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} // case GCM_SELECTED
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonCancelID )
|
||||
{
|
||||
parentPopup = NULL;
|
||||
GameSpyCloseOverlay(GSOVERLAY_GAMEOPTIONS);
|
||||
SetLobbyAttemptHostJoin( FALSE );
|
||||
}
|
||||
else if( controlID == buttonCreateGameID)
|
||||
{
|
||||
UnicodeString name;
|
||||
name = GadgetTextEntryGetText(textEntryGameName);
|
||||
name.trim();
|
||||
if(name.getLength() <= 0)
|
||||
{
|
||||
name.translate(TheGameSpyInfo->getLocalName());
|
||||
GadgetTextEntrySetText(textEntryGameName, name);
|
||||
}
|
||||
createGame();
|
||||
parentPopup = NULL;
|
||||
GameSpyCloseOverlay(GSOVERLAY_GAMEOPTIONS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void createGame( void )
|
||||
{
|
||||
TheGameSpyInfo->setCurrentGroupRoom(0);
|
||||
PeerRequest req;
|
||||
UnicodeString gameName = GadgetTextEntryGetText(textEntryGameName);
|
||||
req.peerRequestType = PeerRequest::PEERREQUEST_CREATESTAGINGROOM;
|
||||
req.text = gameName.str();
|
||||
TheGameSpyGame->setGameName(gameName);
|
||||
AsciiString passwd;
|
||||
passwd.translate(GadgetTextEntryGetText(textEntryGamePassword));
|
||||
req.password = passwd.str();
|
||||
CustomMatchPreferences customPref;
|
||||
Bool aO = GadgetCheckBoxIsChecked(checkBoxAllowObservers);
|
||||
customPref.setAllowsObserver(aO);
|
||||
customPref.write();
|
||||
req.stagingRoomCreation.allowObservers = aO;
|
||||
TheGameSpyGame->setAllowObservers(aO);
|
||||
req.stagingRoomCreation.exeCRC = TheGlobalData->m_exeCRC;
|
||||
req.stagingRoomCreation.iniCRC = TheGlobalData->m_iniCRC;
|
||||
req.stagingRoomCreation.gameVersion = TheGameSpyInfo->getInternalIP();
|
||||
req.stagingRoomCreation.restrictGameList = TheGameSpyConfig->restrictGamesToLobby();
|
||||
|
||||
Int ladderSelectPos = -1, ladderID = -1;
|
||||
GadgetComboBoxGetSelectedPos(comboBoxLadderName, &ladderSelectPos);
|
||||
req.ladderIP = "localhost";
|
||||
req.stagingRoomCreation.ladPort = 0;
|
||||
if (ladderSelectPos >= 0)
|
||||
{
|
||||
ladderID = (Int)GadgetComboBoxGetItemData(comboBoxLadderName, ladderSelectPos);
|
||||
if (ladderID != 0)
|
||||
{
|
||||
// actual ladder
|
||||
const LadderInfo *info = TheLadderList->findLadderByIndex(ladderID);
|
||||
if (info)
|
||||
{
|
||||
req.ladderIP = info->address.str();
|
||||
req.stagingRoomCreation.ladPort = info->port;
|
||||
}
|
||||
}
|
||||
}
|
||||
TheGameSpyGame->setLadderIP(req.ladderIP.c_str());
|
||||
TheGameSpyGame->setLadderPort(req.stagingRoomCreation.ladPort);
|
||||
req.hostPingStr = TheGameSpyInfo->getPingString().str();
|
||||
|
||||
TheGameSpyPeerMessageQueue->addRequest(req);
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
** 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: PopupJoinGame.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Jul 2002
|
||||
//
|
||||
// Filename: PopupJoinGame.cpp
|
||||
//
|
||||
// author: Matthew D. Campbell
|
||||
//
|
||||
// purpose: Contains the Callbacks for the Join Game Popup
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameNetwork/GameSpy/Peerdefs.h"
|
||||
#include "GameNetwork/GameSpy/PeerThread.h"
|
||||
#include "GameNetwork/GameSpyOverlay.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static NameKeyType parentPopupID = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryGamePasswordID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonCancelID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *parentPopup = NULL;
|
||||
static GameWindow *textEntryGamePassword = NULL;
|
||||
|
||||
static void joinGame( AsciiString password );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the PopupHostGameInit menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupJoinGameInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parentPopupID = TheNameKeyGenerator->nameToKey(AsciiString("PopupJoinGame.wnd:ParentJoinPopUp"));
|
||||
parentPopup = TheWindowManager->winGetWindowFromId(NULL, parentPopupID);
|
||||
|
||||
textEntryGamePasswordID = TheNameKeyGenerator->nameToKey(AsciiString("PopupJoinGame.wnd:TextEntryGamePassword"));
|
||||
textEntryGamePassword = TheWindowManager->winGetWindowFromId(parentPopup, textEntryGamePasswordID);
|
||||
GadgetTextEntrySetText(textEntryGamePassword, UnicodeString::TheEmptyString);
|
||||
|
||||
NameKeyType staticTextGameNameID = TheNameKeyGenerator->nameToKey(AsciiString("PopupJoinGame.wnd:StaticTextGameName"));
|
||||
GameWindow *staticTextGameName = TheWindowManager->winGetWindowFromId(parentPopup, staticTextGameNameID);
|
||||
GadgetStaticTextSetText(staticTextGameName, UnicodeString::TheEmptyString);
|
||||
|
||||
buttonCancelID = NAMEKEY("PopupJoinGame.wnd:ButtonCancel");
|
||||
|
||||
GameSpyStagingRoom *ourRoom = TheGameSpyInfo->findStagingRoomByID(TheGameSpyInfo->getCurrentStagingRoomID());
|
||||
if (ourRoom)
|
||||
GadgetStaticTextSetText(staticTextGameName, ourRoom->getGameName());
|
||||
|
||||
TheWindowManager->winSetFocus( parentPopup );
|
||||
TheWindowManager->winSetModal( parentPopup );
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** PopupHostGameInput callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupJoinGameInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
// if (buttonPushed)
|
||||
// break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
GameSpyCloseOverlay(GSOVERLAY_GAMEPASSWORD);
|
||||
SetLobbyAttemptHostJoin( FALSE );
|
||||
parentPopup = NULL;
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** PopupHostGameSystem callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupJoinGameSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if (controlID == buttonCancelID)
|
||||
{
|
||||
GameSpyCloseOverlay(GSOVERLAY_GAMEPASSWORD);
|
||||
SetLobbyAttemptHostJoin( FALSE );
|
||||
parentPopup = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == textEntryGamePasswordID )
|
||||
{
|
||||
// read the user's input and clear the entry box
|
||||
UnicodeString txtInput;
|
||||
txtInput.set(GadgetTextEntryGetText( textEntryGamePassword ));
|
||||
GadgetTextEntrySetText(textEntryGamePassword, UnicodeString::TheEmptyString);
|
||||
txtInput.trim();
|
||||
if (!txtInput.isEmpty())
|
||||
{
|
||||
AsciiString munkee;
|
||||
munkee.translate(txtInput);
|
||||
joinGame(munkee);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void joinGame( AsciiString password )
|
||||
{
|
||||
GameSpyStagingRoom *ourRoom = TheGameSpyInfo->findStagingRoomByID(TheGameSpyInfo->getCurrentStagingRoomID());
|
||||
if (!ourRoom)
|
||||
{
|
||||
GameSpyCloseOverlay(GSOVERLAY_GAMEPASSWORD);
|
||||
SetLobbyAttemptHostJoin( FALSE );
|
||||
parentPopup = NULL;
|
||||
return;
|
||||
}
|
||||
PeerRequest req;
|
||||
req.peerRequestType = PeerRequest::PEERREQUEST_JOINSTAGINGROOM;
|
||||
req.text = ourRoom->getGameName().str();
|
||||
req.stagingRoom.id = ourRoom->getID();
|
||||
req.password = password.str();
|
||||
TheGameSpyPeerMessageQueue->addRequest(req);
|
||||
DEBUG_LOG(("Attempting to join game %d(%ls) with password [%s]\n", ourRoom->getID(), ourRoom->getGameName().str(), password.str()));
|
||||
GameSpyCloseOverlay(GSOVERLAY_GAMEPASSWORD);
|
||||
parentPopup = NULL;
|
||||
}
|
||||
@@ -0,0 +1,682 @@
|
||||
/*
|
||||
** 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: PopupLadderSelect.cpp ////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: August 2002
|
||||
//
|
||||
// Filename: PopupLadderSelect.cpp
|
||||
//
|
||||
// author: Matthew D. Campbell
|
||||
//
|
||||
// purpose: Contains the Callbacks for the Ladder Select Popup
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/Encrypt.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/MapUtil.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameNetwork/GameSpy/LadderDefs.h"
|
||||
#include "GameNetwork/GameSpy/PeerDefs.h"
|
||||
//#include "GameNetwork/GameSpy/PeerThread.h"
|
||||
#include "GameNetwork/GameSpyOverlay.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static NameKeyType parentID = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxLadderSelectID = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxLadderDetailsID = NAMEKEY_INVALID;
|
||||
static NameKeyType staticTextLadderNameID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOkID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonCancelID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *parent = NULL;
|
||||
static GameWindow *listboxLadderSelect = NULL;
|
||||
static GameWindow *listboxLadderDetails = NULL;
|
||||
static GameWindow *staticTextLadderName = NULL;
|
||||
static GameWindow *buttonOk = NULL;
|
||||
static GameWindow *buttonCancel = NULL;
|
||||
|
||||
// password entry popup
|
||||
static NameKeyType passwordParentID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonPasswordOkID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonPasswordCancelID = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryPasswordID = NAMEKEY_INVALID;
|
||||
static GameWindow *passwordParent = NULL;
|
||||
static GameWindow *textEntryPassword = NULL;
|
||||
|
||||
// incorrect password popup
|
||||
static NameKeyType badPasswordParentID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonBadPasswordOkID = NAMEKEY_INVALID;
|
||||
static GameWindow *badPasswordParent = NULL;
|
||||
|
||||
static void updateLadderDetails( Int ladderID, GameWindow *staticTextLadderName, GameWindow *listboxLadderDetails );
|
||||
|
||||
void PopulateQMLadderComboBox( void );
|
||||
void PopulateCustomLadderComboBox( void );
|
||||
|
||||
void PopulateQMLadderListBox( GameWindow *win );
|
||||
void PopulateCustomLadderListBox( GameWindow *win );
|
||||
|
||||
void HandleQMLadderSelection(Int ladderID);
|
||||
void HandleCustomLadderSelection(Int ladderID);
|
||||
|
||||
void CustomMatchHideHostPopup(Bool hide);
|
||||
|
||||
static void populateLadderComboBox( void )
|
||||
{
|
||||
// only one of these will do any work...
|
||||
PopulateQMLadderComboBox();
|
||||
PopulateCustomLadderComboBox();
|
||||
}
|
||||
|
||||
static void populateLadderListBox( void )
|
||||
{
|
||||
// only one of these will do any work...
|
||||
PopulateQMLadderListBox(listboxLadderSelect);
|
||||
PopulateCustomLadderListBox(listboxLadderSelect);
|
||||
|
||||
Int selIndex, selID;
|
||||
GadgetListBoxGetSelected(listboxLadderSelect, &selIndex);
|
||||
if (selIndex < 0)
|
||||
return;
|
||||
selID = (Int)GadgetListBoxGetItemData(listboxLadderSelect, selIndex);
|
||||
if (!selID)
|
||||
return;
|
||||
updateLadderDetails(selID, staticTextLadderName, listboxLadderDetails);
|
||||
}
|
||||
|
||||
static void handleLadderSelection( Int ladderID )
|
||||
{
|
||||
// only one of these will do any work...
|
||||
HandleQMLadderSelection(ladderID);
|
||||
HandleCustomLadderSelection(ladderID);
|
||||
}
|
||||
|
||||
|
||||
enum PasswordMode
|
||||
{
|
||||
PASS_NONE,
|
||||
PASS_ENTRY,
|
||||
PASS_ERROR
|
||||
};
|
||||
|
||||
static PasswordMode s_currentMode = PASS_NONE;
|
||||
static void setPasswordMode(PasswordMode mode)
|
||||
{
|
||||
s_currentMode = mode;
|
||||
switch(mode)
|
||||
{
|
||||
case PASS_NONE:
|
||||
if (passwordParent)
|
||||
passwordParent->winHide(TRUE);
|
||||
if (badPasswordParent)
|
||||
badPasswordParent->winHide(TRUE);
|
||||
if (buttonOk)
|
||||
buttonOk->winEnable(TRUE);
|
||||
if (buttonCancel)
|
||||
buttonCancel->winEnable(TRUE);
|
||||
if (textEntryPassword)
|
||||
textEntryPassword->winEnable(FALSE);
|
||||
if (listboxLadderSelect)
|
||||
listboxLadderSelect->winEnable(TRUE);
|
||||
TheWindowManager->winSetFocus(listboxLadderSelect);
|
||||
break;
|
||||
case PASS_ENTRY:
|
||||
if (passwordParent)
|
||||
passwordParent->winHide(FALSE);
|
||||
if (badPasswordParent)
|
||||
badPasswordParent->winHide(TRUE);
|
||||
if (buttonOk)
|
||||
buttonOk->winEnable(FALSE);
|
||||
if (buttonCancel)
|
||||
buttonCancel->winEnable(FALSE);
|
||||
if (textEntryPassword)
|
||||
{
|
||||
textEntryPassword->winEnable(TRUE);
|
||||
GadgetTextEntrySetText(textEntryPassword, UnicodeString::TheEmptyString);
|
||||
}
|
||||
if (listboxLadderSelect)
|
||||
listboxLadderSelect->winEnable(FALSE);
|
||||
TheWindowManager->winSetFocus(textEntryPassword);
|
||||
break;
|
||||
case PASS_ERROR:
|
||||
if (passwordParent)
|
||||
passwordParent->winHide(TRUE);
|
||||
if (badPasswordParent)
|
||||
badPasswordParent->winHide(FALSE);
|
||||
if (buttonOk)
|
||||
buttonOk->winEnable(FALSE);
|
||||
if (buttonCancel)
|
||||
buttonCancel->winEnable(FALSE);
|
||||
if (textEntryPassword)
|
||||
textEntryPassword->winEnable(FALSE);
|
||||
if (listboxLadderSelect)
|
||||
listboxLadderSelect->winEnable(FALSE);
|
||||
TheWindowManager->winSetFocus(parent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupLadderSelectInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parentID = NAMEKEY("PopupLadderSelect.wnd:Parent");
|
||||
parent = TheWindowManager->winGetWindowFromId(NULL, parentID);
|
||||
|
||||
listboxLadderSelectID = NAMEKEY("PopupLadderSelect.wnd:ListBoxLadderSelect");
|
||||
listboxLadderSelect = TheWindowManager->winGetWindowFromId(parent, listboxLadderSelectID);
|
||||
|
||||
listboxLadderDetailsID = NAMEKEY("PopupLadderSelect.wnd:ListBoxLadderDetails");
|
||||
listboxLadderDetails = TheWindowManager->winGetWindowFromId(parent, listboxLadderDetailsID);
|
||||
|
||||
staticTextLadderNameID = NAMEKEY("PopupLadderSelect.wnd:StaticTextLadderName");
|
||||
staticTextLadderName = TheWindowManager->winGetWindowFromId(parent, staticTextLadderNameID);
|
||||
|
||||
buttonOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonOk");
|
||||
buttonCancelID = NAMEKEY("PopupLadderSelect.wnd:ButtonCancel");
|
||||
|
||||
buttonOk = TheWindowManager->winGetWindowFromId(parent, buttonOkID);
|
||||
buttonCancel = TheWindowManager->winGetWindowFromId(parent, buttonCancelID);
|
||||
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
TheWindowManager->winSetModal( parent );
|
||||
|
||||
// password entry popup
|
||||
passwordParentID = NAMEKEY("PopupLadderSelect.wnd:PasswordParent");
|
||||
passwordParent = TheWindowManager->winGetWindowFromId(parent, passwordParentID);
|
||||
buttonPasswordOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonPasswordOk");
|
||||
buttonPasswordCancelID = NAMEKEY("PopupLadderSelect.wnd:ButtonPasswordCancel");
|
||||
textEntryPasswordID = NAMEKEY("PopupLadderSelect.wnd:PasswordEntry");
|
||||
textEntryPassword = TheWindowManager->winGetWindowFromId(parent, textEntryPasswordID);
|
||||
|
||||
// bad password popup
|
||||
badPasswordParentID = NAMEKEY("PopupLadderSelect.wnd:BadPasswordParent");
|
||||
badPasswordParent = TheWindowManager->winGetWindowFromId(parent, badPasswordParentID);
|
||||
buttonBadPasswordOkID = NAMEKEY("PopupLadderSelect.wnd:ButtonBadPasswordOk");
|
||||
|
||||
setPasswordMode(PASS_NONE);
|
||||
|
||||
CustomMatchHideHostPopup(TRUE);
|
||||
|
||||
// populate list box (based on whether we're in custom or quickmatch)
|
||||
populateLadderListBox();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupLadderSelectInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
// if (buttonPushed)
|
||||
// break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
switch (s_currentMode)
|
||||
{
|
||||
case PASS_NONE:
|
||||
// re-select whatever was chosen before
|
||||
populateLadderComboBox();
|
||||
GameSpyCloseOverlay(GSOVERLAY_LADDERSELECT);
|
||||
break;
|
||||
case PASS_ENTRY:
|
||||
case PASS_ERROR:
|
||||
setPasswordMode(PASS_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
}
|
||||
|
||||
static Int ladderIndex = 0;
|
||||
void ladderSelectedCallback(void)
|
||||
{
|
||||
handleLadderSelection( ladderIndex );
|
||||
|
||||
// update combo box
|
||||
populateLadderComboBox();
|
||||
|
||||
// tear down overlay
|
||||
GameSpyCloseOverlay( GSOVERLAY_LADDERSELECT );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** System callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupLadderSelectSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
break;
|
||||
} // end create
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
parent = NULL;
|
||||
listboxLadderSelect = NULL;
|
||||
listboxLadderDetails = NULL;
|
||||
CustomMatchHideHostPopup(FALSE);
|
||||
break;
|
||||
} // end case
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're given the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
break;
|
||||
} // end input
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if (controlID == buttonOkID)
|
||||
{
|
||||
// save selection
|
||||
Int selectPos = -1;
|
||||
GadgetListBoxGetSelected( listboxLadderSelect, &selectPos );
|
||||
if (selectPos < 0)
|
||||
break;
|
||||
|
||||
ladderIndex = (Int)GadgetListBoxGetItemData( listboxLadderSelect, selectPos, 0 );
|
||||
const LadderInfo *li = TheLadderList->findLadderByIndex( ladderIndex );
|
||||
if (li && li->cryptedPassword.isNotEmpty())
|
||||
{
|
||||
// need password asking
|
||||
setPasswordMode(PASS_ENTRY);
|
||||
}
|
||||
else
|
||||
{
|
||||
ladderSelectedCallback();
|
||||
}
|
||||
}
|
||||
else if (controlID == buttonCancelID)
|
||||
{
|
||||
// reset what had been
|
||||
populateLadderComboBox();
|
||||
|
||||
// tear down overlay
|
||||
GameSpyCloseOverlay( GSOVERLAY_LADDERSELECT );
|
||||
}
|
||||
else if (controlID == buttonPasswordOkID)
|
||||
{
|
||||
const LadderInfo *li = TheLadderList->findLadderByIndex( ladderIndex );
|
||||
if (!li || li->cryptedPassword.isEmpty())
|
||||
{
|
||||
// eh? something's not right. just pretend they typed something wrong...
|
||||
setPasswordMode(PASS_ERROR);
|
||||
break;
|
||||
}
|
||||
|
||||
AsciiString pass;
|
||||
pass.translate(GadgetTextEntryGetText(textEntryPassword));
|
||||
if ( pass.isNotEmpty() ) // password ok
|
||||
{
|
||||
AsciiString cryptPass = EncryptString(pass.str());
|
||||
DEBUG_LOG(("pass is %s, crypted pass is %s, comparing to %s\n",
|
||||
pass.str(), cryptPass.str(), li->cryptedPassword.str()));
|
||||
if (cryptPass == li->cryptedPassword)
|
||||
ladderSelectedCallback();
|
||||
else
|
||||
setPasswordMode(PASS_ERROR);
|
||||
}
|
||||
else
|
||||
{
|
||||
setPasswordMode(PASS_ERROR);
|
||||
}
|
||||
}
|
||||
else if (controlID == buttonPasswordCancelID)
|
||||
{
|
||||
setPasswordMode(PASS_NONE);
|
||||
}
|
||||
else if (controlID == buttonBadPasswordOkID)
|
||||
{
|
||||
setPasswordMode(PASS_NONE);
|
||||
}
|
||||
break;
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GLM_SELECTED:
|
||||
{
|
||||
Int selIndex, selID;
|
||||
GadgetListBoxGetSelected(listboxLadderSelect, &selIndex);
|
||||
if (selIndex < 0)
|
||||
break;
|
||||
|
||||
selID = (Int)GadgetListBoxGetItemData(listboxLadderSelect, selIndex);
|
||||
if (!selID)
|
||||
break;
|
||||
|
||||
updateLadderDetails(selID, staticTextLadderName, listboxLadderDetails);
|
||||
break;
|
||||
} // end GLM_DOUBLE_CLICKED
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GLM_DOUBLE_CLICKED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
Int selectPos = (Int)mData2;
|
||||
GadgetListBoxSetSelected(control, &selectPos);
|
||||
|
||||
if( controlID == listboxLadderSelectID )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( parent, GBM_SELECTED,
|
||||
(WindowMsgData)buttonOk, buttonOk->winGetWindowId() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if (controlID == textEntryPasswordID)
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( parent, GBM_SELECTED,
|
||||
(WindowMsgData)(TheWindowManager->winGetWindowFromId(passwordParent, buttonPasswordOkID)), buttonPasswordOkID );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void updateLadderDetails( Int selID, GameWindow *staticTextLadderName, GameWindow *listboxLadderDetails )
|
||||
{
|
||||
if (!staticTextLadderName || !listboxLadderDetails)
|
||||
return;
|
||||
|
||||
GadgetStaticTextSetText(staticTextLadderName, UnicodeString::TheEmptyString);
|
||||
GadgetListBoxReset(listboxLadderDetails);
|
||||
|
||||
const LadderInfo *info = TheLadderList->findLadderByIndex(selID);
|
||||
if (!info)
|
||||
return;
|
||||
|
||||
UnicodeString line;
|
||||
Color color = GameMakeColor( 255, 255, 255, 255 );
|
||||
Color captionColor = GameMakeColor( 0, 255, 255, 255 );
|
||||
|
||||
// name
|
||||
line.format(TheGameText->fetch("GUI:LadderNameAndSize"), info->name.str(), info->playersPerTeam, info->playersPerTeam);
|
||||
GadgetStaticTextSetText(staticTextLadderName, line);
|
||||
|
||||
// location
|
||||
if (!info->location.isEmpty())
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, info->location, captionColor, -1);
|
||||
|
||||
// homepage
|
||||
line.format(TheGameText->fetch("GUI:LadderURL"), info->homepageURL.str());
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1);
|
||||
|
||||
// description
|
||||
if (!info->description.isEmpty())
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, info->description, color, -1);
|
||||
|
||||
// requires password?
|
||||
if (info->cryptedPassword.isNotEmpty())
|
||||
{
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderHasPassword"), captionColor, -1);
|
||||
}
|
||||
|
||||
// wins limits
|
||||
if (info->minWins)
|
||||
{
|
||||
line.format(TheGameText->fetch("GUI:LadderMinWins"), info->minWins);
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1);
|
||||
}
|
||||
if (info->maxWins)
|
||||
{
|
||||
line.format(TheGameText->fetch("GUI:LadderMaxWins"), info->maxWins);
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, line, captionColor, -1);
|
||||
}
|
||||
|
||||
// random factions?
|
||||
if (info->randomFactions)
|
||||
{
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderRandomFactions"), captionColor, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderFactions"), captionColor, -1);
|
||||
}
|
||||
|
||||
// factions
|
||||
AsciiStringList validFactions = info->validFactions;
|
||||
for (AsciiStringListIterator it = validFactions.begin(); it != validFactions.end(); ++it)
|
||||
{
|
||||
AsciiString marker;
|
||||
marker.format("INI:Faction%s", it->str());
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch(marker), color, -1);
|
||||
}
|
||||
|
||||
// random maps?
|
||||
if (info->randomMaps)
|
||||
{
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderRandomMaps"), captionColor, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, TheGameText->fetch("GUI:LadderMaps"), captionColor, -1);
|
||||
}
|
||||
|
||||
// maps
|
||||
AsciiStringList validMaps = info->validMaps;
|
||||
for (it = validMaps.begin(); it != validMaps.end(); ++it)
|
||||
{
|
||||
const MapMetaData *md = TheMapCache->findMap(*it);
|
||||
if (md)
|
||||
{
|
||||
GadgetListBoxAddEntryText(listboxLadderDetails, md->m_displayName, color, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void closeRightClickMenu(GameWindow *win)
|
||||
{
|
||||
|
||||
if(win)
|
||||
{
|
||||
WindowLayout *winLay = win->winGetLayout();
|
||||
if(!winLay)
|
||||
return;
|
||||
winLay->destroyWindows();
|
||||
winLay->deleteInstance();
|
||||
winLay = NULL;
|
||||
|
||||
}
|
||||
}
|
||||
void RCGameDetailsMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
}
|
||||
|
||||
WindowMsgHandledType RCGameDetailsMenuSystem( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
static NameKeyType ladderInfoID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOkID = NAMEKEY_INVALID;
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
ladderInfoID = NAMEKEY("RCGameDetailsMenu.wnd:ButtonLadderDetails");
|
||||
buttonOkID = NAMEKEY("PopupLadderDetails.wnd:ButtonOk");
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GGM_CLOSE:
|
||||
{
|
||||
closeRightClickMenu(window);
|
||||
//rcMenu = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
Int selectedID = (Int)window->winGetUserData();
|
||||
if(!selectedID)
|
||||
break;
|
||||
closeRightClickMenu(window);
|
||||
|
||||
if (controlID == ladderInfoID)
|
||||
{
|
||||
StagingRoomMap *srm = TheGameSpyInfo->getStagingRoomList();
|
||||
StagingRoomMap::iterator srmIt = srm->find(selectedID);
|
||||
if (srmIt != srm->end())
|
||||
{
|
||||
GameSpyStagingRoom *theRoom = srmIt->second;
|
||||
if (!theRoom)
|
||||
break;
|
||||
const LadderInfo *linfo = TheLadderList->findLadder(theRoom->getLadderIP(), theRoom->getLadderPort());
|
||||
if (linfo)
|
||||
{
|
||||
WindowLayout *rcLayout = TheWindowManager->winCreateLayout(AsciiString("Menus/PopupLadderDetails.wnd"));
|
||||
if (!rcLayout)
|
||||
break;
|
||||
|
||||
GameWindow *rcMenu = rcLayout->getFirstWindow();
|
||||
rcMenu->winGetLayout()->runInit();
|
||||
rcMenu->winBringToTop();
|
||||
rcMenu->winHide(FALSE);
|
||||
|
||||
rcMenu->winSetUserData((void *)selectedID);
|
||||
TheWindowManager->winSetLoneWindow(rcMenu);
|
||||
|
||||
GameWindow *st = TheWindowManager->winGetWindowFromId(NULL,
|
||||
NAMEKEY("PopupLadderDetails.wnd:StaticTextLadderName"));
|
||||
GameWindow *lb = TheWindowManager->winGetWindowFromId(NULL,
|
||||
NAMEKEY("PopupLadderDetails.wnd:ListBoxLadderDetails"));
|
||||
updateLadderDetails(selectedID, st, lb);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
** 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: PopupReplay.cpp /////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: Generals
|
||||
//
|
||||
// File name: PopupReplay.cpp
|
||||
//
|
||||
// Created: Matthew D. Campbell, November 2002
|
||||
//
|
||||
// Desc: the Replay Save window control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/LocalFileSystem.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "Common/Recorder.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/MessageBox.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static NameKeyType buttonBackKey = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonSaveKey = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxGamesKey = NAMEKEY_INVALID;
|
||||
static NameKeyType textEntryReplayNameKey = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *parent = NULL;
|
||||
static GameWindow *replaySavedParent = NULL;
|
||||
|
||||
static time_t s_fileSavePopupStartTime = 0;
|
||||
static const time_t s_fileSavePopupDuration = 1000;
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
extern void PopulateReplayFileListbox(GameWindow *listbox);
|
||||
extern void ScoreScreenEnableControls(Bool enable);
|
||||
extern UnicodeString GetReplayFilenameFromListbox(GameWindow *listbox, Int index);
|
||||
extern std::string LastReplayFileName;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Show or hide the "Replay Saved" popup */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ShowReplaySavedPopup(Bool show)
|
||||
{
|
||||
if (replaySavedParent != NULL) {
|
||||
if (show) {
|
||||
replaySavedParent->winHide(FALSE);
|
||||
} else {
|
||||
replaySavedParent->winHide(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Close the save/load menu */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void closeSaveMenu( GameWindow *window )
|
||||
{
|
||||
WindowLayout *layout = window->winGetLayout();
|
||||
|
||||
if( layout )
|
||||
layout->hide( TRUE );
|
||||
|
||||
} // end closeSaveMenu
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the SaveLoad menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupReplayInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// get ids for our children controls
|
||||
buttonBackKey = NAMEKEY( "PopupReplay.wnd:ButtonBack" );
|
||||
buttonSaveKey = NAMEKEY( "PopupReplay.wnd:ButtonSave" );
|
||||
listboxGamesKey = NAMEKEY( "PopupReplay.wnd:ListboxGames" );
|
||||
textEntryReplayNameKey = NAMEKEY( "PopupReplay.wnd:TextEntryReplayName" );
|
||||
|
||||
//set keyboard focus to main parent and set modal
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey("PopupReplay.wnd:PopupReplayMenu");
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
|
||||
NameKeyType replaySavedParentID = TheNameKeyGenerator->nameToKey("PopupReplay.wnd:PopupReplaySaved");
|
||||
replaySavedParent = TheWindowManager->winGetWindowFromId( NULL, replaySavedParentID);
|
||||
if (replaySavedParent == NULL) {
|
||||
DEBUG_CRASH(("replaySavedParent == NULL"));
|
||||
}
|
||||
|
||||
ShowReplaySavedPopup(FALSE);
|
||||
|
||||
// enable the menu action buttons
|
||||
GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupReplay.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( TRUE );
|
||||
|
||||
// get the listbox that will have the save games in it
|
||||
GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( NULL, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("PopupReplayInit - Unable to find games listbox\n") );
|
||||
|
||||
// populate the listbox with the save games on disk
|
||||
PopulateReplayFileListbox(listboxGames);
|
||||
|
||||
GameWindow *textEntryReplayName = TheWindowManager->winGetWindowFromId( parent, textEntryReplayNameKey );
|
||||
GadgetTextEntrySetText(textEntryReplayName, UnicodeString::TheEmptyString);
|
||||
TheWindowManager->winSetFocus( textEntryReplayName );
|
||||
|
||||
//Disable the button immediately as the code above us starts off with an empty string.
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId( parent, buttonSaveKey );
|
||||
if( control )
|
||||
{
|
||||
control->winEnable( FALSE );
|
||||
}
|
||||
|
||||
} // end SaveLoadMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** SaveLoad menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupReplayShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parent = NULL;
|
||||
|
||||
} // end SaveLoadMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** SaveLoad menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopupReplayUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
if (s_fileSavePopupStartTime != 0)
|
||||
{
|
||||
// the replay save confirmation popup is up
|
||||
// check to see if its time to take it down.
|
||||
if ((timeGetTime() - s_fileSavePopupStartTime) >= s_fileSavePopupDuration)
|
||||
{
|
||||
ShowReplaySavedPopup(FALSE);
|
||||
|
||||
// close the save/load menu
|
||||
closeSaveMenu( parent );
|
||||
ScoreScreenEnableControls(TRUE);
|
||||
|
||||
// reset the timer to 0 cause we have to.
|
||||
s_fileSavePopupStartTime = 0;
|
||||
}
|
||||
}
|
||||
} // end SaveLoadMenuUpdate
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupReplayInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( parent, buttonBackKey );
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonBackKey );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
|
||||
static void reallySaveReplay(void);
|
||||
static std::string replayPath;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Save the replay */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static GameWindow *messageBoxWin = NULL;
|
||||
static void saveReplay( UnicodeString filename )
|
||||
{
|
||||
AsciiString translated;
|
||||
if (filename == TheGameText->fetch("GUI:LastReplay"))
|
||||
{
|
||||
translated = TheRecorder->getLastReplayFileName();
|
||||
}
|
||||
else
|
||||
{
|
||||
translated.translate(filename);
|
||||
}
|
||||
|
||||
AsciiString fullPath = TheRecorder->getReplayDir();
|
||||
fullPath.concat(translated);
|
||||
fullPath.concat(TheRecorder->getReplayExtention());
|
||||
|
||||
replayPath = fullPath.str();
|
||||
messageBoxWin = NULL;
|
||||
if (TheLocalFileSystem->doesFileExist(fullPath.str()))
|
||||
{
|
||||
messageBoxWin = MessageBoxOkCancel(TheGameText->fetch("GUI:OverwriteReplayTitle"), TheGameText->fetch("GUI:OverwriteReplay"), reallySaveReplay, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
reallySaveReplay();
|
||||
}
|
||||
}
|
||||
void reallySaveReplay(void)
|
||||
{
|
||||
AsciiString filename = replayPath.c_str();
|
||||
|
||||
AsciiString oldFilename;
|
||||
oldFilename = TheRecorder->getReplayDir();
|
||||
oldFilename.concat(LastReplayFileName.c_str());
|
||||
oldFilename.concat(TheRecorder->getReplayExtention());
|
||||
|
||||
if (oldFilename == filename)
|
||||
return;
|
||||
|
||||
if (TheLocalFileSystem->doesFileExist(filename.str()))
|
||||
{
|
||||
if(DeleteFile(filename.str()) == 0)
|
||||
{
|
||||
wchar_t buffer[1024];
|
||||
FormatMessageW ( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, buffer, sizeof(buffer), NULL);
|
||||
UnicodeString errorStr;
|
||||
errorStr.set(buffer);
|
||||
errorStr.trim();
|
||||
if(messageBoxWin)
|
||||
{
|
||||
TheWindowManager->winUnsetModal(messageBoxWin);
|
||||
messageBoxWin = NULL;
|
||||
}
|
||||
MessageBoxOk(TheGameText->fetch("GUI:Error"),errorStr, NULL);
|
||||
|
||||
// get the listbox that will have the save games in it
|
||||
GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("reallySaveReplay - Unable to find games listbox\n") );
|
||||
|
||||
// populate the listbox with the save games on disk
|
||||
PopulateReplayFileListbox(listboxGames);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// copy the replay to the right place
|
||||
if(CopyFile(oldFilename.str(),filename.str(), FALSE) == 0)
|
||||
{
|
||||
wchar_t buffer[1024];
|
||||
FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, buffer, sizeof(buffer), NULL);
|
||||
UnicodeString errorStr;
|
||||
errorStr.set(buffer);
|
||||
errorStr.trim();
|
||||
if(messageBoxWin)
|
||||
{
|
||||
TheWindowManager->winUnsetModal(messageBoxWin);
|
||||
messageBoxWin = NULL;
|
||||
}
|
||||
MessageBoxOk(TheGameText->fetch("GUI:Error"),errorStr, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the listbox that will have the save games in it
|
||||
GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("reallySaveReplay - Unable to find games listbox\n") );
|
||||
|
||||
// populate the listbox with the save games on disk
|
||||
PopulateReplayFileListbox(listboxGames);
|
||||
|
||||
ShowReplaySavedPopup(TRUE);
|
||||
s_fileSavePopupStartTime = timeGetTime();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** SaveLoad menu system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType PopupReplaySystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GLM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
|
||||
GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( window, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("PopupReplaySystem - Unable to find games listbox\n") );
|
||||
|
||||
//
|
||||
// handle games listbox, when certain items are selected in the listbox only some
|
||||
// commands are available
|
||||
//
|
||||
if( control == listboxGames )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
if (rowSelected >= 0)
|
||||
{
|
||||
UnicodeString filename;
|
||||
filename = GadgetListBoxGetText(listboxGames, rowSelected);
|
||||
GameWindow *textEntryReplayName = TheWindowManager->winGetWindowFromId( window, textEntryReplayNameKey );
|
||||
DEBUG_ASSERTCRASH( textEntryReplayName != NULL, ("PopupReplaySystem - Unable to find text entry\n") );
|
||||
GadgetTextEntrySetText(textEntryReplayName, filename);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == textEntryReplayNameKey )
|
||||
{
|
||||
UnicodeString filename = GadgetTextEntryGetText( control );
|
||||
if (filename.isEmpty())
|
||||
break;
|
||||
|
||||
saveReplay(filename);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonSaveKey )
|
||||
{
|
||||
// get the filename, and see if we are overwriting
|
||||
GameWindow *textEntryReplayName = TheWindowManager->winGetWindowFromId( window, textEntryReplayNameKey );
|
||||
DEBUG_ASSERTCRASH( textEntryReplayName != NULL, ("PopupReplaySystem - Unable to find text entry\n") );
|
||||
|
||||
UnicodeString filename = GadgetTextEntryGetText( textEntryReplayName );
|
||||
if (filename.isEmpty())
|
||||
break;
|
||||
|
||||
saveReplay(filename);
|
||||
|
||||
}
|
||||
else if( controlID == buttonBackKey )
|
||||
{
|
||||
|
||||
// close the save/load menu
|
||||
closeSaveMenu( window );
|
||||
ScoreScreenEnableControls(TRUE);
|
||||
|
||||
} // end if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
case GEM_UPDATE_TEXT:
|
||||
{
|
||||
//Kris:
|
||||
//Enable or disable the save button -- disabled when empty.
|
||||
GameWindow *control = TheWindowManager->winGetWindowFromId( parent, textEntryReplayNameKey );
|
||||
if( control )
|
||||
{
|
||||
UnicodeString filename;
|
||||
filename.set( GadgetTextEntryGetText( control ) );
|
||||
control = TheWindowManager->winGetWindowFromId( parent, buttonSaveKey );
|
||||
if( control )
|
||||
{
|
||||
if( filename.isEmpty() )
|
||||
{
|
||||
control->winEnable( FALSE );
|
||||
}
|
||||
else
|
||||
{
|
||||
control->winEnable( TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,903 @@
|
||||
/*
|
||||
** 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: PopupSaveLoad.cpp /////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: PopupSaveLoad.cpp
|
||||
//
|
||||
// Created: Chris Brue, June 2002
|
||||
//
|
||||
// Desc: the Save/Load window control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/GameState.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "GameClient/CampaignManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameClient/GameWindowTransitions.h"
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static NameKeyType buttonBackKey = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonSaveKey = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonLoadKey = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonDeleteKey = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxGamesKey = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOverwriteCancel = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOverwriteConfirm = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonLoadCancel = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonLoadConfirm = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonSaveDescCancel = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonSaveDescConfirm = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonDeleteConfirm = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonDeleteCancel = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *buttonFrame = NULL;
|
||||
static GameWindow *overwriteConfirm = NULL;
|
||||
static GameWindow *loadConfirm = NULL;
|
||||
static GameWindow *saveDesc = NULL;
|
||||
static GameWindow *listboxGames = NULL;
|
||||
static GameWindow *editDesc = NULL;
|
||||
static GameWindow *deleteConfirm = NULL;
|
||||
|
||||
static GameWindow *parent = NULL;
|
||||
static SaveLoadLayoutType currentLayoutType = SLLT_INVALID;
|
||||
static Bool isPopup = FALSE;
|
||||
static Int initialGadgetDelay = 2;
|
||||
static Bool justEntered = FALSE;
|
||||
static Bool isShuttingDown = false;
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
extern Bool DontShowMainMenu; //KRIS
|
||||
extern Bool ReplayWasPressed;
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Given the current layout and selection in the game listbox, update the main save/load
|
||||
* menu buttons to be enabled or disabled */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void updateMenuActions( void )
|
||||
{
|
||||
|
||||
// for loading only, disable the save button, otherwise enable it
|
||||
GameWindow *saveButton = TheWindowManager->winGetWindowFromId( NULL, buttonSaveKey );
|
||||
DEBUG_ASSERTCRASH( saveButton, ("SaveLoadMenuInit: Unable to find save button\n") );
|
||||
if( currentLayoutType == SLLT_LOAD_ONLY )
|
||||
saveButton->winEnable( FALSE );
|
||||
else
|
||||
saveButton->winEnable( TRUE );
|
||||
|
||||
// get the games listbox
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
|
||||
// if something with a game file is selected we can use load and delete
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxGames, &selected );
|
||||
AvailableGameInfo *selectedGameInfo;
|
||||
selectedGameInfo = (AvailableGameInfo *)GadgetListBoxGetItemData( listboxGames, selected );
|
||||
GameWindow *buttonLoad = TheWindowManager->winGetWindowFromId( NULL, buttonLoadKey );
|
||||
buttonLoad->winEnable( selectedGameInfo != NULL );
|
||||
GameWindow *buttonDelete = TheWindowManager->winGetWindowFromId( NULL, buttonDeleteKey );
|
||||
buttonDelete->winEnable( selectedGameInfo != NULL );
|
||||
|
||||
} // end updateMenuActions
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the SaveLoad menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SaveLoadMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// set default behavior for this menu
|
||||
currentLayoutType = SLLT_SAVE_AND_LOAD;
|
||||
isPopup = TRUE;
|
||||
// get layout type if present
|
||||
if( userData )
|
||||
currentLayoutType = *((SaveLoadLayoutType *)userData);
|
||||
|
||||
// get ids for our children controls
|
||||
buttonBackKey = NAMEKEY( "PopupSaveLoad.wnd:ButtonBack" );
|
||||
buttonSaveKey = NAMEKEY( "PopupSaveLoad.wnd:ButtonSave" );
|
||||
buttonLoadKey = NAMEKEY( "PopupSaveLoad.wnd:ButtonLoad" );
|
||||
buttonDeleteKey = NAMEKEY( "PopupSaveLoad.wnd:ButtonDelete" );
|
||||
listboxGamesKey = NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" );
|
||||
buttonOverwriteCancel = NAMEKEY( "PopupSaveLoad.wnd:ButtonOverwriteCancel" );
|
||||
buttonOverwriteConfirm = NAMEKEY( "PopupSaveLoad.wnd:ButtonOverwriteConfirm" );
|
||||
buttonLoadCancel = NAMEKEY( "PopupSaveLoad.wnd:ButtonLoadCancel" );
|
||||
buttonLoadConfirm = NAMEKEY( "PopupSaveLoad.wnd:ButtonLoadConfirm" );
|
||||
buttonSaveDescCancel = NAMEKEY( "PopupSaveLoad.wnd:ButtonSaveDescCancel" );
|
||||
buttonSaveDescConfirm = NAMEKEY( "PopupSaveLoad.wnd:ButtonSaveDescConfirm" );
|
||||
buttonDeleteConfirm = NAMEKEY( "PopupSaveLoad.wnd:ButtonDeleteConfirm" );
|
||||
buttonDeleteCancel = NAMEKEY( "PopupSaveLoad.wnd:ButtonDeleteCancel" );
|
||||
|
||||
//set keyboard focus to main parent and set modal
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey("PopupSaveLoad.wnd:SaveLoadMenu");
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
TheWindowManager->winSetModal( parent );
|
||||
|
||||
// enable the menu action buttons
|
||||
buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( TRUE );
|
||||
|
||||
// get confirmation windows and hide
|
||||
overwriteConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:OverwriteConfirmParent" ) );
|
||||
overwriteConfirm->winHide( TRUE );
|
||||
loadConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:LoadConfirmParent" ) );
|
||||
loadConfirm->winHide( TRUE );
|
||||
saveDesc = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:SaveDescParent" ) );
|
||||
saveDesc->winHide( TRUE );
|
||||
deleteConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:DeleteConfirmParent" ) );
|
||||
editDesc = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:EntryDesc" ) );
|
||||
// get the listbox that will have the save games in it
|
||||
listboxGames = TheWindowManager->winGetWindowFromId( NULL, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("SaveLoadMenuInit - Unable to find games listbox\n") );
|
||||
|
||||
// populate the listbox with the save games on disk
|
||||
TheGameState->populateSaveGameListbox( listboxGames, currentLayoutType );
|
||||
|
||||
// update the availability of the menu buttons
|
||||
updateMenuActions();
|
||||
|
||||
} // end SaveLoadMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the SaveLoad menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SaveLoadMenuFullScreenInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
TheShell->showShellMap(TRUE);
|
||||
|
||||
isPopup = FALSE;
|
||||
// set default behavior for this menu
|
||||
currentLayoutType = SLLT_LOAD_ONLY;
|
||||
|
||||
// get layout type if present
|
||||
if( userData )
|
||||
currentLayoutType = *((SaveLoadLayoutType *)userData);
|
||||
|
||||
// get ids for our children controls
|
||||
buttonBackKey = NAMEKEY( "SaveLoad.wnd:ButtonBack" );
|
||||
buttonSaveKey = NAMEKEY( "SaveLoad.wnd:ButtonSave" );
|
||||
buttonLoadKey = NAMEKEY( "SaveLoad.wnd:ButtonLoad" );
|
||||
buttonDeleteKey = NAMEKEY( "SaveLoad.wnd:ButtonDelete" );
|
||||
listboxGamesKey = NAMEKEY( "SaveLoad.wnd:ListboxGames" );
|
||||
buttonOverwriteCancel = NAMEKEY( "SaveLoad.wnd:ButtonOverwriteCancel" );
|
||||
buttonOverwriteConfirm = NAMEKEY( "SaveLoad.wnd:ButtonOverwriteConfirm" );
|
||||
buttonLoadCancel = NAMEKEY( "SaveLoad.wnd:ButtonLoadCancel" );
|
||||
buttonLoadConfirm = NAMEKEY( "SaveLoad.wnd:ButtonLoadConfirm" );
|
||||
buttonSaveDescCancel = NAMEKEY( "SaveLoad.wnd:ButtonSaveDescCancel" );
|
||||
buttonSaveDescConfirm = NAMEKEY( "SaveLoad.wnd:ButtonSaveDescConfirm" );
|
||||
buttonDeleteConfirm = NAMEKEY( "SaveLoad.wnd:ButtonDeleteConfirm" );
|
||||
buttonDeleteCancel = NAMEKEY( "SaveLoad.wnd:ButtonDeleteCancel" );
|
||||
|
||||
//set keyboard focus to main parent and set modal
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey("SaveLoad.wnd:SaveLoadMenu");
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
// TheWindowManager->winSetModal( parent );
|
||||
|
||||
// enable the menu action buttons
|
||||
buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "SaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( TRUE );
|
||||
|
||||
// get confirmation windows and hide
|
||||
overwriteConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "SaveLoad.wnd:OverwriteConfirmParent" ) );
|
||||
overwriteConfirm->winHide( TRUE );
|
||||
loadConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "SaveLoad.wnd:LoadConfirmParent" ) );
|
||||
loadConfirm->winHide( TRUE );
|
||||
saveDesc = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "SaveLoad.wnd:SaveDescParent" ) );
|
||||
saveDesc->winHide( TRUE );
|
||||
|
||||
editDesc = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "SaveLoad.wnd:EntryDesc" ) );
|
||||
deleteConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "SaveLoad.wnd:DeleteConfirmParent" ) );
|
||||
// get the listbox that will have the save games in it
|
||||
listboxGames = TheWindowManager->winGetWindowFromId( NULL, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("SaveLoadMenuInit - Unable to find games listbox\n") );
|
||||
|
||||
// populate the listbox with the save games on disk
|
||||
TheGameState->populateSaveGameListbox( listboxGames, currentLayoutType );
|
||||
|
||||
// update the availability of the menu buttons
|
||||
updateMenuActions();
|
||||
|
||||
layout->hide(FALSE);
|
||||
justEntered = TRUE;
|
||||
initialGadgetDelay = 2;
|
||||
if(parent)
|
||||
parent->winHide(TRUE);
|
||||
isShuttingDown = false;
|
||||
} // end SaveLoadMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** SaveLoad menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SaveLoadMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
Bool popImmediate = *(Bool *)userData;
|
||||
if( popImmediate )
|
||||
{
|
||||
|
||||
layout->hide( TRUE );
|
||||
TheShell->shutdownComplete( layout );
|
||||
return;
|
||||
|
||||
} //end if
|
||||
|
||||
// our shutdown is complete
|
||||
TheTransitionHandler->reverse("SaveLoadMenuFade");
|
||||
isShuttingDown = TRUE;
|
||||
} // end SaveLoadMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** SaveLoad menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SaveLoadMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
if(DontShowMainMenu && justEntered)
|
||||
justEntered = FALSE;
|
||||
if(ReplayWasPressed && justEntered)
|
||||
{
|
||||
justEntered = FALSE;
|
||||
ReplayWasPressed = FALSE;
|
||||
}
|
||||
if(justEntered)
|
||||
{
|
||||
if(initialGadgetDelay == 1)
|
||||
{
|
||||
TheTransitionHandler->remove("MainMenuDefaultMenuLogoFade");
|
||||
TheTransitionHandler->setGroup("SaveLoadMenuFade");
|
||||
initialGadgetDelay = 2;
|
||||
justEntered = FALSE;
|
||||
}
|
||||
else
|
||||
initialGadgetDelay--;
|
||||
}
|
||||
|
||||
if(isShuttingDown && TheShell->isAnimFinished()&& TheTransitionHandler->isFinished())
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // end SaveLoadMenuUpdate
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType SaveLoadMenuInput( GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( parent, buttonBackKey );
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonBackKey );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Get the file info of the selected savegame file in the listbox */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static AvailableGameInfo *getSelectedSaveFileInfo( GameWindow *window )
|
||||
{
|
||||
|
||||
// get the listbox
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( window, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("SaveLoadMenuInit - Unable to find games listbox\n") );
|
||||
|
||||
// which item is selected
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxGames, &selected );
|
||||
|
||||
// get the item data of the selection
|
||||
AvailableGameInfo *selectedGameInfo;
|
||||
selectedGameInfo = (AvailableGameInfo *)GadgetListBoxGetItemData( listboxGames, selected );
|
||||
|
||||
return selectedGameInfo;
|
||||
|
||||
} // end getSelectedSaveFileInfo
|
||||
|
||||
// ---------------------------------------------------con------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------ // close the save/load menu
|
||||
static void doLoadGame( void )
|
||||
{
|
||||
|
||||
// get listbox of games
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
DEBUG_ASSERTCRASH( listboxGames, ("doLoadGame: Unable to find game listbox\n") );
|
||||
|
||||
// get selected game info
|
||||
AvailableGameInfo *selectedGameInfo = getSelectedSaveFileInfo( listboxGames );
|
||||
DEBUG_ASSERTCRASH( selectedGameInfo, ("doLoadGame: No selected game info found\n") );
|
||||
|
||||
// when loading a game we also close the quit/esc menu for the user when in-game
|
||||
if( TheShell->isShellActive() == FALSE )
|
||||
{
|
||||
destroyQuitMenu();
|
||||
// ToggleQuitMenu();
|
||||
// TheTransitionHandler->remove("QuitNoSave");
|
||||
// TheTransitionHandler->remove("QuitFull");
|
||||
}
|
||||
else
|
||||
{
|
||||
TheTransitionHandler->remove("MainMenuLoadReplayMenu");
|
||||
TheTransitionHandler->remove("MainMenuLoadReplayMenuBack");
|
||||
TheGameLogic->prepareNewGame( GAME_SINGLE_PLAYER, DIFFICULTY_NORMAL, 0 );
|
||||
}
|
||||
|
||||
//
|
||||
// load game, note the *copy* of the selected game info is passed here because we will
|
||||
// loose these allocated user data pointers attached as listbox item data when the
|
||||
// engine resets
|
||||
//
|
||||
if (TheGameState->loadGame( *selectedGameInfo ) != SC_OK)
|
||||
{
|
||||
if (TheGameLogic->isInGame())
|
||||
TheGameLogic->clearGameData( FALSE );
|
||||
TheGameEngine->reset();
|
||||
TheShell->showShell(TRUE);
|
||||
}
|
||||
|
||||
} // end doLoadGame
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Close the save/load menu */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void closeSaveMenu( GameWindow *window )
|
||||
{
|
||||
|
||||
if(isPopup)
|
||||
{
|
||||
WindowLayout *saveLoadMenuLayout = window->winGetLayout();
|
||||
if( saveLoadMenuLayout )
|
||||
saveLoadMenuLayout->hide( TRUE );
|
||||
}
|
||||
else
|
||||
TheShell->hideShell();
|
||||
|
||||
} // end closeSaveMenu
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
static void setEditDescription( GameWindow *editControl )
|
||||
{
|
||||
UnicodeString defaultDesc;
|
||||
Campaign *campaign = TheCampaignManager->getCurrentCampaign();
|
||||
|
||||
//
|
||||
// if we have a campaign we will use a default description that describes the
|
||||
// location and map in the campaign nicely, otherwise we will default to just
|
||||
// the map name (which is really only used in debug)
|
||||
//
|
||||
if( campaign )
|
||||
defaultDesc.format( L"%s %d",
|
||||
TheGameText->fetch( campaign->m_campaignNameLabel ).str(),
|
||||
TheCampaignManager->getCurrentMissionNumber() + 1 );
|
||||
else
|
||||
{
|
||||
const char *mapName = TheGlobalData->m_mapName.reverseFind( '\\' );
|
||||
|
||||
if( mapName )
|
||||
defaultDesc.format( L"%S", mapName + 1 );
|
||||
else
|
||||
defaultDesc.format( L"%S", TheGlobalData->m_mapName.str() );
|
||||
|
||||
} // end else
|
||||
|
||||
// set into edit control
|
||||
GadgetTextEntrySetText( editControl, defaultDesc );
|
||||
|
||||
} // end setEditDescription
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
static void processLoadButtonPress(GameWindow *window)
|
||||
{
|
||||
// get the filename of the selected savegame in the listbox
|
||||
AvailableGameInfo *selectedGameInfo = getSelectedSaveFileInfo( window );
|
||||
if( selectedGameInfo )
|
||||
{
|
||||
|
||||
//
|
||||
// if we're in the shell we do not need a confirmation dialog that states we will
|
||||
// lose the current loaded game data cause we're not in a game
|
||||
//
|
||||
if( TheShell->isShellActive() == TRUE )
|
||||
{
|
||||
|
||||
// just close the menu and do the load game logic
|
||||
closeSaveMenu( window );
|
||||
doLoadGame();
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
//GameWindow *loadConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:LoadConfirmParent" ) );
|
||||
|
||||
// disable listbox and buttons
|
||||
listboxGames->winEnable( FALSE );
|
||||
buttonFrame->winEnable( FALSE );
|
||||
|
||||
// show the load confirm dialog
|
||||
loadConfirm->winHide( FALSE );
|
||||
|
||||
} // end else
|
||||
|
||||
} // end if
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** SaveLoad menu system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType SaveLoadMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
|
||||
//----------------------------------------------------------------------------------------------
|
||||
case GLM_DOUBLE_CLICKED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( window, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("SaveLoadMenuInit - Unable to find games listbox\n") );
|
||||
|
||||
if (listboxGames != NULL) {
|
||||
int rowSelected = mData2;
|
||||
GadgetListBoxSetSelected(listboxGames, rowSelected);
|
||||
|
||||
if (control == listboxGames)
|
||||
{
|
||||
processLoadButtonPress(window);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GLM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
|
||||
GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( window, listboxGamesKey );
|
||||
DEBUG_ASSERTCRASH( listboxGames != NULL, ("SaveLoadMenuInit - Unable to find games listbox\n") );
|
||||
|
||||
//
|
||||
// handle games listbox, when certain items are selected in the listbox only some
|
||||
// commands are available
|
||||
//
|
||||
if( control == listboxGames )
|
||||
updateMenuActions();
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonLoadKey )
|
||||
{
|
||||
processLoadButtonPress(window);
|
||||
} // end if
|
||||
else if( controlID == buttonSaveKey )
|
||||
{
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( currentLayoutType == SLLT_SAVE_AND_LOAD ||
|
||||
currentLayoutType == SLLT_SAVE_ONLY,
|
||||
("SaveLoadMenuSystem - layout type '%d' does not allow saving\n",
|
||||
currentLayoutType) );
|
||||
|
||||
// get save file info
|
||||
AvailableGameInfo *selectedGameInfo = getSelectedSaveFileInfo( window );
|
||||
|
||||
// if there is no file info, this is a new game
|
||||
if( selectedGameInfo == NULL )
|
||||
{
|
||||
|
||||
// show the save description window
|
||||
//GameWindow *saveDesc = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:SaveDescParent" ) );
|
||||
saveDesc->winHide( FALSE );
|
||||
|
||||
// set the description text entry field to default value
|
||||
//GameWindow *editDesc = TheWindowManager->winGetWindowFromId( saveDesc, NAMEKEY( "PopupSaveLoad.wnd:EntryDesc" ) );
|
||||
setEditDescription( editDesc );
|
||||
|
||||
// disable the listbox of games
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
listboxGames->winEnable( FALSE );
|
||||
|
||||
// disable the frame window of buttons for the main save/load menu
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
//buttonFrame->winEnable( FALSE );
|
||||
|
||||
TheWindowManager->winSetFocus(editDesc);
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// disable listbox of games
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
listboxGames->winEnable( FALSE );
|
||||
|
||||
// disable and therefore lock out main save/load menu buttons
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( FALSE );
|
||||
|
||||
// show the save save confirm
|
||||
//GameWindow *overwriteConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:OverwriteConfirmParent" ) );
|
||||
overwriteConfirm->winHide( FALSE );
|
||||
|
||||
} // end else
|
||||
|
||||
}
|
||||
else if( controlID == buttonDeleteKey )
|
||||
{
|
||||
|
||||
// which item is selected in the game listbox
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxGames, &selected );
|
||||
AvailableGameInfo *selectedGameInfo;
|
||||
selectedGameInfo = (AvailableGameInfo *)GadgetListBoxGetItemData( listboxGames, selected );
|
||||
|
||||
// delete file
|
||||
if( selectedGameInfo )
|
||||
{
|
||||
|
||||
// disable games listbox
|
||||
listboxGames->winEnable( FALSE );
|
||||
|
||||
// disable menu buttons
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( FALSE );
|
||||
|
||||
// unhide confirmation dialog
|
||||
//GameWindow *deleteConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:DeleteConfirmParent" ) );
|
||||
deleteConfirm->winHide( FALSE );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end else if
|
||||
else if( controlID == buttonBackKey )
|
||||
{
|
||||
if(isPopup)
|
||||
{
|
||||
// close the save/load menu
|
||||
closeSaveMenu( window );
|
||||
}
|
||||
else
|
||||
{
|
||||
TheShell->pop();
|
||||
}
|
||||
|
||||
} // end if
|
||||
else if( controlID == buttonDeleteConfirm || controlID == buttonDeleteCancel )
|
||||
{
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
|
||||
// delete if confirm
|
||||
if( controlID == buttonDeleteConfirm )
|
||||
{
|
||||
|
||||
// which item is selected in the game listbox
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxGames, &selected );
|
||||
AvailableGameInfo *selectedGameInfo;
|
||||
selectedGameInfo = (AvailableGameInfo *)GadgetListBoxGetItemData( listboxGames, selected );
|
||||
|
||||
// construct path to filename
|
||||
AsciiString filepath = TheGameState->getFilePathInSaveDirectory(selectedGameInfo->filename);
|
||||
|
||||
// delete the file
|
||||
DeleteFile( filepath.str() );
|
||||
|
||||
// repopulate the listbox
|
||||
TheGameState->populateSaveGameListbox( listboxGames, currentLayoutType );
|
||||
|
||||
} // end if
|
||||
|
||||
// hide the confirm dialog
|
||||
//GameWindow *deleteConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:DeleteConfirmParent" ) );
|
||||
deleteConfirm->winHide( TRUE );
|
||||
|
||||
// enable listbox of games
|
||||
listboxGames->winEnable( TRUE );
|
||||
|
||||
// enable menu actions pane
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( TRUE );
|
||||
updateMenuActions();
|
||||
|
||||
} // end if
|
||||
else if( controlID == buttonOverwriteCancel || controlID == buttonOverwriteConfirm )
|
||||
{
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
|
||||
// hide save confirm dialog
|
||||
//GameWindow *overwriteConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:OverwriteConfirmParent" ) );
|
||||
overwriteConfirm->winHide( TRUE );
|
||||
|
||||
// if saving, do the save for the selected listbox item
|
||||
if( controlID == buttonOverwriteConfirm )
|
||||
{
|
||||
|
||||
// show the save description window
|
||||
// GameWindow *saveDesc = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:SaveDescParent" ) );
|
||||
// saveDesc->winHide( FALSE );
|
||||
|
||||
// get save game info for the currently selected game in the listbox
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxGames, &selected );
|
||||
|
||||
// get the item data of the selection
|
||||
AvailableGameInfo *selectedGameInfo;
|
||||
selectedGameInfo = (AvailableGameInfo *)GadgetListBoxGetItemData( listboxGames, selected );
|
||||
DEBUG_ASSERTCRASH( selectedGameInfo, ("SaveLoadMenuSystem: Internal error, listbox entry to overwrite game has no item data set into listbox element\n") );
|
||||
|
||||
// enable the listbox of games
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
listboxGames->winEnable( TRUE );
|
||||
|
||||
// enable the frame window of buttons for the main save/load menu
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( TRUE );
|
||||
updateMenuActions();
|
||||
|
||||
//Added By Sadullah Nader
|
||||
//Fix for bug
|
||||
// close save menuu
|
||||
closeSaveMenu( window );
|
||||
|
||||
//
|
||||
// given the context of this menu figure out which type of save game we're acutally
|
||||
// saving right now. As it turns out, when this menu is used in the save only
|
||||
// mode it means that the save is a mission save between maps because you can only
|
||||
// save the game between maps and can of course not load one
|
||||
//
|
||||
SaveFileType fileType;
|
||||
if( currentLayoutType == SLLT_SAVE_AND_LOAD )
|
||||
fileType = SAVE_FILE_TYPE_NORMAL;
|
||||
else
|
||||
fileType = SAVE_FILE_TYPE_MISSION;
|
||||
|
||||
// save the game
|
||||
AsciiString filename;
|
||||
if( selectedGameInfo )
|
||||
filename = selectedGameInfo->filename;
|
||||
TheGameState->saveGame( filename, selectedGameInfo->saveGameInfo.description, fileType );
|
||||
|
||||
/*
|
||||
// set the description text entry field to default value
|
||||
GameWindow *editDesc = TheWindowManager->winGetWindowFromId( saveDesc, NAMEKEY( "PopupSaveLoad.wnd:EntryDesc" ) );
|
||||
setEditDescription( editDesc );
|
||||
*/
|
||||
} // end if
|
||||
else if( controlID == buttonOverwriteCancel )
|
||||
{
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
|
||||
// enable buttons and list box on main parent
|
||||
buttonFrame->winEnable( TRUE );
|
||||
updateMenuActions();
|
||||
listboxGames->winEnable( TRUE );
|
||||
|
||||
} // end else if
|
||||
|
||||
} // end else if
|
||||
else if( controlID == buttonSaveDescConfirm )
|
||||
{
|
||||
|
||||
// get description window
|
||||
//GameWindow *saveDesc = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:SaveDescParent" ) );
|
||||
|
||||
// get description text
|
||||
//GameWindow *entryDesc = TheWindowManager->winGetWindowFromId( saveDesc, NAMEKEY( "PopupSaveLoad.wnd:EntryDesc" ) );
|
||||
UnicodeString desc = GadgetTextEntryGetText( editDesc );
|
||||
|
||||
// hide desc window
|
||||
saveDesc->winHide( TRUE );
|
||||
|
||||
// enable the listbox of games
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
listboxGames->winEnable( TRUE );
|
||||
|
||||
// enable the frame window of buttons for the main save/load menu
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( TRUE );
|
||||
updateMenuActions();
|
||||
|
||||
// close save menuu
|
||||
closeSaveMenu( window );
|
||||
|
||||
// get save filename
|
||||
AvailableGameInfo *selectedGameInfo = getSelectedSaveFileInfo( listboxGames );
|
||||
|
||||
//
|
||||
// given the context of this menu figure out which type of save game we're acutally
|
||||
// saving right now. As it turns out, when this menu is used in the save only
|
||||
// mode it means that the save is a mission save between maps because you can only
|
||||
// save the game between maps and can of course not load one
|
||||
//
|
||||
SaveFileType fileType;
|
||||
if( currentLayoutType == SLLT_SAVE_AND_LOAD )
|
||||
fileType = SAVE_FILE_TYPE_NORMAL;
|
||||
else
|
||||
fileType = SAVE_FILE_TYPE_MISSION;
|
||||
|
||||
// save the game
|
||||
AsciiString filename;
|
||||
if( selectedGameInfo )
|
||||
filename = selectedGameInfo->filename;
|
||||
TheGameState->saveGame( filename, desc, fileType );
|
||||
|
||||
} // end else if
|
||||
else if( controlID == buttonSaveDescCancel )
|
||||
{
|
||||
|
||||
// hide the desc window
|
||||
//GameWindow *saveDesc = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:SaveDescParent" ) );
|
||||
saveDesc->winHide( TRUE );
|
||||
|
||||
// enable the listbox of games
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
listboxGames->winEnable( TRUE );
|
||||
|
||||
// enable the frame window of buttons for the main save/load menu
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( TRUE );
|
||||
updateMenuActions();
|
||||
|
||||
} // end else if
|
||||
else if( controlID == buttonLoadConfirm || controlID == buttonLoadCancel )
|
||||
{
|
||||
|
||||
// hide confirm dialog
|
||||
//GameWindow *loadConfirm = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:LoadConfirmParent" ) );
|
||||
loadConfirm->winHide( TRUE );
|
||||
|
||||
// enable the listbox of games again
|
||||
//GameWindow *listboxGames = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:ListboxGames" ) );
|
||||
listboxGames->winEnable( TRUE );
|
||||
|
||||
// enable the main save/load menu button controls
|
||||
//GameWindow *buttonFrame = TheWindowManager->winGetWindowFromId( parent, NAMEKEY( "PopupSaveLoad.wnd:MenuButtonFrame" ) );
|
||||
buttonFrame->winEnable( TRUE );
|
||||
updateMenuActions();
|
||||
|
||||
|
||||
|
||||
|
||||
// do the load game
|
||||
if( controlID == buttonLoadConfirm )
|
||||
{
|
||||
//Moved by Sadullah Nader
|
||||
//moved to fix the
|
||||
// close save/load layout menu
|
||||
closeSaveMenu( window );
|
||||
doLoadGame();
|
||||
}
|
||||
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
/*
|
||||
** 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: QuitMenu.cpp /////////////////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, October 2001
|
||||
// Description: Quit menu window callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/GameState.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "Common/Player.h"
|
||||
#include "Common/PlayerList.h"
|
||||
#include "Common/RandomValue.h"
|
||||
#include "Common/Recorder.h"
|
||||
#include "GameClient/GUICallbacks.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetPushButton.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/MessageBox.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameLogic/VictoryConditions.h"
|
||||
#include "GameClient/ControlBar.h"
|
||||
#include "GameClient/GameWindowTransitions.h"
|
||||
#include "GameClient/DisconnectMenu.h"
|
||||
#include "GameLogic/ScriptEngine.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static WindowLayout *quitMenuLayout = NULL;
|
||||
static WindowLayout *fullQuitMenuLayout = NULL;
|
||||
static WindowLayout *noSaveLoadQuitMenuLayout = NULL;
|
||||
|
||||
static Bool isVisible = FALSE;
|
||||
|
||||
static GameWindow *quitConfirmationWindow = NULL;
|
||||
|
||||
//external declarations of the Gadgets the callbacks can use
|
||||
static WindowLayout *saveLoadMenuLayout = NULL;
|
||||
|
||||
static GameWindow *buttonRestartWin = NULL;
|
||||
static GameWindow *buttonSaveLoadWin = NULL;
|
||||
static GameWindow *buttonOptionsWin = NULL;
|
||||
static GameWindow *buttonExitWin = NULL;
|
||||
|
||||
static NameKeyType buttonExit = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonRestart = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonReturn = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOptions = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonSaveLoad = NAMEKEY_INVALID;
|
||||
|
||||
static void initGadgetsFullQuit( void )
|
||||
{
|
||||
buttonExit = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonExit" ) );
|
||||
buttonRestart = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonRestart" ) );
|
||||
buttonReturn = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonReturn" ) );
|
||||
buttonOptions = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonOptions" ) );
|
||||
buttonSaveLoad = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMenu.wnd:ButtonSaveLoad" ) );
|
||||
|
||||
buttonRestartWin = TheWindowManager->winGetWindowFromId( NULL, buttonRestart );
|
||||
buttonSaveLoadWin = TheWindowManager->winGetWindowFromId( NULL, buttonSaveLoad );
|
||||
buttonOptionsWin = TheWindowManager->winGetWindowFromId( NULL, buttonOptions );
|
||||
buttonExitWin = TheWindowManager->winGetWindowFromId( NULL, buttonExit );
|
||||
}
|
||||
|
||||
static void initGadgetsNoSaveQuit( void )
|
||||
{
|
||||
buttonExit = TheNameKeyGenerator->nameToKey( AsciiString( "QuitNoSave.wnd:ButtonExit" ) );
|
||||
buttonRestart = TheNameKeyGenerator->nameToKey( AsciiString( "QuitNoSave.wnd:ButtonRestart" ) );
|
||||
buttonReturn = TheNameKeyGenerator->nameToKey( AsciiString( "QuitNoSave.wnd:ButtonReturn" ) );
|
||||
buttonOptions = TheNameKeyGenerator->nameToKey( AsciiString( "QuitNoSave.wnd:ButtonOptions" ) );
|
||||
buttonSaveLoad = NAMEKEY_INVALID;
|
||||
|
||||
buttonRestartWin = TheWindowManager->winGetWindowFromId( NULL, buttonRestart );
|
||||
buttonOptionsWin = TheWindowManager->winGetWindowFromId( NULL, buttonOptions );
|
||||
buttonSaveLoadWin = NULL;
|
||||
buttonExitWin = TheWindowManager->winGetWindowFromId( NULL, buttonExit );
|
||||
|
||||
}
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void destroyQuitMenu()
|
||||
{
|
||||
// destroy the quit menu
|
||||
quitConfirmationWindow = NULL;
|
||||
if(fullQuitMenuLayout)
|
||||
{
|
||||
fullQuitMenuLayout->destroyWindows();
|
||||
fullQuitMenuLayout->deleteInstance();
|
||||
}
|
||||
fullQuitMenuLayout = NULL;
|
||||
if(noSaveLoadQuitMenuLayout)
|
||||
{
|
||||
noSaveLoadQuitMenuLayout->destroyWindows();
|
||||
noSaveLoadQuitMenuLayout->deleteInstance();
|
||||
}
|
||||
noSaveLoadQuitMenuLayout = NULL;
|
||||
quitMenuLayout = NULL;
|
||||
isVisible = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* quits the program
|
||||
*/
|
||||
static void exitQuitMenu()
|
||||
{
|
||||
// destroy the quit menu
|
||||
destroyQuitMenu();
|
||||
|
||||
// clear out all the game data
|
||||
if ( TheGameLogic->isInMultiplayerGame() && !TheGameLogic->isInSkirmishGame() && !TheGameInfo->isSandbox() )
|
||||
{
|
||||
GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_SELF_DESTRUCT);
|
||||
msg->appendBooleanArgument(TRUE);
|
||||
}
|
||||
/*GameMessage *msg =*/ TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_GAME_DATA );
|
||||
if ( !TheGameLogic->isInMultiplayerGame() )
|
||||
TheGameLogic->setGamePaused(FALSE);
|
||||
// TheGameLogic->clearGameData();
|
||||
// display the menu on top of the shell stack
|
||||
// TheShell->showShell();
|
||||
|
||||
// this will trigger an exit
|
||||
// TheGameEngine->setQuitting( TRUE );
|
||||
TheInGameUI->setClientQuiet( TRUE );
|
||||
}
|
||||
static void noExitQuitMenu()
|
||||
{
|
||||
quitConfirmationWindow = NULL;
|
||||
}
|
||||
|
||||
static void quitToDesktopQuitMenu()
|
||||
{
|
||||
// destroy the quit menu
|
||||
destroyQuitMenu();
|
||||
|
||||
if (TheGameLogic->isInGame())
|
||||
{
|
||||
if (TheRecorder->getMode() == RECORDERMODETYPE_RECORD)
|
||||
{
|
||||
TheRecorder->stopRecording();
|
||||
}
|
||||
TheGameLogic->clearGameData();
|
||||
}
|
||||
TheGameEngine->setQuitting(TRUE);
|
||||
TheInGameUI->setClientQuiet( TRUE );
|
||||
|
||||
}
|
||||
|
||||
static void surrenderQuitMenu()
|
||||
{
|
||||
// destroy the quit menu
|
||||
destroyQuitMenu();
|
||||
|
||||
if (TheVictoryConditions->isLocalAlliedVictory())
|
||||
return;
|
||||
|
||||
GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_SELF_DESTRUCT);
|
||||
msg->appendBooleanArgument(TRUE);
|
||||
|
||||
TheInGameUI->setClientQuiet( TRUE );
|
||||
}
|
||||
|
||||
static void restartMissionMenu()
|
||||
{
|
||||
// destroy the quit menu
|
||||
destroyQuitMenu();
|
||||
|
||||
Int gameMode = TheGameLogic->getGameMode();
|
||||
AsciiString mapName = TheGlobalData->m_mapName;
|
||||
|
||||
//
|
||||
// if the map name was from a save game it will have "Save/" at the front of it,
|
||||
// we want to go back to the original pristine map string for the map name when restarting
|
||||
//
|
||||
if (TheGameState->isInSaveDirectory(mapName))
|
||||
mapName = TheGameState->getPristineMapName();
|
||||
|
||||
// End the current game
|
||||
AsciiString replayFile = TheRecorder->getCurrentReplayFilename();
|
||||
if (TheRecorder->getMode() == RECORDERMODETYPE_RECORD)
|
||||
{
|
||||
TheRecorder->stopRecording();
|
||||
}
|
||||
|
||||
Int rankPointsStartedWith = TheGameLogic->getRankPointsToAddAtGameStart();// must write down before reset
|
||||
GameDifficulty diff = TheScriptEngine->getGlobalDifficulty();
|
||||
Int fps = TheGameEngine->getFramesPerSecondLimit();
|
||||
|
||||
TheGameLogic->clearGameData(FALSE);
|
||||
TheGameEngine->setQuitting(FALSE);
|
||||
|
||||
if (replayFile.isNotEmpty())
|
||||
{
|
||||
TheRecorder->playbackFile(replayFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// send a message to the logic for a new game
|
||||
TheWritableGlobalData->m_pendingFile = mapName;
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
|
||||
msg->appendIntegerArgument(gameMode);
|
||||
msg->appendIntegerArgument(diff);
|
||||
msg->appendIntegerArgument(rankPointsStartedWith);
|
||||
msg->appendIntegerArgument(fps);
|
||||
DEBUG_LOG(("Restarting game mode %d, Diff=%d, RankPoints=%d\n", gameMode,
|
||||
TheScriptEngine->getGlobalDifficulty(),
|
||||
rankPointsStartedWith)
|
||||
);
|
||||
//if (TheGlobalData->m_fixedSeed >= 0)
|
||||
//InitRandom(TheGlobalData->m_fixedSeed);
|
||||
InitRandom(0);
|
||||
//else
|
||||
// InitGameLogicRandom(GameClientRandomValue(0, INT_MAX - 1));
|
||||
}
|
||||
//TheTransitionHandler->remove("QuitFull"); //KRISMORNESS ADD
|
||||
//quitMenuLayout = NULL; //KRISMORNESS ADD
|
||||
//isVisible = TRUE; //KRISMORNESS ADD
|
||||
//HideQuitMenu(); //KRISMORNESS ADD
|
||||
TheInGameUI->setClientQuiet( TRUE );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void HideQuitMenu( void )
|
||||
{
|
||||
// Note: This is called as a safety a lot, without checking for the prescence of the quit menu.
|
||||
// So don't do anything that counts on that menu actually being here.
|
||||
if(!isVisible)
|
||||
return;
|
||||
if(quitMenuLayout && quitMenuLayout == noSaveLoadQuitMenuLayout)
|
||||
TheTransitionHandler->reverse("QuitNoSaveBack");
|
||||
else if( quitMenuLayout && quitMenuLayout == fullQuitMenuLayout)
|
||||
TheTransitionHandler->reverse("QuitFullBack");
|
||||
|
||||
TheInGameUI->setQuitMenuVisible( FALSE );
|
||||
isVisible = FALSE;
|
||||
if (quitConfirmationWindow)
|
||||
TheWindowManager->winDestroy(quitConfirmationWindow);
|
||||
quitConfirmationWindow = NULL;
|
||||
if ( !TheGameLogic->isInMultiplayerGame() )
|
||||
TheGameLogic->setGamePaused(FALSE);
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Toggle visibility of the quit menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ToggleQuitMenu()
|
||||
{
|
||||
|
||||
//Added By Sadullah Nader
|
||||
//Added a check to see if we're not in game yet
|
||||
if (TheGameLogic->isIntroMoviePlaying() || TheGameLogic->isLoadingGame() ||TheScriptEngine->isGameEnding())
|
||||
return;
|
||||
|
||||
//End Add
|
||||
|
||||
// BGC- If we are currently in the disconnect screen, don't let the quit menu come up.
|
||||
if (TheDisconnectMenu != NULL) {
|
||||
if (TheDisconnectMenu->isScreenVisible() == TRUE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// BGC- this is kind of hackish, but its the safest way to do it I think.
|
||||
// Basically we're seeing if either the save/load window or the options window is up
|
||||
// and if one of them is, we quit out of them rather than toggle the quit menu.
|
||||
if (TheShell->getOptionsLayout(FALSE) != FALSE) {
|
||||
WindowLayout *optLayout = TheShell->getOptionsLayout(FALSE);
|
||||
GameWindow *optionsParent = optLayout->getFirstWindow();
|
||||
DEBUG_ASSERTCRASH(optionsParent != NULL, ("Not able to get the options layout parent window"));
|
||||
GameWindow *optionsBack = TheWindowManager->winGetWindowFromId(optionsParent, TheNameKeyGenerator->nameToKey( AsciiString( "OptionsMenu.wnd:ButtonBack" ) ));
|
||||
DEBUG_ASSERTCRASH(optionsBack != NULL, ("Not able to get the back button window from the options menu"));
|
||||
TheWindowManager->winSendSystemMsg(optLayout->getFirstWindow(), GBM_SELECTED, (WindowMsgData)optionsBack, NULL);
|
||||
return;
|
||||
}
|
||||
if ((saveLoadMenuLayout != NULL) && (saveLoadMenuLayout->isHidden() == FALSE))
|
||||
{
|
||||
GameWindow *saveLoadParent = saveLoadMenuLayout->getFirstWindow();
|
||||
DEBUG_ASSERTCRASH(saveLoadParent != NULL, ("Not able to get the save/load layout parent window"));
|
||||
GameWindow *saveLoadBack = TheWindowManager->winGetWindowFromId(saveLoadParent, TheNameKeyGenerator->nameToKey( AsciiString( "PopupSaveLoad.wnd:ButtonBack" ) ));
|
||||
DEBUG_ASSERTCRASH(saveLoadBack != NULL, ("Not able to get the back button window from the save/load menu"));
|
||||
TheWindowManager->winSendSystemMsg(saveLoadMenuLayout->getFirstWindow(), GBM_SELECTED, (WindowMsgData)saveLoadBack, NULL);
|
||||
saveLoadMenuLayout = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
// if we're visable hide our quit menu
|
||||
if(isVisible && quitMenuLayout)
|
||||
{
|
||||
|
||||
isVisible = FALSE;
|
||||
|
||||
//Added By Sadullah Nader
|
||||
//Bug: When Toggling the quit menu off, the quit confirmation should also go away
|
||||
if (quitConfirmationWindow)
|
||||
TheWindowManager->winDestroy(quitConfirmationWindow);
|
||||
quitConfirmationWindow = NULL;
|
||||
//
|
||||
|
||||
if ( !TheGameLogic->isInMultiplayerGame() )
|
||||
TheGameLogic->setGamePaused(FALSE);
|
||||
if(quitMenuLayout && quitMenuLayout == noSaveLoadQuitMenuLayout)
|
||||
TheTransitionHandler->reverse("QuitNoSaveBack");
|
||||
else if( quitMenuLayout && quitMenuLayout == fullQuitMenuLayout )
|
||||
{
|
||||
TheTransitionHandler->reverse("QuitFullBack");
|
||||
//begin KRISMORNESS
|
||||
//TheTransitionHandler->reverse("QuitFull");
|
||||
//if( TheTransitionHandler->areTransitionsEnabled() )
|
||||
//else
|
||||
//{
|
||||
// TheTransitionHandler->remove("QuitFull");
|
||||
// quitMenuLayout = NULL;
|
||||
// isVisible = TRUE;
|
||||
// HideQuitMenu();
|
||||
//}
|
||||
//end KRISMORNESS
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Added By Sadullah Nader
|
||||
//Added to compensate for the quit confirmation window pop-up
|
||||
|
||||
TheMouse->setCursor( Mouse::ARROW );
|
||||
|
||||
TheControlBar->hidePurchaseScience();
|
||||
if ( TheGameLogic->isInMultiplayerGame() || TheGameLogic->isInReplayGame() )
|
||||
{
|
||||
// we don't want to show the save load button.
|
||||
if(!noSaveLoadQuitMenuLayout)
|
||||
noSaveLoadQuitMenuLayout = TheWindowManager->winCreateLayout( AsciiString( "Menus/QuitNoSave.wnd" ) );
|
||||
quitMenuLayout = noSaveLoadQuitMenuLayout;
|
||||
initGadgetsNoSaveQuit();
|
||||
TheTransitionHandler->remove("QuitNoSave");
|
||||
TheTransitionHandler->setGroup("QuitNoSave");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!fullQuitMenuLayout)
|
||||
fullQuitMenuLayout= TheWindowManager->winCreateLayout( AsciiString( "Menus/QuitMenu.wnd" ) );
|
||||
quitMenuLayout = fullQuitMenuLayout;
|
||||
initGadgetsFullQuit();
|
||||
TheTransitionHandler->remove("QuitFull");
|
||||
TheTransitionHandler->setGroup("QuitFull");
|
||||
}
|
||||
|
||||
// load the quit menu from the layout file if needed
|
||||
if( quitMenuLayout == NULL )
|
||||
{
|
||||
DEBUG_ASSERTCRASH(FALSE, ("Could not load a quit menu layout"));
|
||||
isVisible = FALSE;
|
||||
TheInGameUI->setQuitMenuVisible(FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
//quitMenuLayout->hide(FALSE);
|
||||
|
||||
// if we are watching a cinematic, we need to disable the save/load button
|
||||
// because the save load window doesn't fit in the screen in letterbox mode.
|
||||
if (TheInGameUI->getInputEnabled() == FALSE) {
|
||||
if(buttonSaveLoadWin)
|
||||
buttonSaveLoadWin->winEnable(FALSE);
|
||||
buttonOptionsWin->winEnable(FALSE);
|
||||
} else if (buttonSaveLoadWin)
|
||||
{
|
||||
if(buttonSaveLoadWin)
|
||||
buttonSaveLoadWin->winEnable(TRUE);
|
||||
buttonOptionsWin->winEnable(TRUE);
|
||||
}
|
||||
|
||||
// Disable the restart, load, save, etc buttons in network games
|
||||
if ( TheGameLogic->isInMultiplayerGame() || TheGameLogic->isInSkirmishGame() )
|
||||
{
|
||||
buttonRestartWin->winEnable(TRUE);
|
||||
if (TheGameLogic->isInSkirmishGame() == FALSE) {
|
||||
GadgetButtonSetText(buttonRestartWin, TheGameText->fetch("GUI:Surrender"));
|
||||
|
||||
}
|
||||
|
||||
if (TheGameLogic->isInSkirmishGame() == TRUE) {
|
||||
TheGameLogic->setGamePaused(TRUE);
|
||||
}
|
||||
|
||||
if ((!ThePlayerList->getLocalPlayer()->isPlayerActive() || TheVictoryConditions->isLocalAlliedVictory()) &&
|
||||
(TheGameLogic->isInSkirmishGame() == FALSE))
|
||||
{
|
||||
buttonRestartWin->winEnable(FALSE); // can't surrender when you're dead
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonRestartWin->winEnable(TRUE);
|
||||
if(!TheGameLogic->isInReplayGame())
|
||||
{
|
||||
GadgetButtonSetText(buttonRestartWin, TheGameText->fetch("GUI:RestartMission"));
|
||||
GadgetButtonSetText(buttonExitWin, TheGameText->fetch("GUI:ExitMission"));
|
||||
|
||||
}
|
||||
//if we're not in a multiplayer game, pause the game
|
||||
TheGameLogic->setGamePaused(TRUE);
|
||||
}
|
||||
|
||||
|
||||
if (quitConfirmationWindow)
|
||||
TheWindowManager->winDestroy(quitConfirmationWindow);
|
||||
quitConfirmationWindow = NULL;
|
||||
HideDiplomacy();
|
||||
HideInGameChat();
|
||||
TheControlBar->hidePurchaseScience();
|
||||
isVisible = TRUE;
|
||||
}
|
||||
|
||||
TheInGameUI->setQuitMenuVisible(isVisible);
|
||||
|
||||
} // end ToggleQuitMenu
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Quit menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType QuitMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonSaveLoad )
|
||||
{
|
||||
|
||||
//
|
||||
// these commented lines (12-11-2002) will allow access to load only when were
|
||||
// viewing an in-game cinema ... but it's brittle, so I'm disableing it for
|
||||
// now and just using the grey button for the whole save/load button for now
|
||||
// during a cinema
|
||||
//
|
||||
|
||||
// SaveLoadLayoutType layoutType = SLLT_SAVE_AND_LOAD;
|
||||
|
||||
//
|
||||
// if input is disabled we are in an in-game cinematic and can load only, since we
|
||||
// are in the quit menu we are paused and therefore input is disabled all
|
||||
// the time ... in order to figure out if the *game* has input disabled we need
|
||||
// to query for the input enabled memory in the game logic which represents the
|
||||
// input enabled status of the game if we were not currently paused
|
||||
//
|
||||
// if( TheGameLogic->getInputEnabledMemory() == FALSE )
|
||||
// layoutType = SLLT_LOAD_ONLY;
|
||||
|
||||
saveLoadMenuLayout = TheShell->getSaveLoadMenuLayout();
|
||||
// saveLoadMenuLayout->runInit( &layoutType );
|
||||
saveLoadMenuLayout->runInit();
|
||||
saveLoadMenuLayout->hide( FALSE );
|
||||
saveLoadMenuLayout->bringForward();
|
||||
}
|
||||
else if( controlID == buttonExit )
|
||||
{
|
||||
quitConfirmationWindow = QuitMessageBoxYesNo(TheGameText->fetch("GUI:QuitPopupTitle"), TheGameText->fetch("GUI:QuitPopupMessage"),/*quitCallback*/exitQuitMenu,noExitQuitMenu);
|
||||
} // end if
|
||||
else if( controlID == buttonReturn )
|
||||
{
|
||||
|
||||
// hide this menu
|
||||
ToggleQuitMenu();
|
||||
|
||||
} // end else if
|
||||
else if( buttonOptions == controlID )
|
||||
{
|
||||
WindowLayout *optLayout = TheShell->getOptionsLayout(TRUE);
|
||||
DEBUG_ASSERTCRASH(optLayout != NULL, ("options menu layout is NULL"));
|
||||
optLayout->runInit();
|
||||
optLayout->hide(FALSE);
|
||||
optLayout->bringForward();
|
||||
}
|
||||
// else if( controlID == buttonQuitToDesktop )
|
||||
// {
|
||||
// quitConfirmationWindow = MessageBoxYesNo(TheGameText->fetch("GUI:QuitPopupTitle"), TheGameText->fetch("GUI:QuitToDesktopConf"),/*quitCallback*/quitToDesktopQuitMenu,noExitQuitMenu);
|
||||
//
|
||||
// } // end else if
|
||||
else if( controlID == buttonRestart )
|
||||
{
|
||||
if ( TheGameLogic->isInMultiplayerGame() )
|
||||
{
|
||||
// we really want to surrender
|
||||
quitConfirmationWindow = MessageBoxYesNo(TheGameText->fetch("GUI:SurrenderConfirmationTitle"),
|
||||
TheGameText->fetch("GUI:SurrenderConfirmation"),
|
||||
/*quitCallback*/surrenderQuitMenu,noExitQuitMenu);
|
||||
}
|
||||
else
|
||||
{
|
||||
//we really want to restart
|
||||
quitConfirmationWindow = MessageBoxYesNo(TheGameText->fetch("GUI:RestartConfirmationTitle"),
|
||||
TheGameText->fetch("GUI:RestartConfirmation"),
|
||||
/*quitCallback*/restartMissionMenu,noExitQuitMenu);
|
||||
}
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end QuitMenuSystem
|
||||
@@ -0,0 +1,680 @@
|
||||
/*
|
||||
** 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: ReplayMenu.cpp /////////////////////////////////////////////////////////////////////
|
||||
// Author: Chris The masta Huybregts, December 2001
|
||||
// Description: Replay Menus
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
|
||||
#include "Lib/BaseType.h"
|
||||
#include "Common/FileSystem.h"
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/GameState.h"
|
||||
#include "Common/Recorder.h"
|
||||
#include "Common/Version.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetListbox.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/MessageBox.h"
|
||||
#include "GameClient/MapUtil.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/GameWindowTransitions.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// window ids -------------------------------------------------------------------------------------
|
||||
static NameKeyType parentReplayMenuID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonLoadID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonBackID = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxReplayFilesID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonDeleteID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonCopyID = NAMEKEY_INVALID;
|
||||
|
||||
static Bool isShuttingDown = false;
|
||||
|
||||
// window pointers --------------------------------------------------------------------------------
|
||||
static GameWindow *parentReplayMenu = NULL;
|
||||
static GameWindow *buttonLoad = NULL;
|
||||
static GameWindow *buttonBack = NULL;
|
||||
static GameWindow *listboxReplayFiles = NULL;
|
||||
static GameWindow *buttonDelete = NULL;
|
||||
static GameWindow *buttonCopy = NULL;
|
||||
static Int initialGadgetDelay = 2;
|
||||
static Bool justEntered = FALSE;
|
||||
|
||||
|
||||
#if defined _DEBUG || defined _INTERNAL
|
||||
static GameWindow *buttonAnalyzeReplay = NULL;
|
||||
#endif
|
||||
|
||||
void deleteReplay( void );
|
||||
void copyReplay( void );
|
||||
static Bool callCopy = FALSE;
|
||||
static Bool callDelete = FALSE;
|
||||
void deleteReplayFlag( void ) { callDelete = TRUE;}
|
||||
void copyReplayFlag( void ) { callCopy = TRUE;}
|
||||
|
||||
UnicodeString GetReplayFilenameFromListbox(GameWindow *listbox, Int index)
|
||||
{
|
||||
UnicodeString fname = GadgetListBoxGetText(listbox, index);
|
||||
|
||||
if (fname == TheGameText->fetch("GUI:LastReplay"))
|
||||
{
|
||||
fname.translate(TheRecorder->getLastReplayFileName());
|
||||
}
|
||||
|
||||
UnicodeString ext;
|
||||
ext.translate(TheRecorder->getReplayExtention());
|
||||
fname.concat(ext);
|
||||
|
||||
return fname;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Populate the listbox with the names of the available replay files */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void PopulateReplayFileListbox(GameWindow *listbox)
|
||||
{
|
||||
if (!TheMapCache)
|
||||
return;
|
||||
|
||||
GadgetListBoxReset(listbox);
|
||||
|
||||
enum {
|
||||
COLOR_SP = 0,
|
||||
COLOR_SP_CRC_MISMATCH,
|
||||
COLOR_MP,
|
||||
COLOR_MP_CRC_MISMATCH,
|
||||
COLOR_MAX
|
||||
};
|
||||
Color colors[COLOR_MAX] = {
|
||||
GameMakeColor( 255, 255, 255, 255 ),
|
||||
GameMakeColor( 128, 128, 128, 255 ),
|
||||
GameMakeColor( 255, 255, 255, 255 ),
|
||||
GameMakeColor( 128, 128, 128, 255 )
|
||||
};
|
||||
|
||||
AsciiString asciistr;
|
||||
AsciiString asciisearch;
|
||||
asciisearch = "*";
|
||||
asciisearch.concat(TheRecorder->getReplayExtention());
|
||||
|
||||
FilenameList replayFilenames;
|
||||
FilenameListIter it;
|
||||
|
||||
TheFileSystem->getFileListInDirectory(TheRecorder->getReplayDir(), asciisearch, replayFilenames, TRUE);
|
||||
|
||||
TheMapCache->updateCache();
|
||||
|
||||
|
||||
for (it = replayFilenames.begin(); it != replayFilenames.end(); ++it)
|
||||
{
|
||||
// just want the filename
|
||||
asciistr.set((*it).reverseFind('\\') + 1);
|
||||
|
||||
// lets get some info about the replay
|
||||
RecorderClass::ReplayHeader header;
|
||||
header.forPlayback = FALSE;
|
||||
header.filename = asciistr;
|
||||
Bool success = TheRecorder && TheMapCache && TheRecorder->readReplayHeader( header );
|
||||
if (success)
|
||||
{
|
||||
ReplayGameInfo info;
|
||||
if (ParseAsciiStringToGameInfo( &info, header.gameOptions ))
|
||||
{
|
||||
|
||||
// columns are: name, date, version, map, extra
|
||||
|
||||
// name
|
||||
header.replayName.translate(asciistr);
|
||||
for (Int tmp=0; tmp < TheRecorder->getReplayExtention().getLength(); ++tmp)
|
||||
header.replayName.removeLastChar();
|
||||
|
||||
UnicodeString replayNameToShow = header.replayName;
|
||||
|
||||
AsciiString lastReplayFName = TheRecorder->getLastReplayFileName();
|
||||
lastReplayFName.concat(TheRecorder->getReplayExtention());
|
||||
if (lastReplayFName.compareNoCase(asciistr) == 0)
|
||||
replayNameToShow = TheGameText->fetch("GUI:LastReplay");
|
||||
|
||||
UnicodeString displayTimeBuffer = getUnicodeTimeBuffer(header.timeVal);
|
||||
|
||||
//displayTimeBuffer.format( L"%ls", timeBuffer);
|
||||
|
||||
// version (no-op)
|
||||
|
||||
// map
|
||||
UnicodeString mapStr;
|
||||
const MapMetaData *md = TheMapCache->findMap(info.getMap());
|
||||
if (!md)
|
||||
{
|
||||
mapStr.translate(info.getMap());
|
||||
}
|
||||
else
|
||||
{
|
||||
mapStr = md->m_displayName;
|
||||
}
|
||||
|
||||
// // extra
|
||||
// UnicodeString extraStr;
|
||||
// if (header.localPlayerIndex >= 0)
|
||||
// {
|
||||
// // MP game
|
||||
// time_t totalSeconds = header.endTime - header.startTime;
|
||||
// Int mins = totalSeconds/60;
|
||||
// Int secs = totalSeconds%60;
|
||||
// Real fps = header.frameDuration/totalSeconds;
|
||||
// extraStr.format(L"%d:%d (%g fps) %hs", mins, secs, fps, header.desyncGame?"OOS ":"");
|
||||
//
|
||||
// for (Int i=0; i<MAX_SLOTS; ++i)
|
||||
// {
|
||||
// const GameSlot *slot = info.getConstSlot(i);
|
||||
// if (slot && slot->isHuman())
|
||||
// {
|
||||
// if (i)
|
||||
// extraStr.concat(L", ");
|
||||
// if (header.playerDiscons[i])
|
||||
// extraStr.concat(L'*');
|
||||
// extraStr.concat(info.getConstSlot(i)->getName());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // solo game
|
||||
// time_t totalSeconds = header.endTime - header.startTime;
|
||||
// Int mins = totalSeconds/60;
|
||||
// Int secs = totalSeconds%60;
|
||||
// Real fps = header.frameDuration/totalSeconds;
|
||||
// extraStr.format(L"%d:%d (%g fps)", mins, secs, fps);
|
||||
// }
|
||||
|
||||
// pick a color
|
||||
Color color;
|
||||
if (header.versionString == TheVersion->getUnicodeVersion() && header.versionNumber == TheVersion->getVersionNumber() &&
|
||||
header.exeCRC == TheGlobalData->m_exeCRC && header.iniCRC == TheGlobalData->m_iniCRC)
|
||||
{
|
||||
// good version
|
||||
if (header.localPlayerIndex >= 0)
|
||||
{
|
||||
// MP
|
||||
color = colors[COLOR_MP];
|
||||
}
|
||||
else
|
||||
{
|
||||
// SP
|
||||
color = colors[COLOR_SP];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// bad version
|
||||
if (header.localPlayerIndex >= 0)
|
||||
{
|
||||
// MP
|
||||
color = colors[COLOR_MP_CRC_MISMATCH];
|
||||
}
|
||||
else
|
||||
{
|
||||
// SP
|
||||
color = colors[COLOR_SP_CRC_MISMATCH];
|
||||
}
|
||||
}
|
||||
|
||||
Int insertionIndex = GadgetListBoxAddEntryText(listbox, replayNameToShow, color, -1, 0);
|
||||
GadgetListBoxAddEntryText(listbox, displayTimeBuffer, color, insertionIndex, 1);
|
||||
GadgetListBoxAddEntryText(listbox, header.versionString, color, insertionIndex, 2);
|
||||
GadgetListBoxAddEntryText(listbox, mapStr, color, insertionIndex, 3);
|
||||
//GadgetListBoxAddEntryText(listbox, extraStr, color, insertionIndex, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
GadgetListBoxSetSelected(listbox, 0);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the single player menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ReplayMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
TheShell->showShellMap(TRUE);
|
||||
|
||||
// get ids for our children controls
|
||||
parentReplayMenuID = TheNameKeyGenerator->nameToKey( AsciiString("ReplayMenu.wnd:ParentReplayMenu") );
|
||||
buttonLoadID = TheNameKeyGenerator->nameToKey( AsciiString("ReplayMenu.wnd:ButtonLoadReplay") );
|
||||
buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString("ReplayMenu.wnd:ButtonBack") );
|
||||
listboxReplayFilesID = TheNameKeyGenerator->nameToKey( AsciiString("ReplayMenu.wnd:ListboxReplayFiles") );
|
||||
buttonDeleteID = TheNameKeyGenerator->nameToKey( AsciiString("ReplayMenu.wnd:ButtonDeleteReplay") );
|
||||
buttonCopyID = TheNameKeyGenerator->nameToKey( AsciiString("ReplayMenu.wnd:ButtonCopyReplay") );
|
||||
|
||||
parentReplayMenu = TheWindowManager->winGetWindowFromId( NULL, parentReplayMenuID );
|
||||
buttonLoad = TheWindowManager->winGetWindowFromId( parentReplayMenu, buttonLoadID );
|
||||
buttonBack = TheWindowManager->winGetWindowFromId( parentReplayMenu, buttonBackID );
|
||||
listboxReplayFiles = TheWindowManager->winGetWindowFromId( parentReplayMenu, listboxReplayFilesID );
|
||||
buttonDelete = TheWindowManager->winGetWindowFromId( parentReplayMenu, buttonDeleteID );
|
||||
buttonCopy = TheWindowManager->winGetWindowFromId( parentReplayMenu, buttonCopyID );
|
||||
|
||||
//Load the listbox shiznit
|
||||
GadgetListBoxReset(listboxReplayFiles);
|
||||
PopulateReplayFileListbox(listboxReplayFiles);
|
||||
|
||||
#if defined _DEBUG || defined _INTERNAL
|
||||
WinInstanceData instData;
|
||||
instData.init();
|
||||
BitSet( instData.m_style, GWS_PUSH_BUTTON | GWS_MOUSE_TRACK );
|
||||
instData.m_textLabelString = "Debug: Analyze Replay";
|
||||
instData.setTooltipText(UnicodeString(L"Only Used in Debug and Internal!"));
|
||||
buttonAnalyzeReplay = TheWindowManager->gogoGadgetPushButton( parentReplayMenu,
|
||||
WIN_STATUS_ENABLED | WIN_STATUS_IMAGE,
|
||||
4, 4,
|
||||
180, 26,
|
||||
&instData, NULL, TRUE );
|
||||
#endif
|
||||
|
||||
// show menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// set keyboard focus to main parent
|
||||
TheWindowManager->winSetFocus( parentReplayMenu );
|
||||
justEntered = TRUE;
|
||||
initialGadgetDelay = 2;
|
||||
GameWindow *win = TheWindowManager->winGetWindowFromId(NULL, TheNameKeyGenerator->nameToKey("ReplayMenu.wnd:GadgetParent"));
|
||||
if(win)
|
||||
win->winHide(TRUE);
|
||||
isShuttingDown = FALSE;
|
||||
|
||||
} // end ReplayMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ReplayMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
Bool popImmediate = *(Bool *)userData;
|
||||
if( popImmediate )
|
||||
{
|
||||
|
||||
layout->hide( TRUE );
|
||||
TheShell->shutdownComplete( layout );
|
||||
return;
|
||||
|
||||
} //end if
|
||||
|
||||
// our shutdown is complete
|
||||
TheTransitionHandler->reverse("ReplayMenuFade");
|
||||
isShuttingDown = TRUE;
|
||||
} // end ReplayMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void ReplayMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
if(justEntered)
|
||||
{
|
||||
if(initialGadgetDelay == 1)
|
||||
{
|
||||
TheTransitionHandler->remove("MainMenuDefaultMenuLogoFade");
|
||||
TheTransitionHandler->setGroup("ReplayMenuFade");
|
||||
initialGadgetDelay = 2;
|
||||
justEntered = FALSE;
|
||||
}
|
||||
else
|
||||
initialGadgetDelay--;
|
||||
}
|
||||
|
||||
if(callCopy)
|
||||
copyReplay();
|
||||
if(callDelete)
|
||||
deleteReplay();
|
||||
// We'll only be successful if we've requested to
|
||||
if(isShuttingDown && TheShell->isAnimFinished()&& TheTransitionHandler->isFinished())
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // end ReplayMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Replay menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType ReplayMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonBack, buttonBackID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end ReplayMenuInput
|
||||
|
||||
void reallyLoadReplay(void)
|
||||
{
|
||||
UnicodeString filename;
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxReplayFiles, &selected );
|
||||
if(selected < 0)
|
||||
{
|
||||
MessageBoxOk(TheGameText->fetch("GUI:NoFileSelected"),TheGameText->fetch("GUI:PleaseSelectAFile"), NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
filename = GetReplayFilenameFromListbox(listboxReplayFiles, selected);
|
||||
|
||||
AsciiString asciiFilename;
|
||||
asciiFilename.translate(filename);
|
||||
|
||||
TheRecorder->playbackFile(asciiFilename);
|
||||
|
||||
if(parentReplayMenu != NULL)
|
||||
{
|
||||
parentReplayMenu->winHide(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType ReplayMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GLM_DOUBLE_CLICKED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxReplayFilesID )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
|
||||
if (rowSelected >= 0)
|
||||
{
|
||||
UnicodeString filename;
|
||||
filename = GetReplayFilenameFromListbox(listboxReplayFiles, rowSelected);
|
||||
|
||||
AsciiString asciiFilename;
|
||||
asciiFilename.translate(filename);
|
||||
TheRecorder->playbackFile(asciiFilename);
|
||||
|
||||
if(parentReplayMenu != NULL)
|
||||
{
|
||||
parentReplayMenu->winHide(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
UnicodeString filename;
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
#if defined _DEBUG || defined _INTERNAL
|
||||
if( controlID == buttonAnalyzeReplay->winGetWindowId() )
|
||||
{
|
||||
if(listboxReplayFiles)
|
||||
{
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxReplayFiles, &selected );
|
||||
if(selected < 0)
|
||||
{
|
||||
MessageBoxOk(UnicodeString(L"Blah Blah"),UnicodeString(L"Please select something munkee boy"), NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
filename = GetReplayFilenameFromListbox(listboxReplayFiles, selected);
|
||||
|
||||
AsciiString asciiFilename;
|
||||
asciiFilename.translate(filename);
|
||||
if (TheRecorder->analyzeReplay(asciiFilename))
|
||||
{
|
||||
do
|
||||
{
|
||||
TheRecorder->update();
|
||||
} while (TheRecorder->isAnalysisInProgress());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if( controlID == buttonLoadID )
|
||||
{
|
||||
if(listboxReplayFiles)
|
||||
{
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxReplayFiles, &selected );
|
||||
if(selected < 0)
|
||||
{
|
||||
MessageBoxOk(TheGameText->fetch("GUI:NoFileSelected"),TheGameText->fetch("GUI:PleaseSelectAFile"), NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
filename = GetReplayFilenameFromListbox(listboxReplayFiles, selected);
|
||||
|
||||
AsciiString asciiFilename;
|
||||
asciiFilename.translate(filename);
|
||||
|
||||
if(TheRecorder->testVersionPlayback(asciiFilename))
|
||||
{
|
||||
MessageBoxOkCancel(TheGameText->fetch("GUI:OlderReplayVersionTitle"), TheGameText->fetch("GUI:OlderReplayVersion"),reallyLoadReplay ,NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
TheRecorder->playbackFile(asciiFilename);
|
||||
|
||||
if(parentReplayMenu != NULL)
|
||||
{
|
||||
parentReplayMenu->winHide(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // end else if
|
||||
else if( controlID == buttonBackID )
|
||||
{
|
||||
|
||||
// thou art directed to return to thy known solar system immediately!
|
||||
TheShell->pop();
|
||||
|
||||
} // end else if
|
||||
else if( controlID == buttonDeleteID )
|
||||
{
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxReplayFiles, &selected );
|
||||
if(selected < 0)
|
||||
{
|
||||
MessageBoxOk(TheGameText->fetch("GUI:NoFileSelected"),TheGameText->fetch("GUI:PleaseSelectAFile"), NULL);
|
||||
break;
|
||||
}
|
||||
filename = GetReplayFilenameFromListbox(listboxReplayFiles, selected);
|
||||
MessageBoxYesNo(TheGameText->fetch("GUI:DeleteFile"), TheGameText->fetch("GUI:AreYouSureDelete"), deleteReplayFlag, NULL);
|
||||
}
|
||||
else if( controlID == buttonCopyID )
|
||||
{
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxReplayFiles, &selected );
|
||||
if(selected < 0)
|
||||
{
|
||||
MessageBoxOk(TheGameText->fetch("GUI:NoFileSelected"),TheGameText->fetch("GUI:PleaseSelectAFile"), NULL);
|
||||
break;
|
||||
}
|
||||
filename = GetReplayFilenameFromListbox(listboxReplayFiles, selected);
|
||||
MessageBoxYesNo(TheGameText->fetch("GUI:CopyReplay"), TheGameText->fetch("GUI:AreYouSureCopy"), copyReplayFlag, NULL);
|
||||
}
|
||||
break;
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
} // end ReplayMenuSystem
|
||||
|
||||
void deleteReplay( void )
|
||||
{
|
||||
callDelete = FALSE;
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxReplayFiles, &selected );
|
||||
if(selected < 0)
|
||||
{
|
||||
MessageBoxOk(TheGameText->fetch("GUI:NoFileSelected"),TheGameText->fetch("GUI:PleaseSelectAFile"), NULL);
|
||||
return;
|
||||
}
|
||||
AsciiString filename, translate;
|
||||
filename = TheRecorder->getReplayDir();
|
||||
translate.translate(GetReplayFilenameFromListbox(listboxReplayFiles, selected));
|
||||
filename.concat(translate);
|
||||
if(DeleteFile(filename.str()) == 0)
|
||||
{
|
||||
char buffer[1024];
|
||||
FormatMessage ( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, buffer, sizeof(buffer), NULL);
|
||||
UnicodeString errorStr;
|
||||
translate.set(buffer);
|
||||
errorStr.translate(translate);
|
||||
MessageBoxOk(TheGameText->fetch("GUI:Error"),errorStr, NULL);
|
||||
}
|
||||
//Load the listbox shiznit
|
||||
GadgetListBoxReset(listboxReplayFiles);
|
||||
PopulateReplayFileListbox(listboxReplayFiles);
|
||||
}
|
||||
|
||||
|
||||
void copyReplay( void )
|
||||
{
|
||||
callCopy = FALSE;
|
||||
Int selected;
|
||||
GadgetListBoxGetSelected( listboxReplayFiles, &selected );
|
||||
if(selected < 0)
|
||||
{
|
||||
MessageBoxOk(TheGameText->fetch("GUI:NoFileSelected"),TheGameText->fetch("GUI:PleaseSelectAFile"), NULL);
|
||||
return;
|
||||
}
|
||||
AsciiString filename, translate;
|
||||
filename = TheRecorder->getReplayDir();
|
||||
translate.translate(GetReplayFilenameFromListbox(listboxReplayFiles, selected));
|
||||
filename.concat(translate);
|
||||
|
||||
char path[1024];
|
||||
LPITEMIDLIST pidl;
|
||||
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &pidl);
|
||||
SHGetPathFromIDList(pidl,path);
|
||||
AsciiString newFilename;
|
||||
newFilename.set(path);
|
||||
newFilename.concat("\\");
|
||||
newFilename.concat(translate);
|
||||
if(CopyFile(filename.str(),newFilename.str(), FALSE) == 0)
|
||||
{
|
||||
wchar_t buffer[1024];
|
||||
FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, buffer, sizeof(buffer), NULL);
|
||||
UnicodeString errorStr;
|
||||
errorStr.set(buffer);
|
||||
errorStr.trim();
|
||||
MessageBoxOk(TheGameText->fetch("GUI:Error"),errorStr, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
** 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: SinglePlayerMenu.cpp /////////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, October 2001
|
||||
// Description: Single Player Menus
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
|
||||
static Bool isShuttingDown = false;
|
||||
static Bool buttonPushed = false;
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** This is called when a shutdown is complete for this menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static void shutdownComplete( WindowLayout *layout )
|
||||
{
|
||||
|
||||
isShuttingDown = false;
|
||||
|
||||
// hide the layout
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // end if
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the single player menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SinglePlayerMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
TheShell->showShellMap(TRUE);
|
||||
buttonPushed = false;
|
||||
isShuttingDown = false;
|
||||
|
||||
// show menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// set keyboard focus to main parent
|
||||
AsciiString parentName( "SinglePlayerMenu.wnd:SinglePlayerMenuParent" );
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
|
||||
NameKeyType buttonNewID = TheNameKeyGenerator->nameToKey( AsciiString("SinglePlayerMenu.wnd:ButtonNew") );
|
||||
GameWindow *buttonNew = TheWindowManager->winGetWindowFromId( NULL, buttonNewID );
|
||||
TheShell->registerWithAnimateManager(buttonNew, WIN_ANIMATION_SLIDE_LEFT, TRUE,1);
|
||||
|
||||
NameKeyType buttonLoadID = TheNameKeyGenerator->nameToKey( AsciiString("SinglePlayerMenu.wnd:ButtonLoad") );
|
||||
GameWindow *buttonLoad = TheWindowManager->winGetWindowFromId( NULL, buttonLoadID );
|
||||
TheShell->registerWithAnimateManager(buttonLoad, WIN_ANIMATION_SLIDE_LEFT, TRUE,200);
|
||||
|
||||
NameKeyType buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString("SinglePlayerMenu.wnd:ButtonBack") );
|
||||
GameWindow *buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID );
|
||||
TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_RIGHT, TRUE,1);
|
||||
|
||||
|
||||
//TheShell->registerWithAnimateManager(parent, WIN_ANIMATION_SLIDE_TOP, TRUE);
|
||||
|
||||
} // end SinglePlayerMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SinglePlayerMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
isShuttingDown = true;
|
||||
|
||||
// if we are shutting down for an immediate pop, skip the animations
|
||||
Bool popImmediate = *(Bool *)userData;
|
||||
if( popImmediate )
|
||||
{
|
||||
|
||||
shutdownComplete( layout );
|
||||
return;
|
||||
|
||||
} //end if
|
||||
|
||||
TheShell->reverseAnimatewindow();
|
||||
|
||||
} // end SinglePlayerMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SinglePlayerMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// We'll only be successful if we've requested to
|
||||
if(isShuttingDown && TheShell->isAnimFinished())
|
||||
shutdownComplete(layout);
|
||||
|
||||
} // end SinglePlayerMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** SinglePlayer menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType SinglePlayerMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
AsciiString buttonName( "SinglePlayerMenu.wnd:ButtonBack" );
|
||||
NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end SinglePlayerMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType SinglePlayerMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
static NameKeyType buttonNew = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonLoad = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonBack = NAMEKEY_INVALID;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
// get ids for our children controls
|
||||
buttonNew = TheNameKeyGenerator->nameToKey( AsciiString("SinglePlayerMenu.wnd:ButtonNew") );
|
||||
buttonLoad = TheNameKeyGenerator->nameToKey( AsciiString("SinglePlayerMenu.wnd:ButtonLoad") );
|
||||
buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("SinglePlayerMenu.wnd:ButtonBack") );
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
if( controlID == buttonNew )
|
||||
{
|
||||
|
||||
// open up the map select menu
|
||||
TheShell->push( AsciiString( "Menus/MapSelectMenu.wnd" ) );
|
||||
buttonPushed = true;
|
||||
|
||||
} // end if
|
||||
else if( controlID == buttonLoad )
|
||||
{
|
||||
|
||||
} // end else if
|
||||
else if( controlID == buttonBack )
|
||||
{
|
||||
|
||||
// thou art directed to return to thy known solar system immediately!
|
||||
TheShell->pop();
|
||||
buttonPushed = true;
|
||||
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
} // end SinglePlayerMenuSystem
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,605 @@
|
||||
/*
|
||||
** 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: SkirmishMapSelectMenu.cpp ////////////////////////////////////////////////////////////////////////
|
||||
// Author: Chris Brue, August 2002
|
||||
// Description: MapSelect menu window callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "Common/UserPreferences.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/Mouse.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetRadioButton.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameNetwork/LANAPICallbacks.h"
|
||||
#include "GameClient/MapUtil.h"
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static NameKeyType buttonBack = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOK = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxMap = NAMEKEY_INVALID;
|
||||
static GameWindow *parent = NULL;
|
||||
static GameWindow *mapList = NULL;
|
||||
|
||||
static NameKeyType radioButtonSystemMapsID = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonUserMapsID = NAMEKEY_INVALID;
|
||||
|
||||
static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL };
|
||||
static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID };
|
||||
|
||||
static GameWindow *winMapPreview = NULL;
|
||||
static NameKeyType winMapPreviewID = NAMEKEY_INVALID;
|
||||
|
||||
static void NullifyControls()
|
||||
{
|
||||
mapList = NULL;
|
||||
winMapPreview = NULL;
|
||||
parent = NULL;
|
||||
for (Int i=0; i<MAX_SLOTS; ++i)
|
||||
{
|
||||
buttonMapStartPosition[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern WindowLayout *skirmishMapSelectLayout;
|
||||
|
||||
// Tooltips -------------------------------------------------------------------------------
|
||||
|
||||
static void mapListTooltipFunc(GameWindow *window,
|
||||
WinInstanceData *instData,
|
||||
UnsignedInt mouse)
|
||||
{
|
||||
Int x, y, row, col;
|
||||
x = LOLONGTOSHORT(mouse);
|
||||
y = HILONGTOSHORT(mouse);
|
||||
|
||||
GadgetListBoxGetEntryBasedOnXY(window, x, y, row, col);
|
||||
|
||||
if (row == -1 || col == -1)
|
||||
{
|
||||
TheMouse->setCursorTooltip( UnicodeString::TheEmptyString);
|
||||
return;
|
||||
}
|
||||
|
||||
Int imageItemData = (Int)GadgetListBoxGetItemData(window, row, 1);
|
||||
UnicodeString tooltip;
|
||||
switch (imageItemData)
|
||||
{
|
||||
case 0:
|
||||
tooltip = TheGameText->fetch("TOOLTIP:MapNoSuccess");
|
||||
break;
|
||||
case 1:
|
||||
tooltip = TheGameText->fetch("TOOLTIP:MapEasySuccess");
|
||||
break;
|
||||
case 2:
|
||||
tooltip = TheGameText->fetch("TOOLTIP:MapMediumSuccess");
|
||||
break;
|
||||
case 3:
|
||||
tooltip = TheGameText->fetch("TOOLTIP:MapHardSuccess");
|
||||
break;
|
||||
}
|
||||
|
||||
TheMouse->setCursorTooltip( tooltip );
|
||||
}
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
void positionStartSpots( AsciiString mapName, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow);
|
||||
void skirmishPositionStartSpots( void );
|
||||
void skirmishUpdateSlotList( void );
|
||||
void showSkirmishGameOptionsUnderlyingGUIElements( Bool show )
|
||||
{
|
||||
AsciiString parentName( "SkirmishGameOptionsMenu.wnd:SkirmishGameOptionsMenuParent" );
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
GameWindow *parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
if (!parent)
|
||||
return;
|
||||
|
||||
// hide some GUI elements of the screen underneath
|
||||
GameWindow *win;
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:MapWindow") );
|
||||
win->winHide( !show );
|
||||
|
||||
//win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:StaticTextTitle") );
|
||||
//win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:StaticTextTeam") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:StaticTextFaction") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:StaticTextColor") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxTeam0") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxTeam1") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxTeam2") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxTeam3") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxTeam4") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxTeam5") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxTeam6") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxTeam7") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxColor0") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxColor1") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxColor2") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxColor3") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxColor4") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxColor5") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxColor6") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxColor7") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxPlayerTemplate0") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxPlayerTemplate1") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxPlayerTemplate2") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxPlayerTemplate3") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxPlayerTemplate4") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxPlayerTemplate5") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxPlayerTemplate6") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ComboBoxPlayerTemplate7") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:TextEntryMapDisplay") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ButtonSelectMap") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ButtonStart") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:StaticTextMapPreview") );
|
||||
win->winHide( !show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ButtonReset") );
|
||||
win->winEnable( show );
|
||||
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:ButtonBack") );
|
||||
win->winEnable( show );
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the MapSelect menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SkirmishMapSelectMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// set keyboard focus to main parent
|
||||
AsciiString parentName( "SkirmishMapSelectMenu.wnd:SkrimishMapSelectMenuParent" );
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
|
||||
LANPreferences pref;
|
||||
Bool usesSystemMapDir = pref.usesSystemMapDir();
|
||||
|
||||
const MapMetaData *mmd = TheMapCache->findMap(TheSkirmishGameInfo->getMap());
|
||||
if (mmd)
|
||||
{
|
||||
usesSystemMapDir = mmd->m_isOfficial;
|
||||
}
|
||||
|
||||
winMapPreviewID = TheNameKeyGenerator->nameToKey( AsciiString("SkirmishMapSelectMenu.wnd:WinMapPreview") );
|
||||
winMapPreview = TheWindowManager->winGetWindowFromId(parent, winMapPreviewID);
|
||||
|
||||
|
||||
buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("SkirmishMapSelectMenu.wnd:ButtonBack") );
|
||||
buttonOK = TheNameKeyGenerator->nameToKey( AsciiString("SkirmishMapSelectMenu.wnd:ButtonOK") );
|
||||
listboxMap = TheNameKeyGenerator->nameToKey( AsciiString("SkirmishMapSelectMenu.wnd:ListboxMap") );
|
||||
|
||||
radioButtonSystemMapsID = TheNameKeyGenerator->nameToKey( "SkirmishMapSelectMenu.wnd:RadioButtonSystemMaps" );
|
||||
radioButtonUserMapsID = TheNameKeyGenerator->nameToKey( "SkirmishMapSelectMenu.wnd:RadioButtonUserMaps" );
|
||||
GameWindow *radioButtonSystemMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonSystemMapsID );
|
||||
GameWindow *radioButtonUserMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonUserMapsID );
|
||||
if (usesSystemMapDir)
|
||||
GadgetRadioSetSelection( radioButtonSystemMaps, FALSE );
|
||||
else
|
||||
GadgetRadioSetSelection( radioButtonUserMaps, FALSE );
|
||||
|
||||
AsciiString tmpString;
|
||||
for (Int i = 0; i < MAX_SLOTS; i++)
|
||||
{
|
||||
tmpString.format("SkirmishMapSelectMenu.wnd:ButtonMapStartPosition%d", i);
|
||||
buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString );
|
||||
buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( winMapPreview, buttonMapStartPositionID[i] );
|
||||
DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i ));
|
||||
buttonMapStartPosition[i]->winHide(TRUE);
|
||||
buttonMapStartPosition[i]->winEnable(FALSE);
|
||||
}
|
||||
|
||||
showSkirmishGameOptionsUnderlyingGUIElements(FALSE);
|
||||
|
||||
// get the listbox window
|
||||
AsciiString listString( "SkirmishMapSelectMenu.wnd:ListboxMap" );
|
||||
NameKeyType mapListID = TheNameKeyGenerator->nameToKey( listString );
|
||||
mapList = TheWindowManager->winGetWindowFromId( parent, mapListID );
|
||||
if( mapList )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
if (usesSystemMapDir)
|
||||
{
|
||||
populateMapListbox( mapList, TRUE, TRUE, TheSkirmishGameInfo->getMap() );
|
||||
}
|
||||
else
|
||||
{
|
||||
populateMapListbox( mapList, FALSE, FALSE, TheSkirmishGameInfo->getMap() );
|
||||
populateMapListboxNoReset( mapList, FALSE, TRUE, TheSkirmishGameInfo->getMap() );
|
||||
}
|
||||
mapList->winSetTooltipFunc(mapListTooltipFunc);
|
||||
}
|
||||
|
||||
} // end SkirmishMapSelectMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SkirmishMapSelectMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
NullifyControls();
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // end LanMapSelectMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void SkirmishMapSelectMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
} // end SkirmishMapSelectMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Map select menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType SkirmishMapSelectMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
AsciiString buttonName( "SkirmishMapSelectMenu.wnd:ButtonBack" );
|
||||
NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end SkirmishMapSelectMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType SkirmishMapSelectMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
NullifyControls();
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GLM_DOUBLE_CLICKED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxMap )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
|
||||
if (rowSelected >= 0)
|
||||
{
|
||||
GadgetListBoxSetSelected( control, rowSelected );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonOK );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonOK );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GLM_SELECTED:
|
||||
{
|
||||
GameWindow *mapWindow = TheWindowManager->winGetWindowFromId( parent, listboxMap );
|
||||
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxMap )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
if( rowSelected < 0 )
|
||||
{
|
||||
positionStartSpots( AsciiString::TheEmptyString, buttonMapStartPosition, winMapPreview);
|
||||
//winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
|
||||
break;
|
||||
}
|
||||
winMapPreview->winSetStatus(WIN_STATUS_IMAGE);
|
||||
UnicodeString map;
|
||||
// get text of the map to load
|
||||
map = GadgetListBoxGetText( mapWindow, rowSelected, 0 );
|
||||
|
||||
// set the map name in the global data map name
|
||||
AsciiString asciiMap;
|
||||
const char *mapFname = (const char *)GadgetListBoxGetItemData( mapWindow, rowSelected );
|
||||
DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
|
||||
if (mapFname)
|
||||
asciiMap = mapFname;
|
||||
else
|
||||
asciiMap.translate( map );
|
||||
asciiMap.toLower();
|
||||
Image *image = getMapPreviewImage(asciiMap);
|
||||
winMapPreview->winSetUserData((void *)TheMapCache->findMap(asciiMap));
|
||||
if(image)
|
||||
{
|
||||
winMapPreview->winSetEnabledImage(0, image);
|
||||
}
|
||||
else
|
||||
{
|
||||
winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
|
||||
}
|
||||
positionStartSpots( asciiMap, buttonMapStartPosition, winMapPreview);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
// this isn't fixed yet
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == radioButtonSystemMapsID )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, TRUE, TRUE, TheSkirmishGameInfo->getMap() );
|
||||
//LANPreferences pref;
|
||||
//pref["UseSystemMapDir"] = "yes";
|
||||
//pref.write();
|
||||
}
|
||||
else if ( controlID == radioButtonUserMapsID )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, FALSE, FALSE, TheSkirmishGameInfo->getMap() );
|
||||
populateMapListboxNoReset( mapList, FALSE, TRUE, TheSkirmishGameInfo->getMap() );
|
||||
//LANPreferences pref;
|
||||
//pref["UseSystemMapDir"] = "no";
|
||||
//pref.write();
|
||||
}
|
||||
else if ( controlID == buttonBack )
|
||||
{
|
||||
showSkirmishGameOptionsUnderlyingGUIElements(TRUE);
|
||||
|
||||
skirmishMapSelectLayout->destroyWindows();
|
||||
skirmishMapSelectLayout->deleteInstance();
|
||||
skirmishMapSelectLayout = NULL;
|
||||
skirmishPositionStartSpots();
|
||||
//TheShell->pop();
|
||||
//do you need this ??
|
||||
//PostToLanGameOptions( MAP_BACK );
|
||||
} // end if
|
||||
else if ( controlID == buttonOK )
|
||||
{
|
||||
|
||||
Int selected;
|
||||
UnicodeString map;
|
||||
GameWindow *mapWindow = TheWindowManager->winGetWindowFromId( parent, listboxMap );
|
||||
|
||||
// get the selected index
|
||||
GadgetListBoxGetSelected( mapWindow, &selected );
|
||||
|
||||
if( selected != -1 )
|
||||
{
|
||||
//buttonPushed = true;
|
||||
// set the map name in the global data map name
|
||||
AsciiString asciiMap;
|
||||
const char *mapFname = (const char *)GadgetListBoxGetItemData( mapWindow, selected );
|
||||
DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
|
||||
if (mapFname)
|
||||
asciiMap = mapFname;
|
||||
else
|
||||
asciiMap.translate( map );
|
||||
TheSkirmishGameInfo->setMap( asciiMap );
|
||||
|
||||
const MapMetaData *md = TheMapCache->findMap(asciiMap);
|
||||
if (!md)
|
||||
{
|
||||
TheSkirmishGameInfo->setMapCRC(0);
|
||||
TheSkirmishGameInfo->setMapSize(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
TheSkirmishGameInfo->setMapCRC(md->m_CRC);
|
||||
TheSkirmishGameInfo->setMapSize(md->m_filesize);
|
||||
}
|
||||
|
||||
// reset the start positions
|
||||
for(Int i = 0; i < MAX_SLOTS; ++i)
|
||||
TheSkirmishGameInfo->getSlot(i)->setStartPos(-1);
|
||||
GameWindow *win;
|
||||
win = TheWindowManager->winGetWindowFromId( parent, TheNameKeyGenerator->nameToKey("SkirmishGameOptionsMenu.wnd:TextEntryMapDisplay") );
|
||||
if(win)
|
||||
{
|
||||
if (md)
|
||||
{
|
||||
GadgetStaticTextSetText(win, md->m_displayName);
|
||||
}
|
||||
}
|
||||
//if (mapFname)
|
||||
//setupGameStart(mapFname);
|
||||
|
||||
showSkirmishGameOptionsUnderlyingGUIElements(TRUE);
|
||||
skirmishPositionStartSpots();
|
||||
skirmishUpdateSlotList();
|
||||
|
||||
skirmishMapSelectLayout->destroyWindows();
|
||||
skirmishMapSelectLayout->deleteInstance();
|
||||
skirmishMapSelectLayout = NULL;
|
||||
//TheShell->pop();
|
||||
|
||||
} // end if
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end SkirmishMapSelectMenuSystem*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
** 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: WOLCustomScoreScreen.cpp
|
||||
// Author: Matt Campbell, December 2001
|
||||
// Description: Custom match score screen
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Lib/BaseType.h"
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "Common/GlobalData.h"
|
||||
//#include "GameNetwork/WOL.h"
|
||||
//#include "GameNetwork/WOLmenus.h"
|
||||
|
||||
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
// window ids ------------------------------------------------------------------------------
|
||||
static NameKeyType parentWOLCustomScoreID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonDisconnectID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonLobbyID = NAMEKEY_INVALID;
|
||||
|
||||
// Window Pointers ------------------------------------------------------------------------
|
||||
static GameWindow *parentWOLCustomScore = NULL;
|
||||
static GameWindow *buttonDisconnect = NULL;
|
||||
static GameWindow *buttonLobby = NULL;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the WOL Status Menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLCustomScoreScreenInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parentWOLCustomScoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:WOLCustomScoreScreenParent" ) );
|
||||
buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:ButtonDisconnect" ) );
|
||||
buttonLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLCustomScoreScreen.wnd:ButtonLobby" ) );
|
||||
parentWOLCustomScore = TheWindowManager->winGetWindowFromId( NULL, parentWOLCustomScoreID );
|
||||
buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID);
|
||||
buttonLobby = TheWindowManager->winGetWindowFromId( NULL, buttonLobbyID);
|
||||
|
||||
/*
|
||||
if (WOL::TheWOL->getState() == WOL::WOLAPI_FATAL_ERROR)
|
||||
{
|
||||
// We can get to the score screen even though we've been disconnected. Just hide
|
||||
// any buttons that lead back into WOL.
|
||||
buttonLobby->winHide( TRUE );
|
||||
}
|
||||
*/
|
||||
|
||||
// Show Menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// Set Keyboard to Main Parent
|
||||
TheWindowManager->winSetFocus( parentWOLCustomScore );
|
||||
} // WOLCustomScoreScreenInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLCustomScoreScreenShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
} // WOLCustomScoreScreenShutdown
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLCustomScoreScreenUpdate( WindowLayout * layout, void *userData)
|
||||
{
|
||||
/*
|
||||
if (WOL::TheWOL)
|
||||
WOL::TheWOL->update();
|
||||
*/
|
||||
}// WOLCustomScoreScreenUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLCustomScoreScreenInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonDisconnect, buttonDisconnectID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}// WOLCustomScoreScreenInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLCustomScoreScreenSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're given the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
/*
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == buttonDisconnectID )
|
||||
{
|
||||
if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR ))
|
||||
{
|
||||
WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything
|
||||
}
|
||||
|
||||
} //if ( controlID == buttonDisconnect )
|
||||
else if ( controlID == buttonLobbyID )
|
||||
{
|
||||
if (WOL::TheWOL->getState() != WOL::WOLAPI_FATAL_ERROR)
|
||||
{
|
||||
WOL::TheWOL->setScreen(WOL::WOLAPI_MENU_CUSTOMLOBBY);
|
||||
WOL::TheWOL->setGameMode(WOL::WOLTYPE_CUSTOM);
|
||||
WOL::TheWOL->setState( WOL::WOLAPI_LOBBY );
|
||||
WOL::TheWOL->addCommand( WOL::WOLCOMMAND_REFRESH_CHANNELS );
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
} //if ( controlID == buttonDisconnect )
|
||||
*/
|
||||
break;
|
||||
}// case GBM_SELECTED:
|
||||
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
}// WOLCustomScoreScreenSystem
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
** 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: ReplayMenu.cpp /////////////////////////////////////////////////////////////////////
|
||||
// Author: Chris The masta Huybregts, December 2001
|
||||
// Description: Replay Menus
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/MessageBox.h"
|
||||
#include "GameNetwork/WOLBrowser/WebBrowser.h"
|
||||
|
||||
// window ids -------------------------------------------------------------------------------------
|
||||
static NameKeyType parentWindowID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonBackID = NAMEKEY_INVALID;
|
||||
static NameKeyType windowLadderID = NAMEKEY_INVALID;
|
||||
|
||||
|
||||
// window pointers --------------------------------------------------------------------------------
|
||||
static GameWindow *parentWindow = NULL;
|
||||
static GameWindow *buttonBack = NULL;
|
||||
static GameWindow *windowLadder = NULL;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the single player menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLLadderScreenInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
TheShell->showShellMap(TRUE);
|
||||
|
||||
// get ids for our children controls
|
||||
parentWindowID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:LadderParent") );
|
||||
buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:ButtonBack") );
|
||||
windowLadderID = TheNameKeyGenerator->nameToKey( AsciiString("WOLLadderScreen.wnd:WindowLadder") );
|
||||
|
||||
parentWindow = TheWindowManager->winGetWindowFromId( NULL, parentWindowID );
|
||||
buttonBack = TheWindowManager->winGetWindowFromId( parentWindow, buttonBackID );
|
||||
windowLadder = TheWindowManager->winGetWindowFromId( parentWindow, windowLadderID );
|
||||
|
||||
//Load the listbox shiznit
|
||||
// PopulateReplayFileListbox(listboxReplayFiles);
|
||||
|
||||
//TheWebBrowser->createBrowserWindow("Westwood", windowLadder);
|
||||
if (TheWebBrowser != NULL)
|
||||
{
|
||||
TheWebBrowser->createBrowserWindow("MessageBoard", windowLadder);
|
||||
}
|
||||
|
||||
// show menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// set keyboard focus to main parent
|
||||
TheWindowManager->winSetFocus( parentWindow );
|
||||
|
||||
} // end ReplayMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLLadderScreenShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
if (TheWebBrowser != NULL)
|
||||
{
|
||||
TheWebBrowser->closeBrowserWindow(windowLadder);
|
||||
}
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // end ReplayMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLLadderScreenUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
} // end ReplayMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Replay menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLLadderScreenInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonBack, buttonBackID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end ReplayMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** single player menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLLadderScreenSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonBackID )
|
||||
{
|
||||
|
||||
// thou art directed to return to thy known solar system immediately!
|
||||
TheShell->pop();
|
||||
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
} // end ReplayMenuSystem
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
** 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: WOLLocaleSelectPopup.cpp
|
||||
// Author: Matt Campbell, December 2001
|
||||
// Description: WOL locale select popup
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/GameText.h"
|
||||
#include "Common/CustomMatchPreferences.h"
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/GameSpyMiscPreferences.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "Common/GlobalData.h"
|
||||
#include "GameNetwork/GameSpyOverlay.h"
|
||||
#include "GameNetwork/GameSpy/PeerDefs.h"
|
||||
#include "GameNetwork/GameSpy/PeerThread.h"
|
||||
#include "GameNetwork/GameSpy/PersistentStorageDefs.h"
|
||||
#include "GameNetwork/GameSpy/PersistentStorageThread.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
// window ids ------------------------------------------------------------------------------
|
||||
static NameKeyType parentLocaleSelectID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOkID = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxLocaleID = NAMEKEY_INVALID;
|
||||
|
||||
// Window Pointers ------------------------------------------------------------------------
|
||||
static GameWindow *parentLocaleSelect = NULL;
|
||||
static GameWindow *buttonOk = NULL;
|
||||
static GameWindow *listboxLocale = NULL;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the WOL Status Menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLLocaleSelectInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parentLocaleSelectID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ParentLocaleSelect" ) );
|
||||
buttonOkID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ButtonOk" ) );
|
||||
listboxLocaleID = TheNameKeyGenerator->nameToKey( AsciiString( "PopupLocaleSelect.wnd:ListBoxLocaleSelect" ) );
|
||||
parentLocaleSelect = TheWindowManager->winGetWindowFromId( NULL, parentLocaleSelectID );
|
||||
buttonOk = TheWindowManager->winGetWindowFromId( NULL, buttonOkID);
|
||||
listboxLocale = TheWindowManager->winGetWindowFromId( NULL, listboxLocaleID);
|
||||
|
||||
for (int i=LOC_MIN; i<=LOC_MAX; ++i)
|
||||
{
|
||||
AsciiString id;
|
||||
id.format("WOL:Locale%2.2d", i);
|
||||
GadgetListBoxAddEntryText(listboxLocale, TheGameText->fetch(id.str()), GameSpyColor[GSCOLOR_DEFAULT], -1, -1);
|
||||
}
|
||||
GadgetListBoxSetSelected(listboxLocale, 0);
|
||||
|
||||
// Show Menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// Set Keyboard to Main Parent
|
||||
TheWindowManager->winSetFocus( parentLocaleSelect );
|
||||
TheWindowManager->winSetModal( parentLocaleSelect );
|
||||
} // WOLLocaleSelectInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLLocaleSelectShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // WOLLocaleSelectShutdown
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLLocaleSelectUpdate( WindowLayout * layout, void *userData)
|
||||
{
|
||||
|
||||
}// WOLLocaleSelectUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLLocaleSelectInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
// UnsignedByte key = mData1;
|
||||
// UnsignedByte state = mData2;
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
} // end char
|
||||
} // end switch( msg )
|
||||
return MSG_IGNORED;
|
||||
}// WOLLocaleSelectInput
|
||||
|
||||
//Int getRegistryNicknameOffset(AsciiString nick); /// @todo: mdc remove this once we can save ini pref files
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLLocaleSelectSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == buttonOkID )
|
||||
{
|
||||
int selected;
|
||||
GadgetListBoxGetSelected(listboxLocale, &selected);
|
||||
if (selected < 0)
|
||||
return MSG_HANDLED; // can't select nothing!
|
||||
PSRequest psReq;
|
||||
psReq.requestType = PSRequest::PSREQUEST_UPDATEPLAYERLOCALE;
|
||||
psReq.player.locale = selected + LOC_MIN;
|
||||
psReq.email = TheGameSpyInfo->getLocalEmail().str();
|
||||
psReq.nick = TheGameSpyInfo->getLocalBaseName().str();
|
||||
psReq.password = TheGameSpyInfo->getLocalPassword().str();
|
||||
psReq.player.id = TheGameSpyInfo->getLocalProfileID();
|
||||
|
||||
TheGameSpyPSMessageQueue->addRequest(psReq);
|
||||
GameSpyCloseOverlay(GSOVERLAY_LOCALESELECT);
|
||||
|
||||
GameSpyMiscPreferences cPref;
|
||||
cPref.setLocale(psReq.player.locale);
|
||||
cPref.write();
|
||||
|
||||
PSPlayerStats stats = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID());
|
||||
stats.locale = psReq.player.locale;
|
||||
if (stats.id == TheGameSpyInfo->getLocalProfileID())
|
||||
TheGameSpyPSMessageQueue->trackPlayerStats(stats);
|
||||
|
||||
if(stats.id == 0)
|
||||
{
|
||||
stats = TheGameSpyInfo->getCachedLocalPlayerStats();
|
||||
stats.locale = psReq.player.locale;
|
||||
TheGameSpyInfo->setCachedLocalPlayerStats(stats);
|
||||
}
|
||||
else
|
||||
{
|
||||
// force an update of our shtuff
|
||||
PSResponse newResp;
|
||||
newResp.responseType = PSResponse::PSRESPONSE_PLAYERSTATS;
|
||||
newResp.player = TheGameSpyPSMessageQueue->findPlayerStatsByID(TheGameSpyInfo->getLocalProfileID());
|
||||
TheGameSpyPSMessageQueue->addResponse(newResp);
|
||||
}
|
||||
CheckReOpenPlayerInfo();
|
||||
} //if ( controlID == buttonDisconnect )
|
||||
break;
|
||||
}// case GBM_SELECTED:
|
||||
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
}// WOLLocaleSelectSystem
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
** 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: WOLMapSelectMenu.cpp ////////////////////////////////////////////////////////////////////////
|
||||
// Author: Matt Campbell, December 2001
|
||||
// Description: MapSelect menu window callbacks
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/CustomMatchPreferences.h"
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/MessageStream.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetRadioButton.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameNetwork/GameSpy/PeerDefs.h"
|
||||
#include "GameNetwork/GameSpyOverlay.h"
|
||||
#include "GameClient/MapUtil.h"
|
||||
#include "GameNetwork/GUIUtil.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static NameKeyType buttonBack = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOK = NAMEKEY_INVALID;
|
||||
static NameKeyType listboxMap = NAMEKEY_INVALID;
|
||||
static GameWindow *parent = NULL;
|
||||
static Bool raiseMessageBoxes = FALSE;
|
||||
static GameWindow *winMapPreview = NULL;
|
||||
static NameKeyType winMapPreviewID = NAMEKEY_INVALID;
|
||||
|
||||
static NameKeyType radioButtonSystemMapsID = NAMEKEY_INVALID;
|
||||
static NameKeyType radioButtonUserMapsID = NAMEKEY_INVALID;
|
||||
|
||||
extern WindowLayout *WOLMapSelectLayout; ///< Map selection overlay
|
||||
static GameWindow *mapList = NULL;
|
||||
|
||||
static GameWindow *buttonMapStartPosition[MAX_SLOTS] = {NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL };
|
||||
static NameKeyType buttonMapStartPositionID[MAX_SLOTS] = { NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID,
|
||||
NAMEKEY_INVALID,NAMEKEY_INVALID };
|
||||
|
||||
static GameWindow *winMapWindow = NULL;
|
||||
|
||||
static void NullifyControls(void)
|
||||
{
|
||||
parent = NULL;
|
||||
winMapPreview = NULL;
|
||||
mapList = NULL;
|
||||
for (Int i=0; i<MAX_SLOTS; ++i)
|
||||
{
|
||||
buttonMapStartPosition[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *layoutFilename = "GameSpyGameOptionsMenu.wnd";
|
||||
static const char *parentName = "GameSpyGameOptionsMenuParent";
|
||||
static const char *gadgetsToHide[] =
|
||||
{
|
||||
"MapWindow",
|
||||
//"StaticTextGameName",
|
||||
"StaticTextTeam",
|
||||
"StaticTextFaction",
|
||||
"StaticTextColor",
|
||||
"TextEntryMapDisplay",
|
||||
"ButtonSelectMap",
|
||||
"ButtonStart",
|
||||
"StaticTextMapPreview",
|
||||
|
||||
NULL // keep this last
|
||||
};
|
||||
static const char *perPlayerGadgetsToHide[] =
|
||||
{
|
||||
"ComboBoxTeam",
|
||||
"ComboBoxColor",
|
||||
"ComboBoxPlayerTemplate",
|
||||
//"ButtonStartPosition",
|
||||
NULL // keep this last
|
||||
};
|
||||
void positionStartSpots( AsciiString mapName, GameWindow *buttonMapStartPositions[], GameWindow *mapWindow);
|
||||
|
||||
static void showGameSpyGameOptionsUnderlyingGUIElements( Bool show )
|
||||
{
|
||||
ShowUnderlyingGUIElements( show, layoutFilename, parentName, gadgetsToHide, perPlayerGadgetsToHide );
|
||||
GameWindow *win = TheWindowManager->winGetWindowFromId( NULL, TheNameKeyGenerator->nameToKey("GameSpyGameOptionsMenu.wnd:ButtonBack") );
|
||||
if(win)
|
||||
win->winEnable( show );
|
||||
}
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the MapSelect menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLMapSelectMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// set keyboard focus to main parent
|
||||
AsciiString parentName( "WOLMapSelectMenu.wnd:WOLMapSelectMenuParent" );
|
||||
NameKeyType parentID = TheNameKeyGenerator->nameToKey( parentName );
|
||||
parent = TheWindowManager->winGetWindowFromId( NULL, parentID );
|
||||
|
||||
TheWindowManager->winSetFocus( parent );
|
||||
|
||||
CustomMatchPreferences pref;
|
||||
Bool usesSystemMapDir = pref.usesSystemMapDir();
|
||||
winMapPreviewID = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:WinMapPreview") );
|
||||
winMapPreview = TheWindowManager->winGetWindowFromId(parent, winMapPreviewID);
|
||||
|
||||
const MapMetaData *mmd = TheMapCache->findMap(TheGameSpyGame->getMap());
|
||||
if (mmd)
|
||||
{
|
||||
usesSystemMapDir = mmd->m_isOfficial;
|
||||
}
|
||||
|
||||
buttonBack = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ButtonBack") );
|
||||
buttonOK = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ButtonOK") );
|
||||
listboxMap = TheNameKeyGenerator->nameToKey( AsciiString("WOLMapSelectMenu.wnd:ListboxMap") );
|
||||
radioButtonSystemMapsID = TheNameKeyGenerator->nameToKey( "WOLMapSelectMenu.wnd:RadioButtonSystemMaps" );
|
||||
radioButtonUserMapsID = TheNameKeyGenerator->nameToKey( "WOLMapSelectMenu.wnd:RadioButtonUserMaps" );
|
||||
winMapWindow = TheWindowManager->winGetWindowFromId( parent, listboxMap );
|
||||
|
||||
GameWindow *radioButtonSystemMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonSystemMapsID );
|
||||
GameWindow *radioButtonUserMaps = TheWindowManager->winGetWindowFromId( parent, radioButtonUserMapsID );
|
||||
if (usesSystemMapDir)
|
||||
GadgetRadioSetSelection( radioButtonSystemMaps, FALSE );
|
||||
else
|
||||
GadgetRadioSetSelection( radioButtonUserMaps, FALSE );
|
||||
|
||||
AsciiString tmpString;
|
||||
for (Int i = 0; i < MAX_SLOTS; i++)
|
||||
{
|
||||
tmpString.format("WOLMapSelectMenu.wnd:ButtonMapStartPosition%d", i);
|
||||
buttonMapStartPositionID[i] = TheNameKeyGenerator->nameToKey( tmpString );
|
||||
buttonMapStartPosition[i] = TheWindowManager->winGetWindowFromId( winMapPreview, buttonMapStartPositionID[i] );
|
||||
DEBUG_ASSERTCRASH(buttonMapStartPosition[i], ("Could not find the ButtonMapStartPosition[%d]",i ));
|
||||
buttonMapStartPosition[i]->winHide(TRUE);
|
||||
buttonMapStartPosition[i]->winEnable(FALSE);
|
||||
}
|
||||
|
||||
raiseMessageBoxes = TRUE;
|
||||
showGameSpyGameOptionsUnderlyingGUIElements( FALSE );
|
||||
|
||||
// get the listbox window
|
||||
AsciiString listString( "WOLMapSelectMenu.wnd:ListboxMap" );
|
||||
NameKeyType mapListID = TheNameKeyGenerator->nameToKey( listString );
|
||||
mapList = TheWindowManager->winGetWindowFromId( parent, mapListID );
|
||||
if( mapList )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, usesSystemMapDir, TRUE, TheGameSpyGame->getMap() );
|
||||
}
|
||||
|
||||
} // end WOLMapSelectMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLMapSelectMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
NullifyControls();
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
} // end WOLMapSelectMenuShutdown
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLMapSelectMenuUpdate( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
if (raiseMessageBoxes)
|
||||
{
|
||||
RaiseGSMessageBox();
|
||||
raiseMessageBoxes = false;
|
||||
}
|
||||
|
||||
// No update because the game setup screen is up at the same
|
||||
// time and it does the update for us...
|
||||
} // end WOLMapSelectMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Map select menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLMapSelectMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
AsciiString buttonName( "WOLMapSelectMenu.wnd:ButtonBack" );
|
||||
NameKeyType buttonID = TheNameKeyGenerator->nameToKey( buttonName );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonID );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end WOLMapSelectMenuInput
|
||||
void WOLPositionStartSpots( void );
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** MapSelect menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLMapSelectMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
{
|
||||
break;
|
||||
|
||||
} // end create
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
NullifyControls();
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GLM_DOUBLE_CLICKED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxMap )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
|
||||
if (rowSelected >= 0)
|
||||
{
|
||||
GadgetListBoxSetSelected( control, rowSelected );
|
||||
GameWindow *button = TheWindowManager->winGetWindowFromId( window, buttonOK );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)button, buttonOK );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GLM_SELECTED:
|
||||
{
|
||||
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
if( controlID == listboxMap )
|
||||
{
|
||||
int rowSelected = mData2;
|
||||
if( rowSelected < 0 )
|
||||
{
|
||||
positionStartSpots( AsciiString::TheEmptyString, buttonMapStartPosition, winMapPreview);
|
||||
// winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
|
||||
break;
|
||||
}
|
||||
winMapPreview->winSetStatus(WIN_STATUS_IMAGE);
|
||||
UnicodeString map;
|
||||
// get text of the map to load
|
||||
map = GadgetListBoxGetText( winMapWindow, rowSelected, 0 );
|
||||
|
||||
// set the map name in the global data map name
|
||||
AsciiString asciiMap;
|
||||
const char *mapFname = (const char *)GadgetListBoxGetItemData( winMapWindow, rowSelected );
|
||||
DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
|
||||
if (mapFname)
|
||||
asciiMap = mapFname;
|
||||
else
|
||||
asciiMap.translate( map );
|
||||
asciiMap.toLower();
|
||||
Image *image = getMapPreviewImage(asciiMap);
|
||||
winMapPreview->winSetUserData((void *)TheMapCache->findMap(asciiMap));
|
||||
if(image)
|
||||
{
|
||||
winMapPreview->winSetEnabledImage(0, image);
|
||||
}
|
||||
else
|
||||
{
|
||||
winMapPreview->winClearStatus(WIN_STATUS_IMAGE);
|
||||
}
|
||||
positionStartSpots( asciiMap, buttonMapStartPosition, winMapPreview);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if( controlID == buttonBack )
|
||||
{
|
||||
showGameSpyGameOptionsUnderlyingGUIElements( TRUE );
|
||||
|
||||
WOLMapSelectLayout->destroyWindows();
|
||||
WOLMapSelectLayout->deleteInstance();
|
||||
WOLMapSelectLayout = NULL;
|
||||
WOLPositionStartSpots();
|
||||
} // end if
|
||||
else if ( controlID == radioButtonSystemMapsID )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, TRUE, TRUE, TheGameSpyGame->getMap() );
|
||||
CustomMatchPreferences pref;
|
||||
pref.setUsesSystemMapDir(TRUE);
|
||||
pref.write();
|
||||
}
|
||||
else if ( controlID == radioButtonUserMapsID )
|
||||
{
|
||||
if (TheMapCache)
|
||||
TheMapCache->updateCache();
|
||||
populateMapListbox( mapList, FALSE, TRUE, TheGameSpyGame->getMap() );
|
||||
CustomMatchPreferences pref;
|
||||
pref.setUsesSystemMapDir(FALSE);
|
||||
pref.write();
|
||||
}
|
||||
else if( controlID == buttonOK )
|
||||
{
|
||||
Int selected;
|
||||
UnicodeString map;
|
||||
|
||||
// get the selected index
|
||||
GadgetListBoxGetSelected( winMapWindow, &selected );
|
||||
|
||||
if( selected != -1 )
|
||||
{
|
||||
|
||||
// get text of the map to load
|
||||
map = GadgetListBoxGetText( winMapWindow, selected, 0 );
|
||||
|
||||
|
||||
// set the map name in the global data map name
|
||||
AsciiString asciiMap;
|
||||
const char *mapFname = (const char *)GadgetListBoxGetItemData( winMapWindow, selected );
|
||||
DEBUG_ASSERTCRASH(mapFname, ("No map item data"));
|
||||
if (mapFname)
|
||||
asciiMap = mapFname;
|
||||
else
|
||||
asciiMap.translate( map );
|
||||
TheGameSpyGame->setMap(asciiMap);
|
||||
asciiMap.toLower();
|
||||
std::map<AsciiString, MapMetaData>::iterator it = TheMapCache->find(asciiMap);
|
||||
if (it != TheMapCache->end())
|
||||
{
|
||||
TheGameSpyGame->getGameSpySlot(0)->setMapAvailability(TRUE);
|
||||
TheGameSpyGame->setMapCRC( it->second.m_CRC );
|
||||
TheGameSpyGame->setMapSize( it->second.m_filesize );
|
||||
}
|
||||
|
||||
TheGameSpyGame->adjustSlotsForMap(); // BGC- adjust the slots for the new map.
|
||||
TheGameSpyGame->resetAccepted();
|
||||
TheGameSpyGame->resetStartSpots();
|
||||
TheGameSpyInfo->setGameOptions();
|
||||
|
||||
WOLDisplaySlotList();
|
||||
WOLDisplayGameOptions();
|
||||
|
||||
WOLMapSelectLayout->destroyWindows();
|
||||
WOLMapSelectLayout->deleteInstance();
|
||||
WOLMapSelectLayout = NULL;
|
||||
|
||||
showGameSpyGameOptionsUnderlyingGUIElements( TRUE );
|
||||
|
||||
WOLPositionStartSpots();
|
||||
|
||||
} // end if
|
||||
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end WOLMapSelectMenuSystem
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
** 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: WOLMessageWindow.cpp
|
||||
// Author: Chris Huybregts, November 2001
|
||||
// Description: Lan Lobby Menu
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameNetwork/IPEnumeration.h"
|
||||
//#include "GameNetwork/WOL.h"
|
||||
|
||||
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
// window ids ------------------------------------------------------------------------------
|
||||
static NameKeyType parentWOLMessageWindowID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonCancelID = NAMEKEY_INVALID;
|
||||
|
||||
// Window Pointers ------------------------------------------------------------------------
|
||||
static GameWindow *parentWOLMessageWindow = NULL;
|
||||
static GameWindow *buttonCancel = NULL;
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the WOLMessage Window */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLMessageWindowInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parentWOLMessageWindowID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLMessageWindow.wnd:WOLMessageWindowParent" ) );
|
||||
buttonCancelID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLMessageWindow.wnd:ButtonCancel" ) );
|
||||
parentWOLMessageWindow = TheWindowManager->winGetWindowFromId( NULL, parentWOLMessageWindowID );
|
||||
buttonCancel = TheWindowManager->winGetWindowFromId( NULL, buttonCancelID);
|
||||
|
||||
|
||||
// Show Menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// Set Keyboard to Main Parent
|
||||
TheWindowManager->winSetFocus( parentWOLMessageWindow );
|
||||
|
||||
} // WOLMessageWindowInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOLMessage Window shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLMessageWindowShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
} // WOLMessageWindowShutdown
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOLMessage Window update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLMessageWindowUpdate( WindowLayout * layout, void *userData)
|
||||
{
|
||||
/*
|
||||
if (WOL::TheWOL)
|
||||
WOL::TheWOL->update();
|
||||
*/
|
||||
|
||||
}// WOLMessageWindowUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOLMessage Window input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLMessageWindowInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonCancel, buttonCancelID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}// WOLMessageWindowInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOLMessage Window window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLMessageWindowSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
break;
|
||||
}// case GBM_SELECTED:
|
||||
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
}// WOLMessageWindowSystem
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
** 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: WOLQMScoreScreen.cpp
|
||||
// Author: Matt Campbell, November 2001
|
||||
// Description: QuickMatch score screen (different from normal screen in that it has 'QM' and 'Discon' buttons)
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
//#include "GameNetwork/WOL.h"
|
||||
//#include "GameNetwork/WOLmenus.h"
|
||||
|
||||
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
// window ids ------------------------------------------------------------------------------
|
||||
static NameKeyType parentWOLQMScoreID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonDisconnectID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonQuickmatchID = NAMEKEY_INVALID;
|
||||
|
||||
// Window Pointers ------------------------------------------------------------------------
|
||||
static GameWindow *parentWOLQMScore = NULL;
|
||||
static GameWindow *buttonDisconnect = NULL;
|
||||
static GameWindow *buttonQuickmatch = NULL;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the WOL Status Menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLQMScoreScreenInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parentWOLQMScoreID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:WOLQMScoreScreenParent" ) );
|
||||
buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:ButtonDisconnect" ) );
|
||||
buttonQuickmatchID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLQMScoreScreen.wnd:ButtonQuickMatch" ) );
|
||||
parentWOLQMScore = TheWindowManager->winGetWindowFromId( NULL, parentWOLQMScoreID );
|
||||
buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID);
|
||||
buttonQuickmatch = TheWindowManager->winGetWindowFromId( NULL, buttonQuickmatchID);
|
||||
|
||||
/*
|
||||
if (WOL::TheWOL->getState() == WOL::WOLAPI_FATAL_ERROR)
|
||||
{
|
||||
// We can get to the score screen even though we've been disconnected. Just hide
|
||||
// any buttons that lead back into WOL.
|
||||
|
||||
buttonQuickmatch->winHide( TRUE );
|
||||
}
|
||||
*/
|
||||
|
||||
// Show Menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// Set Keyboard to Main Parent
|
||||
TheWindowManager->winSetFocus( parentWOLQMScore );
|
||||
|
||||
//progressLayout = TheShell->top();
|
||||
|
||||
} // WOLQMScoreScreenInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLQMScoreScreenShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
//progressLayout = NULL;
|
||||
|
||||
} // WOLQMScoreScreenShutdown
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLQMScoreScreenUpdate( WindowLayout * layout, void *userData)
|
||||
{
|
||||
/*
|
||||
if (WOL::TheWOL)
|
||||
WOL::TheWOL->update();
|
||||
*/
|
||||
}// WOLQMScoreScreenUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLQMScoreScreenInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonDisconnect, buttonDisconnectID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}// WOLQMScoreScreenInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLQMScoreScreenSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're given the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
/*
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == buttonDisconnectID )
|
||||
{
|
||||
//TheShell->pop();
|
||||
if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR ))
|
||||
{
|
||||
WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything
|
||||
}
|
||||
|
||||
} //if ( controlID == buttonDisconnect )
|
||||
else if ( controlID == buttonQuickmatchID )
|
||||
{
|
||||
//TheShell->pop();
|
||||
if (WOL::TheWOL->getState() != WOL::WOLAPI_FATAL_ERROR)
|
||||
{
|
||||
if (WOL::TheWOL->setState( WOL::WOLAPI_TOURNAMENT ))
|
||||
{
|
||||
WOL::TheWOL->setScreen( WOL::WOLAPI_MENU_QUICKMATCH );
|
||||
WOL::TheWOL->addCommand( WOL::WOLCOMMAND_FIND_MATCH_CHANNEL );
|
||||
}
|
||||
}
|
||||
|
||||
} //if ( controlID == buttonDisconnect )
|
||||
*/
|
||||
break;
|
||||
}// case GBM_SELECTED:
|
||||
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
}// WOLQMScoreScreenSystem
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
** 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: WOLLoginMenu.cpp
|
||||
// Author: Chris Huybregts, November 2001
|
||||
// Description: Lan Lobby Menu
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
//#include "GameNetwork/WOL.h"
|
||||
//#include "GameNetwork/WOLmenus.h"
|
||||
|
||||
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
// window ids ------------------------------------------------------------------------------
|
||||
static NameKeyType parentWOLStatusID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonDisconnectID = NAMEKEY_INVALID;
|
||||
|
||||
// Window Pointers ------------------------------------------------------------------------
|
||||
static GameWindow *parentWOLStatus = NULL;
|
||||
static GameWindow *buttonDisconnect = NULL;
|
||||
GameWindow *progressTextWindow = NULL;
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the WOL Status Menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLStatusMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
parentWOLStatusID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:WOLStatusMenuParent" ) );
|
||||
buttonDisconnectID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:ButtonDisconnect" ) );
|
||||
parentWOLStatus = TheWindowManager->winGetWindowFromId( NULL, parentWOLStatusID );
|
||||
buttonDisconnect = TheWindowManager->winGetWindowFromId( NULL, buttonDisconnectID);
|
||||
|
||||
progressTextWindow = TheWindowManager->winGetWindowFromId( NULL,
|
||||
TheNameKeyGenerator->nameToKey( AsciiString( "WOLStatusMenu.wnd:ListboxStatus" ) ) );
|
||||
|
||||
// Show Menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// Set Keyboard to Main Parent
|
||||
TheWindowManager->winSetFocus( parentWOLStatus );
|
||||
|
||||
//progressLayout = TheShell->top();
|
||||
|
||||
//WOL::raiseWOLMessageBox();
|
||||
} // WOLStatusMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLStatusMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
|
||||
// hide menu
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout );
|
||||
|
||||
//progressLayout = NULL;
|
||||
|
||||
//WOL::raiseWOLMessageBox();
|
||||
} // WOLStatusMenuShutdown
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLStatusMenuUpdate( WindowLayout * layout, void *userData)
|
||||
{
|
||||
//if (WOL::TheWOL)
|
||||
//WOL::TheWOL->update();
|
||||
}// WOLStatusMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLStatusMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonDisconnect, buttonDisconnectID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}// WOLStatusMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Status Menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLStatusMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
/*
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == buttonDisconnectID )
|
||||
{
|
||||
//TheShell->pop();
|
||||
if (WOL::TheWOL->setState( WOL::WOLAPI_FATAL_ERROR ))
|
||||
{
|
||||
WOL::TheWOL->addCommand( WOL::WOLCOMMAND_RESET ); // don't display an error, log out, or anything
|
||||
}
|
||||
|
||||
} //if ( controlID == buttonDisconnect )
|
||||
*/
|
||||
break;
|
||||
}// case GBM_SELECTED:
|
||||
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
}// WOLStatusMenuSystem
|
||||
@@ -0,0 +1,894 @@
|
||||
/*
|
||||
** 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: WOLWelcomeMenu.cpp
|
||||
// Author: Chris Huybregts, November 2001
|
||||
// Description: Lan Lobby Menu
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameSpy/peer/peer.h"
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/GameSpyMiscPreferences.h"
|
||||
#include "Common/CustomMatchPreferences.h"
|
||||
#include "Common/GlobalData.h"
|
||||
#include "Common/UserPreferences.h"
|
||||
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/Display.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameText.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GadgetListBox.h"
|
||||
#include "GameClient/GadgetTextEntry.h"
|
||||
#include "GameClient/GadgetStaticText.h"
|
||||
#include "GameClient/MessageBox.h"
|
||||
#include "GameClient/GameWindowTransitions.h"
|
||||
|
||||
#include "GameNetwork/FirewallHelper.h"
|
||||
#include "GameNetwork/GameSpyOverlay.h"
|
||||
|
||||
#include "GameNetwork/GameSpy/BuddyDefs.h"
|
||||
#include "GameNetwork/GameSpy/BuddyThread.h"
|
||||
#include "GameNetwork/GameSpy/PeerDefs.h"
|
||||
#include "GameNetwork/GameSpy/PeerThread.h"
|
||||
#include "GameNetwork/GameSpy/PersistentStorageDefs.h"
|
||||
#include "GameNetwork/GameSpy/PersistentStorageThread.h"
|
||||
#include "GameNetwork/GameSpy/BuddyThread.h"
|
||||
#include "GameNetwork/GameSpy/ThreadUtils.h"
|
||||
#include "GameNetwork/GameSpy/MainMenuUtils.h"
|
||||
#include "GameNetwork/WOLBrowser/WebBrowser.h"
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
static Bool isShuttingDown = FALSE;
|
||||
static Bool buttonPushed = FALSE;
|
||||
static char *nextScreen = NULL;
|
||||
|
||||
// window ids ------------------------------------------------------------------------------
|
||||
static NameKeyType parentWOLWelcomeID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonBackID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonQuickMatchID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonLobbyID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonBuddiesID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonLadderID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonMyInfoID = NAMEKEY_INVALID;
|
||||
|
||||
static NameKeyType listboxInfoID = NAMEKEY_INVALID;
|
||||
static NameKeyType buttonOptionsID = NAMEKEY_INVALID;
|
||||
// Window Pointers ------------------------------------------------------------------------
|
||||
static GameWindow *parentWOLWelcome = NULL;
|
||||
static GameWindow *buttonBack = NULL;
|
||||
static GameWindow *buttonQuickMatch = NULL;
|
||||
static GameWindow *buttonLobby = NULL;
|
||||
static GameWindow *buttonBuddies = NULL;
|
||||
static GameWindow *buttonLadder = NULL;
|
||||
static GameWindow *buttonMyInfo = NULL;
|
||||
static GameWindow *buttonbuttonOptions = NULL;
|
||||
static WindowLayout *welcomeLayout = NULL;
|
||||
static GameWindow *listboxInfo = NULL;
|
||||
|
||||
static GameWindow *staticTextServerName = NULL;
|
||||
static GameWindow *staticTextLastUpdated = NULL;
|
||||
|
||||
static GameWindow *staticTextLadderWins = NULL;
|
||||
static GameWindow *staticTextLadderLosses = NULL;
|
||||
static GameWindow *staticTextLadderRank = NULL;
|
||||
static GameWindow *staticTextLadderPoints = NULL;
|
||||
static GameWindow *staticTextLadderDisconnects = NULL;
|
||||
|
||||
static GameWindow *staticTextHighscoreWins = NULL;
|
||||
static GameWindow *staticTextHighscoreLosses = NULL;
|
||||
static GameWindow *staticTextHighscoreRank = NULL;
|
||||
static GameWindow *staticTextHighscorePoints = NULL;
|
||||
|
||||
static UnicodeString gServerName;
|
||||
void updateServerDisplay(UnicodeString serverName)
|
||||
{
|
||||
if (staticTextServerName)
|
||||
{
|
||||
GadgetStaticTextSetText(staticTextServerName, serverName);
|
||||
}
|
||||
gServerName = serverName;
|
||||
}
|
||||
|
||||
/*
|
||||
void updateLocalPlayerScores(AsciiString name, const WOL::Ladder *ladder, const WOL::Highscore *highscore)
|
||||
{
|
||||
if (ladder)
|
||||
{
|
||||
AsciiString a;
|
||||
UnicodeString u;
|
||||
|
||||
a.format("%d", ladder->wins);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextLadderWins, u);
|
||||
|
||||
a.format("%d", ladder->losses);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextLadderLosses, u);
|
||||
|
||||
a.format("%d", ladder->rank);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextLadderRank, u);
|
||||
|
||||
a.format("%d", ladder->points);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextLadderPoints, u);
|
||||
|
||||
a.format("%d", ladder->disconnects);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextLadderDisconnects, u);
|
||||
}
|
||||
if (highscore)
|
||||
{
|
||||
AsciiString a;
|
||||
UnicodeString u;
|
||||
|
||||
a.format("%d", highscore->wins);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextHighscoreWins, u);
|
||||
|
||||
a.format("%d", highscore->losses);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextHighscoreLosses, u);
|
||||
|
||||
a.format("%d", highscore->rank);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextHighscoreRank, u);
|
||||
|
||||
a.format("%d", highscore->points);
|
||||
u.translate(a);
|
||||
GadgetStaticTextSetText(staticTextHighscorePoints, u);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
static void enableControls( Bool state )
|
||||
{
|
||||
#ifndef _PLAYTEST
|
||||
if (buttonQuickMatch)
|
||||
buttonQuickMatch->winEnable(state);
|
||||
#else
|
||||
if (buttonQuickMatch)
|
||||
buttonQuickMatch->winEnable(FALSE);
|
||||
#endif
|
||||
if (buttonLobby)
|
||||
buttonLobby->winEnable(state);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** This is called when a shutdown is complete for this menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
static void shutdownComplete( WindowLayout *layout )
|
||||
{
|
||||
|
||||
isShuttingDown = FALSE;
|
||||
|
||||
// hide the layout
|
||||
layout->hide( TRUE );
|
||||
|
||||
// our shutdown is complete
|
||||
TheShell->shutdownComplete( layout, (nextScreen != NULL) );
|
||||
|
||||
if (nextScreen != NULL)
|
||||
{
|
||||
TheShell->push(nextScreen);
|
||||
}
|
||||
|
||||
nextScreen = NULL;
|
||||
|
||||
} // end if
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Handle Num Players Online data */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
static Int lastNumPlayersOnline = 0;
|
||||
|
||||
static UnsignedByte grabUByte(const char *s)
|
||||
{
|
||||
char tmp[5] = "0xff";
|
||||
tmp[2] = s[0];
|
||||
tmp[3] = s[1];
|
||||
UnsignedByte b = strtol(tmp, NULL, 16);
|
||||
return b;
|
||||
}
|
||||
|
||||
static void updateNumPlayersOnline(void)
|
||||
{
|
||||
GameWindow *playersOnlineWindow = TheWindowManager->winGetWindowFromId(
|
||||
NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextNumPlayersOnline") );
|
||||
|
||||
if (playersOnlineWindow)
|
||||
{
|
||||
UnicodeString valStr;
|
||||
valStr.format(TheGameText->fetch("GUI:NumPlayersOnline"), lastNumPlayersOnline);
|
||||
GadgetStaticTextSetText(playersOnlineWindow, valStr);
|
||||
}
|
||||
|
||||
if (listboxInfo && TheGameSpyInfo)
|
||||
{
|
||||
GadgetListBoxReset(listboxInfo);
|
||||
AsciiString aLine;
|
||||
UnicodeString line;
|
||||
AsciiString aMotd = TheGameSpyInfo->getMOTD();
|
||||
UnicodeString headingStr;
|
||||
headingStr.format(TheGameText->fetch("MOTD:NumPlayersHeading"), lastNumPlayersOnline);
|
||||
|
||||
while (headingStr.nextToken(&line, UnicodeString(L"\n")))
|
||||
{
|
||||
if (line.getCharAt(line.getLength()-1) == '\r')
|
||||
line.removeLastChar(); // there is a trailing '\r'
|
||||
|
||||
line.trim();
|
||||
|
||||
if (line.isEmpty())
|
||||
{
|
||||
line = UnicodeString(L" ");
|
||||
}
|
||||
|
||||
GadgetListBoxAddEntryText(listboxInfo, line, GameSpyColor[GSCOLOR_MOTD_HEADING], -1, -1);
|
||||
}
|
||||
GadgetListBoxAddEntryText(listboxInfo, UnicodeString(L" "), GameSpyColor[GSCOLOR_MOTD_HEADING], -1, -1);
|
||||
|
||||
while (aMotd.nextToken(&aLine, "\n"))
|
||||
{
|
||||
if (aLine.getCharAt(aLine.getLength()-1) == '\r')
|
||||
aLine.removeLastChar(); // there is a trailing '\r'
|
||||
|
||||
aLine.trim();
|
||||
|
||||
if (aLine.isEmpty())
|
||||
{
|
||||
aLine = " ";
|
||||
}
|
||||
|
||||
Color c = GameSpyColor[GSCOLOR_MOTD];
|
||||
if (aLine.startsWith("\\\\"))
|
||||
{
|
||||
aLine = aLine.str()+1;
|
||||
}
|
||||
else if (aLine.startsWith("\\") && aLine.getLength() > 9)
|
||||
{
|
||||
// take out the hex value from strings starting as "\ffffffffText"
|
||||
UnsignedByte a, r, g, b;
|
||||
a = grabUByte(aLine.str()+1);
|
||||
r = grabUByte(aLine.str()+3);
|
||||
g = grabUByte(aLine.str()+5);
|
||||
b = grabUByte(aLine.str()+7);
|
||||
c = GameMakeColor(r, g, b, a);
|
||||
DEBUG_LOG(("MOTD line '%s' has color %X\n", aLine.str(), c));
|
||||
aLine = aLine.str() + 9;
|
||||
}
|
||||
line = UnicodeString(MultiByteToWideCharSingleLine(aLine.str()).c_str());
|
||||
|
||||
GadgetListBoxAddEntryText(listboxInfo, line, c, -1, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleNumPlayersOnline( Int numPlayersOnline )
|
||||
{
|
||||
lastNumPlayersOnline = numPlayersOnline;
|
||||
if (lastNumPlayersOnline < 1)
|
||||
lastNumPlayersOnline = 1;
|
||||
updateNumPlayersOnline();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Handle Overall Stats data */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
static OverallStats s_statsUSA, s_statsChina, s_statsGLA;
|
||||
|
||||
OverallStats::OverallStats()
|
||||
{
|
||||
for (Int i=0; i<STATS_MAX; ++i)
|
||||
{
|
||||
wins[i] = losses[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static UnicodeString calcPercent(const OverallStats& stats, Int n, UnicodeString sideStr)
|
||||
{
|
||||
// per side percentage of total wins
|
||||
Real winPercentUSA = s_statsUSA.wins[n]*100/INT_TO_REAL(max(1, s_statsUSA.wins[n]+s_statsUSA.losses[n])); // 0.0f - 100.0f
|
||||
Real winPercentChina = s_statsChina.wins[n]*100/INT_TO_REAL(max(1, s_statsChina.wins[n]+s_statsChina.losses[n])); // 0.0f - 100.0f
|
||||
Real winPercentGLA = s_statsGLA.wins[n]*100/INT_TO_REAL(max(1, s_statsGLA.wins[n]+s_statsGLA.losses[n])); // 0.0f - 100.0f
|
||||
Real thisWinPercent = stats.wins[n]*100/INT_TO_REAL(max(1, stats.wins[n]+stats.losses[n])); // 0.0f - 100.0f
|
||||
Real totalWinPercent = winPercentUSA + winPercentChina + winPercentGLA;
|
||||
|
||||
Real val = thisWinPercent*100/max(1.0f,totalWinPercent);
|
||||
|
||||
UnicodeString s;
|
||||
s.format(TheGameText->fetch("GUI:PerSideWinPercentage"), REAL_TO_INT(val), sideStr.str());
|
||||
|
||||
/*
|
||||
Int totalDenominator = s_statsUSA.wins[n] + s_statsChina.wins[n] + s_statsGLA.wins[n];
|
||||
if (!totalDenominator)
|
||||
totalDenominator = 1;
|
||||
|
||||
UnicodeString s;
|
||||
s.format(TheGameText->fetch("GUI:PerSideWinPercentage"), REAL_TO_INT(stats.wins[n]*100/totalDenominator), sideStr.str());
|
||||
*/
|
||||
return s;
|
||||
}
|
||||
|
||||
static void updateOverallStats(void)
|
||||
{
|
||||
UnicodeString usa, china, gla;
|
||||
GameWindow *win;
|
||||
|
||||
usa = calcPercent(s_statsUSA, STATS_LASTWEEK, TheGameText->fetch("SIDE:America"));
|
||||
china = calcPercent(s_statsChina, STATS_LASTWEEK, TheGameText->fetch("SIDE:China"));
|
||||
gla = calcPercent(s_statsGLA, STATS_LASTWEEK, TheGameText->fetch("SIDE:GLA"));
|
||||
DEBUG_LOG(("Last Week: %ls %ls %ls\n", usa.str(), china.str(), gla.str()));
|
||||
win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextUSALastWeek") );
|
||||
GadgetStaticTextSetText(win, usa);
|
||||
win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextChinaLastWeek") );
|
||||
GadgetStaticTextSetText(win, china);
|
||||
win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextGLALastWeek") );
|
||||
GadgetStaticTextSetText(win, gla);
|
||||
|
||||
usa = calcPercent(s_statsUSA, STATS_TODAY, TheGameText->fetch("SIDE:America"));
|
||||
china = calcPercent(s_statsChina, STATS_TODAY, TheGameText->fetch("SIDE:China"));
|
||||
gla = calcPercent(s_statsGLA, STATS_TODAY, TheGameText->fetch("SIDE:GLA"));
|
||||
DEBUG_LOG(("Today: %ls %ls %ls\n", usa.str(), china.str(), gla.str()));
|
||||
win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextUSAToday") );
|
||||
GadgetStaticTextSetText(win, usa);
|
||||
win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextChinaToday") );
|
||||
GadgetStaticTextSetText(win, china);
|
||||
win = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextGLAToday") );
|
||||
GadgetStaticTextSetText(win, gla);
|
||||
}
|
||||
|
||||
void HandleOverallStats( const OverallStats& USA, const OverallStats& China, const OverallStats& GLA )
|
||||
{
|
||||
s_statsUSA = USA;
|
||||
s_statsChina = China;
|
||||
s_statsGLA = GLA;
|
||||
updateOverallStats();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Handle player stats */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
|
||||
void UpdateLocalPlayerStats(void)
|
||||
{
|
||||
|
||||
GameWindow *welcomeParent = TheWindowManager->winGetWindowFromId( NULL, NAMEKEY("WOLWelcomeMenu.wnd:WOLWelcomeMenuParent") );
|
||||
|
||||
if (welcomeParent)
|
||||
{
|
||||
PopulatePlayerInfoWindows( "WOLWelcomeMenu.wnd" );
|
||||
}
|
||||
else
|
||||
{
|
||||
PopulatePlayerInfoWindows( "WOLQuickMatchMenu.wnd" );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static Bool raiseMessageBoxes = FALSE;
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the WOL Welcome Menu */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLWelcomeMenuInit( WindowLayout *layout, void *userData )
|
||||
{
|
||||
nextScreen = NULL;
|
||||
buttonPushed = FALSE;
|
||||
isShuttingDown = FALSE;
|
||||
|
||||
welcomeLayout = layout;
|
||||
|
||||
//TheWOL->reset();
|
||||
|
||||
parentWOLWelcomeID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:WOLWelcomeMenuParent" ) );
|
||||
buttonBackID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonBack" ) );
|
||||
parentWOLWelcome = TheWindowManager->winGetWindowFromId( NULL, parentWOLWelcomeID );
|
||||
buttonBack = TheWindowManager->winGetWindowFromId( NULL, buttonBackID);
|
||||
buttonOptionsID = TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:ButtonOptions" );
|
||||
buttonbuttonOptions = TheWindowManager->winGetWindowFromId( NULL, buttonOptionsID);
|
||||
listboxInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:InfoListbox" ) );
|
||||
|
||||
listboxInfo = TheWindowManager->winGetWindowFromId( NULL, listboxInfoID);
|
||||
|
||||
staticTextServerName = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextServerName" ));
|
||||
staticTextLastUpdated = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLastUpdated" ));
|
||||
|
||||
staticTextLadderWins = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderWins" ));
|
||||
staticTextLadderLosses = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderLosses" ));
|
||||
staticTextLadderPoints = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderPoints" ));
|
||||
staticTextLadderRank = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextLadderRank" ));
|
||||
staticTextLadderDisconnects = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextDisconnects" ));
|
||||
|
||||
staticTextHighscoreWins = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreWins" ));
|
||||
staticTextHighscoreLosses = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreLosses" ));
|
||||
staticTextHighscorePoints = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscorePoints" ));
|
||||
staticTextHighscoreRank = TheWindowManager->winGetWindowFromId( parentWOLWelcome,
|
||||
TheNameKeyGenerator->nameToKey( "WOLWelcomeMenu.wnd:StaticTextHighscoreRank" ));
|
||||
|
||||
if (staticTextServerName)
|
||||
{
|
||||
GadgetStaticTextSetText(staticTextServerName, gServerName);
|
||||
}
|
||||
|
||||
GameWindow *staticTextTitle = TheWindowManager->winGetWindowFromId(parentWOLWelcome, NAMEKEY("WOLWelcomeMenu.wnd:StaticTextTitle"));
|
||||
if (staticTextTitle && TheGameSpyInfo)
|
||||
{
|
||||
UnicodeString title;
|
||||
title.format(TheGameText->fetch("GUI:WOLWelcome"), TheGameSpyInfo->getLocalBaseName().str());
|
||||
GadgetStaticTextSetText(staticTextTitle, title);
|
||||
}
|
||||
|
||||
// Clear some defaults
|
||||
/*
|
||||
UnicodeString questionMark = UnicodeString(L"?");
|
||||
GadgetStaticTextSetText(staticTextLastUpdated, questionMark);
|
||||
GadgetStaticTextSetText(staticTextLadderWins, questionMark);
|
||||
GadgetStaticTextSetText(staticTextLadderLosses, questionMark);
|
||||
GadgetStaticTextSetText(staticTextLadderPoints, questionMark);
|
||||
GadgetStaticTextSetText(staticTextLadderRank, questionMark);
|
||||
GadgetStaticTextSetText(staticTextLadderDisconnects, questionMark);
|
||||
GadgetStaticTextSetText(staticTextHighscoreWins, questionMark);
|
||||
GadgetStaticTextSetText(staticTextHighscoreLosses, questionMark);
|
||||
GadgetStaticTextSetText(staticTextHighscorePoints, questionMark);
|
||||
GadgetStaticTextSetText(staticTextHighscoreRank, questionMark);
|
||||
*/
|
||||
|
||||
//DEBUG_ASSERTCRASH(listboxInfo, ("No control found!"));
|
||||
|
||||
buttonQuickMatchID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonQuickMatch" ) );
|
||||
buttonQuickMatch = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonQuickMatchID );
|
||||
|
||||
buttonLobbyID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonCustomMatch" ) );
|
||||
buttonLobby = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonLobbyID );
|
||||
|
||||
buttonBuddiesID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonBuddies" ) );
|
||||
buttonBuddies = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonBuddiesID );
|
||||
|
||||
buttonMyInfoID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonMyInfo" ) );
|
||||
buttonMyInfo = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonMyInfoID );
|
||||
|
||||
buttonLadderID = TheNameKeyGenerator->nameToKey( AsciiString( "WOLWelcomeMenu.wnd:ButtonLadder" ) );
|
||||
buttonLadder = TheWindowManager->winGetWindowFromId( parentWOLWelcome, buttonLadderID );
|
||||
|
||||
if (TheFirewallHelper == NULL) {
|
||||
TheFirewallHelper = createFirewallHelper();
|
||||
}
|
||||
if (TheFirewallHelper->detectFirewall() == TRUE) {
|
||||
// don't need to detect firewall, already been done.
|
||||
delete TheFirewallHelper;
|
||||
TheFirewallHelper = NULL;
|
||||
}
|
||||
/*
|
||||
|
||||
if (TheGameSpyChat && TheGameSpyChat->isConnected())
|
||||
{
|
||||
const char *keys[3] = { "locale", "wins", "losses" };
|
||||
char valueStrings[3][20];
|
||||
char *values[3] = { valueStrings[0], valueStrings[1], valueStrings[2] };
|
||||
_snprintf(values[0], 20, "%s", TheGameSpyPlayerInfo->getLocale().str());
|
||||
_snprintf(values[1], 20, "%d", TheGameSpyPlayerInfo->getWins());
|
||||
_snprintf(values[2], 20, "%d", TheGameSpyPlayerInfo->getLosses());
|
||||
peerSetGlobalKeys(TheGameSpyChat->getPeer(), 3, (const char **)keys, (const char **)values);
|
||||
peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), GroupRoom, 3, keys, PEERFalse);
|
||||
peerSetGlobalWatchKeys(TheGameSpyChat->getPeer(), StagingRoom, 3, keys, PEERFalse);
|
||||
}
|
||||
*/
|
||||
|
||||
// // animate controls
|
||||
// TheShell->registerWithAnimateManager(buttonQuickMatch, WIN_ANIMATION_SLIDE_LEFT, TRUE, 800);
|
||||
// TheShell->registerWithAnimateManager(buttonLobby, WIN_ANIMATION_SLIDE_LEFT, TRUE, 600);
|
||||
// //TheShell->registerWithAnimateManager(NULL, WIN_ANIMATION_SLIDE_LEFT, TRUE, 400);
|
||||
// TheShell->registerWithAnimateManager(buttonBuddies, WIN_ANIMATION_SLIDE_LEFT, TRUE, 200);
|
||||
// //TheShell->registerWithAnimateManager(NULL, WIN_ANIMATION_SLIDE_LEFT, TRUE, 1);
|
||||
// TheShell->registerWithAnimateManager(buttonBack, WIN_ANIMATION_SLIDE_BOTTOM, TRUE, 1);
|
||||
|
||||
// Show Menu
|
||||
layout->hide( FALSE );
|
||||
|
||||
// Set Keyboard to Main Parent
|
||||
TheWindowManager->winSetFocus( parentWOLWelcome );
|
||||
|
||||
enableControls( TheGameSpyInfo->gotGroupRoomList() );
|
||||
TheShell->showShellMap(TRUE);
|
||||
|
||||
updateNumPlayersOnline();
|
||||
updateOverallStats();
|
||||
|
||||
UpdateLocalPlayerStats();
|
||||
|
||||
GameSpyMiscPreferences cPref;
|
||||
if (cPref.getLocale() < LOC_MIN || cPref.getLocale() > LOC_MAX)
|
||||
{
|
||||
GameSpyOpenOverlay(GSOVERLAY_LOCALESELECT);
|
||||
}
|
||||
|
||||
raiseMessageBoxes = TRUE;
|
||||
TheTransitionHandler->setGroup("WOLWelcomeMenuFade");
|
||||
|
||||
} // WOLWelcomeMenuInit
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Welcome Menu shutdown method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLWelcomeMenuShutdown( WindowLayout *layout, void *userData )
|
||||
{
|
||||
listboxInfo = NULL;
|
||||
|
||||
if (TheFirewallHelper != NULL) {
|
||||
delete TheFirewallHelper;
|
||||
TheFirewallHelper = NULL;
|
||||
}
|
||||
|
||||
isShuttingDown = TRUE;
|
||||
|
||||
// if we are shutting down for an immediate pop, skip the animations
|
||||
Bool popImmediate = *(Bool *)userData;
|
||||
if( popImmediate )
|
||||
{
|
||||
|
||||
shutdownComplete( layout );
|
||||
return;
|
||||
|
||||
} //end if
|
||||
|
||||
TheShell->reverseAnimatewindow();
|
||||
TheTransitionHandler->reverse("WOLWelcomeMenuFade");
|
||||
|
||||
|
||||
RaiseGSMessageBox();
|
||||
} // WOLWelcomeMenuShutdown
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Welcome Menu update method */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WOLWelcomeMenuUpdate( WindowLayout * layout, void *userData)
|
||||
{
|
||||
// We'll only be successful if we've requested to
|
||||
if(isShuttingDown && TheShell->isAnimFinished() && TheTransitionHandler->isFinished())
|
||||
shutdownComplete(layout);
|
||||
|
||||
if (raiseMessageBoxes)
|
||||
{
|
||||
RaiseGSMessageBox();
|
||||
raiseMessageBoxes = FALSE;
|
||||
}
|
||||
|
||||
if (TheFirewallHelper != NULL)
|
||||
{
|
||||
if (TheFirewallHelper->behaviorDetectionUpdate())
|
||||
{
|
||||
TheWritableGlobalData->m_firewallBehavior = TheFirewallHelper->getFirewallBehavior();
|
||||
|
||||
TheFirewallHelper->writeFirewallBehavior();
|
||||
|
||||
TheFirewallHelper->flagNeedToRefresh(FALSE); // 2/19/03 BGC, we're done, so we don't need to refresh the NAT anymore.
|
||||
|
||||
// we are now done with the firewall helper
|
||||
delete TheFirewallHelper;
|
||||
TheFirewallHelper = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (TheShell->isAnimFinished() && !buttonPushed && TheGameSpyPeerMessageQueue)
|
||||
{
|
||||
HandleBuddyResponses();
|
||||
HandlePersistentStorageResponses();
|
||||
|
||||
Int allowedMessages = TheGameSpyInfo->getMaxMessagesPerUpdate();
|
||||
Bool sawImportantMessage = FALSE;
|
||||
PeerResponse resp;
|
||||
while (allowedMessages-- && !sawImportantMessage && TheGameSpyPeerMessageQueue->getResponse( resp ))
|
||||
{
|
||||
switch (resp.peerResponseType)
|
||||
{
|
||||
case PeerResponse::PEERRESPONSE_GROUPROOM:
|
||||
{
|
||||
GameSpyGroupRoom room;
|
||||
room.m_groupID = resp.groupRoom.id;
|
||||
room.m_maxWaiting = resp.groupRoom.maxWaiting;
|
||||
room.m_name = resp.groupRoomName.c_str();
|
||||
room.m_translatedName = UnicodeString(L"TEST");
|
||||
room.m_numGames = resp.groupRoom.numGames;
|
||||
room.m_numPlaying = resp.groupRoom.numPlaying;
|
||||
room.m_numWaiting = resp.groupRoom.numWaiting;
|
||||
TheGameSpyInfo->addGroupRoom( room );
|
||||
if (room.m_groupID == 0)
|
||||
{
|
||||
enableControls( TRUE );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PeerResponse::PEERRESPONSE_JOINGROUPROOM:
|
||||
{
|
||||
sawImportantMessage = TRUE;
|
||||
enableControls( TRUE );
|
||||
if (resp.joinGroupRoom.ok)
|
||||
{
|
||||
//buttonPushed = TRUE;
|
||||
TheGameSpyInfo->setCurrentGroupRoom(resp.joinGroupRoom.id);
|
||||
//GSMessageBoxOk( TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSGroupRoomJoinOK") );
|
||||
|
||||
buttonPushed = TRUE;
|
||||
nextScreen = "Menus/WOLCustomLobby.wnd";
|
||||
TheShell->pop();
|
||||
//TheShell->push( "Menus/WOLCustomLobby.wnd" );
|
||||
}
|
||||
else
|
||||
{
|
||||
GSMessageBoxOk( TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:GSGroupRoomJoinFail") );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PeerResponse::PEERRESPONSE_DISCONNECT:
|
||||
{
|
||||
sawImportantMessage = TRUE;
|
||||
UnicodeString title, body;
|
||||
AsciiString disconMunkee;
|
||||
disconMunkee.format("GUI:GSDisconReason%d", resp.discon.reason);
|
||||
title = TheGameText->fetch( "GUI:GSErrorTitle" );
|
||||
body = TheGameText->fetch( disconMunkee );
|
||||
GameSpyCloseAllOverlays();
|
||||
GSMessageBoxOk( title, body );
|
||||
TheShell->pop();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}// WOLWelcomeMenuUpdate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Welcome Menu input callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLWelcomeMenuInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
UnsignedByte key = mData1;
|
||||
UnsignedByte state = mData2;
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
switch( key )
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
case KEY_ESC:
|
||||
{
|
||||
|
||||
//
|
||||
// send a simulated selected event to the parent window of the
|
||||
// back/exit button
|
||||
//
|
||||
if( BitTest( state, KEY_STATE_UP ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window, GBM_SELECTED,
|
||||
(WindowMsgData)buttonBack, buttonBackID );
|
||||
|
||||
} // end if
|
||||
|
||||
// don't let key fall through anywhere else
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end escape
|
||||
|
||||
} // end switch( key )
|
||||
|
||||
} // end char
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_IGNORED;
|
||||
}// WOLWelcomeMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** WOL Welcome Menu window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType WOLWelcomeMenuSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
UnicodeString txtInput;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
|
||||
case GWM_CREATE:
|
||||
{
|
||||
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
break;
|
||||
} // case GWM_DESTROY:
|
||||
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
return MSG_HANDLED;
|
||||
}//case GWM_INPUT_FOCUS:
|
||||
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
if (buttonPushed)
|
||||
break;
|
||||
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
|
||||
if ( controlID == buttonBackID )
|
||||
{
|
||||
//DEBUG_ASSERTCRASH(TheGameSpyChat->getPeer(), ("No GameSpy Peer object!"));
|
||||
//TheGameSpyChat->disconnectFromChat();
|
||||
|
||||
PeerRequest req;
|
||||
req.peerRequestType = PeerRequest::PEERREQUEST_LOGOUT;
|
||||
TheGameSpyPeerMessageQueue->addRequest( req );
|
||||
BuddyRequest breq;
|
||||
breq.buddyRequestType = BuddyRequest::BUDDYREQUEST_LOGOUT;
|
||||
TheGameSpyBuddyMessageQueue->addRequest( breq );
|
||||
|
||||
DEBUG_LOG(("Tearing down GameSpy from WOLWelcomeMenuSystem(GBM_SELECTED)\n"));
|
||||
TearDownGameSpy();
|
||||
|
||||
/*
|
||||
if (TheGameSpyChat->getPeer())
|
||||
{
|
||||
peerDisconnect(TheGameSpyChat->getPeer());
|
||||
}
|
||||
*/
|
||||
|
||||
buttonPushed = TRUE;
|
||||
|
||||
TheShell->pop();
|
||||
|
||||
/// @todo: log out instead of disconnecting
|
||||
//TheWOL->addCommand( WOL::WOLCOMMAND_LOGOUT );
|
||||
/**
|
||||
closeAllOverlays();
|
||||
TheShell->pop();
|
||||
delete TheWOL;
|
||||
TheWOL = NULL;
|
||||
delete TheWOLGame;
|
||||
TheWOLGame = NULL;
|
||||
**/
|
||||
|
||||
} //if ( controlID == buttonBack )
|
||||
else if (controlID == buttonOptionsID)
|
||||
{
|
||||
GameSpyOpenOverlay( GSOVERLAY_OPTIONS );
|
||||
}
|
||||
else if (controlID == buttonQuickMatchID)
|
||||
{
|
||||
GameSpyMiscPreferences mPref;
|
||||
if ((TheDisplay->getWidth() != 800 || TheDisplay->getHeight() != 600) && mPref.getQuickMatchResLocked())
|
||||
{
|
||||
GSMessageBoxOk(TheGameText->fetch("GUI:GSErrorTitle"), TheGameText->fetch("GUI:QuickMatch800x600"));
|
||||
}
|
||||
else
|
||||
{
|
||||
buttonPushed = TRUE;
|
||||
nextScreen = "Menus/WOLQuickMatchMenu.wnd";
|
||||
TheShell->pop();
|
||||
}
|
||||
}// else if
|
||||
else if (controlID == buttonMyInfoID )
|
||||
{
|
||||
SetLookAtPlayer(TheGameSpyInfo->getLocalProfileID(), TheGameSpyInfo->getLocalName());
|
||||
GameSpyToggleOverlay(GSOVERLAY_PLAYERINFO);
|
||||
}
|
||||
else if (controlID == buttonLobbyID)
|
||||
{
|
||||
//TheGameSpyChat->clearGroupRoomList();
|
||||
//peerListGroupRooms(TheGameSpyChat->getPeer(), ListGroupRoomsCallback, NULL, PEERTrue);
|
||||
TheGameSpyInfo->joinBestGroupRoom();
|
||||
enableControls( FALSE );
|
||||
|
||||
|
||||
/*
|
||||
TheWOL->setScreen(WOL::WOLAPI_MENU_CUSTOMLOBBY);
|
||||
TheWOL->setGameMode(WOL::WOLTYPE_CUSTOM);
|
||||
TheWOL->setState( WOL::WOLAPI_LOBBY );
|
||||
TheWOL->addCommand( WOL::WOLCOMMAND_REFRESH_CHANNELS );
|
||||
*/
|
||||
}// else if
|
||||
else if (controlID == buttonBuddiesID)
|
||||
{
|
||||
GameSpyToggleOverlay( GSOVERLAY_BUDDY );
|
||||
/*
|
||||
Bool joinedRoom = FALSE;
|
||||
ClearGroupRoomList();
|
||||
peerJoinTitleRoom(TheGameSpyChat->getPeer(), JoinRoomCallback, &joinedRoom, PEERTrue);
|
||||
if (joinedRoom)
|
||||
{
|
||||
GameSpyUsingGroupRooms = FALSE;
|
||||
GameSpyCurrentGroupRoomID = 0;
|
||||
TheShell->pop();
|
||||
TheShell->push("Menus/WOLCustomLobby.wnd");
|
||||
}
|
||||
else
|
||||
{
|
||||
GameSpyCurrentGroupRoomID = 0;
|
||||
GSMessageBoxOk(UnicodeString(L"Oops"), UnicodeString(L"Unable to join title room"), NULL);
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (controlID == buttonLadderID)
|
||||
{
|
||||
TheShell->push(AsciiString("Menus/WOLLadderScreen.wnd"));
|
||||
}
|
||||
break;
|
||||
}// case GBM_SELECTED:
|
||||
|
||||
case GEM_EDIT_DONE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}//Switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
}// WOLWelcomeMenuSystem
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
** 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: MessageBox.cpp /////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: MessageBox.cpp
|
||||
//
|
||||
// Created: Chris Huybregts, June 2001
|
||||
//
|
||||
// Desc: the Message Box control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/GameEngine.h"
|
||||
#include "Common/NameKeyGenerator.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/KeyDefs.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/MessageBox.h"
|
||||
|
||||
|
||||
GameWindow *MessageBoxYesNo(UnicodeString titleString,UnicodeString bodyString,GameWinMsgBoxFunc yesCallback,GameWinMsgBoxFunc noCallback) ///< convenience function for displaying a Message box with Yes and No buttons
|
||||
{
|
||||
return TheWindowManager->gogoMessageBox(-1,-1,-1,-1,MSG_BOX_NO | MSG_BOX_YES , titleString, bodyString, yesCallback, noCallback, NULL, NULL);
|
||||
}
|
||||
GameWindow *QuitMessageBoxYesNo(UnicodeString titleString,UnicodeString bodyString,GameWinMsgBoxFunc yesCallback,GameWinMsgBoxFunc noCallback) ///< convenience function for displaying a Message box with Yes and No buttons
|
||||
{
|
||||
return TheWindowManager->gogoMessageBox(-1,-1,-1,-1,MSG_BOX_NO | MSG_BOX_YES , titleString, bodyString, yesCallback, noCallback, NULL, NULL, TRUE);
|
||||
}
|
||||
|
||||
|
||||
GameWindow *MessageBoxYesNoCancel(UnicodeString titleString,UnicodeString bodyString, GameWinMsgBoxFunc yesCallback, GameWinMsgBoxFunc noCallback, GameWinMsgBoxFunc cancelCallback)///< convenience function for displaying a Message box with Yes,No and Cancel buttons
|
||||
{
|
||||
return TheWindowManager->gogoMessageBox(-1,-1,-1,-1,MSG_BOX_NO | MSG_BOX_YES | MSG_BOX_CANCEL , titleString, bodyString, yesCallback, noCallback, NULL, cancelCallback);
|
||||
}
|
||||
|
||||
|
||||
GameWindow *MessageBoxOkCancel(UnicodeString titleString,UnicodeString bodyString,GameWinMsgBoxFunc okCallback,GameWinMsgBoxFunc cancelCallback)///< convenience function for displaying a Message box with Ok and Cancel buttons
|
||||
{
|
||||
return TheWindowManager->gogoMessageBox(-1,-1,-1,-1,MSG_BOX_OK | MSG_BOX_CANCEL , titleString, bodyString, NULL, NULL, okCallback, cancelCallback);
|
||||
}
|
||||
|
||||
GameWindow *MessageBoxOk(UnicodeString titleString,UnicodeString bodyString,GameWinMsgBoxFunc okCallback)///< convenience function for displaying a Message box with Ok button
|
||||
{
|
||||
return TheWindowManager->gogoMessageBox(-1,-1,-1,-1,MSG_BOX_OK, titleString, bodyString, NULL, NULL, okCallback, NULL);
|
||||
}
|
||||
|
||||
|
||||
GameWindow *MessageBoxCancel(UnicodeString titleString,UnicodeString bodyString,GameWinMsgBoxFunc cancelCallback)///< convenience function for displaying a Message box with Cancel button
|
||||
{
|
||||
return TheWindowManager->gogoMessageBox(-1,-1,-1,-1, MSG_BOX_CANCEL, titleString, bodyString, NULL, NULL, NULL, cancelCallback);
|
||||
}
|
||||
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Message Box window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType MessageBoxSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
delete (WindowMessageBoxData *)window->winGetUserData();
|
||||
window->winSetUserData( NULL );
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
static NameKeyType buttonOkID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonOk" ) );
|
||||
static NameKeyType buttonYesID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonYes" ) );
|
||||
static NameKeyType buttonNoID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonNo" ) );
|
||||
static NameKeyType buttonCancelID = TheNameKeyGenerator->nameToKey( AsciiString( "MessageBox.wnd:ButtonCancel" ) );
|
||||
WindowMessageBoxData *MsgBoxCallbacks = (WindowMessageBoxData *)window->winGetUserData();
|
||||
|
||||
if( controlID == buttonOkID )
|
||||
{
|
||||
//simple enough,if we have a callback, call it, if not, then just destroy the window
|
||||
if (MsgBoxCallbacks->okCallback)
|
||||
MsgBoxCallbacks->okCallback();
|
||||
|
||||
TheWindowManager->winDestroy(window);
|
||||
|
||||
} // end if
|
||||
else if( controlID == buttonYesID )
|
||||
{
|
||||
if (MsgBoxCallbacks->yesCallback)
|
||||
MsgBoxCallbacks->yesCallback();
|
||||
TheWindowManager->winDestroy(window);
|
||||
} // end else if
|
||||
else if( controlID == buttonNoID )
|
||||
{
|
||||
if (MsgBoxCallbacks->noCallback)
|
||||
MsgBoxCallbacks->noCallback();
|
||||
TheWindowManager->winDestroy(window);
|
||||
} // end else if
|
||||
else if( controlID == buttonCancelID )
|
||||
{
|
||||
if (MsgBoxCallbacks->cancelCallback)
|
||||
MsgBoxCallbacks->cancelCallback();
|
||||
TheWindowManager->winDestroy(window);
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end MessageBoxSystem
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Message Box window system callback */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType QuitMessageBoxSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
delete (WindowMessageBoxData *)window->winGetUserData();
|
||||
window->winSetUserData( NULL );
|
||||
break;
|
||||
|
||||
} // end case
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// if we're givin the opportunity to take the keyboard focus we must say we want it
|
||||
if( mData1 == TRUE )
|
||||
*(Bool *)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
} // end input
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
GameWindow *control = (GameWindow *)mData1;
|
||||
Int controlID = control->winGetWindowId();
|
||||
static NameKeyType buttonOkID = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMessageBox.wnd:ButtonOk" ) );
|
||||
static NameKeyType buttonYesID = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMessageBox.wnd:ButtonYes" ) );
|
||||
static NameKeyType buttonNoID = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMessageBox.wnd:ButtonNo" ) );
|
||||
static NameKeyType buttonCancelID = TheNameKeyGenerator->nameToKey( AsciiString( "QuitMessageBox.wnd:ButtonCancel" ) );
|
||||
WindowMessageBoxData *MsgBoxCallbacks = (WindowMessageBoxData *)window->winGetUserData();
|
||||
|
||||
if( controlID == buttonOkID )
|
||||
{
|
||||
//simple enough,if we have a callback, call it, if not, then just destroy the window
|
||||
if (MsgBoxCallbacks->okCallback)
|
||||
MsgBoxCallbacks->okCallback();
|
||||
|
||||
TheWindowManager->winDestroy(window);
|
||||
|
||||
} // end if
|
||||
else if( controlID == buttonYesID )
|
||||
{
|
||||
if (MsgBoxCallbacks->yesCallback)
|
||||
MsgBoxCallbacks->yesCallback();
|
||||
TheWindowManager->winDestroy(window);
|
||||
} // end else if
|
||||
else if( controlID == buttonNoID )
|
||||
{
|
||||
if (MsgBoxCallbacks->noCallback)
|
||||
MsgBoxCallbacks->noCallback();
|
||||
TheWindowManager->winDestroy(window);
|
||||
} // end else if
|
||||
else if( controlID == buttonCancelID )
|
||||
{
|
||||
if (MsgBoxCallbacks->cancelCallback)
|
||||
MsgBoxCallbacks->cancelCallback();
|
||||
TheWindowManager->winDestroy(window);
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end MessageBoxSystem
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
** 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: ReplayControls.cpp ///////////////////////////////////////////////////////////////////////
|
||||
// Author: Bryan Cleveland - December 2001
|
||||
// Desc: GUI Control box for the playback controls
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameClient.h"
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Input procedure for the control bar */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType ReplayControlInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end MapSelectMenuInput
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** System callback for the control bar parent */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowMsgHandledType ReplayControlSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end button selected
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end ControlBarSystem
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
** 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: CheckBox.cpp /////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: CheckBox.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: Checkbox GUI control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/Keyboard.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GadgetCheckBoxInput ========================================================
|
||||
/** Handle input for check box */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetCheckBoxInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_ENTERING:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_MOUSE_ENTERING,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
//TheWindowManager->winSetFocus( window );
|
||||
|
||||
} // end if
|
||||
break;
|
||||
|
||||
} // end mouse entering
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_LEAVING:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_MOUSE_LEAVING,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
} // end if
|
||||
break;
|
||||
|
||||
} // end mouse leaving
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DRAG:
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(), GGM_LEFT_DRAG,
|
||||
(WindowMsgData)window, mData1 );
|
||||
break;
|
||||
|
||||
} // end left drag
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DOWN:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end left down
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_UP:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getState(), WIN_STATE_HILITED ) == FALSE )
|
||||
{
|
||||
// this up click was not meant for this button
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
|
||||
// Toggle the check state
|
||||
instData->m_state ^= WIN_STATE_SELECTED;
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(), GBM_SELECTED,
|
||||
(WindowMsgData)window, mData1 );
|
||||
|
||||
|
||||
break;
|
||||
|
||||
} // end left up and left click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_RIGHT_DOWN:
|
||||
{
|
||||
|
||||
break;
|
||||
} // end right down
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
case GWM_RIGHT_UP:
|
||||
{
|
||||
// Need to be specially marked to care about right mouse events
|
||||
if( BitTest( instData->getState(), WIN_STATE_SELECTED ) )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GBM_SELECTED_RIGHT,
|
||||
(WindowMsgData)window, mData1 );
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
}
|
||||
else
|
||||
{
|
||||
// this up click was not meant for this button
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
break;
|
||||
} // end right up or right click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
|
||||
switch( mData1 )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_ENTER:
|
||||
case KEY_SPACE:
|
||||
{
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
// Toggle the check state
|
||||
instData->m_state ^= WIN_STATE_SELECTED;
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_SELECTED,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
} //end if
|
||||
break;
|
||||
|
||||
} // end enter/space
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_DOWN:
|
||||
case KEY_RIGHT:
|
||||
case KEY_TAB:
|
||||
{
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
TheWindowManager->winNextTab(window);
|
||||
break;
|
||||
|
||||
} // end down, right, tab
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_UP:
|
||||
case KEY_LEFT:
|
||||
{
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
TheWindowManager->winPrevTab(window);
|
||||
break;
|
||||
|
||||
} // end up, left
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
default:
|
||||
{
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end default
|
||||
|
||||
} // end switch
|
||||
|
||||
break;
|
||||
|
||||
} // end char msg
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
{
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end default
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetCheckBoxInput
|
||||
|
||||
// GadgetCheckBoxSystem =======================================================
|
||||
/** Handle system messages for check box */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetCheckBoxSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_SET_LABEL:
|
||||
{
|
||||
window->winSetText( *(UnicodeString*)mData1 );
|
||||
break;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
|
||||
if( mData1 == FALSE )
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
else
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GGM_FOCUS_CHANGE,
|
||||
mData1,
|
||||
window->winGetWindowId() );
|
||||
if( mData1 == FALSE )
|
||||
*(Bool*)mData2 = FALSE;
|
||||
else
|
||||
*(Bool*)mData2 = TRUE;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch msg
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetCheckBoxSystem
|
||||
|
||||
// GadgetCheckBoxSetText ======================================================
|
||||
/** Set the text for the control */
|
||||
//=============================================================================
|
||||
void GadgetCheckBoxSetText( GameWindow *g, UnicodeString text )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
TheWindowManager->winSendSystemMsg( g, GGM_SET_LABEL, (WindowMsgData)&text, 0 );
|
||||
|
||||
} // end GadgetCheckBoxSetText
|
||||
|
||||
// GadgetCheckBoxSetChecked ============================================
|
||||
//=============================================================================
|
||||
/** Set the check state for the check box */
|
||||
//=============================================================================
|
||||
void GadgetCheckBoxSetChecked( GameWindow *g, Bool isChecked)
|
||||
{
|
||||
WinInstanceData *instData = g->winGetInstanceData();
|
||||
if (isChecked)
|
||||
{
|
||||
BitSet(instData->m_state, WIN_STATE_SELECTED);
|
||||
}
|
||||
else
|
||||
{
|
||||
BitClear(instData->m_state, WIN_STATE_SELECTED);
|
||||
}
|
||||
|
||||
TheWindowManager->winSendSystemMsg( g->winGetOwner(), GBM_SELECTED,
|
||||
(WindowMsgData)g, 0 );
|
||||
|
||||
}
|
||||
// GadgetCheckBoxIsChecked ======================================================
|
||||
/** Check the check state */
|
||||
//=============================================================================
|
||||
Bool GadgetCheckBoxIsChecked( GameWindow *g )
|
||||
{
|
||||
WinInstanceData *instData = g->winGetInstanceData();
|
||||
return (BitTest(instData->m_state, WIN_STATE_SELECTED));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
** 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: HorizontalSlider.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: HorizontalSlider.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: Horizontal GUI slider
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "Gameclient/GameWindowManager.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetSlider.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// GadgetHorizontalSliderInput ================================================
|
||||
/** Handle input for horizontal slider */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetHorizontalSliderInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
SliderData *s = (SliderData *)window->winGetUserData();
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
ICoord2D size, childSize, childCenter;
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
switch( msg )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_ENTERING:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_MOUSE_ENTERING,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
//TheWindowManager->winSetFocus( window );
|
||||
|
||||
} // end if
|
||||
|
||||
if(window->winGetChild() && BitTest(window->winGetChild()->winGetStyle(),GWS_PUSH_BUTTON) )
|
||||
{
|
||||
WinInstanceData *instDataChild = window->winGetChild()->winGetInstanceData();
|
||||
BitSet(instDataChild->m_state, WIN_STATE_HILITED);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end mouse entering
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_LEAVING:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ))
|
||||
{
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_MOUSE_LEAVING,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
} // end if
|
||||
if(window->winGetChild() && BitTest(window->winGetChild()->winGetStyle(),GWS_PUSH_BUTTON) )
|
||||
{
|
||||
WinInstanceData *instDataChild = window->winGetChild()->winGetInstanceData();
|
||||
BitClear(instDataChild->m_state, WIN_STATE_HILITED);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end mouse leaving
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DRAG:
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GGM_LEFT_DRAG,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DOWN:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_UP:
|
||||
{
|
||||
Int x, y;
|
||||
Int mousex = mData1 & 0xFFFF;
|
||||
// Int mousey = mData1 >> 16;
|
||||
|
||||
GameWindow *child = window->winGetChild();
|
||||
Int pageClickSize, clickPos;
|
||||
|
||||
window->winGetScreenPosition( &x, &y );
|
||||
|
||||
child->winGetSize( &childSize.x, &childSize.y );
|
||||
child->winGetPosition( &childCenter.x, &childCenter.y );
|
||||
childCenter.x += childSize.x / 2;
|
||||
childCenter.y += childSize.y / 2;
|
||||
|
||||
//
|
||||
// when you click on the slider, but not the button, we will jump
|
||||
// the slider position up/down by this much
|
||||
//
|
||||
pageClickSize = size.x / 5;
|
||||
|
||||
clickPos = mousex - x;
|
||||
if( clickPos >= childCenter.x )
|
||||
{
|
||||
|
||||
clickPos = childCenter.x + pageClickSize;
|
||||
if( clickPos > mousex - x )
|
||||
clickPos = mousex - x;
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
clickPos = childCenter.x - pageClickSize;
|
||||
if( clickPos < mousex - x )
|
||||
clickPos = mousex - x;
|
||||
|
||||
} // end else
|
||||
|
||||
// keep it all valid to the window
|
||||
if( clickPos > x + size.x - childSize.x / 2 )
|
||||
clickPos = x + size.y - childSize.x / 2;
|
||||
if( clickPos < childSize.x / 2 )
|
||||
clickPos = childSize.x / 2;
|
||||
|
||||
child->winSetPosition( clickPos - childSize.x / 2, HORIZONTAL_SLIDER_THUMB_POSITION);
|
||||
TheWindowManager->winSendSystemMsg( window, GGM_LEFT_DRAG, 0, mData1 );
|
||||
break;
|
||||
|
||||
} // end left up, left click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
|
||||
switch( mData1 )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_RIGHT:
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
|
||||
if( s->position > s->minVal + 1 )
|
||||
{
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
s->position -= 2;
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
|
||||
// Translate to window coords
|
||||
child->winSetPosition( (Int)((s->position - s->minVal) * s->numTicks), HORIZONTAL_SLIDER_THUMB_POSITION );
|
||||
|
||||
} // end if
|
||||
|
||||
} // if key down
|
||||
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_LEFT:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
|
||||
if( s->position < s->maxVal - 1 )
|
||||
{
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
s->position += 2;
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
|
||||
// Translate to window coords
|
||||
child->winSetPosition( (Int)((s->position - s->minVal) * s->numTicks),HORIZONTAL_SLIDER_THUMB_POSITION );
|
||||
|
||||
}
|
||||
|
||||
} // end if key down
|
||||
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_DOWN:
|
||||
case KEY_TAB:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
window->winNextTab();
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_UP:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
window->winPrevTab();
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( mData1 )
|
||||
|
||||
break;
|
||||
|
||||
} // end char
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetHorizontalSliderInput
|
||||
|
||||
// GadgetHorizontalSliderSystem ===============================================
|
||||
/** Handle system messages for horizontal slider */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetHorizontalSliderSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
SliderData *s = (SliderData *)window->winGetUserData();
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
ICoord2D size, childSize, childCenter,childRelativePos;
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
switch( msg )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_LEFT_DRAG:
|
||||
{
|
||||
Int mousex = mData2 & 0xFFFF;
|
||||
// Int mousey = mData2 >> 16;
|
||||
Int x, y, delta;
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
|
||||
window->winGetScreenPosition( &x, &y );
|
||||
|
||||
child->winGetSize( &childSize.x, &childSize.y );
|
||||
child->winGetScreenPosition( &childCenter.x, &childCenter.y );
|
||||
child->winGetPosition(&childRelativePos.x, &childRelativePos.y);
|
||||
childCenter.x += childSize.x / 2;
|
||||
childCenter.y += childSize.y / 2;
|
||||
|
||||
//
|
||||
// ignore drag attempts when the mouse is right or left of slider totally
|
||||
// and put the dragging thumb back at the slider pos
|
||||
//
|
||||
if( mousex > x + size.x -HORIZONTAL_SLIDER_THUMB_WIDTH/2 )
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GSM_SET_SLIDER,
|
||||
s->maxVal, 0 );
|
||||
// tell owner i moved
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
break;
|
||||
|
||||
} // end if
|
||||
else if( mousex < x + HORIZONTAL_SLIDER_THUMB_WIDTH/2)
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window, GSM_SET_SLIDER,
|
||||
s->minVal, 0 );
|
||||
// tell owner i moved
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
break;
|
||||
|
||||
} // end else if
|
||||
|
||||
if( childCenter.x < x + childSize.x / 2 )
|
||||
{
|
||||
child->winSetPosition( 0,HORIZONTAL_SLIDER_THUMB_POSITION );
|
||||
s->position = s->minVal;
|
||||
|
||||
}
|
||||
else if( childCenter.x >= x + size.x - childSize.x / 2 )
|
||||
{
|
||||
child->winSetPosition( (Int)((s->maxVal - s->minVal) * s->numTicks) -HORIZONTAL_SLIDER_THUMB_WIDTH/2 , HORIZONTAL_SLIDER_THUMB_POSITION );
|
||||
s->position = s->maxVal;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = childCenter.x - x -HORIZONTAL_SLIDER_THUMB_WIDTH/2;
|
||||
|
||||
// Calc slider position
|
||||
s->position = (Int)((delta) / s->numTicks)+ s->minVal ;
|
||||
|
||||
/*
|
||||
s->position += s->minVal;
|
||||
*/
|
||||
|
||||
if( s->position > s->maxVal )
|
||||
s->position = s->maxVal;
|
||||
if( s->position < s->minVal)
|
||||
s->position = s->minVal;
|
||||
|
||||
child->winSetPosition( childRelativePos.x, HORIZONTAL_SLIDER_THUMB_POSITION );
|
||||
}
|
||||
|
||||
// tell owner i moved
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
|
||||
break;
|
||||
|
||||
} // end left drag
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GSM_SET_SLIDER:
|
||||
{
|
||||
Int newPos = (Int)mData1;
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
if( newPos < s->minVal || newPos > s->maxVal )
|
||||
break;
|
||||
|
||||
s->position = newPos;
|
||||
|
||||
// Translate to window coords
|
||||
newPos = (Int)((newPos - s->minVal) * s->numTicks);
|
||||
|
||||
child->winSetPosition( newPos , HORIZONTAL_SLIDER_THUMB_POSITION );
|
||||
break;
|
||||
|
||||
} // end set slider
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GSM_SET_MIN_MAX:
|
||||
{
|
||||
ICoord2D size;
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
|
||||
s->minVal = (Int)mData1;
|
||||
s->maxVal = (Int)mData2;
|
||||
s->numTicks = (Real)(size.x - HORIZONTAL_SLIDER_THUMB_WIDTH)/(Real)(s->maxVal - s->minVal);
|
||||
s->position = s->minVal;
|
||||
|
||||
child->winSetPosition( 0, HORIZONTAL_SLIDER_THUMB_POSITION );
|
||||
break;
|
||||
|
||||
} // end set min max
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
delete ( (SliderData *)window->winGetUserData() );
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
// If we're losing focus
|
||||
if( mData1 == FALSE )
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
else
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GGM_FOCUS_CHANGE,
|
||||
mData1,
|
||||
window->winGetWindowId() );
|
||||
|
||||
*(Bool*)mData2 = TRUE;
|
||||
break;
|
||||
|
||||
} // end focus msg
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_RESIZED:
|
||||
{
|
||||
// Int width = (Int)mData1;
|
||||
Int height = (Int)mData2;
|
||||
GameWindow *thumb = window->winGetChild();
|
||||
|
||||
if( thumb )
|
||||
thumb->winSetSize( GADGET_SIZE, height );
|
||||
|
||||
break;
|
||||
|
||||
} // end resized
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetHorizontalSliderSystem
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
** 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: ProgressBar.cpp //////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: ProgressBar.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: Progress bar GUI control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
|
||||
// GadgetProgressBarSystem ====================================================
|
||||
/** Handle system messages for Progress Bar */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetProgressBarSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GPM_SET_PROGRESS:
|
||||
{
|
||||
Int newPos = (Int)mData1;
|
||||
|
||||
if (newPos < 0 || newPos > 100)
|
||||
break;
|
||||
|
||||
window->winSetUserData( (void *)newPos );
|
||||
|
||||
break;
|
||||
|
||||
} // end set progress
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetProgressBarSystem
|
||||
|
||||
// GadgetProgressBarSetProgress ===============================================
|
||||
/** send progress system message to Progress Bar */
|
||||
//=============================================================================
|
||||
void GadgetProgressBarSetProgress( GameWindow *g, Int progress )
|
||||
{
|
||||
if(!g)
|
||||
return;
|
||||
|
||||
TheWindowManager->winSendSystemMsg( g, GPM_SET_PROGRESS, progress, 0);
|
||||
} // end GadgetProgressBarSetProgress
|
||||
@@ -0,0 +1,711 @@
|
||||
/*
|
||||
** 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: GadgetPushButton.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: PushButton.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: Pushbutton GUI gadget control callbacks
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/AudioEventRTS.h"
|
||||
#include "Common/Language.h"
|
||||
#include "Common/GameAudio.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/InGameUI.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
// GadgetPushButtonInput ======================================================
|
||||
/** Handle input for push button */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetPushButtonInput( GameWindow *window,
|
||||
UnsignedInt msg,
|
||||
WindowMsgData mData1,
|
||||
WindowMsgData mData2 )
|
||||
{
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_ENTERING:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(),
|
||||
GBM_MOUSE_ENTERING,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
|
||||
//TheWindowManager->winSetFocus( window );
|
||||
}
|
||||
if(window->winGetParent() && BitTest(window->winGetParent()->winGetStyle(),GWS_HORZ_SLIDER) )
|
||||
{
|
||||
WinInstanceData *instDataParent = window->winGetParent()->winGetInstanceData();
|
||||
BitSet(instDataParent->m_state, WIN_STATE_HILITED);
|
||||
}
|
||||
break;
|
||||
|
||||
} // end mouse entering
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_LEAVING:
|
||||
{
|
||||
|
||||
if(BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(),
|
||||
GBM_MOUSE_LEAVING,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
}
|
||||
|
||||
//
|
||||
// if this is not a check-like button, clear any selected state when the
|
||||
// move leaves the window area
|
||||
//
|
||||
if( BitTest( window->winGetStatus(), WIN_STATUS_CHECK_LIKE ) == FALSE )
|
||||
if( BitTest( instData->getState(), WIN_STATE_SELECTED ) )
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
//TheWindowManager->winSetFocus( NULL );
|
||||
if(window->winGetParent() && BitTest(window->winGetParent()->winGetStyle(),GWS_HORZ_SLIDER) )
|
||||
{
|
||||
WinInstanceData *instDataParent = window->winGetParent()->winGetInstanceData();
|
||||
BitClear(instDataParent->m_state, WIN_STATE_HILITED);
|
||||
}
|
||||
break;
|
||||
|
||||
} // end mouse leaving
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DRAG:
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GGM_LEFT_DRAG,
|
||||
(WindowMsgData)window, mData1 );
|
||||
break;
|
||||
|
||||
} // end left drag
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DOWN:
|
||||
{
|
||||
PushButtonData *pData = (PushButtonData *)window->winGetUserData();
|
||||
AudioEventRTS buttonClick;
|
||||
if(pData && pData->altSound.isNotEmpty())
|
||||
buttonClick.setEventName(pData->altSound);
|
||||
else
|
||||
buttonClick.setEventName("GUIClick");
|
||||
|
||||
if( TheAudio )
|
||||
{
|
||||
TheAudio->addAudioEvent( &buttonClick );
|
||||
} // end if
|
||||
|
||||
//
|
||||
// for 'check-like' buttons we have "dual state", we flip the selected status
|
||||
// in that case instead of just turning it on like normal ... also note
|
||||
// that selected messages are sent immediately
|
||||
//
|
||||
if( BitTest( window->winGetStatus(), WIN_STATUS_CHECK_LIKE ) )
|
||||
{
|
||||
|
||||
if( BitTest( instData->m_state, WIN_STATE_SELECTED ) )
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
else
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GBM_SELECTED,
|
||||
(WindowMsgData)window, mData1 );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// just select as normal
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end else
|
||||
|
||||
break;
|
||||
} // end left down
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
case GWM_LEFT_UP:
|
||||
{
|
||||
|
||||
//
|
||||
// note check like selected messages aren't sent here ... they are sent
|
||||
// on the down press
|
||||
//
|
||||
if( BitTest( instData->getState(), WIN_STATE_SELECTED ) &&
|
||||
BitTest( window->winGetStatus(), WIN_STATUS_CHECK_LIKE ) == FALSE )
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GBM_SELECTED,
|
||||
(WindowMsgData)window, mData1 );
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// this up click was not meant for this button
|
||||
return MSG_IGNORED;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end left up or left click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_RIGHT_DOWN:
|
||||
{
|
||||
PushButtonData *pData = (PushButtonData *)window->winGetUserData();
|
||||
AudioEventRTS buttonClick;
|
||||
if(pData && pData->altSound.isNotEmpty())
|
||||
buttonClick.setEventName(pData->altSound);
|
||||
else
|
||||
buttonClick.setEventName("GUIClick");
|
||||
|
||||
|
||||
if( BitTest( instData->getStatus(), WIN_STATUS_RIGHT_CLICK ) )
|
||||
{
|
||||
// Need to be specially marked to care about right mouse events
|
||||
if( TheAudio )
|
||||
{
|
||||
TheAudio->addAudioEvent( &buttonClick );
|
||||
} // end if
|
||||
|
||||
//
|
||||
// for 'check-like' buttons we have "dual state", we flip the selected status
|
||||
// in that case instead of just turning it on like normal ... also note
|
||||
// that selected messages are sent immediately
|
||||
//
|
||||
if( BitTest( window->winGetStatus(), WIN_STATUS_CHECK_LIKE ) )
|
||||
{
|
||||
|
||||
if( BitTest( instData->m_state, WIN_STATE_SELECTED ) )
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
else
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GBM_SELECTED_RIGHT,
|
||||
(WindowMsgData)window, mData1 );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// just select as normal
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end else
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else I don't care about right events
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
break;
|
||||
} // end right down
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
case GWM_RIGHT_UP:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getStatus(), WIN_STATUS_RIGHT_CLICK ) )
|
||||
{
|
||||
|
||||
//
|
||||
// note check like selected messages aren't sent here ... they are sent
|
||||
// on the down press
|
||||
//
|
||||
if( BitTest( instData->getState(), WIN_STATE_SELECTED ) &&
|
||||
BitTest( window->winGetStatus(), WIN_STATUS_CHECK_LIKE ) == FALSE )
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GBM_SELECTED_RIGHT,
|
||||
(WindowMsgData)window, mData1 );
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// this up click was not meant for this button
|
||||
return MSG_IGNORED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// Else I don't care about right events
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end right up or right click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
switch( mData1 )
|
||||
{
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_ENTER:
|
||||
case KEY_SPACE:
|
||||
{
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_UP ) )
|
||||
{
|
||||
|
||||
//
|
||||
// note check like selected messages aren't sent here ... they are sent
|
||||
// on the down press
|
||||
//
|
||||
if( BitTest( instData->getState(), WIN_STATE_SELECTED ) &&
|
||||
BitTest( window->winGetStatus(), WIN_STATUS_CHECK_LIKE ) == FALSE )
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GBM_SELECTED,
|
||||
(WindowMsgData)window, 0 );
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//
|
||||
// for 'check-like' buttons we have "dual state", we flip the selected status
|
||||
// in that case instead of just turning it on like normal ... also note
|
||||
// that selected messages are sent immediately
|
||||
//
|
||||
if( BitTest( window->winGetStatus(), WIN_STATUS_CHECK_LIKE ) )
|
||||
{
|
||||
|
||||
if( BitTest( instData->m_state, WIN_STATE_SELECTED ) )
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
else
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GBM_SELECTED,
|
||||
(WindowMsgData)window, mData1 );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// just select as normal
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end else
|
||||
|
||||
|
||||
} // end else
|
||||
|
||||
break;
|
||||
|
||||
} // end handle enter and space button
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_DOWN:
|
||||
case KEY_RIGHT:
|
||||
case KEY_TAB:
|
||||
{
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
TheWindowManager->winNextTab(window);
|
||||
break;
|
||||
|
||||
} // end key down, right or tab
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_UP:
|
||||
case KEY_LEFT:
|
||||
{
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
TheWindowManager->winPrevTab(window);
|
||||
break;
|
||||
|
||||
} // end key up or left
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch on char
|
||||
|
||||
break;
|
||||
|
||||
} // end character message
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetPushButtonInput
|
||||
|
||||
// GadgetPushButtonSystem =====================================================
|
||||
/** Handle system messages for push button */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetPushButtonSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_SET_LABEL:
|
||||
{
|
||||
// set text into the win instance text data field
|
||||
window->winSetText( *(UnicodeString*)mData1 );
|
||||
break;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
PushButtonData *pData = (PushButtonData *)window->winGetUserData();
|
||||
if(pData)
|
||||
delete pData;
|
||||
window->winSetUserData(NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
|
||||
if( mData1 == FALSE )
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
else
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(),
|
||||
GGM_FOCUS_CHANGE,
|
||||
(WindowMsgData)mData1,
|
||||
window->winGetWindowId() );
|
||||
if( mData1 == FALSE )
|
||||
*(Bool*)mData2 = FALSE;
|
||||
else
|
||||
*(Bool*)mData2 = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetPushButtonSystem
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
/** Set the visual status of a button to make it looked checked/unchecked ... DO NOT send
|
||||
* any actual button selected messages, this is ONLY VISUAL */
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void GadgetCheckLikeButtonSetVisualCheck( GameWindow *g, Bool checked )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
// get instance data
|
||||
WinInstanceData *instData = g->winGetInstanceData();
|
||||
if( instData == NULL )
|
||||
return;
|
||||
|
||||
// sanity, must be a check like button
|
||||
if( BitTest( g->winGetStatus(), WIN_STATUS_CHECK_LIKE ) == FALSE )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "GadgetCheckLikeButtonSetVisualCheck: Window is not 'CHECK-LIKE'\n" ));
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// set or clear the 'pushed' state
|
||||
if( instData )
|
||||
{
|
||||
|
||||
if( checked == TRUE )
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
else
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end GadgetCheckLikeButtonSetVisualCheck
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Bool GadgetCheckLikeButtonIsChecked( GameWindow *g )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( g == NULL )
|
||||
return FALSE;
|
||||
|
||||
// get instance data
|
||||
WinInstanceData *instData = g->winGetInstanceData();
|
||||
if( instData == NULL )
|
||||
return FALSE;
|
||||
|
||||
// we just hold this "check like dual state thingie" using the selected state
|
||||
return BitTest( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end GadgetCheckLikeButtonIsChecked
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void GadgetButtonEnableCheckLike( GameWindow *g, Bool makeCheckLike, Bool initiallyChecked )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
// get inst data
|
||||
WinInstanceData *instData = g->winGetInstanceData();
|
||||
if( instData == NULL )
|
||||
return;
|
||||
|
||||
// make it check like
|
||||
if( makeCheckLike )
|
||||
g->winSetStatus( WIN_STATUS_CHECK_LIKE );
|
||||
else
|
||||
g->winClearStatus( WIN_STATUS_CHECK_LIKE );
|
||||
|
||||
// set the initially checked "state"
|
||||
if( initiallyChecked )
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
else
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end GadgetButtonEnableCheckLike
|
||||
|
||||
// GadgetButtonSetText ========================================================
|
||||
/** Set the text for a push button */
|
||||
//=============================================================================
|
||||
void GadgetButtonSetText( GameWindow *g, UnicodeString text )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
TheWindowManager->winSendSystemMsg( g, GGM_SET_LABEL, (WindowMsgData)&text, 0 );
|
||||
|
||||
} // end GadgetButtonSetText
|
||||
|
||||
PushButtonData * getNewPushButtonData( void )
|
||||
{
|
||||
PushButtonData *p = NEW PushButtonData;
|
||||
if(!p)
|
||||
return NULL;
|
||||
|
||||
p->userData = NULL;
|
||||
p->drawBorder = FALSE;
|
||||
p->drawClock = NO_CLOCK;
|
||||
p->overlayImage = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
// GadgetButtonSetBorder ======================================================
|
||||
/** Set to draw the special borders in the game */
|
||||
//=============================================================================
|
||||
void GadgetButtonSetBorder( GameWindow *g, Color color, Bool drawBorder = TRUE )
|
||||
{
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
PushButtonData *pData = (PushButtonData *)g->winGetUserData();
|
||||
if(!pData)
|
||||
{
|
||||
pData = getNewPushButtonData();
|
||||
}
|
||||
pData->drawBorder = drawBorder;
|
||||
pData->colorBorder = color;
|
||||
g->winSetUserData(pData);
|
||||
}
|
||||
|
||||
// GadgetButtonDrawClock ======================================================
|
||||
/** Set to draw a rectClock on the button */
|
||||
//=============================================================================
|
||||
void GadgetButtonDrawClock( GameWindow *g, Int percent, Color color )
|
||||
{
|
||||
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
PushButtonData *pData = (PushButtonData *)g->winGetUserData();
|
||||
if(!pData)
|
||||
{
|
||||
pData = getNewPushButtonData();
|
||||
}
|
||||
pData->drawClock = NORMAL_CLOCK;
|
||||
pData->percentClock = percent;
|
||||
pData->colorClock = color;
|
||||
g->winSetUserData(pData);
|
||||
|
||||
}
|
||||
|
||||
// GadgetButtonDrawInverseClock ======================================================
|
||||
/** Set to draw an inversed rectClock on the button */
|
||||
//=============================================================================
|
||||
void GadgetButtonDrawInverseClock( GameWindow *g, Int percent, Color color )
|
||||
{
|
||||
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
PushButtonData *pData = (PushButtonData *)g->winGetUserData();
|
||||
if(!pData)
|
||||
{
|
||||
pData = getNewPushButtonData();
|
||||
}
|
||||
pData->drawClock = INVERSE_CLOCK;
|
||||
pData->percentClock = percent;
|
||||
pData->colorClock = color;
|
||||
g->winSetUserData(pData);
|
||||
|
||||
}
|
||||
|
||||
void GadgetButtonDrawOverlayImage( GameWindow *g, const Image *image )
|
||||
{
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
PushButtonData *pData = (PushButtonData *)g->winGetUserData();
|
||||
if(!pData)
|
||||
{
|
||||
pData = getNewPushButtonData();
|
||||
}
|
||||
pData->overlayImage = image;
|
||||
g->winSetUserData(pData);
|
||||
}
|
||||
|
||||
|
||||
// GadgetButtonSetData ======================================================
|
||||
/** Sets random data that the user can contain on the button */
|
||||
//=============================================================================
|
||||
void GadgetButtonSetData(GameWindow *g, void *data)
|
||||
{
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
PushButtonData *pData = (PushButtonData *)g->winGetUserData();
|
||||
if(!pData)
|
||||
{
|
||||
pData = getNewPushButtonData();
|
||||
}
|
||||
pData->userData = data;
|
||||
g->winSetUserData(pData);
|
||||
}
|
||||
|
||||
// GadgetButtonGetData ======================================================
|
||||
/** Gets the random data the user had already set on the button */
|
||||
//=============================================================================
|
||||
void *GadgetButtonGetData(GameWindow *g)
|
||||
{
|
||||
if( g == NULL )
|
||||
return NULL;
|
||||
|
||||
PushButtonData *pData = (PushButtonData *)g->winGetUserData();
|
||||
if(!pData)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return pData->userData;
|
||||
}
|
||||
|
||||
void GadgetButtonSetAltSound(GameWindow *g, AsciiString altSound )
|
||||
{
|
||||
if(!g)
|
||||
return;
|
||||
PushButtonData *pData = (PushButtonData *)g->winGetUserData();
|
||||
if(!pData)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pData->altSound = altSound;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
** 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: RadioButton.cpp //////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: RadioButton.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: Radio button GUI control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "Gameclient/GameWindowManager.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// doRadioUnselect ============================================================
|
||||
/** Do the unselect of matching group not including exception window */
|
||||
//=============================================================================
|
||||
static void doRadioUnselect( GameWindow *window, Int group, Int screen,
|
||||
GameWindow *except )
|
||||
{
|
||||
|
||||
//
|
||||
// if this is a radio button we have something to consider, but we
|
||||
// will ignore the except window
|
||||
//
|
||||
if( window != except && BitTest( window->winGetStyle(), GWS_RADIO_BUTTON ) )
|
||||
{
|
||||
RadioButtonData *radioData = (RadioButtonData *)window->winGetUserData();
|
||||
|
||||
if( radioData->group == group && radioData->screen == screen )
|
||||
{
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end if
|
||||
|
||||
// recursively call on all my children
|
||||
GameWindow *child;
|
||||
|
||||
for( child = window->winGetChild(); child; child = child->winGetNext() )
|
||||
doRadioUnselect( child, group, screen, except );
|
||||
|
||||
} // end doRadioUnselect
|
||||
|
||||
// unselectOtherRadioOfGroup ==================================================
|
||||
/** Go through the entire window system, including child windows and
|
||||
* unselect any radio buttons of the specified group, but not the
|
||||
* window specified */
|
||||
//=============================================================================
|
||||
static void unselectOtherRadioOfGroup( Int group, Int screen,
|
||||
GameWindow *except )
|
||||
{
|
||||
GameWindow *window = TheWindowManager->winGetWindowList();
|
||||
|
||||
for( window = TheWindowManager->winGetWindowList();
|
||||
window;
|
||||
window = window->winGetNext() )
|
||||
doRadioUnselect( window, group, screen, except );
|
||||
|
||||
} // end unselectOtherRadioOfGroup
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
|
||||
// GadgetRadioButtonInput =====================================================
|
||||
/** Handle input for radio button */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetRadioButtonInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_ENTERING:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(),
|
||||
GBM_MOUSE_ENTERING,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
//TheWindowManager->winSetFocus( window );
|
||||
|
||||
} // end if
|
||||
|
||||
break;
|
||||
|
||||
} // end mouse enter
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_LEAVING:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(),
|
||||
GBM_MOUSE_LEAVING,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
} // end if
|
||||
|
||||
break;
|
||||
|
||||
} // end mouse leaving
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DRAG:
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( instData->getOwner(), GGM_LEFT_DRAG,
|
||||
(WindowMsgData)window, mData1 );
|
||||
break;
|
||||
|
||||
} // end left drag
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DOWN:
|
||||
{
|
||||
|
||||
break;
|
||||
|
||||
} // end down
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_UP:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getState(), WIN_STATE_SELECTED ) == FALSE )
|
||||
{
|
||||
RadioButtonData *radioData = (RadioButtonData *)window->winGetUserData();
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_SELECTED,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
|
||||
//
|
||||
// unselect any windows in the system (including children) that
|
||||
// are radio buttons with this same group and screen ID
|
||||
//
|
||||
if( radioData->group != 0 )
|
||||
unselectOtherRadioOfGroup(radioData->group, radioData->screen, window );
|
||||
|
||||
// this button is now selected
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end if, not selected
|
||||
else if( BitTest( instData->getState(), WIN_STATE_HILITED ) == FALSE )
|
||||
{
|
||||
|
||||
// this up click was not meant for this button
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end else if
|
||||
|
||||
break;
|
||||
|
||||
} // end left up or click
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
|
||||
switch( mData1 )
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_ENTER:
|
||||
case KEY_SPACE:
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
|
||||
if( BitTest( instData->getState(), WIN_STATE_SELECTED ) == FALSE )
|
||||
{
|
||||
RadioButtonData *radioData = (RadioButtonData *)window->winGetUserData();
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_SELECTED,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
|
||||
//
|
||||
// unselect any windows in the system (including children) that
|
||||
// are radio buttons with this same group and screen ID
|
||||
//
|
||||
if( radioData->group != 0 )
|
||||
unselectOtherRadioOfGroup(radioData->group, radioData->screen, window );
|
||||
|
||||
// this button is now selected
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end if, not selected
|
||||
|
||||
} // end key down
|
||||
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_DOWN:
|
||||
case KEY_RIGHT:
|
||||
case KEY_TAB:
|
||||
{
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
window->winNextTab();
|
||||
break;
|
||||
|
||||
} // end down, right, or tab
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_UP:
|
||||
case KEY_LEFT:
|
||||
{
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
window->winPrevTab();
|
||||
break;
|
||||
|
||||
} // end up, left
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
default:
|
||||
{
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end default
|
||||
|
||||
} // end switch( mData1 )
|
||||
|
||||
break;
|
||||
|
||||
} // end char messsage
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
{
|
||||
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end default
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetRadioButtonInput
|
||||
|
||||
// GadgetRadioButtonSystem ====================================================
|
||||
/** Handle system messages for radio button */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetRadioButtonSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GBM_SET_SELECTION:
|
||||
{
|
||||
|
||||
if( BitTest( instData->getState(), WIN_STATE_SELECTED ) == FALSE )
|
||||
{
|
||||
|
||||
// do we want to send a selected message?
|
||||
if( (Bool)mData1 == TRUE )
|
||||
{
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_SELECTED,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
} // end if
|
||||
|
||||
//
|
||||
// unselect any windows in the system (including children) that
|
||||
// are radio buttons with this same group and screen ID
|
||||
//
|
||||
RadioButtonData *radioData = (RadioButtonData *)window->winGetUserData();
|
||||
if( radioData->group != 0 )
|
||||
unselectOtherRadioOfGroup(radioData->group, radioData->screen, window );
|
||||
|
||||
// this button is now selected
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
|
||||
} // end if
|
||||
|
||||
break;
|
||||
|
||||
} // end set selection
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_SET_LABEL:
|
||||
{
|
||||
|
||||
window->winSetText( *(UnicodeString*)mData1 );
|
||||
break;
|
||||
|
||||
} // end set label
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
RadioButtonData *radioData = (RadioButtonData *)window->winGetUserData();
|
||||
|
||||
// free radio button user data
|
||||
delete radioData;
|
||||
|
||||
break;
|
||||
|
||||
} // end destroy
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
{
|
||||
|
||||
if( mData1 == FALSE )
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GGM_FOCUS_CHANGE,
|
||||
mData1,
|
||||
window->winGetWindowId() );
|
||||
|
||||
*(Bool*)mData2 = TRUE;
|
||||
break;
|
||||
|
||||
} // end focus
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetRadioButtonSystem
|
||||
|
||||
// GadgetRadioSetText =========================================================
|
||||
/** Set the text for the control */
|
||||
//=============================================================================
|
||||
void GadgetRadioSetText( GameWindow *g, UnicodeString text )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
TheWindowManager->winSendSystemMsg( g, GGM_SET_LABEL, (WindowMsgData)&text, 0 );
|
||||
|
||||
} // end GadgetRadioSetText
|
||||
|
||||
// GadgetRadioSetGroup ========================================================
|
||||
/** Set the group number for a radio button, only one radio button of
|
||||
* a group can be selected at any given time */
|
||||
//=============================================================================
|
||||
void GadgetRadioSetGroup( GameWindow *g, Int group, Int screen )
|
||||
{
|
||||
RadioButtonData *radioData = (RadioButtonData *)g->winGetUserData();
|
||||
|
||||
radioData->group = group;
|
||||
radioData->screen = screen;
|
||||
|
||||
} // end GadgetRadioSetGroup
|
||||
|
||||
|
||||
// GadgetRadioSetText =========================================================
|
||||
/** Set the text for the control */
|
||||
//=============================================================================
|
||||
void GadgetRadioSetSelection( GameWindow *g, Bool sendMsg )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( g == NULL )
|
||||
return;
|
||||
|
||||
TheWindowManager->winSendSystemMsg( g, GBM_SET_SELECTION, (WindowMsgData)&sendMsg, 0 );
|
||||
|
||||
} // end GadgetRadioSetText
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
** 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: StaticText.cpp ///////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: StaticText.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: Static text control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "GameClient/DisplayStringManager.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GadgetStaticTextInput ======================================================
|
||||
/** Handle input for text field */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetStaticTextInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
switch (mData1)
|
||||
{
|
||||
|
||||
case KEY_DOWN:
|
||||
case KEY_RIGHT:
|
||||
case KEY_TAB:
|
||||
// Just in case some fool sets static text as a tab stop
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
window->winNextTab();
|
||||
break;
|
||||
|
||||
case KEY_UP:
|
||||
case KEY_LEFT:
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
window->winPrevTab();
|
||||
break;
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
}
|
||||
return MSG_HANDLED;
|
||||
|
||||
|
||||
} // end GadgetStaticTextInput
|
||||
|
||||
// GadgetStaticTextSystem =====================================================
|
||||
/** Handle system messages for text field */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetStaticTextSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
// WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_GET_LABEL:
|
||||
{
|
||||
TextData *tData = (TextData *)window->winGetUserData();
|
||||
if (tData && tData->text)
|
||||
*(UnicodeString*)mData2 = tData->text->getText();
|
||||
break;
|
||||
|
||||
} // end get label
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_SET_LABEL:
|
||||
{
|
||||
if( mData1 )
|
||||
{
|
||||
TextData *tData = (TextData *)window->winGetUserData();
|
||||
if (tData && tData->text)
|
||||
tData->text->setText( *(UnicodeString*)mData1 );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} // end set label
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
TextData *data = (TextData *)window->winGetUserData();
|
||||
|
||||
// free the display string
|
||||
TheDisplayStringManager->freeDisplayString( data->text );
|
||||
|
||||
// free text data
|
||||
delete( data );
|
||||
|
||||
break;
|
||||
|
||||
} // end destroy
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
} // end GadgetStaticTextSystem
|
||||
|
||||
// GadgetStaticTextSetText ====================================================
|
||||
/** Set the text for a static text control */
|
||||
//=============================================================================
|
||||
void GadgetStaticTextSetText( GameWindow *window, UnicodeString text )
|
||||
{
|
||||
if(!window)
|
||||
return;
|
||||
TheWindowManager->winSendSystemMsg( window, GGM_SET_LABEL, (WindowMsgData)&text, 0 );
|
||||
|
||||
} // end GadgetStaticTextSetText
|
||||
|
||||
UnicodeString GadgetStaticTextGetText( GameWindow *window )
|
||||
{
|
||||
if(!window)
|
||||
return UnicodeString::TheEmptyString;
|
||||
TextData *tData = (TextData *)window->winGetUserData();
|
||||
if(!tData)
|
||||
return UnicodeString::TheEmptyString;
|
||||
return tData->text->getText();
|
||||
}
|
||||
|
||||
// GadgetStaticTextSetFont ====================================================
|
||||
/** Set the font for a text control, we need to set the window
|
||||
* text font, the tooltip font, and the static text display strings for
|
||||
* the text data itself */
|
||||
//=============================================================================
|
||||
void GadgetStaticTextSetFont( GameWindow *g, GameFont *font )
|
||||
{
|
||||
TextData *textData = (TextData *)g->winGetUserData();
|
||||
DisplayString *dString;
|
||||
|
||||
// set the font for the display strings all windows have
|
||||
dString = g->winGetInstanceData()->getTextDisplayString();
|
||||
if( dString )
|
||||
dString->setFont( font );
|
||||
dString = g->winGetInstanceData()->getTooltipDisplayString();
|
||||
if( dString )
|
||||
dString->setFont( font );
|
||||
|
||||
// static text specific
|
||||
if( textData )
|
||||
{
|
||||
|
||||
dString = textData->text;
|
||||
if( dString )
|
||||
dString->setFont( font );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end GadgetStaticTextSetFont
|
||||
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
** 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: RadioButton.cpp //////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: \projects\RTS\code\gameengine\Source\GameClient\GUI\Gadget\GadgetTabControl.cpp
|
||||
//
|
||||
// Created: Graham Smallwood, November 2001
|
||||
//
|
||||
// Desc: Tab Set GUI control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "Gameclient/GameWindowManager.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GadgetTabControl.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
|
||||
// GadgetTabControlInput =====================================================
|
||||
/** Handle input for TabControl */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetTabControlInput( GameWindow *tabControl, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
// WinInstanceData *instData = tabControl->winGetInstanceData();
|
||||
TabControlData *tabData = (TabControlData *)tabControl->winGetUserData();
|
||||
|
||||
Int tabX, tabY;
|
||||
tabControl->winGetScreenPosition( &tabX, &tabY );
|
||||
Int mouseX = LOLONGTOSHORT(mData1) - tabX;//mData1 is packedMouseCoords in screen space
|
||||
Int mouseY = HILONGTOSHORT(mData1) - tabY;
|
||||
Int tabsLeft = tabData->tabsLeftLimit;
|
||||
Int tabsRight = tabData->tabsRightLimit;
|
||||
Int tabsBottom = tabData->tabsBottomLimit;
|
||||
Int tabsTop = tabData->tabsTopLimit;
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
case GWM_LEFT_DOWN:
|
||||
{
|
||||
if( (mouseX < tabsLeft)
|
||||
|| (mouseX > tabsRight)
|
||||
|| (mouseY < tabsTop)
|
||||
|| (mouseY > tabsBottom)
|
||||
)
|
||||
{//I eat input on myself that isn't a tab (a button click would mean I don't see the input ever.)
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
Int distanceIn;
|
||||
Int tabSize;
|
||||
if( (tabData->tabEdge == TP_RIGHT_SIDE) || (tabData->tabEdge == TP_LEFT_SIDE) )
|
||||
{//scan down to find which button
|
||||
distanceIn = mouseY - tabsTop;
|
||||
tabSize = tabData->tabHeight;
|
||||
}
|
||||
else
|
||||
{//scan right to find which button
|
||||
distanceIn = mouseX - tabsLeft;
|
||||
tabSize = tabData->tabWidth;
|
||||
}
|
||||
Int tabPressed = distanceIn / tabSize;
|
||||
if( ! tabData->subPaneDisabled[tabPressed] && (tabPressed != tabData->activeTab) )
|
||||
GadgetTabControlShowSubPane( tabControl, tabPressed );
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
return MSG_IGNORED;
|
||||
}
|
||||
}
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetTabControlInput
|
||||
|
||||
// GadgetTabControlSystem ====================================================
|
||||
/** Handle system messages for TabControl */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetTabControlSystem( GameWindow *tabControl, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
switch( msg )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
{
|
||||
TabControlData *tabData = (TabControlData *)tabControl->winGetUserData();
|
||||
|
||||
// free tab control user data
|
||||
delete tabData;
|
||||
|
||||
break;
|
||||
|
||||
} // end destroy
|
||||
|
||||
case GGM_RESIZED:
|
||||
{//On resize, we need to upkeep the pane sizes and tabs since they are bound to us
|
||||
GadgetTabControlResizeSubPanes( tabControl );
|
||||
GadgetTabControlComputeTabRegion( tabControl );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case GBM_SELECTED:
|
||||
{//Pass buttons messages up
|
||||
GameWindow *parent = tabControl->winGetParent();
|
||||
|
||||
if( parent )
|
||||
return TheWindowManager->winSendSystemMsg( parent, msg, mData1, mData2 );
|
||||
}
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetTabControlSystem
|
||||
|
||||
void GadgetTabControlComputeTabRegion( GameWindow *tabControl )///< Recalc the tab positions based on userData
|
||||
{
|
||||
Int winWidth, winHeight;
|
||||
tabControl->winGetSize( &winWidth, &winHeight );
|
||||
|
||||
TabControlData *tabData = (TabControlData *)tabControl->winGetUserData();
|
||||
|
||||
Int horzOffset = 0, vertOffset = 0;
|
||||
if( (tabData->tabEdge == TP_TOP_SIDE) || (tabData->tabEdge == TP_BOTTOM_SIDE) )
|
||||
{
|
||||
if( tabData->tabOrientation == TP_CENTER )
|
||||
{
|
||||
horzOffset = winWidth - ( 2 * tabData->paneBorder ) - ( tabData->tabCount * tabData->tabWidth );
|
||||
horzOffset /= 2;
|
||||
}
|
||||
else if( tabData->tabOrientation == TP_BOTTOMRIGHT )
|
||||
{
|
||||
horzOffset = winWidth - ( 2 * tabData->paneBorder ) - ( tabData->tabCount * tabData->tabWidth );
|
||||
}
|
||||
else if( tabData->tabOrientation == TP_TOPLEFT )
|
||||
{
|
||||
horzOffset = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( tabData->tabOrientation == TP_CENTER )
|
||||
{
|
||||
vertOffset = winHeight - ( 2 * tabData->paneBorder ) - ( tabData->tabCount * tabData->tabHeight );
|
||||
vertOffset /= 2;
|
||||
}
|
||||
else if( tabData->tabOrientation == TP_BOTTOMRIGHT )
|
||||
{
|
||||
vertOffset = winHeight - ( 2 * tabData->paneBorder ) - ( tabData->tabCount * tabData->tabHeight );
|
||||
}
|
||||
else if( tabData->tabOrientation == TP_TOPLEFT )
|
||||
{
|
||||
vertOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if( tabData->tabEdge == TP_TOP_SIDE )
|
||||
{
|
||||
tabData->tabsTopLimit = tabData->paneBorder;
|
||||
tabData->tabsBottomLimit = tabData->paneBorder + tabData->tabHeight;
|
||||
tabData->tabsLeftLimit = tabData->paneBorder + horzOffset;
|
||||
tabData->tabsRightLimit = tabData->paneBorder + horzOffset + ( tabData->tabWidth * tabData->tabCount );
|
||||
}
|
||||
else if( tabData->tabEdge == TP_BOTTOM_SIDE )
|
||||
{
|
||||
tabData->tabsTopLimit = winHeight - tabData->paneBorder - tabData->tabHeight;
|
||||
tabData->tabsBottomLimit = winHeight - tabData->paneBorder;
|
||||
tabData->tabsLeftLimit = tabData->paneBorder + horzOffset;
|
||||
tabData->tabsRightLimit = tabData->paneBorder + horzOffset + ( tabData->tabWidth * tabData->tabCount );
|
||||
}
|
||||
else if( tabData->tabEdge == TP_RIGHT_SIDE )
|
||||
{
|
||||
tabData->tabsLeftLimit = winWidth - tabData->paneBorder - tabData->tabWidth;
|
||||
tabData->tabsRightLimit = winWidth - tabData->paneBorder;
|
||||
tabData->tabsTopLimit = tabData->paneBorder + vertOffset;
|
||||
tabData->tabsBottomLimit = tabData->paneBorder + vertOffset + ( tabData->tabHeight * tabData->tabCount );
|
||||
}
|
||||
else if( tabData->tabEdge == TP_LEFT_SIDE )
|
||||
{
|
||||
tabData->tabsLeftLimit = tabData->paneBorder;
|
||||
tabData->tabsRightLimit = tabData->paneBorder + tabData->tabWidth;
|
||||
tabData->tabsTopLimit = tabData->paneBorder + vertOffset;
|
||||
tabData->tabsBottomLimit = tabData->paneBorder + vertOffset + ( tabData->tabHeight * tabData->tabCount );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GadgetTabControlComputeSubPaneSize( GameWindow *tabControl, Int *width, Int *height, Int *x, Int *y )
|
||||
{
|
||||
Int winWidth, winHeight;
|
||||
tabControl->winGetSize( &winWidth, &winHeight );
|
||||
|
||||
TabControlData *tabData = (TabControlData *)tabControl->winGetUserData();
|
||||
|
||||
if( (tabData->tabEdge == TP_TOP_SIDE) || (tabData->tabEdge == TP_BOTTOM_SIDE) )
|
||||
*height = winHeight - (2 * tabData->paneBorder) - tabData->tabHeight;
|
||||
else
|
||||
*height = winHeight - (2 * tabData->paneBorder);
|
||||
|
||||
if( (tabData->tabEdge == TP_LEFT_SIDE) || (tabData->tabEdge == TP_RIGHT_SIDE) )
|
||||
*width = winWidth - (2 * tabData->paneBorder) - tabData->tabWidth;
|
||||
else
|
||||
*width = winWidth - (2 * tabData->paneBorder);
|
||||
|
||||
if( tabData->tabEdge == TP_LEFT_SIDE )
|
||||
*x = tabData->paneBorder + tabData->tabWidth;
|
||||
else
|
||||
*x = tabData->paneBorder;
|
||||
|
||||
if( tabData->tabEdge == TP_TOP_SIDE )
|
||||
*y = tabData->paneBorder + tabData->tabHeight;
|
||||
else
|
||||
*y = tabData->paneBorder;
|
||||
}
|
||||
|
||||
void GadgetTabControlShowSubPane( GameWindow *tabControl, Int whichPane)
|
||||
{
|
||||
TabControlData *tabData = (TabControlData *)tabControl->winGetUserData();
|
||||
|
||||
for( Int paneIndex = 0; paneIndex < NUM_TAB_PANES; paneIndex++ )
|
||||
{
|
||||
if( tabData->subPanes[paneIndex] != NULL )
|
||||
tabData->subPanes[paneIndex]->winHide( true );
|
||||
}
|
||||
if( tabData->subPanes[whichPane] )
|
||||
tabData->activeTab = whichPane;
|
||||
else
|
||||
tabData->activeTab = 0;
|
||||
|
||||
tabData->activeTab = min( tabData->activeTab, tabData->tabCount - 1 );
|
||||
|
||||
tabData->subPanes[tabData->activeTab]->winHide( false );
|
||||
}
|
||||
|
||||
void GadgetTabControlCreateSubPanes( GameWindow *tabControl )///< Create User Windows attached to userData as Panes
|
||||
{//These two funcs are called after all the Editor set data is updated
|
||||
TabControlData *tabData = (TabControlData *)tabControl->winGetUserData();
|
||||
Int width, height, x, y;
|
||||
GadgetTabControlComputeSubPaneSize(tabControl, &width, &height, &x, &y);
|
||||
|
||||
for( Int paneIndex = 0; paneIndex < NUM_TAB_PANES; paneIndex++ )
|
||||
{
|
||||
if( (tabData->subPanes[paneIndex] == NULL) )//This one is blank
|
||||
{
|
||||
tabData->subPanes[paneIndex] = TheWindowManager->winCreate( tabControl,
|
||||
WIN_STATUS_NONE, x, y,
|
||||
width, height,
|
||||
PassSelectedButtonsToParentSystem,
|
||||
NULL);
|
||||
WinInstanceData *instData = tabData->subPanes[paneIndex]->winGetInstanceData();
|
||||
BitSet( instData->m_style, GWS_TAB_PANE );
|
||||
char buffer[20];
|
||||
sprintf( buffer, "Pane %d", paneIndex );
|
||||
instData->m_decoratedNameString = buffer;
|
||||
//set enabled status to that of Parent
|
||||
tabData->subPanes[paneIndex]->winEnable( BitTest(tabControl->winGetStatus(), WIN_STATUS_ENABLED) );
|
||||
}
|
||||
else//this one exists, tabCount will control keeping extra panes perma-hidden
|
||||
{
|
||||
tabData->subPanes[paneIndex]->winSetSize( width, height );
|
||||
tabData->subPanes[paneIndex]->winSetPosition( x, y );
|
||||
}
|
||||
}
|
||||
|
||||
GadgetTabControlShowSubPane( tabControl, tabData->activeTab );
|
||||
}
|
||||
|
||||
void GadgetTabControlResizeSubPanes( GameWindow *tabControl )
|
||||
{
|
||||
TabControlData *tabData = (TabControlData *)tabControl->winGetUserData();
|
||||
Int width, height, x, y;
|
||||
GadgetTabControlComputeSubPaneSize(tabControl, &width, &height, &x, &y);
|
||||
for( Int paneIndex = 0; paneIndex < NUM_TAB_PANES; paneIndex++ )
|
||||
{
|
||||
if( tabData->subPanes[paneIndex] )
|
||||
{
|
||||
tabData->subPanes[paneIndex]->winSetSize( width, height );
|
||||
tabData->subPanes[paneIndex]->winSetPosition( x, y );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///<In game creation finished, hook up Children to SubPane array
|
||||
void GadgetTabControlFixupSubPaneList( GameWindow *tabControl )
|
||||
{
|
||||
Int childIndex =0;
|
||||
TabControlData *tabData = (TabControlData *)tabControl->winGetUserData();
|
||||
GameWindow *child = tabControl->winGetChild();
|
||||
if( child )
|
||||
{//need to write down children, and they are reversed from our array
|
||||
while( child->winGetNext() != NULL )
|
||||
{
|
||||
child = child->winGetNext();
|
||||
}
|
||||
|
||||
while( child )
|
||||
{
|
||||
tabData->subPanes[childIndex] = child;
|
||||
childIndex++;
|
||||
child = child->winGetPrev();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
** 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: TextEntry.cpp ////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: TextEntry.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: Text entry GUI gadget
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "GameClient/DisplayStringManager.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/IMEManager.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
static Byte drawCnt = 0;
|
||||
// static TbIME *ourIME = NULL; ///< @todo need this for IME kanji support
|
||||
static GameWindow *curWindow = NULL; /**< so we can keep track of the input
|
||||
window when using IME */
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GadgetTextEntryInput =======================================================
|
||||
/** Handle input for text entry field */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetTextEntryInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
EntryData *e = (EntryData *)window->winGetUserData();
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
if ( TheIMEManager && TheIMEManager->isAttachedTo( window) && TheIMEManager->isComposing())
|
||||
{
|
||||
// ignore input while IME has focus
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_IME_CHAR:
|
||||
{
|
||||
WideChar ch = (WideChar) mData1;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
if ( ch == VK_RETURN )
|
||||
{
|
||||
// Done with this edit
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GEM_EDIT_DONE,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
return MSG_HANDLED;
|
||||
};
|
||||
|
||||
if( ch )
|
||||
{
|
||||
// Constrain keys based on rules for entry box.
|
||||
if( e->numericalOnly )
|
||||
{
|
||||
if( TheWindowManager->winIsDigit( ch ) == 0 )
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
if( e->alphaNumericalOnly )
|
||||
{
|
||||
if( TheWindowManager->winIsAlNum( ch ) == 0 )
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
if ( e->aSCIIOnly )
|
||||
{
|
||||
if ( TheWindowManager->winIsAscii( ch ) == 0 )
|
||||
{
|
||||
return MSG_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
if( e->charPos < e->maxTextLen-1 )
|
||||
{
|
||||
e->text->appendChar( ch );
|
||||
e->sText->appendChar( L'*' );
|
||||
e->charPos++;
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GEM_UPDATE_TEXT,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
if ( BitTest( mData2, KEY_STATE_DOWN ) && BitTest( mData2, KEY_STATE_ALT | KEY_STATE_CONTROL ) )
|
||||
{
|
||||
return MSG_IGNORED; // text extries shouldn't care about CTRL+* or ALT+*
|
||||
}
|
||||
|
||||
switch( mData1 )
|
||||
{
|
||||
/*
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_KPENTER:
|
||||
case KEY_ENTER:
|
||||
// Done with this edit
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
if( e->receivedUnichar == FALSE )
|
||||
{
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GEM_EDIT_DONE,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
*/
|
||||
// --------------------------------------------------------------------
|
||||
// Don't process these keys
|
||||
case KEY_ESC:
|
||||
case KEY_PGUP:
|
||||
case KEY_PGDN:
|
||||
case KEY_HOME:
|
||||
case KEY_END:
|
||||
case KEY_F1:
|
||||
case KEY_F2:
|
||||
case KEY_F3:
|
||||
case KEY_F4:
|
||||
case KEY_F5:
|
||||
case KEY_F6:
|
||||
case KEY_F7:
|
||||
case KEY_F8:
|
||||
case KEY_F9:
|
||||
case KEY_F10:
|
||||
case KEY_F11:
|
||||
case KEY_F12:
|
||||
case KEY_CAPS:
|
||||
case KEY_DEL:
|
||||
return MSG_IGNORED;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_DOWN:
|
||||
case KEY_RIGHT:
|
||||
case KEY_TAB:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
GameWindow *parent;
|
||||
parent = window->winGetParent();
|
||||
if(parent && !BitTest(parent->winGetStyle(), GWS_COMBO_BOX))
|
||||
parent = NULL;
|
||||
if(parent)
|
||||
TheWindowManager->winNextTab(parent);
|
||||
else
|
||||
TheWindowManager->winNextTab(window);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_UP:
|
||||
case KEY_LEFT:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
GameWindow *parent;
|
||||
parent = window->winGetParent();
|
||||
if(parent && !BitTest(parent->winGetStyle(), GWS_COMBO_BOX))
|
||||
parent = NULL;
|
||||
if(parent)
|
||||
TheWindowManager->winPrevTab(parent);
|
||||
else
|
||||
TheWindowManager->winPrevTab(window);
|
||||
}
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_BACKSPACE:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
// if conCharPos != 0 this will fall through to next case.
|
||||
// it should be noted that conCharPos can only != 0 in Jap & Kor
|
||||
if( e->conCharPos == 0 )
|
||||
{
|
||||
if( e->charPos > 0 )
|
||||
{
|
||||
|
||||
e->text->removeLastChar();
|
||||
e->sText->removeLastChar();
|
||||
e->charPos--;
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GEM_UPDATE_TEXT,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
} // end if
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
} // end switch( mData1 )
|
||||
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DOWN:
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSetFocus( window );
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_ENTERING:
|
||||
|
||||
if (BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_MOUSE_ENTERING,
|
||||
(WindowMsgData)window, 0 );
|
||||
//TheWindowManager->winSetFocus( window );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_LEAVING:
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_MOUSE_LEAVING,
|
||||
(WindowMsgData)window, 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DRAG:
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GGM_LEFT_DRAG,
|
||||
(WindowMsgData)window, 0 );
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetTextEntryInput
|
||||
|
||||
// GadgetTextEntrySystem ======================================================
|
||||
/** Handle system messages for entry field */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetTextEntrySystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
EntryData *e = (EntryData *)window->winGetUserData();
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GEM_GET_TEXT:
|
||||
*(UnicodeString*)mData2 = e->text->getText();
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GEM_SET_TEXT:
|
||||
{
|
||||
|
||||
const UnicodeString* ustr = (const UnicodeString*)mData1;
|
||||
e->text->setText( *ustr );
|
||||
e->charPos = ustr->getLength();
|
||||
e->constructText->setText( UnicodeString::TheEmptyString );
|
||||
e->conCharPos = 0;
|
||||
|
||||
// set our secret text string to be filled with '*' the same length
|
||||
e->sText->setText( UnicodeString::TheEmptyString );
|
||||
Int len = ustr->getLength();
|
||||
for( Int i = 0; i < len; i++ )
|
||||
e->sText->appendChar( L'*' );
|
||||
|
||||
break;
|
||||
|
||||
} // end set text
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
|
||||
// delete the edit display string
|
||||
TheDisplayStringManager->freeDisplayString( e->text );
|
||||
TheDisplayStringManager->freeDisplayString( e->sText );
|
||||
TheDisplayStringManager->freeDisplayString( e->constructText );
|
||||
|
||||
// delete construct list
|
||||
if( e->constructList )
|
||||
TheWindowManager->winDestroy( e->constructList );
|
||||
|
||||
// free all edit data
|
||||
delete( (EntryData *)window->winGetUserData() );
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
if( mData1 == FALSE )
|
||||
{
|
||||
// If we're losing focus
|
||||
/// @todo need to enable this for IME support
|
||||
// ourIME->UnActivate();
|
||||
curWindow = NULL;
|
||||
BitClear( instData->m_state, WIN_STATE_SELECTED );
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
|
||||
if( e->constructList )
|
||||
e->constructList->winHide( TRUE );
|
||||
e->constructText->setText( UnicodeString::TheEmptyString );
|
||||
e->conCharPos = 0;
|
||||
if(TheIMEManager && TheIMEManager->isAttachedTo(window))
|
||||
TheIMEManager->attach(NULL);
|
||||
//TheIMEManager->detatch();
|
||||
}
|
||||
else
|
||||
{
|
||||
curWindow = window;
|
||||
/// @todo need to enable this for IME support
|
||||
if (TheIMEManager)
|
||||
TheIMEManager->attach( window );
|
||||
// ourIME->Activate( (void *)ApplicationHWnd );
|
||||
BitSet( instData->m_state, WIN_STATE_SELECTED );
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
}
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GGM_FOCUS_CHANGE,
|
||||
mData1,
|
||||
window->winGetWindowId() );
|
||||
|
||||
*(Bool*)mData2 = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetTextEntrySystem
|
||||
|
||||
/** @todo we might want to do something like this if we use IME for language
|
||||
* support in this product */
|
||||
/*
|
||||
// used to create interface to IME
|
||||
BoolCode InitializeEntryGadget( void )
|
||||
{
|
||||
ourIME = NEW TbIME;
|
||||
|
||||
ourIME->Composition_SetMaxLength( 11 );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// used to destroy interface to IME
|
||||
BoolCode ShutdownEntryGadget( void )
|
||||
{
|
||||
delete ourIME;
|
||||
ourIME = NULL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void InformEntry( WideChar c )
|
||||
{
|
||||
Int i, listCount = 0;
|
||||
EntryData *e;
|
||||
|
||||
if( ourIME == NULL || curWindow == NULL )
|
||||
return;
|
||||
|
||||
e = (EntryData *)curWindow->winGetUserData();
|
||||
|
||||
if( ( (OurLanguage == LANGUAGE_ID_JAPANESE) ||
|
||||
(OurLanguage == LANGUAGE_ID_KOREAN) ) &&
|
||||
( (e->aSCIIOnly == FALSE ) &&
|
||||
(e->alphaNumericalOnly == FALSE ) &&
|
||||
(e->numericalOnly == FALSE ) ) )
|
||||
{
|
||||
e->receivedUnichar = TRUE;
|
||||
|
||||
// we must eat the following keys
|
||||
switch( c )
|
||||
{
|
||||
case L'\a':
|
||||
case L'\b':
|
||||
case L'\f':
|
||||
case L'\t':
|
||||
case L'\v':
|
||||
return;
|
||||
|
||||
// we must completely ignore the return key
|
||||
case L'\r':
|
||||
case L'\n':
|
||||
e->receivedUnichar = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if( e->charPos < e->maxTextLen-1 )
|
||||
{
|
||||
e->text[ e->charPos++ ] = c;
|
||||
e->text[ e->charPos ] = 0;
|
||||
}
|
||||
|
||||
// always update the construction buffer after a key has come through here.
|
||||
TheWindowManager->winStrcpy( e->constructText, (WideChar *)ourIME->Composition_Get() );
|
||||
e->conCharPos = NoxStrlen( e->constructText );
|
||||
|
||||
// we might need to update our listbox
|
||||
listCount = ourIME->CandidateList_GetSize();
|
||||
|
||||
if( TRUE ) //listCount == 0)
|
||||
{
|
||||
// if no entries just hide it and leave
|
||||
if( e->constructList )
|
||||
e->constructList->winHide( TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
Int maxWidth = 0;
|
||||
ListboxData list = NULL;
|
||||
ICoord2D constructSize, sliderSize;
|
||||
|
||||
WinHide( e->constructList, FALSE );
|
||||
list = (ListBoxData)e->constructList->winGetUserData();
|
||||
|
||||
e->constructList->winGetSize( &constructSize.x, &constructSize.y );
|
||||
list->slider->winGetSize( &sliderSize.x, &sliderSize.y );
|
||||
|
||||
TheWindowManager->winSendSystemMsg( e->constructList, GLM_DEL_ALL, 0, 0 );
|
||||
|
||||
for( i=0; i<listCount; i++ )
|
||||
{
|
||||
Int tempWidth;
|
||||
|
||||
WideChar *text = (WideChar *)ourIME->CandidateList_GetItem( i );
|
||||
|
||||
TheWindowManager->winGetTextSize( e->constructList->instData.font,
|
||||
text, NULL, &tempWidth, 0 );
|
||||
|
||||
if( tempWidth > maxWidth )
|
||||
maxWidth = tempWidth;
|
||||
|
||||
UnicodeString tmp(text);
|
||||
TheWindowManager->winSendSystemMsg( e->constructList, GLM_ADD_ENTRY,
|
||||
(WindowMsgData)&tmp, -1 );
|
||||
}
|
||||
|
||||
e->constructList->winSetSize( maxWidth + sliderSize.y,
|
||||
constructSize.y );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// GadgetTextEntrySetFont =====================================================
|
||||
/** Set the font for a text entry control, we need to set the window
|
||||
* text font, the tooltip font, and the edit text display strings for
|
||||
* the text data itself and the secret text */
|
||||
//=============================================================================
|
||||
void GadgetTextEntrySetFont( GameWindow *g, GameFont *font )
|
||||
{
|
||||
EntryData *entryData = (EntryData *)g->winGetUserData();
|
||||
DisplayString *dString;
|
||||
|
||||
// set the font for the display strings all windows have
|
||||
dString = g->winGetInstanceData()->getTextDisplayString();
|
||||
if( dString )
|
||||
dString->setFont( font );
|
||||
dString = g->winGetInstanceData()->getTooltipDisplayString();
|
||||
if( dString )
|
||||
dString->setFont( font );
|
||||
|
||||
// text entry specific
|
||||
if( entryData )
|
||||
{
|
||||
|
||||
dString = entryData->text;
|
||||
if( dString )
|
||||
dString->setFont( font );
|
||||
dString = entryData->sText;
|
||||
if( dString )
|
||||
dString->setFont( font );
|
||||
|
||||
} // end if
|
||||
|
||||
} // end GadgetTextEntrySetFont
|
||||
|
||||
// GadgetTextEntryGetText =======================================================
|
||||
/** Get the text for a Text entry */
|
||||
//=============================================================================
|
||||
UnicodeString GadgetTextEntryGetText( GameWindow *textentry )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( textentry == NULL )
|
||||
return UnicodeString::TheEmptyString;
|
||||
|
||||
// verify that this is a list box
|
||||
if( BitTest( textentry->winGetStyle(), GWS_ENTRY_FIELD ) == FALSE )
|
||||
return UnicodeString::TheEmptyString;
|
||||
|
||||
UnicodeString result;
|
||||
TheWindowManager->winSendSystemMsg( textentry, GEM_GET_TEXT, 0, (WindowMsgData)&result );
|
||||
return result;
|
||||
|
||||
} // end GadgetListBoxGetText
|
||||
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
** 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: VerticalSlider.cpp ///////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: VerticalSlider.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: Vertical slider gui control
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "Gameclient/GameWindowManager.h"
|
||||
#include "GameClient/Gadget.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// GadgetVerticlaSliderInput ==================================================
|
||||
/** Handle input for vertical slider */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetVerticalSliderInput( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
SliderData *s = (SliderData *)window->winGetUserData();
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_ENTERING:
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_MOUSE_ENTERING,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
//TheWindowManager->winSetFocus( window );
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_MOUSE_LEAVING:
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
{
|
||||
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GBM_MOUSE_LEAVING,
|
||||
(WindowMsgData)window,
|
||||
0 );
|
||||
}
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DRAG:
|
||||
|
||||
if( BitTest( instData->getStyle(), GWS_MOUSE_TRACK ) )
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GGM_LEFT_DRAG,
|
||||
(WindowMsgData)window,
|
||||
mData1 );
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_DOWN:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_LEFT_UP:
|
||||
{
|
||||
Int x, y;
|
||||
// Int mousex = mData1 & 0xFFFF;
|
||||
Int mousey = mData1 >> 16;
|
||||
ICoord2D size, childSize, childCenter;
|
||||
GameWindow *child = window->winGetChild();
|
||||
Int pageClickSize, clickPos;
|
||||
|
||||
window->winGetScreenPosition( &x, &y );
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
child->winGetSize( &childSize.x, &childSize.y );
|
||||
child->winGetPosition( &childCenter.x, &childCenter.y );
|
||||
childCenter.x += childSize.x / 2;
|
||||
childCenter.y += childSize.y / 2;
|
||||
|
||||
//
|
||||
// when you click on the slider, but not the button, we will jump
|
||||
// the slider position up/down by this much
|
||||
//
|
||||
pageClickSize = size.y / 5;
|
||||
|
||||
clickPos = mousey - y;
|
||||
if( clickPos >= childCenter.y )
|
||||
{
|
||||
|
||||
clickPos = childCenter.y + pageClickSize;
|
||||
if( clickPos > mousey - y )
|
||||
clickPos = mousey - y;
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
clickPos = childCenter.y - pageClickSize;
|
||||
if( clickPos < mousey - y )
|
||||
clickPos = mousey - y;
|
||||
|
||||
} // end else
|
||||
|
||||
// keep pos valid on window
|
||||
if( clickPos > y + size.y - childSize.y / 2 )
|
||||
clickPos = y + size.y - childSize.y / 2;
|
||||
if( clickPos < childSize.y / 2 )
|
||||
clickPos = childSize.y / 2;
|
||||
|
||||
child->winSetPosition( 0, clickPos - childSize.y / 2 );
|
||||
TheWindowManager->winSendSystemMsg( window, GGM_LEFT_DRAG, 0, mData1 );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CHAR:
|
||||
{
|
||||
|
||||
switch (mData1)
|
||||
{
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_UP:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
|
||||
if( s->position < s->maxVal - 1)
|
||||
{
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
s->position += 2;
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
// Translate to window coords
|
||||
child->winSetPosition( 0, (Int)((s->maxVal - s->position) * s->numTicks) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_DOWN:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
{
|
||||
|
||||
if( s->position > s->minVal + 1 )
|
||||
{
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
s->position -= 2;
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
// Translate to window coords
|
||||
child->winSetPosition( 0, (Int)((s->maxVal - s->position) * s->numTicks) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_RIGHT:
|
||||
case KEY_TAB:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
window->winNextTab();
|
||||
break;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
case KEY_LEFT:
|
||||
|
||||
if( BitTest( mData2, KEY_STATE_DOWN ) )
|
||||
window->winPrevTab();
|
||||
break;
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( mData1 )
|
||||
|
||||
break;
|
||||
|
||||
} // end char
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetVerticalSliderInput
|
||||
|
||||
// GadgetVerticalSliderSystem =================================================
|
||||
/** Handle system messages for vertical slider */
|
||||
//=============================================================================
|
||||
WindowMsgHandledType GadgetVerticalSliderSystem( GameWindow *window, UnsignedInt msg,
|
||||
WindowMsgData mData1, WindowMsgData mData2 )
|
||||
{
|
||||
SliderData *s = (SliderData *)window->winGetUserData();
|
||||
WinInstanceData *instData = window->winGetInstanceData();
|
||||
|
||||
switch( msg )
|
||||
{
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GBM_SELECTED:
|
||||
{
|
||||
// tell owner I've finished moving
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_DONE,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_LEFT_DRAG:
|
||||
{
|
||||
// Int mousex = mData2 & 0xFFFF;
|
||||
Int mousey = mData2 >> 16;
|
||||
Int x, y, delta;
|
||||
ICoord2D size, childSize, childCenter;
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
window->winGetScreenPosition( &x, &y );
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
child->winGetSize( &childSize.x, &childSize.y );
|
||||
child->winGetScreenPosition( &childCenter.x, &childCenter.y );
|
||||
childCenter.x += childSize.x / 2;
|
||||
childCenter.y += childSize.y / 2;
|
||||
|
||||
//
|
||||
// ignore drag attempts when the mouse is below or above the slider totally
|
||||
// and put the dragging thumb back at the slider pos
|
||||
//
|
||||
if( mousey > y + size.y )
|
||||
{
|
||||
|
||||
//s->position = s->minVal;
|
||||
TheWindowManager->winSendSystemMsg( window, GSM_SET_SLIDER,
|
||||
s->minVal, 0 );
|
||||
// tell owner i moved
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
break;
|
||||
|
||||
} // end if
|
||||
else if( mousey < y )
|
||||
{
|
||||
|
||||
//s->position = s->maxVal;
|
||||
TheWindowManager->winSendSystemMsg( window, GSM_SET_SLIDER,
|
||||
s->maxVal, 0 );
|
||||
// tell owner i moved
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
break;
|
||||
|
||||
} // end else if
|
||||
|
||||
if( childCenter.y <= y + childSize.y / 2 )
|
||||
{
|
||||
child->winSetPosition( 0, 0 );
|
||||
s->position = s->maxVal;
|
||||
}
|
||||
else if( childCenter.y >= y + size.y - childSize.y / 2 )
|
||||
{
|
||||
child->winSetPosition( 0, size.y - childSize.y );
|
||||
s->position = s->minVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = childCenter.y - y - childSize.y/2;
|
||||
|
||||
// Calc slider position
|
||||
s->position = (Int)(delta / s->numTicks) ;
|
||||
|
||||
/*
|
||||
s->position += s->minVal;
|
||||
*/
|
||||
|
||||
if( s->position > s->maxVal )
|
||||
s->position = s->maxVal;
|
||||
|
||||
// Invert slider position so that maxval is at the top
|
||||
s->position = s->maxVal - s->position;
|
||||
|
||||
}
|
||||
|
||||
// tell owner i moved
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GSM_SLIDER_TRACK,
|
||||
(WindowMsgData)window,
|
||||
s->position );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GSM_SET_SLIDER:
|
||||
{
|
||||
Int newPos = (Int)mData1;
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
if (newPos < s->minVal || newPos > s->maxVal)
|
||||
break;
|
||||
|
||||
s->position = newPos;
|
||||
|
||||
// Translate to window coords
|
||||
newPos = (Int)((s->maxVal - newPos) * s->numTicks);
|
||||
|
||||
child->winSetPosition( 0, newPos );
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GSM_SET_MIN_MAX:
|
||||
{
|
||||
Int newPos;
|
||||
ICoord2D size;
|
||||
GameWindow *child = window->winGetChild();
|
||||
|
||||
window->winGetSize( &size.x, &size.y );
|
||||
|
||||
s->minVal = (Int)mData1;
|
||||
s->maxVal = (Int)mData2;
|
||||
s->numTicks = (Real)( size.y-GADGET_SIZE)/(Real)(s->maxVal - s->minVal);
|
||||
s->position = s->minVal;
|
||||
|
||||
// Translate to window coords
|
||||
newPos = (Int)((s->maxVal - s->minVal) * s->numTicks);
|
||||
|
||||
child->winSetPosition( 0, newPos );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_CREATE:
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_DESTROY:
|
||||
delete( (SliderData *)window->winGetUserData() );
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GWM_INPUT_FOCUS:
|
||||
|
||||
// If we're losing focus
|
||||
if( mData1 == FALSE )
|
||||
{
|
||||
BitClear( instData->m_state, WIN_STATE_HILITED );
|
||||
} else {
|
||||
BitSet( instData->m_state, WIN_STATE_HILITED );
|
||||
}
|
||||
|
||||
TheWindowManager->winSendSystemMsg( window->winGetOwner(),
|
||||
GGM_FOCUS_CHANGE,
|
||||
mData1,
|
||||
window->winGetWindowId() );
|
||||
|
||||
*(Bool*)mData2 = TRUE;
|
||||
break;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
case GGM_RESIZED:
|
||||
{
|
||||
Int width = (Int)mData1;
|
||||
// Int height = (Int)mData2;
|
||||
GameWindow *thumb = window->winGetChild();
|
||||
|
||||
if( thumb )
|
||||
thumb->winSetSize( width, GADGET_SIZE );
|
||||
|
||||
break;
|
||||
|
||||
} // end resized
|
||||
|
||||
default:
|
||||
return MSG_IGNORED;
|
||||
|
||||
} // end switch( msg )
|
||||
|
||||
return MSG_HANDLED;
|
||||
|
||||
} // end GadgetVerticalSliderSystem
|
||||
|
||||
228
Generals/Code/GameEngine/Source/GameClient/GUI/GameFont.cpp
Normal file
228
Generals/Code/GameEngine/Source/GameClient/GUI/GameFont.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
** 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: GameFont.cpp /////////////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, June 2001
|
||||
// Desc: Access to our representation for fonts
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/GameFont.h"
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
|
||||
FontLibrary *TheFontLibrary = NULL;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Link a font to the font list */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FontLibrary::linkFont( GameFont *font )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( font == NULL )
|
||||
return;
|
||||
|
||||
// link it
|
||||
font->next = m_fontList;
|
||||
m_fontList = font;
|
||||
|
||||
// increment linked count
|
||||
m_count++;
|
||||
|
||||
} // end linkFont
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Unlink a font from the font list */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FontLibrary::unlinkFont( GameFont *font )
|
||||
{
|
||||
GameFont *other = NULL;
|
||||
|
||||
// sanity
|
||||
if( font == NULL )
|
||||
return;
|
||||
|
||||
// sanity check and make sure this font is actually in this library
|
||||
for( other = m_fontList; other; other = other->next )
|
||||
if( other == font )
|
||||
break;
|
||||
if( other == NULL )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "Font '%s' not found in library\n", font->nameString.str() ));
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// scan for the font pointing to the one we're going to unlink
|
||||
for( other = m_fontList; other; other = other->next )
|
||||
if( other->next == font )
|
||||
break;
|
||||
|
||||
//
|
||||
// if nothing was fount this was at the head of the list, otherwise
|
||||
// remove from chain
|
||||
//
|
||||
if( other == NULL )
|
||||
m_fontList = font->next;
|
||||
else
|
||||
other->next = font->next;
|
||||
|
||||
// clean up this font we just unlinked just to be cool!
|
||||
font->next = NULL;
|
||||
|
||||
// we now have one less font on the list
|
||||
m_count--;
|
||||
|
||||
} // end unlinkFont
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Delete all font data, DO NOT throw an exception ... the destructor uses this */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FontLibrary::deleteAllFonts( void )
|
||||
{
|
||||
GameFont *font;
|
||||
|
||||
// release all the fonts
|
||||
while( m_fontList )
|
||||
{
|
||||
|
||||
// get temp pointer to this font
|
||||
font = m_fontList;
|
||||
|
||||
// remove font fron the list, this will change m_fontList
|
||||
unlinkFont( font );
|
||||
|
||||
// release font data
|
||||
releaseFontData( font );
|
||||
|
||||
// delete the font list element
|
||||
font->deleteInstance();
|
||||
|
||||
} // end while
|
||||
|
||||
} // deleteAllFonts
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
FontLibrary::FontLibrary( void )
|
||||
{
|
||||
|
||||
m_fontList = NULL;
|
||||
m_count = 0;
|
||||
|
||||
} // end FontLibrary
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
FontLibrary::~FontLibrary( void )
|
||||
{
|
||||
|
||||
// delete all font data
|
||||
deleteAllFonts();
|
||||
|
||||
} // end ~FontLibrary
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize what we need to in the font library */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FontLibrary::init( void )
|
||||
{
|
||||
|
||||
} // end init
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Reset the fonts for this font library */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void FontLibrary::reset( void )
|
||||
{
|
||||
|
||||
// delete all font data
|
||||
deleteAllFonts();
|
||||
|
||||
} // end reset
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Get a font from our list, if we don't have that font loaded we will
|
||||
* attempt to load it */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
GameFont *FontLibrary::getFont( AsciiString name, Int pointSize, Bool bold )
|
||||
{
|
||||
GameFont *font;
|
||||
|
||||
// search for font in list
|
||||
for( font = m_fontList; font; font = font->next )
|
||||
{
|
||||
|
||||
if( font->pointSize == pointSize &&
|
||||
font->bold == bold &&
|
||||
font->nameString == name
|
||||
)
|
||||
return font; // found
|
||||
|
||||
} // end for font
|
||||
|
||||
// font not found, allocate a new font element
|
||||
font = newInstance(GameFont);
|
||||
if( font == NULL )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "getFont: Unable to allocate new font list element\n" ));
|
||||
return NULL;
|
||||
|
||||
} // end if
|
||||
|
||||
// copy font data over to new element
|
||||
font->nameString = name;
|
||||
font->pointSize = pointSize;
|
||||
font->bold = bold;
|
||||
font->fontData = NULL;
|
||||
|
||||
//DEBUG_LOG(("Font: Loading font '%s' %d point\n", font->nameString.str(), font->pointSize));
|
||||
// load the device specific data pointer
|
||||
if( loadFontData( font ) == FALSE )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "getFont: Unable to load font data pointer '%s'\n", name ));
|
||||
font->deleteInstance();
|
||||
return NULL;
|
||||
|
||||
} // end if
|
||||
|
||||
// tie font into list
|
||||
linkFont( font );
|
||||
|
||||
// all is done and loaded
|
||||
return font;
|
||||
|
||||
} // end getFont
|
||||
1792
Generals/Code/GameEngine/Source/GameClient/GUI/GameWindow.cpp
Normal file
1792
Generals/Code/GameEngine/Source/GameClient/GUI/GameWindow.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
** 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: GameWindowGlobal.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: GameWindowGlobal.cpp
|
||||
//
|
||||
// Created: Colin Day, June 2001
|
||||
//
|
||||
// Desc: These are some global functions that every game using this
|
||||
// window system must implement for their current technology
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "Common/Language.h"
|
||||
#include "GameClient/Image.h"
|
||||
#include "GameClient/Display.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GameFont.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GameWindowManager::winDrawImage ============================================
|
||||
/** draw image, coord are in screen and should be kepth within
|
||||
* that box specified */
|
||||
//=============================================================================
|
||||
void GameWindowManager::winDrawImage( const Image *image, Int startX, Int startY,
|
||||
Int endX, Int endY, Color color )
|
||||
{
|
||||
|
||||
TheDisplay->drawImage( image, startX, startY, endX, endY, color );
|
||||
|
||||
} // end WinDrawImage
|
||||
|
||||
// GameWindowManager::winFillRect =============================================
|
||||
/** draw filled rect, coords are absolute screen coords */
|
||||
//=============================================================================
|
||||
void GameWindowManager::winFillRect( Color color, Real width,
|
||||
Int startX, Int startY,
|
||||
Int endX, Int endY )
|
||||
{
|
||||
|
||||
TheDisplay->drawFillRect( startX, startY,
|
||||
endX - startX, endY - startY,
|
||||
color );
|
||||
|
||||
} // end WinFillRect
|
||||
|
||||
// GameWindowManager::winOpenRect =============================================
|
||||
/** draw rect outline, coords are absolute screen coords */
|
||||
//=============================================================================
|
||||
void GameWindowManager::winOpenRect( Color color, Real width,
|
||||
Int startX, Int startY,
|
||||
Int endX, Int endY )
|
||||
{
|
||||
|
||||
TheDisplay->drawOpenRect( startX, startY,
|
||||
endX - startX, endY - startY,
|
||||
width, color );
|
||||
|
||||
} // end WinOpenRect
|
||||
|
||||
// GameWindowManager::winDrawLine =============================================
|
||||
/** draw line, coords are absolute screen coords */
|
||||
//=============================================================================
|
||||
void GameWindowManager::winDrawLine( Color color, Real width,
|
||||
Int startX, Int startY,
|
||||
Int endX, Int endY )
|
||||
{
|
||||
|
||||
TheDisplay->drawLine( startX, startY, endX, endY, width, color );
|
||||
|
||||
} // end WinDrawLine
|
||||
|
||||
// GameWindowManager::winFindImage ============================================
|
||||
/** Given an image name, return an image loc to that image information.
|
||||
* You may reorganize the image loc structure however you like to suit
|
||||
* your individual project */
|
||||
//=============================================================================
|
||||
const Image *GameWindowManager::winFindImage( const char *name )
|
||||
{
|
||||
|
||||
assert( TheMappedImageCollection );
|
||||
if( TheMappedImageCollection )
|
||||
return TheMappedImageCollection->findImageByName( AsciiString( name ) );
|
||||
|
||||
return NULL;
|
||||
|
||||
} // end WinFindImage
|
||||
|
||||
// GameWindowManager::winMakeColor ============================================
|
||||
/** Given RGBA, make a color, you can change color representation for your
|
||||
* individual project needs */
|
||||
//=============================================================================
|
||||
Color GameWindowManager::winMakeColor( UnsignedByte red,
|
||||
UnsignedByte green,
|
||||
UnsignedByte blue,
|
||||
UnsignedByte alpha )
|
||||
{
|
||||
|
||||
return GameMakeColor( red, green, blue, alpha );
|
||||
|
||||
} // end WinMakeColor
|
||||
|
||||
// GameWindowManager::winFormatText ===========================================
|
||||
/** draw text to the screen */
|
||||
//=============================================================================
|
||||
void GameWindowManager::winFormatText( GameFont *font, UnicodeString text, Color color,
|
||||
Int x, Int y, Int width, Int height )
|
||||
{
|
||||
|
||||
/// @todo make all display string rendering go through here!
|
||||
|
||||
} // end WinFormatText
|
||||
|
||||
// GameWindowManager::winGetTextSize ==========================================
|
||||
/** get the extent size of text */
|
||||
//=============================================================================
|
||||
void GameWindowManager::winGetTextSize( GameFont *font, UnicodeString text,
|
||||
Int *width, Int *height, Int maxWidth )
|
||||
{
|
||||
|
||||
/// @todo make display string size stuff go through here
|
||||
|
||||
if( width )
|
||||
*width = 0;
|
||||
|
||||
if( height )
|
||||
*height = 0;
|
||||
|
||||
} // end WinGetTextSize
|
||||
|
||||
// GameWindowManager::winFontHeight ===========================================
|
||||
/** Return the font height in pixels */
|
||||
//=============================================================================
|
||||
Int GameWindowManager::winFontHeight( GameFont *font )
|
||||
{
|
||||
|
||||
return font->height;
|
||||
|
||||
} // end WinFontHeight
|
||||
|
||||
// GameWindowManager::winIsDigit ==============================================
|
||||
/** You implementation of whether or not character is a digit */
|
||||
//=============================================================================
|
||||
Int GameWindowManager::winIsDigit( Int c )
|
||||
{
|
||||
|
||||
return GameIsDigit( c );
|
||||
|
||||
} // end WinIsDigit
|
||||
|
||||
// GameWindowManager::winIsAscii ==============================================
|
||||
/** You implementation of whether or not character is ascii */
|
||||
//=============================================================================
|
||||
Int GameWindowManager::winIsAscii( Int c )
|
||||
{
|
||||
|
||||
return GameIsAscii( c );
|
||||
|
||||
} // end WinIsDigit
|
||||
|
||||
// GameWindowManager::winIsAlNum ==============================================
|
||||
/** Your implementation of whether or not character is alpha numeric */
|
||||
//=============================================================================
|
||||
Int GameWindowManager::winIsAlNum( Int c )
|
||||
{
|
||||
|
||||
return GameIsAlNum( c );
|
||||
|
||||
} // end WinIsAlNum
|
||||
|
||||
// GameWindowManager::winFindFont =============================================
|
||||
/** Get a font */
|
||||
//=============================================================================
|
||||
GameFont *GameWindowManager::winFindFont( AsciiString fontName,
|
||||
Int pointSize,
|
||||
Bool bold )
|
||||
{
|
||||
|
||||
assert( TheFontLibrary );
|
||||
if( TheFontLibrary )
|
||||
return TheFontLibrary->getFont( fontName, pointSize, bold );
|
||||
|
||||
return NULL;
|
||||
|
||||
} // end WinFindFont
|
||||
|
||||
4099
Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp
Normal file
4099
Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
** 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: GameWindowTransitions.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Dec 2002
|
||||
//
|
||||
// Filename: GameWindowTransitions.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "Gamelogic/GameLogic.h"
|
||||
#include "GameClient/GameWindowTransitions.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
GameWindowTransitionsHandler *TheTransitionHandler = NULL;
|
||||
const FieldParse GameWindowTransitionsHandler::m_gameWindowTransitionsFieldParseTable[] =
|
||||
{
|
||||
|
||||
{ "Window", GameWindowTransitionsHandler::parseWindow, NULL, NULL },
|
||||
{ "FireOnce", INI::parseBool, NULL, offsetof( TransitionGroup, m_fireOnce) },
|
||||
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
|
||||
};
|
||||
|
||||
void INI::parseWindowTransitions( INI* ini )
|
||||
{
|
||||
AsciiString name;
|
||||
TransitionGroup *g;
|
||||
|
||||
// read the name
|
||||
const char* c = ini->getNextToken();
|
||||
name.set( c );
|
||||
|
||||
// find existing item if present
|
||||
|
||||
DEBUG_ASSERTCRASH( TheTransitionHandler, ("parseWindowTransitions: TheTransitionHandler doesn't exist yet\n") );
|
||||
if( !TheTransitionHandler )
|
||||
return;
|
||||
|
||||
// If we have a previously allocated control bar, this will return a cleared out pointer to it so we
|
||||
// can overwrite it
|
||||
g = TheTransitionHandler->getNewGroup( name );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( g, ("parseWindowTransitions: Unable to allocate group '%s'\n", name.str()) );
|
||||
|
||||
// parse the ini definition
|
||||
ini->initFromINI( g, TheTransitionHandler->getFieldParse() );
|
||||
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
Transition *getTransitionForStyle( Int style )
|
||||
{
|
||||
switch (style) {
|
||||
case TRANSITION_FLASH:
|
||||
return NEW FlashTransition;
|
||||
case BUTTON_TRANSITION_FLASH:
|
||||
return NEW ButtonFlashTransition;
|
||||
case WIN_FADE_TRANSITION:
|
||||
return NEW FadeTransition;
|
||||
case WIN_SCALE_UP_TRANSITION:
|
||||
return NEW ScaleUpTransition;
|
||||
case MAINMENU_SCALE_UP_TRANSITION:
|
||||
return NEW MainMenuScaleUpTransition;
|
||||
case TEXT_TYPE_TRANSITION:
|
||||
return NEW TextTypeTransition;
|
||||
case SCREEN_FADE_TRANSITION:
|
||||
return NEW ScreenFadeTransition;
|
||||
case COUNT_UP_TRANSITION:
|
||||
return NEW CountUpTransition;
|
||||
case FULL_FADE_TRANSITION:
|
||||
return NEW FullFadeTransition;
|
||||
case TEXT_ON_FRAME_TRANSITION:
|
||||
return NEW TextOnFrameTransition;
|
||||
case REVERSE_SOUND_TRANSITION:
|
||||
return NEW ReverseSoundTransition;
|
||||
|
||||
case MAINMENU_MEDIUM_SCALE_UP_TRANSITION:
|
||||
return NEW MainMenuMediumScaleUpTransition;
|
||||
case MAINMENU_SMALL_SCALE_DOWN_TRANSITION:
|
||||
return NEW MainMenuSmallScaleDownTransition;
|
||||
case CONTROL_BAR_ARROW_TRANSITION:
|
||||
return NEW ControlBarArrowTransition;
|
||||
case SCORE_SCALE_UP_TRANSITION:
|
||||
return NEW ScoreScaleUpTransition;
|
||||
|
||||
default:
|
||||
DEBUG_ASSERTCRASH(FALSE, ("getTransitionForStyle:: An invalid style was passed in. Style = %d", style));
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TransitionWindow::TransitionWindow( void )
|
||||
{
|
||||
m_currentFrameDelay = m_frameDelay = 0;
|
||||
m_style = 0;
|
||||
|
||||
m_winID = NAMEKEY_INVALID;
|
||||
m_win = NULL;
|
||||
m_transition = NULL;
|
||||
}
|
||||
|
||||
TransitionWindow::~TransitionWindow( void )
|
||||
{
|
||||
m_win = NULL;
|
||||
if(m_transition)
|
||||
delete m_transition;
|
||||
|
||||
m_transition = NULL;
|
||||
}
|
||||
|
||||
Bool TransitionWindow::init( void )
|
||||
{
|
||||
m_winID = TheNameKeyGenerator->nameToKey(m_winName);
|
||||
m_win = TheWindowManager->winGetWindowFromId(NULL, m_winID);
|
||||
m_currentFrameDelay = m_frameDelay;
|
||||
// DEBUG_ASSERTCRASH( m_win, ("TransitionWindow::init Failed to find window %s", m_winName.str()));
|
||||
// if( !m_win )
|
||||
// return FALSE;
|
||||
|
||||
if(m_transition)
|
||||
delete m_transition;
|
||||
|
||||
m_transition = getTransitionForStyle( m_style );
|
||||
m_transition->init(m_win);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void TransitionWindow::update( Int frame )
|
||||
{
|
||||
if(frame < m_currentFrameDelay || frame > (m_currentFrameDelay + m_transition->getFrameLength()))
|
||||
return;
|
||||
|
||||
if(m_transition)
|
||||
m_transition->update( frame - m_currentFrameDelay);
|
||||
}
|
||||
|
||||
Bool TransitionWindow::isFinished( void )
|
||||
{
|
||||
if(m_transition)
|
||||
return m_transition->isFinished();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void TransitionWindow::reverse( Int totalFrames )
|
||||
{
|
||||
//m_currentFrameDelay = totalFrames - (m_transition->getFrameLength() + m_frameDelay);
|
||||
if(m_transition)
|
||||
m_transition->reverse();
|
||||
}
|
||||
|
||||
void TransitionWindow::skip( void )
|
||||
{
|
||||
if(m_transition)
|
||||
m_transition->skip();
|
||||
}
|
||||
|
||||
void TransitionWindow::draw( void )
|
||||
{
|
||||
if(m_transition)
|
||||
m_transition->draw();
|
||||
}
|
||||
|
||||
Int TransitionWindow::getTotalFrames( void )
|
||||
{
|
||||
if(m_transition)
|
||||
{
|
||||
return m_frameDelay + m_transition->getFrameLength();
|
||||
}
|
||||
|
||||
return m_frameDelay;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
TransitionGroup::TransitionGroup( void )
|
||||
{
|
||||
m_currentFrame = 0;
|
||||
m_fireOnce = FALSE;
|
||||
}
|
||||
|
||||
TransitionGroup::~TransitionGroup( void )
|
||||
{
|
||||
TransitionWindowList::iterator it = m_transitionWindowList.begin();
|
||||
while (it != m_transitionWindowList.end())
|
||||
{
|
||||
TransitionWindow *tWin = *it;
|
||||
delete tWin;
|
||||
tWin = NULL;
|
||||
it = m_transitionWindowList.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionGroup::init( void )
|
||||
{
|
||||
m_currentFrame = 0;
|
||||
m_directionMultiplier = 1;
|
||||
TransitionWindowList::iterator it = m_transitionWindowList.begin();
|
||||
while (it != m_transitionWindowList.end())
|
||||
{
|
||||
TransitionWindow *tWin = *it;
|
||||
tWin->init();
|
||||
it++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TransitionGroup::update( void )
|
||||
{
|
||||
m_currentFrame += m_directionMultiplier; // we go forward or backwards depending.
|
||||
TransitionWindowList::iterator it = m_transitionWindowList.begin();
|
||||
while (it != m_transitionWindowList.end())
|
||||
{
|
||||
TransitionWindow *tWin = *it;
|
||||
tWin->update(m_currentFrame);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
Bool TransitionGroup::isFinished( void )
|
||||
{
|
||||
TransitionWindowList::iterator it = m_transitionWindowList.begin();
|
||||
while (it != m_transitionWindowList.end())
|
||||
{
|
||||
TransitionWindow *tWin = *it;
|
||||
if(tWin->isFinished() == FALSE)
|
||||
return FALSE;
|
||||
it++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void TransitionGroup::reverse( void )
|
||||
{
|
||||
Int totalFrames =0;
|
||||
m_directionMultiplier = -1;
|
||||
|
||||
TransitionWindowList::iterator it = m_transitionWindowList.begin();
|
||||
while (it != m_transitionWindowList.end())
|
||||
{
|
||||
TransitionWindow *tWin = *it;
|
||||
Int winFrames = tWin->getTotalFrames();
|
||||
if(winFrames > totalFrames)
|
||||
totalFrames = winFrames;
|
||||
it++;
|
||||
}
|
||||
it = m_transitionWindowList.begin();
|
||||
while (it != m_transitionWindowList.end())
|
||||
{
|
||||
TransitionWindow *tWin = *it;
|
||||
tWin->reverse(totalFrames);
|
||||
it++;
|
||||
}
|
||||
m_currentFrame = totalFrames;
|
||||
// m_currentFrame ++;
|
||||
}
|
||||
|
||||
Bool TransitionGroup::isReversed( void )
|
||||
{
|
||||
if(m_directionMultiplier < 0)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void TransitionGroup::skip ( void )
|
||||
{
|
||||
TransitionWindowList::iterator it = m_transitionWindowList.begin();
|
||||
while (it != m_transitionWindowList.end())
|
||||
{
|
||||
TransitionWindow *tWin = *it;
|
||||
tWin->skip();
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionGroup::draw ( void )
|
||||
{
|
||||
TransitionWindowList::iterator it = m_transitionWindowList.begin();
|
||||
while (it != m_transitionWindowList.end())
|
||||
{
|
||||
TransitionWindow *tWin = *it;
|
||||
tWin->draw();
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void TransitionGroup::addWindow( TransitionWindow *transWin )
|
||||
{
|
||||
if(!transWin)
|
||||
return;
|
||||
m_transitionWindowList.push_back(transWin);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GameWindowTransitionsHandler::GameWindowTransitionsHandler(void)
|
||||
{
|
||||
m_currentGroup = NULL;
|
||||
m_pendingGroup = NULL;
|
||||
m_drawGroup = NULL;
|
||||
m_secondaryDrawGroup = NULL;
|
||||
|
||||
}
|
||||
|
||||
GameWindowTransitionsHandler::~GameWindowTransitionsHandler( void )
|
||||
{
|
||||
m_currentGroup = NULL;
|
||||
m_pendingGroup = NULL;
|
||||
m_drawGroup = NULL;
|
||||
m_secondaryDrawGroup = NULL;
|
||||
|
||||
TransitionGroupList::iterator it = m_transitionGroupList.begin();
|
||||
while( it != m_transitionGroupList.end() )
|
||||
{
|
||||
TransitionGroup *g = *it;
|
||||
delete g;
|
||||
it = m_transitionGroupList.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void GameWindowTransitionsHandler::init(void )
|
||||
{
|
||||
m_currentGroup = NULL;
|
||||
m_pendingGroup = NULL;
|
||||
m_drawGroup = NULL;
|
||||
m_secondaryDrawGroup = NULL;
|
||||
}
|
||||
|
||||
void GameWindowTransitionsHandler::load(void )
|
||||
{
|
||||
INI ini;
|
||||
// Read from INI all the ControlBarSchemes
|
||||
ini.load( AsciiString( "Data\\INI\\WindowTransitions.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||||
|
||||
}
|
||||
|
||||
void GameWindowTransitionsHandler::reset( void )
|
||||
{
|
||||
m_currentGroup = NULL;
|
||||
m_pendingGroup = NULL;
|
||||
m_drawGroup = NULL;
|
||||
m_secondaryDrawGroup = NULL;
|
||||
|
||||
}
|
||||
|
||||
void GameWindowTransitionsHandler::update( void )
|
||||
{
|
||||
if(m_drawGroup != m_currentGroup)
|
||||
m_secondaryDrawGroup = m_drawGroup;
|
||||
else
|
||||
m_secondaryDrawGroup = NULL;
|
||||
|
||||
m_drawGroup = m_currentGroup;
|
||||
if(m_currentGroup && !m_currentGroup->isFinished())
|
||||
m_currentGroup->update();
|
||||
|
||||
if(m_currentGroup && m_currentGroup->isFinished() && m_currentGroup->isFireOnce())
|
||||
{
|
||||
m_currentGroup = NULL;
|
||||
}
|
||||
|
||||
if(m_currentGroup && m_pendingGroup && m_currentGroup->isFinished())
|
||||
{
|
||||
m_currentGroup = m_pendingGroup;
|
||||
m_pendingGroup = NULL;
|
||||
}
|
||||
|
||||
if(!m_currentGroup && m_pendingGroup)
|
||||
{
|
||||
m_currentGroup = m_pendingGroup;
|
||||
m_pendingGroup = NULL;
|
||||
}
|
||||
|
||||
if(m_currentGroup && m_currentGroup->isFinished() && m_currentGroup->isReversed())
|
||||
m_currentGroup = NULL;
|
||||
}
|
||||
|
||||
|
||||
void GameWindowTransitionsHandler::draw( void )
|
||||
{
|
||||
// if( TheGameLogic->getFrame() > 0 )//if( areTransitionsEnabled() ) //KRIS
|
||||
if(m_drawGroup)
|
||||
m_drawGroup->draw();
|
||||
if(m_secondaryDrawGroup)
|
||||
m_secondaryDrawGroup->draw();
|
||||
}
|
||||
|
||||
void GameWindowTransitionsHandler::setGroup(AsciiString groupName, Bool immidiate )
|
||||
{
|
||||
if(groupName.isEmpty() && immidiate)
|
||||
m_currentGroup = NULL;
|
||||
if(immidiate && m_currentGroup)
|
||||
{
|
||||
m_currentGroup->skip();
|
||||
m_currentGroup = findGroup(groupName);
|
||||
if(m_currentGroup)
|
||||
m_currentGroup->init();
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_currentGroup)
|
||||
{
|
||||
if(!m_currentGroup->isFireOnce() && !m_currentGroup->isReversed())
|
||||
m_currentGroup->reverse();
|
||||
m_pendingGroup = findGroup(groupName);
|
||||
if(m_pendingGroup)
|
||||
m_pendingGroup->init();
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentGroup = findGroup(groupName);
|
||||
if(m_currentGroup)
|
||||
m_currentGroup->init();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void GameWindowTransitionsHandler::reverse( AsciiString groupName )
|
||||
{
|
||||
TransitionGroup *g = findGroup(groupName);
|
||||
if( m_currentGroup == g )
|
||||
{
|
||||
m_currentGroup->reverse();
|
||||
return;
|
||||
}
|
||||
if( m_pendingGroup == g)
|
||||
{
|
||||
m_pendingGroup = NULL;
|
||||
return;
|
||||
}
|
||||
if(m_currentGroup)
|
||||
m_currentGroup->skip();
|
||||
if(m_pendingGroup)
|
||||
m_pendingGroup->skip();
|
||||
|
||||
m_currentGroup = g;
|
||||
m_currentGroup->init();
|
||||
m_currentGroup->skip();
|
||||
m_currentGroup->reverse();
|
||||
m_pendingGroup = NULL;
|
||||
}
|
||||
|
||||
void GameWindowTransitionsHandler::remove( AsciiString groupName, Bool skipPending )
|
||||
{
|
||||
TransitionGroup *g = findGroup(groupName);
|
||||
if(m_pendingGroup == g)
|
||||
{
|
||||
if(skipPending)
|
||||
m_pendingGroup->skip();
|
||||
|
||||
m_pendingGroup = NULL;
|
||||
}
|
||||
if(m_currentGroup == g)
|
||||
{
|
||||
m_currentGroup->skip();
|
||||
m_currentGroup = NULL;
|
||||
if(m_pendingGroup)
|
||||
m_currentGroup = m_pendingGroup;
|
||||
}
|
||||
}
|
||||
|
||||
TransitionGroup *GameWindowTransitionsHandler::getNewGroup( AsciiString name )
|
||||
{
|
||||
if(name.isEmpty())
|
||||
return NULL;
|
||||
|
||||
// test to see if we're trying to add an already exisitng group.
|
||||
if(findGroup(name))
|
||||
{
|
||||
DEBUG_ASSERTCRASH(FALSE, ("GameWindowTransitionsHandler::getNewGroup - We already have a group %s", name.str()));
|
||||
return NULL;
|
||||
}
|
||||
TransitionGroup *g = NEW TransitionGroup;
|
||||
g->setName(name);
|
||||
m_transitionGroupList.push_back(g);
|
||||
return g;
|
||||
}
|
||||
|
||||
Bool GameWindowTransitionsHandler::isFinished( void )
|
||||
{
|
||||
if(m_currentGroup)
|
||||
return m_currentGroup->isFinished();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
TransitionGroup *GameWindowTransitionsHandler::findGroup( AsciiString groupName )
|
||||
{
|
||||
if(groupName.isEmpty())
|
||||
return NULL;
|
||||
|
||||
TransitionGroupList::iterator it = m_transitionGroupList.begin();
|
||||
while( it != m_transitionGroupList.end() )
|
||||
{
|
||||
TransitionGroup *g = *it;
|
||||
if(groupName.compareNoCase(g->getName()) == 0)
|
||||
return g;
|
||||
it++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GameWindowTransitionsHandler::parseWindow( INI* ini, void *instance, void *store, const void *userData )
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "WinName", INI::parseAsciiString, NULL, offsetof( TransitionWindow, m_winName ) },
|
||||
{ "Style", INI::parseLookupList, TransitionStyleNames, offsetof( TransitionWindow, m_style ) },
|
||||
{ "FrameDelay", INI::parseInt, NULL, offsetof( TransitionWindow, m_frameDelay ) },
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
};
|
||||
TransitionWindow *transWin = NEW TransitionWindow;
|
||||
ini->initFromINI(transWin, myFieldParse);
|
||||
((TransitionGroup*)instance)->addWindow(transWin);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
** 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: HeaderTemplate.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Aug 2002
|
||||
//
|
||||
// Filename: HeaderTemplate.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: The header template system is used to maintain a unified look across
|
||||
// windows. It also allows Localization to customize the looks based
|
||||
// on language fonts.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h"
|
||||
|
||||
#include "Common/INI.h"
|
||||
#include "Common/Filesystem.h"
|
||||
#include "Common/Registry.h"
|
||||
#include "GameClient/HeaderTemplate.h"
|
||||
#include "GameClient/GameFont.h"
|
||||
#include "GameClient/GlobalLanguage.h"
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
const FieldParse HeaderTemplateManager::m_headerFieldParseTable[] =
|
||||
{
|
||||
{ "Font", INI::parseQuotedAsciiString, NULL, offsetof( HeaderTemplate, m_fontName ) },
|
||||
{ "Point", INI::parseInt, NULL, offsetof( HeaderTemplate, m_point) },
|
||||
{ "Bold", INI::parseBool, NULL, offsetof( HeaderTemplate, m_bold ) },
|
||||
{ NULL, NULL, NULL, 0 },
|
||||
};
|
||||
|
||||
HeaderTemplateManager *TheHeaderTemplateManager = NULL;
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
void INI::parseHeaderTemplateDefinition( INI *ini )
|
||||
{
|
||||
AsciiString name;
|
||||
HeaderTemplate *hTemplate;
|
||||
|
||||
// read the name
|
||||
const char* c = ini->getNextToken();
|
||||
name.set( c );
|
||||
|
||||
// find existing item if present
|
||||
hTemplate = TheHeaderTemplateManager->findHeaderTemplate( name );
|
||||
if( hTemplate == NULL )
|
||||
{
|
||||
|
||||
// allocate a new item
|
||||
hTemplate = TheHeaderTemplateManager->newHeaderTemplate( name );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
DEBUG_CRASH(( "[LINE: %d in '%s'] Duplicate header Template %s found!", ini->getLineNum(), ini->getFilename().str(), name.str() ));
|
||||
}
|
||||
// parse the ini definition
|
||||
ini->initFromINI( hTemplate, TheHeaderTemplateManager->getFieldParse() );
|
||||
|
||||
} // end parseCommandButtonDefinition
|
||||
|
||||
HeaderTemplate::HeaderTemplate( void ) :
|
||||
m_font(NULL),
|
||||
m_point(0),
|
||||
m_bold(FALSE)
|
||||
{
|
||||
//Added By Sadullah Nader
|
||||
//Initializations missing and needed
|
||||
m_fontName.clear();
|
||||
m_name.clear();
|
||||
}
|
||||
|
||||
HeaderTemplate::~HeaderTemplate( void ){}
|
||||
|
||||
HeaderTemplateManager::HeaderTemplateManager( void )
|
||||
{}
|
||||
|
||||
HeaderTemplateManager::~HeaderTemplateManager( void )
|
||||
{
|
||||
HeaderTemplateListIt it = m_headerTemplateList.begin();
|
||||
while(it != m_headerTemplateList.end())
|
||||
{
|
||||
HeaderTemplate *hTemplate = *it;
|
||||
if(hTemplate)
|
||||
{
|
||||
hTemplate->m_font = NULL;
|
||||
delete hTemplate;
|
||||
}
|
||||
it = m_headerTemplateList.erase(it);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void HeaderTemplateManager::init( void )
|
||||
{
|
||||
INI ini;
|
||||
AsciiString fname;
|
||||
fname.format("Data\\%s\\HeaderTemplate.ini", GetRegistryLanguage().str());
|
||||
OSVERSIONINFO osvi;
|
||||
osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
|
||||
if (GetVersionEx(&osvi))
|
||||
{ //check if we're running Win9x variant since they may need different fonts
|
||||
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
||||
{ AsciiString tempName;
|
||||
|
||||
tempName.format("Data\\%s\\HeaderTemplate9x.ini", GetRegistryLanguage().str());
|
||||
if (TheFileSystem->doesFileExist(tempName.str()))
|
||||
fname = tempName;
|
||||
}
|
||||
}
|
||||
ini.load( fname, INI_LOAD_OVERWRITE, NULL );
|
||||
populateGameFonts();
|
||||
}
|
||||
|
||||
HeaderTemplate *HeaderTemplateManager::findHeaderTemplate( AsciiString name )
|
||||
{
|
||||
HeaderTemplateListIt it = m_headerTemplateList.begin();
|
||||
while(it != m_headerTemplateList.end())
|
||||
{
|
||||
HeaderTemplate *hTemplate = *it;
|
||||
if(hTemplate->m_name.compare(name) == 0)
|
||||
return hTemplate;
|
||||
++it;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HeaderTemplate *HeaderTemplateManager::newHeaderTemplate( AsciiString name )
|
||||
{
|
||||
HeaderTemplate *newHTemplate = NEW HeaderTemplate;
|
||||
DEBUG_ASSERTCRASH(newHTemplate, ("Unable to create a new Header Template in HeaderTemplateManager::newHeaderTemplate"));
|
||||
if(!newHTemplate)
|
||||
return NULL;
|
||||
|
||||
newHTemplate->m_name = name;
|
||||
m_headerTemplateList.push_front(newHTemplate);
|
||||
return newHTemplate;
|
||||
|
||||
}
|
||||
|
||||
GameFont *HeaderTemplateManager::getFontFromTemplate( AsciiString name )
|
||||
{
|
||||
HeaderTemplate *ht = findHeaderTemplate( name );
|
||||
if(!ht)
|
||||
{
|
||||
//DEBUG_LOG(("HeaderTemplateManager::getFontFromTemplate - Could not find header %s\n", name.str()));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ht->m_font;
|
||||
}
|
||||
|
||||
HeaderTemplate *HeaderTemplateManager::getFirstHeader( void )
|
||||
{
|
||||
HeaderTemplateListIt it = m_headerTemplateList.begin();
|
||||
if( it == m_headerTemplateList.end())
|
||||
return NULL;
|
||||
|
||||
return *it;
|
||||
}
|
||||
|
||||
HeaderTemplate *HeaderTemplateManager::getNextHeader( HeaderTemplate *ht )
|
||||
{
|
||||
HeaderTemplateListIt it = m_headerTemplateList.begin();
|
||||
while(it != m_headerTemplateList.end())
|
||||
{
|
||||
if(*it == ht)
|
||||
{
|
||||
++it;
|
||||
if( it == m_headerTemplateList.end())
|
||||
return NULL;
|
||||
return *it;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void HeaderTemplateManager::headerNotifyResolutionChange( void )
|
||||
{
|
||||
populateGameFonts();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void HeaderTemplateManager::populateGameFonts( void )
|
||||
{
|
||||
HeaderTemplateListIt it = m_headerTemplateList.begin();
|
||||
while(it != m_headerTemplateList.end())
|
||||
{
|
||||
HeaderTemplate *hTemplate = *it;
|
||||
Real pointSize = TheGlobalLanguageData->adjustFontSize(hTemplate->m_point);
|
||||
GameFont *font = TheFontLibrary->getFont(hTemplate->m_fontName, pointSize,hTemplate->m_bold);
|
||||
DEBUG_ASSERTCRASH(font,("HeaderTemplateManager::populateGameFonts - Could not find font %s %d",hTemplate->m_fontName, hTemplate->m_point));
|
||||
|
||||
hTemplate->m_font = font;
|
||||
|
||||
++it;
|
||||
}
|
||||
}
|
||||
1615
Generals/Code/GameEngine/Source/GameClient/GUI/IMEManager.cpp
Normal file
1615
Generals/Code/GameEngine/Source/GameClient/GUI/IMEManager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1456
Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
Normal file
1456
Generals/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user