mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6102 3b4a5df2-a311-0410-b5c6-a8a6f20db521
1854 lines
45 KiB
C++
1854 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 aaliable 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
|
|
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;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
} |