Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
CGUI.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2013 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 /*
19 CGUI
20 */
21 
22 #include "precompiled.h"
23 
24 #include <string>
25 
26 #include <stdarg.h>
27 
28 #include "GUI.h"
29 
30 // Types - when including them into the engine.
31 #include "CButton.h"
32 #include "CImage.h"
33 #include "CText.h"
34 #include "CCheckBox.h"
35 #include "CRadioButton.h"
36 #include "CInput.h"
37 #include "CList.h"
38 #include "CDropDown.h"
39 #include "CProgressBar.h"
40 #include "CTooltip.h"
41 #include "MiniMap.h"
43 
44 #include "graphics/ShaderManager.h"
45 #include "graphics/TextRenderer.h"
46 #include "lib/input.h"
47 #include "lib/bits.h"
48 #include "lib/timer.h"
49 #include "lib/sysdep/sysdep.h"
50 #include "ps/CLogger.h"
51 #include "ps/Filesystem.h"
52 #include "ps/Font.h"
53 #include "ps/Hotkey.h"
54 #include "ps/Globals.h"
55 #include "ps/Overlay.h"
56 #include "ps/Profile.h"
57 #include "ps/Pyrogenesis.h"
58 #include "ps/XML/Xeromyces.h"
59 #include "renderer/Renderer.h"
62 
63 extern int g_yres;
64 
65 const double SELECT_DBLCLICK_RATE = 0.5;
66 
68 {
71 }
72 
74 {
75  InReaction ret = IN_PASS;
76 
77  if (ev->ev.type == SDL_HOTKEYDOWN)
78  {
79  const char* hotkey = static_cast<const char*>(ev->ev.user.data1);
80  std::map<CStr, std::vector<IGUIObject*> >::iterator it = m_HotkeyObjects.find(hotkey);
81  if (it != m_HotkeyObjects.end())
82  {
83  for (size_t i = 0; i < it->second.size(); ++i)
84  {
85  it->second[i]->SendEvent(GUIM_PRESSED, "press");
86  }
87  }
88  }
89 
90  else if (ev->ev.type == SDL_MOUSEMOTION)
91  {
92  // Yes the mouse position is stored as float to avoid
93  // constant conversions when operating in a
94  // float-based environment.
95  m_MousePos = CPos((float)ev->ev.motion.x, (float)ev->ev.motion.y);
96 
100  msg);
101  }
102 
103  // Update m_MouseButtons. (BUTTONUP is handled later.)
104  else if (ev->ev.type == SDL_MOUSEBUTTONDOWN)
105  {
106  switch (ev->ev.button.button)
107  {
108  case SDL_BUTTON_LEFT:
109  case SDL_BUTTON_RIGHT:
110  case SDL_BUTTON_MIDDLE:
111  m_MouseButtons |= Bit<unsigned int>(ev->ev.button.button);
112  break;
113  default:
114  break;
115  }
116  }
117 
118  // Update m_MousePos (for delayed mouse button events)
119  CPos oldMousePos = m_MousePos;
120  if (ev->ev.type == SDL_MOUSEBUTTONDOWN || ev->ev.type == SDL_MOUSEBUTTONUP)
121  {
122  m_MousePos = CPos((float)ev->ev.button.x, (float)ev->ev.button.y);
123  }
124 
125  // Only one object can be hovered
126  IGUIObject *pNearest = NULL;
127 
128  // TODO Gee: (2004-09-08) Big TODO, don't do the below if the SDL_Event is something like a keypress!
129  try
130  {
131  PROFILE( "mouse events" );
132  // TODO Gee: Optimizations needed!
133  // these two recursive function are quite overhead heavy.
134 
135  // pNearest will after this point at the hovered object, possibly NULL
136  pNearest = FindObjectUnderMouse();
137 
138  // Is placed in the UpdateMouseOver function
139  //if (ev->ev.type == SDL_MOUSEMOTION && pNearest)
140  // pNearest->ScriptEvent("mousemove");
141 
142  // Now we'll call UpdateMouseOver on *all* objects,
143  // we'll input the one hovered, and they will each
144  // update their own data and send messages accordingly
145 
148  pNearest);
149 
150  if (ev->ev.type == SDL_MOUSEBUTTONDOWN)
151  {
152  switch (ev->ev.button.button)
153  {
154  case SDL_BUTTON_LEFT:
155  // Focus the clicked object (or focus none if nothing clicked on)
156  SetFocusedObject(pNearest);
157 
158  if (pNearest)
159  ret = pNearest->SendEvent(GUIM_MOUSE_PRESS_LEFT, "mouseleftpress");
160  break;
161 
162  case SDL_BUTTON_RIGHT:
163  if (pNearest)
164  ret = pNearest->SendEvent(GUIM_MOUSE_PRESS_RIGHT, "mouserightpress");
165  break;
166 
167 #if !SDL_VERSION_ATLEAST(2, 0, 0)
168  case SDL_BUTTON_WHEELDOWN: // wheel down
169  if (pNearest)
170  ret = pNearest->SendEvent(GUIM_MOUSE_WHEEL_DOWN, "mousewheeldown");
171  break;
172 
173  case SDL_BUTTON_WHEELUP: // wheel up
174  if (pNearest)
175  ret = pNearest->SendEvent(GUIM_MOUSE_WHEEL_UP, "mousewheelup");
176  break;
177 #endif
178  default:
179  break;
180  }
181  }
182 #if SDL_VERSION_ATLEAST(2, 0, 0)
183  else if (ev->ev.type == SDL_MOUSEWHEEL)
184  {
185  if (ev->ev.wheel.y < 0)
186  {
187  if (pNearest)
188  ret = pNearest->SendEvent(GUIM_MOUSE_WHEEL_DOWN, "mousewheeldown");
189  }
190  else if (ev->ev.wheel.y > 0)
191  {
192  if (pNearest)
193  ret = pNearest->SendEvent(GUIM_MOUSE_WHEEL_UP, "mousewheelup");
194  }
195  }
196 #endif
197  else if (ev->ev.type == SDL_MOUSEBUTTONUP)
198  {
199  switch (ev->ev.button.button)
200  {
201  case SDL_BUTTON_LEFT:
202  if (pNearest)
203  {
204  double timeElapsed = timer_Time() - pNearest->m_LastClickTime[SDL_BUTTON_LEFT];
206 
207  //Double click?
208  if (timeElapsed < SELECT_DBLCLICK_RATE)
209  {
210  ret = pNearest->SendEvent(GUIM_MOUSE_DBLCLICK_LEFT, "mouseleftdoubleclick");
211  }
212  else
213  {
214  ret = pNearest->SendEvent(GUIM_MOUSE_RELEASE_LEFT, "mouseleftrelease");
215  }
216  }
217  break;
218  case SDL_BUTTON_RIGHT:
219  if (pNearest)
220  {
221  double timeElapsed = timer_Time() - pNearest->m_LastClickTime[SDL_BUTTON_RIGHT];
223 
224  //Double click?
225  if (timeElapsed < SELECT_DBLCLICK_RATE)
226  {
227  ret = pNearest->SendEvent(GUIM_MOUSE_DBLCLICK_RIGHT, "mouserightdoubleclick");
228  }
229  else
230  {
231  ret = pNearest->SendEvent(GUIM_MOUSE_RELEASE_RIGHT, "mouserightrelease");
232  }
233  }
234  break;
235  }
236 
237  // Reset all states on all visible objects
240 
241  // It will have reset the mouse over of the current hovered, so we'll
242  // have to restore that
243  if (pNearest)
244  pNearest->m_MouseHovering = true;
245  }
246  }
247  catch (PSERROR_GUI& e)
248  {
249  UNUSED2(e);
250  debug_warn(L"CGUI::HandleEvent error");
251  // TODO Gee: Handle
252  }
253 
254  // BUTTONUP's effect on m_MouseButtons is handled after
255  // everything else, so that e.g. 'press' handlers (activated
256  // on button up) see which mouse button had been pressed.
257  if (ev->ev.type == SDL_MOUSEBUTTONUP)
258  {
259  switch (ev->ev.button.button)
260  {
261  case SDL_BUTTON_LEFT:
262  case SDL_BUTTON_RIGHT:
263  case SDL_BUTTON_MIDDLE:
264  m_MouseButtons &= ~Bit<unsigned int>(ev->ev.button.button);
265  break;
266  default:
267  break;
268  }
269  }
270 
271  // Restore m_MousePos (for delayed mouse button events)
272  if (ev->ev.type == SDL_MOUSEBUTTONDOWN || ev->ev.type == SDL_MOUSEBUTTONUP)
273  {
274  m_MousePos = oldMousePos;
275  }
276 
277  // Handle keys for input boxes
278  if (GetFocusedObject())
279  {
280  if (
281  (ev->ev.type == SDL_KEYDOWN &&
282  ev->ev.key.keysym.sym != SDLK_ESCAPE &&
283  !g_keys[SDLK_LCTRL] && !g_keys[SDLK_RCTRL] &&
284  !g_keys[SDLK_LALT] && !g_keys[SDLK_RALT])
285  || ev->ev.type == SDL_HOTKEYDOWN
286  )
287  {
289  }
290  // else will return IN_PASS because we never used the button.
291  }
292 
293  return ret;
294 }
295 
297 {
298  CStr action = "tick";
300  &IGUIObject::ScriptEvent, action);
301 
302  // Also update tooltips:
304 }
305 
306 void CGUI::SendEventToAll(const CStr& EventName)
307 {
308  // janwas 2006-03-03: spoke with Ykkrosh about EventName case.
309  // when registering, case is converted to lower - this avoids surprise
310  // if someone were to get the case wrong and then not notice their
311  // handler is never called. however, until now, the other end
312  // (sending events here) wasn't converting to lower case,
313  // leading to a similar problem.
314  // now fixed; case is irrelevant since all are converted to lower.
316  &IGUIObject::ScriptEvent, EventName.LowerCase());
317 }
318 
319 //-------------------------------------------------------------------
320 // Constructor / Destructor
321 //-------------------------------------------------------------------
322 
323 // To isolate the vars declared by each GUI page, we need to create
324 // a pseudo-global object to declare them in. In particular, it must
325 // have no parent object, so it must be declared with JS_NewGlobalObject.
326 // But GUI scripts should have access to the real global's properties
327 // (Array, undefined, getGUIObjectByName, etc), so we add a custom resolver
328 // that defers to the real global object when necessary.
329 
330 static JSBool GetGlobalProperty(JSContext* cx, JSObject* UNUSED(obj), jsid id, jsval* vp)
331 {
332  return JS_GetPropertyById(cx, g_ScriptingHost.GetGlobalObject(), id, vp);
333 }
334 
335 static JSBool SetGlobalProperty(JSContext* cx, JSObject* UNUSED(obj), jsid id, JSBool UNUSED(strict), jsval* vp)
336 {
337  return JS_SetPropertyById(cx, g_ScriptingHost.GetGlobalObject(), id, vp);
338 }
339 
340 static JSBool ResolveGlobalProperty(JSContext* cx, JSObject* obj, jsid id, uintN flags, JSObject** objp)
341 {
342  // This gets called when the property can't be resolved in the page_global object.
343 
344  // Warning: The interaction between this resolution stuff and the JITs appears
345  // to be quite fragile, and I don't quite understand what the constraints are.
346  // If changing it, be careful to test with each JIT to make sure it works.
347  // (This code is somewhat based on GPSEE's module system.)
348 
349  // Declarations and assignments shouldn't affect the real global
350  if (flags & (JSRESOLVE_DECLARING | JSRESOLVE_ASSIGNING))
351  {
352  // Can't be resolved - return NULL
353  *objp = NULL;
354  return JS_TRUE;
355  }
356 
357  // Check whether the real global object defined this property
358  uintN attrs;
359  JSBool found;
360  if (!JS_GetPropertyAttrsGetterAndSetterById(cx, g_ScriptingHost.GetGlobalObject(), id, &attrs, &found, NULL, NULL))
361  return JS_FALSE;
362 
363  if (!found)
364  {
365  // Not found on real global, so can't be resolved - return NULL
366  *objp = NULL;
367  return JS_TRUE;
368  }
369 
370  // Retrieve the property value from the global
371  jsval v;
372  if (!JS_GetPropertyById(cx, g_ScriptingHost.GetGlobalObject(), id, &v))
373  return JS_FALSE;
374 
375  // Add the global's property value onto this object, with getter/setter that will
376  // update the global's copy instead of this copy, and then return this object
377  if (!JS_DefinePropertyById(cx, obj, id, v, GetGlobalProperty, SetGlobalProperty, attrs))
378  return JS_FALSE;
379 
380  *objp = obj;
381  return JS_TRUE;
382 }
383 
384 static JSClass page_global_class = {
385  "page_global", JSCLASS_GLOBAL_FLAGS | JSCLASS_NEW_RESOLVE,
386  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
387  JS_EnumerateStub, (JSResolveOp)ResolveGlobalProperty, JS_ConvertStub, JS_FinalizeStub,
388  NULL, NULL, NULL, NULL,
389  NULL, NULL, NULL, NULL
390 };
391 
392 CGUI::CGUI() : m_MouseButtons(0), m_FocusedObject(NULL), m_InternalNameNumber(0)
393 {
395  m_BaseObject->SetGUI(this);
396 
397  // Construct the root object for all GUI JavaScript things
398  m_ScriptObject = JS_NewGlobalObject(g_ScriptingHost.getContext(), &page_global_class);
399  JS_AddObjectRoot(g_ScriptingHost.getContext(), &m_ScriptObject);
400 }
401 
403 {
404  Destroy();
405 
406  if (m_BaseObject)
407  delete m_BaseObject;
408 
409  if (m_ScriptObject)
410  {
411  // Let it be garbage-collected
412  JS_RemoveObjectRoot(g_ScriptingHost.getContext(), &m_ScriptObject);
413  }
414 }
415 
416 //-------------------------------------------------------------------
417 // Functions
418 //-------------------------------------------------------------------
420 {
421  if (m_ObjectTypes.count(str) > 0)
422  return (*m_ObjectTypes[str])();
423  else
424  {
425  // Error reporting will be handled with the NULL return.
426  return NULL;
427  }
428 }
429 
431 {
432  // Add base types!
433  // You can also add types outside the GUI to extend the flexibility of the GUI.
434  // Pyrogenesis though will have all the object types inserted from here.
435  AddObjectType("empty", &CGUIDummyObject::ConstructObject);
436  AddObjectType("button", &CButton::ConstructObject);
437  AddObjectType("image", &CImage::ConstructObject);
438  AddObjectType("text", &CText::ConstructObject);
439  AddObjectType("checkbox", &CCheckBox::ConstructObject);
440  AddObjectType("radiobutton", &CRadioButton::ConstructObject);
441  AddObjectType("progressbar", &CProgressBar::ConstructObject);
442  AddObjectType("minimap", &CMiniMap::ConstructObject);
443  AddObjectType("input", &CInput::ConstructObject);
444  AddObjectType("list", &CList::ConstructObject);
445  AddObjectType("dropdown", &CDropDown::ConstructObject);
446  AddObjectType("tooltip", &CTooltip::ConstructObject);
447 }
448 
450 {
451  // Clear the depth buffer, so the GUI is
452  // drawn on top of everything else
453  glClear(GL_DEPTH_BUFFER_BIT);
454 
455  try
456  {
457  // Recurse IGUIObject::Draw() with restriction: hidden
458  // meaning all hidden objects won't call Draw (nor will it recurse its children)
460  }
461  catch (PSERROR_GUI& e)
462  {
463  LOGERROR(L"GUI draw error: %hs", e.what());
464  }
465 }
466 
468  int CellID,
469  const float& Z,
470  const CRect& Rect,
471  const CRect& UNUSED(Clipping))
472 {
473  // If the sprite doesn't exist (name == ""), don't bother drawing anything
474  if (Sprite.IsEmpty())
475  return;
476 
477  // TODO: Clipping?
478 
479  Sprite.Draw(Rect, CellID, m_Sprites, Z);
480 }
481 
483 {
484  // We can use the map to delete all
485  // now we don't want to cancel all if one Destroy fails
486  map_pObjects::iterator it;
487  for (it = m_pAllObjects.begin(); it != m_pAllObjects.end(); ++it)
488  {
489  try
490  {
491  it->second->Destroy();
492  }
493  catch (PSERROR_GUI& e)
494  {
495  UNUSED2(e);
496  debug_warn(L"CGUI::Destroy error");
497  // TODO Gee: Handle
498  }
499 
500  delete it->second;
501  }
502 
503  for (std::map<CStr, CGUISprite>::iterator it2 = m_Sprites.begin(); it2 != m_Sprites.end(); ++it2)
504  for (std::vector<SGUIImage>::iterator it3 = it2->second.m_Images.begin(); it3 != it2->second.m_Images.end(); ++it3)
505  delete it3->m_Effects;
506 
507  // Clear all
508  m_pAllObjects.clear();
509  m_Sprites.clear();
510  m_Icons.clear();
511 }
512 
514 {
515  // Update ALL cached
517 }
518 
520 {
521  try
522  {
523  // Add CGUI pointer
524  GUI<CGUI*>::RecurseObject(0, pObject, &IGUIObject::SetGUI, this);
525 
526  // Add child to base object
527  m_BaseObject->AddChild(pObject); // can throw
528 
529  // Cache tree
531 
532  // Loaded
533  SGUIMessage msg(GUIM_LOAD);
535  }
536  catch (PSERROR_GUI&)
537  {
538  throw;
539  }
540 }
541 
543 {
544  // We'll fill a temporary map until we know everything
545  // succeeded
546  map_pObjects AllObjects;
547 
548  try
549  {
550  // Fill freshly
552  }
553  catch (PSERROR_GUI&)
554  {
555  // Throw the same error
556  throw;
557  }
558 
559  // Else actually update the real one
560  m_pAllObjects.swap(AllObjects);
561 }
562 
563 bool CGUI::ObjectExists(const CStr& Name) const
564 {
565  return m_pAllObjects.count(Name) != 0;
566 }
567 
568 IGUIObject* CGUI::FindObjectByName(const CStr& Name) const
569 {
570  map_pObjects::const_iterator it = m_pAllObjects.find(Name);
571  if (it == m_pAllObjects.end())
572  return NULL;
573  else
574  return it->second;
575 }
576 
578 {
579  IGUIObject* pNearest = NULL;
582  pNearest);
583  return pNearest;
584 }
585 
587 {
588  if (pObject == m_FocusedObject)
589  return;
590 
591  if (m_FocusedObject)
592  {
595  }
596 
597  m_FocusedObject = pObject;
598 
599  if (m_FocusedObject)
600  {
603  }
604 }
605 
606 // private struct used only in GenerateText(...)
608 {
609  float m_YFrom, // The image's starting location in Y
610  m_YTo, // The image's end location in Y
611  m_Indentation; // The image width in other words
612 
613  // Some help functions
614  // TODO Gee: CRect => CPoint ?
615  void SetupSpriteCall(const bool Left, SGUIText::SSpriteCall &SpriteCall,
616  const float width, const float y,
617  const CSize &Size, const CStr& TextureName,
618  const float BufferZone, const int CellID)
619  {
620  // TODO Gee: Temp hardcoded values
621  SpriteCall.m_Area.top = y+BufferZone;
622  SpriteCall.m_Area.bottom = y+BufferZone + Size.cy;
623 
624  if (Left)
625  {
626  SpriteCall.m_Area.left = BufferZone;
627  SpriteCall.m_Area.right = Size.cx+BufferZone;
628  }
629  else
630  {
631  SpriteCall.m_Area.left = width-BufferZone - Size.cx;
632  SpriteCall.m_Area.right = width-BufferZone;
633  }
634 
635  SpriteCall.m_CellID = CellID;
636  SpriteCall.m_Sprite = TextureName;
637 
638  m_YFrom = SpriteCall.m_Area.top-BufferZone;
639  m_YTo = SpriteCall.m_Area.bottom+BufferZone;
640  m_Indentation = Size.cx+BufferZone*2;
641  }
642 };
643 
645  const CStrW& Font, const float &Width, const float &BufferZone,
646  const IGUIObject *pObject)
647 {
648  SGUIText Text; // object we're generating
649 
650  if (string.m_Words.size() == 0)
651  return Text;
652 
653  float x=BufferZone, y=BufferZone; // drawing pointer
654  int from=0;
655  bool done=false;
656 
657  bool FirstLine = true; // Necessary because text in the first line is shorter
658  // (it doesn't count the line spacing)
659 
660  // Images on the left or the right side.
661  std::vector<SGenerateTextImage> Images[2];
662  int pos_last_img=-1; // Position in the string where last img (either left or right) were encountered.
663  // in order to avoid duplicate processing.
664 
665  // Easier to read.
666  bool WordWrapping = (Width != 0);
667 
668  // get the alignment type for the control we are computing the text for since
669  // we are computing the horizontal alignment in this method in order to not have
670  // to run through the TextCalls a second time in the CalculateTextPosition method again
671  EAlign align;
672  GUI<EAlign>::GetSetting(pObject, "text_align", align);
673 
674  // Go through string word by word
675  for (int i=0; i<(int)string.m_Words.size()-1 && !done; ++i)
676  {
677  // Pre-process each line one time, so we know which floating images
678  // will be added for that line.
679 
680  // Generated stuff is stored in Feedback.
681  CGUIString::SFeedback Feedback;
682 
683  // Preliminary line_height, used for word-wrapping with floating images.
684  float prelim_line_height=0.f;
685 
686  // Width and height of all text calls generated.
687  string.GenerateTextCall(Feedback, Font,
688  string.m_Words[i], string.m_Words[i+1],
689  FirstLine);
690 
691  // Loop through our images queues, to see if images has been added.
692 
693  // Check if this has already been processed.
694  // Also, floating images are only applicable if Word-Wrapping is on
695  if (WordWrapping && i > pos_last_img)
696  {
697  // Loop left/right
698  for (int j=0; j<2; ++j)
699  {
700  for (std::vector<CStr>::const_iterator it = Feedback.m_Images[j].begin();
701  it != Feedback.m_Images[j].end();
702  ++it)
703  {
704  SGUIText::SSpriteCall SpriteCall;
705  SGenerateTextImage Image;
706 
707  // Y is if no other floating images is above, y. Else it is placed
708  // after the last image, like a stack downwards.
709  float _y;
710  if (!Images[j].empty())
711  _y = std::max(y, Images[j].back().m_YTo);
712  else
713  _y = y;
714 
715  // Get Size from Icon database
716  SGUIIcon icon = GetIcon(*it);
717 
718  CSize size = icon.m_Size;
719  Image.SetupSpriteCall((j==CGUIString::SFeedback::Left), SpriteCall, Width, _y, size, icon.m_SpriteName, BufferZone, icon.m_CellID);
720 
721  // Check if image is the lowest thing.
722  Text.m_Size.cy = std::max(Text.m_Size.cy, Image.m_YTo);
723 
724  Images[j].push_back(Image);
725  Text.m_SpriteCalls.push_back(SpriteCall);
726  }
727  }
728  }
729 
730  pos_last_img = std::max(pos_last_img, i);
731 
732  x += Feedback.m_Size.cx;
733  prelim_line_height = std::max(prelim_line_height, Feedback.m_Size.cy);
734 
735  // If Width is 0, then there's no word-wrapping, disable NewLine.
736  if ((WordWrapping && (x > Width-BufferZone || Feedback.m_NewLine)) || i == (int)string.m_Words.size()-2)
737  {
738  // Change 'from' to 'i', but first keep a copy of its value.
739  int temp_from = from;
740  from = i;
741 
742  static const int From=0, To=1;
743  //int width_from=0, width_to=width;
744  float width_range[2];
745  width_range[From] = BufferZone;
746  width_range[To] = Width - BufferZone;
747 
748  // Floating images are only applicable if word-wrapping is enabled.
749  if (WordWrapping)
750  {
751  // Decide width of the line. We need to iterate our floating images.
752  // this won't be exact because we're assuming the line_height
753  // will be as our preliminary calculation said. But that may change,
754  // although we'd have to add a couple of more loops to try straightening
755  // this problem out, and it is very unlikely to happen noticeably if one
756  // structures his text in a stylistically pure fashion. Even if not, it
757  // is still quite unlikely it will happen.
758  // Loop through left and right side, from and to.
759  for (int j=0; j<2; ++j)
760  {
761  for (std::vector<SGenerateTextImage>::const_iterator it = Images[j].begin();
762  it != Images[j].end();
763  ++it)
764  {
765  // We're working with two intervals here, the image's and the line height's.
766  // let's find the union of these two.
767  float union_from, union_to;
768 
769  union_from = std::max(y, it->m_YFrom);
770  union_to = std::min(y+prelim_line_height, it->m_YTo);
771 
772  // The union is not empty
773  if (union_to > union_from)
774  {
775  if (j == From)
776  width_range[From] = std::max(width_range[From], it->m_Indentation);
777  else
778  width_range[To] = std::min(width_range[To], Width - it->m_Indentation);
779  }
780  }
781  }
782  }
783 
784  // Reset X for the next loop
785  x = width_range[From];
786 
787  // Now we'll do another loop to figure out the height and width of
788  // the line (the height of the largest character and the width is
789  // the sum of all of the individual widths). This
790  // couldn't be determined in the first loop (main loop)
791  // because it didn't regard images, so we don't know
792  // if all characters processed, will actually be involved
793  // in that line.
794  float line_height=0.f;
795  float line_width=0.f;
796  for (int j=temp_from; j<=i; ++j)
797  {
798  // We don't want to use Feedback now, so we'll have to use
799  // another.
800  CGUIString::SFeedback Feedback2;
801 
802  // Don't attach object, it'll suppress the errors
803  // we want them to be reported in the final GenerateTextCall()
804  // so that we don't get duplicates.
805  string.GenerateTextCall(Feedback2, Font,
806  string.m_Words[j], string.m_Words[j+1],
807  FirstLine);
808 
809  // Append X value.
810  x += Feedback2.m_Size.cx;
811 
812  if (WordWrapping && x > width_range[To] && j!=temp_from && !Feedback2.m_NewLine)
813  break;
814 
815  // Let line_height be the maximum m_Height we encounter.
816  line_height = std::max(line_height, Feedback2.m_Size.cy);
817 
818  line_width += Feedback2.m_Size.cx;
819 
820  if (WordWrapping && Feedback2.m_NewLine)
821  break;
822  }
823 
824  float dx = 0.f;
825  // compute offset based on what kind of alignment
826  switch (align)
827  {
828  case EAlign_Left:
829  // don't add an offset
830  dx = 0.f;
831  break;
832 
833  case EAlign_Center:
834  dx = ((width_range[To] - width_range[From]) - line_width) / 2;
835  break;
836 
837  case EAlign_Right:
838  dx = width_range[To] - line_width;
839  break;
840 
841  default:
842  debug_warn(L"Broken EAlign in CGUI::GenerateText()");
843  break;
844  }
845  // Reset x once more
846  x = width_range[From];
847  // Move down, because font drawing starts from the baseline
848  y += line_height;
849 
850  // Do the real processing now
851  for (int j=temp_from; j<=i; ++j)
852  {
853  // We don't want to use Feedback now, so we'll have to use
854  // another one.
855  CGUIString::SFeedback Feedback2;
856 
857  // Defaults
858  string.GenerateTextCall(Feedback2, Font,
859  string.m_Words[j], string.m_Words[j+1],
860  FirstLine, pObject);
861 
862  // Iterate all and set X/Y values
863  // Since X values are not set, we need to make an internal
864  // iteration with an increment that will append the internal
865  // x, that is what x_pointer is for.
866  float x_pointer=0.f;
867 
868  std::vector<SGUIText::STextCall>::iterator it;
869  for (it = Feedback2.m_TextCalls.begin(); it != Feedback2.m_TextCalls.end(); ++it)
870  {
871  it->m_Pos = CPos(dx + x + x_pointer, y);
872 
873  x_pointer += it->m_Size.cx;
874 
875  if (it->m_pSpriteCall)
876  {
877  it->m_pSpriteCall->m_Area += it->m_Pos - CSize(0,it->m_pSpriteCall->m_Area.GetHeight());
878  }
879  }
880 
881  // Append X value.
882  x += Feedback2.m_Size.cx;
883 
884  Text.m_Size.cx = std::max(Text.m_Size.cx, x+BufferZone);
885 
886  // The first word overrides the width limit, what we
887  // do, in those cases, are just drawing that word even
888  // though it'll extend the object.
889  if (WordWrapping) // only if word-wrapping is applicable
890  {
891  if (Feedback2.m_NewLine)
892  {
893  from = j+1;
894 
895  // Sprite call can exist within only a newline segment,
896  // therefore we need this.
897  Text.m_SpriteCalls.insert(Text.m_SpriteCalls.end(), Feedback2.m_SpriteCalls.begin(), Feedback2.m_SpriteCalls.end());
898  break;
899  }
900  else
901  if (x > width_range[To] && j==temp_from)
902  {
903  from = j+1;
904  // do not break, since we want it to be added to m_TextCalls
905  }
906  else
907  if (x > width_range[To])
908  {
909  from = j;
910  break;
911  }
912  }
913 
914  // Add the whole Feedback2.m_TextCalls to our m_TextCalls.
915  Text.m_TextCalls.insert(Text.m_TextCalls.end(), Feedback2.m_TextCalls.begin(), Feedback2.m_TextCalls.end());
916  Text.m_SpriteCalls.insert(Text.m_SpriteCalls.end(), Feedback2.m_SpriteCalls.begin(), Feedback2.m_SpriteCalls.end());
917 
918  if (j == (int)string.m_Words.size()-2)
919  done = true;
920  }
921 
922  // Reset X
923  x = 0.f;
924 
925  // Update height of all
926  Text.m_Size.cy = std::max(Text.m_Size.cy, y+BufferZone);
927 
928  FirstLine = false;
929 
930  // Now if we entered as from = i, then we want
931  // i being one minus that, so that it will become
932  // the same i in the next loop. The difference is that
933  // we're on a new line now.
934  i = from-1;
935  }
936  }
937 
938  return Text;
939 }
940 
941 void CGUI::DrawText(SGUIText &Text, const CColor &DefaultColor,
942  const CPos &pos, const float &z, const CRect &clipping)
943 {
944  CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_gui_text);
945 
946  tech->BeginPass();
947 
948  if (clipping != CRect())
949  {
950  glEnable(GL_SCISSOR_TEST);
951  glScissor(clipping.left, g_yres - clipping.bottom, clipping.GetWidth(), clipping.GetHeight());
952  }
953 
954  CTextRenderer textRenderer(tech->GetShader());
955  textRenderer.Translate(0.0f, 0.0f, z);
956 
957  for (std::vector<SGUIText::STextCall>::const_iterator it = Text.m_TextCalls.begin();
958  it != Text.m_TextCalls.end();
959  ++it)
960  {
961  // If this is just a placeholder for a sprite call, continue
962  if (it->m_pSpriteCall)
963  continue;
964 
965  CColor color = it->m_UseCustomColor ? it->m_Color : DefaultColor;
966 
967  textRenderer.Color(color);
968  textRenderer.Font(it->m_Font);
969  textRenderer.Put((float)(int)(pos.x+it->m_Pos.x), (float)(int)(pos.y+it->m_Pos.y), it->m_String.c_str());
970  }
971 
972  textRenderer.Render();
973 
974  for (std::list<SGUIText::SSpriteCall>::iterator it=Text.m_SpriteCalls.begin();
975  it!=Text.m_SpriteCalls.end();
976  ++it)
977  {
978  DrawSprite(it->m_Sprite, it->m_CellID, z, it->m_Area + pos);
979  }
980 
981  if (clipping != CRect())
982  glDisable(GL_SCISSOR_TEST);
983 
984  tech->EndPass();
985 }
986 
987 bool CGUI::GetPreDefinedColor(const CStr& name, CColor &Output)
988 {
989  if (m_PreDefinedColors.count(name) == 0)
990  {
991  return false;
992  }
993  else
994  {
995  Output = m_PreDefinedColors[name];
996  return true;
997  }
998 }
999 
1000 /**
1001  * @callgraph
1002  */
1003 void CGUI::LoadXmlFile(const VfsPath& Filename, boost::unordered_set<VfsPath>& Paths)
1004 {
1005  Paths.insert(Filename);
1006 
1007  CXeromyces XeroFile;
1008  if (XeroFile.Load(g_VFS, Filename) != PSRETURN_OK)
1009  // Fail silently
1010  return;
1011 
1012  XMBElement node = XeroFile.GetRoot();
1013 
1014  // Check root element's (node) name so we know what kind of
1015  // data we'll be expecting
1016  CStr root_name (XeroFile.GetElementString(node.GetNodeName()));
1017 
1018  try
1019  {
1020 
1021  if (root_name == "objects")
1022  {
1023  Xeromyces_ReadRootObjects(node, &XeroFile, Paths);
1024 
1025  // Re-cache all values so these gets cached too.
1026  //UpdateResolution();
1027  }
1028  else
1029  if (root_name == "sprites")
1030  {
1031  Xeromyces_ReadRootSprites(node, &XeroFile);
1032  }
1033  else
1034  if (root_name == "styles")
1035  {
1036  Xeromyces_ReadRootStyles(node, &XeroFile);
1037  }
1038  else
1039  if (root_name == "setup")
1040  {
1041  Xeromyces_ReadRootSetup(node, &XeroFile);
1042  }
1043  else
1044  {
1045  debug_warn(L"CGUI::LoadXmlFile error");
1046  // TODO Gee: Output in log
1047  }
1048  }
1049  catch (PSERROR_GUI& e)
1050  {
1051  LOGERROR(L"Errors loading GUI file %ls (%u)", Filename.string().c_str(), e.getCode());
1052  return;
1053  }
1054 }
1055 
1056 //===================================================================
1057 // XML Reading Xeromyces Specific Sub-Routines
1058 //===================================================================
1059 
1060 void CGUI::Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces* pFile, boost::unordered_set<VfsPath>& Paths)
1061 {
1062  int el_script = pFile->GetElementID("script");
1063 
1064  std::vector<std::pair<CStr, CStr> > subst;
1065 
1066  // Iterate main children
1067  // they should all be <object> or <script> elements
1068  XMBElementList children = Element.GetChildNodes();
1069  for (int i=0; i<children.Count; ++i)
1070  {
1071  //debug_printf(L"Object %d\n", i);
1072  XMBElement child = children.Item(i);
1073 
1074  if (child.GetNodeName() == el_script)
1075  // Execute the inline script
1076  Xeromyces_ReadScript(child, pFile, Paths);
1077  else
1078  // Read in this whole object into the GUI
1079  Xeromyces_ReadObject(child, pFile, m_BaseObject, subst, Paths);
1080  }
1081 }
1082 
1084 {
1085  // Iterate main children
1086  // they should all be <sprite> elements
1087  XMBElementList children = Element.GetChildNodes();
1088  for (int i=0; i<children.Count; ++i)
1089  {
1090  XMBElement child = children.Item(i);
1091 
1092  // Read in this whole object into the GUI
1093  Xeromyces_ReadSprite(child, pFile);
1094  }
1095 }
1096 
1098 {
1099  // Iterate main children
1100  // they should all be <styles> elements
1101  XMBElementList children = Element.GetChildNodes();
1102  for (int i=0; i<children.Count; ++i)
1103  {
1104  XMBElement child = children.Item(i);
1105 
1106  // Read in this whole object into the GUI
1107  Xeromyces_ReadStyle(child, pFile);
1108  }
1109 }
1110 
1112 {
1113  // Iterate main children
1114  // they should all be <icon>, <scrollbar> or <tooltip>.
1115  XMBElementList children = Element.GetChildNodes();
1116  for (int i=0; i<children.Count; ++i)
1117  {
1118  XMBElement child = children.Item(i);
1119 
1120  // Read in this whole object into the GUI
1121 
1122  CStr name (pFile->GetElementString(child.GetNodeName()));
1123 
1124  if (name == "scrollbar")
1125  {
1126  Xeromyces_ReadScrollBarStyle(child, pFile);
1127  }
1128  else
1129  if (name == "icon")
1130  {
1131  Xeromyces_ReadIcon(child, pFile);
1132  }
1133  else
1134  if (name == "tooltip")
1135  {
1136  Xeromyces_ReadTooltip(child, pFile);
1137  }
1138  else
1139  if (name == "color")
1140  {
1141  Xeromyces_ReadColor(child, pFile);
1142  }
1143  else
1144  {
1145  debug_warn(L"Invalid data - DTD shouldn't allow this");
1146  }
1147  }
1148 }
1149 
1150 void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent, const std::vector<std::pair<CStr, CStr> >& NameSubst, boost::unordered_set<VfsPath>& Paths)
1151 {
1152  ENSURE(pParent);
1153  int i;
1154 
1155  // Our object we are going to create
1156  IGUIObject *object = NULL;
1157 
1158  XMBAttributeList attributes = Element.GetAttributes();
1159 
1160  // Well first of all we need to determine the type
1161  CStr type (attributes.GetNamedItem(pFile->GetAttributeID("type")));
1162  if (type.empty())
1163  type = "empty";
1164 
1165  // Construct object from specified type
1166  // henceforth, we need to do a rollback before aborting.
1167  // i.e. releasing this object
1168  object = ConstructObject(type);
1169 
1170  if (!object)
1171  {
1172  // Report error that object was unsuccessfully loaded
1173  LOGERROR(L"GUI: Unrecognized object type \"%hs\"", type.c_str());
1174  return;
1175  }
1176 
1177  // Cache some IDs for element attribute names, to avoid string comparisons
1178  #define ELMT(x) int elmt_##x = pFile->GetElementID(#x)
1179  #define ATTR(x) int attr_##x = pFile->GetAttributeID(#x)
1180  ELMT(object);
1181  ELMT(action);
1182  ELMT(repeat);
1183  ATTR(style);
1184  ATTR(type);
1185  ATTR(name);
1186  ATTR(hotkey);
1187  ATTR(z);
1188  ATTR(on);
1189  ATTR(file);
1190 
1191  //
1192  // Read Style and set defaults
1193  //
1194  // If the setting "style" is set, try loading that setting.
1195  //
1196  // Always load default (if it's available) first!
1197  //
1198  CStr argStyle (attributes.GetNamedItem(attr_style));
1199 
1200  if (m_Styles.count("default") == 1)
1201  object->LoadStyle(*this, "default");
1202 
1203  if (! argStyle.empty())
1204  {
1205  // additional check
1206  if (m_Styles.count(argStyle) == 0)
1207  {
1208  LOGERROR(L"GUI: Trying to use style '%hs' that doesn't exist.", argStyle.c_str());
1209  }
1210  else object->LoadStyle(*this, argStyle);
1211  }
1212 
1213 
1214  //
1215  // Read Attributes
1216  //
1217 
1218  bool NameSet = false;
1219  bool ManuallySetZ = false; // if z has been manually set, this turn true
1220 
1221  CStr hotkeyTag;
1222 
1223  // Now we can iterate all attributes and store
1224  for (i=0; i<attributes.Count; ++i)
1225  {
1226  XMBAttribute attr = attributes.Item(i);
1227 
1228  // If value is "null", then it is equivalent as never being entered
1229  if (CStr(attr.Value) == "null")
1230  continue;
1231 
1232  // Ignore "type" and "style", we've already checked it
1233  if (attr.Name == attr_type || attr.Name == attr_style)
1234  continue;
1235 
1236  // Also the name needs some special attention
1237  if (attr.Name == attr_name)
1238  {
1239  CStr name (attr.Value);
1240 
1241  // Apply the requested substitutions
1242  for (size_t j = 0; j < NameSubst.size(); ++j)
1243  name.Replace(NameSubst[j].first, NameSubst[j].second);
1244 
1245  object->SetName(name);
1246  NameSet = true;
1247  continue;
1248  }
1249 
1250  // Wire up the hotkey tag, if it has one
1251  if (attr.Name == attr_hotkey)
1252  hotkeyTag = attr.Value;
1253 
1254  if (attr.Name == attr_z)
1255  ManuallySetZ = true;
1256 
1257  // Try setting the value
1258  if (object->SetSetting(pFile->GetAttributeString(attr.Name), attr.Value.FromUTF8(), true) != PSRETURN_OK)
1259  {
1260  LOGERROR(L"GUI: (object: %hs) Can't set \"%hs\" to \"%ls\"", object->GetPresentableName().c_str(), pFile->GetAttributeString(attr.Name).c_str(), attr.Value.FromUTF8().c_str());
1261 
1262  // This is not a fatal error
1263  }
1264  }
1265 
1266  // Check if name isn't set, generate an internal name in that case.
1267  if (!NameSet)
1268  {
1269  object->SetName("__internal(" + CStr::FromInt(m_InternalNameNumber) + ")");
1271  }
1272 
1273  // Attempt to register the hotkey tag, if one was provided
1274  if (! hotkeyTag.empty())
1275  m_HotkeyObjects[hotkeyTag].push_back(object);
1276 
1277  CStrW caption (Element.GetText().FromUTF8());
1278  if (! caption.empty())
1279  {
1280  // Set the setting caption to this
1281  object->SetSetting("caption", caption, true);
1282 
1283  // There is no harm if the object didn't have a "caption"
1284  }
1285 
1286 
1287  //
1288  // Read Children
1289  //
1290 
1291  // Iterate children
1292  XMBElementList children = Element.GetChildNodes();
1293 
1294  for (i=0; i<children.Count; ++i)
1295  {
1296  // Get node
1297  XMBElement child = children.Item(i);
1298 
1299  // Check what name the elements got
1300  int element_name = child.GetNodeName();
1301 
1302  if (element_name == elmt_object)
1303  {
1304  // Call this function on the child
1305  Xeromyces_ReadObject(child, pFile, object, NameSubst, Paths);
1306  }
1307  else if (element_name == elmt_action)
1308  {
1309  // Scripted <action> element
1310 
1311  // Check for a 'file' parameter
1312  CStrW filename (child.GetAttributes().GetNamedItem(attr_file).FromUTF8());
1313 
1314  CStr code;
1315 
1316  // If there is a file, open it and use it as the code
1317  if (! filename.empty())
1318  {
1319  Paths.insert(filename);
1320  CVFSFile scriptfile;
1321  if (scriptfile.Load(g_VFS, filename) != PSRETURN_OK)
1322  {
1323  LOGERROR(L"Error opening GUI script action file '%ls'", filename.c_str());
1324  throw PSERROR_GUI_JSOpenFailed();
1325  }
1326 
1327  code = scriptfile.DecodeUTF8(); // assume it's UTF-8
1328  }
1329 
1330  // Read the inline code (concatenating to the file code, if both are specified)
1331  code += CStr(child.GetText());
1332 
1333  CStr action = CStr(child.GetAttributes().GetNamedItem(attr_on));
1334  object->RegisterScriptHandler(action.LowerCase(), code, this);
1335  }
1336  else if (element_name == elmt_repeat)
1337  {
1338  Xeromyces_ReadRepeat(child, pFile, object, Paths);
1339  }
1340  else
1341  {
1342  // Try making the object read the tag.
1343  if (!object->HandleAdditionalChildren(child, pFile))
1344  {
1345  LOGERROR(L"GUI: (object: %hs) Reading unknown children for its type", object->GetPresentableName().c_str());
1346  }
1347  }
1348  }
1349 
1350  //
1351  // Check if Z wasn't manually set
1352  //
1353  if (!ManuallySetZ)
1354  {
1355  // Set it automatically to 10 plus its parents
1356  bool absolute;
1357  GUI<bool>::GetSetting(object, "absolute", absolute);
1358 
1359  // If the object is absolute, we'll have to get the parent's Z buffered,
1360  // and add to that!
1361  if (absolute)
1362  {
1363  GUI<float>::SetSetting(object, "z", pParent->GetBufferedZ() + 10.f, true);
1364  }
1365  else
1366  // If the object is relative, then we'll just store Z as "10"
1367  {
1368  GUI<float>::SetSetting(object, "z", 10.f, true);
1369  }
1370  }
1371 
1372 
1373  //
1374  // Input Child
1375  //
1376 
1377  try
1378  {
1379  if (pParent == m_BaseObject)
1380  AddObject(object);
1381  else
1382  pParent->AddChild(object);
1383  }
1384  catch (PSERROR_GUI& e)
1385  {
1386  LOGERROR(L"GUI error: %hs", e.what());
1387  }
1388 }
1389 
1390 void CGUI::Xeromyces_ReadRepeat(XMBElement Element, CXeromyces* pFile, IGUIObject *pParent, boost::unordered_set<VfsPath>& Paths)
1391 {
1392  #define ELMT(x) int elmt_##x = pFile->GetElementID(#x)
1393  #define ATTR(x) int attr_##x = pFile->GetAttributeID(#x)
1394  ELMT(object);
1395  ATTR(count);
1396 
1397  XMBAttributeList attributes = Element.GetAttributes();
1398 
1399  int count = CStr(attributes.GetNamedItem(attr_count)).ToInt();
1400 
1401  for (int n = 0; n < count; ++n)
1402  {
1403  std::vector<std::pair<CStr, CStr> > subst;
1404  subst.push_back(std::make_pair(CStr("[n]"), "[" + CStr::FromInt(n) + "]"));
1405 
1406  XERO_ITER_EL(Element, child)
1407  {
1408  if (child.GetNodeName() == elmt_object)
1409  {
1410  Xeromyces_ReadObject(child, pFile, pParent, subst, Paths);
1411  }
1412  }
1413  }
1414 }
1415 
1416 void CGUI::Xeromyces_ReadScript(XMBElement Element, CXeromyces* pFile, boost::unordered_set<VfsPath>& Paths)
1417 {
1418  // Check for a 'file' parameter
1419  CStrW file (Element.GetAttributes().GetNamedItem( pFile->GetAttributeID("file") ).FromUTF8());
1420 
1421  // If there is a file specified, open and execute it
1422  if (! file.empty())
1423  {
1424  Paths.insert(file);
1425  try
1426  {
1427  g_ScriptingHost.RunScript(file, m_ScriptObject);
1428  }
1429  catch (PSERROR_Scripting& e)
1430  {
1431  LOGERROR(L"GUI: Error executing script %ls: %hs", file.c_str(), e.what());
1432  }
1433  }
1434 
1435  // Execute inline scripts
1436  try
1437  {
1438  CStr code (Element.GetText());
1439  if (! code.empty())
1440  g_ScriptingHost.RunMemScript(code.c_str(), code.length(), "Some XML file", Element.GetLineNumber(), m_ScriptObject);
1441  }
1442  catch (PSERROR_Scripting& e)
1443  {
1444  LOGERROR(L"GUI: Error executing inline script: %hs", e.what());
1445  }
1446 }
1447 
1449 {
1450  // Sprite object we're adding
1451  CGUISprite sprite;
1452 
1453  // and what will be its reference name
1454  CStr name;
1455 
1456  //
1457  // Read Attributes
1458  //
1459 
1460  // Get name, we know it exists because of DTD requirements
1461  name = Element.GetAttributes().GetNamedItem( pFile->GetAttributeID("name") );
1462 
1463  if (m_Sprites.find(name) != m_Sprites.end())
1464  LOGWARNING(L"GUI sprite name '%hs' used more than once; first definition will be discarded", name.c_str());
1465 
1466  //
1467  // Read Children (the images)
1468  //
1469 
1470  SGUIImageEffects* effects = NULL;
1471 
1472  // Iterate children
1473  XMBElementList children = Element.GetChildNodes();
1474 
1475  for (int i=0; i<children.Count; ++i)
1476  {
1477  // Get node
1478  XMBElement child = children.Item(i);
1479 
1480  CStr ElementName (pFile->GetElementString(child.GetNodeName()));
1481 
1482  if (ElementName == "image")
1483  {
1484  Xeromyces_ReadImage(child, pFile, sprite);
1485  }
1486  else if (ElementName == "effect")
1487  {
1488  if (effects)
1489  {
1490  LOGERROR(L"GUI <sprite> must not have more than one <effect>");
1491  }
1492  else
1493  {
1494  effects = new SGUIImageEffects;
1495  Xeromyces_ReadEffects(child, pFile, *effects);
1496  }
1497  }
1498  else
1499  {
1500  debug_warn(L"Invalid data - DTD shouldn't allow this");
1501  }
1502  }
1503 
1504  // Apply the effects to every image (unless the image overrides it with
1505  // different effects)
1506  if (effects)
1507  for (std::vector<SGUIImage>::iterator it = sprite.m_Images.begin(); it != sprite.m_Images.end(); ++it)
1508  if (! it->m_Effects)
1509  it->m_Effects = new SGUIImageEffects(*effects); // do a copy just so it can be deleted correctly later
1510 
1511  delete effects;
1512 
1513  //
1514  // Add Sprite
1515  //
1516 
1517  m_Sprites[name] = sprite;
1518 }
1519 
1521 {
1522 
1523  // Image object we're adding
1524  SGUIImage image;
1525 
1526  // Set defaults to "0 0 100% 100%"
1527  image.m_TextureSize = CClientArea(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
1528  image.m_Size = CClientArea(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
1529 
1530  // TODO Gee: Setup defaults here (or maybe they are in the SGUIImage ctor)
1531 
1532  //
1533  // Read Attributes
1534  //
1535 
1536  // Now we can iterate all attributes and store
1537  XMBAttributeList attributes = Element.GetAttributes();
1538  for (int i=0; i<attributes.Count; ++i)
1539  {
1540  XMBAttribute attr = attributes.Item(i);
1541  CStr attr_name (pFile->GetAttributeString(attr.Name));
1542  CStrW attr_value (attr.Value.FromUTF8());
1543 
1544  if (attr_name == "texture")
1545  {
1546  image.m_TextureName = VfsPath("art/textures/ui") / attr_value;
1547  }
1548  else
1549  if (attr_name == "size")
1550  {
1551  CClientArea ca;
1552  if (!GUI<CClientArea>::ParseString(attr_value, ca))
1553  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1554  else image.m_Size = ca;
1555  }
1556  else
1557  if (attr_name == "texture_size")
1558  {
1559  CClientArea ca;
1560  if (!GUI<CClientArea>::ParseString(attr_value, ca))
1561  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1562  else image.m_TextureSize = ca;
1563  }
1564  else
1565  if (attr_name == "real_texture_placement")
1566  {
1567  CRect rect;
1568  if (!GUI<CRect>::ParseString(attr_value, rect))
1569  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1570  else image.m_TexturePlacementInFile = rect;
1571  }
1572  else
1573  if (attr_name == "cell_size")
1574  {
1575  CSize size;
1576  if (!GUI<CSize>::ParseString(attr_value, size))
1577  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1578  else image.m_CellSize = size;
1579  }
1580  else
1581  if (attr_name == "fixed_h_aspect_ratio")
1582  {
1583  float val;
1584  if (!GUI<float>::ParseString(attr_value, val))
1585  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1586  else image.m_FixedHAspectRatio = val;
1587  }
1588  else
1589  if (attr_name == "round_coordinates")
1590  {
1591  bool b;
1592  if (!GUI<bool>::ParseString(attr_value, b))
1593  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1594  else image.m_RoundCoordinates = b;
1595  }
1596  else
1597  if (attr_name == "wrap_mode")
1598  {
1599  if (attr_value == L"repeat")
1600  image.m_WrapMode = GL_REPEAT;
1601  else if (attr_value == L"mirrored_repeat")
1602  image.m_WrapMode = GL_MIRRORED_REPEAT;
1603  else if (attr_value == L"clamp_to_edge")
1604  image.m_WrapMode = GL_CLAMP_TO_EDGE;
1605  else
1606  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1607  }
1608  else
1609  if (attr_name == "z_level")
1610  {
1611  float z_level;
1612  if (!GUI<float>::ParseString(attr_value, z_level))
1613  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1614  else image.m_DeltaZ = z_level/100.f;
1615  }
1616  else
1617  if (attr_name == "backcolor")
1618  {
1619  CColor color;
1620  if (!GUI<CColor>::ParseString(attr_value, color))
1621  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1622  else image.m_BackColor = color;
1623  }
1624  else
1625  if (attr_name == "bordercolor")
1626  {
1627  CColor color;
1628  if (!GUI<CColor>::ParseString(attr_value, color))
1629  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1630  else image.m_BorderColor = color;
1631  }
1632  else
1633  if (attr_name == "border")
1634  {
1635  bool b;
1636  if (!GUI<bool>::ParseString(attr_value, b))
1637  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1638  else image.m_Border = b;
1639  }
1640  else
1641  {
1642  debug_warn(L"Invalid data - DTD shouldn't allow this");
1643  }
1644  }
1645 
1646  // Look for effects
1647  XMBElementList children = Element.GetChildNodes();
1648  for (int i=0; i<children.Count; ++i)
1649  {
1650  XMBElement child = children.Item(i);
1651  CStr ElementName (pFile->GetElementString(child.GetNodeName()));
1652  if (ElementName == "effect")
1653  {
1654  if (image.m_Effects)
1655  {
1656  LOGERROR(L"GUI <image> must not have more than one <effect>");
1657  }
1658  else
1659  {
1660  image.m_Effects = new SGUIImageEffects;
1661  Xeromyces_ReadEffects(child, pFile, *image.m_Effects);
1662  }
1663  }
1664  else
1665  {
1666  debug_warn(L"Invalid data - DTD shouldn't allow this");
1667  }
1668  }
1669 
1670  //
1671  // Input
1672  //
1673 
1674  parent.AddImage(image);
1675 }
1676 
1678 {
1679  XMBAttributeList attributes = Element.GetAttributes();
1680  for (int i=0; i<attributes.Count; ++i)
1681  {
1682  XMBAttribute attr = attributes.Item(i);
1683  CStr attr_name (pFile->GetAttributeString(attr.Name));
1684  CStrW attr_value (attr.Value.FromUTF8());
1685 
1686  if (attr_name == "add_color")
1687  {
1688  CColor color;
1689  if (!GUI<int>::ParseColor(attr_value, color, 0.f))
1690  LOGERROR(L"GUI: Error parsing '%hs' (\"%ls\")", attr_name.c_str(), attr_value.c_str());
1691  else effects.m_AddColor = color;
1692  }
1693  else if (attr_name == "grayscale")
1694  {
1695  effects.m_Greyscale = true;
1696  }
1697  else
1698  {
1699  debug_warn(L"Invalid data - DTD shouldn't allow this");
1700  }
1701  }
1702 }
1703 
1705 {
1706  // style object we're adding
1707  SGUIStyle style;
1708  CStr name;
1709 
1710  //
1711  // Read Attributes
1712  //
1713 
1714  // Now we can iterate all attributes and store
1715  XMBAttributeList attributes = Element.GetAttributes();
1716  for (int i=0; i<attributes.Count; ++i)
1717  {
1718  XMBAttribute attr = attributes.Item(i);
1719  CStr attr_name (pFile->GetAttributeString(attr.Name));
1720 
1721  // The "name" setting is actually the name of the style
1722  // and not a new default
1723  if (attr_name == "name")
1724  name = attr.Value;
1725  else
1726  style.m_SettingsDefaults[attr_name] = attr.Value.FromUTF8();
1727  }
1728 
1729  //
1730  // Add to CGUI
1731  //
1732 
1733  m_Styles[name] = style;
1734 }
1735 
1737 {
1738  // style object we're adding
1739  SGUIScrollBarStyle scrollbar;
1740  CStr name;
1741 
1742  //
1743  // Read Attributes
1744  //
1745 
1746  // Now we can iterate all attributes and store
1747  XMBAttributeList attributes = Element.GetAttributes();
1748  for (int i=0; i<attributes.Count; ++i)
1749  {
1750  XMBAttribute attr = attributes.Item(i);
1751  CStr attr_name = pFile->GetAttributeString(attr.Name);
1752  CStr attr_value (attr.Value);
1753 
1754  if (attr_value == "null")
1755  continue;
1756 
1757  if (attr_name == "name")
1758  name = attr_value;
1759  else
1760  if (attr_name == "width")
1761  {
1762  float f;
1763  if (!GUI<float>::ParseString(attr_value.FromUTF8(), f))
1764  LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
1765  else
1766  scrollbar.m_Width = f;
1767  }
1768  else
1769  if (attr_name == "minimum_bar_size")
1770  {
1771  float f;
1772  if (!GUI<float>::ParseString(attr_value.FromUTF8(), f))
1773  LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
1774  else
1775  scrollbar.m_MinimumBarSize = f;
1776  }
1777  else
1778  if (attr_name == "maximum_bar_size")
1779  {
1780  float f;
1781  if (!GUI<float>::ParseString(attr_value.FromUTF8(), f))
1782  LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\")", attr_name.c_str(), attr_value.c_str());
1783  else
1784  scrollbar.m_MaximumBarSize = f;
1785  }
1786  else
1787  if (attr_name == "sprite_button_top")
1788  scrollbar.m_SpriteButtonTop = attr_value;
1789  else
1790  if (attr_name == "sprite_button_top_pressed")
1791  scrollbar.m_SpriteButtonTopPressed = attr_value;
1792  else
1793  if (attr_name == "sprite_button_top_disabled")
1794  scrollbar.m_SpriteButtonTopDisabled = attr_value;
1795  else
1796  if (attr_name == "sprite_button_top_over")
1797  scrollbar.m_SpriteButtonTopOver = attr_value;
1798  else
1799  if (attr_name == "sprite_button_bottom")
1800  scrollbar.m_SpriteButtonBottom = attr_value;
1801  else
1802  if (attr_name == "sprite_button_bottom_pressed")
1803  scrollbar.m_SpriteButtonBottomPressed = attr_value;
1804  else
1805  if (attr_name == "sprite_button_bottom_disabled")
1806  scrollbar.m_SpriteButtonBottomDisabled = attr_value;
1807  else
1808  if (attr_name == "sprite_button_bottom_over")
1809  scrollbar.m_SpriteButtonBottomOver = attr_value;
1810  else
1811  if (attr_name == "sprite_back_vertical")
1812  scrollbar.m_SpriteBackVertical = attr_value;
1813  else
1814  if (attr_name == "sprite_bar_vertical")
1815  scrollbar.m_SpriteBarVertical = attr_value;
1816  else
1817  if (attr_name == "sprite_bar_vertical_over")
1818  scrollbar.m_SpriteBarVerticalOver = attr_value;
1819  else
1820  if (attr_name == "sprite_bar_vertical_pressed")
1821  scrollbar.m_SpriteBarVerticalPressed = attr_value;
1822  }
1823 
1824  //
1825  // Add to CGUI
1826  //
1827 
1828  m_ScrollBarStyles[name] = scrollbar;
1829 }
1830 
1832 {
1833  // Icon we're adding
1834  SGUIIcon icon;
1835  CStr name;
1836 
1837  XMBAttributeList attributes = Element.GetAttributes();
1838  for (int i=0; i<attributes.Count; ++i)
1839  {
1840  XMBAttribute attr = attributes.Item(i);
1841  CStr attr_name (pFile->GetAttributeString(attr.Name));
1842  CStr attr_value (attr.Value);
1843 
1844  if (attr_value == "null")
1845  continue;
1846 
1847  if (attr_name == "name")
1848  name = attr_value;
1849  else
1850  if (attr_name == "sprite")
1851  icon.m_SpriteName = attr_value;
1852  else
1853  if (attr_name == "size")
1854  {
1855  CSize size;
1856  if (!GUI<CSize>::ParseString(attr_value.FromUTF8(), size))
1857  LOGERROR(L"Error parsing '%hs' (\"%hs\") inside <icon>.", attr_name.c_str(), attr_value.c_str());
1858  else
1859  icon.m_Size = size;
1860  }
1861  else
1862  if (attr_name == "cell_id")
1863  {
1864  int cell_id;
1865  if (!GUI<int>::ParseString(attr_value.FromUTF8(), cell_id))
1866  LOGERROR(L"GUI: Error parsing '%hs' (\"%hs\") inside <icon>.", attr_name.c_str(), attr_value.c_str());
1867  else
1868  icon.m_CellID = cell_id;
1869  }
1870  else
1871  {
1872  debug_warn(L"Invalid data - DTD shouldn't allow this");
1873  }
1874  }
1875 
1876  m_Icons[name] = icon;
1877 }
1878 
1880 {
1881  // Read the tooltip, and store it as a specially-named object
1882 
1883  IGUIObject* object = new CTooltip;
1884 
1885  XMBAttributeList attributes = Element.GetAttributes();
1886  for (int i=0; i<attributes.Count; ++i)
1887  {
1888  XMBAttribute attr = attributes.Item(i);
1889  CStr attr_name (pFile->GetAttributeString(attr.Name));
1890  CStr attr_value (attr.Value);
1891 
1892  if (attr_name == "name")
1893  {
1894  object->SetName("__tooltip_" + attr_value);
1895  }
1896  else
1897  {
1898  object->SetSetting(attr_name, attr_value.FromUTF8());
1899  }
1900  }
1901 
1902  AddObject(object);
1903 }
1904 
1905 // Reads Custom Color
1907 {
1908  // Read the color and stor in m_PreDefinedColors
1909 
1910  XMBAttributeList attributes = Element.GetAttributes();
1911 
1912  //IGUIObject* object = new CTooltip;
1913  CColor color;
1914  CStr name = attributes.GetNamedItem(pFile->GetAttributeID("name"));
1915 
1916  // Try parsing value
1917  CStr value (Element.GetText());
1918  if (! value.empty())
1919  {
1920  // Try setting color to value
1921  if (!color.ParseString(value, 255.f))
1922  {
1923  LOGERROR(L"GUI: Unable to create custom color '%hs'. Invalid color syntax.", name.c_str());
1924  }
1925  else
1926  {
1927  // input color
1928  m_PreDefinedColors[name] = color;
1929  }
1930  }
1931 }
bool ObjectExists(const CStr &Name) const
Checks if object exists and return true or false accordingly.
Definition: CGUI.cpp:563
void Xeromyces_ReadImage(XMBElement Element, CXeromyces *pFile, CGUISprite &parent)
Reads in the element &lt;image&gt; (the XMBElement) and stores the result within the CGUISprite.
Definition: CGUI.cpp:1520
std::map< CStr, CColor > m_PreDefinedColors
This is a bank of custom colors, it is simply a look up table that will return a color object when so...
Definition: CGUI.h:614
float m_MinimumBarSize
Sometimes there is a lot to scroll, but to prevent the scroll &quot;bar&quot; from being almost invisible (or u...
Definition: IGUIScrollBar.h:91
int m_CellID
Definition: GUIbase.h:170
virtual void ResetStates()
Reset internal state of this object.
Definition: IGUIObject.h:381
CStr DecodeUTF8() const
Returns contents of a UTF-8 encoded file as a string with optional BOM removed.
Definition: Filesystem.cpp:153
CColor m_AddColor
Definition: CGUISprite.h:68
void Translate(float x, float y, float z)
Made to represent a screen size, should in philosophy be made of unsigned ints, but for the sake of c...
Definition: Overlay.h:205
#define UNUSED(param)
mark a function parameter as unused and avoid the corresponding compiler warning. ...
Path VfsPath
VFS path of the form &quot;(dir/)*file?&quot;.
Definition: vfs_path.h:40
void DrawSprite(const CGUISpriteInstance &Sprite, int CellID, const float &Z, const CRect &Rect, const CRect &Clipping=CRect())
Draw GUI Sprite.
Definition: CGUI.cpp:467
void Xeromyces_ReadRootSprites(XMBElement Element, CXeromyces *pFile)
Reads in the root element &lt;sprites&gt; (the DOMElement).
Definition: CGUI.cpp:1083
SDL_KeyboardEvent key
Definition: wsdl.h:305
std::map< CStr, CStrW > m_SettingsDefaults
Definition: CGUI.h:76
PSRETURN Load(const PIVFS &vfs, const VfsPath &filename)
Load from an XML file (with invisible XMB caching).
Definition: Xeromyces.cpp:65
#define LOGERROR
Definition: CLogger.h:35
float m_FixedHAspectRatio
If non-zero, then the image&#39;s width will be adjusted when rendering so that the width:height ratio eq...
Definition: CGUISprite.h:109
void Xeromyces_ReadObject(XMBElement Element, CXeromyces *pFile, IGUIObject *pParent, const std::vector< std::pair< CStr, CStr > > &NameSubst, boost::unordered_set< VfsPath > &Paths)
Notice! Recursive function!
Definition: CGUI.cpp:1150
IGUIObject * m_FocusedObject
Focused object! Say an input box that is selected.
Definition: CGUI.h:633
~CGUI()
Definition: CGUI.cpp:402
const PSRETURN PSRETURN_OK
Definition: Errors.h:103
float top
Definition: Overlay.h:159
GUITooltip m_Tooltip
Definition: CGUI.h:606
void ScriptEvent(const CStr &Action)
Execute the script for a particular action.
Definition: IGUIObject.cpp:480
Reads a file, then gives read-only access to the contents.
Definition: Filesystem.h:69
void Xeromyces_ReadScrollBarStyle(XMBElement Element, CXeromyces *pFile)
Reads in the element &lt;scrollbar&gt; (the XMBElement) and stores the result in m_ScrollBarStyles.
Definition: CGUI.cpp:1736
Definition: Overlay.h:34
JSObject * m_ScriptObject
An JSObject* under which all GUI JavaScript things will be created, so that they can be garbage-colle...
Definition: CGUI.h:590
float m_Width
Width of bar, also both sides of the edge buttons.
Definition: IGUIScrollBar.h:67
Dummy object used primarily for the root object or objects of type &#39;empty&#39;.
Definition: IGUIObject.h:568
The GUI Scroll-bar style.
Definition: IGUIScrollBar.h:57
All data generated in GenerateTextCall()
Definition: GUItext.h:252
std::vector< SGUIText::STextCall > m_TextCalls
Text and Sprite Calls.
Definition: GUItext.h:271
int GetElementID(const char *Name) const
Definition: XeroXMB.cpp:104
float left
Returning CPos representing each corner.
Definition: Overlay.h:159
static PSRETURN GetSetting(const IGUIObject *pObject, const CStr &Setting, T &Value)
Retrieves a setting by name from object pointer.
Definition: GUIutil.cpp:344
IGUIObject * FindObjectUnderMouse() const
Returns the GUI object under the mouse, or NULL if none.
Definition: CGUI.cpp:577
XMBAttributeList GetAttributes() const
Definition: XeroXMB.cpp:185
XMBElementList GetChildNodes() const
Definition: XeroXMB.cpp:174
#define XERO_ITER_EL(parent_element, child_element)
Definition: Xeromyces.h:91
CGUISpriteInstance m_SpriteButtonBottomDisabled
shared_ptr< CShaderTechnique > CShaderTechniquePtr
static JSBool GetGlobalProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
Definition: CGUI.cpp:330
void SetGUI(CGUI *const &pGUI)
Definition: IGUIObject.h:371
CSize m_Size
Width and Height feedback
Definition: GUItext.h:278
CRect m_Area
Size and position of sprite.
Definition: GUItext.h:74
Base settings, all objects possess these settings in their m_BaseSettings Instructions can be found i...
Definition: IGUIObject.h:140
A sprite call to the CRenderer.
Definition: GUItext.h:67
bool m_Border
Definition: CGUISprite.h:130
void Xeromyces_ReadRootObjects(XMBElement Element, CXeromyces *pFile, boost::unordered_set< VfsPath > &Paths)
Reads in the root element &lt;objects&gt; (the DOMElement).
Definition: CGUI.cpp:1060
CStr GetPresentableName() const
Definition: IGUIObject.cpp:536
int GetLineNumber() const
Definition: XeroXMB.cpp:205
CGUISpriteInstance m_SpriteButtonTop
void Xeromyces_ReadRootSetup(XMBElement Element, CXeromyces *pFile)
Reads in the root element &lt;setup&gt; (the DOMElement).
Definition: CGUI.cpp:1111
static JSBool SetGlobalProperty(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp)
Definition: CGUI.cpp:335
static JSClass page_global_class
Definition: CGUI.cpp:384
std::map< CStr, std::vector< IGUIObject * > > m_HotkeyObjects
Map from hotkey names to objects that listen to the hotkey.
Definition: CGUI.h:666
float m_Indentation
Definition: CGUI.cpp:609
bool ParseString(const CStr8 &Value, float DefaultAlpha)
Definition: Overlay.cpp:30
SDL_MouseMotionEvent motion
Definition: wsdl.h:307
void Destroy()
Clean up, call this to clean up all memory allocated within the GUI.
Definition: CGUI.cpp:482
virtual float GetBufferedZ() const
Returns not the Z value, but the actual buffered Z value, i.e.
Definition: IGUIObject.cpp:406
virtual bool HandleAdditionalChildren(const XMBElement &child, CXeromyces *pFile)
Handle additional children to the &lt;object&gt;-tag.
Definition: IGUIObject.h:426
#define g_Renderer
Definition: Renderer.h:61
virtual InReaction ManuallyHandleEvent(const SDL_Event_ *ev)
Some objects need to handle the SDL_Event_ manually.
Definition: IGUIObject.h:345
void TickObjects()
Performs processing that should happen every frame (including sending the &quot;Tick&quot; event to scripts) ...
Definition: CGUI.cpp:296
Hotkey system.
#define LOGWARNING
Definition: CLogger.h:34
float GetWidth() const
Definition: Overlay.cpp:232
CGUISpriteInstance m_SpriteButtonTopPressed
std::map< CStr, CGUISprite > m_Sprites
Definition: CGUI.h:673
SDL_Event ev
Definition: libsdl.h:56
Includes static functions that needs one template argument.
Definition: GUIutil.h:103
bool m_RoundCoordinates
If true, the image&#39;s coordinates will be rounded to integer pixels when rendering, to avoid blurry filtering.
Definition: CGUISprite.h:115
unsigned int m_MouseButtons
Indicates which buttons are pressed (bit 0 = LMB, bit 1 = RMB, bit 2 = MMB)
Definition: CGUI.h:603
virtual void UpdateCachedSize()
All sizes are relative to resolution, and the calculation is not wanted in real time, therefore it is cached, update the cached size with this function.
Definition: IGUIObject.cpp:336
CGUISpriteInstance m_SpriteButtonTopDisabled
CPos m_MousePos
don&#39;t want to pass this around with the ChooseMouseOverAndClosest broadcast - we&#39;d need to pack this ...
Definition: CGUI.h:597
void Xeromyces_ReadRootStyles(XMBElement Element, CXeromyces *pFile)
Reads in the root element &lt;styles&gt; (the DOMElement).
Definition: CGUI.cpp:1097
virtual PSRETURN getCode() const =0
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
#define UNUSED2(param)
mark a function local variable or parameter as unused and avoid the corresponding compiler warning...
float m_MaximumBarSize
Sometimes you would like your scroll bar to have a fixed maximum size so that the texture does not ge...
Definition: IGUIScrollBar.h:98
#define g_ScriptingHost
Uint8 type
Definition: wsdl.h:302
static JSBool ResolveGlobalProperty(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **objp)
Definition: CGUI.cpp:340
float m_DeltaZ
Z value modification of the image.
Definition: CGUISprite.h:137
CStr8 GetText() const
Definition: XeroXMB.cpp:196
SDL_MouseButtonEvent button
Definition: wsdl.h:308
IGUIObject * GetFocusedObject()
Get Focused Object.
Definition: CGUI.h:322
static void ScriptingInit()
Initializes GUI script classes.
Definition: CGUI.cpp:67
CGUISpriteInstance m_SpriteButtonTopOver
Definition: path.h:75
void UpdateObjects()
Updates the object pointers, needs to be called each time an object has been added or removed...
Definition: CGUI.cpp:542
std::vector< CStr > m_Images[2]
Image stacks, for left and right floating images.
Definition: GUItext.h:266
std::vector< SGUIImage > m_Images
List of images.
Definition: CGUISprite.h:164
const String & string() const
Definition: path.h:123
InReaction
Definition: input.h:34
void Xeromyces_ReadScript(XMBElement Element, CXeromyces *pFile, boost::unordered_set< VfsPath > &Paths)
Reads in the element &lt;script&gt; (the XMBElement) and executes the script&#39;s code.
Definition: CGUI.cpp:1416
Definition: input.h:40
CSize m_Size
Width and height of the whole output, used when setting up scrollbars and such.
Definition: GUItext.h:162
CStr m_SpriteName
Definition: GUIbase.h:164
virtual const char * what() const
Definition: Errors.cpp:453
int g_yres
Definition: Config.cpp:58
CColor m_BackColor
Definition: CGUISprite.h:126
void Update(IGUIObject *Nearest, CPos MousePos, CGUI *GUI)
Definition: GUITooltip.cpp:267
CClientArea m_Size
Definition: CGUISprite.h:89
XMBAttribute Item(const int id)
Definition: XeroXMB.cpp:276
std::map< CStr, SGUIStyle > m_Styles
Definition: CGUI.h:676
bool GetPreDefinedColor(const CStr &name, CColor &Output)
Get pre-defined color (if it exists) Returns false if it fails.
Definition: CGUI.cpp:987
void AddImage(const SGUIImage &image)
Adds an image to the sprite collage.
Definition: CGUISprite.h:161
IGUIObject * ConstructObject(const CStr &str)
You input the name of the object type, and let&#39;s say you input &quot;button&quot;, then it will construct a CGU...
Definition: CGUI.cpp:419
#define PROFILE(name)
Definition: Profile.h:195
void AddChild(IGUIObject *pChild)
Notice nothing will be returned or thrown if the child hasn&#39;t been inputted into the GUI yet...
Definition: IGUIObject.cpp:104
SGUIImageEffects * m_Effects
Definition: CGUISprite.h:123
std::vector< STextCall > m_TextCalls
List of TextCalls, for instance &quot;Hello&quot;, &quot;there!&quot;.
Definition: GUItext.h:149
static const int Left
Definition: GUItext.h:255
void AddObjectType(const CStr &str, ConstructObjectFunction pFunc)
The GUI needs to have all object types inputted and their constructors.
Definition: CGUI.h:229
const int SDL_HOTKEYDOWN
Definition: Hotkey.h:41
CRect m_TexturePlacementInFile
Definition: CGUISprite.h:97
CStr8 GetNamedItem(const int AttributeName) const
Definition: XeroXMB.cpp:259
double timer_Time()
Definition: timer.cpp:98
void ChooseMouseOverAndClosest(IGUIObject *&pObject)
Inputs a reference pointer, checks if the new inputted object if hovered, if so, then check if this&#39;s...
Definition: IGUIObject.cpp:303
int m_InternalNameNumber
Number of object that has been given name automatically.
Definition: CGUI.h:650
std::string GetElementString(const int ID) const
Definition: XeroXMB.cpp:148
CGUISpriteInstance m_SpriteButtonBottomOver
std::map< CStr, SGUIIcon > m_Icons
Definition: CGUI.h:682
Made to represent screen positions and delta values.
Definition: Overlay.h:167
InReaction SendEvent(EGUIMessageType type, const CStr &EventName)
Send event to this GUI object (HandleMessage and ScriptEvent)
Definition: IGUIObject.cpp:466
void Xeromyces_ReadColor(XMBElement Element, CXeromyces *pFile)
Reads in the element &lt;color&gt; (the XMBElement) and stores the result in m_PreDefinedColors.
Definition: CGUI.cpp:1906
double m_LastClickTime[6]
Definition: IGUIObject.h:522
VfsPath m_TextureName
Definition: CGUISprite.h:86
std::map< CStr, IGUIObject * > map_pObjects
Definition: GUIbase.h:154
A CGUISprite is actually a collage of several real sprites, this struct represents is such real sprit...
Definition: CGUISprite.h:77
virtual void Draw()=0
Draws the object.
CStr8 Value
Definition: XeroXMB.h:226
The GUI sprite, is actually several real sprites (images) like a collage.
Definition: CGUISprite.h:150
CGUISpriteInstance m_SpriteBarVertical
CGUISpriteInstance m_SpriteBarVerticalPressed
#define ELMT(x)
bool IsEmpty() const
Definition: CGUISprite.cpp:38
IGUIObject * m_BaseObject
Base Object, all its children are considered parentless because this is not a real object per se...
Definition: CGUI.h:626
void Xeromyces_ReadStyle(XMBElement Element, CXeromyces *pFile)
Reads in the element &lt;style&gt; (the XMBElement) and stores the result in m_Styles.
Definition: CGUI.cpp:1704
CColor m_BorderColor
Definition: CGUISprite.h:127
map_pObjects m_pAllObjects
Just pointers for fast name access, each object is really constructed within its parent for easy recu...
Definition: CGUI.h:642
void SetupSpriteCall(const bool Left, SGUIText::SSpriteCall &SpriteCall, const float width, const float y, const CSize &Size, const CStr &TextureName, const float BufferZone, const int CellID)
Definition: CGUI.cpp:615
Wrapper class for OS paths used by the game.
Definition: Paths.h:27
void Initialize()
Initializes the GUI, needs to be called before the GUI is used.
Definition: CGUI.cpp:430
float right
Definition: Overlay.h:159
XMBElement GetRoot() const
Definition: XeroXMB.cpp:84
Definition: Decompose.h:22
#define ATTR(x)
PSRETURN Load(const PIVFS &vfs, const VfsPath &filename)
Returns either PSRETURN_OK or PSRETURN_CVFSFile_LoadFailed.
Definition: Filesystem.cpp:117
void UpdateResolution()
Update Resolution, should be called every time the resolution of the OpenGL screen has been changed...
Definition: CGUI.cpp:513
CGUISpriteInstance m_SpriteBarVerticalOver
CGUI()
Definition: CGUI.cpp:392
void UpdateMouseOver(IGUIObject *const &pMouseOver)
Inputes the object that is currently hovered, this function updates this object accordingly (i...
Definition: IGUIObject.cpp:212
void DrawText(SGUIText &Text, const CColor &DefaultColor, const CPos &pos, const float &z, const CRect &clipping)
Draw a SGUIText object.
Definition: CGUI.cpp:941
PSRETURN SetSetting(const CStr &Setting, const CStrW &Value, const bool &SkipMessage=false)
Set a setting by string, regardless of what type it is.
Definition: IGUIObject.cpp:260
void LoadXmlFile(const VfsPath &Filename, boost::unordered_set< VfsPath > &Paths)
Load a GUI XML file into the GUI.
Definition: CGUI.cpp:1003
void Xeromyces_ReadEffects(XMBElement Element, CXeromyces *pFile, SGUIImageEffects &effects)
Reads in the element &lt;effect&gt; (the XMBElement) and stores the result within the SGUIImageEffects.
Definition: CGUI.cpp:1677
static PSRETURN SetSetting(IGUIObject *pObject, const CStr &Setting, const T &Value, const bool &SkipMessage=false)
Sets a value by name using a real datatype as input.
Definition: GUIutil.cpp:366
void AddObject(IGUIObject *pObject)
Adds an object to the GUI&#39;s object database Private, since you can only add objects through XML files...
Definition: CGUI.cpp:519
void Xeromyces_ReadSprite(XMBElement Element, CXeromyces *pFile)
Reads in the element &lt;sprite&gt; (the XMBElement) and stores the result in a new CGUISprite.
Definition: CGUI.cpp:1448
CGUISpriteInstance m_SpriteButtonBottomPressed
float y
Definition: Overlay.h:195
std::list< SGUIText::SSpriteCall > m_SpriteCalls
Definition: GUItext.h:272
float GetHeight() const
Definition: Overlay.cpp:237
SDL_keysym keysym
Definition: wsdl.h:196
std::map< CStr, SGUIScrollBarStyle > m_ScrollBarStyles
Definition: CGUI.h:679
bool m_NewLine
If the word inputted was a new line.
Definition: GUItext.h:283
void SendEventToAll(const CStr &EventName)
Sends a specified script event to every object.
Definition: CGUI.cpp:306
#define debug_warn(expr)
display the error dialog with the given text.
Definition: debug.h:324
void AddToPointersMap(map_pObjects &ObjectMap)
Adds object and its children to the map, it&#39;s name being the first part, and the second being itself...
Definition: IGUIObject.cpp:138
void Draw(CRect Size, int CellID, std::map< CStr, CGUISprite > &Sprites, float Z) const
Definition: CGUISprite.cpp:21
bool m_MouseHovering
This is an array of true or false, each element is associated with a string representing a setting...
Definition: IGUIObject.h:539
SDL_UserEvent user
Definition: wsdl.h:312
EAlign
Definition: GUIbase.h:150
int GetAttributeID(const char *Name) const
Definition: XeroXMB.cpp:124
CSize m_CellSize
Definition: CGUISprite.h:103
const double SELECT_DBLCLICK_RATE
Definition: CGUI.cpp:65
void Xeromyces_ReadIcon(XMBElement Element, CXeromyces *pFile)
Reads in the element &lt;icon&gt; (the XMBElement) and stores the result in m_Icons.
Definition: CGUI.cpp:1831
std::string GetAttributeString(const int ID) const
Definition: XeroXMB.cpp:156
float cy
Definition: Overlay.h:234
static void RecurseObject(int RR, IGUIObject *pObject, void_Object_pFunction_argT pFunc, const T &Argument)
If you want to call a IGUIObject-function on not just an object, but also on ALL of their children yo...
Definition: GUIutil.h:274
CSize m_Size
Definition: GUIbase.h:167
Message send to IGUIObject::HandleMessage() in order to give life to Objects manually with a derived ...
Definition: GUIbase.h:106
CGUISpriteInstance m_SpriteButtonBottom
XMBElement Item(const int id)
Definition: XeroXMB.cpp:233
void Xeromyces_ReadTooltip(XMBElement Element, CXeromyces *pFile)
Reads in the element &lt;tooltip&gt; (the XMBElement) and stores the result as an object with the name __to...
Definition: CGUI.cpp:1879
float bottom
Definition: Overlay.h:159
std::map< CStr, ConstructObjectFunction > m_ObjectTypes
Function pointers to functions that constructs IGUIObjects by name...
Definition: CGUI.h:657
IGUIObject * FindObjectByName(const CStr &Name) const
Returns the GUI object with the desired name, or NULL if no match is found,.
Definition: CGUI.cpp:568
PIVFS g_VFS
Definition: Filesystem.cpp:30
std::list< SSpriteCall > m_SpriteCalls
List of sprites, or &quot;icons&quot; that should be rendered along with the text.
Definition: GUItext.h:155
virtual void HandleMessage(SGUIMessage &Message)
This function is called with different messages for instance when the mouse enters the object...
Definition: IGUIObject.h:322
CGUISpriteInstance m_SpriteBackVertical
SDLKey sym
Definition: wsdl.h:188
float x
Position.
Definition: Overlay.h:195
void LoadStyle(CGUI &GUIinstance, const CStr &StyleName)
Loads a style.
Definition: IGUIObject.cpp:375
CGUISpriteInstance m_Sprite
Sprite from global GUI sprite database.
Definition: GUItext.h:79
Contains a list of values for new defaults to objects.
Definition: CGUI.h:73
String class, substitute for CStr, but that parses the tags and builds up a list of all text that wil...
Definition: GUItext.h:176
CClientArea m_TextureSize
Definition: CGUISprite.h:92
SGUIText GenerateText(const CGUIString &Text, const CStrW &Font, const float &Width, const float &BufferZone, const IGUIObject *pObject=NULL)
Generate a SGUIText object from the inputted string.
Definition: CGUI.cpp:644
float cx
Size.
Definition: Overlay.h:234
void Xeromyces_ReadRepeat(XMBElement Element, CXeromyces *pFile, IGUIObject *pParent, boost::unordered_set< VfsPath > &Paths)
Reads in the element &lt;repeat&gt;, which repeats its child &lt;object&gt;s &#39;count&#39; times, replacing the string &quot;[n...
Definition: CGUI.cpp:1390
GLint m_WrapMode
Texture wrapping mode (GL_REPEAT, GL_CLAMP_TO_EDGE, etc)
Definition: CGUISprite.h:120
InReaction HandleEvent(const SDL_Event_ *ev)
The replacement of Process(), handles an SDL_Event_.
Definition: CGUI.cpp:73
void SetFocusedObject(IGUIObject *pObject)
Change focus to new object.
Definition: CGUI.cpp:586
std::map< int32_t, bool > g_keys
g_keys: Key states, indexed by SDLK* constants.
Definition: Globals.cpp:29
SGUIIcon GetIcon(const CStr &str) const
Get Icon (a copy, can never be changed)
Definition: CGUI.h:278
void * data1
Definition: wsdl.h:282
An SGUIText object is a parsed string, divided into text-rendering components.
Definition: GUItext.h:62
int GetNodeName() const
Definition: XeroXMB.cpp:166
void Draw()
Displays the whole GUI.
Definition: CGUI.cpp:449
Rectangle class used for screen rectangles.
Definition: Overlay.h:71
Client Area is a rectangle relative to a parent rectangle.
Definition: GUIbase.h:179