File indexing completed on 2024-04-14 04:46:26
0001 /* 0002 SPDX-FileCopyrightText: 2021 Jean-Baptiste Mardelle <jb@kdenlive.org> 0003 0004 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #pragma once 0008 0009 #include "ui_timeremap_ui.h" 0010 0011 #include "definitions.h" 0012 #include "utils/timecode.h" 0013 0014 #include <QMutex> 0015 #include <QTimer> 0016 #include <QUuid> 0017 #include <QWidget> 0018 0019 #include "mlt++/Mlt.h" 0020 0021 class ProjectClip; 0022 class TimecodeDisplay; 0023 0024 0025 /** 0026 * @class RemapView 0027 * @brief A widget to view remap keyframes. 0028 * @author Jean-Baptiste Mardelle 0029 */ 0030 0031 class RemapView : public QWidget 0032 { 0033 Q_OBJECT 0034 0035 public: 0036 friend class TimeRemap; 0037 explicit RemapView(QWidget *parent = nullptr); 0038 void setBinClipDuration(std::shared_ptr<ProjectClip> clip, int duration); 0039 void setDuration(std::shared_ptr<Mlt::Producer> service, int duration, int sourceDuration = 0); 0040 void loadKeyframes(const QString &mapData); 0041 const QString getKeyframesData(QMap<int,int> keyframes = {}) const; 0042 int position() const; 0043 int remapDuration() const; 0044 int remapMax() const; 0045 bool movingKeyframe() const; 0046 void refreshOnDurationChanged(int remapDuration); 0047 /** @brief Returns true if timeline cursor is inside the remapped clip */ 0048 bool isInRange() const; 0049 QTimer timer; 0050 0051 protected: 0052 void resizeEvent(QResizeEvent *event) override; 0053 void paintEvent(QPaintEvent *event) override; 0054 void mouseMoveEvent(QMouseEvent *event) override; 0055 void mousePressEvent(QMouseEvent *event) override; 0056 void mouseReleaseEvent(QMouseEvent *event) override; 0057 void wheelEvent(QWheelEvent *event) override; 0058 Mlt::Properties m_remapProps; 0059 /** @brief The position of the clip in timeline, used to seek to correct place */ 0060 int m_startPos; 0061 /** @brief The in frame of the clip in timeline, used to correctly offset keyframes */ 0062 int m_inFrame; 0063 int m_oldInFrame; 0064 /** @brief the original in/out of the clip when opening the remap widget, used to snap to ends */ 0065 std::pair<int,int> m_originalRange; 0066 0067 public Q_SLOTS: 0068 void updateInPos(int pos); 0069 void updateOutPos(int pos); 0070 void slotSetPosition(int pos); 0071 void slotSetBottomPosition(int pos); 0072 void addKeyframe(); 0073 void goNext(); 0074 void goPrev(); 0075 void updateBeforeSpeed(double speed); 0076 void updateAfterSpeed(double speed); 0077 void toggleMoveNext(bool moveNext); 0078 void reloadProducer(); 0079 void centerCurrentKeyframe(); 0080 void centerCurrentTopKeyframe(); 0081 0082 private: 0083 enum MOVEMODE {NoMove, TopMove, BottomMove, CursorMove, CursorMoveBottom}; 0084 int m_duration; 0085 int m_sourceDuration; 0086 int m_lastMaxDuration; 0087 int m_position; 0088 /** @brief the maximum duration of the parent (bin) clip */ 0089 int m_maxLength; 0090 int m_bottomPosition; 0091 double m_scale; 0092 QColor m_colSelected; 0093 QColor m_colKeyframe; 0094 int m_zoomHeight; 0095 int m_centerPos; 0096 int m_lineHeight; 0097 double m_zoomFactor; 0098 double m_zoomStart; 0099 /** @brief The zoom factor (start, end - between 0 and 1) */ 0100 QPointF m_zoomHandle; 0101 /** @brief the keyframes for the remap effect. first value is output, second is source time */ 0102 QMap<int, int>m_keyframes; 0103 QMap<int, int>m_keyframesOrigin; 0104 std::shared_ptr<ProjectClip> m_clip; 0105 std::shared_ptr<Mlt::Producer> m_service; 0106 QPointF m_lastZoomHandle; 0107 /** @brief Mouse is the zoom left handle */ 0108 bool m_hoverZoomIn; 0109 /** @brief Mouse is the zoom right handle */ 0110 bool m_hoverZoomOut; 0111 /** @brief Mouse is over the zoom bar */ 0112 bool m_hoverZoom; 0113 int m_bottomView; 0114 std::pair<int, int> m_currentKeyframe{-1, -1}; 0115 std::pair<int, int> m_currentKeyframeOriginal{-1, -1}; 0116 MOVEMODE m_moveKeyframeMode; 0117 double m_clickOffset; 0118 int m_clickPoint; 0119 bool m_moveNext; 0120 int m_clickEnd; 0121 int m_offset; 0122 QMutex m_kfrMutex; 0123 QMap <int,int>m_selectedKeyframes; 0124 QMap<int,int>m_previousSelection; 0125 std::pair<int,int> getClosestKeyframe(int pos, bool bottomKeyframe = false) const; 0126 std::pair<double,double> getSpeed(std::pair<int,int>kf); 0127 0128 Q_SIGNALS: 0129 void seekToPos(int,int); 0130 void selectedKf(std::pair<int,int>, std::pair<double,double>, std::pair<bool,bool>atEnd = {true,true}); 0131 void updateSpeeds(std::pair<double,double>); 0132 /** When the cursor position changes inform parent if we are on a keyframe or not. */ 0133 void atKeyframe(bool isKeyframe, bool last); 0134 void updateKeyframes(bool resize); 0135 void updateKeyframesWithUndo(QMap<int,int>updatedKeyframes, QMap<int,int>previousKeyframes); 0136 void updateMaxDuration(); 0137 }; 0138 0139 /** 0140 * @class TimeRemap 0141 * @brief A dialog for editing time remap effect. 0142 * @author Jean-Baptiste Mardelle 0143 */ 0144 class TimeRemap : public QWidget, public Ui::TimeRemap_UI 0145 { 0146 Q_OBJECT 0147 0148 public: 0149 explicit TimeRemap(QWidget *parent = nullptr); 0150 ~TimeRemap() override; 0151 void selectedClip(int cid, const QUuid uuid); 0152 void setClip(std::shared_ptr<ProjectClip> clip, int in = -1, int out = -1); 0153 /** @brief the bin id of the clip currently active in remap widget */ 0154 const QString ¤tClip() const; 0155 /** @brief Returns true if timeline cursor is inside the remapped clip */ 0156 bool isInRange() const; 0157 0158 private Q_SLOTS: 0159 void updateKeyframes(); 0160 void updateKeyframesWithUndo(const QMap<int,int>&updatedKeyframes, const QMap<int,int>&previousKeyframes); 0161 void checkClipUpdate(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int>& roles); 0162 void switchRemapParam(); 0163 void monitorSeek(int pos); 0164 0165 private: 0166 std::shared_ptr<Mlt::Link> m_remapLink; 0167 std::shared_ptr<Mlt::Link> m_splitRemap; 0168 RemapView *m_view; 0169 int m_lastLength; 0170 int m_cid; 0171 QUuid m_uuid; 0172 int m_splitId; 0173 QString m_binId; 0174 QMetaObject::Connection m_seekConnection1; 0175 QMetaObject::Connection m_seekConnection2; 0176 QMetaObject::Connection m_seekConnection3; 0177 0178 };