QGIS API Documentation 3.39.0-Master (d85f3c2a281)
Loading...
Searching...
No Matches
qgsfgutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsfgutils.cpp
3 --------------------------------------
4 Date : August 2024
5 Copyright : (C) 2024 by Mike Krus / Benoit De Mezzo
6 Email : mike dot krus at kdab dot com / benoit dot de dot mezzo at oslandia dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsfgutils.h"
17
18#include <QMetaEnum>
19#include <Qt3DRender/QGeometryRenderer>
20#include <Qt3DRender/QTechnique>
21#include <Qt3DRender/QGraphicsApiFilter>
22#include <Qt3DRender/QBlendEquation>
23#include <Qt3DRender/QColorMask>
24#include <Qt3DRender/QSortPolicy>
25#include <Qt3DRender/QPointSize>
26#include <Qt3DRender/QSeamlessCubemap>
27#include <Qt3DRender/QNoDepthMask>
28#include <Qt3DRender/QBlendEquationArguments>
29#include <Qt3DExtras/QTextureMaterial>
30#include <Qt3DRender/QAbstractTexture>
31#include <Qt3DRender/QNoDraw>
32#include <Qt3DRender/QEffect>
33
34QStringList QgsFgUtils::dumpSceneGraph( const Qt3DCore::QNode *node, FgDumpContext context )
35{
36 return dumpSG( context, node );
37}
38
39QStringList QgsFgUtils::dumpFrameGraph( const Qt3DCore::QNode *node, FgDumpContext context )
40{
41 return dumpFG( context, node );
42}
43
44QString QgsFgUtils::formatIdName( FgDumpContext context, quint64 id, const QString &name )
45{
46 QString fixedName = name.isEmpty() ? QLatin1String( "<no_name>" ) : name;
47 return QLatin1String( "{%1/%2}" ).arg( QString::number( id - context.lowestId ) ).arg( fixedName );
48}
49
50QString QgsFgUtils::formatIdName( FgDumpContext context, const Qt3DRender::QAbstractTexture *texture )
51{
52 QString fixedName = texture->objectName().isEmpty() ? QLatin1String( "<no_name>" ) : texture->objectName();
53 return QLatin1String( "{%1[%2]/%3" )
54 .arg( QString::number( texture->id().id() - context.lowestId )
55 , QString( QMetaEnum::fromType<Qt3DRender::QAbstractTexture::TextureFormat>().valueToKey( texture->format() ) )
56 , fixedName );
57}
58
59QString QgsFgUtils::formatNode( FgDumpContext context, const Qt3DCore::QNode *node )
60{
61 QString res = QLatin1String( "(%1%2)" )
62 .arg( QLatin1String( node->metaObject()->className() ) )
63 .arg( formatIdName( context, node->id().id(), node->objectName() ) );
64 if ( !node->isEnabled() )
65 res += QLatin1String( " [D]" );
66 return res;
67}
68
69QString QgsFgUtils::formatList( const QStringList &lst )
70{
71 return QString( QLatin1String( "[ %1 ]" ) ).arg( lst.join( QLatin1String( ", " ) ) );
72}
73
74QString QgsFgUtils::formatLongList( const QStringList &lst, int level )
75{
76 QString out = formatList( lst );
77 if ( out.size() < 200 )
78 return out;
79
80 out = QString( QLatin1String( "[\n" ) );
81 for ( QString item : lst )
82 {
83 item = QString( "-> %1\n" ).arg( item );
84 out += item.rightJustified( item.length() + ( 1 + level ) * 2, ' ' );
85 }
86 QString end( QLatin1String( "]" ) );
87 return out + end.rightJustified( end.length() + ( 1 + level ) * 2, ' ' );
88}
89
90QString QgsFgUtils::formatField( const QString &name, const QString &value )
91{
92 if ( value == "<no_value>" )
93 return QString( QLatin1String( "(%1)" ) ).arg( name );
94 return QString( QLatin1String( "(%1:%2)" ) ).arg( name, value );
95}
96
97QString QgsFgUtils::dumpSGEntity( FgDumpContext context, const Qt3DCore::QEntity *node, int level )
98{
99 auto extractTextureParam = []( FgDumpContext context, const QVector<Qt3DRender::QParameter *> &params, QStringList & fl )
100 {
101 for ( const auto *param : params )
102 {
103 if ( strstr( param->value().typeName(), "QAbstractTexture*" ) )
104 {
105 const Qt3DRender::QAbstractTexture *tex = param->value().value<Qt3DRender::QAbstractTexture *>();
106 fl += formatField( param->name(), formatIdName( context, tex ) );
107 }
108 }
109 };
110
111
112 QString res = formatNode( context, node );
113 const auto &components = node->components();
114 if ( ! components.isEmpty() )
115 {
116 QStringList componentNames;
117 for ( const auto &comp : components )
118 {
119 QString res = formatNode( context, comp );
120 QStringList fl;
121 if ( const auto *textMat = qobject_cast<const Qt3DExtras::QTextureMaterial *>( comp ) )
122 {
123 if ( textMat->texture() )
124 {
125 const auto texImages = textMat->texture()->textureImages();
126 for ( const auto *texImg : texImages )
127 {
128 fl += formatField(
129 texImg->metaObject()->className(),
130 formatIdName( context, texImg->id().id(), texImg->objectName() ) );
131 }
132 }
133 }
134 if ( const auto *material = qobject_cast<const Qt3DRender::QMaterial *>( comp ) )
135 {
136 if ( material->effect() )
137 {
138 const auto techniques = material->effect()->techniques();
139 for ( const auto *tech : techniques )
140 {
141 extractTextureParam( context, tech->parameters(), fl );
142 const auto passes = tech->renderPasses();
143 for ( const auto *pass : passes )
144 {
145 extractTextureParam( context, pass->parameters(), fl );
146 }
147 }
148 extractTextureParam( context, material->effect()->parameters(), fl );
149 }
150 extractTextureParam( context, material->parameters(), fl );
151 if ( !fl.empty() )
152 res += formatList( fl );
153 }
154
155 componentNames << res;
156 }
157 res += formatLongList( componentNames, level );
158 }
159
160 return res;
161}
162
163QStringList QgsFgUtils::dumpSG( FgDumpContext context, const Qt3DCore::QNode *node, int level )
164{
165 QStringList reply;
166 const auto *entity = qobject_cast<const Qt3DCore::QEntity *>( node );
167 if ( entity )
168 {
169 QString res = dumpSGEntity( context, entity, level );
170 reply += res.rightJustified( res.length() + level * 2, ' ' );
171 level++;
172 }
173
174 const auto children = node->childNodes();
175 for ( auto *child : children )
176 reply += dumpSG( context, child, level );
177
178 return reply;
179}
180
181QString QgsFgUtils::dumpFGNode( FgDumpContext context, const Qt3DRender::QFrameGraphNode *node )
182{
183 QString res = formatNode( context, node );
184
185 if ( const auto *lf = qobject_cast<const Qt3DRender::QLayerFilter *>( node ) )
186 {
187 QStringList sl;
188 const auto layers = lf->layers();
189 for ( auto layer : layers )
190 {
191 sl += formatIdName( context, layer->id().id(), layer->objectName() );
192 }
193
194 QStringList fl;
195 fl += formatField( QMetaEnum::fromType<Qt3DRender::QLayerFilter::FilterMode>().valueToKey( lf->filterMode() )
196 , formatList( sl ) );
197 res += QString( " %1" ).arg( formatList( fl ) );
198 }
199
200 else if ( const auto *cs = qobject_cast<const Qt3DRender::QCameraSelector *>( node ) )
201 {
202 QStringList fl;
203 fl += formatField( cs->camera()->metaObject()->className(),
204 formatIdName( context, cs->camera()->id().id(), cs->camera()->objectName() ) );
205 res += QString( " %1" ).arg( formatList( fl ) );
206 }
207
208 else if ( const auto *rss = qobject_cast<const Qt3DRender::QRenderStateSet *>( node ) )
209 {
210 QStringList sl;
211 const auto renderStates = rss->renderStates();
212 for ( auto rs : renderStates )
213 {
214 if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QCullFace *>( rs ) )
215 {
216 sl += formatField( "QCullFace", QMetaEnum::fromType<Qt3DRender::QCullFace::CullingMode>().valueToKey( rs_cast->mode() ) );
217 }
218 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QBlendEquation *>( rs ) )
219 {
220 sl += formatField( "QBlendEquation", QMetaEnum::fromType<Qt3DRender::QBlendEquation::BlendFunction>().valueToKey( rs_cast->blendFunction() ) );
221 }
222 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QBlendEquationArguments *>( rs ) )
223 {
224 QStringList fl;
225 fl += formatField( "sourceRgb", QMetaEnum::fromType<Qt3DRender::QBlendEquationArguments::Blending>().valueToKey( rs_cast->sourceRgb() ) );
226 fl += formatField( "destinationRgb", QMetaEnum::fromType<Qt3DRender::QBlendEquationArguments::Blending>().valueToKey( rs_cast->destinationRgb() ) );
227 fl += formatField( "sourceAlpha", QMetaEnum::fromType<Qt3DRender::QBlendEquationArguments::Blending>().valueToKey( rs_cast->sourceAlpha() ) );
228 fl += formatField( "destinationAlpha", QMetaEnum::fromType<Qt3DRender::QBlendEquationArguments::Blending>().valueToKey( rs_cast->destinationAlpha() ) );
229 fl += formatField( "bufferIndex", QString::number( rs_cast->bufferIndex() ) );
230
231 sl += formatField( "QBlendEquationArguments", formatList( fl ) );
232 }
233 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QColorMask *>( rs ) )
234 {
235 QStringList fl;
236 fl += formatField( "red", ( rs_cast->isRedMasked() ? QLatin1String( "true" ) : QLatin1String( "false" ) ) );
237 fl += formatField( "green", ( rs_cast->isGreenMasked() ? QLatin1String( "true" ) : QLatin1String( "false" ) ) );
238 fl += formatField( "blue", ( rs_cast->isBlueMasked() ? QLatin1String( "true" ) : QLatin1String( "false" ) ) );
239 fl += formatField( "alpha", ( rs_cast->isAlphaMasked() ? QLatin1String( "true" ) : QLatin1String( "false" ) ) );
240 sl += formatField( "QColorMask", formatList( fl ) );
241 }
242 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QDepthTest *>( rs ) )
243 {
244 sl += formatField( "QDepthTest", QMetaEnum::fromType<Qt3DRender::QDepthTest::DepthFunction>().valueToKey( rs_cast->depthFunction() ) );
245 }
246 else if ( qobject_cast<const Qt3DRender::QNoDepthMask *>( rs ) )
247 {
248 sl += formatField( "QNoDepthMask", "<no_value>" );
249 }
250 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QPointSize *>( rs ) )
251 {
252 QStringList fl;
253 fl += formatField( "sizeMode", QMetaEnum::fromType<Qt3DRender::QPointSize::SizeMode>().valueToKey( rs_cast->sizeMode() ) );
254 fl += formatField( "value", QString::number( rs_cast->value() ) );
255 sl += formatField( "QPointSize", formatList( fl ) );
256 }
257 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QPolygonOffset *>( rs ) )
258 {
259 QStringList fl;
260 fl += formatField( "scaleFactor", QString::number( rs_cast->scaleFactor() ) );
261 fl += formatField( "depthSteps", QString::number( rs_cast->depthSteps() ) );
262 sl += formatField( "QPolygonOffset", formatList( fl ) );
263 }
264 else if ( qobject_cast<const Qt3DRender::QSeamlessCubemap *>( rs ) )
265 {
266 sl += formatField( "QSeamlessCubemap", "<no_value>" );
267 }
268 }
269 res += QString( " %1" ).arg( formatList( sl ) );
270 }
271
272 else if ( const auto *rs = qobject_cast<const Qt3DRender::QRenderTargetSelector *>( node ) )
273 {
274 if ( rs->target() )
275 {
276 QStringList sl;
277 const auto outputs = rs->target()->outputs();
278 for ( auto output : outputs )
279 {
280 sl += formatField( QMetaEnum::fromType<Qt3DRender::QRenderTargetOutput::AttachmentPoint>().valueToKey( output->attachmentPoint() ),
281 formatIdName( context, output->texture() ) );
282 }
283 QStringList fl;
284 fl += formatField( QLatin1String( "outputs" ),
285 formatList( sl ) );
286 res += QString( " %1" ).arg( formatList( fl ) );
287 }
288 }
289 // if (!n->isEnabled())
290 // res += QLatin1String(" [D]");
291 return res;
292}
293
294QStringList QgsFgUtils::dumpFG( FgDumpContext context, const Qt3DCore::QNode *node, int level )
295{
296 QStringList reply;
297
298 const Qt3DRender::QFrameGraphNode *fgNode = qobject_cast<const Qt3DRender::QFrameGraphNode *>( node );
299 if ( fgNode )
300 {
301 QString res = dumpFGNode( context, fgNode );
302 reply += res.rightJustified( res.length() + level * 2, ' ' );
303 }
304
305 const auto children = node->childNodes();
306 const int inc = fgNode ? 1 : 0;
307 for ( auto *child : children )
308 {
309 auto *childFGNode = qobject_cast<Qt3DCore::QNode *>( child );
310 if ( childFGNode )
311 reply += dumpFG( context, childFGNode, level + inc );
312 }
313
314 return reply;
315}
static QStringList dumpFrameGraph(const Qt3DCore::QNode *node, FgDumpContext context)
Returns a tree view of the frame graph starting from node. The object ids will be given relatively to...
static QStringList dumpSceneGraph(const Qt3DCore::QNode *node, FgDumpContext context)
Returns a tree view of the scene graph starting from node. The object ids will be given relatively to...