[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-kimageshop
Subject: [graphics/krita/krita/4.3] /: Fix inconvenient default shortcuts in the Mesh Transform tool
From: Dmitry Kazakov <null () kde ! org>
Date: 2020-11-30 13:02:34
Message-ID: 20201130130234.EDB3E1242E63 () leptone ! kde ! org
[Download RAW message or body]
Git commit 40f8c1689c3809bd098fbf4a2b3cd35d65db97af by Dmitry Kazakov.
Committed on 30/11/2020 at 12:53.
Pushed by dkazakov into branch 'krita/4.3'.
Fix inconvenient default shortcuts in the Mesh Transform tool
The patch bascially makes symmetric transforms be the default choice
available without any modifiers.
Now the shortcuts are the following:
1) Mesh node:
- click+drag --- move node
2) Border node:
- click+drag --- move node
- shift+click+drag --- move whole row/column
- ctrl+alt+click+drag --- split/slide row/column
- ctrl+alt+click+drag-away --- remove split
3) Control point:
- click+drag --- change control point symmetrically
- shift+click+drag --- change control point non-symmetrically;
this action will create angular texture
artifacts
4) Node or Control:
- ctrl+click --- select multiple nodes
5) Patch area:
- click+drag --- free patch deform
- shift+click+drag --- move whole mesh
6) Empty area outside mesh:
- click+drag --- rotate mesh or selection
- ctrl+click+drag --- scale mesh or selection
- shift+click+drag --- move mesh or selection
CC:kimageshop@kde.org
M +25 -11 libs/global/KisBezierMesh.h
M +60 -29 plugins/tools/tool_transform2/kis_mesh_transform_strategy.cpp
https://invent.kde.org/graphics/krita/commit/40f8c1689c3809bd098fbf4a2b3cd35d65db97af
diff --git a/libs/global/KisBezierMesh.h b/libs/global/KisBezierMesh.h
index d23333fb1e..f31ff62a55 100644
--- a/libs/global/KisBezierMesh.h
+++ b/libs/global/KisBezierMesh.h
@@ -1305,11 +1305,17 @@ Mesh<NodeArg, \
PatchArg>::control_point_iterator_impl<is_const>::rightSegment() c return \
SegmentIteratorType(m_mesh, m_col, m_row, true); }
+enum SmartMoveMeshControlMode {
+ MoveFree,
+ MoveSymmetricLock,
+ MoveRotationLock
+};
+
template<typename NodeArg, typename PatchArg>
void smartMoveControl(Mesh<NodeArg, PatchArg> &mesh,
typename Mesh<NodeArg, PatchArg>::ControlPointIndex index,
const QPointF &move,
- bool lockNodes)
+ SmartMoveMeshControlMode mode)
{
using ControlType = typename Mesh<NodeArg, PatchArg>::ControlType;
using ControlPointIndex = typename Mesh<NodeArg, PatchArg>::ControlPointIndex;
@@ -1322,7 +1328,7 @@ void smartMoveControl(Mesh<NodeArg, PatchArg> &mesh,
} else {
const QPointF newPos = *it + move;
- if (lockNodes) {
+ if (mode == MoveRotationLock || mode == MoveSymmetricLock) {
const qreal rotation = KisAlgebra2D::angleBetweenVectors(*it - \
it.node().node,
newPos - \
it.node().node); QTransform R;
@@ -1333,19 +1339,26 @@ void smartMoveControl(Mesh<NodeArg, PatchArg> &mesh,
R *
QTransform::fromTranslate(it.node().node.x(), \
it.node().node.y());
- for (int intType = 0; intType < 4; intType++) {
- ControlType type = static_cast<ControlType>(intType);
+ if (mode == MoveRotationLock) {
+ for (int intType = 0; intType < 4; intType++) {
+ ControlType type = static_cast<ControlType>(intType);
- if (type == ControlType::Node ||
- type == index.controlType) {
+ if (type == ControlType::Node ||
+ type == index.controlType) {
- continue;
- }
+ continue;
+ }
- auto neighbourIt = mesh.find(ControlPointIndex(index.nodeIndex, \
type));
- if (neighbourIt == mesh.endControlPoints()) continue;
+ auto neighbourIt = mesh.find(ControlPointIndex(index.nodeIndex, \
type)); + if (neighbourIt == mesh.endControlPoints()) continue;
- *neighbourIt = t.map(*neighbourIt);
+ *neighbourIt = t.map(*neighbourIt);
+ }
+ } else {
+ auto neighbourIt = it.symmetricControl();
+ if (neighbourIt != mesh.endControlPoints()) {
+ *neighbourIt = t.map(*neighbourIt);
+ }
}
}
@@ -1372,6 +1385,7 @@ using KisBezierMeshDetails::saveValue;
template <typename Node, typename Patch>
using KisBezierMeshBase = KisBezierMeshDetails::Mesh<Node, Patch>;
+using KisSmartMoveMeshControlMode = KisBezierMeshDetails::SmartMoveMeshControlMode;
using KisBezierMesh = KisBezierMeshDetails::Mesh<KisBezierMeshDetails::BaseMeshNode, \
KisBezierPatch>;
diff --git a/plugins/tools/tool_transform2/kis_mesh_transform_strategy.cpp \
b/plugins/tools/tool_transform2/kis_mesh_transform_strategy.cpp index \
bfe95f5285..b3d593de06 100644
--- a/plugins/tools/tool_transform2/kis_mesh_transform_strategy.cpp
+++ b/plugins/tools/tool_transform2/kis_mesh_transform_strategy.cpp
@@ -55,6 +55,8 @@ struct KisMeshTransformStrategy::Private
enum Mode {
OVER_POINT = 0,
OVER_POINT_SYMMETRIC,
+ OVER_NODE,
+ OVER_NODE_WHOLE_LINE,
OVER_SEGMENT,
OVER_SEGMENT_SYMMETRIC,
OVER_PATCH,
@@ -134,15 +136,19 @@ void KisMeshTransformStrategy::setTransformFunction(const \
QPointF &mousePos, boo
auto index = m_d->currentArgs.meshTransform()->hitTestControlPoint(mousePos, \
grabRadius); if (m_d->currentArgs.meshTransform()->isIndexValid(index)) {
hoveredControl = index;
- mode = Private::OVER_POINT;
+ mode = !shiftModifierActive ? Private::OVER_POINT_SYMMETRIC : \
Private::OVER_POINT; }
}
if (mode == Private::NOTHING) {
auto index = m_d->currentArgs.meshTransform()->hitTestNode(mousePos, \
grabRadius);
- if (m_d->currentArgs.meshTransform()->isIndexValid(index)) {
+ auto nodeIt = m_d->currentArgs.meshTransform()->find(index);
+
+ if (nodeIt != m_d->currentArgs.meshTransform()->endControlPoints()) {
hoveredControl = index;
- mode = Private::OVER_POINT;
+ mode = shiftModifierActive && nodeIt.isBorderNode() && \
!nodeIt.isCornerNode() ? + Private::OVER_NODE_WHOLE_LINE :
+ Private::OVER_NODE;
}
}
@@ -150,7 +156,7 @@ void KisMeshTransformStrategy::setTransformFunction(const QPointF \
&mousePos, boo
auto index = m_d->currentArgs.meshTransform()->hitTestSegment(mousePos, \
grabRadius, &localSegmentPos); if \
(m_d->currentArgs.meshTransform()->isIndexValid(index)) { hoveredSegment = index;
- mode = Private::OVER_SEGMENT;
+ mode = !shiftModifierActive ? Private::OVER_SEGMENT_SYMMETRIC : \
Private::OVER_SEGMENT; }
}
@@ -158,7 +164,7 @@ void KisMeshTransformStrategy::setTransformFunction(const QPointF \
&mousePos, boo
auto index = m_d->currentArgs.meshTransform()->hitTestPatch(mousePos, \
&localPatchPos); if (m_d->currentArgs.meshTransform()->isIndexValid(index)) {
hoveredPatch = index;
- mode = Private::OVER_PATCH;
+ mode = !shiftModifierActive ? Private::OVER_PATCH : Private::MOVE_MODE;
}
}
@@ -185,13 +191,6 @@ void KisMeshTransformStrategy::setTransformFunction(const \
QPointF &mousePos, boo
mode = Private::SPLIT_SEGMENT;
- } else if (shiftModifierActive &&
- hoveredControl &&
- !hoveredControl->isNode()) {
- mode = Private::OVER_POINT_SYMMETRIC;
- } else if (shiftModifierActive &&
- hoveredSegment) {
- mode = Private::OVER_SEGMENT_SYMMETRIC;
} else {
if (hoveredControl || hoveredSegment) {
if (perspectiveModifierActive) {
@@ -202,13 +201,12 @@ void KisMeshTransformStrategy::setTransformFunction(const \
QPointF &mousePos, boo
m_d->selectedNodes.contains(hoveredControl->nodeIndex)) {
mode = Private::MOVE_MODE;
-
}
- } else {
- if (hoveredPatch) {
- mode = shiftModifierActive ? Private::OVER_PATCH : \
Private::MOVE_MODE;
- } else if (perspectiveModifierActive) {
+ } else if (!hoveredPatch) {
+ if (perspectiveModifierActive) {
mode = Private::SCALE_MODE;
+ } else if (shiftModifierActive) {
+ mode = Private::MOVE_MODE;
} else {
mode = Private::ROTATE_MODE;
}
@@ -315,10 +313,12 @@ QCursor KisMeshTransformStrategy::getCurrentCursor() const
QCursor cursor;
switch (m_d->mode) {
+ case Private::OVER_NODE:
case Private::OVER_POINT:
case Private::OVER_SEGMENT:
cursor = KisCursor::meshCursorFree();
break;
+ case Private::OVER_NODE_WHOLE_LINE:
case Private::OVER_POINT_SYMMETRIC:
case Private::OVER_SEGMENT_SYMMETRIC:
case Private::OVER_PATCH:
@@ -479,7 +479,9 @@ bool KisMeshTransformStrategy::beginPrimaryAction(const QPointF \
&pt)
m_d->pointWasDragged = false;
- if (m_d->mode == Private::OVER_POINT || m_d->mode == \
Private::OVER_POINT_SYMMETRIC) { + if (m_d->mode == Private::OVER_NODE ||
+ m_d->mode == Private::OVER_POINT ||
+ m_d->mode == Private::OVER_POINT_SYMMETRIC) {
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_d->hoveredControl, false);
if (m_d->selectedNodes.size() <= 1 ||
@@ -490,7 +492,21 @@ bool KisMeshTransformStrategy::beginPrimaryAction(const QPointF \
&pt) }
retval = true;
+ } else if (m_d->mode == Private::OVER_NODE_WHOLE_LINE) {
+ m_d->selectedNodes.clear();
+ auto it = m_d->currentArgs.meshTransform()->find(*m_d->hoveredControl);
+ KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(it != \
m_d->currentArgs.meshTransform()->endControlPoints(), false);
+ if (it.isTopBorder() || it.isBottomBorder()) {
+ for (int i = 0; i < m_d->currentArgs.meshTransform()->size().height(); \
i++) { + m_d->selectedNodes << \
KisBezierTransformMesh::NodeIndex(m_d->hoveredControl->nodeIndex.x(), i); + \
} + } else {
+ for (int i = 0; i < m_d->currentArgs.meshTransform()->size().width(); \
i++) { + m_d->selectedNodes << KisBezierTransformMesh::NodeIndex(i, \
m_d->hoveredControl->nodeIndex.y()); + }
+ }
+ retval = true;
} else if (m_d->mode == Private::OVER_SEGMENT || m_d->mode == \
Private::OVER_SEGMENT_SYMMETRIC) { \
KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(m_d->hoveredSegment, false);
@@ -543,13 +559,21 @@ void KisMeshTransformStrategy::continuePrimaryAction(const \
QPointF &pt, bool shi Q_UNUSED(shiftModifierActve);
Q_UNUSED(altModifierActive);
- if (m_d->mode == Private::OVER_POINT || m_d->mode == \
Private::OVER_POINT_SYMMETRIC) { + if (m_d->mode == Private::OVER_POINT ||
+ m_d->mode == Private::OVER_POINT_SYMMETRIC ||
+ m_d->mode == Private::OVER_NODE) {
+
KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->hoveredControl);
+ KisSmartMoveMeshControlMode mode =
+ m_d->mode == Private::OVER_POINT_SYMMETRIC ?
+ KisSmartMoveMeshControlMode::MoveSymmetricLock :
+ KisSmartMoveMeshControlMode::MoveFree;
+
smartMoveControl(*m_d->currentArgs.meshTransform(),
*m_d->hoveredControl,
pt - m_d->lastMousePos,
- m_d->mode == Private::OVER_POINT_SYMMETRIC);
+ mode);
} else if (m_d->mode == Private::OVER_SEGMENT || m_d->mode == \
Private::OVER_SEGMENT_SYMMETRIC) { \
KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->hoveredSegment); @@ -568,8 +592,14 @@ void \
KisMeshTransformStrategy::continuePrimaryAction(const QPointF &pt, bool shi \
std::tie(offsetP1, offsetP2) =
KisBezierUtils::offsetSegment(m_d->localSegmentPosition, offset);
- smartMoveControl(*m_d->currentArgs.meshTransform(), \
it.itP1().controlIndex(), offsetP1, m_d->mode == \
Private::OVER_SEGMENT_SYMMETRIC);
- smartMoveControl(*m_d->currentArgs.meshTransform(), \
it.itP2().controlIndex(), offsetP2, m_d->mode == Private::OVER_SEGMENT_SYMMETRIC); +
+ KisSmartMoveMeshControlMode mode =
+ m_d->mode == Private::OVER_SEGMENT_SYMMETRIC ?
+ KisSmartMoveMeshControlMode::MoveSymmetricLock :
+ KisSmartMoveMeshControlMode::MoveFree;
+
+ smartMoveControl(*m_d->currentArgs.meshTransform(), \
it.itP1().controlIndex(), offsetP1, mode); + \
smartMoveControl(*m_d->currentArgs.meshTransform(), it.itP2().controlIndex(), \
offsetP2, mode);
} else if (m_d->mode == Private::OVER_PATCH) {
KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->hoveredPatch);
@@ -581,10 +611,10 @@ void KisMeshTransformStrategy::continuePrimaryAction(const \
QPointF &pt, bool shi const QPointF offset = pt - m_d->mouseClickPos;
auto offsetSegment =
- [] (KisBezierTransformMesh::segment_iterator it,
- qreal t,
- qreal distance,
- const QPointF &offset) {
+ [this] (KisBezierTransformMesh::segment_iterator it,
+ qreal t,
+ qreal distance,
+ const QPointF &offset) {
QPointF offsetP1;
QPointF offsetP2;
@@ -592,8 +622,9 @@ void KisMeshTransformStrategy::continuePrimaryAction(const \
QPointF &pt, bool shi std::tie(offsetP1, offsetP2) =
KisBezierUtils::offsetSegment(t, (1.0 - distance) * offset);
- it.p1() += offsetP1;
- it.p2() += offsetP2;
+
+ smartMoveControl(*m_d->currentArgs.meshTransform(), \
it.itP1().controlIndex(), offsetP1, KisSmartMoveMeshControlMode::MoveSymmetricLock); \
+ smartMoveControl(*m_d->currentArgs.meshTransform(), \
it.itP2().controlIndex(), offsetP2, KisSmartMoveMeshControlMode::MoveSymmetricLock); \
};
offsetSegment(patchIt.segmentP(), m_d->localPatchPosition.x(), \
m_d->localPatchPosition.y(), offset); @@ -606,7 +637,7 @@ void \
KisMeshTransformStrategy::continuePrimaryAction(const QPointF &pt, bool shi const \
bool sanitySplitResult = splitHoveredSegment(pt); \
KIS_SAFE_ASSERT_RECOVER_NOOP(sanitySplitResult);
- } else if (m_d->mode == Private::MOVE_MODE) {
+ } else if (m_d->mode == Private::MOVE_MODE || m_d->mode == \
Private::OVER_NODE_WHOLE_LINE) { const QPointF offset = pt - m_d->lastMousePos;
if (m_d->selectedNodes.size() > 1) {
for (auto it = m_d->selectedNodes.begin(); it != \
m_d->selectedNodes.end(); ++it) {
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic