1/* 2 * Copyright (c) 2018-2020 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.1 19import Shotcut.Controls 1.0 as Shotcut 20 21Shotcut.VuiBase { 22 property string rectProperty: 'rect' 23 property real zoom: (video.zoom > 0)? video.zoom : 1.0 24 property rect filterRect 25 property bool blockUpdate: false 26 property string startValue: '_shotcut:startValue' 27 property string middleValue: '_shotcut:middleValue' 28 property string endValue: '_shotcut:endValue' 29 30 Component.onCompleted: { 31 application.showStatusMessage(qsTr('Click in rectangle + hold Shift to drag')) 32 filterRect = filter.getRect(rectProperty, getPosition()) 33 rectangle.setHandles(filterRect) 34 setRectangleControl() 35 } 36 37 function getPosition() { 38 return Math.max(producer.position - (filter.in - producer.in), 0) 39 } 40 41 function setRectangleControl() { 42 if (blockUpdate) return 43 var position = getPosition() 44 var newValue = filter.getRect(rectProperty, position) 45 if (filterRect !== newValue) { 46 filterRect = newValue 47 rectangle.setHandles(filterRect) 48 } 49 rectangle.enabled = position <= 0 || (position >= (filter.animateIn - 1) && position <= (filter.duration - filter.animateOut)) || position >= (filter.duration - 1) 50 } 51 52 function setFilter(position) { 53 blockUpdate = true 54 var rect = rectangle.rectangle 55 filterRect.x = Math.round(rect.x / rectangle.widthScale) 56 filterRect.y = Math.round(rect.y / rectangle.heightScale) 57 filterRect.width = Math.round(rect.width / rectangle.widthScale) 58 filterRect.height = Math.round(rect.height / rectangle.heightScale) 59 60 if (position !== null) { 61 filter.blockSignals = true 62 if (position <= 0 && filter.animateIn > 0) 63 filter.set(startValue, filterRect) 64 else if (position >= filter.duration - 1 && filter.animateOut > 0) 65 filter.set(endValue, filterRect) 66 else 67 filter.set(middleValue, filterRect) 68 filter.blockSignals = false 69 } 70 71 if (filter.animateIn > 0 || filter.animateOut > 0) { 72 filter.resetProperty(rectProperty) 73 if (filter.animateIn > 0) { 74 filter.set(rectProperty, filter.getRect(startValue), 1.0, 0) 75 filter.set(rectProperty, filter.getRect(middleValue), 1.0, filter.animateIn - 1) 76 } 77 if (filter.animateOut > 0) { 78 filter.set(rectProperty, filter.getRect(middleValue), 1.0, filter.duration - filter.animateOut) 79 filter.set(rectProperty, filter.getRect(endValue), 1.0, filter.duration - 1) 80 } 81 } else if (filter.keyframeCount(rectProperty) <= 0) { 82 filter.resetProperty(rectProperty) 83 filter.set(rectProperty, filter.getRect(middleValue)) 84 } else if (position !== null) { 85 filter.set(rectProperty, filterRect, 1.0, position) 86 } 87 blockUpdate = false 88 } 89 90 Flickable { 91 anchors.fill: parent 92 interactive: false 93 clip: true 94 contentWidth: video.rect.width * zoom 95 contentHeight: video.rect.height * zoom 96 contentX: video.offset.x 97 contentY: video.offset.y 98 99 Item { 100 id: videoItem 101 x: video.rect.x 102 y: video.rect.y 103 width: video.rect.width 104 height: video.rect.height 105 scale: zoom 106 107 Shotcut.RectangleControl { 108 id: rectangle 109 widthScale: video.rect.width / profile.width 110 heightScale: video.rect.height / profile.height 111 handleSize: Math.max(Math.round(8 / zoom), 4) 112 borderSize: Math.max(Math.round(1.33 / zoom), 1) 113 onWidthScaleChanged: setHandles(filterRect) 114 onHeightScaleChanged: setHandles(filterRect) 115 onRectChanged: setFilter(getPosition()) 116 } 117 } 118 } 119 120 Connections { 121 target: filter 122 onChanged: { 123 setRectangleControl() 124 videoItem.enabled = filter.get('disable') !== '1' 125 } 126 } 127 128 Connections { 129 target: producer 130 onPositionChanged: setRectangleControl() 131 } 132} 133