Warning, /multimedia/kdenlive/src/monitor/view/kdenlivemonitoreffectscene.qml is written in an unsupported language. File is not indexed.

0001 /*
0002     SPDX-FileCopyrightText: 2015 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004 */
0005 
0006 import QtQuick 2.15
0007 
0008 Item {
0009     id: root
0010     objectName: "rooteffectscene"
0011     SystemPalette { id: activePalette }
0012 
0013     // default size, but scalable by user
0014     height: 300; width: 400
0015     property string comment
0016     property string framenum
0017     property rect framesize
0018     property rect adjustedFrame
0019     property point profile: controller.profile
0020     property int overlayType: controller.overlayType
0021     property color overlayColor: controller.overlayColor
0022     property point center
0023     property double scalex
0024     property double scaley
0025     property bool captureRightClick: false
0026     // Zoombar properties
0027     property double zoomStart: 0
0028     property double zoomFactor: 1
0029     property int zoomOffset: 0
0030     property bool showZoomBar: false
0031     property double offsetx : 0
0032     property double offsety : 0
0033     property double lockratio : -1
0034     property double timeScale: 1
0035     property double frameSize: 10
0036     property int duration: 300
0037     property real baseUnit: fontMetrics.font.pixelSize * 0.8
0038     property int mouseRulerPos: 0
0039     onScalexChanged: canvas.requestPaint()
0040     onScaleyChanged: canvas.requestPaint()
0041     onOffsetxChanged: canvas.requestPaint()
0042     onOffsetyChanged: canvas.requestPaint()
0043     property bool iskeyframe
0044     property int requestedKeyFrame: 0
0045     property var centerPoints: []
0046     property var centerPointsTypes: []
0047     onCenterPointsChanged: canvas.requestPaint()
0048     signal effectChanged()
0049     signal centersChanged()
0050 
0051     function updateClickCapture() {
0052         root.captureRightClick = false
0053     }
0054 
0055     onDurationChanged: {
0056         clipMonitorRuler.updateRuler()
0057     }
0058     onWidthChanged: {
0059         clipMonitorRuler.updateRuler()
0060     }
0061 
0062     FontMetrics {
0063         id: fontMetrics
0064         font.family: "Arial"
0065     }
0066 
0067     Canvas {
0068       id: canvas
0069       property double handleSize
0070       width: root.width
0071       height: root.height
0072       anchors.centerIn: root
0073       contextType: "2d";
0074       handleSize: root.baseUnit / 2
0075       renderStrategy: Canvas.Threaded;
0076       onPaint:
0077       {
0078         if (context && root.centerPoints.length > 0) {
0079             context.beginPath()
0080             context.strokeStyle = Qt.rgba(1, 0, 0, 0.5)
0081             context.fillStyle = Qt.rgba(1, 0, 0, 1)
0082             context.lineWidth = 1
0083             context.setLineDash([3,3])
0084             var p1 = convertPoint(root.centerPoints[0])
0085             context.moveTo(p1.x, p1.y)
0086             context.clearRect(0,0, width, height);
0087             for(var i = 0; i < root.centerPoints.length; i++)
0088             {
0089                 context.translate(p1.x, p1.y)
0090                 context.rotate(Math.PI/4);
0091                 context.fillRect(- handleSize, 0, 2 * handleSize, 1);
0092                 context.fillRect(0, - handleSize, 1, 2 * handleSize);
0093                 context.rotate(-Math.PI/4);
0094                 context.translate(-p1.x, -p1.y)
0095                 if (i + 1 < root.centerPoints.length)
0096                 {
0097                     var end = convertPoint(root.centerPoints[i + 1])
0098 
0099                     if (root.centerPointsTypes.length != root.centerPoints.length || root.centerPointsTypes[i] == 0) {
0100                         context.lineTo(end.x, end.y)
0101                         p1 = end
0102                         continue
0103                     }
0104 
0105                     var j = i - 1
0106                     if (j < 0) {
0107                         j = 0
0108                     }
0109                     var pre = convertPoint(root.centerPoints[j])
0110                     j = i + 2
0111                     if (j >= root.centerPoints.length) {
0112                         j = root.centerPoints.length - 1
0113                     }
0114                     var post = convertPoint(root.centerPoints[j])
0115                     var c1 = substractPoints(end, pre, 6.0)
0116                     var c2 = substractPoints(p1, post, 6.0)
0117                     c1 = addPoints(c1, p1)
0118                     c2 = addPoints(c2, end)
0119                     context.bezierCurveTo(c1.x, c1.y, c2.x, c2.y, end.x, end.y);
0120                 } else {
0121                     context.lineTo(p1.x, p1.y)
0122                 }
0123                 p1 = end
0124             }
0125             context.stroke()
0126             context.restore()
0127         }
0128     }
0129 
0130     function convertPoint(p)
0131     {
0132         var x = frame.x + p.x * root.scalex
0133         var y = frame.y + p.y * root.scaley
0134         return Qt.point(x,y);
0135     }
0136     function addPoints(p1, p2)
0137     {
0138         var x = p1.x + p2.x
0139         var y = p1.y + p2.y
0140         return Qt.point(x,y);
0141     }
0142     function distance(p1, p2)
0143     {
0144         var x = p1.x + p2.x
0145         var y = p1.y + p2.y
0146         return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
0147     }
0148     function substractPoints(p1, p2, f)
0149     {
0150         var x = (p1.x - p2.x) / f
0151         var y = (p1.y - p2.y) / f
0152         return Qt.point(x,y);
0153     }
0154   }
0155     Rectangle {
0156         id: frame
0157         objectName: "referenceframe"
0158         width: root.profile.x * root.scalex
0159         height: root.profile.y * root.scaley
0160         x: root.center.x - width / 2 - root.offsetx;
0161         y: root.center.y - height / 2 - root.offsety;
0162         color: "transparent"
0163         border.color: "#ffffff00"
0164         Loader {
0165             anchors.fill: parent
0166             source: {
0167                 switch(root.overlayType)
0168                 {
0169                     case 0:
0170                         return '';
0171                     case 1:
0172                         return "OverlayStandard.qml";
0173                     case 2:
0174                         return "OverlayMinimal.qml";
0175                     case 3:
0176                         return "OverlayCenter.qml";
0177                     case 4:
0178                         return "OverlayCenterDiagonal.qml";
0179                     case 5:
0180                         return "OverlayThirds.qml";
0181                 }
0182             }
0183         }
0184     }
0185     MouseArea {
0186         id: global
0187         property bool isMoving : false
0188         anchors.fill: parent
0189         anchors.bottomMargin: clipMonitorRuler.height
0190         hoverEnabled: true
0191         acceptedButtons: Qt.LeftButton
0192         cursorShape: handleContainsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
0193         readonly property bool handleContainsMouse: {
0194               if (isMoving) {
0195                   return true;
0196               }
0197               for(var i = 0; i < root.centerPoints.length; i++)
0198               {
0199                 var p1 = canvas.convertPoint(root.centerPoints[i])
0200                 if (Math.abs(p1.x - mouseX) <= canvas.handleSize && Math.abs(p1.y - mouseY) <= canvas.handleSize) {
0201                     root.requestedKeyFrame = i
0202                     return true
0203                 }
0204               }
0205               root.requestedKeyFrame = -1
0206               return false
0207         }
0208 
0209         onPositionChanged: mouse => {
0210             if (!pressed) {
0211                 mouse.accepted = false
0212                 return
0213             }
0214             if (root.requestedKeyFrame != -1) {
0215                   isMoving = true
0216                   root.centerPoints[root.requestedKeyFrame].x = (mouseX - frame.x) / root.scalex;
0217                   root.centerPoints[root.requestedKeyFrame].y = (mouseY - frame.y) / root.scaley;
0218                   canvas.requestPaint()
0219                   root.centersChanged()
0220             }
0221         }
0222 
0223         onPressed: mouse => {
0224             root.captureRightClick = true
0225             if (mouse.button & Qt.LeftButton) {
0226                 if (root.requestedKeyFrame >= 0 && !isMoving) {
0227                     controller.seekToKeyframe();
0228                 }
0229             }
0230             isMoving = false
0231         }
0232         onDoubleClicked: {
0233             controller.addRemoveKeyframe()
0234         }
0235         onReleased: {
0236             root.captureRightClick = false
0237             root.requestedKeyFrame = -1
0238             isMoving = false;
0239         }
0240         onEntered: {
0241             controller.setWidgetKeyBinding(xi18nc("@info:whatsthis","<shortcut>Double click</shortcut> to add a keyframe, <shortcut>Shift drag</shortcut> for proportional rescale, <shortcut>Ctrl drag</shortcut> for center-based rescale, <shortcut>Hover right</shortcut> for toolbar, <shortcut>Click</shortcut> on a center to seek to its keyframe"));
0242         }
0243         onExited: {
0244             controller.setWidgetKeyBinding();
0245         }
0246         onWheel: wheel => {
0247             controller.seek(wheel.angleDelta.x + wheel.angleDelta.y, wheel.modifiers)
0248         }
0249     }
0250 
0251     Rectangle {
0252         id: framerect
0253         property color hoverColor: activePalette.highlight //"#ffff00"
0254         x: frame.x + root.framesize.x * root.scalex
0255         y: frame.y + root.framesize.y * root.scaley
0256         width: root.framesize.width * root.scalex
0257         height: root.framesize.height * root.scaley
0258         color: "transparent"
0259         border.color: "#ffff0000"
0260         Rectangle {
0261             id: tlhandle
0262             anchors {
0263             top: parent.top
0264             left: parent.left
0265             }
0266             width: root.baseUnit
0267             height: width
0268             color: "red"
0269             visible: root.iskeyframe || controller.autoKeyframe
0270             opacity: root.iskeyframe ? 1 : 0.4
0271             MouseArea {
0272               property int oldMouseX
0273               property int oldMouseY
0274               property double handleRatio: 1
0275               acceptedButtons: Qt.LeftButton
0276               width: parent.width; height: parent.height
0277               anchors.centerIn: parent
0278               hoverEnabled: true
0279               cursorShape: Qt.SizeFDiagCursor
0280               onEntered: { 
0281                 if (!pressed) {
0282                   tlhandle.color = framerect.hoverColor
0283                 }
0284               }
0285               onExited: {
0286                 if (!pressed) {
0287                   tlhandle.color = '#ff0000'
0288                 }
0289               }
0290               onPressed: mouse => {
0291                   root.captureRightClick = true
0292                   if (root.iskeyframe == false && controller.autoKeyframe) {
0293                     console.log('ADDREMOVE THAND PRESSED')
0294                     controller.addRemoveKeyframe();
0295                   }
0296                   oldMouseX = mouseX
0297                   oldMouseY = mouseY
0298                   effectsize.visible = true
0299                   tlhandle.color = framerect.hoverColor
0300                   handleRatio = framesize.width / framesize.height
0301               }
0302               onPositionChanged: mouse => {
0303                 if (pressed) {
0304                   adjustedFrame = framesize
0305                   if (root.lockratio > 0 || mouse.modifiers & Qt.ShiftModifier) {
0306                       var delta = Math.max(mouseX - oldMouseX, mouseY - oldMouseY)
0307                       var newwidth = framerect.width - delta
0308                       adjustedFrame.width = Math.round(newwidth / root.scalex);
0309                       adjustedFrame.height = Math.round(adjustedFrame.width / (root.lockratio > 0 ?root.lockratio : handleRatio))
0310                       adjustedFrame.y = (framerect.y - frame.y) / root.scaley + framesize.height - adjustedFrame.height;
0311                       adjustedFrame.x = (framerect.x - frame.x) / root.scalex + framesize.width - adjustedFrame.width;
0312                   } else {
0313                     adjustedFrame.x = (framerect.x + (mouseX - oldMouseX) - frame.x) / root.scalex;
0314                     adjustedFrame.y = (framerect.y + (mouseY - oldMouseY) - frame.y) / root.scaley;
0315                     adjustedFrame.width = (framerect.width - (mouseX - oldMouseX)) / root.scalex;
0316                     adjustedFrame.height = (framerect.height - (mouseY - oldMouseY)) / root.scaley;
0317                   }
0318                   if (mouse.modifiers & Qt.ControlModifier) {
0319                       adjustedFrame.width -= (framesize.width - adjustedFrame.width)
0320                       adjustedFrame.height -= (framesize.height - adjustedFrame.height)
0321                   }
0322                   framesize = adjustedFrame
0323                   root.effectChanged()
0324                 }
0325               }
0326               onReleased: {
0327                   root.captureRightClick = false
0328                   effectsize.visible = false
0329                   tlhandle.color = '#ff0000'
0330                   handleRatio = 1
0331               }
0332             }
0333             Text {
0334                 id: effectpos
0335                 objectName: "effectpos"
0336                 color: "red"
0337                 visible: false
0338                 anchors {
0339                     top: parent.bottom
0340                     left: parent.right
0341                 }
0342                 text: framesize.x.toFixed(0) + "x" + framesize.y.toFixed(0)
0343             }
0344         }
0345         Rectangle {
0346             id: trhandle
0347             anchors {
0348             top: parent.top
0349             right: parent.right
0350             }
0351             width: root.baseUnit
0352             height: width
0353             color: "red"
0354             visible: root.iskeyframe || controller.autoKeyframe
0355             opacity: root.iskeyframe ? 1 : 0.4
0356             MouseArea {
0357               property int oldMouseX
0358               property int oldMouseY
0359               property double handleRatio: 1
0360               width: parent.width; height: parent.height
0361               anchors.centerIn: parent
0362               hoverEnabled: true
0363               cursorShape: Qt.SizeBDiagCursor
0364               onEntered: {
0365                 if (!pressed) {
0366                   trhandle.color = framerect.hoverColor
0367                 }
0368               }
0369               onExited: {
0370                 if (!pressed) {
0371                   trhandle.color = '#ff0000'
0372                 }
0373               }
0374               onPressed: mouse => {
0375                   root.captureRightClick = true
0376                   if (root.iskeyframe == false && controller.autoKeyframe) {
0377                       console.log('ADDREMOVE TRAND PRESSED')
0378                     controller.addRemoveKeyframe();
0379                   }
0380                   oldMouseX = mouseX
0381                   oldMouseY = mouseY
0382                   effectsize.visible = true
0383                   trhandle.color = framerect.hoverColor
0384                   handleRatio = framesize.width / framesize.height
0385               }
0386               onPositionChanged: mouse => {
0387                 if (pressed) {
0388                   adjustedFrame = framesize
0389                   if (root.lockratio > 0 || mouse.modifiers & Qt.ShiftModifier) {
0390                       var delta = Math.max(oldMouseX - mouseX, mouseY - oldMouseY)
0391                       var newwidth = framerect.width - delta
0392                       adjustedFrame.width = Math.round(newwidth / root.scalex);
0393                       adjustedFrame.height = Math.round(adjustedFrame.width / (root.lockratio > 0 ?root.lockratio : handleRatio))
0394                       adjustedFrame.y = (framerect.y - frame.y) / root.scaley + framesize.height - adjustedFrame.height;
0395                   } else {
0396                       adjustedFrame.width = (framerect.width + (mouseX - oldMouseX)) / root.scalex;
0397                       adjustedFrame.y = (framerect.y + (mouseY - oldMouseY) - frame.y) / root.scaley;
0398                       adjustedFrame.height = (framerect.height - (mouseY - oldMouseY)) / root.scaley;
0399                   }
0400                   if (mouse.modifiers & Qt.ControlModifier) {
0401                       var xOffset = framesize.width - adjustedFrame.width
0402                       adjustedFrame.x += xOffset
0403                       adjustedFrame.width -= xOffset
0404                       adjustedFrame.height -= (framesize.height - adjustedFrame.height)
0405                   }
0406                   framesize = adjustedFrame
0407                   root.effectChanged()
0408                 }
0409               }
0410               onReleased: {
0411                   root.captureRightClick = false
0412                   effectsize.visible = false
0413                   trhandle.color = '#ff0000'
0414                   handleRatio = 1
0415               }
0416             }
0417         }
0418         Rectangle {
0419             id: blhandle
0420             anchors {
0421             bottom: parent.bottom
0422             left: parent.left
0423             }
0424             width: root.baseUnit
0425             height: width
0426             color: "red"
0427             visible: root.iskeyframe || controller.autoKeyframe
0428             opacity: root.iskeyframe ? 1 : 0.4
0429             MouseArea {
0430               property int oldMouseX
0431               property int oldMouseY
0432               property double handleRatio: 1
0433               width: parent.width; height: parent.height
0434               anchors.centerIn: parent
0435               hoverEnabled: true
0436               cursorShape: Qt.SizeBDiagCursor
0437               onEntered: {
0438                 if (!pressed) {
0439                   blhandle.color = framerect.hoverColor
0440                 }
0441               }
0442               onExited: {
0443                 if (!pressed) {
0444                   blhandle.color = '#ff0000'
0445                 }
0446               }
0447               onPressed: mouse => {
0448                   root.captureRightClick = true
0449                   if (root.iskeyframe == false && controller.autoKeyframe) {
0450                       console.log('ADDREMOVE BLAND PRESSED')
0451                     controller.addRemoveKeyframe();
0452                   }
0453                   oldMouseX = mouseX
0454                   oldMouseY = mouseY
0455                   effectsize.visible = true
0456                   blhandle.color = framerect.hoverColor
0457                   handleRatio = framesize.width / framesize.height
0458               }
0459               onPositionChanged: mouse => {
0460                 if (pressed) {
0461                   adjustedFrame = framesize
0462                   if (root.lockratio > 0 || mouse.modifiers & Qt.ShiftModifier) {
0463                       var delta = Math.max(mouseX - oldMouseX, oldMouseY - mouseY)
0464                       var newwidth = framerect.width - delta
0465                       adjustedFrame.x = (framerect.x + (framerect.width - newwidth) - frame.x) / root.scalex;
0466                       adjustedFrame.width = Math.round(newwidth / root.scalex);
0467                       adjustedFrame.height = Math.round(adjustedFrame.width / (root.lockratio > 0 ?root.lockratio : handleRatio))
0468                   } else {
0469                     adjustedFrame.x = (framerect.x + (mouseX - oldMouseX) - frame.x) / root.scalex;
0470                     adjustedFrame.width = (framerect.width - (mouseX - oldMouseX)) / root.scalex;
0471                     adjustedFrame.height = (framerect.height + (mouseY - oldMouseY)) / root.scaley;
0472                   }
0473                   if (mouse.modifiers & Qt.ControlModifier) {
0474                       adjustedFrame.width -= (framesize.width - adjustedFrame.width)
0475                       var yOffset = framesize.height - adjustedFrame.height
0476                       adjustedFrame.y += yOffset
0477                       adjustedFrame.height -= yOffset
0478                   }
0479                   framesize = adjustedFrame
0480                   root.effectChanged()
0481                 }
0482               }
0483               onReleased: {
0484                   root.captureRightClick = false
0485                   effectsize.visible = false
0486                   blhandle.color = '#ff0000'
0487                   handleRatio = 1
0488               }
0489             }
0490         }
0491         Rectangle {
0492             id: brhandle
0493             anchors {
0494             bottom: parent.bottom
0495             right: parent.right
0496             }
0497             width: root.baseUnit
0498             height: width
0499             color: "red"
0500             visible: root.iskeyframe || controller.autoKeyframe
0501             opacity: root.iskeyframe ? 1 : 0.4
0502             MouseArea {
0503               property int oldMouseX
0504               property int oldMouseY
0505               property double handleRatio: 1
0506               width: parent.width; height: parent.height
0507               anchors.centerIn: parent
0508               hoverEnabled: true
0509               cursorShape: Qt.SizeFDiagCursor
0510               onEntered: {
0511                 if (!pressed) {
0512                   brhandle.color = framerect.hoverColor
0513                 }
0514               }
0515               onExited: {
0516                 if (!pressed) {
0517                   brhandle.color = '#ff0000'
0518                 }
0519               }
0520               onPressed: mouse => {
0521                   root.captureRightClick = true
0522                   if (root.iskeyframe == false && controller.autoKeyframe) {
0523                       console.log('ADDREMOVE BRHAND PRESSED')
0524                     controller.addRemoveKeyframe();
0525                   }
0526                   oldMouseX = mouseX
0527                   oldMouseY = mouseY
0528                   effectsize.visible = true
0529                   brhandle.color = framerect.hoverColor
0530                   handleRatio = framesize.width / framesize.height
0531               }
0532               onPositionChanged: mouse => {
0533                 if (pressed) {
0534                    adjustedFrame = framesize
0535                    if (root.lockratio > 0 || mouse.modifiers & Qt.ShiftModifier) {
0536                       var delta = Math.max(oldMouseX - mouseX, oldMouseY - mouseY)
0537                       var newwidth = framerect.width - delta
0538                       adjustedFrame.width = Math.round(newwidth / root.scalex);
0539                       adjustedFrame.height = Math.round(adjustedFrame.width / (root.lockratio > 0 ?root.lockratio : handleRatio))
0540                   } else {
0541                     adjustedFrame.width = (framerect.width + (mouseX - oldMouseX)) / root.scalex;
0542                     adjustedFrame.height = (framerect.height + (mouseY - oldMouseY)) / root.scaley;
0543                   }
0544                   if (mouse.modifiers & Qt.ControlModifier) {
0545                       var xOffset = framesize.width - adjustedFrame.width
0546                       adjustedFrame.x += xOffset
0547                       adjustedFrame.width -= xOffset
0548                       var yOffset = framesize.height - adjustedFrame.height
0549                       adjustedFrame.y += yOffset
0550                       adjustedFrame.height -= yOffset
0551                   }
0552                   framesize = adjustedFrame
0553                   root.effectChanged()
0554                 }
0555               }
0556               onReleased: {
0557                   root.captureRightClick = false
0558                   effectsize.visible = false
0559                   brhandle.color = '#ff0000'
0560                   handleRatio = 1
0561               }
0562             }
0563             Text {
0564                 id: effectsize
0565                 objectName: "effectsize"
0566                 color: "red"
0567                 visible: false
0568                 anchors {
0569                     bottom: parent.top
0570                     right: parent.left
0571                 }
0572                 text: framesize.width.toFixed(0) + "x" + framesize.height.toFixed(0)
0573             }
0574         }
0575         Rectangle {
0576             anchors.centerIn: parent
0577             width: root.iskeyframe ? effectsize.height : effectsize.height / 2
0578             height: width
0579             radius: width / 2
0580             border.color: centerArea.containsMouse || centerArea.pressed ? framerect.hoverColor : "#ff0000"
0581             border.width: 1
0582             color: centerArea.containsMouse || centerArea.pressed ? framerect.hoverColor : "transparent"
0583             opacity: centerArea.containsMouse || centerArea.pressed ? 0.5 : 1
0584             MouseArea {
0585                 id: centerArea
0586               width: effectsize.height * 1.5; height: effectsize.height * 1.5
0587               anchors.centerIn: parent
0588               property int oldMouseX
0589               property int oldMouseY
0590               hoverEnabled: true
0591               enabled: root.iskeyframe || controller.autoKeyframe
0592               cursorShape: enabled ? Qt.SizeAllCursor : Qt.ArrowCursor
0593               onPressed: {
0594                   root.captureRightClick = true
0595                   if (root.iskeyframe == false && controller.autoKeyframe) {
0596                       console.log('ADDREMOVE CENTER PRESSED')
0597                     controller.addRemoveKeyframe();
0598                   }
0599                   oldMouseX = mouseX
0600                   oldMouseY = mouseY
0601                   effectpos.visible = true
0602               }
0603               onPositionChanged: {
0604                   if (pressed) {
0605                       framesize.x = (framerect.x + (mouseX - oldMouseX) - frame.x) / root.scalex;
0606                       framesize.y = (framerect.y + (mouseY - oldMouseY) - frame.y) / root.scaley;
0607                       root.effectChanged()
0608                   }
0609               }
0610               onReleased: {
0611                   root.captureRightClick = false
0612                   effectpos.visible = false
0613               }
0614             }
0615         }
0616     }
0617 
0618     EffectToolBar {
0619         id: effectToolBar
0620         anchors {
0621             right: parent.right
0622             top: parent.top
0623             bottom: parent.bottom
0624             rightMargin: 4
0625             leftMargin: 4
0626         }
0627     }
0628     MonitorRuler {
0629         id: clipMonitorRuler
0630         anchors {
0631             left: root.left
0632             right: root.right
0633             bottom: root.bottom
0634         }
0635         height: controller.rulerHeight
0636     }
0637 }