Commit a4f550b6 authored by Dmitry Kazakov's avatar Dmitry Kazakov

[FEATURE] Keep Selection Masks while merging layers

From now on active selection masks are saved through a merge operation
and are added to a new merged layer as inactive ones. You can activate
them later manually.

Next we will implement merging of selection masks, then the user will be
able to merge selection masks as well.

Fixes T508
CC:kimageshop@kde.org
parent dd5e2cea
......@@ -99,6 +99,7 @@ set(kritaimage_LIB_SRCS
commands_new/kis_set_layer_style_command.cpp
commands_new/kis_selection_move_command2.cpp
commands_new/kis_update_command.cpp
commands_new/kis_activate_selection_mask_command.cpp
processing/kis_do_nothing_processing_visitor.cpp
processing/kis_simple_processing_visitor.cpp
processing/kis_crop_processing_visitor.cpp
......
/*
* Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "kis_activate_selection_mask_command.h"
#include "kis_layer.h"
#include "kis_selection_mask.h"
KisActivateSelectionMaskCommand::KisActivateSelectionMaskCommand(KisSelectionMaskSP selectionMask, bool value)
: m_selectionMask(selectionMask),
m_value(value)
{
if (m_previousActiveMask != m_selectionMask) {
KisLayerSP parent = dynamic_cast<KisLayer*>(selectionMask->parent().data());
if (parent) {
m_previousActiveMask = parent->selectionMask();
}
}
m_previousValue = selectionMask->active();
}
void KisActivateSelectionMaskCommand::redo()
{
m_selectionMask->setActive(m_value);
}
void KisActivateSelectionMaskCommand::undo()
{
m_selectionMask->setActive(m_previousValue);
if (m_value && m_previousActiveMask) {
m_previousActiveMask->setActive(true);
}
}
/*
* Copyright (c) 2015 Dmitry Kazakov <dimula73@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __KIS_ACTIVATE_SELECTION_MASK_COMMAND_H
#define __KIS_ACTIVATE_SELECTION_MASK_COMMAND_H
#include <klocale.h>
#include "kundo2command.h"
#include "kritaimage_export.h"
#include "kis_types.h"
class KRITAIMAGE_EXPORT KisActivateSelectionMaskCommand : public KUndo2Command
{
public:
KisActivateSelectionMaskCommand(KisSelectionMaskSP selectionMask, bool value);
void undo();
void redo();
private:
KisSelectionMaskSP m_selectionMask;
KisSelectionMaskSP m_previousActiveMask;
bool m_value;
bool m_previousValue;
};
#endif /* __KIS_ACTIVATE_SELECTION_MASK_COMMAND_H */
......@@ -79,6 +79,7 @@
#include "processing/kis_transform_processing_visitor.h"
#include "commands_new/kis_image_resize_command.h"
#include "commands_new/kis_image_set_resolution_command.h"
#include "commands_new/kis_activate_selection_mask_command.h"
#include "kis_composite_progress_proxy.h"
#include "kis_layer_composition.h"
#include "kis_wrapped_rect.h"
......@@ -1043,6 +1044,28 @@ void sortMergableNodes(KisNodeSP root, QList<KisNodeSP> &inputNodes, QList<KisNo
KIS_ASSERT_RECOVER_NOOP(root->parent() || inputNodes.isEmpty());
}
void fetchSelectionMasks(QList<KisNodeSP> mergedNodes, QVector<KisSelectionMaskSP> &selectionMasks)
{
foreach (KisNodeSP node, mergedNodes) {
KisLayerSP layer = dynamic_cast<KisLayer*>(node.data());
KisSelectionMaskSP mask;
if (layer && (mask = layer->selectionMask())) {
selectionMasks.append(mask);
}
}
}
void reparentSelectionMasks(KisLayerSP newLayer, const QVector<KisSelectionMaskSP> &selectionMasks)
{
KisImageSP image = newLayer->image();
foreach (KisSelectionMaskSP mask, selectionMasks) {
image->undoAdapter()->addCommand(new KisImageLayerMoveCommand(image, mask, newLayer, newLayer->lastChild()));
image->undoAdapter()->addCommand(new KisActivateSelectionMaskCommand(mask, false));
}
}
KisNodeSP KisImage::mergeMultipleLayers(QList<KisNodeSP> mergedNodes, KisNodeSP putAfter)
{
filterMergableNodes(mergedNodes);
......@@ -1055,6 +1078,10 @@ KisNodeSP KisImage::mergeMultipleLayers(QList<KisNodeSP> mergedNodes, KisNodeSP
if (mergedNodes.size() <= 1) return KisNodeSP();
// fetch selection masks to move them into the destination layer
QVector<KisSelectionMaskSP> selectionMasks;
fetchSelectionMasks(mergedNodes, selectionMasks);
foreach (KisNodeSP layer, mergedNodes) {
refreshHiddenArea(layer, bounds());
}
......@@ -1079,7 +1106,7 @@ KisNodeSP KisImage::mergeMultipleLayers(QList<KisNodeSP> mergedNodes, KisNodeSP
.arg(mergedLayerName).arg(mergedLayerSuffix);
}
KisNodeSP newLayer = new KisPaintLayer(this, mergedLayerName, OPACITY_OPAQUE_U8, mergedDevice);
KisLayerSP newLayer = new KisPaintLayer(this, mergedLayerName, OPACITY_OPAQUE_U8, mergedDevice);
undoAdapter()->beginMacro(kundo2_i18n("Merge Selected Nodes"));
......@@ -1101,6 +1128,9 @@ KisNodeSP KisImage::mergeMultipleLayers(QList<KisNodeSP> mergedNodes, KisNodeSP
undoAdapter()->addCommand(new KisImageLayerAddCommand(this, newLayer, parent, parent->lastChild()));
}
// reparent selection masks into the newly created node
reparentSelectionMasks(newLayer, selectionMasks);
safeRemoveMultipleNodes(mergedNodes);
undoAdapter()->endMacro();
......@@ -1119,6 +1149,14 @@ KisLayerSP KisImage::mergeDown(KisLayerSP layer, const KisMetaData::MergeStrateg
refreshHiddenArea(layer, bounds());
refreshHiddenArea(prevLayer, bounds());
QVector<KisSelectionMaskSP> selectionMasks;
{
QList<KisNodeSP> mergedNodes;
mergedNodes << layer;
mergedNodes << prevLayer;
fetchSelectionMasks(mergedNodes, selectionMasks);
}
QRect layerProjectionExtent = this->projection()->extent();
QRect prevLayerProjectionExtent = prevLayer->projection()->extent();
......@@ -1145,6 +1183,10 @@ KisLayerSP KisImage::mergeDown(KisLayerSP layer, const KisMetaData::MergeStrateg
undoAdapter()->beginMacro(kundo2_i18n("Merge with Layer Below"));
undoAdapter()->addCommand(new KisImageLayerAddCommand(this, mergedLayer, parent, layer));
// reparent selection masks into the newly created node
reparentSelectionMasks(mergedLayer, selectionMasks);
safeRemoveTwoNodes(layer, prevLayer);
undoAdapter()->endMacro();
......
Markdown is supported
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