1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt3D module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include <QtTest/QTest> |
30 | #include <Qt3DCore/private/qnode_p.h> |
31 | #include <Qt3DCore/private/qscene_p.h> |
32 | #include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> |
33 | |
34 | #include <Qt3DRender/QAttribute> |
35 | #include <Qt3DRender/private/qattribute_p.h> |
36 | #include <Qt3DRender/QBuffer> |
37 | |
38 | #include "testpostmanarbiter.h" |
39 | |
40 | class tst_QAttribute: public QObject |
41 | { |
42 | Q_OBJECT |
43 | public: |
44 | tst_QAttribute() |
45 | { |
46 | qRegisterMetaType<Qt3DRender::QBuffer*>(typeName: "Qt3DCore::QBuffer*" ); |
47 | } |
48 | |
49 | private Q_SLOTS: |
50 | void shouldHaveDefaultAttributeNames() |
51 | { |
52 | // GIVEN |
53 | Qt3DRender::QAttribute attribute; |
54 | |
55 | // THEN |
56 | QCOMPARE(Qt3DRender::QAttribute::defaultPositionAttributeName(), QStringLiteral("vertexPosition" )); |
57 | QCOMPARE(Qt3DRender::QAttribute::defaultNormalAttributeName(), QStringLiteral("vertexNormal" )); |
58 | QCOMPARE(Qt3DRender::QAttribute::defaultColorAttributeName(), QStringLiteral("vertexColor" )); |
59 | QCOMPARE(Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName(), QStringLiteral("vertexTexCoord" )); |
60 | QCOMPARE(Qt3DRender::QAttribute::defaultTangentAttributeName(), QStringLiteral("vertexTangent" )); |
61 | QCOMPARE(Qt3DRender::QAttribute::defaultJointIndicesAttributeName(), QStringLiteral("vertexJointIndices" )); |
62 | QCOMPARE(Qt3DRender::QAttribute::defaultJointWeightsAttributeName(), QStringLiteral("vertexJointWeights" )); |
63 | |
64 | QCOMPARE(attribute.property("defaultPositionAttributeName" ).toString(), |
65 | Qt3DRender::QAttribute::defaultPositionAttributeName()); |
66 | QCOMPARE(attribute.property("defaultNormalAttributeName" ).toString(), |
67 | Qt3DRender::QAttribute::defaultNormalAttributeName()); |
68 | QCOMPARE(attribute.property("defaultColorAttributeName" ).toString(), |
69 | Qt3DRender::QAttribute::defaultColorAttributeName()); |
70 | QCOMPARE(attribute.property("defaultTextureCoordinateAttributeName" ).toString(), |
71 | Qt3DRender::QAttribute::defaultTextureCoordinateAttributeName()); |
72 | QCOMPARE(attribute.property("defaultTangentAttributeName" ).toString(), |
73 | Qt3DRender::QAttribute::defaultTangentAttributeName()); |
74 | QCOMPARE(attribute.property("defaultJointIndicesAttributeName" ).toString(), |
75 | Qt3DRender::QAttribute::defaultJointIndicesAttributeName()); |
76 | QCOMPARE(attribute.property("defaultJointWeightsAttributeName" ).toString(), |
77 | Qt3DRender::QAttribute::defaultJointWeightsAttributeName()); |
78 | } |
79 | |
80 | void checkCloning_data() |
81 | { |
82 | QTest::addColumn<Qt3DRender::QAttribute *>(name: "attribute" ); |
83 | |
84 | Qt3DRender::QAttribute *defaultConstructed = new Qt3DRender::QAttribute(); |
85 | QTest::newRow(dataTag: "defaultConstructed" ) << defaultConstructed; |
86 | |
87 | Qt3DRender::QAttribute *customVertex = new Qt3DRender::QAttribute(); |
88 | Qt3DRender::QBuffer *buffer = new Qt3DRender::QBuffer(); |
89 | customVertex->setBuffer(buffer); |
90 | customVertex->setAttributeType(Qt3DRender::QAttribute::VertexAttribute); |
91 | customVertex->setCount(454); |
92 | customVertex->setByteStride(427); |
93 | customVertex->setByteOffset(305); |
94 | customVertex->setDivisor(235); |
95 | customVertex->setName("BB" ); |
96 | customVertex->setVertexBaseType(Qt3DRender::QAttribute::Float); |
97 | customVertex->setVertexSize(4); |
98 | QTest::newRow(dataTag: "vertex" ) << customVertex; |
99 | |
100 | Qt3DRender::QAttribute *customIndex = new Qt3DRender::QAttribute(); |
101 | Qt3DRender::QBuffer *indexBuffer = new Qt3DRender::QBuffer(); |
102 | customIndex->setBuffer(indexBuffer); |
103 | customIndex->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); |
104 | customIndex->setCount(383); |
105 | customIndex->setByteStride(350); |
106 | customIndex->setByteOffset(327); |
107 | customIndex->setDivisor(355); |
108 | customIndex->setName("SB" ); |
109 | customIndex->setVertexBaseType(Qt3DRender::QAttribute::Float); |
110 | customIndex->setVertexSize(3); |
111 | QTest::newRow(dataTag: "index" ) << customIndex; |
112 | |
113 | Qt3DRender::QAttribute *customIndirect = new Qt3DRender::QAttribute(); |
114 | Qt3DRender::QBuffer *indirectBuffer = new Qt3DRender::QBuffer(); |
115 | customIndirect->setBuffer(indirectBuffer); |
116 | customIndirect->setAttributeType(Qt3DRender::QAttribute::DrawIndirectAttribute); |
117 | customIndirect->setCount(1); |
118 | customIndirect->setByteStride(12); |
119 | customIndirect->setByteOffset(0); |
120 | customIndirect->setName("DrawIndirect" ); |
121 | QTest::newRow(dataTag: "index" ) << customIndirect; |
122 | } |
123 | |
124 | void checkCloning() |
125 | { |
126 | // GIVEN |
127 | QFETCH(Qt3DRender::QAttribute *, attribute); |
128 | |
129 | // WHEN |
130 | Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(attribute); |
131 | QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges = creationChangeGenerator.creationChanges(); |
132 | |
133 | // THEN |
134 | QCOMPARE(creationChanges.size(), 1 + (attribute->buffer() ? 1 : 0)); |
135 | |
136 | const Qt3DCore::QNodeCreatedChangePtr<Qt3DRender::QAttributeData> creationChangeData = |
137 | qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DRender::QAttributeData>>(src: creationChanges.first()); |
138 | const Qt3DRender::QAttributeData &cloneData = creationChangeData->data; |
139 | |
140 | QCOMPARE(attribute->id(), creationChangeData->subjectId()); |
141 | QCOMPARE(attribute->isEnabled(), creationChangeData->isNodeEnabled()); |
142 | QCOMPARE(attribute->metaObject(), creationChangeData->metaObject()); |
143 | QCOMPARE(attribute->name(), cloneData.name); |
144 | QCOMPARE(attribute->count(), cloneData.count); |
145 | QCOMPARE(attribute->byteStride(), cloneData.byteStride); |
146 | QCOMPARE(attribute->byteOffset(), cloneData.byteOffset); |
147 | QCOMPARE(attribute->divisor(), cloneData.divisor); |
148 | QCOMPARE(attribute->vertexBaseType(), cloneData.vertexBaseType); |
149 | QCOMPARE(attribute->vertexSize(), cloneData.vertexSize); |
150 | QVERIFY(attribute->attributeType() == cloneData.attributeType); |
151 | QCOMPARE(attribute->buffer() ? attribute->buffer()->id() : Qt3DCore::QNodeId(), cloneData.bufferId); |
152 | } |
153 | |
154 | void checkPropertyUpdates() |
155 | { |
156 | // GIVEN |
157 | TestArbiter arbiter; |
158 | QScopedPointer<Qt3DRender::QAttribute> attribute(new Qt3DRender::QAttribute()); |
159 | arbiter.setArbiterOnNode(attribute.data()); |
160 | |
161 | // WHEN |
162 | attribute->setVertexBaseType(Qt3DRender::QAttribute::Double); |
163 | |
164 | // THEN |
165 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
166 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
167 | |
168 | arbiter.dirtyNodes.clear(); |
169 | |
170 | // WHEN |
171 | attribute->setVertexSize(4); |
172 | |
173 | // THEN |
174 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
175 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
176 | |
177 | arbiter.dirtyNodes.clear(); |
178 | |
179 | // WHEN |
180 | attribute->setName(QStringLiteral("Duntov" )); |
181 | |
182 | // THEN |
183 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
184 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
185 | |
186 | arbiter.dirtyNodes.clear(); |
187 | |
188 | // WHEN |
189 | attribute->setCount(883); |
190 | |
191 | // THEN |
192 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
193 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
194 | |
195 | arbiter.dirtyNodes.clear(); |
196 | |
197 | // WHEN |
198 | attribute->setByteStride(1340); |
199 | |
200 | // THEN |
201 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
202 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
203 | |
204 | arbiter.dirtyNodes.clear(); |
205 | |
206 | // WHEN |
207 | attribute->setByteOffset(1584); |
208 | |
209 | // THEN |
210 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
211 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
212 | |
213 | arbiter.dirtyNodes.clear(); |
214 | |
215 | // WHEN |
216 | attribute->setDivisor(1450); |
217 | |
218 | // THEN |
219 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
220 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
221 | |
222 | arbiter.dirtyNodes.clear(); |
223 | |
224 | // WHEN |
225 | attribute->setAttributeType(Qt3DRender::QAttribute::IndexAttribute); |
226 | |
227 | // THEN |
228 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
229 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
230 | |
231 | arbiter.dirtyNodes.clear(); |
232 | |
233 | // WHEN |
234 | Qt3DRender::QBuffer buf; |
235 | attribute->setBuffer(&buf); |
236 | |
237 | // THEN |
238 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
239 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
240 | |
241 | arbiter.dirtyNodes.clear(); |
242 | |
243 | // WHEN |
244 | Qt3DRender::QBuffer buf2; |
245 | attribute->setBuffer(&buf2); |
246 | |
247 | // THEN |
248 | QCOMPARE(arbiter.dirtyNodes.size(), 1); |
249 | QCOMPARE(arbiter.dirtyNodes.front(), attribute.data()); |
250 | |
251 | arbiter.dirtyNodes.clear(); |
252 | } |
253 | |
254 | void checkBufferBookkeeping() |
255 | { |
256 | // GIVEN |
257 | QScopedPointer<Qt3DRender::QAttribute> attribute(new Qt3DRender::QAttribute); |
258 | { |
259 | // WHEN |
260 | Qt3DRender::QBuffer buf; |
261 | attribute->setBuffer(&buf); |
262 | |
263 | // THEN |
264 | QCOMPARE(buf.parent(), attribute.data()); |
265 | QCOMPARE(attribute->buffer(), &buf); |
266 | } |
267 | // THEN (Should not crash and parameter be unset) |
268 | QVERIFY(attribute->buffer() == nullptr); |
269 | |
270 | { |
271 | // WHEN |
272 | Qt3DRender::QAttribute someOtherAttribute; |
273 | QScopedPointer<Qt3DRender::QBuffer> buf(new Qt3DRender::QBuffer(&someOtherAttribute)); |
274 | attribute->setBuffer(buf.data()); |
275 | |
276 | // THEN |
277 | QCOMPARE(buf->parent(), &someOtherAttribute); |
278 | QCOMPARE(attribute->buffer(), buf.data()); |
279 | |
280 | // WHEN |
281 | attribute.reset(); |
282 | buf.reset(); |
283 | |
284 | // THEN Should not crash when the buffer is destroyed (tests for failed removal of destruction helper) |
285 | } |
286 | } |
287 | }; |
288 | |
289 | QTEST_MAIN(tst_QAttribute) |
290 | |
291 | #include "tst_qattribute.moc" |
292 | |