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 | |
180 | QParameterPrivate::QParameterPrivate() |
181 | : QNodePrivate() |
182 | { |
183 | } |
184 | |
185 | namespace { |
186 | |
187 | /*! \internal */ |
188 | inline QVariant toBackendValue(const QVariant &v) |
189 | { |
190 | if (auto nodeValue = v.value<Qt3DCore::QNode*>()) |
191 | return QVariant::fromValue(value: nodeValue->id()); |
192 | return v; |
193 | } |
194 | |
195 | } // anonymous |
196 | |
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(alloc: iterable.size()); |
203 | for (const auto &v : iterable) |
204 | variants.append(t: toBackendValue(v)); |
205 | m_backendValue = variants; |
206 | } else { |
207 | m_backendValue = toBackendValue(v); |
208 | } |
209 | m_value = v; |
210 | } |
211 | |
212 | /*! \internal */ |
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 | */ |
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 | */ |
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 | */ |
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(value: texture)); |
249 | } |
250 | |
251 | /*! \internal */ |
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 | */ |
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 | |
274 | 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 | */ |
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(node: 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(node: nodeValue, func: &QParameter::setValue, nodeValue, resetValue: QVariant()); |
308 | |
309 | emit valueChanged(value: dv); |
310 | } |
311 | } |
312 | |
313 | QVariant QParameter::value() const |
314 | { |
315 | Q_D(const QParameter); |
316 | return d->m_value; |
317 | } |
318 | |
319 | Qt3DCore::QNodeCreatedChangeBasePtr QParameter::createNodeCreationChange() const |
320 | { |
321 | auto creationChange = Qt3DCore::QNodeCreatedChangePtr<QParameterData>::create(arguments: 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 | |