/*
** Command & Conquer Generals Zero Hour(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 .
*/
////////////////////////////////////////////////////////////////////////////////
// //
// (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; isetCursorTooltip( 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;
case 4:
tooltip = TheGameText->fetch("TOOLTIP:MapMaxBrutalSuccess");
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*/