mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-11 04:31:35 -10:00
remove render option for fog (why was this even there??) add tech model view for missiles with special tech models (will hopefully help spur some work towards fixing the currently broken models) handle Z-buf issue that made the lab interface disappear when the transparent render option was ticked
2888 lines
68 KiB
C++
2888 lines
68 KiB
C++
/*
|
|
* wmcgui.cpp
|
|
* created by WMCoolmon
|
|
*
|
|
* You may not sell or otherwise commercially exploit the source or things you
|
|
* create based on the source.
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* $Logfile: /Freespace2/code/lab/wmcgui.cpp $
|
|
* $Revision: 1.29 $
|
|
* $Date: 2006-08-20 00:47:10 $
|
|
* $Author: taylor $
|
|
*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 1.28 2006/03/22 18:20:06 taylor
|
|
* minor warning fixage
|
|
*
|
|
* Revision 1.27 2006/01/21 02:22:05 wmcoolmon
|
|
* Scripting updates; Special scripting image list; Better operator meta; Orientation type; Wing type; Texture type. Fix for MSVC7 compiling.
|
|
*
|
|
* Revision 1.26 2005/12/06 03:17:48 taylor
|
|
* cleanup some debug log messages:
|
|
* note that a nprintf() with "Warning" or "General" is basically the same thing as mprintf()
|
|
* make sure that OpenAL init failures always get to the debug log
|
|
*
|
|
* Revision 1.25 2005/12/04 19:07:48 wmcoolmon
|
|
* Final commit of codebase
|
|
*
|
|
* Revision 1.23 2005/10/22 20:17:18 wmcoolmon
|
|
* mission-set-nebula fixage; remainder of python code
|
|
*
|
|
* Revision 1.22 2005/10/09 00:43:08 wmcoolmon
|
|
* Extendable modular tables (XMTs); added weapon dialogs to the Lab
|
|
*
|
|
* Revision 1.21 2005/09/25 07:27:33 Goober5000
|
|
* and again
|
|
* --Goober5000
|
|
*
|
|
* Revision 1.20 2005/09/25 07:26:05 Goober5000
|
|
* try to fix the headers
|
|
* --Goober5000
|
|
*
|
|
*/
|
|
|
|
#include "lab/wmcgui.h"
|
|
#include "graphics/2d.h"
|
|
#include "hud/hudbrackets.h"
|
|
#include "parse/parselo.h"
|
|
#include "globalincs/linklist.h"
|
|
#include "io/key.h"
|
|
#include "freespace2/freespace.h"
|
|
#include "localization/localize.h"
|
|
|
|
//Gobals
|
|
GUISystem GUI_system;
|
|
|
|
//*****************************ClassInfoEntry*******************************
|
|
ClassInfoEntry::ClassInfoEntry()
|
|
{
|
|
CIEType = CIE_NONE;
|
|
|
|
for(uint i = 0; i < CIE_NUM_HANDLES; i++)
|
|
{
|
|
IMG_HANDLE_SET_INVALID(Handles[i].Image);
|
|
}
|
|
|
|
Coords[0] = Coords[1] = INT_MAX;
|
|
}
|
|
ClassInfoEntry::~ClassInfoEntry()
|
|
{
|
|
//Unload image handles
|
|
if(CIEType == CIE_IMAGE_NMCSD || CIEType == CIE_IMAGE || CIEType == CIE_IMAGE_BORDER)
|
|
{
|
|
int i = 0;
|
|
int num = sizeof(Handle)/sizeof(int);
|
|
for(; i < num; i++)
|
|
{
|
|
if(IMG_HANDLE_IS_VALID(Handles[i].Image))
|
|
IMG_UNLOAD(Handles[i].Image);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ObjectClassInfoEntry::Parse()
|
|
{
|
|
//Do we actually have a tag?
|
|
//This is hackish, but it should get the job done
|
|
if(check_for_string("<") && !check_for_string("</"))
|
|
{
|
|
char buf[NAME_LENGTH];
|
|
char buf2[NAME_LENGTH+3]; //for the end tag and name buffer
|
|
|
|
//Find the name of the thing we're parsing
|
|
parse_advance(1);
|
|
stuff_string(buf, F_NAME, ">", sizeof(buf)/sizeof(char));
|
|
parse_advance(1); //skip the end ">"
|
|
|
|
if(optional_string("+Name:"))
|
|
{
|
|
stuff_string(buf2, F_NAME, NULL, NAME_LENGTH);
|
|
Name = buf2;
|
|
}
|
|
if(optional_string("+Coords:"))
|
|
{
|
|
stuff_int_list(Coords, 2, RAW_INTEGER_TYPE);
|
|
}
|
|
if(optional_string("+Size:"))
|
|
{
|
|
stuff_int_list(&Coords[2], 2, RAW_INTEGER_TYPE);
|
|
}
|
|
|
|
//LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK
|
|
//LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK
|
|
//LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK
|
|
//LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK
|
|
//LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK
|
|
//LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK LOOK
|
|
|
|
//This is where you add specific classes to parse.
|
|
//Follow the current classes' example, this basically involves
|
|
//a !stricmp(), a resize() (to the number of entries) and multiple Entries[ID].Parse()
|
|
|
|
//=================================================
|
|
if(!stricmp(buf, "Window"))
|
|
{
|
|
Object = GT_WINDOW;
|
|
Entries.resize(WCI_NUM_ENTRIES);
|
|
|
|
//Fill it out
|
|
Entries[WCI_CAPTION].Parse("Caption", CIE_IMAGE_NMCSD);
|
|
Entries[WCI_HIDE].Parse("Hider", CIE_IMAGE_NMCSD);
|
|
Entries[WCI_CLOSE].Parse("Closer", CIE_IMAGE_NMCSD);
|
|
Entries[WCI_BODY].Parse("Body", CIE_IMAGE);
|
|
Entries[WCI_BORDER].Parse("Border", CIE_IMAGE_BORDER);
|
|
}
|
|
else if(!stricmp(buf, "Button"))
|
|
{
|
|
Object = GT_BUTTON;
|
|
Entries.resize(BCI_NUM_ENTRIES);
|
|
|
|
//Fill it out
|
|
Entries[BCI_BUTTON].Parse("Button", CIE_IMAGE_NMCSD);
|
|
}
|
|
|
|
//=================================================
|
|
|
|
//Make sure that the next token isn't an end tag, but
|
|
//is a tag
|
|
ObjectClassInfoEntry temp_ocie;
|
|
while(temp_ocie.Parse())
|
|
{
|
|
Subentries.push_back(temp_ocie);
|
|
temp_ocie = ObjectClassInfoEntry();
|
|
}
|
|
|
|
//We MUST have the end tag
|
|
strcpy(buf2, "</");
|
|
strcat(buf2, buf);
|
|
strcat(buf2, ">");
|
|
|
|
required_string(buf2);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ScreenClassInfoEntry::Parse()
|
|
{
|
|
if(check_for_string("#") && !check_for_string("#End"))
|
|
{
|
|
char buf[NAME_LENGTH];
|
|
|
|
//Find the name of the thing we're parsing
|
|
parse_advance(1);
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf)/sizeof(char));
|
|
|
|
Name = buf;
|
|
|
|
//Parse all objects for this screen
|
|
ObjectClassInfoEntry temp_ocie;
|
|
while(temp_ocie.Parse())
|
|
{
|
|
Entries.push_back(temp_ocie);
|
|
temp_ocie = ObjectClassInfoEntry();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void GUISystem::ParseClassInfo(char* filename)
|
|
{
|
|
if(ClassInfoParsed)
|
|
{
|
|
Warning(LOCATION, "Class info is being parsed twice");
|
|
DestroyClassInfo();
|
|
}
|
|
|
|
lcl_ext_open();
|
|
if(setjmp(parse_abort) != 0)
|
|
{
|
|
mprintf(("Unable to parse %s!\n", filename));
|
|
lcl_ext_close();
|
|
return;
|
|
}
|
|
read_file_text(filename);
|
|
reset_parse();
|
|
ScreenClassInfo.Parse();
|
|
|
|
bool rval;
|
|
do
|
|
{
|
|
ScreenClassInfoEntry* sciep = new ScreenClassInfoEntry;
|
|
rval = sciep->Parse();
|
|
if(rval)
|
|
list_append(&ScreenClassInfo, sciep);
|
|
|
|
} while(rval);
|
|
|
|
lcl_ext_close();
|
|
ClassInfoParsed = true;
|
|
}
|
|
|
|
void ClassInfoEntry::Parse(char* tag, int in_type)
|
|
{
|
|
char buf[MAX_FILENAME_LEN];
|
|
strcpy(buf, "+");
|
|
strcat(buf, tag);
|
|
if(in_type != CIE_IMAGE_BORDER)
|
|
strcat(buf, ":");
|
|
|
|
if(optional_string(buf))
|
|
{
|
|
CIEType = in_type;
|
|
if(in_type == CIE_IMAGE || in_type == CIE_IMAGE_NMCSD)
|
|
{
|
|
int num_frames;
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_N].Image = IMG_LOAD_ANIM(buf, &num_frames, NULL);
|
|
if(IMG_HANDLE_IS_VALID(Handles[CIE_HANDLE_N].Image) && num_frames)
|
|
{
|
|
if(num_frames > 1)
|
|
IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_M].Image, 1);
|
|
if(num_frames > 2)
|
|
IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_C].Image, 2);
|
|
if(num_frames > 3)
|
|
IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_S].Image, 3);
|
|
if(num_frames > 4)
|
|
IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_D].Image, 4);
|
|
|
|
IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_N].Image, 0);
|
|
}
|
|
else
|
|
Handles[CIE_HANDLE_N].Image = IMG_LOAD(buf);
|
|
if(in_type == CIE_IMAGE_NMCSD)
|
|
{
|
|
if(optional_string("+Mouseover:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_M].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Clicked:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_C].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Selected:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_S].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Disabled:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_D].Image = IMG_LOAD(buf);
|
|
}
|
|
}
|
|
if(optional_string("+Coords:"))
|
|
stuff_int_list(Coords, 2, RAW_INTEGER_TYPE);
|
|
}
|
|
else if(in_type == CIE_IMAGE_BORDER)
|
|
{
|
|
if(optional_string("+Top Left:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_TL].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Top Mid:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_TM].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Top Right:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_TR].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Mid Left:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_ML].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Mid Right:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_MR].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Bottom left:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_BL].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Bottom Mid:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_BM].Image = IMG_LOAD(buf);
|
|
}
|
|
if(optional_string("+Bottom Right:"))
|
|
{
|
|
stuff_string(buf, F_NAME, NULL, sizeof(buf));
|
|
Handles[CIE_HANDLE_BR].Image = IMG_LOAD(buf);
|
|
}
|
|
}
|
|
else if(in_type == CIE_COORDS)
|
|
{
|
|
stuff_int_list(Coords, 2, RAW_INTEGER_TYPE);
|
|
}
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
//Do a little extra checking in debug mode
|
|
//This makes sure the skinnger knows if they did something bad
|
|
if(CIEType == CIE_IMAGE || CIEType == CIE_IMAGE_NMCSD)
|
|
{
|
|
int w,h,cw,ch;
|
|
IMG_INFO(Handles[0].Image, &w, &h);
|
|
for(uint i = 1; i < CIE_NUM_HANDLES; i++)
|
|
{
|
|
if(IMG_HANDLE_IS_VALID(Handles[i].Image))
|
|
{
|
|
IMG_INFO(Handles[i].Image, &cw, &ch);
|
|
if(cw != w || ch != h)
|
|
{
|
|
Warning(LOCATION, "Grouped image size unequal; Handle number %d under $%s: has a different size than base image type", i, tag);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int ClassInfoEntry::GetCoords(int *x, int *y)
|
|
{
|
|
int rval = CIE_GC_NONE_SET;
|
|
if(Coords[0]!=INT_MAX && x!=NULL)
|
|
{
|
|
*x=Coords[0];
|
|
rval |= CIE_GC_X_SET;
|
|
}
|
|
if(Coords[1]!=INT_MAX && x!=NULL)
|
|
{
|
|
*y=Coords[1];
|
|
rval |= CIE_GC_Y_SET;
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
|
|
int ObjectClassInfoEntry::GetObjectCoords(int *x, int *y, int *w, int *h)
|
|
{
|
|
int rval = CIE_GC_NONE_SET;
|
|
if(Coords[0] != INT_MAX && x != NULL)
|
|
{
|
|
*x = Coords[0];
|
|
rval |= CIE_GC_X_SET;
|
|
}
|
|
if(Coords[1] != INT_MAX && y != NULL)
|
|
{
|
|
*y = Coords[1];
|
|
rval |= CIE_GC_Y_SET;
|
|
}
|
|
if(Coords[2] != INT_MAX && w != NULL)
|
|
{
|
|
*w = Coords[2];
|
|
rval |= CIE_GC_W_SET;
|
|
}
|
|
if(Coords[3] != INT_MAX && h != NULL)
|
|
{
|
|
*h = Coords[3];
|
|
rval |= CIE_GC_H_SET;
|
|
}
|
|
|
|
return rval;
|
|
}
|
|
//*****************************GUIScreen*******************************
|
|
GUIScreen::GUIScreen(std::string in_Name)
|
|
{
|
|
//Set the name
|
|
Name = in_Name;
|
|
|
|
//Setup the parent system
|
|
//This can actually be null; but you must attach a screen to a
|
|
//system for it to be functional.
|
|
//this may allow for saving of screens in the future. Incredibly useful for HUDs.
|
|
OwnerSystem = NULL;
|
|
|
|
//Get class info
|
|
if(OwnerSystem != NULL)
|
|
{
|
|
OwnerSystem->PushScreen(this);
|
|
ScreenClassInfo = OwnerSystem->GetScreenClassInfo(Name);
|
|
}
|
|
else
|
|
{
|
|
ScreenClassInfo = NULL;
|
|
}
|
|
}
|
|
|
|
GUIScreen::~GUIScreen()
|
|
{
|
|
GUIObject* cgp = (GUIObject*)GET_FIRST(&Guiobjects);
|
|
GUIObject* cgp_next;
|
|
for(; cgp != END_OF_LIST(&Guiobjects); cgp = cgp_next)
|
|
{
|
|
cgp_next = (GUIObject*)GET_NEXT(cgp);
|
|
delete cgp;
|
|
}
|
|
|
|
//Get it out of the system
|
|
// nm; I just realized the linked list class should do this -WMC
|
|
/*
|
|
if(OwnerSystem != NULL && NOT_EMPTY(&OwnerSystem->Screens))
|
|
{
|
|
GUIScreen *csp_next;
|
|
for(GUIScreen *csp = (GUIScreen*)GET_FIRST(&OwnerSystem->Screens); csp != END_OF_LIST(&OwnerSystem->Screens); csp = csp_next)
|
|
{
|
|
csp_next = (GUIScreen*)GET_NEXT(csp);
|
|
if(csp == this)
|
|
list_remove(&OwnerSystem->Screens, csp);
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
ObjectClassInfoEntry *GUIScreen::GetObjectClassInfo(GUIObject *cgp)
|
|
{
|
|
size_t len;
|
|
uint i;
|
|
ObjectClassInfoEntry *ociep;
|
|
|
|
if(cgp->Parent != NULL && cgp->Parent->InfoEntry != NULL)
|
|
{
|
|
ociep = &cgp->Parent->InfoEntry->Subentries[0];
|
|
len = cgp->Parent->InfoEntry->Subentries.size();
|
|
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
if(ociep[i].Name == cgp->Name)
|
|
return &ociep[i];
|
|
}
|
|
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
if(ociep[i].Name.size() == 0 && ociep[i].Object == cgp->Type)
|
|
return &ociep[i];
|
|
}
|
|
}
|
|
else if(cgp->Parent == NULL && ScreenClassInfo != NULL)
|
|
{
|
|
ociep = &ScreenClassInfo->Entries[0];
|
|
len = ScreenClassInfo->Entries.size();
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
if(ociep[i].Name == cgp->Name)
|
|
return &ociep[i];
|
|
}
|
|
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
if(ociep[i].Name.size() == 0 && ociep[i].Object == cgp->Type)
|
|
return &ociep[i];
|
|
}
|
|
}
|
|
|
|
//Generic templates - ie if you want every single OK button to look the same,
|
|
//or every single window to look the same.
|
|
if(OwnerSystem != NULL)
|
|
{
|
|
ociep = &OwnerSystem->GetClassInfo()->Entries[0];
|
|
len = OwnerSystem->GetClassInfo()->Entries.size();
|
|
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
if(ociep[i].Name == cgp->Name)
|
|
return &ociep[i];
|
|
}
|
|
|
|
for(i = 0; i < len; i++)
|
|
{
|
|
if(ociep[i].Name.size() == 0 && ociep[i].Object == cgp->Type)
|
|
return &ociep[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//Adds objects to a screen
|
|
//IMPORTANT: Options added with the same name as
|
|
//older objects will make this function return
|
|
//a pointer to the original object with that name
|
|
GUIObject* GUIScreen::Add(GUIObject* new_gauge)
|
|
{
|
|
if(new_gauge == NULL)
|
|
return NULL;
|
|
|
|
Assert(this != NULL);
|
|
|
|
//First - do we have anything with the same name.
|
|
for(GUIObject *tgp = (GUIObject*) GET_FIRST(&Guiobjects); tgp != END_OF_LIST(&Guiobjects); tgp = (GUIObject*) GET_NEXT(tgp))
|
|
{
|
|
if(tgp->Name == new_gauge->Name)
|
|
{
|
|
//Get rid of the new gauge
|
|
//We don't want it; breaks skinning
|
|
delete new_gauge;
|
|
|
|
if(tgp->Type == new_gauge->Type)
|
|
{
|
|
//If the type of the existing object is the same
|
|
//as the new one, we can safely pass this one off
|
|
delete new_gauge;
|
|
return tgp;
|
|
}
|
|
else
|
|
{
|
|
//This is icky; we might cast a pointer after this.
|
|
//So return NULL with a warning
|
|
Warning(LOCATION, "Attempt to create another object with name '%s'; new object type was %d, existing object type was %d. This may cause null pointer issues.", tgp->Name.c_str(), new_gauge->Type, tgp->Type);
|
|
delete new_gauge;
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Add to the end of the list
|
|
list_append(&Guiobjects, new_gauge);
|
|
new_gauge->OwnerSystem = OwnerSystem;
|
|
new_gauge->OwnerScreen = this;
|
|
|
|
//If no position specified, try to find an empty spot.
|
|
//ALTERNATE IDEA:
|
|
//Try corners of windows.
|
|
/*
|
|
int TempX = -1;
|
|
int TempY = -1;
|
|
int TempTotal = 0;
|
|
GUIObject *agp, *bgp, *dgp;
|
|
bool problem = false;
|
|
//Do X first
|
|
if(new_gauge->Coords[0] < 0)
|
|
{
|
|
for(GUIObject *agp = (GUIObject*) GET_FIRST(&Guiobjects); agp != END_OF_LIST(&Guiobjects); agp = (GUIObject*) GET_NEXT(agp))
|
|
{
|
|
problem = false;
|
|
|
|
TempX = agp->Coords[2] + 1;
|
|
|
|
//More than 50% offscreen? This is unacceptable.
|
|
TempTotal = TempX + new_gauge->Coords[2];
|
|
if(TempTotal > gr_screen.max_w)
|
|
{
|
|
if((float)(TempTotal - gr_screen.max_w)/(float)TempTotal < 0.5f)
|
|
continue;
|
|
}
|
|
|
|
if(new_gauge->Coords[1] < 0)
|
|
{
|
|
for(GUIObject *bgp = (GUIObject*) GET_FIRST(&Guiobjects); bgp != END_OF_LIST(&Guiobjects); bgp = (GUIObject*) GET_NEXT(bgp))
|
|
{
|
|
problem = false;
|
|
|
|
TempY = bgp->Coords[3] + 1;
|
|
for(GUIObject *dgp = (GUIObject*) GET_FIRST(&Guiobjects); dgp != END_OF_LIST(&Guiobjects); dgp = (GUIObject*) GET_NEXT(dgp))
|
|
{
|
|
if(TempX > dgp->Coords[0] && TempX < dgp->Coords[2])
|
|
{
|
|
problem = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(GUIObject *dgp = (GUIObject*) GET_FIRST(&Guiobjects); dgp != END_OF_LIST(&Guiobjects); dgp = (GUIObject*) GET_NEXT(dgp))
|
|
{
|
|
if( TempX > dgp->Coords[0]
|
|
&& TempX < dgp->Coords[2]
|
|
&& new_gauge->Coords[1] > dgp->Coords[1]
|
|
&& new_gauge->Coords[1] < dgp->Coords[3])
|
|
{
|
|
problem = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!problem)
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Set actual coordinates
|
|
if(Coords[0] < 0)
|
|
{
|
|
if(TempX < 0)
|
|
Coords[0] = 0;
|
|
else
|
|
Coords[0] = TempX;
|
|
}
|
|
if(Coords[1] < 0)
|
|
{
|
|
if(TempY < 0)
|
|
Coords[1] = 0;
|
|
else
|
|
Coords[1] = TempY;
|
|
}*/
|
|
|
|
//For skinning
|
|
new_gauge->SetCIPointer();
|
|
//Set position and stuff
|
|
new_gauge->GetOIECoords(&new_gauge->Coords[0], &new_gauge->Coords[1], &new_gauge->Coords[2], &new_gauge->Coords[3]);
|
|
//In case we need to resize
|
|
new_gauge->OnRefreshSize();
|
|
|
|
return new_gauge;
|
|
}
|
|
|
|
int GUIScreen::OnFrame(float frametime, bool doevents)
|
|
{
|
|
GUIObject* cgp;
|
|
GUIObject* cgp_prev;
|
|
bool SomethingPressed = false;
|
|
|
|
if(NOT_EMPTY(&Guiobjects) && doevents)
|
|
{
|
|
//Note that children WILL be changing this variable as they go along,
|
|
//as they use up statuses.
|
|
int status = OwnerSystem->GetStatus();
|
|
|
|
//Pass the status on
|
|
GUIObject* cgp = (GUIObject*)GET_LAST(&Guiobjects);
|
|
cgp->Status |= (status & GST_KEYBOARD_STATUS);
|
|
for(; cgp != END_OF_LIST(&Guiobjects); cgp = cgp_prev)
|
|
{
|
|
//In case an object deletes itself
|
|
cgp_prev = (GUIObject*)GET_PREV(cgp);
|
|
cgp->LastStatus = cgp->Status;
|
|
cgp->Status = 0;
|
|
|
|
//If we are moving something, nothing else can get click events
|
|
if(OwnerSystem->GetGraspedObject() == NULL)
|
|
{
|
|
if(OwnerSystem->GetMouseX() >= cgp->Coords[0]
|
|
&& OwnerSystem->GetMouseX() <= cgp->Coords[2]
|
|
&& OwnerSystem->GetMouseY() >= cgp->Coords[1]
|
|
&& OwnerSystem->GetMouseY() <= cgp->Coords[3])
|
|
{
|
|
cgp->Status |= (status & GST_MOUSE_STATUS);
|
|
if(status & GST_MOUSE_PRESS)
|
|
{
|
|
SomethingPressed = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
cgp->OnFrame(frametime, &status);
|
|
}
|
|
}
|
|
|
|
for(uint i = DeletionCache.size(); i > 0; i--)
|
|
{
|
|
delete DeletionCache[i-1];
|
|
DeletionCache.pop_back();
|
|
}
|
|
|
|
// save zbuffer so that we can reset it after drawing (FIXME: this could probably be done better)
|
|
int saved_zbuf = gr_zbuffer_get();
|
|
gr_zbuffer_set(GR_ZBUFF_NONE);
|
|
|
|
//Draw now. This prevents problems from an object deleting itself or moving around in the list
|
|
for(cgp = (GUIObject*)GET_LAST(&Guiobjects); cgp != END_OF_LIST(&Guiobjects); cgp = (GUIObject*)GET_PREV(cgp))
|
|
{
|
|
if(!doevents)
|
|
cgp->Status = 0;
|
|
cgp->OnDraw(frametime);
|
|
}
|
|
|
|
// reset zbuffer to saved value
|
|
gr_zbuffer_set(saved_zbuf);
|
|
|
|
if(SomethingPressed)
|
|
return GSOF_SOMETHINGPRESSED;
|
|
else
|
|
return GSOF_NOTHINGPRESSED;
|
|
}
|
|
|
|
//*****************************GUISystem*******************************
|
|
GUISystem::GUISystem()
|
|
{
|
|
GraspedGuiobject=ActiveObject=NULL;
|
|
Status=LastStatus=0;
|
|
|
|
//Fill out Guiobjects with some handy info
|
|
//On 2nd thought, don't. This is hackish.
|
|
/*
|
|
Guiobjects.OwnerSystem=this;
|
|
Guiobjects.Coords[0] = 0;
|
|
Guiobjects.Coords[1] = 0;
|
|
Guiobjects.Coords[2] = gr_screen.clip_width;
|
|
Guiobjects.Coords[3] = gr_screen.clip_height;
|
|
Guiobjects.ChildCoords[0] = gr_screen.clip_left;
|
|
Guiobjects.ChildCoords[1] = gr_screen.clip_top;
|
|
Guiobjects.ChildCoords[2] = gr_screen.clip_right;
|
|
Guiobjects.ChildCoords[3] = gr_screen.clip_bottom;*/
|
|
|
|
//Make ClassInfo all NULL
|
|
/*
|
|
for(uint i = 0; i < GT_NUM_TYPES; i++)
|
|
{
|
|
ClassInfo[i] = NULL;
|
|
}*/
|
|
ClassInfoParsed = false;
|
|
}
|
|
GUISystem::~GUISystem()
|
|
{
|
|
GUIScreen* csp = (GUIScreen*)GET_FIRST(&Screens);
|
|
GUIScreen* csp_next;
|
|
for(; csp != END_OF_LIST(&Screens); csp = csp_next)
|
|
{
|
|
csp_next = (GUIScreen*)GET_NEXT(csp);
|
|
delete csp;
|
|
}
|
|
DestroyClassInfo();
|
|
}
|
|
|
|
GUIScreen *GUISystem::PushScreen(GUIScreen *csp)
|
|
{
|
|
Assert(csp != NULL);
|
|
|
|
list_append(&Screens, csp);
|
|
csp->OwnerSystem = this;
|
|
csp->ScreenClassInfo = GetScreenClassInfo(csp->Name);
|
|
|
|
return csp;
|
|
}
|
|
|
|
//Removes a screen from a GUISystem
|
|
//Handy if you want to save window movements and such;
|
|
//just call this and it'll take care of everything
|
|
void GUISystem::PullScreen(GUIScreen *in_screen)
|
|
{
|
|
GUIScreen *csp_next;
|
|
for(GUIScreen *csp = (GUIScreen*)GET_FIRST(&Screens); csp != END_OF_LIST(&Screens); csp = csp_next)
|
|
{
|
|
csp_next = (GUIScreen*)GET_NEXT(csp);
|
|
if(csp == in_screen)
|
|
{
|
|
csp->prev->next = csp->next;
|
|
csp->next->prev = csp->prev;
|
|
csp->next = csp;
|
|
csp->prev = csp;
|
|
csp->OwnerSystem = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
ScreenClassInfoEntry *GUISystem::GetScreenClassInfo(const std::string & screen_name)
|
|
{
|
|
ScreenClassInfoEntry *sciep;
|
|
for(sciep = (ScreenClassInfoEntry*)GET_FIRST(&ScreenClassInfo); sciep != END_OF_LIST(&ScreenClassInfo); sciep = (ScreenClassInfoEntry*)GET_NEXT(sciep))
|
|
{
|
|
if(sciep->GetName() == screen_name)
|
|
return sciep;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int GUISystem::OnFrame(float frametime, bool doevents, bool clearandflip)
|
|
{
|
|
//Set the global status variables for this frame
|
|
LastStatus = Status;
|
|
Status = GST_MOUSE_OVER;
|
|
|
|
bool something_pressed = false;
|
|
int unused_queue;
|
|
if(clearandflip)
|
|
gr_clear();
|
|
|
|
if(NOT_EMPTY(&Screens))
|
|
{
|
|
if(doevents)
|
|
{
|
|
KeyPressed = game_check_key();
|
|
|
|
//Add keyboard event stuff
|
|
if(KeyPressed)
|
|
{
|
|
Status |= GST_KEYBOARD_KEYPRESS;
|
|
|
|
if(KeyPressed & KEY_CTRLED)
|
|
Status |= GST_KEYBOARD_CTRL;
|
|
if(KeyPressed & KEY_ALTED)
|
|
Status |= GST_KEYBOARD_ALT;
|
|
if(KeyPressed & KEY_SHIFTED)
|
|
Status |= GST_KEYBOARD_SHIFT;
|
|
}
|
|
|
|
//Add mouse event stuff
|
|
if(mouse_down(MOUSE_LEFT_BUTTON))
|
|
Status |= GST_MOUSE_LEFT_BUTTON;
|
|
else if(mouse_down(MOUSE_MIDDLE_BUTTON))
|
|
Status |= GST_MOUSE_MIDDLE_BUTTON;
|
|
else if(mouse_down(MOUSE_RIGHT_BUTTON))
|
|
Status |= GST_MOUSE_RIGHT_BUTTON;
|
|
|
|
//Now that we are done setting status, add all that stuff to the unused queue
|
|
//Children will be changing this function as they do stuff with statuses
|
|
unused_queue = Status;
|
|
|
|
mouse_get_pos(&MouseX, &MouseY);
|
|
|
|
//Handle any grasped object (we are in the process of moving this)
|
|
if(GraspedGuiobject != NULL)
|
|
{
|
|
if(Status & GraspingButton)
|
|
{
|
|
something_pressed = true;
|
|
GraspedGuiobject->SetPosition(MouseX - GraspedDiff[0], MouseY - GraspedDiff[1]);
|
|
GraspedGuiobject->Status = (Status & GST_MOUSE_STATUS);
|
|
}
|
|
else
|
|
{
|
|
GraspedGuiobject = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
GUIScreen *csp_prev; //so screens can delete themselves
|
|
for(GUIScreen* csp = (GUIScreen*)GET_LAST(&Screens); csp != END_OF_LIST(&Screens); csp = csp_prev)
|
|
{
|
|
csp_prev = (GUIScreen*)GET_PREV(csp);
|
|
if(csp->OnFrame(frametime, doevents) == GSOF_SOMETHINGPRESSED)
|
|
something_pressed = true;
|
|
}
|
|
}
|
|
|
|
if(clearandflip)
|
|
gr_flip();
|
|
|
|
if(something_pressed)
|
|
return GSOF_SOMETHINGPRESSED;
|
|
else
|
|
return GSOF_NOTHINGPRESSED;
|
|
}
|
|
|
|
void GUISystem::SetActiveObject(GUIObject *cgp)
|
|
{
|
|
if(cgp != NULL)
|
|
{
|
|
ActiveObject = cgp;
|
|
//Move everything to the end of the list
|
|
//This way, it gets precedence
|
|
while(cgp->Parent != NULL)
|
|
{
|
|
list_move_append(&cgp->Parent->Children, cgp);
|
|
cgp = cgp->Parent;
|
|
}
|
|
|
|
//Eventually, we make this last guy the last object in Guiobjects
|
|
list_move_append(&cgp->OwnerScreen->Guiobjects, cgp);
|
|
}
|
|
}
|
|
|
|
void GUISystem::SetGraspedObject(GUIObject *cgp, int button)
|
|
{
|
|
//Protect thyself!
|
|
if(cgp == NULL)
|
|
return;
|
|
|
|
GraspedGuiobject = cgp;
|
|
GraspingButton = button;
|
|
GraspedDiff[0] = MouseX - cgp->Coords[0];
|
|
GraspedDiff[1] = MouseY - cgp->Coords[1];
|
|
}
|
|
|
|
void GUISystem::DestroyClassInfo()
|
|
{
|
|
ScreenClassInfoEntry *sciep, *next_sciep;
|
|
for(sciep = (ScreenClassInfoEntry*)GET_FIRST(&ScreenClassInfo); sciep != END_OF_LIST(&ScreenClassInfo); sciep = next_sciep)
|
|
{
|
|
next_sciep = (ScreenClassInfoEntry*)GET_NEXT(sciep);
|
|
delete sciep;
|
|
}
|
|
ClassInfoParsed = false;
|
|
}
|
|
|
|
//*****************************GUIObject*******************************
|
|
GUIObject::GUIObject(std::string in_Name, int x_coord, int y_coord, int x_width, int y_height, int in_style)
|
|
{
|
|
//General stuff
|
|
next = prev = this;
|
|
LastStatus = Status = 0;
|
|
OwnerSystem = NULL;
|
|
OwnerScreen = NULL;
|
|
Parent = NULL;
|
|
CloseFunction = NULL;
|
|
|
|
//These would make no sense
|
|
//x_coord and y_coord of < 0 mean to let the parent handle placement.
|
|
if(x_width == 0 || y_height == 0)
|
|
return;
|
|
|
|
//No! Bad!
|
|
if(in_Name.length() < 1)
|
|
return;
|
|
|
|
Name = in_Name;
|
|
Coords[0] = x_coord;
|
|
Coords[1] = y_coord;
|
|
Coords[2] = x_coord + x_width;
|
|
Coords[3] = y_coord + y_height;
|
|
|
|
Style = in_style;
|
|
|
|
if(x_width > 0)
|
|
Style |= GS_NOAUTORESIZEX;
|
|
if(y_height > 0)
|
|
Style |= GS_NOAUTORESIZEY;
|
|
|
|
Type = GT_NONE;
|
|
InfoEntry = NULL;
|
|
}
|
|
|
|
GUIObject::~GUIObject()
|
|
{
|
|
if(CloseFunction != NULL)
|
|
CloseFunction(this);
|
|
//Set these properly
|
|
next->prev = prev;
|
|
prev->next = next;
|
|
DeleteChildren();
|
|
}
|
|
|
|
void GUIObject::DeleteChildren(GUIObject* exception)
|
|
{
|
|
GUIObject* cgp = (GUIObject*)GET_FIRST(&Children);
|
|
GUIObject* cgp_next;
|
|
for(; cgp != END_OF_LIST(&Children); cgp = cgp_next)
|
|
{
|
|
cgp_next = (GUIObject*)GET_NEXT(cgp);
|
|
delete cgp;
|
|
}
|
|
}
|
|
|
|
GUIObject* GUIObject::AddChildInternal(GUIObject *cgp)
|
|
{
|
|
if(cgp == NULL)
|
|
return NULL;
|
|
|
|
cgp->Style |= GS_INTERNALCHILD;
|
|
|
|
//Add to end of child list
|
|
list_append(&Children, cgp);
|
|
|
|
cgp->Parent = this;
|
|
cgp->OwnerSystem = OwnerSystem;
|
|
cgp->OwnerScreen = OwnerScreen;
|
|
|
|
//Update coordinates (Should be relative x/y and width/height) to absolute coordinates
|
|
cgp->Coords[0] += Coords[0];
|
|
cgp->Coords[1] += Coords[1];
|
|
cgp->Coords[2] += Coords[0];
|
|
cgp->Coords[3] += Coords[1];
|
|
|
|
//For skinning
|
|
cgp->SetCIPointer();
|
|
//Check position
|
|
cgp->GetOIECoords(&cgp->Coords[0], &cgp->Coords[1], &cgp->Coords[2], &cgp->Coords[3]);
|
|
//In case we need to resize
|
|
cgp->OnRefreshSize();
|
|
|
|
return cgp;
|
|
}
|
|
|
|
GUIObject* GUIObject::AddChild(GUIObject* cgp)
|
|
{
|
|
if(cgp == NULL)
|
|
return NULL;
|
|
|
|
//AddInternalChild must be used
|
|
if(cgp->Style & GS_INTERNALCHILD)
|
|
return NULL;
|
|
|
|
//Add to end of child list
|
|
list_append(&Children, cgp);
|
|
|
|
cgp->Parent = this;
|
|
cgp->OwnerSystem = OwnerSystem;
|
|
cgp->OwnerScreen = OwnerScreen;
|
|
|
|
//Update coordinates (Should be relative x/y and width/height) to absolute coordinates
|
|
cgp->Coords[0] += ChildCoords[0];
|
|
cgp->Coords[1] += ChildCoords[1];
|
|
cgp->Coords[2] += ChildCoords[0];
|
|
cgp->Coords[3] += ChildCoords[1];
|
|
|
|
//For skinning
|
|
cgp->SetCIPointer();
|
|
//Check position
|
|
cgp->GetOIECoords(&cgp->Coords[0], &cgp->Coords[1], &cgp->Coords[2], &cgp->Coords[3]);
|
|
//In case we need to resize
|
|
cgp->OnRefreshSize();
|
|
|
|
return cgp;
|
|
}
|
|
|
|
void GUIObject::Delete()
|
|
{
|
|
if(OwnerScreen != NULL)
|
|
OwnerScreen->DeleteObject(this);
|
|
else
|
|
delete this;
|
|
}
|
|
|
|
void GUIObject::OnDraw(float frametime)
|
|
{
|
|
DoDraw(frametime);
|
|
if(!(Style & GS_HIDDEN))
|
|
{
|
|
GUIObject *cgp_prev;
|
|
for(GUIObject* cgp = (GUIObject*)GET_LAST(&Children); cgp != END_OF_LIST(&Children); cgp = cgp_prev)
|
|
{
|
|
cgp_prev = (GUIObject*)GET_PREV(cgp);
|
|
cgp->OnDraw(frametime);
|
|
}
|
|
}
|
|
}
|
|
|
|
int GUIObject::OnFrame(float frametime, int *unused_queue)
|
|
{
|
|
int rval = OF_TRUE;
|
|
|
|
GUIObject *cgp_prev; //Elements will move themselves to the end of the list if they become active
|
|
for(GUIObject *cgp = (GUIObject*)GET_LAST(&Children); cgp != END_OF_LIST(&Children); cgp = cgp_prev)
|
|
{
|
|
cgp_prev = (GUIObject*)GET_PREV(cgp);
|
|
cgp->LastStatus = cgp->Status;
|
|
cgp->Status = 0;
|
|
|
|
if(Status & GST_MOUSE_OVER)
|
|
{
|
|
if(OwnerSystem->GetMouseX() >= cgp->Coords[0]
|
|
&& OwnerSystem->GetMouseX() <= cgp->Coords[2]
|
|
&& OwnerSystem->GetMouseY() >= cgp->Coords[1]
|
|
&& OwnerSystem->GetMouseY() <= cgp->Coords[3])
|
|
{
|
|
cgp->Status |= (Status & GST_MOUSE_STATUS);
|
|
}
|
|
}
|
|
if(cgp == GET_LAST(&Children))
|
|
{
|
|
cgp->Status |= (Status & GST_KEYBOARD_STATUS);
|
|
}
|
|
cgp->OnFrame(frametime, &Status);
|
|
}
|
|
|
|
if(Status)
|
|
{
|
|
//MOUSE OVER
|
|
if(Status & GST_MOUSE_OVER)
|
|
{
|
|
rval = DoMouseOver(frametime);
|
|
|
|
/*if(rval == OF_DESTROYED)
|
|
return OF_DESTROYED;*/
|
|
if(rval == OF_TRUE)
|
|
(*unused_queue) &= ~GST_MOUSE_OVER;
|
|
}
|
|
|
|
//MOUSE DOWN
|
|
if(Status & GST_MOUSE_PRESS)
|
|
{
|
|
rval = DoMouseDown(frametime);
|
|
|
|
/*if(rval == OF_DESTROYED)
|
|
return OF_DESTROYED;*/
|
|
if(rval == OF_TRUE)
|
|
(*unused_queue) &= ~(GST_MOUSE_LEFT_BUTTON | GST_MOUSE_RIGHT_BUTTON | GST_MOUSE_MIDDLE_BUTTON);
|
|
}
|
|
|
|
//MOUSE UP
|
|
if((LastStatus & GST_MOUSE_PRESS) && !(OwnerSystem->GetStatus() & GST_MOUSE_PRESS))
|
|
{
|
|
rval = DoMouseUp(frametime);
|
|
|
|
/*if(rval == OF_DESTROYED)
|
|
return OF_DESTROYED;*/
|
|
if(rval == OF_TRUE)
|
|
(*unused_queue) &= ~(GST_MOUSE_LEFT_BUTTON | GST_MOUSE_RIGHT_BUTTON | GST_MOUSE_MIDDLE_BUTTON);
|
|
}
|
|
|
|
//KEY STATE
|
|
if((Status & GST_KEYBOARD_CTRL) || (Status & GST_KEYBOARD_ALT) || (Status & GST_KEYBOARD_SHIFT))
|
|
{
|
|
rval = DoKeyState(frametime);
|
|
|
|
/*if(rval == OF_DESTROYED)
|
|
return OF_DESTROYED;*/
|
|
if(rval == OF_TRUE)
|
|
(*unused_queue) &= ~(GST_KEYBOARD_CTRL | GST_KEYBOARD_ALT | GST_KEYBOARD_SHIFT);
|
|
}
|
|
|
|
//KEYPRESS
|
|
if(Status & GST_KEYBOARD_KEYPRESS)
|
|
{
|
|
rval = DoKeyPress(frametime);
|
|
|
|
/*if(rval == OF_DESTROYED)
|
|
return OF_DESTROYED;*/
|
|
if(rval == OF_TRUE)
|
|
(*unused_queue) &= ~GST_KEYBOARD_KEYPRESS;
|
|
}
|
|
}
|
|
|
|
if(!(Status & GST_MOUSE_OVER) && (LastStatus & GST_MOUSE_OVER))
|
|
{
|
|
rval = DoMouseOut(frametime);
|
|
}
|
|
|
|
/*if(rval == OF_DESTROYED)
|
|
return OF_DESTROYED;*/
|
|
|
|
/*if(!child_keypress && (Status & GST_KEY_PRESSED))
|
|
rval = DoKeyPress(OwnerSystem->CurrentKeyChar,frametime);*/
|
|
|
|
return DoFrame(frametime);
|
|
}
|
|
|
|
void GUIObject::OnMove(int dx, int dy)
|
|
{
|
|
Coords[0]+=dx;
|
|
Coords[1]+=dy;
|
|
Coords[2]+=dx;
|
|
Coords[3]+=dy;
|
|
ChildCoords[0]+=dx;
|
|
ChildCoords[1]+=dy;
|
|
ChildCoords[2]+=dx;
|
|
ChildCoords[3]+=dy;
|
|
|
|
for(GUIObject *cgp = (GUIObject*)GET_FIRST(&Children); cgp != END_OF_LIST(&Children); cgp = (GUIObject*)GET_NEXT(cgp))
|
|
{
|
|
cgp->OnMove(dx, dy);
|
|
}
|
|
|
|
DoMove(dx, dy);
|
|
}
|
|
|
|
int GUIObject::GetCIECoords(int id, int *x, int *y)
|
|
{
|
|
if(InfoEntry!=NULL)
|
|
{
|
|
int rv = InfoEntry->GetCoords(id, x, y);
|
|
if(rv & CIE_GC_X_SET)
|
|
{
|
|
if(*x < 0)
|
|
*x += Coords[2];
|
|
else
|
|
*x += Coords[0];
|
|
}
|
|
if(rv & CIE_GC_Y_SET)
|
|
{
|
|
if(*y < 0)
|
|
*y += Coords[3];
|
|
else
|
|
*y += Coords[1];
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
return CIE_GC_NONE_SET;
|
|
}
|
|
|
|
int GUIObject::GetOIECoords(int *x1, int *y1, int *x2, int *y2)
|
|
{
|
|
if(InfoEntry != NULL)
|
|
{
|
|
int rv = InfoEntry->GetObjectCoords(x1, y1, x2, y2);
|
|
if(Parent != NULL)
|
|
{
|
|
if(rv & CIE_GC_X_SET)
|
|
{
|
|
if(*x1 < 0)
|
|
*x1 += Parent->ChildCoords[2];
|
|
else
|
|
*x1 += Parent->ChildCoords[0];
|
|
}
|
|
if(rv & CIE_GC_Y_SET)
|
|
{
|
|
if(*y1 < 0)
|
|
*y1 += Parent->ChildCoords[3];
|
|
else
|
|
*y1 += Parent->ChildCoords[1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(rv & CIE_GC_X_SET)
|
|
{
|
|
if(*x1 < 0)
|
|
*x1 += gr_screen.clip_right;
|
|
else
|
|
*x1 += gr_screen.clip_left;
|
|
}
|
|
if(rv & CIE_GC_Y_SET)
|
|
{
|
|
if(*y1 < 0)
|
|
*y1 += gr_screen.clip_bottom;
|
|
else
|
|
*y1 += gr_screen.clip_top;
|
|
}
|
|
}
|
|
if(rv & CIE_GC_W_SET)
|
|
{
|
|
*x2 = *x1 + *x2;
|
|
Style |= GS_NOAUTORESIZEX;
|
|
}
|
|
if(rv & CIE_GC_H_SET)
|
|
{
|
|
*y2 = *y1 + *y2;
|
|
Style |= GS_NOAUTORESIZEY;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
return CIE_GC_NONE_SET;
|
|
}
|
|
|
|
//Call this after an object's type is set to enable the GUIObject CIE functions
|
|
void GUIObject::SetCIPointer()
|
|
{
|
|
if(OwnerScreen)
|
|
InfoEntry=OwnerScreen->GetObjectClassInfo(this);
|
|
}
|
|
|
|
void GUIObject::SetPosition(int x, int y)
|
|
{
|
|
int dx, dy;
|
|
dx = x - Coords[0];
|
|
dy = y - Coords[1];
|
|
|
|
if(dx == 0 && dy == 0)
|
|
return;
|
|
|
|
if(Parent != NULL)
|
|
{
|
|
//Don't let stuff get moved outside client window
|
|
if(Coords[2] + dx > Parent->Coords[2])
|
|
dx = Parent->Coords[2] - Coords[2];
|
|
if(Coords[3] + dy > gr_screen.clip_bottom)
|
|
dy = Parent->Coords[3] - Coords[3];
|
|
|
|
//Check these last, so we're sure we can move stuff around still
|
|
if(Coords[0] + dx < gr_screen.clip_left)
|
|
dx = Parent->Coords[0] - Coords[0];
|
|
if(Coords[1] + dy < gr_screen.clip_top)
|
|
dy = Parent->Coords[1] - Coords[1];
|
|
}
|
|
|
|
OnMove(dx, dy);
|
|
}
|
|
|
|
//*****************************Window*******************************
|
|
int Window::DoRefreshSize()
|
|
{
|
|
float num;
|
|
int w=0, h=0;
|
|
//Top left, top right, bottom left, bottom right
|
|
int CornerWidths[4];
|
|
|
|
//Determine left border's width
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_ML)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_ML), &BorderSizes[0], NULL);
|
|
else
|
|
BorderSizes[0] = W_BORDERHEIGHT;
|
|
|
|
//Determine right border's width
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_MR)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_MR), &BorderSizes[2], NULL);
|
|
else
|
|
BorderSizes[2] = W_BORDERWIDTH;
|
|
|
|
//Determine top border height
|
|
bool custom_top = true;
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TL)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TL), NULL, &BorderSizes[1]);
|
|
else if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR), NULL, &BorderSizes[1]);
|
|
else if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TM)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TM), NULL, &BorderSizes[1]);
|
|
else
|
|
{
|
|
custom_top = false;
|
|
BorderSizes[1] = W_BORDERHEIGHT;
|
|
}
|
|
|
|
//Determine bottom border height
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), NULL, &BorderSizes[3]);
|
|
else if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BR)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BR), NULL, &BorderSizes[3]);
|
|
else if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM), NULL, &BorderSizes[3]);
|
|
else
|
|
BorderSizes[3] = W_BORDERHEIGHT;
|
|
|
|
|
|
//Determine corner sizes
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TL)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), &CornerWidths[0], NULL);
|
|
else
|
|
CornerWidths[0] = BorderSizes[0];
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR), &CornerWidths[1], NULL);
|
|
else
|
|
CornerWidths[1] = BorderSizes[2];
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), &CornerWidths[2], NULL);
|
|
else
|
|
CornerWidths[2] = BorderSizes[0];
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BR)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), &CornerWidths[3], NULL);
|
|
else
|
|
CornerWidths[3] = BorderSizes[2];
|
|
|
|
|
|
//Do child stuff
|
|
ChildCoords[0] = Coords[0] + BorderSizes[0];
|
|
if(custom_top || (Style & WS_NOTITLEBAR))
|
|
ChildCoords[1] = Coords[1] + BorderSizes[1]; //Set earlier on
|
|
else
|
|
ChildCoords[1] = Coords[1] + gr_get_font_height() + 5 + 3*W_BORDERHEIGHT;
|
|
ChildCoords[2] = Coords[2] - BorderSizes[2];
|
|
ChildCoords[3] = Coords[3] - BorderSizes[3];
|
|
|
|
if(!(Style & GS_NOAUTORESIZEX))
|
|
{
|
|
ChildCoords[2] = Coords[2] = 0;
|
|
}
|
|
if(!(Style & GS_NOAUTORESIZEY))
|
|
{
|
|
ChildCoords[3] = Coords[3] = 0;
|
|
}
|
|
|
|
for(GUIObject *cgp = (GUIObject*)GET_FIRST(&Children); cgp != END_OF_LIST(&Children); cgp = (GUIObject*)GET_NEXT(cgp))
|
|
{
|
|
//SetPosition children around so they're within the upper-left corner of dialog
|
|
if(cgp->Coords[0] < ChildCoords[0])
|
|
cgp->SetPosition(ChildCoords[0], cgp->Coords[1] + BorderSizes[0]);
|
|
if(cgp->Coords[1] < ChildCoords[1])
|
|
cgp->SetPosition(cgp->Coords[0], Coords[1] + BorderSizes[1]);
|
|
|
|
//Resize window to fit children
|
|
if(cgp->Coords[2] > ChildCoords[2] && !(Style & GS_NOAUTORESIZEX))
|
|
{
|
|
ChildCoords[2] = cgp->Coords[2];
|
|
Coords[2] = cgp->Coords[2] + BorderSizes[2];
|
|
}
|
|
if(cgp->Coords[3] > ChildCoords[3] && !(Style & GS_NOAUTORESIZEY))
|
|
{
|
|
ChildCoords[3] = cgp->Coords[3];
|
|
Coords[3] = cgp->Coords[3] + BorderSizes[3];
|
|
}
|
|
}
|
|
|
|
//Find caption coordinates
|
|
if(!(Style & WS_NOTITLEBAR))
|
|
{
|
|
int close_w,close_h,hide_w,hide_h;
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_CLOSE)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_CLOSE), &close_w, &close_h);
|
|
else
|
|
gr_get_string_size(&close_w, &close_h, "X");
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_HIDE)))
|
|
IMG_INFO(GetCIEImageHandle(WCI_HIDE), &hide_w, &hide_h);
|
|
else
|
|
gr_get_string_size(&hide_w, &hide_h, "-");
|
|
|
|
int caption_min_size;
|
|
if(Caption.size() > 0)
|
|
{
|
|
gr_get_string_size(&w, &h, (char *)Caption.c_str());
|
|
caption_min_size = w + close_w + hide_w;
|
|
}
|
|
else
|
|
{
|
|
caption_min_size = close_w + hide_w;
|
|
}
|
|
|
|
if((Coords[2] - Coords[0]) < (caption_min_size))
|
|
Coords[2] = Coords[0] + caption_min_size + BorderSizes[0] + BorderSizes[2];
|
|
|
|
if(Caption.size() > 0)
|
|
{
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_CAPTION)))
|
|
{
|
|
int cw, ch;
|
|
CaptionCoords[0] = Coords[0] + BorderSizes[0];
|
|
CaptionCoords[1] = Coords[1] + BorderSizes[1];
|
|
GetCIECoords(WCI_CAPTION, &CaptionCoords[0], &CaptionCoords[1]);
|
|
|
|
//do the image
|
|
IMG_INFO(GetCIEImageHandle(WCI_CAPTION), &cw, &ch);
|
|
num = (float) w / cw;
|
|
CaptionRectList = bitmap_rect_list(Coords[0] + CornerWidths[2], Coords[1], w, ch, 0, 0, 1.0f, 1.0f);
|
|
h = ch;
|
|
}
|
|
else
|
|
{
|
|
h += 5;
|
|
CaptionCoords[0] = Coords[0] +(((Coords[2]-Coords[0]) - w) / 2);
|
|
CaptionCoords[1] = Coords[1] + BorderSizes[1];
|
|
}
|
|
CaptionCoords[2] = CaptionCoords[0] + w;
|
|
CaptionCoords[3] = CaptionCoords[1] + h;
|
|
}
|
|
|
|
//Find close coordinates now
|
|
CloseCoords[0] = Coords[2] - close_w;
|
|
CloseCoords[1] = Coords[1] + BorderSizes[1];
|
|
GetCIECoords(WCI_CLOSE, &CloseCoords[0], &CloseCoords[1]);
|
|
CloseCoords[2] = CloseCoords[0] + close_w;
|
|
CloseCoords[3] = CloseCoords[1] + close_h;
|
|
|
|
//Find hide coordinates now
|
|
HideCoords[0] = CloseCoords[0] - hide_w;
|
|
HideCoords[1] = CloseCoords[1];
|
|
GetCIECoords(WCI_HIDE, &HideCoords[0], &HideCoords[1]);
|
|
HideCoords[2] = HideCoords[0] + hide_w;
|
|
HideCoords[3] = HideCoords[1] + hide_h;
|
|
}
|
|
|
|
//Do bitmap stuff
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TM)))
|
|
{
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TM), &w, &h);
|
|
num = (float)((Coords[2]-CornerWidths[3])-(Coords[0]+CornerWidths[2])) / (float)w;
|
|
BorderRectLists[CIE_HANDLE_TM] = bitmap_rect_list(Coords[0] + CornerWidths[2], Coords[1], fl2i(w*num),h,0,0,num,1.0f);
|
|
//gr_bitmap_list(&BorderRectLists[CIE_HANDLE_BM], 1, false);
|
|
}
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM)))
|
|
{
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM), &w, &h);
|
|
num = (float)((Coords[2]-CornerWidths[3])-(Coords[0]+CornerWidths[2])) / (float)w;
|
|
BorderRectLists[CIE_HANDLE_BM] = bitmap_rect_list(Coords[0] + CornerWidths[2], Coords[3]-h, fl2i(w*num),h,0,0,num,1.0f);
|
|
//gr_bitmap_list(&BorderRectLists[CIE_HANDLE_BM], 1, false);
|
|
}
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_ML)))
|
|
{
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_ML), &w, &h);
|
|
num = (float)((Coords[3]-BorderSizes[3])-(Coords[1]+BorderSizes[1])) / (float)h;
|
|
BorderRectLists[CIE_HANDLE_ML] = bitmap_rect_list(Coords[0], Coords[1] + BorderSizes[1], w,fl2i(h*num),0,0,1.0f,num);
|
|
}
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_MR)))
|
|
{
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_MR), &w, &h);
|
|
num = (float)((Coords[3]-BorderSizes[3])-(Coords[1]+BorderSizes[1])) / (float)h;
|
|
BorderRectLists[CIE_HANDLE_MR] = bitmap_rect_list(Coords[2]-w, Coords[1] + BorderSizes[1], w,fl2i(h*num),0,0,1.0f,num);
|
|
}
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Window::DoMouseOver(float frametime)
|
|
{
|
|
if(OwnerSystem->GetMouseX() >= HideCoords[0]
|
|
&& OwnerSystem->GetMouseX() <= HideCoords[2]
|
|
&& OwnerSystem->GetMouseY() >= HideCoords[1]
|
|
&& OwnerSystem->GetMouseY() <= HideCoords[3])
|
|
{
|
|
HideHighlight = true;
|
|
}
|
|
else
|
|
HideHighlight = false;
|
|
|
|
if(OwnerSystem->GetMouseX() >= CloseCoords[0]
|
|
&& OwnerSystem->GetMouseX() <= CloseCoords[2]
|
|
&& OwnerSystem->GetMouseY() >= CloseCoords[1]
|
|
&& OwnerSystem->GetMouseY() <= CloseCoords[3])
|
|
{
|
|
CloseHighlight = true;
|
|
}
|
|
else
|
|
CloseHighlight = false;
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Window::DoMouseDown(float frametime)
|
|
{
|
|
OwnerSystem->SetActiveObject(this);
|
|
|
|
if(Style & WS_NONMOVEABLE)
|
|
return OF_TRUE;
|
|
|
|
if((OwnerSystem->GetGraspedObject() == NULL)
|
|
&& (Status & GST_MOUSE_LEFT_BUTTON)
|
|
&& OwnerSystem->GetMouseX() >= CaptionCoords[0]
|
|
&& ((OwnerSystem->GetMouseX() < CaptionCoords[2]) || ((Style & WS_NOTITLEBAR) && OwnerSystem->GetMouseX() <= Coords[2]))
|
|
&& OwnerSystem->GetMouseY() >= CaptionCoords[1]
|
|
&& ((OwnerSystem->GetMouseY() <= CaptionCoords[3]) || ((Style & WS_NOTITLEBAR) && OwnerSystem->GetMouseY() <= Coords[2])))
|
|
{
|
|
OwnerSystem->SetGraspedObject(this, GST_MOUSE_LEFT_BUTTON);
|
|
}
|
|
|
|
//All further movement of grasped objects is handled by GUISystem
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Window::DoMouseUp(float frametime)
|
|
{
|
|
if(CloseHighlight)
|
|
{
|
|
Delete();
|
|
return OF_TRUE;
|
|
}
|
|
|
|
if(HideHighlight)
|
|
{
|
|
if(Style & GS_HIDDEN)
|
|
{
|
|
Coords[3] = UnhiddenHeight;
|
|
Style &= ~GS_HIDDEN;
|
|
}
|
|
else
|
|
{
|
|
UnhiddenHeight = Coords[3];
|
|
Coords[3] = Coords[1] + BorderSizes[1] + BorderSizes[3];
|
|
Style |= GS_HIDDEN;
|
|
}
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM)))
|
|
{
|
|
int h;
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM), NULL, &h);
|
|
BorderRectLists[CIE_HANDLE_BM].screen_rect.y = Coords[3] - h;
|
|
}
|
|
}
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Window::DoMouseOut(float frametime)
|
|
{
|
|
HideHighlight = false;
|
|
CloseHighlight = false;
|
|
return OF_TRUE;
|
|
}
|
|
|
|
void Window::DoMove(int dx, int dy)
|
|
{
|
|
CloseCoords[0] += dx;
|
|
CloseCoords[1] += dy;
|
|
CloseCoords[2] += dx;
|
|
CloseCoords[3] += dy;
|
|
|
|
HideCoords[0] += dx;
|
|
HideCoords[1] += dy;
|
|
HideCoords[2] += dx;
|
|
HideCoords[3] += dy;
|
|
|
|
CaptionCoords[0] += dx;
|
|
CaptionCoords[1] += dy;
|
|
CaptionCoords[2] += dx;
|
|
CaptionCoords[3] += dy;
|
|
|
|
//Handle moving the border around
|
|
uint i;
|
|
for(i = 0; i < 8; i++)
|
|
{
|
|
BorderRectLists[i].screen_rect.x += dx;
|
|
BorderRectLists[i].screen_rect.y += dy;
|
|
}
|
|
|
|
//now the caption
|
|
CaptionRectList.screen_rect.x += dx;
|
|
CaptionRectList.screen_rect.y += dy;
|
|
}
|
|
|
|
void draw_open_rect(int x1, int y1, int x2, int y2, bool resize = false)
|
|
{
|
|
gr_line(x1, y1, x2, y1, resize);
|
|
gr_line(x2, y1, x2, y2, resize);
|
|
gr_line(x2, y2, x1, y2, resize);
|
|
gr_line(x1, y2, x1, y1, resize);
|
|
}
|
|
|
|
void Window::DoDraw(float frametime)
|
|
{
|
|
gr_set_color_fast(&Color_text_normal);
|
|
int w, h;
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TL)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TL));
|
|
IMG_DRAW(Coords[0], Coords[1]);
|
|
}
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR));
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR), &w, NULL);
|
|
IMG_DRAW(Coords[2] - w, Coords[1]);
|
|
}
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL)))
|
|
{
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), NULL, &h);
|
|
IMG_SET(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL));
|
|
IMG_DRAW(Coords[0], Coords[3] - h);
|
|
}
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BR)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BR));
|
|
IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BR), &w, &h);
|
|
//IMG_DRAW(Coords[2] - w, Coords[3] - h, false);
|
|
IMG_DRAW(Coords[2]-w, Coords[3] - h);
|
|
}
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TM)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TM));
|
|
gr_bitmap_list(&BorderRectLists[CIE_HANDLE_TM], 1, false);
|
|
}
|
|
else
|
|
{
|
|
gr_line(Coords[0] + BorderSizes[0], Coords[1], Coords[2] - BorderSizes[2], Coords[1], false);
|
|
}
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM));
|
|
gr_bitmap_list(&BorderRectLists[CIE_HANDLE_BM], 1, false);
|
|
}
|
|
else
|
|
{
|
|
gr_line(Coords[0] + BorderSizes[0], Coords[3], Coords[2] - BorderSizes[2], Coords[3], false);
|
|
}
|
|
|
|
if(!(Style & GS_HIDDEN))
|
|
{
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_ML)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_ML));
|
|
gr_bitmap_list(&BorderRectLists[CIE_HANDLE_ML], 1, false);
|
|
}
|
|
else
|
|
{
|
|
gr_line(Coords[0], Coords[1] + BorderSizes[1], Coords[0], Coords[3] - BorderSizes[3], false);
|
|
}
|
|
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_MR)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_MR));
|
|
gr_bitmap_list(&BorderRectLists[CIE_HANDLE_MR], 1, false);
|
|
}
|
|
else
|
|
{
|
|
gr_line(Coords[2], Coords[1] + BorderSizes[1], Coords[2], Coords[3] - BorderSizes[3], false);
|
|
}
|
|
}
|
|
|
|
if(!(Style & WS_NOTITLEBAR))
|
|
{
|
|
//Draw the caption background
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_CAPTION)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(WCI_CAPTION));
|
|
gr_bitmap_list(&CaptionRectList, 1, false);
|
|
}
|
|
else
|
|
{
|
|
draw_open_rect(Coords[0], Coords[1], Coords[2], CaptionCoords[3]);
|
|
}
|
|
|
|
//Close button
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_CLOSE)))
|
|
{
|
|
if(CloseHighlight && IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_CLOSE, CIE_HANDLE_M)))
|
|
IMG_SET(GetCIEImageHandle(WCI_CLOSE, CIE_HANDLE_M));
|
|
else
|
|
IMG_SET(GetCIEImageHandle(WCI_CLOSE));
|
|
|
|
IMG_DRAW(CloseCoords[0], CloseCoords[1]);
|
|
}
|
|
else
|
|
{
|
|
if(CloseHighlight)
|
|
gr_set_color_fast(&Color_text_active);
|
|
else
|
|
gr_set_color_fast(&Color_text_normal);
|
|
|
|
gr_string(CloseCoords[0], CloseCoords[1], "X", false);
|
|
}
|
|
|
|
|
|
//Hide button
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_HIDE)))
|
|
{
|
|
if(HideHighlight && IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_HIDE, CIE_HANDLE_M)))
|
|
IMG_SET(GetCIEImageHandle(WCI_HIDE, CIE_HANDLE_M));
|
|
else
|
|
IMG_SET(GetCIEImageHandle(WCI_HIDE));
|
|
IMG_DRAW(HideCoords[0], HideCoords[1]);
|
|
}
|
|
else
|
|
{
|
|
if(HideHighlight)
|
|
gr_set_color_fast(&Color_text_active);
|
|
else
|
|
gr_set_color_fast(&Color_text_normal);
|
|
|
|
gr_string(HideCoords[0], HideCoords[1], "-", false);
|
|
}
|
|
|
|
//Caption text
|
|
gr_set_color_fast(&Color_text_normal);
|
|
|
|
gr_string(CaptionCoords[0], CaptionCoords[1], (char *)Caption.c_str(), false);
|
|
}
|
|
}
|
|
|
|
Window::Window(std::string in_caption, int x_coord, int y_coord, int x_width, int y_width, int in_style)
|
|
:GUIObject(in_caption, x_coord,y_coord,x_width,y_width,in_style)
|
|
{
|
|
Caption = in_caption;
|
|
|
|
CloseHighlight = false;
|
|
HideHighlight = false;
|
|
|
|
//Set the type
|
|
Type = GT_WINDOW;
|
|
}
|
|
|
|
//*****************************Button*******************************
|
|
|
|
Button::Button(std::string in_caption, int x_coord, int y_coord, void (*in_function)(Button *caller), int x_width, int y_height, int in_style)
|
|
:GUIObject(in_caption, x_coord, y_coord, x_width, y_height, in_style)
|
|
{
|
|
Caption = in_caption;
|
|
|
|
function = in_function;
|
|
|
|
IsDown = false;
|
|
|
|
//Set the type
|
|
Type = GT_BUTTON;
|
|
}
|
|
|
|
int Button::DoRefreshSize()
|
|
{
|
|
int w, h;
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(BCI_BUTTON)))
|
|
{
|
|
IMG_INFO(GetCIEImageHandle(BCI_BUTTON), &w, &h);
|
|
if(!(Style & GS_NOAUTORESIZEX))
|
|
{
|
|
Coords[2] = Coords[0] + w;
|
|
}
|
|
if(!(Style & GS_NOAUTORESIZEY))
|
|
{
|
|
Coords[3] = Coords[1] + h;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gr_get_string_size(&w, &h, (char *)Caption.c_str());
|
|
if(!(Style & GS_NOAUTORESIZEX))
|
|
{
|
|
Coords[2] = Coords[0] + w;
|
|
}
|
|
if(!(Style & GS_NOAUTORESIZEY))
|
|
{
|
|
Coords[3] = Coords[1] + h;
|
|
}
|
|
}
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
void Button::DoDraw(float frametime)
|
|
{
|
|
if(IMG_HANDLE_IS_VALID(GetCIEImageHandle(BCI_BUTTON)))
|
|
{
|
|
IMG_SET(GetCIEImageHandle(BCI_BUTTON));
|
|
|
|
if((Status & GST_MOUSE_OVER) && IMG_HANDLE_IS_VALID(GetCIEImageHandle(BCI_BUTTON, CIE_HANDLE_M)))
|
|
IMG_SET(GetCIEImageHandle(BCI_BUTTON, CIE_HANDLE_M));
|
|
else if((Status & GST_MOUSE_LEFT_BUTTON) && IMG_HANDLE_IS_VALID(GetCIEImageHandle(BCI_BUTTON, CIE_HANDLE_C)))
|
|
IMG_SET(GetCIEImageHandle(BCI_BUTTON, CIE_HANDLE_C));
|
|
else if((Style & BS_STICKY) && IsDown && IMG_HANDLE_IS_VALID(GetCIEImageHandle(BCI_BUTTON, CIE_HANDLE_S)))
|
|
IMG_SET(GetCIEImageHandle(BCI_BUTTON, CIE_HANDLE_S));
|
|
|
|
IMG_DRAW(Coords[0], Coords[1]);
|
|
}
|
|
else
|
|
{
|
|
if(Status == 0)
|
|
gr_set_color_fast(&Color_text_normal);
|
|
else if(Status & GST_MOUSE_OVER)
|
|
gr_set_color_fast(&Color_text_active);
|
|
else
|
|
gr_set_color_fast(&Color_text_selected);
|
|
draw_open_rect(Coords[0], Coords[1], Coords[2], Coords[3], false);
|
|
|
|
int half_x, half_y;
|
|
gr_get_string_size(&half_x, &half_y, (char *)Caption.c_str());
|
|
half_x = Coords[0] +(((Coords[2]-Coords[0]) - half_x) / 2);
|
|
half_y = Coords[1] +(((Coords[3]-Coords[1]) - half_y) / 2);
|
|
gr_string(half_x, half_y, (char *)Caption.c_str(), false);
|
|
}
|
|
}
|
|
|
|
int Button::DoMouseDown(float frametime)
|
|
{
|
|
OwnerSystem->SetActiveObject(this);
|
|
|
|
if(!(Style & BS_STICKY))
|
|
IsDown = true;
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Button::DoMouseUp(float frametime)
|
|
{
|
|
if(function != NULL)
|
|
{
|
|
function(this);
|
|
}
|
|
if(!(Style & BS_STICKY))
|
|
IsDown = false;
|
|
else
|
|
IsDown = !IsDown;
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Button::DoMouseOut(float frametime)
|
|
{
|
|
if(!(Style & BS_STICKY))
|
|
IsDown = false;
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
//*****************************Menu*******************************
|
|
TreeItem::TreeItem()
|
|
:LinkedList()
|
|
{
|
|
Function = NULL;
|
|
Data=0;
|
|
ShowThis=true;
|
|
ShowChildren=false;
|
|
DeleteData=true;
|
|
memset(Coords, 0, sizeof(Coords));
|
|
}
|
|
void TreeItem::ClearAllItems()
|
|
{
|
|
LinkedList* cgp = GET_FIRST(&Children);
|
|
LinkedList* cgp_next;
|
|
for(; cgp != END_OF_LIST(&Children); cgp = cgp_next)
|
|
{
|
|
cgp_next = GET_NEXT(cgp);
|
|
delete cgp;
|
|
}
|
|
}
|
|
TreeItem::~TreeItem()
|
|
{
|
|
ClearAllItems();
|
|
}
|
|
|
|
void Tree::CalcItemsSize(TreeItem *items, int DrawData[4])
|
|
{
|
|
//DrawData
|
|
//0 - indent
|
|
//1 - largest width so far
|
|
//2 - total height so far
|
|
//3 - Are we done?
|
|
int w, h;
|
|
|
|
int temp_largest = DrawData[1];
|
|
for(TreeItem* tip = (TreeItem*)GET_FIRST(items); tip != END_OF_LIST(items); tip = (TreeItem*)GET_NEXT(tip))
|
|
{
|
|
if(!DrawData[3])
|
|
{
|
|
gr_get_string_size(&w, &h, (char*)tip->Name.c_str());
|
|
if((w + DrawData[0]) > temp_largest)
|
|
temp_largest = w + DrawData[0];
|
|
|
|
//This should really be moved to where we handle the scrolling code
|
|
//I'm not doing that right now. :)
|
|
//Or at least this should be called from that
|
|
if(((DrawData[2] + h) > Coords[3] && (Style & GS_NOAUTORESIZEY))
|
|
|| (temp_largest > Coords[2] && (Style & GS_NOAUTORESIZEX))
|
|
//|| ((Coords[0] + w) > OwnerSystem->Guiobjects.Coords[2])
|
|
//|| ((Coords[1] + h) > OwnerSystem->Guiobjects.Coords[3])
|
|
)
|
|
{
|
|
DrawData[3] = 1;
|
|
tip->ShowThis = false;
|
|
}
|
|
else
|
|
tip->ShowThis = true;
|
|
|
|
//Do we care?
|
|
if(tip->ShowThis)
|
|
{
|
|
if((w + DrawData[0]) > DrawData[1])
|
|
DrawData[1] = w + DrawData[0];
|
|
|
|
tip->Coords[0] = Coords[0] + DrawData[0];
|
|
tip->Coords[1] = Coords[1] + DrawData[2];
|
|
tip->Coords[2] = Coords[0] + DrawData[0] + w;
|
|
tip->Coords[3] = Coords[1] + DrawData[2] + h;
|
|
|
|
DrawData[2] += h;
|
|
|
|
if(NOT_EMPTY(&tip->Children) && tip->ShowChildren)
|
|
{
|
|
//Indent
|
|
DrawData[0] += TI_INDENT_PER_LEVEL;
|
|
CalcItemsSize((TreeItem*)&tip->Children, DrawData);
|
|
DrawData[0] -= TI_INDENT_PER_LEVEL;
|
|
}
|
|
}
|
|
}
|
|
if(DrawData[3] || !tip->ShowThis)
|
|
{
|
|
tip->ShowThis = false;
|
|
tip->ShowChildren = false;
|
|
tip->Coords[0] = tip->Coords[1] = tip->Coords[2] = tip->Coords[3] = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
int Tree::DoRefreshSize()
|
|
{
|
|
//DrawData
|
|
//0 - indent
|
|
//1 - largest width so far
|
|
//2 - total height so far
|
|
//3 - Are we done? 0=no,1=yes
|
|
int DrawData[4] = {TI_INITIAL_INDENT,0,TI_INITIAL_INDENT_VERTICAL,0};
|
|
CalcItemsSize(&Items, DrawData);
|
|
|
|
//CalcItemsSize takes into account limited height/width
|
|
if(!(Style & GS_NOAUTORESIZEX))
|
|
{
|
|
Coords[2] = Coords[0] + DrawData[1] + TI_BORDER_WIDTH;
|
|
}
|
|
if(!(Style & GS_NOAUTORESIZEY))
|
|
{
|
|
Coords[3] = Coords[1] + DrawData[2] + TI_BORDER_HEIGHT;
|
|
if(Parent != NULL)
|
|
{
|
|
if(DrawData[2] >= Parent->ChildCoords[3])
|
|
{
|
|
//The parent must resize.
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!(Style & GS_NOAUTORESIZEX))
|
|
{
|
|
Coords[2] = Coords[0] + DrawData[1];
|
|
}
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
Tree::Tree(std::string in_name, int x_coord, int y_coord, void* in_associateditem, int x_width, int y_height, int in_style)
|
|
:GUIObject(in_name, x_coord, y_coord, x_width, y_height, in_style)
|
|
{
|
|
|
|
AssociatedItem = in_associateditem;
|
|
|
|
//Set the type
|
|
Type = GT_MENU;
|
|
}
|
|
|
|
void Tree::DrawItems(TreeItem *items)
|
|
{
|
|
for(TreeItem* tip = (TreeItem*)GET_FIRST(items); tip != END_OF_LIST(items); tip = (TreeItem*)GET_NEXT(tip))
|
|
{
|
|
if(tip->ShowThis)
|
|
{
|
|
if(SelectedItem == tip)
|
|
gr_set_color_fast(&Color_text_selected);
|
|
else if(HighlightedItem == tip)
|
|
gr_set_color_fast(&Color_text_active);
|
|
else
|
|
gr_set_color_fast(&Color_text_normal);
|
|
|
|
gr_string(tip->Coords[0], tip->Coords[1], (char*)tip->Name.c_str(), false);
|
|
|
|
if(NOT_EMPTY(&tip->Children) && tip->ShowChildren)
|
|
{
|
|
DrawItems((TreeItem*)&tip->Children);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Tree::DoDraw(float frametime)
|
|
{
|
|
|
|
if(EMPTY(&Items))
|
|
return;
|
|
|
|
DrawItems(&Items);
|
|
|
|
gr_set_color_fast(&Color_text_normal);
|
|
draw_open_rect(Coords[0], Coords[1], Coords[2], Coords[3]);
|
|
}
|
|
|
|
TreeItem* Tree::HitTest(TreeItem *items)
|
|
{
|
|
TreeItem *hti = NULL; //Highlighted item
|
|
|
|
for(TreeItem *tip = (TreeItem*)GET_FIRST(items);tip != END_OF_LIST(items); tip = (TreeItem*)GET_NEXT(tip))
|
|
{
|
|
if(OwnerSystem->GetMouseX() >= tip->Coords[0]
|
|
&& OwnerSystem->GetMouseX() <= tip->Coords[2]
|
|
&& OwnerSystem->GetMouseY() >= tip->Coords[1]
|
|
&& OwnerSystem->GetMouseY() <= tip->Coords[3])
|
|
{
|
|
hti = tip;
|
|
}
|
|
|
|
if(hti != NULL)
|
|
return hti;
|
|
else if(NOT_EMPTY(&tip->Children) && tip->ShowChildren)
|
|
hti = HitTest((TreeItem*)&tip->Children);
|
|
|
|
if(hti != NULL)
|
|
return hti;
|
|
}
|
|
|
|
return hti;
|
|
}
|
|
|
|
int Tree::DoMouseOver(float frametime)
|
|
{
|
|
HighlightedItem = HitTest(&Items);
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Tree::DoMouseDown(float frametime)
|
|
{
|
|
OwnerSystem->SetActiveObject(this);
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Tree::DoMouseUp(float frametime)
|
|
{
|
|
OwnerSystem->SetActiveObject(this);
|
|
|
|
if(HighlightedItem != NULL)
|
|
{
|
|
SelectedItem = HighlightedItem;
|
|
SelectedItem->ShowChildren = !SelectedItem->ShowChildren;
|
|
if(NOT_EMPTY(&SelectedItem->Children))
|
|
{
|
|
OnRefreshSize(); //Unfortunately
|
|
}
|
|
if(SelectedItem->Function != NULL)
|
|
{
|
|
SelectedItem->Function(this);
|
|
}
|
|
}
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
void Tree::MoveTreeItems(int dx, int dy, TreeItem *items)
|
|
{
|
|
for(TreeItem *tip = (TreeItem*)GET_FIRST(items);tip != END_OF_LIST(items); tip = (TreeItem*)GET_NEXT(tip))
|
|
{
|
|
if(tip->ShowThis)
|
|
{
|
|
tip->Coords[0] += dx;
|
|
tip->Coords[1] += dy;
|
|
tip->Coords[2] += dx;
|
|
tip->Coords[3] += dy;
|
|
|
|
if(NOT_EMPTY(&tip->Children) && tip->ShowChildren)
|
|
MoveTreeItems(dx, dy, (TreeItem*)&tip->Children);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Tree::DoMove(int dx, int dy)
|
|
{
|
|
MoveTreeItems(dx, dy, &Items);
|
|
}
|
|
|
|
TreeItem* Tree::AddItem(TreeItem *parent, std::string in_name, int in_data, bool in_delete_data, void (*in_function)(Tree* caller))
|
|
{
|
|
TreeItem *ni = new TreeItem;
|
|
|
|
ni->Parent = parent;
|
|
ni->Name = in_name;
|
|
ni->Data = in_data;
|
|
ni->DeleteData = in_delete_data;
|
|
ni->Function = in_function;
|
|
if(parent != NULL)
|
|
list_append(&parent->Children, ni);
|
|
else
|
|
list_append(&Items, ni);
|
|
|
|
OnRefreshSize();
|
|
return ni;
|
|
}
|
|
|
|
void Tree::ClearItems()
|
|
{
|
|
Items.ClearAllItems();
|
|
}
|
|
|
|
//*****************************Text*******************************
|
|
int Text::DoRefreshSize()
|
|
{
|
|
int width;
|
|
if(Style & GS_NOAUTORESIZEX)
|
|
width = Coords[2] - Coords[0];
|
|
else if(Parent != NULL && (Parent->Style & GS_NOAUTORESIZEX))
|
|
width = Parent->ChildCoords[2] - Coords[0];
|
|
else
|
|
width = gr_screen.clip_right - Coords[0];
|
|
|
|
NumLines = split_str((char*)Content.c_str(), width, LineLengths, LineStartPoints, MAX_TEXT_LINES);
|
|
|
|
//Find the shortest width we need to show all the shortened strings
|
|
int longest_width = 0;
|
|
int width_test;
|
|
for(int i = 0; i < NumLines; i++)
|
|
{
|
|
gr_get_string_size(&width_test, NULL, LineStartPoints[i], LineLengths[i]);
|
|
if(width_test > longest_width)
|
|
longest_width = width_test;
|
|
}
|
|
if(longest_width < width)
|
|
width = longest_width;
|
|
|
|
//Resize along the Y axis
|
|
if(Style & GS_NOAUTORESIZEY)
|
|
{
|
|
int new_height = (Coords[3] - Coords[1]) / gr_get_font_height();
|
|
|
|
if(new_height < NumLines)
|
|
NumLines = new_height;
|
|
}
|
|
else
|
|
{
|
|
Coords[3] = Coords[1] + gr_get_font_height() * NumLines;
|
|
if(Parent != NULL)
|
|
{
|
|
if(Coords[3] >= Parent->ChildCoords[3] && (Parent->Style & GS_NOAUTORESIZEY))
|
|
{
|
|
Coords[3] = Coords[1] + (Parent->ChildCoords[3] - Coords[1]);
|
|
NumLines = (Coords[3] - Coords[1]) / gr_get_font_height();
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!(Style & GS_NOAUTORESIZEX))
|
|
{
|
|
Coords[2] = Coords[0] + width;
|
|
}
|
|
|
|
if(Style & T_EDITTABLE)
|
|
{
|
|
ChildCoords[0] = Coords[0] + 1;
|
|
ChildCoords[1] = Coords[1] + 1;
|
|
ChildCoords[2] = Coords[2] - 1;
|
|
ChildCoords[3] = Coords[3] - 1;
|
|
}
|
|
else
|
|
{
|
|
ChildCoords[0] = Coords[0];
|
|
ChildCoords[1] = Coords[1];
|
|
ChildCoords[2] = Coords[2];
|
|
ChildCoords[3] = Coords[3];
|
|
}
|
|
|
|
//Tell the parent to recalculate its size too
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Text::DoMouseDown(float frametime)
|
|
{
|
|
//Make this the active object
|
|
if(Style & T_EDITTABLE)
|
|
{
|
|
OwnerSystem->SetActiveObject(this);
|
|
|
|
//For now, always set the cursor pos to the end
|
|
CursorPos = Content.size();
|
|
|
|
return OF_TRUE;
|
|
}
|
|
else
|
|
{
|
|
return OF_FALSE;
|
|
}
|
|
}
|
|
|
|
void Text::DoDraw(float frametime)
|
|
{
|
|
if(OwnerSystem->GetActiveObject() != this)
|
|
gr_set_color_fast(&Color_text_normal);
|
|
else
|
|
gr_set_color_fast(&Color_text_active);
|
|
|
|
if(Style & T_EDITTABLE)
|
|
{
|
|
draw_open_rect(Coords[0], Coords[1], Coords[2], Coords[3]);
|
|
}
|
|
|
|
//Don't draw anything. Besides, it crashes
|
|
if(!Content.length())
|
|
return;
|
|
|
|
int font_height = gr_get_font_height();
|
|
|
|
for(int i = 0; i < NumLines; i++)
|
|
{
|
|
gr_string(ChildCoords[0], ChildCoords[1] + (i*font_height), (char*)Content.substr(LineStartPoints[i] - Content.c_str(), LineLengths[i]).c_str(), false);
|
|
}
|
|
}
|
|
|
|
extern int keypad_to_ascii(int c);
|
|
|
|
int Text::DoKeyPress(float frametime)
|
|
{
|
|
if(!(Style & T_EDITTABLE))
|
|
return OF_FALSE;
|
|
|
|
switch(OwnerSystem->GetKeyPressed())
|
|
{
|
|
case KEY_BACKSP:
|
|
Content = Content.substr(0, Content.length() - 1);
|
|
break;
|
|
case KEY_ENTER:
|
|
if(SaveType & T_ST_ONENTER)
|
|
{
|
|
if(Save())
|
|
OwnerSystem->SetActiveObject(Parent);
|
|
else
|
|
Load();
|
|
}
|
|
break;
|
|
case KEY_ESC:
|
|
Load();
|
|
OwnerSystem->SetActiveObject(Parent);
|
|
break;
|
|
default:
|
|
{
|
|
//Figure out what key, exactly, we have
|
|
int symbol = keypad_to_ascii(OwnerSystem->GetKeyPressed());
|
|
if(symbol == -1)
|
|
symbol = key_to_ascii(OwnerSystem->GetKeyPressed());
|
|
//Is it ok with us?
|
|
if(iscntrl(symbol))
|
|
{
|
|
return OF_FALSE; //Guess not
|
|
}
|
|
else if(SaveType & T_ST_INT)
|
|
{
|
|
if(!isdigit(symbol) && symbol != '-')
|
|
return OF_FALSE;
|
|
}
|
|
else if(SaveType & T_ST_FLOAT)
|
|
{
|
|
if(!isdigit(symbol) && symbol != '.' && symbol != '-')
|
|
return OF_FALSE;
|
|
}
|
|
else if(SaveType & T_ST_UBYTE)
|
|
{
|
|
if(!isdigit(symbol))
|
|
return OF_FALSE;
|
|
}
|
|
else if(!isalnum(symbol) && symbol != ' ')
|
|
{
|
|
return OF_FALSE;
|
|
}
|
|
|
|
//We can add the letter to the box. Cheers.
|
|
//If this warning bothers you, go ahead and cast it.
|
|
Content += symbol;
|
|
if(SaveType & T_ST_REALTIME)
|
|
{
|
|
Save();
|
|
}
|
|
}
|
|
}
|
|
OnRefreshSize();
|
|
return OF_TRUE;
|
|
}
|
|
|
|
Text::Text(std::string in_name, std::string in_content, int x_coord, int y_coord, int x_width, int y_height, int in_style)
|
|
:GUIObject(in_name, x_coord, y_coord, x_width, y_height, in_style)
|
|
{
|
|
Content = in_content;
|
|
|
|
NumLines = 0;
|
|
|
|
SaveType = T_ST_NONE;
|
|
CursorPos = -1; //Not editing
|
|
|
|
Type = GT_TEXT;
|
|
}
|
|
|
|
void Text::SetText(std::string in_content)
|
|
{
|
|
Content = in_content;
|
|
|
|
OnRefreshSize();
|
|
}
|
|
|
|
void Text::SetText(int the_int)
|
|
{
|
|
char buf[32];
|
|
itoa(the_int, buf, 10);
|
|
Content = buf;
|
|
|
|
OnRefreshSize();
|
|
}
|
|
|
|
void Text::SetText(float the_float)
|
|
{
|
|
char buf[32];
|
|
sprintf(buf, "%f", the_float);
|
|
Content = buf;
|
|
|
|
OnRefreshSize();
|
|
}
|
|
|
|
void Text::AddLine(std::string in_line)
|
|
{
|
|
Content += in_line;
|
|
|
|
OnRefreshSize();
|
|
}
|
|
|
|
void Text::SetSaveLoc(int *int_ptr, int save_method, int max_value, int min_value)
|
|
{
|
|
Assert(int_ptr != NULL); //Naughty.
|
|
Assert(min_value < max_value); //Mmm-hmm.
|
|
|
|
SaveType = T_ST_INT;
|
|
if(save_method == T_ST_CLOSE)
|
|
SaveType |= T_ST_CLOSE;
|
|
else if(save_method == T_ST_REALTIME)
|
|
SaveType |= T_ST_REALTIME;
|
|
else if(save_method == T_ST_ONENTER)
|
|
SaveType |= T_ST_ONENTER;
|
|
|
|
iSavePointer = int_ptr;
|
|
SaveMax = max_value;
|
|
SaveMin = min_value;
|
|
}
|
|
|
|
void Text::SetSaveLoc(short int *sint_ptr, int save_method, short int max_value, short int min_value)
|
|
{
|
|
Assert(sint_ptr != NULL); //Naughty.
|
|
Assert(min_value < max_value); //Mmm-hmm.
|
|
|
|
SaveType = T_ST_SINT;
|
|
if(save_method == T_ST_CLOSE)
|
|
SaveType |= T_ST_CLOSE;
|
|
else if(save_method == T_ST_REALTIME)
|
|
SaveType |= T_ST_REALTIME;
|
|
else if(save_method == T_ST_ONENTER)
|
|
SaveType |= T_ST_ONENTER;
|
|
|
|
siSavePointer = sint_ptr;
|
|
SaveMax = max_value;
|
|
SaveMin = min_value;
|
|
}
|
|
|
|
void Text::SetSaveLoc(float *ptr, int save_method, float max_value, float min_value)
|
|
{
|
|
Assert(ptr != NULL); //Naughty.
|
|
Assert(min_value < max_value); //Causes problems with floats
|
|
|
|
SaveType = T_ST_FLOAT;
|
|
if(save_method == T_ST_CLOSE)
|
|
SaveType |= T_ST_CLOSE;
|
|
else if(save_method == T_ST_REALTIME)
|
|
SaveType |= T_ST_REALTIME;
|
|
else if(save_method == T_ST_ONENTER)
|
|
SaveType |= T_ST_ONENTER;
|
|
|
|
flSavePointer = ptr;
|
|
flSaveMax = max_value;
|
|
flSaveMin = min_value;
|
|
}
|
|
|
|
void Text::SetSaveLoc(char *ptr, int save_method, uint max_length, uint min_length)
|
|
{
|
|
Assert(ptr != NULL); //Naughty.
|
|
|
|
SaveType = T_ST_CHAR;
|
|
|
|
if(save_method == T_ST_CLOSE)
|
|
SaveType |= T_ST_CLOSE;
|
|
else if(save_method == T_ST_REALTIME)
|
|
SaveType |= T_ST_REALTIME;
|
|
else if(save_method == T_ST_ONENTER)
|
|
SaveType |= T_ST_ONENTER;
|
|
|
|
chSavePointer = ptr;
|
|
uSaveMax = max_length;
|
|
uSaveMin = min_length;
|
|
}
|
|
|
|
void Text::SetSaveStringAlloc(char **ptr, int save_method, int mem_flags, uint max_length, uint min_length)
|
|
{
|
|
Assert(ptr != NULL); //Naughty.
|
|
|
|
if(mem_flags == T_ST_NEW)
|
|
SaveType = T_ST_NEW;
|
|
else if(mem_flags == T_ST_MALLOC)
|
|
SaveType = T_ST_MALLOC;
|
|
else
|
|
return; //This MUST use some sort of mem allocation
|
|
|
|
SaveType |= T_ST_CHAR;
|
|
|
|
if(save_method == T_ST_CLOSE)
|
|
SaveType |= T_ST_CLOSE;
|
|
else if(save_method == T_ST_REALTIME)
|
|
SaveType |= T_ST_REALTIME;
|
|
else if(save_method == T_ST_ONENTER)
|
|
SaveType |= T_ST_ONENTER;
|
|
|
|
chpSavePointer = ptr;
|
|
uSaveMax = max_length;
|
|
uSaveMin = min_length;
|
|
}
|
|
|
|
void Text::SetSaveLoc(ubyte *ptr, int save_method, int max_value, int min_value)
|
|
{
|
|
Assert(ptr != NULL); //Naughty.
|
|
Assert(min_value < max_value); //Mmm-hmm.
|
|
|
|
SaveType = T_ST_UBYTE;
|
|
if(save_method == T_ST_CLOSE)
|
|
SaveType |= T_ST_CLOSE;
|
|
else if(save_method == T_ST_REALTIME)
|
|
SaveType |= T_ST_REALTIME;
|
|
else if(save_method == T_ST_ONENTER)
|
|
SaveType |= T_ST_ONENTER;
|
|
|
|
ubSavePointer = ptr;
|
|
SaveMax = max_value;
|
|
SaveMin = min_value;
|
|
}
|
|
|
|
bool Text::Save()
|
|
{
|
|
if(SaveType == T_ST_NONE)
|
|
return false;
|
|
|
|
if(SaveType & T_ST_INT)
|
|
{
|
|
int the_int = atoi(Content.c_str());
|
|
if(the_int <= SaveMax && the_int >= SaveMin)
|
|
{
|
|
*iSavePointer = the_int;
|
|
return true;
|
|
}
|
|
}
|
|
else if(SaveType & T_ST_SINT)
|
|
{
|
|
int the_sint = atoi(Content.c_str());
|
|
if(the_sint <= SaveMax && the_sint >= SaveMin)
|
|
{
|
|
*siSavePointer = the_sint;
|
|
return true;
|
|
}
|
|
}
|
|
else if(SaveType & T_ST_FLOAT)
|
|
{
|
|
float the_float = (float)atof(Content.c_str());
|
|
if(the_float <= flSaveMax && the_float >= flSaveMin)
|
|
{
|
|
*flSavePointer = the_float;
|
|
return true;
|
|
}
|
|
}
|
|
else if(SaveType & T_ST_CHAR)
|
|
{
|
|
size_t len = Content.length();
|
|
if(SaveType & T_ST_NEW
|
|
&& len < uSaveMax)
|
|
{
|
|
if(*chpSavePointer != NULL)
|
|
delete[] *chpSavePointer;
|
|
|
|
*chpSavePointer = new char[len + 1];
|
|
|
|
strcpy(*chpSavePointer, Content.c_str());
|
|
return true;
|
|
}
|
|
else if(SaveType & T_ST_MALLOC
|
|
&& len < uSaveMax)
|
|
{
|
|
if(*chpSavePointer != NULL)
|
|
vm_free(*chpSavePointer);
|
|
|
|
*chpSavePointer = (char*)vm_malloc(sizeof(char) * (len + 1));
|
|
|
|
strcpy(*chpSavePointer, Content.c_str());
|
|
return true;
|
|
}
|
|
else if(len < uSaveMax)
|
|
{
|
|
strcpy(chSavePointer, Content.c_str());
|
|
return true;
|
|
}
|
|
}
|
|
else if(SaveType & T_ST_UBYTE)
|
|
{
|
|
int the_int = atoi(Content.c_str());
|
|
if(the_int <= SaveMax && the_int >= SaveMin)
|
|
{
|
|
*ubSavePointer = (ubyte)the_int;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void Text::Load()
|
|
{
|
|
if(SaveType == T_ST_NONE)
|
|
return;
|
|
|
|
if(SaveType & T_ST_INT)
|
|
SetText(*iSavePointer);
|
|
else if(SaveType & T_ST_FLOAT)
|
|
SetText(*flSavePointer);
|
|
else if((SaveType & T_ST_CHAR) && (SaveType & (T_ST_MALLOC | T_ST_NEW)))
|
|
SetText(*chpSavePointer);
|
|
else if(SaveType & T_ST_CHAR)
|
|
SetText(chSavePointer);
|
|
else if(SaveType & T_ST_UBYTE)
|
|
SetText(*ubSavePointer);
|
|
else
|
|
Warning(LOCATION, "Unknown type (or no type) given in Text::Load() - nothing happened.");
|
|
}
|
|
|
|
//*****************************Checkbox*******************************
|
|
|
|
Checkbox::Checkbox(std::string in_label, int x_coord, int y_coord, void (*in_function)(Checkbox *caller), int x_width, int y_height, int in_style)
|
|
:GUIObject(in_label, x_coord, y_coord, x_width, y_height, in_style)
|
|
{
|
|
Label = in_label;
|
|
|
|
function = in_function;
|
|
|
|
IsChecked = false;
|
|
HighlightStatus = 0;
|
|
FlagPtr = NULL;
|
|
|
|
//Set the type
|
|
Type = GT_CHECKBOX;
|
|
}
|
|
|
|
int Checkbox::DoRefreshSize()
|
|
{
|
|
int w, h,tw,th;
|
|
gr_get_string_size(&w, &h, (char *)Label.c_str());
|
|
tw = w;
|
|
th = h;
|
|
|
|
gr_get_string_size(&w, &h, "X");
|
|
tw += w;
|
|
th += h + CB_TEXTCHECKDIST; //Spacing b/t 'em
|
|
|
|
CheckCoords[0] = Coords[0];
|
|
CheckCoords[1] = Coords[1];
|
|
CheckCoords[2] = Coords[0] + w;
|
|
CheckCoords[3] = Coords[1] + h;
|
|
|
|
if(!(Style & GS_NOAUTORESIZEX))
|
|
{
|
|
Coords[2] = Coords[0] + tw;
|
|
}
|
|
if(!(Style & GS_NOAUTORESIZEY))
|
|
{
|
|
Coords[3] = Coords[1] + th;
|
|
}
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
void Checkbox::DoMove(int dx, int dy)
|
|
{
|
|
CheckCoords[0] += dx;
|
|
CheckCoords[2] += dx;
|
|
CheckCoords[1] += dy;
|
|
CheckCoords[3] += dy;
|
|
}
|
|
|
|
void Checkbox::DoDraw(float frametime)
|
|
{
|
|
if(HighlightStatus == 1)
|
|
gr_set_color_fast(&Color_text_active);
|
|
else if(HighlightStatus == 2)
|
|
gr_set_color_fast(&Color_text_selected);
|
|
else
|
|
gr_set_color_fast(&Color_text_normal);
|
|
|
|
draw_open_rect(CheckCoords[0], CheckCoords[1], CheckCoords[2], CheckCoords[3], false);
|
|
if((IsChecked && FlagPtr == NULL) || (FlagPtr!= NULL && ((*FlagPtr) & Flag)))
|
|
gr_string(CheckCoords[0], CheckCoords[1], "X", false);
|
|
|
|
gr_set_color_fast(&Color_text_normal);
|
|
gr_string(CheckCoords[2] + CB_TEXTCHECKDIST, CheckCoords[1], (char *)Label.c_str(), false);
|
|
}
|
|
|
|
int Checkbox::DoMouseOver(float frametime)
|
|
{
|
|
if(OwnerSystem->GetMouseX() >= CheckCoords[0]
|
|
&& OwnerSystem->GetMouseX() <= CheckCoords[2]
|
|
&& OwnerSystem->GetMouseY() >= CheckCoords[1]
|
|
&& OwnerSystem->GetMouseY() <= CheckCoords[3])
|
|
HighlightStatus = 1;
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Checkbox::DoMouseDown(float frametime)
|
|
{
|
|
OwnerSystem->SetActiveObject(this);
|
|
|
|
if(OwnerSystem->GetMouseX() >= CheckCoords[0]
|
|
&& OwnerSystem->GetMouseX() <= CheckCoords[2]
|
|
&& OwnerSystem->GetMouseY() >= CheckCoords[1]
|
|
&& OwnerSystem->GetMouseY() <= CheckCoords[3])
|
|
HighlightStatus = 2;
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Checkbox::DoMouseUp(float frametime)
|
|
{
|
|
if(OwnerSystem->GetMouseX() >= CheckCoords[0]
|
|
&& OwnerSystem->GetMouseX() <= CheckCoords[2]
|
|
&& OwnerSystem->GetMouseY() >= CheckCoords[1]
|
|
&& OwnerSystem->GetMouseY() <= CheckCoords[3])
|
|
{
|
|
HighlightStatus = 1;
|
|
if(function != NULL)
|
|
{
|
|
function(this);
|
|
}
|
|
if(FlagPtr != NULL)
|
|
{
|
|
if(!(*FlagPtr & Flag))
|
|
{
|
|
*FlagPtr |= Flag;
|
|
IsChecked = true;
|
|
}
|
|
else
|
|
{
|
|
*FlagPtr &= ~Flag;
|
|
IsChecked = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IsChecked = !IsChecked;
|
|
}
|
|
}
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
int Checkbox::DoMouseOut(float frametime)
|
|
{
|
|
HighlightStatus = 0;
|
|
|
|
return OF_TRUE;
|
|
}
|
|
|
|
//*****************************ImageAnim*******************************
|
|
ImageAnim::ImageAnim(std::string in_name, std::string in_imagename, int x_coord, int y_coord, int x_width, int y_width, int in_style)
|
|
:GUIObject(in_name, x_coord, y_coord, x_width, y_width, in_style)
|
|
{
|
|
//Load the image
|
|
IsSet = false;
|
|
ImageHandle = -1;
|
|
ImageFlags = 0;
|
|
TotalFrames = 0;
|
|
FPS = 0;
|
|
Stop();
|
|
|
|
Type = GT_IMAGEANIM;
|
|
}
|
|
|
|
void ImageAnim::DoDraw(float frametime)
|
|
{
|
|
//Do nothing if nothing to draw
|
|
if(ImageHandle == -1)
|
|
return;
|
|
|
|
if(PlayType != PT_STOPPED)
|
|
{
|
|
if(PlayType == PT_PLAYING)
|
|
ElapsedTime += frametime;
|
|
else if(PlayType == PT_PLAYING_REVERSE)
|
|
ElapsedTime -= frametime;
|
|
|
|
Progress = ElapsedTime/TotalTime;
|
|
}
|
|
|
|
int CurrentFrame = fl2i(Progress * TotalFrames);
|
|
if(Progress > 1.0f)
|
|
{
|
|
if(ImageFlags & IF_BOUNCE)
|
|
{
|
|
Progress = 1.0f;
|
|
CurrentFrame = TotalFrames;
|
|
PlayType = PT_PLAYING_REVERSE;
|
|
}
|
|
else if(ImageFlags & IF_REPEAT)
|
|
{
|
|
Progress = 0.0f;
|
|
CurrentFrame = 0;
|
|
PlayType = PT_PLAYING;
|
|
}
|
|
else
|
|
{
|
|
Progress = 1.0f;
|
|
CurrentFrame = TotalFrames;
|
|
PlayType = PT_STOPPED;
|
|
}
|
|
}
|
|
else if(Progress < 1.0f)
|
|
{
|
|
if(ImageFlags & IF_BOUNCE)
|
|
{
|
|
Progress = 0.0f;
|
|
CurrentFrame = 0;
|
|
PlayType = PT_PLAYING;
|
|
}
|
|
else if(ImageFlags & IF_REPEAT && ImageFlags & (IF_REVERSED))
|
|
{
|
|
Progress = 1.0f;
|
|
CurrentFrame = TotalFrames;
|
|
PlayType = PT_PLAYING_REVERSE;
|
|
}
|
|
else
|
|
{
|
|
Progress = 0.0f;
|
|
CurrentFrame = 0;
|
|
PlayType = PT_STOPPED;
|
|
}
|
|
}
|
|
|
|
//IMG_SET_FRAME(ImageHandle, CurrentFrame);
|
|
gr_set_bitmap( ImageHandle + CurrentFrame, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1-((Progress - (float)(CurrentFrame / TotalFrames)) / (float)(TotalFrames/CurrentFrame)));
|
|
IMG_DRAW(Coords[0], Coords[1]);
|
|
gr_set_bitmap( ImageHandle + CurrentFrame + 1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, ((Progress - (float)(CurrentFrame / TotalFrames)) / (float)(TotalFrames/CurrentFrame)));
|
|
IMG_DRAW(Coords[0], Coords[1]);
|
|
}
|
|
|
|
int ImageAnim::DoRefreshSize()
|
|
{
|
|
//TODO: Fill this in
|
|
return OF_FALSE;
|
|
}
|
|
|
|
void ImageAnim::SetImage(std::string in_imagename)
|
|
{
|
|
if(in_imagename.size())
|
|
{
|
|
ImageHandle = IMG_LOAD_ANIM((char*)in_imagename.c_str(), &TotalFrames, &FPS);
|
|
TotalTime = (float) (TotalFrames/FPS);
|
|
if(IMG_HANDLE_IS_INVALID(ImageHandle))
|
|
{
|
|
ImageHandle = IMG_LOAD((char*)in_imagename.c_str());
|
|
if(IMG_HANDLE_IS_VALID(ImageHandle))
|
|
TotalFrames = 1;
|
|
else
|
|
TotalFrames = 0;
|
|
FPS = 0;
|
|
TotalTime = 0.0f;
|
|
}
|
|
}
|
|
|
|
//This takes care of setting up the play-flags
|
|
Stop();
|
|
|
|
IsSet = true;
|
|
OnRefreshSize();
|
|
}
|
|
|
|
void ImageAnim::Play(bool in_isreversed)
|
|
{
|
|
if(ImageFlags & IF_REVERSED)
|
|
PlayType = PT_PLAYING;
|
|
}
|
|
|
|
void ImageAnim::Pause()
|
|
{
|
|
if(PlayType == PT_PLAYING)
|
|
PlayType = PT_STOPPED;
|
|
else
|
|
PlayType = PT_STOPPED_REVERSE;
|
|
}
|
|
|
|
void ImageAnim::Stop()
|
|
{
|
|
if(ImageFlags & IF_REVERSED)
|
|
PlayType = PT_STOPPED_REVERSE;
|
|
else
|
|
PlayType = PT_STOPPED;
|
|
|
|
Progress = 0.0f;
|
|
ElapsedTime = 0.0f;
|
|
}
|
|
#ifdef USE_PYTHON
|
|
//*****************************HUDGauge*******************************
|
|
HUDGauge::HUDGauge(std::string in_name, int x_coord, int y_coord, PyBytecode in_drawfunc, int x_width, int y_height, int in_style)
|
|
:GUIObject(in_name, x_coord, y_coord, x_width, y_height, in_style)
|
|
{
|
|
Name = in_name;
|
|
|
|
DrawFunc = in_drawfunc;
|
|
|
|
//Set the type
|
|
Type = GT_HUDGAUGE;
|
|
}
|
|
|
|
void HUDGauge::DoDraw(float frametime)
|
|
{
|
|
if(DrawFunc.Get() != NULL)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
HUDGauge::~HUDGauge()
|
|
{
|
|
|
|
}
|
|
|
|
#endif // USE_PYTHON
|