diff --git a/plugins/tools/tool_transform2/kis_tool_transform.h b/plugins/tools/tool_transform2/kis_tool_transform.h --- a/plugins/tools/tool_transform2/kis_tool_transform.h +++ b/plugins/tools/tool_transform2/kis_tool_transform.h @@ -49,6 +49,7 @@ #include "KisToolChangesTracker.h" #include "kis_tool_transform_config_widget.h" #include "transform_transaction_properties.h" +#include "kis_node_commands_adapter.h" class QTouchEvent; class KisTransformStrategyBase; @@ -249,6 +250,13 @@ void commitChanges(); + /** + * some layer types cannot be transformed directly, but can only be done through + * a transform mask. Automatically create a transform mask if someone tries to transform + * one of those type of layers + */ + void createAndUseTransformIfNeeded(); + bool tryInitArgsFromNode(KisNodeSP node); bool tryFetchArgsFromCommandAndUndo(ToolTransformArgs *args, ToolTransformArgs::TransformMode mode, KisNodeSP currentNode); @@ -265,6 +273,7 @@ private: ToolTransformArgs m_currentArgs; + KisNodeCommandsAdapter* m_commandsAdapter; bool m_actuallyMoveWhileSelected; // true <=> selection has been moved while clicked diff --git a/plugins/tools/tool_transform2/kis_tool_transform.cc b/plugins/tools/tool_transform2/kis_tool_transform.cc --- a/plugins/tools/tool_transform2/kis_tool_transform.cc +++ b/plugins/tools/tool_transform2/kis_tool_transform.cc @@ -67,6 +67,7 @@ #include #include #include +#include "kis_group_layer.h" #include @@ -205,8 +206,19 @@ { Q_UNUSED(converter); + // if we are switching layers while transforming, the transform decoration will be cleared + // unless we click on the canvas. This will catch that case and show the handles right away + if (!m_strokeData.strokeId()) { + cancelStroke(); + if (currentNode()) { + m_transaction = TransformTransactionProperties(QRectF(), &m_currentArgs, KisNodeSP(), {}); + } + startStroke(ToolTransformArgs::FREE_TRANSFORM, false); + } if (!m_strokeData.strokeId()) return; + + QRectF newRefRect = KisTransformUtils::imageToFlake(m_canvas->coordinatesConverter(), QRectF(0.0,0.0,1.0,1.0)); if (m_refRect != newRefRect) { m_refRect = newRefRect; @@ -846,7 +858,7 @@ KisNodeSP currentNode = resources->currentNode(); - if (!currentNode || !currentNode->isEditable()) { + if (!currentNode) { return; } @@ -860,7 +872,11 @@ * just disable starting a new stroke asynchronously */ - if(nodePaintAbility() == NodePaintAbility::UNPAINTABLE) { + + + + // Colorize mask layers cannot be transformed + if(currentNode->inherits("KisColorizeMask") || !currentNode->isEditable() ) { KisCanvas2 *kisCanvas = dynamic_cast(canvas()); kisCanvas->viewManager()-> showFloatingMessage( @@ -871,12 +887,19 @@ return; } + + // Some types of layers can be transformed only with a transform mask + // create a transform mask if needed so transforming will work + createAndUseTransformIfNeeded(); + + if (image()->tryBarrierLock()) { image()->unlock(); } else { return; } + /** * We must ensure that the currently selected subtree * has finished all its updates. @@ -999,6 +1022,38 @@ outlineChanged(); } +void KisToolTransform::createAndUseTransformIfNeeded() +{ + if ( dynamic_cast(currentNode().data()) ) { + return; + } + + // These type of layers can have transform masks applied for transform tool + if ( currentNode()->inherits("KisGroupLayer") || + currentNode()->inherits("KisCloneLayer") || + currentNode()->inherits("KisFileLayer") ) { + + + // if transform tool is set to recursive mode, + // group layers don't need a transform mask since it affects the contents inside + if (currentNode()->inherits("KisGroupLayer") && m_workRecursively) { + return; + } + + + KisCanvas2 *kisCanvas = dynamic_cast(canvas()); + m_commandsAdapter = new KisNodeCommandsAdapter(kisCanvas->viewManager()); + + KisTransformMaskSP newMask = new KisTransformMask(); + newMask->setName(i18n("Transform Mask")); + + m_commandsAdapter->addNode(newMask, currentNode(), 0); + currentNode()->setDirty(); + } + +} + + void KisToolTransform::slotPreviewDeviceGenerated(KisPaintDeviceSP device) { if (device && device->exactBounds().isEmpty()) {