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

0001 /*
0002     SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org>
0003     SPDX-FileCopyrightText: 2021 Julius Künzel <jk.kdedev@smartlab.uber.space>
0004     SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 import QtQuick 2.15
0008 import QtQuick.Controls 2.15
0009 
0010 Item {
0011     id: root
0012     objectName: "rootrotoscene"
0013 
0014     SystemPalette { id: activePalette }
0015     // default size, but scalable by user
0016     height: 300; width: 400
0017     property string comment
0018     property string framenum
0019     property point profile: controller.profile
0020     property point center
0021     property real baseUnit: fontMetrics.font.pixelSize * 0.8
0022     property int overlayType: controller.overlayType
0023     property color overlayColor: controller.overlayColor
0024     property double scalex : 1
0025     property double scaley : 1
0026     property bool captureRightClick: true
0027     // Zoombar properties
0028     property double zoomStart: 0
0029     property double zoomFactor: 1
0030     property int zoomOffset: 0
0031     property bool showZoomBar: false
0032     property double stretch : 1
0033     property double sourcedar : 1
0034     property double offsetx : 0
0035     property double offsety : 0
0036     property double frameSize: 10
0037     property int duration: 300
0038     property double timeScale: 1
0039     property int mouseRulerPos: 0
0040     onOffsetxChanged: canvas.requestPaint()
0041     onOffsetyChanged: canvas.requestPaint()
0042     onScalexChanged: canvas.requestPaint()
0043     onScaleyChanged: canvas.requestPaint()
0044     onSourcedarChanged: refreshdar()
0045     property bool iskeyframe : true
0046     property bool autoKeyframe: controller.autoKeyframe
0047     property bool isDefined: false
0048     property int requestedKeyFrame : -1
0049     property int requestedSubKeyFrame : -1
0050     // Index in points array where we want to insert a new point
0051     property int addedPointIndex : -1
0052     // Position of the added point
0053     property var addPointPossible : Qt.point(0, 0)
0054     // Index of the hovered resize handle
0055     property int resizeContainsMouse: 0
0056     property bool requestedCenter : false
0057     // Display resize handles and rect if true
0058     property bool displayResize : false
0059     // The coordinate points where the bezier curve passes
0060     property var centerPoints : []
0061     property var centerCross : []
0062     // The control points for the bezier curve points (2 controls points for each coordinate)
0063     property var centerPointsTypes : []
0064     // The coordinate points for bounding box
0065     property var topRight: []
0066     property var bottomLeft: []
0067     property bool showToolbar: false
0068     property string emptyCanvasKeyBindInfo: xi18nc("@info:whatsthis", "<shortcut>Click</shortcut> to add points, <shortcut>Right click</shortcut> to close shape.")
0069     property string defaultKeyBindInfo: xi18nc("@info:whatsthis", "<shortcut>Double click</shortcut> on center to resize, <shortcut>Double click</shortcut> on line segment to add new point, <shortcut>Double click</shortcut> point to delete it, <shortcut>Double click</shortcut> background to create new keyframe, <shortcut>Hover right</shortcut> for toolbar");
0070     property string resizeKeyBindInfo: xi18nc("@info:whatsthis", "<shortcut>Shift drag handle</shortcut> for center-based resize")
0071     onCenterPointsTypesChanged: checkDefined()
0072     signal effectPolygonChanged(var points, var centers)
0073     signal seekToKeyframe()
0074 
0075     function updateClickCapture() {
0076         if (root.isDefined) {
0077             root.captureRightClick = false
0078         } else {
0079             root.captureRightClick = true
0080         }
0081     }
0082 
0083     onDurationChanged: {
0084         clipMonitorRuler.updateRuler()
0085     }
0086     onWidthChanged: {
0087         clipMonitorRuler.updateRuler()
0088     }
0089 
0090     onIskeyframeChanged: {
0091         console.log('KEYFRAME CHANGED: ', iskeyframe)
0092         if (root.displayResize && !controller.autoKeyframe) {
0093             root.displayResize = false
0094         }
0095         canvas.requestPaint()
0096     }
0097     onDisplayResizeChanged: {
0098         controller.setWidgetKeyBinding(root.displayResize ? resizeKeyBindInfo : defaultKeyBindInfo);
0099     }
0100 
0101     onIsDefinedChanged: {
0102         controller.setWidgetKeyBinding(root.isDefined ? defaultKeyBindInfo : emptyCanvasKeyBindInfo);
0103         root.captureRightClick = false
0104     }
0105 
0106     onAutoKeyframeChanged: {
0107         canvas.requestPaint()
0108     }
0109 
0110     FontMetrics {
0111         id: fontMetrics
0112         font.family: "Arial"
0113     }
0114 
0115     function refreshdar() {
0116         canvas.darOffset = root.sourcedar < root.profile.x * root.stretch / root.profile.y ? (root.profile.x * root.stretch - root.profile.y * root.sourcedar) / (2 * root.profile.x * root.stretch) :(root.profile.y - root.profile.x * root.stretch / root.sourcedar) / (2 * root.profile.y);
0117         canvas.requestPaint()
0118     }
0119 
0120     function checkDefined() {
0121         root.isDefined = root.centerPointsTypes.length > 0
0122         canvas.requestPaint()
0123     }
0124 
0125     Item {
0126         id: monitorOverlay
0127         height: root.height - controller.rulerHeight
0128         width: root.width
0129 
0130     Canvas {
0131       id: canvas
0132       property double handleSize
0133       property double darOffset : 0
0134       anchors.fill: parent
0135       contextType: "2d";
0136       handleSize: root.baseUnit / 2
0137       renderTarget: Canvas.FramebufferObject
0138       renderStrategy: Canvas.Cooperative
0139 
0140       onPaint:
0141       {
0142         var ctx = getContext('2d')
0143         //if (context) {
0144             ctx.clearRect(0,0, width, height);
0145             ctx.beginPath()
0146             ctx.strokeStyle = Qt.rgba(1, 0, 0, 0.5)
0147             ctx.fillStyle = Qt.rgba(1, 0, 0, 0.5)
0148             ctx.lineWidth = 2
0149             if (root.centerPoints.length == 0) {
0150                 // no points defined yet
0151                 return
0152             }
0153             var p1 = convertPoint(root.centerPoints[0])
0154             var startP = p1;
0155             ctx.moveTo(p1.x, p1.y)
0156             if (!isDefined) {
0157                 // We are still building the shape, only draw points connected with lines
0158                 ctx.fillRect(p1.x - handleSize, p1.y - handleSize, 2 * handleSize, 2 * handleSize);
0159                 for (var i = 1; i < root.centerPoints.length; i++) {
0160                     p1 = convertPoint(root.centerPoints[i])
0161                     ctx.lineTo(p1.x, p1.y);
0162                     if (i == root.requestedKeyFrame) {
0163                         ctx.fillStyle = activePalette.highlight
0164                         ctx.fillRect(p1.x - handleSize, p1.y - handleSize, 2 * handleSize, 2 * handleSize);
0165                         ctx.fillStyle = Qt.rgba(1, 0, 0, 0.5)
0166                     } else {
0167                         ctx.fillRect(p1.x - handleSize, p1.y - handleSize, 2 * handleSize, 2 * handleSize);
0168                     }
0169                 }
0170             } else {
0171                 var c1; var c2
0172                 var alphaColor = Qt.hsla(activePalette.highlight.hslHue, activePalette.highlight.hslSaturation, activePalette.highlight.hslLightness, 0.5)
0173                 for (var i = 0; i < root.centerPoints.length; i++) {
0174                     p1 = convertPoint(root.centerPoints[i])
0175                     // Control points
0176                     var subkf = false
0177                     if (i == 0) {
0178                         c1 = convertPoint(root.centerPointsTypes[root.centerPointsTypes.length - 1])
0179                         if (root.requestedSubKeyFrame == root.centerPointsTypes.length - 1) {
0180                             subkf = true
0181                         }
0182                         topRight.x = p1.x
0183                         topRight.y = p1.y
0184                         bottomLeft.x = p1.x
0185                         bottomLeft.y = p1.y
0186                     } else {
0187                         c1 = convertPoint(root.centerPointsTypes[2*i - 1])
0188                         if (root.requestedSubKeyFrame == 2*i - 1) {
0189                             subkf = true
0190                         }
0191                         // Find bounding box
0192                         topRight.x = Math.max(p1.x, topRight.x)
0193                         topRight.y = Math.min(p1.y, topRight.y)
0194                         bottomLeft.x = Math.min(p1.x, bottomLeft.x)
0195                         bottomLeft.y = Math.max(p1.y, bottomLeft.y)
0196                     }
0197                     c2 = convertPoint(root.centerPointsTypes[2*i])
0198                     ctx.bezierCurveTo(c1.x, c1.y, c2.x, c2.y, p1.x, p1.y);
0199                     if ((iskeyframe || autoKeyframe) && !root.displayResize) {
0200                         // Draw control points and segments
0201                         if (subkf) {
0202                             ctx.fillStyle = activePalette.highlight
0203                             ctx.fillRect(c1.x - handleSize/2, c1.y - handleSize/2, handleSize, handleSize);
0204                             ctx.fillStyle = Qt.rgba(1, 0, 0, 0.5)
0205                         } else {
0206                             ctx.fillRect(c1.x - handleSize/2, c1.y - handleSize/2, handleSize, handleSize);
0207                         }
0208                         if (root.requestedSubKeyFrame == 2 * i) {
0209                             ctx.fillStyle = activePalette.highlight
0210                             ctx.fillRect(c2.x - handleSize/2, c2.y - handleSize/2, handleSize, handleSize);
0211                             ctx.fillStyle = Qt.rgba(1, 0, 0, 0.5)
0212                         } else {
0213                             ctx.fillRect(c2.x - handleSize/2, c2.y - handleSize/2, handleSize, handleSize);
0214                         }
0215                         if (i == root.requestedKeyFrame) {
0216                             ctx.fillStyle = activePalette.highlight
0217                             ctx.fillRect(p1.x - handleSize, p1.y - handleSize, 2 * handleSize, 2 * handleSize);
0218                             ctx.fillStyle = Qt.rgba(1, 0, 0, 0.5)
0219                         } else {
0220                             ctx.fillRect(p1.x - handleSize, p1.y - handleSize, 2 * handleSize, 2 * handleSize);
0221                         }
0222                         c1 = convertPoint(root.centerPointsTypes[2*i + 1])
0223                         ctx.lineTo(c1.x, c1.y)
0224                         ctx.moveTo(p1.x, p1.y)
0225                         ctx.lineTo(c2.x, c2.y)
0226                         ctx.moveTo(p1.x, p1.y)
0227                     }
0228                 }
0229                 if (root.centerPoints.length > 2) {
0230                     // Close shape
0231                     c1 = convertPoint(root.centerPointsTypes[root.centerPointsTypes.length - 1])
0232                     c2 = convertPoint(root.centerPointsTypes[0])
0233                     ctx.bezierCurveTo(c1.x, c1.y, c2.x, c2.y, startP.x, startP.y);
0234                 }
0235                 // Calculate and draw center
0236                 centerCross.x = bottomLeft.x + (topRight.x - bottomLeft.x)/2
0237                 centerCross.y = topRight.y + (bottomLeft.y - topRight.y)/2
0238                 ctx.moveTo(centerCross.x - root.baseUnit/2, centerCross.y - root.baseUnit/2)
0239                 ctx.lineTo(centerCross.x + root.baseUnit/2, centerCross.y + root.baseUnit/2)
0240                 ctx.moveTo(centerCross.x + root.baseUnit/2, centerCross.y - root.baseUnit/2)
0241                 ctx.lineTo(centerCross.x - root.baseUnit/2, centerCross.y + root.baseUnit/2)
0242             }
0243             ctx.stroke()
0244             if (root.addedPointIndex > -1 && !root.displayResize) {
0245                 // Ghost point where a new one could be inserted
0246                 ctx.beginPath()
0247                 ctx.fillStyle = activePalette.highlight
0248                 ctx.strokeStyle = activePalette.highlight
0249                 ctx.lineWidth = 1
0250                 ctx.roundedRect(addPointPossible.x - handleSize, addPointPossible.y - handleSize, 2 * handleSize, 2 * handleSize, handleSize, handleSize);
0251                 if (root.addedPointIndex === 0) {
0252                     p1 = convertPoint(root.centerPoints[root.centerPoints.length - 1])
0253                 } else {
0254                     p1 = convertPoint(root.centerPoints[root.addedPointIndex - 1])
0255                 }
0256                 // Segment where the point would be added
0257                 ctx.moveTo(p1.x, p1.y)
0258                 var p2 = convertPoint(root.centerPoints[root.addedPointIndex])
0259                 ctx.lineTo(p2.x, p2.y)
0260                 ctx.stroke()
0261             }
0262             if (root.displayResize) {
0263                 // Draw resize rectangle / handles
0264                 ctx.beginPath()
0265                 ctx.fillStyle = alphaColor
0266                 ctx.strokeStyle = activePalette.highlight
0267                 ctx.lineWidth = 1
0268                 ctx.rect(bottomLeft.x, topRight.y, topRight.x - bottomLeft.x, bottomLeft.y - topRight.y)
0269                 if (root.resizeContainsMouse == 4) {
0270                     ctx.fillStyle = activePalette.highlight
0271                     ctx.fillRect(bottomLeft.x - handleSize, bottomLeft.y - handleSize, 2 * handleSize, 2 * handleSize);
0272                     ctx.fillStyle = alphaColor
0273                 } else {
0274                     ctx.fillRect(bottomLeft.x - handleSize, bottomLeft.y - handleSize, 2 * handleSize, 2 * handleSize);
0275                 }
0276                 if (root.resizeContainsMouse == 3) {
0277                     ctx.fillStyle = activePalette.highlight
0278                     ctx.fillRect(topRight.x - handleSize, bottomLeft.y - handleSize, 2 * handleSize, 2 * handleSize);
0279                     ctx.fillStyle = alphaColor
0280                 } else {
0281                     ctx.fillRect(topRight.x - handleSize, bottomLeft.y - handleSize, 2 * handleSize, 2 * handleSize);
0282                 }
0283                 if (root.resizeContainsMouse == 2) {
0284                     ctx.fillStyle = activePalette.highlight
0285                     ctx.fillRect(topRight.x - handleSize, topRight.y - handleSize, 2 * handleSize, 2 * handleSize);
0286                     ctx.fillStyle = alphaColor
0287                 } else {
0288                     ctx.fillRect(topRight.x - handleSize, topRight.y - handleSize, 2 * handleSize, 2 * handleSize);
0289                 }
0290                 if (root.resizeContainsMouse == 1) {
0291                     ctx.fillStyle = activePalette.highlight
0292                     ctx.fillRect(bottomLeft.x - handleSize, topRight.y - handleSize, 2 * handleSize, 2 * handleSize);
0293                     ctx.fillStyle = alphaColor
0294                 } else {
0295                     ctx.fillRect(bottomLeft.x - handleSize, topRight.y - handleSize, 2 * handleSize, 2 * handleSize);
0296                 }
0297                 if (root.resizeContainsMouse == 5) {
0298                     ctx.fillStyle = activePalette.highlight
0299                     ctx.fillRect(bottomLeft.x + (topRight.x - bottomLeft.x) / 2 - handleSize, topRight.y - handleSize, 2 * handleSize, 2 * handleSize);
0300                     ctx.fillStyle = alphaColor
0301                 } else {
0302                     ctx.fillRect(bottomLeft.x + (topRight.x - bottomLeft.x) / 2 - handleSize, topRight.y - handleSize, 2 * handleSize, 2 * handleSize);
0303                 }
0304                 if (root.resizeContainsMouse == 7) {
0305                     ctx.fillStyle = activePalette.highlight
0306                     ctx.fillRect(bottomLeft.x + (topRight.x - bottomLeft.x) / 2 - handleSize, bottomLeft.y - handleSize, 2 * handleSize, 2 * handleSize);
0307                     ctx.fillStyle = alphaColor
0308                 } else {
0309                     ctx.fillRect(bottomLeft.x + (topRight.x - bottomLeft.x) / 2 - handleSize, bottomLeft.y - handleSize, 2 * handleSize, 2 * handleSize);
0310                 }
0311                 if (root.resizeContainsMouse == 6) {
0312                     ctx.fillStyle = activePalette.highlight
0313                     ctx.fillRect(topRight.x - handleSize, topRight.y + (bottomLeft.y - topRight.y) / 2 - handleSize, 2 * handleSize, 2 * handleSize);
0314                     ctx.fillStyle = alphaColor
0315                 } else {
0316                     ctx.fillRect(topRight.x - handleSize, topRight.y + (bottomLeft.y - topRight.y) / 2 - handleSize, 2 * handleSize, 2 * handleSize);
0317                 }
0318                 if (root.resizeContainsMouse == 8) {
0319                     ctx.fillStyle = activePalette.highlight
0320                     ctx.fillRect(bottomLeft.x - handleSize, topRight.y + (bottomLeft.y - topRight.y) / 2 - handleSize, 2 * handleSize, 2 * handleSize);
0321                     ctx.fillStyle = alphaColor
0322                 } else {
0323                     ctx.fillRect(bottomLeft.x - handleSize, topRight.y + (bottomLeft.y - topRight.y) / 2 - handleSize, 2 * handleSize, 2 * handleSize);
0324                 }
0325                 ctx.stroke()
0326             }
0327     }
0328 
0329     function convertPoint(p)
0330     {
0331         var x = frame.x + p.x * root.scalex
0332         var y = frame.y + p.y * root.scaley
0333         return Qt.point(x,y);
0334     }
0335   }
0336 
0337     Rectangle {
0338         id: frame
0339         objectName: "referenceframe"
0340         width: root.profile.x * root.scalex
0341         height: root.profile.y * root.scaley
0342         x: root.center.x - width / 2 - root.offsetx;
0343         y: root.center.y - height / 2 - root.offsety;
0344         color: "transparent"
0345         border.color: "#ffffff00"
0346         Loader {
0347             anchors.fill: parent
0348             source: {
0349                 switch(root.overlayType)
0350                 {
0351                     case 0:
0352                         return '';
0353                     case 1:
0354                         return "OverlayStandard.qml";
0355                     case 2:
0356                         return "OverlayMinimal.qml";
0357                     case 3:
0358                         return "OverlayCenter.qml";
0359                     case 4:
0360                         return "OverlayCenterDiagonal.qml";
0361                     case 5:
0362                         return "OverlayThirds.qml";
0363                 }
0364             }
0365         }
0366     }
0367 
0368     Rectangle {
0369         anchors.centerIn: parent
0370         width: label.contentWidth + 6
0371         height: label.contentHeight + 6
0372         visible: !root.isDefined && !global.containsMouse
0373         opacity: 0.8
0374         Text {
0375             id: label
0376             text: i18n("Click to add points,\nright click to close shape.")
0377             font: fixedFont
0378             verticalAlignment: Text.AlignVCenter
0379             horizontalAlignment: Text.AlignHCenter
0380             anchors {
0381                 fill: parent
0382             }
0383             color: 'black'
0384          }
0385         color: "yellow"
0386     }
0387 
0388     MouseArea {
0389         id: global
0390         objectName: "global"
0391         acceptedButtons: Qt.LeftButton | Qt.RightButton
0392         anchors.fill: parent
0393         anchors.bottomMargin: clipMonitorRuler.height
0394         property bool pointContainsMouse
0395         property bool centerContainsMouse
0396         hoverEnabled: true
0397         cursorShape: (!root.isDefined || pointContainsMouse || centerContainsMouse || addedPointIndex >= 0 || resizeContainsMouse > 0 ) ? Qt.PointingHandCursor : Qt.ArrowCursor
0398         onEntered: {
0399             if(!root.isDefined) {
0400                 controller.setWidgetKeyBinding(emptyCanvasKeyBindInfo);
0401             } else if(root.displayResize){
0402                 controller.setWidgetKeyBinding(resizeKeyBindInfo);
0403             } else {
0404                 controller.setWidgetKeyBinding(defaultKeyBindInfo);
0405             }
0406         }
0407         onExited: {
0408             controller.setWidgetKeyBinding()
0409         }
0410         onWheel: wheel => {
0411             controller.seek(wheel.angleDelta.x + wheel.angleDelta.y, wheel.modifiers)
0412         }
0413         onDoubleClicked: {
0414             if (root.isDefined) {
0415                 if (root.iskeyframe == false && controller.autoKeyframe) {
0416                     controller.addRemoveKeyframe();
0417                 }
0418                 if (root.displayResize) {
0419                     // Disable resize mode
0420                     root.displayResize = false
0421                     canvas.requestPaint()
0422                     return
0423                 } else if (centerContainsMouse) {
0424                     // Enable resize mode
0425                     root.displayResize = true
0426                     canvas.requestPaint()
0427                     return
0428                 }
0429                 if (root.requestedKeyFrame > -1) {
0430                     // Remove existing keyframe
0431                     if (root.centerPoints.length > 3) {
0432                         root.centerPoints.splice(root.requestedKeyFrame, 1)
0433                         root.centerPointsTypes.splice(2 * root.requestedKeyFrame, 2)
0434                         root.effectPolygonChanged(root.centerPoints, root.centerPointsTypes)
0435                         root.requestedKeyFrame = -1
0436                         canvas.requestPaint()
0437                     }
0438                     return
0439                 }
0440                 // Add new keyframe
0441                 if (addPointPossible.x > 0 && root.addedPointIndex >= 0) {
0442                     var p0; var p1; var p2;
0443                     var newPoint = Qt.point((addPointPossible.x - frame.x) / root.scalex, (addPointPossible.y - frame.y) / root.scaley);
0444                     p1 = root.centerPoints[root.addedPointIndex]
0445                     if (root.addedPointIndex == 0) {
0446                         p0 = root.centerPoints[root.centerPoints.length - 1]
0447                     } else {
0448                         p0 = root.centerPoints[root.addedPointIndex - 1]
0449                     }
0450                     var ctrl1 = Qt.point((p0.x - newPoint.x) / 5, (p0.y - newPoint.y) / 5);
0451                     var ctrl2 = Qt.point((p1.x - newPoint.x) / 5, (p1.y - newPoint.y) / 5);
0452                     if (root.addedPointIndex == 0) {
0453                         root.centerPoints.push(newPoint)
0454                         root.centerPointsTypes.push(Qt.point(newPoint.x + ctrl1.x, newPoint.y + ctrl1.y))
0455                         root.centerPointsTypes.push(Qt.point(newPoint.x + ctrl2.x, newPoint.y + ctrl2.y))
0456                     } else {
0457                         root.centerPoints.splice(root.addedPointIndex, 0, newPoint)
0458                         root.centerPointsTypes.splice(2 * root.addedPointIndex, 0, Qt.point(newPoint.x + ctrl2.x, newPoint.y + ctrl2.y))
0459                         root.centerPointsTypes.splice(2 * root.addedPointIndex, 0, Qt.point(newPoint.x + ctrl1.x, newPoint.y + ctrl1.y))
0460                     }
0461                     root.effectPolygonChanged(root.centerPoints, root.centerPointsTypes)
0462                     canvas.requestPaint()
0463                 }
0464             }
0465         }
0466 
0467         onClicked: mouse => {
0468             if (!root.isDefined) {
0469                 if (mouse.button == Qt.RightButton && root.centerPoints.length > 2) {
0470                     // close shape, define control points
0471                     var p0; var p1; var p2
0472                     for (var i = 0; i < root.centerPoints.length; i++) {
0473                         p1 = root.centerPoints[i]
0474                         if (i == 0) {
0475                             p0 = root.centerPoints[root.centerPoints.length - 1]
0476                         } else {
0477                             p0 = root.centerPoints[i - 1]
0478                         }
0479                         if (i == root.centerPoints.length - 1) {
0480                             p2 = root.centerPoints[0]
0481                         } else {
0482                             p2 = root.centerPoints[i + 1]
0483                         }
0484                         var ctrl1 = Qt.point((p0.x - p1.x) / 5, (p0.y - p1.y) / 5);
0485                         var ctrl2 = Qt.point((p2.x - p1.x) / 5, (p2.y - p1.y) / 5);
0486                         root.centerPointsTypes.push(Qt.point(p1.x + ctrl1.x, p1.y + ctrl1.y))
0487                         root.centerPointsTypes.push(Qt.point(p1.x + ctrl2.x, p1.y + ctrl2.y))
0488                     }
0489                     root.isDefined = true;
0490                     root.effectPolygonChanged(root.centerPoints, root.centerPointsTypes)
0491                     canvas.requestPaint()
0492                 } else if (root.requestedKeyFrame < 0) {
0493                     var newPoint = Qt.point((mouseX - frame.x) / root.scalex, (mouseY - frame.y) / root.scaley);
0494                     root.centerPoints.push(newPoint)
0495                     canvas.requestPaint()
0496                 }
0497             }
0498         }
0499 
0500         onPositionChanged: mouse => {
0501             if (pressed && root.iskeyframe == false) {
0502                 if (controller.autoKeyframe) {
0503                     controller.addRemoveKeyframe();
0504                 } else {
0505                     return;
0506                 }
0507             }
0508             if (pressed) {
0509                 if (root.resizeContainsMouse > 0) {
0510                     // resizing shape
0511                     var movingCorner = []
0512                     var referenceCorner = []
0513                     if (root.resizeContainsMouse == 1) {
0514                         // Top left resize
0515                         movingCorner = Qt.point(bottomLeft.x, topRight.y)
0516                         referenceCorner = Qt.point(topRight.x, bottomLeft.y)
0517                     } else if (root.resizeContainsMouse == 2) {
0518                         // Top right resize
0519                         movingCorner = Qt.point(topRight.x, topRight.y)
0520                         referenceCorner = Qt.point(bottomLeft.x, bottomLeft.y)
0521                     } else if (root.resizeContainsMouse == 3) {
0522                         // Bottom right resize
0523                         movingCorner = Qt.point(topRight.x, bottomLeft.y)
0524                         referenceCorner = Qt.point(bottomLeft.x, topRight.y)
0525                     } else if (root.resizeContainsMouse == 4) {
0526                         // Bottom left resize
0527                         movingCorner = Qt.point(bottomLeft.x, bottomLeft.y)
0528                         referenceCorner = Qt.point(topRight.x, topRight.y)
0529                     } else if (root.resizeContainsMouse == 5) {
0530                         // top resize
0531                         movingCorner = Qt.point(bottomLeft.x + (topRight.x - bottomLeft.x) / 2, topRight.y)
0532                         referenceCorner = Qt.point(bottomLeft.x + (topRight.x - bottomLeft.x) / 2, bottomLeft.y)
0533                     } else if (root.resizeContainsMouse == 7) {
0534                         // bottom resize
0535                         movingCorner = Qt.point(bottomLeft.x + (topRight.x - bottomLeft.x) / 2, bottomLeft.y)
0536                         referenceCorner = Qt.point(bottomLeft.x + (topRight.x - bottomLeft.x) / 2, topRight.y)
0537                     } else if (root.resizeContainsMouse == 6) {
0538                         // right resize
0539                         movingCorner = Qt.point(topRight.x, topRight.y + (bottomLeft.y - topRight.y) / 2)
0540                         referenceCorner = Qt.point(bottomLeft.x, topRight.y + (bottomLeft.y - topRight.y) / 2)
0541                     } else if (root.resizeContainsMouse == 8) {
0542                         // left resize
0543                         movingCorner = Qt.point(bottomLeft.x, topRight.y + (bottomLeft.y - topRight.y) / 2)
0544                         referenceCorner = Qt.point(topRight.x, topRight.y + (bottomLeft.y - topRight.y) / 2)
0545                     }
0546                     if(mouse.modifiers && mouse.modifiers === Qt.ShiftModifier) {
0547                         referenceCorner = Qt.point(centerCross.x, centerCross.y)
0548                     }
0549                     var originalDist = Math.sqrt( Math.pow(movingCorner.x - referenceCorner.x, 2) + Math.pow(movingCorner.y - referenceCorner.y, 2) );
0550                     var mouseDist = Math.sqrt( Math.pow(mouseX - referenceCorner.x, 2) + Math.pow(mouseY - referenceCorner.y, 2) );
0551                     var factor = Math.max(0.1, mouseDist / originalDist)
0552                     for (var j = 0; j < root.centerPoints.length; j++) {
0553                         if (root.resizeContainsMouse != 5 && root.resizeContainsMouse!= 7) {
0554                             root.centerPoints[j].x = (referenceCorner.x - frame.x + (root.centerPoints[j].x * root.scalex - (referenceCorner.x - frame.x)) * factor) / root.scalex
0555                             root.centerPointsTypes[j * 2].x = (referenceCorner.x - frame.x + (root.centerPointsTypes[j * 2].x * root.scalex - (referenceCorner.x - frame.x)) * factor) / root.scalex
0556                             root.centerPointsTypes[j * 2 + 1].x = (referenceCorner.x - frame.x + (root.centerPointsTypes[j * 2 + 1].x * root.scalex - (referenceCorner.x - frame.x)) * factor) / root.scalex
0557                         }
0558                         if (root.resizeContainsMouse != 6 && root.resizeContainsMouse!= 8) {
0559                             root.centerPoints[j].y = (referenceCorner.y - frame.y + (root.centerPoints[j].y * root.scaley - (referenceCorner.y - frame.y)) * factor) / root.scaley
0560                             root.centerPointsTypes[j * 2].y = (referenceCorner.y - frame.y + (root.centerPointsTypes[j * 2].y * root.scaley - (referenceCorner.y - frame.y)) * factor) / root.scaley
0561                             root.centerPointsTypes[j * 2 + 1].y = (referenceCorner.y - frame.y + (root.centerPointsTypes[j * 2 + 1].y * root.scaley - (referenceCorner.y - frame.y)) * factor) / root.scaley
0562                         }
0563                     }
0564                     canvas.requestPaint()
0565                     root.effectPolygonChanged(root.centerPoints, root.centerPointsTypes)
0566                     return
0567                 }
0568                 if (centerContainsMouse) {
0569                     // moving shape
0570                     var xDiff = (mouseX - centerCross.x) / root.scalex
0571                     var yDiff = (mouseY - centerCross.y) / root.scaley
0572                     for (var j = 0; j < root.centerPoints.length; j++) {
0573                         root.centerPoints[j].x += xDiff
0574                         root.centerPoints[j].y += yDiff
0575                         root.centerPointsTypes[j * 2].x += xDiff
0576                         root.centerPointsTypes[j * 2].y += yDiff
0577                         root.centerPointsTypes[j * 2 + 1].x += xDiff
0578                         root.centerPointsTypes[j * 2 + 1].y += yDiff
0579                     }
0580                     canvas.requestPaint()
0581                     root.effectPolygonChanged(root.centerPoints, root.centerPointsTypes)
0582                     return
0583                 }
0584                 if (root.requestedKeyFrame >= 0) {
0585                     var xDiff = (mouseX - frame.x) / root.scalex - root.centerPoints[root.requestedKeyFrame].x
0586                     var yDiff = (mouseY - frame.y) / root.scaley - root.centerPoints[root.requestedKeyFrame].y
0587                     root.centerPoints[root.requestedKeyFrame].x += xDiff
0588                     root.centerPoints[root.requestedKeyFrame].y += yDiff
0589                     if (root.centerPointsTypes.length > root.requestedKeyFrame * 2 + 1) {
0590                         root.centerPointsTypes[root.requestedKeyFrame * 2].x += xDiff
0591                         root.centerPointsTypes[root.requestedKeyFrame * 2].y += yDiff
0592                         root.centerPointsTypes[root.requestedKeyFrame * 2 + 1].x += xDiff
0593                         root.centerPointsTypes[root.requestedKeyFrame * 2 + 1].y += yDiff
0594                     }
0595                     canvas.requestPaint()
0596                     if (root.isDefined) {
0597                         root.effectPolygonChanged(root.centerPoints, root.centerPointsTypes)
0598                     }
0599                 } else if (root.requestedSubKeyFrame >= 0) {
0600                     root.centerPointsTypes[root.requestedSubKeyFrame].x = (mouseX - frame.x) / root.scalex
0601                     root.centerPointsTypes[root.requestedSubKeyFrame].y = (mouseY - frame.y) / root.scaley
0602                     canvas.requestPaint()
0603                     root.effectPolygonChanged(root.centerPoints, root.centerPointsTypes)
0604                 }
0605             } else if ((root.iskeyframe || controller.autoKeyframe) && root.centerPoints.length > 0) {
0606               // Check if we are over a keyframe
0607               if (!root.displayResize) {
0608                   addPointPossible = Qt.point(0, 0)
0609                   for(var i = 0; i < root.centerPoints.length; i++)
0610                   {
0611                       var p1 = canvas.convertPoint(root.centerPoints[i])
0612                       if (Math.abs(p1.x - mouseX) <= canvas.handleSize && Math.abs(p1.y - mouseY) <= canvas.handleSize) {
0613                           if (i == root.requestedKeyFrame) {
0614                               centerContainsMouse = false
0615                               pointContainsMouse = true;
0616                               addedPointIndex = -1
0617                               return;
0618                           }
0619                           root.requestedKeyFrame = i
0620                           centerContainsMouse = false
0621                           pointContainsMouse = true;
0622                           addedPointIndex = -1
0623                           canvas.requestPaint()
0624                           return;
0625                       }
0626                   }
0627                   // Check if we are on a control point
0628                   for(var i = 0; i < root.centerPointsTypes.length; i++)
0629                   {
0630                       var p1 = canvas.convertPoint(root.centerPointsTypes[i])
0631                       if (Math.abs(p1.x - mouseX) <= canvas.handleSize/2 && Math.abs(p1.y - mouseY) <= canvas.handleSize/2) {
0632                           if (i == root.requestedSubKeyFrame) {
0633                               centerContainsMouse = false
0634                               pointContainsMouse = true;
0635                               addedPointIndex = -1
0636                               return;
0637                           }
0638                           root.requestedSubKeyFrame = i
0639                           addedPointIndex = -1
0640                           centerContainsMouse = false
0641                           pointContainsMouse = true;
0642                           canvas.requestPaint()
0643                           return;
0644                       } 
0645                   }
0646 
0647                   // Check if we are on a line segment
0648                   if (root.isDefined) {
0649                       var p0; var p1; var p2; var dab; var dap; var dbp;
0650                       var newPoint = Qt.point((mouseX - frame.x) / root.scalex, (mouseY - frame.y) / root.scaley);
0651                       for (var i = 0; i < root.centerPoints.length; i++) {
0652                           p1 = root.centerPoints[i]
0653                           if (i == 0) {
0654                               p0 = root.centerPoints[root.centerPoints.length - 1]
0655                           } else {
0656                               p0 = root.centerPoints[i - 1]
0657                           }
0658                           dab = Math.sqrt(Math.pow(p1.x - p0.x, 2) + Math.pow(p1.y - p0.y, 2))
0659                           dap = Math.sqrt(Math.pow(newPoint.x - p0.x, 2) + Math.pow(newPoint.y - p0.y, 2))
0660                           dbp = Math.sqrt(Math.pow(p1.x - newPoint.x, 2) + Math.pow(p1.y - newPoint.y, 2))
0661                           if (Math.abs(dab - dap - dbp) * root.scalex < 4 && dap > dab / 4 && dbp > dab / 4) {
0662                               addPointPossible = Qt.point(mouseX, mouseY)
0663                               addedPointIndex = i
0664                               root.requestedKeyFrame = -1
0665                               root.requestedSubKeyFrame = -1
0666                               centerContainsMouse = false
0667                               pointContainsMouse = false
0668                               canvas.requestPaint()
0669                               return
0670                           }
0671                       }
0672                   }
0673                   addedPointIndex = -1
0674               }
0675               // Check if we are on center point
0676               if (Math.abs(centerCross.x - mouseX) <= canvas.handleSize && Math.abs(centerCross.y - mouseY) <= canvas.handleSize) {
0677                     centerContainsMouse = true;
0678                     pointContainsMouse = false;
0679                     canvas.requestPaint()
0680                     return;
0681               }
0682               if (root.displayResize) {
0683                   var currentResize = root.resizeContainsMouse
0684                   root.resizeContainsMouse = 0
0685                   // Check if we are on a resize handle
0686                   if (Math.abs(bottomLeft.x - mouseX) <= canvas.handleSize) {
0687                       // close to left side
0688                       if (Math.abs(bottomLeft.y - mouseY) <= canvas.handleSize) {
0689                           // on the bottom left handle
0690                           root.resizeContainsMouse = 4
0691                       } else if (Math.abs(topRight.y - mouseY) <= canvas.handleSize) {
0692                           // on the top left handle
0693                           root.resizeContainsMouse = 1
0694                       } else if (Math.abs(topRight.y + (bottomLeft.y - topRight.y) / 2 - mouseY) <= canvas.handleSize) {
0695                           // Middle left handle
0696                           root.resizeContainsMouse = 8
0697                       }
0698                   } else if (Math.abs(topRight.x - mouseX) <= canvas.handleSize) {
0699                       // close to right side
0700                       if (Math.abs(bottomLeft.y - mouseY) <= canvas.handleSize) {
0701                           // on the bottom right handle
0702                           root.resizeContainsMouse = 3
0703                       } else if (Math.abs(topRight.y - mouseY) <= canvas.handleSize) {
0704                           // on the top right handle
0705                           root.resizeContainsMouse = 2
0706                       } else if (Math.abs(topRight.y + (bottomLeft.y - topRight.y) / 2 - mouseY) <= canvas.handleSize) {
0707                           // Middle left handle
0708                           root.resizeContainsMouse = 6
0709                       }
0710                   } else if (Math.abs(bottomLeft.x + (topRight.x - bottomLeft.x) / 2 - mouseX) <= canvas.handleSize) {
0711                       // horizontal center
0712                       if (Math.abs(bottomLeft.y - mouseY) <= canvas.handleSize) {
0713                           // on the bottom center handle
0714                           root.resizeContainsMouse = 7
0715                       } else if (Math.abs(topRight.y - mouseY) <= canvas.handleSize) {
0716                           // on the top center handle
0717                           root.resizeContainsMouse = 5
0718                       }
0719                   }
0720                   if (currentResize != root.resizeContainsMouse) {
0721                       canvas.requestPaint()
0722                       return;
0723                   }
0724               }
0725               root.requestedKeyFrame = -1
0726               root.requestedSubKeyFrame = -1
0727               pointContainsMouse = false;
0728               centerContainsMouse = false
0729               canvas.requestPaint()
0730             }
0731         }
0732     }
0733 }
0734     EffectToolBar {
0735         id: effectToolBar
0736         anchors {
0737             right: parent.right
0738             top: parent.top
0739             bottom: parent.bottom
0740             rightMargin: 4
0741             leftMargin: 4
0742         }
0743     }
0744     MonitorRuler {
0745         id: clipMonitorRuler
0746         anchors {
0747             left: root.left
0748             right: root.right
0749             bottom: root.bottom
0750         }
0751         height: controller.rulerHeight
0752     }
0753 
0754 }