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