42 [image, node, channelId, time, copy] ()
mutable ->
KUndo2Command* {
48 quint8 originalOpacity = node->
opacity();
51 bool channelCreated =
false;
56 if (!channel)
return nullptr;
58 channelCreated =
true;
61 bool shouldPreserveCanvas = channelCreated && time == 0;
69 bool clearExistingFrame = channel->
keyframeAt(time) && !channelCreated;
77 const QRect dirtyRect = device->
extent();
92 if (isScalar && !referenceKey) {
100 auto it = std::min_element(allTimes.begin(), allTimes.end());
101 if (it != allTimes.end()) {
106 if (isScalar && referenceKey) {
115 if (referenceKey && channel->
keyframeAt(time)) {
116 channel->
keyframeAt(time)->setColorLabel(referenceKey->colorLabel());
128 return success ? cmd.take() :
nullptr;
153 QScopedPointer<KUndo2Command> cmd(new KUndo2Command());
155 Q_FOREACH (const FrameItem &item, frames) {
156 const int time = item.time;
157 KisNodeSP node = item.node;
158 KisKeyframeChannel *channel = 0;
160 channel = node->getKeyframeChannel(item.channel);
162 if (!channel) continue;
164 KisKeyframeSP keyframe = channel->keyframeAt(time);
165 if (!keyframe) continue;
167 channel->removeKeyframe(time, cmd.data());
172 return result ? cmd.take() : 0;
182 frames <<
FrameItem(node, channel, time);
189 Q_FOREACH(
const QString& channelID, channelIDs) {
195 frames <<
FrameItem(node, channelID, time);
204 channels << channelID;
216 bool operator()(
const QModelIndex &lhs,
const QModelIndex &rhs) {
218 m_columnCoeff * lhs.column() + m_rowCoeff * lhs.row() <
219 m_columnCoeff * rhs.column() + m_rowCoeff * rhs.row();
229 std::sort(points->begin(), points->end(),
LessOperator(offset));
234 return node->inherits(
"KisPaintLayer") || node->inherits(
"KisFilterMask") || node->inherits(
"KisTransparencyMask") || node->inherits(
"KisSelectionBasedLayer");
239 const int srcTime = src.time;
243 const int dstTime = dst.
time;
247 if (srcNode == dstNode) {
248 if (!srcChannel)
return;
252 if (!srcChannel || !dstChannel)
return;
260 const int srcTime = src.time;
264 const int dstTime = dst.
time;
268 if (srcNode == dstNode) {
269 if (!srcChannel)
return;
273 srcChannel->
copyKeyframe(srcTime, dstTime, parentCommand);
275 srcChannel->
moveKeyframe(srcTime, dstTime, parentCommand);
278 if (srcChannel->
keyframeAt(dstTime) && moveEmptyFrames && !copy) {
284 if (!srcChannel || !dstChannel)
return;
288 if (!srcKeyframe)
return;
305 for (
int i = 0; i < srcFrames.size(); i++) {
306 srcDstPairs << std::make_pair(srcFrames[i], dstFrames[i]);
313 bool moveEmptyFrames,
321 srcDstPairs.size()) :
335 QHash<FrameItem, MoveChain> moveMap;
337 moveMap.insert(pair.first, {pair.second});
340 auto it = moveMap.begin();
341 while (it != moveMap.end()) {
342 MoveChain &chain = it.value();
343 const FrameItem &previousFrame = chain.last();
345 auto tailIt = moveMap.find(previousFrame);
347 if (tailIt == it || tailIt == moveMap.end()) {
352 chain.append(tailIt.value());
353 tailIt = moveMap.erase(tailIt);
357 for (it = moveMap.begin(); it != moveMap.end(); ++it) {
358 MoveChain &chain = it.value();
359 chain.prepend(it.key());
362 bool isCycle =
false;
363 if (chain.last() == chain.first()) {
368 auto frameIt = chain.rbegin();
372 while (frameIt != chain.rend()) {
386 return result ? cmd.take() :
nullptr;
397 "Clone %1 Keyframes",
402 Q_UNUSED(parentCommand);
403 QScopedPointer<KUndo2Command> cmd(new KUndo2Command());
405 foreach (const FrameMovePair &move, srcDstPairs) {
406 KisRasterKeyframeChannel *srcRasterChan = dynamic_cast<KisRasterKeyframeChannel*>(move.first.node->getKeyframeChannel(move.first.channel));
407 KisRasterKeyframeChannel *dstRasterChan = dynamic_cast<KisRasterKeyframeChannel*>(move.second.node->getKeyframeChannel(move.second.channel));
409 if (!srcRasterChan || !dstRasterChan) {
413 if (srcRasterChan == dstRasterChan) {
414 srcRasterChan->cloneKeyframe(move.first.time, move.second.time, cmd.data());
416 KisKeyframeChannel::copyKeyframe(srcRasterChan, move.first.time, dstRasterChan, move.second.time, cmd.data());
431 foreach (
const FrameItem &frameItem, frames) {
450 dbg.nospace() <<
"FrameItem(" << item.
node->
name() <<
", " << item.
channel <<
", " << item.
time <<
")";
float value(const T *src, size_t ch)
QDebug KRITACOMMAND_EXPORT operator<<(QDebug dbg, const KisCumulativeUndoData &data)
KisImageAnimationInterface * animationInterface() const
KisKeyframeChannel stores and manages KisKeyframes. Maps units of time to virtual keyframe values....
QSet< int > allKeyframeTimes() const
Get a set of all integer times that map to a keyframe.
virtual void removeKeyframe(int time, KUndo2Command *parentUndoCmd=nullptr)
Remove a keyframe from the channel at the specified time.
static void swapKeyframes(KisKeyframeChannel *channelA, int timeA, KisKeyframeChannel *channelB, int timeB, KUndo2Command *parentUndoCmd=nullptr)
Swap two keyframes across channel(s) at the specified times.
KisKeyframeSP keyframeAt(int time) const
Get a keyframe at specified time. Used primarily when the value of a given keyframe is needed.
static void copyKeyframe(const KisKeyframeChannel *sourceChannel, int sourceTime, KisKeyframeChannel *targetChannel, int targetTime, KUndo2Command *parentUndoCmd=nullptr)
Copy a keyframe across channel(s) at the specified times.
void addKeyframe(int time, KUndo2Command *parentUndoCmd=nullptr)
Add a new keyframe to the channel at the specified time.
KisKeyframeSP activeKeyframeAt(int time) const
int activeKeyframeTime(int time) const
Get the time of the active keyframe. Useful for snapping any time to that of the most recent keyframe...
static void moveKeyframe(KisKeyframeChannel *sourceChannel, int sourceTime, KisKeyframeChannel *targetChannel, int targetTime, KUndo2Command *parentUndoCmd=nullptr)
Move a keyframe across channel(s) at the specified times.
static void runSingleCommandStroke(KisImageSP image, KUndo2Command *cmd, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
runSingleCommandStroke creates a stroke and runs cmd in it. The text() field of cmd is used as a titl...
The KisRasterKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisRas...
void makeUnique(int time, KUndo2Command *parentUndoCmd=nullptr)
The KisScalarKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisSca...
qreal valueAt(int time) const
Quickly get the interpolated value at the given time.
void addScalarKeyframe(int time, qreal value, KUndo2Command *parentUndoCmd=nullptr)
KUndo2Command * endAndTake()
#define KIS_SAFE_ASSERT_RECOVER(cond)
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
KUndo2MagicString kundo2_i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1)
KUndo2MagicString kundo2_i18n(const char *text)
KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1)
void makeClonesUnique(KisImageSP image, const FrameItemList &frames)
void resetChannels(KisImageSP image, KisNodeSP node, const QList< QString > &channelIDs)
void removeKeyframes(KisImageSP image, const FrameItemList &frames)
void createKeyframeLazy(KisImageSP image, KisNodeSP node, const QString &channelId, int time, bool copy)
const QString newLayerActionName
void removeKeyframe(KisImageSP image, KisNodeSP node, const QString &channel, int time)
const QString addTransformKeyframeActionName
void resetChannel(KisImageSP image, KisNodeSP node, const QString &channelID)
const QString lazyFrameCreationActionName
void sortPointsForSafeMove(QModelIndexList *points, const QPoint &offset)
KUndo2Command * createKeyframeCommand(KisImageSP image, KisNodeSP node, const QString &channelId, int time, bool copy, KUndo2Command *parentCommand)
const QString removeLayerActionName
const QString removeTransformKeyframeActionName
bool supportsContentFrames(KisNodeSP node)
void swapOneFrameItem(const FrameItem &src, const FrameItem &dst, KUndo2Command *parentCommand)
const QString dropFramesActionName
KUndo2Command * createMoveKeyframesCommand(const FrameItemList &srcFrames, const FrameItemList &dstFrames, bool copy, bool moveEmpty, KUndo2Command *parentCommand)
std::pair< FrameItem, FrameItem > FrameMovePair
void moveOneFrameItem(const FrameItem &src, const FrameItem &dst, bool copy, bool moveEmptyFrames, KUndo2Command *parentCommand)
const QString pinExistingLayerActionName
KUndo2Command * createCloneKeyframesCommand(const FrameMovePairList &srcDstPairs, KUndo2Command *parentCommand)
bool operator()(const QModelIndex &lhs, const QModelIndex &rhs)
LessOperator(const QPoint &offset)
void setOpacity(quint8 val)
KisKeyframeChannel * getKeyframeChannel(const QString &id, bool create)
virtual KisPaintDeviceSP paintDevice() const =0
The LambdaCommand struct is a shorthand for creation of AggregateCommand commands using C++ lambda fe...