Commit a4e97e22 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Merge remote-tracking branch 'origin/kazakov/scale-from-pivot-point-T119' into...

Merge remote-tracking branch 'origin/kazakov/scale-from-pivot-point-T119' into rempt/impex-refactoring

# Conflicts:
#	plugins/tools/tool_transform2/kis_tool_transform_config_widget.cpp
#	plugins/tools/tool_transform2/wdg_tool_transform.ui
parents 96e6d6ee bfe18d2e
......@@ -382,15 +382,20 @@ bool KisFreeTransformStrategy::beginPrimaryAction(const QPointF &pt)
return true;
}
void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bool specialModifierActive)
void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos,
bool shiftModifierActive,
bool altModifierActive)
{
// Note: "specialModifierActive" just tells us if the shift key is being pressed
// Note: "shiftModifierActive" just tells us if the shift key is being pressed
// Note: "altModifierActive" just tells us if the alt key is being pressed
const QPointF anchorPoint = m_d->clickArgs.originalCenter() + m_d->clickArgs.rotationCenterOffset();
switch (m_d->function) {
case MOVE: {
QPointF diff = mousePos - m_d->clickPos;
if (specialModifierActive) {
if (shiftModifierActive) {
KisTransformUtils::MatricesPack m(m_d->clickArgs);
QTransform t = m.S * m.projectedP;
......@@ -425,7 +430,7 @@ void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bo
qreal theta = a2 - a1;
// Snap with shift key
if (specialModifierActive) {
if (shiftModifierActive) {
const qreal snapAngle = M_PI_4 / 6.0; // fifteen degrees
qint32 thetaIndex = static_cast<qint32>((theta / snapAngle) + 0.5);
m_d->currentArgs.setAZ(normalizeAngle(thetaIndex * snapAngle));
......@@ -471,7 +476,6 @@ void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bo
qreal extraSign;
if (m_d->function == TOPSCALE) {
staticPoint = m_d->transaction.originalMiddleBottom();
movingPoint = m_d->transaction.originalMiddleTop();
extraSign = -1.0;
......@@ -481,6 +485,13 @@ void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bo
extraSign = 1.0;
}
// override scale static point if it is locked
if ((m_d->currentArgs.transformAroundRotationCenter() ^ altModifierActive) &&
!qFuzzyCompare(anchorPoint.y(), movingPoint.y())) {
staticPoint = anchorPoint;
}
QPointF mouseImagePos = m_d->transform.inverted().map(mousePos);
qreal sign = mouseImagePos.y() <= staticPoint.y() ? -extraSign : extraSign;
......@@ -497,7 +508,7 @@ void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bo
movingPoint,
dist);
if (specialModifierActive || m_d->currentArgs.keepAspectRatio()) {
if (shiftModifierActive || m_d->currentArgs.keepAspectRatio()) {
qreal aspectRatio = m_d->clickArgs.scaleX() / m_d->clickArgs.scaleY();
m_d->currentArgs.setScaleX(aspectRatio * result.scale);
}
......@@ -524,6 +535,13 @@ void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bo
extraSign = 1.0;
}
// override scale static point if it is locked
if ((m_d->currentArgs.transformAroundRotationCenter() ^ altModifierActive) &&
!qFuzzyCompare(anchorPoint.x(), movingPoint.x())) {
staticPoint = anchorPoint;
}
QPointF mouseImagePos = m_d->transform.inverted().map(mousePos);
qreal sign = mouseImagePos.x() <= staticPoint.x() ? -extraSign : extraSign;
......@@ -540,7 +558,7 @@ void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bo
movingPoint,
dist);
if (specialModifierActive || m_d->currentArgs.keepAspectRatio()) {
if (shiftModifierActive || m_d->currentArgs.keepAspectRatio()) {
qreal aspectRatio = m_d->clickArgs.scaleY() / m_d->clickArgs.scaleX();
m_d->currentArgs.setScaleY(aspectRatio * result.scale);
}
......@@ -570,10 +588,18 @@ void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bo
movingPoint = m_d->transaction.originalBottomLeft();
}
// override scale static point if it is locked
if ((m_d->currentArgs.transformAroundRotationCenter() ^ altModifierActive) &&
!(qFuzzyCompare(anchorPoint.x(), movingPoint.x()) ||
qFuzzyCompare(anchorPoint.y(), movingPoint.y()))) {
staticPoint = anchorPoint;
}
QPointF staticPointInView = m_d->transform.map(staticPoint);
QPointF movingPointInView = mousePos;
if (specialModifierActive || m_d->currentArgs.keepAspectRatio()) {
if (shiftModifierActive || m_d->currentArgs.keepAspectRatio()) {
KisTransformUtils::MatricesPack m(m_d->clickArgs);
QTransform t = m.finalTransform();
......@@ -602,7 +628,7 @@ void KisFreeTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bo
QPointF newRotationCenterOffset = pt - m_d->currentArgs.originalCenter();
if (specialModifierActive) {
if (shiftModifierActive) {
if (qAbs(newRotationCenterOffset.x()) > qAbs(newRotationCenterOffset.y())) {
newRotationCenterOffset.ry() = 0;
} else {
......
......@@ -52,7 +52,7 @@ public:
using KisTransformStrategyBase::endPrimaryAction;
bool beginPrimaryAction(const QPointF &pt);
void continuePrimaryAction(const QPointF &pt, bool specialModifierActve);
void continuePrimaryAction(const QPointF &pt, bool shiftModifierActve, bool altModifierActive);
bool endPrimaryAction();
Q_SIGNALS:
......
......@@ -453,9 +453,10 @@ QPointF toQPointF(const QVector4D &v) {
return v.toVector2DAffine().toPointF();
}
void KisPerspectiveTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bool specialModifierActve)
void KisPerspectiveTransformStrategy::continuePrimaryAction(const QPointF &mousePos, bool shiftModifierActve, bool altModifierActive)
{
Q_UNUSED(specialModifierActve);
Q_UNUSED(shiftModifierActve);
Q_UNUSED(altModifierActive);
switch (m_d->function) {
case NONE:
......
......@@ -52,7 +52,7 @@ public:
using KisTransformStrategyBase::endPrimaryAction;
bool beginPrimaryAction(const QPointF &pt);
void continuePrimaryAction(const QPointF &pt, bool specialModifierActve);
void continuePrimaryAction(const QPointF &pt, bool shiftModifierActve, bool altModifierActive);
bool endPrimaryAction();
Q_SIGNALS:
......
......@@ -37,6 +37,7 @@ struct KisSimplifiedActionPolicyStrategy::Private
bool changeSizeModifierActive;
bool anyPickerModifierActive;
QPointF dragOffset;
QPointF lastImagePos;
};
......@@ -76,7 +77,10 @@ bool KisSimplifiedActionPolicyStrategy::beginPrimaryAction(KoPointerEvent *event
m_d->snapGuide->snap(event->point, m_d->dragOffset, event->modifiers()) :
event->point;
return beginPrimaryAction(m_d->converter->documentToImage(pos));
QPointF imagePos = m_d->converter->documentToImage(pos);
m_d->lastImagePos = imagePos;
return beginPrimaryAction(imagePos);
}
void KisSimplifiedActionPolicyStrategy::continuePrimaryAction(KoPointerEvent *event)
......@@ -94,26 +98,40 @@ void KisSimplifiedActionPolicyStrategy::continuePrimaryAction(KoPointerEvent *ev
* See bug 340496
*/
const bool shiftIsActive = event->modifiers() & Qt::ShiftModifier;
const bool altIsActive = event->modifiers() & Qt::AltModifier;
const QPointF pos =
m_d->snapGuide ?
m_d->snapGuide->snap(event->point, m_d->dragOffset, event->modifiers()) :
event->point;
return continuePrimaryAction(m_d->converter->documentToImage(pos), shiftIsActive);
QPointF imagePos = m_d->converter->documentToImage(pos);
m_d->lastImagePos = imagePos;
return continuePrimaryAction(imagePos, shiftIsActive, altIsActive);
}
void KisSimplifiedActionPolicyStrategy::hoverActionCommon(KoPointerEvent *event)
{
hoverActionCommon(m_d->converter->documentToImage(event->point));
QPointF imagePos = m_d->converter->documentToImage(event->point);
m_d->lastImagePos = imagePos;
hoverActionCommon(imagePos);
}
bool KisSimplifiedActionPolicyStrategy::endPrimaryAction(KoPointerEvent *event)
{
Q_UNUSED(event);
QPointF imagePos = m_d->converter->documentToImage(event->point);
m_d->lastImagePos = imagePos;
return endPrimaryAction();
}
void KisSimplifiedActionPolicyStrategy::activatePrimaryAction()
{
setTransformFunction(m_d->lastImagePos, m_d->anyPickerModifierActive);
}
void KisSimplifiedActionPolicyStrategy::activateAlternateAction(KisTool::AlternateAction action)
{
if (action == KisTool::ChangeSize) {
......@@ -123,6 +141,8 @@ void KisSimplifiedActionPolicyStrategy::activateAlternateAction(KisTool::Alterna
m_d->anyPickerModifierActive = true;
}
setTransformFunction(m_d->lastImagePos, m_d->anyPickerModifierActive);
}
void KisSimplifiedActionPolicyStrategy::deactivateAlternateAction(KisTool::AlternateAction action)
......@@ -142,7 +162,10 @@ bool KisSimplifiedActionPolicyStrategy::beginAlternateAction(KoPointerEvent *eve
if (!m_d->changeSizeModifierActive && !m_d->anyPickerModifierActive) return false;
return beginPrimaryAction(m_d->converter->documentToImage(event->point));
QPointF imagePos = m_d->converter->documentToImage(event->point);
m_d->lastImagePos = imagePos;
return beginPrimaryAction(imagePos);
}
void KisSimplifiedActionPolicyStrategy::continueAlternateAction(KoPointerEvent *event, KisTool::AlternateAction action)
......@@ -150,17 +173,23 @@ void KisSimplifiedActionPolicyStrategy::continueAlternateAction(KoPointerEvent *
Q_UNUSED(action);
if (!m_d->changeSizeModifierActive && !m_d->anyPickerModifierActive) return;
const bool altIsActive = event->modifiers() & Qt::AltModifier;
continuePrimaryAction(m_d->converter->documentToImage(event->point), m_d->changeSizeModifierActive);
QPointF imagePos = m_d->converter->documentToImage(event->point);
m_d->lastImagePos = imagePos;
continuePrimaryAction(imagePos, m_d->changeSizeModifierActive, altIsActive);
}
bool KisSimplifiedActionPolicyStrategy::endAlternateAction(KoPointerEvent *event, KisTool::AlternateAction action)
{
Q_UNUSED(event);
Q_UNUSED(action);
if (!m_d->changeSizeModifierActive && !m_d->anyPickerModifierActive) return false;
QPointF imagePos = m_d->converter->documentToImage(event->point);
m_d->lastImagePos = imagePos;
return endPrimaryAction();
}
......
......@@ -34,6 +34,8 @@ public:
KisSimplifiedActionPolicyStrategy(const KisCoordinatesConverter *_converter, KoSnapGuide *snapGuide = 0);
~KisSimplifiedActionPolicyStrategy();
void activatePrimaryAction();
virtual bool beginPrimaryAction(KoPointerEvent *event);
virtual void continuePrimaryAction(KoPointerEvent *event);
virtual bool endPrimaryAction(KoPointerEvent *event);
......@@ -53,7 +55,7 @@ protected:
virtual void setTransformFunction(const QPointF &mousePos, bool perspectiveModifierActive) = 0;
virtual bool beginPrimaryAction(const QPointF &pt) = 0;
virtual void continuePrimaryAction(const QPointF &pt, bool specialModifierActve) = 0;
virtual void continuePrimaryAction(const QPointF &pt, bool shiftModifierActve, bool altModifierActive) = 0;
virtual bool endPrimaryAction() = 0;
virtual void hoverActionCommon(const QPointF &pt);
......
......@@ -151,9 +151,7 @@ void KisToolTransform::canvasUpdateRequested()
void KisToolTransform::resetCursorStyle()
{
KisTool::resetCursorStyle();
overrideCursorIfNotEditable();
setFunctionalCursor();
}
void KisToolTransform::resetRotationCenterButtonsRequested()
......@@ -346,9 +344,21 @@ void KisToolTransform::endPrimaryAction(KoPointerEvent *event)
endActionImpl(event, true, KisTool::NONE);
}
void KisToolTransform::activatePrimaryAction()
{
currentStrategy()->activatePrimaryAction();
setFunctionalCursor();
}
void KisToolTransform::deactivatePrimaryAction()
{
currentStrategy()->deactivatePrimaryAction();
}
void KisToolTransform::activateAlternateAction(AlternateAction action)
{
currentStrategy()->activateAlternateAction(action);
setFunctionalCursor();
}
void KisToolTransform::deactivateAlternateAction(AlternateAction action)
......
......@@ -138,6 +138,8 @@ public:
void continueActionImpl(KoPointerEvent *event, bool usePrimaryAction, KisTool::AlternateAction action);
void endActionImpl(KoPointerEvent *event, bool usePrimaryAction, KisTool::AlternateAction action);
void activatePrimaryAction();
void deactivatePrimaryAction();
void beginPrimaryAction(KoPointerEvent *event);
void continuePrimaryAction(KoPointerEvent *event);
void endPrimaryAction(KoPointerEvent *event);
......
......@@ -26,7 +26,6 @@
#include "KisMainWindow.h"
#include "KisViewManager.h"
#include "kis_transform_utils.h"
......@@ -148,6 +147,7 @@ KisToolTransformConfigWidget::KisToolTransformConfigWidget(TransformTransactionP
connect(m_rotationCenterButtons, SIGNAL(buttonPressed(int)), this, SLOT(slotRotationCenterChanged(int)));
connect(btnTransformAroundPivotPoint, SIGNAL(clicked(bool)), this, SLOT(slotTransformAroundRotationCenter(bool)));
// Init Free Transform Values
connect(scaleXBox, SIGNAL(valueChanged(int)), this, SLOT(slotSetScaleX(int)));
......@@ -324,6 +324,9 @@ void KisToolTransformConfigWidget::slotUpdateIcons()
middleBottomButton->setIcon(KisIconUtils::loadIcon("arrow-down"));
bottomRightButton->setIcon(KisIconUtils::loadIcon("arrow-downright"));
// TODO: change the icon!
btnTransformAroundPivotPoint->setIcon(KisIconUtils::loadIcon("transform_icons_liquify_main"));
// pressure icons
liquifySizePressureBox->setIcon(KisIconUtils::loadIcon("transform_icons_penPressure"));
......@@ -573,6 +576,9 @@ void KisToolTransformConfigWidget::updateConfig(const ToolTransformArgs &config)
break;
}
}
btnTransformAroundPivotPoint->setChecked(config.transformAroundRotationCenter());
} else if (config.mode() == ToolTransformArgs::WARP) {
stackedWidget->setCurrentIndex(1);
......@@ -842,8 +848,16 @@ void KisToolTransformConfigWidget::slotRotationCenterChanged(int index)
notifyConfigChanged();
updateConfig(*config);
}
}
void KisToolTransformConfigWidget::slotTransformAroundRotationCenter(bool value)
{
if (m_uiSlotsBlocked) return;
ToolTransformArgs *config = m_transaction->currentConfig();
config->setTransformAroundRotationCenter(value);
notifyConfigChanged();
notifyEditingFinished();
}
void KisToolTransformConfigWidget::slotSetScaleX(int value)
......@@ -851,7 +865,11 @@ void KisToolTransformConfigWidget::slotSetScaleX(int value)
if (m_uiSlotsBlocked) return;
ToolTransformArgs *config = m_transaction->currentConfig();
config->setScaleX(value / 100.);
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setScaleX(value / 100.);
}
if (config->keepAspectRatio()) {
......@@ -875,7 +893,11 @@ void KisToolTransformConfigWidget::slotSetScaleY(int value)
if (m_uiSlotsBlocked) return;
ToolTransformArgs *config = m_transaction->currentConfig();
config->setScaleY(value / 100.);
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setScaleY(value / 100.);
}
if (config->keepAspectRatio()) {
blockNotifications();
......@@ -896,7 +918,12 @@ void KisToolTransformConfigWidget::slotSetShearX(qreal value)
if (m_uiSlotsBlocked) return;
ToolTransformArgs *config = m_transaction->currentConfig();
config->setShearX((double)value);
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setShearX((double)value);
}
notifyConfigChanged();
notifyEditingFinished();
}
......@@ -906,7 +933,13 @@ void KisToolTransformConfigWidget::slotSetShearY(qreal value)
if (m_uiSlotsBlocked) return;
ToolTransformArgs *config = m_transaction->currentConfig();
config->setShearY((double)value);
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setShearY((double)value);
}
notifyConfigChanged();
notifyEditingFinished();
}
......@@ -948,7 +981,10 @@ void KisToolTransformConfigWidget::slotSetAX(qreal value)
if (m_uiSlotsBlocked) return;
ToolTransformArgs *config = m_transaction->currentConfig();
config->setAX(degreeToRadian((double)value));
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setAX(degreeToRadian((double)value));
}
notifyConfigChanged();
notifyEditingFinished();
}
......@@ -958,7 +994,12 @@ void KisToolTransformConfigWidget::slotSetAY(qreal value)
if (m_uiSlotsBlocked) return;
ToolTransformArgs *config = m_transaction->currentConfig();
config->setAY(degreeToRadian((double)value));
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setAY(degreeToRadian((double)value));
}
notifyConfigChanged();
notifyEditingFinished();
}
......@@ -968,7 +1009,12 @@ void KisToolTransformConfigWidget::slotSetAZ(qreal value)
if (m_uiSlotsBlocked) return;
ToolTransformArgs *config = m_transaction->currentConfig();
config->setAZ(degreeToRadian((double)value));
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setAZ(degreeToRadian((double)value));
}
notifyConfigChanged();
notifyEditingFinished();
}
......@@ -976,7 +1022,12 @@ void KisToolTransformConfigWidget::slotSetAZ(qreal value)
void KisToolTransformConfigWidget::slotFlipX()
{
ToolTransformArgs *config = m_transaction->currentConfig();
config->setScaleX(config->scaleX() * -1);
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setScaleX(config->scaleX() * -1);
}
notifyConfigChanged();
notifyEditingFinished();
}
......@@ -984,7 +1035,12 @@ void KisToolTransformConfigWidget::slotFlipX()
void KisToolTransformConfigWidget::slotFlipY()
{
ToolTransformArgs *config = m_transaction->currentConfig();
config->setScaleY(config->scaleY() * -1);
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setScaleY(config->scaleY() * -1);
}
notifyConfigChanged();
notifyEditingFinished();
}
......@@ -992,7 +1048,12 @@ void KisToolTransformConfigWidget::slotFlipY()
void KisToolTransformConfigWidget::slotRotateCW()
{
ToolTransformArgs *config = m_transaction->currentConfig();
config->setAZ(normalizeAngle(config->aZ() + M_PI_2));
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setAZ(normalizeAngle(config->aZ() + M_PI_2));
}
notifyConfigChanged();
notifyEditingFinished();
}
......@@ -1000,7 +1061,12 @@ void KisToolTransformConfigWidget::slotRotateCW()
void KisToolTransformConfigWidget::slotRotateCCW()
{
ToolTransformArgs *config = m_transaction->currentConfig();
config->setAZ(normalizeAngle(config->aZ() - M_PI_2));
{
KisTransformUtils::AnchorHolder keeper(config->transformAroundRotationCenter(), config);
config->setAZ(normalizeAngle(config->aZ() - M_PI_2));
}
notifyConfigChanged();
notifyEditingFinished();
}
......
......@@ -56,6 +56,7 @@ public Q_SLOTS:
void slotFilterChanged(const KoID &filter);
void slotWarpTypeChanged(int index);
void slotRotationCenterChanged(int index);
void slotTransformAroundRotationCenter(bool value);
void slotSetScaleX(int value);
void slotSetScaleY(int value);
......
......@@ -44,6 +44,14 @@ QPainterPath KisTransformStrategyBase::getCursorOutline() const
return QPainterPath();
}
void KisTransformStrategyBase::activatePrimaryAction()
{
}
void KisTransformStrategyBase::deactivatePrimaryAction()
{
}
QImage KisTransformStrategyBase::originalImage() const
{
return m_d->originalImage;
......
......@@ -54,6 +54,9 @@ public:
virtual void externalConfigChanged() = 0;
virtual void activatePrimaryAction();
virtual void deactivatePrimaryAction();
virtual bool beginPrimaryAction(KoPointerEvent *event) = 0;
virtual void continuePrimaryAction(KoPointerEvent *event) = 0;
virtual bool endPrimaryAction(KoPointerEvent *event) = 0;
......
......@@ -366,3 +366,26 @@ QRect KisTransformUtils::changeRect(const ToolTransformArgs &config,
return result;
}
KisTransformUtils::AnchorHolder::AnchorHolder(bool enabled, ToolTransformArgs *config)
: m_enabled(enabled),
m_config(config)
{
if (!m_enabled) return;
m_staticPoint = m_config->originalCenter() + m_config->rotationCenterOffset();
const KisTransformUtils::MatricesPack m(*m_config);
m_oldStaticPointInView = m.finalTransform().map(m_staticPoint);
}
KisTransformUtils::AnchorHolder::~AnchorHolder() {
if (!m_enabled) return;
const KisTransformUtils::MatricesPack m(*m_config);
const QPointF newStaticPointInView = m.finalTransform().map(m_staticPoint);
const QPointF diff = m_oldStaticPointInView - newStaticPointInView;
m_config->setTransformedCenter(m_config->transformedCenter() + diff);
}
......@@ -134,6 +134,23 @@ public:
qreal m_minDistance;
Function m_function;
};
/**
* A special class that ensures that the view position of the anchor point of the
* transformation is unchanged during the lifetime of the object. On destruction
* of the keeper the position of the anchor point will be restored.