1/*
2 * Copyright (c) 2014-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    width: 350
25    height: 50
26    property bool blockUpdate: true
27    property double startValue: 1.0
28    property double middleValue: 1.0
29    property double endValue: 1.0
30
31    Component.onCompleted: {
32        filter.set('start', 1)
33        if (filter.isNew) {
34            // Set default parameter values
35            filter.set('level', 1)
36            filter.set('alpha', 1.0)
37            filter.set('opacity', filter.getDouble('alpha'))
38            filter.savePreset(preset.parameters)
39        } else {
40            middleValue = filter.getDouble('opacity', filter.animateIn)
41            if (filter.animateIn > 0)
42                startValue = filter.getDouble('opacity', 0)
43            if (filter.animateOut > 0)
44                endValue = filter.getDouble('opacity', filter.duration - 1)
45        }
46        setControls()
47    }
48
49    function getPosition() {
50        return Math.max(producer.position - (filter.in - producer.in), 0)
51    }
52
53    function setControls() {
54        var position = getPosition()
55        blockUpdate = true
56        slider.value = filter.getDouble('opacity', position) * 100.0
57        keyframesButton.checked = filter.animateIn <= 0 && filter.animateOut <= 0 && filter.keyframeCount('opacity') > 0
58        blockUpdate = false
59        slider.enabled = position <= 0 || (position >= (filter.animateIn - 1) && position <= (filter.duration - filter.animateOut)) || position >= (filter.duration - 1)
60    }
61
62    function updateFilter(position) {
63        if (blockUpdate) return
64        var value = slider.value / 100.0
65
66        if (position !== null) {
67            if (position <= 0 && filter.animateIn > 0)
68                startValue = value
69            else if (position >= filter.duration - 1 && filter.animateOut > 0)
70                endValue = value
71            else
72                middleValue = value
73        }
74
75        if (filter.animateIn > 0 || filter.animateOut > 0) {
76            filter.resetProperty('alpha')
77            filter.resetProperty('opacity')
78            keyframesButton.checked = false
79            if (filter.animateIn > 0) {
80                filter.set('alpha', startValue, 0)
81                filter.set('alpha', middleValue, filter.animateIn - 1)
82                filter.set('opacity', startValue, 0)
83                filter.set('opacity', middleValue, filter.animateIn - 1)
84            }
85            if (filter.animateOut > 0) {
86                filter.set('alpha', middleValue, filter.duration - filter.animateOut)
87                filter.set('alpha', endValue, filter.duration - 1)
88                filter.set('opacity', middleValue, filter.duration - filter.animateOut)
89                filter.set('opacity', endValue, filter.duration - 1)
90            }
91        } else if (!keyframesButton.checked) {
92            filter.resetProperty('alpha')
93            filter.resetProperty('opacity')
94            filter.set('alpha', middleValue)
95            filter.set('opacity', middleValue)
96        } else if (position !== null) {
97            filter.set('alpha', value, position)
98            filter.set('opacity', value, position)
99        }
100    }
101
102    GridLayout {
103        columns: 4
104        anchors.fill: parent
105        anchors.margins: 8
106
107        Label {
108            text: qsTr('Preset')
109            Layout.alignment: Qt.AlignRight
110        }
111        Shotcut.Preset {
112            id: preset
113            Layout.columnSpan: parent.columns
114            parameters: ['opacity', 'alpha']
115            onBeforePresetLoaded: {
116                filter.resetProperty(parameters[0])
117                filter.resetProperty(parameters[1])
118            }
119            onPresetSelected: {
120                setControls()
121                keyframesButton.checked = filter.keyframeCount(parameters[0]) > 0 && filter.animateIn <= 0 && filter.animateOut <= 0
122                middleValue = filter.getDouble(parameters[0], filter.animateIn)
123                if (filter.animateIn > 0)
124                    startValue = filter.getDouble(parameters[0], 0)
125                if (filter.animateOut > 0)
126                    endValue = filter.getDouble(parameters[0], filter.duration - 1)
127            }
128        }
129
130        Label {
131            text: qsTr('Level')
132            Layout.alignment: Qt.AlignRight
133        }
134        Shotcut.SliderSpinner {
135            id: slider
136            minimumValue: 0
137            maximumValue: 100
138            suffix: ' %'
139            onValueChanged: updateFilter(getPosition())
140        }
141        Shotcut.UndoButton {
142            onClicked: slider.value = 100
143        }
144        Shotcut.KeyframesButton {
145            id: keyframesButton
146            onToggled: {
147                var value = slider.value / 100.0
148                if (checked) {
149                    blockUpdate = true
150                    filter.clearSimpleAnimation('alpha')
151                    filter.clearSimpleAnimation('opacity')
152                    blockUpdate = false
153                    filter.set('alpha', value, getPosition())
154                    filter.set('opacity', value, getPosition())
155                } else {
156                    filter.resetProperty('alpha')
157                    filter.resetProperty('opacity')
158                    filter.set('alpha', value)
159                    filter.set('opacity', value)
160                }
161            }
162        }
163
164        Item {
165            Layout.fillHeight: true
166        }
167    }
168
169    Connections {
170        target: filter
171        onInChanged: updateFilter(null)
172        onOutChanged: updateFilter(null)
173        onAnimateInChanged: updateFilter(null)
174        onAnimateOutChanged: updateFilter(null)
175    }
176
177    Connections {
178        target: producer
179        onPositionChanged: {
180            if (filter.animateIn > 0 || filter.animateOut > 0) {
181                setControls()
182            } else {
183                blockUpdate = true
184                slider.value = filter.getDouble('opacity', getPosition()) * 100.0
185                blockUpdate = false
186                slider.enabled = true
187            }
188        }
189    }
190}
191