File indexing completed on 2024-05-12 04:52:47
0001 /* 0002 SPDX-FileCopyrightText: 2017 Nicolas Carion 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 0006 #pragma once 0007 0008 #include "definitions.h" 0009 #include "keyframemodel.hpp" 0010 #include "undohelper.hpp" 0011 #include "utils/gentime.h" 0012 0013 #include <QReadWriteLock> 0014 0015 #include <QObject> 0016 #include <map> 0017 #include <memory> 0018 #include <unordered_map> 0019 0020 class AssetParameterModel; 0021 class DocUndoStack; 0022 0023 /** @class KeyframeModelList 0024 @brief This class is a container for the keyframe models. 0025 If an asset has several keyframable parameters, each one has its own keyframeModel, 0026 but we regroup all of these in a common class to provide unified access. 0027 */ 0028 class KeyframeModelList : public QObject 0029 { 0030 Q_OBJECT 0031 0032 public: 0033 /** @brief Construct a keyframe list bound to the given asset 0034 @param init_value and index correspond to the first parameter 0035 */ 0036 explicit KeyframeModelList(std::weak_ptr<AssetParameterModel> model, const QModelIndex &index, std::weak_ptr<DocUndoStack> undo_stack, int in, int out); 0037 0038 /** @brief Add a keyframable parameter to be managed by this model */ 0039 void addParameter(const QModelIndex &index, int in, int out); 0040 0041 /** @brief Adds a keyframe at the given position. If there is already one then we update it. 0042 @param pos defines the position of the keyframe, relative to the clip 0043 @param type is the type of the keyframe. 0044 */ 0045 bool addKeyframe(GenTime pos, KeyframeType type); 0046 bool addKeyframe(int frame, double val); 0047 0048 /** @brief Removes the keyframe at the given position. */ 0049 bool removeKeyframe(GenTime pos); 0050 bool removeKeyframeWithUndo(GenTime pos, Fun &undo, Fun &redo); 0051 0052 /** @brief Duplicate a keyframe at the given position. */ 0053 bool duplicateKeyframeWithUndo(GenTime srcPos, GenTime destPos, Fun &undo, Fun &redo); 0054 /** @brief Delete all the keyframes of the model (except first) */ 0055 bool removeAllKeyframes(); 0056 /** @brief Delete all the keyframes after a certain position (except first) */ 0057 bool removeNextKeyframes(GenTime pos); 0058 0059 /** @brief moves a keyframe 0060 @param oldPos is the old position of the keyframe 0061 @param pos defines the new position of the keyframe, relative to the clip 0062 @param logUndo if true, then an undo object is created 0063 */ 0064 bool moveKeyframe(GenTime oldPos, GenTime pos, bool logUndo, bool updateView = true); 0065 bool moveKeyframeWithUndo(GenTime oldPos, GenTime pos, Fun &undo, Fun &redo); 0066 0067 /** @brief updates the value of a keyframe 0068 @param pos is the position of the keyframe 0069 @param value is the new value of the param 0070 @param index is the index of the wanted keyframe 0071 */ 0072 bool updateKeyframe(GenTime pos, const QVariant &value, const QPersistentModelIndex &index, QUndoCommand *parentCommand = nullptr); 0073 /** @brief updates the value of a keyframe which contains multiple params, like Lift/Gamma/Gain 0074 @param pos is the position of the keyframe 0075 @param sourceValues is the list of previous values (used when undoing) 0076 @param values is the new values list 0077 @param indexes is the index list of the wanted keyframe 0078 */ 0079 bool updateMultiKeyframe(GenTime pos, const QStringList &sourceValues, const QStringList &values, const QList<QModelIndex> &indexes, 0080 QUndoCommand *parentCommand = nullptr); 0081 bool updateKeyframeType(GenTime pos, int type, const QPersistentModelIndex &index); 0082 bool updateKeyframe(GenTime oldPos, GenTime pos, const QVariant &normalizedVal, bool logUndo = true); 0083 KeyframeType keyframeType(GenTime pos) const; 0084 /** @brief Returns a keyframe data at given pos 0085 ok is a return parameter, set to true if everything went good 0086 */ 0087 Keyframe getKeyframe(const GenTime &pos, bool *ok) const; 0088 0089 /** @brief Returns true if we only have 1 keyframe 0090 */ 0091 bool singleKeyframe() const; 0092 /** @brief Returns true if we only have no keyframe 0093 */ 0094 bool isEmpty() const; 0095 /** @brief Returns the number of keyframes 0096 */ 0097 int count() const; 0098 0099 /** @brief Returns the keyframe located after given position. 0100 If there is a keyframe at given position it is ignored. 0101 @param ok is a return parameter to tell if a keyframe was found. 0102 */ 0103 Keyframe getNextKeyframe(const GenTime &pos, bool *ok) const; 0104 0105 /** @brief Returns the keyframe located before given position. 0106 If there is a keyframe at given position it is ignored. 0107 @param ok is a return parameter to tell if a keyframe was found. 0108 */ 0109 Keyframe getPrevKeyframe(const GenTime &pos, bool *ok) const; 0110 0111 /** @brief Returns the closest keyframe from given position. 0112 @param ok is a return parameter to tell if a keyframe was found. 0113 */ 0114 Keyframe getClosestKeyframe(const GenTime &pos, bool *ok) const; 0115 0116 /** @brief Returns true if a keyframe exists at given pos 0117 Notice that add/remove queries are done in real time (gentime), but this request is made in frame 0118 */ 0119 Q_INVOKABLE bool hasKeyframe(int frame) const; 0120 0121 /** @brief Return the interpolated value of a parameter. 0122 @param pos is the position where we interpolate 0123 @param index is the index of the queried parameter. */ 0124 QVariant getInterpolatedValue(int pos, const QPersistentModelIndex &index) const; 0125 /** @brief Return the interpolated value of a parameter. 0126 @param pos is the position where we interpolate 0127 @param index is the index of the queried parameter. */ 0128 QVariant getInterpolatedValue(const GenTime &pos, const QPersistentModelIndex &index) const; 0129 0130 /** @brief Load keyframes from the current parameter value. */ 0131 void refresh(); 0132 void setParametersFromTask(const paramVector ¶ms); 0133 /** @brief Reset all keyframes and add a default one */ 0134 void reset(); 0135 Q_INVOKABLE KeyframeModel *getKeyModel(); 0136 KeyframeModel *getKeyModel(const QPersistentModelIndex &index); 0137 /** @brief Returns parent asset owner id*/ 0138 ObjectId getOwnerId() const; 0139 /** @brief Returns parent asset id*/ 0140 const QString getAssetId(); 0141 const QString getAssetRow(); 0142 0143 /** @brief Returns the list of selected keyframes */ 0144 QVector<int> selectedKeyframes() const; 0145 /** @brief Remove a position from selected keyframes */ 0146 void removeFromSelected(int pos); 0147 /** @brief Replace list of selected keyframes */ 0148 void setSelectedKeyframes(const QVector<int> &list); 0149 /** @brief Append a keyframe to selection */ 0150 void appendSelectedKeyframe(int frame); 0151 0152 /** @brief Get the currently active keyframe */ 0153 int activeKeyframe() const; 0154 /** @brief Set the currently active keyframe */ 0155 void setActiveKeyframe(int pos); 0156 0157 /** @brief Parent item size change, update keyframes*/ 0158 void resizeKeyframes(int oldIn, int oldOut, int in, int out, int offset, bool adjustFromEnd, Fun &undo, Fun &redo); 0159 0160 /** @brief Parent item size change, update keyframes*/ 0161 void moveKeyframes(int oldIn, int in, Fun &undo, Fun &redo); 0162 0163 /** @brief Return position of the nth keyframe (ix = nth)*/ 0164 GenTime getPosAtIndex(int ix); 0165 int getIndexForPos(GenTime pos); 0166 QModelIndex getIndexAtRow(int row); 0167 0168 /** @brief Check that all keyframable parameters have the same keyframes on loading 0169 * (that's how our model works) */ 0170 void checkConsistency(); 0171 /** @brief Returns the indexes of all parameters */ 0172 std::vector<QPersistentModelIndex> getIndexes(); 0173 0174 protected: 0175 /** @brief Helper function to apply a given operation on all parameters */ 0176 bool applyOperation(const std::function<bool(std::shared_ptr<KeyframeModel>, Fun &, Fun &)> &op, const QString &undoString); 0177 0178 Q_SIGNALS: 0179 void modelChanged(); 0180 void modelDisplayChanged(); 0181 0182 private: 0183 std::weak_ptr<AssetParameterModel> m_model; 0184 std::weak_ptr<DocUndoStack> m_undoStack; 0185 std::unordered_map<QPersistentModelIndex, std::shared_ptr<KeyframeModel>> m_parameters; 0186 /** @brief Index of the parameter that is displayed in timeline */ 0187 QModelIndex m_inTimelineIndex; 0188 mutable QReadWriteLock m_lock; // This is a lock that ensures safety in case of concurrent access 0189 0190 private Q_SLOTS: 0191 void slotUpdateModels(const QModelIndex &ix1, const QModelIndex &ix2, const QVector<int> &roles); 0192 0193 public: 0194 // this is to enable for range loops 0195 auto begin() -> decltype(m_parameters.begin()->second->begin()) { return m_parameters.begin()->second->begin(); } 0196 auto end() -> decltype(m_parameters.begin()->second->end()) { return m_parameters.begin()->second->end(); } 0197 };