1/****************************************************************************
2**
3** Copyright (C) 2014 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:LGPL$
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 Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qparameter.h"
41#include "qparameter_p.h"
42#include <Qt3DRender/private/renderlogging_p.h>
43#include <Qt3DCore/qpropertyupdatedchange.h>
44#include <Qt3DRender/qtexture.h>
45
46
47/*!
48 \qmltype Parameter
49 \instantiates Qt3DRender::QParameter
50 \inqmlmodule Qt3D.Render
51 \brief Provides storage for a name and value pair. This maps to a shader uniform.
52
53 A Parameter can be referenced by a RenderPass, Technique, Effect, Material,
54 TechniqueFilter, RenderPassFilter. At runtime, depending on which shader is
55 selected for a given step of the rendering, the value contained in a
56 Parameter will be converted and uploaded if the shader contains a uniform
57 with a name matching that of the Parameter.
58
59 \code
60 Parameter {
61 name: "diffuseColor"
62 value: "blue"
63 }
64
65 // Works with the following GLSL uniform shader declarations
66 // uniform vec4 diffuseColor;
67 // uniform vec3 diffuseColor;
68 // uniform vec2 diffuseColor;
69 // uniform float diffuseColor;
70 \endcode
71
72 \note some care must be taken to ensure the value wrapped by a Parameter
73 can actually be converted to what the real uniform expect. Giving a value
74 stored as an int where the actual shader uniform is of type float could
75 result in undefined behaviors.
76
77 \note when the targeted uniform is an array, the name should be the name
78 of the uniform with [0] appended to it.
79
80 \code
81 Parameter {
82 name: "diffuseValues[0]"
83 value: [0.0, 1.0. 2.0, 3.0, 4.0, 883.0, 1340.0, 1584.0]
84 }
85
86 // Matching GLSL shader uniform declaration
87 // uniform float diffuseValues[8];
88 \endcode
89
90 When it comes to texture support, the Parameter value should be set to the
91 appropriate \l {Qt3DRender::QAbstractTexture}{texture} subclass that matches the sampler type of the shader
92 uniform.
93
94 \code
95 Parameter {
96 name: "diffuseTexture"
97 value: Texture2D { ... }
98 }
99
100 // Works with the following GLSL uniform shader declaration
101 // uniform sampler2D diffuseTexture
102 \endcode
103
104 \sa Qt3DRender::QAbstractTexture
105 */
106
107/*!
108 \class Qt3DRender::QParameter
109 \inheaderfile Qt3DRender/QParameter
110 \inmodule Qt3DRender
111 \brief Provides storage for a name and value pair. This maps to a shader uniform.
112
113 A QParameter can be referenced by a QRenderPass, QTechnique, QEffect, QMaterial,
114 QTechniqueFilter, QRenderPassFilter. At runtime, depending on which shader is
115 selected for a given step of the rendering, the value contained in a
116 QParameter will be converted and uploaded if the shader contains a uniform
117 with a name matching that of the QParameter.
118
119 \code
120 QParameter *param = new QParameter();
121 param->setName(QStringLiteral("diffuseColor"));
122 param->setValue(QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
123
124 // Alternatively you can create and set a QParameter this way
125 QParameter *param2 = new QParameter(QStringLiteral("diffuseColor"), QColor::fromRgbF(0.0f, 0.0f, 1.0f, 1.0f));
126
127 // Such QParameters will work with the following GLSL uniform shader declarations
128 // uniform vec4 diffuseColor;
129 // uniform vec3 diffuseColor;
130 // uniform vec2 diffuseColor;
131 // uniform float diffuseColor;
132 \endcode
133
134 \note some care must be taken to ensure the value wrapped by a QParameter
135 can actually be converted to what the real uniform expect. Giving a value
136 stored as an int where the actual shader uniform is of type float could
137 result in undefined behaviors.
138
139 \note when the targeted uniform is an array, the name should be the name
140 of the uniform with [0] appended to it.
141
142 \code
143 QParameter *param = new QParameter();
144 QVariantList values = QVariantList() << 0.0f << 1.0f << 2.0f << 3.0f << 4.0f << 883.0f << 1340.0f << 1584.0f;
145
146 param->setName(QStringLiteral("diffuseValues[0]"));
147 param->setValue(values);
148
149 // Matching GLSL shader uniform declaration
150 // uniform float diffuseValues[8];
151 \endcode
152
153 When it comes to texture support, the QParameter value should be set to the
154 appropriate QAbstractTexture subclass that matches the sampler type of the shader
155 uniform.
156
157 \code
158 QTexture2D *texture = new QTexture2D();
159 ...
160 QParameter *param = new QParameter();
161 param->setName(QStringLiteral("diffuseTexture"));
162 param->setValue(QVariant::fromValue(texture));
163
164 // Works with the following GLSL uniform shader declaration
165 // uniform sampler2D diffuseTexture
166 \endcode
167
168 \sa QAbstractTexture
169 */
170
171QT_BEGIN_NAMESPACE
172
173using namespace Qt3DCore;
174
175namespace Qt3DRender {
176
177QParameterPrivate::QParameterPrivate()
178 : QNodePrivate()
179{
180}
181
182namespace {
183
184/*! \internal */
185inline QVariant toBackendValue(const QVariant &v)
186{
187 if (auto nodeValue = v.value<Qt3DCore::QNode*>())
188 return QVariant::fromValue(nodeValue->id());
189 return v;
190}
191
192} // anonymous
193
194void QParameterPrivate::setValue(const QVariant &v)
195{
196 if (v.type() == QVariant::List) {
197 QSequentialIterable iterable = v.value<QSequentialIterable>();
198 QVariantList variants;
199 variants.reserve(iterable.size());
200 for (const auto &v : iterable)
201 variants.append(toBackendValue(v));
202 m_backendValue = variants;
203 } else {
204 m_backendValue = toBackendValue(v);
205 }
206 m_value = v;
207}
208
209/*! \internal */
210QParameter::QParameter(QParameterPrivate &dd, QNode *parent)
211 : QNode(dd, parent)
212{
213}
214
215/*!
216 \fn Qt3DRender::QParameter::QParameter(Qt3DCore::QNode *parent)
217 Constructs a new QParameter with the specified \a parent.
218 */
219QParameter::QParameter(QNode *parent)
220 : QNode(*new QParameterPrivate, parent)
221{
222}
223
224/*!
225 \fn Qt3DRender::QParameter::QParameter(const QString &name, const QVariant &value, QNode *parent)
226 Constructs a new QParameter with the specified \a parent \a name and \a value.
227 */
228QParameter::QParameter(const QString &name, const QVariant &value, QNode *parent)
229 : QNode(*new QParameterPrivate, parent)
230{
231 Q_D(QParameter);
232 d->m_name = name;
233 setValue(value);
234}
235
236/*!
237 \fn Qt3DRender::QParameter::QParameter(const QString &name, QAbstractTexture *texture, QNode *parent)
238 Constructs a new QParameter with the specified \a parent \a name and takes its value from \a texture.
239 */
240QParameter::QParameter(const QString &name, QAbstractTexture *texture, QNode *parent)
241 : QNode(*new QParameterPrivate, parent)
242{
243 Q_D(QParameter);
244 d->m_name = name;
245 setValue(QVariant::fromValue(texture));
246}
247
248/*! \internal */
249QParameter::~QParameter()
250{
251}
252
253/*!
254 \qmlproperty QString Qt3D.Render::Parameter::name
255 Specifies the name of the parameter
256*/
257
258/*!
259 \property Qt3DRender::QParameter::name
260 Specifies the name of the parameter
261 */
262void QParameter::setName(const QString &name)
263{
264 Q_D(QParameter);
265 if (d->m_name != name) {
266 d->m_name = name;
267 emit nameChanged(name);
268 }
269}
270
271QString QParameter::name() const
272{
273 Q_D(const QParameter);
274 return d->m_name;
275}
276
277/*!
278 \qmlproperty QVariant Qt3D.Render::Parameter::value
279 Specifies the value of the parameter
280*/
281
282/*!
283 \property Qt3DRender::QParameter::value
284 Specifies the value of the parameter
285 */
286void QParameter::setValue(const QVariant &dv)
287{
288 Q_D(QParameter);
289 if (d->m_value != dv) {
290
291 QNode *oldNodeValue = d->m_value.value<QNode *>();
292 if (oldNodeValue != nullptr)
293 d->unregisterDestructionHelper(oldNodeValue);
294
295 // In case node values are declared inline
296 QNode *nodeValue = dv.value<QNode *>();
297 if (nodeValue != nullptr && !nodeValue->parent())
298 nodeValue->setParent(this);
299
300 d->setValue(dv);
301
302 // Ensures proper bookkeeping
303 if (nodeValue != nullptr)
304 d->registerDestructionHelper(nodeValue, &QParameter::setValue, nodeValue, QVariant());
305
306 emit valueChanged(dv);
307 }
308}
309
310QVariant QParameter::value() const
311{
312 Q_D(const QParameter);
313 return d->m_value;
314}
315
316Qt3DCore::QNodeCreatedChangeBasePtr QParameter::createNodeCreationChange() const
317{
318 auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QParameterData>::create(this);
319 auto &data = creationChange->data;
320 Q_D(const QParameter);
321 data.name = d->m_name;
322 data.backendValue = d->m_backendValue;
323 return creationChange;
324}
325
326} // namespace Qt3DRender
327
328QT_END_NAMESPACE
329