1/* 2 * Copyright (c) 2015-2021 Meltytech, LLC 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18import QtQuick 2.12 19import QtQuick.Controls 2.12 20import QtQuick.Layouts 1.12 21import Shotcut.Controls 1.0 as Shotcut 22 23Item { 24 property string keyColorParam: '0' 25 property string keyColorDefault: '#19cc19' 26 property string targetColorParam: '1' 27 property string targetColorDefault: '#c67f66' 28 property string maskTypeParam: '2' 29 property string maskTypeDefault: '0' 30 property string toleranceParam: '3' 31 property double toleranceDefault: 0.24 32 property string slopeParam: '4' 33 property double slopeDefault: 0.4 34 property string hueGateParam: '5' 35 property double hueGateDefault: 0.25 36 property string saturationParam: '6' 37 property double saturationDefault: 0.15 38 property string operation1Param: '7' 39 property string operation1Default: '1' 40 property string amount1Param: '8' 41 property double amount1Default: 0.5 42 property string operation2Param: '9' 43 property string operation2Default: '0' 44 property string amount2Param: '10' 45 property double amount2Default: 0.5 46 property string showMaskParam: '11' 47 property bool showMaskDefault: false 48 property string maskAlphaParam: '12' 49 property bool maskAlphaDefault: false 50 property var defaultParameters: [keyColorParam, targetColorParam, maskTypeParam, 51 toleranceParam, slopeParam, hueGateParam, saturationParam, operation1Param, 52 amount1Param, operation2Param, amount2Param] 53 54 width: 200 55 height: 380 56 Component.onCompleted: { 57 filter.set('threads', 0) 58 if (filter.isNew) { 59 filter.set(keyColorParam, keyColorDefault) 60 filter.set(targetColorParam, targetColorDefault) 61 filter.set(maskTypeParam, maskTypeDefault) 62 filter.set(toleranceParam, toleranceDefault) 63 filter.set(slopeParam, slopeDefault) 64 filter.set(hueGateParam, hueGateDefault) 65 filter.set(saturationParam, saturationDefault) 66 filter.set(operation1Param, operation1Default) 67 filter.set(amount1Param, amount1Default) 68 filter.set(operation2Param, operation2Default) 69 filter.set(amount2Param, amount2Default) 70 filter.set(showMaskParam, showMaskDefault) 71 filter.set(maskAlphaParam, maskAlphaDefault) 72 filter.savePreset(defaultParameters) 73 } 74 setControls() 75 } 76 77 function setControls() { 78 keyColorPicker.value = filter.get(keyColorParam) 79 targetColorPicker.value = filter.get(targetColorParam) 80 maskTypeCombo.currentIndex = filter.get(maskTypeParam) 81 toleranceSlider.value = filter.getDouble(toleranceParam) * 100 82 slopeSlider.value = filter.getDouble(slopeParam) * 100 83 hueGateSlider.value = filter.getDouble(hueGateParam) * 100 84 saturationSlider.value = filter.getDouble(saturationParam) * 100 85 operation1Combo.currentIndex = filter.get(operation1Param) 86 amount1Slider.value = filter.getDouble(amount1Param) * 100 87 operation2Combo.currentIndex = filter.get(operation2Param) 88 amount2Slider.value = filter.getDouble(amount2Param) * 100 89 showMaskCheckbox.checked = parseInt(filter.get(showMaskParam)) 90 maskAlphaCheckbox.checked = parseInt(filter.get(maskAlphaParam)) 91 } 92 93 GridLayout { 94 columns: 3 95 anchors.fill: parent 96 anchors.margins: 8 97 98 Label { 99 text: qsTr('Preset') 100 Layout.alignment: Qt.AlignRight 101 } 102 Shotcut.Preset { 103 id: presetItem 104 Layout.columnSpan: 2 105 parameters: defaultParameters 106 onPresetSelected: setControls() 107 } 108 109 Label { 110 text: qsTr('Key color') 111 Layout.alignment: Qt.AlignRight 112 } 113 Shotcut.ColorPicker { 114 id: keyColorPicker 115 property bool isReady: false 116 Component.onCompleted: isReady = true 117 onValueChanged: { 118 if (isReady) { 119 filter.set(keyColorParam, value) 120 filter.set("disable", 0); 121 } 122 } 123 onPickStarted: { 124 filter.set("disable", 1); 125 } 126 onPickCancelled: filter.set('disable', 0) 127 } 128 Shotcut.UndoButton { 129 onClicked: keyColorPicker.value = keyColorDefault 130 } 131 132 Label { 133 text: qsTr('Target color') 134 Layout.alignment: Qt.AlignRight 135 } 136 Shotcut.ColorPicker { 137 id: targetColorPicker 138 property bool isReady: false 139 Component.onCompleted: isReady = true 140 onValueChanged: { 141 if (isReady) { 142 filter.set(targetColorParam, value) 143 filter.set("disable", 0); 144 } 145 } 146 onPickStarted: { 147 filter.set("disable", 1); 148 } 149 onPickCancelled: filter.set('disable', 0) 150 } 151 Shotcut.UndoButton { 152 onClicked: targetColorPicker.value = targetColorDefault 153 } 154 155 Label { 156 text: qsTr('Mask type') 157 Layout.alignment: Qt.AlignRight 158 } 159 Shotcut.ComboBox { 160 id: maskTypeCombo 161 implicitWidth: 180 162 model: [qsTr('Color Distance'), qsTr('Transparency'), qsTr('Edge Inwards'), qsTr('Edge Outwards')] 163 onActivated: filter.set(maskTypeParam, currentIndex) 164 } 165 Shotcut.UndoButton { 166 onClicked: { 167 filter.set(maskTypeParam, maskTypeDefault) 168 maskTypeCombo.currentIndex = maskTypeDefault 169 } 170 } 171 172 Label { 173 text: qsTr('Tolerance') 174 Layout.alignment: Qt.AlignRight 175 } 176 Shotcut.SliderSpinner { 177 id: toleranceSlider 178 minimumValue: 0 179 maximumValue: 100 180 decimals: 1 181 suffix: ' %' 182 value: filter.getDouble(toleranceParam) * 100 183 onValueChanged: filter.set(toleranceParam, value / 100) 184 } 185 Shotcut.UndoButton { 186 onClicked: toleranceSlider.value = toleranceDefault * 100 187 } 188 189 Label { 190 text: qsTr('Slope') 191 Layout.alignment: Qt.AlignRight 192 } 193 Shotcut.SliderSpinner { 194 id: slopeSlider 195 minimumValue: 0 196 maximumValue: 100 197 decimals: 1 198 suffix: ' %' 199 value: filter.getDouble(slopeParam) * 100 200 onValueChanged: filter.set(slopeParam, value / 100) 201 } 202 Shotcut.UndoButton { 203 onClicked: slopeSlider.value = slopeDefault * 100 204 } 205 206 Label { 207 text: qsTr('Hue gate') 208 Layout.alignment: Qt.AlignRight 209 } 210 Shotcut.SliderSpinner { 211 id: hueGateSlider 212 minimumValue: 0 213 maximumValue: 100 214 decimals: 1 215 suffix: ' %' 216 value: filter.getDouble(hueGateParam) * 100 217 onValueChanged: filter.set(hueGateParam, value / 100) 218 } 219 Shotcut.UndoButton { 220 onClicked: hueGateSlider.value = hueGateDefault * 100 221 } 222 223 Label { 224 text: qsTr('Saturation threshold') 225 Layout.alignment: Qt.AlignRight 226 } 227 Shotcut.SliderSpinner { 228 id: saturationSlider 229 minimumValue: 0 230 maximumValue: 100 231 decimals: 1 232 suffix: ' %' 233 value: filter.getDouble(saturationParam) * 100 234 onValueChanged: filter.set(saturationParam, value / 100) 235 } 236 Shotcut.UndoButton { 237 onClicked: saturationSlider.value = saturationDefault * 100 238 } 239 240 Label { 241 text: qsTr('Operation 1') 242 Layout.alignment: Qt.AlignRight 243 } 244 Shotcut.ComboBox { 245 id: operation1Combo 246 implicitWidth: 180 247 model: [qsTr('None'), qsTr('De-Key'), qsTr('Desaturate'), qsTr('Adjust Luma')] 248 onActivated: filter.set(operation1Param, currentIndex) 249 } 250 Shotcut.UndoButton { 251 onClicked: { 252 filter.set(operation1Param, operation1Default) 253 operation1Combo.currentIndex = operation1Default 254 } 255 } 256 257 Label { 258 text: qsTr('Amount 1') 259 Layout.alignment: Qt.AlignRight 260 } 261 Shotcut.SliderSpinner { 262 id: amount1Slider 263 minimumValue: 0 264 maximumValue: 100 265 decimals: 1 266 suffix: ' %' 267 value: filter.getDouble(amount1Param) * 100 268 onValueChanged: filter.set(amount1Param, value / 100) 269 } 270 Shotcut.UndoButton { 271 onClicked: amount1Slider.value = amount1Default * 100 272 } 273 274 Label { 275 text: qsTr('Operation 2') 276 Layout.alignment: Qt.AlignRight 277 } 278 Shotcut.ComboBox { 279 id: operation2Combo 280 implicitWidth: 180 281 model: [qsTr('None'), qsTr('De-Key'), qsTr('Desaturate'), qsTr('Adjust Luma')] 282 onActivated: filter.set(operation2Param, currentIndex) 283 } 284 Shotcut.UndoButton { 285 onClicked: { 286 filter.set(operation2Param, operation2Default) 287 operation2Combo.currentIndex = operation2Default 288 } 289 } 290 291 Label { 292 text: qsTr('Amount 2') 293 Layout.alignment: Qt.AlignRight 294 } 295 Shotcut.SliderSpinner { 296 id: amount2Slider 297 minimumValue: 0 298 maximumValue: 100 299 decimals: 1 300 suffix: ' %' 301 value: filter.getDouble(amount2Param) * 100 302 onValueChanged: filter.set(amount2Param, value / 100) 303 } 304 Shotcut.UndoButton { 305 onClicked: amount2Slider.value = amount2Default * 100 306 } 307 308 Label {} 309 CheckBox { 310 id: showMaskCheckbox 311 text: qsTr('Show mask') 312 onCheckedChanged: filter.set(showMaskParam, checked) 313 } 314 Shotcut.UndoButton { 315 onClicked: showMaskCheckbox.checked = showMaskDefault 316 } 317 318 Label {} 319 CheckBox { 320 id: maskAlphaCheckbox 321 text: qsTr('Send mask to alpha channel') 322 onCheckedChanged: filter.set(maskAlphaParam, checked) 323 } 324 Shotcut.UndoButton { 325 onClicked: maskAlphaCheckbox.checked = maskAlphaDefault 326 } 327 328 Item { Layout.fillHeight: true } 329 } 330} 331