├── logo.png ├── examples ├── DesignerExample.qml ├── SimpleStep.qml ├── Spectrogram.qml ├── ContainerExample.qml ├── Overview.qml ├── OssiaServerExample.qml ├── Limiter.qml ├── DesignerExampleForm.ui.qml └── OssiaClientExample.qml ├── icons ├── leds.ai ├── logo.ai ├── cosPad.ai ├── graph.ai ├── label.ai ├── matrix.ai ├── scope.ai ├── slider.ai ├── switch.ai ├── xyPad.ai ├── container.ai ├── hsvSlider.ai ├── joystick.ai ├── keyboard.ai ├── logoCabin.ai ├── rgbSlider.ai ├── textEdit.ai ├── angleSlider.ai ├── donutSlider.ai ├── logo_slider.ai ├── multislider.ai └── toggleSwitch.ai ├── com └── github │ └── jcelerier │ └── CreativeControls │ ├── Random1D.qml │ ├── Random2D.qml │ ├── Random3D.qml │ ├── ColorWheel.qml │ ├── designer │ ├── leds-icon.png │ ├── pad-icon.png │ ├── cosPad-icon.png │ ├── graph-icon.png │ ├── graph-icon16.png │ ├── hslider-icon.png │ ├── label-icon.png │ ├── label-icon16.png │ ├── leds-icon16.png │ ├── leds-icon@2x.png │ ├── matrix-icon.png │ ├── pad-icon16.png │ ├── pad-icon@2x.png │ ├── scope-icon.png │ ├── scope-icon16.png │ ├── switch-icon.png │ ├── vslider-icon.png │ ├── container-icon.png │ ├── cosPad-icon16.png │ ├── cosPad-icon@2x.png │ ├── graph-icon@2x.png │ ├── hslider-icon16.png │ ├── hsvSlider-icon.png │ ├── joystick-icon.png │ ├── keyboard-icon.png │ ├── label-icon@2x.png │ ├── matrix-icon16.png │ ├── matrix-icon@2x.png │ ├── rgbSlider-icon.png │ ├── scope-icon@2x.png │ ├── switch-icon16.png │ ├── switch-icon@2x.png │ ├── textEdit-icon.png │ ├── vslider-icon16.png │ ├── angleSlider-icon.png │ ├── container-icon16.png │ ├── container-icon@2x.png │ ├── donutSlider-icon.png │ ├── hslider-icon@2x.png │ ├── hsvSlider-icon16.png │ ├── hsvSlider-icon@2x.png │ ├── joystick-icon16.png │ ├── joystick-icon@2x.png │ ├── keyboard-icon16.png │ ├── keyboard-icon@2x.png │ ├── multislider-icon.png │ ├── rgbSlider-icon16.png │ ├── rgbSlider-icon@2x.png │ ├── textEdit-icon16.png │ ├── textEdit-icon@2x.png │ ├── toggleSwitch-icon.png │ ├── vslider-icon@2x.png │ ├── angleSlider-icon16.png │ ├── angleSlider-icon@2x.png │ ├── donutSlider-icon16.png │ ├── donutSlider-icon@2x.png │ ├── multislider-icon16.png │ ├── multislider-icon@2x.png │ ├── toggleSwitch-icon16.png │ ├── toggleSwitch-icon@2x.png │ └── CreativeControls.metainfo │ ├── Graph2D.qml │ ├── Trajectory.qml │ ├── Spectrum.qml │ ├── ColorChooser.qml │ ├── Scale.qml │ ├── HSLSlider.qml │ ├── HSVSlider.qml │ ├── RGBSlider.qml │ ├── AngleSlider.qml │ ├── Frame.qml │ ├── Label.qml │ ├── Graph.qml │ ├── Scope.qml │ ├── Styles.qml │ ├── Utils.qml │ ├── XYPad.qml │ ├── Switch.qml │ ├── qmldir-qpm │ ├── qmldir │ ├── Container.qml │ ├── DarkStyle.qml │ ├── LightStyle.qml │ ├── ToggleSwitch.qml │ ├── Spat.qml │ ├── Matrix.qml │ ├── Step.qml │ ├── Joystick.qml │ ├── MultiSlider.qml │ ├── ColorSlider.qml │ ├── Leds.qml │ ├── CosInfluence.qml │ ├── DonutSlider.qml │ ├── HSlider.qml │ ├── VSlider.qml │ ├── HRangeSlider.qml │ ├── ArcSlider.qml │ └── VRangeSlider.qml ├── tests ├── Various.qml └── SliderTest.qml ├── src ├── creativecontrolsplugin.hpp ├── cpputils.hpp ├── toucharea.hpp ├── cpputils.cpp ├── graph.hpp ├── creativecontrolsplugin.cpp ├── polygon.hpp ├── painted_polygon.hpp ├── angleslider.hpp ├── toucharea.cpp ├── scope.hpp ├── xytarget.hpp ├── painted_polygon.cpp ├── graph.cpp ├── angleslider.cpp ├── polygon.cpp ├── scope.cpp └── xytarget.cpp ├── travis ├── build.sh └── deps.sh ├── .travis.yml ├── qpm.json ├── com_github_jcelerier_qml-creative-controls.pri ├── appveyor.yml ├── .gitignore ├── .clang-format ├── qml-creative-controls.pro ├── README.md └── com_github_jcelerier_qml-creative-controls.qrc /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/logo.png -------------------------------------------------------------------------------- /examples/DesignerExample.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | 3 | DesignerExampleForm { 4 | } 5 | -------------------------------------------------------------------------------- /icons/leds.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/leds.ai -------------------------------------------------------------------------------- /icons/logo.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/logo.ai -------------------------------------------------------------------------------- /icons/cosPad.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/cosPad.ai -------------------------------------------------------------------------------- /icons/graph.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/graph.ai -------------------------------------------------------------------------------- /icons/label.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/label.ai -------------------------------------------------------------------------------- /icons/matrix.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/matrix.ai -------------------------------------------------------------------------------- /icons/scope.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/scope.ai -------------------------------------------------------------------------------- /icons/slider.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/slider.ai -------------------------------------------------------------------------------- /icons/switch.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/switch.ai -------------------------------------------------------------------------------- /icons/xyPad.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/xyPad.ai -------------------------------------------------------------------------------- /icons/container.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/container.ai -------------------------------------------------------------------------------- /icons/hsvSlider.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/hsvSlider.ai -------------------------------------------------------------------------------- /icons/joystick.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/joystick.ai -------------------------------------------------------------------------------- /icons/keyboard.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/keyboard.ai -------------------------------------------------------------------------------- /icons/logoCabin.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/logoCabin.ai -------------------------------------------------------------------------------- /icons/rgbSlider.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/rgbSlider.ai -------------------------------------------------------------------------------- /icons/textEdit.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/textEdit.ai -------------------------------------------------------------------------------- /icons/angleSlider.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/angleSlider.ai -------------------------------------------------------------------------------- /icons/donutSlider.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/donutSlider.ai -------------------------------------------------------------------------------- /icons/logo_slider.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/logo_slider.ai -------------------------------------------------------------------------------- /icons/multislider.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/multislider.ai -------------------------------------------------------------------------------- /icons/toggleSwitch.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/icons/toggleSwitch.ai -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Random1D.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // A 1D random generator 5 | Text { 6 | font.pointSize: 20 7 | text: "TODO" 8 | } 9 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Random2D.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // A 2D random generator 5 | Text { 6 | font.pointSize: 20 7 | text: "TODO" 8 | } 9 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Random3D.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // A 3D random generator 5 | Text { 6 | font.pointSize: 20 7 | text: "TODO" 8 | } 9 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/ColorWheel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // A color wheel like in Krita 5 | Text { 6 | font.pointSize: 20 7 | text: "TODO" 8 | } 9 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/leds-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/leds-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/pad-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/pad-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Graph2D.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // Displays 2D input messages in a graph 5 | Text { 6 | font.pointSize: 20 7 | text: "TODO" 8 | } 9 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/cosPad-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/cosPad-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/graph-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/graph-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/graph-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/graph-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/hslider-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/hslider-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/label-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/label-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/label-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/label-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/leds-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/leds-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/leds-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/leds-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/matrix-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/matrix-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/pad-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/pad-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/pad-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/pad-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/scope-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/scope-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/scope-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/scope-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/switch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/switch-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/vslider-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/vslider-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Trajectory.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // 2D trajectory 5 | // TODO 3D ? 6 | Text { 7 | font.pointSize: 20 8 | text: "TODO" 9 | } 10 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/container-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/container-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/cosPad-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/cosPad-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/cosPad-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/cosPad-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/graph-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/graph-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/hslider-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/hslider-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/hsvSlider-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/hsvSlider-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/joystick-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/joystick-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/keyboard-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/keyboard-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/label-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/label-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/matrix-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/matrix-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/matrix-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/matrix-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/rgbSlider-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/rgbSlider-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/scope-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/scope-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/switch-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/switch-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/switch-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/switch-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/textEdit-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/textEdit-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/vslider-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/vslider-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Spectrum.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // Displays a spectrum 5 | // No input 6 | Text { 7 | font.pointSize: 20 8 | text: "TODO" 9 | } 10 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/angleSlider-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/angleSlider-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/container-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/container-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/container-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/container-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/donutSlider-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/donutSlider-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/hslider-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/hslider-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/hsvSlider-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/hsvSlider-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/hsvSlider-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/hsvSlider-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/joystick-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/joystick-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/joystick-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/joystick-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/keyboard-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/keyboard-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/keyboard-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/keyboard-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/multislider-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/multislider-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/rgbSlider-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/rgbSlider-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/rgbSlider-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/rgbSlider-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/textEdit-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/textEdit-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/textEdit-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/textEdit-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/toggleSwitch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/toggleSwitch-icon.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/vslider-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/vslider-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/ColorChooser.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // A general 2D color chooser like Photoshop, etc. 5 | Text { 6 | font.pointSize: 20 7 | text: "TODO" 8 | } 9 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/angleSlider-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/angleSlider-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/angleSlider-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/angleSlider-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/donutSlider-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/donutSlider-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/donutSlider-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/donutSlider-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/multislider-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/multislider-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/multislider-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/multislider-icon@2x.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/toggleSwitch-icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/toggleSwitch-icon16.png -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/toggleSwitch-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jcelerier/qml-creative-controls/HEAD/com/github/jcelerier/CreativeControls/designer/toggleSwitch-icon@2x.png -------------------------------------------------------------------------------- /tests/Various.qml: -------------------------------------------------------------------------------- 1 | import com.github.jcelerier.CreativeControls 1.0 as CC 2 | import QtQuick 2.10 3 | import QtQuick.Controls 2.2 4 | 5 | ApplicationWindow 6 | { 7 | CC.XYPad { 8 | anchors.fill: parent 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Scale.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | 3 | 4 | // A graphical scale to display near to sliders, etc. 5 | // TODO : linear / logarithmic 6 | // TODO : rounded scale 7 | // See qwt 8 | Text { 9 | font.pointSize: 20 10 | text: "TODO" 11 | } 12 | -------------------------------------------------------------------------------- /tests/SliderTest.qml: -------------------------------------------------------------------------------- 1 | import com.github.jcelerier.CreativeControls 1.0 as CC 2 | import QtQuick 2.10 3 | import QtQuick.Controls 2.2 4 | 5 | ApplicationWindow 6 | { 7 | Row 8 | { 9 | spacing: 16 10 | CC.HSlider { } 11 | CC.VSlider { } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/creativecontrolsplugin.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace CreativeControls 5 | { 6 | class Plugin final : public QQmlExtensionPlugin 7 | { 8 | Q_OBJECT 9 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") 10 | public: 11 | Plugin(); 12 | void registerTypes(const char *uri) final override; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/HSLSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | import QtQuick.Layouts 1.3 4 | 5 | 6 | // Sliders to control hue, saturation, luminance, alpha, of a color 7 | // Properties: 8 | // * color: the current color 9 | // * enableAlpha: show the alpha channel slider 10 | ColorSlider { 11 | colorSpace: Qt.hsla 12 | enableAlpha: false 13 | } 14 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/HSVSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | import QtQuick.Layouts 1.3 4 | 5 | 6 | // Sliders to control hue, saturation, value, alpha, of a color 7 | // Properties: 8 | // * color: the current color 9 | // * enableAlpha: show the alpha channel slider 10 | ColorSlider { 11 | colorSpace: Qt.hsva 12 | enableAlpha: false 13 | } 14 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/RGBSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | import QtQuick.Layouts 1.3 4 | 5 | 6 | // Three to four sliders to control red, green, blue, alpha of a color 7 | // Properties: 8 | // * color: the current color 9 | // * enableAlpha: show the alpha channel slider 10 | ColorSlider { 11 | colorSpace: Qt.rgba 12 | enableAlpha: false 13 | } 14 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/AngleSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // An angular slider. 6 | // Parameter: angle. Range: [0; 360[ 7 | // TODO: infinite mode that uses the delta instead of the position. 8 | AngleSliderImpl { 9 | property var styles: DarkStyle 10 | 11 | width: 100 12 | height: 100 13 | baseColor: styles.background 14 | detailColor: styles.base 15 | angle: 0 16 | } 17 | -------------------------------------------------------------------------------- /travis/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | case "$TRAVIS_OS_NAME" in 4 | linux) 5 | export CC=/usr/bin/gcc-6 6 | export CXX=/usr/bin/g++-6 7 | 8 | QT_ENV_SCRIPT=$(find /opt -name 'qt*-env.sh') 9 | source $QT_ENV_SCRIPT 10 | export LD_LIBRARY_PATH="/usr/lib64:$LD_LIBRARY_PATH" 11 | 12 | qmake 13 | make -j2 14 | ;; 15 | 16 | osx) 17 | export PATH=$PATH:$(dirname $(find /usr/local/Cellar/qt5 -name qmake) ) 18 | 19 | qmake 20 | make -j2 21 | ;; 22 | esac 23 | -------------------------------------------------------------------------------- /travis/deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eux 2 | 3 | case "$TRAVIS_OS_NAME" in 4 | linux) 5 | sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 1397BC53640DB551 6 | sudo add-apt-repository --yes ppa:ubuntu-toolchain-r/test 7 | sudo add-apt-repository --yes ppa:beineri/opt-qt58-trusty 8 | sudo apt-get update -qq 9 | sudo apt-get install -qq --yes --force-yes g++-6 qt58-meta-minimal 10 | ;; 11 | osx) 12 | # work around a homebrew bug 13 | brew install qt5 14 | brew link --force qt5 15 | ;; 16 | esac 17 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | branches: 4 | except: 5 | - gh-pages 6 | 7 | env: 8 | global: 9 | - GH_REPO_NAME: qml-creative-controls 10 | - GH_REPO_REF: github.com/jcelerier/qml-creative-controls.git 11 | 12 | osx_image: xcode8.3 13 | dist: trusty 14 | sudo: required 15 | 16 | 17 | matrix: 18 | exclude: 19 | - os: linux 20 | - os: osx 21 | 22 | include: 23 | - os: linux 24 | dist: trusty 25 | 26 | - os: osx 27 | 28 | before_install: 29 | - "./travis/deps.sh" 30 | 31 | script: 32 | - "./travis/build.sh" 33 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Frame.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // Container 6 | // Rectangle with a background color and border 7 | Rectangle { 8 | id: container 9 | 10 | property var styles: DarkStyle 11 | 12 | anchors.centerIn: parent 13 | 14 | width: parent.width + border.width * 2 15 | height: parent.height + border.width * 2 16 | color: "transparent" 17 | 18 | border { 19 | width: 3 20 | color: styles.base 21 | } 22 | radius: 10 23 | } 24 | -------------------------------------------------------------------------------- /qpm.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.github.jcelerier.qml-creative-controls", 3 | "description": "", 4 | "author": { 5 | "name": "Jean-Michaël Celerier", 6 | "email": "jeanmichael.celerier@gmail.com" 7 | }, 8 | "repository": { 9 | "type": "GITHUB", 10 | "url": "https://github.com/jcelerier/qml-creative-controls" 11 | }, 12 | "version": { 13 | "label": "0.0.3", 14 | "revision": "", 15 | "fingerprint": "" 16 | }, 17 | "dependencies": [ 18 | ], 19 | "license": "AGPL_3_0", 20 | "pri_filename": "com_github_jcelerier_qml-creative-controls.pri", 21 | "webpage": "" 22 | } 23 | -------------------------------------------------------------------------------- /src/cpputils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace CreativeControls 6 | { 7 | class CppUtils final : public QObject 8 | { 9 | Q_OBJECT 10 | public: 11 | explicit CppUtils(QObject *parent = 0); 12 | 13 | signals: 14 | 15 | public slots: 16 | double getHSVHue(const QColor col); 17 | double getHSVSaturation(const QColor col); 18 | double getHSVValue(const QColor col); 19 | 20 | QColor setHSVHue(const QColor col, const double h); 21 | QColor setHSVSaturation(const QColor col, const double s); 22 | QColor setHSVValue(const QColor col, const double v); 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Label.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A label displaying text 6 | // Properties: 7 | // * selected: if the the control is selected the label changes 8 | Text { 9 | id: label 10 | 11 | 12 | // anchors.centerIn: parent 13 | property bool selected: false 14 | property var styles: DarkStyle 15 | 16 | color: styles.labelColor 17 | 18 | horizontalAlignment: Text.AlignHCenter 19 | verticalAlignment: Text.AlignVCenter 20 | 21 | font { 22 | bold: true 23 | pointSize: selected ? 15 : 14 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/SimpleStep.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.1 3 | import QtQuick.Layouts 1.1 4 | import com.github.jcelerier.CreativeControls 1.0 5 | 6 | Rectangle { 7 | width: 800 8 | height: step.height + 10 9 | 10 | color: DarkStyle.background 11 | Timer { 12 | running: true 13 | interval: 200 14 | repeat: true 15 | onTriggered: step.nextStep() 16 | } 17 | 18 | Container { 19 | width: 800 20 | height: step.height + 10 21 | 22 | Step { 23 | id: step 24 | anchors.centerIn: parent 25 | 26 | width: parent.width 27 | onStep: { 28 | console.log(values) 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Graph.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // Displays input messages in a graph 6 | // No UI input. 7 | // * lines: will display lines between dots 8 | Rectangle { 9 | property var styles: DarkStyle 10 | 11 | color: styles.background 12 | property alias lines: plot.lines 13 | 14 | // Use this function to add a value to the graph. 15 | function pushValue(v) { 16 | plot.values.push(v) 17 | if (plot.values.length > (width / 2)) 18 | plot.values.shift() 19 | } 20 | 21 | GraphImpl { 22 | id: plot 23 | anchors.fill: parent 24 | 25 | color: styles.base 26 | lines: true 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /com_github_jcelerier_qml-creative-controls.pri: -------------------------------------------------------------------------------- 1 | config += c++14 2 | RESOURCES += $$PWD/com_github_jcelerier_qml-creative-controls.qrc 3 | 4 | HEADERS += \ 5 | $$PWD/src/graph.hpp \ 6 | $$PWD/src/creativecontrolsplugin.hpp \ 7 | $$PWD/src/angleslider.hpp \ 8 | $$PWD/src/scope.hpp \ 9 | $$PWD/src/cpputils.hpp \ 10 | $$PWD/src/xytarget.hpp \ 11 | $$PWD/src/polygon.hpp \ 12 | $$PWD/src/toucharea.hpp \ 13 | $$PWD/src/painted_polygon.hpp 14 | 15 | SOURCES += \ 16 | $$PWD/src/graph.cpp \ 17 | $$PWD/src/creativecontrolsplugin.cpp \ 18 | $$PWD/src/angleslider.cpp \ 19 | $$PWD/src/scope.cpp \ 20 | $$PWD/src/cpputils.cpp \ 21 | $$PWD/src/xytarget.cpp \ 22 | $$PWD/src/polygon.cpp \ 23 | $$PWD/src/toucharea.cpp \ 24 | $$PWD/src/painted_polygon.cpp 25 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Scope.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // An oscilliscope. 6 | // No user input. 7 | // Properties: 8 | // * points: an array of values that will be displayed. 9 | // * symmetrize: render a waveform instead of a scope 10 | // * yMin / yMax: bounds (in the value domain) that should be shown. Default is [-1; 1] 11 | // TODO allow to display a "fill" under the scope in non-symmetrized mode 12 | Item { 13 | property alias symmetrize: scope.symmetrize 14 | property alias points: scope.points 15 | property var styles: DarkStyle 16 | 17 | Rectangle { 18 | anchors.fill: parent 19 | color: styles.background 20 | } 21 | 22 | ScopeImpl { 23 | anchors.fill: parent 24 | id: scope 25 | yMin: -1 26 | yMax: 1 27 | baseColor: styles.colorOn 28 | detailColor: styles.base 29 | symmetrize: false 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Visual Studio 2017 2 | 3 | environment: 4 | 5 | matrix: 6 | - platform: Win32 7 | configuration: Debug 8 | QTDIR: C:\Qt\5.11\msvc2015 9 | CMAKE_GENERATOR_NAME: Visual Studio 15 2017 10 | - platform: Win32 11 | configuration: Release 12 | QTDIR: C:\Qt\5.11\msvc2015 13 | CMAKE_GENERATOR_NAME: Visual Studio 15 2017 14 | - platform: x64 15 | configuration: Debug 16 | QTDIR: C:\Qt\5.11\msvc2017_64 17 | CMAKE_GENERATOR_NAME: Visual Studio 15 2017 Win64 18 | - platform: x64 19 | configuration: Release 20 | QTDIR: C:\Qt\5.11\msvc2017_64 21 | CMAKE_GENERATOR_NAME: Visual Studio 15 2017 Win64 22 | 23 | before_build: 24 | - set PATH=%QTDIR%\bin;%PATH% 25 | - if %QTDIR:_64=%==%QTDIR% (set ARCH=x86) else (set ARCH=x64) 26 | - call "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %ARCH% 27 | 28 | build_script: 29 | - qmake qml-creative-controls.pro -r 30 | - call nmake 31 | -------------------------------------------------------------------------------- /src/toucharea.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace CreativeControls 6 | { 7 | class TouchArea : public QQuickItem 8 | { 9 | Q_OBJECT 10 | Q_PROPERTY(bool pressState READ pressState WRITE setPressState NOTIFY pressStateChanged) 11 | bool m_pressState{}; 12 | 13 | public: 14 | TouchArea(); 15 | 16 | bool pressState() const; 17 | 18 | public slots: 19 | void setPressState(const bool pressState); 20 | 21 | signals: 22 | void pressed(QPointF point); 23 | void positionChanged(QPointF point); 24 | void released(QPointF point); 25 | void doubleClicked(QPointF point); 26 | 27 | void pressStateChanged(bool pressState); 28 | 29 | protected: 30 | void mousePressEvent(QMouseEvent* event) final override; 31 | void mouseMoveEvent(QMouseEvent* event) final override; 32 | void mouseReleaseEvent(QMouseEvent* event) final override; 33 | void mouseDoubleClickEvent(QMouseEvent* event) final override; 34 | void touchEvent(QTouchEvent* event) final override; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /examples/Spectrogram.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | Container { 5 | id: root 6 | width: 800 7 | height: 400 8 | 9 | MultiSlider { 10 | id: slider 11 | anchors.fill:parent 12 | count: 64 13 | textVisible: false 14 | interactive: false 15 | spacing: 1 16 | ease: true 17 | } 18 | 19 | // Init to zero 20 | Component.onCompleted: { 21 | var array = []; 22 | for (var i = 0; i < slider.count; i++) { 23 | array.push(0.3); 24 | } 25 | slider.values = array; 26 | } 27 | 28 | Timer { 29 | interval: 100 30 | running: true 31 | repeat: true 32 | 33 | onTriggered: { 34 | var array = []; 35 | for (var i = 0; i < slider.count; i++) { 36 | array.push(Math.random() / (0.01 * i * i + 1)); 37 | } 38 | slider.values = array; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Styles.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | 3 | import QtQuick 2.6 4 | import com.github.jcelerier.CreativeControls 1.0 5 | QtObject 6 | { 7 | property bool defaultTheme: true // default = dark, other = light 8 | 9 | property color base: defaultTheme ?"#b4c889" : "#561C49" 10 | property color baseLighter: defaultTheme ?"#b4c889" : "#561C49" 11 | 12 | property color detail: "#3a4407" 13 | property color colorOn: defaultTheme ? "#7b9a4a" : "orange" 14 | property color colorOff: "#7f8287" 15 | property color background: defaultTheme ? "#424041" : "#ffffff" 16 | 17 | property color whiteKeyColor: colorOff 18 | property color blackKeyColor: background 19 | property color whiteKeyDetail: base 20 | property color blackKeyDetail: colorOn 21 | 22 | property color labelColor: "#CCCCCC" 23 | 24 | property real cornerRadius : 0. 25 | 26 | function randomDetailColor() 27 | { 28 | return CppUtils.setHSVHue(detail, Math.random()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/ContainerExample.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.1 3 | import QtQuick.Layouts 1.1 4 | import com.github.jcelerier.CreativeControls 1.0 5 | 6 | Page { 7 | Row { 8 | Container { 9 | height: col.childrenRect.height + 2 * radius 10 | 11 | Column { 12 | id: col 13 | 14 | Repeater { 15 | model :5 16 | 17 | Column { 18 | HSlider { 19 | height: 50 20 | } 21 | Text { 22 | height: 50 23 | text: "coucou" 24 | color: "white" 25 | font.pointSize: 34 26 | } 27 | } 28 | } 29 | } 30 | } 31 | 32 | Container { 33 | VSlider { 34 | anchors.fill: parent 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/cpputils.cpp: -------------------------------------------------------------------------------- 1 | #include "cpputils.hpp" 2 | 3 | namespace CreativeControls 4 | { 5 | CppUtils::CppUtils(QObject* parent) : QObject(parent) 6 | { 7 | } 8 | 9 | double CppUtils::getHSVHue(const QColor col) 10 | { 11 | return col.hsvHueF(); 12 | } 13 | 14 | double CppUtils::getHSVSaturation(const QColor col) 15 | { 16 | return col.hsvSaturationF(); 17 | } 18 | 19 | double CppUtils::getHSVValue(const QColor col) 20 | { 21 | return col.valueF(); 22 | } 23 | 24 | QColor CppUtils::setHSVHue(const QColor col, double h) 25 | { 26 | auto s = col.hsvSaturationF(); 27 | auto v = col.valueF(); 28 | 29 | return QColor::fromHsvF(h, s, v); 30 | } 31 | 32 | QColor CppUtils::setHSVSaturation(const QColor col, const double s) 33 | { 34 | auto h = col.hsvHueF(); 35 | auto v = col.valueF(); 36 | 37 | return QColor::fromHsvF(h, s, v); 38 | } 39 | 40 | QColor CppUtils::setHSVValue(const QColor col, const double v) 41 | { 42 | auto h = col.hsvHueF(); 43 | auto s = col.hsvSaturationF(); 44 | 45 | return QColor::fromHsvF(h, s, v); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Utils.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | 3 | import QtQuick 2.6 4 | 5 | QtObject { 6 | function sliderLogMap() { 7 | return 1. + Math.log(linearMap()) 8 | } 9 | 10 | function distance(x1, y1, x2, y2) { 11 | var a = x1 - x2 12 | var b = y1 - y2 13 | 14 | return Math.sqrt(a * a + b * b) 15 | } 16 | 17 | function clamp(val, min, max) { 18 | return Math.min(Math.max(val, min), max) 19 | } 20 | 21 | // a : source range; b : target range. 22 | // val in [a0; a1] is scaled to [b0; b1] 23 | function rescale(val, a0, a1, b0, b1) { 24 | var coeff = (b1 - b0) / (a1 - a0) 25 | return b0 + coeff * (val - a0) 26 | } 27 | 28 | function clampRescale(val, a0, a1, b0, b1) { 29 | return rescale(clamp(val, a0, a1), a0, a1, b0, b1) 30 | } 31 | 32 | function inside(x, y, areaX, areaY, areaWidth, areaHeight) { 33 | return x > areaX && y > areaY && x < (areaX + areaWidth) 34 | && y < (areaY + areaHeight) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/graph.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace CreativeControls 7 | { 8 | class Graph : public QQuickItem 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) 12 | Q_PROPERTY(QVector values READ values WRITE setValues NOTIFY valuesChanged FINAL) 13 | Q_PROPERTY(bool lines READ lines WRITE setLines NOTIFY linesChanged FINAL) 14 | 15 | public: 16 | Graph(); 17 | 18 | QColor color() const; 19 | QVector values() const; 20 | bool lines() const; 21 | 22 | signals: 23 | void colorChanged(QColor color); 24 | void valuesChanged(QVector values); 25 | void linesChanged(bool lines); 26 | 27 | public slots: 28 | void setColor(const QColor color); 29 | void setValues(QVector values); 30 | void setLines(const bool lines); 31 | 32 | private: 33 | QSGNode* updatePaintNode(QSGNode*, UpdatePaintNodeData*) final override; 34 | 35 | QVector m_values; 36 | QColor m_graphColor{}; 37 | bool m_lines{}; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | moc_predefs.h 4 | *.dylib 5 | *.user 6 | *.qmlc 7 | *~ 8 | *.autosave 9 | *.a 10 | *.core 11 | *.moc 12 | *.o 13 | *.obj 14 | *.orig 15 | *.rej 16 | *.so 17 | *.so.* 18 | *_pch.h.cpp 19 | *_resource.rc 20 | *.qm 21 | .#* 22 | *.*# 23 | core 24 | !core/ 25 | tags 26 | .DS_Store 27 | .directory 28 | *.debug 29 | Makefile* 30 | *.prl 31 | *.app 32 | moc_*.cpp 33 | ui_*.h 34 | qrc_*.cpp 35 | Thumbs.db 36 | *.res 37 | *.rc 38 | /.qmake.cache 39 | /.qmake.stash 40 | 41 | # qtcreator generated files 42 | *.pro.user* 43 | 44 | # xemacs temporary files 45 | *.flc 46 | 47 | # Vim temporary files 48 | .*.swp 49 | 50 | # Visual Studio generated files 51 | *.ib_pdb_index 52 | *.idb 53 | *.ilk 54 | *.pdb 55 | *.sln 56 | *.suo 57 | *.vcproj 58 | *vcproj.*.*.user 59 | *.ncb 60 | *.sdf 61 | *.opensdf 62 | *.vcxproj 63 | *vcxproj.* 64 | 65 | # MinGW generated files 66 | *.Debug 67 | *.Release 68 | 69 | # Python byte code 70 | *.pyc 71 | 72 | # Binaries 73 | # -------- 74 | *.dll 75 | *.exe 76 | 77 | -------------------------------------------------------------------------------- /src/creativecontrolsplugin.cpp: -------------------------------------------------------------------------------- 1 | #include "creativecontrolsplugin.hpp" 2 | 3 | #include "angleslider.hpp" 4 | #include "cpputils.hpp" 5 | #include "graph.hpp" 6 | #include "painted_polygon.hpp" 7 | #include "polygon.hpp" 8 | #include "scope.hpp" 9 | #include "toucharea.hpp" 10 | #include "xytarget.hpp" 11 | 12 | namespace CreativeControls 13 | { 14 | 15 | Plugin::Plugin() 16 | { 17 | } 18 | 19 | void Plugin::registerTypes(const char* uri) 20 | { 21 | qmlRegisterType(uri, 1, 0, "GraphImpl"); 22 | qmlRegisterType(uri, 1, 0, "AngleSliderImpl"); 23 | qmlRegisterType(uri, 1, 0, "ScopeImpl"); 24 | qmlRegisterType(uri, 1, 0, "Polygon"); 25 | qmlRegisterType(uri, 1, 0, "Crosshair"); 26 | qmlRegisterType(uri, 1, 0, "TouchArea"); 27 | 28 | qmlRegisterSingletonType( 29 | uri, 1, 0, "CppUtils", 30 | [](QQmlEngine*, QJSEngine*) -> QObject* { return new CppUtils; }); 31 | } 32 | } 33 | 34 | #if defined(QPM_INIT) 35 | static void creative_controls_init() 36 | { 37 | static CreativeControls::Plugin p; 38 | p.registerTypes("com.github.jcelerier.CreativeControls"); 39 | } 40 | Q_COREAPP_STARTUP_FUNCTION(creative_controls_init) 41 | #endif 42 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/XYPad.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // X-Y pad 6 | Item { 7 | id: xyPad 8 | 9 | width: 200 10 | height: 200 11 | 12 | property alias stickX: xy.centerX 13 | property alias stickY: xy.centerY 14 | 15 | property var styles: DarkStyle 16 | 17 | signal pointChanged(point p) 18 | 19 | Rectangle { 20 | anchors.fill: parent 21 | color: styles.background 22 | } 23 | 24 | Crosshair { 25 | id: xy 26 | anchors.fill: parent 27 | color: touchArea.pressState ? styles.colorOn : styles.colorOff 28 | radiusScale: touchArea.pressState ? 25 : 35 29 | } 30 | 31 | TouchArea { 32 | id: touchArea 33 | anchors.fill: parent 34 | 35 | onPressed: applyPos(point) 36 | onPositionChanged: applyPos(point) 37 | 38 | onDoubleClicked: stickX = stickY = 0.5 39 | 40 | function applyPos(point) { 41 | stickX = Utils.clamp(point.x, 0, xyPad.width) / width 42 | stickY = Utils.clamp(point.y, 0, xyPad.height) / height 43 | xyPad.pointChanged(Qt.point(stickX, stickY)) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /examples/Overview.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.1 3 | import QtQuick.Layouts 1.1 4 | import com.github.jcelerier.CreativeControls 1.0 5 | 6 | Item { 7 | width: 1920 8 | height: 1080 9 | 10 | Rectangle { 11 | x: 0 12 | y: 0 13 | width: 1920 14 | height: 1080 15 | color: "#555" 16 | } 17 | 18 | GridLayout { 19 | x: 0 20 | y: 0 21 | 22 | scale: 1 23 | rows: 4 24 | columns: 8 25 | 26 | AngleSlider { } 27 | ArcSlider { } 28 | ColorChooser { } 29 | ColorSlider { } 30 | ColorWheel { } 31 | CosInfluence { } 32 | DonutSlider { } 33 | Frame { } 34 | 35 | Graph { } 36 | Graph2D { } 37 | HSLSlider { } 38 | HSVSlider { } 39 | Joystick { } 40 | Keyboard { } 41 | Leds { } 42 | 43 | Matrix { } 44 | MultiSlider { } 45 | Random1D { } 46 | Random2D { } 47 | Random3D { } 48 | RangeSlider { } 49 | RGBSlider { } 50 | Scale { } 51 | 52 | Scope { } 53 | Spat { } 54 | Spectrum { } 55 | Step { } 56 | Switch { } 57 | Trajectory { } 58 | XYPad { } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Switch.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A simple toggle switch. 6 | 7 | // Signal: 8 | // * pressed(): signal, on pressed 9 | // * released(): signal, on released 10 | Rectangle { 11 | id: pressSwitch 12 | 13 | width: 50 14 | height: 50 15 | radius: width / 2 16 | 17 | property var styles: DarkStyle 18 | 19 | border.color: styles.borderColor 20 | border.width: width / 10. 21 | 22 | color: (pressSwitch.state == "ON") ? styles.colorOn : styles.colorOff 23 | property bool ease: true 24 | Behavior on color { 25 | enabled: ease 26 | ColorAnimation { 27 | easing.type: Easing.OutQuint 28 | } 29 | } 30 | 31 | signal pressed 32 | signal released 33 | 34 | TouchArea { 35 | anchors.fill: parent 36 | onPressed: { 37 | pressSwitch.pressed() 38 | pressSwitch.state = "ON" 39 | } 40 | onReleased: { 41 | pressSwitch.released() 42 | pressSwitch.state = "OFF" 43 | } 44 | } 45 | state: "OFF" 46 | states: [ 47 | State { 48 | name: "ON" 49 | }, 50 | State { 51 | name: "OFF" 52 | } 53 | ] 54 | } 55 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/qmldir-qpm: -------------------------------------------------------------------------------- 1 | module com.github.jcelerier.CreativeControls 2 | typeinfo plugins.qmltypes 3 | 4 | AngleSlider 1.0 AngleSlider.qml 5 | ArcSlider 1.0 ArcSlider.qml 6 | ColorChooser 1.0 ColorChooser.qml 7 | ColorSlider 1.0 ColorSlider.qml 8 | ColorWheel 1.0 ColorWheel.qml 9 | Container 1.0 Container.qml 10 | CosInfluence 1.0 CosInfluence.qml 11 | DonutSlider 1.0 DonutSlider.qml 12 | Frame 1.0 Frame.qml 13 | Graph 1.0 Graph.qml 14 | Graph2D 1.0 Graph2D.qml 15 | HSlider 1.0 HSlider.qml 16 | HSLSlider 1.0 HSLSlider.qml 17 | HSVSlider 1.0 HSVSlider.qml 18 | Joystick 1.0 Joystick.qml 19 | Keyboard 1.0 Keyboard.qml 20 | Label 1.0 Label.qml 21 | Leds 1.0 Leds.qml 22 | LogSlider 1.0 LogSlider.qml 23 | Matrix 1.0 Matrix.qml 24 | MultiSlider 1.0 MultiSlider.qml 25 | Random1D 1.0 Random1D.qml 26 | Random2D 1.0 Random2D.qml 27 | Random3D 1.0 Random3D.qml 28 | RangeSlider 1.0 RangeSlider.qml 29 | RGBSlider 1.0 RGBSlider.qml 30 | Scale 1.0 Scale.qml 31 | Scope 1.0 Scope.qml 32 | Slider 1.0 Slider.qml 33 | Spat 1.0 Spat.qml 34 | Spectrum 1.0 Spectrum.qml 35 | Step 1.0 Step.qml 36 | Switch 1.0 Switch.qml 37 | ToggleSwitch 1.0 ToggleSwitch.qml 38 | Trajectory 1.0 Trajectory.qml 39 | VSlider 1.0 VSlider.qml 40 | XYPad 1.0 XYPad.qml 41 | 42 | singleton Styles 1.0 Styles.qml 43 | singleton DarkStyle 1.0 DarkStyle.qml 44 | singleton LightStyle 1.0 LightStyle.qml 45 | 46 | singleton Utils 1.0 Utils.qml 47 | designersupported 48 | 49 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/qmldir: -------------------------------------------------------------------------------- 1 | module com.github.jcelerier.CreativeControls 2 | plugin qml-creative-controls 3 | classname CreativeControls::Plugin 4 | typeinfo plugins.qmltypes 5 | 6 | AngleSlider 1.0 AngleSlider.qml 7 | ArcSlider 1.0 ArcSlider.qml 8 | ColorChooser 1.0 ColorChooser.qml 9 | ColorSlider 1.0 ColorSlider.qml 10 | ColorWheel 1.0 ColorWheel.qml 11 | Container 1.0 Container.qml 12 | CosInfluence 1.0 CosInfluence.qml 13 | DonutSlider 1.0 DonutSlider.qml 14 | Frame 1.0 Frame.qml 15 | Graph 1.0 Graph.qml 16 | Graph2D 1.0 Graph2D.qml 17 | HRangeSlider 1.0 HRangeSlider.qml 18 | HSlider 1.0 HSlider.qml 19 | HSLSlider 1.0 HSLSlider.qml 20 | HSVSlider 1.0 HSVSlider.qml 21 | Joystick 1.0 Joystick.qml 22 | Keyboard 1.0 Keyboard.qml 23 | Label 1.0 Label.qml 24 | Leds 1.0 Leds.qml 25 | LogSlider 1.0 LogSlider.qml 26 | Matrix 1.0 Matrix.qml 27 | MultiSlider 1.0 MultiSlider.qml 28 | Random1D 1.0 Random1D.qml 29 | Random2D 1.0 Random2D.qml 30 | Random3D 1.0 Random3D.qml 31 | RGBSlider 1.0 RGBSlider.qml 32 | Scale 1.0 Scale.qml 33 | Scope 1.0 Scope.qml 34 | Slider 1.0 Slider.qml 35 | Spat 1.0 Spat.qml 36 | Spectrum 1.0 Spectrum.qml 37 | Step 1.0 Step.qml 38 | Switch 1.0 Switch.qml 39 | ToggleSwitch 1.0 ToggleSwitch.qml 40 | Trajectory 1.0 Trajectory.qml 41 | VRangeSlider 1.0 VRangeSlider.qml 42 | VSlider 1.0 VSlider.qml 43 | XYPad 1.0 XYPad.qml 44 | 45 | singleton Styles 1.0 Styles.qml 46 | singleton DarkStyle 1.0 DarkStyle.qml 47 | singleton LightStyle 1.0 LightStyle.qml 48 | 49 | singleton Utils 1.0 Utils.qml 50 | designersupported 51 | 52 | -------------------------------------------------------------------------------- /src/polygon.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace CreativeControls 5 | { 6 | class Polygon : public QQuickItem 7 | { 8 | Q_OBJECT 9 | Q_PROPERTY(int sides READ sides WRITE setSides NOTIFY sidesChanged FINAL) 10 | Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged FINAL) 11 | Q_PROPERTY(qreal borderWidth READ borderWidth WRITE setBorderWidth NOTIFY borderWidthChanged FINAL) 12 | Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged FINAL) 13 | Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged FINAL) 14 | 15 | public: 16 | Polygon(); 17 | 18 | int sides() const; 19 | QColor borderColor() const; 20 | QColor fillColor() const; 21 | qreal borderWidth() const; 22 | qreal rotation() const; 23 | 24 | public slots: 25 | void setSides(const int sides); 26 | void setBorderColor(const QColor borderColor); 27 | void setFillColor(const QColor fillColor); 28 | void setBorderWidth(const qreal borderWidth); 29 | void setRotation(const qreal rotation); 30 | 31 | signals: 32 | void sidesChanged(int sides); 33 | void borderColorChanged(QColor borderColor); 34 | void fillColorChanged(QColor fillColor); 35 | void borderWidthChanged(qreal borderWidth); 36 | void rotationChanged(qreal rotation); 37 | 38 | private: 39 | QSGNode* updatePaintNode(QSGNode*, UpdatePaintNodeData*) final override; 40 | 41 | int m_sides = 64; 42 | QColor m_borderColor = Qt::red; 43 | QColor m_color = Qt::white; 44 | qreal m_borderWidth = 4; 45 | qreal m_rotation = 0; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /src/painted_polygon.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace CreativeControls 5 | { 6 | class PaintedPolygon : public QQuickPaintedItem 7 | { 8 | Q_OBJECT 9 | Q_PROPERTY(int sides READ sides WRITE setSides NOTIFY sidesChanged FINAL) 10 | Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged FINAL) 11 | Q_PROPERTY(qreal borderWidth READ borderWidth WRITE setBorderWidth NOTIFY borderWidthChanged FINAL) 12 | Q_PROPERTY(QColor borderColor READ borderColor WRITE setBorderColor NOTIFY borderColorChanged FINAL) 13 | Q_PROPERTY(QColor fillColor READ fillColor WRITE setFillColor NOTIFY fillColorChanged FINAL) 14 | 15 | public: 16 | PaintedPolygon(); 17 | 18 | int sides() const; 19 | QColor borderColor() const; 20 | QColor fillColor() const; 21 | qreal borderWidth() const; 22 | qreal rotation() const; 23 | 24 | public slots: 25 | void setSides(const int sides); 26 | void setBorderColor(const QColor borderColor); 27 | void setFillColor(const QColor fillColor); 28 | void setBorderWidth(const qreal borderWidth); 29 | void setRotation(const qreal rotation); 30 | 31 | signals: 32 | void sidesChanged(int sides); 33 | void borderColorChanged(QColor borderColor); 34 | void fillColorChanged(QColor fillColor); 35 | void borderWidthChanged(qreal borderWidth); 36 | void rotationChanged(qreal rotation); 37 | 38 | private: 39 | void paint(QPainter* painter) final override; 40 | 41 | int m_sides = 64; 42 | QColor m_borderColor = Qt::red; 43 | QColor m_color = Qt::white; 44 | qreal m_borderWidth = 4; 45 | qreal m_rotation = 0; 46 | }; 47 | } 48 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Container.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | Rectangle { 5 | id: container 6 | 7 | width: 150 8 | height: 150 9 | radius: 10 10 | 11 | property var styles: DarkStyle 12 | 13 | color: styles.background 14 | border { 15 | color: styles.base 16 | width: styles.containerCornerRadius 17 | } 18 | 19 | default property alias main: content.data 20 | 21 | Item { 22 | id: content 23 | anchors { 24 | top: container.top 25 | topMargin: container.radius 26 | leftMargin: container.radius 27 | horizontalCenter: container.horizontalCenter 28 | } 29 | width: container.width - 2 * container.radius 30 | height: title == "" 31 | ? container.height - 2. * container.radius 32 | : container.height - 2. * container.radius - (titleLabel.height + titleBottomMargin) 33 | } 34 | 35 | Component.onCompleted: main.parent = content 36 | 37 | property alias title: titleLabel.text 38 | property real titleBottomMargin: titleLabel.height * 0.3 39 | 40 | Text { 41 | id: titleLabel 42 | text: "" 43 | 44 | anchors { 45 | top: content.bottom 46 | topMargin: container.titleBottomMargin 47 | horizontalCenter: container.horizontalCenter 48 | } 49 | width: container.width 50 | verticalAlignment: Text.AlignVCenter 51 | horizontalAlignment: Text.AlignHCenter 52 | 53 | font { 54 | bold: true 55 | capitalization: Font.AllUppercase 56 | } 57 | color: styles.base 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/angleslider.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace CreativeControls 5 | { 6 | class AngleSlider : public QQuickPaintedItem 7 | { 8 | Q_OBJECT 9 | Q_PROPERTY(qreal angle READ angle WRITE setAngle NOTIFY angleChanged FINAL) 10 | Q_PROPERTY(qreal min READ min WRITE setMin FINAL) 11 | Q_PROPERTY(qreal max READ max WRITE setMax FINAL) 12 | Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor NOTIFY baseColorChanged FINAL) 13 | Q_PROPERTY(QColor detailColor READ detailColor WRITE setDetailColor NOTIFY detailColorChanged FINAL) 14 | 15 | public: 16 | AngleSlider(); 17 | 18 | qreal angle() const; 19 | qreal min() const; 20 | qreal max() const; 21 | QColor baseColor() const; 22 | QColor detailColor() const; 23 | 24 | public slots: 25 | void setAngle(const qreal angle); 26 | void setMin(const qreal angle); 27 | void setMax(const qreal angle); 28 | void setBaseColor(const QColor baseColor); 29 | void setDetailColor(const QColor detailColor); 30 | 31 | signals: 32 | void angleChanged(qreal angle); 33 | void baseColorChanged(QColor baseColor); 34 | void detailColorChanged(QColor detailColor); 35 | 36 | private: 37 | void paint(QPainter* painter) final override; 38 | void mousePressEvent(QMouseEvent* event) final override; 39 | void mouseDoubleClickEvent(QMouseEvent* event) final override; 40 | void mouseMoveEvent(QMouseEvent* event) final override; 41 | void mouseReleaseEvent(QMouseEvent* event) final override; 42 | void touchEvent(QTouchEvent*) final override; 43 | 44 | void updateAngle(QPointF point); 45 | 46 | qreal m_angle{}; 47 | qreal m_min{-180}; 48 | qreal m_max{180}; 49 | QColor m_baseColor{Qt::blue}; 50 | QColor m_detailColor{Qt::black}; 51 | }; 52 | } 53 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/DarkStyle.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | 3 | import QtQuick 2.6 4 | import com.github.jcelerier.CreativeControls 1.0 5 | 6 | QtObject { 7 | property color base: "#b4c889" 8 | property color baseLighter: "#bec889" 9 | property color detail: "#3a4407" 10 | property color borderColor: "#666666" 11 | property color background: "#424041" 12 | 13 | // container properties 14 | property real containerCornerRadius: 3 15 | 16 | // slider colors 17 | property color sliderBackgroundColor: background 18 | property color handleColor: colorOn 19 | property color pressedHandleColor: colorOnLighter 20 | 21 | // range slider colors 22 | property color handlesColor: detail 23 | property color pressedHandlesColor: borderColor 24 | property color handlesValueColor: colorOnLighter 25 | 26 | // switch, leds, matrix color 27 | property color colorOn: "#7b9a4a" 28 | property color colorOff: "#7f8287" 29 | property color colorOnLighter: "#93a54d" 30 | property color colorOffDarker: "#4c4e51" 31 | 32 | // step properties 33 | property real stepRectCornerRadius: 8 34 | 35 | // CosInfluence text color 36 | property color textPressedColor: base 37 | 38 | // keyboard colors 39 | property color keyBorder: detail 40 | property color whiteKeyColor: colorOff 41 | property color blackKeyColor: background 42 | property color whiteKeyDetail: base 43 | property color blackKeyDetail: colorOn 44 | 45 | // label text color (e.g. sliders) 46 | property color labelColor: "#cccfbf" 47 | 48 | property real cornerRadius: 0. 49 | 50 | function randomDetailColor() { 51 | return CppUtils.setHSVHue(colorOn, Math.random()) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/LightStyle.qml: -------------------------------------------------------------------------------- 1 | pragma Singleton 2 | 3 | import QtQuick 2.6 4 | import com.github.jcelerier.CreativeControls 1.0 5 | 6 | QtObject { 7 | property color base: "#561C49" 8 | property color baseLighter: "#561C49" 9 | property color detail: "#3d1233" 10 | property color borderColor: "#6d3160" 11 | property color background: "#ffffff" 12 | 13 | // container properties 14 | property real containerCornerRadius: 3 15 | 16 | // slider colors 17 | property color sliderBackgroundColor: background 18 | property color handleColor: colorOn 19 | property color pressedHandleColor: colorOnLighter 20 | 21 | // range slider colors 22 | property color handlesColor: borderColor 23 | property color pressedHandlesColor: detail 24 | property color handlesValueColor: colorOnLighter 25 | 26 | // switch, leds, matrix color 27 | property color colorOn: "orange" 28 | property color colorOff: "#8c5580" 29 | property color colorOnLighter: "#ffb20c" 30 | property color colorOffDarker: "#230a1d" 31 | 32 | // step properties 33 | property real stepRectCornerRadius: 5 34 | 35 | // keyboard colors 36 | property color keyBorder: detail 37 | property color whiteKeyColor: background 38 | property color blackKeyColor: detail 39 | property color whiteKeyDetail: colorOn 40 | property color blackKeyDetail: colorOn 41 | 42 | // CosInfluence text color 43 | property color textPressedColor: colorOnLighter 44 | 45 | // label text color (e.g. sliders) 46 | property color labelColor: "#561C49" 47 | 48 | property real cornerRadius: 0. 49 | 50 | function randomDetailColor() { 51 | return CppUtils.setHSVHue(borderColor, Math.random()) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/toucharea.cpp: -------------------------------------------------------------------------------- 1 | #include "toucharea.hpp" 2 | 3 | namespace CreativeControls 4 | { 5 | 6 | TouchArea::TouchArea() 7 | { 8 | this->setAcceptedMouseButtons(Qt::LeftButton); 9 | } 10 | 11 | bool TouchArea::pressState() const 12 | { 13 | return m_pressState; 14 | } 15 | 16 | void TouchArea::setPressState(const bool pressState) 17 | { 18 | if (m_pressState == pressState) 19 | return; 20 | 21 | m_pressState = pressState; 22 | emit pressStateChanged(m_pressState); 23 | } 24 | 25 | void TouchArea::mousePressEvent(QMouseEvent* event) 26 | { 27 | emit pressed(event->localPos()); 28 | setPressState(true); 29 | event->accept(); 30 | } 31 | 32 | void TouchArea::mouseMoveEvent(QMouseEvent* event) 33 | { 34 | emit positionChanged(event->localPos()); 35 | event->accept(); 36 | } 37 | 38 | void TouchArea::mouseReleaseEvent(QMouseEvent* event) 39 | { 40 | emit released(event->localPos()); 41 | setPressState(false); 42 | event->accept(); 43 | } 44 | 45 | void TouchArea::mouseDoubleClickEvent(QMouseEvent* event) 46 | { 47 | emit doubleClicked(event->localPos()); 48 | event->accept(); 49 | } 50 | 51 | void TouchArea::touchEvent(QTouchEvent* event) 52 | { 53 | setPressState(event->touchPoints().size() > 0); 54 | if (m_pressState) 55 | { 56 | const auto& touchpoint = *event->touchPoints().begin(); 57 | switch (touchpoint.state()) 58 | { 59 | case Qt::TouchPointPressed: 60 | emit pressed(touchpoint.pos()); 61 | break; 62 | case Qt::TouchPointMoved: 63 | emit positionChanged(touchpoint.pos()); 64 | break; 65 | case Qt::TouchPointStationary: 66 | break; 67 | case Qt::TouchPointReleased: 68 | emit released(touchpoint.pos()); 69 | break; 70 | default: 71 | break; 72 | } 73 | } 74 | event->accept(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/scope.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace CreativeControls 6 | { 7 | class Scope : public QQuickPaintedItem 8 | { 9 | Q_OBJECT 10 | Q_PROPERTY(QVector points READ points WRITE setPoints NOTIFY pointsChanged FINAL) 11 | Q_PROPERTY(qreal yMin READ yMin WRITE setYMin NOTIFY yMinChanged FINAL) 12 | Q_PROPERTY(qreal yMax READ yMax WRITE setYMax NOTIFY yMaxChanged FINAL) 13 | Q_PROPERTY(QColor baseColor READ baseColor WRITE setBaseColor NOTIFY baseColorChanged FINAL) 14 | Q_PROPERTY(QColor detailColor READ detailColor WRITE setDetailColor NOTIFY detailColorChanged FINAL) 15 | Q_PROPERTY(bool symmetrize READ symmetrize WRITE setSymmetrize NOTIFY symmetrizeChanged FINAL) 16 | 17 | public: 18 | Scope(); 19 | 20 | QVector points() const; 21 | qreal yMin() const; 22 | qreal yMax() const; 23 | QColor baseColor() const; 24 | QColor detailColor() const; 25 | bool symmetrize() const; 26 | 27 | public slots: 28 | void setPoints(QVector points); 29 | void setYMin(const qreal yMin); 30 | void setYMax(const qreal yMax); 31 | void setBaseColor(const QColor baseColor); 32 | void setDetailColor(const QColor detailColor); 33 | void setSymmetrize(const bool symmetrize); 34 | 35 | signals: 36 | void pointsChanged(QVector points); 37 | void yMinChanged(qreal yMin); 38 | void yMaxChanged(qreal yMax); 39 | void baseColorChanged(QColor baseColor); 40 | void detailColorChanged(QColor detailColor); 41 | void symmetrizeChanged(bool symmetrize); 42 | 43 | private: 44 | void paint(QPainter* painter) final override; 45 | void updatePath(); 46 | 47 | QVector m_points; 48 | QVector m_data; 49 | qreal m_yMin{-1}; 50 | qreal m_yMax{1}; 51 | QColor m_baseColor; 52 | QColor m_detailColor; 53 | QPen m_scopePen; 54 | QBrush m_scopeBrush; 55 | bool m_symmetrize{true}; 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/ToggleSwitch.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A simple toggle switch. 6 | 7 | // Signal: 8 | // * toggle(): signal, on toggled 9 | // Function: 10 | // * switchState(): changes the switch state (on or off) 11 | Rectangle { 12 | id: toggleSwitch 13 | 14 | width: 100 15 | height: 50 16 | radius: height 17 | 18 | property var styles: DarkStyle 19 | 20 | border.color: styles.borderColor 21 | border.width: width / 20 22 | 23 | color: (toggleSwitch.state == "ON") ? styles.colorOn : styles.colorOff 24 | property bool ease: true 25 | Behavior on color { 26 | enabled: ease 27 | ColorAnimation { 28 | easing.type: Easing.InOutQuint 29 | } 30 | } 31 | 32 | signal toggle(bool onoff) 33 | function switchState() { 34 | toggleSwitch.state = (toggleSwitch.state == "ON") ? "OFF" : "ON" 35 | } 36 | 37 | Rectangle { 38 | id: toggleHandle 39 | 40 | height: toggleSwitch.height - toggleSwitch.border.width * 2 41 | 42 | width: height 43 | radius: width / 2 44 | color: styles.borderColor 45 | 46 | x: (toggleSwitch.state == "ON") 47 | ? toggleSwitch.width - toggleHandle.width - toggleSwitch.border.width 48 | : toggleSwitch.border.width 49 | anchors.verticalCenter: parent.verticalCenter 50 | Behavior on x { 51 | enabled: toggleSwitch.ease 52 | NumberAnimation { 53 | easing.type: Easing.InOutQuint 54 | } 55 | } 56 | } 57 | 58 | TouchArea { 59 | anchors.fill: parent 60 | onPressed: { 61 | toggleSwitch.switchState() 62 | toggle(toggleSwitch.state == "ON") 63 | } 64 | } 65 | 66 | state: "OFF" 67 | states: [ 68 | State { 69 | name: "ON" 70 | }, 71 | State { 72 | name: "OFF" 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /src/xytarget.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace CreativeControls 7 | { 8 | class XYTarget : public QQuickPaintedItem 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(qreal centerX READ centerX WRITE setCenterX NOTIFY centerXChanged FINAL) 12 | Q_PROPERTY(qreal centerY READ centerY WRITE setCenterY NOTIFY centerYChanged FINAL) 13 | Q_PROPERTY(qreal radiusScale READ radiusScale WRITE setRadiusScale NOTIFY radiusScaleChanged FINAL) 14 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged FINAL) 15 | Q_PROPERTY(bool pressed READ pressed WRITE setPressed NOTIFY pressedChanged FINAL) 16 | 17 | public: 18 | XYTarget(); 19 | 20 | qreal centerX() const; 21 | qreal centerY() const; 22 | qreal radiusScale() const; 23 | QColor color() const; 24 | bool pressed() const; 25 | 26 | public slots: 27 | void setCenterX(const qreal centerX); 28 | void setCenterY(const qreal centerY); 29 | void setRadiusScale(const qreal radiusScale); 30 | void setColor(const QColor color); 31 | void setPressed(const bool pressed); 32 | 33 | signals: 34 | void centerXChanged(qreal centerX); 35 | void centerYChanged(qreal centerY); 36 | void radiusScaleChanged(qreal radiusScale); 37 | void colorChanged(QColor color); 38 | void pressedChanged(bool pressed); 39 | 40 | private: 41 | void paint(QPainter* painter) final override; 42 | void mousePressEvent(QMouseEvent* event) final override; 43 | void mouseDoubleClickEvent(QMouseEvent* event) final override; 44 | void mouseMoveEvent(QMouseEvent* event) final override; 45 | void mouseReleaseEvent(QMouseEvent* event) final override; 46 | void touchEvent(QTouchEvent* event) final override; 47 | bool contains(const QPointF &point) const final override; 48 | 49 | void updatePenWidth(); 50 | 51 | qreal m_centerX{0.5}; 52 | qreal m_centerY{0.5}; 53 | qreal m_width{}; 54 | qreal m_radius{35.}; 55 | qreal m_radiusScale{35.}; 56 | 57 | QColor m_color{}; 58 | QPen m_pen; 59 | QBrush m_brush; 60 | QPointF m_lastPos{}; 61 | 62 | bool m_pressed{}; 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Spat.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | // Controls spatialization 4 | Item { 5 | id: spat 6 | 7 | property int sources: 8 8 | property real dim: Math.min(height, width) 9 | 10 | property real radSmall: dim / 2 - 0.05 * dim 11 | 12 | Rectangle { 13 | x: 0.05 * dim 14 | y: 0.05 * dim 15 | width: dim - 0.1 * dim 16 | height: dim - 0.1 * dim 17 | radius: dim 18 | border { 19 | width: 1 20 | color: "black" 21 | } 22 | } 23 | 24 | Rectangle { 25 | width: 2 26 | border { 27 | width: 2 28 | color: "black" 29 | } 30 | height: dim 31 | x: dim / 2 32 | y: 0 33 | color: "black" 34 | } 35 | 36 | Rectangle { 37 | height: 2 38 | border { 39 | width: 2 40 | color: "black" 41 | } 42 | width: dim 43 | x: 0 44 | y: dim / 2 45 | color: "black" 46 | } 47 | 48 | Repeater { 49 | model: sources 50 | Rectangle { 51 | id: src 52 | 53 | x: radSmall + radSmall * Math.cos(2 * Math.PI * index / sources) 54 | y: radSmall + radSmall * Math.sin(2 * Math.PI * index / sources) 55 | 56 | width: 0.1 * dim 57 | height: width 58 | radius: width 59 | color: "red" 60 | Rectangle { 61 | anchors.centerIn: src 62 | id: sub 63 | width: 0.08 * dim 64 | height: width 65 | radius: width 66 | color: "blue" 67 | } 68 | } 69 | } 70 | 71 | Rectangle { 72 | id: interactor 73 | width: 0.15 * dim 74 | x: dim / 2 - width / 2 75 | y: dim / 2 - width / 2 76 | height: width 77 | radius: width 78 | color: "green" 79 | MouseArea { 80 | drag.target: parent 81 | anchors.fill: parent 82 | drag.minimumX: 0 83 | drag.maximumX: dim - width 84 | drag.minimumY: 0 85 | drag.maximumY: dim - height 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Matrix.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A matrix of buttons. Buttons can be toggles or triggers. 6 | Grid { 7 | id: grid 8 | 9 | width: 200 10 | height: 200 11 | 12 | columns: 3 13 | rows: 3 14 | spacing: 5 15 | padding: 2.5 16 | horizontalItemAlignment: Grid.AlignHCenter 17 | verticalItemAlignment: Grid.AlignVCenter 18 | 19 | property real radius: styles.cornerRadius 20 | 21 | property bool togglable: false 22 | property var pressed: [] 23 | property var styles: DarkStyle 24 | onStylesChanged: { 25 | for (var k = 0; k < repeater.count; k++) { 26 | var item = repeater.itemAt(k) 27 | if (item !== null) { 28 | item.color = item.toggled ? styles.colorOn : styles.colorOff 29 | } 30 | } 31 | } 32 | 33 | Repeater { 34 | id: repeater 35 | model: parent.columns * parent.rows 36 | 37 | anchors.fill: parent 38 | delegate: Rectangle { 39 | 40 | id: rect 41 | 42 | width: grid.width / grid.columns - 5 43 | height: grid.height / grid.rows - 5 44 | radius: grid.radius 45 | 46 | color: styles.colorOff 47 | border.width: 3 48 | border.color: styles.colorOnLighter 49 | 50 | property bool toggled: false 51 | 52 | onToggledChanged: { 53 | if (toggled) 54 | rect.color = styles.colorOn 55 | else 56 | rect.color = styles.colorOff 57 | } 58 | 59 | MouseArea { 60 | anchors.fill: parent 61 | 62 | onPressed: { 63 | if (togglable) 64 | toggled = !toggled 65 | else 66 | toggled = true 67 | grid.pressed = [index] 68 | } 69 | onReleased: { 70 | if (togglable) 71 | ; 72 | else 73 | toggled = false 74 | grid.pressed = [] 75 | } 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/painted_polygon.cpp: -------------------------------------------------------------------------------- 1 | #include "painted_polygon.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace CreativeControls 9 | { 10 | PaintedPolygon::PaintedPolygon() 11 | { 12 | setFlag(ItemHasContents, true); 13 | setAntialiasing(true); 14 | } 15 | 16 | int PaintedPolygon::sides() const 17 | { 18 | return m_sides; 19 | } 20 | 21 | QColor PaintedPolygon::borderColor() const 22 | { 23 | return m_borderColor; 24 | } 25 | 26 | QColor PaintedPolygon::fillColor() const 27 | { 28 | return m_color; 29 | } 30 | 31 | qreal PaintedPolygon::borderWidth() const 32 | { 33 | return m_borderWidth; 34 | } 35 | 36 | qreal PaintedPolygon::rotation() const 37 | { 38 | return m_rotation; 39 | } 40 | 41 | void PaintedPolygon::setSides(const int sides) 42 | { 43 | if (m_sides == sides) 44 | return; 45 | 46 | m_sides = sides; 47 | emit sidesChanged(m_sides); 48 | update(); 49 | } 50 | 51 | void PaintedPolygon::setBorderColor(const QColor borderColor) 52 | { 53 | if (m_borderColor == borderColor) 54 | return; 55 | 56 | m_borderColor = borderColor; 57 | emit borderColorChanged(m_borderColor); 58 | update(); 59 | } 60 | 61 | void PaintedPolygon::setFillColor(const QColor color) 62 | { 63 | if (m_color == color) 64 | return; 65 | 66 | m_color = color; 67 | emit fillColorChanged(m_color); 68 | update(); 69 | } 70 | 71 | void PaintedPolygon::setBorderWidth(const qreal borderWidth) 72 | { 73 | if (qFuzzyCompare(m_borderWidth, borderWidth)) 74 | return; 75 | 76 | m_borderWidth = borderWidth; 77 | emit borderWidthChanged(m_borderWidth); 78 | update(); 79 | } 80 | 81 | void PaintedPolygon::setRotation(const qreal rotation) 82 | { 83 | if (qFuzzyCompare(m_rotation, rotation)) 84 | return; 85 | 86 | m_rotation = rotation; 87 | emit rotationChanged(m_rotation); 88 | update(); 89 | } 90 | 91 | void PaintedPolygon::paint(QPainter* painter) 92 | { 93 | const auto bounds = boundingRect(); 94 | const auto w = bounds.width() - 4.; 95 | const auto h = bounds.height() - 4.; 96 | const auto half_w = w / 2.; 97 | const auto half_h = h / 2.; 98 | const auto theta = 2. * M_PI / m_sides; 99 | 100 | QPolygonF poly; 101 | poly.reserve(m_sides); 102 | // The user gives the rotation in degrees, we convert to radians for sin / 103 | // cos. 104 | const auto rotation = 2. * M_PI * m_rotation / 360.; 105 | for (int i = 0; i < m_sides; ++i) 106 | { 107 | const auto x 108 | = 2. + bounds.x() + half_w + std::cos(i * theta + rotation) * half_w; 109 | const auto y 110 | = 2. + bounds.y() + half_h + std::sin(i * theta + rotation) * half_h; 111 | 112 | poly.push_back(QPointF{x, y}); 113 | } 114 | 115 | painter->setPen(m_borderColor); 116 | painter->setBrush(m_color); 117 | painter->drawConvexPolygon(poly); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: WebKit 2 | AccessModifierOffset: -2 3 | AlignAfterOpenBracket: AlwaysBreak 4 | AlignEscapedNewlinesLeft: true 5 | AlignOperands: true 6 | AlignTrailingComments: true 7 | AlignConsecutiveDeclarations: false 8 | AllowAllParametersOfDeclarationOnNextLine: true 9 | AllowShortBlocksOnASingleLine: false 10 | AllowShortCaseLabelsOnASingleLine: false 11 | AllowShortFunctionsOnASingleLine: None 12 | AllowShortIfStatementsOnASingleLine: false 13 | AllowShortLoopsOnASingleLine: false 14 | AlwaysBreakAfterDefinitionReturnType: false 15 | AlwaysBreakBeforeMultilineStrings: true 16 | AlwaysBreakTemplateDeclarations: true 17 | 18 | BraceWrapping: 19 | AfterClass: true 20 | AfterControlStatement: true 21 | AfterEnum: true 22 | AfterFunction: true 23 | AfterNamespace: true 24 | AfterStruct: true 25 | AfterUnion: true 26 | BeforeCatch: true 27 | BeforeElse: true 28 | IndentBraces: false 29 | 30 | BinPackArguments: true 31 | BinPackParameters: true 32 | BreakBeforeBinaryOperators: All 33 | BreakBeforeBraces: Allman 34 | BreakBeforeTernaryOperators: true 35 | BreakConstructorInitializersBeforeComma: true 36 | ColumnLimit: 79 37 | CommentPragmas: '^ IWYU pragma:' 38 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 39 | ConstructorInitializerIndentWidth: 4 40 | ContinuationIndentWidth: 4 41 | Cpp11BracedListStyle: true 42 | DerivePointerAlignment: false 43 | IndentCaseLabels: true 44 | IndentWidth: 2 45 | IndentWrappedFunctionNames: false 46 | KeepEmptyLinesAtTheStartOfBlocks: true 47 | Language: Cpp 48 | MaxEmptyLinesToKeep: 1 49 | NamespaceIndentation: None 50 | PenaltyBreakBeforeFirstCallParameter: 19 51 | PenaltyBreakComment: 300 52 | PenaltyBreakFirstLessLess: 120 53 | PenaltyBreakString: 1000 54 | PenaltyExcessCharacter: 1000000 55 | PenaltyReturnTypeOnItsOwnLine: 60 56 | PointerAlignment: Left 57 | SpaceAfterCStyleCast: false 58 | SpaceBeforeAssignmentOperators: true 59 | SpaceBeforeParens: ControlStatements 60 | SpaceInEmptyParentheses: false 61 | SpacesBeforeTrailingComments: 1 62 | SpacesInAngles: false 63 | SpacesInCStyleCastParentheses: false 64 | SpacesInContainerLiterals: true 65 | SpacesInParentheses: false 66 | SpacesInSquareBrackets: false 67 | Standard: Cpp11 68 | TabWidth: 2 69 | UseTab: Never 70 | 71 | SortIncludes: true 72 | IncludeBlocks: Regroup 73 | IncludeCategories: 74 | - Regex: '^"' 75 | Priority: 1 76 | - Regex: '^<(Scenario|Explorer|Protocols|Process|State|Device|Media|Midi|JS|Curve|Inspector|Automation|Dataflow|Fx|Library|Mapping|Loop|Recording|PluginSettings)' 77 | Priority: 2 78 | - Regex: '^' 93 | Priority: 9 94 | - Regex: '<[[:alnum:]]+>' 95 | Priority: 800 96 | 97 | -------------------------------------------------------------------------------- /src/graph.cpp: -------------------------------------------------------------------------------- 1 | #include "graph.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace CreativeControls 9 | { 10 | Graph::Graph() 11 | { 12 | setFlag(ItemHasContents, true); 13 | setAntialiasing(true); 14 | } 15 | 16 | QColor Graph::color() const 17 | { 18 | return m_graphColor; 19 | } 20 | 21 | QVector Graph::values() const 22 | { 23 | return m_values; 24 | } 25 | 26 | bool Graph::lines() const 27 | { 28 | return m_lines; 29 | } 30 | 31 | void Graph::setColor(const QColor main) 32 | { 33 | if (m_graphColor == main) 34 | return; 35 | 36 | m_graphColor = main; 37 | emit colorChanged(m_graphColor); 38 | update(); 39 | } 40 | 41 | /*! 42 | * \brief Move given values to inner member. 43 | * \note \c values could be empty after executing of this method. 44 | * \param values vector of values that should be moved. 45 | */ 46 | void Graph::setValues(QVector values) 47 | { 48 | if (m_values == values) 49 | return; 50 | 51 | m_values = std::move(values); 52 | emit valuesChanged(m_values); 53 | update(); 54 | } 55 | 56 | void Graph::setLines(const bool lines) 57 | { 58 | if (m_lines == lines) 59 | return; 60 | 61 | m_lines = lines; 62 | emit linesChanged(m_lines); 63 | update(); 64 | } 65 | 66 | QSGNode* 67 | Graph::updatePaintNode(QSGNode* oldNode, QQuickItem::UpdatePaintNodeData*) 68 | { 69 | QSGGeometryNode* dotsNode{}; 70 | QSGGeometry* dotsGeometry{}; 71 | 72 | const auto n_pts = m_values.size(); 73 | if (n_pts == 0) 74 | { 75 | if (dotsNode) 76 | delete dotsNode; 77 | return nullptr; 78 | } 79 | 80 | if (!oldNode) 81 | { 82 | dotsNode = new QSGGeometryNode; 83 | dotsGeometry 84 | = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), n_pts); 85 | 86 | dotsGeometry->setLineWidth(2); 87 | dotsGeometry->setDrawingMode( 88 | m_lines ? QSGGeometry::DrawLineStrip : QSGGeometry::DrawPoints); 89 | 90 | dotsNode->setGeometry(dotsGeometry); 91 | dotsNode->setFlag(QSGNode::OwnsGeometry); 92 | 93 | auto border = new QSGFlatColorMaterial; 94 | border->setColor(m_graphColor); 95 | dotsNode->setMaterial(border); 96 | 97 | dotsNode->setFlag(QSGNode::OwnsMaterial); 98 | } 99 | else 100 | { 101 | dotsNode = static_cast(oldNode); 102 | dotsGeometry = dotsNode->geometry(); 103 | 104 | dotsGeometry->allocate(n_pts); 105 | dotsGeometry->setDrawingMode( 106 | m_lines ? QSGGeometry::DrawLineStrip : QSGGeometry::DrawPoints); 107 | 108 | auto border = static_cast(dotsNode->material()); 109 | border->setColor(m_graphColor); 110 | } 111 | 112 | const auto w = width(); 113 | const auto h = height(); 114 | 115 | auto dotsVertices = dotsGeometry->vertexDataAsPoint2D(); 116 | 117 | for (int i = 0; i < n_pts; ++i) 118 | { 119 | const auto x = qBound(0., w - 2 * (n_pts - i), w); 120 | const auto y = qBound(0., h - h * m_values[i], h); 121 | dotsVertices[i].set(x, y); 122 | } 123 | 124 | dotsNode->markDirty(QSGNode::DirtyGeometry); 125 | 126 | return dotsNode; 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Step.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A matrix of buttons. Buttons can be toggles or triggers. 6 | Item { 7 | id: root 8 | width: 800 9 | height: 200 10 | 11 | property int currentStep: 0 12 | property int maxStep: 15 13 | property int numValues: 4 14 | 15 | property var steps: [] 16 | property var styles: DarkStyle 17 | 18 | onMaxStepChanged: initSteps() 19 | onNumValuesChanged: initSteps() 20 | Component.onCompleted: initSteps() 21 | 22 | function nextStep() { 23 | currentStep = (currentStep + 1) % maxStep 24 | } 25 | 26 | function initSteps() { 27 | steps.length = maxStep 28 | for (var i = 0; i < maxStep; i++) { 29 | var arr = [] 30 | arr.length = numValues 31 | for (var j = 0; j < numValues; j++) { 32 | arr[j] = rects.itemAt(i * j).toggled 33 | } 34 | steps[i] = arr 35 | } 36 | } 37 | function getStep(step) { 38 | var arr = [] 39 | for (var i = 0; i < numValues; i++) { 40 | if (rects.itemAt(i * maxStep + step).toggled) { 41 | arr.push(numValues - i - 1) 42 | } 43 | } 44 | return arr 45 | } 46 | 47 | // an array with the 0-valued steps that were triggered 48 | signal step(var values) 49 | onCurrentStepChanged: { 50 | step(getStep(currentStep)) 51 | } 52 | 53 | Grid { 54 | id: grid 55 | anchors.fill: parent 56 | columns: maxStep 57 | rows: numValues 58 | spacing: 3 59 | padding: 1.5 60 | horizontalItemAlignment: Grid.AlignHCenter 61 | verticalItemAlignment: Grid.AlignVCenter 62 | 63 | property real contentWidth: (width - padding * 2 - spacing * columns) 64 | property real contentHeight: (height - padding * 2 - spacing * rows) 65 | 66 | Repeater { 67 | id: rects 68 | model: parent.columns * parent.rows 69 | 70 | anchors.centerIn: parent 71 | delegate: Rectangle { 72 | id: rect 73 | property bool toggled: false 74 | 75 | property int step: computeStep() 76 | function computeStep() { 77 | var idx = index 78 | var quo = Math.floor(idx / maxStep) 79 | var rem = idx - quo * maxStep 80 | return rem 81 | } 82 | 83 | width: grid.contentWidth / maxStep 84 | height: grid.contentHeight / numValues 85 | radius: styles.stepRectCornerRadius 86 | 87 | color: !toggled ? styles.colorOffDarker : step == currentStep 88 | ? styles.colorOn : styles.colorOnLighter 89 | border.width: 3 90 | border.color: step == currentStep ? styles.colorOnLighter : styles.colorOff 91 | 92 | MouseArea { 93 | anchors.fill: parent 94 | onPressed: toggled = !toggled 95 | } 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /examples/OssiaServerExample.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.0 3 | import QtQuick.Layouts 1.1 4 | import com.github.jcelerier.CreativeControls 1.0 5 | import Ossia 1.0 as Ossia 6 | 7 | /** 8 | * This file presents an example of usage of the controls 9 | * provided by this library, with libossia. 10 | * libossia is a library that provides multiple network and message 11 | * protocols useful for creative coding: MIDI, OSC, OSCQuery, etc. 12 | * 13 | * More information is available on : 14 | * https://github.com/OSSIA/libossia 15 | * 16 | * In the current example, the application we are writing acts as a server: 17 | * nodes are declared through the OSCQuery protocol, and other applications 18 | * can connect to this one. It is also possible to query the state through a 19 | * web browser, by going to http://localhost:5678/ 20 | */ 21 | Page { 22 | id: root 23 | header: Text { font.pointSize: 30 ; text: "Server example" } 24 | width: 800 25 | height: 500 26 | 27 | 28 | // From this point, we enter the /test relative namespace level 29 | // If no 'node' is given, the parent object's objectName will be used. 30 | // If there is no objectName, the name of the parent class will be used. 31 | // Nodes with an absolute address repsect their given address. 32 | Ossia.Node { node: 'test' } 33 | 34 | GridLayout 35 | { 36 | Text { Layout.row: 0; Layout.column: 0; width: 50; wrapMode: Text.Wrap; 37 | text: "Graph" } 38 | Rectangle { 39 | Layout.row: 0 40 | Layout.column: 1 41 | width: 400 42 | height: 200 43 | border.width: 2 44 | 45 | Graph { 46 | width: parent.width - 2 47 | height: parent.height - 4 48 | y: 2 49 | 50 | // A value we add for receiving the new message 51 | property real nextVal 52 | onNextValChanged: pushValue(nextVal) 53 | 54 | // This creates a new node '/units/float' 55 | // with the type of nextVal. 56 | Ossia.Property on nextVal { 57 | node: '/units/float' 58 | } 59 | } 60 | } 61 | 62 | Text { Layout.row: 1; Layout.column: 0; width: 50; wrapMode: Text.Wrap; 63 | text: "Sliders (controlled by the Joystick in the client)" } 64 | MultiSlider { 65 | Layout.row: 1 66 | Layout.column: 1 67 | 68 | count: 2 69 | height: 100 70 | // Reads and writes from /test/values 71 | Ossia.Property on values { } 72 | } 73 | 74 | Text { Layout.row: 2; Layout.column: 0; width: 50; wrapMode: Text.Wrap; 75 | text: "Angle slider (changes the text in client)" } 76 | AngleSlider { 77 | Layout.row: 2 78 | Layout.column: 1 79 | 80 | // Reads and writes from /test/angle 81 | Ossia.Property on angle { 82 | // The value will be bounded between these: 83 | min: -90 84 | max: 0 85 | bounding: Ossia.Context.Clip 86 | } 87 | } 88 | } 89 | 90 | Component.onCompleted: { 91 | Ossia.SingleDevice.openOSCQueryServer(5678,1234) 92 | Ossia.SingleDevice.recreate(root) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Joystick.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A round 2D touch area. The ballpen automatically returns to center upon release. 6 | // Properties: 7 | // * stickX / stickY : the position of the stick between [-1; 1] 8 | // * stickR : the distance of the stick to the center between [0; 1] 9 | // * stickAngle : the angle in degrees; 0 is at the right, 90 at the top. 10 | Rectangle { 11 | id: pad 12 | 13 | width: 100 14 | height: width 15 | radius: width / 2 16 | 17 | property var styles: DarkStyle 18 | color: styles.background 19 | 20 | state: "default" 21 | 22 | border { 23 | color: styles.base 24 | width: 5. 25 | } 26 | 27 | property real stickX: 0 28 | property real stickY: 0 29 | property real stickR: 0 30 | property real stickTheta: 0 31 | 32 | signal polarChanged(point p) 33 | 34 | function moveStick(mouseX, mouseY) { 35 | var dist = Utils.distance(0, 0, mouseX - pad.radius, 36 | mouseY - pad.radius) 37 | stickTheta = mouseY === pad.radius 38 | && mouseX === pad.radius ? 0 : Math.atan2(mouseY - pad.radius, 39 | mouseX - pad.radius) 40 | var radius = Utils.clamp(dist, 0, pad.radius - stick.radius) 41 | 42 | stick.x = radius * Math.cos(stickTheta) + pad.radius - stick.radius 43 | stick.y = radius * Math.sin(stickTheta) + pad.radius - stick.radius 44 | 45 | // rescale between 0 and 1 46 | stickX = Utils.rescale(stick.x, 0, pad.width - stick.width, -1.00, 1.00) 47 | stickY = -Utils.rescale(stick.y, 0, pad.height - stick.height, -1, 1) 48 | stickR = Utils.distance(stickX, stickY, 0, 0) 49 | 50 | polarChanged(stickR, stickTheta) 51 | } 52 | 53 | function releaseStick() { 54 | stickX = 0 55 | stickY = 0 56 | stickTheta = 0 57 | stickR = 0 58 | } 59 | 60 | Rectangle { 61 | id: stick 62 | color: pad.state === "move" ? styles.colorOn : styles.base 63 | radius: pad.state === "move" ? pad.radius / 6 * 1.1 : pad.radius / 6 64 | height: radius * 2 65 | width: height 66 | } 67 | 68 | TouchArea { 69 | id: area 70 | anchors.fill: parent 71 | onPressed: { 72 | pad.state = "move" 73 | moveStick(point.x, point.y) 74 | } 75 | 76 | onPositionChanged: moveStick(point.x, point.y) 77 | onReleased: { 78 | pad.state = "default" 79 | releaseStick() 80 | } 81 | } 82 | 83 | states: [ 84 | State { 85 | id: def 86 | name: "default" 87 | AnchorChanges { 88 | target: stick 89 | anchors.horizontalCenter: pad.horizontalCenter 90 | anchors.verticalCenter: pad.verticalCenter 91 | } 92 | }, 93 | State { 94 | id: move 95 | name: "move" 96 | AnchorChanges { 97 | target: stick 98 | anchors.horizontalCenter: undefined 99 | anchors.verticalCenter: undefined 100 | } 101 | } 102 | ] 103 | 104 | transitions: Transition { 105 | AnchorAnimation { 106 | duration: 50 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/MultiSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | 3 | 4 | // Vertical or horizontal set of sliders. 5 | // Parameters: 6 | // * count: the number of sliders 7 | // * orientation: vertical / horizontal 8 | // * spacing: spacing between sliders 9 | // * values: an array with all the output values. 10 | Item { 11 | id: multiSlider 12 | 13 | objectName: "multiSlider" 14 | width: orientation == Qt.Vertical ? 500 : 400 15 | height: orientation == Qt.Vertical ? 200 : 500 16 | 17 | property var styles: DarkStyle 18 | 19 | property int count: 10 20 | property int orientation: Qt.Vertical 21 | property bool textVisible: true 22 | property bool interactive: true 23 | property bool ease: false 24 | property real spacing: 0. 25 | property real sliderWidth: (multiSlider.orientation == Qt.Vertical) 26 | ? (multiSlider.width) / count - spacing 27 | : (multiSlider.height) / count - spacing 28 | 29 | property bool __updating: false 30 | 31 | property var values: [0.2,0.4,0.5,0.6,0.1,0.9] 32 | onValuesChanged: updateValues() 33 | Row { 34 | spacing: multiSlider.spacing 35 | 36 | Repeater { 37 | id: hSliders 38 | 39 | model: (multiSlider.orientation == Qt.Vertical) ? multiSlider.count : 0 40 | VSlider { 41 | styles: multiSlider.styles 42 | 43 | textVisible: multiSlider.textVisible 44 | ease: multiSlider.ease 45 | interactive: multiSlider.interactive 46 | height: multiSlider.height 47 | width: multiSlider.sliderWidth 48 | border.width: 0 49 | 50 | onValueChanged: recomputeValues() 51 | } 52 | } 53 | } 54 | 55 | Column { 56 | spacing: multiSlider.spacing 57 | Repeater { 58 | id: vSliders 59 | 60 | model: (multiSlider.orientation == Qt.Horizontal) ? multiSlider.count : 0 61 | HSlider { 62 | styles: multiSlider.styles 63 | 64 | textVisible: multiSlider.textVisible 65 | ease: multiSlider.ease 66 | interactive: multiSlider.interactive 67 | height: multiSlider.sliderWidth 68 | width: multiSlider.width 69 | border.width: 0 70 | 71 | onValueChanged: recomputeValues() 72 | } 73 | } 74 | } 75 | 76 | // outside -> inside 77 | function updateValues() { 78 | if (!__updating) { 79 | __updating = true 80 | var source = (orientation == Qt.Vertical) ? hSliders : vSliders 81 | 82 | for (var i = 0; i < count; i++) { 83 | var item = source.itemAt(i) 84 | 85 | if (item !== null) { 86 | item.value = values[i] 87 | item.updateHandle() 88 | } 89 | } 90 | __updating = false 91 | } 92 | } 93 | 94 | // inside -> outside 95 | function recomputeValues() { 96 | if (!__updating) { 97 | var source = (orientation == Qt.Vertical) ? hSliders : vSliders 98 | var array = [] 99 | for (var i = 0; i < count; i++) { 100 | var item = source.itemAt(i) 101 | if (item !== null) { 102 | array.push(item.value) 103 | } 104 | } 105 | __updating = true 106 | values = array 107 | __updating = false 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/ColorSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | import QtQuick.Layouts 1.3 4 | 5 | 6 | // Three to four sliders to control red, green, blue, alpha of a color 7 | // Properties: 8 | // * color: the current color 9 | // * colorSpace: the colorSpace for these sliders 10 | // * enableAlpha: show the alpha channel slider 11 | Rectangle { 12 | id: colorSlider 13 | 14 | height: 200 15 | width: 200 16 | 17 | color: colorSpace(x.value, y.value, z.value, alphaValue) 18 | property color contourColor: colorSpace(x.value, y.value, 1. - z.value, 0.5) 19 | 20 | // add an alpha slider 21 | property bool enableAlpha: false 22 | property real alphaValue: enableAlpha ? a.value : 1.0 23 | 24 | // slider width varies according to channel number (3 without alpha and 4 with alpha) 25 | property real sliderWidth: enableAlpha ? width / 4. : width / 3. 26 | property var colorSpace: Qt.hsla 27 | 28 | RowLayout { 29 | width: parent.width 30 | height: parent.height * 2 / 3 31 | anchors.centerIn: parent 32 | 33 | VSlider { 34 | id: x 35 | 36 | text: colorSpace == Qt.rgba ? "R" : "H" 37 | 38 | border { 39 | width: 2 40 | color: colorSlider.contourColor 41 | } 42 | 43 | Layout.fillHeight: true 44 | Layout.alignment: Qt.AlignHCenter 45 | Layout.preferredWidth: colorSlider.sliderWidth - 10 46 | 47 | initialValue: 153. / 255. 48 | 49 | handleColor: colorSpace == Qt.rgba 50 | ? colorSpace(value, 0, 0, 1.) 51 | : colorSpace(value, 0.5, 0.5, 1.) 52 | } 53 | 54 | VSlider { 55 | id: y 56 | 57 | text: colorSpace == Qt.rgba ? "G" : "S" 58 | 59 | border { 60 | width: 2 61 | color: colorSlider.contourColor 62 | } 63 | 64 | Layout.fillHeight: true 65 | Layout.alignment: Qt.AlignHCenter 66 | Layout.preferredWidth: colorSlider.sliderWidth - 10 67 | 68 | initialValue: 187. / 255. 69 | handleColor: colorSpace == Qt.rgba 70 | ? colorSpace(0, value, 0.,1.) 71 | : colorSpace(x.value, value, 0.5, 1.) 72 | } 73 | 74 | VSlider { 75 | id: z 76 | text: colorSpace == Qt.rgba ? "B" : colorSpace == Qt.hsla ? "L" : "V" 77 | 78 | border { 79 | width: 2 80 | color: colorSlider.contourColor 81 | } 82 | 83 | Layout.fillHeight: true 84 | Layout.alignment: Qt.AlignHCenter 85 | Layout.preferredWidth: colorSlider.sliderWidth - 10 86 | 87 | initialValue: 153. / 255. 88 | 89 | handleColor: colorSpace == Qt.rgba 90 | ? colorSpace(0, 0., value, 1.) 91 | : colorSpace(x.value, 0.5, value, 1.) 92 | } 93 | 94 | VSlider { 95 | id: a 96 | 97 | visible: colorSlider.enableAlpha 98 | text: "A" 99 | 100 | border { 101 | width: 2 102 | color: colorSlider.contourColor 103 | } 104 | 105 | Layout.fillHeight: true 106 | Layout.alignment: Qt.AlignHCenter 107 | Layout.preferredWidth: colorSlider.sliderWidth - 10 108 | 109 | initialValue: 0.7 110 | 111 | handleColor: Qt.rgba(value, value, value, 1.0) 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /qml-creative-controls.pro: -------------------------------------------------------------------------------- 1 | QT += qml quick 2 | CONFIG += plugin 3 | TEMPLATE = lib 4 | 5 | # QMAKE_CXXFLAGS += -fsanitize=address -fsanitize=undefined -O0 6 | # QMAKE_LFLAGS += -fsanitize=address -fsanitize=undefined -O0 7 | QML_IMPORT_PATH += $$PWD 8 | QML2_IMPORT_PATH += $$PWD 9 | QML_DESIGNER_IMPORT_PATH += $$PWD 10 | 11 | DEFINES += QT_DEPRECATED_WARNINGS 12 | DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 13 | CCPATH = $$PWD/com/github/jcelerier 14 | HEADERS += \ 15 | $$PWD/src/graph.hpp \ 16 | $$PWD/src/creativecontrolsplugin.hpp \ 17 | $$PWD/src/angleslider.hpp \ 18 | $$PWD/src/scope.hpp \ 19 | $$PWD/src/cpputils.hpp \ 20 | $$PWD/src/xytarget.hpp \ 21 | $$PWD/src/polygon.hpp \ 22 | $$PWD/src/toucharea.hpp \ 23 | $$PWD/src/painted_polygon.hpp 24 | 25 | SOURCES += \ 26 | $$PWD/src/graph.cpp \ 27 | $$PWD/src/creativecontrolsplugin.cpp \ 28 | $$PWD/src/angleslider.cpp \ 29 | $$PWD/src/scope.cpp \ 30 | $$PWD/src/cpputils.cpp \ 31 | $$PWD/src/xytarget.cpp \ 32 | $$PWD/src/polygon.cpp \ 33 | $$PWD/src/toucharea.cpp \ 34 | $$PWD/src/painted_polygon.cpp 35 | 36 | DESTDIR = $$_PRO_FILE_PWD_/CreativeControls/ 37 | 38 | OTHER_FILES += \ 39 | $$CCPATH/CreativeControls/AngleSlider.qml \ 40 | $$CCPATH/CreativeControls/ArcSlider.qml \ 41 | $$CCPATH/CreativeControls/ColorChooser.qml \ 42 | $$CCPATH/CreativeControls/ColorSlider.qml \ 43 | $$CCPATH/CreativeControls/ColorWheel.qml \ 44 | $$CCPATH/CreativeControls/Container.qml \ 45 | $$CCPATH/CreativeControls/CosInfluence.qml \ 46 | $$CCPATH/CreativeControls/DarkStyle.qml \ 47 | $$CCPATH/CreativeControls/DonutSlider.qml \ 48 | $$CCPATH/CreativeControls/Frame.qml \ 49 | $$CCPATH/CreativeControls/Graph2D.qml \ 50 | $$CCPATH/CreativeControls/Graph.qml \ 51 | $$CCPATH/CreativeControls/HRangeSlider.qml \ 52 | $$CCPATH/CreativeControls/HSlider.qml \ 53 | $$CCPATH/CreativeControls/HSLSlider.qml \ 54 | $$CCPATH/CreativeControls/HSVSlider.qml \ 55 | $$CCPATH/CreativeControls/Joystick.qml \ 56 | $$CCPATH/CreativeControls/Keyboard.qml \ 57 | $$CCPATH/CreativeControls/Label.qml \ 58 | $$CCPATH/CreativeControls/Leds.qml \ 59 | $$CCPATH/CreativeControls/LightStyle.qml \ 60 | $$CCPATH/CreativeControls/Matrix.qml \ 61 | $$CCPATH/CreativeControls/MultiSlider.qml \ 62 | $$CCPATH/CreativeControls/Random1D.qml \ 63 | $$CCPATH/CreativeControls/Random2D.qml \ 64 | $$CCPATH/CreativeControls/Random3D.qml \ 65 | $$CCPATH/CreativeControls/RGBSlider.qml \ 66 | $$CCPATH/CreativeControls/Scale.qml \ 67 | $$CCPATH/CreativeControls/Scope.qml \ 68 | $$CCPATH/CreativeControls/Spat.qml \ 69 | $$CCPATH/CreativeControls/Spectrum.qml \ 70 | $$CCPATH/CreativeControls/Step.qml \ 71 | $$CCPATH/CreativeControls/Switch.qml \ 72 | $$CCPATH/CreativeControls/ToggleSwitch.qml \ 73 | $$CCPATH/CreativeControls/Trajectory.qml \ 74 | $$CCPATH/CreativeControls/Utils.qml \ 75 | $$CCPATH/CreativeControls/VRangeSlider.qml \ 76 | $$CCPATH/CreativeControls/VSlider.qml \ 77 | $$CCPATH/CreativeControls/XYPad.qml \ 78 | $$CCPATH/CreativeControls/qmldir \ 79 | $$CCPATH/CreativeControls/designer/CreativeControls.metainfo \ 80 | $$PWD/README.md 81 | 82 | DISTFILES += \ 83 | $$PWD/examples/Limiter.qml \ 84 | $$PWD/examples/Gallery.qml \ 85 | $$PWD/examples/OssiaClientExample.qml \ 86 | $$PWD/examples/OssiaServerExample.qml \ 87 | $$PWD/examples/Overview.qml \ 88 | $$PWD/examples/SimpleStep.qml \ 89 | $$PWD/examples/ContainerExample.qml \ 90 | $$PWD/examples/Spectrogram.qml \ 91 | $$PWD/tests/SliderTest.qml \ 92 | $$PWD/tests/Various.qml \ 93 | $$PWD/examples/DesignerExampleForm.ui.qml \ 94 | $$PWD/examples/DesignerExample.qml 95 | 96 | FORMS += 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

