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 if ( parent )
92 {
93 auto node = parent->firstChild();
94 while ( node )
95 {
96 if ( nodeRole( node ) == role )
97 return node;
98
99 node = node->nextSibling();
100 }
101 }
102
103 return nullptr;
104}
105
106bool QskSGNode::removeChildNode( QSGNode* parent, quint8 role )
107{
108 if ( auto node = findChildNode( parent, role ) )
109 {
110 qskRemoveChildNode( parent, node );
111 return true;
112 }
113
114 return false;
115}
116
117void QskSGNode::removeAllChildNodesAfter( QSGNode* parent, QSGNode* child )
118{
119 if ( parent && child && child->parent() == parent )
120 qskRemoveAllChildNodesAfter( parent, child );
121}
122
123void QskSGNode::removeAllChildNodesFrom( QSGNode* parent, QSGNode* child )
124{
125 if ( parent && child && child->parent() == parent )
126 {
127 qskRemoveAllChildNodesAfter( parent, child );
128 qskRemoveChildNode( parent, child );
129 }
130}
131
132void QskSGNode::replaceChildNode(
133 const QVector< quint8 >& roles, quint8 role,
134 QSGNode* parentNode, QSGNode* oldNode, QSGNode* newNode )
135{
136 if ( newNode && newNode->parent() != parentNode )
137 {
138 setNodeRole( newNode, role );
139
140 switch ( role )
141 {
142 case BackgroundRole:
143 {
144 parentNode->prependChildNode( newNode );
145 break;
146 }
147 case DebugRole:
148 {
149 auto firstNode = parentNode->firstChild();
150
151 if ( firstNode && ( nodeRole( firstNode ) == BackgroundRole ) )
152 parentNode->insertChildNodeAfter( newNode, firstNode );
153 else
154 parentNode->prependChildNode( newNode );
155
156 break;
157 }
158 default:
159 {
160 qskInsertChildSorted( parentNode, newNode, roles );
161 }
162 }
163 }
164
165 if ( oldNode && oldNode != newNode )
166 {
167 parentNode->removeChildNode( oldNode );
168 if ( oldNode->flags() & QSGNode::OwnedByParent )
169 delete oldNode;
170 }
171}
172
173void QskSGNode::resetGeometry( QSGGeometryNode* node )
174{
175 if ( node )
176 {
177 if ( auto g = node->geometry() )
178 {
179 const bool hasVertices = g->vertexCount() > 0;
180 const bool hasIndexes = g->indexCount() > 0;
181
182 if ( hasVertices || hasIndexes )
183 {
184 g->allocate( 0, 0 );
185
186 if ( hasVertices )
187 g->markVertexDataDirty();
188
189 if ( hasIndexes )
190 g->markIndexDataDirty();
191
192 node->markDirty( QSGNode::DirtyGeometry );
193 }
194 }
195 }
196}