1 | // Copyright (C) 2022 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qtypes.h" |
5 | #include <private/qquickmultieffect_p_p.h> |
6 | #include <private/qquickshadereffect_p.h> |
7 | #include <private/qquickshadereffectsource_p.h> |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | Q_LOGGING_CATEGORY(lcQuickEffect, "qt.quick.effects" ) |
12 | |
13 | /*! |
14 | \keyword Qt Quick Effects |
15 | \qmlmodule QtQuick.Effects |
16 | \title Qt Quick Effects QML Types |
17 | \ingroup qmlmodules |
18 | \brief Provides QML types for applying one or more simple graphical effects to Qt Quick items. |
19 | |
20 | To use the types in this module, import the module with the following line: |
21 | |
22 | \qml |
23 | import QtQuick.Effects |
24 | \endqml |
25 | */ |
26 | |
27 | /*! |
28 | \qmltype MultiEffect |
29 | \nativetype QQuickMultiEffect |
30 | \inqmlmodule QtQuick.Effects |
31 | \inherits Item |
32 | \ingroup qtquick-effects |
33 | \brief Applies post-processing effect to an item. |
34 | |
35 | The MultiEffect type, the successor to the deprecated Qt Graphical Effects |
36 | from Qt 5, applies a post-processing effect to the \l source item. Compared |
37 | to the Qt Graphical Effects module, MultiEffect combines multiple |
38 | effects (blur, shadow, colorization etc.) into a single item and shader |
39 | which makes it better for multiple effects. There are several shader |
40 | variations and the most optimal one gets selected based on the features |
41 | used. |
42 | |
43 | MultiEffect is designed specifically for most common effects and can be easily animated. |
44 | If the MultiEffect doesn't contain the effect you need, consider implementing a custom |
45 | effect using \l {Qt Quick Effect Maker}. For more information about shader effects, |
46 | see the \l ShaderEffect reference documentation. |
47 | |
48 | Note that MultiEffect type renders a new visual item alongside the source |
49 | item. To apply the effect to the source item, you need to place the new |
50 | MultiEffect item at the position of the source item. If the source item and |
51 | the MultiEffect item are not opaque, both the items can be visible, thus you |
52 | may not get the desired effect. To hide the source item, do any of |
53 | these: |
54 | |
55 | \list |
56 | \li Set \c{visible: false} for the source item. In this case, the source |
57 | item is not rendered at all and cannot receive touch or click input. |
58 | \li Set \c{opacity: 0} for the source item. In this case, the source |
59 | item is completely transparent, but still can receive touch or click |
60 | input. |
61 | \endlist |
62 | |
63 | \section1 Example Usage |
64 | |
65 | The following example shows how to apply a saturation effect to an item: |
66 | |
67 | \table 70% |
68 | \row |
69 | \li \image multieffect-example1.png |
70 | \li \qml |
71 | import QtQuick |
72 | import QtQuick.Effects |
73 | |
74 | ... |
75 | Image { |
76 | id: sourceItem |
77 | source: "qt_logo_green_rgb.png" |
78 | // Hide the source item, otherwise both the source item and |
79 | // MultiEffect will be rendered |
80 | visible: false |
81 | // or you can set: |
82 | // opacity: 0 |
83 | } |
84 | // Renders a new item with the specified effects rendered |
85 | // at the same position where the source item was rendered |
86 | MultiEffect { |
87 | source: sourceItem |
88 | anchors.fill: sourceItem |
89 | saturation: -1.0 |
90 | } |
91 | \endqml |
92 | \endtable |
93 | |
94 | The following example shows how to apply a saturation effect to |
95 | a \l [QML]{Item#Item Layers}{layered Item}: |
96 | |
97 | \table 70% |
98 | \row |
99 | \li \image multieffect-example1.png |
100 | \li \qml |
101 | import QtQuick |
102 | import QtQuick.Effects |
103 | |
104 | ... |
105 | Image { |
106 | id: sourceItem |
107 | source: "qt_logo_green_rgb.png" |
108 | layer.enabled: true |
109 | // For the layered items, you can assign a MultiEffect directly |
110 | // to layer.effect. |
111 | layer.effect: MultiEffect { |
112 | saturation: -1.0 |
113 | } |
114 | } |
115 | \endqml |
116 | \endtable |
117 | |
118 | The following example shows how to apply multiple effects at the same time: |
119 | |
120 | \table 70% |
121 | \row |
122 | \li \image multieffect-example2.png |
123 | \li \qml |
124 | import QtQuick |
125 | import QtQuick.Effects |
126 | |
127 | ... |
128 | MultiEffect { |
129 | source: sourceItem |
130 | anchors.fill: sourceItem |
131 | brightness: 0.4 |
132 | saturation: 0.2 |
133 | blurEnabled: true |
134 | blurMax: 64 |
135 | blur: 1.0 |
136 | } |
137 | \endqml |
138 | \endtable |
139 | |
140 | Below is an example of how to use the mask, colorization and brightness effects together to |
141 | fade away an element. This kind of hiding/showing of elements can be, for example, bind |
142 | to a slider value or animations like NumberAnimation. Note how the \c visible property is |
143 | false when the item is totally faded away, to avoid unnecessary rendering of the effect. |
144 | |
145 | \table 70% |
146 | \row |
147 | \li \image multieffect-example3.png |
148 | \li \qml |
149 | import QtQuick |
150 | import QtQuick.Effects |
151 | import QtQuick.Controls.Material |
152 | |
153 | ... |
154 | MultiEffect { |
155 | property real effectAmount: effectSlider.value |
156 | source: sourceItem |
157 | anchors.fill: sourceItem |
158 | brightness: effectAmount |
159 | colorizationColor: "#ff20d0" |
160 | colorization: effectAmount |
161 | maskEnabled: true |
162 | maskSource: Image { |
163 | source: "mask.png" |
164 | } |
165 | maskSpreadAtMin: 0.2 |
166 | maskThresholdMin: effectAmount |
167 | visible: effectAmount < 1.0 |
168 | } |
169 | Slider { |
170 | id: effectSlider |
171 | anchors.bottom: parent.bottom |
172 | anchors.horizontalCenter: parent.horizontalCenter |
173 | } |
174 | \endqml |
175 | \endtable |
176 | |
177 | \section1 Performance |
178 | There are a few things to consider for optimal performance: |
179 | \list |
180 | \li To get the most optimal shader, enable only the effects which you actually use |
181 | (see \l blurEnabled, \l shadowEnabled, \l maskEnabled). Simple color effects (\l brightness, |
182 | \l contrast, \l saturation, \l colorization) are always enabled, so using them doesn't |
183 | add extra overhead. |
184 | \li See the \b {Performance notes} of the properties which may change the shader or the effect |
185 | item size and don't modify these during animations. |
186 | \li When the MultiEffect isn't used, remember to set its \c visible property to be false to |
187 | avoid rendering the effects in the background. |
188 | \li Blur and shadow are the heaviest effects. With these, prefer increasing \l blurMultiplier |
189 | over \l blurMax and avoid using \l source items which animate, so blurring doesn't need |
190 | to be regenerated in every frame. |
191 | \li Apply effects to optimally sized QML elements as more pixels means more work for |
192 | the GPU. When applying the blur effect to the whole background, remember to set |
193 | \l autoPaddingEnabled false or the effect grows "outside" the window / screen. |
194 | \endlist |
195 | |
196 | \include notes.qdocinc shadereffectsource and multieffect |
197 | */ |
198 | |
199 | /*! |
200 | \qmlsignal QtQuick.Effects::MultiEffect::shaderChanged() |
201 | |
202 | This signal is emitted when the used shader changes. |
203 | \sa fragmentShader, vertexShader |
204 | */ |
205 | |
206 | QQuickMultiEffect::QQuickMultiEffect(QQuickItem *parent) |
207 | : QQuickItem(*new QQuickMultiEffectPrivate, parent) |
208 | { |
209 | setFlag(flag: ItemHasContents); |
210 | } |
211 | |
212 | QQuickMultiEffect::~QQuickMultiEffect() |
213 | { |
214 | } |
215 | |
216 | /*! |
217 | \qmlproperty Item QtQuick.Effects::MultiEffect::source |
218 | |
219 | This property holds the item to be used as a source for the effect. |
220 | If needed, MultiEffect will internally generate a \l ShaderEffectSource |
221 | as the texture source. |
222 | |
223 | \note It is not supported to let the effect include itself, for instance |
224 | by setting source to the effect's parent. |
225 | |
226 | \note If the source item has \l {QtQuick::Item::layer.enabled} {layer.enabled} set to true, |
227 | it will be used directly. This is good for the performance and often desired, when the source |
228 | is hidden. But if the source remains visible and the effect adds padding (autoPaddingEnabled, |
229 | paddingRect), that padding can affect the appearance of the source item. |
230 | |
231 | \sa hasProxySource |
232 | */ |
233 | QQuickItem *QQuickMultiEffect::source() const |
234 | { |
235 | Q_D(const QQuickMultiEffect); |
236 | return d->source(); |
237 | } |
238 | |
239 | void QQuickMultiEffect::setSource(QQuickItem *item) |
240 | { |
241 | Q_D(QQuickMultiEffect); |
242 | d->setSource(item); |
243 | } |
244 | |
245 | /*! |
246 | \qmlproperty bool QtQuick.Effects::MultiEffect::autoPaddingEnabled |
247 | |
248 | When blur or shadow effects are enabled and this is set to true (default), |
249 | the item size is padded automatically based on blurMax and blurMultiplier. |
250 | Note that \l paddingRect is always added to the size. |
251 | |
252 | \image multieffect-example4.png |
253 | |
254 | \sa paddingRect |
255 | |
256 | \include notes.qdocinc performance item size |
257 | |
258 | \include notes.qdocinc performance item resize |
259 | */ |
260 | bool QQuickMultiEffect::autoPaddingEnabled() const |
261 | { |
262 | Q_D(const QQuickMultiEffect); |
263 | return d->autoPaddingEnabled(); |
264 | } |
265 | |
266 | void QQuickMultiEffect::setAutoPaddingEnabled(bool enabled) |
267 | { |
268 | Q_D(QQuickMultiEffect); |
269 | d->setAutoPaddingEnabled(enabled); |
270 | } |
271 | |
272 | /*! |
273 | \qmlproperty rect QtQuick.Effects::MultiEffect::paddingRect |
274 | |
275 | Set this to increase item size manually so that blur and/or shadows will fit. |
276 | If autoPaddingEnabled is true and paddingRect is not set, the item is padded |
277 | to fit maximally blurred item based on blurMax and blurMultiplier. When |
278 | enabling the shadow, you typically need to take \l shadowHorizontalOffset and |
279 | \l shadowVerticalOffset into account and adjust this paddingRect accordingly. |
280 | |
281 | Below is an example of adjusting paddingRect with autoPaddingEnabled set to |
282 | false so that the shadow fits inside the MultiEffect item. |
283 | |
284 | \image multieffect-example5.png |
285 | |
286 | \sa autoPaddingEnabled |
287 | |
288 | \include notes.qdocinc performance item size |
289 | |
290 | \include notes.qdocinc performance item resize |
291 | */ |
292 | QRectF QQuickMultiEffect::paddingRect() const |
293 | { |
294 | Q_D(const QQuickMultiEffect); |
295 | return d->paddingRect(); |
296 | } |
297 | |
298 | void QQuickMultiEffect::setPaddingRect(const QRectF &rect) |
299 | { |
300 | Q_D(QQuickMultiEffect); |
301 | d->setPaddingRect(rect); |
302 | } |
303 | |
304 | /*! |
305 | \qmlproperty real QtQuick.Effects::MultiEffect::brightness |
306 | |
307 | This property defines how much the source brightness is increased or |
308 | decreased. |
309 | |
310 | The value ranges from -1.0 to 1.0. By default, the property is set to \c |
311 | 0.0 (no change). |
312 | */ |
313 | qreal QQuickMultiEffect::brightness() const |
314 | { |
315 | Q_D(const QQuickMultiEffect); |
316 | return d->brightness(); |
317 | } |
318 | |
319 | void QQuickMultiEffect::setBrightness(qreal brightness) |
320 | { |
321 | Q_D(QQuickMultiEffect); |
322 | d->setBrightness(brightness); |
323 | } |
324 | |
325 | /*! |
326 | \qmlproperty real QtQuick.Effects::MultiEffect::contrast |
327 | |
328 | This property defines how much the source contrast is increased or |
329 | decreased. |
330 | |
331 | The value ranges from -1.0 to 1.0. By default, the property is set to \c |
332 | 0.0 (no change). |
333 | */ |
334 | qreal QQuickMultiEffect::contrast() const |
335 | { |
336 | Q_D(const QQuickMultiEffect); |
337 | return d->contrast(); |
338 | } |
339 | |
340 | void QQuickMultiEffect::setContrast(qreal contrast) |
341 | { |
342 | Q_D(QQuickMultiEffect); |
343 | d->setContrast(contrast); |
344 | } |
345 | |
346 | /*! |
347 | \qmlproperty real QtQuick.Effects::MultiEffect::saturation |
348 | |
349 | This property defines how much the source saturation is increased or |
350 | decreased. |
351 | |
352 | The value ranges from -1.0 (totally desaturated) to inf. By default, |
353 | the property is set to \c 0.0 (no change). |
354 | */ |
355 | qreal QQuickMultiEffect::saturation() const |
356 | { |
357 | Q_D(const QQuickMultiEffect); |
358 | return d->saturation(); |
359 | } |
360 | |
361 | void QQuickMultiEffect::setSaturation(qreal saturation) |
362 | { |
363 | Q_D(QQuickMultiEffect); |
364 | d->setSaturation(saturation); |
365 | } |
366 | |
367 | /*! |
368 | \qmlproperty real QtQuick.Effects::MultiEffect::colorization |
369 | |
370 | This property defines how much the source is colorized with the |
371 | colorizationColor. |
372 | |
373 | The value ranges from 0.0 (not colorized) to 1.0 (fully colorized). |
374 | By default, the property is set to \c 0.0 (no change). |
375 | */ |
376 | qreal QQuickMultiEffect::colorization() const |
377 | { |
378 | Q_D(const QQuickMultiEffect); |
379 | return d->colorization(); |
380 | } |
381 | |
382 | void QQuickMultiEffect::setColorization(qreal colorization) |
383 | { |
384 | Q_D(QQuickMultiEffect); |
385 | d->setColorization(colorization); |
386 | } |
387 | |
388 | /*! |
389 | \qmlproperty color QtQuick.Effects::MultiEffect::colorizationColor |
390 | |
391 | This property defines the RGBA color value which is used to |
392 | colorize the source. |
393 | |
394 | By default, the property is set to \c {Qt.rgba(1.0, 0.0, 0.0, 1.0)} (red). |
395 | |
396 | \sa colorization |
397 | */ |
398 | QColor QQuickMultiEffect::colorizationColor() const |
399 | { |
400 | Q_D(const QQuickMultiEffect); |
401 | return d->colorizationColor(); |
402 | } |
403 | |
404 | void QQuickMultiEffect::setColorizationColor(const QColor &color) |
405 | { |
406 | Q_D(QQuickMultiEffect); |
407 | d->setColorizationColor(color); |
408 | } |
409 | |
410 | /*! |
411 | \qmlproperty bool QtQuick.Effects::MultiEffect::blurEnabled |
412 | |
413 | Enables the blur effect. |
414 | |
415 | \include notes.qdocinc performance shader regen |
416 | */ |
417 | bool QQuickMultiEffect::blurEnabled() const |
418 | { |
419 | Q_D(const QQuickMultiEffect); |
420 | return d->blurEnabled(); |
421 | } |
422 | |
423 | void QQuickMultiEffect::setBlurEnabled(bool enabled) |
424 | { |
425 | Q_D(QQuickMultiEffect); |
426 | d->setBlurEnabled(enabled); |
427 | } |
428 | |
429 | /*! |
430 | \qmlproperty real QtQuick.Effects::MultiEffect::blur |
431 | |
432 | This property defines how much blur (radius) is applied to the source. |
433 | |
434 | The value ranges from 0.0 (no blur) to 1.0 (full blur). By default, |
435 | the property is set to \c 0.0 (no change). The amount of full blur |
436 | is affected by blurMax and blurMultiplier. |
437 | |
438 | \b {Performance note:} If you don't need to go close to 1.0 at any point |
439 | of blur animations, consider reducing blurMax or blurMultiplier for |
440 | optimal performance. |
441 | */ |
442 | qreal QQuickMultiEffect::blur() const |
443 | { |
444 | Q_D(const QQuickMultiEffect); |
445 | return d->blur(); |
446 | } |
447 | |
448 | void QQuickMultiEffect::setBlur(qreal blur) |
449 | { |
450 | Q_D(QQuickMultiEffect); |
451 | d->setBlur(blur); |
452 | } |
453 | |
454 | /*! |
455 | \qmlproperty int QtQuick.Effects::MultiEffect::blurMax |
456 | |
457 | This property defines the maximum pixel radius that blur with value |
458 | 1.0 will reach. |
459 | |
460 | Meaningful range of this value is from 2 (subtle blur) to 64 (high |
461 | blur). By default, the property is set to \c 32. For the most optimal |
462 | performance, select as small value as you need. |
463 | |
464 | \note This affects to both blur and shadow effects. |
465 | |
466 | \include notes.qdocinc performance shader regen |
467 | |
468 | \include notes.qdocinc performance item resize |
469 | */ |
470 | int QQuickMultiEffect::blurMax() const |
471 | { |
472 | Q_D(const QQuickMultiEffect); |
473 | return d->blurMax(); |
474 | } |
475 | |
476 | void QQuickMultiEffect::setBlurMax(int blurMax) |
477 | { |
478 | Q_D(QQuickMultiEffect); |
479 | d->setBlurMax(blurMax); |
480 | } |
481 | |
482 | /*! |
483 | \qmlproperty real QtQuick.Effects::MultiEffect::blurMultiplier |
484 | |
485 | This property defines a multiplier for extending the blur radius. |
486 | |
487 | The value ranges from 0.0 (not multiplied) to inf. By default, |
488 | the property is set to \c 0.0. Incresing the multiplier extends the |
489 | blur radius, but decreases the blur quality. This is more performant |
490 | option for a bigger blur radius than blurMax as it doesn't increase |
491 | the amount of texture lookups. |
492 | |
493 | \note This affects to both blur and shadow effects. |
494 | |
495 | \include notes.qdocinc performance item resize |
496 | */ |
497 | qreal QQuickMultiEffect::blurMultiplier() const |
498 | { |
499 | Q_D(const QQuickMultiEffect); |
500 | return d->blurMultiplier(); |
501 | } |
502 | |
503 | void QQuickMultiEffect::setBlurMultiplier(qreal blurMultiplier) |
504 | { |
505 | Q_D(QQuickMultiEffect); |
506 | d->setBlurMultiplier(blurMultiplier); |
507 | } |
508 | |
509 | /*! |
510 | \qmlproperty bool QtQuick.Effects::MultiEffect::shadowEnabled |
511 | |
512 | Enables the shadow effect. |
513 | |
514 | \include notes.qdocinc performance shader regen |
515 | */ |
516 | bool QQuickMultiEffect::shadowEnabled() const |
517 | { |
518 | Q_D(const QQuickMultiEffect); |
519 | return d->shadowEnabled(); |
520 | } |
521 | |
522 | void QQuickMultiEffect::setShadowEnabled(bool enabled) |
523 | { |
524 | Q_D(QQuickMultiEffect); |
525 | d->setShadowEnabled(enabled); |
526 | } |
527 | |
528 | /*! |
529 | \qmlproperty real QtQuick.Effects::MultiEffect::shadowOpacity |
530 | |
531 | This property defines the opacity of the drop shadow. This value |
532 | is multiplied with the \c shadowColor alpha value. |
533 | |
534 | The value ranges from 0.0 (fully transparent) to 1.0 (fully opaque). |
535 | By default, the property is set to \c 1.0. |
536 | */ |
537 | qreal QQuickMultiEffect::shadowOpacity() const |
538 | { |
539 | Q_D(const QQuickMultiEffect); |
540 | return d->shadowOpacity(); |
541 | } |
542 | |
543 | void QQuickMultiEffect::setShadowOpacity(qreal shadowOpacity) |
544 | { |
545 | Q_D(QQuickMultiEffect); |
546 | d->setShadowOpacity(shadowOpacity); |
547 | } |
548 | |
549 | /*! |
550 | \qmlproperty real QtQuick.Effects::MultiEffect::shadowBlur |
551 | |
552 | This property defines how much blur (radius) is applied to the shadow. |
553 | |
554 | The value ranges from 0.0 (no blur) to 1.0 (full blur). By default, |
555 | the property is set to \c 1.0. The amount of full blur |
556 | is affected by blurMax and blurMultiplier. |
557 | |
558 | \b {Performance note:} The most optimal way to reduce shadow blurring is |
559 | to make blurMax smaller (if it isn't needed for item blur). Just remember |
560 | to not adjust blurMax during animations. |
561 | */ |
562 | qreal QQuickMultiEffect::shadowBlur() const |
563 | { |
564 | Q_D(const QQuickMultiEffect); |
565 | return d->shadowBlur(); |
566 | } |
567 | |
568 | void QQuickMultiEffect::setShadowBlur(qreal shadowBlur) |
569 | { |
570 | Q_D(QQuickMultiEffect); |
571 | d->setShadowBlur(shadowBlur); |
572 | } |
573 | |
574 | /*! |
575 | \qmlproperty real QtQuick.Effects::MultiEffect::shadowHorizontalOffset |
576 | |
577 | This property defines the horizontal offset of the shadow from the |
578 | item center. |
579 | |
580 | The value ranges from -inf to inf. By default, the property is set |
581 | to \c 0.0. |
582 | |
583 | \note When moving shadow position away from center and adding |
584 | shadowBlur, you possibly also need to increase the paddingRect |
585 | accordingly if you want the shadow to not be clipped. |
586 | */ |
587 | qreal QQuickMultiEffect::shadowHorizontalOffset() const |
588 | { |
589 | Q_D(const QQuickMultiEffect); |
590 | return d->shadowHorizontalOffset(); |
591 | } |
592 | |
593 | void QQuickMultiEffect::setShadowHorizontalOffset(qreal offset) |
594 | { |
595 | Q_D(QQuickMultiEffect); |
596 | d->setShadowHorizontalOffset(offset); |
597 | } |
598 | |
599 | /*! |
600 | \qmlproperty real QtQuick.Effects::MultiEffect::shadowVerticalOffset |
601 | |
602 | This property defines the vertical offset of the shadow from the |
603 | item center. |
604 | |
605 | The value ranges from -inf to inf. By default, the property is set |
606 | to \c 0.0. |
607 | |
608 | \note When moving shadow position away from center and adding |
609 | shadowBlur, you possibly also need to increase the paddingRect |
610 | accordingly if you want the shadow to not be clipped. |
611 | */ |
612 | qreal QQuickMultiEffect::shadowVerticalOffset() const |
613 | { |
614 | Q_D(const QQuickMultiEffect); |
615 | return d->shadowVerticalOffset(); |
616 | } |
617 | |
618 | void QQuickMultiEffect::setShadowVerticalOffset(qreal offset) |
619 | { |
620 | Q_D(QQuickMultiEffect); |
621 | d->setShadowVerticalOffset(offset); |
622 | } |
623 | |
624 | /*! |
625 | \qmlproperty color QtQuick.Effects::MultiEffect::shadowColor |
626 | |
627 | This property defines the RGBA color value which is used for |
628 | the shadow. It is useful for example when a shadow is used for |
629 | simulating a glow effect. |
630 | |
631 | By default, the property is set to \c {Qt.rgba(0.0, 0.0, 0.0, 1.0)} |
632 | (black). |
633 | */ |
634 | QColor QQuickMultiEffect::shadowColor() const |
635 | { |
636 | Q_D(const QQuickMultiEffect); |
637 | return d->shadowColor(); |
638 | } |
639 | |
640 | void QQuickMultiEffect::setShadowColor(const QColor &color) |
641 | { |
642 | Q_D(QQuickMultiEffect); |
643 | d->setShadowColor(color); |
644 | } |
645 | |
646 | /*! |
647 | \qmlproperty real QtQuick.Effects::MultiEffect::shadowScale |
648 | |
649 | This property defines the scale of the shadow. Scaling is applied from |
650 | the center of the item. |
651 | |
652 | The value ranges from 0 to inf. By default, the property is set to |
653 | \c 1.0. |
654 | |
655 | \note When increasing the shadowScale, you possibly also need to |
656 | increase the paddingRect accordingly to avoid the shadow from being |
657 | clipped. |
658 | */ |
659 | qreal QQuickMultiEffect::shadowScale() const |
660 | { |
661 | Q_D(const QQuickMultiEffect); |
662 | return d->shadowScale(); |
663 | } |
664 | |
665 | void QQuickMultiEffect::setShadowScale(qreal shadowScale) |
666 | { |
667 | Q_D(QQuickMultiEffect); |
668 | d->setShadowScale(shadowScale); |
669 | } |
670 | |
671 | /*! |
672 | \qmlproperty bool QtQuick.Effects::MultiEffect::maskEnabled |
673 | |
674 | Enables the mask effect. |
675 | |
676 | \include notes.qdocinc performance shader regen |
677 | */ |
678 | bool QQuickMultiEffect::maskEnabled() const |
679 | { |
680 | Q_D(const QQuickMultiEffect); |
681 | return d->maskEnabled(); |
682 | } |
683 | |
684 | void QQuickMultiEffect::setMaskEnabled(bool enabled) |
685 | { |
686 | Q_D(QQuickMultiEffect); |
687 | d->setMaskEnabled(enabled); |
688 | } |
689 | |
690 | /*! |
691 | \qmlproperty Item QtQuick.Effects::MultiEffect::maskSource |
692 | |
693 | Source item for the mask effect. Should point to ShaderEffectSource, |
694 | item with \l {QtQuick::Item::layer.enabled} {layer.enabled} set to \c true, |
695 | or to an item that can be directly used as a texture source (for example, |
696 | \l [QML] Image). The alpha channel of the source item is used for masking. |
697 | |
698 | If the maskSource and the source have different dimensions, the maskSource |
699 | image is stretched to match the source size. |
700 | */ |
701 | QQuickItem *QQuickMultiEffect::maskSource() const |
702 | { |
703 | Q_D(const QQuickMultiEffect); |
704 | return d->maskSource(); |
705 | } |
706 | |
707 | void QQuickMultiEffect::setMaskSource(QQuickItem *item) |
708 | { |
709 | Q_D(QQuickMultiEffect); |
710 | d->setMaskSource(item); |
711 | } |
712 | |
713 | /*! |
714 | \qmlproperty real QtQuick.Effects::MultiEffect::maskThresholdMin |
715 | |
716 | This property defines a lower threshold value for the mask pixels. |
717 | The mask pixels that have an alpha value below this property are used |
718 | to completely mask away the corresponding pixels from the source item. |
719 | The mask pixels that have a higher alpha value are used to alphablend |
720 | the source item to the display. |
721 | |
722 | The value ranges from 0.0 (alpha value 0) to 1.0 (alpha value 255). By |
723 | default, the property is set to \c 0.0. |
724 | */ |
725 | qreal QQuickMultiEffect::maskThresholdMin() const |
726 | { |
727 | Q_D(const QQuickMultiEffect); |
728 | return d->maskThresholdMin(); |
729 | } |
730 | |
731 | void QQuickMultiEffect::setMaskThresholdMin(qreal threshold) |
732 | { |
733 | Q_D(QQuickMultiEffect); |
734 | d->setMaskThresholdMin(threshold); |
735 | } |
736 | |
737 | /*! |
738 | \qmlproperty real QtQuick.Effects::MultiEffect::maskSpreadAtMin |
739 | |
740 | This property defines the smoothness of the mask edges near the |
741 | maskThresholdMin. Setting higher spread values softens the transition |
742 | from the transparent mask pixels towards opaque mask pixels by adding |
743 | interpolated values between them. |
744 | |
745 | The value ranges from 0.0 (sharp mask edge) to 1.0 (smooth mask edge). |
746 | By default, the property is set to \c 0.0. |
747 | */ |
748 | qreal QQuickMultiEffect::maskSpreadAtMin() const |
749 | { |
750 | Q_D(const QQuickMultiEffect); |
751 | return d->maskSpreadAtMin(); |
752 | } |
753 | |
754 | void QQuickMultiEffect::setMaskSpreadAtMin(qreal spread) |
755 | { |
756 | Q_D(QQuickMultiEffect); |
757 | d->setMaskSpreadAtMin(spread); |
758 | } |
759 | |
760 | /*! |
761 | \qmlproperty real QtQuick.Effects::MultiEffect::maskThresholdMax |
762 | |
763 | This property defines an upper threshold value for the mask pixels. |
764 | The mask pixels that have an alpha value below this property are used |
765 | to completely mask away the corresponding pixels from the source item. |
766 | The mask pixels that have a higher alpha value are used to alphablend |
767 | the source item to the display. |
768 | |
769 | The value ranges from 0.0 (alpha value 0) to 1.0 (alpha value 255). By |
770 | default, the property is set to \c 1.0. |
771 | */ |
772 | qreal QQuickMultiEffect::maskThresholdMax() const |
773 | { |
774 | Q_D(const QQuickMultiEffect); |
775 | return d->maskThresholdMax(); |
776 | } |
777 | |
778 | void QQuickMultiEffect::setMaskThresholdMax(qreal threshold) |
779 | { |
780 | Q_D(QQuickMultiEffect); |
781 | d->setMaskThresholdMax(threshold); |
782 | } |
783 | |
784 | /*! |
785 | \qmlproperty real QtQuick.Effects::MultiEffect::maskSpreadAtMax |
786 | |
787 | This property defines the smoothness of the mask edges near the |
788 | maskThresholdMax. Using higher spread values softens the transition |
789 | from the transparent mask pixels towards opaque mask pixels by adding |
790 | interpolated values between them. |
791 | |
792 | The value ranges from 0.0 (sharp mask edge) to 1.0 (smooth mask edge). |
793 | By default, the property is set to \c 0.0. |
794 | */ |
795 | qreal QQuickMultiEffect::maskSpreadAtMax() const |
796 | { |
797 | Q_D(const QQuickMultiEffect); |
798 | return d->maskSpreadAtMax(); |
799 | } |
800 | |
801 | void QQuickMultiEffect::setMaskSpreadAtMax(qreal spread) |
802 | { |
803 | Q_D(QQuickMultiEffect); |
804 | d->setMaskSpreadAtMax(spread); |
805 | } |
806 | |
807 | /*! |
808 | \qmlproperty bool QtQuick.Effects::MultiEffect::maskInverted |
809 | |
810 | This property switches the mask to the opposite side; instead of |
811 | masking away the content outside maskThresholdMin and maskThresholdMax, |
812 | content between them will get masked away. |
813 | |
814 | By default, the property is set to \c false. |
815 | */ |
816 | bool QQuickMultiEffect::maskInverted() const |
817 | { |
818 | Q_D(const QQuickMultiEffect); |
819 | return d->maskInverted(); |
820 | } |
821 | |
822 | void QQuickMultiEffect::setMaskInverted(bool inverted) |
823 | { |
824 | Q_D(QQuickMultiEffect); |
825 | d->setMaskInverted(inverted); |
826 | } |
827 | |
828 | /*! |
829 | \qmlproperty rect QtQuick.Effects::MultiEffect::itemRect |
830 | \readonly |
831 | |
832 | Read-only access to effect item rectangle. This can be used e.g. to see |
833 | the area item covers. |
834 | |
835 | \sa paddingRect, autoPaddingEnabled |
836 | */ |
837 | QRectF QQuickMultiEffect::itemRect() const |
838 | { |
839 | Q_D(const QQuickMultiEffect); |
840 | return d->itemRect(); |
841 | } |
842 | |
843 | /*! |
844 | \qmlproperty string QtQuick.Effects::MultiEffect::fragmentShader |
845 | \readonly |
846 | |
847 | Read-only access to filename of the currently used fragment shader. |
848 | */ |
849 | QString QQuickMultiEffect::fragmentShader() const |
850 | { |
851 | Q_D(const QQuickMultiEffect); |
852 | return d->fragmentShader(); |
853 | } |
854 | |
855 | /*! |
856 | \qmlproperty string QtQuick.Effects::MultiEffect::vertexShader |
857 | \readonly |
858 | |
859 | Read-only access to filename of the currently used vertex shader. |
860 | */ |
861 | QString QQuickMultiEffect::vertexShader() const |
862 | { |
863 | Q_D(const QQuickMultiEffect); |
864 | return d->vertexShader(); |
865 | } |
866 | |
867 | /*! |
868 | \qmlproperty bool QtQuick.Effects::MultiEffect::hasProxySource |
869 | \readonly |
870 | |
871 | Returns true when the MultiEffect internally creates \l ShaderEffectSource |
872 | for the \l source item and false when \l source item is used as-is. |
873 | For example when source is \l Image element or \l Item with |
874 | \l {QtQuick::Item::layer.enabled} {layer.enabled} set to \c true, |
875 | this additional proxy source is not needed. |
876 | */ |
877 | bool QQuickMultiEffect::hasProxySource() const |
878 | { |
879 | Q_D(const QQuickMultiEffect); |
880 | return d->hasProxySource(); |
881 | } |
882 | |
883 | // *** protected *** |
884 | |
885 | void QQuickMultiEffect::componentComplete() |
886 | { |
887 | Q_D(QQuickMultiEffect); |
888 | QQuickItem::componentComplete(); |
889 | d->initialize(); |
890 | } |
891 | |
892 | void QQuickMultiEffect::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) |
893 | { |
894 | Q_D(QQuickMultiEffect); |
895 | QQuickItem::geometryChange(newGeometry, oldGeometry); |
896 | if (width() > 0 && height() > 0) |
897 | d->handleGeometryChange(newGeometry, oldGeometry); |
898 | } |
899 | |
900 | void QQuickMultiEffect::itemChange(ItemChange change, const ItemChangeData &value) |
901 | { |
902 | Q_D(QQuickMultiEffect); |
903 | d->handleItemChange(change, value); |
904 | QQuickItem::itemChange(change, value); |
905 | } |
906 | |
907 | // *** private *** |
908 | |
909 | QQuickMultiEffectPrivate::QQuickMultiEffectPrivate() |
910 | { |
911 | } |
912 | |
913 | QQuickMultiEffectPrivate::~QQuickMultiEffectPrivate() |
914 | { |
915 | } |
916 | |
917 | void QQuickMultiEffectPrivate::handleGeometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) |
918 | { |
919 | Q_UNUSED(oldGeometry); |
920 | Q_UNUSED(newGeometry); |
921 | initialize(); |
922 | if (!m_shaderEffect) |
923 | return; |
924 | updateBlurItemSizes(); |
925 | updateSourcePadding(); |
926 | } |
927 | |
928 | void QQuickMultiEffectPrivate::handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) |
929 | { |
930 | Q_UNUSED(value); |
931 | if (change == QQuickItem::ItemSceneChange) |
932 | initialize(); |
933 | } |
934 | |
935 | |
936 | QQuickItem *QQuickMultiEffectPrivate::source() const |
937 | { |
938 | return m_sourceItem; |
939 | } |
940 | |
941 | void QQuickMultiEffectPrivate::setSource(QQuickItem *item) |
942 | { |
943 | Q_Q(QQuickMultiEffect); |
944 | if (item == m_sourceItem) |
945 | return; |
946 | |
947 | m_sourceItem = item; |
948 | if (m_shaderSource) |
949 | m_shaderSource->setInput(m_sourceItem); |
950 | |
951 | updateSourcePadding(); |
952 | q->update(); |
953 | Q_EMIT q->sourceChanged(); |
954 | } |
955 | |
956 | bool QQuickMultiEffectPrivate::autoPaddingEnabled() const |
957 | { |
958 | return m_autoPaddingEnabled; |
959 | } |
960 | |
961 | void QQuickMultiEffectPrivate::setAutoPaddingEnabled(bool enabled) |
962 | { |
963 | Q_Q(QQuickMultiEffect); |
964 | if (enabled == m_autoPaddingEnabled) |
965 | return; |
966 | |
967 | m_autoPaddingEnabled = enabled; |
968 | updateSourcePadding(); |
969 | q->update(); |
970 | Q_EMIT q->autoPaddingEnabledChanged(); |
971 | } |
972 | |
973 | QRectF QQuickMultiEffectPrivate::paddingRect() const |
974 | { |
975 | return m_paddingRect; |
976 | } |
977 | |
978 | void QQuickMultiEffectPrivate::setPaddingRect(const QRectF &rect) |
979 | { |
980 | Q_Q(QQuickMultiEffect); |
981 | if (rect == m_paddingRect) |
982 | return; |
983 | m_paddingRect = rect; |
984 | updateCenterOffset(); |
985 | updateSourcePadding(); |
986 | q->update(); |
987 | emit q->paddingRectChanged(); |
988 | } |
989 | |
990 | qreal QQuickMultiEffectPrivate::brightness() const |
991 | { |
992 | return m_brightness; |
993 | } |
994 | |
995 | void QQuickMultiEffectPrivate::setBrightness(qreal brightness) |
996 | { |
997 | Q_Q(QQuickMultiEffect); |
998 | if (brightness == m_brightness) |
999 | return; |
1000 | |
1001 | m_brightness = brightness; |
1002 | if (m_shaderEffect) |
1003 | m_shaderEffect->setProperty(name: "brightness" , value: m_brightness); |
1004 | |
1005 | q->update(); |
1006 | Q_EMIT q->brightnessChanged(); |
1007 | } |
1008 | |
1009 | qreal QQuickMultiEffectPrivate::contrast() const |
1010 | { |
1011 | return m_contrast; |
1012 | } |
1013 | |
1014 | void QQuickMultiEffectPrivate::setContrast(qreal contrast) |
1015 | { |
1016 | Q_Q(QQuickMultiEffect); |
1017 | if (contrast == m_contrast) |
1018 | return; |
1019 | |
1020 | m_contrast = contrast; |
1021 | if (m_shaderEffect) |
1022 | m_shaderEffect->setProperty(name: "contrast" , value: m_contrast); |
1023 | |
1024 | q->update(); |
1025 | Q_EMIT q->contrastChanged(); |
1026 | } |
1027 | |
1028 | qreal QQuickMultiEffectPrivate::saturation() const |
1029 | { |
1030 | return m_saturation; |
1031 | } |
1032 | |
1033 | void QQuickMultiEffectPrivate::setSaturation(qreal saturation) |
1034 | { |
1035 | Q_Q(QQuickMultiEffect); |
1036 | if (saturation == m_saturation) |
1037 | return; |
1038 | |
1039 | m_saturation = saturation; |
1040 | if (m_shaderEffect) |
1041 | m_shaderEffect->setProperty(name: "saturation" , value: m_saturation); |
1042 | |
1043 | q->update(); |
1044 | Q_EMIT q->saturationChanged(); |
1045 | } |
1046 | |
1047 | qreal QQuickMultiEffectPrivate::colorization() const |
1048 | { |
1049 | return m_colorization; |
1050 | } |
1051 | |
1052 | void QQuickMultiEffectPrivate::setColorization(qreal colorization) |
1053 | { |
1054 | Q_Q(QQuickMultiEffect); |
1055 | if (colorization == m_colorization) |
1056 | return; |
1057 | |
1058 | m_colorization = colorization; |
1059 | updateColorizationColor(); |
1060 | |
1061 | q->update(); |
1062 | Q_EMIT q->colorizationChanged(); |
1063 | } |
1064 | |
1065 | QColor QQuickMultiEffectPrivate::colorizationColor() const |
1066 | { |
1067 | return m_colorizationColor; |
1068 | } |
1069 | |
1070 | void QQuickMultiEffectPrivate::setColorizationColor(const QColor &color) |
1071 | { |
1072 | Q_Q(QQuickMultiEffect); |
1073 | if (color == m_colorizationColor) |
1074 | return; |
1075 | |
1076 | m_colorizationColor = color; |
1077 | updateColorizationColor(); |
1078 | |
1079 | q->update(); |
1080 | Q_EMIT q->colorizationColorChanged(); |
1081 | } |
1082 | |
1083 | bool QQuickMultiEffectPrivate::blurEnabled() const |
1084 | { |
1085 | return m_blurEnabled; |
1086 | } |
1087 | |
1088 | void QQuickMultiEffectPrivate::setBlurEnabled(bool enabled) |
1089 | { |
1090 | Q_Q(QQuickMultiEffect); |
1091 | if (enabled == m_blurEnabled) |
1092 | return; |
1093 | |
1094 | m_blurEnabled = enabled; |
1095 | updateSourcePadding(); |
1096 | updateBlurLevel(); |
1097 | updateEffectShaders(); |
1098 | |
1099 | q->update(); |
1100 | Q_EMIT q->blurEnabledChanged(); |
1101 | } |
1102 | |
1103 | qreal QQuickMultiEffectPrivate::blur() const |
1104 | { |
1105 | return m_blur; |
1106 | } |
1107 | |
1108 | void QQuickMultiEffectPrivate::setBlur(qreal blur) |
1109 | { |
1110 | Q_Q(QQuickMultiEffect); |
1111 | if (blur == m_blur) |
1112 | return; |
1113 | |
1114 | m_blur = blur; |
1115 | updateBlurWeights(); |
1116 | |
1117 | q->update(); |
1118 | Q_EMIT q->blurChanged(); |
1119 | } |
1120 | |
1121 | int QQuickMultiEffectPrivate::blurMax() const |
1122 | { |
1123 | return m_blurMax; |
1124 | } |
1125 | |
1126 | void QQuickMultiEffectPrivate::setBlurMax(int blurMax) |
1127 | { |
1128 | Q_Q(QQuickMultiEffect); |
1129 | if (blurMax == m_blurMax) |
1130 | return; |
1131 | |
1132 | m_blurMax = blurMax; |
1133 | updateSourcePadding(); |
1134 | updateBlurLevel(); |
1135 | updateBlurItemSizes(); |
1136 | updateBlurWeights(); |
1137 | updateShadowBlurWeights(); |
1138 | updateEffectShaders(); |
1139 | |
1140 | q->update(); |
1141 | Q_EMIT q->blurMaxChanged(); |
1142 | } |
1143 | |
1144 | qreal QQuickMultiEffectPrivate::blurMultiplier() const |
1145 | { |
1146 | return m_blurMultiplier; |
1147 | } |
1148 | |
1149 | void QQuickMultiEffectPrivate::setBlurMultiplier(qreal blurMultiplier) |
1150 | { |
1151 | Q_Q(QQuickMultiEffect); |
1152 | if (blurMultiplier == m_blurMultiplier) |
1153 | return; |
1154 | |
1155 | m_blurMultiplier = blurMultiplier; |
1156 | updateSourcePadding(); |
1157 | updateBlurItemSizes(forceUpdate: true); |
1158 | updateBlurWeights(); |
1159 | updateShadowBlurWeights(); |
1160 | |
1161 | q->update(); |
1162 | Q_EMIT q->blurMultiplierChanged(); |
1163 | } |
1164 | |
1165 | bool QQuickMultiEffectPrivate::shadowEnabled() const |
1166 | { |
1167 | return m_shadowEnabled; |
1168 | } |
1169 | |
1170 | void QQuickMultiEffectPrivate::setShadowEnabled(bool enabled) |
1171 | { |
1172 | Q_Q(QQuickMultiEffect); |
1173 | if (enabled == m_shadowEnabled) |
1174 | return; |
1175 | |
1176 | m_shadowEnabled = enabled; |
1177 | updateSourcePadding(); |
1178 | updateBlurLevel(); |
1179 | updateEffectShaders(); |
1180 | |
1181 | q->update(); |
1182 | Q_EMIT q->shadowEnabledChanged(); |
1183 | } |
1184 | |
1185 | qreal QQuickMultiEffectPrivate::shadowOpacity() const |
1186 | { |
1187 | return m_shadowOpacity; |
1188 | } |
1189 | |
1190 | void QQuickMultiEffectPrivate::setShadowOpacity(qreal shadowOpacity) |
1191 | { |
1192 | Q_Q(QQuickMultiEffect); |
1193 | if (shadowOpacity == m_shadowOpacity) |
1194 | return; |
1195 | |
1196 | m_shadowOpacity = shadowOpacity; |
1197 | updateShadowColor(); |
1198 | |
1199 | q->update(); |
1200 | Q_EMIT q->shadowOpacityChanged(); |
1201 | } |
1202 | |
1203 | qreal QQuickMultiEffectPrivate::shadowBlur() const |
1204 | { |
1205 | return m_shadowBlur; |
1206 | } |
1207 | |
1208 | void QQuickMultiEffectPrivate::setShadowBlur(qreal shadowBlur) |
1209 | { |
1210 | Q_Q(QQuickMultiEffect); |
1211 | if (shadowBlur == m_shadowBlur) |
1212 | return; |
1213 | |
1214 | m_shadowBlur = shadowBlur; |
1215 | updateShadowBlurWeights(); |
1216 | |
1217 | q->update(); |
1218 | Q_EMIT q->shadowBlurChanged(); |
1219 | } |
1220 | |
1221 | qreal QQuickMultiEffectPrivate::shadowHorizontalOffset() const |
1222 | { |
1223 | return m_shadowHorizontalOffset; |
1224 | } |
1225 | |
1226 | void QQuickMultiEffectPrivate::setShadowHorizontalOffset(qreal offset) |
1227 | { |
1228 | Q_Q(QQuickMultiEffect); |
1229 | if (offset == m_shadowHorizontalOffset) |
1230 | return; |
1231 | |
1232 | m_shadowHorizontalOffset = offset; |
1233 | updateShadowOffset(); |
1234 | |
1235 | q->update(); |
1236 | Q_EMIT q->shadowHorizontalOffsetChanged(); |
1237 | } |
1238 | |
1239 | qreal QQuickMultiEffectPrivate::shadowVerticalOffset() const |
1240 | { |
1241 | return m_shadowVerticalOffset; |
1242 | } |
1243 | |
1244 | void QQuickMultiEffectPrivate::setShadowVerticalOffset(qreal offset) |
1245 | { |
1246 | Q_Q(QQuickMultiEffect); |
1247 | if (offset == m_shadowVerticalOffset) |
1248 | return; |
1249 | |
1250 | m_shadowVerticalOffset = offset; |
1251 | updateShadowOffset(); |
1252 | |
1253 | q->update(); |
1254 | Q_EMIT q->shadowVerticalOffsetChanged(); |
1255 | } |
1256 | |
1257 | QColor QQuickMultiEffectPrivate::shadowColor() const |
1258 | { |
1259 | return m_shadowColor; |
1260 | } |
1261 | |
1262 | void QQuickMultiEffectPrivate::setShadowColor(const QColor &color) |
1263 | { |
1264 | Q_Q(QQuickMultiEffect); |
1265 | if (color == m_shadowColor) |
1266 | return; |
1267 | |
1268 | m_shadowColor = color; |
1269 | updateShadowColor(); |
1270 | |
1271 | q->update(); |
1272 | Q_EMIT q->shadowColorChanged(); |
1273 | } |
1274 | |
1275 | qreal QQuickMultiEffectPrivate::shadowScale() const |
1276 | { |
1277 | return m_shadowScale; |
1278 | } |
1279 | |
1280 | void QQuickMultiEffectPrivate::setShadowScale(qreal shadowScale) |
1281 | { |
1282 | Q_Q(QQuickMultiEffect); |
1283 | if (shadowScale == m_shadowScale) |
1284 | return; |
1285 | |
1286 | m_shadowScale = shadowScale; |
1287 | updateCenterOffset(); |
1288 | if (m_shaderEffect) |
1289 | m_shaderEffect->setProperty(name: "shadowScale" , value: 1.0 / m_shadowScale); |
1290 | |
1291 | q->update(); |
1292 | Q_EMIT q->shadowScaleChanged(); |
1293 | } |
1294 | |
1295 | bool QQuickMultiEffectPrivate::maskEnabled() const |
1296 | { |
1297 | return m_maskEnabled; |
1298 | } |
1299 | |
1300 | void QQuickMultiEffectPrivate::setMaskEnabled(bool enabled) |
1301 | { |
1302 | Q_Q(QQuickMultiEffect); |
1303 | if (enabled == m_maskEnabled) |
1304 | return; |
1305 | |
1306 | m_maskEnabled = enabled; |
1307 | updateEffectShaders(); |
1308 | |
1309 | q->update(); |
1310 | Q_EMIT q->maskEnabledChanged(); |
1311 | } |
1312 | |
1313 | QQuickItem *QQuickMultiEffectPrivate::maskSource() const |
1314 | { |
1315 | return m_maskSourceItem; |
1316 | } |
1317 | |
1318 | void QQuickMultiEffectPrivate::setMaskSource(QQuickItem *item) |
1319 | { |
1320 | Q_Q(QQuickMultiEffect); |
1321 | if (item == m_maskSourceItem) |
1322 | return; |
1323 | |
1324 | m_maskSourceItem = item; |
1325 | if (m_shaderEffect) { |
1326 | auto maskSourceVariant = QVariant::fromValue<QQuickItem*>(value: m_maskSourceItem); |
1327 | m_shaderEffect->setProperty(name: "maskSrc" , value: maskSourceVariant); |
1328 | } |
1329 | |
1330 | q->update(); |
1331 | Q_EMIT q->maskSourceChanged(); |
1332 | } |
1333 | |
1334 | qreal QQuickMultiEffectPrivate::maskThresholdMin() const |
1335 | { |
1336 | return m_maskThresholdMin; |
1337 | } |
1338 | |
1339 | void QQuickMultiEffectPrivate::setMaskThresholdMin(qreal threshold) |
1340 | { |
1341 | Q_Q(QQuickMultiEffect); |
1342 | if (threshold == m_maskThresholdMin) |
1343 | return; |
1344 | |
1345 | m_maskThresholdMin = threshold; |
1346 | updateMaskThresholdSpread(); |
1347 | |
1348 | q->update(); |
1349 | Q_EMIT q->maskThresholdMinChanged(); |
1350 | } |
1351 | |
1352 | qreal QQuickMultiEffectPrivate::maskSpreadAtMin() const |
1353 | { |
1354 | return m_maskSpreadAtMin; |
1355 | } |
1356 | |
1357 | void QQuickMultiEffectPrivate::setMaskSpreadAtMin(qreal spread) |
1358 | { |
1359 | Q_Q(QQuickMultiEffect); |
1360 | if (spread == m_maskSpreadAtMin) |
1361 | return; |
1362 | |
1363 | m_maskSpreadAtMin = spread; |
1364 | updateMaskThresholdSpread(); |
1365 | |
1366 | q->update(); |
1367 | Q_EMIT q->maskSpreadAtMinChanged(); |
1368 | } |
1369 | |
1370 | qreal QQuickMultiEffectPrivate::maskThresholdMax() const |
1371 | { |
1372 | return m_maskThresholdMax; |
1373 | } |
1374 | |
1375 | void QQuickMultiEffectPrivate::setMaskThresholdMax(qreal threshold) |
1376 | { |
1377 | Q_Q(QQuickMultiEffect); |
1378 | if (threshold == m_maskThresholdMax) |
1379 | return; |
1380 | |
1381 | m_maskThresholdMax = threshold; |
1382 | updateMaskThresholdSpread(); |
1383 | |
1384 | q->update(); |
1385 | Q_EMIT q->maskThresholdMaxChanged(); |
1386 | } |
1387 | |
1388 | qreal QQuickMultiEffectPrivate::maskSpreadAtMax() const |
1389 | { |
1390 | return m_maskSpreadAtMax; |
1391 | } |
1392 | |
1393 | void QQuickMultiEffectPrivate::setMaskSpreadAtMax(qreal spread) |
1394 | { |
1395 | Q_Q(QQuickMultiEffect); |
1396 | if (spread == m_maskSpreadAtMax) |
1397 | return; |
1398 | |
1399 | m_maskSpreadAtMax = spread; |
1400 | updateMaskThresholdSpread(); |
1401 | |
1402 | q->update(); |
1403 | Q_EMIT q->maskSpreadAtMaxChanged(); |
1404 | } |
1405 | |
1406 | bool QQuickMultiEffectPrivate::maskInverted() const |
1407 | { |
1408 | return m_maskInverted; |
1409 | } |
1410 | |
1411 | void QQuickMultiEffectPrivate::setMaskInverted(bool inverted) |
1412 | { |
1413 | Q_Q(QQuickMultiEffect); |
1414 | if (inverted == m_maskInverted) |
1415 | return; |
1416 | |
1417 | m_maskInverted = inverted; |
1418 | if (m_shaderEffect) |
1419 | m_shaderEffect->setProperty(name: "maskInverted" , value: float(m_maskInverted)); |
1420 | |
1421 | q->update(); |
1422 | Q_EMIT q->maskInvertedChanged(); |
1423 | } |
1424 | |
1425 | QRectF QQuickMultiEffectPrivate::itemRect() const |
1426 | { |
1427 | if (!m_shaderEffect || !m_shaderSource) |
1428 | return QRectF(); |
1429 | |
1430 | QRectF sourceRect = m_shaderSource->sourceRect(); |
1431 | if (sourceRect.width() > 0 && sourceRect.height() > 0) |
1432 | return sourceRect; |
1433 | else |
1434 | return m_shaderEffect->boundingRect(); |
1435 | } |
1436 | |
1437 | QString QQuickMultiEffectPrivate::fragmentShader() const |
1438 | { |
1439 | return m_fragShader; |
1440 | } |
1441 | |
1442 | QString QQuickMultiEffectPrivate::vertexShader() const |
1443 | { |
1444 | return m_vertShader; |
1445 | } |
1446 | |
1447 | bool QQuickMultiEffectPrivate::hasProxySource() const |
1448 | { |
1449 | return m_shaderSource && m_shaderSource->isActive(); |
1450 | } |
1451 | |
1452 | // This initializes the component. It will be ran once, when |
1453 | // the component is ready and it has a valid size. |
1454 | void QQuickMultiEffectPrivate::initialize() |
1455 | { |
1456 | Q_Q(QQuickMultiEffect); |
1457 | if (m_initialized) |
1458 | return; |
1459 | if (!q->isComponentComplete()) |
1460 | return; |
1461 | if (!q->window()) |
1462 | return; |
1463 | if (q->width() <= 0 || q->height() <= 0) |
1464 | return; |
1465 | |
1466 | m_shaderEffect = new QQuickShaderEffect(q); |
1467 | m_shaderSource = new QGfxSourceProxyME(q); |
1468 | QObject::connect(sender: m_shaderSource, signal: &QGfxSourceProxyME::outputChanged, context: q, slot: [this] { proxyOutputChanged(); }); |
1469 | QObject::connect(sender: m_shaderSource, signal: &QGfxSourceProxyME::activeChanged, context: q, slot: &QQuickMultiEffect::hasProxySourceChanged); |
1470 | |
1471 | m_shaderEffect->setParentItem(q); |
1472 | m_shaderEffect->setSize(q->size()); |
1473 | |
1474 | m_shaderSource->setParentItem(q); |
1475 | m_shaderSource->setSize(q->size()); |
1476 | m_shaderSource->setInput(m_sourceItem); |
1477 | |
1478 | updateCenterOffset(); |
1479 | updateMaskThresholdSpread(); |
1480 | updateBlurWeights(); |
1481 | updateShadowBlurWeights(); |
1482 | updateColorizationColor(); |
1483 | updateShadowColor(); |
1484 | updateShadowOffset(); |
1485 | |
1486 | // Create properties |
1487 | auto sourceVariant = QVariant::fromValue<QQuickItem*>(value: m_shaderSource->output()); |
1488 | m_shaderEffect->setProperty(name: "src" , value: sourceVariant); |
1489 | m_shaderEffect->setProperty(name: "brightness" , value: m_brightness); |
1490 | m_shaderEffect->setProperty(name: "contrast" , value: m_contrast); |
1491 | m_shaderEffect->setProperty(name: "saturation" , value: m_saturation); |
1492 | m_shaderEffect->setProperty(name: "shadowScale" , value: 1.0 / m_shadowScale); |
1493 | auto maskSourceVariant = QVariant::fromValue<QQuickItem*>(value: m_maskSourceItem); |
1494 | m_shaderEffect->setProperty(name: "maskSrc" , value: maskSourceVariant); |
1495 | m_shaderEffect->setProperty(name: "maskInverted" , value: float(m_maskInverted)); |
1496 | |
1497 | updateBlurLevel(); |
1498 | updateBlurItemSizes(); |
1499 | updateSourcePadding(); |
1500 | |
1501 | updateEffectShaders(); |
1502 | |
1503 | m_initialized = true; |
1504 | } |
1505 | |
1506 | void QQuickMultiEffectPrivate::updateMaskThresholdSpread() |
1507 | { |
1508 | if (!m_shaderEffect) |
1509 | return; |
1510 | |
1511 | // Calculate threshold and spread values for mask |
1512 | // smoothstep, keeping always edge0 < edge1. |
1513 | const qreal c0 = 0.0001; |
1514 | const qreal c1 = 1.0 - c0; |
1515 | const qreal mt1 = m_maskThresholdMin + c0; |
1516 | const qreal ms1 = m_maskSpreadAtMin + 1.0; |
1517 | const qreal mt2 = c1 - m_maskThresholdMax; |
1518 | const qreal ms2 = m_maskSpreadAtMax + 1.0; |
1519 | const QVector4D maskThresholdSpread = QVector4D( |
1520 | mt1 * ms1 - (ms1 - c1), |
1521 | mt1 * ms1, |
1522 | mt2 * ms2 - (ms2 - c1), |
1523 | mt2 * ms2); |
1524 | m_shaderEffect->setProperty(name: "mask" , value: maskThresholdSpread); |
1525 | } |
1526 | |
1527 | void QQuickMultiEffectPrivate::updateCenterOffset() |
1528 | { |
1529 | if (!m_shaderEffect) |
1530 | return; |
1531 | |
1532 | const qreal scale = 1.0 / m_shadowScale; |
1533 | QVector2D centerOffset((1.0 - scale) * (0.5 + 0.5 * (m_paddingRect.x() - m_paddingRect.width()) / m_shaderEffect->width()), |
1534 | (1.0 - scale) * (0.5 + 0.5 * (m_paddingRect.y() - m_paddingRect.height()) / m_shaderEffect->height())); |
1535 | m_shaderEffect->setProperty(name: "centerOffset" , value: centerOffset); |
1536 | } |
1537 | |
1538 | void QQuickMultiEffectPrivate::updateShadowOffset() |
1539 | { |
1540 | if (!m_shaderEffect) |
1541 | return; |
1542 | |
1543 | QVector2D shadowOffset = QVector2D(m_shadowHorizontalOffset / m_shaderEffect->width(), m_shadowVerticalOffset / m_shaderEffect->height()); |
1544 | m_shaderEffect->setProperty(name: "shadowOffset" , value: shadowOffset); |
1545 | } |
1546 | |
1547 | void QQuickMultiEffectPrivate::updateColorizationColor() |
1548 | { |
1549 | if (!m_shaderEffect) |
1550 | return; |
1551 | |
1552 | float alpha = std::clamp(val: float(m_colorizationColor.alphaF() * m_colorization), lo: 0.0f, hi: 1.0f); |
1553 | QVector4D colorizationColor(m_colorizationColor.redF(), |
1554 | m_colorizationColor.greenF(), |
1555 | m_colorizationColor.blueF(), |
1556 | alpha); |
1557 | m_shaderEffect->setProperty(name: "colorizationColor" , value: colorizationColor); |
1558 | } |
1559 | |
1560 | void QQuickMultiEffectPrivate::updateShadowColor() |
1561 | { |
1562 | if (!m_shaderEffect) |
1563 | return; |
1564 | |
1565 | // Shader shadowColor has premultiplied alpha |
1566 | float alpha = std::clamp(val: float(m_shadowOpacity), lo: 0.0f, hi: 1.0f); |
1567 | QVector4D shadowColor(m_shadowColor.redF() * alpha, |
1568 | m_shadowColor.greenF() * alpha, |
1569 | m_shadowColor.blueF() * alpha, |
1570 | m_shadowColor.alphaF() * alpha); |
1571 | m_shaderEffect->setProperty(name: "shadowColor" , value: shadowColor); |
1572 | } |
1573 | |
1574 | float QQuickMultiEffectPrivate::calculateLod(float blurAmount) |
1575 | { |
1576 | return qSqrt(v: blurAmount * float(m_blurMax) / 64.0f) * 1.2f - 0.2f; |
1577 | } |
1578 | |
1579 | float QQuickMultiEffectPrivate::blurWeight(float v) |
1580 | { |
1581 | return std::max(a: 0.0f, b: std::min(a: 1.0f, b: 1.0f - v * 2.0f)); |
1582 | } |
1583 | |
1584 | void QQuickMultiEffectPrivate::getBlurWeights(float blurLod, QVector4D &blurWeight1, QVector2D &blurWeight2) |
1585 | { |
1586 | float bw1 = blurWeight(v: std::fabs(x: blurLod - 0.1f)); |
1587 | float bw2 = blurWeight(v: std::fabs(x: blurLod - 0.3f)); |
1588 | float bw3 = blurWeight(v: std::fabs(x: blurLod - 0.5f)); |
1589 | float bw4 = blurWeight(v: std::fabs(x: blurLod - 0.7f)); |
1590 | float bw5 = blurWeight(v: std::fabs(x: blurLod - 0.9f)); |
1591 | float bw6 = blurWeight(v: std::fabs(x: blurLod - 1.1f)); |
1592 | float bsum = bw1 + bw2 + bw3 + bw4 + bw5 + bw6; |
1593 | blurWeight1 = QVector4D(bw1 / bsum, bw2 / bsum, bw3 / bsum, bw4 / bsum); |
1594 | blurWeight2 = QVector2D(bw5 / bsum, bw6 / bsum); |
1595 | } |
1596 | |
1597 | void QQuickMultiEffectPrivate::updateBlurWeights() |
1598 | { |
1599 | if (!m_shaderEffect) |
1600 | return; |
1601 | float blurLod = calculateLod(blurAmount: m_blur); |
1602 | getBlurWeights(blurLod, blurWeight1&: m_blurWeight1, blurWeight2&: m_blurWeight2); |
1603 | m_shaderEffect->setProperty(name: "blurWeight1" , value: m_blurWeight1); |
1604 | m_shaderEffect->setProperty(name: "blurWeight2" , value: m_blurWeight2); |
1605 | } |
1606 | |
1607 | void QQuickMultiEffectPrivate::updateShadowBlurWeights() |
1608 | { |
1609 | if (!m_shaderEffect) |
1610 | return; |
1611 | float blurLod = calculateLod(blurAmount: m_shadowBlur); |
1612 | getBlurWeights(blurLod, blurWeight1&: m_shadowBlurWeight1, blurWeight2&: m_shadowBlurWeight2); |
1613 | m_shaderEffect->setProperty(name: "shadowBlurWeight1" , value: m_shadowBlurWeight1); |
1614 | m_shaderEffect->setProperty(name: "shadowBlurWeight2" , value: m_shadowBlurWeight2); |
1615 | } |
1616 | |
1617 | void QQuickMultiEffectPrivate::updateBlurItemSizes(bool forceUpdate) |
1618 | { |
1619 | if (m_blurEffects.isEmpty() || !m_shaderSource || !m_sourceItem) |
1620 | return; |
1621 | |
1622 | // First blur item size to be half of th source item |
1623 | // extended size, rounded to next divisible by 16. |
1624 | QSizeF sourceSize = itemRect().size(); |
1625 | QSizeF firstItemSize(std::ceil(x: sourceSize.width() / 16) * 8, |
1626 | std::ceil(x: sourceSize.height() / 16) * 8); |
1627 | |
1628 | if (!forceUpdate && m_firstBlurItemSize == firstItemSize) |
1629 | return; |
1630 | |
1631 | qCDebug(lcQuickEffect) << "Source size:" << sourceSize; |
1632 | m_firstBlurItemSize = firstItemSize; |
1633 | |
1634 | for (int i = 0; i < m_blurEffects.size(); i++) { |
1635 | auto *blurEffect = m_blurEffects[i]; |
1636 | QSizeF itemSize = (i == 0) ? firstItemSize : m_blurEffects[i - 1]->size() * 0.5; |
1637 | qCDebug(lcQuickEffect) << "Blur item" << i << ":" << itemSize; |
1638 | blurEffect->setSize(itemSize); |
1639 | |
1640 | const QVector2D offset((1.0 + m_blurMultiplier) / itemSize.width(), |
1641 | (1.0 + m_blurMultiplier) / itemSize.height()); |
1642 | blurEffect->setProperty(name: "offset" , value: offset); |
1643 | } |
1644 | } |
1645 | |
1646 | void QQuickMultiEffectPrivate::updateEffectShaders() |
1647 | { |
1648 | Q_Q(QQuickMultiEffect); |
1649 | if (!q->isComponentComplete() || !m_shaderEffect) |
1650 | return; |
1651 | |
1652 | QString vShader = QStringLiteral("multieffect_c" ); |
1653 | if (m_shadowEnabled) |
1654 | vShader += QStringLiteral("s" ); |
1655 | |
1656 | QString fShader = QStringLiteral("multieffect_c" ); |
1657 | if (m_maskEnabled) |
1658 | fShader += QStringLiteral("m" ); |
1659 | if (m_blurEnabled && m_blurMax > 0) |
1660 | fShader += QStringLiteral("b" ); |
1661 | if (m_shadowEnabled) |
1662 | fShader += QStringLiteral("s" ); |
1663 | |
1664 | fShader += QString::number(m_blurLevel); |
1665 | |
1666 | bool shaderChanged = false; |
1667 | if (fShader != m_fragShader) { |
1668 | shaderChanged = true; |
1669 | m_fragShader = fShader; |
1670 | QUrl fs = QUrl(QStringLiteral("qrc:/data/shaders/%1.frag.qsb" ).arg(a: m_fragShader)); |
1671 | m_shaderEffect->setFragmentShader(fs); |
1672 | Q_EMIT q->fragmentShaderChanged(); |
1673 | } |
1674 | if (vShader != m_vertShader) { |
1675 | shaderChanged = true; |
1676 | m_vertShader = vShader; |
1677 | QUrl vs = QUrl(QStringLiteral("qrc:/data/shaders/%1.vert.qsb" ).arg(a: m_vertShader)); |
1678 | m_shaderEffect->setVertexShader(vs); |
1679 | Q_EMIT q->vertexShaderChanged(); |
1680 | } |
1681 | if (shaderChanged) { |
1682 | qCDebug(lcQuickEffect) << this << "Shaders: " << m_fragShader << m_vertShader; |
1683 | Q_EMIT q->shaderChanged(); |
1684 | } |
1685 | } |
1686 | |
1687 | void QQuickMultiEffectPrivate::updateBlurLevel(bool forceUpdate) |
1688 | { |
1689 | int blurLevel = 0; |
1690 | if ((m_blurEnabled || m_shadowEnabled) && m_blurMax > 0) { |
1691 | if (m_blurMax > 32) |
1692 | blurLevel = 3; |
1693 | else if (m_blurMax > 16) |
1694 | blurLevel = 2; |
1695 | else |
1696 | blurLevel = 1; |
1697 | } |
1698 | |
1699 | if (blurLevel != m_blurLevel || (blurLevel > 0 && m_blurEffects.isEmpty()) || forceUpdate) { |
1700 | // Blur level has changed or blur items need to be |
1701 | // initially created. |
1702 | updateBlurItemsAmount(blurLevel); |
1703 | // When the level grows, new items must be resized |
1704 | if (blurLevel > m_blurLevel) |
1705 | updateBlurItemSizes(forceUpdate: true); |
1706 | } |
1707 | m_blurLevel = blurLevel; |
1708 | } |
1709 | |
1710 | void QQuickMultiEffectPrivate::updateBlurItemsAmount(int blurLevel) |
1711 | { |
1712 | Q_Q(QQuickMultiEffect); |
1713 | if (!m_shaderEffect) |
1714 | return; |
1715 | |
1716 | const auto engine = qmlEngine(q); |
1717 | if (!engine) |
1718 | return; |
1719 | |
1720 | // Lowest blur level uses 3 items, highest 5 items. |
1721 | int itemsAmount = blurLevel == 0 ? 0 : blurLevel + 2; |
1722 | |
1723 | if (m_blurEffects.size() < itemsAmount) { |
1724 | // Add more blur items. |
1725 | // Note that by design blur items are only added and never reduced |
1726 | // during the lifetime of the effect component. |
1727 | QUrl blurVs = QUrl(QStringLiteral("qrc:/data/shaders/bluritems.vert.qsb" )); |
1728 | QUrl blurFs = QUrl(QStringLiteral("qrc:/data/shaders/bluritems.frag.qsb" )); |
1729 | QQmlComponent blurComponent(engine, QUrl(QStringLiteral("qrc:/data/BlurItem.qml" ))); |
1730 | for (int i = m_blurEffects.size(); i < itemsAmount; i++) { |
1731 | auto blurEffect = qobject_cast<QQuickShaderEffect*>(object: blurComponent.create()); |
1732 | blurEffect->setParent(q); |
1733 | blurEffect->setParentItem(q); |
1734 | auto sourceVariant = QVariant::fromValue<QQuickItem*>(value: blurEffect); |
1735 | QString sourceProperty = QStringLiteral("blurSrc%1" ).arg(a: i + 1); |
1736 | m_shaderEffect->setProperty(name: sourceProperty.toUtf8(), value: sourceVariant); |
1737 | // Initial value to avoid "'source' does not have a matching property" warning. |
1738 | // Will be updated with the correct one few lines forward. |
1739 | blurEffect->setProperty(name: "source" , value: sourceVariant); |
1740 | QQuickItemPrivate *priv = QQuickItemPrivate::get(item: blurEffect); |
1741 | priv->layer()->setEnabled(true); |
1742 | priv->layer()->setSmooth(true); |
1743 | blurEffect->setVertexShader(blurVs); |
1744 | blurEffect->setFragmentShader(blurFs); |
1745 | m_blurEffects << blurEffect; |
1746 | } |
1747 | } |
1748 | |
1749 | // Set the blur items source components |
1750 | if (!m_dummyShaderSource) |
1751 | m_dummyShaderSource = new QQuickShaderEffectSource(q); |
1752 | for (int i = 0; i < m_blurEffects.size(); i++) { |
1753 | auto *blurEffect = m_blurEffects[i]; |
1754 | auto sourceItem = (i >= itemsAmount) ? |
1755 | static_cast<QQuickItem *>(m_dummyShaderSource) : (i == 0) ? |
1756 | static_cast<QQuickItem *>(m_shaderSource->output()) : |
1757 | static_cast<QQuickItem *>(m_blurEffects[i - 1]); |
1758 | auto sourceVariant = QVariant::fromValue<QQuickItem*>(value: sourceItem); |
1759 | blurEffect->setProperty(name: "source" , value: sourceVariant); |
1760 | } |
1761 | } |
1762 | |
1763 | void QQuickMultiEffectPrivate::updateSourcePadding() |
1764 | { |
1765 | Q_Q(QQuickMultiEffect); |
1766 | if (!m_shaderEffect || !m_shaderSource) |
1767 | return; |
1768 | |
1769 | const bool blurItemsNeeded = (m_blurEnabled || m_shadowEnabled) && (m_blurMax > 0); |
1770 | const int itemPadding = m_autoPaddingEnabled && blurItemsNeeded ? m_blurMax * (1.0 + m_blurMultiplier) : 0; |
1771 | |
1772 | // Set the shader effect size |
1773 | if (m_paddingRect != QRectF() || itemPadding > 0) { |
1774 | QRectF effectRect(-m_paddingRect.x() - itemPadding, |
1775 | -m_paddingRect.y() - itemPadding, |
1776 | q->width() + m_paddingRect.x() + m_paddingRect.width() + (itemPadding * 2), |
1777 | q->height() + m_paddingRect.y() + m_paddingRect.height() + (itemPadding * 2)); |
1778 | m_shaderEffect->setX(effectRect.x()); |
1779 | m_shaderEffect->setY(effectRect.y()); |
1780 | m_shaderEffect->setWidth(effectRect.width()); |
1781 | m_shaderEffect->setHeight(effectRect.height()); |
1782 | |
1783 | // Set the source size |
1784 | m_shaderSource->setSize(m_shaderEffect->size()); |
1785 | |
1786 | // When m_sourceItem is set and has size, use that as the base size. |
1787 | // When effect is used as a component in Item "layer.effect", source |
1788 | // doesn't have a size and then we follow the effect item size. |
1789 | const qreal baseWidth = m_sourceItem && m_sourceItem->width() > 0 ? m_sourceItem->width() : q->width(); |
1790 | const qreal baseHeight = m_sourceItem && m_sourceItem->height() > 0 ? m_sourceItem->height() : q->height(); |
1791 | |
1792 | // Set the source rect |
1793 | const qreal widthMultiplier = q->width() > 0 ? baseWidth / q->width() : 1.0; |
1794 | const qreal heightMultiplier = q->height() > 0 ? baseHeight / q->height() : 1.0; |
1795 | const qreal xPadding = itemPadding * widthMultiplier; |
1796 | const qreal yPadding = itemPadding * heightMultiplier; |
1797 | QRectF rect = QRectF(m_paddingRect.x() * widthMultiplier, |
1798 | m_paddingRect.y() * heightMultiplier, |
1799 | m_paddingRect.width() * widthMultiplier, |
1800 | m_paddingRect.height() * heightMultiplier); |
1801 | QRectF sourceRect = QRectF(-rect.x() - xPadding, |
1802 | -rect.y() - yPadding, |
1803 | baseWidth + rect.x() + rect.width() + xPadding * 2, |
1804 | baseHeight + rect.y() + rect.height() + yPadding * 2); |
1805 | m_shaderSource->setSourceRect(sourceRect); |
1806 | } else { |
1807 | m_shaderEffect->setX(0); |
1808 | m_shaderEffect->setY(0); |
1809 | m_shaderEffect->setSize(q->size()); |
1810 | m_shaderSource->setSize(q->size()); |
1811 | m_shaderSource->setSourceRect(QRectF()); |
1812 | } |
1813 | |
1814 | updateShadowOffset(); |
1815 | updateProxyActiveCheck(); |
1816 | updateBlurItemSizes(); |
1817 | Q_EMIT q->paddingRectChanged(); |
1818 | Q_EMIT q->itemRectChanged(); |
1819 | Q_EMIT q->itemSizeChanged(); |
1820 | } |
1821 | |
1822 | void QQuickMultiEffectPrivate::proxyOutputChanged() |
1823 | { |
1824 | if (!m_shaderSource) |
1825 | return; |
1826 | |
1827 | auto sourceVariant = QVariant::fromValue<QQuickItem*>(value: m_shaderSource->output()); |
1828 | m_shaderEffect->setProperty(name: "src" , value: sourceVariant); |
1829 | |
1830 | // Force updating the blur items since the source output has changed |
1831 | updateBlurLevel(forceUpdate: true); |
1832 | updateBlurItemSizes(); |
1833 | updateSourcePadding(); |
1834 | } |
1835 | |
1836 | void QQuickMultiEffectPrivate::updateProxyActiveCheck() |
1837 | { |
1838 | if (!m_shaderSource) |
1839 | return; |
1840 | |
1841 | m_shaderSource->polish(); |
1842 | } |
1843 | |
1844 | QT_END_NAMESPACE |
1845 | |
1846 | #include "moc_qquickmultieffect_p.cpp" |
1847 | |