FS2_Open
Open source remastering of the Freespace 2 engine
wmcgui.cpp
Go to the documentation of this file.
1 /*
2  * wmcgui.cpp
3  * created by WMCoolmon
4  *
5  * You may not sell or otherwise commercially exploit the source or things you
6  * create based on the source.
7  *
8  */
9 
10 
11 
12 #include "freespace2/freespace.h"
13 #include "graphics/2d.h"
14 #include "hud/hudbrackets.h"
15 #include "io/key.h"
16 #include "lab/wmcgui.h"
17 #include "localization/localize.h"
18 #include "parse/parselo.h"
19 
20 //Gobals
22 
23 //*****************************ClassInfoEntry*******************************
25 {
26  CIEType = CIE_NONE;
27 
28  for (uint i = 0; i < CIE_NUM_HANDLES; i++) {
29  IMG_HANDLE_SET_INVALID(Handles[i].Image);
30  }
31 
32  Coords[0] = Coords[1] = INT_MAX;
33 }
35 {
36  //Unload image handles
37  if (CIEType == CIE_IMAGE_NMCSD || CIEType == CIE_IMAGE || CIEType == CIE_IMAGE_BORDER) {
38  int i = 0;
39  int num = sizeof(Handle)/sizeof(int);
40  for (; i < num; i++) {
41  if (IMG_HANDLE_IS_VALID(Handles[i].Image)) {
42  IMG_UNLOAD(Handles[i].Image);
43  }
44  }
45  }
46 }
47 
49 {
50  //Do we actually have a tag?
51  //This is hackish, but it should get the job done
52  if (check_for_string("<") && !check_for_string("</")) {
53  char buf[NAME_LENGTH];
54  char buf2[NAME_LENGTH+3]; //for the end tag and name buffer
55 
56  Assert( sizeof(buf2) >= (sizeof(buf) + 3) );
57 
58  //Find the name of the thing we're parsing
59  parse_advance(1);
60  stuff_string(buf, F_NAME, sizeof(buf), ">");
61  parse_advance(1); //skip the end ">"
62 
63  if (optional_string("+Name:")) {
64  stuff_string(buf2, F_NAME, sizeof(buf2));
65  Name = buf2;
66  }
67  if (optional_string("+Coords:")) {
68  stuff_int_list(Coords, 2, RAW_INTEGER_TYPE);
69  }
70  if (optional_string("+Size:")) {
71  stuff_int_list(&Coords[2], 2, RAW_INTEGER_TYPE);
72  }
73 
74  //This is where you add specific classes to parse.
75  //Follow the current classes' example, this basically involves
76  //a !stricmp(), a resize() (to the number of entries) and multiple Entries[ID].Parse()
77 
78  //=================================================
79  if (!stricmp(buf, "Window")) {
80  Object = GT_WINDOW;
81  Entries.resize(WCI_NUM_ENTRIES);
82 
83  //Fill it out
84  Entries[WCI_CAPTION].Parse("Caption", CIE_IMAGE_NMCSD);
85  Entries[WCI_HIDE].Parse("Hider", CIE_IMAGE_NMCSD);
86  Entries[WCI_CLOSE].Parse("Closer", CIE_IMAGE_NMCSD);
87  Entries[WCI_BODY].Parse("Body", CIE_IMAGE);
88  Entries[WCI_BORDER].Parse("Border", CIE_IMAGE_BORDER);
89  } else if (!stricmp(buf, "Button")) {
90  Object = GT_BUTTON;
91  Entries.resize(BCI_NUM_ENTRIES);
92 
93  //Fill it out
94  Entries[BCI_BUTTON].Parse("Button", CIE_IMAGE_NMCSD);
95  }
96 
97  //=================================================
98 
99  //Make sure that the next token isn't an end tag, but
100  //is a tag
101  ObjectClassInfoEntry temp_ocie;
102  while (temp_ocie.Parse()) {
103  Subentries.push_back(temp_ocie);
104  temp_ocie = ObjectClassInfoEntry();
105  }
106 
107  //We MUST have the end tag
108  strcpy_s(buf2, "</");
109  strcat_s(buf2, buf);
110  strcat_s(buf2, ">");
111 
112  required_string(buf2);
113  return true;
114  }
115 
116  return false;
117 }
118 
120 {
121  if (check_for_string("#") && !check_for_string("#End")) {
122  char buf[NAME_LENGTH];
123 
124  //Find the name of the thing we're parsing
125  parse_advance(1);
126  stuff_string(buf, F_NAME, sizeof(buf));
127  Name = buf;
128 
129  //Parse all objects for this screen
130  ObjectClassInfoEntry temp_ocie;
131  while (temp_ocie.Parse()) {
132  Entries.push_back(temp_ocie);
133  temp_ocie = ObjectClassInfoEntry();
134  }
135 
136  return true;
137  }
138 
139  return false;
140 }
141 
143 {
144  if (ClassInfoParsed) {
145  Warning(LOCATION, "Class info is being parsed twice");
146  DestroyClassInfo();
147  }
148 
149  try
150  {
151  read_file_text(filename);
152  reset_parse();
153  ScreenClassInfo.Parse();
154 
155  bool flag;
156  do {
158  flag = sciep->Parse();
159  if (flag) {
160  list_append(&ScreenClassInfo, sciep);
161  } else {
162  delete sciep;
163  }
164  } while (flag);
165 
166  ClassInfoParsed = true;
167  }
168  catch (const parse::ParseException& e)
169  {
170  mprintf(("WMCGUI: Unable to parse '%s'! Error message = %s.\n", filename, e.what()));
171  return;
172  }
173 }
174 
175 void ClassInfoEntry::Parse(char* tag, int in_type)
176 {
177  char buf[MAX_FILENAME_LEN];
178  strcpy_s(buf, "+");
179  strcat_s(buf, tag);
180  if (in_type != CIE_IMAGE_BORDER) {
181  strcat_s(buf, ":");
182  }
183 
184  if(optional_string(buf)) {
185  CIEType = in_type;
186  if (in_type == CIE_IMAGE || in_type == CIE_IMAGE_NMCSD) {
187  int num_frames;
188  stuff_string(buf, F_NAME, sizeof(buf));
189  Handles[CIE_HANDLE_N].Image = IMG_LOAD_ANIM(buf, &num_frames, NULL);
190  if (IMG_HANDLE_IS_VALID(Handles[CIE_HANDLE_N].Image) && num_frames) {
191  if (num_frames > 1) {
192  IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_M].Image, 1);
193  }
194  if (num_frames > 2) {
195  IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_C].Image, 2);
196  }
197  if (num_frames > 3) {
198  IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_S].Image, 3);
199  }
200  if (num_frames > 4) {
201  IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_D].Image, 4);
202  }
203  IMG_HANDLE_SET_FRAME(Handles[CIE_HANDLE_N].Image, Handles[CIE_HANDLE_N].Image, 0);
204  } else {
205  Handles[CIE_HANDLE_N].Image = IMG_LOAD(buf);
206  }
207  if (in_type == CIE_IMAGE_NMCSD) {
208  if (optional_string("+Mouseover:")) {
209  stuff_string(buf, F_NAME, sizeof(buf));
210  Handles[CIE_HANDLE_M].Image = IMG_LOAD(buf);
211  }
212  if (optional_string("+Clicked:")) {
213  stuff_string(buf, F_NAME, sizeof(buf));
214  Handles[CIE_HANDLE_C].Image = IMG_LOAD(buf);
215  }
216  if (optional_string("+Selected:")) {
217  stuff_string(buf, F_NAME, sizeof(buf));
218  Handles[CIE_HANDLE_S].Image = IMG_LOAD(buf);
219  }
220  if (optional_string("+Disabled:")) {
221  stuff_string(buf, F_NAME, sizeof(buf));
222  Handles[CIE_HANDLE_D].Image = IMG_LOAD(buf);
223  }
224  }
225  if(optional_string("+Coords:")) {
226  stuff_int_list(Coords, 2, RAW_INTEGER_TYPE);
227  }
228  } else if (in_type == CIE_IMAGE_BORDER) {
229  if (optional_string("+Top Left:")) {
230  stuff_string(buf, F_NAME, sizeof(buf));
231  Handles[CIE_HANDLE_TL].Image = IMG_LOAD(buf);
232  }
233  if (optional_string("+Top Mid:")) {
234  stuff_string(buf, F_NAME, sizeof(buf));
235  Handles[CIE_HANDLE_TM].Image = IMG_LOAD(buf);
236  }
237  if (optional_string("+Top Right:")) {
238  stuff_string(buf, F_NAME, sizeof(buf));
239  Handles[CIE_HANDLE_TR].Image = IMG_LOAD(buf);
240  }
241  if (optional_string("+Mid Left:")) {
242  stuff_string(buf, F_NAME, sizeof(buf));
243  Handles[CIE_HANDLE_ML].Image = IMG_LOAD(buf);
244  }
245  if (optional_string("+Mid Right:")) {
246  stuff_string(buf, F_NAME, sizeof(buf));
247  Handles[CIE_HANDLE_MR].Image = IMG_LOAD(buf);
248  }
249  if (optional_string("+Bottom left:")) {
250  stuff_string(buf, F_NAME, sizeof(buf));
251  Handles[CIE_HANDLE_BL].Image = IMG_LOAD(buf);
252  }
253  if (optional_string("+Bottom Mid:")) {
254  stuff_string(buf, F_NAME, sizeof(buf));
255  Handles[CIE_HANDLE_BM].Image = IMG_LOAD(buf);
256  }
257  if (optional_string("+Bottom Right:")) {
258  stuff_string(buf, F_NAME, sizeof(buf));
259  Handles[CIE_HANDLE_BR].Image = IMG_LOAD(buf);
260  }
261  } else if (in_type == CIE_COORDS) {
262  stuff_int_list(Coords, 2, RAW_INTEGER_TYPE);
263  }
264  }
265 
266 #ifndef NDEBUG
267  //Do a little extra checking in debug mode
268  //This makes sure the skinnger knows if they did something bad
269  if (CIEType == CIE_IMAGE || CIEType == CIE_IMAGE_NMCSD) {
270  int w,h,cw,ch;
271  IMG_INFO(Handles[0].Image, &w, &h);
272  for (uint i = 1; i < CIE_NUM_HANDLES; i++) {
273  if (IMG_HANDLE_IS_VALID(Handles[i].Image)) {
274  IMG_INFO(Handles[i].Image, &cw, &ch);
275  if (cw != w || ch != h) {
276  Warning(LOCATION, "Grouped image size unequal; Handle number %d under $%s: has a different size than base image type", i, tag);
277  }
278  }
279  }
280  }
281 #endif
282 }
283 
285 {
286  int rval = CIE_GC_NONE_SET;
287  if (Coords[0]!=INT_MAX && x!=NULL) {
288  *x=Coords[0];
289  rval |= CIE_GC_X_SET;
290  }
291  if (Coords[1]!=INT_MAX && y!=NULL) {
292  *y=Coords[1];
293  rval |= CIE_GC_Y_SET;
294  }
295 
296  return rval;
297 }
298 
299 int ObjectClassInfoEntry::GetImageHandle(int id, int handle_num)
300 {
301  return Entries[id].GetImageHandle(handle_num);
302 }
303 
304 int ObjectClassInfoEntry::GetCoords(int id, int *x, int *y)
305 {
306  return Entries[id].GetCoords(x, y);
307 }
308 
309 int ObjectClassInfoEntry::GetObjectCoords(int *x, int *y, int *w, int *h)
310 {
311  int rval = CIE_GC_NONE_SET;
312  if (Coords[0] != INT_MAX && x != NULL) {
313  *x = Coords[0];
314  rval |= CIE_GC_X_SET;
315  }
316  if (Coords[1] != INT_MAX && y != NULL) {
317  *y = Coords[1];
318  rval |= CIE_GC_Y_SET;
319  }
320  if (Coords[2] != INT_MAX && w != NULL) {
321  *w = Coords[2];
322  rval |= CIE_GC_W_SET;
323  }
324  if (Coords[3] != INT_MAX && h != NULL) {
325  *h = Coords[3];
326  rval |= CIE_GC_H_SET;
327  }
328 
329  return rval;
330 }
331 //*****************************GUIScreen*******************************
333 {
334  //Set the name
335  Name = in_Name;
336 
337  //Setup the parent system
338  //This can actually be null; but you must attach a screen to a
339  //system for it to be functional.
340  //this may allow for saving of screens in the future. Incredibly useful for HUDs.
341  OwnerSystem = NULL;
342 
343  //Get class info
344  if (OwnerSystem != NULL) {
345  OwnerSystem->PushScreen(this);
346  ScreenClassInfo = OwnerSystem->GetScreenClassInfo(Name);
347  } else {
348  ScreenClassInfo = NULL;
349  }
350 }
351 
353 {
354  GUIObject* cgp = (GUIObject*)GET_FIRST(&Guiobjects);
355  GUIObject* cgp_next;
356  for (; cgp != END_OF_LIST(&Guiobjects); cgp = cgp_next) {
357  cgp_next = (GUIObject*)GET_NEXT(cgp);
358  delete cgp;
359  }
360 }
361 
363 {
364  size_t len;
365  uint i;
366 
367  if (cgp->Parent != NULL && cgp->Parent->InfoEntry != NULL) {
368  len = cgp->Parent->InfoEntry->Subentries.size();
369 
370  for (i = 0; i < len; i++) {
371  if (cgp->Parent->InfoEntry->Subentries[i].Name == cgp->Name) {
372  return &cgp->Parent->InfoEntry->Subentries[i];
373  }
374  }
375 
376  for (i = 0; i < len; i++) {
377  if ( cgp->Parent->InfoEntry->Subentries[i].Name.size() == 0
378  && cgp->Parent->InfoEntry->Subentries[i].Object == cgp->Type ) {
379  return &cgp->Parent->InfoEntry->Subentries[i];
380  }
381  }
382  } else if (cgp->Parent == NULL && ScreenClassInfo != NULL) {
383  len = ScreenClassInfo->Entries.size();
384  for (i = 0; i < len; i++) {
385  if (ScreenClassInfo->Entries[i].Name == cgp->Name) {
386  return &ScreenClassInfo->Entries[i];
387  }
388  }
389 
390  for (i = 0; i < len; i++) {
391  if( ScreenClassInfo->Entries[i].Name.size() == 0 &&
392  ScreenClassInfo->Entries[i].Object == cgp->Type ) {
393  return &ScreenClassInfo->Entries[i];
394  }
395  }
396  }
397 
398  //Generic templates - ie if you want every single OK button to look the same,
399  //or every single window to look the same.
400  if (OwnerSystem != NULL) {
401  len = OwnerSystem->GetClassInfo()->Entries.size();
402 
403  for (i = 0; i < len; i++) {
404  if (OwnerSystem->GetClassInfo()->Entries[i].Name == cgp->Name) {
405  return &OwnerSystem->GetClassInfo()->Entries[i];
406  }
407  }
408 
409  for (i = 0; i < len; i++) {
410  if( OwnerSystem->GetClassInfo()->Entries[i].Name.size() == 0 &&
411  OwnerSystem->GetClassInfo()->Entries[i].Object == cgp->Type) {
412  return &OwnerSystem->GetClassInfo()->Entries[i];
413  }
414  }
415  }
416 
417  return NULL;
418 }
419 
420 //Adds objects to a screen
421 //IMPORTANT: Options added with the same name as
422 //older objects will make this function return
423 //a pointer to the original object with that name
425 {
426  if(new_gauge == NULL) {
427  return NULL;
428  }
429 
430  Assert(this != NULL);
431 
432  //First - do we have anything with the same name.
433  for (GUIObject *tgp = (GUIObject*) GET_FIRST(&Guiobjects); tgp != END_OF_LIST(&Guiobjects); tgp = (GUIObject*) GET_NEXT(tgp)) {
434  if (tgp->Name == new_gauge->Name) {
435  //Get rid of the new gauge
436  //We don't want it; breaks skinning
437 
438  if (tgp->Type == new_gauge->Type) {
439  //If the type of the existing object is the same
440  //as the new one, we can safely pass this one off
441  delete new_gauge;
442  return tgp;
443  } else {
444  //This is icky; we might cast a pointer after this.
445  //So return NULL with a warning
446  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);
447  delete new_gauge;
448  return NULL;
449  }
450  }
451  }
452 
453  //Add to the end of the list
454  list_append(&Guiobjects, new_gauge);
455  new_gauge->OwnerSystem = OwnerSystem;
456  new_gauge->OwnerScreen = this;
457 
458  //For skinning
459  new_gauge->SetCIPointer();
460  //Set position and stuff
461  new_gauge->GetOIECoords(&new_gauge->Coords[0], &new_gauge->Coords[1], &new_gauge->Coords[2], &new_gauge->Coords[3]);
462  //In case we need to resize
463  new_gauge->OnRefreshSize();
464 
465  return new_gauge;
466 }
467 
469 {
470  DeletionCache.push_back(dgp);
471 }
472 
473 int GUIScreen::OnFrame(float frametime, bool doevents)
474 {
475  GUIObject* cgp;
476  GUIObject* cgp_prev;
477  bool SomethingPressed = false;
478 
479  if (NOT_EMPTY(&Guiobjects) && doevents) {
480  //Note that children WILL be changing this variable as they go along,
481  //as they use up statuses.
482  int status = OwnerSystem->GetStatus();
483 
484  //Pass the status on
485  cgp = (GUIObject*)GET_LAST(&Guiobjects);
486  cgp->Status |= (status & GST_KEYBOARD_STATUS);
487  for (; cgp != END_OF_LIST(&Guiobjects); cgp = cgp_prev) {
488  //In case an object deletes itself
489  cgp_prev = (GUIObject*)GET_PREV(cgp);
490  cgp->LastStatus = cgp->Status;
491  cgp->Status = 0;
492 
493  //If we are moving something, nothing else can get click events
494  if (OwnerSystem->GetGraspedObject() == NULL) {
495  if (OwnerSystem->GetMouseX() >= cgp->Coords[0]
496  && OwnerSystem->GetMouseX() <= cgp->Coords[2]
497  && OwnerSystem->GetMouseY() >= cgp->Coords[1]
498  && OwnerSystem->GetMouseY() <= cgp->Coords[3]) {
499  cgp->Status |= (status & GST_MOUSE_STATUS);
500  if (status & GST_MOUSE_PRESS) {
501  SomethingPressed = true;
502  }
503  }
504  }
505 
506  cgp->OnFrame(frametime, &status);
507  }
508  }
509 
510  for (size_t i = DeletionCache.size(); i > 0; i--) {
511  delete DeletionCache[i-1];
512  DeletionCache.pop_back();
513  }
514 
515  // save zbuffer so that we can reset it after drawing (FIXME: this could probably be done better)
516  int saved_zbuf = gr_zbuffer_get();
518 
519  //Draw now. This prevents problems from an object deleting itself or moving around in the list
520  cgp = (GUIObject*)GET_FIRST(&Guiobjects);
521 
522  while (cgp != END_OF_LIST(&Guiobjects)) {
523  if ( !doevents ) {
524  cgp->Status = 0;
525  }
526 
527  cgp->OnDraw(frametime);
528 
529  cgp = (GUIObject*)GET_NEXT(cgp);
530  }
531 
532  // reset zbuffer to saved value
533  gr_zbuffer_set(saved_zbuf);
534 
535  if(SomethingPressed) {
536  return GSOF_SOMETHINGPRESSED;
537  } else {
538  return GSOF_NOTHINGPRESSED;
539  }
540 }
541 
542 //*****************************GUISystem*******************************
544 {
545  GraspedGuiobject=ActiveObject=NULL;
546  Status=LastStatus=0;
547  MouseX = MouseY = 0;
548  ClassInfoParsed = false;
549 }
550 
552 {
553  GUIScreen* csp = (GUIScreen*)GET_FIRST(&Screens);
554  GUIScreen* csp_next;
555  for (; csp != END_OF_LIST(&Screens); csp = csp_next) {
556  csp_next = (GUIScreen*)GET_NEXT(csp);
557  delete csp;
558  }
559  DestroyClassInfo();
560 }
561 
563 {
564  Assert(csp != NULL);
565  list_append(&Screens, csp);
566  csp->OwnerSystem = this;
567  csp->ScreenClassInfo = GetScreenClassInfo(csp->Name);
568  return csp;
569 }
570 
571 //Removes a screen from a GUISystem
572 //Handy if you want to save window movements and such;
573 //just call this and it'll take care of everything
575 {
576  GUIScreen *csp_next;
577  for (GUIScreen *csp = (GUIScreen*)GET_FIRST(&Screens); csp != END_OF_LIST(&Screens); csp = csp_next) {
578  csp_next = (GUIScreen*)GET_NEXT(csp);
579  if (csp == in_screen) {
580  csp->prev->next = csp->next;
581  csp->next->prev = csp->prev;
582  csp->next = csp;
583  csp->prev = csp;
584  csp->OwnerSystem = NULL;
585  }
586  }
587 }
588 
590 {
591  ScreenClassInfoEntry *sciep;
592  for (sciep = (ScreenClassInfoEntry*)GET_FIRST(&ScreenClassInfo); sciep != END_OF_LIST(&ScreenClassInfo); sciep = (ScreenClassInfoEntry*)GET_NEXT(sciep)) {
593  if (sciep->GetName() == screen_name) {
594  return sciep;
595  }
596  }
597 
598  return NULL;
599 }
600 
601 int GUISystem::OnFrame(float frametime, bool doevents, bool clearandflip)
602 {
603  //Set the global status variables for this frame
604  LastStatus = Status;
605  Status = GST_MOUSE_OVER;
606 
607  bool something_pressed = false;
608 
609  if (clearandflip) {
610  gr_clear();
611  }
612 
613  if (NOT_EMPTY(&Screens)) {
614  if (doevents) {
615  KeyPressed = game_check_key();
616 
617  //Add keyboard event stuff
618  if (KeyPressed) {
619  Status |= GST_KEYBOARD_KEYPRESS;
620 
621  if (KeyPressed & KEY_CTRLED) {
622  Status |= GST_KEYBOARD_CTRL;
623  }
624  if (KeyPressed & KEY_ALTED) {
625  Status |= GST_KEYBOARD_ALT;
626  }
627  if (KeyPressed & KEY_SHIFTED) {
628  Status |= GST_KEYBOARD_SHIFT;
629  }
630  }
631 
632  //Add mouse event stuff
634  Status |= GST_MOUSE_LEFT_BUTTON;
635  } else if (mouse_down(MOUSE_MIDDLE_BUTTON)) {
636  Status |= GST_MOUSE_MIDDLE_BUTTON;
637  } else if (mouse_down(MOUSE_RIGHT_BUTTON)) {
638  Status |= GST_MOUSE_RIGHT_BUTTON;
639  }
640 
641  mouse_get_pos(&MouseX, &MouseY);
642 
643  //Handle any grasped object (we are in the process of moving this)
644  if (GraspedGuiobject != NULL) {
645  if (Status & GraspingButton) {
646  something_pressed = true;
647  GraspedGuiobject->SetPosition(MouseX - GraspedDiff[0], MouseY - GraspedDiff[1]);
648  GraspedGuiobject->Status = (Status & GST_MOUSE_STATUS);
649  } else {
650  GraspedGuiobject = NULL;
651  }
652  }
653  }
654 
655  GUIScreen *csp_prev; //so screens can delete themselves
656  for (GUIScreen* csp = (GUIScreen*)GET_LAST(&Screens); csp != END_OF_LIST(&Screens); csp = csp_prev) {
657  csp_prev = (GUIScreen*)GET_PREV(csp);
658  if (csp->OnFrame(frametime, doevents) == GSOF_SOMETHINGPRESSED) {
659  something_pressed = true;
660  }
661  }
662  }
663 
664  if (clearandflip) {
665  gr_flip();
666  }
667 
668  if (something_pressed) {
669  return GSOF_SOMETHINGPRESSED;
670  } else {
671  return GSOF_NOTHINGPRESSED;
672  }
673 }
674 
676 {
677  if (cgp != NULL) {
678  ActiveObject = cgp;
679  //Move everything to the end of the list
680  //This way, it gets precedence
681  while (cgp->Parent != NULL) {
682  list_move_append(&cgp->Parent->Children, cgp);
683  cgp = cgp->Parent;
684  }
685 
686  //Eventually, we make this last guy the last object in Guiobjects
687  list_move_append(&cgp->OwnerScreen->Guiobjects, cgp);
688  }
689 }
690 
692 {
693  //Protect thyself!
694  if (cgp == NULL) {
695  return;
696  }
697 
698  GraspedGuiobject = cgp;
699  GraspingButton = button;
700  GraspedDiff[0] = MouseX - cgp->Coords[0];
701  GraspedDiff[1] = MouseY - cgp->Coords[1];
702 }
703 
704 void GUISystem::DestroyClassInfo()
705 {
706  ScreenClassInfoEntry *sciep, *next_sciep;
707  for (sciep = (ScreenClassInfoEntry*)GET_FIRST(&ScreenClassInfo); sciep != END_OF_LIST(&ScreenClassInfo); sciep = next_sciep) {
708  next_sciep = (ScreenClassInfoEntry*)GET_NEXT(sciep);
709  delete sciep;
710  }
711  ClassInfoParsed = false;
712 }
713 
714 //*****************************GUIObject*******************************
715 GUIObject::GUIObject(const SCP_string &in_Name, int x_coord, int y_coord, int x_width, int y_height, int in_style)
716 {
717  //General stuff
718  LastStatus = Status = 0;
719  OwnerSystem = NULL;
720  OwnerScreen = NULL;
721  Parent = NULL;
722  CloseFunction = NULL;
723 
724  list_init(this);
725  list_init(&Children);
726 
727  //These would make no sense
728  //x_coord and y_coord of < 0 mean to let the parent handle placement.
729  if (x_width == 0 || y_height == 0) {
730  return;
731  }
732 
733  //No! Bad!
734  if (in_Name.length() < 1) {
735  return;
736  }
737 
738  Name = in_Name;
739  Coords[0] = x_coord;
740  Coords[1] = y_coord;
741  Coords[2] = x_coord + x_width;
742  Coords[3] = y_coord + y_height;
743 
744  Style = in_style;
745 
746  if (x_width > 0) {
747  Style |= GS_NOAUTORESIZEX;
748  }
749  if (y_height > 0) {
750  Style |= GS_NOAUTORESIZEY;
751  }
752 
753  Type = GT_NONE;
754  InfoEntry = NULL;
755 }
756 
758 {
759  if (CloseFunction != NULL) {
760  CloseFunction(this);
761  }
762 
763  DeleteChildren();
764 
765  // Set these properly
766  next->prev = prev;
767  prev->next = next;
768 }
769 
771 {
772  if ( EMPTY(&Children) ) {
773  return;
774  }
775 
776  GUIObject* cgp = (GUIObject*)GET_FIRST(&Children);
777  GUIObject* cgp_temp;
778 
779  while (cgp != END_OF_LIST(&Children)) {
780  cgp_temp = cgp;
781  cgp = (GUIObject*)GET_NEXT(cgp);
782  delete cgp_temp;
783  }
784 
785  list_init(&Children);
786 }
787 
788 GUIObject* GUIObject::AddChildInternal(GUIObject *cgp)
789 {
790  if (cgp == NULL) {
791  return NULL;
792  }
793 
794  cgp->Style |= GS_INTERNALCHILD;
795 
796  //Add to end of child list
797  list_append(&Children, cgp);
798 
799  cgp->Parent = this;
800  cgp->OwnerSystem = OwnerSystem;
801  cgp->OwnerScreen = OwnerScreen;
802 
803  //Update coordinates (Should be relative x/y and width/height) to absolute coordinates
804  cgp->Coords[0] += Coords[0];
805  cgp->Coords[1] += Coords[1];
806  cgp->Coords[2] += Coords[0];
807  cgp->Coords[3] += Coords[1];
808 
809  //For skinning
810  cgp->SetCIPointer();
811  //Check position
812  cgp->GetOIECoords(&cgp->Coords[0], &cgp->Coords[1], &cgp->Coords[2], &cgp->Coords[3]);
813  //In case we need to resize
814  cgp->OnRefreshSize();
815 
816  return cgp;
817 }
818 
820 {
821  if (cgp == NULL) {
822  return NULL;
823  }
824 
825  //AddInternalChild must be used
826  if (cgp->Style & GS_INTERNALCHILD) {
827  return NULL;
828  }
829 
830  //Add to end of child list
831  list_append(&Children, cgp);
832 
833  cgp->Parent = this;
834  cgp->OwnerSystem = OwnerSystem;
835  cgp->OwnerScreen = OwnerScreen;
836 
837  // Update coordinates (Should be relative x/y and width/height) to absolute coordinates
838  cgp->Coords[0] += ChildCoords[0];
839  cgp->Coords[1] += ChildCoords[1];
840  cgp->Coords[2] += ChildCoords[0];
841  cgp->Coords[3] += ChildCoords[1];
842 
843  //For skinning
844  cgp->SetCIPointer();
845  //Check position
846  cgp->GetOIECoords(&cgp->Coords[0], &cgp->Coords[1], &cgp->Coords[2], &cgp->Coords[3]);
847  //In case we need to resize
848  cgp->OnRefreshSize();
849 
850  return cgp;
851 }
852 
854 {
855  if (OwnerScreen != NULL) {
856  OwnerScreen->DeleteObject(this);
857  } else {
858  delete this;
859  }
860 }
861 
862 void GUIObject::OnDraw(float frametime)
863 {
864  DoDraw(frametime);
865  if (!(Style & GS_HIDDEN)) {
866  GUIObject *cgp_prev;
867  for (GUIObject* cgp = (GUIObject*)GET_LAST(&Children); cgp != END_OF_LIST(&Children); cgp = cgp_prev) {
868  cgp_prev = (GUIObject*)GET_PREV(cgp);
869  cgp->OnDraw(frametime);
870  }
871  }
872 }
873 
874 int GUIObject::OnFrame(float frametime, int *unused_queue)
875 {
876  int rval = OF_TRUE;
877 
878  GUIObject *cgp_prev; //Elements will move themselves to the end of the list if they become active
879  GUIObject *cgp = (GUIObject*)GET_LAST(&Children);
880 
881  for ( ; (cgp != NULL) && (cgp != END_OF_LIST(&Children)); cgp = cgp_prev) {
882  cgp_prev = (GUIObject*)GET_PREV(cgp);
883  cgp->LastStatus = cgp->Status;
884  cgp->Status = 0;
885 
886  if (Status & GST_MOUSE_OVER) {
887  if (OwnerSystem->GetMouseX() >= cgp->Coords[0]
888  && OwnerSystem->GetMouseX() <= cgp->Coords[2]
889  && OwnerSystem->GetMouseY() >= cgp->Coords[1]
890  && OwnerSystem->GetMouseY() <= cgp->Coords[3]) {
891  cgp->Status |= (Status & GST_MOUSE_STATUS);
892  }
893  }
894  if (cgp == GET_LAST(&Children)) {
895  cgp->Status |= (Status & GST_KEYBOARD_STATUS);
896  }
897  cgp->OnFrame(frametime, &Status);
898  }
899 
900  if (Status) {
901  //MOUSE OVER
902  if (Status & GST_MOUSE_OVER) {
903  rval = DoMouseOver(frametime);
904 
905  if (rval == OF_TRUE) {
906  (*unused_queue) &= ~GST_MOUSE_OVER;
907  }
908  }
909 
910  //MOUSE DOWN
911  if (Status & GST_MOUSE_PRESS) {
912  rval = DoMouseDown(frametime);
913 
914  if (rval == OF_TRUE) {
916  }
917  }
918 
919  //MOUSE UP
920  if ((LastStatus & GST_MOUSE_PRESS) && !(OwnerSystem->GetStatus() & GST_MOUSE_PRESS)) {
921  rval = DoMouseUp(frametime);
922 
923  if (rval == OF_TRUE) {
925  }
926  }
927 
928  //KEY STATE
929  if ((Status & GST_KEYBOARD_CTRL) || (Status & GST_KEYBOARD_ALT) || (Status & GST_KEYBOARD_SHIFT)) {
930  rval = DoKeyState(frametime);
931 
932  if (rval == OF_TRUE) {
933  (*unused_queue) &= ~(GST_KEYBOARD_CTRL | GST_KEYBOARD_ALT | GST_KEYBOARD_SHIFT);
934  }
935  }
936 
937  //KEYPRESS
938  if (Status & GST_KEYBOARD_KEYPRESS) {
939  rval = DoKeyPress(frametime);
940 
941  if (rval == OF_TRUE) {
942  (*unused_queue) &= ~GST_KEYBOARD_KEYPRESS;
943  }
944  }
945  }
946 
947  if (!(Status & GST_MOUSE_OVER) && (LastStatus & GST_MOUSE_OVER)) {
948  rval = DoMouseOut(frametime);
949  }
950 
951  return DoFrame(frametime);
952 }
953 
954 void GUIObject::OnMove(int dx, int dy)
955 {
956  Coords[0]+=dx;
957  Coords[1]+=dy;
958  Coords[2]+=dx;
959  Coords[3]+=dy;
960  ChildCoords[0]+=dx;
961  ChildCoords[1]+=dy;
962  ChildCoords[2]+=dx;
963  ChildCoords[3]+=dy;
964 
965  for (GUIObject *cgp = (GUIObject*)GET_FIRST(&Children); cgp != END_OF_LIST(&Children); cgp = (GUIObject*)GET_NEXT(cgp)) {
966  cgp->OnMove(dx, dy);
967  }
968 
969  DoMove(dx, dy);
970 }
971 
972 int GUIObject::GetCIECoords(int id, int *x, int *y)
973 {
974  if (InfoEntry!=NULL) {
975  int rv = InfoEntry->GetCoords(id, x, y);
976  if (rv & CIE_GC_X_SET) {
977  if (*x < 0) {
978  *x += Coords[2];
979  } else {
980  *x += Coords[0];
981  }
982  }
983  if (rv & CIE_GC_Y_SET) {
984  if (*y < 0) {
985  *y += Coords[3];
986  } else {
987  *y += Coords[1];
988  }
989  }
990 
991  return rv;
992  }
993 
994  return CIE_GC_NONE_SET;
995 }
996 
997 int GUIObject::GetOIECoords(int *x1, int *y1, int *x2, int *y2)
998 {
999  if (InfoEntry != NULL) {
1000  int rv = InfoEntry->GetObjectCoords(x1, y1, x2, y2);
1001  if (Parent != NULL) {
1002  if (rv & CIE_GC_X_SET) {
1003  if (*x1 < 0) {
1004  *x1 += Parent->ChildCoords[2];
1005  } else {
1006  *x1 += Parent->ChildCoords[0];
1007  }
1008  }
1009  if (rv & CIE_GC_Y_SET) {
1010  if (*y1 < 0) {
1011  *y1 += Parent->ChildCoords[3];
1012  } else {
1013  *y1 += Parent->ChildCoords[1];
1014  }
1015  }
1016  } else {
1017  if (rv & CIE_GC_X_SET) {
1018  if (*x1 < 0) {
1019  *x1 += gr_screen.clip_right;
1020  } else {
1021  *x1 += gr_screen.clip_left;
1022  }
1023  }
1024  if (rv & CIE_GC_Y_SET) {
1025  if (*y1 < 0) {
1026  *y1 += gr_screen.clip_bottom;
1027  } else {
1028  *y1 += gr_screen.clip_top;
1029  }
1030  }
1031  }
1032  if (rv & CIE_GC_W_SET) {
1033  *x2 = *x1 + *x2;
1034  Style |= GS_NOAUTORESIZEX;
1035  }
1036  if (rv & CIE_GC_H_SET) {
1037  *y2 = *y1 + *y2;
1038  Style |= GS_NOAUTORESIZEY;
1039  }
1040 
1041  return rv;
1042  }
1043 
1044  return CIE_GC_NONE_SET;
1045 }
1046 
1047 //Call this after an object's type is set to enable the GUIObject CIE functions
1049 {
1050  if (OwnerScreen) {
1051  InfoEntry=OwnerScreen->GetObjectClassInfo(this);
1052  }
1053 }
1054 
1056 {
1057  int dx, dy;
1058  dx = x - Coords[0];
1059  dy = y - Coords[1];
1060 
1061  if (dx == 0 && dy == 0) {
1062  return;
1063  }
1064 
1065  if (Parent != NULL) {
1066  //Don't let stuff get moved outside client window
1067  if (Coords[2] + dx > Parent->Coords[2]) {
1068  dx = Parent->Coords[2] - Coords[2];
1069  }
1070  if (Coords[3] + dy > gr_screen.clip_bottom) {
1071  dy = Parent->Coords[3] - Coords[3];
1072  }
1073 
1074  //Check these last, so we're sure we can move stuff around still
1075  if (Coords[0] + dx < gr_screen.clip_left) {
1076  dx = Parent->Coords[0] - Coords[0];
1077  }
1078  if (Coords[1] + dy < gr_screen.clip_top) {
1079  dy = Parent->Coords[1] - Coords[1];
1080  }
1081  }
1082 
1083  OnMove(dx, dy);
1084 }
1085 
1086 //*****************************Window*******************************
1088 {
1089  float num;
1090  int w=0, h=0;
1091  //Top left, top right, bottom left, bottom right
1092  int CornerWidths[4];
1093 
1094  //Determine left border's width
1096  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_ML), &BorderSizes[0], NULL);
1097  } else {
1098  BorderSizes[0] = W_BORDERHEIGHT;
1099  }
1100 
1101  //Determine right border's width
1103  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_MR), &BorderSizes[2], NULL);
1104  } else {
1105  BorderSizes[2] = W_BORDERWIDTH;
1106  }
1107 
1108  //Determine top border height
1109  bool custom_top = true;
1111  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TL), NULL, &BorderSizes[1]);
1113  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR), NULL, &BorderSizes[1]);
1115  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TM), NULL, &BorderSizes[1]);
1116  } else {
1117  custom_top = false;
1118  BorderSizes[1] = W_BORDERHEIGHT;
1119  }
1120 
1121  //Determine bottom border height
1123  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), NULL, &BorderSizes[3]);
1125  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BR), NULL, &BorderSizes[3]);
1127  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BM), NULL, &BorderSizes[3]);
1128  } else {
1129  BorderSizes[3] = W_BORDERHEIGHT;
1130  }
1131 
1132 
1133  //Determine corner sizes
1135  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), &CornerWidths[0], NULL);
1136  } else {
1137  CornerWidths[0] = BorderSizes[0];
1138  }
1139 
1141  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_TR), &CornerWidths[1], NULL);
1142  } else {
1143  CornerWidths[1] = BorderSizes[2];
1144  }
1145 
1147  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), &CornerWidths[2], NULL);
1148  } else {
1149  CornerWidths[2] = BorderSizes[0];
1150  }
1151 
1153  IMG_INFO(GetCIEImageHandle(WCI_BORDER, CIE_HANDLE_BL), &CornerWidths[3], NULL);
1154  } else {
1155  CornerWidths[3] = BorderSizes[2];
1156  }
1157 
1158 
1159  //Do child stuff
1160  ChildCoords[0] = Coords[0] + BorderSizes[0];
1161  if (custom_top || (Style & WS_NOTITLEBAR)) {
1162  ChildCoords[1] = Coords[1] + BorderSizes[1]; //Set earlier on
1163  } else {
1164  ChildCoords[1] = Coords[1] + gr_get_font_height() + 5 + 3*W_BORDERHEIGHT;
1165  }
1166  ChildCoords[2] = Coords[2] - BorderSizes[2];
1167  ChildCoords[3] = Coords[3] - BorderSizes[3];
1168 
1169  if (!(Style & GS_NOAUTORESIZEX)) {
1170  ChildCoords[2] = Coords[2] = 0;
1171  }
1172  if (!(Style & GS_NOAUTORESIZEY)) {
1173  ChildCoords[3] = Coords[3] = 0;
1174  }
1175 
1176  for (GUIObject *cgp = (GUIObject*)GET_FIRST(&Children); cgp != END_OF_LIST(&Children); cgp = (GUIObject*)GET_NEXT(cgp)) {
1177  //SetPosition children around so they're within the upper-left corner of dialog
1178  if (cgp->Coords[0] < ChildCoords[0]) {
1179  cgp->SetPosition(ChildCoords[0], cgp->Coords[1] + BorderSizes[0]);
1180  }
1181  if (cgp->Coords[1] < ChildCoords[1]) {
1182  cgp->SetPosition(cgp->Coords[0], Coords[1] + BorderSizes[1]);
1183  }
1184 
1185  //Resize window to fit children
1186  if (cgp->Coords[2] > ChildCoords[2] && !(Style & GS_NOAUTORESIZEX)) {
1187  ChildCoords[2] = cgp->Coords[2];
1188  Coords[2] = cgp->Coords[2] + BorderSizes[2];
1189  }
1190  if (cgp->Coords[3] > ChildCoords[3] && !(Style & GS_NOAUTORESIZEY)) {
1191  ChildCoords[3] = cgp->Coords[3];
1192  Coords[3] = cgp->Coords[3] + BorderSizes[3];
1193  }
1194  }
1195 
1196  //Find caption coordinates
1197  if (!(Style & WS_NOTITLEBAR)) {
1198  int close_w = 0,close_h = 0;
1199  int hide_w = 0, hide_h = 0;
1200 
1202  IMG_INFO(GetCIEImageHandle(WCI_CLOSE), &close_w, &close_h);
1203  } else {
1204  gr_get_string_size(&close_w, &close_h, "X");
1205  }
1206 
1208  IMG_INFO(GetCIEImageHandle(WCI_HIDE), &hide_w, &hide_h);
1209  } else {
1210  gr_get_string_size(&hide_w, &hide_h, "-");
1211  }
1212 
1213  int caption_min_size;
1214  if (Caption.size() > 0) {
1215  gr_get_string_size(&w, &h, Caption.c_str());
1216  caption_min_size = w + close_w + hide_w + 5;
1217  } else {
1218  caption_min_size = close_w + hide_w;
1219  }
1220 
1221  if ((Coords[2] - Coords[0]) < (caption_min_size)) {
1222  Coords[2] = Coords[0] + caption_min_size + BorderSizes[0] + BorderSizes[2];
1223  }
1224 
1225  if (Caption.size() > 0) {
1227  int cw, ch;
1228  CaptionCoords[0] = Coords[0] + BorderSizes[0];
1229  CaptionCoords[1] = Coords[1] + BorderSizes[1];
1230  GetCIECoords(WCI_CAPTION, &CaptionCoords[0], &CaptionCoords[1]);
1231 
1232  //do the image
1234  num = (float) w / cw;
1235  CaptionRectList = bitmap_rect_list(Coords[0] + CornerWidths[2], Coords[1], w, ch, 0, 0, 1.0f, 1.0f);
1236  h = ch;
1237  } else {
1238  h += 5;
1239  CaptionCoords[0] = Coords[0] + (((Coords[2]-Coords[0]) - w - (close_w + hide_w)) / 2);
1240  CaptionCoords[1] = Coords[1] + BorderSizes[1];
1241  }
1242  CaptionCoords[2] = CaptionCoords[0] + w;
1243  CaptionCoords[3] = CaptionCoords[1] + h;
1244  }
1245 
1246  //Find close coordinates now
1247  CloseCoords[0] = Coords[2] - close_w;
1248  CloseCoords[1] = Coords[1] + BorderSizes[1];
1249  GetCIECoords(WCI_CLOSE, &CloseCoords[0], &CloseCoords[1]);
1250  CloseCoords[2] = CloseCoords[0] + close_w;
1251  CloseCoords[3] = CloseCoords[1] + close_h;
1252 
1253  //Find hide coordinates now
1254  HideCoords[0] = CloseCoords[0] - hide_w;
1255  HideCoords[1] = CloseCoords[1];
1256  GetCIECoords(WCI_HIDE, &HideCoords[0], &HideCoords[1]);
1257  HideCoords[2] = HideCoords[0] + hide_w;
1258  HideCoords[3] = HideCoords[1] + hide_h;
1259  }
1260 
1261  //Do bitmap stuff
1264  num = (float)((Coords[2]-CornerWidths[3])-(Coords[0]+CornerWidths[2])) / (float)w;
1265  BorderRectLists[CIE_HANDLE_TM] = bitmap_rect_list(Coords[0] + CornerWidths[2], Coords[1], fl2i(w*num),h,0,0,num,1.0f);
1266  //gr_bitmap_list(&BorderRectLists[CIE_HANDLE_BM], 1, GR_RESIZE_NONE);
1267  }
1270  num = (float)((Coords[2]-CornerWidths[3])-(Coords[0]+CornerWidths[2])) / (float)w;
1271  BorderRectLists[CIE_HANDLE_BM] = bitmap_rect_list(Coords[0] + CornerWidths[2], Coords[3]-h, fl2i(w*num),h,0,0,num,1.0f);
1272  //gr_bitmap_list(&BorderRectLists[CIE_HANDLE_BM], 1, GR_RESIZE_NONE);
1273  }
1276  num = (float)((Coords[3]-BorderSizes[3])-(Coords[1]+BorderSizes[1])) / (float)h;
1277  BorderRectLists[CIE_HANDLE_ML] = bitmap_rect_list(Coords[0], Coords[1] + BorderSizes[1], w,fl2i(h*num),0,0,1.0f,num);
1278  }
1281  num = (float)((Coords[3]-BorderSizes[3])-(Coords[1]+BorderSizes[1])) / (float)h;
1282  BorderRectLists[CIE_HANDLE_MR] = bitmap_rect_list(Coords[2]-w, Coords[1] + BorderSizes[1], w,fl2i(h*num),0,0,1.0f,num);
1283  }
1284 
1285  return OF_TRUE;
1286 }
1287 
1288 int Window::DoMouseOver(float frametime)
1289 {
1290  if (OwnerSystem->GetMouseX() >= HideCoords[0]
1291  && OwnerSystem->GetMouseX() <= HideCoords[2]
1292  && OwnerSystem->GetMouseY() >= HideCoords[1]
1293  && OwnerSystem->GetMouseY() <= HideCoords[3]) {
1294  HideHighlight = true;
1295  } else {
1296  HideHighlight = false;
1297  }
1298 
1299  if (OwnerSystem->GetMouseX() >= CloseCoords[0]
1300  && OwnerSystem->GetMouseX() <= CloseCoords[2]
1301  && OwnerSystem->GetMouseY() >= CloseCoords[1]
1302  && OwnerSystem->GetMouseY() <= CloseCoords[3]) {
1303  CloseHighlight = true;
1304  } else {
1305  CloseHighlight = false;
1306  }
1307 
1308  return OF_TRUE;
1309 }
1310 
1311 int Window::DoMouseDown(float frametime)
1312 {
1313  OwnerSystem->SetActiveObject(this);
1314 
1315  if (Style & WS_NONMOVEABLE) {
1316  return OF_TRUE;
1317  }
1318 
1319  if ((OwnerSystem->GetGraspedObject() == NULL)
1320  && (Status & GST_MOUSE_LEFT_BUTTON)
1321  && OwnerSystem->GetMouseX() >= CaptionCoords[0]
1322  && ((OwnerSystem->GetMouseX() < CaptionCoords[2]) || ((Style & WS_NOTITLEBAR) && OwnerSystem->GetMouseX() <= Coords[2]))
1323  && OwnerSystem->GetMouseY() >= CaptionCoords[1]
1324  && ((OwnerSystem->GetMouseY() <= CaptionCoords[3]) || ((Style & WS_NOTITLEBAR) && OwnerSystem->GetMouseY() <= Coords[2])))
1325  {
1326  OwnerSystem->SetGraspedObject(this, GST_MOUSE_LEFT_BUTTON);
1327  }
1328 
1329  //All further movement of grasped objects is handled by GUISystem
1330 
1331  return OF_TRUE;
1332 }
1333 
1334 int Window::DoMouseUp(float frametime)
1335 {
1336  if (Style & WS_NONMOVEABLE) {
1337  return OF_TRUE;
1338  }
1339 
1340  if (CloseHighlight) {
1341  Delete();
1342  return OF_TRUE;
1343  }
1344 
1345  if (HideHighlight) {
1346  if (Style & GS_HIDDEN) {
1347  Coords[3] = UnhiddenHeight;
1348  Style &= ~GS_HIDDEN;
1349  } else {
1350  UnhiddenHeight = Coords[3];
1351  Coords[3] = Coords[1] + (CaptionCoords[3] - CaptionCoords[1]) + BorderSizes[1] + BorderSizes[3];
1352  Style |= GS_HIDDEN;
1353  }
1354 
1356  int h;
1358  BorderRectLists[CIE_HANDLE_BM].screen_rect.y = Coords[3] - h;
1359  }
1360  }
1361  return OF_TRUE;
1362 }
1363 
1364 int Window::DoMouseOut(float frametime)
1365 {
1366  HideHighlight = false;
1367  CloseHighlight = false;
1368  return OF_TRUE;
1369 }
1370 
1371 void Window::DoMove(int dx, int dy)
1372 {
1373  CloseCoords[0] += dx;
1374  CloseCoords[1] += dy;
1375  CloseCoords[2] += dx;
1376  CloseCoords[3] += dy;
1377 
1378  HideCoords[0] += dx;
1379  HideCoords[1] += dy;
1380  HideCoords[2] += dx;
1381  HideCoords[3] += dy;
1382 
1383  CaptionCoords[0] += dx;
1384  CaptionCoords[1] += dy;
1385  CaptionCoords[2] += dx;
1386  CaptionCoords[3] += dy;
1387 
1388  // change the hidden height too if needed
1389  if (Style & GS_HIDDEN) {
1390  UnhiddenHeight += dy;
1391  }
1392 
1393  //Handle moving the border around
1394  uint i;
1395  for (i = 0; i < 8; i++) {
1396  BorderRectLists[i].screen_rect.x += dx;
1397  BorderRectLists[i].screen_rect.y += dy;
1398  }
1399 
1400  //now the caption
1401  CaptionRectList.screen_rect.x += dx;
1402  CaptionRectList.screen_rect.y += dy;
1403 }
1404 
1405 void draw_open_rect(int x1, int y1, int x2, int y2, int resize_mode = GR_RESIZE_NONE)
1406 {
1407  gr_line(x1, y1, x2, y1, resize_mode);
1408  gr_line(x2, y1, x2, y2, resize_mode);
1409  gr_line(x2, y2, x1, y2, resize_mode);
1410  gr_line(x1, y2, x1, y1, resize_mode);
1411 }
1412 
1413 extern void gr_opengl_shade(int x, int y, int w, int h, int resize_mode);
1414 
1415 void Window::DoDraw(float frametime)
1416 {
1417  int w, h;
1418 
1419  // if the window has no title bar, and no content, then don't draw any of it
1420  if ( (Style & WS_NOTITLEBAR) && !HasChildren() ) {
1421  return;
1422  }
1423 
1424  // shade the background of the window so that it's just slightly transparent
1425  gr_set_shader(&WindowShade);
1426  gr_opengl_shade(Coords[0], Coords[1], Coords[2], Coords[3], GR_RESIZE_NONE);
1427 
1429 
1432  IMG_DRAW(Coords[0], Coords[1]);
1433  }
1434 
1438  IMG_DRAW(Coords[2] - w, Coords[1]);
1439  }
1440 
1444  IMG_DRAW(Coords[0], Coords[3] - h);
1445  }
1446 
1450  //IMG_DRAW(Coords[2] - w, Coords[3] - h, false);
1451  IMG_DRAW(Coords[2]-w, Coords[3] - h);
1452  }
1453 
1456  gr_bitmap_list(&BorderRectLists[CIE_HANDLE_TM], 1, GR_RESIZE_NONE);
1457  } else {
1458  gr_line(Coords[0] + BorderSizes[0], Coords[1], Coords[2] - BorderSizes[2], Coords[1], GR_RESIZE_NONE);
1459  }
1460 
1463  gr_bitmap_list(&BorderRectLists[CIE_HANDLE_BM], 1, GR_RESIZE_NONE);
1464  } else {
1465  gr_line(Coords[0] + BorderSizes[0], Coords[3], Coords[2] - BorderSizes[2], Coords[3], GR_RESIZE_NONE);
1466  }
1467 
1468  if (!(Style & GS_HIDDEN)) {
1471  gr_bitmap_list(&BorderRectLists[CIE_HANDLE_ML], 1, GR_RESIZE_NONE);
1472  } else {
1473  gr_line(Coords[0], Coords[1] + BorderSizes[1], Coords[0], Coords[3] - BorderSizes[3], GR_RESIZE_NONE);
1474  }
1475 
1478  gr_bitmap_list(&BorderRectLists[CIE_HANDLE_MR], 1, GR_RESIZE_NONE);
1479  } else {
1480  gr_line(Coords[2], Coords[1] + BorderSizes[1], Coords[2], Coords[3] - BorderSizes[3], GR_RESIZE_NONE);
1481  }
1482  }
1483 
1484  if (!(Style & WS_NOTITLEBAR)) {
1485  //Draw the caption background
1488  gr_bitmap_list(&CaptionRectList, 1, GR_RESIZE_NONE);
1489  } else {
1490  draw_open_rect(Coords[0], Coords[1], Coords[2], CaptionCoords[3]);
1491  }
1492 
1493  //Close button
1495  if (CloseHighlight && IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_CLOSE, CIE_HANDLE_M))) {
1497  } else {
1499  }
1500  IMG_DRAW(CloseCoords[0], CloseCoords[1]);
1501  } else {
1502  if (CloseHighlight) {
1504  } else {
1506  }
1507  gr_string(CloseCoords[0], CloseCoords[1], "X", GR_RESIZE_NONE);
1508  }
1509 
1510 
1511  //Hide button
1513  if (HideHighlight && IMG_HANDLE_IS_VALID(GetCIEImageHandle(WCI_HIDE, CIE_HANDLE_M))) {
1515  } else {
1517  }
1518  IMG_DRAW(HideCoords[0], HideCoords[1]);
1519  } else {
1520  if (HideHighlight) {
1522  } else {
1524  }
1525  gr_string(HideCoords[0], HideCoords[1], "-", GR_RESIZE_NONE);
1526  }
1527 
1528  //Caption text
1530 
1531  gr_string(CaptionCoords[0], CaptionCoords[1], Caption.c_str(), GR_RESIZE_NONE);
1532  }
1533 }
1534 
1536 {
1537  if ( !HasChildren() ) {
1538  return;
1539  }
1540 
1541  LinkedList *cgp = GET_FIRST(&Children);
1542  LinkedList *cgp_next;
1543 
1544  while ( cgp && (cgp != END_OF_LIST(&Children)) ) {
1545  cgp_next = GET_NEXT(cgp);
1546  delete cgp;
1547  cgp = cgp_next;
1548  }
1549 }
1550 
1551 Window::Window(const SCP_string &in_caption, int x_coord, int y_coord, int x_width, int y_width, int in_style)
1552 :GUIObject(in_caption, x_coord,y_coord,x_width,y_width,in_style)
1553 {
1554  Caption = in_caption;
1555 
1556  CloseHighlight = false;
1557  HideHighlight = false;
1558 
1559  //Set the type
1560  Type = GT_WINDOW;
1561 
1562  // create a shader for the window
1563  gr_create_shader(&WindowShade, 0, 0, 0, 200);
1564 }
1565 
1566 //*****************************Button*******************************
1567 
1568 Button::Button(const SCP_string &in_caption, int x_coord, int y_coord, void (*in_function)(Button *caller), int x_width, int y_height, int in_style)
1569 :GUIObject(in_caption, x_coord, y_coord, x_width, y_height, in_style)
1570 {
1571  Caption = in_caption;
1572 
1573  function = in_function;
1574 
1575  IsDown = false;
1576 
1577  //Set the type
1578  Type = GT_BUTTON;
1579 }
1580 
1582 {
1583  int w, h;
1586  if (!(Style & GS_NOAUTORESIZEX)) {
1587  Coords[2] = Coords[0] + w;
1588  }
1589  if (!(Style & GS_NOAUTORESIZEY)) {
1590  Coords[3] = Coords[1] + h;
1591  }
1592  } else {
1593  gr_get_string_size(&w, &h, Caption.c_str());
1594  if (!(Style & GS_NOAUTORESIZEX)) {
1595  Coords[2] = Coords[0] + w;
1596  }
1597  if (!(Style & GS_NOAUTORESIZEY)) {
1598  Coords[3] = Coords[1] + h;
1599  }
1600  }
1601 
1602  return OF_TRUE;
1603 }
1604 
1605 void Button::DoDraw(float frametime)
1606 {
1609 
1614  } else if((Style & BS_STICKY) && IsDown && IMG_HANDLE_IS_VALID(GetCIEImageHandle(BCI_BUTTON, CIE_HANDLE_S))) {
1616  }
1617  IMG_DRAW(Coords[0], Coords[1]);
1618  } else {
1619  if (Status == 0) {
1621  } else if (Status & GST_MOUSE_OVER) {
1623  } else {
1625  }
1626  draw_open_rect(Coords[0], Coords[1], Coords[2], Coords[3], GR_RESIZE_NONE);
1627 
1628  int half_x, half_y;
1629  gr_get_string_size(&half_x, &half_y, Caption.c_str());
1630  half_x = Coords[0] +(((Coords[2]-Coords[0]) - half_x) / 2);
1631  half_y = Coords[1] +(((Coords[3]-Coords[1]) - half_y) / 2);
1632  gr_string(half_x, half_y, Caption.c_str(), GR_RESIZE_NONE);
1633  }
1634 }
1635 
1636 int Button::DoMouseDown(float frametime)
1637 {
1638  OwnerSystem->SetActiveObject(this);
1639 
1640  if (!(Style & BS_STICKY)) {
1641  IsDown = true;
1642  }
1643  return OF_TRUE;
1644 }
1645 
1646 int Button::DoMouseUp(float frametime)
1647 {
1648  if (function != NULL) {
1649  function(this);
1650  }
1651 
1652  if (!(Style & BS_STICKY)) {
1653  IsDown = false;
1654  } else {
1655  IsDown = !IsDown;
1656  }
1657 
1658  return OF_TRUE;
1659 }
1660 
1661 int Button::DoMouseOut(float frametime)
1662 {
1663  if (!(Style & BS_STICKY)) {
1664  IsDown = false;
1665  }
1666 
1667  return OF_TRUE;
1668 }
1669 
1670 //*****************************Menu*******************************
1672 :LinkedList()
1673 {
1674  Function = NULL;
1675  Data = 0;
1676  ShowThis = true;
1677  ShowChildren = false;
1678  DeleteData = true;
1679  Parent = NULL;
1680  memset(Coords, 0, sizeof(Coords));
1681 }
1682 
1684 {
1685  LinkedList* cgp = GET_FIRST(&Children);
1686  LinkedList* cgp_next;
1687  for (; cgp != END_OF_LIST(&Children); cgp = cgp_next) {
1688  cgp_next = GET_NEXT(cgp);
1689  delete cgp;
1690  }
1691 }
1692 
1694 {
1695  ClearAllItems();
1696 }
1697 
1698 void Tree::CalcItemsSize(TreeItem *items, int DrawData[4])
1699 {
1700  //DrawData
1701  //0 - indent
1702  //1 - largest width so far
1703  //2 - total height so far
1704  //3 - Are we done?
1705  int w, h;
1706 
1707  int temp_largest = DrawData[1];
1708  for (TreeItem* tip = (TreeItem*)GET_FIRST(items); tip != END_OF_LIST(items); tip = (TreeItem*)GET_NEXT(tip)) {
1709  if (!DrawData[3]) {
1710  gr_get_string_size(&w, &h, tip->Name.c_str());
1711  if ((w + DrawData[0]) > temp_largest) {
1712  temp_largest = w + DrawData[0];
1713  }
1714 
1715  //This should really be moved to where we handle the scrolling code
1716  //I'm not doing that right now. :)
1717  //Or at least this should be called from that
1718  if ( ((DrawData[2] + h) > Coords[3] && (Style & GS_NOAUTORESIZEY)) || (temp_largest > Coords[2] && (Style & GS_NOAUTORESIZEX)) ) {
1719  DrawData[3] = 1;
1720  tip->ShowThis = false;
1721  } else {
1722  tip->ShowThis = true;
1723  }
1724 
1725  //Do we care?
1726  if (tip->ShowThis) {
1727  if ((w + DrawData[0]) > DrawData[1]) {
1728  DrawData[1] = w + DrawData[0];
1729  }
1730 
1731  tip->Coords[0] = Coords[0] + DrawData[0];
1732  tip->Coords[1] = Coords[1] + DrawData[2];
1733  tip->Coords[2] = Coords[0] + DrawData[0] + w;
1734  tip->Coords[3] = Coords[1] + DrawData[2] + h;
1735 
1736  DrawData[2] += h;
1737 
1738  if (NOT_EMPTY(&tip->Children) && tip->ShowChildren) {
1739  //Indent
1740  DrawData[0] += TI_INDENT_PER_LEVEL;
1741  CalcItemsSize((TreeItem*)&tip->Children, DrawData);
1742  DrawData[0] -= TI_INDENT_PER_LEVEL;
1743  }
1744  }
1745  }
1746  if (DrawData[3] || !tip->ShowThis) {
1747  tip->ShowThis = false;
1748  tip->ShowChildren = false;
1749  tip->Coords[0] = tip->Coords[1] = tip->Coords[2] = tip->Coords[3] = -1;
1750  }
1751  }
1752 }
1753 
1755 {
1756  //DrawData
1757  //0 - indent
1758  //1 - largest width so far
1759  //2 - total height so far
1760  //3 - Are we done? 0=no,1=yes
1761  int DrawData[4] = {TI_INITIAL_INDENT,0,TI_INITIAL_INDENT_VERTICAL,0};
1762  CalcItemsSize(&Items, DrawData);
1763 
1764  //CalcItemsSize takes into account limited height/width
1765  if (!(Style & GS_NOAUTORESIZEX)) {
1766  Coords[2] = Coords[0] + DrawData[1] + TI_BORDER_WIDTH;
1767  }
1768  if (!(Style & GS_NOAUTORESIZEY)) {
1769  Coords[3] = Coords[1] + DrawData[2] + TI_BORDER_HEIGHT;
1770  if (Parent != NULL) {
1771  if(DrawData[2] >= Parent->ChildCoords[3]) {
1772  }
1773  }
1774  }
1775 
1776  return OF_TRUE;
1777 }
1778 
1779 Tree::Tree(const SCP_string &in_name, int x_coord, int y_coord, void* in_associateditem, int x_width, int y_height, int in_style)
1780 :GUIObject(in_name, x_coord, y_coord, x_width, y_height, in_style)
1781 {
1782  AssociatedItem = in_associateditem;
1783 
1784  SelectedItem = NULL;
1785  HighlightedItem = NULL;
1786 
1787  //Set the type
1788  Type = GT_MENU;
1789 }
1790 
1791 void Tree::DrawItems(TreeItem *items)
1792 {
1793  for (TreeItem* tip = (TreeItem*)GET_FIRST(items); tip != END_OF_LIST(items); tip = (TreeItem*)GET_NEXT(tip)) {
1794  if (tip->ShowThis) {
1795  if (SelectedItem == tip) {
1797  } else if (HighlightedItem == tip) {
1799  } else {
1801  }
1802 
1803  gr_string(tip->Coords[0], tip->Coords[1], tip->Name.c_str(), GR_RESIZE_NONE);
1804 
1805  if (NOT_EMPTY(&tip->Children) && tip->ShowChildren) {
1806  DrawItems((TreeItem*)&tip->Children);
1807  }
1808  }
1809  }
1810 }
1811 
1812 void Tree::DoDraw(float frametime)
1813 {
1814 
1815  if (EMPTY(&Items)) {
1816  return;
1817  }
1818 
1819  DrawItems(&Items);
1820 
1822  draw_open_rect(Coords[0], Coords[1], Coords[2], Coords[3]);
1823 }
1824 
1825 TreeItem* Tree::HitTest(TreeItem *items)
1826 {
1827  TreeItem *hti = NULL; //Highlighted item
1828 
1829  for (TreeItem *tip = (TreeItem*)GET_FIRST(items);tip != END_OF_LIST(items); tip = (TreeItem*)GET_NEXT(tip)) {
1830  if (OwnerSystem->GetMouseX() >= tip->Coords[0]
1831  && OwnerSystem->GetMouseX() <= tip->Coords[2]
1832  && OwnerSystem->GetMouseY() >= tip->Coords[1]
1833  && OwnerSystem->GetMouseY() <= tip->Coords[3]) {
1834 
1835  hti = tip;
1836  }
1837 
1838  if (hti != NULL) {
1839  return hti;
1840  } else if (NOT_EMPTY(&tip->Children) && tip->ShowChildren) {
1841  hti = HitTest((TreeItem*)&tip->Children);
1842  }
1843 
1844  if (hti != NULL) {
1845  return hti;
1846  }
1847  }
1848  return hti;
1849 }
1850 
1851 int Tree::DoMouseOver(float frametime)
1852 {
1853  HighlightedItem = HitTest(&Items);
1854  return OF_TRUE;
1855 }
1856 
1857 int Tree::DoMouseDown(float frametime)
1858 {
1859  OwnerSystem->SetActiveObject(this);
1860  return OF_TRUE;
1861 }
1862 
1863 int Tree::DoMouseUp(float frametime)
1864 {
1865  OwnerSystem->SetActiveObject(this);
1866 
1867  if (HighlightedItem != NULL) {
1868  SelectedItem = HighlightedItem;
1869  SelectedItem->ShowChildren = !SelectedItem->ShowChildren;
1870  if (NOT_EMPTY(&SelectedItem->Children)) {
1871  OnRefreshSize(); //Unfortunately
1872  }
1873  if (SelectedItem->Function != NULL) {
1874  SelectedItem->Function(this);
1875  }
1876  }
1877 
1878  return OF_TRUE;
1879 }
1880 
1881 void Tree::MoveTreeItems(int dx, int dy, TreeItem *items)
1882 {
1883  for (TreeItem *tip = (TreeItem*)GET_FIRST(items);tip != END_OF_LIST(items); tip = (TreeItem*)GET_NEXT(tip)) {
1884  if (tip->ShowThis) {
1885  tip->Coords[0] += dx;
1886  tip->Coords[1] += dy;
1887  tip->Coords[2] += dx;
1888  tip->Coords[3] += dy;
1889 
1890  if (NOT_EMPTY(&tip->Children) && tip->ShowChildren) {
1891  MoveTreeItems(dx, dy, (TreeItem*)&tip->Children);
1892  }
1893  }
1894  }
1895 }
1896 
1897 void Tree::DoMove(int dx, int dy)
1898 {
1899  MoveTreeItems(dx, dy, &Items);
1900 }
1901 
1902 TreeItem* Tree::AddItem(TreeItem *parent, const SCP_string &in_name, int in_data, bool in_delete_data, void (*in_function)(Tree* caller))
1903 {
1904  TreeItem *ni = new TreeItem;
1905 
1906  ni->Parent = parent;
1907  ni->Name = in_name;
1908  ni->Data = in_data;
1909  ni->DeleteData = in_delete_data;
1910  ni->Function = in_function;
1911 
1912  if (parent != NULL) {
1913  list_append(&parent->Children, ni);
1914  } else {
1915  list_append(&Items, ni);
1916  }
1917 
1918  OnRefreshSize();
1919 
1920  return ni;
1921 }
1922 
1924 {
1925  Items.ClearAllItems();
1926 
1927  LinkedList* cgp = GET_FIRST(&Items);
1928  LinkedList* cgp_next;
1929  for (; cgp != END_OF_LIST(&Items); cgp = cgp_next) {
1930  cgp_next = GET_NEXT(cgp);
1931  delete cgp;
1932  }
1933 }
1934 
1935 //*****************************Text*******************************
1937 {
1938  int width;
1939  if (Style & GS_NOAUTORESIZEX) {
1940  width = Coords[2] - Coords[0];
1941  } else if (Parent != NULL && (Parent->Style & GS_NOAUTORESIZEX)) {
1942  width = Parent->ChildCoords[2] - Coords[0];
1943  } else {
1944  width = gr_screen.clip_right - Coords[0];
1945  }
1946 
1947  NumLines = split_str(Content.c_str(), width, LineLengths, LineStartPoints, MAX_TEXT_LINES);
1948 
1949  //Find the shortest width we need to show all the shortened strings
1950  int longest_width = 0;
1951  int width_test;
1952  for (int i = 0; i < NumLines; i++) {
1953  gr_get_string_size(&width_test, NULL, LineStartPoints[i], LineLengths[i]);
1954  if (width_test > longest_width) {
1955  longest_width = width_test;
1956  }
1957  }
1958  if (longest_width < width) {
1959  width = longest_width;
1960  }
1961 
1962  //Resize along the Y axis
1963  if (Style & GS_NOAUTORESIZEY) {
1964  int new_height = (Coords[3] - Coords[1]) / gr_get_font_height();
1965 
1966  if (new_height < NumLines) {
1967  NumLines = new_height;
1968  }
1969  } else {
1970  Coords[3] = Coords[1] + gr_get_font_height() * NumLines;
1971  if (Parent != NULL) {
1972  if (Coords[3] >= Parent->ChildCoords[3] && (Parent->Style & GS_NOAUTORESIZEY)) {
1973  Coords[3] = Coords[1] + (Parent->ChildCoords[3] - Coords[1]);
1974  NumLines = (Coords[3] - Coords[1]) / gr_get_font_height();
1975  }
1976  }
1977  }
1978 
1979  if (!(Style & GS_NOAUTORESIZEX)) {
1980  Coords[2] = Coords[0] + width;
1981  }
1982 
1983  if (Style & T_EDITTABLE) {
1984  ChildCoords[0] = Coords[0] + 1;
1985  ChildCoords[1] = Coords[1] + 1;
1986  ChildCoords[2] = Coords[2] - 1;
1987  ChildCoords[3] = Coords[3] - 1;
1988  } else {
1989  ChildCoords[0] = Coords[0];
1990  ChildCoords[1] = Coords[1];
1991  ChildCoords[2] = Coords[2];
1992  ChildCoords[3] = Coords[3];
1993  }
1994 
1995  //Tell the parent to recalculate its size too
1996  return OF_TRUE;
1997 }
1998 
1999 int Text::DoMouseDown(float frametime)
2000 {
2001  //Make this the active object
2002  if (Style & T_EDITTABLE) {
2003  OwnerSystem->SetActiveObject(this);
2004  //For now, always set the cursor pos to the end
2005  CursorPos = Content.size();
2006  return OF_TRUE;
2007  } else {
2008  return OF_FALSE;
2009  }
2010 }
2011 
2012 void Text::DoDraw(float frametime)
2013 {
2014  if (OwnerSystem->GetActiveObject() != this) {
2016  } else {
2018  }
2019 
2020  if (Style & T_EDITTABLE) {
2021  draw_open_rect(Coords[0], Coords[1], Coords[2], Coords[3]);
2022  }
2023 
2024  //Don't draw anything. Besides, it crashes
2025  if (!Content.length()) {
2026  return;
2027  }
2028 
2029  int font_height = gr_get_font_height();
2030 
2031  for (int i = 0; i < NumLines; i++) {
2032  gr_string(ChildCoords[0], ChildCoords[1] + (i*font_height), Content.substr(LineStartPoints[i] - Content.c_str(), LineLengths[i]).c_str(), GR_RESIZE_NONE);
2033  }
2034 }
2035 
2036 extern int keypad_to_ascii(int c);
2037 
2038 int Text::DoKeyPress(float frametime)
2039 {
2040  if (!(Style & T_EDITTABLE)) {
2041  return OF_FALSE;
2042  }
2043 
2044  switch(OwnerSystem->GetKeyPressed()) {
2045  case KEY_BACKSP:
2046  Content = Content.substr(0, Content.length() - 1);
2047  break;
2048 
2049  case KEY_ENTER:
2050  if (SaveType & T_ST_ONENTER) {
2051  if (Save()) {
2052  OwnerSystem->SetActiveObject(Parent);
2053  } else {
2054  Load();
2055  }
2056  }
2057  break;
2058 
2059  case KEY_ESC:
2060  Load();
2061  OwnerSystem->SetActiveObject(Parent);
2062  break;
2063 
2064  default: {
2065  //Figure out what key, exactly, we have
2066  int symbol = keypad_to_ascii(OwnerSystem->GetKeyPressed());
2067  if (symbol == -1) {
2068  symbol = key_to_ascii(OwnerSystem->GetKeyPressed());
2069  }
2070  //Is it ok with us?
2071  if (iscntrl(symbol)) {
2072  return OF_FALSE; //Guess not
2073  } else if (SaveType & T_ST_INT) {
2074  if (!isdigit(symbol) && symbol != '-') {
2075  return OF_FALSE;
2076  }
2077  } else if (SaveType & T_ST_FLOAT) {
2078  if (!isdigit(symbol) && symbol != '.' && symbol != '-') {
2079  return OF_FALSE;
2080  }
2081  } else if (SaveType & T_ST_UBYTE) {
2082  if (!isdigit(symbol)) {
2083  return OF_FALSE;
2084  }
2085  } else if (!isalnum(symbol) && symbol != ' ') {
2086  return OF_FALSE;
2087  }
2088 
2089  //We can add the letter to the box. Cheers.
2090  Content += char(symbol);
2091  if (SaveType & T_ST_REALTIME) {
2092  Save();
2093  }
2094  }
2095  }
2096  OnRefreshSize();
2097  return OF_TRUE;
2098 }
2099 
2100 Text::Text(const SCP_string &in_name, const SCP_string &in_content, int x_coord, int y_coord, int x_width, int y_height, int in_style)
2101 :GUIObject(in_name, x_coord, y_coord, x_width, y_height, in_style)
2102 {
2103  Content = in_content;
2104  NumLines = 0;
2105  SaveType = T_ST_NONE;
2106  CursorPos = -1; //Not editing
2107  Type = GT_TEXT;
2108 }
2109 
2110 void Text::SetText(const SCP_string &in_content)
2111 {
2112  Content = in_content;
2113  OnRefreshSize();
2114 }
2115 
2116 void Text::SetText(int the_int)
2117 {
2118  char buf[33];
2119  sprintf(buf, "%d", the_int);
2120  Content = buf;
2121  OnRefreshSize();
2122 }
2123 
2124 void Text::SetText(float the_float)
2125 {
2126  char buf[32];
2127  sprintf(buf, "%f", the_float);
2128  Content = buf;
2129  OnRefreshSize();
2130 }
2131 
2132 void Text::AddLine(const SCP_string &in_line)
2133 {
2134  Content += in_line;
2135  OnRefreshSize();
2136 }
2137 
2138 void Text::SetSaveLoc(int *int_ptr, int save_method, int max_value, int min_value)
2139 {
2140  Assert(int_ptr != NULL); //Naughty.
2141  Assert(min_value < max_value); //Mmm-hmm.
2142 
2143  SaveType = T_ST_INT;
2144  if (save_method == T_ST_CLOSE) {
2145  SaveType |= T_ST_CLOSE;
2146  } else if (save_method == T_ST_REALTIME) {
2147  SaveType |= T_ST_REALTIME;
2148  } else if (save_method == T_ST_ONENTER) {
2149  SaveType |= T_ST_ONENTER;
2150  }
2151 
2152  iSavePointer = int_ptr;
2153  SaveMax = max_value;
2154  SaveMin = min_value;
2155 }
2156 
2157 void Text::SetSaveLoc(short int *sint_ptr, int save_method, short int max_value, short int min_value)
2158 {
2159  Assert(sint_ptr != NULL); //Naughty.
2160  Assert(min_value < max_value); //Mmm-hmm.
2161 
2162  SaveType = T_ST_SINT;
2163  if (save_method == T_ST_CLOSE) {
2164  SaveType |= T_ST_CLOSE;
2165  } else if (save_method == T_ST_REALTIME) {
2166  SaveType |= T_ST_REALTIME;
2167  } else if (save_method == T_ST_ONENTER) {
2168  SaveType |= T_ST_ONENTER;
2169  }
2170 
2171  siSavePointer = sint_ptr;
2172  SaveMax = max_value;
2173  SaveMin = min_value;
2174 }
2175 
2176 void Text::SetSaveLoc(float *ptr, int save_method, float max_value, float min_value)
2177 {
2178  Assert(ptr != NULL); //Naughty.
2179  Assert(min_value < max_value); //Causes problems with floats
2180 
2181  SaveType = T_ST_FLOAT;
2182  if (save_method == T_ST_CLOSE) {
2183  SaveType |= T_ST_CLOSE;
2184  } else if (save_method == T_ST_REALTIME) {
2185  SaveType |= T_ST_REALTIME;
2186  } else if (save_method == T_ST_ONENTER) {
2187  SaveType |= T_ST_ONENTER;
2188  }
2189 
2190  flSavePointer = ptr;
2191  flSaveMax = max_value;
2192  flSaveMin = min_value;
2193 }
2194 
2195 void Text::SetSaveLoc(char *ptr, int save_method, uint max_length, uint min_length)
2196 {
2197  Assert(ptr != NULL); //Naughty.
2198 
2199  SaveType = T_ST_CHAR;
2200  if (save_method == T_ST_CLOSE) {
2201  SaveType |= T_ST_CLOSE;
2202  } else if (save_method == T_ST_REALTIME) {
2203  SaveType |= T_ST_REALTIME;
2204  } else if (save_method == T_ST_ONENTER) {
2205  SaveType |= T_ST_ONENTER;
2206  }
2207 
2208  chSavePointer = ptr;
2209  uSaveMax = max_length;
2210  uSaveMin = min_length;
2211 }
2212 
2213 void Text::SetSaveStringAlloc(char **ptr, int save_method, int mem_flags, uint max_length, uint min_length)
2214 {
2215  Assert(ptr != NULL); //Naughty.
2216 
2217  if (mem_flags == T_ST_NEW) {
2218  SaveType = T_ST_NEW;
2219  } else if (mem_flags == T_ST_MALLOC) {
2220  SaveType = T_ST_MALLOC;
2221  } else {
2222  return; //This MUST use some sort of mem allocation
2223  }
2224 
2225  SaveType |= T_ST_CHAR;
2226  if (save_method == T_ST_CLOSE) {
2227  SaveType |= T_ST_CLOSE;
2228  } else if (save_method == T_ST_REALTIME) {
2229  SaveType |= T_ST_REALTIME;
2230  } else if (save_method == T_ST_ONENTER) {
2231  SaveType |= T_ST_ONENTER;
2232  }
2233 
2234  chpSavePointer = ptr;
2235  uSaveMax = max_length;
2236  uSaveMin = min_length;
2237 }
2238 
2239 void Text::SetSaveLoc(ubyte *ptr, int save_method, int max_value, int min_value)
2240 {
2241  Assert(ptr != NULL); //Naughty.
2242  Assert(min_value < max_value); //Mmm-hmm.
2243 
2244  SaveType = T_ST_UBYTE;
2245  if (save_method == T_ST_CLOSE) {
2246  SaveType |= T_ST_CLOSE;
2247  } else if (save_method == T_ST_REALTIME) {
2248  SaveType |= T_ST_REALTIME;
2249  } else if (save_method == T_ST_ONENTER) {
2250  SaveType |= T_ST_ONENTER;
2251  }
2252 
2253  ubSavePointer = ptr;
2254  SaveMax = max_value;
2255  SaveMin = min_value;
2256 }
2257 
2259 {
2260  if (SaveType == T_ST_NONE) {
2261  return false;
2262  }
2263 
2264  if (SaveType & T_ST_INT) {
2265  int the_int = atoi(Content.c_str());
2266  if (the_int <= SaveMax && the_int >= SaveMin) {
2267  *iSavePointer = the_int;
2268  return true;
2269  }
2270  } else if (SaveType & T_ST_SINT) {
2271  short the_sint = (short)atoi(Content.c_str());
2272  if (the_sint <= SaveMax && the_sint >= SaveMin) {
2273  *siSavePointer = the_sint;
2274  return true;
2275  }
2276  } else if (SaveType & T_ST_FLOAT) {
2277  float the_float = (float)atof(Content.c_str());
2278  if (the_float <= flSaveMax && the_float >= flSaveMin) {
2279  *flSavePointer = the_float;
2280  return true;
2281  }
2282  } else if (SaveType & T_ST_CHAR) {
2283  size_t len = Content.length();
2284  if (SaveType & T_ST_NEW && len < uSaveMax) {
2285  if (*chpSavePointer != NULL) {
2286  delete[] *chpSavePointer;
2287  }
2288 
2289  *chpSavePointer = new char[len + 1];
2290  strcpy(*chpSavePointer, Content.c_str());
2291  return true;
2292  } else if (SaveType & T_ST_MALLOC && len < uSaveMax) {
2293  if (*chpSavePointer != NULL) {
2295  }
2296 
2297  *chpSavePointer = (char*)vm_malloc(sizeof(char) * (len + 1));
2298  strcpy(*chpSavePointer, Content.c_str());
2299  return true;
2300  } else if (len < uSaveMax) {
2301  strcpy(chSavePointer, Content.c_str());
2302  return true;
2303  }
2304 
2305  } else if (SaveType & T_ST_UBYTE) {
2306  int the_int = atoi(Content.c_str());
2307  if (the_int <= SaveMax && the_int >= SaveMin) {
2308  *ubSavePointer = (ubyte)the_int;
2309  return true;
2310  }
2311  }
2312 
2313  return false;
2314 }
2315 
2317 {
2318  if (SaveType == T_ST_NONE) {
2319  return;
2320  }
2321 
2322  if (SaveType & T_ST_INT) {
2324  } else if (SaveType & T_ST_FLOAT) {
2326  } else if ((SaveType & T_ST_CHAR) && (SaveType & (T_ST_MALLOC | T_ST_NEW))) {
2328  } else if (SaveType & T_ST_CHAR) {
2330  } else if (SaveType & T_ST_UBYTE) {
2332  } else {
2333  Warning(LOCATION, "Unknown type (or no type) given in Text::Load() - nothing happened.");
2334  }
2335 }
2336 
2337 //*****************************Checkbox*******************************
2338 
2339 Checkbox::Checkbox(const SCP_string &in_label, int x_coord, int y_coord, void (*in_function)(Checkbox *caller), int x_width, int y_height, int in_style)
2340 :GUIObject(in_label, x_coord, y_coord, x_width, y_height, in_style)
2341 {
2342  Label = in_label;
2343 
2344  function = in_function;
2345 
2346  IsChecked = false;
2347  HighlightStatus = 0;
2348  FlagPtr = NULL;
2349  BoolFlagPtr = NULL;
2350 
2351  //Set the type
2352  Type = GT_CHECKBOX;
2353 }
2354 
2356 {
2357  int w, h,tw,th;
2358  gr_get_string_size(&w, &h, Label.c_str());
2359  tw = w;
2360  th = h;
2361 
2362  gr_get_string_size(&w, &h, "X");
2363  tw += w;
2364  th += h + CB_TEXTCHECKDIST; //Spacing b/t 'em
2365 
2366  CheckCoords[0] = Coords[0];
2367  CheckCoords[1] = Coords[1];
2368  CheckCoords[2] = Coords[0] + w;
2369  CheckCoords[3] = Coords[1] + h;
2370 
2371  if (!(Style & GS_NOAUTORESIZEX)) {
2372  Coords[2] = Coords[0] + tw;
2373  }
2374 
2375  if (!(Style & GS_NOAUTORESIZEY)) {
2376  Coords[3] = Coords[1] + th;
2377  }
2378 
2379  return OF_TRUE;
2380 }
2381 
2382 void Checkbox::DoMove(int dx, int dy)
2383 {
2384  CheckCoords[0] += dx;
2385  CheckCoords[2] += dx;
2386  CheckCoords[1] += dy;
2387  CheckCoords[3] += dy;
2388 }
2389 
2390 void Checkbox::DoDraw(float frametime)
2391 {
2392  if (HighlightStatus == 1) {
2394  } else if (HighlightStatus == 2) {
2396  } else {
2398  }
2399 
2400  draw_open_rect(CheckCoords[0], CheckCoords[1], CheckCoords[2], CheckCoords[3], GR_RESIZE_NONE);
2401 
2402  if ( (IsChecked && ((FlagPtr == NULL) && (BoolFlagPtr == NULL)))
2403  || ((FlagPtr != NULL) && ((*FlagPtr) & Flag))
2404  || ((BoolFlagPtr != NULL) && (*BoolFlagPtr)) ) {
2405  gr_string(CheckCoords[0], CheckCoords[1], "X", GR_RESIZE_NONE);
2406  }
2407 
2409  gr_string(CheckCoords[2] + CB_TEXTCHECKDIST, CheckCoords[1], Label.c_str(), GR_RESIZE_NONE);
2410 }
2411 
2412 int Checkbox::DoMouseOver(float frametime)
2413 {
2414  if ( (OwnerSystem->GetMouseX() >= CheckCoords[0])
2415  && (OwnerSystem->GetMouseX() <= CheckCoords[2])
2416  && (OwnerSystem->GetMouseY() >= CheckCoords[1])
2417  && (OwnerSystem->GetMouseY() <= CheckCoords[3]) ) {
2418  HighlightStatus = 1;
2419  }
2420 
2421  return OF_TRUE;
2422 }
2423 
2424 int Checkbox::DoMouseDown(float frametime)
2425 {
2426  OwnerSystem->SetActiveObject(this);
2427 
2428  if ( (OwnerSystem->GetMouseX() >= CheckCoords[0])
2429  && (OwnerSystem->GetMouseX() <= CheckCoords[2])
2430  && (OwnerSystem->GetMouseY() >= CheckCoords[1])
2431  && (OwnerSystem->GetMouseY() <= CheckCoords[3]) ) {
2432  HighlightStatus = 2;
2433  }
2434 
2435  return OF_TRUE;
2436 }
2437 
2438 int Checkbox::DoMouseUp(float frametime)
2439 {
2440  if ( (OwnerSystem->GetMouseX() >= CheckCoords[0])
2441  && (OwnerSystem->GetMouseX() <= CheckCoords[2])
2442  && (OwnerSystem->GetMouseY() >= CheckCoords[1])
2443  && (OwnerSystem->GetMouseY() <= CheckCoords[3]) ) {
2444  HighlightStatus = 1;
2445 
2446  if (function != NULL) {
2447  function(this);
2448  }
2449 
2450  if (FlagPtr != NULL) {
2451  if ( !(*FlagPtr & Flag) ) {
2452  *FlagPtr |= Flag;
2453  IsChecked = true;
2454  } else {
2455  *FlagPtr &= ~Flag;
2456  IsChecked = false;
2457  }
2458  } else if (BoolFlagPtr != NULL) {
2459  *BoolFlagPtr = !(*BoolFlagPtr);
2460  IsChecked = *BoolFlagPtr;
2461  } else {
2462  IsChecked = !IsChecked;
2463  }
2464  }
2465 
2466  return OF_TRUE;
2467 }
2468 
2469 int Checkbox::DoMouseOut(float frametime)
2470 {
2471  HighlightStatus = 0;
2472 
2473  return OF_TRUE;
2474 }
2475 
2476 //*****************************ImageAnim*******************************
2477 ImageAnim::ImageAnim(const SCP_string &in_name, const SCP_string &in_imagename, int x_coord, int y_coord, int x_width, int y_width, int in_style)
2478 :GUIObject(in_name, x_coord, y_coord, x_width, y_width, in_style)
2479 {
2480  //Load the image
2481  IsSet = false;
2482  ImageHandle = -1;
2483  ImageFlags = 0;
2484  TotalFrames = 0;
2485  FPS = 0;
2486  Stop();
2487 
2488  Type = GT_IMAGEANIM;
2489 }
2490 
2491 void ImageAnim::DoDraw(float frametime)
2492 {
2493  //Do nothing if nothing to draw
2494  if (ImageHandle == -1) {
2495  return;
2496  }
2497 
2498  if (PlayType != PT_STOPPED) {
2499  if (PlayType == PT_PLAYING) {
2500  ElapsedTime += frametime;
2501  } else if (PlayType == PT_PLAYING_REVERSE) {
2502  ElapsedTime -= frametime;
2503  }
2504 
2505  Progress = ElapsedTime/TotalTime;
2506  }
2507 
2508  int CurrentFrame = fl2i(Progress * TotalFrames);
2509  if (Progress > 1.0f) {
2510  if (ImageFlags & IF_BOUNCE) {
2511  Progress = 1.0f;
2512  CurrentFrame = TotalFrames;
2513  PlayType = PT_PLAYING_REVERSE;
2514  } else if (ImageFlags & IF_REPEAT) {
2515  Progress = 0.0f;
2516  CurrentFrame = 0;
2517  PlayType = PT_PLAYING;
2518  } else {
2519  Progress = 1.0f;
2520  CurrentFrame = TotalFrames;
2521  PlayType = PT_STOPPED;
2522  }
2523  } else if (Progress < 1.0f) {
2524  if (ImageFlags & IF_BOUNCE) {
2525  Progress = 0.0f;
2526  CurrentFrame = 0;
2527  PlayType = PT_PLAYING;
2528  } else if (ImageFlags & IF_REPEAT && ImageFlags & (IF_REVERSED)) {
2529  Progress = 1.0f;
2530  CurrentFrame = TotalFrames;
2531  PlayType = PT_PLAYING_REVERSE;
2532  } else {
2533  Progress = 0.0f;
2534  CurrentFrame = 0;
2535  PlayType = PT_STOPPED;
2536  }
2537  }
2538 
2539  //IMG_SET_FRAME(ImageHandle, CurrentFrame);
2540  gr_set_bitmap( ImageHandle + CurrentFrame, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, 1-((Progress - (float)(CurrentFrame / TotalFrames)) / (float)(TotalFrames/CurrentFrame)));
2541  IMG_DRAW(Coords[0], Coords[1]);
2542  gr_set_bitmap( ImageHandle + CurrentFrame + 1, GR_ALPHABLEND_FILTER, GR_BITBLT_MODE_NORMAL, ((Progress - (float)(CurrentFrame / TotalFrames)) / (float)(TotalFrames/CurrentFrame)));
2543  IMG_DRAW(Coords[0], Coords[1]);
2544 }
2545 
2547 {
2548  //TODO: Fill this in
2549  return OF_FALSE;
2550 }
2551 
2552 void ImageAnim::SetImage(const SCP_string &in_imagename)
2553 {
2554  if (in_imagename.size()) {
2555  ImageHandle = IMG_LOAD_ANIM(in_imagename.c_str(), &TotalFrames, &FPS);
2556  TotalTime = (float) (TotalFrames/FPS);
2557  if (IMG_HANDLE_IS_INVALID(ImageHandle)) {
2558  ImageHandle = IMG_LOAD(in_imagename.c_str());
2559  if (IMG_HANDLE_IS_VALID(ImageHandle)) {
2560  TotalFrames = 1;
2561  } else {
2562  TotalFrames = 0;
2563  }
2564  FPS = 0;
2565  TotalTime = 0.0f;
2566  }
2567  }
2568 
2569  //This takes care of setting up the play-flags
2570  Stop();
2571 
2572  IsSet = true;
2573  OnRefreshSize();
2574 }
2575 
2576 void ImageAnim::Play(bool in_isreversed)
2577 {
2578  if (ImageFlags & IF_REVERSED) {
2579  PlayType = PT_PLAYING;
2580  }
2581 }
2582 
2584 {
2585  if (PlayType == PT_PLAYING) {
2586  PlayType = PT_STOPPED;
2587  } else {
2588  PlayType = PT_STOPPED_REVERSE;
2589  }
2590 }
2591 
2593 {
2594  if (ImageFlags & IF_REVERSED) {
2595  PlayType = PT_STOPPED_REVERSE;
2596  } else {
2597  PlayType = PT_STOPPED;
2598  }
2599 
2600  Progress = 0.0f;
2601  ElapsedTime = 0.0f;
2602 }
int OnFrame(float frametime, int *unused_queue)
Definition: wmcgui.cpp:874
#define GST_KEYBOARD_ALT
Definition: wmcgui.h:191
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
#define CIE_HANDLE_TL
Definition: wmcgui.h:86
#define gr_zbuffer_set
Definition: 2d.h:817
#define CIE_HANDLE_D
Definition: wmcgui.h:83
int DoRefreshSize()
Definition: wmcgui.cpp:1936
void SetSaveLoc(int *ptr, int save_method, int max_value=INT_MAX, int min_value=INT_MIN)
Definition: wmcgui.cpp:2138
Definition: wmcgui.h:139
int i
Definition: multi_pxo.cpp:466
#define vm_free(ptr)
Definition: pstypes.h:548
int GetMouseY()
Definition: wmcgui.h:369
void DeleteChildren(GUIObject *exception=NULL)
Definition: wmcgui.cpp:770
int DoMouseDown(float frametime)
Definition: wmcgui.cpp:1311
#define CIE_GC_H_SET
Definition: wmcgui.h:106
GUIScreen * PushScreen(GUIScreen *csp)
Definition: wmcgui.cpp:562
struct LinkedList * prev
Definition: wmcgui.h:46
~GUIScreen()
Definition: wmcgui.cpp:352
#define gr_clear
Definition: 2d.h:749
void parse_advance(int s)
Definition: parselo.h:243
#define W_BORDERHEIGHT
Definition: wmcgui.h:381
int DoKeyPress(float frametime)
Definition: wmcgui.cpp:2038
int DoMouseDown(float frametime)
Definition: wmcgui.cpp:1636
virtual int DoKeyPress(float frametime)
Definition: wmcgui.h:267
int check_for_string(const char *pstr)
Definition: parselo.cpp:517
#define CIE_GC_Y_SET
Definition: wmcgui.h:104
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
void gr_flip()
Definition: 2d.cpp:2113
#define GST_MOUSE_LEFT_BUTTON
Definition: wmcgui.h:186
void AddLine(const SCP_string &in_line)
Definition: wmcgui.cpp:2132
void OnRefreshSize()
Definition: wmcgui.h:252
void gr_opengl_shade(int x, int y, int w, int h, int resize_mode)
#define MOUSE_LEFT_BUTTON
Definition: mouse.h:43
#define CIE_HANDLE_ML
Definition: wmcgui.h:89
int GetStatus()
Definition: wmcgui.h:370
int GetCIECoords(int id, int *x, int *y)
Definition: wmcgui.cpp:972
int DoMouseDown(float frametime)
Definition: wmcgui.cpp:2424
int keypad_to_ascii(int c)
Definition: inputbox.cpp:31
#define T_ST_INT
Definition: wmcgui.h:545
Checkbox(const SCP_string &in_label, int x_coord, int y_coord, void(*in_function)(Checkbox *caller)=NULL, int x_width=-1, int y_height=DEFAULT_BUTTON_HEIGHT, int in_style=0)
Definition: wmcgui.cpp:2339
#define GS_NOAUTORESIZEY
Definition: wmcgui.h:201
int SaveMin
Definition: wmcgui.h:582
Tree(const SCP_string &in_name, int x_coord, int y_coord, void *in_associateditem=NULL, int x_width=-1, int y_width=-1, int in_style=0)
Definition: wmcgui.cpp:1779
#define WCI_CLOSE
Definition: wmcgui.h:391
int SaveMax
Definition: wmcgui.h:581
uint uSaveMax
Definition: wmcgui.h:581
#define PT_STOPPED_REVERSE
Definition: wmcgui.h:673
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
bitmap_2d_list screen_rect
Definition: tmapper.h:127
#define mprintf(args)
Definition: pstypes.h:238
void Parse(char *tag, int in_type)
Definition: wmcgui.cpp:175
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
#define MOUSE_MIDDLE_BUTTON
Definition: mouse.h:45
int OnFrame(float frametime, bool doevents, bool clearandflip)
Definition: wmcgui.cpp:601
#define GT_TEXT
Definition: wmcgui.h:178
#define GST_KEYBOARD_STATUS
Definition: wmcgui.h:197
#define CIE_GC_X_SET
Definition: wmcgui.h:103
#define T_ST_ONENTER
Definition: wmcgui.h:552
#define TI_BORDER_HEIGHT
Definition: wmcgui.h:472
GLclampf f
Definition: Glext.h:7097
GUIObject * Add(GUIObject *new_gauge)
Definition: wmcgui.cpp:424
#define GR_ZBUFF_NONE
Definition: 2d.h:672
#define BCI_NUM_ENTRIES
Definition: wmcgui.h:447
~TreeItem()
Definition: wmcgui.cpp:1693
#define CB_TEXTCHECKDIST
Definition: wmcgui.h:610
TreeItem()
Definition: wmcgui.cpp:1671
int DoMouseUp(float frametime)
Definition: wmcgui.cpp:1646
virtual int DoMouseOver(float frametime)
Definition: wmcgui.h:262
#define GT_NONE
Definition: wmcgui.h:174
GUIObject * GetGraspedObject()
Definition: wmcgui.h:373
#define PT_STOPPED
Definition: wmcgui.h:670
int mouse_get_pos(int *xpos, int *ypos)
Definition: mouse.cpp:512
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
bool Parse()
Definition: wmcgui.cpp:119
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
#define CIE_GC_NONE_SET
Definition: wmcgui.h:102
#define CIE_NUM_HANDLES
Definition: wmcgui.h:109
#define PT_PLAYING
Definition: wmcgui.h:671
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
int key_to_ascii(int keycode)
Definition: key.cpp:336
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
#define GR_RESIZE_NONE
Definition: 2d.h:681
virtual void DoMove(int dx, int dy)
Definition: wmcgui.h:261
#define GS_NOAUTORESIZEX
Definition: wmcgui.h:200
GUISystem GUI_system
Definition: wmcgui.cpp:21
void SetGraspedObject(GUIObject *cgp, int button)
Definition: wmcgui.cpp:691
int GetMouseX()
Definition: wmcgui.h:368
ObjectClassInfoEntry()
Definition: wmcgui.h:151
void SetCIPointer()
Definition: wmcgui.cpp:1048
GLint GLsizei width
Definition: Gl.h:1505
#define CIE_HANDLE_C
Definition: wmcgui.h:81
char * chSavePointer
Definition: wmcgui.h:578
#define GST_MOUSE_PRESS
Definition: wmcgui.h:195
int DoMouseOver(float frametime)
Definition: wmcgui.cpp:1851
int DoMouseUp(float frametime)
Definition: wmcgui.cpp:2438
void ClearAllItems()
Definition: wmcgui.cpp:1683
int mouse_down(int btn)
Definition: mouse.cpp:315
void SetActiveObject(GUIObject *cgp)
Definition: wmcgui.cpp:675
#define GST_KEYBOARD_SHIFT
Definition: wmcgui.h:192
void DoDraw(float frametime)
Definition: wmcgui.cpp:2390
int DoMouseDown(float frametime)
Definition: wmcgui.cpp:1999
#define GST_MOUSE_STATUS
Definition: wmcgui.h:196
int DoRefreshSize()
Definition: wmcgui.cpp:2546
char ** chpSavePointer
Definition: wmcgui.h:579
#define GR_ALPHABLEND_FILTER
Definition: 2d.h:349
virtual int DoMouseUp(float frametime)
Definition: wmcgui.h:264
#define IF_REPEAT
Definition: wmcgui.h:677
GUIScreen(const SCP_string &in_Name="")
Definition: wmcgui.cpp:332
unsigned int uint
Definition: pstypes.h:64
#define CIE_IMAGE_NMCSD
Definition: wmcgui.h:73
Window(const SCP_string &in_caption, int x_coord, int y_coord, int x_width=-1, int y_height=-1, int in_style=0)
Definition: wmcgui.cpp:1551
#define CIE_NONE
Definition: wmcgui.h:71
#define T_ST_NONE
Definition: wmcgui.h:544
GUIObject(const SCP_string &in_Name="", int x_coord=0, int y_coord=0, int x_width=-1, int y_height=-1, int in_style=0)
Definition: wmcgui.cpp:715
#define W_BORDERWIDTH
Definition: wmcgui.h:380
#define T_ST_REALTIME
Definition: wmcgui.h:554
#define CIE_HANDLE_BR
Definition: wmcgui.h:93
#define OF_TRUE
Definition: wmcgui.h:206
#define WCI_HIDE
Definition: wmcgui.h:390
#define IMG_INFO(ha, w, h)
Definition: wmcgui.h:34
void Play(bool in_isreversed)
Definition: wmcgui.cpp:2576
char * filename
void draw_open_rect(int x1, int y1, int x2, int y2, int resize_mode=GR_RESIZE_NONE)
Definition: wmcgui.cpp:1405
#define IMG_UNLOAD(a)
Definition: wmcgui.h:30
#define BS_STICKY
Definition: wmcgui.h:443
#define T_EDITTABLE
Definition: wmcgui.h:541
int DoMouseOver(float frametime)
Definition: wmcgui.cpp:2412
#define KEY_SHIFTED
Definition: key.h:62
void Stop()
Definition: wmcgui.cpp:2592
void stuff_string(char *outstr, int type, int len, char *terminators)
Definition: parselo.cpp:1189
#define T_ST_MALLOC
Definition: wmcgui.h:558
bool Parse()
Definition: wmcgui.cpp:48
#define WCI_BORDER
Definition: wmcgui.h:388
#define PT_PLAYING_REVERSE
Definition: wmcgui.h:672
#define w(p)
Definition: modelsinc.h:68
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define OF_FALSE
Definition: wmcgui.h:207
#define T_ST_CLOSE
Definition: wmcgui.h:553
#define IMG_HANDLE_SET_FRAME(dh, h, f)
Definition: wmcgui.h:27
#define KEY_ENTER
Definition: key.h:125
#define IMG_HANDLE_SET_INVALID(h)
Definition: wmcgui.h:24
#define GST_MOUSE_RIGHT_BUTTON
Definition: wmcgui.h:187
Definition: wmcgui.h:509
int required_string(const char *pstr)
Definition: parselo.cpp:468
void OnMove(int dx, int dy)
Definition: wmcgui.cpp:954
int GetObjectCoords(int *x, int *y, int *w, int *h)
Definition: wmcgui.cpp:309
#define GSOF_SOMETHINGPRESSED
Definition: wmcgui.h:300
void ClearItems()
Definition: wmcgui.cpp:1923
int split_str(const char *src, int max_pixel_w, int *n_chars, const char **p_str, int max_lines, char ignore_char)
Definition: parselo.cpp:3412
int optional_string(const char *pstr)
Definition: parselo.cpp:539
#define CIE_HANDLE_M
Definition: wmcgui.h:80
Definition: wmcgui.h:110
#define CIE_HANDLE_TR
Definition: wmcgui.h:88
int DoMouseOver(float frametime)
Definition: wmcgui.cpp:1288
uint uSaveMin
Definition: wmcgui.h:582
int DoRefreshSize()
Definition: wmcgui.cpp:1754
GLenum GLuint id
Definition: Glext.h:5156
#define IMG_SET(h)
Definition: wmcgui.h:31
void read_file_text(const char *filename, int mode, char *processed_text, char *raw_text)
Definition: parselo.cpp:1995
#define GT_CHECKBOX
Definition: wmcgui.h:179
void DoDraw(float frametime)
Definition: wmcgui.cpp:2491
void SetText(const SCP_string &in_content)
Definition: wmcgui.cpp:2110
#define KEY_BACKSP
Definition: key.h:126
#define WS_NOTITLEBAR
Definition: wmcgui.h:383
#define GS_INTERNALCHILD
Definition: wmcgui.h:203
int clip_bottom
Definition: 2d.h:388
SCP_string GetName()
Definition: wmcgui.h:169
int OnFrame(float frametime, bool doevents)
Definition: wmcgui.cpp:473
#define IF_REVERSED
Definition: wmcgui.h:678
int clip_top
Definition: 2d.h:388
#define IMG_LOAD_ANIM(f, n, fps)
Definition: wmcgui.h:29
void DoMove(int dx, int dy)
Definition: wmcgui.cpp:1371
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
#define CIE_HANDLE_N
Definition: wmcgui.h:79
unsigned char ubyte
Definition: pstypes.h:62
TreeItem * AddItem(TreeItem *parent, const SCP_string &in_name, int in_data=0, bool in_delete_data=true, void(*in_function)(Tree *caller)=NULL)
Definition: wmcgui.cpp:1902
void SetSaveStringAlloc(char **ptr, int save_method, int mem_flags, uint max_len=UINT_MAX, uint min_len=0)
Definition: wmcgui.cpp:2213
bool HasChildren()
Definition: wmcgui.h:429
GUIObject * AddChild(GUIObject *cgp)
Definition: wmcgui.cpp:819
#define CIE_HANDLE_BM
Definition: wmcgui.h:92
Button(const SCP_string &in_caption, int x_coord, int y_coord, void(*in_function)(Button *caller)=NULL, int x_width=-1, int y_height=-1, int in_style=0)
Definition: wmcgui.cpp:1568
int * iSavePointer
Definition: wmcgui.h:575
void OnDraw(float frametime)
Definition: wmcgui.cpp:862
#define TI_BORDER_WIDTH
Definition: wmcgui.h:471
#define CIE_GC_W_SET
Definition: wmcgui.h:105
#define CIE_HANDLE_BL
Definition: wmcgui.h:91
ImageAnim(const SCP_string &in_name, const SCP_string &in_imagename, int x_coord, int y_coord, int x_width=-1, int y_width=-1, int in_style=0)
Definition: wmcgui.cpp:2477
float * flSavePointer
Definition: wmcgui.h:577
int GetCoords(int *x, int *y)
Definition: wmcgui.cpp:284
#define vm_malloc(size)
Definition: pstypes.h:547
#define CIE_HANDLE_TM
Definition: wmcgui.h:87
void reset_parse(char *text)
Definition: parselo.cpp:3305
color Color_text_active
Definition: alphacolors.cpp:27
__inline void gr_line(int x1, int y1, int x2, int y2, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:791
int DoMouseOut(float frametime)
Definition: wmcgui.cpp:2469
int GetCoords(int id, int *x, int *y)
Definition: wmcgui.cpp:304
int DoMouseOut(float frametime)
Definition: wmcgui.cpp:1364
ScreenClassInfoEntry * GetClassInfo()
Definition: wmcgui.h:358
void Pause()
Definition: wmcgui.cpp:2583
int stuff_int_list(int *ilp, int max_ints, int lookup_type)
Definition: parselo.cpp:2782
#define T_ST_SINT
Definition: wmcgui.h:546
#define WCI_NUM_ENTRIES
Definition: wmcgui.h:393
float flSaveMin
Definition: wmcgui.h:582
color Color_text_selected
Definition: alphacolors.cpp:26
int clip_right
Definition: 2d.h:388
#define WCI_CAPTION
Definition: wmcgui.h:386
#define MOUSE_RIGHT_BUTTON
Definition: mouse.h:44
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
#define TI_INITIAL_INDENT_VERTICAL
Definition: wmcgui.h:474
Definition: wmcgui.h:160
GLuint GLuint num
Definition: Glext.h:9089
#define T_ST_NEW
Definition: wmcgui.h:557
#define CIE_HANDLE_MR
Definition: wmcgui.h:90
virtual int DoMouseDown(float frametime)
Definition: wmcgui.h:263
GUISystem()
Definition: wmcgui.cpp:543
virtual void DoDraw(float frametime)
Definition: wmcgui.h:257
#define GST_KEYBOARD_CTRL
Definition: wmcgui.h:190
#define strcat_s(...)
Definition: safe_strings.h:68
#define T_ST_UBYTE
Definition: wmcgui.h:549
#define KEY_ESC
Definition: key.h:124
#define NAME_LENGTH
Definition: globals.h:15
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
#define KEY_ALTED
Definition: key.h:63
bool Save()
Definition: wmcgui.cpp:2258
#define fl2i(fl)
Definition: floating.h:33
short * siSavePointer
Definition: wmcgui.h:574
void gr_bitmap_list(bitmap_2d_list *list, int n_bm, int resize_mode)
Definition: 2d.cpp:1407
int game_check_key()
Definition: fredstubs.cpp:65
screen gr_screen
Definition: 2d.cpp:46
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
void DoDraw(float frametime)
Definition: wmcgui.cpp:2012
#define CIE_COORDS
Definition: wmcgui.h:75
#define TI_INDENT_PER_LEVEL
Definition: wmcgui.h:475
int DoMouseDown(float frametime)
Definition: wmcgui.cpp:1857
void Load()
Definition: wmcgui.cpp:2316
#define BCI_BUTTON
Definition: wmcgui.h:446
int DoMouseOut(float frametime)
Definition: wmcgui.cpp:1661
void DoDraw(float frametime)
Definition: wmcgui.cpp:1605
void DoMove(int dx, int dy)
Definition: wmcgui.cpp:1897
int DoMouseUp(float frametime)
Definition: wmcgui.cpp:1863
int gr_get_font_height()
Definition: font.cpp:187
ubyte * ubSavePointer
Definition: wmcgui.h:576
void ClearContent()
Definition: wmcgui.cpp:1535
int DoMouseUp(float frametime)
Definition: wmcgui.cpp:1334
int DoRefreshSize()
Definition: wmcgui.cpp:1087
#define F_NAME
Definition: parselo.h:34
ScreenClassInfoEntry * GetScreenClassInfo(const SCP_string &screen_name)
Definition: wmcgui.cpp:589
#define LOCATION
Definition: pstypes.h:245
int DoRefreshSize()
Definition: wmcgui.cpp:1581
void DoDraw(float frametime)
Definition: wmcgui.cpp:1812
~GUIObject()
Definition: wmcgui.cpp:757
#define CIE_HANDLE_S
Definition: wmcgui.h:82
#define GST_KEYBOARD_KEYPRESS
Definition: wmcgui.h:193
#define IMG_LOAD(f)
Definition: wmcgui.h:28
#define KEY_CTRLED
Definition: key.h:64
#define IMG_HANDLE_IS_INVALID(h)
Definition: wmcgui.h:25
virtual int DoMouseOut(float frametime)
Definition: wmcgui.h:265
#define GSOF_NOTHINGPRESSED
Definition: wmcgui.h:299
#define TI_INITIAL_INDENT
Definition: wmcgui.h:473
#define GR_BITBLT_MODE_NORMAL
Definition: 2d.h:351
void PullScreen(GUIScreen *in_screen)
Definition: wmcgui.cpp:574
GLenum GLsizei len
Definition: Glext.h:6283
color Color_text_normal
Definition: alphacolors.cpp:26
#define GST_MOUSE_MIDDLE_BUTTON
Definition: wmcgui.h:188
#define MAX_TEXT_LINES
Definition: cutscenes.cpp:245
~GUISystem()
Definition: wmcgui.cpp:551
virtual int DoKeyState(float frametime)
Definition: wmcgui.h:266
void DeleteObject(GUIObject *dgp)
Definition: wmcgui.cpp:468
IMG_HANDLE Image
Definition: wmcgui.h:113
void gr_create_shader(shader *shade, ubyte r, ubyte g, ubyte b, ubyte c)
Definition: 2d.cpp:1211
#define T_ST_CHAR
Definition: wmcgui.h:547
#define IF_BOUNCE
Definition: wmcgui.h:676
#define IMG_HANDLE_IS_VALID(h)
Definition: wmcgui.h:26
Definition: wmcgui.h:449
int clip_left
Definition: 2d.h:388
#define GT_IMAGEANIM
Definition: wmcgui.h:180
void ParseClassInfo(char *section)
Definition: wmcgui.cpp:142
#define gr_zbuffer_get
Definition: 2d.h:816
#define T_ST_FLOAT
Definition: wmcgui.h:548
#define IMG_DRAW(x, y)
Definition: wmcgui.h:33
struct LinkedList * next
Definition: wmcgui.h:46
#define CIE_IMAGE
Definition: wmcgui.h:72
void DoDraw(float frametime)
Definition: wmcgui.cpp:1415
#define CIE_IMAGE_BORDER
Definition: wmcgui.h:74
void SetPosition(int x, int y)
Definition: wmcgui.cpp:1055
ClassInfoEntry()
Definition: wmcgui.cpp:24
void gr_set_shader(shader *shade)
Definition: 2d.cpp:1220
#define GT_BUTTON
Definition: wmcgui.h:176
#define WCI_BODY
Definition: wmcgui.h:389
ObjectClassInfoEntry * GetObjectClassInfo(GUIObject *cgp)
Definition: wmcgui.cpp:362
#define GT_WINDOW
Definition: wmcgui.h:175
int GetCIEImageHandle(int id, int handleid=0)
Definition: wmcgui.h:275
#define GST_MOUSE_OVER
Definition: wmcgui.h:189
#define stricmp(s1, s2)
Definition: config.h:271
~ClassInfoEntry()
Definition: wmcgui.cpp:34
int DoRefreshSize()
Definition: wmcgui.cpp:2355
void SetImage(const SCP_string &in_imagename)
Definition: wmcgui.cpp:2552
virtual int DoFrame(float frametime)
Definition: wmcgui.h:258
float flSaveMax
Definition: wmcgui.h:581
friend struct TreeItem
Definition: wmcgui.h:43
const GLubyte * c
Definition: Glext.h:8376
Text(const SCP_string &in_name, const SCP_string &in_content, int x_coord, int y_coord, int x_width=-1, int y_width=-1, int in_style=0)
Definition: wmcgui.cpp:2100
#define GS_HIDDEN
Definition: wmcgui.h:202
GLint y
Definition: Gl.h:1505
#define WS_NONMOVEABLE
Definition: wmcgui.h:384
#define RAW_INTEGER_TYPE
Definition: parselo.h:52
#define GT_MENU
Definition: wmcgui.h:177
#define strcpy_s(...)
Definition: safe_strings.h:67
void DoMove(int dx, int dy)
Definition: wmcgui.cpp:2382
void Delete()
Definition: wmcgui.cpp:853
int GetImageHandle(int id, int handle_num)
Definition: wmcgui.cpp:299