File indexing completed on 2024-05-19 04:26:40

0001 /*
0002  *  SPDX-FileCopyrightText: 2022 Emmet O'Neill <emmetoneill.pdx@gmail.com>
0003  *  SPDX-FileCopyrightText: 2022 Eoin O'Neill <eoinoneill1991@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "KisAnimAutoKey.h"
0009 
0010 #include <QReadWriteLock>
0011 
0012 #include <QApplication>
0013 #include <QThread>
0014 
0015 #include "kis_image_config.h"
0016 #include "KisImageConfigNotifier.h"
0017 
0018 #include "kis_transaction.h"
0019 #include "kis_raster_keyframe_channel.h"
0020 
0021 
0022 namespace KisAutoKey
0023 {
0024 
0025 class AutoKeyFrameStateHolder : public QObject
0026 {
0027     Q_OBJECT
0028 public:
0029 
0030     AutoKeyFrameStateHolder() {
0031         KIS_SAFE_ASSERT_RECOVER_NOOP(qApp->thread() == QThread::currentThread());
0032 
0033         connect(KisImageConfigNotifier::instance(), SIGNAL(autoKeyFrameConfigurationChanged()),
0034                 this, SLOT(slotAutoKeyFrameSettingChanged()));
0035         slotAutoKeyFrameSettingChanged();
0036     }
0037 
0038     Mode mode() const {
0039         QReadLocker l(&m_lock);
0040         return m_mode;
0041     }
0042 
0043     void testingSetActiveMode(Mode mode) {
0044         QWriteLocker l(&m_lock);
0045         m_mode = mode;
0046     }
0047 
0048 private Q_SLOTS:
0049     void slotAutoKeyFrameSettingChanged() {
0050         QWriteLocker l(&m_lock);
0051 
0052         KisImageConfig cfg(true);
0053 
0054         if (cfg.autoKeyEnabled()) {
0055             m_mode = cfg.autoKeyModeDuplicate() ? KisAutoKey::DUPLICATE
0056                                                 : KisAutoKey::BLANK;
0057         } else {
0058             m_mode = KisAutoKey::NONE;
0059         }
0060     }
0061 
0062 private:
0063     mutable QReadWriteLock m_lock;
0064     KisAutoKey::Mode m_mode {NONE};
0065 };
0066 
0067 QScopedPointer<AutoKeyFrameStateHolder> s_holder;
0068 void initHolder () {
0069     if (!s_holder) {
0070         s_holder.reset(new AutoKeyFrameStateHolder());
0071     }
0072 }
0073 Q_COREAPP_STARTUP_FUNCTION(initHolder)
0074 
0075 Mode activeMode()
0076 {
0077     return s_holder->mode();
0078 }
0079 
0080 KUndo2Command* tryAutoCreateDuplicatedFrame(KisPaintDeviceSP device, AutoCreateKeyframeFlags flags) {
0081     KUndo2Command* undo = nullptr;
0082     KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(device, undo);
0083 
0084     const bool isLodNMode = device->defaultBounds()->currentLevelOfDetail() > 0;
0085 
0086     KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(!isLodNMode || flags & SupportsLod, undo);
0087 
0088     const KisAutoKey::Mode autoKeyMode = KisAutoKey::activeMode();
0089     if (autoKeyMode == KisAutoKey::NONE) return undo;
0090 
0091     KisRasterKeyframeChannel *channel = device->keyframeChannel();
0092     if (!channel) return undo;
0093 
0094     const int activeKeyframe = channel->activeKeyframeTime();
0095     const int targetKeyframe = device->defaultBounds()->currentTime();
0096 
0097     if (activeKeyframe == targetKeyframe) return undo;
0098 
0099     if (isLodNMode) {
0100         if (flags & AllowBlankMode && autoKeyMode == KisAutoKey::BLANK) {
0101             const QRect originalDirtyRect = device->exactBounds();
0102             KisTransaction transaction(device);
0103             device->clear();
0104             device->setDirty(originalDirtyRect);
0105             undo = transaction.endAndTake();
0106         }
0107         // for KisAutoKey::DUPLICATE mode we do nothing and just reuse
0108         // the LoDN device
0109     } else {
0110         undo = new KUndo2Command;
0111 
0112         if (flags & AllowBlankMode && autoKeyMode == KisAutoKey::BLANK) {
0113             channel->addKeyframe(targetKeyframe, undo);
0114 
0115             /// Use the same color label as previous keyframe, the duplicate
0116             /// action duplicates the label automatically, but addKeyframe not
0117 
0118             KisKeyframeSP newKeyframe = channel->keyframeAt(targetKeyframe);
0119             KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(newKeyframe, undo);
0120 
0121             KisKeyframeSP oldKeyframe = channel->keyframeAt(activeKeyframe);
0122             KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(oldKeyframe, undo);
0123 
0124             newKeyframe->setColorLabel(oldKeyframe->colorLabel());
0125         } else {
0126             channel->copyKeyframe(activeKeyframe, targetKeyframe, undo);
0127         }
0128     }
0129 
0130     return undo;
0131 }
0132 
0133 void testingSetActiveMode(Mode mode)
0134 {
0135     s_holder->testingSetActiveMode(mode);
0136 }
0137 
0138 
0139 } // namespace KisAutoKey
0140 
0141 #include "KisAnimAutoKey.moc"