From 76aee61eae401dd0ec0af9e008fcf3f154fffcbb Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 27 Nov 2017 13:53:56 -0300 Subject: [PATCH] Fix drawing straight lines w/Pencil tool and Shift+right button https://community.aseprite.org/t/eraser-tool-right-click-shift-should-work/726 --- src/app/tools/tool_loop.h | 1 + src/app/ui/editor/drawing_state.cpp | 37 +++++++++++++++++++++++++--- src/app/ui/editor/drawing_state.h | 2 +- src/app/ui/editor/editor.cpp | 8 +++--- src/app/ui/editor/editor.h | 3 +-- src/app/ui/editor/glue.h | 7 +++--- src/app/ui/editor/standby_state.cpp | 20 +++++++++------ src/app/ui/editor/standby_state.h | 2 +- src/app/ui/editor/tool_loop_impl.cpp | 13 +++++----- src/app/ui/editor/tool_loop_impl.h | 2 ++ 10 files changed, 69 insertions(+), 26 deletions(-) diff --git a/src/app/tools/tool_loop.h b/src/app/tools/tool_loop.h index aa17db2a8..c74617780 100644 --- a/src/app/tools/tool_loop.h +++ b/src/app/tools/tool_loop.h @@ -14,6 +14,7 @@ #include "doc/frame.h" #include "filters/tiled_mode.h" #include "gfx/point.h" +#include "gfx/rect.h" namespace gfx { class Region; diff --git a/src/app/ui/editor/drawing_state.cpp b/src/app/ui/editor/drawing_state.cpp index 5c89a440e..142b23b56 100644 --- a/src/app/ui/editor/drawing_state.cpp +++ b/src/app/ui/editor/drawing_state.cpp @@ -74,9 +74,13 @@ void DrawingState::initToolLoop(Editor* editor, static_cast(m_toolLoop->getLayer())->blendMode(): BlendMode::NEG_BW)); + ASSERT(!m_toolLoopManager->isCanceled()); + m_toolLoopManager->prepareLoop(pointer); m_toolLoopManager->pressButton(pointer); + ASSERT(!m_toolLoopManager->isCanceled()); + editor->captureMouse(); } @@ -100,14 +104,40 @@ bool DrawingState::onMouseDown(Editor* editor, MouseMessage* msg) if (!editor->hasCapture()) editor->captureMouse(); + tools::Pointer pointer = pointer_from_msg(editor, msg); + + // Check if this drawing state was started with a Shift+Pencil tool + // and now the user pressed the right button to draw the straight + // line with the background color. + bool recreateLoop = false; + if (m_type == DrawingType::LineFreehand && + !m_mousePressedReceived) { + recreateLoop = true; + } + m_mousePressedReceived = true; // Notify the mouse button down to the tool loop manager. - m_toolLoopManager->pressButton(pointer_from_msg(editor, msg)); + m_toolLoopManager->pressButton(pointer); + + // Store the isCanceled flag, because destroyLoopIfCanceled might + // destroy the tool loop manager. + ASSERT(m_toolLoopManager); + const bool isCanceled = m_toolLoopManager->isCanceled(); // The user might have canceled by the tool loop clicking with the // secondary mouse button. destroyLoopIfCanceled(editor); + + // In this case, the user canceled the straight line preview + // (Shift+Pencil) pressing the right-click (other mouse button). Now + // we have to restart the loop calling + // checkStartDrawingStraightLine() with the right-button. + if (recreateLoop && isCanceled) { + ASSERT(!m_toolLoopManager); + checkStartDrawingStraightLine(editor, msg); + } + return true; } @@ -142,7 +172,8 @@ bool DrawingState::onMouseUp(Editor* editor, MouseMessage* msg) // button, if the Shift key is pressed, the whole ToolLoop starts // again. if (Preferences::instance().editor.straightLinePreview()) - checkStartDrawingStraightLine(editor); + checkStartDrawingStraightLine(editor, msg); + return true; } @@ -208,7 +239,7 @@ bool DrawingState::onKeyUp(Editor* editor, KeyMessage* msg) // released and the user didn't press the mouse button. (m_type == DrawingType::LineFreehand && !m_mousePressedReceived && - !editor->startStraightLineWithFreehandTool())) { + !editor->startStraightLineWithFreehandTool(nullptr))) { m_toolLoop->cancel(); } diff --git a/src/app/ui/editor/drawing_state.h b/src/app/ui/editor/drawing_state.h index 95beede9e..7ac8812d7 100644 --- a/src/app/ui/editor/drawing_state.h +++ b/src/app/ui/editor/drawing_state.h @@ -8,13 +8,13 @@ #define APP_UI_EDITOR_DRAWING_STATE_H_INCLUDED #pragma once +#include "app/tools/pointer.h" #include "app/ui/editor/standby_state.h" #include "obs/connection.h" #include namespace app { namespace tools { - class Pointer; class ToolLoop; class ToolLoopManager; } diff --git a/src/app/ui/editor/editor.cpp b/src/app/ui/editor/editor.cpp index 468833256..cf55d2648 100644 --- a/src/app/ui/editor/editor.cpp +++ b/src/app/ui/editor/editor.cpp @@ -1556,15 +1556,17 @@ app::Color Editor::getColorByPosition(const gfx::Point& mousePos) return app::Color::fromMask(); } -bool Editor::startStraightLineWithFreehandTool() +bool Editor::startStraightLineWithFreehandTool(const ui::MouseMessage* msg) { tools::Tool* tool = App::instance()->activeToolManager()->selectedTool(); + // TODO add support for more buttons (X1, X2, etc.) + int i = (msg && msg->right() ? 1: 0); return (isActive() && (hasMouse() || hasCapture()) && tool && - tool->getController(0)->isFreehand() && - tool->getInk(0)->isPaint() && + tool->getController(i)->isFreehand() && + tool->getInk(i)->isPaint() && (getCustomizationDelegate() ->getPressedKeyAction(KeyContext::FreehandTool) & KeyAction::StraightLineFromLastPoint) == KeyAction::StraightLineFromLastPoint && document()->lastDrawingPoint() != app::Document::NoLastDrawingPoint()); diff --git a/src/app/ui/editor/editor.h b/src/app/ui/editor/editor.h index e96bf9457..a69b46be6 100644 --- a/src/app/ui/editor/editor.h +++ b/src/app/ui/editor/editor.h @@ -195,7 +195,6 @@ namespace app { tools::ToolLoopModifiers getToolLoopModifiers() const { return m_toolLoopModifiers; } bool isAutoSelectLayer() const; - bool isSecondaryButton() const { return m_secondaryButton; } // Returns true if we are able to draw in the current doc/sprite/layer/cel. bool canDraw(); @@ -268,7 +267,7 @@ namespace app { // Returns true if the Shift key to draw straight lines with a // freehand tool is pressed. - bool startStraightLineWithFreehandTool(); + bool startStraightLineWithFreehandTool(const ui::MouseMessage* msg); protected: bool onProcessMessage(ui::Message* msg) override; diff --git a/src/app/ui/editor/glue.h b/src/app/ui/editor/glue.h index f593521f5..0dcb62b1b 100644 --- a/src/app/ui/editor/glue.h +++ b/src/app/ui/editor/glue.h @@ -1,5 +1,5 @@ // Aseprite -// Copyright (C) 2016 David Capello +// Copyright (C) 2016-2017 David Capello // // This program is distributed under the terms of // the End-User License Agreement for Aseprite. @@ -16,14 +16,15 @@ namespace app { // Code to convert "ui" messages to "tools" mouse pointers -inline tools::Pointer::Button button_from_msg(ui::MouseMessage* msg) { +inline tools::Pointer::Button button_from_msg(const ui::MouseMessage* msg) { return (msg->right() ? tools::Pointer::Right: (msg->middle() ? tools::Pointer::Middle: tools::Pointer::Left)); } -inline tools::Pointer pointer_from_msg(Editor* editor, ui::MouseMessage* msg) { +inline tools::Pointer pointer_from_msg(Editor* editor, + const ui::MouseMessage* msg) { return tools::Pointer(editor->screenToEditor(msg->position()), button_from_msg(msg)); diff --git a/src/app/ui/editor/standby_state.cpp b/src/app/ui/editor/standby_state.cpp index e025f561d..968baa028 100644 --- a/src/app/ui/editor/standby_state.cpp +++ b/src/app/ui/editor/standby_state.cpp @@ -319,7 +319,7 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg) // Shift+click on Pencil tool starts a line onMouseDown() when the // preview (onKeyDown) is disabled. if (!Preferences::instance().editor.straightLinePreview() && - checkStartDrawingStraightLine(editor)) { + checkStartDrawingStraightLine(editor, msg)) { // Send first mouse down to draw the straight line and start the // freehand mode. editor->getState()->onMouseDown(editor, msg); @@ -501,7 +501,7 @@ bool StandbyState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos) bool StandbyState::onKeyDown(Editor* editor, KeyMessage* msg) { if (Preferences::instance().editor.straightLinePreview() && - checkStartDrawingStraightLine(editor)) + checkStartDrawingStraightLine(editor, nullptr)) return true; return false; } @@ -607,6 +607,7 @@ DrawingState* StandbyState::startDrawingState(Editor* editor, tools::ToolLoop* toolLoop = create_tool_loop( editor, UIContext::instance(), + pointer.button(), (drawingType == DrawingType::LineFreehand)); if (!toolLoop) return nullptr; @@ -624,21 +625,26 @@ DrawingState* StandbyState::startDrawingState(Editor* editor, return static_cast(newState.get()); } -bool StandbyState::checkStartDrawingStraightLine(Editor* editor) +bool StandbyState::checkStartDrawingStraightLine(Editor* editor, + const ui::MouseMessage* msg) { // Start line preview with shift key - if (editor->startStraightLineWithFreehandTool()) { + if (editor->startStraightLineWithFreehandTool(msg)) { + tools::Pointer::Button pointerButton = + (msg ? button_from_msg(msg): tools::Pointer::Left); + DrawingState* drawingState = startDrawingState(editor, DrawingType::LineFreehand, tools::Pointer( editor->document()->lastDrawingPoint(), - tools::Pointer::Left)); + pointerButton)); if (drawingState) { drawingState->sendMovementToToolLoop( tools::Pointer( - editor->screenToEditor(ui::get_mouse_position()), - tools::Pointer::Left)); + editor->screenToEditor(msg ? msg->position(): + ui::get_mouse_position()), + pointerButton)); return true; } } diff --git a/src/app/ui/editor/standby_state.h b/src/app/ui/editor/standby_state.h index 01b095a21..dabbcc763 100644 --- a/src/app/ui/editor/standby_state.h +++ b/src/app/ui/editor/standby_state.h @@ -50,7 +50,7 @@ namespace app { protected: void callEyedropper(Editor* editor); - bool checkStartDrawingStraightLine(Editor* editor); + bool checkStartDrawingStraightLine(Editor* editor, const ui::MouseMessage* msg); class Decorator : public EditorDecorator { public: diff --git a/src/app/ui/editor/tool_loop_impl.cpp b/src/app/ui/editor/tool_loop_impl.cpp index aebb0dc61..80f6c5950 100644 --- a/src/app/ui/editor/tool_loop_impl.cpp +++ b/src/app/ui/editor/tool_loop_impl.cpp @@ -543,6 +543,7 @@ public: tools::ToolLoop* create_tool_loop( Editor* editor, Context* context, + const tools::Pointer::Button button, const bool convertLineToFreehand) { tools::Tool* tool = editor->getCurrentEditorTool(); @@ -562,7 +563,7 @@ tools::ToolLoop* create_tool_loop( // isFloodFill) because we need the original layer source // image/pixels to stop the flood-fill algorithm. if (ink->isSelection() && - !tool->getPointShape(editor->isSecondaryButton() ? 1: 0)->isFloodFill()) { + !tool->getPointShape(button != tools::Pointer::Left ? 1: 0)->isFloodFill()) { layer = nullptr; } else { @@ -603,15 +604,15 @@ tools::ToolLoop* create_tool_loop( // Create the new tool loop try { - tools::ToolLoop::Button button = - (!editor->isSecondaryButton() ? tools::ToolLoop::Left: - tools::ToolLoop::Right); + tools::ToolLoop::Button toolLoopButton = + (button == tools::Pointer::Left ? tools::ToolLoop::Left: + tools::ToolLoop::Right); tools::Controller* controller = (convertLineToFreehand ? App::instance()->toolBox()->getControllerById( tools::WellKnownControllers::LineFreehand): - tool->getController(button)); + tool->getController(toolLoopButton)); const bool saveLastPoint = (ink->isPaint() && @@ -624,7 +625,7 @@ tools::ToolLoop* create_tool_loop( ink, controller, editor->document(), - button, + toolLoopButton, fg, bg, saveLastPoint); } diff --git a/src/app/ui/editor/tool_loop_impl.h b/src/app/ui/editor/tool_loop_impl.h index b25b621e0..594708c3e 100644 --- a/src/app/ui/editor/tool_loop_impl.h +++ b/src/app/ui/editor/tool_loop_impl.h @@ -8,6 +8,7 @@ #define APP_UI_EDITOR_TOOL_LOOP_IMPL_H_INCLUDED #pragma once +#include "app/tools/pointer.h" #include "doc/image_ref.h" #include "gfx/fwd.h" @@ -26,6 +27,7 @@ namespace app { tools::ToolLoop* create_tool_loop( Editor* editor, Context* context, + const tools::Pointer::Button button, const bool convertLineToFreehand); tools::ToolLoop* create_tool_loop_preview(