TDME2  1.9.200
GUI.cpp
Go to the documentation of this file.
1 #include <tdme/gui/GUI.h>
2 
3 #if defined(__APPLE__)
4  #include <Carbon/Carbon.h>
5 #endif
6 
7 #include <algorithm>
8 #include <map>
9 #include <string>
10 #include <unordered_map>
11 #include <unordered_set>
12 #include <vector>
13 
14 #include <tdme/tdme.h>
15 #include <tdme/engine/Engine.h>
21 #include <tdme/gui/nodes/GUINode.h>
28 #include <tdme/gui/GUIParser.h>
30 #include <tdme/utilities/Console.h>
33 #include <tdme/utilities/Time.h>
34 
35 using std::find;
36 using std::map;
37 using std::remove;
38 using std::reverse;
39 using std::string;
40 using std::to_string;
41 using std::unordered_map;
42 using std::unordered_set;
43 using std::vector;
44 
58 using tdme::gui::GUI;
65 
66 bool GUI::disableTabFocusControl = false;
67 
68 GUI::GUI(Engine* engine, GUIRenderer* guiRenderer)
69 {
70  this->lastMouseButton = 0;
71  this->engine = engine;
72  this->guiRenderer = guiRenderer;
73  this->width = engine->getWidth();
74  this->height = engine->getHeight();
75 }
76 
78 }
79 
81 {
82 }
83 
84 void GUI::reshape(int width, int height)
85 {
86  this->width = width;
87  this->height = height;
88  for (const auto& [screenId, screen]: screens) {
89  reshapeScreen(screen);
90  }
91 }
92 
94 {
95  reset();
96 }
97 
98 void GUI::addScreen(const string& id, GUIScreenNode* screen)
99 {
100  if (id != screen->getId()) {
101  Console::println("GUI::addScreen(): screen id '" + id + "' must be '" + screen->getId() + "'");
102  return;
103  }
104  screens.emplace(id, screen);
105  reshapeScreen(screen);
106 }
107 
108 void GUI::removeScreen(const string& id)
109 {
110  auto screensIt = screens.find(id);
111  if (screensIt != screens.end()) {
112  removeRenderScreen(id);
113  auto screen = screensIt->second;
114  screens.erase(screensIt);
117  mousePressedEventNodeIds.erase(id);
118  mouseDraggingEventNodeIds.erase(id);
119  mouseIsDragging.erase(id);
120  delete screen;
121  }
122 }
123 
125 {
126  vector<string> entitiesToRemove;
127  for (const auto& [screenId, screen]: screens) {
128  entitiesToRemove.push_back(screenId);
129  }
130  for (auto i = 0; i < entitiesToRemove.size(); i++) {
131  removeScreen(entitiesToRemove[i]);
132  }
133  renderScreens.clear();
134 }
135 
137 {
138  // focussed node
139  unfocusNode();
140  focussedNodeScreenId.clear();
141  focussedNodeNodeId.clear();
142 
143  //
145 
146  // unset GUI
147  for (auto i = 0; i < renderScreens.size(); i++) {
148  renderScreens[i]->setGUI(nullptr);
149  }
150 
151  // clear
152  renderScreens.clear();
153 }
154 
155 void GUI::addRenderScreen(const string& screenId, int screenIdx)
156 {
157  auto screenIt = screens.find(screenId);
158  if (screenIt == screens.end()) return;
159 
160  //
162 
163  //
164  auto screen = screenIt->second;
165  screen->setGUI(this);
166  screen->setConditionsMet();
167  if (screenIdx == -1) {
168  renderScreens.push_back(screenIt->second);
169  } else {
170  renderScreens.insert(renderScreens.begin() + screenIdx, screenIt->second);
171  }
172 
173  // focussed node
174  focussedNodeScreenId.clear();
175  focussedNodeNodeId.clear();
177 
178  //
179  screen->initializeMiniScript();
180 }
181 
182 void GUI::removeRenderScreen(const string& screenId)
183 {
184  auto screenIt = screens.find(screenId);
185  if (screenIt == screens.end()) return;
186 
187  //
188  screenIt->second->setGUI(nullptr);
189 
190  //
192 
193  //
194  renderScreens.erase(remove(renderScreens.begin(), renderScreens.end(), screenIt->second), renderScreens.end());
195 }
196 
198 {
199  unfocusNode();
200  focussedNodeScreenId.clear();
201  focussedNodeNodeId.clear();
202 }
203 
205 {
206  focusableNodes.clear();
207  focusableScreenNodes.clear();
208  for (int i = renderScreens.size() - 1; i >= 0; i--) {
209  auto screen = renderScreens[i];
210  if (screen->isEnabled() == false)
211  continue;
212 
213  focusableScreenNodes.push_back(screen);
214  if (screen->isPopUp() == true)
215  break;
216 
217  }
218  for (int i = focusableScreenNodes.size() - 1; i >= 0; i--) {
219  auto screen = focusableScreenNodes[i];
220  screen->determineFocussedNodes(screen, focusableNodes);
221  }
222 }
223 
225 {
226  if (focussedNodeScreenId.empty() == true || focussedNodeNodeId.empty() == true) return nullptr;
227  auto focussedNodeScreen = getScreen(focussedNodeScreenId);
228  auto focussedNode = dynamic_cast<GUIElementNode*>(focussedNodeScreen != nullptr?focussedNodeScreen->getNodeById(focussedNodeNodeId):nullptr);
229  return focussedNode;
230 }
231 
233 {
234  if (focussedNodeScreenId.empty() == true || focussedNodeNodeId.empty() == true) return;
235  auto focussedNodeScreen = getScreen(focussedNodeScreenId);
236  auto focussedNode = dynamic_cast<GUIElementNode*>(focussedNodeScreen != nullptr?focussedNodeScreen->getNodeById(focussedNodeNodeId):nullptr);
237  if (focussedNode != nullptr) {
238  focussedNode->getActiveConditions().remove(GUIElementNode::CONDITION_FOCUS);
239  focussedNode->getBorder().topColor = unfocussedNodeBorderTopColor;
240  focussedNode->getBorder().leftColor = unfocussedNodeBorderLeftColor;
241  focussedNode->getBorder().bottomColor = unfocussedNodeBorderBottomColor;
242  focussedNode->getBorder().rightColor = unfocussedNodeBorderRightColor;
243  if (focussedNode->getController() != nullptr) focussedNode->getController()->onFocusLost();
244  focussedNode->getScreenNode()->forwardUnfocus(focussedNode);
245  }
246 }
247 
249 {
250  auto focussedNodeScreen = getScreen(focussedNodeScreenId);
251  auto focussedNode = dynamic_cast<GUIElementNode*>(focussedNodeScreen != nullptr?focussedNodeScreen->getNodeById(focussedNodeNodeId):nullptr);
252  if (focussedNode != nullptr) {
253  focussedNode->getActiveConditions().add(GUIElementNode::CONDITION_FOCUS);
254  unfocussedNodeBorderTopColor = focussedNode->getBorder().topColor;
255  unfocussedNodeBorderLeftColor = focussedNode->getBorder().leftColor;
256  unfocussedNodeBorderBottomColor = focussedNode->getBorder().bottomColor;
257  unfocussedNodeBorderRightColor = focussedNode->getBorder().rightColor;
258  focussedNode->getBorder().topColor = focussedNodeScreen->getFoccussedBorderColor();
259  focussedNode->getBorder().leftColor = focussedNodeScreen->getFoccussedBorderColor();
260  focussedNode->getBorder().bottomColor = focussedNodeScreen->getFoccussedBorderColor();
261  focussedNode->getBorder().rightColor = focussedNodeScreen->getFoccussedBorderColor();
262  if (focussedNode->getController() != nullptr) focussedNode->getController()->onFocusGained();
263  focussedNode->getScreenNode()->forwardFocus(focussedNode);
264  }
265 }
266 
267 void GUI::setFoccussedNode(GUIElementNode* newFoccussedNode)
268 {
269  auto focussedNodeScreen = getScreen(focussedNodeScreenId);
270  auto focussedNode = dynamic_cast<GUIElementNode*>(focussedNodeScreen != nullptr?focussedNodeScreen->getNodeById(focussedNodeNodeId):nullptr);
271  if (focussedNode == newFoccussedNode) {
272  return;
273  }
274  unfocusNode();
276  this->focussedNodeScreenId = newFoccussedNode == nullptr?string():newFoccussedNode->getScreenNode()->getId();
277  this->focussedNodeNodeId = newFoccussedNode == nullptr?string():newFoccussedNode->getId();
278  if (newFoccussedNode != nullptr) focusNode();
279 }
280 
282 {
284  unfocusNode();
285  auto focussedNodeScreen = getScreen(focussedNodeScreenId);
286  auto focussedNode = dynamic_cast<GUIElementNode*>(focussedNodeScreen != nullptr?focussedNodeScreen->getNodeById(focussedNodeNodeId):nullptr);
287  if (focusableNodes.size() > 0) {
288  auto focussedNodeIdx = -1;
289  for (auto i = 0; i < focusableNodes.size(); i++) {
290  if (focussedNode == focusableNodes[i]) {
291  focussedNodeIdx = i;
292  }
293  }
294  auto focussedNextNodeIdx = (focussedNodeIdx + 1) % focusableNodes.size();
295  auto newFocussedNode = focusableNodes[focussedNextNodeIdx];
296  setFoccussedNode(newFocussedNode);
297  newFocussedNode->scrollToNodeX();
298  newFocussedNode->scrollToNodeY();
299  }
300 }
301 
303 {
305  unfocusNode();
306  auto focussedNodeScreen = getScreen(focussedNodeScreenId);
307  auto focussedNode = dynamic_cast<GUIElementNode*>(focussedNodeScreen != nullptr?focussedNodeScreen->getNodeById(focussedNodeNodeId):nullptr);
308  if (focusableNodes.size() > 0) {
309  auto focussedNodeIdx = -1;
310  for (auto i = 0; i < focusableNodes.size(); i++) {
311  if (focussedNode == focusableNodes[i]) {
312  focussedNodeIdx = i;
313  }
314  }
315  int focussedPreviousNodeIdx = (focussedNodeIdx - 1) % focusableNodes.size();
316  if (focussedPreviousNodeIdx < 0) focussedPreviousNodeIdx += focusableNodes.size();
317  auto newFocussedNode = focusableNodes[focussedPreviousNodeIdx];
318  setFoccussedNode(newFocussedNode);
319  newFocussedNode->scrollToNodeX();
320  newFocussedNode->scrollToNodeY();
321  }
322 }
323 
325 {
326  //
327  if (renderScreens.empty() == true)
328  return;
329 
330  // invalidate layouts
331  for (int i = renderScreens.size() - 1; i >= 0; i--) {
332  auto screen = renderScreens[i];
333 
334  if (screen->isEnabled() == false) continue;
335 
336  screen->invalidateLayouts();
337  screen->scrollToNodes();
338  }
339 
340  //
341  guiRenderer->setGUI(this);
342  engine->initGUIMode();
344  for (auto i = 0; i < renderScreens.size(); i++) {
345  auto screen = renderScreens[i];
346 
347  if (screen->isEnabled() == false) continue;
348 
349  //
350  screen->render(guiRenderer);
351  screen->renderFloatingNodes(guiRenderer);
352  }
354  engine->doneGUIMode();
355 }
356 
358  auto nodeId = node->getId();
359  auto screenNodeId = node->getScreenNode()->getId();
360  return
361  mousePressedEventNodeIds[screenNodeId].find(nodeId) != mousePressedEventNodeIds[screenNodeId].end() ||
362  mouseDraggingEventNodeIds[screenNodeId].find(nodeId) != mouseDraggingEventNodeIds[screenNodeId].end();
363 }
364 
365 void GUI::handleMouseEvent(GUINode* node, GUIMouseEvent* event, const unordered_set<string>& mouseOutCandidateEventNodeIds, const unordered_set<string>& mouseOutClickCandidateEventNodeIds, unordered_set<string>& mousePressedEventNodeIds, bool floatingNodes)
366 {
367  // handle each event
368  unordered_set<string> mouseEventNodeIgnore;
369  unordered_set<string> mouseEventNodeIds;
370 
371  //
372  event->setX((float)event->getXUnscaled() * (float)node->getScreenNode()->getScreenWidth() / (float)width + node->getScreenNode()->getGUIEffectOffsetX());
373  event->setY((float)event->getYUnscaled() * (float)node->getScreenNode()->getScreenHeight() / (float)height + node->getScreenNode()->getGUIEffectOffsetY());
374 
375  // if dragging only send events to dragging origin nodes
376  if (event->getType() == GUIMouseEvent::MOUSEEVENT_DRAGGED) {
377  mouseEventNodeIds = mouseDraggingEventNodeIds[node->getScreenNode()->getId()];
378  } else
379  if (event->getType() == GUIMouseEvent::MOUSEEVENT_RELEASED &&
380  mouseIsDragging[node->getScreenNode()->getId()] == true) {
381  mouseEventNodeIds = mouseDraggingEventNodeIds[node->getScreenNode()->getId()];
382  } else {
383  // otherwise continue with determining nodes that receive this event
384  if (floatingNodes == true) {
385  node->determineMouseEventNodes(event, node->flow == GUINode_Flow::FLOATING, mouseEventNodeIgnore, mouseEventNodeIds);
386  } else {
387  node->determineMouseEventNodes(event, node->flow == GUINode_Flow::FLOATING, mouseEventNodeIds, mouseEventNodeIgnore);
388  }
389  }
390 
391  // inject former mouse out candidates
392  for (const auto& eventNodeId: mouseOutCandidateEventNodeIds) {
393  mouseEventNodeIds.insert(eventNodeId);
394  }
395 
396  // inject former mouse out click candidates
397  for (const auto& eventNodeId: mouseOutClickCandidateEventNodeIds) {
398  mouseEventNodeIds.insert(eventNodeId);
399  }
400 
401  // sort this list by hierarichal ids and execute processing reversed
402  // means nodes deeper in the hierarchy are processed first
403  map<string, string> sortedMouseEventNodeIds;
404  for (const auto& eventNodeId: mouseEventNodeIds) {
405  // node event occurred on
406  auto eventNode = node->getScreenNode()->getNodeById(eventNodeId);
407  if (eventNode == nullptr) continue;
408  //
409  sortedMouseEventNodeIds[to_string(eventNode->isEventBelongingToNode(event) != true) + "_" + eventNode->getHierarchicalId()] = eventNodeId;
410  }
411  vector<string> sortedMouseEventNodeIdsVector;
412  for (const auto& [sortedMouseEventNodeId, sortedMouseEventNode]: sortedMouseEventNodeIds) {
413  sortedMouseEventNodeIdsVector.push_back(sortedMouseEventNode);
414  }
415  reverse(sortedMouseEventNodeIdsVector.begin(), sortedMouseEventNodeIdsVector.end());
416 
417  // handle mouse event for each node we collected
418  for (const auto& eventNodeId: sortedMouseEventNodeIdsVector) {
419  // node event occurred on
420  auto eventNode = node->getScreenNode()->getNodeById(eventNodeId);
421  if (eventNode == nullptr) continue;
422 
423  //
424  if (floatingNodes == false && eventNode->flow == GUINode_Flow::FLOATING) continue;
425 
426  // we only want to process drag event once
427  if (event->getType() == GUIMouseEvent::MOUSEEVENT_DRAGGED && event->isProcessed() == true) break;
428 
429  // controller node
430  auto controllerNode = eventNode;
431  if (controllerNode->getController() == nullptr) {
432  controllerNode = controllerNode->getParentControllerNode();
433  }
434  if (controllerNode == nullptr) continue;
435 
436  // this corresponding screen node could have been detached from GUI by removing it from render screens
437  if (eventNode->getScreenNode()->getGUI() == nullptr) continue;
438 
439  // handle event with determined controller
440  controllerNode->getController()->handleMouseEvent(eventNode, event);
441  }
442 
443  // compile list of gui node ids that received mouse PRESSED events
444  if (event->getType() == GUIMouseEvent::MOUSEEVENT_PRESSED) {
445  for (const auto& eventNodeId: mouseEventNodeIds) {
446  mousePressedEventNodeIds.insert(eventNodeId);
447  }
448  }
449 
450  // clear event node id list
451  mouseEventNodeIds.clear();
452 }
453 
455  // skip if processed
456  if (event->isProcessed() == true) return;
457 
458  // otherwise dispatch event to focussed node
459  if (focussedNodeScreenId.empty() == false && focussedNodeNodeId.empty() == false) {
460  auto focussedNodeScreen = getScreen(focussedNodeScreenId);
461  auto focussedNode = dynamic_cast<GUIElementNode*>(focussedNodeScreen != nullptr?focussedNodeScreen->getNodeById(focussedNodeNodeId):nullptr);
462  if (focussedNode != nullptr) focussedNode->handleKeyboardEvent(event);
463  }
464 
465  // skip if already processed
466  if (event->isProcessed() == true) return;
467 
468  //
469  switch (event->getKeyCode()) {
470  case (GUIKeyboardEvent::KEYCODE_TAB):
471  if (disableTabFocusControl == false) {
472  if (event->getType() == GUIKeyboardEvent::KEYBOARDEVENT_KEY_PRESSED) {
473  if (event->isShiftDown() == true) {
475  } else {
476  focusNextNode();
477  }
478  }
479  event->setProcessed(true);
480  }
481  break;
482  case (GUIKeyboardEvent::KEYCODE_LEFT_ALT):
483  case (GUIKeyboardEvent::KEYCODE_RIGHT_ALT):
484  {
485  altDown = event->getType() == GUIKeyboardEvent::KEYBOARDEVENT_KEY_PRESSED;
486  break;
487  }
488  case (GUIKeyboardEvent::KEYCODE_LEFT_CONTROL):
489  case (GUIKeyboardEvent::KEYCODE_RIGHT_CONTROL):
490  {
491  controlDown = event->getType() == GUIKeyboardEvent::KEYBOARDEVENT_KEY_PRESSED;
492  break;
493  }
494  case (GUIKeyboardEvent::KEYCODE_LEFT_SHIFT):
495  case (GUIKeyboardEvent::KEYCODE_RIGHT_SHIFT):
496  {
497  shiftDown = event->getType() == GUIKeyboardEvent::KEYBOARDEVENT_KEY_PRESSED;
498  break;
499  }
500  default:
501  {
502  break;
503  }
504  }
505 }
506 
507 void GUI::handleEvents(bool clearEvents)
508 {
509  //
510  unordered_map<string, unordered_set<string>> _mouseOutCandidateEventNodeIds;
511  unordered_map<string, unordered_set<string>> _mouseOutClickCandidateEventNodeIds;
512 
513  //
514  auto renderScreensCopy = renderScreens;
515 
516  // tooltips
517  if (mouseEvents.empty() == true && keyboardEvents.empty() == true) {
518  if (tooltipShown == false && Time::getCurrentMillis() - lastEventTime > TOOLTIP_TIME) {
519  //
520  map<string, GUINode*> tooltipFloatingNodes;
521  map<string, GUINode*> tooltipNodes;
522 
523  // handle floating nodes first
524  for (int i = renderScreensCopy.size() - 1; i >= 0; i--) {
525  auto screen = renderScreensCopy[i];
526 
527  // skip on invisible
528  if (screen->isEnabled() == false) continue;
529 
530  //
531  const auto& floatingNodes = screen->getFloatingNodes();
532  for (auto j = 0; j < floatingNodes.size(); j++) {
533  //
534  unordered_set<string> eventNodeIds;
535  unordered_set<string> eventFloatingNodeIds;
536 
537  //
538  auto floatingNode = floatingNodes[j];
539  // TODO: collect only nodes with tooltips
540  floatingNode->determineMouseEventNodes(&lastMouseEvent, floatingNode->flow == GUINode_Flow::FLOATING, eventNodeIds, eventFloatingNodeIds, GUINode::DETERMINEMOUSEEVENTNODES_FLAG_TOOLTIP);
541 
542  // collect as hierarchical ids -> node
543  for (const auto& eventFloatingNodeId: eventFloatingNodeIds) {
544  auto node = screen->getNodeById(eventFloatingNodeId);
545  tooltipFloatingNodes[node->getHierarchicalId()] = node;
546  }
547  for (const auto& eventNodeId: eventNodeIds) {
548  auto node = screen->getNodeById(eventNodeId);
549  tooltipFloatingNodes[node->getHierarchicalId()] = node;
550  }
551  }
552  // skip on pop ups
553  if (screen->isPopUp() == true) break;
554  }
555 
556  // handle normal screen nodes if not processed already by floating node
557  for (int i = renderScreensCopy.size() - 1; i >= 0; i--) {
558  //
559  unordered_set<string> eventNodeIds;
560  unordered_set<string> eventFloatingNodeIds;
561 
562  //
563  auto screen = renderScreensCopy[i];
564  if (screen->isEnabled() == false) continue;
565 
566  //
567  screen->determineMouseEventNodes(&lastMouseEvent, screen->flow == GUINode_Flow::FLOATING, eventNodeIds, eventFloatingNodeIds, GUINode::DETERMINEMOUSEEVENTNODES_FLAG_TOOLTIP);
568 
569  // collect as hierarchical ids -> node
570  for (const auto& eventFloatingNodeId: eventFloatingNodeIds) {
571  auto node = screen->getNodeById(eventFloatingNodeId);
572  tooltipNodes[node->getHierarchicalId()] = node;
573  }
574  for (const auto& eventNodeId: eventNodeIds) {
575  auto node = screen->getNodeById(eventNodeId);
576  tooltipNodes[node->getHierarchicalId()] = node;
577  }
578 
579  //
580  if (screen->isPopUp() == true) break;
581  }
582 
583  //
584  if (tooltipFloatingNodes.empty() == false) {
585  vector<GUINode*> tooltipFloatingNodesVector;
586  for (const auto& [tooltipFloatingNodeId, tooltipFloatingNode]: tooltipFloatingNodes) {
587  tooltipFloatingNodesVector.push_back(tooltipFloatingNode);
588  }
589  reverse(tooltipFloatingNodesVector.begin(), tooltipFloatingNodesVector.end());
590  //
591  auto node = tooltipFloatingNodesVector[0];
592  node->getScreenNode()->forwardTooltipShowRequest(node, lastMouseEvent.getXUnscaled(), lastMouseEvent.getYUnscaled());
593  } else
594  if (tooltipNodes.empty() == false) {
595  vector<GUINode*> tooltipNodesVector;
596  for (const auto& [tooltipNodeId, tooltipNode]: tooltipNodes) {
597  tooltipNodesVector.push_back(tooltipNode);
598  }
599  reverse(tooltipNodesVector.begin(), tooltipNodesVector.end());
600 
601  //
602  auto node = tooltipNodesVector[0];
603  node->getScreenNode()->forwardTooltipShowRequest(node, lastMouseEvent.getXUnscaled(), lastMouseEvent.getYUnscaled());
604  }
605 
606  //
607  tooltipShown = true;
608  }
609  } else
610  if (tooltipShown == true) {
611  // close tooltip
612  tooltipShown = false;
613  //
614  for (int i = renderScreensCopy.size() - 1; i >= 0; i--) {
615  //
616  auto screen = renderScreensCopy[i];
617 
618  //
619  screen->forwardTooltipCloseRequest();
620  }
621  }
622 
623  // handle mouse events
624  for (auto& event: mouseEvents) {
625  //
626  lastEventTime = event.getTime();
627 
628  // fetch and clear last mouse out candidates as we now will actually send them
629  if (event.getType() == GUIMouseEvent::MOUSEEVENT_MOVED) {
630  _mouseOutCandidateEventNodeIds = mouseOutCandidateEventNodeIds;
632  } else
633  if (event.getType() == GUIMouseEvent::MOUSEEVENT_PRESSED || event.getType() == GUIMouseEvent::MOUSEEVENT_RELEASED) {
634  _mouseOutClickCandidateEventNodeIds = mouseOutClickCandidateEventNodeIds;
636  }
637 
638  // handle mouse dragged event
639  if (event.getType() == GUIMouseEvent::MOUSEEVENT_DRAGGED) {
640  for (int i = renderScreensCopy.size() - 1; i >= 0; i--) {
641  auto screen = renderScreensCopy[i];
642  if (mouseIsDragging[screen->getId()] == false) {
643  mouseIsDragging[screen->getId()] = true;
644  mouseDraggingEventNodeIds[screen->getId()] = mousePressedEventNodeIds[screen->getId()];
645  }
646  }
647  }
648 
649  // handle floating nodes first
650  for (int i = renderScreensCopy.size() - 1; i >= 0; i--) {
651  auto screen = renderScreensCopy[i];
652 
653  // skip on invisible
654  if (screen->isEnabled() == false) continue;
655 
656  //
657  auto processed = false;
658  const auto& floatingNodes = screen->getFloatingNodes();
659  for (auto j = 0; j < floatingNodes.size(); j++) {
660  auto floatingNode = floatingNodes[j];
661 
662  handleMouseEvent(floatingNode, &event, _mouseOutCandidateEventNodeIds[screen->getId()], _mouseOutClickCandidateEventNodeIds[screen->getId()], mousePressedEventNodeIds[screen->getId()], true);
663 
664  // do not continue handling mouse events if already processed
665  if (event.isProcessed() == true) break;
666 
667  // We do not consume mouse moved events by default, so:
668  // consume mouse move event, if floating node has conditions met and is expanded/collapsed by condition
669  // as in this case you do not want to have other mouse movement event handling
670  if ((event.getType() == GUIMouseEvent::MOUSEEVENT_MOVED || floatingNode->isEventBelongingToNode(&event) == true) &&
671  floatingNode->flow == GUINode_Flow::FLOATING &&
672  floatingNode->conditionsMet == true &&
673  ((floatingNode->showOn.getConditions().empty() == false && floatingNode->showOn.has("always") == false) ||
674  (floatingNode->hideOn.getConditions().empty() == false && floatingNode->showOn.has("never") == false))) processed = true;
675  }
676  // do not continue handling mouse events if already processed
677  if (event.isProcessed() == true) break;
678  // set processed if we decided to do so :D
679  if (processed == true) event.setProcessed(true);
680  // skip on pop ups
681  if (screen->isPopUp() == true) break;
682  }
683 
684  // handle normal screen nodes if not processed already by floating node
685  // Note: Different screens should not have UI elements that overlap and process events
686  if (event.isProcessed() == false) {
687  for (int i = renderScreensCopy.size() - 1; i >= 0; i--) {
688  auto screen = renderScreensCopy[i];
689  if (screen->isEnabled() == false) continue;
690  handleMouseEvent(screen, &event, _mouseOutCandidateEventNodeIds[screen->getId()], _mouseOutClickCandidateEventNodeIds[screen->getId()], mousePressedEventNodeIds[screen->getId()], false);
691  if (screen->isPopUp() == true) break;
692  }
693  }
694 
695  // handle mouse released event
696  if (event.getType() == GUIMouseEvent::MOUSEEVENT_RELEASED) {
697  for (int i = renderScreensCopy.size() - 1; i >= 0; i--) {
698  auto screen = renderScreensCopy[i];
699  mouseIsDragging[screen->getId()] = false;
700  mouseDraggingEventNodeIds.erase(screen->getId());
701  mousePressedEventNodeIds.erase(screen->getId());
702  }
703  // unfocus foccussed node, if GUIMouseEvent::MOUSEEVENT_RELEASED event with left mouse button was not processed,
704  // means you were not clicking on a element,button,...
705  if (event.getButton() == GUIMouseEvent::MOUSEEVENT_BUTTON_LEFT && event.isProcessed() == false) setFoccussedNode(nullptr);
706  }
707  }
708 
709  //
710  if (mouseEvents.empty() == false) {
711  lastMouseEvent = mouseEvents[mouseEvents.size() - 1];
712  }
713 
714  // handle keyboard events
715  for (auto& event: keyboardEvents) {
716  //
717  lastEventTime = event.getTime();
718  //
719  handleKeyboardEvent(&event);
720  }
721 
722  // call tick and input event handler
723  for (int i = renderScreensCopy.size() - 1; i >= 0; i--) {
724  auto screen = renderScreensCopy[i];
725  if (screen->isEnabled() == false) continue;
726  screen->tick();
727  if (screen->getInputEventHandler() != nullptr) {
728  screen->getInputEventHandler()->handleInputEvents();
729  }
730  screen->forwardEvents();
731  if (screen->getMiniScript() != nullptr) {
732  screen->getMiniScript()->collectHIDEvents(mouseEvents, keyboardEvents);
733  }
734  if (screen->isPopUp() == true) break;
735  }
736 
737  // clear events
738  for (auto screen: renderScreensCopy) {
739  screen->clearEvents();
740  }
741 
742  //
743  if (clearEvents == true) {
744  mouseEvents.clear();
745  keyboardEvents.clear();
746  }
747 
748  //
749  for (int i = 0; i < renderScreensCopy.size(); i++) {
750  auto screen = renderScreensCopy[i];
751  // miniscript?
752  auto screenMiniScript = screen->getMiniScript();
753  if (screenMiniScript == nullptr) continue;
754  // pop screen if requested
755  if (screenMiniScript->isPopped() == true) {
756  removeScreen(screen->getId());
757  continue;
758  }
759  // try to goTo next screen
760  auto nextScreen = screenMiniScript->releaseNextScreenNode();
761  if (nextScreen == nullptr) continue;
762  auto screenIt = find(renderScreens.begin(), renderScreens.end(), screen);
763  if (screenIt != renderScreens.end()) {
764  auto screenIdx = screenIt - renderScreens.begin();
765  removeScreen(screen->getId());
766  addScreen(nextScreen->getId(), nextScreen);
767  addRenderScreen(nextScreen->getId(), screenIdx);
768  }
769  }
770 }
771 
772 void GUI::onChar(int key, int x, int y) {
774  GUIKeyboardEvent guiKeyboardEvent;
775  guiKeyboardEvent.setTime(Time::getCurrentMillis());
776  guiKeyboardEvent.setType(GUIKeyboardEvent::KEYBOARDEVENT_KEY_TYPED);
777  guiKeyboardEvent.setKeyCode(-1);
778  guiKeyboardEvent.setKeyChar(key);
779  guiKeyboardEvent.setMetaDown(false);
780  guiKeyboardEvent.setControlDown(controlDown);
781  guiKeyboardEvent.setAltDown(altDown);
782  guiKeyboardEvent.setShiftDown(shiftDown);
783  guiKeyboardEvent.setRepeat(false);
784  guiKeyboardEvent.setProcessed(false);
785  keyboardEvents.push_back(guiKeyboardEvent);
786 }
787 
788 void GUI::onKeyDown (int key, int keyCode, int x, int y, bool repeat, int modifiers) {
790  GUIKeyboardEvent guiKeyboardEvent;
791  guiKeyboardEvent.setTime(Time::getCurrentMillis());
792  guiKeyboardEvent.setType(GUIKeyboardEvent::KEYBOARDEVENT_KEY_PRESSED);
793  guiKeyboardEvent.setKeyCode(keyCode);
794  guiKeyboardEvent.setKeyChar(key);
795  guiKeyboardEvent.setMetaDown(false);
796  guiKeyboardEvent.setControlDown((modifiers & KEYBOARD_MODIFIER_CTRL) != 0);
797  guiKeyboardEvent.setAltDown((modifiers & KEYBOARD_MODIFIER_ALT) != 0);
798  guiKeyboardEvent.setShiftDown((modifiers & KEYBOARD_MODIFIER_SHIFT) != 0);
799  guiKeyboardEvent.setRepeat(repeat);
800  guiKeyboardEvent.setProcessed(false);
801  keyboardEvents.push_back(guiKeyboardEvent);
802 }
803 
804 void GUI::onKeyUp(int key, int keyCode, int x, int y) {
806  GUIKeyboardEvent guiKeyboardEvent;
807  guiKeyboardEvent.setTime(Time::getCurrentMillis());
808  guiKeyboardEvent.setType(GUIKeyboardEvent::KEYBOARDEVENT_KEY_RELEASED);
809  guiKeyboardEvent.setKeyCode(keyCode);
810  guiKeyboardEvent.setKeyChar(key);
811  guiKeyboardEvent.setMetaDown(false);
812  guiKeyboardEvent.setControlDown(controlDown);
813  guiKeyboardEvent.setAltDown(altDown);
814  guiKeyboardEvent.setShiftDown(shiftDown);
815  guiKeyboardEvent.setRepeat(false);
816  guiKeyboardEvent.setProcessed(false);
817  keyboardEvents.push_back(guiKeyboardEvent);
818 }
819 
820 void GUI::onMouseDragged(int x, int y) {
821  GUIMouseEvent guiMouseEvent;
822  guiMouseEvent.setTime(Time::getCurrentMillis());
823  guiMouseEvent.setType(GUIMouseEvent::MOUSEEVENT_DRAGGED);
824  guiMouseEvent.setXUnscaled(x);
825  guiMouseEvent.setYUnscaled(y);
826  guiMouseEvent.setX(x);
827  guiMouseEvent.setY(y);
828  guiMouseEvent.setButton(lastMouseButton);
829  guiMouseEvent.setWheelX(0.0f);
830  guiMouseEvent.setWheelY(0.0f);
831  guiMouseEvent.setWheelZ(0.0f);
832  guiMouseEvent.setControlDown(controlDown);
833  guiMouseEvent.setAltDown(altDown);
834  guiMouseEvent.setShiftDown(shiftDown);
835  guiMouseEvent.setProcessed(false);
836  mouseEvents.push_back(guiMouseEvent);
837 }
838 
839 void GUI::onMouseMoved(int x, int y) {
840  GUIMouseEvent guiMouseEvent;
841  guiMouseEvent.setTime(Time::getCurrentMillis());
842  guiMouseEvent.setType(GUIMouseEvent::MOUSEEVENT_MOVED);
843  guiMouseEvent.setXUnscaled(x);
844  guiMouseEvent.setYUnscaled(y);
845  guiMouseEvent.setX(x);
846  guiMouseEvent.setY(y);
847  guiMouseEvent.setButton(0);
848  guiMouseEvent.setWheelX(0.0f);
849  guiMouseEvent.setWheelY(0.0f);
850  guiMouseEvent.setWheelZ(0.0f);
851  guiMouseEvent.setControlDown(controlDown);
852  guiMouseEvent.setAltDown(altDown);
853  guiMouseEvent.setShiftDown(shiftDown);
854  guiMouseEvent.setProcessed(false);
855  mouseEvents.push_back(guiMouseEvent);
856 }
857 
858 void GUI::onMouseButton(int button, int state, int x, int y) {
860 
861  lastMouseButton = button + 1;
862  GUIMouseEvent guiMouseEvent;
863  guiMouseEvent.setTime(Time::getCurrentMillis());
864  guiMouseEvent.setType(state == MOUSE_BUTTON_DOWN?GUIMouseEvent::MOUSEEVENT_PRESSED:GUIMouseEvent::MOUSEEVENT_RELEASED);
865  guiMouseEvent.setXUnscaled(x);
866  guiMouseEvent.setYUnscaled(y);
867  guiMouseEvent.setX(x);
868  guiMouseEvent.setY(y);
869  guiMouseEvent.setButton(lastMouseButton);
870  guiMouseEvent.setWheelX(0.0f);
871  guiMouseEvent.setWheelY(0.0f);
872  guiMouseEvent.setWheelZ(0.0f);
873  guiMouseEvent.setControlDown(controlDown);
874  guiMouseEvent.setAltDown(altDown);
875  guiMouseEvent.setShiftDown(shiftDown);
876  guiMouseEvent.setProcessed(false);
877  mouseEvents.push_back(guiMouseEvent);
878 }
879 
880 void GUI::onMouseWheel(int button, int direction, int x, int y) {
882 
883  lastMouseButton = button + 1;
884  GUIMouseEvent guiMouseEvent;
885  guiMouseEvent.setTime(Time::getCurrentMillis());
886  guiMouseEvent.setType(GUIMouseEvent::MOUSEEVENT_WHEEL_MOVED);
887  guiMouseEvent.setXUnscaled(x);
888  guiMouseEvent.setYUnscaled(y);
889  guiMouseEvent.setX(x);
890  guiMouseEvent.setY(y);
891  guiMouseEvent.setButton(lastMouseButton);
892  guiMouseEvent.setWheelX(0.0f);
893  guiMouseEvent.setWheelY(direction * 1.0f);
894  guiMouseEvent.setWheelZ(0.0f);
895  guiMouseEvent.setControlDown(controlDown);
896  guiMouseEvent.setAltDown(altDown);
897  guiMouseEvent.setShiftDown(shiftDown);
898  guiMouseEvent.setProcessed(false);
899  mouseEvents.push_back(guiMouseEvent);
900 }
901 
903  bool isControlDown = false;
904  bool isAltDown = false;
905  bool isShiftDown = false;
906  #if defined(__APPLE__)
907  KeyMap keys;
908  GetKeys(keys);
909  #define IS_KEY_DOWN(key, var) \
910  { \
911  uint8_t index = key / 32 ; \
912  uint8_t shift = key % 32 ; \
913  var = keys[index].bigEndianValue & (1 << shift); \
914  }
915  IS_KEY_DOWN(kVK_Command, isControlDown);
916  IS_KEY_DOWN(kVK_Option, isAltDown);
917  IS_KEY_DOWN(kVK_Shift, isShiftDown);
918  #endif
919 
920  if (isControlDown == false &&
921  isAltDown == false &&
922  isShiftDown == false) {
923  return;
924  }
925 
926  GUIKeyboardEvent guiKeyboardEvent;
927  guiKeyboardEvent.setTime(Time::getCurrentMillis());
928  guiKeyboardEvent.setType(GUIKeyboardEvent::KEYBOARDEVENT_KEY_PRESSED);
929  guiKeyboardEvent.setKeyCode(-1);
930  guiKeyboardEvent.setKeyChar(-1);
931  guiKeyboardEvent.setMetaDown(false);
932  guiKeyboardEvent.setControlDown(isControlDown);
933  guiKeyboardEvent.setAltDown(isAltDown);
934  guiKeyboardEvent.setShiftDown(isShiftDown);
935  guiKeyboardEvent.setProcessed(false);
936  keyboardEvents.push_back(guiKeyboardEvent);
937 }
938 
940  // TODO: maybe move logic into GUIScreenNode
941  // FIXME: always keep aspect ratio
942  auto screenNodeWidthConstrained = width;
943  auto screenNodeHeightConstrained = height;
944 
945  auto minRatio = 1.0f;
946 
947  if ((screenNode->sizeConstraints.maxWidth > 0 && screenNodeWidthConstrained > screenNode->sizeConstraints.maxWidth) ||
948  (screenNode->sizeConstraints.maxHeight > 0 && screenNodeHeightConstrained > screenNode->sizeConstraints.maxHeight)) {
949  if (screenNode->sizeConstraints.maxWidth > 0 && screenNodeWidthConstrained > screenNode->sizeConstraints.maxWidth) {
950  minRatio = (float)screenNode->sizeConstraints.maxWidth / (float)width;
951  screenNodeWidthConstrained = screenNode->sizeConstraints.maxWidth;
952  screenNodeHeightConstrained = (int)((float)screenNodeHeightConstrained * minRatio);
953  }
954  if (screenNode->sizeConstraints.maxHeight > 0 && screenNodeHeightConstrained > screenNode->sizeConstraints.maxHeight) {
955  minRatio = (float)screenNode->sizeConstraints.maxHeight / (float)height;
956  screenNodeHeightConstrained = screenNode->sizeConstraints.maxHeight;
957  screenNodeWidthConstrained = (int)((float)screenNodeWidthConstrained * minRatio);
958  }
959  }
960  if ((screenNode->sizeConstraints.minWidth > 0 && screenNodeWidthConstrained < screenNode->sizeConstraints.minWidth) ||
961  (screenNode->sizeConstraints.minHeight > 0 && screenNodeHeightConstrained < screenNode->sizeConstraints.minHeight)) {
962  if (screenNode->sizeConstraints.minWidth > 0 && screenNodeWidthConstrained < screenNode->sizeConstraints.minWidth) {
963  auto ratio = (float)screenNode->sizeConstraints.minWidth / (float)width;
964  screenNodeWidthConstrained = screenNode->sizeConstraints.minWidth;
965  screenNodeHeightConstrained = (int)((float)screenNodeHeightConstrained * ratio / minRatio);
966  }
967  if (screenNode->sizeConstraints.minHeight > 0 && screenNodeHeightConstrained < screenNode->sizeConstraints.minHeight) {
968  auto ratio = (float)screenNode->sizeConstraints.minHeight / (float)height;
969  screenNodeHeightConstrained = screenNode->sizeConstraints.minHeight;
970  screenNodeWidthConstrained = (int)((float)screenNodeWidthConstrained * ratio / minRatio);
971  }
972  }
973 
974  screenNode->setScreenSize(screenNodeWidthConstrained, screenNodeHeightConstrained);
975 }
976 
978  for (auto screen: renderScreens) screen->unsetMouseStates();
979 }
#define KEYBOARD_MODIFIER_SHIFT
#define KEYBOARD_MODIFIER_ALT
#define MOUSE_BUTTON_DOWN
#define KEYBOARD_MODIFIER_CTRL
Engine main class.
Definition: Engine.h:131
int32_t getWidth()
Definition: Engine.h:1029
void doneGUIMode()
Set up GUI mode rendering.
Definition: Engine.cpp:2142
void initGUIMode()
Set up GUI mode rendering.
Definition: Engine.cpp:2130
int32_t getHeight()
Definition: Engine.h:1036
GUI parser.
Definition: GUIParser.h:40
GUI module class.
Definition: GUI.h:64
unordered_map< string, unordered_set< string > > mousePressedEventNodeIds
Definition: GUI.h:93
GUIColor unfocussedNodeBorderTopColor
Definition: GUI.h:79
void onMouseMoved(int x, int y) override
On mouse moved.
Definition: GUI.cpp:839
Engine * engine
Definition: GUI.h:71
bool controlDown
Definition: GUI.h:98
bool shiftDown
Definition: GUI.h:99
bool tooltipShown
Definition: GUI.h:88
GUIElementNode * getFocussedNode()
Definition: GUI.cpp:224
vector< GUIScreenNode * > renderScreens
Definition: GUI.h:83
string focussedNodeScreenId
Definition: GUI.h:75
bool altDown
Definition: GUI.h:97
unordered_map< string, unordered_set< string > > mouseOutCandidateEventNodeIds
Definition: GUI.h:91
void onMouseDragged(int x, int y) override
On mouse dragged.
Definition: GUI.cpp:820
int width
Definition: GUI.h:84
void initialize()
Init.
Definition: GUI.cpp:80
void focusPreviousNode()
Focus next node.
Definition: GUI.cpp:302
static STATIC_DLL_IMPEXT bool disableTabFocusControl
Definition: GUI.h:68
bool isHavingMouseInteraction(GUINode *node)
Reports if node has currently mouse interaction like dragging or pressing.
Definition: GUI.cpp:357
void removeRenderScreen(const string &screenId)
Remove render screen.
Definition: GUI.cpp:182
~GUI()
Destructor.
Definition: GUI.cpp:77
void handleEvents(bool clearEvents=true)
Handle screen events.
Definition: GUI.cpp:507
vector< GUIScreenNode * > focusableScreenNodes
Definition: GUI.h:74
void addRenderScreen(const string &screenId, int screenIdx=-1)
Add render screen.
Definition: GUI.cpp:155
vector< GUIElementNode * > focusableNodes
Definition: GUI.h:73
void onMouseButton(int button, int state, int x, int y) override
On mouse moved.
Definition: GUI.cpp:858
void handleMouseEvent(GUINode *node, GUIMouseEvent *event, const unordered_set< string > &mouseOutCandidateEventNodeIds, const unordered_set< string > &mouseOutClickCandidateEventNodeIds, unordered_set< string > &mousePressedEventNodeIds, bool floatingNodes)
Handle mouse event for given node.
Definition: GUI.cpp:365
unordered_map< string, bool > mouseIsDragging
Definition: GUI.h:95
void determineFocussedNodes()
Determine focussed nodes.
Definition: GUI.cpp:204
void onMouseWheel(int button, int direction, int x, int y) override
On mouse wheel.
Definition: GUI.cpp:880
GUIScreenNode * getScreen(const string &id)
Get screen.
Definition: GUI.h:222
unordered_map< string, GUIScreenNode * > screens
Definition: GUI.h:72
GUIRenderer * guiRenderer
Definition: GUI.h:70
void reshape(int width, int height)
Reshape.
Definition: GUI.cpp:84
string focussedNodeNodeId
Definition: GUI.h:76
void unfocusNode()
Unfocus current focussed node.
Definition: GUI.cpp:232
void unsetMouseStates()
Render screens change.
Definition: GUI.cpp:977
void render()
Render GUIs.
Definition: GUI.cpp:324
void onKeyUp(int key, int keyCode, int x, int y) override
On key up.
Definition: GUI.cpp:804
vector< GUIKeyboardEvent > keyboardEvents
Definition: GUI.h:82
static constexpr int64_t TOOLTIP_TIME
Definition: GUI.h:140
void setFoccussedNode(GUIElementNode *newFoccussedNode)
Set focussed node.
Definition: GUI.cpp:267
void onKeyDown(int key, int keyCode, int x, int y, bool repeat, int modifiers) override
On key down.
Definition: GUI.cpp:788
unordered_map< string, unordered_set< string > > mouseOutClickCandidateEventNodeIds
Definition: GUI.h:92
void focusNode()
Focus current focussed node.
Definition: GUI.cpp:248
void fakeKeyboardModifierEvent()
Fake a keyboard modifier event.
Definition: GUI.cpp:902
GUIColor unfocussedNodeBorderRightColor
Definition: GUI.h:78
void removeScreen(const string &id)
Removes an screen.
Definition: GUI.cpp:108
void addScreen(const string &id, GUIScreenNode *screen)
Add screen.
Definition: GUI.cpp:98
void onChar(int key, int x, int y) override
On char.
Definition: GUI.cpp:772
void dispose()
Dispose.
Definition: GUI.cpp:93
void invalidateFocussedNode()
Invalidate focussed node.
Definition: GUI.cpp:197
void reshapeScreen(GUIScreenNode *screenNode)
Reshape screen.
Definition: GUI.cpp:939
unordered_map< string, unordered_set< string > > mouseDraggingEventNodeIds
Definition: GUI.h:94
void focusNextNode()
Focus next node.
Definition: GUI.cpp:281
GUIColor unfocussedNodeBorderLeftColor
Definition: GUI.h:77
int height
Definition: GUI.h:85
void reset()
Removes all screens and caches.
Definition: GUI.cpp:124
GUIMouseEvent lastMouseEvent
Definition: GUI.h:89
int lastMouseButton
Definition: GUI.h:86
void handleKeyboardEvent(GUIKeyboardEvent *event)
Handle mouse event for given node.
Definition: GUI.cpp:454
void resetRenderScreens()
Reset render screens.
Definition: GUI.cpp:136
int64_t lastEventTime
Definition: GUI.h:87
GUIColor unfocussedNodeBorderBottomColor
Definition: GUI.h:80
vector< GUIMouseEvent > mouseEvents
Definition: GUI.h:81
void setKeyCode(int32_t code)
Set key code.
void setAltDown(bool altDown)
Set alt down.
void setProcessed(bool processed)
Set event processed.
void setType(GUIKeyboardEventType type)
Set type.
void setControlDown(bool controlDown)
Set control down.
GUIKeyboardEventType getType() const
void setKeyChar(int32_t keyChar)
Set key char.
void setTime(int64_t time)
Time in milliseconds.
void setMetaDown(bool metaDown)
Set meta down.
void setRepeat(bool repeat)
Set repeat.
void setShiftDown(bool shiftDown)
Set shift down.
GUIMouseEventType getType() const
Definition: GUIMouseEvent.h:78
void setYUnscaled(int yUnscaled)
Set y unscaled.
void setAltDown(bool altDown)
Set alt down.
void setWheelX(float wheelX)
Set up wheel x.
void setProcessed(bool processed)
Set processed.
void setControlDown(bool controlDown)
Set control down.
void setWheelZ(float wheelZ)
Set up wheel z.
void setXUnscaled(int xUnscaled)
Set x unscaled.
void setTime(int64_t time)
Set time.
Definition: GUIMouseEvent.h:71
void setButton(int button)
Set button.
void setShiftDown(bool shiftDown)
Set shift down.
void setType(GUIMouseEventType type)
Set type.
Definition: GUIMouseEvent.h:86
void setWheelY(float wheelY)
Set up wheel y.
void handleKeyboardEvent(GUIKeyboardEvent *event)
Handle keyboard event.
GUINodeConditions & getActiveConditions()
GUI element node conditions.
bool add(const string &condition)
Add a condition.
bool remove(const string &condition)
Remove a condition.
GUI node controller base class.
virtual void handleMouseEvent(GUINode *node, GUIMouseEvent *event)=0
Handle mouse event.
GUI node base class.
Definition: GUINode.h:64
virtual void determineMouseEventNodes(GUIMouseEvent *event, bool floatingNode, unordered_set< string > &eventNodeIds, unordered_set< string > &eventFloatingNodeIds, int flags=DETERMINEMOUSEEVENTNODES_FLAG_NONE)
Determine mouse event nodes.
Definition: GUINode.cpp:1030
GUINodeController * getController()
Definition: GUINode.h:661
GUIParentNode * getParentControllerNode()
Definition: GUINode.cpp:1011
GUIScreenNode * getScreenNode()
Definition: GUINode.h:325
const string & getId()
Definition: GUINode.h:339
GUINode_Flow * flow
Definition: GUINode.h:86
GUI screen node that represents a screen that can be rendered via GUI system.
Definition: GUIScreenNode.h:72
GUIScreenNode_SizeConstraints sizeConstraints
void setScreenSize(int width, int height)
Set screen size.
GUINode * getNodeById(const string &nodeId)
Get GUI node by id.
void initRendering()
Init rendering.
void doneRendering()
Done rendering.
void setGUI(GUI *gui)
Set GUI.
Definition: GUIRenderer.h:123
Console class.
Definition: Console.h:29
Properties class, which helps out with storeing or loading key value pairs from/to property files.
Definition: Properties.h:23
Time utility class.
Definition: Time.h:20
std::exception Exception
Exception base class.
Definition: Exception.h:18
GUI input event handler interface.
GUI node border entity.