[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-kimageshop
Subject: [graphics/krita] /: Fix inconvenient default shortcuts in the Mesh Transform tool
From: Dmitry Kazakov <null () kde ! org>
Date: 2020-11-30 13:03:16
Message-ID: 20201130130316.2F45A1242E63 () leptone ! kde ! org
[Download RAW message or body]
Git commit 4b4b1f4ae6cabc86d3936348d7a26e0da0611505 by Dmitry Kazakov.
Committed on 30/11/2020 at 13:03.
Pushed by dkazakov into branch 'master'.
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/4b4b1f4ae6cabc86d3936348d7a26e0da0611505
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 \
2c8d738d57..5cd3b6dbf7 100644
--- a/plugins/tools/tool_transform2/kis_mesh_transform_strategy.cpp
+++ b/plugins/tools/tool_transform2/kis_mesh_transform_strategy.cpp
@@ -43,6 +43,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,
@@ -122,15 +124,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;
}
}
@@ -138,7 +144,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; }
}
@@ -146,7 +152,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;
}
}
@@ -173,13 +179,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) {
@@ -190,13 +189,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;
}
@@ -303,10 +301,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:
@@ -467,7 +467,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 ||
@@ -478,7 +480,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);
@@ -531,13 +547,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); @@ -556,8 +580,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);
@@ -569,10 +599,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;
@@ -580,8 +610,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); @@ -594,7 +625,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