diff --git a/libs/image/brushengine/kis_paintop_settings.h b/libs/image/brushengine/kis_paintop_settings.h --- a/libs/image/brushengine/kis_paintop_settings.h +++ b/libs/image/brushengine/kis_paintop_settings.h @@ -86,11 +86,18 @@ /** * This function is called by a tool when the mouse is pressed. It's useful if * the paintop needs mouse interaction for instance in the case of the clone op. - * If the tool is supposed to ignore the event, the paint op should return false - * and if the tool is supposed to use the event, return true. + * If the tool is supposed to ignore the event, the paint op should return true + * and if the tool is supposed to use the event, return false. + * See kis_tool_freehand:tryPickByPaintOp() */ virtual bool mousePressEvent(const KisPaintInformation &paintInformation, Qt::KeyboardModifiers modifiers, KisNodeWSP currentNode); - + /** + * This function is called by a tool when the mouse is released. It's useful if + * the paintop needs mouse interaction for instance in the case of the clone op. + * If the tool is supposed to ignore the event, the paint op should return true + * and if the tool is supposed to use the event, return false. + */ + virtual bool mouseReleaseEvent(); /** * Clone the current settings object. Override this if your settings instance doesn't * store everything as properties. diff --git a/libs/image/brushengine/kis_paintop_settings.cpp b/libs/image/brushengine/kis_paintop_settings.cpp --- a/libs/image/brushengine/kis_paintop_settings.cpp +++ b/libs/image/brushengine/kis_paintop_settings.cpp @@ -131,6 +131,11 @@ return true; // ignore the event by default } +bool KisPaintOpSettings::mouseReleaseEvent() +{ + return true; // ignore the event by default +} + void KisPaintOpSettings::setRandomOffset(const KisPaintInformation &paintInformation) { if (getBool("Texture/Pattern/Enabled")) { diff --git a/libs/ui/tool/kis_tool_freehand.cc b/libs/ui/tool/kis_tool_freehand.cc --- a/libs/ui/tool/kis_tool_freehand.cc +++ b/libs/ui/tool/kis_tool_freehand.cc @@ -188,6 +188,8 @@ void KisToolFreehand::endStroke() { m_helper->endPaint(); + bool paintOpIgnoredEvent = currentPaintOpPreset()->settings()->mouseReleaseEvent(); + Q_UNUSED(paintOpIgnoredEvent); } bool KisToolFreehand::primaryActionSupportsHiResEvents() const @@ -285,6 +287,8 @@ perspective, 0, 0), event->modifiers(), currentNode()); + // DuplicateOP during the picking of new source point (origin) + // is the only paintop that returns "false" here return !paintOpIgnoredEvent; } diff --git a/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.h b/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.h --- a/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.h +++ b/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.h @@ -23,6 +23,7 @@ const QString DUPLICATE_HEALING = "Duplicateop/Healing"; const QString DUPLICATE_CORRECT_PERSPECTIVE = "Duplicateop/CorrectPerspective"; const QString DUPLICATE_MOVE_SOURCE_POINT = "Duplicateop/MoveSourcePoint"; +const QString DUPLICATE_RESET_SOURCE_POINT = "Duplicateop/ResetSourcePoint"; const QString DUPLICATE_CLONE_FROM_PROJECTION = "Duplicateop/CloneFromProjection"; class KisDuplicateOpOptionsWidget; @@ -43,6 +44,9 @@ bool moveSourcePoint() const; void setMoveSourcePoint(bool move); + bool resetSourcePoint() const; + void setResetSourcePoint(bool resetSource); + bool cloneFromProjection() const; void setCloneFromProjection(bool cloneFromProjection); public: @@ -63,19 +67,22 @@ bool duplicate_healing; bool duplicate_correct_perspective; bool duplicate_move_source_point; + bool duplicate_reset_source_point; bool duplicate_clone_from_projection; void readOptionSettingImpl(const KisPropertiesConfiguration* setting) override { duplicate_healing = setting->getBool(DUPLICATE_HEALING, false); duplicate_correct_perspective = setting->getBool(DUPLICATE_CORRECT_PERSPECTIVE, false); duplicate_move_source_point = setting->getBool(DUPLICATE_MOVE_SOURCE_POINT, true); + duplicate_reset_source_point = setting->getBool(DUPLICATE_RESET_SOURCE_POINT, false); duplicate_clone_from_projection = setting->getBool(DUPLICATE_CLONE_FROM_PROJECTION, false); } void writeOptionSettingImpl(KisPropertiesConfiguration *setting) const override { setting->setProperty(DUPLICATE_HEALING, duplicate_healing); setting->setProperty(DUPLICATE_CORRECT_PERSPECTIVE, duplicate_correct_perspective); setting->setProperty(DUPLICATE_MOVE_SOURCE_POINT, duplicate_move_source_point); + setting->setProperty(DUPLICATE_RESET_SOURCE_POINT, duplicate_reset_source_point); setting->setProperty(DUPLICATE_CLONE_FROM_PROJECTION, duplicate_clone_from_projection); } }; diff --git a/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.cpp b/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.cpp --- a/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.cpp +++ b/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.cpp @@ -52,6 +52,7 @@ connect(m_optionWidget->cbHealing, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_optionWidget->cbPerspective, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_optionWidget->cbSourcePoint, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); + connect(m_optionWidget->cbResetSourcePoint, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_optionWidget->chkCloneProjection, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); setConfigurationPage(m_optionWidget); @@ -92,6 +93,16 @@ m_optionWidget->cbSourcePoint->setChecked(move); } +bool KisDuplicateOpOption::resetSourcePoint() const +{ + return m_optionWidget->cbResetSourcePoint->isChecked(); +} + +void KisDuplicateOpOption::setResetSourcePoint(bool reset) +{ + m_optionWidget->cbResetSourcePoint->setChecked(reset); +} + bool KisDuplicateOpOption::cloneFromProjection() const { return m_optionWidget->chkCloneProjection->isChecked(); @@ -109,6 +120,7 @@ op.duplicate_healing = healing(); op.duplicate_correct_perspective = correctPerspective(); op.duplicate_move_source_point = moveSourcePoint(); + op.duplicate_reset_source_point = resetSourcePoint(); op.duplicate_clone_from_projection = cloneFromProjection(); op.writeOptionSetting(setting); @@ -122,6 +134,7 @@ m_optionWidget->cbHealing->setChecked(op.duplicate_healing); m_optionWidget->cbPerspective->setChecked(op.duplicate_correct_perspective); m_optionWidget->cbSourcePoint->setChecked(op.duplicate_move_source_point); + m_optionWidget->cbResetSourcePoint->setChecked(op.duplicate_reset_source_point); m_optionWidget->chkCloneProjection->setChecked(op.duplicate_clone_from_projection); } diff --git a/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_settings.h b/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_settings.h --- a/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_settings.h +++ b/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_settings.h @@ -42,7 +42,19 @@ QPointF offset() const; QPointF position() const; + /** + * This function is called by a tool when the mouse is pressed. + * Returns false if picking new origin is in action, + * and returns true otherwise (i.e. if brush is starting a new stroke). + * See kis_tool_freehand:tryPickByPaintOp() + */ bool mousePressEvent(const KisPaintInformation& pos, Qt::KeyboardModifiers modifiers, KisNodeWSP currentNode) override; + /** + * This function is called by a tool when the mouse is released. + * If the tool is supposed to ignore the event, the paint op should return true + * and if the tool is supposed to use the event, return false. + */ + bool mouseReleaseEvent() override; void activate() override; void fromXML(const QDomElement& elt) override; @@ -61,9 +73,10 @@ Q_DISABLE_COPY(KisDuplicateOpSettings) QPointF m_offset; - bool m_isOffsetNotUptodate; + bool m_isOffsetNotUptodate; // true between the act of setting a new origin and the first stroke + bool m_duringPaintingStroke; // true if the stroke is begin painted now, false otherwise QPointF m_position; // Give the position of the last alt-click - KisNodeWSP m_sourceNode; + KisNodeWSP m_sourceNode; // Give the node of the source point (origin) QList m_uniformProperties; }; diff --git a/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_settings.cpp b/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_settings.cpp --- a/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_settings.cpp +++ b/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_settings.cpp @@ -40,7 +40,7 @@ #include KisDuplicateOpSettings::KisDuplicateOpSettings() - : m_isOffsetNotUptodate(false) + : m_isOffsetNotUptodate(false), m_duringPaintingStroke(false) { } @@ -81,16 +81,26 @@ ignoreEvent = false; } else { - if (m_isOffsetNotUptodate) { + bool resetOrigin = getBool(DUPLICATE_RESET_SOURCE_POINT); + if (m_isOffsetNotUptodate || resetOrigin) { m_offset = info.pos() - m_position; m_isOffsetNotUptodate = false; } + m_duringPaintingStroke = true; ignoreEvent = true; } return ignoreEvent; } +bool KisDuplicateOpSettings::mouseReleaseEvent() +{ + m_duringPaintingStroke = false; + bool ignoreEvent = true; + return ignoreEvent; +} + + KisNodeWSP KisDuplicateOpSettings::sourceNode() const { return m_sourceNode; @@ -129,6 +139,7 @@ s->m_isOffsetNotUptodate = m_isOffsetNotUptodate; s->m_position = m_position; s->m_sourceNode = m_sourceNode; + s->m_duringPaintingStroke = m_duringPaintingStroke; return setting; } @@ -149,7 +160,11 @@ QPainterPath copy(path); QRectF rect2 = copy.boundingRect(); - if (m_isOffsetNotUptodate || !getBool(DUPLICATE_MOVE_SOURCE_POINT)) { + bool shouldStayInOrigin = m_isOffsetNotUptodate // the clone brush right now waits for first stroke with a new origin, so stays at origin point + || !getBool(DUPLICATE_MOVE_SOURCE_POINT) // the brush always use the same source point, so stays at origin point + || (!m_duringPaintingStroke && getBool(DUPLICATE_RESET_SOURCE_POINT)); // during the stroke, with reset Origin selected, outline should stay at origin point + + if (shouldStayInOrigin) { copy.translate(m_position - info.pos()); } else { diff --git a/plugins/paintops/defaultpaintops/duplicate/wdgduplicateop.ui b/plugins/paintops/defaultpaintops/duplicate/wdgduplicateop.ui --- a/plugins/paintops/defaultpaintops/duplicate/wdgduplicateop.ui +++ b/plugins/paintops/defaultpaintops/duplicate/wdgduplicateop.ui @@ -45,6 +45,19 @@ + + + + Reset the origin every time you make a new stroke. + + + Source point reset before a new stroke + + + false + + +