Qt Quick 3D - Scene Effects Example▲
Sélectionnez
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import
QtQuick
import
QtQuick.Controls
import
QtQuick.Layouts
Item
{
id
:
colorPicker
property
bool
isHovered
:
false
property
alias
color
:
root.color
width
:
100
height
:
26
Rectangle
{
id
:
border
color
:
&
quot;transparent&
quot;
border.width
:
2
border.color
:
isHovered ? palette.dark :
palette.alternateBase
anchors.fill
:
parent
Image
{
anchors.fill
:
parent
anchors.margins
:
4
source
:
&
quot;qrc
:/
images/
grid_8x8.png&
quot;
fillMode
:
Image.Tile
}
Rectangle
{
anchors.fill
:
parent
anchors.margins
:
4
color
:
colorPicker.color
}
MouseArea
{
anchors.fill
:
parent
hoverEnabled
:
true
onEntered
:
colorPicker.isHovered =
true
onExited
:
colorPicker.isHovered =
false
onClicked
: {
colorPickerPopup.open
(
)
}
}
}
Dialog
{
id
:
colorPickerPopup
title
:
&
quot;Color Picker&
quot;
anchors.centerIn
:
Overlay.overlay
modal
:
true
focus
:
true
closePolicy
:
Popup.CloseOnEscape |
Popup.CloseOnPressOutsideParent
RowLayout
{
anchors.centerIn
:
parent
id
:
root
property
color
color
:
&
quot;red&
quot;
spacing
:
0
Item
{
width
:
135
height
:
135
ShaderEffect
{
id
:
hsvWheel
anchors.centerIn
:
parent
blending
:
true
width
:
128
height
:
128
property
real
value
:
1.0
fragmentShader
:
&
quot;qrc
:/
shaders/
huesaturation.frag.qsb&
quot;
Item
{
id
:
reticule
function
reflectColor(hue, saturation) {
let angleDegrees =
hue *
360
if (
angleDegrees &
gt;
180
)
angleDegrees =
angleDegrees -
360
let angleRadians =
angleDegrees * (
Math.
PI /
180
)
let vector =
Qt.vector2d
(
Math.cos
(
angleRadians),
Math.sin
(
angleRadians)).normalized
(
).times
(
0
.
5
).times
(
saturation)
vector =
vector.plus
(
Qt.vector2d
(
0
.
5
,
0
.
5
))
reticule.
x =
vector.
x *
hsvWheel.
width
reticule.
y =
vector.
y *
hsvWheel.
width
}
Rectangle
{
x
:
-
5
y
:
-
5
width
:
10
height
:
10
radius
:
5
color
:
&
quot;transparent&
quot;
border.width
:
1
border.color
:
&
quot;black&
quot;
Rectangle
{
x
:
0.5
y
:
0.5
width
:
9
height
:
9
radius
:
4.5
color
:
root.color
border.width
:
1
border.color
:
&
quot;white&
quot;
}
}
}
MouseArea
{
anchors.fill
:
parent
function
handleMouseMove(x
, y
, width
) {
let normalizedX =
x /
width -
0
.
5
;
let normalizedY =
y /
width -
0
.
5
;
let angle =
Math.atan2
(
normalizedY,
normalizedX);
let toCenter =
Qt.vector2d
(
normalizedX,
normalizedY);
let radius =
toCenter.length
(
) *
2
.
0
;
let degrees =
angle * (
180
/
Math.
PI)
if (
degrees &
lt;
0
)
degrees =
360
+
degrees
let hue =
degrees /
360
root.
color =
Qt.hsva
(
hue,
radius,
root.
color.
hsvValue,
root.
color.
a)
if (
radius &
lt;=
1
.
0
)
return Qt.vector2d
(
x,
y)
// Limit to radius of 1.0
toCenter =
toCenter.normalized
(
);
let halfWidth =
width *
0
.
5
;
let newX =
halfWidth *
toCenter.
x +
halfWidth
let newY =
halfWidth *
toCenter.
y +
halfWidth
return Qt.vector2d
(
newX,
newY)
}
onPositionChanged
:
(mouse) =&
gt; {
let pos =
handleMouseMove(mouse.x, mouse.y, hsvWheel.width)
reticule.x =
pos.x;
reticule.y =
pos.y;
}
}
}
}
Component.onCompleted
: {
updateColorSections
(
)
reticule.reflectColor
(
root.
color.
hsvHue,
root.
color.
hsvSaturation)
}
Connections
{
target
:
root
function
onColorChanged() {
root.updateColorSections
(
)
}
}
function
updateColorSections() {
rgbSection.
redValue =
root.
color.
r *
255
rgbSection.
greenValue =
root.
color.
g *
255
rgbSection.
blueValue =
root.
color.
b *
255
hsvSection.
hueValue =
root.
color.
hsvHue *
360
hsvSection.
saturationValue =
root.
color.
hsvSaturation *
100
hsvSection.
valueValue =
root.
color.
hsvValue *
100
alphaSection.
alphaValue =
root.
color.
a *
255
}
ColumnLayout
{
width
:
250
SectionLayout {
title
:
&
quot;RGB&
quot;
id
:
rgbSection
property
int
redValue
:
0
property
int
greenValue
:
0
property
int
blueValue
:
0
function
updateRGB() {
root.
color =
Qt.rgba
(
redValue /
255
,
greenValue /
255
,
blueValue /
255
,
alphaSection.
alphaValue /
255
)
reticule.reflectColor
(
root.
color.
hsvHue,
root.
color.
hsvSaturation)
}
RowLayout
{
Label
{
text
:
&
quot;R:&
quot;
}
Slider
{
id
:
redSlider
Layout.fillWidth
:
true
from
:
0
to
:
255
value
:
rgbSection.redValue
onValueChanged
: {
if (
value !==
rgbSection.
redValue) {
rgbSection.
redValue =
value
if (
activeFocus)
rgbSection.updateRGB
(
)
}
}
}
SpinBox
{
from
:
0
to
:
255
value
:
rgbSection.redValue
onValueChanged
: {
if (
value !==
rgbSection.
redValue) {
rgbSection.
redValue =
value
if (
activeFocus)
rgbSection.updateRGB
(
)
}
}
}
}
RowLayout
{
Label
{
text
:
&
quot;G:&
quot;
}
Slider
{
id
:
greenSlider
Layout.fillWidth
:
true
from
:
0
to
:
255
value
:
rgbSection.greenValue
onValueChanged
: {
if (
value !==
rgbSection.
greenValue) {
rgbSection.
greenValue =
value
if (
activeFocus)
rgbSection.updateRGB
(
)
}
}
}
SpinBox
{
from
:
0
to
:
255
value
:
rgbSection.greenValue
onValueChanged
: {
if (
value !==
rgbSection.
greenValue) {
rgbSection.
greenValue =
value
if (
activeFocus)
rgbSection.updateRGB
(
)
}
}
}
}
RowLayout
{
Label
{
text
:
&
quot;B:&
quot;
}
Slider
{
id
:
blueSlider
Layout.fillWidth
:
true
from
:
0
to
:
255
value
:
rgbSection.blueValue
onValueChanged
: {
if (
value !==
rgbSection.
blueValue) {
rgbSection.
blueValue =
value
if (
activeFocus)
rgbSection.updateRGB
(
)
}
}
}
SpinBox
{
from
:
0
to
:
255
value
:
rgbSection.blueValue
onValueChanged
: {
if (
value !==
rgbSection.
blueValue) {
rgbSection.
blueValue =
value
if (
activeFocus)
rgbSection.updateRGB
(
)
}
}
}
}
RowLayout
{
Label
{
text
:
&
quot;Hex
:&
quot;
Layout.fillWidth
:
true
}
TextField
{
id
:
hexTextField
maximumLength
:
6
implicitWidth
:
75
function
updateText() {
if (
activeFocus)
return
let redText =
rgbSection.
redValue.toString
(
16
).toUpperCase
(
)
let greenText =
rgbSection.
greenValue.toString
(
16
).toUpperCase
(
)
let blueText =
rgbSection.
blueValue.toString
(
16
).toUpperCase
(
)
if (
redText.
length ==
1
)
redText =
&
quot;
0
&
quot;
+
redText
if (
greenText.
length ==
1
)
greenText =
&
quot;
0
&
quot;
+
greenText
if (
blueText.
length ==
1
)
blueText =
&
quot;
0
&
quot;
+
blueText
text
=
redText +
greenText +
blueText;
}
function
expandText(text
) {
let newText =
text
.toUpperCase
(
)
let expandLength =
6
-
newText.
length
for (
let i =
0
;
i &
lt;
expandLength;
++
i)
newText =
&
quot;
0
&
quot;
+
newText
return newText
}
Component.onCompleted
:
updateText()
validator
:
RegularExpressionValidator {
regularExpression
:
/^
[0
-
9A-
Fa-
f]{
0
,6
}
$/
}
onTextChanged
: {
if (!
acceptableInput)
return;
let colorText =
expandText
(
text
)
rgbSection.
redValue =
parseInt(
colorText.substr
(
0
,
2
),
16
)
rgbSection.
greenValue =
parseInt(
colorText.substr
(
2
,
2
),
16
)
rgbSection.
blueValue =
parseInt(
colorText.substr
(
4
,
2
),
16
)
if (
activeFocus)
rgbSection.updateRGB
(
)
}
onAccepted
: {
text
=
expandText
(
text
)
}
}
Connections
{
target
:
rgbSection
function
onRedValueChanged() {
hexTextField.updateText
(
)
}
function
onGreenValueChanged() {
hexTextField.updateText
(
)
}
function
onBlueValueChanged() {
hexTextField.updateText
(
)
}
}
}
}
SectionLayout {
title
:
&
quot;HSV&
quot;
id
:
hsvSection
property
int
hueValue
:
0
property
int
saturationValue
:
0
property
int
valueValue
:
0
function
updateHSV() {
root.
color =
Qt.hsva
(
hueValue /
360
,
saturationValue /
100
,
valueValue /
100
,
alphaSection.
alphaValue /
255
)
reticule.reflectColor
(
root.
color.
hsvHue,
root.
color.
hsvSaturation)
}
RowLayout
{
Label
{
text
:
&
quot;H:&
quot;
}
Slider
{
id
:
hueSlider
Layout.fillWidth
:
true
from
:
0
to
:
360
value
:
hsvSection.hueValue
onValueChanged
: {
if (
value !==
hsvSection.
hueValue) {
hsvSection.
hueValue =
value
if (
activeFocus)
hsvSection.updateHSV
(
)
}
}
}
SpinBox
{
from
:
0
to
:
360
value
:
hsvSection.hueValue
onValueChanged
: {
if (
value !==
hsvSection.
hueValue) {
hsvSection.
hueValue =
value
if (
activeFocus)
hsvSection.updateHSV
(
)
}
}
}
}
RowLayout
{
Label
{
text
:
&
quot;S:&
quot;
}
Slider
{
id
:
saturationSlider
Layout.fillWidth
:
true
from
:
0
to
:
100
value
:
hsvSection.saturationValue
onValueChanged
: {
if (
value !==
hsvSection.
saturationValue) {
hsvSection.
saturationValue =
value
if (
activeFocus)
hsvSection.updateHSV
(
)
}
}
}
SpinBox
{
from
:
0
to
:
100
value
:
hsvSection.saturationValue
onValueChanged
: {
if (
value !==
hsvSection.
saturationValue) {
hsvSection.
saturationValue =
value
if (
activeFocus)
hsvSection.updateHSV
(
)
}
}
}
}
RowLayout
{
Label
{
text
:
&
quot;V:&
quot;
}
Slider
{
id
:
valueSlider
Layout.fillWidth
:
true
from
:
0
to
:
100
value
:
hsvSection.valueValue
onValueChanged
: {
if (
value !==
hsvSection.
valueValue) {
hsvSection.
valueValue =
value
if (
activeFocus)
hsvSection.updateHSV
(
)
}
}
}
SpinBox
{
from
:
0
to
:
100
value
:
hsvSection.valueValue
onValueChanged
: {
if (
value !==
hsvSection.
valueValue) {
hsvSection.
valueValue =
value
if (
activeFocus)
hsvSection.updateHSV
(
)
}
}
}
}
}
SectionLayout {
title
:
&
quot;Opacity /
Alpha&
quot;
id
:
alphaSection
property
int
alphaValue
:
0
RowLayout
{
Label
{
text
:
&
quot;V:&
quot;
}
Slider
{
id
:
alphaSlider
Layout.fillWidth
:
true
from
:
0
to
:
255
value
:
alphaSection.alphaValue
onValueChanged
: {
if (
value !==
alphaSection.
alphaValue) {
alphaSection.
alphaValue =
value
if (
activeFocus)
hsvSection.updateHSV
(
)
}
}
}
SpinBox
{
from
:
0
to
:
255
value
:
alphaSection.alphaValue
onValueChanged
: {
if (
value !==
alphaSection.
alphaValue) {
alphaSection.
alphaValue =
value
if (
activeFocus)
hsvSection.updateHSV
(
)
}
}
}
}
}
}
}
}
}