File indexing completed on 2024-05-12 15:58:21
0001 /* 0002 * SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef __KIS_IMAGE_ANIMATION_INTERFACE_H 0008 #define __KIS_IMAGE_ANIMATION_INTERFACE_H 0009 0010 #include <QObject> 0011 #include <QScopedPointer> 0012 0013 #include "kis_types.h" 0014 #include "kritaimage_export.h" 0015 0016 class KisUpdatesFacade; 0017 class KisTimeSpan; 0018 class KisKeyframeChannel; 0019 class KoColor; 0020 class KisRegion; 0021 0022 namespace KisLayerUtils { 0023 struct SwitchFrameCommand; 0024 } 0025 0026 class KRITAIMAGE_EXPORT KisImageAnimationInterface : public QObject 0027 { 0028 Q_OBJECT 0029 0030 public: 0031 KisImageAnimationInterface(KisImage *image); 0032 KisImageAnimationInterface(const KisImageAnimationInterface &rhs, KisImage *newImage); 0033 ~KisImageAnimationInterface() override; 0034 0035 /** 0036 * Returns true of the image has at least one animated layer 0037 */ 0038 bool hasAnimation() const; 0039 0040 /** 0041 * Returns currently active frame of the underlying image. Some strokes 0042 * can override this value and it will report a different value. 0043 */ 0044 int currentTime() const; 0045 0046 /** 0047 * Same as currentTime, except it isn't changed when background strokes 0048 * are running. 0049 */ 0050 int currentUITime() const; 0051 0052 /** 0053 * While any non-current frame is being regenerated by the 0054 * strategy, the image is kept in a special state, named 0055 * 'externalFrameActive'. Is this state the following applies: 0056 * 0057 * 1) All the animated paint devices switch its state into 0058 * frameId() defined by global time. 0059 * 0060 * 2) All animation-not-capable devices switch to a temporary 0061 * content device, which *is in undefined state*. The stroke 0062 * should regenerate the image projection manually. 0063 */ 0064 bool externalFrameActive() const; 0065 0066 void requestTimeSwitchWithUndo(int time); 0067 0068 void requestTimeSwitchNonGUI(int time, bool useUndo = false); 0069 0070 /** 0071 * Start a background thread that will recalculate some extra frame. 0072 * The result will be reported using two types of signals: 0073 * 0074 * 1) KisImage::sigImageUpdated() will be emitted for every chunk 0075 * of updated area. 0076 * 0077 * 2) sigFrameReady() will be emitted in the end of the operation. 0078 * IMPORTANT: to get the result you must connect to this signal 0079 * with Qt::DirectConnection and fetch the result from 0080 * frameProjection(). After the signal handler is exited, the 0081 * data will no longer be available. 0082 */ 0083 void requestFrameRegeneration(int frameId, const KisRegion &dirtyRegion, bool isCancellable); 0084 0085 void notifyNodeChanged(const KisNode *node, const QRect &rect, bool recursive); 0086 void notifyNodeChanged(const KisNode *node, const QVector<QRect> &rects, bool recursive); 0087 void invalidateFrames(const KisTimeSpan &range, const QRect &rect); 0088 void invalidateFrame(const int time, KisNodeSP target); 0089 0090 /** 0091 * Changes the default color of the "external frame" projection of 0092 * the image's root layer. Please note that this command should be 0093 * executed from a context of an exclusive job! 0094 */ 0095 void setDefaultProjectionColor(const KoColor &color); 0096 0097 /** 0098 * The current time range selected by user. 0099 * @return current time range 0100 */ 0101 const KisTimeSpan& fullClipRange() const; 0102 void setFullClipRange(const KisTimeSpan range); 0103 0104 0105 const KisTimeSpan &playbackRange() const; 0106 void setPlaybackRange(const KisTimeSpan range); 0107 int framerate() const; 0108 0109 /** 0110 * @return **absolute** file name of the audio channel file 0111 */ 0112 QString audioChannelFileName() const; 0113 0114 /** 0115 * Sets **absolute** file name of the audio channel file. Don't try to pass 0116 * a relative path, it'll assert! 0117 */ 0118 void setAudioChannelFileName(const QString &fileName); 0119 0120 QString exportSequenceFilePath(); 0121 void setExportSequenceFilePath(const QString &filePath); 0122 0123 QString exportSequenceBaseName(); 0124 void setExportSequenceBaseName(const QString &baseName); 0125 0126 int exportInitialFrameNumber(); 0127 void setExportInitialFrameNumber(const int frameNum); 0128 0129 /** 0130 * @return is the audio channel is currently muted 0131 */ 0132 bool isAudioMuted() const; 0133 0134 /** 0135 * Mutes the audio channel 0136 */ 0137 void setAudioMuted(bool value); 0138 0139 /** 0140 * Returns the preferred audio value in rangle [0, 1] 0141 */ 0142 qreal audioVolume() const; 0143 0144 /** 0145 * Set the preferred volume for the audio channel in range [0, 1] 0146 */ 0147 void setAudioVolume(qreal value); 0148 0149 QSet<int> activeLayerSelectedTimes(); 0150 void setActiveLayerSelectedTimes(const QSet<int> ×); 0151 0152 KisImageWSP image() const; 0153 0154 int totalLength(); 0155 0156 public Q_SLOTS: 0157 /** 0158 * Switches current frame (synchronously) and starts an 0159 * asynchronous regeneration of the entire image. 0160 */ 0161 void switchCurrentTimeAsync(int frameId, bool useUndo = false); 0162 0163 void setFullClipRangeStartTime(int column); 0164 void setFullClipRangeEndTime(int column); 0165 0166 void setFramerate(int fps); 0167 0168 Q_SIGNALS: 0169 void sigFrameReady(int time); 0170 void sigFrameCancelled(); 0171 void sigUiTimeChanged(int newTime); 0172 void sigFramesChanged(const KisTimeSpan &range, const QRect &rect); 0173 0174 void sigInternalRequestTimeSwitch(int frameId, bool useUndo); 0175 0176 void sigFramerateChanged(); 0177 void sigFullClipRangeChanged(); 0178 void sigPlaybackRangeChanged(); 0179 0180 /** 0181 * Emitted when the audio channel of the document is changed 0182 */ 0183 void sigAudioChannelChanged(); 0184 0185 /** 0186 * Emitted when audion volume changes. Please note that it doesn't change 0187 * when you mute the channel! When muting, sigAudioChannelChanged() is used instead! 0188 */ 0189 void sigAudioVolumeChanged(); 0190 0191 void sigKeyframeAdded(const KisKeyframeChannel* channel, int time); 0192 void sigKeyframeRemoved(const KisKeyframeChannel* channel, int time); 0193 0194 private: 0195 // interface for: 0196 friend class KisRegenerateFrameStrokeStrategy; 0197 friend class KisSuspendProjectionUpdatesStrokeStrategy; //TODO These friend classes are ugly. Let's refactor after Krita 5 release. 0198 friend class KisAnimationFrameCacheTest; 0199 friend struct KisLayerUtils::SwitchFrameCommand; 0200 friend class KisImageTest; 0201 void saveAndResetCurrentTime(int frameId, int *savedValue); 0202 void restoreCurrentTime(int *savedValue); 0203 void notifyFrameReady(); 0204 void notifyFrameCancelled(); 0205 bool requiresOnionSkinRendering(); 0206 0207 KisUpdatesFacade* updatesFacade() const; 0208 0209 void blockFrameInvalidation(bool value); 0210 0211 friend class KisSwitchTimeStrokeStrategy; 0212 friend class TransformStrokeStrategy; 0213 void explicitlySetCurrentTime(int frameId); 0214 struct Private; 0215 const QScopedPointer<Private> m_d; 0216 }; 0217 0218 #endif /* __KIS_IMAGE_ANIMATION_INTERFACE_H */