QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskSGNode.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskSGNode.h"
7
8static inline void qskRemoveChildNode( QSGNode* parent, QSGNode* child )
9{
10 parent->removeChildNode( child );
11
12 if ( child->flags() & QSGNode::OwnedByParent )
13 delete child;
14
15}
16
17static inline void qskRemoveAllChildNodesAfter( QSGNode* parent, QSGNode* child )
18{
19 while ( auto sibling = parent->lastChild() )
20 {
21 if ( sibling == child )
22 return;
23
24 qskRemoveChildNode( parent, sibling );
25 }
26}
27
28static void qskInsertChildSorted( QSGNode* parent, QSGNode* child,
29 const QVector< quint8 >& roles )
30{
31 QSGNode* sibling = nullptr;
32
33 if ( parent->childCount() > 0 )
34 {
35 using namespace QskSGNode;
36
37 const int nodePos = roles.indexOf( nodeRole( child ) );
38
39 // in most cases we are appending, so let's start at the end
40
41 for ( auto childNode = parent->lastChild();
42 childNode != nullptr; childNode = childNode->previousSibling() )
43 {
44 const auto childNodeRole = nodeRole( childNode );
45 if ( childNodeRole == BackgroundRole )
46 {
47 sibling = childNode;
48 }
49 else
50 {
51 /*
52 Imperformant implementation, but as the number of roles is
53 usually < 5 we don't introduce some sort of support for faster lookups
54 */
55
56 const int index = roles.indexOf( nodeRole( childNode ) );
57 if ( index >= 0 && index < nodePos )
58 sibling = childNode;
59 }
60
61 if ( sibling != nullptr )
62 break;
63 }
64 }
65
66 if ( sibling )
67 parent->insertChildNodeAfter( child, sibling );
68 else
69 parent->prependChildNode( child );
70}
71
72void QskSGNode::setParentNode( QSGNode* node, QSGNode* parent )
73{
74 if ( node )
75 {
76 auto oldParent = node->parent();
77
78 if ( oldParent != parent )
79 {
80 if ( oldParent )
81 oldParent->removeChildNode( node );
82
83 if ( parent )
84 parent->appendChildNode( node );
85 }
86 }
87}
88
89QSGNode* QskSGNode::findChildNode( QSGNode* parent, quint8 role )
90{
91 auto node = parent->firstChild();
92 while ( node )
93 {
94 if ( nodeRole( node ) == role )
95 return node;
96
97 node = node->nextSibling();
98 }
99
100 return nullptr;
101}
102
103bool QskSGNode::removeChildNode( QSGNode* parent, quint8 role )
104{
105 if ( auto node = findChildNode( parent, role ) )
106 {
107 qskRemoveChildNode( parent, node );
108 return true;
109 }
110
111 return false;
112}
113
114void QskSGNode::removeAllChildNodesAfter( QSGNode* parent, QSGNode* child )
115{
116 if ( parent && child && child->parent() == parent )
117 qskRemoveAllChildNodesAfter( parent, child );
118}
119
120void QskSGNode::removeAllChildNodesFrom( QSGNode* parent, QSGNode* child )
121{
122 if ( parent && child && child->parent() == parent )
123 {
124 qskRemoveAllChildNodesAfter( parent, child );
125 qskRemoveChildNode( parent, child );
126 }
127}
128
129void QskSGNode::replaceChildNode(
130 const QVector< quint8 >& roles, quint8 role,
131 QSGNode* parentNode, QSGNode* oldNode, QSGNode* newNode )
132{
133 if ( newNode && newNode->parent() != parentNode )
134 {
135 setNodeRole( newNode, role );
136
137 switch ( role )
138 {
139 case BackgroundRole:
140 {
141 parentNode->prependChildNode( newNode );
142 break;
143 }
144 case DebugRole:
145 {
146 auto firstNode = parentNode->firstChild();
147
148 if ( firstNode && ( nodeRole( firstNode ) == BackgroundRole ) )
149 parentNode->insertChildNodeAfter( newNode, firstNode );
150 else
151 parentNode->prependChildNode( newNode );
152
153 break;
154 }
155 default:
156 {
157 qskInsertChildSorted( parentNode, newNode, roles );
158 }
159 }
160 }
161
162 if ( oldNode && oldNode != newNode )
163 {
164 parentNode->removeChildNode( oldNode );
165 if ( oldNode->flags() & QSGNode::OwnedByParent )
166 delete oldNode;
167 }
168}
169
170void QskSGNode::resetGeometry( QSGGeometryNode* node )
171{
172 if ( node )
173 {
174 if ( auto g = node->geometry() )
175 {
176 const bool hasVertices = g->vertexCount() > 0;
177 const bool hasIndexes = g->indexCount() > 0;
178
179 if ( hasVertices || hasIndexes )
180 {
181 g->allocate( 0, 0 );
182
183 if ( hasVertices )
184 g->markVertexDataDirty();
185
186 if ( hasIndexes )
187 g->markIndexDataDirty();
188
189 node->markDirty( QSGNode::DirtyGeometry );
190 }
191 }
192 }
193}