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:
@@ -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
File diff suppressed because it is too large
Load Diff
833
Generals/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp
Normal file
833
Generals/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp
Normal file
@@ -0,0 +1,833 @@
|
||||
/*
|
||||
** 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: Shell.cpp ////////////////////////////////////////////////////////////////////////////////
|
||||
// Author: Colin Day, September 2001
|
||||
// Description: Shell menu representations
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/RandomValue.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#include "GameClient/GameWindowTransitions.h"
|
||||
#include "GameClient/IMEManager.h"
|
||||
#include "GameClient/AnimateWindowManager.h"
|
||||
#include "GameClient/ShellMenuScheme.h"
|
||||
#include "GameLogic/GameLogic.h"
|
||||
#include "GameNetwork/GameSpyOverlay.h"
|
||||
#include "GameNetwork/GameSpy/PeerDefsImplementation.h"
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////////////////////////
|
||||
Shell *TheShell = NULL; ///< the shell singleton definition
|
||||
|
||||
#ifdef _INTERNAL
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Shell::Shell( void )
|
||||
{
|
||||
Int i;
|
||||
|
||||
m_screenCount = 0;
|
||||
for( i = 0; i < MAX_SHELL_STACK; i++ )
|
||||
m_screenStack[ i ] = NULL;
|
||||
|
||||
m_pendingPush = FALSE;
|
||||
m_pendingPop = FALSE;
|
||||
m_pendingPushName.set( "" );
|
||||
m_isShellActive = TRUE;
|
||||
m_shellMapOn = FALSE;
|
||||
m_background = NULL;
|
||||
m_clearBackground = FALSE;
|
||||
m_animateWindowManager = NEW AnimateWindowManager;
|
||||
m_schemeManager = NEW ShellMenuSchemeManager;
|
||||
m_saveLoadMenuLayout = NULL;
|
||||
m_popupReplayLayout = NULL;
|
||||
//Added By Sadullah Nader
|
||||
//Initializations
|
||||
m_optionsLayout = NULL;
|
||||
m_screenCount = 0;
|
||||
//
|
||||
|
||||
} // end Shell
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Shell::~Shell( void )
|
||||
{
|
||||
WindowLayout *newTop = top();
|
||||
while(newTop)
|
||||
{
|
||||
popImmediate();
|
||||
newTop = top();
|
||||
}
|
||||
|
||||
if(m_background)
|
||||
{
|
||||
m_background->destroyWindows();
|
||||
m_background->deleteInstance();
|
||||
m_background = NULL;
|
||||
}
|
||||
|
||||
if(m_animateWindowManager)
|
||||
delete m_animateWindowManager;
|
||||
m_animateWindowManager = NULL;
|
||||
|
||||
if(m_schemeManager)
|
||||
delete m_schemeManager;
|
||||
m_schemeManager = NULL;
|
||||
|
||||
// delete the save/load menu if present
|
||||
if( m_saveLoadMenuLayout )
|
||||
{
|
||||
|
||||
m_saveLoadMenuLayout->destroyWindows();
|
||||
m_saveLoadMenuLayout->deleteInstance();
|
||||
m_saveLoadMenuLayout = NULL;
|
||||
|
||||
} //end if
|
||||
|
||||
// delete the replay save menu if present
|
||||
if( m_popupReplayLayout )
|
||||
{
|
||||
|
||||
m_popupReplayLayout->destroyWindows();
|
||||
m_popupReplayLayout->deleteInstance();
|
||||
m_popupReplayLayout = NULL;
|
||||
|
||||
} //end if
|
||||
|
||||
// delete the options menu if present.
|
||||
if (m_optionsLayout != NULL) {
|
||||
m_optionsLayout->destroyWindows();
|
||||
m_optionsLayout->deleteInstance();
|
||||
m_optionsLayout = NULL;
|
||||
}
|
||||
|
||||
} // end ~Shell
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Initialize the shell system */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::init( void )
|
||||
{
|
||||
INI ini;
|
||||
// Read from INI all the ShellMenuScheme
|
||||
ini.load( AsciiString( "Data\\INI\\Default\\ShellMenuScheme.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||||
ini.load( AsciiString( "Data\\INI\\ShellMenuScheme.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||||
|
||||
if( m_schemeManager )
|
||||
m_schemeManager->init();
|
||||
|
||||
} // end init
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Reset the shell system to a clean state just as though init had
|
||||
* just been called and ready to re-use */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::reset( void )
|
||||
{
|
||||
|
||||
if (TheIMEManager)
|
||||
TheIMEManager->detatch();
|
||||
|
||||
// pop all screens
|
||||
while( m_screenCount )
|
||||
pop();
|
||||
|
||||
m_animateWindowManager->reset();
|
||||
|
||||
} // end reset
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Update shell system cycle. All windows are updated that are on the stack, starting
|
||||
* with the top layout and progressing to the bottom one */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::update( void )
|
||||
{
|
||||
static Int lastUpdate = timeGetTime();
|
||||
static const Int shellUpdateDelay = 30; // try to update 30 frames a second
|
||||
Int now = timeGetTime();
|
||||
|
||||
//
|
||||
// we keep the shell updates fixed in time so that we can write consitent animation
|
||||
// speeds during the screen update functions
|
||||
//
|
||||
if( now - lastUpdate >= ((1000.0f / shellUpdateDelay ) - 1) )
|
||||
{
|
||||
|
||||
// run the updates for every window layout on the stack
|
||||
for( Int i = m_screenCount - 1; i >= 0; i-- )
|
||||
{
|
||||
|
||||
DEBUG_ASSERTCRASH( m_screenStack[ i ], ("Top of shell stack is NULL!\n") );
|
||||
m_screenStack[ i ]->runUpdate( NULL );
|
||||
|
||||
} // end for i
|
||||
if(TheGlobalData->m_shellMapOn && m_shellMapOn &&m_background)
|
||||
{
|
||||
|
||||
m_background->destroyWindows();
|
||||
m_background->deleteInstance();
|
||||
m_background = NULL;
|
||||
|
||||
}
|
||||
|
||||
// Update the animate window manager
|
||||
m_animateWindowManager->update();
|
||||
|
||||
m_schemeManager->update();
|
||||
|
||||
// mark last time we ran the updates
|
||||
lastUpdate = now;
|
||||
|
||||
} // end if
|
||||
|
||||
} // end update
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Find a screen via the .wnd script filename loaded */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowLayout *Shell::findScreenByFilename( AsciiString filename )
|
||||
{
|
||||
|
||||
if (filename.isEmpty())
|
||||
return NULL;
|
||||
|
||||
// search screen list
|
||||
WindowLayout *screen;
|
||||
Int i;
|
||||
for( i = 0; i < MAX_SHELL_STACK; i++ )
|
||||
{
|
||||
|
||||
screen = m_screenStack[ i ];
|
||||
if( screen && filename.compareNoCase(screen->getFilename()) == 0 )
|
||||
return screen;
|
||||
|
||||
} // end for i
|
||||
|
||||
return NULL;
|
||||
|
||||
} // end findScreenByFilename
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Hide or unhide all window layouts loaded */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::hide( Bool hide )
|
||||
{
|
||||
Int i;
|
||||
|
||||
for( i = 0; i < MAX_SHELL_STACK; i++ )
|
||||
if( m_screenStack[ i ] )
|
||||
m_screenStack[ i ]->hide( hide );
|
||||
|
||||
if (TheIMEManager)
|
||||
TheIMEManager->detatch();
|
||||
|
||||
} // end hide
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Push layout onto shell */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::push( AsciiString filename, Bool shutdownImmediate )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( filename.isEmpty() )
|
||||
return;
|
||||
if(TheGameSpyInfo)
|
||||
GameSpyCloseAllOverlays();
|
||||
|
||||
|
||||
#ifdef DEBUG_LOGGING
|
||||
DEBUG_LOG(("Shell:push(%s) - stack was\n", filename.str()));
|
||||
for (Int i=0; i<m_screenCount; ++i)
|
||||
{
|
||||
DEBUG_LOG(("\t\t%s\n", m_screenStack[i]->getFilename().str()));
|
||||
}
|
||||
#endif
|
||||
|
||||
// make sure we have an available spot for another screen
|
||||
if( m_screenCount >= MAX_SHELL_STACK )
|
||||
{
|
||||
|
||||
DEBUG_LOG(( "Unable to load screen '%s', max '%d' reached\n",
|
||||
filename, MAX_SHELL_STACK ));
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// set a push as pending with the layout name passed in
|
||||
m_pendingPush = TRUE;
|
||||
m_pendingPushName = filename;
|
||||
|
||||
// get the top of the current stack
|
||||
WindowLayout *currentTop = top();
|
||||
|
||||
//
|
||||
// if we have someting on the top of the stack we won't do the push
|
||||
// right now, we will instead shutdown the top, and when the top tells
|
||||
// us it's done shutting down (via the shutdownComplete() method) we do
|
||||
// the push then
|
||||
//
|
||||
if( currentTop && !currentTop->isHidden() )
|
||||
{
|
||||
|
||||
// run the shutdown
|
||||
currentTop->runShutdown( &shutdownImmediate );
|
||||
|
||||
} // end if
|
||||
else
|
||||
{
|
||||
|
||||
// just call shutdownComplete() which will immediately cause the push to happen
|
||||
shutdownComplete( NULL );
|
||||
|
||||
} // end else
|
||||
|
||||
// if (TheIMEManager)
|
||||
// TheIMEManager->detatch();
|
||||
|
||||
} // end push
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Pop top layout of the stack. Note that we don't actually do the pop right here,
|
||||
* we instead run the layout shutdown. That shutdown() in turn notifies the
|
||||
* shell when the shutdown is complete and at that point we do the actual pop */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::pop( void )
|
||||
{
|
||||
WindowLayout *screen = top();
|
||||
if(TheGameSpyInfo)
|
||||
GameSpyCloseAllOverlays();
|
||||
|
||||
|
||||
// sanity
|
||||
if( screen == NULL )
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_LOGGING
|
||||
DEBUG_LOG(("Shell:pop() - stack was\n"));
|
||||
for (Int i=0; i<m_screenCount; ++i)
|
||||
{
|
||||
DEBUG_LOG(("\t\t%s\n", m_screenStack[i]->getFilename().str()));
|
||||
}
|
||||
#endif
|
||||
|
||||
// set a pop as pending
|
||||
m_pendingPop = TRUE;
|
||||
|
||||
//
|
||||
// run the shutdown function for the screen, when it's actually shutdown it
|
||||
// will call Shell::shutdownComplete(), where the pending pop will be seen
|
||||
// and the actual pop will occur
|
||||
//
|
||||
Bool immediatePop = FALSE;
|
||||
screen->runShutdown( &immediatePop );
|
||||
|
||||
if (TheIMEManager)
|
||||
TheIMEManager->detatch();
|
||||
|
||||
} // end pop
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** When you need to immediately pop a screen off the stack use this method. It
|
||||
* gives the screen the opportunity to shutdown and tells the shutdown
|
||||
* method that an immediate pop is going to take place. When control returns
|
||||
* from the shutdown() for the screen, it will be immediately popped off
|
||||
* the stack */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::popImmediate( void )
|
||||
{
|
||||
WindowLayout *screen = top();
|
||||
|
||||
// sanity
|
||||
if( screen == NULL )
|
||||
return;
|
||||
|
||||
#ifdef DEBUG_LOGGING
|
||||
DEBUG_LOG(("Shell:popImmediate() - stack was\n"));
|
||||
for (Int i=0; i<m_screenCount; ++i)
|
||||
{
|
||||
DEBUG_LOG(("\t\t%s\n", m_screenStack[i]->getFilename().str()));
|
||||
}
|
||||
#endif
|
||||
|
||||
// do NOT set pending pop, we are going to force a pop after the shutdown is run
|
||||
m_pendingPop = FALSE;
|
||||
|
||||
// run the shutdown
|
||||
Bool immediatePop = TRUE;
|
||||
screen->runShutdown( &immediatePop );
|
||||
|
||||
// pop the screen of the stack
|
||||
doPop( FALSE );
|
||||
|
||||
if (TheIMEManager)
|
||||
TheIMEManager->detatch();
|
||||
|
||||
} // end popImmediate
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Run the initialize function for the top of the stack just as though it was pushed
|
||||
* on the stack. We want this behavior when we want to act like the top was just
|
||||
* pushed on the stack, but it's already there (ie going from in game back to the
|
||||
* pre-game shell menus */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::showShell( Bool runInit )
|
||||
{
|
||||
DEBUG_LOG(("Shell:showShell() - %s (%s)\n", TheGlobalData->m_initialFile.str(), (top())?top()->getFilename().str():"no top screen"));
|
||||
|
||||
if(!TheGlobalData->m_initialFile.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// runInit is used if we want show shell to run
|
||||
if(runInit)
|
||||
{
|
||||
WindowLayout *layout = top();
|
||||
|
||||
if( layout )
|
||||
{
|
||||
layout->runInit( NULL );
|
||||
// layout->bringForward();
|
||||
}
|
||||
}
|
||||
// @todo remove this hack
|
||||
// TheGlobalData->m_inGame = FALSE;
|
||||
// add in the background stuff
|
||||
|
||||
// if(TheGlobalData->m_shellMapOn)
|
||||
// {
|
||||
// if( top() )
|
||||
// top()->hide(TRUE);
|
||||
// m_background = TheWindowManager->winCreateLayout("Menus/BlankWindow.wnd");
|
||||
// DEBUG_ASSERTCRASH(m_background,("We Couldn't Load Menus/BlankWindow.wnd"));
|
||||
// m_background->hide(FALSE);
|
||||
// m_background->bringForward();
|
||||
// if (TheGameLogic->isInGame())
|
||||
// TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_GAME_DATA );
|
||||
//
|
||||
// TheGlobalData->m_pendingFile = TheGlobalData->m_shellMapName;
|
||||
// GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
|
||||
// msg->appendIntegerArgument(GAME_SHELL);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
//
|
||||
// m_background = TheWindowManager->winCreateLayout("Menus/BlankWindow.wnd");
|
||||
//
|
||||
// DEBUG_ASSERTCRASH(m_background,("We Couldn't Load Menus/BlankWindow.wnd"));
|
||||
// m_background->hide(FALSE);
|
||||
// if (top())
|
||||
// top()->bringForward();
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
if (!TheGlobalData->m_shellMapOn && m_screenCount == 0)
|
||||
//else
|
||||
TheShell->push( AsciiString("Menus/MainMenu.wnd") );
|
||||
m_isShellActive = TRUE;
|
||||
} // end showShell
|
||||
|
||||
void Shell::showShellMap(Bool useShellMap )
|
||||
{
|
||||
// we don't want any of this to show if we're loading straight into a file
|
||||
if(TheGlobalData->m_initialFile.isNotEmpty() || !TheGameLogic )
|
||||
return;
|
||||
if(useShellMap && TheGlobalData->m_shellMapOn)
|
||||
{
|
||||
// we're already in a shell game, return
|
||||
if(TheGameLogic->isInGame() && TheGameLogic->getGameMode() == GAME_SHELL)
|
||||
return;
|
||||
// we're in some other kind of game, clear it out foo!
|
||||
if(TheGameLogic->isInGame())
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_GAME_DATA );
|
||||
|
||||
TheWritableGlobalData->m_pendingFile = TheGlobalData->m_shellMapName;
|
||||
InitGameLogicRandom(0);
|
||||
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_NEW_GAME );
|
||||
msg->appendIntegerArgument(GAME_SHELL);
|
||||
m_shellMapOn = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we're in a shell game, stop it!
|
||||
if(TheGameLogic->isInGame() && TheGameLogic->getGameMode() == GAME_SHELL)
|
||||
TheMessageStream->appendMessage( GameMessage::MSG_CLEAR_GAME_DATA );
|
||||
|
||||
// if the shell is active,we need a background
|
||||
if(!m_isShellActive)
|
||||
return;
|
||||
if(!m_background)
|
||||
m_background = TheWindowManager->winCreateLayout("Menus/BlankWindow.wnd");
|
||||
|
||||
DEBUG_ASSERTCRASH(m_background,("We Couldn't Load Menus/BlankWindow.wnd"));
|
||||
m_background->getFirstWindow()->winSetStatus(WIN_STATUS_IMAGE);
|
||||
m_background->hide(FALSE);
|
||||
if (top())
|
||||
top()->bringForward();
|
||||
m_shellMapOn = FALSE;
|
||||
m_clearBackground = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Run the shutdown() function for the top of the stack just like we're going to pop
|
||||
* it off but DO NOT pop it off the stack. We want this behavior when leaving the
|
||||
* pre-game menus and entering the game and want the shell to still exist and contain
|
||||
* the stack information but don't want it to go away */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::hideShell( void )
|
||||
{
|
||||
// If we have the 3d background running, mark it to close
|
||||
m_clearBackground = TRUE;
|
||||
|
||||
DEBUG_LOG(("Shell:hideShell() - %s\n", (top())?top()->getFilename().str():"no top screen"));
|
||||
|
||||
WindowLayout *layout = top();
|
||||
|
||||
if( layout )
|
||||
{
|
||||
Bool immediatePop = TRUE;
|
||||
|
||||
layout->runShutdown( &immediatePop );
|
||||
|
||||
} // end if
|
||||
|
||||
if (TheIMEManager)
|
||||
TheIMEManager->detatch();
|
||||
|
||||
// Mark that the shell is no longer up.
|
||||
m_isShellActive = FALSE;
|
||||
|
||||
} // end hideShell
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Return the top layout on the stack */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowLayout *Shell::top( void )
|
||||
{
|
||||
|
||||
// emtpy stack
|
||||
if( m_screenCount == 0 )
|
||||
return NULL;
|
||||
|
||||
// top layout is at count index
|
||||
return m_screenStack[ m_screenCount - 1 ];
|
||||
|
||||
} // end top
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Add screen to our list */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::linkScreen( WindowLayout *screen )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( screen == NULL )
|
||||
return;
|
||||
|
||||
// check to see if at top already
|
||||
if( m_screenCount == MAX_SHELL_STACK )
|
||||
{
|
||||
|
||||
DEBUG_CRASH(( "No room in shell stack for screen\n" ));
|
||||
return;
|
||||
|
||||
} // end if
|
||||
|
||||
// add to array at top index
|
||||
m_screenStack[ m_screenCount++ ] = screen;
|
||||
|
||||
} // end linkScreen
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Remove screen from our list */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::unlinkScreen( WindowLayout *screen )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( screen == NULL )
|
||||
return;
|
||||
|
||||
DEBUG_ASSERTCRASH( m_screenStack[ m_screenCount - 1 ] == screen,
|
||||
("Screen not on top of stack\n") );
|
||||
|
||||
// remove reference to screen and decrease count
|
||||
if( m_screenStack[ m_screenCount - 1 ] == screen )
|
||||
m_screenStack[ --m_screenCount ] = NULL;
|
||||
|
||||
} // end unlinkScreen
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Actually do the work for a push */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::doPush( AsciiString layoutFile )
|
||||
{
|
||||
if(TheGameSpyInfo)
|
||||
GameSpyCloseAllOverlays();
|
||||
WindowLayout *newScreen;
|
||||
|
||||
// create new layout and load from window manager
|
||||
newScreen = TheWindowManager->winCreateLayout( layoutFile );
|
||||
DEBUG_ASSERTCRASH( newScreen != NULL, ("Shell unable to load pending push layout\n") );
|
||||
|
||||
// link screen to the top
|
||||
linkScreen( newScreen );
|
||||
|
||||
if (TheIMEManager)
|
||||
TheIMEManager->detatch();
|
||||
|
||||
// run the init function automatically
|
||||
newScreen->runInit( NULL );
|
||||
newScreen->bringForward();
|
||||
|
||||
|
||||
} // end doPush
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Actually do the work for a pop */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::doPop( Bool impendingPush )
|
||||
{
|
||||
WindowLayout *currentTop = top();
|
||||
|
||||
// there better be a top of the stack since we're popping
|
||||
DEBUG_ASSERTCRASH( currentTop, ("Shell: No top of stack and we want to pop!\n") );
|
||||
|
||||
// remove this screen from our list
|
||||
unlinkScreen( currentTop );
|
||||
|
||||
// delete all the windows in the screen
|
||||
currentTop->destroyWindows();
|
||||
|
||||
// release the screen object back to the memory pool
|
||||
currentTop->deleteInstance();
|
||||
|
||||
// run the init for the new top of the stack if present
|
||||
WindowLayout *newTop = top();
|
||||
if( newTop && !impendingPush )
|
||||
{
|
||||
newTop->runInit( NULL );
|
||||
//newTop->bringForward();
|
||||
}
|
||||
|
||||
if (TheIMEManager)
|
||||
TheIMEManager->detatch();
|
||||
|
||||
} // end doPop
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** This is called when a layout has finished its shutdown process. Layouts are
|
||||
* shutdown when a new screen is being pushed on the stack, or when we are
|
||||
* popping the current screen off the top of the stack. It is here that we
|
||||
* can look for any pending push or pop operations and actually do them
|
||||
*
|
||||
* NOTE: It is possible for the screen parameter to be NULL when we are
|
||||
* short circuiting the shutdown logic because there is no layout
|
||||
* to actually shutdown (ie, the stack is empty and we push) */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void Shell::shutdownComplete( WindowLayout *screen, Bool impendingPush )
|
||||
{
|
||||
|
||||
// there should never be a pending push AND pop operation
|
||||
DEBUG_ASSERTCRASH( m_pendingPush == FALSE || m_pendingPop == FALSE,
|
||||
("There is a pending push AND pop in the shell. Not allowed!\n") );
|
||||
|
||||
// Reset the AnimateWindowManager
|
||||
m_animateWindowManager->reset();
|
||||
|
||||
// check for pending push or pop
|
||||
if( m_pendingPush )
|
||||
{
|
||||
|
||||
// do the push
|
||||
doPush( m_pendingPushName );
|
||||
|
||||
// no more pending pushy for you!
|
||||
m_pendingPush = FALSE;
|
||||
m_pendingPushName.set( "" );
|
||||
|
||||
} // end if
|
||||
else if( m_pendingPop )
|
||||
{
|
||||
|
||||
// do the pop
|
||||
doPop( impendingPush );
|
||||
|
||||
// no more pending pop for you!
|
||||
m_pendingPop = FALSE;
|
||||
|
||||
} // end else if
|
||||
|
||||
if(m_clearBackground)
|
||||
{
|
||||
if(m_background)
|
||||
{
|
||||
m_background->destroyWindows();
|
||||
m_background->deleteInstance();
|
||||
m_background = NULL;
|
||||
m_clearBackground = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // end shutdownComplete
|
||||
|
||||
|
||||
void Shell::registerWithAnimateManager( GameWindow *win, AnimTypes animType, Bool needsToFinish, UnsignedInt delayMS)
|
||||
{
|
||||
if(!m_animateWindowManager)
|
||||
{
|
||||
DEBUG_CRASH(("We called registerWithAnimateManager and we don't have an Animate Manager created"));
|
||||
return;
|
||||
}
|
||||
if (TheGlobalData->m_animateWindows)
|
||||
m_animateWindowManager->registerGameWindow(win,animType,needsToFinish, 500,delayMS);
|
||||
}
|
||||
|
||||
Bool Shell::isAnimFinished( void )
|
||||
{
|
||||
// check the new way also.
|
||||
if (!TheTransitionHandler->isFinished())
|
||||
return FALSE;
|
||||
|
||||
if(!m_animateWindowManager)
|
||||
{
|
||||
DEBUG_CRASH(("We called registerWithAnimateManager and we don't have an Animate Manager created"));
|
||||
return TRUE;
|
||||
}
|
||||
if (TheGlobalData->m_animateWindows)
|
||||
return m_animateWindowManager->isFinished();
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Shell::reverseAnimatewindow( void )
|
||||
{
|
||||
if(!m_animateWindowManager)
|
||||
{
|
||||
DEBUG_CRASH(("We called registerWithAnimateManager and we don't have an Animate Manager created"));
|
||||
return;
|
||||
}
|
||||
if (TheGlobalData->m_animateWindows)
|
||||
m_animateWindowManager->reverseAnimateWindow();
|
||||
}
|
||||
|
||||
Bool Shell::isAnimReversed( void )
|
||||
{
|
||||
if(!m_animateWindowManager)
|
||||
{
|
||||
DEBUG_CRASH(("We called registerWithAnimateManager and we don't have an Animate Manager created"));
|
||||
return TRUE;
|
||||
}
|
||||
if (TheGlobalData->m_animateWindows)
|
||||
return m_animateWindowManager->isReversed();
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void Shell::loadScheme( AsciiString name )
|
||||
{
|
||||
if(!m_schemeManager)
|
||||
return;
|
||||
|
||||
m_schemeManager->setShellMenuScheme( name );
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
WindowLayout *Shell::getSaveLoadMenuLayout( void )
|
||||
{
|
||||
|
||||
// if layout has not been created, create it now
|
||||
if( m_saveLoadMenuLayout == NULL )
|
||||
m_saveLoadMenuLayout = TheWindowManager->winCreateLayout( AsciiString( "Menus/PopupSaveLoad.wnd" ) );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( m_saveLoadMenuLayout, ("Unable to create save/load menu layout\n") );
|
||||
|
||||
// return the layout
|
||||
return m_saveLoadMenuLayout;
|
||||
|
||||
} // end getSaveLoadMenuLayout
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
WindowLayout *Shell::getPopupReplayLayout( void )
|
||||
{
|
||||
|
||||
// if layout has not been created, create it now
|
||||
if( m_popupReplayLayout == NULL )
|
||||
m_popupReplayLayout = TheWindowManager->winCreateLayout( AsciiString( "Menus/PopupReplay.wnd" ) );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( m_popupReplayLayout, ("Unable to create replay save menu layout\n") );
|
||||
|
||||
// return the layout
|
||||
return m_popupReplayLayout;
|
||||
|
||||
} // end getSaveLoadMenuLayout
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
WindowLayout *Shell::getOptionsLayout( Bool create )
|
||||
{
|
||||
// if layout has not been created, create it now
|
||||
if ((m_optionsLayout == NULL) && (create == TRUE))
|
||||
{
|
||||
m_optionsLayout = TheWindowManager->winCreateLayout( AsciiString( "Menus/OptionsMenu.wnd" ) );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( m_optionsLayout, ("Unable to create options menu layout\n") );
|
||||
}
|
||||
|
||||
// return the layout
|
||||
return m_optionsLayout;
|
||||
} // end getOptionsLayout
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Shell::destroyOptionsLayout() {
|
||||
if (m_optionsLayout != NULL) {
|
||||
m_optionsLayout->destroyWindows();
|
||||
m_optionsLayout->deleteInstance();
|
||||
m_optionsLayout = NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
** 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: ShellMenuScheme.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Jul 2002
|
||||
//
|
||||
// Filename: ShellMenuScheme.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose:
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "Common/INI.h"
|
||||
#include "GameClient/ShellMenuScheme.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/Display.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const FieldParse ShellMenuSchemeManager::m_shellMenuSchemeFieldParseTable[] =
|
||||
{
|
||||
|
||||
{ "ImagePart", ShellMenuSchemeManager::parseImagePart, NULL, NULL },
|
||||
{ "LinePart", ShellMenuSchemeManager::parseLinePart, NULL, NULL },
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
void INI::parseShellMenuSchemeDefinition( INI *ini )
|
||||
{
|
||||
AsciiString name;
|
||||
ShellMenuSchemeManager *SMSchemeManager;
|
||||
ShellMenuScheme *SMScheme;
|
||||
|
||||
// read the name
|
||||
const char* c = ini->getNextToken();
|
||||
name.set( c );
|
||||
|
||||
// find existing item if present
|
||||
SMSchemeManager = TheShell->getShellMenuSchemeManager();
|
||||
DEBUG_ASSERTCRASH( SMSchemeManager, ("parseShellMenuSchemeDefinition: Unable to Get SMSchemeManager\n") );
|
||||
if( !SMSchemeManager )
|
||||
return;
|
||||
|
||||
// If we have a previously allocated control bar, this will return a cleared out pointer to it so we
|
||||
// can overwrite it
|
||||
SMScheme = SMSchemeManager->newShellMenuScheme( name );
|
||||
|
||||
// sanity
|
||||
DEBUG_ASSERTCRASH( SMScheme, ("parseControlBarSchemeDefinition: Unable to allocate Scheme '%s'\n", name.str()) );
|
||||
|
||||
// parse the ini definition
|
||||
ini->initFromINI( SMScheme, SMSchemeManager->getFieldParse() );
|
||||
|
||||
} // end parseCommandButtonDefinition
|
||||
|
||||
ShellMenuSchemeLine::ShellMenuSchemeLine( void )
|
||||
{
|
||||
m_startPos.x = m_startPos.y = 0;
|
||||
m_endPos.x = m_endPos.y = 0;
|
||||
m_color = GAME_COLOR_UNDEFINED;
|
||||
m_width = 1;
|
||||
}
|
||||
ShellMenuSchemeLine::~ShellMenuSchemeLine( void )
|
||||
{
|
||||
}
|
||||
|
||||
ShellMenuSchemeImage::ShellMenuSchemeImage( void )
|
||||
{
|
||||
m_name.clear();
|
||||
m_position.x = m_position.y = 0;
|
||||
m_size.x = m_size.x = 0;
|
||||
m_image = NULL;
|
||||
}
|
||||
|
||||
ShellMenuSchemeImage::~ShellMenuSchemeImage( void )
|
||||
{
|
||||
m_image = NULL;
|
||||
}
|
||||
|
||||
ShellMenuScheme::ShellMenuScheme( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ShellMenuScheme::~ShellMenuScheme( void )
|
||||
{
|
||||
ShellMenuSchemeImageListIt it = m_imageList.begin();
|
||||
while(it != m_imageList.end())
|
||||
{
|
||||
ShellMenuSchemeImage *image = *it;
|
||||
it = m_imageList.erase( it );
|
||||
if(image)
|
||||
delete image;
|
||||
}
|
||||
|
||||
ShellMenuSchemeLineListIt lineIt = m_lineList.begin();
|
||||
while(lineIt != m_lineList.end())
|
||||
{
|
||||
ShellMenuSchemeLine *line = *lineIt;
|
||||
lineIt = m_lineList.erase( lineIt );
|
||||
if(line)
|
||||
delete line;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ShellMenuScheme::addLine( ShellMenuSchemeLine* schemeLine )
|
||||
{
|
||||
if(!schemeLine)
|
||||
return;
|
||||
|
||||
m_lineList.push_back( schemeLine );
|
||||
}
|
||||
|
||||
|
||||
void ShellMenuScheme::addImage( ShellMenuSchemeImage* schemeImage )
|
||||
{
|
||||
if(!schemeImage)
|
||||
return;
|
||||
|
||||
m_imageList.push_back( schemeImage );
|
||||
}
|
||||
|
||||
void ShellMenuScheme::draw( void )
|
||||
{
|
||||
|
||||
ShellMenuSchemeImageListIt imageIt = m_imageList.begin();
|
||||
while(imageIt != m_imageList.end())
|
||||
{
|
||||
ShellMenuSchemeImage *image = *imageIt;
|
||||
if(image && image->m_image)
|
||||
{
|
||||
TheDisplay->drawImage(image->m_image, image->m_position.x, image->m_position.y,
|
||||
image->m_position.x + image->m_size.x , image->m_position.y + image->m_size.y);
|
||||
}
|
||||
++imageIt;
|
||||
}
|
||||
|
||||
ShellMenuSchemeLineListIt it = m_lineList.begin();
|
||||
while(it != m_lineList.end())
|
||||
{
|
||||
ShellMenuSchemeLine *line = *it;
|
||||
|
||||
if(line)
|
||||
{
|
||||
TheDisplay->drawLine(line->m_startPos.x, line->m_startPos.y, line->m_endPos.x,
|
||||
line->m_endPos.y,line->m_width, line->m_color);
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
ShellMenuSchemeManager::ShellMenuSchemeManager( void )
|
||||
{
|
||||
m_currentScheme = NULL;
|
||||
}
|
||||
|
||||
ShellMenuSchemeManager::~ShellMenuSchemeManager( void )
|
||||
{
|
||||
m_currentScheme = NULL;
|
||||
|
||||
|
||||
ShellMenuSchemeListIt it = m_schemeList.begin();
|
||||
while(it != m_schemeList.end())
|
||||
{
|
||||
ShellMenuScheme *scheme = *it;
|
||||
it = m_schemeList.erase( it );
|
||||
if(scheme)
|
||||
delete scheme;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ShellMenuSchemeManager::parseImagePart(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "Position", INI::parseICoord2D, NULL, offsetof( ShellMenuSchemeImage, m_position ) },
|
||||
{ "Size", INI::parseICoord2D, NULL, offsetof( ShellMenuSchemeImage, m_size ) },
|
||||
{ "ImageName", INI::parseMappedImage, NULL, offsetof( ShellMenuSchemeImage, m_image ) },
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
};
|
||||
|
||||
ShellMenuSchemeImage *schemeImage = NEW ShellMenuSchemeImage;
|
||||
ini->initFromINI(schemeImage, myFieldParse);
|
||||
((ShellMenuScheme*)instance)->addImage(schemeImage);
|
||||
|
||||
}
|
||||
|
||||
void ShellMenuSchemeManager::parseLinePart(INI *ini, void *instance, void* /*store*/, const void* /*userData*/)
|
||||
{
|
||||
static const FieldParse myFieldParse[] =
|
||||
{
|
||||
{ "StartPosition", INI::parseICoord2D, NULL, offsetof( ShellMenuSchemeLine, m_startPos ) },
|
||||
{ "EndPosition", INI::parseICoord2D, NULL, offsetof( ShellMenuSchemeLine, m_endPos ) },
|
||||
{ "Color", INI::parseColorInt, NULL, offsetof( ShellMenuSchemeLine, m_color ) },
|
||||
{ "Width", INI::parseInt, NULL, offsetof( ShellMenuSchemeLine, m_width ) },
|
||||
|
||||
{ NULL, NULL, NULL, 0 } // keep this last
|
||||
};
|
||||
|
||||
ShellMenuSchemeLine *schemeLine = NEW ShellMenuSchemeLine;
|
||||
ini->initFromINI(schemeLine, myFieldParse);
|
||||
((ShellMenuScheme*)instance)->addLine(schemeLine);
|
||||
|
||||
}
|
||||
|
||||
ShellMenuScheme *ShellMenuSchemeManager::newShellMenuScheme(AsciiString name)
|
||||
{
|
||||
ShellMenuSchemeListIt it;
|
||||
it = m_schemeList.begin();
|
||||
name.toLower();
|
||||
while(it != m_schemeList.end())
|
||||
{
|
||||
ShellMenuScheme *scheme = *it;
|
||||
if(scheme->m_name.compare(name) == 0)
|
||||
{
|
||||
m_schemeList.erase( it );
|
||||
delete scheme;
|
||||
break;
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
ShellMenuScheme *newScheme = NEW ShellMenuScheme;
|
||||
newScheme->m_name.set(name);
|
||||
m_schemeList.push_back(newScheme);
|
||||
return newScheme;
|
||||
}
|
||||
|
||||
void ShellMenuSchemeManager::init( void )
|
||||
{
|
||||
INI ini;
|
||||
// Read from INI all the ControlBarSchemes
|
||||
ini.load( AsciiString( "Data\\INI\\Default\\ShellMenuScheme.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||||
ini.load( AsciiString( "Data\\INI\\ShellMenuScheme.ini" ), INI_LOAD_OVERWRITE, NULL );
|
||||
|
||||
}
|
||||
|
||||
void ShellMenuSchemeManager::setShellMenuScheme( AsciiString name )
|
||||
{
|
||||
if(name.isEmpty())
|
||||
{
|
||||
m_currentScheme = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
ShellMenuSchemeListIt it;
|
||||
it = m_schemeList.begin();
|
||||
name.toLower();
|
||||
while(it != m_schemeList.end())
|
||||
{
|
||||
ShellMenuScheme *scheme = *it;
|
||||
if(scheme->m_name.compare(name) == 0)
|
||||
{
|
||||
m_currentScheme = scheme;
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void ShellMenuSchemeManager::draw( void )
|
||||
{
|
||||
if(m_currentScheme)
|
||||
m_currentScheme->draw();
|
||||
}
|
||||
|
||||
void ShellMenuSchemeManager::update( void )
|
||||
{
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -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: WinInstanceData.cpp //////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Westwood Studios Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2001 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Project: RTS3
|
||||
//
|
||||
// File name: WinInstanceData.cpp
|
||||
//
|
||||
// Created: Colin Day, July 2001
|
||||
//
|
||||
// Desc: Game window instance data
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
#include "GameClient/WinInstanceData.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/DisplayStringManager.h"
|
||||
#include "Common/Debug.h"
|
||||
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE TYPES //////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE DATA ///////////////////////////////////////////////////////////////
|
||||
|
||||
// PUBLIC DATA ////////////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE PROTOTYPES /////////////////////////////////////////////////////////
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// WinInstanceData::WinInstanceData ===========================================
|
||||
//=============================================================================
|
||||
WinInstanceData::WinInstanceData( void )
|
||||
{
|
||||
|
||||
// we don't allocate strings unless we need them
|
||||
m_text = NULL;
|
||||
m_tooltip = NULL;
|
||||
m_videoBuffer = NULL;
|
||||
init();
|
||||
|
||||
} // end WinInstanceData
|
||||
|
||||
// WinInstanceData::~WinInstanceData ==========================================
|
||||
//=============================================================================
|
||||
WinInstanceData::~WinInstanceData( void )
|
||||
{
|
||||
|
||||
if( m_text )
|
||||
TheDisplayStringManager->freeDisplayString( m_text );
|
||||
|
||||
if( m_tooltip )
|
||||
TheDisplayStringManager->freeDisplayString( m_tooltip );
|
||||
|
||||
m_videoBuffer = NULL; //Video Buffer needs to be clean up by the control that is in charge of the video.
|
||||
|
||||
} // end ~WinInstanceData
|
||||
|
||||
// WinInstanceData::init ======================================================
|
||||
/** Set initial values for instance data if desired */
|
||||
//=============================================================================
|
||||
void WinInstanceData::init( void )
|
||||
{
|
||||
Int i;
|
||||
|
||||
// init our draw data images/colors for the states
|
||||
for( i = 0; i < MAX_DRAW_DATA; i++ )
|
||||
{
|
||||
|
||||
m_enabledDrawData[ i ].image = NULL;
|
||||
m_enabledDrawData[ i ].color = WIN_COLOR_UNDEFINED;
|
||||
m_enabledDrawData[ i ].borderColor = WIN_COLOR_UNDEFINED;
|
||||
|
||||
m_disabledDrawData[ i ].image = NULL;
|
||||
m_disabledDrawData[ i ].color = WIN_COLOR_UNDEFINED;
|
||||
m_disabledDrawData[ i ].borderColor = WIN_COLOR_UNDEFINED;
|
||||
|
||||
m_hiliteDrawData[ i ].image = NULL;
|
||||
m_hiliteDrawData[ i ].color = WIN_COLOR_UNDEFINED;
|
||||
m_hiliteDrawData[ i ].borderColor = WIN_COLOR_UNDEFINED;
|
||||
|
||||
} // end for i
|
||||
|
||||
// initialize text colors
|
||||
m_enabledText.color = WIN_COLOR_UNDEFINED;
|
||||
m_enabledText.borderColor = WIN_COLOR_UNDEFINED;
|
||||
m_disabledText.color = WIN_COLOR_UNDEFINED;
|
||||
m_disabledText.borderColor = WIN_COLOR_UNDEFINED;
|
||||
m_hiliteText.color = WIN_COLOR_UNDEFINED;
|
||||
m_hiliteText.borderColor = WIN_COLOR_UNDEFINED;
|
||||
|
||||
m_id = 0;
|
||||
m_state = 0;
|
||||
m_style = 0;
|
||||
m_status = WIN_STATUS_NONE;
|
||||
m_owner = NULL;
|
||||
m_textLabelString.clear();
|
||||
m_tooltipString.clear();
|
||||
m_tooltipDelay = -1; ///< default value
|
||||
m_decoratedNameString.clear();
|
||||
|
||||
m_imageOffset.x = 0;
|
||||
m_imageOffset.y = 0;
|
||||
|
||||
// reset all data for the text display strings and font for window
|
||||
m_font = NULL;
|
||||
if( m_text )
|
||||
{
|
||||
|
||||
TheDisplayStringManager->freeDisplayString( m_text );
|
||||
m_text = NULL;
|
||||
|
||||
} // end if
|
||||
if( m_tooltip )
|
||||
{
|
||||
|
||||
TheDisplayStringManager->freeDisplayString( m_tooltip );
|
||||
m_tooltip = NULL;
|
||||
|
||||
} // end if
|
||||
|
||||
m_videoBuffer = NULL;
|
||||
|
||||
|
||||
} // end init
|
||||
|
||||
// WinInstanceData::setTooltipText ============================================
|
||||
//=============================================================================
|
||||
void WinInstanceData::setTooltipText( UnicodeString tip )
|
||||
{
|
||||
|
||||
// allocate a text tooltip string if needed
|
||||
if( m_tooltip == NULL )
|
||||
m_tooltip = TheDisplayStringManager->newDisplayString();
|
||||
DEBUG_ASSERTCRASH( m_tooltip, ("no tooltip") );
|
||||
|
||||
// set text
|
||||
m_tooltip->setText( tip );
|
||||
|
||||
} // end setTooltipText
|
||||
|
||||
// WinInstanceData:setText ====================================================
|
||||
/** Set the text for this window instance data */
|
||||
//=============================================================================
|
||||
void WinInstanceData::setText( UnicodeString text )
|
||||
{
|
||||
|
||||
// allocate a text instance if needed
|
||||
if( m_text == NULL )
|
||||
m_text = TheDisplayStringManager->newDisplayString();
|
||||
DEBUG_ASSERTCRASH( m_text, ("no text") );
|
||||
|
||||
// set the text
|
||||
m_text->setText( text );
|
||||
|
||||
} // end set text
|
||||
|
||||
// WinInstanceData:setText ====================================================
|
||||
/** Set the text for this window instance data */
|
||||
//=============================================================================
|
||||
void WinInstanceData::setVideoBuffer( VideoBuffer * videoBuffer )
|
||||
{
|
||||
m_videoBuffer = videoBuffer;
|
||||
}
|
||||
308
Generals/Code/GameEngine/Source/GameClient/GUI/WindowLayout.cpp
Normal file
308
Generals/Code/GameEngine/Source/GameClient/GUI/WindowLayout.cpp
Normal file
@@ -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: WindowLayout.cpp /////////////////////////////////////////////////////////////////////////
|
||||
// Created: Colin Day, September 2001
|
||||
// Desc: Layouts for grouping windows together
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/WindowLayout.h"
|
||||
#include "GameClient/Shell.h"
|
||||
#include "GameClient/GameWindowManager.h"
|
||||
#ifdef _INTERNAL
|
||||
|
||||
// for occasional debugging...
|
||||
//#pragma optimize("", off)
|
||||
//#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
|
||||
#endif
|
||||
|
||||
// PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowLayout::WindowLayout( void )
|
||||
{
|
||||
m_filenameString.set("EmptyLayout");
|
||||
|
||||
m_windowList = NULL;
|
||||
m_windowTail = NULL;
|
||||
m_windowCount = 0;
|
||||
|
||||
m_hidden = FALSE;
|
||||
|
||||
m_init = NULL;
|
||||
m_update = NULL;
|
||||
m_shutdown = NULL;
|
||||
|
||||
} // end WindowLayout
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
WindowLayout::~WindowLayout( void )
|
||||
{
|
||||
|
||||
//
|
||||
// it is the users responsability to remove windows from the layout beforing destroying the
|
||||
// layout itself. This allows for maximum flexibility of the window layouts and you can
|
||||
// use them in any you see fit, as long as they are clean when they go away
|
||||
//
|
||||
DEBUG_ASSERTCRASH( m_windowList == NULL, ("Window layout being destroyed still has window references") );
|
||||
DEBUG_ASSERTCRASH( m_windowTail == NULL, ("Window layout being destroyed still has window references") );
|
||||
|
||||
} // end ~WindowLayout
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Set the hidden/visible status of all the windows in this layout */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WindowLayout::hide( Bool hide )
|
||||
{
|
||||
GameWindow *window;
|
||||
|
||||
// hide or unhide all windows in this layout
|
||||
for( window = m_windowList; window; window = window->winGetNextInLayout() )
|
||||
{
|
||||
|
||||
window->winHide( hide );
|
||||
|
||||
} // end for window
|
||||
|
||||
// save the new visible state of the system
|
||||
m_hidden = hide;
|
||||
|
||||
} // end hide
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Add window to this layout */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WindowLayout::addWindow( GameWindow *window )
|
||||
{
|
||||
GameWindow *win = findWindow( window );
|
||||
|
||||
// only add window if window is not in this layout already
|
||||
if( win == NULL )
|
||||
{
|
||||
|
||||
DEBUG_ASSERTCRASH( window->winGetNextInLayout() == NULL,
|
||||
("NextInLayout should be NULL before adding") );
|
||||
DEBUG_ASSERTCRASH( window->winGetPrevInLayout() == NULL,
|
||||
("PrevInLayout should be NULL before adding") );
|
||||
|
||||
window->winSetPrevInLayout( NULL );
|
||||
window->winSetNextInLayout( m_windowList );
|
||||
if( m_windowList )
|
||||
m_windowList->winSetPrevInLayout( window );
|
||||
m_windowList = window;
|
||||
|
||||
// set layout into window
|
||||
window->winSetLayout( this );
|
||||
|
||||
// if no tail pointer, this is it
|
||||
if( m_windowTail == NULL )
|
||||
m_windowTail = window;
|
||||
|
||||
// we gots another window now
|
||||
m_windowCount++;
|
||||
|
||||
} // end if
|
||||
|
||||
} // end addWindow
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Remove window from this layout */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WindowLayout::removeWindow( GameWindow *window )
|
||||
{
|
||||
GameWindow *win = findWindow( window );
|
||||
|
||||
// can't remove window unless it's really part of this layout
|
||||
if( win )
|
||||
{
|
||||
GameWindow *prev, *next;
|
||||
|
||||
prev = win->winGetPrevInLayout();
|
||||
next = win->winGetNextInLayout();
|
||||
|
||||
if( next )
|
||||
next->winSetPrevInLayout( prev );
|
||||
if( prev )
|
||||
prev->winSetNextInLayout( next );
|
||||
else
|
||||
m_windowList = next;
|
||||
|
||||
// set window as having no layout info
|
||||
win->winSetLayout( NULL );
|
||||
win->winSetNextInLayout( NULL );
|
||||
win->winSetPrevInLayout( NULL );
|
||||
|
||||
// if we removed the tail, set the new tail
|
||||
if( m_windowTail == win )
|
||||
m_windowTail = prev;
|
||||
|
||||
// we lost one sir!
|
||||
m_windowCount--;
|
||||
|
||||
} // end if
|
||||
|
||||
} // end removeWindow
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Destroy all the windows in a layout */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WindowLayout::destroyWindows( void )
|
||||
{
|
||||
if (this == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
GameWindow *window;
|
||||
|
||||
while( (window = getFirstWindow()) != 0 )
|
||||
{
|
||||
|
||||
// remove window from this layout
|
||||
removeWindow( window );
|
||||
|
||||
// destroy window in window system
|
||||
TheWindowManager->winDestroy( window );
|
||||
|
||||
} // end while
|
||||
|
||||
} // end destroyWindows
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Create the windows using the .wnd file script and load all windows into
|
||||
* this layout */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Bool WindowLayout::load( AsciiString filename )
|
||||
{
|
||||
|
||||
// sanity
|
||||
if( filename.isEmpty() )
|
||||
return FALSE;
|
||||
|
||||
//
|
||||
// when we create new windows they are always placed on the top
|
||||
// of the window stack. The load layout from script will return the
|
||||
// FIRST window loaded from the script, if we traverse from the head of
|
||||
// the window list till we see that window returned from the layout
|
||||
// loader, that will be all the root windows loaded from the .wnd file
|
||||
//
|
||||
GameWindow *target;
|
||||
WindowLayoutInfo info;
|
||||
|
||||
target = TheWindowManager->winCreateFromScript( filename, &info );
|
||||
if( target == NULL )
|
||||
{
|
||||
|
||||
DEBUG_ASSERTCRASH( target, ("WindowLayout::load - Failed to load layout") );
|
||||
DEBUG_LOG(( "WindowLayout::load - Unable to load layout file '%s'\n", filename.str() ));
|
||||
return FALSE;
|
||||
|
||||
} // end if
|
||||
|
||||
//
|
||||
// add windows loaded from .wnd file to the layout, via info.windows.
|
||||
//
|
||||
std::list<GameWindow *>::iterator it;
|
||||
for (it = info.windows.begin(); it != info.windows.end(); ++it)
|
||||
{
|
||||
// add window to this layout
|
||||
addWindow( *it );
|
||||
}
|
||||
|
||||
/* MDC - can't do this, as modal windows will be at the head...
|
||||
//
|
||||
// add windows loaded from .wnd file to the layout, note we start at
|
||||
// target and go backwards as the layout->addWindow() puts at top
|
||||
// of list and will therefore reverse the order
|
||||
//
|
||||
GameWindow *window;
|
||||
for( window = target; window; window = window->winGetPrev() )
|
||||
{
|
||||
|
||||
// add window to this layout
|
||||
addWindow( window );
|
||||
|
||||
} // end for window
|
||||
*/
|
||||
|
||||
// copy filename
|
||||
m_filenameString = filename;
|
||||
|
||||
// assign script info to the layout
|
||||
setInit( info.init );
|
||||
setUpdate( info.update );
|
||||
setShutdown( info.shutdown );
|
||||
|
||||
return TRUE; // success
|
||||
|
||||
} // end load
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Bring all windows in this layout forward */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void WindowLayout::bringForward( void )
|
||||
{
|
||||
|
||||
//
|
||||
// loop through all our windows and bring each of them to the top of
|
||||
// the window stack, note that we are getting a prev pointer because the
|
||||
// action of bringing a window to the top of the stack does detach it
|
||||
// from the window list and the layout window list ... it is then
|
||||
// re-attached at the top. Also note, to preserve the ordering of
|
||||
// the windows we pull from the tail and add to the top
|
||||
//
|
||||
GameWindow *window, *prev;
|
||||
Int countLeft = m_windowCount;
|
||||
|
||||
for( window = m_windowTail; countLeft; window = prev )
|
||||
{
|
||||
|
||||
DEBUG_ASSERTCRASH( window, ("Must have window: m_windowCount is off") );
|
||||
prev = window->winGetPrevInLayout();
|
||||
window->winBringToTop();
|
||||
countLeft--;
|
||||
|
||||
} // end for window
|
||||
|
||||
} // end bringForward
|
||||
|
||||
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/** Find window within this layout */
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
GameWindow *WindowLayout::findWindow( GameWindow *window )
|
||||
{
|
||||
GameWindow *win;
|
||||
|
||||
for( win = m_windowList; win; win = win->winGetNextInLayout() )
|
||||
if( win == window )
|
||||
return win;
|
||||
|
||||
return NULL; // window not found
|
||||
|
||||
} // end findWindow
|
||||
@@ -0,0 +1,420 @@
|
||||
/*
|
||||
** 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: WindowVideoManager.cpp /////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Electronic Arts Pacific.
|
||||
//
|
||||
// Confidential Information
|
||||
// Copyright (C) 2002 - All Rights Reserved
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// created: Apr 2002
|
||||
//
|
||||
// Filename: WindowVideoManager.cpp
|
||||
//
|
||||
// author: Chris Huybregts
|
||||
//
|
||||
// purpose: Every window is setup to be able to draw a movie. The
|
||||
// WindowVideoManager will take care of setting up the window,
|
||||
// creating/destroying the buffers, and the ability to pause/stop
|
||||
// movies.
|
||||
//
|
||||
// To Use: Create a manager and initialize it. Make sure the manager's Update
|
||||
// is called every frame or how ever often it needs to be updated.
|
||||
// Call reset if the manager needs to be cleared.
|
||||
// Play a movie in a window by passing a window pointer, a movie name,
|
||||
// and the playtype.
|
||||
// If a user trys to play a two different movies on the same window,
|
||||
// only the last one added will play.
|
||||
// It's important when destroying a window, that window is removed
|
||||
// from the manager (Or call Reset if you know no other windows are
|
||||
// playing a movie).
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SYSTEM INCLUDES ////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// USER INCLUDES //////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
|
||||
|
||||
#include "GameClient/WindowVideoManager.h"
|
||||
#include "GameClient/GameWindow.h"
|
||||
#include "GameClient/VideoPlayer.h"
|
||||
#include "GameClient/Display.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DEFINES ////////////////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// WindowVideo PUBLIC FUNCTIONS ///////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
WindowVideo::WindowVideo( void )
|
||||
{
|
||||
|
||||
m_playType = WINDOW_PLAY_MOVIE_ONCE;
|
||||
m_win = NULL;
|
||||
m_videoBuffer = NULL;
|
||||
m_videoStream = NULL;
|
||||
m_movieName.clear();
|
||||
m_state = WINDOW_VIDEO_STATE_STOP;
|
||||
|
||||
}
|
||||
|
||||
WindowVideo::~WindowVideo( void )
|
||||
{
|
||||
// Don't Delete the window, only set it's video buffer to NULL
|
||||
if(m_win)
|
||||
m_win->winGetInstanceData()->setVideoBuffer( NULL );
|
||||
m_win = NULL;
|
||||
|
||||
delete m_videoBuffer;
|
||||
m_videoBuffer = NULL;
|
||||
|
||||
if ( m_videoStream )
|
||||
m_videoStream->close();
|
||||
m_videoStream = NULL;
|
||||
|
||||
}
|
||||
|
||||
void WindowVideo::init( GameWindow *win, AsciiString movieName,
|
||||
WindowVideoPlayType playType,
|
||||
VideoBuffer *videoBuffer, VideoStreamInterface *videoStream)
|
||||
{
|
||||
m_win = win;
|
||||
m_movieName = movieName;
|
||||
m_playType = playType;
|
||||
m_videoBuffer = videoBuffer;
|
||||
m_videoStream = videoStream;
|
||||
m_state = WINDOW_VIDEO_STATE_PLAY;
|
||||
if(m_win)
|
||||
m_win->winGetInstanceData()->setVideoBuffer( m_videoBuffer );
|
||||
}
|
||||
|
||||
void WindowVideo::setWindowState( WindowVideoStates state )
|
||||
{
|
||||
m_state = state;
|
||||
|
||||
if(m_state == WINDOW_VIDEO_STATE_STOP && m_win)
|
||||
m_win->winGetInstanceData()->setVideoBuffer( NULL );
|
||||
|
||||
if((m_state == WINDOW_VIDEO_STATE_PLAY || m_state == WINDOW_VIDEO_STATE_PAUSE )&& m_win)
|
||||
m_win->winGetInstanceData()->setVideoBuffer( m_videoBuffer );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// WindowVideoManager PUBLIC FUNCTIONS ////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
WindowVideoManager::WindowVideoManager( void )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.begin();
|
||||
while(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
delete winVid;
|
||||
it++;
|
||||
}
|
||||
m_playingVideos.clear();
|
||||
|
||||
m_stopAllMovies = FALSE;
|
||||
m_pauseAllMovies = FALSE;
|
||||
|
||||
}
|
||||
|
||||
WindowVideoManager::~WindowVideoManager( void )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.begin();
|
||||
while(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
delete winVid;
|
||||
it++;
|
||||
}
|
||||
m_playingVideos.clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void WindowVideoManager::init( void )
|
||||
{
|
||||
m_playingVideos.clear();
|
||||
|
||||
m_stopAllMovies = FALSE;
|
||||
m_pauseAllMovies = FALSE;
|
||||
}
|
||||
|
||||
void WindowVideoManager::reset( void )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.begin();
|
||||
while(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
delete winVid;
|
||||
it++;
|
||||
}
|
||||
m_playingVideos.clear();
|
||||
|
||||
m_stopAllMovies = FALSE;
|
||||
m_pauseAllMovies = FALSE;
|
||||
}
|
||||
|
||||
void WindowVideoManager::update( void )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.begin();
|
||||
|
||||
if(m_pauseAllMovies || m_stopAllMovies)
|
||||
return;
|
||||
|
||||
//Iterate through the maps
|
||||
while(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
|
||||
if(!winVid)
|
||||
{
|
||||
DEBUG_CRASH(("There's No WindowVideo in the m_playignVideos list"));
|
||||
return;
|
||||
}
|
||||
GameWindow *win = winVid->getWin();
|
||||
|
||||
if(winVid->getState() == WINDOW_VIDEO_STATE_HIDDEN && (win->winIsHidden() == FALSE))
|
||||
{
|
||||
resumeMovie(win);
|
||||
}
|
||||
|
||||
if(winVid->getState() == WINDOW_VIDEO_STATE_PLAY && win->winIsHidden())
|
||||
{
|
||||
hideMovie(win);
|
||||
}
|
||||
|
||||
// Only advance the frame if we're playing
|
||||
if(winVid->getState() != WINDOW_VIDEO_STATE_PLAY)
|
||||
{
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the Stream and the buffer to update for each animation
|
||||
VideoStreamInterface *videoStream = winVid->getVideoStream();
|
||||
VideoBuffer *videoBuffer = winVid->getVideoBuffer();
|
||||
|
||||
if ( videoStream && videoBuffer )
|
||||
{
|
||||
if ( videoStream->isFrameReady())
|
||||
{
|
||||
videoStream->frameDecompress();
|
||||
videoStream->frameRender( videoBuffer );
|
||||
videoStream->frameNext();
|
||||
|
||||
// If we reach frame Index of 0, we might have to pause, or loop.
|
||||
if ( videoStream->frameIndex() == 0 )
|
||||
{
|
||||
if(winVid->getPlayType() == WINDOW_PLAY_MOVIE_ONCE)
|
||||
stopMovie(win);
|
||||
else if (winVid->getPlayType() == WINDOW_PLAY_MOVIE_SHOW_LAST_FRAME)
|
||||
pauseMovie(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void WindowVideoManager::playMovie( GameWindow *win, AsciiString movieName, WindowVideoPlayType playType )
|
||||
{
|
||||
// if we already have a movie playing for that window, kill it.
|
||||
stopAndRemoveMovie( win );
|
||||
|
||||
// create the new stream
|
||||
VideoStreamInterface *videoStream = TheVideoPlayer->open( movieName );
|
||||
if ( videoStream == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the new buffer
|
||||
VideoBuffer *videoBuffer = TheDisplay->createVideoBuffer();
|
||||
if ( videoBuffer == NULL ||
|
||||
!videoBuffer->allocate( videoStream->width(),
|
||||
videoStream->height())
|
||||
)
|
||||
{
|
||||
// If we failed to create the buffer...
|
||||
delete videoBuffer;
|
||||
videoBuffer = NULL;
|
||||
|
||||
if ( videoStream )
|
||||
videoStream->close();
|
||||
videoStream = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// now that we have everything, create the new WindowVideo Structure
|
||||
WindowVideo *winVid = NEW WindowVideo;
|
||||
|
||||
// init it.
|
||||
winVid->init( win, movieName,playType,videoBuffer,videoStream);
|
||||
|
||||
// add it to our map.
|
||||
m_playingVideos[win] = winVid;
|
||||
|
||||
m_pauseAllMovies = FALSE;
|
||||
m_stopAllMovies = FALSE;
|
||||
}
|
||||
|
||||
|
||||
void WindowVideoManager::pauseMovie( GameWindow *win )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.find(win);
|
||||
if(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
winVid->setWindowState(WINDOW_VIDEO_STATE_PAUSE);
|
||||
}
|
||||
|
||||
}
|
||||
void WindowVideoManager::hideMovie( GameWindow *win )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.find(win);
|
||||
if(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
winVid->setWindowState(WINDOW_VIDEO_STATE_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowVideoManager::resumeMovie( GameWindow *win )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.find(win);
|
||||
if(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
winVid->setWindowState(WINDOW_VIDEO_STATE_PLAY);
|
||||
}
|
||||
m_pauseAllMovies = FALSE;
|
||||
m_stopAllMovies = FALSE;
|
||||
}
|
||||
|
||||
void WindowVideoManager::stopMovie( GameWindow *win )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.find(win);
|
||||
if(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
winVid->setWindowState(WINDOW_VIDEO_STATE_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowVideoManager::stopAndRemoveMovie( GameWindow *win )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.find(win);
|
||||
if(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
delete winVid;
|
||||
winVid = NULL;
|
||||
m_playingVideos.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void WindowVideoManager::stopAllMovies( void )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.begin();
|
||||
//Iterate through the maps
|
||||
while(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
winVid->setWindowState(WINDOW_VIDEO_STATE_STOP);
|
||||
it++;
|
||||
}
|
||||
|
||||
m_stopAllMovies = TRUE;
|
||||
m_pauseAllMovies = FALSE;
|
||||
}
|
||||
|
||||
void WindowVideoManager::pauseAllMovies( void )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.begin();
|
||||
//Iterate through the maps
|
||||
while(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
winVid->setWindowState(WINDOW_VIDEO_STATE_PAUSE);
|
||||
it++;
|
||||
}
|
||||
|
||||
m_pauseAllMovies = TRUE;
|
||||
m_stopAllMovies = FALSE;
|
||||
}
|
||||
|
||||
void WindowVideoManager::resumeAllMovies( void )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.begin();
|
||||
//Iterate through the maps
|
||||
while(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
winVid->setWindowState(WINDOW_VIDEO_STATE_PLAY);
|
||||
it++;
|
||||
}
|
||||
m_stopAllMovies = FALSE;
|
||||
m_pauseAllMovies = FALSE;
|
||||
}
|
||||
|
||||
Int WindowVideoManager::getWinState( GameWindow *win )
|
||||
{
|
||||
WindowVideoMap::iterator it = m_playingVideos.find(win);
|
||||
if(it != m_playingVideos.end())
|
||||
{
|
||||
WindowVideo *winVid = it->second;
|
||||
if(winVid)
|
||||
return winVid->getState();
|
||||
}
|
||||
return WINDOW_VIDEO_STATE_STOP;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// PRIVATE FUNCTIONS //////////////////////////////////////////////////////////
|
||||
//-----------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user