aboutsummaryrefslogtreecommitdiffstats
path: root/examples/quick
diff options
context:
space:
mode:
authorKaj Grönholm <kaj.gronholm@qt.io>2022-11-11 15:39:29 +0200
committerKaj Grönholm <kaj.gronholm@qt.io>2022-12-07 08:31:43 +0200
commitfc0d46971869e88c3ff82f090c57fb888e9787f5 (patch)
tree76f10f132fd05c4ac881471b08bf72b101304d38 /examples/quick
parent84d3c382f808d70c418a9c220cff6fee06f5639a (diff)
Add QtQuick.Effects & MultiEffect
Add new QtQuick.Effects plugin for post-processing effects. The plan is to add essential effects directly into QtQuick, not to duplicate Qt Graphical Effects. Initially the plugin will contain MultiEffect which supports 7 different effects in a single ShaderEffect (brightness, contrast, saturation, colorize, blur, shadow, mask). Combining multiple effects into a single shader is more performant than chaining multiple effect items. Depending on used features, the most optimal shader gets selected. Includes two examples demonstrating the usage of MultiEffect. Task-number: QTBUG-106651 Change-Id: I35865030fd4b7a1f657146cee03b195451545bc6 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'examples/quick')
-rw-r--r--examples/quick/CMakeLists.txt3
-rw-r--r--examples/quick/multieffect/CMakeLists.txt5
-rw-r--r--examples/quick/multieffect/itemswitcher/CMakeLists.txt71
-rw-r--r--examples/quick/multieffect/itemswitcher/itemswitcher.pro10
-rw-r--r--examples/quick/multieffect/itemswitcher/main.cpp4
-rw-r--r--examples/quick/multieffect/itemswitcher/qml.qrc27
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/ItemSwitcher.qml57
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/PagesItem.qml49
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/PagesView.qml30
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SettingsComponentButton.qml35
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SettingsComponentSlider.qml54
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SettingsView.qml168
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SwitchEffect3DFlip.qml93
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SwitchEffectBlinds.qml49
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SwitchEffectBlur.qml34
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SwitchEffectHeart.qml48
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SwitchEffectStars.qml50
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/SwitchEffectThunder.qml87
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/Built_with_Qt.pngbin0 -> 13891 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/Built_with_Qt_RGB_logo.pngbin0 -> 14224 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/arrow.pngbin0 -> 835 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/background.pngbin0 -> 22366 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/hblinds.pngbin0 -> 12054 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/heart.pngbin0 -> 3786 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/quit_coding.pngbin0 -> 23713 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/smoke.pngbin0 -> 45280 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/star.pngbin0 -> 2852 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/images/stripes.pngbin0 -> 41520 bytes
-rw-r--r--examples/quick/multieffect/itemswitcher/qml/main.qml219
-rw-r--r--examples/quick/multieffect/multieffect.pro3
-rw-r--r--examples/quick/multieffect/testbed/CMakeLists.txt69
-rw-r--r--examples/quick/multieffect/testbed/main.cpp4
-rw-r--r--examples/quick/multieffect/testbed/qml.qrc25
-rw-r--r--examples/quick/multieffect/testbed/qml/FpsItem.qml65
-rw-r--r--examples/quick/multieffect/testbed/qml/ResetSettingsOverlay.qml170
-rw-r--r--examples/quick/multieffect/testbed/qml/Settings.qml91
-rw-r--r--examples/quick/multieffect/testbed/qml/SettingsComponentCheckBox.qml35
-rw-r--r--examples/quick/multieffect/testbed/qml/SettingsComponentColorSelector.qml135
-rw-r--r--examples/quick/multieffect/testbed/qml/SettingsComponentSlider.qml54
-rw-r--r--examples/quick/multieffect/testbed/qml/SettingsComponentView.qml147
-rw-r--r--examples/quick/multieffect/testbed/qml/SettingsView.qml400
-rw-r--r--examples/quick/multieffect/testbed/qml/ShaderView.qml29
-rw-r--r--examples/quick/multieffect/testbed/qml/TestMaskItem.qml17
-rw-r--r--examples/quick/multieffect/testbed/qml/TestSourceItem.qml113
-rw-r--r--examples/quick/multieffect/testbed/qml/WarningsItem.qml66
-rw-r--r--examples/quick/multieffect/testbed/qml/WarningsView.qml31
-rw-r--r--examples/quick/multieffect/testbed/qml/images/Built_with_Qt.pngbin0 -> 13891 bytes
-rw-r--r--examples/quick/multieffect/testbed/qml/images/Built_with_Qt_RGB_logo.pngbin0 -> 14224 bytes
-rw-r--r--examples/quick/multieffect/testbed/qml/images/arrow.pngbin0 -> 835 bytes
-rw-r--r--examples/quick/multieffect/testbed/qml/images/pause.pngbin0 -> 245 bytes
-rw-r--r--examples/quick/multieffect/testbed/qml/images/play.pngbin0 -> 281 bytes
-rw-r--r--examples/quick/multieffect/testbed/qml/images/spinner.pngbin0 -> 1687 bytes
-rw-r--r--examples/quick/multieffect/testbed/qml/images/warning.pngbin0 -> 10285 bytes
-rw-r--r--examples/quick/multieffect/testbed/qml/main.qml155
-rw-r--r--examples/quick/multieffect/testbed/testbed.pro10
-rw-r--r--examples/quick/quick.pro3
56 files changed, 2714 insertions, 1 deletions
diff --git a/examples/quick/CMakeLists.txt b/examples/quick/CMakeLists.txt
index d9cdeb617f..f063585486 100644
--- a/examples/quick/CMakeLists.txt
+++ b/examples/quick/CMakeLists.txt
@@ -30,6 +30,7 @@ add_subdirectory(particles)
qt_internal_add_example(delegatechooser)
qt_internal_add_example(shapes)
qt_internal_add_example(itemvariablerefreshrate)
+add_subdirectory(multieffect)
if(QT_FEATURE_opengl OR QT_FEATURE_opengles2 OR QT_FEATURE_opengles3)
add_subdirectory(rendercontrol)
endif()
@@ -62,6 +63,8 @@ set(reused_dir_targets
itemparticle_shared
system_shared
draganddrop_shared
+ testbed_shared
+ itemswitcher_shared
)
foreach(target IN LISTS reused_dir_targets)
diff --git a/examples/quick/multieffect/CMakeLists.txt b/examples/quick/multieffect/CMakeLists.txt
new file mode 100644
index 0000000000..7462337905
--- /dev/null
+++ b/examples/quick/multieffect/CMakeLists.txt
@@ -0,0 +1,5 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_internal_add_example(itemswitcher)
+qt_internal_add_example(testbed)
diff --git a/examples/quick/multieffect/itemswitcher/CMakeLists.txt b/examples/quick/multieffect/itemswitcher/CMakeLists.txt
new file mode 100644
index 0000000000..17ccb243d6
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/CMakeLists.txt
@@ -0,0 +1,71 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(itemswitcher LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quick/multieffect/itemswitcher")
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick QuickControls2)
+
+add_subdirectory("../../shared" "shared")
+
+qt_add_executable(itemswitcherexample WIN32 MACOSX_BUNDLE
+ main.cpp
+)
+
+target_link_libraries(itemswitcherexample PRIVATE
+ Qt::Core
+ Qt::Gui
+ Qt::Qml
+ Qt::Quick
+ Qt::QuickControls2
+)
+
+add_dependencies(itemswitcherexample itemswitcher_shared)
+
+# Resources:
+qt_add_qml_module(itemswitcherexample
+ URI itemswitcher
+ VERSION 1.0
+ AUTO_RESOURCE_PREFIX
+ QML_FILES
+ "qml/main.qml"
+ "qml/PagesView.qml"
+ "qml/SwitchEffect3DFlip.qml"
+ "qml/SwitchEffectBlur.qml"
+ "qml/SwitchEffectStars.qml"
+ "qml/ItemSwitcher.qml"
+ "qml/PagesItem.qml"
+ "qml/SettingsView.qml"
+ "qml/SwitchEffectBlinds.qml"
+ "qml/SwitchEffectHeart.qml"
+ "qml/SwitchEffectThunder.qml"
+ "qml/SettingsComponentButton.qml"
+ "qml/SettingsComponentSlider.qml"
+ RESOURCES
+ "qml/images/background.png"
+ "qml/images/hblinds.png"
+ "qml/images/heart.png"
+ "qml/images/quit_coding.png"
+ "qml/images/smoke.png"
+ "qml/images/star.png"
+ "qml/images/stripes.png"
+ "qml/images/arrow.png"
+ "qml/images/Built_with_Qt.png"
+ "qml/images/Built_with_Qt_RGB_logo.png"
+)
+
+install(TARGETS itemswitcherexample
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
+
+bundle_shared(itemswitcherexample)
diff --git a/examples/quick/multieffect/itemswitcher/itemswitcher.pro b/examples/quick/multieffect/itemswitcher/itemswitcher.pro
new file mode 100644
index 0000000000..f1ab3e381b
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/itemswitcher.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+QT += quick qml
+QT += quickcontrols2
+SOURCES += main.cpp
+RESOURCES += \
+ qml.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/multieffect/itemswitcher
+INSTALLS += target
diff --git a/examples/quick/multieffect/itemswitcher/main.cpp b/examples/quick/multieffect/itemswitcher/main.cpp
new file mode 100644
index 0000000000..a7d7046411
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/main.cpp
@@ -0,0 +1,4 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(itemswitcher/qml/main)
diff --git a/examples/quick/multieffect/itemswitcher/qml.qrc b/examples/quick/multieffect/itemswitcher/qml.qrc
new file mode 100644
index 0000000000..3ccc23502a
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml.qrc
@@ -0,0 +1,27 @@
+<RCC>
+ <qresource prefix="/qt/qml/itemswitcher">
+ <file>qml/ItemSwitcher.qml</file>
+ <file>qml/main.qml</file>
+ <file>qml/SwitchEffectBlur.qml</file>
+ <file>qml/SwitchEffectBlinds.qml</file>
+ <file>qml/images/hblinds.png</file>
+ <file>qml/SwitchEffectHeart.qml</file>
+ <file>qml/images/heart.png</file>
+ <file>qml/SwitchEffectStars.qml</file>
+ <file>qml/images/star.png</file>
+ <file>qml/PagesView.qml</file>
+ <file>qml/PagesItem.qml</file>
+ <file>qml/SwitchEffectThunder.qml</file>
+ <file>qml/images/stripes.png</file>
+ <file>qml/images/background.png</file>
+ <file>qml/SettingsView.qml</file>
+ <file>qml/images/quit_coding.png</file>
+ <file>qml/images/smoke.png</file>
+ <file>qml/SwitchEffect3DFlip.qml</file>
+ <file>qml/SettingsComponentButton.qml</file>
+ <file>qml/SettingsComponentSlider.qml</file>
+ <file>qml/images/arrow.png</file>
+ <file>qml/images/Built_with_Qt.png</file>
+ <file>qml/images/Built_with_Qt_RGB_logo.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/multieffect/itemswitcher/qml/ItemSwitcher.qml b/examples/quick/multieffect/itemswitcher/qml/ItemSwitcher.qml
new file mode 100644
index 0000000000..eb405749be
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/ItemSwitcher.qml
@@ -0,0 +1,57 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: rootItem
+
+ property var sourceItems: []
+
+ property Item fromItem
+ property Item toItem
+
+ property var effect
+
+ property int currentIndex: 0
+ property int previousIndex: 0
+ property real inAnimation: 0
+ readonly property real outAnimation: 1.0 - inAnimation
+ // Duration of switch animation, in ms
+ property int duration: 1500
+
+ property bool _initialized: false
+
+ onCurrentIndexChanged: {
+ fromItem = sourceItems[previousIndex];
+ toItem = sourceItems[currentIndex];
+ if (_initialized)
+ switchAnimation.restart();
+ previousIndex = currentIndex;
+ }
+
+ // Initialize the items and currentIndex
+ Timer {
+ running: true
+ interval: 0
+ onTriggered: {
+ fromItem = sourceItems[previousIndex];
+ toItem = sourceItems[currentIndex];
+ previousIndex = currentIndex;
+ _initialized = true;
+ }
+ }
+
+ SequentialAnimation {
+ id: switchAnimation
+ alwaysRunToEnd: true
+ NumberAnimation {
+ target: rootItem
+ property: "inAnimation"
+ from: 0
+ to: 1
+ duration: rootItem.duration
+ easing.type: Easing.InOutQuad
+ }
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/PagesItem.qml b/examples/quick/multieffect/itemswitcher/qml/PagesItem.qml
new file mode 100644
index 0000000000..87b39d4947
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/PagesItem.qml
@@ -0,0 +1,49 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: rootItem
+
+ property Item source
+ property bool selected: false
+ property string text
+
+ signal clicked
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#000000"
+ border.color: "#f0f0f0"
+ opacity: rootItem.selected ? 0.4 : 0
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 400
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+
+ ShaderEffectSource {
+ anchors.fill: parent
+ anchors.margins: 10
+ sourceItem: rootItem.source
+ smooth: true
+ mipmap: true
+ }
+ Text {
+ anchors.centerIn: parent
+ visible: rootItem.text != ""
+ text: rootItem.text
+ font.pixelSize: 14 * dp
+ color: "#ffffff"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ rootItem.clicked();
+ }
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/PagesView.qml b/examples/quick/multieffect/itemswitcher/qml/PagesView.qml
new file mode 100644
index 0000000000..b6e5c45a94
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/PagesView.qml
@@ -0,0 +1,30 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: rootItem
+
+ property real itemSize: 120 * dp
+ property real margin: 10 * dp
+
+ default property alias contents: contentItem.children
+
+ width: contentItem.width + 2 * margin
+ height: itemSize + 2 * margin
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#606060"
+ border.color: "#f0f0f0"
+ border.width: 1
+ opacity: 0.4
+ }
+ Row {
+ id: contentItem
+ x: margin
+ y: margin
+ spacing: margin
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SettingsComponentButton.qml b/examples/quick/multieffect/itemswitcher/qml/SettingsComponentButton.qml
new file mode 100644
index 0000000000..26a0085d8a
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SettingsComponentButton.qml
@@ -0,0 +1,35 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: rootItem
+
+ property alias text: textItem.text
+ property bool selected: false
+
+ signal clicked
+
+ width: parent.width
+ height: 40 * dp
+ Rectangle {
+ anchors.fill: parent
+ color: "#606060"
+ border.color: "#d0d0d0"
+ border.width: 1
+ opacity: selected ? 0.8 : 0.4
+ }
+ Text {
+ id: textItem
+ anchors.centerIn: parent
+ font.pixelSize: 16 * dp
+ color: "#f0f0f0"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ rootItem.clicked();
+ }
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SettingsComponentSlider.qml b/examples/quick/multieffect/itemswitcher/qml/SettingsComponentSlider.qml
new file mode 100644
index 0000000000..ed04584e44
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SettingsComponentSlider.qml
@@ -0,0 +1,54 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.Material
+
+Column {
+ id: rootItem
+
+ property alias text: textItem.text
+ property alias value: slider.value
+ property alias from: slider.from
+ property alias to: slider.to
+ property alias checked: checkBox.checked
+ property alias stepSize: slider.stepSize
+ property bool showCheckbox: false
+
+ signal toggled
+ signal moved
+
+ Material.theme: Material.Dark
+ Material.accent: Material.LightGreen
+ spacing: -12
+
+ Text {
+ id: textItem
+ anchors.horizontalCenter: parent.horizontalCenter
+ color: "#f0f0f0"
+ font.pixelSize: 14 * dp
+ }
+
+ Row {
+ CheckBox {
+ id: checkBox
+ visible: rootItem.showCheckbox
+ checked: true
+ onToggled: {
+ rootItem.toggled();
+ }
+ }
+ Slider {
+ id: slider
+ property real sliderWidth: settings.settingsViewWidth - 50
+ width: rootItem.showCheckbox ? sliderWidth : sliderWidth + checkBox.width
+ value: 50
+ from: 0
+ to: 800
+ onMoved: {
+ rootItem.moved();
+ }
+ }
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SettingsView.qml b/examples/quick/multieffect/itemswitcher/qml/SettingsView.qml
new file mode 100644
index 0000000000..cf1a753b4d
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SettingsView.qml
@@ -0,0 +1,168 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls.Material
+
+Item {
+ id: rootItem
+
+ property bool show: true
+ property real showAnimation: show ? 1 : 0
+
+ Material.theme: Material.Dark
+ Material.accent: Material.LightGreen
+ width: settings.settingsViewWidth
+ x: -(width + 30) * (1 - showAnimation) + 20
+
+ Behavior on showAnimation {
+ NumberAnimation {
+ duration: 400
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ // Open/close button
+ Item {
+ width: 30 * dp
+ height: 30 * dp
+ anchors.left: parent.right
+ anchors.leftMargin: 20
+ anchors.top: parent.top
+ anchors.topMargin: -10
+ Rectangle {
+ anchors.fill: parent
+ color: "#404040"
+ opacity: 0.4
+ border.width: 1
+ border.color: "#808080"
+ }
+
+ Image {
+ anchors.centerIn: parent
+ source: "images/arrow.png"
+ rotation: rootItem.showAnimation * 180
+ }
+ MouseArea {
+ anchors.fill: parent
+ anchors.margins: -30 * dp
+ onClicked: {
+ rootItem.show = !rootItem.show;
+ }
+ }
+ }
+
+ // Background
+ Rectangle {
+ anchors.fill: scrollView
+ opacity: showAnimation ? 0.6 : 0
+ visible: opacity
+ anchors.margins: -10
+ color: "#202020"
+ border.color: "#808080"
+ border.width: 1
+ }
+
+ ScrollView {
+ id: scrollView
+ anchors.fill: parent
+ ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
+ ScrollBar.vertical.interactive: false
+ clip: true
+ Column {
+ id: settingsArea
+ width: rootItem.width
+ opacity: showAnimation
+ visible: opacity
+ spacing: 8 * dp
+
+ Item {
+ width: 1
+ height: 20 * dp
+ }
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ fillMode: Image.PreserveAspectFit
+ width: parent.width * 0.8
+ height: width * 0.25
+ source: "images/Built_with_Qt_RGB_logo.png"
+ }
+ Item {
+ width: 1
+ height: 28 * dp
+ }
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: qsTr("Switching Effects")
+ font.pixelSize: 20 * dp
+ font.bold: true
+ color: "#f0f0f0"
+ }
+ SettingsComponentButton {
+ text: "Blinds"
+ selected: settings.effectIndex === 0
+ onClicked: {
+ settings.effectIndex = 0;
+ }
+ }
+ SettingsComponentButton {
+ text: "Blurry"
+ selected: settings.effectIndex === 1
+ onClicked: {
+ settings.effectIndex = 1;
+ }
+ }
+ SettingsComponentButton {
+ text: "Heart"
+ selected: settings.effectIndex === 2
+ onClicked: {
+ settings.effectIndex = 2;
+ }
+ }
+ SettingsComponentButton {
+ text: "Stars"
+ selected: settings.effectIndex === 3
+ onClicked: {
+ settings.effectIndex = 3;
+ }
+ }
+ SettingsComponentButton {
+ text: "Thunder"
+ selected: settings.effectIndex === 4
+ onClicked: {
+ settings.effectIndex = 4;
+ }
+ }
+ SettingsComponentButton {
+ text: "3D Flip"
+ selected: settings.effectIndex === 5
+ onClicked: {
+ settings.effectIndex = 5;
+ }
+ }
+ Item {
+ width: 1
+ height: 10
+ }
+
+ SettingsComponentSlider {
+ text: qsTr("Animation Duration") + ": " + value.toFixed(0) + " ms"
+ value: settings.switchDuration
+ from: 500
+ to: 5000
+ onMoved: {
+ settings.switchDuration = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Animation Time") + ": " + (value * settings.switchDuration).toFixed(0) + " ms"
+ value: itemSwitcher.inAnimation
+ from: 0
+ to: 1
+ onMoved: {
+ itemSwitcher.inAnimation = value;
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SwitchEffect3DFlip.qml b/examples/quick/multieffect/itemswitcher/qml/SwitchEffect3DFlip.qml
new file mode 100644
index 0000000000..ae8ec481fb
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SwitchEffect3DFlip.qml
@@ -0,0 +1,93 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Effects
+
+Item {
+ id: rootItem
+ // We expect all effects to be placed under ItemSwitcher
+ property Item switcher: rootItem.parent
+
+ anchors.fill: parent
+
+ MultiEffect {
+ source: switcher.fromItem
+ width: parent.width
+ height: parent.height
+ x: switcher.inAnimation * rootItem.width
+ blurEnabled: true
+ blur: switcher.inAnimation
+ blurMax: 32
+ blurMultiplier: 1.0
+ opacity: switcher.outAnimation
+
+ saturation: -switcher.inAnimation * 1.5
+
+ maskEnabled: true
+ maskSource: Image {
+ source: "images/smoke.png"
+ visible: false
+ }
+ maskThresholdLow: switcher.inAnimation * 0.6
+ maskSpreadLow: 0.1
+ maskThresholdUp: 1.0 - (switcher.inAnimation * 0.6)
+ maskSpreadUp: 0.1
+
+ shadowEnabled: true
+ shadowOpacity: 0.5
+ shadowBlur: 0.8
+ shadowVerticalOffset: 5
+ shadowHorizontalOffset: 10 + (x * 0.2)
+ shadowScale: 1.02
+
+ transform: Rotation {
+ origin.x: parent.width / 2
+ origin.y: parent.height / 2
+ axis { x: 0; y: 1; z: 0 }
+ angle: switcher.inAnimation * 60
+ }
+ rotation: -switcher.inAnimation * 20
+ scale: 1.0 + (switcher.inAnimation * 0.2)
+ }
+
+ MultiEffect {
+ source: switcher.toItem
+ width: parent.width
+ height: parent.height
+ x: -switcher.outAnimation * rootItem.width
+ blurEnabled: true
+ blur: switcher.outAnimation * 2
+ blurMax: 32
+ blurMultiplier: 1.0
+ opacity: switcher.inAnimation
+
+ saturation: -switcher.outAnimation * 1.5
+
+ maskEnabled: true
+ maskSource: Image {
+ source: "images/smoke.png"
+ visible: false
+ }
+ maskThresholdLow: switcher.outAnimation * 0.6
+ maskSpreadLow: 0.1
+ maskThresholdUp: 1.0 - (switcher.outAnimation * 0.6)
+ maskSpreadUp: 0.1
+
+ shadowEnabled: true
+ shadowOpacity: 0.5
+ shadowBlur: 0.8
+ shadowVerticalOffset: 5
+ shadowHorizontalOffset: 10 + (x * 0.2)
+ shadowScale: 1.02
+
+ transform: Rotation {
+ origin.x: parent.width / 2
+ origin.y: parent.height / 2
+ axis { x: 0; y: 1; z: 0 }
+ angle: -switcher.outAnimation * 60
+ }
+ rotation: switcher.outAnimation * 20
+ scale: 1.0 - (switcher.outAnimation * 0.4)
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SwitchEffectBlinds.qml b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectBlinds.qml
new file mode 100644
index 0000000000..3a9f22e3ad
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectBlinds.qml
@@ -0,0 +1,49 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Effects
+
+Item {
+ id: rootItem
+ // We expect all effects to be placed under ItemSwitcher
+ property Item switcher: rootItem.parent
+ property real rotation: 0
+
+ anchors.fill: parent
+
+ Item {
+ id: mask
+ anchors.fill: parent
+ layer.enabled: true
+ visible: false
+ smooth: false
+ clip: true
+ Image {
+ anchors.fill: parent
+ anchors.margins: -parent.width * 0.25
+ source: "images/hblinds.png"
+ rotation: rootItem.rotation
+ smooth: false
+ }
+ }
+
+ // Item going out
+ MultiEffect {
+ source: switcher.fromItem
+ anchors.fill: parent
+ maskEnabled: true
+ maskSource: mask
+ maskThresholdLow: switcher.inAnimation
+ maskSpreadLow: 0.4
+ }
+ // Item coming in
+ MultiEffect {
+ source: switcher.toItem
+ anchors.fill: parent
+ maskEnabled: true
+ maskSource: mask
+ maskThresholdUp: switcher.inAnimation
+ maskSpreadUp: 0.4
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SwitchEffectBlur.qml b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectBlur.qml
new file mode 100644
index 0000000000..9b48116226
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectBlur.qml
@@ -0,0 +1,34 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Effects
+
+Item {
+ id: rootItem
+ // We expect all effects to be placed under ItemSwitcher
+ property Item switcher: rootItem.parent
+
+ anchors.fill: parent
+
+ MultiEffect {
+ source: switcher.fromItem
+ anchors.fill: parent
+ blurEnabled: true
+ blur: switcher.inAnimation * 4
+ blurMax: 32
+ blurMultiplier: 1.0
+ opacity: switcher.outAnimation
+ saturation: -switcher.inAnimation * 2
+ }
+ MultiEffect {
+ source: switcher.toItem
+ anchors.fill: parent
+ blurEnabled: true
+ blur: switcher.outAnimation * 4
+ blurMax: 32
+ blurMultiplier: 1.0
+ opacity: switcher.inAnimation
+ saturation: -switcher.outAnimation * 2
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SwitchEffectHeart.qml b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectHeart.qml
new file mode 100644
index 0000000000..e81c648e2c
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectHeart.qml
@@ -0,0 +1,48 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Effects
+
+Item {
+ id: rootItem
+ // We expect all effects to be placed under ItemSwitcher
+ property Item switcher: rootItem.parent
+
+ anchors.fill: parent
+
+ Item {
+ id: mask
+ anchors.fill: parent
+ layer.enabled: true
+ visible: false
+ clip: true
+ Image {
+ anchors.fill: parent
+ source: "images/heart.png"
+ scale: switcher.inAnimation * 3
+ }
+ }
+
+ // Item going out
+ MultiEffect {
+ source: switcher.fromItem
+ anchors.fill: parent
+ maskEnabled: true
+ maskSource: mask
+ maskInverted: true
+ maskThresholdLow: 0.5
+ maskSpreadLow: 0.0
+ }
+ // Item coming in
+ MultiEffect {
+ source: switcher.toItem
+ anchors.fill: parent
+ maskEnabled: true
+ maskSource: mask
+ maskThresholdLow: 0.5
+ maskSpreadLow: 0.0
+ colorizeColor: "red"
+ colorize: Math.max(0, 1.0 - switcher.inAnimation * 2)
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SwitchEffectStars.qml b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectStars.qml
new file mode 100644
index 0000000000..47bdf3f64d
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectStars.qml
@@ -0,0 +1,50 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Effects
+
+Item {
+ id: rootItem
+ // We expect all effects to be placed under ItemSwitcher
+ property Item switcher: rootItem.parent
+
+ anchors.fill: parent
+
+ Item {
+ id: mask
+ anchors.fill: parent
+ layer.enabled: true
+ visible: false
+ clip: true
+ Image {
+ anchors.fill: parent
+ source: "images/star.png"
+ scale: switcher.inAnimation * 5
+ rotation: switcher.outAnimation * 360
+ }
+ }
+
+ // Item going out
+ MultiEffect {
+ source: switcher.fromItem
+ anchors.fill: parent
+ maskEnabled: true
+ maskSource: mask
+ maskInverted: true
+ maskThresholdLow: 0.5
+ maskSpreadLow: 0.5
+ }
+ // Item coming in
+ MultiEffect {
+ source: switcher.toItem
+ anchors.fill: parent
+ maskEnabled: true
+ maskSource: mask
+ maskThresholdLow: 0.5
+ maskSpreadLow: 0.5
+ colorizeColor: "#ffd020"
+ colorize: Math.max(0, 1.0 - switcher.inAnimation * 2)
+ brightness: Math.max(0.0, 0.8 - switcher.inAnimation * 2)
+ }
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/SwitchEffectThunder.qml b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectThunder.qml
new file mode 100644
index 0000000000..581d001e26
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/SwitchEffectThunder.qml
@@ -0,0 +1,87 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Effects
+
+Item {
+ id: rootItem
+ // We expect all effects to be placed under ItemSwitcher
+ property Item switcher: rootItem.parent
+
+ property real _xPos: Math.sin(switcher.inAnimation * Math.PI * 50) * width * 0.03 * (0.5 - Math.abs(0.5 - switcher.inAnimation))
+ property real _yPos: Math.sin(switcher.inAnimation * Math.PI * 35) * width * 0.02 * (0.5 - Math.abs(0.5 - switcher.inAnimation))
+
+ anchors.fill: parent
+
+ Image {
+ id: maskImage
+ source: "images/stripes.png"
+ visible: false
+ }
+
+ MultiEffect {
+ source: switcher.fromItem
+ width: parent.width
+ height: parent.height
+ x: rootItem._xPos
+ y: rootItem._yPos
+ blurEnabled: true
+ blur: switcher.inAnimation
+ blurMax: 32
+ blurMultiplier: 1.0
+ opacity: switcher.outAnimation
+ colorizeColor: "#f0d060"
+ colorize: switcher.inAnimation
+
+ contrast: switcher.inAnimation
+ brightness: switcher.inAnimation
+
+ maskEnabled: true
+ maskSource: maskImage
+ maskThresholdLow: switcher.inAnimation * 0.9
+ maskSpreadLow: 0.2
+ maskThresholdUp: 1.0
+
+ shadowEnabled: true
+ shadowColor: "#f04000"
+ shadowBlur: 1.0
+ shadowOpacity: 5.0 - switcher.outAnimation * 5.0
+ shadowHorizontalOffset: 0
+ shadowVerticalOffset: 0
+ shadowScale: 1.04
+
+ }
+ MultiEffect {
+ source: switcher.toItem
+ width: parent.width
+ height: parent.height
+ x: -rootItem._xPos
+ y: -rootItem._yPos
+ blurEnabled: true
+ blur: switcher.outAnimation * 2
+ blurMax: 32
+ blurMultiplier: 1.0
+ opacity: switcher.inAnimation * 3.0 - 1.0
+
+ colorizeColor: "#f0d060"
+ colorize: switcher.outAnimation
+ contrast: switcher.outAnimation
+ brightness: switcher.outAnimation
+
+ maskEnabled: true
+ maskSource: maskImage
+ maskThresholdLow: switcher.outAnimation * 0.6
+ maskSpreadLow: 0.2
+ maskThresholdUp: 1.0
+
+ shadowEnabled: true
+ shadowColor: "#f04000"
+ shadowBlur: 1.0
+ shadowOpacity: 5.0 - switcher.inAnimation * 5.0
+ shadowHorizontalOffset: 0
+ shadowVerticalOffset: 0
+ shadowScale: 1.04
+ }
+
+}
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/Built_with_Qt.png b/examples/quick/multieffect/itemswitcher/qml/images/Built_with_Qt.png
new file mode 100644
index 0000000000..e612481510
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/Built_with_Qt.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/Built_with_Qt_RGB_logo.png b/examples/quick/multieffect/itemswitcher/qml/images/Built_with_Qt_RGB_logo.png
new file mode 100644
index 0000000000..8d2dfc17ec
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/Built_with_Qt_RGB_logo.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/arrow.png b/examples/quick/multieffect/itemswitcher/qml/images/arrow.png
new file mode 100644
index 0000000000..067bec4509
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/arrow.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/background.png b/examples/quick/multieffect/itemswitcher/qml/images/background.png
new file mode 100644
index 0000000000..9b9e9e487d
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/background.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/hblinds.png b/examples/quick/multieffect/itemswitcher/qml/images/hblinds.png
new file mode 100644
index 0000000000..09ce73ee03
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/hblinds.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/heart.png b/examples/quick/multieffect/itemswitcher/qml/images/heart.png
new file mode 100644
index 0000000000..dda1f4bab1
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/heart.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/quit_coding.png b/examples/quick/multieffect/itemswitcher/qml/images/quit_coding.png
new file mode 100644
index 0000000000..0930013af4
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/quit_coding.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/smoke.png b/examples/quick/multieffect/itemswitcher/qml/images/smoke.png
new file mode 100644
index 0000000000..83dfcc453c
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/smoke.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/star.png b/examples/quick/multieffect/itemswitcher/qml/images/star.png
new file mode 100644
index 0000000000..f83bd87892
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/star.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/images/stripes.png b/examples/quick/multieffect/itemswitcher/qml/images/stripes.png
new file mode 100644
index 0000000000..7a79767e6e
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/images/stripes.png
Binary files differ
diff --git a/examples/quick/multieffect/itemswitcher/qml/main.qml b/examples/quick/multieffect/itemswitcher/qml/main.qml
new file mode 100644
index 0000000000..9685c71ccb
--- /dev/null
+++ b/examples/quick/multieffect/itemswitcher/qml/main.qml
@@ -0,0 +1,219 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Controls
+import QtQuick.Controls.Material
+
+Rectangle {
+ id: mainWindow
+
+ // Multiplier for resolution independency
+ readonly property real dp: 0.2 + Math.min(width, height) / 1200
+
+ width: 1280
+ height: 720
+ visible: true
+ color: "#404040"
+
+ QtObject {
+ id: settings
+ property real settingsViewWidth: 100 + 150 * dp
+ property int effectIndex: 0
+ property int switchDuration: 1500
+ property int itemSize: mainWindow.height * 0.6
+ }
+
+ Item {
+ id: testItem1
+ width: 1
+ height: 1
+ }
+
+ Rectangle {
+ id: testItem2
+ anchors.fill: itemSwitcher
+ color: "#d0d0d0"
+ visible: false
+ Image {
+ anchors.fill: parent
+ anchors.margins: 4
+ source: "images/background.png"
+ }
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: 40 * dp
+ horizontalAlignment: Text.AlignHCenter
+ text: "This is the\nfirst item"
+ color: "#ffffff"
+ style: Text.Outline
+ styleColor: "#202020"
+ }
+ }
+
+ Rectangle {
+ id: testItem3Content
+ anchors.fill: itemSwitcher
+ color: "white"
+ border.width: 5
+ visible: itemSwitcher.currentIndex === 2
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: 48 * dp
+ horizontalAlignment: Text.AlignHCenter
+ text: "This is a\nDIFFERENT\nsecond item"
+ rotation: slider.value * 360
+ }
+ Slider {
+ id: slider
+ anchors.top: parent.top
+ anchors.topMargin: 20 * dp
+ anchors.horizontalCenter: parent.horizontalCenter
+ from: 0
+ to: 1
+ width: parent.width * 0.8
+ }
+ Button {
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 20 * dp
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "Controls Button"
+ }
+ }
+ ShaderEffectSource {
+ // Wrap testItem3 into ShaderEffectSource so it doesn't need
+ // visible = false and can be interactive.
+ id: testItem3
+ anchors.fill: testItem3Content
+ sourceItem: testItem3Content
+ hideSource: true
+ visible: false
+ }
+
+ Image {
+ id: testItem4
+ source: "images/Built_with_Qt.png"
+ anchors.fill: itemSwitcher
+ visible: false
+ }
+
+ Image {
+ id: testItem5
+ source: "images/quit_coding.png"
+ anchors.fill: itemSwitcher
+ visible: false
+ }
+
+ Item {
+ id: mainArea
+ anchors.left: settingsView.right
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+
+ PagesView {
+ id: pagesView
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.topMargin: 20 * dp
+ PagesItem {
+ width: pagesView.itemSize
+ height: pagesView.itemSize
+ source: testItem1
+ text: "(EMPTY)"
+ selected: itemSwitcher.currentIndex === 0
+ onClicked: {
+ itemSwitcher.currentIndex = 0;
+ }
+ }
+ PagesItem {
+ width: pagesView.itemSize
+ height: pagesView.itemSize
+ source: testItem2
+ selected: itemSwitcher.currentIndex === 1
+ onClicked: {
+ itemSwitcher.currentIndex = 1;
+ }
+ }
+ PagesItem {
+ width: pagesView.itemSize
+ height: pagesView.itemSize
+ source: testItem3
+ selected: itemSwitcher.currentIndex === 2
+ onClicked: {
+ itemSwitcher.currentIndex = 2;
+ }
+ }
+ PagesItem {
+ width: pagesView.itemSize
+ height: pagesView.itemSize
+ source: testItem4
+ selected: itemSwitcher.currentIndex === 3
+ onClicked: {
+ itemSwitcher.currentIndex = 3;
+ }
+ }
+ PagesItem {
+ width: pagesView.itemSize
+ height: pagesView.itemSize
+ source: testItem5
+ selected: itemSwitcher.currentIndex === 4
+ onClicked: {
+ itemSwitcher.currentIndex = 4;
+ }
+ }
+ }
+ }
+ ItemSwitcher {
+ id: itemSwitcher
+ anchors.centerIn: mainArea
+ anchors.verticalCenterOffset: pagesView.height / 2
+ width: settings.itemSize
+ height: settings.itemSize
+ duration: settings.switchDuration
+ Component.onCompleted: {
+ // Add all switchable items into switcher
+ sourceItems.push(testItem1);
+ sourceItems.push(testItem2);
+ sourceItems.push(testItem3);
+ sourceItems.push(testItem4);
+ sourceItems.push(testItem5);
+ // From item is the currently selected one
+ currentIndex = settings.effectIndex;
+ }
+
+ SwitchEffectBlinds {
+ id: blindsEffect
+ visible: settings.effectIndex == 0
+ rotation: 45
+ }
+ SwitchEffectBlur {
+ id: blurEffect
+ visible: settings.effectIndex == 1
+ }
+ SwitchEffectHeart {
+ id: heartEffect
+ visible: settings.effectIndex == 2
+ }
+ SwitchEffectStars {
+ id: starsEffect
+ visible: settings.effectIndex == 3
+ }
+ SwitchEffectThunder {
+ id: thunderEffect
+ visible: settings.effectIndex == 4
+ }
+ SwitchEffect3DFlip {
+ id: flipEffect
+ visible: settings.effectIndex == 5
+ }
+ }
+
+ SettingsView {
+ id: settingsView
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: 20
+ }
+}
diff --git a/examples/quick/multieffect/multieffect.pro b/examples/quick/multieffect/multieffect.pro
new file mode 100644
index 0000000000..b06faae7df
--- /dev/null
+++ b/examples/quick/multieffect/multieffect.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS += testbed \
+ itemswitcher
diff --git a/examples/quick/multieffect/testbed/CMakeLists.txt b/examples/quick/multieffect/testbed/CMakeLists.txt
new file mode 100644
index 0000000000..7f7fda0082
--- /dev/null
+++ b/examples/quick/multieffect/testbed/CMakeLists.txt
@@ -0,0 +1,69 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(testbed LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+
+if(NOT DEFINED INSTALL_EXAMPLESDIR)
+ set(INSTALL_EXAMPLESDIR "examples")
+endif()
+
+set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/quick/multieffect/testbed")
+
+find_package(Qt6 REQUIRED COMPONENTS Core Gui Qml Quick QuickControls2)
+
+add_subdirectory("../../shared" "shared")
+
+qt_add_executable(testbedexample WIN32 MACOSX_BUNDLE
+ main.cpp
+)
+
+target_link_libraries(testbedexample PRIVATE
+ Qt::Core
+ Qt::Gui
+ Qt::Qml
+ Qt::Quick
+ Qt::QuickControls2
+)
+
+add_dependencies(testbedexample testbed_shared)
+
+# Resources:
+qt_add_qml_module(testbedexample
+ URI testbed
+ VERSION 1.0
+ AUTO_RESOURCE_PREFIX
+ QML_FILES
+ "qml/FpsItem.qml"
+ "qml/main.qml"
+ "qml/ResetSettingsOverlay.qml"
+ "qml/Settings.qml"
+ "qml/SettingsView.qml"
+ "qml/ShaderView.qml"
+ "qml/TestMaskItem.qml"
+ "qml/TestSourceItem.qml"
+ "qml/WarningsItem.qml"
+ "qml/WarningsView.qml"
+ "qml/SettingsComponentView.qml"
+ "qml/SettingsComponentSlider.qml"
+ "qml/SettingsComponentCheckBox.qml"
+ "qml/SettingsComponentColorSelector.qml"
+ RESOURCES
+ "qml/images/pause.png"
+ "qml/images/play.png"
+ "qml/images/spinner.png"
+ "qml/images/warning.png"
+ "qml/images/arrow.png"
+ "qml/images/Built_with_Qt.png"
+ "qml/images/Built_with_Qt_RGB_logo.png"
+)
+
+install(TARGETS testbedexample
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
+
+bundle_shared(testbedexample)
diff --git a/examples/quick/multieffect/testbed/main.cpp b/examples/quick/multieffect/testbed/main.cpp
new file mode 100644
index 0000000000..130e3ab0b4
--- /dev/null
+++ b/examples/quick/multieffect/testbed/main.cpp
@@ -0,0 +1,4 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include "../../shared/shared.h"
+DECLARATIVE_EXAMPLE_MAIN(testbed/qml/main)
diff --git a/examples/quick/multieffect/testbed/qml.qrc b/examples/quick/multieffect/testbed/qml.qrc
new file mode 100644
index 0000000000..ab21cc8b0f
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml.qrc
@@ -0,0 +1,25 @@
+<RCC>
+ <qresource prefix="/qt/qml/testbed">
+ <file>qml/main.qml</file>
+ <file>qml/Settings.qml</file>
+ <file>qml/ResetSettingsOverlay.qml</file>
+ <file>qml/FpsItem.qml</file>
+ <file>qml/images/spinner.png</file>
+ <file>qml/images/warning.png</file>
+ <file>qml/WarningsView.qml</file>
+ <file>qml/WarningsItem.qml</file>
+ <file>qml/ShaderView.qml</file>
+ <file>qml/TestSourceItem.qml</file>
+ <file>qml/TestMaskItem.qml</file>
+ <file>qml/SettingsView.qml</file>
+ <file>qml/images/pause.png</file>
+ <file>qml/images/play.png</file>
+ <file>qml/SettingsComponentCheckBox.qml</file>
+ <file>qml/SettingsComponentColorSelector.qml</file>
+ <file>qml/SettingsComponentSlider.qml</file>
+ <file>qml/SettingsComponentView.qml</file>
+ <file>qml/images/arrow.png</file>
+ <file>qml/images/Built_with_Qt.png</file>
+ <file>qml/images/Built_with_Qt_RGB_logo.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/quick/multieffect/testbed/qml/FpsItem.qml b/examples/quick/multieffect/testbed/qml/FpsItem.qml
new file mode 100644
index 0000000000..53042655a3
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/FpsItem.qml
@@ -0,0 +1,65 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: root
+ property int frameCounter: 0
+ property int frameCounterAvg: 0
+ property int counter: 0
+ property int fps: 0
+ property int fpsAvg: 0
+
+ width: 200 * dp
+ height: Math.floor(42 * dp)
+
+ Image {
+ id: spinnerImage
+ anchors.verticalCenter: parent.verticalCenter
+ x: 4 * dp
+ width: 32 * dp
+ height: width
+ source: "images/spinner.png"
+ NumberAnimation on rotation {
+ from:0
+ to: 360
+ duration: 800
+ loops: Animation.Infinite
+ }
+ onRotationChanged: frameCounter++;
+ }
+ Image {
+ anchors.centerIn: spinnerImage
+ width: 18 * dp
+ height: width
+ source: settings.animateMovement ? "images/play.png" : "images/pause.png"
+ opacity: 0.5
+ }
+
+ Text {
+ anchors.left: spinnerImage.right
+ anchors.leftMargin: 8 * dp
+ anchors.verticalCenter: spinnerImage.verticalCenter
+ color: "#c0c0c0"
+ font.pixelSize: 22 * dp
+ text: "Ø " + root.fpsAvg + " | " + root.fps + " fps"
+ }
+
+ Timer {
+ interval: 2000
+ repeat: true
+ running: true
+ onTriggered: {
+ frameCounterAvg += frameCounter;
+ root.fps = Math.ceil(frameCounter / 2);
+ counter++;
+ frameCounter = 0;
+ if (counter >= 3) {
+ root.fpsAvg = Math.ceil(frameCounterAvg / (2 * counter));
+ frameCounterAvg = 0;
+ counter = 0;
+ }
+ }
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/ResetSettingsOverlay.qml b/examples/quick/multieffect/testbed/qml/ResetSettingsOverlay.qml
new file mode 100644
index 0000000000..3931548124
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/ResetSettingsOverlay.qml
@@ -0,0 +1,170 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Shapes
+
+Item {
+ id: rootItem
+
+ property real showAnimationProgress: 0
+ property int itemWidth: 256 * dp
+ property int lineSpacing1: 0
+ property int lineWidth1: 20 * dp
+ property int lineSpacing2: 10 * dp
+ property int lineWidth2: 10 * dp
+
+ readonly property int cx: itemWidth / 2
+ readonly property int cy: itemWidth / 2
+
+ signal animationFinished
+
+ function startShow() {
+ hideAnimationItem.stop();
+ showAnimationItem.restart();
+ }
+ function stopShow() {
+ showAnimationItem.stop();
+ hideAnimationItem.restart();
+ }
+
+ function ringProgress() {
+ return showAnimationProgress * (2 * Math.PI) - (Math.PI / 2);
+ }
+
+ function useLargeArcFunc() {
+ return (ringProgress() > Math.PI / 2);
+ }
+
+ anchors.fill: parent
+ visible: opacity
+ opacity: 0
+
+ SequentialAnimation {
+ id: showAnimationItem
+ PauseAnimation {
+ duration: 400
+ }
+ ScriptAction {
+ script: {
+ rootItem.showAnimationProgress = 0;
+ }
+ }
+ NumberAnimation {
+ target: rootItem
+ property: "opacity"
+ to: 1
+ duration: 400
+ easing.type: Easing.InOutQuad
+ }
+ NumberAnimation {
+ target: rootItem
+ property: "showAnimationProgress"
+ to: 1
+ duration: 2000
+ easing.type: Easing.InOutQuad
+ }
+ ScriptAction {
+ script: rootItem.animationFinished();
+ }
+ }
+ SequentialAnimation {
+ id: hideAnimationItem
+ NumberAnimation {
+ target: rootItem
+ property: "opacity"
+ to: 0
+ duration: 400
+ easing.type: Easing.InOutQuad
+ }
+ ScriptAction {
+ script: {
+ rootItem.showAnimationProgress = 0;
+ }
+ }
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#000000"
+ opacity: 0.6
+ }
+
+ Shape {
+ id: shapeItem
+ x: (parent.width / 2) - (itemWidth / 2)
+ y: (parent.height / 2) - (itemWidth / 2)
+ opacity: rootItem.showAnimationProgress
+ width: itemWidth
+ height: itemWidth
+ rotation: rootItem.showAnimationProgress * 360
+ ShapePath {
+ strokeColor: "#606060"
+ fillColor: "transparent"
+ strokeWidth: lineWidth1
+ capStyle: ShapePath.RoundCap
+ PathMove {
+ x: itemWidth / 2
+ y: pathArc1.spacing
+ }
+ PathArc {
+ id: pathArc1
+ property real spacing: lineSpacing1 + lineWidth1
+ x: cx + ((itemWidth / 2 - spacing) * Math.cos(ringProgress()))
+ y: cy + ((itemWidth / 2 - spacing) * Math.sin(ringProgress()))
+ radiusX: itemWidth / 2 - spacing
+ radiusY: itemWidth / 2 - spacing
+ useLargeArc: useLargeArcFunc()
+ }
+ }
+
+ ShapePath {
+ strokeColor: "#808080"
+ fillColor: "transparent"
+ strokeWidth: lineWidth2
+ capStyle: ShapePath.RoundCap
+ PathMove {
+ x: itemWidth / 2
+ y: pathArc2.spacing
+ }
+ PathArc {
+ id: pathArc2
+ property real spacing: lineSpacing2 + lineWidth2
+ x: cx + ((itemWidth / 2 - spacing) * Math.cos(ringProgress()))
+ y: cy + ((itemWidth / 2 - spacing) * Math.sin(ringProgress()))
+ radiusX: itemWidth / 2 - spacing
+ radiusY: itemWidth / 2 - spacing
+ useLargeArc: useLargeArcFunc()
+ }
+ }
+ }
+ Text {
+ id: textItem
+ anchors.centerIn: shapeItem
+ font.pixelSize: 32 * dp
+ color: "#d0d0d0"
+ text: showAnimationProgress < 1 ? qsTr("Reset to default settings?") : qsTr("Reseted!")
+ Behavior on text {
+ SequentialAnimation {
+ NumberAnimation {
+ target: textItem
+ properties: "scale, opacity"
+ to: 0
+ duration: 200
+ easing.type: Easing.InOutQuad
+ }
+ PropertyAction {
+ target: textItem
+ property: "text"
+ }
+ NumberAnimation {
+ target: textItem
+ properties: "scale, opacity"
+ to: 1.0
+ duration: 200
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/Settings.qml b/examples/quick/multieffect/testbed/qml/Settings.qml
new file mode 100644
index 0000000000..82db53202c
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/Settings.qml
@@ -0,0 +1,91 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+QtObject {
+ id: rootItem
+
+ // Emitted when settings are reseted to default
+ signal reseted
+
+ // When adding settings here remember to add them also into reset()
+
+ // *** General settings - No UI for these ***
+ // Change to false to not show settings view at all
+ property bool showSettingsView: true
+ property real settingsViewWidth: 100 + 150 * dp
+ property bool animateMovement: true
+ property bool showShader: false
+ property bool showItemSize: false
+
+ property bool autoPaddingEnabled: true
+ property rect paddingRect: Qt.rect(0, 0, 0, 0)
+
+ property bool brightnessEnabled: true
+ property real brightness: 0.0
+ property bool contrastEnabled: true
+ property real contrast: 0.0
+ property bool saturationEnabled: true
+ property real saturation: 0.0
+ property bool colorizeEnabled: true
+ property color colorizeColor: Qt.rgba(1.0, 0.0, 0.0, 1.0)
+ property real colorize: 0.0
+
+ property bool blurEnabled: true
+ property real blur: 0.0
+ property int blurMax: 32
+ property real blurMultiplier: 0.0
+
+ property bool shadowEnabled: true
+ property real shadowOpacity: 1.0
+ property real shadowBlur: 1.0
+ property real shadowHorizontalOffset: 10
+ property real shadowVerticalOffset: 5
+ property color shadowColor: Qt.rgba(0.0, 0.0, 0.0, 1.0)
+ property real shadowScale: 1.0
+
+ property bool maskEnabled: true
+ property bool maskInverted: false
+ property real maskThresholdLow: 0.0
+ property real maskSpreadLow: 0.0
+ property real maskThresholdUp: 1.0
+ property real maskSpreadUp: 0.0
+
+ function reset() {
+ autoPaddingEnabled = defaultSettings.autoPaddingEnabled;
+ paddingRect = defaultSettings.paddingRect;
+
+ brightnessEnabled = defaultSettings.brightnessEnabled;
+ brightness = defaultSettings.brightness;
+ contrastEnabled = defaultSettings.contrastEnabled;
+ contrast = defaultSettings.contrast;
+ saturationEnabled = defaultSettings.saturationEnabled;
+ saturation = defaultSettings.saturation;
+ colorizeEnabled = defaultSettings.colorizeEnabled;
+ colorizeColor = defaultSettings.colorizeColor;
+ colorize = defaultSettings.colorize;
+
+ blurEnabled = defaultSettings.blurEnabled;
+ blur = defaultSettings.blur;
+ blurMax = defaultSettings.blurMax;
+ blurMultiplier = defaultSettings.blurMultiplier;
+
+ shadowEnabled = defaultSettings.shadowEnabled;
+ shadowOpacity = defaultSettings.shadowOpacity;
+ shadowBlur = defaultSettings.shadowBlur;
+ shadowHorizontalOffset = defaultSettings.shadowHorizontalOffset;
+ shadowVerticalOffset = defaultSettings.shadowVerticalOffset;
+ shadowColor = defaultSettings.shadowColor;
+ shadowScale = defaultSettings.shadowScale;
+
+ maskEnabled = defaultSettings.maskEnabled;
+ maskInverted = defaultSettings.maskInverted;
+ maskThresholdLow = defaultSettings.maskThresholdLow;
+ maskSpreadLow = defaultSettings.maskSpreadLow;
+ maskThresholdUp = defaultSettings.maskThresholdUp;
+ maskSpreadUp = defaultSettings.maskSpreadUp;
+
+ rootItem.reseted();
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/SettingsComponentCheckBox.qml b/examples/quick/multieffect/testbed/qml/SettingsComponentCheckBox.qml
new file mode 100644
index 0000000000..ef1cb27d89
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/SettingsComponentCheckBox.qml
@@ -0,0 +1,35 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.Material
+
+Column {
+ id: rootItem
+
+ property alias text: textItem.text
+ property alias checked: checkBox.checked
+
+ signal toggled
+
+ Material.theme: Material.Dark
+ Material.accent: Material.LightGreen
+ spacing: -12
+
+ Row {
+ CheckBox {
+ id: checkBox
+ checked: true
+ onToggled: {
+ rootItem.toggled();
+ }
+ }
+ Text {
+ id: textItem
+ anchors.verticalCenter: parent.verticalCenter
+ color: "#f0f0f0"
+ font.pixelSize: 14 * dp
+ }
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/SettingsComponentColorSelector.qml b/examples/quick/multieffect/testbed/qml/SettingsComponentColorSelector.qml
new file mode 100644
index 0000000000..c158f84a7d
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/SettingsComponentColorSelector.qml
@@ -0,0 +1,135 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.Material
+
+Column {
+ id: rootItem
+
+ property alias text: textItem.text
+ readonly property color value: Qt.rgba(colorRed, colorGreen, colorBlue, 1.0)
+ readonly property real colorRed: sliderRed.value
+ readonly property real colorGreen: sliderGreen.value
+ readonly property real colorBlue: sliderBlue.value
+ readonly property real itemWidth: (rootItem.width / 3) - itemMargin
+ readonly property real itemMargin: 4
+ readonly property real colorBarHeight: 4
+
+ // Use this to set the initial values
+ function setValues(r, g, b) {
+ sliderRed.value = r;
+ sliderGreen.value = g;
+ sliderBlue.value = b;
+ }
+
+ Material.theme: Material.Dark
+ Material.accent: Material.LightGreen
+ spacing: -12
+ width: 200
+
+ Text {
+ id: textItem
+ anchors.horizontalCenter: parent.horizontalCenter
+ color: "#f0f0f0"
+ font.pixelSize: 14 * dp
+ }
+ Item {
+ width: 1
+ height: 36
+ }
+
+ Row {
+ x: itemMargin / 2
+ spacing: itemMargin
+ opacity: rootItem.enabled ? 1.0 : 0.2
+ Column {
+ Rectangle {
+ width: rootItem.itemWidth
+ height: colorBarHeight
+ border.width: 1
+ border.color: "#202020"
+ gradient: Gradient {
+ orientation: Gradient.Horizontal
+ GradientStop { position: 0.0; color: Qt.rgba(0.0, colorGreen, colorBlue, 1.0) }
+ GradientStop { position: 1.0; color: Qt.rgba(1.0, colorGreen, colorBlue, 1.0) }
+ }
+ Text {
+ id: textItemRed
+ anchors.centerIn: parent
+ color: "#f0f0f0"
+ style: Text.Outline
+ styleColor: "#000000"
+ text: "R: " + Math.ceil(sliderRed.value * 255)
+ font.pixelSize: 14 * dp
+ }
+ }
+ Slider {
+ id: sliderRed
+ width: rootItem.itemWidth
+ value: 0
+ from: 0
+ to: 1
+ }
+ }
+ Column {
+ Rectangle {
+ width: rootItem.itemWidth
+ height: colorBarHeight
+ border.width: 1
+ border.color: "#202020"
+ gradient: Gradient {
+ orientation: Gradient.Horizontal
+ GradientStop { position: 0.0; color: Qt.rgba(colorRed, 0.0, colorBlue, 1.0) }
+ GradientStop { position: 1.0; color: Qt.rgba(colorRed, 1.0, colorBlue, 1.0) }
+ }
+ Text {
+ id: textItemGreen
+ anchors.centerIn: parent
+ color: "#f0f0f0"
+ style: Text.Outline
+ styleColor: "#000000"
+ text: "G: " + Math.ceil(sliderGreen.value * 255)
+ font.pixelSize: 14 * dp
+ }
+ }
+ Slider {
+ id: sliderGreen
+ width: rootItem.itemWidth
+ value: 0
+ from: 0
+ to: 1
+ }
+ }
+ Column {
+ Rectangle {
+ width: rootItem.itemWidth
+ height: colorBarHeight
+ border.width: 1
+ border.color: "#202020"
+ gradient: Gradient {
+ orientation: Gradient.Horizontal
+ GradientStop { position: 0.0; color: Qt.rgba(colorRed, colorGreen, 0.0, 1.0) }
+ GradientStop { position: 1.0; color: Qt.rgba(colorRed, colorGreen, 1.0, 1.0) }
+ }
+ Text {
+ id: textItemBlue
+ anchors.centerIn: parent
+ color: "#f0f0f0"
+ style: Text.Outline
+ styleColor: "#000000"
+ text: "B: " + Math.ceil(sliderBlue.value * 255)
+ font.pixelSize: 14 * dp
+ }
+ }
+ Slider {
+ id: sliderBlue
+ width: rootItem.itemWidth
+ value: 0
+ from: 0
+ to: 1
+ }
+ }
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/SettingsComponentSlider.qml b/examples/quick/multieffect/testbed/qml/SettingsComponentSlider.qml
new file mode 100644
index 0000000000..ed04584e44
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/SettingsComponentSlider.qml
@@ -0,0 +1,54 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.Material
+
+Column {
+ id: rootItem
+
+ property alias text: textItem.text
+ property alias value: slider.value
+ property alias from: slider.from
+ property alias to: slider.to
+ property alias checked: checkBox.checked
+ property alias stepSize: slider.stepSize
+ property bool showCheckbox: false
+
+ signal toggled
+ signal moved
+
+ Material.theme: Material.Dark
+ Material.accent: Material.LightGreen
+ spacing: -12
+
+ Text {
+ id: textItem
+ anchors.horizontalCenter: parent.horizontalCenter
+ color: "#f0f0f0"
+ font.pixelSize: 14 * dp
+ }
+
+ Row {
+ CheckBox {
+ id: checkBox
+ visible: rootItem.showCheckbox
+ checked: true
+ onToggled: {
+ rootItem.toggled();
+ }
+ }
+ Slider {
+ id: slider
+ property real sliderWidth: settings.settingsViewWidth - 50
+ width: rootItem.showCheckbox ? sliderWidth : sliderWidth + checkBox.width
+ value: 50
+ from: 0
+ to: 800
+ onMoved: {
+ rootItem.moved();
+ }
+ }
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/SettingsComponentView.qml b/examples/quick/multieffect/testbed/qml/SettingsComponentView.qml
new file mode 100644
index 0000000000..08eb0ad300
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/SettingsComponentView.qml
@@ -0,0 +1,147 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Column {
+ id: rootItem
+
+ property alias text: textItem.text
+ property bool show: true
+
+ default property alias contents: contentItem.children
+ property real showHideAnimationSpeed: 400
+
+ width: settings.settingsViewWidth
+
+ Component.onCompleted: {
+ // Set initial open state
+ contentItem.visible = rootItem.show;
+ contentItem.opacity = rootItem.show;
+ contentItemArea.height = rootItem.show ? contentItem.height : 0;
+ }
+
+ Item {
+ id: lightsSettings
+ width: parent.width
+ height: 30
+ Rectangle {
+ anchors.fill: parent
+ color: "#404040"
+ border.width: 1
+ border.color: "#808080"
+ opacity: 0.4
+ }
+ Image {
+ x: 8
+ source: "images/arrow.png"
+ anchors.verticalCenter: parent.verticalCenter
+ rotation: rootItem.show ? 90 : 0
+ Behavior on rotation {
+ NumberAnimation {
+ duration: showHideAnimationSpeed
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+
+ Text {
+ id: textItem
+ x: 30
+ anchors.verticalCenter: parent.verticalCenter
+ color: "#f0f0f0"
+ font.bold: true
+ font.pixelSize: 16 * dp
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ rootItem.show = !rootItem.show;
+ if (rootItem.show) {
+ hideAnimation.stop();
+ showAnimation.start();
+ } else {
+ showAnimation.stop();
+ hideAnimation.start();
+ }
+
+ }
+ }
+ }
+
+ Item {
+ width: 1
+ height: 5
+ }
+
+ SequentialAnimation {
+ id: showAnimation
+ ScriptAction {
+ script: contentItem.visible = true;
+ }
+ ParallelAnimation {
+ NumberAnimation {
+ target: contentItemArea
+ property: "height"
+ to: contentItem.height
+ duration: showHideAnimationSpeed
+ easing.type: Easing.InOutQuad
+ }
+ SequentialAnimation {
+ PauseAnimation {
+ duration: showHideAnimationSpeed / 2
+ }
+ NumberAnimation {
+ target: contentItem
+ property: "opacity"
+ to: 1.0
+ duration: showHideAnimationSpeed / 2
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+
+ SequentialAnimation {
+ id: hideAnimation
+ ParallelAnimation {
+ NumberAnimation {
+ target: contentItemArea
+ property: "height"
+ to: 0
+ duration: showHideAnimationSpeed
+ easing.type: Easing.InOutQuad
+ }
+ SequentialAnimation {
+ NumberAnimation {
+ target: contentItem
+ property: "opacity"
+ to: 0
+ duration: showHideAnimationSpeed / 2
+ easing.type: Easing.InOutQuad
+ }
+ PauseAnimation {
+ duration: showHideAnimationSpeed / 2
+ }
+ }
+ }
+ ScriptAction {
+ script: contentItem.visible = false;
+ }
+ }
+
+ Item {
+ id: contentItemArea
+ width: parent.width - 10
+ x: 5
+ Column {
+ id: contentItem
+ spacing: -10
+ }
+ }
+
+ Item {
+ width: 1
+ height: 5
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/SettingsView.qml b/examples/quick/multieffect/testbed/qml/SettingsView.qml
new file mode 100644
index 0000000000..d0d70958bf
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/SettingsView.qml
@@ -0,0 +1,400 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls.Material
+
+Item {
+ id: rootItem
+
+ property bool show: true
+ property real showAnimation: show ? 1 : 0
+
+ function resetSettings() {
+ colorizeColorSelector.setValues(defaultSettings.colorizeColor.r,
+ defaultSettings.colorizeColor.g,
+ defaultSettings.colorizeColor.b);
+ shadowColorSelector.setValues(defaultSettings.shadowColor.r,
+ defaultSettings.shadowColor.g,
+ defaultSettings.shadowColor.b);
+ }
+
+ Material.theme: Material.Dark
+ Material.accent: Material.LightGreen
+ width: settings.settingsViewWidth
+ x: -(width + 30) * (1 - showAnimation) + 20
+
+ Behavior on showAnimation {
+ NumberAnimation {
+ duration: 400
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ // Open/close button
+ Item {
+ width: 30 * dp
+ height: 30 * dp
+ anchors.left: parent.right
+ anchors.leftMargin: 20
+ anchors.top: parent.top
+ anchors.topMargin: -10
+ Rectangle {
+ anchors.fill: parent
+ color: "#404040"
+ opacity: 0.4
+ border.width: 1
+ border.color: "#808080"
+ }
+
+ Image {
+ anchors.centerIn: parent
+ source: "images/arrow.png"
+ rotation: rootItem.showAnimation * 180
+ }
+ MouseArea {
+ anchors.fill: parent
+ anchors.margins: -30 * dp
+ onClicked: {
+ rootItem.show = !rootItem.show;
+ }
+ }
+ }
+
+ // Background
+ Rectangle {
+ anchors.fill: scrollView
+ opacity: showAnimation ? 0.6 : 0
+ visible: opacity
+ anchors.margins: -10
+ color: "#202020"
+ border.color: "#808080"
+ border.width: 1
+ }
+
+ ScrollView {
+ id: scrollView
+ anchors.fill: parent
+ ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
+ ScrollBar.vertical.interactive: false
+ clip: true
+ Column {
+ id: settingsArea
+ anchors.fill: parent
+ opacity: showAnimation
+ visible: opacity
+
+ Item {
+ width: 1
+ height: 20 * dp
+ }
+ Image {
+ anchors.horizontalCenter: parent.horizontalCenter
+ fillMode: Image.PreserveAspectFit
+ width: parent.width * 0.8
+ height: width * 0.25
+ source: "images/Built_with_Qt_RGB_logo.png"
+ }
+ Item {
+ width: 1
+ height: 28 * dp
+ }
+
+ SettingsComponentView {
+ id: settingsViewGeneral
+ text: qsTr("General")
+ show: true
+ SettingsComponentCheckBox {
+ text: "Show Shaders"
+ checked: settings.showShader
+ onToggled: {
+ settings.showShader = checked;
+ }
+ }
+ SettingsComponentCheckBox {
+ text: "Show Item Size"
+ checked: settings.showItemSize
+ onToggled: {
+ settings.showItemSize = checked;
+ }
+ }
+ SettingsComponentCheckBox {
+ text: "AutoPadding Enabled"
+ checked: settings.autoPaddingEnabled
+ onToggled: {
+ settings.autoPaddingEnabled = checked;
+ }
+ }
+ Item {
+ width: 1
+ height: 20 * dp
+ }
+ SettingsComponentSlider {
+ text: qsTr("Padding Left") + ": " + value.toFixed(0)
+ value: settings.paddingRect.x
+ from: 0.0
+ to: 300
+ onMoved: {
+ settings.paddingRect.x = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Padding Right") + ": " + value.toFixed(0)
+ value: settings.paddingRect.width
+ from: 0.0
+ to: 300
+ onMoved: {
+ settings.paddingRect.width = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Padding Top") + ": " + value.toFixed(0)
+ value: settings.paddingRect.y
+ from: 0.0
+ to: 300
+ onMoved: {
+ settings.paddingRect.y = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Padding Bottom") + ": " + value.toFixed(0)
+ value: settings.paddingRect.height
+ from: 0.0
+ to: 300
+ onMoved: {
+ settings.paddingRect.height = value;
+ }
+ }
+ }
+
+ SettingsComponentView {
+ text: qsTr("Color")
+ show: false
+ SettingsComponentSlider {
+ text: qsTr("Brightness") + ": " + value.toFixed(3)
+ showCheckbox: true
+ checked: settings.brightnessEnabled
+ onToggled: {
+ settings.brightnessEnabled = checked;
+ }
+ value: settings.brightness
+ from: -1
+ to: 1
+ onMoved: {
+ settings.brightness = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Contrast") + ": " + value.toFixed(3)
+ showCheckbox: true
+ checked: settings.contrastEnabled
+ onToggled: {
+ settings.contrastEnabled = checked;
+ }
+ value: settings.contrast
+ from: -1
+ to: 1
+ onMoved: {
+ settings.contrast = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Saturation") + ": " + value.toFixed(3)
+ showCheckbox: true
+ checked: settings.saturationEnabled
+ onToggled: {
+ settings.saturationEnabled = checked;
+ }
+ value: settings.saturation
+ from: -1
+ to: 1
+ onMoved: {
+ settings.saturation = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Colorize") + ": " + value.toFixed(3)
+ showCheckbox: true
+ checked: settings.colorizeEnabled
+ onToggled: {
+ settings.colorizeEnabled = checked;
+ }
+ value: settings.colorize
+ from: 0
+ to: 1
+ onMoved: {
+ settings.colorize = value;
+ }
+ }
+ SettingsComponentColorSelector {
+ id: colorizeColorSelector
+ text: qsTr("Colorize Color")
+ width: settings.settingsViewWidth - 10
+ onValueChanged: {
+ settings.colorizeColor = value;
+ }
+ }
+ }
+ SettingsComponentView {
+ text: qsTr("Blur")
+ show: false
+
+ SettingsComponentSlider {
+ text: qsTr("Blur") + ": " + value.toFixed(3)
+ showCheckbox: true
+ checked: settings.blurEnabled
+ onToggled: {
+ settings.blurEnabled = checked;
+ }
+ value: settings.blur
+ from: 0
+ to: 1.0
+ onMoved: {
+ settings.blur = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Blur Multiplier") + ": " + value.toFixed(3)
+ value: settings.blurMultiplier
+ from: 0.0
+ to: 2.0
+ onMoved: {
+ settings.blurMultiplier = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Blur Max") + ": " + value.toFixed(0)
+ value: settings.blurMax
+ from: 0
+ to: 64
+ stepSize: 2
+ onMoved: {
+ settings.blurMax = value;
+ }
+ }
+
+ }
+ SettingsComponentView {
+ text: qsTr("Shadow")
+ show: false
+
+ SettingsComponentSlider {
+ text: qsTr("Shadow") + ": " + value.toFixed(3)
+ showCheckbox: true
+ checked: settings.shadowEnabled
+ onToggled: {
+ settings.shadowEnabled = checked;
+ }
+ value: settings.shadowOpacity
+ from: 0
+ to: 1.0
+ onMoved: {
+ settings.shadowOpacity = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Shadow Blur") + ": " + value.toFixed(3)
+ value: settings.shadowBlur
+ from: 0.0
+ to: 1.0
+ onMoved: {
+ settings.shadowBlur = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Shadow HorizontalOffset") + ": " + value.toFixed(1)
+ value: settings.shadowHorizontalOffset
+ from: -20.0
+ to: 20.0
+ onMoved: {
+ settings.shadowHorizontalOffset = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Shadow VerticalOffset") + ": " + value.toFixed(1)
+ value: settings.shadowVerticalOffset
+ from: -20.0
+ to: 20.0
+ onMoved: {
+ settings.shadowVerticalOffset = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Shadow Scale") + ": " + value.toFixed(3)
+ value: settings.shadowScale
+ from: 0.8
+ to: 1.2
+ onMoved: {
+ settings.shadowScale = value;
+ }
+ }
+ SettingsComponentColorSelector {
+ id: shadowColorSelector
+ text: qsTr("Shadow Color")
+ width: settings.settingsViewWidth - 10
+ onValueChanged: {
+ settings.shadowColor = value;
+ }
+ }
+ }
+ SettingsComponentView {
+ text: qsTr("Mask")
+ show: false
+ SettingsComponentCheckBox {
+ text: "Mask Enabled"
+ checked: settings.maskEnabled
+ onToggled: {
+ settings.maskEnabled = checked;
+ }
+ }
+ SettingsComponentCheckBox {
+ text: "Mask Inverted"
+ checked: settings.maskInverted
+ onToggled: {
+ settings.maskInverted = checked;
+ }
+ }
+ Item {
+ width: 1
+ height: 20 * dp
+ }
+ SettingsComponentSlider {
+ text: qsTr("Mask Lower Threshold") + ": " + value.toFixed(3)
+ value: settings.maskThresholdLow
+ from: 0.0
+ to: 1.0
+ onMoved: {
+ settings.maskThresholdLow = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Mask Lower Spread") + ": " + value.toFixed(3)
+ value: settings.maskSpreadLow
+ from: 0.0
+ to: 1.0
+ onMoved: {
+ settings.maskSpreadLow = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Mask Upper Threshold") + ": " + value.toFixed(3)
+ value: settings.maskThresholdUp
+ from: 0.0
+ to: 1.0
+ onMoved: {
+ settings.maskThresholdUp = value;
+ }
+ }
+ SettingsComponentSlider {
+ text: qsTr("Mask Upper Spread") + ": " + value.toFixed(3)
+ value: settings.maskSpreadUp
+ from: 0.0
+ to: 1.0
+ onMoved: {
+ settings.maskSpreadUp = value;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/ShaderView.qml b/examples/quick/multieffect/testbed/qml/ShaderView.qml
new file mode 100644
index 0000000000..fc89f5aec5
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/ShaderView.qml
@@ -0,0 +1,29 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: rootItem
+
+ property string text
+
+ width: textItem.width
+ height: textItem.height
+
+ Rectangle {
+ anchors.fill: textItem
+ anchors.margins: -10
+ z: -1
+ color: "#000000"
+ opacity: 0.6
+ border.color: "#ffffff"
+ border.width: 2
+ }
+ Text {
+ id: textItem
+ text: rootItem.text
+ font.pixelSize: 16
+ color: "#ffffff"
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/TestMaskItem.qml b/examples/quick/multieffect/testbed/qml/TestMaskItem.qml
new file mode 100644
index 0000000000..4ba5950b96
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/TestMaskItem.qml
@@ -0,0 +1,17 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: rootItem
+ layer.enabled: true
+ visible: false
+ Rectangle {
+ anchors.fill: parent
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#00000000" }
+ GradientStop { position: 1.0; color: "#ffffffff" }
+ }
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/TestSourceItem.qml b/examples/quick/multieffect/testbed/qml/TestSourceItem.qml
new file mode 100644
index 0000000000..ca5ca387ec
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/TestSourceItem.qml
@@ -0,0 +1,113 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Controls.Material
+
+Item {
+ id: rootItem
+
+ Material.theme: Material.Dark
+ Material.accent: Material.LightGreen
+
+ Image {
+ anchors.centerIn: parent
+ width: parent.width / 2
+ height: parent.height / 2
+ sourceSize.width: width
+ sourceSize.height: height
+ source: "images/Built_with_Qt.png"
+ fillMode: Image.PreserveAspectFit
+ SequentialAnimation on anchors.verticalCenterOffset {
+ loops: Animation.Infinite
+ paused: !settings.animateMovement
+ NumberAnimation {
+ to: 50
+ duration: 2000
+ easing.type: Easing.InOutQuad
+ }
+ NumberAnimation {
+ to: -50
+ duration: 2000
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ Text {
+ font.pixelSize: 50
+ font.bold: true
+ text: "TESTING"
+ color: "white"
+ }
+ Image {
+ source: "images/warning.png"
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ mipmap: true
+ SequentialAnimation on scale {
+ loops: Animation.Infinite
+ paused: !settings.animateMovement
+ NumberAnimation {
+ to: 0.4
+ duration: 3000
+ easing.type: Easing.InOutQuad
+ }
+ NumberAnimation {
+ to: 1.0
+ duration: 1000
+ easing.type: Easing.OutBack
+ }
+ }
+
+ }
+ Rectangle {
+ width: parent.width * 0.2
+ height: width
+ anchors.top: parent.top
+ anchors.topMargin: width * 0.2
+ anchors.right: parent.right
+ anchors.rightMargin: width * 0.2
+ color: "#808080"
+ border.color: "#f0f0f0"
+ border.width: 2
+ radius: width * 0.1
+ SequentialAnimation on opacity {
+ paused: !settings.animateMovement
+ loops: Animation.Infinite
+ NumberAnimation {
+ to: 0.0
+ duration: 2000
+ easing.type: Easing.InOutQuad
+ }
+ NumberAnimation {
+ to: 1.0
+ duration: 2000
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ NumberAnimation on rotation {
+ paused: !settings.animateMovement
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 10000
+ }
+ }
+
+ Column {
+ anchors.right: parent.right
+ anchors.rightMargin: width * 0.2
+ anchors.bottom: parent.bottom
+ Button {
+ id: button
+ text: "Controls Button"
+ Material.theme: Material.Light
+ }
+ Slider {
+ width: button.width
+ }
+ }
+}
+
diff --git a/examples/quick/multieffect/testbed/qml/WarningsItem.qml b/examples/quick/multieffect/testbed/qml/WarningsItem.qml
new file mode 100644
index 0000000000..201332c87b
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/WarningsItem.qml
@@ -0,0 +1,66 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: rootItem
+
+ property string text
+
+ function show() {
+ showAnimation.restart();
+ }
+
+ height: 42
+ width: warningIcon.width + textItem.width + 40
+ opacity: 0
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#000000"
+ opacity: 0.6
+ }
+
+ SequentialAnimation {
+ id: showAnimation
+ NumberAnimation {
+ target: rootItem
+ property: "opacity"
+ to: 1
+ duration: 400
+ easing.type: Easing.InOutQuad
+ }
+ PauseAnimation {
+ duration: 2000
+ }
+ NumberAnimation {
+ target: rootItem
+ property: "opacity"
+ to: 0
+ duration: 400
+ easing.type: Easing.InOutQuad
+ }
+ }
+
+ Image {
+ id: warningIcon
+ anchors.verticalCenter: parent.verticalCenter
+ x: 8
+ source: "images/warning.png"
+ mipmap: true
+ width: 24
+ height: width
+ }
+
+ Text {
+ id: textItem
+ anchors.left: warningIcon.right
+ anchors.leftMargin: 8
+ anchors.verticalCenter: parent.verticalCenter
+ color: "#ffffff"
+ font.pixelSize: 16
+ text: rootItem.text
+ }
+
+}
diff --git a/examples/quick/multieffect/testbed/qml/WarningsView.qml b/examples/quick/multieffect/testbed/qml/WarningsView.qml
new file mode 100644
index 0000000000..880a75b885
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/WarningsView.qml
@@ -0,0 +1,31 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+
+Item {
+ id: rootItem
+
+ function showShaderWarning() {
+ shaderWarning.show();
+ }
+ function showSizeWarning() {
+ sizeWarning.show();
+ }
+
+ height: 60
+
+ WarningsItem {
+ id: shaderWarning
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: parent.left
+ text: qsTr("Shader changed!")
+ }
+ WarningsItem {
+ id: sizeWarning
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.left: shaderWarning.right
+ anchors.leftMargin: 16
+ text: qsTr("Item resized!")
+ }
+}
diff --git a/examples/quick/multieffect/testbed/qml/images/Built_with_Qt.png b/examples/quick/multieffect/testbed/qml/images/Built_with_Qt.png
new file mode 100644
index 0000000000..e612481510
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/images/Built_with_Qt.png
Binary files differ
diff --git a/examples/quick/multieffect/testbed/qml/images/Built_with_Qt_RGB_logo.png b/examples/quick/multieffect/testbed/qml/images/Built_with_Qt_RGB_logo.png
new file mode 100644
index 0000000000..8d2dfc17ec
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/images/Built_with_Qt_RGB_logo.png
Binary files differ
diff --git a/examples/quick/multieffect/testbed/qml/images/arrow.png b/examples/quick/multieffect/testbed/qml/images/arrow.png
new file mode 100644
index 0000000000..067bec4509
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/images/arrow.png
Binary files differ
diff --git a/examples/quick/multieffect/testbed/qml/images/pause.png b/examples/quick/multieffect/testbed/qml/images/pause.png
new file mode 100644
index 0000000000..ef6e0ac26a
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/images/pause.png
Binary files differ
diff --git a/examples/quick/multieffect/testbed/qml/images/play.png b/examples/quick/multieffect/testbed/qml/images/play.png
new file mode 100644
index 0000000000..4cd0f78184
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/images/play.png
Binary files differ
diff --git a/examples/quick/multieffect/testbed/qml/images/spinner.png b/examples/quick/multieffect/testbed/qml/images/spinner.png
new file mode 100644
index 0000000000..3ff86d53ac
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/images/spinner.png
Binary files differ
diff --git a/examples/quick/multieffect/testbed/qml/images/warning.png b/examples/quick/multieffect/testbed/qml/images/warning.png
new file mode 100644
index 0000000000..08d74b8b83
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/images/warning.png
Binary files differ
diff --git a/examples/quick/multieffect/testbed/qml/main.qml b/examples/quick/multieffect/testbed/qml/main.qml
new file mode 100644
index 0000000000..71cec0a486
--- /dev/null
+++ b/examples/quick/multieffect/testbed/qml/main.qml
@@ -0,0 +1,155 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Window
+import QtQuick.Effects
+
+Rectangle {
+ id: mainWindow
+
+ // Multiplier for resolution independency
+ readonly property real dp: 0.2 + Math.min(width, height) / 1200
+
+ width: 1280
+ height: 720
+ color: "#404040"
+
+ Settings {
+ id: settings
+ onReseted: {
+ settingsView.resetSettings();
+ }
+ }
+
+ Settings {
+ id: defaultSettings
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (resetSettingsOverlay.showAnimationProgress == 0)
+ settings.animateMovement = !settings.animateMovement;
+ }
+ onPressed: {
+ resetSettingsOverlay.startShow();
+ }
+ onReleased: {
+ resetSettingsOverlay.stopShow();
+ }
+ }
+
+
+ Item {
+ id: mainArea
+ anchors.left: settingsView.right
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+
+ TestSourceItem {
+ id: testSourceItem
+ anchors.centerIn: parent
+ width: parent.width / 2
+ height: parent.height / 2
+
+ layer.enabled: true
+ visible: false
+ }
+ TestMaskItem {
+ id: testMaskItem
+ anchors.fill: testSourceItem
+ }
+
+ Rectangle {
+ readonly property int margin: 2
+ x: quickMultiEffect.x + quickMultiEffect.itemRect.x - margin
+ y: quickMultiEffect.y + quickMultiEffect.itemRect.y - margin
+ width: quickMultiEffect.itemRect.width + margin * 2
+ height: quickMultiEffect.itemRect.height + margin * 2
+ visible: settings.showItemSize
+ color: "transparent"
+ border.color: "#ffffff"
+ border.width: 2
+ }
+
+ MultiEffect {
+ id: quickMultiEffect
+ anchors.fill: testSourceItem
+ source: testSourceItem
+ maskSource: testMaskItem
+
+ autoPaddingEnabled: settings.autoPaddingEnabled
+ paddingRect: settings.paddingRect
+ brightness: settings.brightnessEnabled ? settings.brightness : 0
+ contrast: settings.contrastEnabled ? settings.contrast : 0
+ saturation: settings.saturationEnabled ? settings.saturation : 0
+ colorizeColor: settings.colorizeColor
+ colorize: settings.colorizeEnabled ? settings.colorize : 0
+ blurEnabled: settings.blurEnabled
+ blur: settings.blur
+ blurMax: settings.blurMax
+ blurMultiplier: settings.blurMultiplier
+ shadowEnabled: settings.shadowEnabled
+ shadowOpacity: settings.shadowOpacity
+ shadowBlur: settings.shadowBlur
+ shadowHorizontalOffset: settings.shadowHorizontalOffset
+ shadowVerticalOffset: settings.shadowVerticalOffset
+ shadowColor: settings.shadowColor
+ shadowScale: settings.shadowScale
+ maskEnabled: settings.maskEnabled
+ maskInverted: settings.maskInverted
+ maskThresholdLow: settings.maskThresholdLow
+ maskSpreadLow: settings.maskSpreadLow
+ maskThresholdUp: settings.maskThresholdUp
+ maskSpreadUp: settings.maskSpreadUp
+
+ onItemSizeChanged: {
+ warningsView.showSizeWarning();
+ }
+ onShaderChanged: {
+ warningsView.showShaderWarning();
+ }
+ }
+ }
+
+ SettingsView {
+ id: settingsView
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.margins: 20
+ visible: settings.showSettingsView
+ Component.onCompleted: {
+ settings.reset();
+ }
+ }
+
+ FpsItem {
+ anchors.right: parent.right
+ }
+
+ ShaderView {
+ id: shaderView
+ visible: settings.showShader
+ anchors.horizontalCenter: mainArea.horizontalCenter
+ anchors.top: mainArea.top
+ anchors.topMargin: 20
+ text: "Fragment shader: " + quickMultiEffect.fragmentShader + "\nVertex shader: " + quickMultiEffect.vertexShader
+ }
+
+ WarningsView {
+ id: warningsView
+ anchors.bottom: parent.bottom
+ anchors.left: settingsView.right
+ anchors.leftMargin: 40
+ anchors.right: parent.right
+ }
+
+ ResetSettingsOverlay {
+ id: resetSettingsOverlay
+ onAnimationFinished: {
+ settings.reset();
+ }
+ }
+}
diff --git a/examples/quick/multieffect/testbed/testbed.pro b/examples/quick/multieffect/testbed/testbed.pro
new file mode 100644
index 0000000000..e1ae55b118
--- /dev/null
+++ b/examples/quick/multieffect/testbed/testbed.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+QT += quick qml
+QT += quickcontrols2
+SOURCES += main.cpp
+RESOURCES += \
+ qml.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/quick/multieffect/testbed
+INSTALLS += target
diff --git a/examples/quick/quick.pro b/examples/quick/quick.pro
index 2003b1c03b..159b0082a3 100644
--- a/examples/quick/quick.pro
+++ b/examples/quick/quick.pro
@@ -27,7 +27,8 @@ SUBDIRS = quick-accessibility \
particles \
delegatechooser \
shapes \
- itemvariablerefreshrate
+ itemvariablerefreshrate \
+ multieffect
#OpenGL Support Required
qtConfig(opengl(es1|es2)?) {