5 #include <unordered_set>
35 using std::unordered_set;
62 GUIParentNode::GUIParentNode(
72 const string& backgroundImage,
74 const GUIColor& backgroundImageEffectColorMul,
75 const GUIColor& backgroundImageEffectColorAdd,
82 GUINode(screenNode, parentNode, id, flow, alignments, requestedConstraints, backgroundColor, backgroundImage, backgroundImageScale9Grid, backgroundImageEffectColorMul, backgroundImageEffectColorAdd, border, padding, showOn, hideOn, tooltip)
92 if (index < 0 || index >=
subNodes.size())
return nullptr;
94 auto detachedSubNode =
subNodes[index];
101 auto _parentControllerNode = parentControllerNode;
102 while (_parentControllerNode !=
nullptr) {
103 _parentControllerNode->getController()->onSubTreeChange();
104 _parentControllerNode = _parentControllerNode->getParentControllerNode();
115 auto _parentControllerNode = parentControllerNode;
116 while (_parentControllerNode !=
nullptr) {
117 _parentControllerNode->getController()->onSubTreeChange();
118 _parentControllerNode = _parentControllerNode->getParentControllerNode();
123 return detachedSubNode;
130 for (
auto subNode: detachedSubNodes) {
131 subNode->parentNode =
nullptr;
142 auto _parentControllerNode = parentControllerNode;
143 while (_parentControllerNode !=
nullptr) {
144 _parentControllerNode->getController()->onSubTreeChange();
145 _parentControllerNode = _parentControllerNode->getParentControllerNode();
156 auto _parentControllerNode = parentControllerNode;
157 while (_parentControllerNode !=
nullptr) {
158 _parentControllerNode->getController()->onSubTreeChange();
159 _parentControllerNode = _parentControllerNode->getParentControllerNode();
164 return detachedSubNodes;
173 for (
auto i = 0; i < detachedSubNodes.size(); i++) {
174 auto subNode = detachedSubNodes[i];
183 for (
auto i = 0; i <
subNodes.size(); i++) {
190 auto _parentControllerNode = parentControllerNode;
191 while (_parentControllerNode !=
nullptr) {
192 _parentControllerNode->getController()->onSubTreeChange();
193 _parentControllerNode = _parentControllerNode->getParentControllerNode();
201 for (
auto i = 0; i <
subNodes.size(); i++) {
211 if (
layouted ==
false || resetScrollOffsets ==
true) {
218 auto scrollableWidth = contentWidth - elementWidth;
219 if (scrollableWidth < 0.0f) scrollableWidth = 0.0;
227 auto scrollableHeight = contentHeight - elementHeight;
228 if (scrollableHeight < 0.0f) scrollableHeight = 0.0f;
235 auto _parentControllerNode = parentControllerNode;
236 while (_parentControllerNode !=
nullptr) {
237 _parentControllerNode->getController()->onSubTreeChange();
238 _parentControllerNode = _parentControllerNode->getParentControllerNode();
249 for (
auto i = 0; i <
subNodes.size(); i++) {
259 if (
layouted ==
false || resetScrollOffsets ==
true) {
266 auto scrollableWidth = contentWidth - elementWidth;
267 if (scrollableWidth < 0.0f) scrollableWidth = 0.0;
275 auto scrollableHeight = contentHeight - elementHeight;
276 if (scrollableHeight < 0.0f) scrollableHeight = 0.0f;
284 while (parentControllerNode !=
nullptr) {
285 parentControllerNode->getController()->onSubTreeChange();
286 parentControllerNode = parentControllerNode->getParentControllerNode();
297 "' already has a node attached with given node id '" +
309 auto detachedSubNode = otherParentNode->
detachSubNode(index);
310 if (detachedSubNode ==
nullptr)
return;
316 detachedSubNode->parentNode =
this;
317 subNodes.push_back(detachedSubNode);
320 for (
auto i = 0; i <
subNodes.size(); i++) {
336 while (parentControllerNode !=
nullptr) {
337 parentControllerNode->getController()->onSubTreeChange();
338 parentControllerNode = parentControllerNode->getParentControllerNode();
350 for (
auto subNode: detachedSubNodes) {
351 subNode->parentNode =
this;
356 for (
auto i = 0; i <
subNodes.size(); i++) {
372 while (parentControllerNode !=
nullptr) {
373 parentControllerNode->getController()->onSubTreeChange();
374 parentControllerNode = parentControllerNode->getParentControllerNode();
391 if (StringTools::equalsIgnoreCase(StringTools::trim(overflow),
"hidden") ==
true) {
394 if (StringTools::equalsIgnoreCase(StringTools::trim(overflow),
"downsize-children") ==
true) {
397 if (StringTools::equalsIgnoreCase(StringTools::trim(overflow),
"scroll") ==
true) {
400 if (overflow.empty() ==
true || StringTools::trim(overflow).length() == 0) {
404 "Unknown overflow '" +
454 for (
auto i = 0; i <
subNodes.size(); i++) {
463 for (
auto i = 0; i <
subNodes.size(); i++) {
465 if (guiSubNode->conditionsMet ==
false)
continue;
470 for (
auto i = 0; i <
subNodes.size(); i++) {
472 if (guiSubNode->conditionsMet ==
false)
continue;
473 guiSubNode->computedConstraints.alignmentLeft = Math::max(0, (
computedConstraints.
width - guiSubNode->computedConstraints.width) / 2);
477 for (
auto i = 0; i <
subNodes.size(); i++) {
479 if (guiSubNode->conditionsMet ==
false)
continue;
490 for (
auto i = 0; i <
subNodes.size(); i++) {
492 if (guiSubNode->conditionsMet ==
false)
continue;
497 for (
auto i = 0; i <
subNodes.size(); i++) {
499 if (guiSubNode->conditionsMet ==
false)
continue;
500 guiSubNode->computedConstraints.alignmentTop = Math::max(0, (
computedConstraints.
height - guiSubNode->computedConstraints.height) / 2);
504 for (
auto i = 0; i <
subNodes.size(); i++) {
506 if (guiSubNode->conditionsMet ==
false)
continue;
515 if (requireConditionsMet ==
true &&
conditionsMet ==
false)
return;
516 for (
auto i = 0; i <
subNodes.size(); i++) {
518 if (node->controller !=
nullptr) {
519 childControllerNodes.push_back(node);
529 childControllerNodes.clear();
535 for (
auto i = 0; i <
subNodes.size(); i++) {
545 for (
auto i = 0; i <
subNodes.size(); i++) {
547 guiSubNode->setConditionsMet();
570 auto renderOffsetXPixel = 0.0f;
571 auto renderOffsetYPixel = 0.0f;
572 for (
auto *_parentNode =
this; _parentNode !=
nullptr; _parentNode = _parentNode->parentNode) {
573 renderOffsetXPixel += _parentNode->childrenRenderOffsetX;
574 renderOffsetYPixel += _parentNode->childrenRenderOffsetY;
576 auto renderOffsetX = renderOffsetXPixel / (screenWidth / 2.0f);
577 auto renderOffsetY = renderOffsetYPixel / (screenHeight / 2.0f);
578 auto renderAreaLeft = renderAreaLeftCurrent;
579 auto renderAreaTop = renderAreaTopCurrent;
580 auto renderAreaRight = renderAreaRightCurrent;
581 auto renderAreaBottom = renderAreaBottomCurrent;
584 renderAreaLeft = ((left) / (screenWidth / 2.0f)) - renderOffsetXCurrent - 1.0f;
585 renderAreaTop = ((screenHeight - top) / (screenHeight / 2.0f)) + renderOffsetYCurrent - 1.0f;
586 renderAreaRight = ((left + width) / (screenWidth / 2.0f)) - renderOffsetXCurrent - 1.0f;
587 renderAreaBottom = ((screenHeight - top - height) / (screenHeight / 2.0f)) + renderOffsetYCurrent - 1.0f;
601 for (
auto i = 0; i <
subNodes.size(); i++) {
606 if (guiSubNode->layouted ==
false) {
619 float left = guiSubNode->computedConstraints.left + guiSubNode->computedConstraints.alignmentLeft + guiSubNode->border.left;
620 float top = guiSubNode->computedConstraints.top + guiSubNode->computedConstraints.alignmentTop + guiSubNode->border.top;
621 float width = guiSubNode->computedConstraints.width - guiSubNode->border.left - guiSubNode->border.right;
622 float height = guiSubNode->computedConstraints.height - guiSubNode->border.top - guiSubNode->border.bottom;
624 ((left) / (screenWidth / 2.0f)) - 1.0f,
625 ((screenHeight - top) / (screenHeight / 2.0f)) - 1.0f,
626 ((left + width) / (screenWidth / 2.0f)) - 1.0f,
627 ((screenHeight - top) / (screenHeight / 2.0f)) - 1.0f,
628 ((left + width) / (screenWidth / 2.0f)) - 1.0f,
629 ((screenHeight - top - height) / (screenHeight / 2.0f)) - 1.0f,
630 ((left) / (screenWidth / 2.0f)) - 1.0f,
631 ((screenHeight - top - height) / (screenHeight / 2.0f)) - 1.0f) ==
true) {
634 if (guiSubNode->hasEffects() ==
true) guiSubNode->applyEffects(guiRenderer);
635 guiSubNode->render(guiRenderer);
636 if (guiSubNode->hasEffects() ==
true) guiSubNode->undoEffects(guiRenderer);
654 if (guiSubNode->hasEffects() ==
true) guiSubNode->applyEffects(guiRenderer);
655 guiSubNode->render(guiRenderer);
656 if (guiSubNode->hasEffects() ==
true) guiSubNode->undoEffects(guiRenderer);
677 subNode->determineNodesByCoordinate(coordinate, nodeIds);
691 if (event->
getType() == GUIMouseEvent::MOUSEEVENT_WHEEL_MOVED) {
696 auto scrollableWidth = contentWidth - nodeWidth;
697 if (
static_cast<int>(nodeWidth) >=
static_cast<int>(contentWidth)) {
702 event->setProcessed(
true);
711 auto scrollableHeight = contentHeight - nodeHeight;
712 if (
static_cast<int>(nodeHeight) >=
static_cast<int>(contentHeight)) {
717 event->setProcessed(
true);
725 subNode->determineMouseEventNodes(event, floatingNode ==
true || subNode->flow ==
GUINode_Flow::FLOATING, eventNodeIds, eventFloatingNodeIds, flags);
735 for (
auto i = 0; i <
subNodes.size(); i++) {
747 for (
auto i = 0; i <
subNodes.size(); i++) {
759 while (parentControllerNode !=
nullptr) {
760 parentControllerNode->getController()->onSubTreeChange();
761 parentControllerNode = parentControllerNode->getParentControllerNode();
765 if (
layouted ==
false || resetScrollOffsets ==
true) {
772 auto scrollableWidth = contentWidth - elementWidth;
773 if (scrollableWidth < 0.0f) scrollableWidth = 0.0;
781 auto scrollableHeight = contentHeight - elementHeight;
782 if (scrollableHeight < 0.0f) scrollableHeight = 0.0f;
790 for (
auto i = 0; i <
subNodes.size(); i++) {
792 auto guiElementSubNode =
dynamic_cast<GUIElementNode*
>(guiSubNode);
793 if (guiElementSubNode !=
nullptr) {
796 guiElementSubNode->unsetMouseStates();
798 auto guiParentSubNode =
dynamic_cast<GUIParentNode*
>(guiSubNode);
static GUIScreenNode * parse(const string &pathName, const string &fileName, const unordered_map< string, string > &variables={}, const EngineMiniScript::ScriptVariable &miniScriptArguments=EngineMiniScript::ScriptVariable(), Context *context=nullptr)
Parses a GUI XML file.
GUIMouseEventType getType() const
static STATIC_DLL_IMPEXT string CONDITION_ONMOUSEOVER
static STATIC_DLL_IMPEXT string CONDITION_CLICK
GUINodeConditions & getActiveConditions()
GUI element node conditions.
bool remove(const string &condition)
Remove a condition.
GUI node controller base class.
GUI node horizontal alignment enum.
static STATIC_DLL_IMPEXT GUINode_AlignmentHorizontal * RIGHT
static STATIC_DLL_IMPEXT GUINode_AlignmentHorizontal * CENTER
static STATIC_DLL_IMPEXT GUINode_AlignmentHorizontal * LEFT
GUI node vertical alignment enum.
static STATIC_DLL_IMPEXT GUINode_AlignmentVertical * BOTTOM
static STATIC_DLL_IMPEXT GUINode_AlignmentVertical * CENTER
static STATIC_DLL_IMPEXT GUINode_AlignmentVertical * TOP
static STATIC_DLL_IMPEXT GUINode_Flow * FLOATING
static STATIC_DLL_IMPEXT GUINode_Flow * INTEGRATED
GUI node requested constraints requested constraints type enum.
static STATIC_DLL_IMPEXT GUINode_RequestedConstraints_RequestedConstraintsType * NONE
static STATIC_DLL_IMPEXT GUINode_RequestedConstraints_RequestedConstraintsType * PIXEL
static STATIC_DLL_IMPEXT GUINode_RequestedConstraints_RequestedConstraintsType * AUTO
virtual int getContentHeight()=0
static GUINode_RequestedConstraints_RequestedConstraintsType * getRequestedConstraintsType(const string &constraint, GUINode_RequestedConstraints_RequestedConstraintsType *defaultConstraintsType)
Get requested constraints type.
virtual void determineMouseEventNodes(GUIMouseEvent *event, bool floatingNode, unordered_set< string > &eventNodeIds, unordered_set< string > &eventFloatingNodeIds, int flags=DETERMINEMOUSEEVENTNODES_FLAG_NONE)
Determine mouse event nodes.
virtual int getContentWidth()=0
virtual void layoutOnDemand()
Layout on demand.
virtual void determineNodesByCoordinate(const Vector2 &coordinate, unordered_set< string > &nodeIds)
Determine nodes by coordinate.
virtual void render(GUIRenderer *guiRenderer)
Render.
unique_ptr< GUINodeController > controller
bool isEventBelongingToNode(GUIMouseEvent *event, Vector2 &nodeCoordinate)
Is event belonging to node.
GUINode_ComputedConstraints computedConstraints
virtual void setConditionsMet()
Set conditions met for this node and its subnodes.
GUIScreenNode * screenNode
bool shouldRender()
Returns if to render.
GUIParentNode * getParentControllerNode()
virtual void dispose()
Dispose node.
GUINode_Alignments alignments
bool isCoordinateBelongingToNode(const Vector2 &coordinate, Vector2 &nodeCoordinate)
Is coordinate belonging to node.
virtual void layout()
Layout.
static int getRequestedConstraintsValue(const string &constraint, int defaultConstraintsValue)
Get requested constraints value.
GUI parent node overflow enum.
static STATIC_DLL_IMPEXT GUIParentNode_Overflow * DOWNSIZE_CHILDREN
static STATIC_DLL_IMPEXT GUIParentNode_Overflow * HIDDEN
static STATIC_DLL_IMPEXT GUIParentNode_Overflow * SCROLL
GUI parent node base class thats supporting child nodes.
GUIParentNode_Overflow * overflowX
void getChildControllerNodes(vector< GUINode * > &childControllerNodes, bool requireConditionsMet=false)
Get child controller nodes.
void dispose() override
Dispose node.
virtual void computeHorizontalChildrenAlignment()
Compute horizontal children alignment.
float childrenRenderOffsetY
void setConditionsMet() override
Set conditions met for this node and its subnodes.
void getChildControllerNodesInternal(vector< GUINode * > &childControllerNodes, bool requireConditionsMet=false)
Get child controller nodes internal.
static GUIParentNode_Overflow * createOverflow(const string &overflow)
Create over flow.
void setChildrenRenderOffsetX(float childrenRenderOffSetX)
Set children render offset x.
GUIParentNode_Overflow * getOverflowX()
bool computeViewportCache
void removeSubNode(GUINode *node, bool resetScrollOffsets)
Remove sub node.
vector< GUINode * > vieportSubNodesCache
void replaceSubNodes(const string &xml, bool resetScrollOffsets)
Replace sub nodes with given XML.
void layout() override
Layout.
void clearSubNodes()
Clear sub nodes.
void unsetMouseStates()
Unset mouse over and click conditions on element nodes.
GUIParentNode_Overflow * getOverflowY()
vector< GUINode * > floatingNodesCache
void determineMouseEventNodes(GUIMouseEvent *event, bool floatingNode, unordered_set< string > &eventNodeIds, unordered_set< string > &eventFloatingNodeIds, int flags=DETERMINEMOUSEEVENTNODES_FLAG_NONE) override
Determine mouse event nodes.
void moveSubNodes(GUIParentNode *otherParentNode)
Move children nodes from other parent node into this parent node.
void render(GUIRenderer *guiRenderer) override
Render.
void moveSubNode(GUIParentNode *otherParentNode, int index)
Move children node from other parent node into this parent node.
GUINode * detachSubNode(int index)
Detach sub node at given index.
GUIParentNode_Overflow * overflowY
virtual void layoutSubNodes()
Layout sub nodes.
vector< GUINode * > subNodes
static GUINode_RequestedConstraints createRequestedConstraints(const string &left, const string &top, const string &width, const string &height, int factor)
Create requested constraints.
vector< GUINode * > detachSubNodes()
Detach sub nodes.
void setChildrenRenderOffsetY(float childrenRenderOffSetY)
Set children render offset y.
void addSubNode(GUINode *node)
Add sub node.
void determineNodesByCoordinate(const Vector2 &coordinate, unordered_set< string > &nodeIds) override
Determine nodes by coordinate.
float childrenRenderOffsetX
virtual void computeVerticalChildrenAlignment()
Compute vertical children alignment.
void addSubNodes(const string &xml, bool resetScrollOffsets)
Add sub nodes with given XML.
void invalidateRenderCaches()
Invalidate render caches.
GUI screen node that represents a screen that can be rendered via GUI system.
void invalidateLayout(GUINode *node)
Mark a node to be invalidated regarding layout.
bool removeNode(GUINode *node)
Add node.
bool addNode(GUINode *node)
Add node.
void setSubRenderAreaBottom(float renderAreaBottom)
Set sub render area bottom.
void setRenderAreaLeft(float renderAreaLeft)
Set up render area left.
float getRenderAreaBottom()
float getRenderAreaLeft()
void setRenderAreaRight(float renderAreaRight)
Set up render area right.
void setRenderAreaTop(float renderAreaTop)
Set up render area top.
void setSubRenderAreaRight(float renderAreaRight)
Set sub render area right.
void setSubRenderAreaLeft(float renderAreaLeft)
Set sub render area left.
bool isQuadVisible(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
void setSubRenderAreaTop(float renderAreaTop)
Set sub render area top.
void setRenderOffsetY(float renderOffsetY)
Set render offset y.
void setRenderAreaBottom(float renderAreaBottom)
Set up render area bottom.
float getRenderAreaRight()
void setRenderOffsetX(float renderOffsetX)
Set render offset x.
Vector2 class representing vector2 mathematical structure and operations with x, y components.
GUINode_AlignmentVertical * vertical
GUINode_AlignmentHorizontal * horizontal
GUI node computed constraints.
GUI node requested constraints entity.
GUINode_RequestedConstraints_RequestedConstraintsType * topType
GUINode_RequestedConstraints_RequestedConstraintsType * widthType
GUINode_RequestedConstraints_RequestedConstraintsType * leftType
GUINode_RequestedConstraints_RequestedConstraintsType * heightType
GUI node scale 9 grid entity.