QML Creative Controls

2 | 3 |

4 | 5 |

6 | 7 | Controls useful in a creative coding context. 8 | 9 | Requirements: 10 | 11 | * Qt >= 5.7 12 | * Tested on Windows, Linux, macOS, Android. Should work everywhere. 13 | 14 | [![Build Status](https://travis-ci.org/jcelerier/qml-creative-controls.svg)](https://travis-ci.org/jcelerier/qml-creative-controls) 15 | [![Build status](https://ci.appveyor.com/api/projects/status/j07ij1y6tf6awey5?svg=true)](https://ci.appveyor.com/project/JeanMichalCelerier/qml-creative-controls) [![Join the chat at https://gitter.im/qml-creative-controls/Lobby](https://badges.gitter.im/qml-creative-controls/Lobby.svg)](https://gitter.im/qml-creative-controls/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 16 | 17 | 18 | ## Building 19 | 20 | ### With QPM 21 | 22 | The library is compatible with [qpm](https://qpm.io). 23 | Just do 24 | 25 | qpm install com.github.jcelerier.qml-creative-controls 26 | 27 | in your project. 28 | 29 | ### Manually 30 | 31 | After cloning the repository, run : 32 | 33 | cd qml-creative-controls 34 | qmake 35 | make -j 36 | 37 | (Or open the .pro file in Qt Creator) 38 | 39 | Then put the `CreativeControls` folder in your Qt installation, so that it looks like: 40 | 41 | ``` 42 | ~/Qt/5.11/gcc_64/qml/CreativeControls/libqml-creative-controls.so 43 | /Foo.qml 44 | # /etc... 45 | ``` 46 | 47 | If you do not wish to pollute your path, you will have to add the parent folder (the git repostiory) 48 | to your QML2_IMPORT_PATH, either through qmake, an environment variable, code... 49 | 50 | To try an example, run for instance : 51 | 52 | ~/Qt/5.11/gcc_64/bin/qmlscene --multisample examples/Gallery.qml 53 | 54 | ## Notes 55 | 56 | This library can be useful in conjunction with [libossia](https://github.com/OSSIA/libossia). 57 | See [OssiaClientExample.qml](examples/OssiaClientExample.qml) and [OssiaServerExample.qml](examples/OssiaServerExample.qml) 58 | This allows to build pretty control interfaces for MIDI or OSC-able software. 59 | 60 | ## Gallery 61 | 62 | ![QtDesigner](https://i.imgur.com/mGzRNor.png) 63 | 64 | ## Inspiration 65 | 66 | * [Lemur](https://liine.net) 67 | * [HOALibrary](https://cycling74.com/toolbox/hoalibrary-v2/) 68 | * [Musinekit](http://www.sensomusic.org/musinekit/en) 69 | * [TouchOSC](https://hexler.net/software/touchosc) 70 | * [Audiomulch](http://www.audiomulch.com/) 71 | * [NexusUI](https://nexus-js.github.io/ui/) 72 | * [ofxDatGui](https://github.com/braitsch/ofxDatGui) 73 | * [Luminosus](https://www.luminosus.org) 74 | * [oui.js](https://github.com/wearekuva/oui) 75 | * [nuklear](https://github.com/vurtun/nuklear) 76 | * [dat.gui](http://workshop.chromeexperiments.com/examples/gui) 77 | * [p5.gui](https://github.com/bitcraftlab/p5.gui) 78 | * [controlp5](https://github.com/sojamo/controlp5) 79 | * [Dear ImGui](https://github.com/ocornut/imgui) 80 | * [nanogui](https://github.com/wjakob/nanogui) 81 | * [Bach](http://www.bachproject.net/) slots 82 | * [Open Stage Control](https://github.com/jean-emmanuel/open-stage-control) 83 | * [ofxMightyUI](https://github.com/kritzikratzi/ofxMightyUI) 84 | * [ofxAVUI](https://github.com/AVUIs/ofxAVUI) 85 | * [ofxCvGui](https://github.com/elliotwoods/ofxCvGui) 86 | * [quickcollider](https://github.com/jleben/quickcollider) 87 | * [QtQuickVcp](https://github.com/qtquickvcp/QtQuickVcp) 88 | * [FlatUI](https://github.com/obeezzy/FlatUI) 89 | * [spatium](https://vimeo.com/52321647) 90 | * [qml-color-picker](https://github.com/astorije/qml-color-picker) 91 | * [Interface.js](http://charlie-roberts.com/interface/) 92 | * [ofxDmtrUI3](https://github.com/dimitre/ofxDmtrUI3) 93 | 94 | -------------------------------------------------------------------------------- /examples/Limiter.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.10 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | Container { 5 | width: 800 6 | height: 200 7 | 8 | AngleSlider { 9 | id: output 10 | x: 189 11 | y: 40 12 | } 13 | 14 | Label { 15 | id: text15 16 | x: 506 17 | y: 166 18 | text: qsTr("Limiting Amplifier") 19 | anchors { 20 | bottomMargin: 11 21 | topMargin: -11 22 | verticalCenter: text4.verticalCenter 23 | bottom: text4.bottom 24 | top: text4.top 25 | } 26 | font.pixelSize: 12 27 | } 28 | 29 | Label { 30 | id: text14 31 | x: 693 32 | y: 125 33 | text: qsTr("OFF") 34 | font.pixelSize: 12 35 | } 36 | 37 | Label { 38 | id: text13 39 | x: 693 40 | y: 92 41 | text: qsTr("+4") 42 | font.pixelSize: 12 43 | } 44 | 45 | Label { 46 | id: text12 47 | x: 693 48 | y: 58 49 | text: qsTr("+8") 50 | font.pixelSize: 12 51 | } 52 | 53 | Label { 54 | id: text11 55 | x: 693 56 | y: 24 57 | text: qsTr("GR") 58 | font.pixelSize: 12 59 | } 60 | 61 | Label { 62 | id: text10 63 | x: 660 64 | y: -1 65 | text: qsTr("Meter") 66 | font.pixelSize: 12 67 | } 68 | 69 | Label { 70 | id: text9 71 | x: 434 72 | y: -1 73 | text: qsTr("Ratio") 74 | font.pixelSize: 12 75 | } 76 | 77 | Label { 78 | id: text8 79 | x: 423 80 | y: 127 81 | text: qsTr("4") 82 | font.pixelSize: 12 83 | } 84 | 85 | Label { 86 | id: text7 87 | x: 422 88 | y: 91 89 | text: qsTr("8") 90 | font.pixelSize: 12 91 | } 92 | 93 | Label { 94 | id: text6 95 | x: 419 96 | y: 59 97 | text: qsTr("12") 98 | font.pixelSize: 12 99 | } 100 | 101 | Label { 102 | id: text5 103 | x: 419 104 | y: 22 105 | text: qsTr("20") 106 | font.pixelSize: 12 107 | } 108 | 109 | Label { 110 | id: text4 111 | x: 346 112 | y: 155 113 | text: qsTr("Release") 114 | font.pixelSize: 12 115 | } 116 | 117 | Label { 118 | id: text3 119 | x: 348 120 | y: -1 121 | text: qsTr("Attack") 122 | font.pixelSize: 12 123 | } 124 | 125 | Label { 126 | id: text2 127 | x: 218 128 | y: 140 129 | text: qsTr("Output") 130 | font.pixelSize: 12 131 | } 132 | 133 | Label { 134 | id: text1 135 | x: 72 136 | y: 140 137 | text: qsTr("Input") 138 | font.pixelSize: 12 139 | } 140 | 141 | AngleSlider { 142 | id: input 143 | x: 39 144 | y: 40 145 | } 146 | 147 | AngleSlider { 148 | id: attack 149 | x: 348 150 | y: 20 151 | width: 40 152 | height: 40 153 | } 154 | 155 | AngleSlider { 156 | id: release 157 | x: 348 158 | y: 113 159 | width: 40 160 | height: 40 161 | } 162 | 163 | Matrix { 164 | id: ratio 165 | x: 434 166 | y: 15 167 | width: 30 168 | height: 150 169 | spacing: 1 170 | rows: 4 171 | columns: 1 172 | } 173 | 174 | Container { 175 | id: container 176 | x: 471 177 | y: 13 178 | width: 186 179 | height: 134 180 | 181 | Graph { 182 | id: gr 183 | x: 4 184 | y: -3 185 | width: 157 186 | height: 121 187 | } 188 | } 189 | 190 | Matrix { 191 | id: meter 192 | x: 664 193 | y: 15 194 | width: 30 195 | height: 150 196 | columns: 1 197 | rows: 4 198 | spacing: 1 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/Leds.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A LED matrix. 6 | 7 | // Property: 8 | // * intensity[]: 9 | // array containing the color intensity for each led of the matrix 10 | 11 | // Functions: 12 | // * toggle(index): 13 | // toggle the led at index(1D index for the grid) in the grid, 14 | // switching it on or off 15 | // * setIntensity(index,val): 16 | // set intensity at val for the led at index (1D index for the grid) 17 | // * setIntensityForAll(val): 18 | // set intensity at val for all the leds in the matrix 19 | Grid { 20 | id: leds 21 | 22 | width: 200 23 | height: 200 24 | 25 | columns: 3 26 | rows: 3 27 | 28 | columnSpacing: Utils.clamp((leds.width - leds.radius * 2 * leds.columns) / (leds.columns - 1), 0, leds.width) 29 | rowSpacing: Utils.clamp((leds.height - leds.radius * 2 * leds.rows) / (leds.rows - 1), 0, leds.height) 30 | 31 | property var styles: DarkStyle 32 | onStylesChanged: updateColor() 33 | 34 | property real radius: 20 35 | property color ledColorOn: styles.colorOn 36 | property color ledColorOff: styles.colorOff 37 | 38 | property bool easing: false 39 | 40 | // intensity default values 41 | property var intensity: [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9]] 42 | 43 | // update color if the style changed 44 | function updateColor() { 45 | for (var k = 0; k < repeater.count; k++) { 46 | var item = repeater.itemAt(k) 47 | if (item !== null) { 48 | item.color = Qt.darker( styles.colorOn, intensity[item.indexColumn][item.indexRow] * 10.) 49 | } 50 | } 51 | } 52 | 53 | // toggle on/off 54 | function toggle(index) { 55 | var indexRow = index % leds.columns 56 | var indexColumn = (index - indexRow) / (leds.columns) 57 | 58 | // modify the intensity matrix 59 | var val = intensity[indexColumn][indexRow] > 0. ? 0. : 1.0 60 | setIntensity(index, val) 61 | } 62 | 63 | // set intensity for one led at index (1D index for the grid) 64 | function setIntensity(index, val) { 65 | var indexRow = index % leds.columns 66 | var indexColumn = (index - indexRow) / (leds.columns) 67 | 68 | // modify the intensity matrix 69 | intensity[indexColumn][indexRow] = val 70 | 71 | // set the led color 72 | var item = repeater.itemAt(index) 73 | if (item !== null) { 74 | item.color = Qt.darker(ledColorOn, val * 10.) 75 | } 76 | } 77 | 78 | // set intensity for all the leds 79 | function setIntensityForAll(val) { 80 | // modify the intensity matrix 81 | for (var i = 0; i < leds.columns; i++) { 82 | for (var j = 0; j < leds.rows; j++) { 83 | intensity[i][j] = val 84 | } 85 | } 86 | 87 | // set the led color 88 | for (var k = 0; k < leds.rows * leds.columns; k++) { 89 | var item = repeater.itemAt(k) 90 | if (item !== null) { 91 | item.color = Qt.darker(ledColorOn, val * 10.) 92 | } 93 | } 94 | } 95 | 96 | Repeater { 97 | id: repeater 98 | model: leds.rows * leds.columns 99 | 100 | Rectangle { 101 | id: rect 102 | width: leds.radius * 2. 103 | height: leds.radius * 2. 104 | radius: leds.radius 105 | 106 | // border.width: 2 107 | // border.color : Styles.base 108 | color: Qt.darker(ledColorOn, intensity[indexColumn][indexRow] * 10.) 109 | 110 | Behavior on color { 111 | enabled: leds.easing 112 | ColorAnimation { 113 | easing.type: Easing.InOutQuad 114 | } 115 | } 116 | property real indexRow: index % leds.columns 117 | property real indexColumn: (index - indexRow) / (leds.columns) 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/CosInfluence.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // Cosine influence area. 6 | // Parameters: 7 | // * points: a list of points betwen (0;0) and (1;1). 8 | // * centerX / centerY: the position of the crosshair 9 | // * values: when the crosshair moves, values is updated to contain an array of distances 10 | // to each point in points 11 | Rectangle { 12 | id: cosInfluence 13 | 14 | width: 200 15 | height: 200 16 | 17 | property var points: [Qt.point(0.2, 0.4), Qt.point(0.5, 0.1)] 18 | property alias centerX: xy.centerX 19 | property alias centerY: xy.centerY 20 | onCenterXChanged: updateValues() 21 | onCenterYChanged: updateValues() 22 | onPointsChanged: updateValues() 23 | 24 | property var styles: DarkStyle 25 | color: styles.background 26 | 27 | property real sizeRatio: Math.min(cosInfluence.width, 28 | cosInfluence.height) / 13. 29 | property var values: [] 30 | 31 | function updateValues() { 32 | var newvalues = [] 33 | for (var i = 0; i < cosInfluence.points.length; i++) { 34 | var x1 = cosInfluence.points[i].x - centerX + sizeRatio / width 35 | var x2 = cosInfluence.points[i].y - centerY + sizeRatio / width 36 | var dist = 3 * Math.sqrt(x1 * x1 + x2 * x2) 37 | if (Math.abs(dist) < Math.PI / 2) 38 | newvalues.push(Math.cos(dist)) 39 | else 40 | newvalues.push(0) 41 | } 42 | values = newvalues 43 | } 44 | 45 | // Mouse area for when the background is clicked 46 | TouchArea { 47 | id: touchArea 48 | anchors.fill: parent 49 | onPressed: applyPos(point) 50 | onPositionChanged: applyPos(point) 51 | 52 | function applyPos(point) { 53 | centerX = Utils.clamp(point.x, 0, cosInfluence.width) / width 54 | centerY = Utils.clamp(point.y, 0, cosInfluence.height) / height 55 | } 56 | } 57 | 58 | // The circles 59 | Repeater { 60 | model: points 61 | delegate: Polygon { 62 | smooth: true 63 | antialiasing: true 64 | x: points[index].x * cosInfluence.width 65 | y: points[index].y * cosInfluence.height 66 | onXChanged: { 67 | points[index].x = x / cosInfluence.width 68 | updateValues() 69 | } 70 | onYChanged: { 71 | points[index].y = y / cosInfluence.height 72 | updateValues() 73 | } 74 | width: 2. * sizeRatio 75 | height: width 76 | borderWidth: 0.05 * sizeRatio 77 | fillColor: styles.randomDetailColor() 78 | borderColor: dragArea.pressed ? styles.textPressedColor : styles.background 79 | 80 | Text { 81 | anchors.centerIn: parent 82 | horizontalAlignment: Text.AlignHCenter 83 | verticalAlignment: Text.AlignVCenter 84 | 85 | font.pointSize: Math.max(2, 1.1 * sizeRatio) 86 | text: index 87 | color: parent.borderColor 88 | } 89 | 90 | Drag.hotSpot: Qt.point(width / 2, height / 2) 91 | 92 | MouseArea { 93 | id: dragArea 94 | anchors.fill: parent 95 | 96 | drag { 97 | target: parent 98 | smoothed: false 99 | minimumX: 0. - width / 2. 100 | maximumX: cosInfluence.width - width / 2. 101 | minimumY: 0 - height / 2. 102 | maximumY: cosInfluence.height - height / 2. 103 | } 104 | } 105 | } 106 | } 107 | 108 | // Crosshair. When clicked it will also move. 109 | Crosshair { 110 | id: xy 111 | anchors.fill: parent 112 | color: xy.pressed 113 | || touchArea.pressState ? styles.colorOn : styles.colorOff 114 | radiusScale: xy.pressed || touchArea.pressState ? 25 : 35 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /examples/DesignerExampleForm.ui.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.4 2 | import com.github.jcelerier.CreativeControls 1.0 3 | import QtQuick.Layouts 1.0 4 | 5 | Item { 6 | id: element 7 | width: 1000 8 | height: 600 9 | clip: false 10 | visible: true 11 | 12 | Container { 13 | id: container 14 | x: 16 15 | y: 16 16 | width: 900 17 | height: 580 18 | anchors.verticalCenter: parent.verticalCenter 19 | anchors.horizontalCenter: parent.horizontalCenter 20 | 21 | Matrix { 22 | id: buttonMatrix 23 | x: 354 24 | width: 300 25 | height: 300 26 | anchors.top: parent.top 27 | anchors.topMargin: 20 28 | rows: 4 29 | columns: 4 30 | } 31 | 32 | Label { 33 | id: label 34 | x: 368 35 | y: 502 36 | text: "QML Creative Controls" 37 | anchors.horizontalCenterOffset: 135 38 | anchors.horizontalCenter: parent.horizontalCenter 39 | anchors.bottom: parent.bottom 40 | anchors.bottomMargin: 31 41 | } 42 | 43 | RGBSlider { 44 | id: rGBSliders 45 | x: 681 46 | width: 180 47 | height: 180 48 | anchors.right: parent.right 49 | anchors.rightMargin: 20 50 | anchors.top: parent.top 51 | anchors.topMargin: 20 52 | } 53 | 54 | Container { 55 | id: container2 56 | y: 359 57 | width: 310 58 | height: 190 59 | radius: 10 60 | anchors.left: parent.left 61 | anchors.leftMargin: 20 62 | anchors.bottom: parent.bottom 63 | anchors.bottomMargin: 20 64 | 65 | CosInfluence { 66 | id: cosineInfluence 67 | radius: 1 68 | anchors.fill: parent 69 | } 70 | } 71 | 72 | Keyboard { 73 | id: pianoKeyboard 74 | x: 362 75 | y: 356 76 | width: 497 77 | height: 108 78 | } 79 | 80 | Leds { 81 | id: leds 82 | x: 681 83 | y: 216 84 | width: 180 85 | height: 100 86 | rows: 2 87 | } 88 | 89 | ToggleSwitch { 90 | id: toggleSwitch1 91 | x: 725 92 | y: 492 93 | anchors.right: parent.right 94 | anchors.rightMargin: 55 95 | } 96 | 97 | Container { 98 | id: container1 99 | width: 310 100 | height: 136 101 | anchors.left: parent.left 102 | anchors.leftMargin: 20 103 | anchors.top: parent.top 104 | anchors.topMargin: 20 105 | 106 | MultiSlider { 107 | id: element1 108 | ease: false 109 | interactive: false 110 | anchors.topMargin: -2 111 | anchors.rightMargin: -2 112 | textVisible: true 113 | anchors.fill: parent 114 | count: 5 115 | 116 | values: [0.1, 0.5, 0.9, 0.4, 0.7] 117 | } 118 | } 119 | 120 | Switch { 121 | id: element2 122 | x: 365 123 | y: 491 124 | } 125 | 126 | RowLayout { 127 | x: 32 128 | y: 192 129 | spacing: 20 130 | 131 | Joystick { 132 | id: joystick 133 | radius: 60 134 | Layout.preferredHeight: 120 135 | Layout.preferredWidth: 120 136 | } 137 | 138 | AngleSlider { 139 | id: angleSlider 140 | Layout.preferredHeight: 120 141 | Layout.preferredWidth: 120 142 | } 143 | } 144 | } 145 | } 146 | 147 | 148 | 149 | 150 | /*##^## Designer { 151 | D{i:2;anchors_y:15}D{i:4;anchors_y:35}D{i:5;anchors_height:174;anchors_width:255;anchors_x:37;anchors_y:359} 152 | D{i:10;anchors_x:15;anchors_y:15} 153 | } 154 | ##^##*/ 155 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/DonutSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | import QtQuick.Controls.Styles 1.4 4 | 5 | 6 | // A RGB slider shaped in donut 7 | 8 | // Properties: 9 | // * resColor: the current color 10 | // * colorSpace: choose the colorSpace for the slider (Qt.rgba/Qt.hsla/Qt.hsva) 11 | Rectangle { 12 | id: donutSlider 13 | 14 | width: 200 15 | height: width 16 | radius: width / 2. 17 | color: "transparent" 18 | 19 | // border.width : 3. 20 | // border.color : donutSlider.resColor 21 | property real channels: 3. 22 | property real innerRadius: radius * 0.4 //0.38 23 | property color resColor: Styles.detail 24 | property var colorSpace: Qt.hsla 25 | 26 | function updateColor() { 27 | if (repeater.itemAt(2) !== null && (colorSpace === Qt.hsla 28 | || colorSpace === Qt.hsva)) { 29 | for (var i = 1; i < repeater.count; i++) { 30 | repeater.itemAt(i).updateHue(repeater.itemAt(0).value) 31 | } 32 | } 33 | donutSlider.resColor = (repeater.itemAt(2) !== null) 34 | ? colorSpace(repeater.itemAt(0).value, repeater.itemAt(1).value, repeater.itemAt(2).value, 1.) 35 | : Styles.detail 36 | } 37 | 38 | Repeater { 39 | id: repeater 40 | model: donutSlider.channels 41 | 42 | delegate: ArcSlider { 43 | id: arcSlider 44 | channelIndex: index 45 | colorSpace: donutSlider.colorSpace 46 | 47 | anchors.fill: parent 48 | 49 | innerRadius: donutSlider.innerRadius * 1.5 50 | onValueChanged: donutSlider.updateColor() 51 | } 52 | } 53 | 54 | Rectangle { 55 | id: center 56 | 57 | width: innerRadius * 2. 58 | height: width 59 | radius: innerRadius 60 | 61 | anchors.centerIn: parent 62 | color: donutSlider.resColor 63 | visible: true 64 | } 65 | 66 | Rectangle { 67 | id: border 68 | 69 | anchors.fill: parent 70 | radius: parent.radius 71 | color: "transparent" 72 | 73 | border.width: 3. 74 | border.color: donutSlider.resColor 75 | } 76 | 77 | /*Rectangle 78 | { 79 | id: innerBorder 80 | 81 | anchors.centerIn : parent 82 | width : radius *2. 83 | height : radius *2. 84 | 85 | radius : donutSlider.innerRadius * 1.5 86 | color : "transparent" 87 | 88 | border.width : 3. 89 | border.color : donutSlider.resColor 90 | }*/ 91 | function updateSliders(ptX, ptY) { 92 | var angleRad = Math.PI - Math.atan2( 93 | ptX - donutSlider.radius, 94 | ptY - donutSlider.radius) //+ (2.* Math.PI); 95 | angleRad -= Math.PI / 2. 96 | 97 | angleRad += angleRad < 0 ? 2. * Math.PI : 0 98 | 99 | for (var i = 0; i < repeater.count; i++) { 100 | if (repeater.itemAt(i).isInside(angleRad)) { 101 | repeater.itemAt(i).moveHandle(angleRad) 102 | return true 103 | } 104 | } 105 | } 106 | 107 | TouchArea { 108 | anchors.fill: parent 109 | onPressed: { 110 | var distToCenter = Utils.distance(point.x, point.y, parent.radius, 111 | parent.radius) 112 | if (distToCenter > innerRadius) { 113 | updateSliders(point.x, point.y) 114 | } 115 | } 116 | onPositionChanged: updateSliders(point.x, point.y) 117 | 118 | onDoubleClicked: { 119 | var distToCenter = Utils.distance(point.x, point.y, parent.radius, 120 | parent.radius) 121 | if (distToCenter < innerRadius) { 122 | for (var i = 0; i < repeater.count; i++) { 123 | repeater.itemAt(i).reset() 124 | } 125 | } else { 126 | for (var i = 0; i < repeater.count; i++) { 127 | if (repeater.itemAt(i).isInside(angleRad)) { 128 | repeater.itemAt(i).reset() 129 | return true 130 | } 131 | } 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/angleslider.cpp: -------------------------------------------------------------------------------- 1 | #include "angleslider.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace CreativeControls 9 | { 10 | static const constexpr auto deg_to_rad = 2. * M_PI / 360.; 11 | static const constexpr auto rad_to_deg = 360. / (2. * M_PI); 12 | 13 | AngleSlider::AngleSlider() 14 | { 15 | setFlag(ItemHasContents, true); 16 | setAcceptedMouseButtons(Qt::LeftButton); 17 | setAntialiasing(true); 18 | } 19 | 20 | void AngleSlider::paint(QPainter* painter) 21 | { 22 | const auto rect = boundingRect(); 23 | auto borderWidth = (rect.width() / 2) * 1. / 15.; 24 | const auto radius = rect.width() / 2. - borderWidth / 2. - 1; 25 | QPen p; 26 | p.setWidth(borderWidth); 27 | p.setColor(m_detailColor); 28 | 29 | painter->setPen(p); 30 | painter->setBrush(m_baseColor); 31 | painter->drawEllipse(rect.center(), radius, radius); 32 | 33 | std::complex pt = std::polar(radius - 2, angle() * deg_to_rad); 34 | std::complex pt_min = std::polar(radius - 2, min() * deg_to_rad); 35 | std::complex pt_min_end = std::polar(radius - 5, min() * deg_to_rad); 36 | std::complex pt_max = std::polar(radius - 2, max() * deg_to_rad); 37 | std::complex pt_max_end = std::polar(radius - 5, max() * deg_to_rad); 38 | 39 | const auto cx = rect.center().x(); 40 | const auto cy = rect.center().y(); 41 | painter->setBrush(m_detailColor); 42 | painter->drawLine(rect.center(), QPointF{pt.real() + cx, pt.imag() + cy}); 43 | painter->drawEllipse(rect.center(), radius / 20., radius / 20.); 44 | 45 | p.setWidth(borderWidth * 0.75); 46 | painter->setPen(p); 47 | painter->drawLine( 48 | QPointF{pt_min_end.real() + cx, pt_min_end.imag() + cy}, 49 | QPointF{pt_min.real() + cx, pt_min.imag() + cy}); 50 | painter->drawLine( 51 | QPointF{pt_max_end.real() + cx, pt_max_end.imag() + cy}, 52 | QPointF{pt_max.real() + cx, pt_max.imag() + cy}); 53 | } 54 | 55 | qreal AngleSlider::angle() const 56 | { 57 | return m_angle; 58 | } 59 | 60 | qreal AngleSlider::min() const 61 | { 62 | return m_min; 63 | } 64 | 65 | qreal AngleSlider::max() const 66 | { 67 | return m_max; 68 | } 69 | 70 | QColor AngleSlider::baseColor() const 71 | { 72 | return m_baseColor; 73 | } 74 | 75 | QColor AngleSlider::detailColor() const 76 | { 77 | return m_detailColor; 78 | } 79 | 80 | void AngleSlider::setAngle(const qreal angle) 81 | { 82 | if (qFuzzyCompare(m_angle, angle)) 83 | return; 84 | 85 | if (angle < min()) 86 | m_angle = min(); 87 | else if (angle > max()) 88 | m_angle = max(); 89 | else 90 | m_angle = angle; 91 | emit angleChanged(m_angle); 92 | update(); 93 | } 94 | 95 | void AngleSlider::setMin(const qreal angle) 96 | { 97 | if (qFuzzyCompare(m_min, angle)) 98 | return; 99 | 100 | m_min = angle; 101 | update(); 102 | } 103 | 104 | void AngleSlider::setMax(const qreal angle) 105 | { 106 | if (qFuzzyCompare(m_max, angle)) 107 | return; 108 | 109 | m_max = angle; 110 | update(); 111 | } 112 | 113 | void AngleSlider::setBaseColor(const QColor baseColor) 114 | { 115 | if (m_baseColor == baseColor) 116 | return; 117 | 118 | m_baseColor = baseColor; 119 | emit baseColorChanged(m_baseColor); 120 | update(); 121 | } 122 | 123 | void AngleSlider::setDetailColor(const QColor detailColor) 124 | { 125 | if (m_detailColor == detailColor) 126 | return; 127 | 128 | m_detailColor = detailColor; 129 | emit detailColorChanged(m_detailColor); 130 | update(); 131 | } 132 | 133 | void AngleSlider::updateAngle(QPointF point) 134 | { 135 | const auto c = boundingRect().center(); 136 | 137 | std::complex pt(point.x() - c.x(), point.y() - c.y()); 138 | setAngle(std::arg(pt) * rad_to_deg); 139 | } 140 | 141 | void AngleSlider::mousePressEvent(QMouseEvent* event) 142 | { 143 | updateAngle(event->localPos()); 144 | 145 | event->accept(); 146 | } 147 | 148 | void AngleSlider::mouseDoubleClickEvent(QMouseEvent* event) 149 | { 150 | setAngle(0); 151 | event->accept(); 152 | } 153 | 154 | void AngleSlider::mouseMoveEvent(QMouseEvent* event) 155 | { 156 | updateAngle(event->localPos()); 157 | 158 | event->accept(); 159 | } 160 | 161 | void AngleSlider::mouseReleaseEvent(QMouseEvent* event) 162 | { 163 | event->accept(); 164 | } 165 | 166 | void AngleSlider::touchEvent(QTouchEvent* event) 167 | { 168 | if (!event->touchPoints().empty()) 169 | updateAngle(event->touchPoints().first().pos()); 170 | event->accept(); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/HSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A simple slider 6 | 7 | // Properties: 8 | // * value: the slider value, between 0 and 1 9 | // * initialValue: the slider's initial value 10 | // * mapFunc: 11 | // function to apply on the slider value 12 | // which is already scaled linearly between 0 and 1 13 | // * orientation: vertical / horizontal 14 | // * text : the text to display on the slider 15 | Rectangle { 16 | id: slider 17 | 18 | width: 200 19 | height: 100 20 | onWidthChanged: updateHandle() 21 | onHeightChanged: updateHandle() 22 | 23 | property var styles: DarkStyle 24 | 25 | color: styles.sliderBackgroundColor 26 | border { 27 | width: height / 25. 28 | color: styles.sliderBackgroundColor 29 | } 30 | 31 | radius: styles.cornerRadius 32 | 33 | function updateHandle() { 34 | handle.update() 35 | } 36 | 37 | property alias ease: handle.ease 38 | property alias interactive: mouseArea.enabled 39 | 40 | // the value is between 0 and 1. 41 | property real value 42 | //: initialValue; 43 | property real initialValue: 0.5 44 | 45 | // value mapping 46 | property var mapFunc: function (linearVal) { 47 | return linearVal 48 | } 49 | 50 | // handle color 51 | property alias handleColor: handle.color 52 | 53 | property bool __updating: false 54 | 55 | property var linearMap: function () { 56 | var mappedVal = 0. 57 | var borderW = border.width 58 | 59 | mappedVal = handle.width / (slider.width - 2. * borderW) 60 | 61 | return Utils.clamp(mappedVal.toFixed(2), 0., 1.) 62 | } 63 | 64 | // by reseting, the handle width and height are initialized according to the initalValue 65 | Component.onCompleted: reset() 66 | 67 | // function called when updating the value from outside 68 | function updateValue() { 69 | // TODO use a function instead so that one can use linear, or log, or whatever mapping. 70 | if (!__updating) { 71 | slider.value = mapFunc() 72 | } 73 | } 74 | 75 | // called when a mouse event (onPressed / onPositionChanged) is detected 76 | // moves the slider's handle to the mouse position 77 | function moveHandle(mouseX, mouseY) { 78 | handle.width = Utils.clamp(mouseX, 0, slider.width - 2. * slider.border.width) 79 | // __updating = false; 80 | } 81 | 82 | function reset() { 83 | slider.value = slider.initialValue 84 | updateHandle() 85 | } 86 | 87 | Rectangle { 88 | id: handle 89 | 90 | x: slider.border.width 91 | y: slider.border.width 92 | 93 | height: slider.height - slider.border.width * 2 94 | 95 | color: mouseArea.pressed ? styles.pressedHandleColor : styles.handleColor 96 | 97 | onWidthChanged: { 98 | if (!resize) 99 | slider.value = mapFunc(linearMap()) 100 | } 101 | Behavior on width { 102 | enabled: handle.ease 103 | NumberAnimation { 104 | duration: 100 105 | } 106 | } 107 | 108 | property bool ease: false 109 | property bool resize: false 110 | 111 | function update() { 112 | resize = true 113 | handle.width = slider.value * (slider.width - 2. * slider.border.width) 114 | } 115 | } 116 | 117 | MouseArea { 118 | id: mouseArea 119 | anchors.fill: parent 120 | 121 | onPressed: { 122 | __updating = true 123 | handle.ease = true 124 | handle.resize = false 125 | moveHandle(mouseX, mouseY) 126 | } 127 | 128 | onPositionChanged: { 129 | handle.ease = false 130 | handle.resize = false 131 | moveHandle(mouseX, mouseY) 132 | } 133 | 134 | onReleased: __updating = false 135 | 136 | onDoubleClicked: slider.reset() 137 | } 138 | 139 | // label 140 | property alias textVisible: label.visible 141 | property alias text: label.text 142 | 143 | Label { 144 | id: label 145 | text: slider.value.toFixed(2) 146 | selected: mouseArea.pressed 147 | styles: slider.styles 148 | 149 | anchors { 150 | verticalCenter: slider.verticalCenter 151 | } 152 | property real margin: 5 153 | 154 | // the label is always on top of the handle 155 | x: Utils.clamp( 156 | handle.width + slider.border.width + margin, 157 | slider.border.width, 158 | slider.width - slider.border.width - label.width - margin) 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /src/polygon.cpp: -------------------------------------------------------------------------------- 1 | #include "polygon.hpp" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace CreativeControls 8 | { 9 | Polygon::Polygon() 10 | { 11 | setFlag(ItemHasContents, true); 12 | setAntialiasing(true); 13 | } 14 | 15 | QSGNode* 16 | Polygon::updatePaintNode(QSGNode* oldNode, QQuickItem::UpdatePaintNodeData*) 17 | { 18 | // Attention les yeux... 19 | QSGGeometryNode *fillNode{}, *borderNode{}; 20 | QSGGeometry *fillGeometry{}, *borderGeometry{}; 21 | 22 | if (!oldNode) 23 | { 24 | // D'abord un noeud racine pour le "fill" 25 | fillNode = new QSGGeometryNode; 26 | fillGeometry 27 | = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_sides); 28 | 29 | fillGeometry->setLineWidth(0); 30 | fillGeometry->setDrawingMode(GL_TRIANGLE_FAN); 31 | 32 | fillNode->setGeometry(fillGeometry); 33 | fillNode->setFlag(QSGNode::OwnsGeometry); 34 | 35 | auto fill = new QSGFlatColorMaterial; 36 | fill->setColor(m_color); 37 | fillNode->setMaterial(fill); 38 | 39 | fillNode->setFlag(QSGNode::OwnsMaterial); 40 | 41 | borderNode = new QSGGeometryNode; 42 | borderGeometry 43 | = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_sides); 44 | 45 | borderGeometry->setLineWidth(m_borderWidth); 46 | borderGeometry->setDrawingMode(GL_LINE_LOOP); 47 | 48 | borderNode->setGeometry(borderGeometry); 49 | borderNode->setFlag(QSGNode::OwnsGeometry); 50 | 51 | auto border = new QSGFlatColorMaterial; 52 | border->setColor(m_borderColor); 53 | borderNode->setMaterial(border); 54 | 55 | borderNode->setFlag(QSGNode::OwnsMaterial); 56 | fillNode->appendChildNode(borderNode); 57 | } 58 | else 59 | { 60 | fillNode = static_cast(oldNode); 61 | fillGeometry = fillNode->geometry(); 62 | fillGeometry->allocate(m_sides); 63 | auto fill = static_cast(fillNode->material()); 64 | fill->setColor(m_color); 65 | 66 | borderNode = static_cast(fillNode->childAtIndex(0)); 67 | borderGeometry = borderNode->geometry(); 68 | borderGeometry->allocate(m_sides); 69 | 70 | auto border = static_cast(borderNode->material()); 71 | border->setColor(m_borderColor); 72 | } 73 | 74 | const auto bounds = boundingRect(); 75 | const auto w = bounds.width(); 76 | const auto h = bounds.height(); 77 | const auto half_w = w / 2.; 78 | const auto half_h = h / 2.; 79 | auto fillVertices = fillGeometry->vertexDataAsPoint2D(); 80 | auto borderVertices = borderGeometry->vertexDataAsPoint2D(); 81 | 82 | const auto theta = 2. * M_PI / m_sides; 83 | 84 | // The user gives the rotation in degrees, we convert to radians for sin / 85 | // cos. 86 | const auto rotation = 2. * M_PI * m_rotation / 360.; 87 | for (int i = 0; i < m_sides; ++i) 88 | { 89 | const auto x 90 | = bounds.x() + half_w + std::cos(i * theta + rotation) * half_w; 91 | const auto y 92 | = bounds.y() + half_h + std::sin(i * theta + rotation) * half_h; 93 | fillVertices[i].set(x, y); 94 | borderVertices[i].set(x, y); 95 | } 96 | 97 | fillNode->markDirty(QSGNode::DirtyGeometry); 98 | fillNode->markDirty(QSGNode::DirtyMaterial); 99 | borderNode->markDirty(QSGNode::DirtyGeometry); 100 | borderNode->markDirty(QSGNode::DirtyMaterial); 101 | 102 | return fillNode; 103 | } 104 | 105 | int Polygon::sides() const 106 | { 107 | return m_sides; 108 | } 109 | 110 | QColor Polygon::borderColor() const 111 | { 112 | return m_borderColor; 113 | } 114 | 115 | QColor Polygon::fillColor() const 116 | { 117 | return m_color; 118 | } 119 | 120 | qreal Polygon::borderWidth() const 121 | { 122 | return m_borderWidth; 123 | } 124 | 125 | qreal Polygon::rotation() const 126 | { 127 | return m_rotation; 128 | } 129 | 130 | void Polygon::setSides(const int sides) 131 | { 132 | if (m_sides == sides) 133 | return; 134 | 135 | m_sides = sides; 136 | emit sidesChanged(m_sides); 137 | update(); 138 | } 139 | 140 | void Polygon::setBorderColor(const QColor borderColor) 141 | { 142 | if (m_borderColor == borderColor) 143 | return; 144 | 145 | m_borderColor = borderColor; 146 | emit borderColorChanged(borderColor); 147 | update(); 148 | } 149 | 150 | void Polygon::setFillColor(const QColor color) 151 | { 152 | if (m_color == color) 153 | return; 154 | 155 | m_color = color; 156 | emit fillColorChanged(m_color); 157 | update(); 158 | } 159 | 160 | void Polygon::setBorderWidth(const qreal borderWidth) 161 | { 162 | if (qFuzzyCompare(m_borderWidth, borderWidth)) 163 | return; 164 | 165 | m_borderWidth = borderWidth; 166 | emit borderWidthChanged(m_borderWidth); 167 | update(); 168 | } 169 | 170 | void Polygon::setRotation(const qreal rotation) 171 | { 172 | if (qFuzzyCompare(m_rotation, rotation)) 173 | return; 174 | 175 | m_rotation = rotation; 176 | emit rotationChanged(m_rotation); 177 | update(); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/scope.cpp: -------------------------------------------------------------------------------- 1 | #include "scope.hpp" 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace CreativeControls 8 | { 9 | Scope::Scope() 10 | { 11 | setAntialiasing(true); 12 | setFlag(ItemHasContents, true); 13 | connect(this, &Scope::heightChanged, this, &Scope::updatePath); 14 | connect(this, &Scope::widthChanged, this, &Scope::updatePath); 15 | 16 | m_scopePen.setCapStyle(Qt::RoundCap); 17 | m_scopePen.setJoinStyle(Qt::RoundJoin); 18 | m_scopePen.setWidth(2.); 19 | m_scopeBrush.setStyle(Qt::SolidPattern); 20 | } 21 | 22 | void Scope::paint(QPainter* painter) 23 | { 24 | painter->setRenderHint(QPainter::Antialiasing); 25 | painter->setRenderHint(QPainter::SmoothPixmapTransform); 26 | painter->setBrush(m_scopeBrush); 27 | painter->setPen(m_scopePen); 28 | if (m_symmetrize) 29 | { 30 | painter->drawPolygon(m_data); 31 | } 32 | else 33 | { 34 | painter->drawLines(m_data); 35 | } 36 | } 37 | 38 | QVector Scope::points() const 39 | { 40 | return m_points; 41 | } 42 | 43 | qreal Scope::yMin() const 44 | { 45 | return m_yMin; 46 | } 47 | 48 | qreal Scope::yMax() const 49 | { 50 | return m_yMax; 51 | } 52 | 53 | QColor Scope::baseColor() const 54 | { 55 | return m_baseColor; 56 | } 57 | 58 | QColor Scope::detailColor() const 59 | { 60 | return m_detailColor; 61 | } 62 | 63 | bool Scope::symmetrize() const 64 | { 65 | return m_symmetrize; 66 | } 67 | 68 | /*! 69 | * \brief Move given points to inner member. 70 | * \note \c points could be empty after executing of this method. 71 | * \param points vector of values that should be moved. 72 | */ 73 | void Scope::setPoints(QVector points) 74 | { 75 | if (m_points == points) 76 | return; 77 | 78 | m_points = std::move(points); 79 | emit pointsChanged(m_points); 80 | updatePath(); 81 | } 82 | 83 | void Scope::setYMin(const qreal yMin) 84 | { 85 | if (qFuzzyCompare(m_yMin, yMin)) 86 | return; 87 | 88 | m_yMin = yMin; 89 | emit yMinChanged(m_yMin); 90 | updatePath(); 91 | } 92 | 93 | void Scope::setYMax(const qreal yMax) 94 | { 95 | if (qFuzzyCompare(m_yMax, yMax)) 96 | return; 97 | 98 | m_yMax = yMax; 99 | emit yMaxChanged(m_yMax); 100 | updatePath(); 101 | } 102 | 103 | void Scope::setBaseColor(const QColor baseColor) 104 | { 105 | if (m_baseColor == baseColor) 106 | return; 107 | 108 | m_baseColor = baseColor; 109 | m_scopeBrush.setColor(m_baseColor); 110 | emit baseColorChanged(m_baseColor); 111 | update(); 112 | } 113 | 114 | void Scope::setDetailColor(const QColor detailColor) 115 | { 116 | if (m_detailColor == detailColor) 117 | return; 118 | 119 | m_detailColor = detailColor; 120 | m_scopePen.setColor(m_detailColor); 121 | emit detailColorChanged(m_detailColor); 122 | update(); 123 | } 124 | 125 | void Scope::setSymmetrize(const bool symmetrize) 126 | { 127 | if (m_symmetrize == symmetrize) 128 | return; 129 | 130 | m_symmetrize = symmetrize; 131 | emit symmetrizeChanged(m_symmetrize); 132 | updatePath(); 133 | } 134 | 135 | void Scope::updatePath() 136 | { 137 | if (!m_symmetrize) 138 | { 139 | // y = yMin -> height 140 | // y = yMax -> 0 141 | const auto y0 = yMin(); 142 | const auto y1 = yMax(); 143 | const auto h0 = height(); 144 | const auto h1 = 0; 145 | const auto coeff = (h1 - h0) / (y1 - y0); 146 | auto scale = [=](qreal val) { return h0 + coeff * (val - y0); }; 147 | 148 | m_data.resize(2 * m_points.size()); 149 | if (m_points.size() > 0) 150 | { 151 | const auto inc = width() / m_points.size(); 152 | 153 | auto it = m_points.cbegin(); 154 | auto x = 0.; 155 | QPointF start{x, scale(*it)}; 156 | int i = 0; 157 | const auto end = m_points.cend(); 158 | for (; it != end; ++it) 159 | { 160 | m_data[i] = start; 161 | ++i; 162 | x += inc; 163 | m_data[i] = {x, scale(*it)}; 164 | start = m_data[i]; 165 | ++i; 166 | } 167 | } 168 | } 169 | else 170 | { 171 | // yMin is not used, we assume it's zero 172 | // y = yMax -> 0 for the upper part, height for the lower part 173 | 174 | const auto h = height(); 175 | const auto y0 = 0.; 176 | const auto y1 = yMax(); 177 | const auto h0 = height() / 2.; 178 | const auto h1 = 0.; 179 | const auto coeff = (h1 - h0) / (y1 - y0); 180 | auto scale = [=](qreal val) { return h0 + coeff * (std::fabs(val) - y0); }; 181 | 182 | m_data.resize(2 * m_points.size()); 183 | 184 | if (m_points.size() > 0.) 185 | { 186 | const auto inc = width() / (m_points.size() - 1); 187 | auto x = 0.; 188 | 189 | // Draw the upper part 190 | const auto Npts = m_points.size(); 191 | for (int i = 0; i < Npts; i++) 192 | { 193 | m_data[i] = {x, scale(m_points[i])}; 194 | x += inc; 195 | } 196 | 197 | // Symmetrize 198 | for (int i = 0; i < Npts; i++) 199 | { 200 | const auto top_pt = m_data[Npts - i - 1]; 201 | m_data[Npts + i] = {top_pt.x(), (h - top_pt.y())}; 202 | } 203 | } 204 | } 205 | 206 | update(); 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /examples/OssiaClientExample.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.1 3 | import QtQuick.Layouts 1.1 4 | import com.github.jcelerier.CreativeControls 1.0 5 | import Ossia 1.0 as Ossia 6 | 7 | /** 8 | * This file presents an example of usage of the controls 9 | * provided by this library, with libossia. 10 | * libossia is a library that provides multiple network and message 11 | * protocols useful for creative coding: MIDI, OSC, OSCQuery, etc. 12 | * 13 | * More information is available on : 14 | * https://github.com/OSSIA/libossia 15 | * 16 | * In the current example, the application we are writing acts as a client: 17 | * that is, it connects to existing adresses / parameters of a remote 18 | * software / hardware. 19 | */ 20 | Page { 21 | header: Text { font.pointSize: 30 ; text: "Client example" } 22 | width: 800 23 | height: 500 24 | 25 | id: root 26 | 27 | // A midi device to which one can send messages to. 28 | Ossia.MidiSink 29 | { 30 | id: midiOutDevice 31 | // look at the console output to know MIDI devices' port number 32 | // and report the one you want to use below 33 | midiPort: 0 34 | } 35 | 36 | Ossia.MidiSource 37 | { 38 | id: midiInDevice 39 | // look at the console output to know MIDI input devices' port number 40 | // and report the one you want to use below 41 | midiPort: 0 42 | } 43 | 44 | Ossia.OSCQueryClient 45 | { 46 | id: oscqDevice 47 | // Connect to an OSCQuery server. See for instance OssiaServerExample.qml 48 | // or libossia's oscquery_publication_example 49 | address: "ws://127.0.0.1:5678" 50 | } 51 | 52 | Row { 53 | spacing: 100 54 | Column { 55 | AngleSlider 56 | { 57 | id: slider 58 | width: 200 59 | height: 200 60 | 61 | Ossia.Binding { 62 | // Scale the angle between 0 - 127 63 | on: 127 * (180 + slider.angle) / 360 64 | 65 | // The value changes are sent to CC 34 on channel 1 66 | node: '/1/control/34' 67 | device: midiOutDevice 68 | 69 | } 70 | } 71 | Label { text: "To Midi CC 34" } 72 | 73 | AngleSlider 74 | { 75 | width: 200 76 | height: 200 77 | angle: 0 78 | 79 | Ossia.Writer on angle { 80 | node: '/1/control/13' 81 | device: midiInDevice 82 | } 83 | } 84 | Label { text: "From Midi CC 13" } 85 | } 86 | ColumnLayout { 87 | Joystick 88 | { 89 | id: joystick 90 | width: 200 91 | height: 200 92 | 93 | // Modify a single propriety using a property value source 94 | Ossia.Reader on stickR { 95 | node: '/units/float' 96 | device: oscqDevice 97 | } 98 | 99 | // /units/vec2 will be updated whenever the bound expression changes 100 | Ossia.Binding { 101 | on: Qt.point(0.5 * (1 + joystick.stickX), 0.5 * (1 + joystick.stickY)) 102 | node: '/test/values' 103 | device: oscqDevice 104 | } 105 | } 106 | Label { text: "To OSCQuery server (graph and sliders)" } 107 | 108 | Item { height: 50 } 109 | 110 | Text { 111 | id: txt 112 | anchors.topMargin: 50 113 | text: "Callback from OSCQuery server (angle slider)" 114 | 115 | // This updates the text according to messages sent 116 | // by the remote software 117 | Ossia.Callback 118 | { 119 | device: oscqDevice 120 | onValueChanged: txt.text = "foo " + value.toFixed(2) + " bar" 121 | node: '/test/angle' 122 | } 123 | } 124 | 125 | // More concise form using a property value source: 126 | Text { 127 | anchors.topMargin: 50 128 | text: "Callback from OSCQuery server (angle slider)" 129 | Ossia.Writer on text { 130 | node: '/test/angle' 131 | device: oscqDevice 132 | } 133 | } 134 | } 135 | } 136 | 137 | Component.onCompleted: 138 | { 139 | // List midi devices 140 | console.log("get MIDI output devices..."); 141 | var midi_outs = midiOutDevice.getMIDIOutputDevices(); 142 | for(var midi in midi_outs) 143 | console.log("device: '" + midi + "'\t\tport number: ", midi_outs[midi]) 144 | // midi_outs[midi] is the value to pass to "midiPort" 145 | 146 | console.log("get MIDI input devices..."); 147 | var midi_ins = midiInDevice.getMIDIInputDevices(); 148 | for(var midi in midi_ins) 149 | console.log("device: '" + midi + "'\t\tport number: ", midi_ins[midi]) 150 | // midi_ins[midi] is the value to pass to "midiPort" 151 | 152 | // Call this at the end to set-up the connections 153 | oscqDevice.openOSCQueryClient(oscqDevice.address, oscqDevice.localPort) 154 | oscqDevice.remap(root) 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/VSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // A simple slider 6 | 7 | // Properties: 8 | // * value: the slider value, between 0 and 1 9 | // * initialValue: the slider's initial value 10 | // * mapFunc: 11 | // function to apply on the slider value 12 | // which is already scaled linearly between 0 and 1 13 | // * orientation: vertical / horizontal 14 | // * text : the text to display on the slider 15 | Rectangle { 16 | id: slider 17 | 18 | width: 100 19 | height: 200 20 | onWidthChanged: updateHandle() 21 | onHeightChanged: updateHandle() 22 | 23 | property var styles: DarkStyle 24 | 25 | color: styles.sliderBackgroundColor 26 | border { 27 | width: width / 25. 28 | color: styles.sliderBackgroundColor 29 | } 30 | radius: styles.cornerRadius 31 | 32 | function updateHandle() { 33 | antiHandle.update() 34 | } 35 | 36 | property alias ease: antiHandle.ease 37 | property alias interactive: mouseArea.enabled 38 | 39 | // the value is between 0 and 1. 40 | property real value 41 | //: initialValue; 42 | property real initialValue: 0.5 43 | 44 | // value mapping 45 | property var mapFunc: function (linearVal) { 46 | return linearVal 47 | } 48 | 49 | // handle color 50 | property alias handleColor: handle.color 51 | 52 | property bool __updating: false 53 | 54 | property var linearMap: function () { 55 | var mappedVal = 0. 56 | var borderW = border.width 57 | 58 | mappedVal = (handle.height - antiHandle.height) / (slider.height - 2. * borderW) 59 | 60 | return Utils.clamp(mappedVal.toFixed(2), 0., 1.) 61 | } 62 | 63 | // by reseting, the handle width and height are initialized according to the initalValue 64 | Component.onCompleted: reset() 65 | 66 | // function called when updating the value from outside 67 | function updateValue() { 68 | // TODO use a function instead so that one can use linear, or log, or whatever mapping. 69 | if (!__updating) { 70 | slider.value = mapFunc() 71 | } 72 | } 73 | 74 | // called when a mouse event (onPressed / onPositionChanged) is detected 75 | // moves the slider's handle to the mouse position 76 | function moveHandle(mouseX, mouseY) { 77 | 78 | antiHandle.height = Utils.clamp( 79 | mouseY - slider.border.width, 0, 80 | slider.height - 2. * slider.border.width) 81 | // __updating = false; 82 | } 83 | 84 | function reset() { 85 | slider.value = slider.initialValue 86 | updateHandle(); 87 | } 88 | 89 | Rectangle { 90 | id: handle 91 | 92 | width: slider.width - slider.border.width * 2 93 | height: slider.height - slider.border.width * 2 94 | anchors.centerIn: parent 95 | color: mouseArea.pressed ? styles.pressedHandleColor : styles.handleColor 96 | } 97 | 98 | Rectangle { 99 | id: antiHandle 100 | 101 | x: slider.border.width 102 | y: slider.border.width 103 | 104 | width: slider.width - slider.border.width * 2 105 | 106 | color: slider.color 107 | radius: styles.cornerRadius 108 | 109 | Behavior on height { 110 | enabled: antiHandle.ease 111 | NumberAnimation { 112 | duration: 100 113 | } 114 | } 115 | onHeightChanged: { 116 | if (!resize) 117 | slider.value = mapFunc(linearMap()) 118 | } 119 | 120 | property bool ease: false 121 | property bool resize: false 122 | 123 | function update() { 124 | resize = true 125 | antiHandle.height = (1.0 - slider.value) * (slider.height - 2*slider.border.width) 126 | } 127 | } 128 | 129 | MouseArea { 130 | id: mouseArea 131 | anchors.fill: parent 132 | 133 | onPressed: { 134 | __updating = true 135 | antiHandle.ease = true 136 | antiHandle.resize = false 137 | moveHandle(mouseX, mouseY) 138 | } 139 | 140 | onPositionChanged: { 141 | antiHandle.resize = false 142 | antiHandle.ease = false 143 | moveHandle(mouseX, mouseY) 144 | } 145 | 146 | onReleased: __updating = false 147 | 148 | onDoubleClicked: { 149 | antiHandle.ease = true 150 | antiHandle.resize = false 151 | slider.reset() 152 | } 153 | } 154 | 155 | // label 156 | property alias textVisible: label.visible 157 | property alias text: label.text 158 | 159 | Label { 160 | id: label 161 | text: slider.value.toFixed(2) 162 | styles: slider.styles 163 | selected: mouseArea.pressed 164 | anchors { 165 | horizontalCenter: slider.horizontalCenter 166 | } 167 | 168 | property real margin: 5 169 | // the label is always on top of the handle 170 | y: Utils.clamp(antiHandle.height - label.height, 171 | slider.border.width + margin, 172 | slider.height - label.height - margin) 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/xytarget.cpp: -------------------------------------------------------------------------------- 1 | #include "xytarget.hpp" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | namespace CreativeControls 9 | { 10 | XYTarget::XYTarget() 11 | { 12 | setFlag(ItemHasContents, true); 13 | setAcceptedMouseButtons(Qt::LeftButton); 14 | setAntialiasing(true); 15 | m_pen.setCosmetic(true); 16 | m_brush.setStyle(Qt::SolidPattern); 17 | 18 | connect(this, &QQuickItem::widthChanged, this, &XYTarget::updatePenWidth); 19 | connect(this, &QQuickItem::heightChanged, this, &XYTarget::updatePenWidth); 20 | } 21 | 22 | void XYTarget::paint(QPainter* painter) 23 | { 24 | const auto w = m_centerX * width(); 25 | const auto h = m_centerY * height(); 26 | 27 | painter->setRenderHint(QPainter::RenderHint::Antialiasing, false); 28 | painter->setPen(m_pen); 29 | painter->setBrush(m_brush); 30 | painter->drawLine(w, 0., w, height()); 31 | painter->drawLine(0., h, width(), h); 32 | painter->setRenderHint(QPainter::RenderHint::Antialiasing, true); 33 | painter->drawEllipse( 34 | w - m_radius, h - m_radius, 2. * m_radius, 2. * m_radius); 35 | } 36 | 37 | void XYTarget::mousePressEvent(QMouseEvent* event) 38 | { 39 | if (contains(event->pos())) 40 | { 41 | auto new_x = event->pos().x() / width(); 42 | auto new_y = event->pos().y() / height(); 43 | 44 | m_lastPos = event->pos(); 45 | setCenterX(new_x); 46 | setCenterY(new_y); 47 | setPressed(true); 48 | event->accept(); 49 | return; 50 | } 51 | event->ignore(); 52 | } 53 | 54 | void XYTarget::mouseDoubleClickEvent(QMouseEvent* event) 55 | { 56 | event->ignore(); 57 | } 58 | 59 | void XYTarget::mouseMoveEvent(QMouseEvent* event) 60 | { 61 | auto new_x = event->pos().x() / width(); 62 | auto new_y = event->pos().y() / height(); 63 | 64 | m_lastPos = event->pos(); 65 | setCenterX(new_x); 66 | setCenterY(new_y); 67 | event->accept(); 68 | } 69 | 70 | void XYTarget::mouseReleaseEvent(QMouseEvent* event) 71 | { 72 | setPressed(false); 73 | event->accept(); 74 | } 75 | 76 | void XYTarget::touchEvent(QTouchEvent* event) 77 | { 78 | if (!event->touchPoints().empty()) 79 | { 80 | setPressed(true); 81 | const auto& first = event->touchPoints().first(); 82 | switch (first.state()) 83 | { 84 | case Qt::TouchPointPressed: 85 | { 86 | if (contains(first.pos())) 87 | { 88 | m_lastPos = first.pos(); 89 | event->accept(); 90 | } 91 | else 92 | { 93 | event->ignore(); 94 | } 95 | break; 96 | } 97 | case Qt::TouchPointMoved: 98 | { 99 | auto new_x = first.pos().x() / width(); 100 | auto new_y = first.pos().y() / height(); 101 | 102 | m_lastPos = first.pos(); 103 | setCenterX(new_x); 104 | setCenterY(new_y); 105 | event->accept(); 106 | 107 | break; 108 | } 109 | case Qt::TouchPointStationary: 110 | break; 111 | case Qt::TouchPointReleased: 112 | event->accept(); 113 | break; 114 | default: 115 | break; 116 | } 117 | } 118 | else 119 | { 120 | setPressed(false); 121 | } 122 | } 123 | 124 | bool XYTarget::contains(const QPointF& point) const 125 | { 126 | const auto w = m_centerX * width(); 127 | const auto h = m_centerY * height(); 128 | return point.x() > (w - m_radius) && point.x() < (w + m_radius) 129 | && point.y() > (h - m_radius) && point.y() < (h + m_radius); 130 | } 131 | 132 | void XYTarget::updatePenWidth() 133 | { 134 | using namespace std; 135 | m_pen.setWidthF(lround(std::min(height(), width()) / 40.)); 136 | 137 | m_radius = std::min(height(), width()) / m_radiusScale; 138 | } 139 | 140 | qreal XYTarget::centerX() const 141 | { 142 | return m_centerX; 143 | } 144 | 145 | qreal XYTarget::centerY() const 146 | { 147 | return m_centerY; 148 | } 149 | 150 | qreal XYTarget::radiusScale() const 151 | { 152 | return m_radiusScale; 153 | } 154 | 155 | QColor XYTarget::color() const 156 | { 157 | return m_color; 158 | } 159 | 160 | bool XYTarget::pressed() const 161 | { 162 | return m_pressed; 163 | } 164 | 165 | void XYTarget::setCenterX(const qreal centerX) 166 | { 167 | if (qFuzzyCompare(m_centerX, centerX)) 168 | return; 169 | 170 | m_centerX = qBound(0., centerX, 1.); 171 | emit centerXChanged(centerX); 172 | update(); 173 | } 174 | 175 | void XYTarget::setCenterY(const qreal centerY) 176 | { 177 | if (qFuzzyCompare(m_centerY, centerY)) 178 | return; 179 | 180 | m_centerY = qBound(0., centerY, 1.); 181 | emit centerYChanged(centerY); 182 | update(); 183 | } 184 | 185 | void XYTarget::setRadiusScale(const qreal radiusScale) 186 | { 187 | if (qFuzzyCompare(m_radiusScale, radiusScale)) 188 | return; 189 | 190 | m_radiusScale = radiusScale; 191 | emit radiusScaleChanged(m_radiusScale); 192 | updatePenWidth(); 193 | update(); 194 | } 195 | 196 | void XYTarget::setColor(const QColor color) 197 | { 198 | if (m_color == color) 199 | return; 200 | 201 | m_color = color; 202 | m_pen.setColor(m_color); 203 | m_brush.setColor(m_color); 204 | emit colorChanged(m_color); 205 | update(); 206 | } 207 | 208 | void XYTarget::setPressed(const bool pressed) 209 | { 210 | if (pressed != m_pressed) 211 | { 212 | m_pressed = pressed; 213 | pressedChanged(m_pressed); 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /com_github_jcelerier_qml-creative-controls.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | CreativeControls/qmldir-qpm 4 | CreativeControls/AngleSlider.qml 5 | CreativeControls/ArcSlider.qml 6 | CreativeControls/ColorChooser.qml 7 | CreativeControls/ColorSlider.qml 8 | CreativeControls/ColorWheel.qml 9 | CreativeControls/Container.qml 10 | CreativeControls/CosInfluence.qml 11 | CreativeControls/DarkStyle.qml 12 | CreativeControls/DonutSlider.qml 13 | CreativeControls/Frame.qml 14 | CreativeControls/Graph.qml 15 | CreativeControls/Graph2D.qml 16 | CreativeControls/HRangeSlider.qml 17 | CreativeControls/HSlider.qml 18 | CreativeControls/HSLSlider.qml 19 | CreativeControls/HSVSlider.qml 20 | CreativeControls/Joystick.qml 21 | CreativeControls/Keyboard.qml 22 | CreativeControls/Label.qml 23 | CreativeControls/Leds.qml 24 | CreativeControls/LightStyle.qml 25 | CreativeControls/Matrix.qml 26 | CreativeControls/MultiSlider.qml 27 | CreativeControls/Random1D.qml 28 | CreativeControls/Random2D.qml 29 | CreativeControls/Random3D.qml 30 | CreativeControls/RangeSlider.qml 31 | CreativeControls/RGBSlider.qml 32 | CreativeControls/Scale.qml 33 | CreativeControls/Scope.qml 34 | CreativeControls/Spat.qml 35 | CreativeControls/Spectrum.qml 36 | CreativeControls/Step.qml 37 | CreativeControls/Styles.qml 38 | CreativeControls/Switch.qml 39 | CreativeControls/ToggleSwitch.qml 40 | CreativeControls/Trajectory.qml 41 | CreativeControls/Utils.qml 42 | CreativeControls/VRangeSlider.qml 43 | CreativeControls/VSlider.qml 44 | CreativeControls/XYPad.qml 45 | 46 | 47 | 48 | CreativeControls/qmldir-qpm 49 | CreativeControls/AngleSlider.qml 50 | CreativeControls/ArcSlider.qml 51 | CreativeControls/ColorChooser.qml 52 | CreativeControls/ColorSlider.qml 53 | CreativeControls/ColorWheel.qml 54 | CreativeControls/Container.qml 55 | CreativeControls/CosInfluence.qml 56 | CreativeControls/DarkStyle.qml 57 | CreativeControls/DonutSlider.qml 58 | CreativeControls/Frame.qml 59 | CreativeControls/Graph.qml 60 | CreativeControls/Graph2D.qml 61 | CreativeControls/HRangeSlider.qml 62 | CreativeControls/HSlider.qml 63 | CreativeControls/HSLSlider.qml 64 | CreativeControls/HSVSlider.qml 65 | CreativeControls/Joystick.qml 66 | CreativeControls/Keyboard.qml 67 | CreativeControls/Label.qml 68 | CreativeControls/Leds.qml 69 | CreativeControls/LightStyle.qml 70 | CreativeControls/Matrix.qml 71 | CreativeControls/MultiSlider.qml 72 | CreativeControls/Random1D.qml 73 | CreativeControls/Random2D.qml 74 | CreativeControls/Random3D.qml 75 | CreativeControls/RangeSlider.qml 76 | CreativeControls/RGBSlider.qml 77 | CreativeControls/Scale.qml 78 | CreativeControls/Scope.qml 79 | CreativeControls/Spat.qml 80 | CreativeControls/Spectrum.qml 81 | CreativeControls/Step.qml 82 | CreativeControls/Styles.qml 83 | CreativeControls/Switch.qml 84 | CreativeControls/ToggleSwitch.qml 85 | CreativeControls/Trajectory.qml 86 | CreativeControls/Utils.qml 87 | CreativeControls/VRangeSlider.qml 88 | CreativeControls/VSlider.qml 89 | CreativeControls/XYPad.qml 90 | 91 | 92 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/HRangeSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // Slider with a min and max 6 | Rectangle { 7 | id: rangeSlider 8 | 9 | width: 300 10 | height: 100 11 | // onWidthChanged: handle.updateHandle(); 12 | // onHeightChanged: handle.updateHandle(); 13 | property var styles: DarkStyle 14 | 15 | color: styles.sliderBackgroundColor 16 | border { 17 | width: height / 25. 18 | color: styles.sliderBackgroundColor 19 | } 20 | 21 | radius: styles.cornerRadius 22 | 23 | // the value is between 0 and 1. 24 | property real value 25 | 26 | //: initialValue; 27 | property real minValue: initialMinValue 28 | property real maxValue: initialMaxValue 29 | 30 | property real initialMinValue: 0.4 31 | property real initialMaxValue: 0.8 32 | 33 | // value mapping 34 | property var mapFunc: function (linearVal) { 35 | return linearVal 36 | } 37 | 38 | property bool __updating: false 39 | 40 | // by reseting, the handle width and height are initialized according to the initalValue 41 | Component.onCompleted: reset() 42 | 43 | // function called when updating the value from outside 44 | function updateValue() { 45 | // TODO use a function instead so that one can use linear, or log, or whatever mapping. 46 | if (!__updating) { 47 | rangeSlider.value = mapFunc() 48 | } 49 | } 50 | 51 | function reset() { 52 | minHandle.reset() 53 | maxHandle.reset() 54 | } 55 | 56 | property real handleSize: 40. 57 | 58 | property color handleColor: styles.handleColor 59 | 60 | Rectangle { 61 | id: range 62 | 63 | anchors { 64 | right: maxHandle.left 65 | verticalCenter: rangeSlider.verticalCenter 66 | } 67 | 68 | width: maxHandle.x - (minHandle.x + minHandle.width) 69 | height: rangeSlider.height - rangeSlider.border.width * 2 70 | 71 | color: styles.colorOn 72 | 73 | function updateValues(offset) { 74 | console.log(offset) 75 | 76 | var xMax = maxHandle.x + offset 77 | var xMin = minHandle.x + offset 78 | 79 | var clampedMaxX = Utils.clamp(xMax + handleSize / 2., 80 | minHandle.x + 3. * handleSize / 2., 81 | rangeSlider.width - handleSize / 2.) 82 | var clampedMinX = Utils.clamp(xMin + handleSize / 2., 83 | handleSize / 2., 84 | xMax - handleSize / 2.) 85 | 86 | var tmp = Utils.clamp(Utils.rescale( 87 | clampedMaxX, 3. * handleSize / 2., 88 | rangeSlider.width - handleSize / 2., 0., 89 | 1.), 0, 1) 90 | rangeSlider.maxValue = tmp 91 | 92 | rangeSlider.minValue = Utils.clamp(Utils.rescale( 93 | clampedMinX, handleSize / 2., rangeSlider.width 94 | - 3. * handleSize / 2., 0., 95 | 1.), 0, 1) 96 | } 97 | } 98 | 99 | Rectangle { 100 | id: minHandle 101 | 102 | width: handleSize 103 | height: rangeSlider.height - rangeSlider.border.width * 2 104 | 105 | x: Utils.rescale( 106 | rangeSlider.minValue, 0., 1., handleSize / 2., 107 | rangeSlider.width - 3. * handleSize / 2.) - handleSize / 2 108 | 109 | y: rangeSlider.border.width 110 | 111 | color: styles.detail 112 | 113 | function moveHandle(mouseX, mouseY) { 114 | var clampedX = Utils.clamp(mouseX, handleSize / 2., 115 | maxHandle.x - handleSize / 2.) 116 | rangeSlider.minValue = Utils.rescale( 117 | clampedX, handleSize / 2., 118 | rangeSlider.width - handleSize * 1.5, 0., 1.) 119 | // __updating = false; 120 | } 121 | 122 | function reset() { 123 | rangeSlider.minValue = rangeSlider.initialMinValue 124 | } 125 | } 126 | 127 | Rectangle { 128 | id: maxHandle 129 | 130 | width: handleSize 131 | height: rangeSlider.height - rangeSlider.border.width * 2 132 | 133 | x: Utils.rescale(rangeSlider.maxValue, 0., 1., 3. * handleSize / 2., rangeSlider.width - handleSize / 2.) - handleSize / 2. 134 | y: rangeSlider.border.width 135 | color: styles.detail 136 | 137 | function moveHandle(mouseX, mouseY) { 138 | var clampedX = Utils.clamp(mouseX, minHandle.x + minHandle.width + handleSize / 2, rangeSlider.width - handleSize / 2) 139 | rangeSlider.maxValue = Utils.rescale(clampedX, handleSize * 1.5, rangeSlider.width - handleSize / 2, 0., 1.) 140 | } 141 | 142 | function reset() { 143 | rangeSlider.maxValue = rangeSlider.initialMaxValue 144 | } 145 | } 146 | 147 | Text { 148 | anchors.fill: minHandle 149 | 150 | // anchors.horizontalCenter: range.horizontalCenter 151 | horizontalAlignment: Text.AlignHCenter 152 | verticalAlignment: Text.AlignVCenter 153 | 154 | text: rangeSlider.minValue.toFixed(2) 155 | color: styles.labelColor 156 | font.bold: true 157 | } 158 | 159 | Text { 160 | anchors.fill: maxHandle 161 | 162 | horizontalAlignment: Text.AlignHCenter 163 | verticalAlignment: Text.AlignVCenter 164 | text: rangeSlider.maxValue.toFixed(2) 165 | color: styles.labelColor 166 | font.bold: true 167 | } 168 | 169 | MouseArea { 170 | id: mouseArea 171 | anchors.fill: parent 172 | property var handlePressed: null 173 | property bool moveRange: false 174 | property real offset: 0 175 | onPressed: { 176 | __updating = true 177 | 178 | if (mouseX < minHandle.x + minHandle.width) { 179 | handlePressed = minHandle 180 | handlePressed.moveHandle(mouseX, mouseY) 181 | } else if (mouseX > maxHandle.x) { 182 | handlePressed = maxHandle 183 | handlePressed.moveHandle(mouseX, mouseY) 184 | } else { 185 | moveRange = true 186 | offset = mouseX - range.x 187 | } 188 | } 189 | 190 | onPositionChanged: { 191 | if (handlePressed) 192 | handlePressed.moveHandle(mouseX, mouseY) 193 | else if (moveRange) { 194 | var newVal = 0 195 | newVal = Utils.clamp( 196 | mouseX - offset, handleSize, 197 | rangeSlider.width - (range.width + handleSize)) 198 | newVal -= range.x 199 | range.updateValues(newVal) 200 | } 201 | } 202 | 203 | onReleased: { 204 | handlePressed = null 205 | __updating = false 206 | moveRange = false 207 | } 208 | 209 | onDoubleClicked: { 210 | if (Utils.inside(mouseX, mouseY, maxHandle.x, maxHandle.y, 211 | maxHandle.width, maxHandle.height)) { 212 | maxHandle.reset() 213 | } else if (Utils.inside(mouseX, mouseY, minHandle.x, minHandle.y, 214 | minHandle.width, minHandle.height)) { 215 | minHandle.reset() 216 | } else 217 | rangeSlider.reset() 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/ArcSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | import QtGraphicalEffects 1.0 4 | 5 | 6 | // arc slider 7 | Rectangle { 8 | id: arcSlider 9 | width: 200 10 | height: width 11 | onWidthChanged: canvas.requestPaint() 12 | onHeightChanged: canvas.requestPaint() 13 | 14 | radius: width / 2. 15 | 16 | color: "transparent" 17 | 18 | property real innerRadius: radius * 0.7 / 0.9 * 0.5 19 | property real channels: 3 20 | property real channelIndex: 0 21 | 22 | property real angleStart: channelIndex * 2 * Math.PI / channels 23 | property real angleEnd: (channelIndex + 1) * 2 * Math.PI / channels 24 | 25 | property real value: (angle * Math.PI / 180. - angleStart) / (angleEnd - angleStart) 26 | 27 | property var colorSpace: Qt.hsla //function(){return Qt.rgba()} 28 | 29 | property real angle: 180 / Math.PI * (arcSlider.angleStart + arcSlider.angleEnd) * 0.5 30 | Behavior on angle { 31 | id: easing 32 | enabled: false 33 | NumberAnimation { 34 | easing.type: Easing.InOutCubic 35 | } 36 | } 37 | 38 | function moveHandle(newAngle) { 39 | arcSlider.angle = 180 / Math.PI * newAngle 40 | canvas.requestPaint() 41 | } 42 | 43 | function getColor(c) { 44 | switch (channelIndex) { 45 | case 0: 46 | return colorSpace === Qt.rgba 47 | ? colorSpace(c, 0., 0., 1.) 48 | : colorSpace === Qt.hsva ? colorSpace(c, 1., 1.0, 1.) : colorSpace(c, 1., 0.5, 1.) 49 | case 1: 50 | return colorSpace === Qt.rgba 51 | ? colorSpace(0., c, 0., 1.) 52 | : colorSpace(hue, c, 0.5, 1.) 53 | case 2: 54 | return colorSpace == Qt.rgba 55 | ? colorSpace(0., 0., c, 1.) 56 | : colorSpace(hue, 0.5, c, 1.) 57 | default: 58 | return "transparent" 59 | } 60 | } 61 | 62 | property real hue: 0. 63 | 64 | function updateHue(h) { 65 | arcSlider.hue = h 66 | canvas.requestPaint() 67 | } 68 | 69 | function reset() { 70 | moveHandle((arcSlider.angleStart + arcSlider.angleEnd) * 0.5) 71 | } 72 | 73 | property bool drawHue: arcSlider.channelIndex == 0 74 | && (arcSlider.colorSpace === Qt.hsla 75 | || arcSlider.colorSpace === Qt.hsva) 76 | 77 | Canvas { 78 | id: canvas 79 | // width : parent.width *2. 80 | // height : parent.width *2. 81 | anchors.fill: parent 82 | antialiasing: true 83 | smooth: true 84 | visible: true 85 | 86 | //visible : !shader.visible 87 | //anchors.fill : parent 88 | onPaint: { 89 | var ctx = getContext("2d") 90 | ctx.reset() 91 | 92 | ctx.clearRect(0, 0, canvas.width, canvas.height) 93 | ctx.lineWidth = 0 94 | 95 | var center = arcSlider.innerRadius + (arcSlider.radius - arcSlider.innerRadius) * 0.5 96 | 97 | /* var grd = ctx.createLinearlGradient( arcSlider.radius + center * Math.cos(arcSlider.angleStart), 98 | arcSlider.radius + center * Math.sin(arcSlider.angleStart), 99 | 100 | arcSlider.radius + center * Math.cos(arcSlider.angleEnd), 101 | arcSlider.radius + center * Math.sin(arcSlider.angleEnd));*/ 102 | var origin = Qt.point(canvas.width / 2., canvas.height / 2.) 103 | var grd = ctx.createLinearGradient( 104 | arcSlider.radius + center * Math.cos(arcSlider.angleStart), 105 | arcSlider.radius + center * Math.sin(arcSlider.angleStart), 106 | arcSlider.radius + center * Math.cos(arcSlider.angleEnd), 107 | arcSlider.radius + center * Math.sin(arcSlider.angleEnd)) 108 | for (var i = 0; i < 50; i++) { 109 | grd.addColorStop(i / 50., arcSlider.getColor(i / 50.)) 110 | } 111 | 112 | ctx.strokeStyle = Styles.background 113 | ctx.fillStyle = grd 114 | 115 | ctx.lineWidth = 1 116 | ctx.lineCap = "round" 117 | ctx.lineJoin = "round" 118 | 119 | if (!arcSlider.drawHue) { 120 | ctx.beginPath() 121 | ctx.arc(origin.x, origin.y, arcSlider.innerRadius, 122 | arcSlider.angleStart, arcSlider.angleEnd) 123 | ctx.arc(origin.x, origin.y, arcSlider.radius, 124 | arcSlider.angleEnd, arcSlider.angleStart - 2. * Math.PI) 125 | ctx.closePath() 126 | 127 | //ctx.fillRect(0, 0, canvas.width, canvas.height); 128 | ctx.fill() 129 | } else { 130 | var nbLines = arcSlider.width / 2. 131 | for (var i = 0; i < nbLines; i++) { 132 | var iAng = arcSlider.angleStart + i 133 | * (arcSlider.angleEnd - arcSlider.angleStart) / nbLines 134 | 135 | /* var ang = Math.PI - Math.atan2(arcSlider.radius *Math.cos(iAng) - radius*2., 136 | arcSlider.radius *Math.sin(iAng) - radius*2.) ; 137 | ang -= Math.PI/2. ; 138 | ang += ang < 0. ? 2.*Math.PI : 0.;*/ 139 | var color = (iAng - arcSlider.angleStart) 140 | / (arcSlider.angleEnd - arcSlider.angleStart) 141 | ctx.strokeStyle = Qt.hsla(color, 1., 0.5, 1.0) 142 | ctx.lineWidth = 3. 143 | 144 | ctx.beginPath() 145 | 146 | ctx.moveTo(arcSlider.radius + (arcSlider.innerRadius + ctx.lineWidth * 0.5) * Math.cos(iAng), 147 | arcSlider.radius + (arcSlider.innerRadius + ctx.lineWidth * 0.5) * Math.sin(iAng)) 148 | ctx.lineTo(arcSlider.radius + (arcSlider.radius - ctx.lineWidth) * Math.cos(iAng), 149 | arcSlider.radius + (arcSlider.radius - ctx.lineWidth) * Math.sin(iAng)) 150 | ctx.stroke() 151 | } 152 | } 153 | 154 | // if(shader.visible)ctx.stroke(); 155 | ctx.lineWidth = 0.2 * arcSlider.innerRadius 156 | 157 | if (arcSlider.drawHue) { 158 | ctx.strokeStyle = arcSlider.getColor(arcSlider.value) 159 | ctx.fillStyle = arcSlider.getColor(arcSlider.value) 160 | } else 161 | ctx.strokeStyle = grd 162 | 163 | ctx.beginPath() 164 | 165 | var lineLength = 0.84 * arcSlider.innerRadius 166 | 167 | var perimeter = 2. * Math.PI * lineLength 168 | * (arcSlider.angleEnd - arcSlider.angleStart) / (2. * Math.PI) 169 | var angleOffset = (ctx.lineWidth * 0.5) / perimeter 170 | * (arcSlider.angleEnd - arcSlider.angleStart) 171 | var clampedAngle = Utils.clamp(Math.PI / 180. * arcSlider.angle, 172 | arcSlider.angleStart + angleOffset, 173 | arcSlider.angleEnd - angleOffset) 174 | var angleToDeg = Math.PI / 180. * arcSlider.angle 175 | ctx.moveTo(origin.x + (lineLength) * Math.cos(clampedAngle), 176 | origin.y + (lineLength) * Math.sin(clampedAngle)) 177 | ctx.lineTo(origin.x, origin.y) 178 | ctx.stroke() 179 | ctx.fill() 180 | } 181 | } 182 | 183 | function isInside(angleRad) { 184 | if (angleRad > arcSlider.angleStart && angleRad < arcSlider.angleEnd) 185 | return true 186 | return false 187 | } 188 | 189 | /* 190 | Text 191 | { 192 | x : arcSlider.radius + 0.2 * arcSlider.radius * Math.cos(Math.PI /180. * arcSlider.angle) 193 | y : arcSlider.radius + 0.2 * arcSlider.radius * Math.sin(Math.PI /180. * arcSlider.angle) 194 | color : "red" 195 | text : channelIndex 196 | }*/ 197 | } 198 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/VRangeSlider.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.6 2 | import com.github.jcelerier.CreativeControls 1.0 3 | 4 | 5 | // Slider with a min and max 6 | Rectangle { 7 | id: rangeSlider 8 | 9 | width: 100 10 | height: 200 11 | // onWidthChanged: handle.updateHandle(); 12 | // onHeightChanged: handle.updateHandle(); 13 | property var styles: DarkStyle 14 | 15 | color: styles.sliderBackgroundColor 16 | border { 17 | width: width / 25. 18 | color: styles.sliderBackgroundColor 19 | } 20 | radius: styles.cornerRadius 21 | 22 | // the value is between 0 and 1. 23 | property real value 24 | 25 | //: initialValue; 26 | property real minValue: initialMinValue 27 | property real maxValue: initialMaxValue 28 | 29 | property real initialMinValue: 0.4 30 | property real initialMaxValue: 0.8 31 | 32 | // value mapping 33 | property var mapFunc: function (linearVal) { 34 | return linearVal 35 | } 36 | 37 | property bool __updating: false 38 | 39 | // by reseting, the handle width and height are initialized according to the initalValue 40 | Component.onCompleted: reset() 41 | 42 | // function called when updating the value from outside 43 | function updateValue() { 44 | // TODO use a function instead so that one can use linear, or log, or whatever mapping. 45 | if (!__updating) { 46 | rangeSlider.value = mapFunc() 47 | } 48 | } 49 | 50 | function reset() { 51 | minHandle.reset() 52 | maxHandle.reset() 53 | } 54 | 55 | property real handleSize: rangeSlider.border.width * 5. 56 | 57 | property color handleColor: styles.handleColor 58 | 59 | Rectangle { 60 | id: range 61 | 62 | anchors { 63 | top: maxHandle.bottom 64 | horizontalCenter: rangeSlider.horizontalCenter 65 | } 66 | 67 | width: rangeSlider.width - rangeSlider.border.width * 2 68 | height: minHandle.y - (maxHandle.y + maxHandle.height) 69 | 70 | color: mouseArea.moveRange ? styles.colorOnLighter : styles.colorOn 71 | 72 | function updateValues(offset) { 73 | 74 | var yMax = maxHandle.y + offset 75 | var yMin = minHandle.y + offset 76 | 77 | var clampedMaxY = Utils.clamp(yMax + handleSize / 2., 78 | handleSize / 2., 79 | minHandle.y - handleSize / 2.) 80 | var clampedMinY = Utils.clamp(yMin + handleSize / 2., 81 | yMax + 3. * handleSize / 2., 82 | rangeSlider.height - handleSize / 2.) 83 | 84 | rangeSlider.maxValue = Utils.clamp(Utils.rescale( 85 | rangeSlider.height - clampedMaxY, 86 | 3. * handleSize / 2., rangeSlider.height 87 | - handleSize / 2., 88 | 0., 1.), 0, 1) 89 | rangeSlider.minValue = Utils.clamp(Utils.rescale( 90 | rangeSlider.height - clampedMinY, 91 | handleSize / 2., 92 | rangeSlider.height - 3. * handleSize / 2., 93 | 0., 1.), 0, 1) 94 | } 95 | } 96 | 97 | Rectangle { 98 | id: minHandle 99 | 100 | width: rangeSlider.width - rangeSlider.border.width * 2 101 | height: handleSize 102 | 103 | x: rangeSlider.border.width 104 | 105 | y: Utils.rescale(1. - rangeSlider.minValue, 0., 1., 106 | 3. * handleSize / 2., 107 | rangeSlider.height - handleSize / 2.) - handleSize / 2. 108 | 109 | color: mouseArea.handlePressed == minHandle 110 | ? styles.pressedHandlesColor : styles.handlesColor 111 | 112 | function moveHandle(mouseX, mouseY) { 113 | var clampedY = Utils.clamp( 114 | mouseY, 115 | maxHandle.y + maxHandle.height + handleSize / 2., 116 | rangeSlider.height - handleSize / 2.) 117 | rangeSlider.minValue = Utils.rescale( 118 | rangeSlider.height - clampedY, handleSize / 2., 119 | rangeSlider.height - 3. * handleSize / 2., 0., 1.) 120 | 121 | // __updating = false; 122 | } 123 | 124 | function reset() { 125 | rangeSlider.minValue = rangeSlider.initialMinValue 126 | } 127 | } 128 | 129 | Rectangle { 130 | id: maxHandle 131 | 132 | width: rangeSlider.width - rangeSlider.border.width * 2 133 | height: handleSize 134 | 135 | x: rangeSlider.border.width 136 | y: Utils.rescale( 137 | 1. - rangeSlider.maxValue, 0., 1., handleSize / 2., 138 | rangeSlider.height - 3. * handleSize / 2.) - handleSize / 2. 139 | 140 | color: mouseArea.handlePressed == maxHandle 141 | ? styles.pressedHandlesColor : styles.handlesColor 142 | 143 | function moveHandle(mouseX, mouseY) { 144 | var clampedY = Utils.clamp(mouseY, handleSize / 2., 145 | minHandle.y - handleSize / 2.) 146 | rangeSlider.maxValue = Utils.rescale( 147 | rangeSlider.height - clampedY, 3. * handleSize / 2., 148 | rangeSlider.height - handleSize / 2., 0., 1.) 149 | } 150 | function reset() { 151 | rangeSlider.maxValue = rangeSlider.initialMaxValue 152 | } 153 | } 154 | 155 | Text { 156 | anchors.fill: minHandle 157 | 158 | // anchors.horizontalCenter: range.horizontalCenter 159 | horizontalAlignment: Text.AlignHCenter 160 | verticalAlignment: Text.AlignVCenter 161 | 162 | text: rangeSlider.minValue.toFixed(2) 163 | color: styles.handlesValueColor 164 | font.bold: true 165 | } 166 | 167 | Text { 168 | anchors.fill: maxHandle 169 | 170 | horizontalAlignment: Text.AlignHCenter 171 | verticalAlignment: Text.AlignVCenter 172 | text: rangeSlider.maxValue.toFixed(2) 173 | color: styles.handlesValueColor 174 | font.bold: true 175 | } 176 | 177 | MouseArea { 178 | id: mouseArea 179 | 180 | anchors.fill: parent 181 | property var handlePressed: null 182 | property bool moveRange: false 183 | property real offset: 0 184 | onPressed: { 185 | __updating = true 186 | if (mouseY < maxHandle.y + maxHandle.height) { 187 | handlePressed = maxHandle 188 | handlePressed.moveHandle(mouseX, mouseY) 189 | } else if (mouseY > minHandle.y) { 190 | handlePressed = minHandle 191 | handlePressed.moveHandle(mouseX, mouseY) 192 | } else { 193 | moveRange = true 194 | offset = mouseY - range.y 195 | } 196 | } 197 | 198 | onPositionChanged: { 199 | if (handlePressed) 200 | handlePressed.moveHandle(mouseX, mouseY) 201 | else if (moveRange) { 202 | var newVal = 0 203 | newVal = Math.min( 204 | Math.max(handleSize, mouseY - offset), 205 | rangeSlider.height - (range.height + handleSize)) 206 | newVal -= range.y 207 | 208 | range.updateValues(newVal) 209 | } 210 | } 211 | 212 | onReleased: { 213 | handlePressed = null 214 | __updating = false 215 | moveRange = false 216 | } 217 | 218 | onDoubleClicked: { 219 | if (Utils.inside(mouseX, mouseY, maxHandle.x, maxHandle.y, 220 | maxHandle.width, maxHandle.height)) { 221 | maxHandle.reset() 222 | } else if (Utils.inside(mouseX, mouseY, minHandle.x, minHandle.y, 223 | minHandle.width, minHandle.height)) { 224 | minHandle.reset() 225 | } else 226 | rangeSlider.reset() 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /com/github/jcelerier/CreativeControls/designer/CreativeControls.metainfo: -------------------------------------------------------------------------------- 1 | MetaInfo { 2 | Type { 3 | name: "com.github.jcelerier.CreativeControls.AngleSlider" 4 | icon: "angleSlider-icon.png" 5 | 6 | ItemLibraryEntry { 7 | name: "Angle Slider" 8 | category: "Creative Controls" 9 | version: "1.0" 10 | requiredImport: "com.github.jcelerier.CreativeControls" 11 | libraryIcon: "angleSlider-icon.png" 12 | } 13 | } 14 | Type { 15 | name: "com.github.jcelerier.CreativeControls.Container" 16 | icon: "container-icon.png" 17 | 18 | ItemLibraryEntry { 19 | name: "Container" 20 | category: "Creative Controls" 21 | version: "1.0" 22 | requiredImport: "com.github.jcelerier.CreativeControls" 23 | libraryIcon: "container-icon.png" 24 | } 25 | } 26 | Type { 27 | name: "com.github.jcelerier.CreativeControls.CosInfluence" 28 | icon: "cosPad-icon.png" 29 | 30 | ItemLibraryEntry { 31 | name: "Cosine Influence" 32 | category: "Creative Controls" 33 | version: "1.0" 34 | requiredImport: "com.github.jcelerier.CreativeControls" 35 | libraryIcon: "cosPad-icon.png" 36 | 37 | } 38 | } 39 | Type { 40 | name: "com.github.jcelerier.CreativeControls.DonutSlider" 41 | icon: "donutSlider-icon.png" 42 | 43 | ItemLibraryEntry { 44 | name: "Donut Slider" 45 | category: "Creative Controls" 46 | version: "1.0" 47 | requiredImport: "com.github.jcelerier.CreativeControls" 48 | libraryIcon: "donutSlider-icon.png" 49 | } 50 | } 51 | Type { 52 | name: "com.github.jcelerier.CreativeControls.Graph" 53 | icon: "graph-icon.png" 54 | 55 | ItemLibraryEntry { 56 | name: "1D Graph" 57 | category: "Creative Controls" 58 | version: "1.0" 59 | requiredImport: "com.github.jcelerier.CreativeControls" 60 | libraryIcon: "graph-icon.png" 61 | } 62 | } 63 | 64 | Type { 65 | name: "com.github.jcelerier.CreativeControls.HSVSlider" 66 | icon: "hsvSlider-icon.png" 67 | ItemLibraryEntry { 68 | name: "HSV Sliders" 69 | category: "Creative Controls" 70 | version: "1.0" 71 | requiredImport: "com.github.jcelerier.CreativeControls" 72 | libraryIcon: "hsvSlider-icon.png" 73 | } 74 | } 75 | 76 | Type { 77 | name: "com.github.jcelerier.CreativeControls.HSLSlider" 78 | icon: "hsvSlider-icon.png" 79 | 80 | ItemLibraryEntry { 81 | name: "HSL Sliders" 82 | category: "Creative Controls" 83 | version: "1.0" 84 | requiredImport: "com.github.jcelerier.CreativeControls" 85 | libraryIcon: "hsvSlider-icon.png" 86 | } 87 | } 88 | 89 | Type { 90 | name: "com.github.jcelerier.CreativeControls.Joystick" 91 | icon: "joystick-icon.png" 92 | 93 | ItemLibraryEntry { 94 | name: "Joystick" 95 | category: "Creative Controls" 96 | version: "1.0" 97 | requiredImport: "com.github.jcelerier.CreativeControls" 98 | libraryIcon: "joystick-icon.png" 99 | } 100 | } 101 | 102 | Type { 103 | name: "com.github.jcelerier.CreativeControls.HSlider" 104 | icon: "hslider-icon.png" 105 | 106 | ItemLibraryEntry { 107 | name: "Horizontal Slider" 108 | category: "Creative Controls" 109 | version: "1.0" 110 | requiredImport: "com.github.jcelerier.CreativeControls" 111 | libraryIcon: "hslider-icon.png" 112 | } 113 | } 114 | Type { 115 | name: "com.github.jcelerier.CreativeControls.Keyboard" 116 | icon: "keyboard-icon.png" 117 | 118 | ItemLibraryEntry { 119 | name: "Piano Keyboard" 120 | category: "Creative Controls" 121 | version: "1.0" 122 | requiredImport: "com.github.jcelerier.CreativeControls" 123 | libraryIcon: "keyboard-icon.png" 124 | } 125 | } 126 | 127 | Type { 128 | name: "com.github.jcelerier.CreativeControls.Label" 129 | icon: "label-icon.png" 130 | 131 | ItemLibraryEntry { 132 | name: "Label" 133 | category: "Creative Controls" 134 | version: "1.0" 135 | requiredImport: "com.github.jcelerier.CreativeControls" 136 | libraryIcon: "label-icon.png" 137 | } 138 | } 139 | 140 | Type { 141 | name: "com.github.jcelerier.CreativeControls.Leds" 142 | icon: "leds-icon.png" 143 | 144 | ItemLibraryEntry { 145 | name: "Leds" 146 | category: "Creative Controls" 147 | version: "1.0" 148 | requiredImport: "com.github.jcelerier.CreativeControls" 149 | libraryIcon: "leds-icon.png" 150 | } 151 | } 152 | 153 | Type { 154 | name: "com.github.jcelerier.CreativeControls.Matrix" 155 | icon: "matrix-icon.png" 156 | 157 | ItemLibraryEntry { 158 | name: "Button Matrix" 159 | category: "Creative Controls" 160 | version: "1.0" 161 | requiredImport: "com.github.jcelerier.CreativeControls" 162 | libraryIcon: "matrix-icon.png" 163 | } 164 | } 165 | 166 | Type { 167 | name: "com.github.jcelerier.CreativeControls.MultiSlider" 168 | icon: "multislider-icon.png" 169 | 170 | ItemLibraryEntry { 171 | name: "Multi-Sliders" 172 | category: "Creative Controls" 173 | version: "1.0" 174 | requiredImport: "com.github.jcelerier.CreativeControls" 175 | libraryIcon: "multislider-icon.png" 176 | 177 | } 178 | } 179 | 180 | 181 | Type { 182 | name: "com.github.jcelerier.CreativeControls.RGBSlider" 183 | icon: "rgbSlider-icon.png" 184 | 185 | ItemLibraryEntry { 186 | name: "RGB Sliders" 187 | category: "Creative Controls" 188 | version: "1.0" 189 | requiredImport: "com.github.jcelerier.CreativeControls" 190 | libraryIcon: "rgbSlider-icon.png" 191 | } 192 | } 193 | 194 | 195 | Type { 196 | name: "com.github.jcelerier.CreativeControls.Scope" 197 | icon: "scope-icon.png" 198 | 199 | ItemLibraryEntry { 200 | name: "Scope" 201 | category: "Creative Controls" 202 | version: "1.0" 203 | requiredImport: "com.github.jcelerier.CreativeControls" 204 | libraryIcon: "scope-icon.png" 205 | } 206 | } 207 | 208 | Type { 209 | name: "com.github.jcelerier.CreativeControls.Switch" 210 | icon: "switch-icon.png" 211 | 212 | ItemLibraryEntry { 213 | name: "Switch" 214 | category: "Creative Controls" 215 | version: "1.0" 216 | requiredImport: "com.github.jcelerier.CreativeControls" 217 | libraryIcon: "switch-icon.png" 218 | } 219 | } 220 | 221 | Type { 222 | name: "com.github.jcelerier.CreativeControls.ToggleSwitch" 223 | icon: "toggleSwitch-icon.png" 224 | 225 | ItemLibraryEntry { 226 | name: "Toggle Switch" 227 | category: "Creative Controls" 228 | version: "1.0" 229 | requiredImport: "com.github.jcelerier.CreativeControls" 230 | libraryIcon: "toggleSwitch-icon.png" 231 | } 232 | } 233 | 234 | 235 | Type { 236 | name: "com.github.jcelerier.CreativeControls.VSlider" 237 | icon: "vslider-icon.png" 238 | 239 | ItemLibraryEntry { 240 | name: "Vertical Slider" 241 | category: "Creative Controls" 242 | version: "1.0" 243 | requiredImport: "com.github.jcelerier.CreativeControls" 244 | libraryIcon: "vslider-icon.png" 245 | } 246 | } 247 | 248 | Type { 249 | name: "com.github.jcelerier.CreativeControls.XYPad" 250 | icon: "pad-icon.png" 251 | 252 | ItemLibraryEntry { 253 | name: "X-Y Pad" 254 | category: "Creative Controls" 255 | version: "1.0" 256 | requiredImport: "com.github.jcelerier.CreativeControls" 257 | libraryIcon: "pad-icon.png" 258 | } 259 | } 260 | 261 | 262 | 263 | 264 | /* 265 | Type { 266 | name: "com.github.jcelerier.CreativeControls.ColorChooser" 267 | 268 | ItemLibraryEntry { 269 | name: "Color Chooser" 270 | category: "Creative Controls" 271 | version: "1.0" 272 | requiredImport: "com.github.jcelerier.CreativeControls" 273 | } 274 | } 275 | 276 | Type { 277 | name: "com.github.jcelerier.CreativeControls.ColorWheel" 278 | 279 | ItemLibraryEntry { 280 | name: "Color Wheel" 281 | category: "Creative Controls" 282 | version: "1.0" 283 | requiredImport: "com.github.jcelerier.CreativeControls" 284 | } 285 | } 286 | 287 | 288 | 289 | Type { 290 | name: "com.github.jcelerier.CreativeControls.Graph2D" 291 | 292 | ItemLibraryEntry { 293 | name: "2D Graph" 294 | category: "Creative Controls" 295 | version: "1.0" 296 | requiredImport: "com.github.jcelerier.CreativeControls" 297 | } 298 | } 299 | 300 | Type { 301 | name: "com.github.jcelerier.CreativeControls.Random1D" 302 | 303 | ItemLibraryEntry { 304 | name: "1D Random Generator" 305 | category: "Creative Controls" 306 | version: "1.0" 307 | requiredImport: "com.github.jcelerier.CreativeControls" 308 | } 309 | } 310 | 311 | Type { 312 | name: "com.github.jcelerier.CreativeControls.Random2D" 313 | 314 | ItemLibraryEntry { 315 | name: "2D Random Generator" 316 | category: "Creative Controls" 317 | version: "1.0" 318 | requiredImport: "com.github.jcelerier.CreativeControls" 319 | } 320 | } 321 | 322 | Type { 323 | name: "com.github.jcelerier.CreativeControls.Random3D" 324 | 325 | ItemLibraryEntry { 326 | name: "3D Random Generator" 327 | category: "Creative Controls" 328 | version: "1.0" 329 | requiredImport: "com.github.jcelerier.CreativeControls" 330 | } 331 | } 332 | 333 | Type { 334 | name: "com.github.jcelerier.CreativeControls.Scale" 335 | 336 | ItemLibraryEntry { 337 | name: "Linear Scale" 338 | category: "Creative Controls" 339 | version: "1.0" 340 | requiredImport: "com.github.jcelerier.CreativeControls" 341 | } 342 | } 343 | 344 | Type { 345 | name: "com.github.jcelerier.CreativeControls.Spat" 346 | 347 | ItemLibraryEntry { 348 | name: "Spatializer" 349 | category: "Creative Controls" 350 | version: "1.0" 351 | requiredImport: "com.github.jcelerier.CreativeControls" 352 | } 353 | } 354 | 355 | Type { 356 | name: "com.github.jcelerier.CreativeControls.Spectrum" 357 | 358 | ItemLibraryEntry { 359 | name: "Spectrum Display" 360 | category: "Creative Controls" 361 | version: "1.0" 362 | requiredImport: "com.github.jcelerier.CreativeControls" 363 | } 364 | } 365 | 366 | Type { 367 | name: "com.github.jcelerier.CreativeControls.Step" 368 | 369 | ItemLibraryEntry { 370 | name: "Step Sequencer" 371 | category: "Creative Controls" 372 | version: "1.0" 373 | requiredImport: "com.github.jcelerier.CreativeControls" 374 | } 375 | } 376 | 377 | Type { 378 | name: "com.github.jcelerier.CreativeControls.Trajectory" 379 | 380 | ItemLibraryEntry { 381 | name: "Trajectory Editor" 382 | category: "Creative Controls" 383 | version: "1.0" 384 | requiredImport: "com.github.jcelerier.CreativeControls" 385 | } 386 | } 387 | 388 | 389 | */ 390 | } 391 | --------------------------------------------------------------------------------