File indexing completed on 2024-12-22 04:10:02
0001 /* 0002 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org> 0003 * SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include <klocalizedstring.h> 0009 #include "kis_node.h" 0010 #include "commands/kis_node_opacity_command.h" 0011 #include "kis_command_ids.h" 0012 #include "kis_command_utils.h" 0013 #include "kis_keyframe_channel.h" 0014 #include "kis_image.h" 0015 #include "kis_image_animation_interface.h" 0016 #include "kis_scalar_keyframe_channel.h" 0017 0018 using namespace KisCommandUtils; 0019 0020 KisNodeOpacityCommand::KisNodeOpacityCommand(KisNodeSP node, quint8 newOpacity) : 0021 KisNodeCommand(kundo2_i18n("Opacity Change"), node) 0022 { 0023 m_newOpacity = newOpacity; 0024 0025 KIS_SAFE_ASSERT_RECOVER_RETURN(node->image()); 0026 0027 const int time = node->image()->animationInterface()->currentTime(); 0028 0029 KisKeyframeChannel* channel = m_node->getKeyframeChannel(KisKeyframeChannel::Opacity.id()); 0030 if (channel && !channel->keyframeAt(time)) { 0031 KisScalarKeyframeChannel* scalarChannel = dynamic_cast<KisScalarKeyframeChannel*>(channel); 0032 KIS_ASSERT(scalarChannel); 0033 m_autokey.reset(new SkipFirstRedoWrapper()); 0034 scalarChannel->addScalarKeyframe(time, newOpacity, m_autokey.data()); 0035 } 0036 } 0037 0038 void KisNodeOpacityCommand::redo() 0039 { 0040 if (!m_oldOpacity) { 0041 m_oldOpacity = m_node->opacity(); 0042 } 0043 0044 if (m_autokey) { 0045 m_autokey->redo(); 0046 } 0047 0048 m_node->setOpacity(m_newOpacity); 0049 m_node->setDirty(); 0050 } 0051 0052 void KisNodeOpacityCommand::undo() 0053 { 0054 KIS_SAFE_ASSERT_RECOVER_RETURN(m_oldOpacity); 0055 0056 m_node->setOpacity(*m_oldOpacity); 0057 m_node->setDirty(); 0058 0059 if (m_autokey) { 0060 m_autokey->undo(); 0061 } 0062 } 0063 0064 int KisNodeOpacityCommand::id() const 0065 { 0066 return KisCommandUtils::ChangeNodeOpacityId; 0067 } 0068 0069 bool KisNodeOpacityCommand::mergeWith(const KUndo2Command *command) 0070 { 0071 const KisNodeOpacityCommand *other = 0072 dynamic_cast<const KisNodeOpacityCommand*>(command); 0073 0074 if (other && other->m_node == m_node) { 0075 // verify both commands have been executed and they are consecutive 0076 KIS_SAFE_ASSERT_RECOVER_NOOP(m_oldOpacity); 0077 KIS_SAFE_ASSERT_RECOVER_NOOP(other->m_oldOpacity); 0078 KIS_SAFE_ASSERT_RECOVER_NOOP(other->m_oldOpacity && m_newOpacity == *other->m_oldOpacity); 0079 0080 m_newOpacity = other->m_newOpacity; 0081 return true; 0082 } 0083 0084 return false; 0085 } 0086 0087 bool KisNodeOpacityCommand::canMergeWith(const KUndo2Command *command) const 0088 { 0089 const KisNodeOpacityCommand *other = 0090 dynamic_cast<const KisNodeOpacityCommand*>(command); 0091 if (!other) return false; 0092 0093 0094 bool otherCreatedKeyframe = other->m_autokey; 0095 bool weCreatedKeyframe = m_autokey; 0096 bool canMergeKeyframe = ((otherCreatedKeyframe ^ weCreatedKeyframe) == true) || (!otherCreatedKeyframe && !weCreatedKeyframe); 0097 0098 return other->m_node == m_node && canMergeKeyframe; 0099 } 0100 0101 bool KisNodeOpacityCommand::canAnnihilateWith(const KUndo2Command *command) const 0102 { 0103 const KisNodeOpacityCommand *other = 0104 dynamic_cast<const KisNodeOpacityCommand*>(command); 0105 0106 if (!other || other->m_node != m_node) { 0107 return false; 0108 } 0109 0110 if (m_autokey || other->m_autokey) { 0111 return false; 0112 } 0113 0114 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_oldOpacity, false); 0115 return *m_oldOpacity == other->m_newOpacity; 0116 }