Fix drawing straight lines w/Pencil tool and Shift+right button

https://community.aseprite.org/t/eraser-tool-right-click-shift-should-work/726
This commit is contained in:
David Capello 2017-11-27 13:53:56 -03:00
parent 848ce5972d
commit 76aee61eae
10 changed files with 69 additions and 26 deletions

View File

@ -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;

View File

@ -74,9 +74,13 @@ void DrawingState::initToolLoop(Editor* editor,
static_cast<LayerImage*>(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();
}

View File

@ -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 <memory>
namespace app {
namespace tools {
class Pointer;
class ToolLoop;
class ToolLoopManager;
}

View File

@ -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());

View File

@ -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;

View File

@ -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));

View File

@ -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<DrawingState*>(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;
}
}

View File

@ -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:

View File

@ -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);
}

View File

@ -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(