Add customization for square aspect, draw from center, and move origin keys (fix #1028)

Some changes:
- Now ui::Keys aren't processed in app::tools side, they are processed
  in Editor side and converted to ToolLoopModifiers flags.
- Replace ToolLoop::getSelectionMode -> ToolLoop::getModifiers()
This commit is contained in:
David Capello 2016-04-04 18:46:48 -03:00
parent 5847624d0e
commit 2ce09c53dd
24 changed files with 199 additions and 233 deletions

View File

@ -483,6 +483,13 @@
<!-- Modifiers for freehand tool controller -->
<key action="StraightLineFromLastPoint" shortcut="Shift" />
<!-- Modifiers for two-points tool controller -->
<key action="SquareAspect" shortcut="Shift" />
<key action="DrawFromCenter" shortcut="Ctrl" />
<!-- Modifiers for two-or-more-points tools -->
<key action="MoveOrigin" shortcut="Space" />
<!-- Without default shortcuts -->
<key action="LeftMouseButton" />
<key action="RightMouseButton" />

View File

@ -52,6 +52,11 @@
<value id="ALL_LAYERS" value="0" />
<value id="CURRENT_LAYER" value="1" />
</enum>
<enum id="SelectionMode">
<value id="DEFAULT" value="0" />
<value id="ADD" value="1" />
! <value id="SUBTRACT" value="2" />
</enum>
<enum id="PivotPosition">
<value id="NORTHWEST" value="0" />
<value id="NORTH" value="1" />
@ -151,7 +156,7 @@
<option id="pixel_perfect" type="bool" default="false" />
</section>
<section id="selection">
<option id="mode" type="app::tools::SelectionMode" default="app::tools::SelectionMode::DEFAULT" />
<option id="mode" type="SelectionMode" default="SelectionMode::DEFAULT" />
<option id="pivot_visibility" type="bool" default="false" />
<option id="pivot_position" type="PivotPosition" default="PivotPosition::CENTER" />
<option id="opaque" type="bool" default="false" />

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -361,6 +361,9 @@ private:
case KeyContext::FreehandTool:
text = "Freehand Tools: " + text;
break;
case KeyContext::ShapeTool:
text = "Shape Tools: " + text;
break;
}
KeyItem* keyItem = new KeyItem(text, key, NULL, 0);

View File

@ -38,14 +38,14 @@ protected:
std::string onGetFriendlyName() const override;
private:
tools::SelectionMode m_mode;
gen::SelectionMode m_mode;
};
SelectTileCommand::SelectTileCommand()
: Command("SelectTile",
"Select Tile",
CmdRecordableFlag)
, m_mode(tools::SelectionMode::DEFAULT)
, m_mode(gen::SelectionMode::DEFAULT)
{
}
@ -53,11 +53,11 @@ void SelectTileCommand::onLoadParams(const Params& params)
{
std::string mode = params.get("mode");
if (mode == "add")
m_mode = tools::SelectionMode::ADD;
m_mode = gen::SelectionMode::ADD;
else if (mode == "subtract")
m_mode = tools::SelectionMode::SUBTRACT;
m_mode = gen::SelectionMode::SUBTRACT;
else
m_mode = tools::SelectionMode::DEFAULT;
m_mode = gen::SelectionMode::DEFAULT;
}
bool SelectTileCommand::onEnabled(Context* ctx)
@ -78,7 +78,7 @@ void SelectTileCommand::onExecute(Context* ctx)
base::UniquePtr<Mask> mask(new Mask());
if (m_mode != tools::SelectionMode::DEFAULT)
if (m_mode != gen::SelectionMode::DEFAULT)
mask->copyFrom(doc->mask());
{
@ -87,7 +87,7 @@ void SelectTileCommand::onExecute(Context* ctx)
pos = snap_to_grid(gridBounds, pos, PreferSnapTo::BoxOrigin);
gridBounds.setOrigin(pos);
if (m_mode != tools::SelectionMode::SUBTRACT)
if (m_mode != gen::SelectionMode::SUBTRACT)
mask->add(gridBounds);
else
mask->subtract(gridBounds);
@ -109,8 +109,8 @@ std::string SelectTileCommand::onGetFriendlyName() const
std::string text = "Select Tile";
switch (m_mode) {
case tools::SelectionMode::ADD: text += " (Add)"; break;
case tools::SelectionMode::SUBTRACT: text += " (Subtract)"; break;
case gen::SelectionMode::ADD: text += " (Add)"; break;
case gen::SelectionMode::SUBTRACT: text += " (Subtract)"; break;
}
return text;

View File

@ -16,7 +16,6 @@
#include "app/tools/freehand_algorithm.h"
#include "app/tools/ink_type.h"
#include "app/tools/rotation_algorithm.h"
#include "app/tools/selection_mode.h"
#include "app/ui/color_bar.h"
#include "doc/anidir.h"
#include "doc/brush_pattern.h"

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -10,7 +10,6 @@
#pragma once
#include "gfx/point.h"
#include "ui/keys.h"
#include <string>
#include <vector>
@ -30,13 +29,6 @@ namespace app {
virtual bool isFreehand() { return false; }
virtual bool isOnePoint() { return false; }
virtual void prepareController(ui::KeyModifiers modifiers) { }
// Called when the user presses or releases a key. Returns true
// if the key is used (so a new mouse point is generated).
virtual bool pressKey(ui::KeyScancode key) { return false; }
virtual bool releaseKey(ui::KeyScancode key) { return false; }
// Called when the user starts drawing and each time a new button is
// pressed. The controller could be sure that this method is called
// at least one time. The point is a position relative to sprite

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -18,29 +18,15 @@ using namespace gfx;
// using the space bar.
class MoveOriginCapability : public Controller {
public:
void prepareController(ui::KeyModifiers modifiers) override {
m_movingOrigin = false;
}
void pressButton(Stroke& stroke, const Point& point) override {
m_last = point;
}
bool pressKey(ui::KeyScancode key) override {
TRACE("pressKey(%d)\n", key);
return processKey(key, true);
}
bool releaseKey(ui::KeyScancode key) override {
TRACE("releaseKey(%d)\n", key);
return processKey(key, false);
}
protected:
bool isMovingOrigin(Stroke& stroke, const Point& point) {
bool isMovingOrigin(ToolLoop* loop, Stroke& stroke, const Point& point) {
bool used = false;
if (m_movingOrigin) {
if (int(loop->getModifiers()) & int(ToolLoopModifiers::kMoveOrigin)) {
Point delta = (point - m_last);
stroke.offset(delta);
@ -57,18 +43,6 @@ protected:
}
private:
bool processKey(ui::KeyScancode key, bool state) {
if (key == ui::kKeySpace) {
m_movingOrigin = state;
return true;
}
return false;
}
// Flag used to know if the space bar is pressed, i.e., we have
// displace all points.
bool m_movingOrigin;
// Last known mouse position used to calculate delta values (dx, dy)
// with the new mouse position to displace all points.
Point m_last;
@ -120,13 +94,6 @@ public:
// Controls clicks for tools like line
class TwoPointsController : public MoveOriginCapability {
public:
void prepareController(ui::KeyModifiers modifiers) override {
MoveOriginCapability::prepareController(modifiers);
m_squareAspect = (modifiers & ui::kKeyShiftModifier) ? true: false;
m_fromCenter = (modifiers & ui::kKeyCtrlModifier) ? true: false;
}
void pressButton(Stroke& stroke, const Point& point) override {
MoveOriginCapability::pressButton(stroke, point);
@ -140,31 +107,17 @@ public:
return false;
}
bool pressKey(ui::KeyScancode key) override {
if (MoveOriginCapability::pressKey(key))
return true;
return processKey(key, true);
}
bool releaseKey(ui::KeyScancode key) override {
if (MoveOriginCapability::releaseKey(key))
return true;
return processKey(key, false);
}
void movement(ToolLoop* loop, Stroke& stroke, const Point& point) override {
ASSERT(stroke.size() >= 2);
if (stroke.size() < 2)
return;
if (MoveOriginCapability::isMovingOrigin(stroke, point))
if (MoveOriginCapability::isMovingOrigin(loop, stroke, point))
return;
stroke[1] = point;
if (m_squareAspect) {
if (int(loop->getModifiers()) & int(ToolLoopModifiers::kSquareAspect)) {
int dx = stroke[1].x - m_first.x;
int dy = stroke[1].y - m_first.y;
int minsize = MIN(ABS(dx), ABS(dy));
@ -209,7 +162,7 @@ public:
stroke[0] = m_first;
if (m_fromCenter) {
if (int(loop->getModifiers()) & int(ToolLoopModifiers::kFromCenter)) {
int rx = stroke[1].x - m_first.x;
int ry = stroke[1].y - m_first.y;
stroke[0].x = m_first.x - rx;
@ -264,23 +217,7 @@ private:
m_first += delta;
}
bool processKey(ui::KeyScancode key, bool state) {
switch (key) {
case ui::kKeyLShift:
case ui::kKeyRShift:
m_squareAspect = state;
return true;
case ui::kKeyLControl:
case ui::kKeyRControl:
m_fromCenter = state;
return true;
}
return false;
}
Point m_first;
bool m_squareAspect;
bool m_fromCenter;
};
// Controls clicks for tools like polygon
@ -311,7 +248,7 @@ public:
if (stroke.empty())
return;
if (MoveOriginCapability::isMovingOrigin(stroke, point))
if (MoveOriginCapability::isMovingOrigin(loop, stroke, point))
return;
stroke[stroke.size()-1] = point;
@ -392,7 +329,7 @@ public:
}
void movement(ToolLoop* loop, Stroke& stroke, const Point& point) override {
if (MoveOriginCapability::isMovingOrigin(stroke, point))
if (MoveOriginCapability::isMovingOrigin(loop, stroke, point))
return;
switch (m_clickCounter) {

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -322,16 +322,15 @@ public:
void inkHline(int x1, int y, int x2, ToolLoop* loop) override {
if (m_modify_selection) {
int modifiers = int(loop->getModifiers());
Point origin = loop->getCelOrigin();
switch (loop->getSelectionMode()) {
case SelectionMode::DEFAULT:
case SelectionMode::ADD:
m_mask.add(gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1));
break;
case SelectionMode::SUBTRACT:
m_mask.subtract(gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1));
break;
if ((modifiers & (int(ToolLoopModifiers::kReplaceSelection) |
int(ToolLoopModifiers::kAddSelection))) != 0) {
m_mask.add(gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1));
}
else if ((modifiers & int(ToolLoopModifiers::kSubtractSelection)) != 0) {
m_mask.subtract(gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1));
}
m_maxBounds |= gfx::Rect(x1+origin.x, y+origin.y, x2-x1+1, 1);

View File

@ -1,24 +0,0 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_TOOLS_SELECTION_MODE_H_INCLUDED
#define APP_TOOLS_SELECTION_MODE_H_INCLUDED
#pragma once
namespace app {
namespace tools {
enum class SelectionMode {
DEFAULT = 0,
ADD = 1,
SUBTRACT = 2,
};
} // namespace tools
} // namespace app
#endif

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -9,7 +9,7 @@
#define APP_TOOLS_TOOL_LOOP_H_INCLUDED
#pragma once
#include "app/tools/selection_mode.h"
#include "app/tools/tool_loop_modifiers.h"
#include "app/tools/trace_policy.h"
#include "doc/color.h"
#include "doc/frame.h"
@ -159,8 +159,9 @@ namespace app {
// contiguous pixels or not.
virtual bool getContiguous() = 0;
// Returns the selection mode (if the ink is of selection type).
virtual tools::SelectionMode getSelectionMode() = 0;
// Returns flags/modifiers that change the way each part of the
// tool (ink/controllers/etc.) work.
virtual tools::ToolLoopModifiers getModifiers() = 0;
// Returns the preferred "tiled" mode of the document.
// See the method PointShape::doInkHline to check how this member is

View File

@ -48,8 +48,7 @@ bool ToolLoopManager::isCanceled() const
return m_toolLoop->isCanceled();
}
void ToolLoopManager::prepareLoop(const Pointer& pointer,
ui::KeyModifiers modifiers)
void ToolLoopManager::prepareLoop(const Pointer& pointer)
{
// Start with no points at all
m_stroke.reset();
@ -57,35 +56,16 @@ void ToolLoopManager::prepareLoop(const Pointer& pointer,
// Prepare the ink
m_toolLoop->getInk()->prepareInk(m_toolLoop);
m_toolLoop->getIntertwine()->prepareIntertwine();
m_toolLoop->getController()->prepareController(modifiers);
m_toolLoop->getPointShape()->preparePointShape(m_toolLoop);
}
void ToolLoopManager::pressKey(ui::KeyScancode key)
void ToolLoopManager::notifyToolLoopModifiersChange()
{
if (isCanceled())
return;
if (m_toolLoop->getController()->pressKey(key)) {
if (m_lastPointer.getButton() != Pointer::None)
movement(m_lastPointer);
}
}
void ToolLoopManager::releaseKey(ui::KeyScancode key)
{
if (isCanceled())
return;
if (key == ui::kKeyEsc) {
m_toolLoop->cancel();
return;
}
if (m_toolLoop->getController()->releaseKey(key)) {
if (m_lastPointer.getButton() != Pointer::None)
movement(m_lastPointer);
}
if (m_lastPointer.getButton() != Pointer::None)
movement(m_lastPointer);
}
void ToolLoopManager::pressButton(const Pointer& pointer)

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -12,7 +12,6 @@
#include "app/tools/stroke.h"
#include "gfx/point.h"
#include "gfx/region.h"
#include "ui/keys.h"
#include <vector>
@ -69,11 +68,11 @@ namespace app {
// Should be called when the user start a tool-trace (pressing the
// left or right button for first time in the editor).
void prepareLoop(const Pointer& pointer,
ui::KeyModifiers modifiers);
void prepareLoop(const Pointer& pointer);
void pressKey(ui::KeyScancode key);
void releaseKey(ui::KeyScancode key);
// Should be called when the ToolLoop::getModifiers()
// value was modified (e.g. when the user press/release a key).
void notifyToolLoopModifiersChange();
// Should be called each time the user presses a mouse button.
void pressButton(const Pointer& pointer);

View File

@ -0,0 +1,28 @@
// Aseprite
// Copyright (C) 2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
#ifndef APP_TOOLS_TOOL_LOOP_MODIFIERS_H_INCLUDED
#define APP_TOOLS_TOOL_LOOP_MODIFIERS_H_INCLUDED
#pragma once
namespace app {
namespace tools {
enum class ToolLoopModifiers {
kNone = 0x00000000,
kReplaceSelection = 0x00000001,
kAddSelection = 0x00000002,
kSubtractSelection = 0x00000004,
kMoveOrigin = 0x00000008,
kSquareAspect = 0x00000010,
kFromCenter = 0x00000020,
};
} // namespace tools
} // namespace app
#endif

View File

@ -27,9 +27,9 @@
#include "app/tools/ink.h"
#include "app/tools/ink_type.h"
#include "app/tools/point_shape.h"
#include "app/tools/selection_mode.h"
#include "app/tools/tool.h"
#include "app/tools/tool_box.h"
#include "app/tools/tool_loop_modifiers.h"
#include "app/ui/brush_popup.h"
#include "app/ui/button_set.h"
#include "app/ui/color_button.h"
@ -1110,7 +1110,7 @@ public:
tooltipManager->addTooltipFor(at(2), "Subtract from selection\n(Shift+Alt)", BOTTOM);
}
void setSelectionMode(SelectionMode mode) {
void setSelectionMode(gen::SelectionMode mode) {
setSelectedItem((int)mode);
invalidate();
}
@ -1120,7 +1120,7 @@ protected:
ButtonSet::onItemChange(item);
Preferences::instance().selection.mode(
(tools::SelectionMode)selectedItem());
(gen::SelectionMode)selectedItem());
}
};
@ -1624,11 +1624,17 @@ void ContextBar::updateForSelectingBox(const std::string& text)
layout();
}
void ContextBar::updateSelectionMode(SelectionMode mode)
void ContextBar::updateToolLoopModifiersIndicators(tools::ToolLoopModifiers modifiers)
{
if (!m_selectionMode->isVisible())
return;
gen::SelectionMode mode = gen::SelectionMode::DEFAULT;
if (int(modifiers) & int(tools::ToolLoopModifiers::kAddSelection))
mode = gen::SelectionMode::ADD;
else if (int(modifiers) & int(tools::ToolLoopModifiers::kSubtractSelection))
mode = gen::SelectionMode::SUBTRACT;
m_selectionMode->setSelectionMode(mode);
}

View File

@ -12,7 +12,7 @@
#include "app/pref/preferences.h"
#include "app/shade.h"
#include "app/tools/ink_type.h"
#include "app/tools/selection_mode.h"
#include "app/tools/tool_loop_modifiers.h"
#include "app/ui/context_bar_observer.h"
#include "base/connection.h"
#include "base/observable.h"
@ -48,7 +48,7 @@ namespace app {
void updateForTool(tools::Tool* tool);
void updateForMovingPixels();
void updateForSelectingBox(const std::string& text);
void updateSelectionMode(app::tools::SelectionMode mode);
void updateToolLoopModifiersIndicators(app::tools::ToolLoopModifiers modifiers);
void updateAutoSelectLayer(bool state);
void setActiveBrush(const doc::BrushRef& brush);

View File

@ -207,7 +207,6 @@ void BrushPreview::show(const gfx::Point& screenPos)
if (loop) {
loop->getInk()->prepareInk(loop);
loop->getIntertwine()->prepareIntertwine();
loop->getController()->prepareController(ui::kKeyNoneModifier);
loop->getPointShape()->preparePointShape(loop);
loop->getPointShape()->transformPoint(
loop, -origBrushBounds.x, -origBrushBounds.y);

View File

@ -94,7 +94,7 @@ void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg)
pointer = pointer_from_msg(editor, msg);
}
m_toolLoopManager->prepareLoop(pointer, msg->modifiers());
m_toolLoopManager->prepareLoop(pointer);
m_toolLoopManager->pressButton(pointer);
// This first movement is done when the user pressed Shift+click in
@ -108,6 +108,12 @@ void DrawingState::initToolLoop(Editor* editor, MouseMessage* msg)
editor->captureMouse();
}
void DrawingState::notifyToolLoopModifiersChange(Editor* editor)
{
if (!m_toolLoopManager->isCanceled())
m_toolLoopManager->notifyToolLoopModifiersChange();
}
bool DrawingState::onMouseDown(Editor* editor, MouseMessage* msg)
{
// Drawing loop
@ -190,9 +196,6 @@ bool DrawingState::onSetCursor(Editor* editor, const gfx::Point& mouseScreenPos)
bool DrawingState::onKeyDown(Editor* editor, KeyMessage* msg)
{
if (msg->repeat() == 0)
m_toolLoopManager->pressKey(msg->scancode());
Command* command = NULL;
Params params;
if (KeyboardShortcuts::instance()
@ -208,7 +211,8 @@ bool DrawingState::onKeyDown(Editor* editor, KeyMessage* msg)
bool DrawingState::onKeyUp(Editor* editor, KeyMessage* msg)
{
m_toolLoopManager->releaseKey(msg->scancode());
if (msg->scancode() == ui::kKeyEsc)
m_toolLoop->cancel();
// The user might have canceled the tool loop pressing the 'Esc' key.
destroyLoopIfCanceled(editor);

View File

@ -35,6 +35,7 @@ namespace app {
virtual bool requireBrushPreview() override { return false; }
void initToolLoop(Editor* editor, ui::MouseMessage* msg);
void notifyToolLoopModifiersChange(Editor* editor);
private:
void destroyLoopIfCanceled(Editor* editor);

View File

@ -30,6 +30,7 @@
#include "app/tools/tool_box.h"
#include "app/ui/color_bar.h"
#include "app/ui/context_bar.h"
#include "app/ui/editor/drawing_state.h"
#include "app/ui/editor/editor_customization_delegate.h"
#include "app/ui/editor/editor_decorator.h"
#include "app/ui/editor/moving_pixels_state.h"
@ -157,7 +158,7 @@ Editor::Editor(Document* document, EditorFlags flags)
, m_brushPreview(this)
, m_lastDrawingPosition(-1, -1)
, m_quicktool(NULL)
, m_selectionMode(tools::SelectionMode::DEFAULT)
, m_toolLoopModifiers(tools::ToolLoopModifiers::kNone)
, m_padding(0, 0)
, m_antsTimer(100, this)
, m_antsOffset(0)
@ -1110,7 +1111,7 @@ void Editor::updateStatusBar()
void Editor::updateQuicktool()
{
if (m_customizationDelegate) {
if (m_customizationDelegate && !hasCapture()) {
tools::Tool* current_tool = App::instance()->activeTool();
// Don't change quicktools if we are in a selection tool and using
@ -1156,42 +1157,67 @@ void Editor::updateQuicktool()
}
}
void Editor::updateContextBarFromModifiers()
void Editor::updateToolLoopModifiersIndicators()
{
// We update the selection mode only if we're not selecting.
if (hasCapture())
return;
int modifiers = int(tools::ToolLoopModifiers::kNone);
bool autoSelectLayer = Preferences::instance().editor.autoSelectLayer();
KeyAction action;
if (m_customizationDelegate) {
// When the mouse is captured, is when we are scrolling, or
// drawing, or moving, or selecting, etc. So several
// parameters/tool-loop-modifiers are static.
if (hasCapture()) {
modifiers |= (int(m_toolLoopModifiers) &
(int(tools::ToolLoopModifiers::kReplaceSelection) |
int(tools::ToolLoopModifiers::kAddSelection) |
int(tools::ToolLoopModifiers::kSubtractSelection)));
autoSelectLayer = m_autoSelectLayer;
// Shape tools (line, curves, rectangles, etc.)
action = m_customizationDelegate->getPressedKeyAction(KeyContext::ShapeTool);
if (int(action & KeyAction::MoveOrigin))
modifiers |= int(tools::ToolLoopModifiers::kMoveOrigin);
if (int(action & KeyAction::SquareAspect))
modifiers |= int(tools::ToolLoopModifiers::kSquareAspect);
if (int(action & KeyAction::DrawFromCenter))
modifiers |= int(tools::ToolLoopModifiers::kFromCenter);
}
else {
// We update the selection mode only if we're not selecting.
action = m_customizationDelegate->getPressedKeyAction(KeyContext::SelectionTool);
gen::SelectionMode mode = Preferences::instance().selection.mode();
if (int(action & KeyAction::AddSelection))
mode = gen::SelectionMode::ADD;
if (int(action & KeyAction::SubtractSelection) || m_secondaryButton)
mode = gen::SelectionMode::SUBTRACT;
switch (mode) {
case gen::SelectionMode::DEFAULT: modifiers |= int(tools::ToolLoopModifiers::kReplaceSelection); break;
case gen::SelectionMode::ADD: modifiers |= int(tools::ToolLoopModifiers::kAddSelection); break;
case gen::SelectionMode::SUBTRACT: modifiers |= int(tools::ToolLoopModifiers::kSubtractSelection); break;
}
// For move tool
action = m_customizationDelegate->getPressedKeyAction(KeyContext::MoveTool);
if (int(action & KeyAction::AutoSelectLayer))
autoSelectLayer = true;
}
}
ContextBar* ctxBar = App::instance()->getMainWindow()->getContextBar();
// Selection mode
if (int(m_toolLoopModifiers) != modifiers) {
m_toolLoopModifiers = tools::ToolLoopModifiers(modifiers);
tools::SelectionMode mode = Preferences::instance().selection.mode();
// TODO the contextbar should be a observer of the current editor
ctxBar->updateToolLoopModifiersIndicators(m_toolLoopModifiers);
KeyAction action = KeyAction::None;
if (m_customizationDelegate)
action = m_customizationDelegate->getPressedKeyAction(KeyContext::SelectionTool);
if (int(action & KeyAction::AddSelection))
mode = tools::SelectionMode::ADD;
if (int(action & KeyAction::SubtractSelection))
mode = tools::SelectionMode::SUBTRACT;
else if (m_secondaryButton)
mode = tools::SelectionMode::SUBTRACT;
if (mode != m_selectionMode) {
m_selectionMode = mode;
ctxBar->updateSelectionMode(mode);
if (auto drawingState = dynamic_cast<DrawingState*>(m_state.get())) {
drawingState->notifyToolLoopModifiersChange(this);
}
}
// Move tool options
bool autoSelectLayer = Preferences::instance().editor.autoSelectLayer();
if ((m_customizationDelegate) &&
int(m_customizationDelegate->getPressedKeyAction(KeyContext::MoveTool) & KeyAction::AutoSelectLayer))
autoSelectLayer = true;
if (m_autoSelectLayer != autoSelectLayer) {
m_autoSelectLayer = autoSelectLayer;
ctxBar->updateAutoSelectLayer(autoSelectLayer);
@ -1238,7 +1264,7 @@ bool Editor::onProcessMessage(Message* msg)
case kMouseEnterMessage:
updateQuicktool();
updateContextBarFromModifiers();
updateToolLoopModifiersIndicators();
break;
case kMouseLeaveMessage:
@ -1255,7 +1281,7 @@ bool Editor::onProcessMessage(Message* msg)
m_secondaryButton = mouseMsg->right();
updateQuicktool();
updateContextBarFromModifiers();
updateToolLoopModifiersIndicators();
setCursor(mouseMsg->position());
}
@ -1281,7 +1307,7 @@ bool Editor::onProcessMessage(Message* msg)
m_secondaryButton = false;
updateQuicktool();
updateContextBarFromModifiers();
updateToolLoopModifiersIndicators();
setCursor(mouseMsg->position());
}
@ -1314,9 +1340,9 @@ bool Editor::onProcessMessage(Message* msg)
if (hasMouse()) {
updateQuicktool();
updateContextBarFromModifiers();
setCursor(ui::get_mouse_position());
}
updateToolLoopModifiersIndicators();
if (used)
return true;
@ -1330,9 +1356,9 @@ bool Editor::onProcessMessage(Message* msg)
if (hasMouse()) {
updateQuicktool();
updateContextBarFromModifiers();
setCursor(ui::get_mouse_position());
}
updateToolLoopModifiersIndicators();
if (used)
return true;
@ -1481,7 +1507,7 @@ bool Editor::isInsideSelection()
{
gfx::Point spritePos = screenToEditor(ui::get_mouse_position());
return
(m_selectionMode != tools::SelectionMode::SUBTRACT) &&
((int(m_toolLoopModifiers) & int(tools::ToolLoopModifiers::kSubtractSelection)) == 0) &&
m_document != NULL &&
m_document->isMaskVisible() &&
m_document->mask()->containsPoint(spritePos.x, spritePos.y);

View File

@ -13,7 +13,7 @@
#include "app/color.h"
#include "app/document.h"
#include "app/pref/preferences.h"
#include "app/tools/selection_mode.h"
#include "app/tools/tool_loop_modifiers.h"
#include "app/ui/color_source.h"
#include "app/ui/editor/brush_preview.h"
#include "app/ui/editor/editor_observers.h"
@ -173,9 +173,8 @@ namespace app {
tools::Tool* getCurrentEditorTool();
tools::Ink* getCurrentEditorInk();
tools::SelectionMode getSelectionMode() const { return m_selectionMode; }
tools::ToolLoopModifiers getToolLoopModifiers() const { return m_toolLoopModifiers; }
bool isAutoSelectLayer() const { return m_autoSelectLayer; }
bool isSecondaryButton() const { return m_secondaryButton; }
gfx::Point lastDrawingPosition() const { return m_lastDrawingPosition; }
@ -241,7 +240,7 @@ namespace app {
private:
void setStateInternal(const EditorStatePtr& newState);
void updateQuicktool();
void updateContextBarFromModifiers();
void updateToolLoopModifiersIndicators();
bool isCurrentToolAffectedByRightClickMode();
void drawMaskSafe();
@ -288,7 +287,7 @@ namespace app {
// the user is not pressing any keyboard key).
tools::Tool* m_quicktool;
tools::SelectionMode m_selectionMode;
tools::ToolLoopModifiers m_toolLoopModifiers;
bool m_autoSelectLayer;
// Extra space around the sprite.

View File

@ -350,14 +350,10 @@ bool StandbyState::onDoubleClick(Editor* editor, MouseMessage* msg)
CommandsModule::instance()->getCommandByName(CommandId::SelectTile);
Params params;
switch (editor->getSelectionMode()) {
case tools::SelectionMode::ADD:
params.set("mode", "add");
break;
case tools::SelectionMode::SUBTRACT:
params.set("mode", "subtract");
break;
}
if (int(editor->getToolLoopModifiers()) & int(tools::ToolLoopModifiers::kAddSelection))
params.set("mode", "add");
else if (int(editor->getToolLoopModifiers()) & int(tools::ToolLoopModifiers::kSubtractSelection))
params.set("mode", "subtract");
UIContext::instance()->executeCommand(selectTileCmd, params);
return true;

View File

@ -203,7 +203,7 @@ public:
int getOpacity() override { return m_opacity; }
int getTolerance() override { return m_tolerance; }
bool getContiguous() override { return m_contiguous; }
tools::SelectionMode getSelectionMode() override { return m_editor->getSelectionMode(); }
tools::ToolLoopModifiers getModifiers() override { return m_editor->getToolLoopModifiers(); }
filters::TiledMode getTiledMode() override { return m_docPref.tiled.mode(); }
bool getGridVisible() override { return m_docPref.show.grid(); }
bool getSnapToGrid() override { return m_docPref.grid.snap(); }
@ -324,7 +324,7 @@ public:
// Start with an empty mask if the user is selecting with "default selection mode"
if (getInk()->isSelection() &&
(!m_document->isMaskVisible() ||
getSelectionMode() == tools::SelectionMode::DEFAULT)) {
(int(getModifiers()) & int(tools::ToolLoopModifiers::kReplaceSelection)))) {
Mask emptyMask;
m_transaction.execute(new cmd::SetMask(m_document, &emptyMask));
}

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -42,8 +42,11 @@ namespace {
{ "LockAxis" , "Lock Axis" , app::KeyAction::LockAxis },
{ "AddSelection" , "Add Selection" , app::KeyAction::AddSelection },
{ "SubtractSelection" , "Subtract Selection" , app::KeyAction::SubtractSelection },
{ "AutoSelectLayer" , "Auto Select Layer" , app::KeyAction::AutoSelectLayer },
{ "AutoSelectLayer" , "Auto Select Layer" , app::KeyAction::AutoSelectLayer },
{ "StraightLineFromLastPoint", "Straight Line from Last Point", app::KeyAction::StraightLineFromLastPoint },
{ "MoveOrigin" , "Move Origin" , app::KeyAction::MoveOrigin },
{ "SquareAspect" , "Square Aspect" , app::KeyAction::SquareAspect },
{ "DrawFromCenter" , "Draw From Center" , app::KeyAction::DrawFromCenter },
{ "LeftMouseButton" , "Trigger Left Mouse Button" , app::KeyAction::LeftMouseButton },
{ "RightMouseButton" , "Trigger Right Mouse Button" , app::KeyAction::RightMouseButton },
{ NULL , NULL , app::KeyAction::None }
@ -136,9 +139,8 @@ Key::Key(KeyAction action)
m_keycontext = KeyContext::Any;
break;
case KeyAction::CopySelection:
m_keycontext = KeyContext::TranslatingSelection;
break;
case KeyAction::SnapToGrid:
case KeyAction::LockAxis:
m_keycontext = KeyContext::TranslatingSelection;
break;
case KeyAction::AngleSnap:
@ -147,12 +149,7 @@ Key::Key(KeyAction action)
case KeyAction::MaintainAspectRatio:
m_keycontext = KeyContext::ScalingSelection;
break;
case KeyAction::LockAxis:
m_keycontext = KeyContext::TranslatingSelection;
break;
case KeyAction::AddSelection:
m_keycontext = KeyContext::SelectionTool;
break;
case KeyAction::SubtractSelection:
m_keycontext = KeyContext::SelectionTool;
break;
@ -162,6 +159,11 @@ Key::Key(KeyAction action)
case KeyAction::StraightLineFromLastPoint:
m_keycontext = KeyContext::FreehandTool;
break;
case KeyAction::MoveOrigin:
case KeyAction::SquareAspect:
case KeyAction::DrawFromCenter:
m_keycontext = KeyContext::ShapeTool;
break;
case KeyAction::LeftMouseButton:
m_keycontext = KeyContext::Any;
break;
@ -538,6 +540,9 @@ void KeyboardShortcuts::exportAccel(TiXmlElement& parent, Key* key, const ui::Ac
case KeyContext::FreehandTool:
keycontextStr = "FreehandTool";
break;
case KeyContext::ShapeTool:
keycontextStr = "ShapeTool";
break;
}
if (keycontextStr)

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2001-2015 David Capello
// Copyright (C) 2001-2016 David Capello
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
@ -39,6 +39,7 @@ namespace app {
RotatingSelection,
MoveTool,
FreehandTool,
ShapeTool,
};
enum class KeySource {
@ -66,7 +67,10 @@ namespace app {
AutoSelectLayer = 0x00000080,
LeftMouseButton = 0x00000100,
RightMouseButton = 0x00000200,
StraightLineFromLastPoint = 0x00000400
StraightLineFromLastPoint = 0x00000400,
MoveOrigin = 0x00000800,
SquareAspect = 0x00001000,
DrawFromCenter = 0x00002000,
};
inline KeyAction operator&(KeyAction a, KeyAction b) {