Files
source/Utils/popup_class.cpp
T
Marco Antonio J. Costaandmajcosta 86ad401186 add newline at end of file where it's lacking
.editorconfig already enforces it but it's getting changed piecemeal in
every commit. just get it done with.

the script:
```

find . -type f -not -path "./.git/*" -not -path "./.vs/*" | while read -r file; do
	isFile=$(file -0 "$file" | cut -d $'\0' -f2)
	case "$isFile" in
		(*text*)
			echo "$file is text"
			if [[ $(tail -c 1 "$file" | wc -l) -ne 1 ]]; then
				echo "" >> "$file"
			fi
			;;
		(*)
			echo "file isn't text"
			;;
	esac
done
```
2024-12-14 19:05:48 -03:00

1865 lines
45 KiB
C++

#include "Map Screen Interface.h"
#include "popupbox.h"
#include "interface control.h"
#include "renderworld.h"
#include "Text.h"
#include "utilities.h"
#include "Interface.h"
#include "GameSettings.h"
#include "Input.h"
#include "Console.h"
#include "lwstring.h"
#include "message.h"
#include "mousesystem.h"
#include "Lua Interpreter.h"
#include "popup_callback.h"
#include "popup_class.h"
//////////////////////////////////////////////////////////////////
// functions and variable declarations for binding the class with C callbacks
//////////////////////////////////////////////////////////////////
vector<PopupIndex> gPopupRegionIndex;
vector<POPUP*> gPopupIndex;
UINT32 gPopupRegionIndexCounter = 0;
UINT32 gPopupIndexCounter = 0;
UINT32 POPUP::nextid = 0;
UINT32 POPUP::uiPOPUPBORDERS = 0;
UINT32 POPUP::uiPOPUPTEX = 0;
///////////////////////
// Lua vars
/////////////////
BOOLEAN gfPopupInit = FALSE;
POPUP * gPopup; // single popup
///////////////////////
// Lua Popup functions
/////////////////
void initPopupIndex(void)
{
/*
int i;
for (i=0; i<MAX_POPUPS; i++)
{
gPopupIndex[i] = NULL;
}
*/
}
void reinitPopupIndex(void)
{
/*
int i;
for (i=0; i<MAX_POPUPS; i++)
{
if (gPopupIndex[i] != NULL)
{
gPopupIndex[i]->~POPUP();
gPopupIndex[i] = NULL;
}
}
*/
}
POPUP * findPopupInIndex( UINT32 cID )
{
for(std::vector<POPUP*>::iterator cPopup=gPopupIndex.begin(); cPopup != gPopupIndex.end(); ++cPopup)
if ((*cPopup)->id == cID){
return (*cPopup);
}
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Failed to find popup id: %i \n",cID);
OutputDebugString( debugStr );
#endif
return NULL;
}
void rebuildPopupIndex(void)
{
/*UINT8 i,j;
POPUP* TempPopupIndex[MAX_POPUPS];
//cout << "cleaning index"<<endl;
for (i = 0; i < gPopupIndexCounter; i++)
{
TempPopupIndex[i] = gPopupIndex[i];
}
j=0; // actual index
for (i = 0; i < gPopupIndexCounter; i++)
{
if (TempPopupIndex[i] != NULL)
{
gPopupIndex[j] = TempPopupIndex[i];
j++;
}
}
// We only have j elements worth keeping.
gPopupIndexCounter = j;*/
}
//////////////////////////////////////////////////////////////////
// POPUP_OPTION methods
//////////////////////////////////////////////////////////////////
POPUP_OPTION::POPUP_OPTION(void)
{
this->name = L"unnamed option";
this->action = 0;
this->avail = 0;
this->hover = 0;
// set highlight color
this->color_highlight = FONT_WHITE;
// unhighlighted color
this->color_foreground = FONT_LTGREEN;
// background color
this->color_background = FONT_BLACK;
// shaded color..for darkened text
this->color_shade = FONT_GRAY7 ;
}
POPUP_OPTION::~POPUP_OPTION(void)
{
if(this->action) delete(this->action);
if(this->avail) delete(this->avail);
if(this->hover) delete(this->hover);
}
POPUP_OPTION::POPUP_OPTION(std::wstring *newName, popupCallback * newFunction)
{
this->name = *newName;
this->action = newFunction;
this->avail = 0;
this->hover = 0;
// set highlight color
this->color_highlight = FONT_WHITE;
// unhighlighted color
this->color_foreground = FONT_LTGREEN;
// background color
this->color_background = FONT_BLACK;
// shaded color..for darkened text
this->color_shade = FONT_GRAY7 ;
}
BOOLEAN POPUP_OPTION::setName( std::wstring * newName )
{
this->name = *newName;
return TRUE;
}
BOOLEAN POPUP_OPTION::setAction( popupCallback *fun )
{
this->action = fun;
return TRUE;
}
BOOLEAN POPUP_OPTION::setAvail( popupCallback *fun )
{
this->avail = fun;
return TRUE;
}
BOOLEAN POPUP_OPTION::setHover( popupCallback *fun )
{
this->hover = fun;
return TRUE;
}
BOOLEAN POPUP_OPTION::checkAvailability()
{
if (this->avail != 0)
return ( this->avail->call() == true );
else if ( this->action == 0 ) // options with no action are always shaded
return false;
else
return true;
}
BOOLEAN POPUP_OPTION::runHoverCallback(MOUSE_REGION * pRegion)
{
// TODO: pass the mouse region data to the function (if it can accept it)
if (this->hover != 0)
return ( this->hover->call() == true );
else
return true;
}
BOOLEAN POPUP_OPTION::run()
{
// check if it's available at this time
if ( this->action != 0 && this->checkAvailability() )
{
this->action->call();
return TRUE;
}
else
return FALSE;
}
BOOLEAN POPUP_OPTION::forceRun()
{
if (this->action != 0)
this->action->call();
else
return FALSE;
return TRUE;
}
//////////////////////////////////////////////////////////////////
// POPUP_SUB_POPUP_OPTION methods
//////////////////////////////////////////////////////////////////
// constructor
POPUP_SUB_POPUP_OPTION::POPUP_SUB_POPUP_OPTION(void) : POPUP_OPTION(new wstring(L"Unnamed subPopup"),NULL) //TODO: possible memmory leak!
{
this->parent = NULL;
this->initSubPopup();
}
POPUP_SUB_POPUP_OPTION::POPUP_SUB_POPUP_OPTION(wstring* name) : POPUP_OPTION(name, NULL)
{
this->parent = NULL;
this->initSubPopup();
}
POPUP_SUB_POPUP_OPTION::POPUP_SUB_POPUP_OPTION(wstring* newName, const POPUP * parent) : POPUP_OPTION(newName, NULL)
{
this->parent = parent;
this->initSubPopup();
}
// destructor
POPUP_SUB_POPUP_OPTION::~POPUP_SUB_POPUP_OPTION(void)
{
}
void POPUP_SUB_POPUP_OPTION::showPopup()
{
// check if it's available at this time, if there is an avail function set
if ( !this->AvailabilityFunctionSet() || this->checkAvailability() )
{
if (!this->customPositionSet || this->customRule == POPUP_POSITION_RELATIVE) {
this->positionSubPopup();
}
this->subPopup->show();
}
}
void POPUP_SUB_POPUP_OPTION::hidePopup()
{
this->subPopup->hide();
}
void POPUP_SUB_POPUP_OPTION::positionSubPopup()
{
INT16 x,y;
if( this->customPositionSet )
{
x = this->parent->X + this->parent->Dimensions.iLeft + this->parent->Dimensions.iRight + this->customX;
y = this->parent->Y + this->customY;
} else {
x = this->parent->X + this->parent->Dimensions.iLeft + this->parent->Dimensions.iRight + 10;
y = this->parent->Y + 10;
}
this->subPopup->setPosition(x,y);
}
BOOLEAN POPUP_SUB_POPUP_OPTION::run()
{
//cout << "running function " << utf8string::as_utf8(this->name.c_str()).c_str() << endl;
this->showPopup();
return TRUE;
}
BOOLEAN POPUP_SUB_POPUP_OPTION::setPopupPosition(UINT16 x, UINT16 y, INT8 positioningRule){
this->customPositionSet = true;
if (positioningRule != POPUP_POSITION_RELATIVE){
return this->subPopup->setPosition(x,y,positioningRule);
} else {
this->customX = x;
this->customY = y;
this->customRule = positioningRule;
return this->subPopup->setPosition(this->parent->X + this->parent->Dimensions.iRight + x, this->parent->Y + y,POPUP_POSITION_TOP_LEFT);
}
}
static void shadeOpenSubPopup( POPUP_SUB_POPUP_OPTION * opt ){
// make the option yellow while its open
SetCurrentBox( opt->parent->getBoxId() );
SetStringForeground( opt->stringHandle, FONT_YELLOW);
}
extern void RenderTeamRegionBackground();
static void unShadeOpenSubPopup( POPUP_SUB_POPUP_OPTION * opt ){
// restore the option's color
SetCurrentBox( opt->parent->getBoxId() );
SetStringForeground( opt->stringHandle, FONT_LTGREEN);
// if in mapscreen, redraw the UI
if( guiCurrentScreen == MAP_SCREEN ){
fTeamPanelDirty = TRUE;
fMapPanelDirty = TRUE;
RenderTeamRegionBackground();
}
}
void POPUP_SUB_POPUP_OPTION::initSubPopup()
{
this->subPopup = new POPUP( (CHAR*) wstring(this->name).c_str() );
this->subPopup->setCallback(POPUP_CALLBACK_SHOW,new popupCallbackFunction<void,POPUP_SUB_POPUP_OPTION*>( &shadeOpenSubPopup, this ));
this->subPopup->setCallback(POPUP_CALLBACK_HIDE,new popupCallbackFunction<void,POPUP_SUB_POPUP_OPTION*>( &unShadeOpenSubPopup, this ));
this->customPositionSet = false;
// set highlight color
this->color_highlight = FONT_WHITE;
// unhighlighted color
this->color_foreground = FONT_LTGREEN;
// background color
this->color_background = FONT_BLACK;
// shaded color..for darkened text
this->color_shade = FONT_GRAY7 ;
}
void POPUP_SUB_POPUP_OPTION::destroySubPopup()
{
this->subPopup->~POPUP();
}
//////////////////////////////////////////////////////////////////
// POPUP methods
//////////////////////////////////////////////////////////////////
// constructors
POPUP::POPUP(void)
{
strcpy((char*) this->name, (char*) "unNamed popup");
this->optionCount = 0;
this->addToIndex();
this->setInitialValues();
}
POPUP::POPUP(CHAR* name)
{
strcpy((char*) this->name, (char*) name);
this->optionCount = 0;
this->addToIndex();
this->setInitialValues();
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Created popup: %s \n",this->name);
OutputDebugString( debugStr );
#endif
}
// destructor
POPUP::~POPUP(void)
{
if(this->PopupVisible)
this->hide();
for (UINT16 i = 0; i<this->options.size(); i++)
{
this->options[i]->~POPUP_OPTION();
}
for (UINT16 i = 0; i<this->subPopupOptions.size(); i++)
{
this->subPopupOptions[i]->subPopup->hide();
this->subPopupOptions[i]->~POPUP_SUB_POPUP_OPTION();
}
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Destroyed popup: %s \n",this->name);
OutputDebugString( debugStr );
#endif
this->removeFromIndex();
if (this->initCallback) this->initCallback->~popupCallback();
if (this->ShowCallback) this->ShowCallback->~popupCallback();
if (this->HideCallback) this->HideCallback->~popupCallback();
if (this->EndCallback) {
this->EndCallback->call();
this->EndCallback->~popupCallback();
}
}
// callback handlers
BOOLEAN POPUP::setCallback(UINT8 type, popupCallback * callback){
if(callback == NULL) return FALSE;
switch(type){
case POPUP_CALLBACK_INIT:
if (this->initCallback) this->initCallback->~popupCallback();
this->initCallback = callback;
break;
case POPUP_CALLBACK_END:
if (this->EndCallback) this->EndCallback->~popupCallback();
this->EndCallback = callback;
break;
case POPUP_CALLBACK_SHOW:
if (this->ShowCallback) this->ShowCallback->~popupCallback();
this->ShowCallback = callback;
break;
case POPUP_CALLBACK_HIDE:
if (this->HideCallback) this->HideCallback->~popupCallback();
this->HideCallback = callback;
break;
default: return false;
}
return true;
}
BOOLEAN POPUP::isCallbackSet(UINT8 type){
switch(type){
case POPUP_CALLBACK_INIT: if (this->initCallback) return true; break;
case POPUP_CALLBACK_END: if (this->EndCallback) return true; break;
case POPUP_CALLBACK_SHOW: if (this->ShowCallback) return true; break;
case POPUP_CALLBACK_HIDE: if (this->HideCallback) return true; break;
default: return false;
}
return false;
}
// popup index handlers
BOOLEAN POPUP::addToIndex()
{
/*
if (gPopupIndexCounter == MAX_POPUPS)
{
rebuildPopupIndex(); // if index full, try to rebuild it before giving up
if (gPopupIndexCounter == MAX_POPUPS)
return FALSE;
}
*/
// assign the ID and increment the counter.
this->id = this->nextid;
this->nextid++;
//gPopupIndex[gPopupIndexCounter] = this;
gPopupIndex.push_back( this );
gPopupIndexCounter++;
return TRUE;
}
BOOLEAN POPUP::removeFromIndex()
{
for(std::vector<POPUP*>::iterator cPopup=gPopupIndex.begin(); cPopup != gPopupIndex.end(); ++cPopup)
if ((*cPopup)->id == this->id){
gPopupIndex.erase(cPopup);
return TRUE;
}
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Failed to remove popup from index: %i \n",this->id);
OutputDebugString( debugStr );
#endif
return FALSE;
}
// set defaults
void POPUP::setInitialValues(void)
{
this->Position.iX=20;
this->Position.iY=20;
this->OrigPosition.iX = 0 ;
this->OrigPosition.iY = 0 ;
this->Dimensions.iLeft=0;
this->Dimensions.iTop=0;
this->Dimensions.iBottom=100;
this->Dimensions.iRight=120;
this->BoxesX = 20;
this->BoxesY = 20;
// the x,y position of the pop up in tactical
this->X = 20;
this->Y = 20;
this->positioningRule = POPUP_POSITION_TOP_LEFT;
//int i = 0;
//for (i=0; i<POPUP_MAX_OPTIONS; i++)
//{
// this->options[i] = NULL;
// //this->MenuRegion[i] = NULL;
//}
this->PopupVisible = FALSE;
this->FirstClickInScreenMask = FALSE;
this->BoxPersist = FALSE;
this->subPopupOptionCount = 0;
this->optionCount = 0;
this->initCallback = NULL;
this->EndCallback = NULL;
this->ShowCallback = NULL;
this->HideCallback = NULL;
}
// setup functions
POPUP_OPTION * POPUP::addOption(wstring * name, popupCallback* action)
{
if (this->optionCount < POPUP_MAX_OPTIONS)
{
this->options.push_back( new POPUP_OPTION ( name, action ) );
this->optionCount++;
return this->options.back();
}
else
return NULL;
}
/*
INT16 POPUP::findFreeOptionIndex()
{
int i;
for (i=0; i<POPUP_MAX_OPTIONS; i++)
if ( this->options[i] == NULL )
return i;
return -1;
}
*/
BOOLEAN POPUP::addOption(POPUP_OPTION &option)
{
if (this->optionCount < POPUP_MAX_OPTIONS)
{
this->options.push_back( &option );
this->optionCount++;
return TRUE;
}
else
return FALSE;
}
POPUP_OPTION * POPUP::getOption(UINT16 n)
{
if (n < this->options.size() && this->options[n])
return this->options[n];
return NULL;
}
POPUP * POPUP::addSubMenuOption(wstring * name)
{
if (this->subPopupOptionCount < POPUP_MAX_SUB_POPUPS)
{
this->subPopupOptions.push_back( new POPUP_SUB_POPUP_OPTION ( name, this ) );
this->subPopupOptionCount++;
return this->subPopupOptions.back()->subPopup;
}
else
return NULL;
}
BOOL POPUP::addSubMenuOption( POPUP_SUB_POPUP_OPTION* sub )
{
if (this->subPopupOptionCount < POPUP_MAX_SUB_POPUPS)
{
sub->parent = this;
this->subPopupOptions.push_back( sub );
this->subPopupOptionCount++;
return TRUE;
}
else
return FALSE;
}
POPUP_SUB_POPUP_OPTION * POPUP::getSubPopupOption(UINT8 n)
{
if (n < this->subPopupOptions.size() && this->subPopupOptions[n])
return this->subPopupOptions[n];
else
return NULL;
}
void POPUP::recalculateWidth(void){
this->Dimensions.iRight = this->getCurrentWidth();
}
INT16 POPUP::getCurrentWidth(void){
INT16 longestString = 0, longestStringTmp;
CHAR16 sString[ 128 ];
if (this->subPopupOptionCount > 0)
for(std::vector<POPUP_SUB_POPUP_OPTION*>::iterator cOption=this->subPopupOptions.begin(); cOption != this->subPopupOptions.end(); ++cOption)
{
swprintf( sString, (*cOption)->name.c_str() );
longestStringTmp = StringPixLength( sString, MAP_SCREEN_FONT);
if( longestString < longestStringTmp ) longestString = longestStringTmp;
}
if (this->optionCount > 0)
for(std::vector<POPUP_OPTION*>::iterator cOption=this->options.begin(); cOption != this->options.end(); ++cOption)
{
swprintf( sString, (*cOption)->name.c_str() );
longestStringTmp = StringPixLength( sString, MAP_SCREEN_FONT);
if( longestString < longestStringTmp ) longestString = longestStringTmp;
}
return longestString + 10; // 10+ marginLeft(6) + marginRight(4)
}
INT16 POPUP::getCurrentHeight(void){
// linespace = 2; margin = 6+4
return ( this->optionCount + this->subPopupOptionCount ) * ( GetFontHeight(MAP_SCREEN_FONT) + 2 ) +10;
}
SGPRect POPUP::getBoxDimensions(){
SGPRect tmp;
GetBoxSize( this->boxId, &tmp );
return tmp;
}
SGPPoint POPUP::getBoxPosition(){
SGPPoint tmp;
GetBoxPosition( this->boxId, &tmp );
return tmp;
}
BOOLEAN POPUP::setPosition(UINT16 x, UINT16 y, UINT8 positioningRule )
{
//TODO: check if the desired position is valid.
// why the hell are there three sets of box positions ?
this->Position.iX=x;
this->Position.iY=y;
this->BoxesX = x;
this->BoxesY = y;
this->X = x;
this->Y = y;
// make that four
this->OrigPosition.iX = x ;
this->OrigPosition.iY = y ;
this->positioningRule = positioningRule;
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Positioning popup %i at (x/y) %i / %i ; positioning rule: %i \n",this->id, x, y, positioningRule);
OutputDebugString( debugStr );
#endif
return TRUE;
}
//////////////////////////////////
// usage functions
BOOLEAN POPUP::show()
{
if (this->PopupVisible) {
// this->RebuildBox();
return false;
}
if (this->ShowCallback) this->ShowCallback->call();
// can't show an empty popup.
if ( (this->optionCount + this->subPopupOptionCount) == 0) return FALSE;
// set the box to visible
this->PopupVisible = TRUE;
// should take care of creating the box
this->CreatePopUpBoxes();
// set the position before creating the screen mask and mouse regions
this->DetermineBoxPositions();
// create all the GUI areas
this->CreateScreenMask();
this->CreateMouseRegions();
// make SURE the regions have been repositioned
this->CheckAndUpdateTacticalPopUpPositions();
// shade unavaliable options
this->HandleShadingOfLines();
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Showing popup id: %i \n",this->boxId);
OutputDebugString( debugStr );
#endif
// showtime !
ShowBox(this->boxId);
return TRUE;
}
void POPUP::hideAfter(){
this->hideAfterRun = TRUE;
}
BOOLEAN POPUP::hide()
{
if (!this->PopupVisible) {
#ifdef JA2TESTVERSION
// __debugbreak();
#else
// Assert(false);
#endif
return false;
}
for (UINT16 i = 0; i<this->subPopupOptions.size(); i++)
{
this->subPopupOptions[i]->subPopup->hide();
}
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Hiding popup id: %i \n",this->boxId);
OutputDebugString( debugStr );
#endif
this->DestroyMouseRegions();
this->DestroyScreenMask();
HideBox(this->boxId);
RemoveBox(this->boxId);
this->DestroyPopUpBoxes();
this->boxId = -1;
this->PopupVisible = FALSE;
if (this->HideCallback) this->HideCallback->call();
return TRUE;
}
BOOLEAN POPUP::callOption(int optIndex)
{
this->hideAfterRun = FALSE;
if ( this->optionCount > 0
&& optIndex < POPUP_MAX_OPTIONS
&& optIndex < optionCount
&& optIndex >= 0)
{
BOOLEAN callbackStatus = this->options[optIndex]->run();
if(!this->hideAfterRun)
{
return callbackStatus;
} else
{
return this->hide();
}
}
else
return FALSE;
}
BOOLEAN POPUP::forceDraw(){
if (!this->PopupVisible) {
// set the box to visible
this->PopupVisible = TRUE;
// should take care of creating the box
this->CreatePopUpBoxes();
// set the position before creating the screen mask and mouse regions
this->DetermineBoxPositions();
// create all the GUI areas
this->CreateScreenMask();
this->CreateMouseRegions();
// make SURE the regions have been repositioned
this->CheckAndUpdateTacticalPopUpPositions();
// shade unavaliable options
this->HandleShadingOfLines();
// showtime !
ShowBox(this->boxId);
} else {
this->RebuildBox();
}
DisplayOnePopupBox(this->boxId, FRAME_BUFFER);
ForceUpDateOfBox(this->boxId);
return true;
}
////////////////////////////
// private utility functions
//////
// external flag access functions
//////
BOOLEAN POPUP::TeamPanelDirty(void)
{
extern BOOLEAN fTeamPanelDirty;
return fTeamPanelDirty;
}
BOOLEAN POPUP::CharacterInfoPanelDirty(void)
{
extern BOOLEAN fCharacterInfoPanelDirty;
return fCharacterInfoPanelDirty;
}
BOOLEAN POPUP::MapScreenBottomDirty(void)
{
extern BOOLEAN fMapScreenBottomDirty;
return fMapScreenBottomDirty;
}
BOOLEAN POPUP::RenderPBInterface(void)
{
extern BOOLEAN gfRenderPBInterface ;
return gfRenderPBInterface ;
}
void POPUP::setTeamPanelDirty(BOOLEAN flag )
{
extern BOOLEAN fTeamPanelDirty;
fTeamPanelDirty = flag;
}
void POPUP::setCharacterInfoPanelDirty(BOOLEAN flag )
{
extern BOOLEAN fCharacterInfoPanelDirty;
fCharacterInfoPanelDirty = flag;
}
void POPUP::setMapScreenBottomDirty(BOOLEAN flag )
{
extern BOOLEAN fMapScreenBottomDirty;
fMapScreenBottomDirty = flag;
}
void POPUP::setRenderPBInterface(BOOLEAN flag )
{
extern BOOLEAN gfRenderPBInterface ;
gfRenderPBInterface = flag;
}
//////
// internal box setup methods
//////
// rewrites all the text lines in the box and adjusts
// the box's size and mouse regions to potential changes
// less expensive then hide();show();
void POPUP::RebuildBox( void )
{ if ( this->boxId != -1 && this->id < POPUP::nextid )
{
// make sure we're working with the right popup!
SetCurrentBox( this->boxId );
// remove all the 'old' text from the box
RemoveAllCurrentBoxStrings();
// add the sub popups (they go first)
this->AddSubPopupStrings();
// add the options
this->AddOptionStrings();
// set fonts and what not
this->UpdateTextProperties();
// adjust the mouse regions (might've changed substantially)
this->AdjustMouseRegions();
// shade/unshade accordingly
this->HandleShadingOfLines();
} else if ( this->id > POPUP::nextid ) {
// chances are buggered up data will have impossible boxid
#ifdef JA2TESTVERSION
__debugbreak();
#else
Assert(false);
#endif
}
}
BOOLEAN POPUP::CreateBox()
{
// this->Position.iX = this->OrigPosition.iX;
if( giBoxY != 0 )
{
this->Position.iY = giBoxY;
}
// create basic box
CreatePopUpBox(&this->boxId, this->Dimensions, this->Position, (POPUP_BOX_FLAG_CLIP_TEXT|POPUP_BOX_FLAG_CENTER_TEXT|POPUP_BOX_FLAG_RESIZE ));
// which buffer will box render to
SetBoxBuffer(this->boxId, FRAME_BUFFER);
// border type?
SetBorderType(this->boxId,POPUP::uiPOPUPBORDERS);
// background texture
SetBackGroundSurface(this->boxId, POPUP::uiPOPUPTEX);
// margin sizes
SetMargins(this->boxId, 6, 6, 4, 4 );
// space between lines
SetLineSpace(this->boxId, 2);
// set current box to this one
SetCurrentBox( this->boxId );
// add the sub popups (they go first)
this->AddSubPopupStrings();
// add the options
this->AddOptionStrings();
// set fonts and what not
this->UpdateTextProperties();
//UpdateMapScreenthis->Positions();
return TRUE;
}
void POPUP::AddSubPopupStrings()
{
UINT32 hStringHandle;
CHAR16 sString[ 128 ];
if (this->subPopupOptionCount > 0)
for(std::vector<POPUP_SUB_POPUP_OPTION*>::iterator cOption=this->subPopupOptions.begin(); cOption != this->subPopupOptions.end(); ++cOption)
{
swprintf( sString, (*cOption)->name.c_str() );
AddMonoString((UINT32 *)&hStringHandle, sString );
// make sure it is unhighlighted
UnHighLightLine(hStringHandle);
// update options string handle for setting colors
(*cOption)->stringHandle = hStringHandle;
}
}
void POPUP::AddOptionStrings()
{
UINT32 hStringHandle;
CHAR16 sString[ 128 ];
if (this->optionCount > 0)
for(std::vector<POPUP_OPTION*>::iterator cOption=this->options.begin(); cOption != this->options.end(); ++cOption)
{
swprintf( sString, (*cOption)->name.c_str() );
AddMonoString((UINT32 *)&hStringHandle, sString );
// make sure it is unhighlighted
UnHighLightLine(hStringHandle);
// update options string handle for setting colors
(*cOption)->stringHandle = hStringHandle;
}
}
void POPUP::UpdateTextProperties()
{
// set font type
SetBoxFont(this->boxId, MAP_SCREEN_FONT);
// set highlight color
SetBoxHighLight(this->boxId, FONT_WHITE);
// unhighlighted color
SetBoxForeground(this->boxId, FONT_LTGREEN);
// background color
SetBoxBackground(this->boxId, FONT_BLACK);
// shaded color..for darkened text
SetBoxShade( this->boxId, FONT_GRAY7 );
// alt shaded color
SetBoxSecondaryShade( this->boxId, FONT_YELLOW );
if (this->subPopupOptionCount > 0)
for(std::vector<POPUP_SUB_POPUP_OPTION*>::iterator cOption=this->subPopupOptions.begin(); cOption != this->subPopupOptions.end(); ++cOption)
{
SetStringForeground( (*cOption)->stringHandle, (*cOption)->color_foreground);
SetStringBackground( (*cOption)->stringHandle, (*cOption)->color_background);
SetStringHighLight( (*cOption)->stringHandle, (*cOption)->color_highlight);
SetStringShade( (*cOption)->stringHandle, (*cOption)->color_shade);
}
if (this->optionCount > 0)
for(std::vector<POPUP_OPTION*>::iterator cOption=this->options.begin(); cOption != this->options.end(); ++cOption)
{
SetStringForeground( (*cOption)->stringHandle, (*cOption)->color_foreground);
SetStringBackground( (*cOption)->stringHandle, (*cOption)->color_background);
SetStringHighLight( (*cOption)->stringHandle, (*cOption)->color_highlight);
SetStringShade( (*cOption)->stringHandle, (*cOption)->color_shade);
}
// resize box to text
ResizeBoxToText( this->boxId );
}
BOOLEAN POPUP::CreateDestroyPopUpBoxes( void )
{
static BOOLEAN fCreated = FALSE;
BOOLEAN returnStatus = TRUE;
if( ( this->PopupVisible == TRUE ) && ( fCreated == FALSE ) )
{
returnStatus = this->CreatePopUpBoxes();
fCreated = TRUE;
}
else if( ( this->PopupVisible == FALSE ) && ( fCreated == TRUE ) )
{
returnStatus = this->DestroyPopUpBoxes();
fCreated = FALSE;
}
return( returnStatus );
}
BOOLEAN POPUP::CreatePopUpBoxes()
{
VSURFACE_DESC vs_desc;
VOBJECT_DESC VObjectDesc;
// load textures
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
FilenameForBPP("INTERFACE\\popup.sti", VObjectDesc.ImageFile);
CHECKF(AddVideoObject(&VObjectDesc, &POPUP::uiPOPUPBORDERS));
vs_desc.fCreateFlags = VSURFACE_CREATE_FROMFILE | VSURFACE_SYSTEM_MEM_USAGE;
strcpy(vs_desc.ImageFile, "INTERFACE\\popupbackground.pcx");
CHECKF(AddVideoSurface(&vs_desc, &POPUP::uiPOPUPTEX));
// does some other stff
this->CreateBox();
return TRUE;
}
BOOLEAN POPUP::DestroyPopUpBoxes()
{
if ( gPopupIndex.size() < 2 ){
DeleteVideoObjectFromIndex(POPUP::uiPOPUPBORDERS);
DeleteVideoSurfaceFromIndex(POPUP::uiPOPUPTEX);
}
gfIgnoreScrolling = FALSE;
return TRUE;
}
void POPUP::CreateDestroyScreenMask( void )
{
static BOOLEAN fCreated = FALSE;
// not created, create
if( ( fCreated == FALSE ) )
{
this->CreateScreenMask();
fCreated = TRUE;
}
else if( ( fCreated == TRUE ) )
{
this->DestroyScreenMask();
fCreated = FALSE;
}
return;
}
void POPUP::CreateScreenMask( void )
{
/* void (POPUP::*ScreenMaskBtnCallbackMethod) (MOUSE_REGION *, INT32 );
ScreenMaskBtnCallbackMethod = &POPUP::ScreenMaskBtnCallback;
*/
// will create a screen mask to catch mouse input to disable LPC menus
MSYS_DefineRegion( &this->ScreenMaskRegion,
0,
0,
SCREEN_WIDTH,
SCREEN_HEIGHT,
POPUP_SCREEN_MASK_PRIORITY ,
MSYS_NO_CURSOR,
MSYS_NO_CALLBACK,
popupMaskCallback );
// if in tactical...
if ( !(guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN) )
MSYS_ChangeRegionCursor( &this->ScreenMaskRegion, 0 );
if (!registerPopupRegion( this->ScreenMaskRegion.IDNumber, this->id)){
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Failed to register screen mask for box id: %i \n",this->boxId);
OutputDebugString( debugStr );
#endif
}
return;
}
void POPUP::DestroyScreenMask( void )
{
unregisterPopupRegion(this->ScreenMaskRegion.IDNumber); // unregister it before removing it
// otherwise the ID might get lost somewhere
MSYS_RemoveRegion( &this->ScreenMaskRegion );
return;
}
void POPUP::CreateDestroyMouseRegions( void )
{
static BOOLEAN fCreated = FALSE;
if( ( this->PopupVisible == TRUE ) && ( fCreated == FALSE ) )
{
this->CreateMouseRegions();
fCreated = TRUE;
}
else if( ( this->PopupVisible == FALSE ) && ( fCreated == TRUE ) )
{
this->DestroyMouseRegions();
fCreated = FALSE;
}
}
void POPUP::CreateMouseRegions( void )
{
UINT32 iCounter = 0;
UINT32 iTotal = 0;
INT32 iFontHeight = 0;
INT32 iBoxXPosition = 0;
INT32 iBoxYPosition = 0;
SGPPoint pPosition={0,0};
INT32 iBoxWidth = 0;
SGPRect pDimensions={0,0,0,0};
static BOOLEAN fShowRemoveMenu = FALSE;
gfIgnoreScrolling = FALSE;
if( ( guiCurrentScreen == MAP_SCREEN ) )
{
SetBoxPosition( this->boxId, this->Position );
}
// grab height of font
iFontHeight = GetLineSpace( this->boxId ) + GetFontHeight( GetBoxFont( this->boxId ) );
// get x.y position of box
GetBoxPosition( this->boxId, &pPosition);
// grab box x and y position
iBoxXPosition = pPosition.iX;
iBoxYPosition = pPosition.iY;
// get dimensions..mostly for width
GetBoxSize( this->boxId, &pDimensions );
// get width
iBoxWidth = pDimensions.iRight;
SetCurrentBox( this->boxId );
// define regions for sub popups
for( iCounter = 0; iCounter < this->subPopupOptionCount ; iCounter++ )
{
// add mouse region for each line of text..and set user data
MSYS_DefineRegion( &this->MenuRegion[ iTotal ],
( INT16 )( iBoxXPosition ),
( INT16 )( iBoxYPosition + GetTopMarginSize( this->boxId ) +
( iFontHeight ) * iTotal ),
( INT16 )( iBoxXPosition + iBoxWidth ),
( INT16 )( iBoxYPosition + GetTopMarginSize( this->boxId ) +
( iFontHeight ) * ( iTotal + 1 ) ),
POPUP_OPTION_PRIORITY ,
MSYS_NO_CURSOR,
popupMouseMoveCallback,
popupMouseClickCallback );
MSYS_SetRegionUserData( &this->MenuRegion[ iTotal ], 0, iCounter );
MSYS_SetRegionUserData( &this->MenuRegion[ iTotal ], 1, REGION_SUB_POPUP );
MSYS_SetRegionUserData( &this->MenuRegion[ iTotal ], 2, iTotal );
if (!registerPopupRegion( this->MenuRegion[ iTotal ].IDNumber, this->id)){}
iTotal++;
}
// define regions for options
for( iCounter = 0; iCounter < this->optionCount ; iCounter++ )
{
// add mouse region for each line of text..and set user data
MSYS_DefineRegion( &this->MenuRegion[ iTotal ],
( INT16 )( iBoxXPosition ),
( INT16 )( iBoxYPosition + GetTopMarginSize( this->boxId ) + ( iFontHeight ) * iTotal ),
( INT16 )( iBoxXPosition + iBoxWidth ),
( INT16 )( iBoxYPosition + GetTopMarginSize( this->boxId ) + ( iFontHeight ) * ( iTotal + 1 ) ),
POPUP_OPTION_PRIORITY ,
MSYS_NO_CURSOR,
popupMouseMoveCallback,
popupMouseClickCallback );
MSYS_SetRegionUserData( &this->MenuRegion[ iTotal ], 0, iCounter );
MSYS_SetRegionUserData( &this->MenuRegion[ iTotal ], 1, REGION_OPTION );
MSYS_SetRegionUserData( &this->MenuRegion[ iTotal ], 2, iTotal );
if (!registerPopupRegion( this->MenuRegion[ iTotal ].IDNumber, this->id)){}
iTotal++;
}
// unhighlight all strings in box
UnHighLightBox( this->boxId );
this->CheckAndUpdateTacticalPopUpPositions();
}
void POPUP::DestroyMouseRegions( void )
{
UINT32 iCounter = 0;
for( iCounter = 0; iCounter < GetNumberOfLinesOfTextInBox( this->boxId ); iCounter++ )
{
unregisterPopupRegion(this->MenuRegion[ iCounter ].IDNumber);
MSYS_RemoveRegion( &this->MenuRegion[ iCounter ] );
}
SetRenderFlags( RENDER_FLAG_FULL );
}
void POPUP::AdjustMouseRegions( void )
{
UINT32 iCounter = 0;
UINT32 iTotal = 0;
INT32 iFontHeight = 0;
INT32 iBoxXPosition = 0;
INT32 iBoxYPosition = 0;
INT32 iBoxWidth = 0;
SGPPoint pPosition={0,0};
SGPRect pDimensions={0,0,0,0};
// grab height of font
iFontHeight = GetLineSpace( this->boxId ) + GetFontHeight( GetBoxFont( this->boxId ) );
// get x.y position of box
GetBoxPosition( this->boxId, &pPosition);
// grab box x and y position
iBoxXPosition = pPosition.iX;
iBoxYPosition = pPosition.iY;
// get dimensions..mostly for width
GetBoxSize( this->boxId, &pDimensions );
// get width
iBoxWidth = pDimensions.iRight;
// adjust regions for sub popups
for( iCounter = 0; iCounter < this->subPopupOptionCount ; iCounter++ )
{
this->MenuRegion[ iTotal ].RegionTopLeftX = ( INT16 )( iBoxXPosition );
this->MenuRegion[ iTotal ].RegionTopLeftY = ( INT16 )( iBoxYPosition
+ GetTopMarginSize( this->boxId )
+ ( iFontHeight ) * iTotal );
this->MenuRegion[ iTotal ].RegionBottomRightX = ( INT16 )( iBoxXPosition + iBoxWidth );
this->MenuRegion[ iTotal ].RegionBottomRightY = ( INT16 )( iBoxYPosition
+ GetTopMarginSize( this->boxId )
+ ( iFontHeight ) * ( iTotal + 1 ) );
iTotal++;
}
// adjust regions for options
for( iCounter = 0; iCounter < this->optionCount ; iCounter++ )
{
this->MenuRegion[ iTotal ].RegionTopLeftX = ( INT16 )( iBoxXPosition );
this->MenuRegion[ iTotal ].RegionTopLeftY = ( INT16 )( iBoxYPosition
+ GetTopMarginSize( this->boxId )
+ ( iFontHeight ) * iTotal );
this->MenuRegion[ iTotal ].RegionBottomRightX = ( INT16 )( iBoxXPosition + iBoxWidth );
this->MenuRegion[ iTotal ].RegionBottomRightY = ( INT16 )( iBoxYPosition
+ GetTopMarginSize( this->boxId )
+ ( iFontHeight ) * ( iTotal + 1 ) );
iTotal++;
}
}
void POPUP::ScreenMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason )
{
// btn callback handler for screen mask region
if( ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP ) || ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP ) )
{
if( this->FirstClickInScreenMask == TRUE )
{
this->FirstClickInScreenMask = FALSE;
return;
}
// button event, stop showing menus
if (!this->BoxPersist)
{
this->hide();
}
// update mapscreen
setTeamPanelDirty(TRUE);
setCharacterInfoPanelDirty(TRUE);
setMapScreenBottomDirty(TRUE);
setRenderPBInterface(TRUE);
SetRenderFlags( RENDER_FLAG_FULL );
}
return;
}
void POPUP::MenuBtnCallBack( MOUSE_REGION * pRegion, INT32 iReason )
{
// btn callback handler for LPC region
INT32 iValue = -1;
INT32 iType = 0;
INT32 iTotal = 0;
SOLDIERTYPE * pSoldier = NULL;
UINT8 ubVolume = 10;
// sanity check #1
if (!this || this->boxId < 0 || this->id > POPUP::nextid){
#ifdef JA2TESTVERSION
__debugbreak();
#else
Assert(false);
#endif
}
iValue = MSYS_GetRegionUserData( pRegion, 0 );
iType = MSYS_GetRegionUserData( pRegion, 1 );
iTotal = MSYS_GetRegionUserData( pRegion, 2 );
switch (iType)
{
case REGION_OPTION:
if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
UnHighLightBox( this->boxId );
if (iValue < POPUP_MAX_OPTIONS
&& iValue < this->optionCount
&& iValue >= 0
&& this->options[iValue] != NULL)
{
this->options[iValue]->run(); // run the option's callback
// sanity check #2
// if this popup was fine in check #1 but is broken now, chances are
// we got deleted (or just plain broken) by the callback.
if (!this || this->id > POPUP::nextid){
#ifdef JA2TESTVERSION
__debugbreak();
#else
Assert(false);
#endif
}
this->RebuildBox(); // rebuild the box so that the changes can take effect
if( GetBoxShadeFlag( this->boxId, iTotal ) == FALSE ) // highlight the line again, if appropriate
HighLightBoxLine( this->boxId, iTotal );
}
}
break;
case REGION_SUB_POPUP:
if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP)
{
UnHighLightBox( this->boxId );
if (iValue < POPUP_MAX_SUB_POPUPS
&& iValue < this->subPopupOptionCount
&& iValue >= 0
&& this->subPopupOptions[iValue] != NULL)
{
this->recalculateWidth();
this->subPopupOptions[iValue]->run();
}
}
break;
}
}
void POPUP::MenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason )
{
// mvt callback handler for LPC region
INT32 iTotal = -1;
INT32 iType = 0;
INT32 iValue = 0;
if (!this || this->boxId < 0){
__debugbreak();
}
iTotal = MSYS_GetRegionUserData( pRegion, 2 ); // set this to the total value of all mouse regions
iType = MSYS_GetRegionUserData( pRegion, 1 );
iValue = MSYS_GetRegionUserData( pRegion, 0 );
if (iReason & MSYS_CALLBACK_REASON_GAIN_MOUSE )
{
// highlight string
if( GetBoxShadeFlag( this->boxId, iTotal ) == FALSE )
{
// get the string line handle
HighLightBoxLine( this->boxId, iTotal );
if ( iType == REGION_OPTION && this->options[iValue]->HoverFunctionSet() ) // if it has been set...
this->options[iValue]->runHoverCallback(pRegion); // run the custom mouse callback
}
}
else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE )
{
// unhighlight all strings in box
UnHighLightBox( this->boxId );
}
else if (iReason & MSYS_CALLBACK_REASON_MOVE)
{
// if the hover callback is set then also react to mouse movement within the region (only when available)
if( iType == REGION_OPTION && this->options[iValue]->HoverFunctionSet() && GetBoxShadeFlag( this->boxId, iTotal ) == FALSE )
{
this->options[iValue]->runHoverCallback(pRegion); // run the custom mouse callback
if ( (pRegion->ButtonState & MSYS_LEFT_BUTTON) || (pRegion->ButtonState & MSYS_RIGHT_BUTTON) )
{ // if drag detedted,rebuild the boxstrings
this->RebuildBox();
}
}
}
}
void POPUP::HandleShadingOfLines( void )
{
// check if valid
if( ( this->PopupVisible == FALSE ) || ( this->boxId == - 1 ) )
{
return;
}
UINT8 i = 0;
// subPopups with no options are shaded
for(std::vector<POPUP_SUB_POPUP_OPTION*>::iterator cOption=this->subPopupOptions.begin(); cOption != this->subPopupOptions.end(); ++cOption)
{
if ( (*cOption)->subPopup->optionCount + (*cOption)->subPopup->subPopupOptionCount > 0 )
UnShadeStringInBox( this->boxId, i);
else
ShadeStringInBox( this->boxId, i);
i++;
}
i = 0;
// shade strings past the this->subPopupOptionCount offset
for(std::vector<POPUP_OPTION*>::iterator cOption=this->options.begin(); cOption != this->options.end(); ++cOption)
{
if ((*cOption)->checkAvailability()) {
UnShadeStringInBox(this->boxId, i + this->subPopupOptionCount);
}
else {
SetStringShade((*cOption)->stringHandle, (*cOption)->color_shade); // handle checkAvailability() changing string shade color
ShadeStringInBox(this->boxId, i + this->subPopupOptionCount);
}
i++;
}
return;
}
void POPUP::DetermineBoxPositions( void )
{
// depending on how many boxes there are, reposition as needed
SGPPoint pPoint;
SGPPoint pNewPoint;
SGPRect pDimensions;
if( ( this->PopupVisible == FALSE ) || ( this->boxId == -1 ) )
{
return;
}
// get an idea about what size the box ought to be
pPoint.iX = 0;
pPoint.iY = 0;
SetBoxPosition( this->boxId, pPoint );
GetBoxSize( this->boxId, &pDimensions );
INT32 boxWidth = pDimensions.iRight;
INT32 boxHeight = pDimensions.iBottom;
/*
if ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
{
GetBoxPosition( this->boxId, &pPoint );
this->BoxesX = ( INT16 )pPoint.iX;
this->BoxesY = ( INT16 )pPoint.iY;
}
*/
switch (this->positioningRule){
case POPUP_POSITION_TOP_LEFT:
pPoint.iX = this->OrigPosition.iX;
pPoint.iY = this->OrigPosition.iY;
break;
case POPUP_POSITION_TOP_RIGHT:
pPoint.iX = this->OrigPosition.iX - boxWidth;
pPoint.iY = this->OrigPosition.iY;
break;
case POPUP_POSITION_BOTTOM_RIGHT:
pPoint.iX = this->OrigPosition.iX - boxWidth;
pPoint.iY = this->OrigPosition.iY - boxHeight;
break;
case POPUP_POSITION_BOTTOM_LEFT:
pPoint.iX = this->OrigPosition.iX;
pPoint.iY = this->OrigPosition.iY - boxHeight;
break;
default:
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Incorrect positioning rule for box id: %i \n",this->boxId);
OutputDebugString( debugStr );
#endif
// assume default
pPoint.iX = this->OrigPosition.iX;
pPoint.iY = this->OrigPosition.iY;
return;
}
// Flugente: fix obvious errors
pPoint.iX = max( pPoint.iX, 0 );
pPoint.iX = min( pPoint.iX, SCREEN_WIDTH );
pPoint.iY = max( pPoint.iY, 0 );
pPoint.iY = min( pPoint.iY, SCREEN_HEIGHT );
// set all the other positions to match this one
this->Position = pPoint;
this->BoxesX = pPoint.iX;
this->BoxesY = pPoint.iY;
this->X= pPoint.iX;
this->Y= pPoint.iY;
SetBoxPosition( this->boxId, pPoint );
GetBoxSize( this->boxId, &pDimensions );
// hang it right beside the LPC/EPC box menu
pNewPoint.iX = pPoint.iX + pDimensions.iRight;
pNewPoint.iY = pPoint.iY;
return;
}
void POPUP::CheckAndUpdateTacticalPopUpPositions( void )
{
SGPRect pDimensions2;
SGPPoint pPoint;
if( this->PopupVisible == FALSE )
{
return;
}
if ( (guiTacticalInterfaceFlags & INTERFACE_MAPSCREEN ) )
{
return;
}
GetBoxSize( this->boxId, &pDimensions2 );
if( this->BoxesX + pDimensions2.iRight >= SCREEN_WIDTH )
{
this->BoxesX = ( INT16 ) ( SCREEN_WIDTH - 1 - ( pDimensions2.iRight ) );
SetRenderFlags( RENDER_FLAG_FULL );
}
if( this->BoxesY + pDimensions2.iBottom >= SCREEN_HEIGHT-120 )
{
this->BoxesY = ( INT16 )( SCREEN_HEIGHT - 121 - ( pDimensions2.iBottom ) );
SetRenderFlags( RENDER_FLAG_FULL );
}
pPoint.iX = this->BoxesX;
pPoint.iY = this->BoxesY;
SetBoxPosition( this->boxId, pPoint );
this->RepositionMouseRegions( );
}
void POPUP::RepositionMouseRegions( void )
{
INT16 sDeltaX, sDeltaY;
INT32 iCounter = 0;
if( this->PopupVisible == TRUE )
{
sDeltaX = this->BoxesX - this->MenuRegion[ 0 ].RegionTopLeftX;
sDeltaY = ( INT16 ) ( this->BoxesY - this->MenuRegion[ 0 ].RegionTopLeftY + GetTopMarginSize( this->boxId ) );
// find the delta from the old to the new, and alter values accordingly
for( iCounter = 0; iCounter < ( INT32 )GetNumberOfLinesOfTextInBox( this->boxId ); iCounter++ )
{
this->MenuRegion[ iCounter ].RegionTopLeftX += sDeltaX;
this->MenuRegion[ iCounter ].RegionTopLeftY += sDeltaY;
this->MenuRegion[ iCounter ].RegionBottomRightX += sDeltaX;
this->MenuRegion[ iCounter ].RegionBottomRightY += sDeltaY;
}
gfPausedTacticalRenderFlags = RENDER_FLAG_FULL;
}
}
void POPUP::PositionCursorForBox(void)
{
// position cursor over y of on duty in tactical assignments
SGPPoint pPosition;
SGPRect pDimensions;
INT32 iFontHeight;
// get x.y position of box
GetBoxPosition( this->boxId, &pPosition);
// get dimensions..mostly for width
GetBoxSize( this->boxId, &pDimensions );
iFontHeight = GetLineSpace( this->boxId ) + GetFontHeight( GetBoxFont( this->boxId ) );
if( gGameSettings.fOptions[ TOPTION_DONT_MOVE_MOUSE ] == FALSE )
{
SimulateMouseMovement( pPosition.iX + pDimensions.iRight - 6, pPosition.iY + ( iFontHeight / 2 ) + 2 );
}
}
//////////////////////////////////////////////////////////////////
// Functions for binding POPUP class with MSYS callbacks
//////////////////////////////////////////////////////////////////
PopupIndex * findMouseRegionInIndex(UINT16 regionId)
{
for(std::vector<PopupIndex>::iterator cPopupIndex=gPopupRegionIndex.begin(); cPopupIndex != gPopupRegionIndex.end(); ++cPopupIndex)
if ((*cPopupIndex).regionId == regionId){
return &(*cPopupIndex);
}
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Failed to find callback to mouse region id: %i \n",regionId);
OutputDebugString( debugStr );
#endif
return NULL;
}
BOOLEAN registerPopupRegion(UINT16 rID, UINT32 cID)
{
/*
if (gPopupRegionIndexCounter == MAX_REGIONS_IN_INDEX)
{ // If we can't fit in any more regions, try to rebuild the index before giving up
rebuildPopupRegionIndex(); // since there may be some unregistered regions
if (gPopupRegionIndexCounter == MAX_REGIONS_IN_INDEX)
return FALSE; // if index still full, return false
}
*/
PopupIndex * pi = new PopupIndex;
pi->regionId = rID;
pi->classId = cID;
gPopupRegionIndex.push_back(*pi); // FIXME: memory leak
gPopupRegionIndexCounter++;
return TRUE;
}
BOOLEAN unregisterPopupRegion(UINT16 regionId)
{
for(std::vector<PopupIndex>::iterator cPopupIndex=gPopupRegionIndex.begin(); cPopupIndex != gPopupRegionIndex.end(); ++cPopupIndex)
if ((*cPopupIndex).regionId == regionId){
gPopupRegionIndex.erase(cPopupIndex);
return TRUE;
}
#ifdef JA2TESTVERSION
CHAR8 debugStr[120];
wsprintf(debugStr,"Failed to erase mouse region index: %i \n",regionId);
OutputDebugString( debugStr );
#endif
return FALSE;
}
void rebuildPopupRegionIndex(void)
{/*
UINT8 i,j;
PopupIndex TempPopupIndex[MAX_REGIONS_IN_INDEX];
// cout << "cleaning index"<<endl;
for (i = 0; i < gPopupRegionIndexCounter; i++)
{
TempPopupIndex[i].classId = gPopupRegionIndex[i].classId;
TempPopupIndex[i].regionId = gPopupRegionIndex[i].regionId;
}
j=0; // actual region index
for (i = 0; i < gPopupRegionIndexCounter; i++)
{
if (TempPopupIndex[i].classId < MAX_POPUPS)
{
gPopupRegionIndex[j].classId = TempPopupIndex[i].classId;
gPopupRegionIndex[j].regionId = TempPopupIndex[i].regionId;
j++;
}
}
// We only have j elements worth keeping.
gPopupRegionIndexCounter = j;*/
}
void popupMaskCallback(MOUSE_REGION *pRegion, INT32 iReason)
{
UINT32 cID = findMouseRegionInIndex(pRegion->IDNumber)->classId;
if (cID < 0) return;
POPUP * p = findPopupInIndex(cID);
if (p) { p->ScreenMaskBtnCallback(pRegion, iReason); }
}
void popupMouseMoveCallback(MOUSE_REGION *pRegion, INT32 iReason)
{
UINT32 cID = findMouseRegionInIndex(pRegion->IDNumber)->classId;
if (cID < 0) return;
POPUP * p = findPopupInIndex(cID);
if (p) p->MenuMvtCallBack(pRegion, iReason);
}
void popupMouseClickCallback(MOUSE_REGION *pRegion, INT32 iReason)
{
UINT32 cID = findMouseRegionInIndex(pRegion->IDNumber)->classId;
if (cID < 0) return;
POPUP * p = findPopupInIndex(cID);
if (p) {
p->MenuBtnCallBack(pRegion, iReason);
}
}