Commit ca2ec62c authored by Eoin O'Neill's avatar Eoin O'Neill 🍀
Browse files

Fix copy+paste working strangely with animated layers.

Achieved this by "burning" the current frameid into copied paint
devices. This is the desired behavior, as copy/pasted selections
should really be a simple WYSIWYG interaction where the visible
contents of a selection are copied.

BUG:457319
BUG:459763
(cherry picked from commit 72bad700)
parent c52f4aa3
Pipeline #245308 passed with stage
in 65 minutes and 9 seconds
......@@ -2184,6 +2184,32 @@ KisPaintDeviceFramesInterface* KisPaintDevice::framesInterface()
return m_d->framesInterface.data();
}
bool KisPaintDevice::burnKeyframe(int frameID)
{
KIS_ASSERT_RECOVER_RETURN_VALUE(m_d->framesInterface.data()->frames().contains(frameID), false);
// Preserve keyframe data from frameID...
KisPaintDeviceSP holder = new KisPaintDevice(m_d->colorSpace());
m_d->framesInterface->writeFrameToDevice(frameID, holder);
// Remove all keyframes..
QSet<int> times = m_d->contentChannel->allKeyframeTimes();
Q_FOREACH( const int& time, times ) {
m_d->contentChannel->removeKeyframe(time);
}
// TODO: Eventually rewrite this to completely remove contentChannel.
// For now, importing it as frame 0 will be close enough.
m_d->contentChannel->importFrame(0, holder, nullptr);
return true;
}
bool KisPaintDevice::burnKeyframe()
{
return burnKeyframe(m_d->framesInterface->currentFrameId());
}
/******************************************************************/
/* KisPaintDeviceFramesInterface */
/******************************************************************/
......
......@@ -774,6 +774,24 @@ public:
*/
KisPaintDeviceFramesInterface* framesInterface();
/**
* @brief burnKeyframe
*
* Take a frame from the keyframe channel,
* Copy the contents onto the "base" frame,
* and completely remove the keyframe channel.
*
* Should be useful for copy+paste operations where
* we shouldn't expect keyframe data to persist.
*
* Parameterless version simply gets the current frameID.
*
* @param frameID -- frameID (from the framesInterface, **not the time**) to burn to device.
* @return success
*/
bool burnKeyframe(int frameID);
bool burnKeyframe();
public:
/**
......
......@@ -69,7 +69,8 @@ namespace ActionHelper {
bool makeSharpClip = false,
const KisTimeSpan &range = KisTimeSpan())
{
Q_UNUSED(range)
Q_UNUSED(range); // TODO: Allow multiple frame operation across a timespan.
KisImageWSP image = view->image();
if (!image) return;
......@@ -113,6 +114,8 @@ namespace ActionHelper {
}
}
if ( needsTransparentPixel ) {
device->setDefaultPixel(KoColor(Qt::transparent, device->colorSpace()));
device->purgeDefaultPixels();
......@@ -315,64 +318,28 @@ void KisCutCopyActionFactory::run(bool willCut, bool makeSharpClip, KisViewManag
nodes.append(dupNode);
}
{
//KisImageBarrierLocker locker(image); not needed as these nodes do not belong to 'image'
Q_FOREACH (KisNodeSP node, nodes) {
KisLayerUtils::recursiveApplyNodes(node, [image, view, makeSharpClip] (KisNodeSP node) {
KisPaintDeviceSP dev = node->paintDevice();
Q_FOREACH (KisNodeSP node, nodes) {
KisLayerUtils::recursiveApplyNodes(node, [image, view, makeSharpClip] (KisNodeSP node) {
KisPaintDeviceSP dev = node->paintDevice();
dev->burnKeyframe();
KisTimeSpan range;
KisTimeSpan range;
KisKeyframeChannel *channel = node->getKeyframeChannel(KisKeyframeChannel::Raster.id());
if (channel) {
const int currentTime = image->animationInterface()->currentTime();
range = channel->affectedFrames(currentTime);
}
KisKeyframeChannel *channel = node->getKeyframeChannel(KisKeyframeChannel::Raster.id());
if (channel) {
const int currentTime = image->animationInterface()->currentTime();
range = channel->affectedFrames(currentTime);
}
if (dev && !node->inherits("KisMask")) {
ActionHelper::trimDevice(view, dev, makeSharpClip, range);
}
});
}
if (dev && !node->inherits("KisMask")) {
ActionHelper::trimDevice(view, dev, makeSharpClip, range);
}
});
}
KisImageSP tempImage = ActionHelper::makeImage(view, nodes);
KisClipboard::instance()->setLayers(nodes, tempImage);
/* {
KisImageBarrierLocker locker(image);
KisPaintDeviceSP dev = node->paintDevice();
if (!dev) {
dev = node->projection();
}
if (!dev) {
view->showFloatingMessage(
i18nc("floating message when cannot copy from a node",
"Cannot copy pixels from this type of layer "),
QIcon(), 3000, KisFloatingMessage::Medium);
return;
}
if (dev->exactBounds().isEmpty()) {
view->showFloatingMessage(
i18nc("floating message when copying empty selection",
"Selection is empty: no pixels were copied "),
QIcon(), 3000, KisFloatingMessage::Medium);
return;
}
KisTimeSpan range;
KisKeyframeChannel *channel = node->getKeyframeChannel(KisKeyframeChannel::Raster.id());
if (channel) {
const int currentTime = image->animationInterface()->currentTime();
range = channel->affectedFrames(currentTime);
}
ActionHelper::copyFromDevice(view, dev, makeSharpClip, range);
}*/
KUndo2MagicString actionName = willCut ?
kundo2_i18n("Cut") :
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment