diff --git a/Helpers/ColorList.js b/Helpers/ColorList.js new file mode 100644 index 000000000..389321493 --- /dev/null +++ b/Helpers/ColorList.js @@ -0,0 +1,187 @@ +var colors = [ + // --- REDS --- + { name: "MistyRose", color: "mistyrose" }, + { name: "LightPink", color: "lightpink" }, + { name: "Pink", color: "pink" }, + { name: "PaleVioletRed", color: "palevioletred" }, + { name: "Pink 500", color: "#E91E63" }, // Material + { name: "HotPink", color: "hotpink" }, + { name: "DeepPink", color: "deeppink" }, + { name: "MediumVioletRed", color: "mediumvioletred" }, + { name: "LightSalmon", color: "lightsalmon" }, + { name: "Salmon", color: "salmon" }, + { name: "DarkSalmon", color: "darksalmon" }, + { name: "LightCoral", color: "lightcoral" }, + { name: "IndianRed", color: "indianred" }, + { name: "Alizarin", color: "#E74C3C" }, // Flat UI + { name: "Red 500", color: "#F44336" }, // Material + { name: "Crimson", color: "crimson" }, + { name: "Red", color: "red" }, + { name: "FireBrick", color: "firebrick" }, + { name: "DarkRed", color: "darkred" }, + { name: "Maroon", color: "maroon" }, + { name: "Brown", color: "brown" }, + + // --- ORANGES & BROWNS --- + { name: "Coral", color: "coral" }, + { name: "Tomato", color: "tomato" }, + { name: "OrangeRed", color: "orangered" }, + { name: "Deep Orange 500", color: "#FF5722" }, // Material + { name: "DarkOrange", color: "darkorange" }, + { name: "Carrot", color: "#E67E22" }, // Flat UI + { name: "Orange 500", color: "#FF9800" }, // Material + { name: "Orange", color: "orange" }, + { name: "SandyBrown", color: "sandybrown" }, + { name: "Peru", color: "peru" }, + { name: "Chocolate", color: "chocolate" }, + { name: "SaddleBrown", color: "saddlebrown" }, + { name: "Sienna", color: "sienna" }, + { name: "Brown 500", color: "#795548" }, // Material + + // --- YELLOWS, BEIGES & GOLDS --- + { name: "LightYellow", color: "lightyellow" }, + { name: "LemonChiffon", color: "lemonchiffon" }, + { name: "LightGoldenrodYellow", color: "lightgoldenrodyellow" }, + { name: "PapayaWhip", color: "papayawhip" }, + { name: "Moccasin", color: "moccasin" }, + { name: "PeachPuff", color: "peachpuff" }, + { name: "NavajoWhite", color: "navajowhite" }, + { name: "Wheat", color: "wheat" }, + { name: "BurlyWood", color: "burlywood" }, + { name: "Tan", color: "tan" }, + { name: "Bisque", color: "bisque" }, + { name: "BlanchedAlmond", color: "blanchedalmond" }, + { name: "Cornsilk", color: "cornsilk" }, + { name: "PaleGoldenrod", color: "palegoldenrod" }, + { name: "Khaki", color: "khaki" }, + { name: "DarkKhaki", color: "darkkhaki" }, + { name: "Goldenrod", color: "goldenrod" }, + { name: "DarkGoldenrod", color: "darkgoldenrod" }, + { name: "Sun Flower", color: "#F1C40F" }, // Flat UI + { name: "Yellow 500", color: "#FFEB3B" }, // Material + { name: "Yellow", color: "yellow" }, + { name: "Gold", color: "gold" }, + { name: "Amber 500", color: "#FFC107" }, // Material + + // --- GREENS --- + { name: "GreenYellow", color: "greenyellow" }, + { name: "Chartreuse", color: "chartreuse" }, + { name: "LawnGreen", color: "lawngreen" }, + { name: "Lime 500", color: "#CDDC39" }, // Material + { name: "Lime", color: "lime" }, + { name: "LimeGreen", color: "limegreen" }, + { name: "PaleGreen", color: "palegreen" }, + { name: "LightGreen", color: "lightgreen" }, + { name: "Light Green 500", color: "#8BC34A" }, // Material + { name: "MediumSpringGreen", color: "mediumspringgreen" }, + { name: "SpringGreen", color: "springgreen" }, + { name: "Emerald", color: "#2ECC71" }, // Flat UI + { name: "Green 500", color: "#4CAF50" }, // Material + { name: "MediumSeaGreen", color: "mediumseagreen" }, + { name: "SeaGreen", color: "seagreen" }, + { name: "ForestGreen", color: "forestgreen" }, + { name: "Green", color: "green" }, + { name: "DarkGreen", color: "darkgreen" }, + { name: "YellowGreen", color: "yellowgreen" }, + { name: "OliveDrab", color: "olivedrab" }, + { name: "Olive", color: "olive" }, + { name: "DarkOliveGreen", color: "darkolivegreen" }, + + // --- TEALS & CYANS --- + { name: "MediumAquamarine", color: "mediumaquamarine" }, + { name: "DarkSeaGreen", color: "darkseagreen" }, + { name: "LightSeaGreen", color: "lightseagreen" }, + { name: "DarkCyan", color: "darkcyan" }, + { name: "Teal", color: "teal" }, + { name: "Turquoise", color: "#1ABC9C" }, // Flat UI + { name: "LightCyan", color: "lightcyan" }, + { name: "PaleTurquoise", color: "paleturquoise" }, + { name: "Aquamarine", color: "aquamarine" }, + { name: "Turquoise", color: "turquoise" }, + { name: "MediumTurquoise", color: "mediumturquoise" }, + { name: "DarkTurquoise", color: "darkturquoise" }, + { name: "Aqua", color: "aqua" }, + { name: "Cyan", color: "cyan" }, + { name: "Cyan 500", color: "#00BCD4" }, // Material + { name: "CadetBlue", color: "cadetblue" }, + { name: "Teal 500", color: "#009688" }, // Material + { name: "DarkSlateGray", color: "darkslategray" }, + + // --- BLUES --- + { name: "PowderBlue", color: "powderblue" }, + { name: "LightBlue", color: "lightblue" }, + { name: "SkyBlue", color: "skyblue" }, + { name: "LightSkyBlue", color: "lightskyblue" }, + { name: "Light Blue 500", color: "#03A9F4" }, // Material + { name: "DeepSkyBlue", color: "deepskyblue" }, + { name: "DodgerBlue", color: "dodgerblue" }, + { name: "CornflowerBlue", color: "cornflowerblue" }, + { name: "Peter River", color: "#3498DB" }, // Flat UI + { name: "Blue 500", color: "#2196F3" }, // Material + { name: "SteelBlue", color: "steelblue" }, + { name: "LightSteelBlue", color: "lightsteelblue" }, + { name: "RoyalBlue", color: "royalblue" }, + { name: "Blue", color: "blue" }, + { name: "MediumBlue", color: "mediumblue" }, + { name: "Belize Hole", color: "#2980B9" }, // Flat UI + { name: "DarkBlue", color: "darkblue" }, + { name: "Navy", color: "navy" }, + { name: "MidnightBlue", color: "midnightblue" }, + { name: "Midnight Blue", color: "#2C3E50" }, // Flat UI (Same name, different color) + { name: "Indigo 500", color: "#3F51B5" }, // Material + { name: "DarkSlateBlue", color: "darkslateblue" }, + { name: "MediumSlateBlue", color: "mediumslateblue" }, + { name: "SlateBlue", color: "slateblue" }, + + // --- PURPLES & MAGENTAS --- + { name: "Lavender", color: "lavender" }, + { name: "Thistle", color: "thistle" }, + { name: "Plum", color: "plum" }, + { name: "Violet", color: "violet" }, + { name: "Orchid", color: "orchid" }, + { name: "Fuchsia", color: "fuchsia" }, + { name: "Magenta", color: "magenta" }, + { name: "MediumOrchid", color: "mediumorchid" }, + { name: "MediumPurple", color: "mediumpurple" }, + { name: "Amethyst", color: "#9B59B6" }, // Flat UI + { name: "Purple 500", color: "#9C27B0" }, // Material + { name: "BlueViolet", color: "blueviolet" }, + { name: "DarkViolet", color: "darkviolet" }, + { name: "DarkOrchid", color: "darkorchid" }, + { name: "DarkMagenta", color: "darkmagenta" }, + { name: "Purple", color: "purple" }, + { name: "Deep Purple 500", color: "#673AB7" }, // Material + { name: "Indigo", color: "indigo" }, + + // --- NEUTRALS --- + { name: "White", color: "white" }, + { name: "Snow", color: "snow" }, + { name: "HoneyDew", color: "honeydew" }, + { name: "MintCream", color: "mintcream" }, + { name: "Azure", color: "azure" }, + { name: "AliceBlue", color: "aliceblue" }, + { name: "GhostWhite", color: "ghostwhite" }, + { name: "WhiteSmoke", color: "whitesmoke" }, + { name: "Seashell", color: "seashell" }, + { name: "Beige", color: "beige" }, + { name: "OldLace", color: "oldlace" }, + { name: "FloralWhite", color: "floralwhite" }, + { name: "Ivory", color: "ivory" }, + { name: "AntiqueWhite", color: "antiquewhite" }, + { name: "Linen", color: "linen" }, + { name: "LavenderBlush", color: "lavenderblush" }, + { name: "Gainsboro", color: "gainsboro" }, + { name: "LightGray", color: "lightgray" }, + { name: "Silver", color: "silver" }, + { name: "DarkGray", color: "darkgray" }, + { name: "Gray", color: "gray" }, + { name: "Grey 500", color: "#9E9E9E" }, // Material + { name: "Concrete", color: "#95A5A6" }, // Flat UI + { name: "DimGray", color: "dimgray" }, + { name: "LightSlateGray", color: "lightslategray" }, + { name: "SlateGray", color: "slategray" }, + { name: "Asbestos", color: "#7F8C8D" }, // Flat UI + { name: "Blue Grey 500", color: "#607D8B" }, // Material + { name: "Wet Asphalt", color: "#34495E" }, // Flat UI + { name: "Black", color: "black" } + ] diff --git a/Shaders/frag/color_picker.frag b/Shaders/frag/color_picker.frag new file mode 100644 index 000000000..c38539cdd --- /dev/null +++ b/Shaders/frag/color_picker.frag @@ -0,0 +1,54 @@ +#version 450 + +layout(location = 0) in vec2 qt_TexCoord0; +layout(location = 0) out vec4 fragColor; + +layout(std140, binding = 0) uniform buf +{ + mat4 qt_Matrix; + vec4 params; // x=opacity, y=fixedVal, z=mode, w=padding +}; + +vec3 hsv2rgb(vec3 c) +{ + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} + +void main() +{ + float x = qt_TexCoord0.x; + float y = 1.0 - qt_TexCoord0.y; // Flip Y direction + + // Unpack vector + float opacity = params.x; + float fixedVal = params.y; + float mode = params.z + 0.1; // +0.1 safely handles float rounding + + // Build permutation matrices for swizzling + vec3 base = vec3(x, y, fixedVal); + + // Determine Mode Logic + // 0: (Red/Hue) 1: (Green/Sat) 2: (Blue/Val) + int perm = int(mode) % 3; + + float isHSV = step(3.0, mode); + + // Branchless Selection + vec3 mask = vec3( + float(perm == 0), + float(perm == 1), + float(perm == 2)); + + // Swizzle fo shizzle + // If perm 0: base.zxy -> (fixedVal, x, y) + // If perm 1: base.xzy -> (x, fixedVal, y) + // If perm 2: base.xyz -> (x, y, fixedVal) + vec3 rgb_base = (base.zxy * mask.x) + (base.xzy * mask.y) + (base.xyz * mask.z); + + // Final mix + vec3 finalColor = mix(rgb_base, hsv2rgb(rgb_base), isHSV); + + fragColor = vec4(finalColor, 1.0) * opacity; +} diff --git a/Shaders/qsb/color_picker.frag.qsb b/Shaders/qsb/color_picker.frag.qsb new file mode 100644 index 000000000..f73dfd661 Binary files /dev/null and b/Shaders/qsb/color_picker.frag.qsb differ diff --git a/Widgets/NColorSlider.qml b/Widgets/NColorSlider.qml new file mode 100644 index 000000000..1e7264eb6 --- /dev/null +++ b/Widgets/NColorSlider.qml @@ -0,0 +1,177 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Effects +import qs.Commons +import qs.Services.UI + +Slider { + id: root + + property color fillColor: "transparent" + property var cutoutColor: Color.mSurface + property bool snapAlways: true + property real widthRatio: 0.7 + property string tooltipText + property string tooltipDirection: "auto" + property bool hovering: false + property color topColor: "white" + property color bottomColor: "black" + property bool rainbowMode: false + + readonly property real knobDiameter: Math.round((Style.baseWidgetSize * widthRatio * Style.uiScaleRatio) / 2) * 2 + readonly property real trackWidth: Math.round((knobDiameter * 0.4 * Style.uiScaleRatio) / 2) * 2 + readonly property real cutoutExtra: Math.round((Style.baseWidgetSize * 0.1 * Style.uiScaleRatio) / 2) * 2 + + //horizontal: false + orientation: Qt.Vertical + + padding: cutoutExtra / 2 + + snapMode: snapAlways ? Slider.SnapAlways : Slider.SnapOnRelease + implicitWidth: Math.max(trackWidth, knobDiameter) + + background: Rectangle { + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter + + x: root.leftPadding + root.availableWidth / 2 - width / 2 + + height: root.availableHeight - root.knobDiameter + width: root.trackWidth + + radius: width / 2 + color: Qt.alpha(Color.mSurface, 0.5) + border.color: Qt.alpha(Color.mOutline, 0.5) + border.width: Style.borderS + + // Gradients + gradient: root.rainbowMode ? rainbowGradient : standardGradient + Gradient { + id: standardGradient + orientation: Gradient.Vertical + GradientStop { + position: 0.0 + color: root.topColor + } + GradientStop { + position: 1.0 + color: root.bottomColor + } + } + Gradient { + id: rainbowGradient + orientation: Gradient.Vertical + GradientStop { + position: 0.000 + color: "#FF0000" + } + GradientStop { + position: 0.167 + color: "#FF00FF" + } + GradientStop { + position: 0.333 + color: "#0000FF" + } + GradientStop { + position: 0.500 + color: "#00FFFF" + } + GradientStop { + position: 0.667 + color: "#00FF00" + } + GradientStop { + position: 0.833 + color: "#FFFF00" + } + GradientStop { + position: 1.000 + color: "#FF0000" + } + } + + // Circular cutout + Rectangle { + id: knobCutout + implicitWidth: root.knobDiameter + root.cutoutExtra + implicitHeight: root.knobDiameter + root.cutoutExtra + radius: width / 2 + color: root.cutoutColor !== undefined ? root.cutoutColor : Color.mSurface + + y: root.visualPosition * (root.availableHeight - root.knobDiameter) - ((root.knobDiameter + root.cutoutExtra) / 2) + anchors.horizontalCenter: parent.horizontalCenter + } + } + + handle: Item { + implicitWidth: root.knobDiameter + implicitHeight: root.knobDiameter + y: root.topPadding + root.visualPosition * (root.availableHeight - height) + anchors.horizontalCenter: parent.horizontalCenter + + Rectangle { + id: knob + implicitWidth: root.knobDiameter + implicitHeight: root.knobDiameter + radius: width / 2 + color: { + if (root.rainbowMode) { + // Hue Logic: Map position (0.0 to 1.0) directly to Hue + return Qt.hsva(1 - root.visualPosition, 1, 1, 1); + } else { + // Linear Interpolation for Standard Gradients + // visualPosition 0.0 = Top, 1.0 = Bottom + var t = root.visualPosition; + var r = root.topColor.r * (1 - t) + root.bottomColor.r * t; + var g = root.topColor.g * (1 - t) + root.bottomColor.g * t; + var b = root.topColor.b * (1 - t) + root.bottomColor.b * t; + return Qt.rgba(r, g, b, 1); + } + } + + border.color: root.pressed ? Color.mHover : Color.mPrimary + border.width: Style.borderL + anchors.centerIn: parent + + Behavior on color { + ColorAnimation { + duration: Style.animationFast + } + } + } + + MouseArea { + enabled: true + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + acceptedButtons: Qt.NoButton // Don't accept any mouse buttons - only hover + propagateComposedEvents: true + + onEntered: { + root.hovering = true; + if (root.tooltipText) { + TooltipService.show(screen, knob, root.tooltipText, root.tooltipDirection); + } + } + + onExited: { + root.hovering = false; + if (root.tooltipText) { + TooltipService.hide(); + } + } + } + + // Hide tooltip when slider is pressed (anywhere on the slider) + Connections { + target: root + function onPressedChanged() { + if (root.pressed && root.tooltipText) { + TooltipService.hide(); + } + } + } + } +}