mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-21 07:20:46 +00:00
Add "intersect" selection mode
Discussions: https://community.aseprite.org/t/intersectional-selection/801 https://community.aseprite.org/t/feature-request-intersect-with-selection-tool/1797
This commit is contained in:
parent
b27c685d70
commit
3a77321597
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@ -244,6 +244,7 @@
|
||||
<part id="selection_replace" x="176" y="160" w="7" h="7" />
|
||||
<part id="selection_add" x="184" y="160" w="7" h="7" />
|
||||
<part id="selection_subtract" x="192" y="160" w="7" h="7" />
|
||||
<part id="selection_intersect" x="200" y="160" w="7" h="7" />
|
||||
<part id="unpinned" x="192" y="144" w="8" h="8" />
|
||||
<part id="pinned" x="200" y="144" w="8" h="8" />
|
||||
<part id="drop_down_button_left_normal" x="48" y="32" w1="3" w2="2" w3="3" h1="4" h2="6" h3="6" />
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Aseprite -->
|
||||
<!-- Copyright (C) 2001-2018 by David Capello -->
|
||||
<!-- Copyright (C) 2018 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2001-2018 David Capello -->
|
||||
<gui version="1.3-dev">
|
||||
<!-- Keyboard shortcuts -->
|
||||
<keyboard version="1">
|
||||
@ -449,6 +450,9 @@
|
||||
<key command="SelectTile">
|
||||
<param name="mode" value="subtract" />
|
||||
</key>
|
||||
<key command="SelectTile">
|
||||
<param name="mode" value="intersect" />
|
||||
</key>
|
||||
<key command="ChangePixelFormat">
|
||||
<param name="format" value="rgb" />
|
||||
</key>
|
||||
@ -543,7 +547,8 @@
|
||||
|
||||
<!-- Modifiers for selection tool -->
|
||||
<key action="AddSelection" shortcut="Shift" />
|
||||
<key action="SubtractSelection" shortcut="Shift+Alt" />
|
||||
<key action="SubtractSelection" shortcut="Alt+Shift" />
|
||||
<key action="IntersectSelection" shortcut="Ctrl+Shift" />
|
||||
|
||||
<!-- Modifiers for move tool -->
|
||||
<key action="AutoSelectLayer" shortcut="Ctrl" mac="Cmd" />
|
||||
|
@ -68,6 +68,7 @@
|
||||
<value id="DEFAULT" value="0" />
|
||||
<value id="ADD" value="1" />
|
||||
<value id="SUBTRACT" value="2" />
|
||||
<value id="INTERSECT" value="3" />
|
||||
</enum>
|
||||
<enum id="PivotPosition">
|
||||
<value id="NORTHWEST" value="0" />
|
||||
|
@ -380,6 +380,7 @@ ScrollCenter = Scroll to center of canvas
|
||||
SelectTile = Select Tile
|
||||
SelectTile_Add = Select Tile (Add)
|
||||
SelectTile_Subtract = Select Tile (Subtract)
|
||||
SelectTile_Intersect = Select Tile (Intersect)
|
||||
SelectionAsGrid = Selection as Grid
|
||||
SetColorSelector = Set Color Selector
|
||||
SetColorSelector_Spectrum = Color Spectrum
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2015-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -55,6 +56,8 @@ void SelectTileCommand::onLoadParams(const Params& params)
|
||||
m_mode = gen::SelectionMode::ADD;
|
||||
else if (mode == "subtract")
|
||||
m_mode = gen::SelectionMode::SUBTRACT;
|
||||
else if (mode == "intersect")
|
||||
m_mode = gen::SelectionMode::INTERSECT;
|
||||
else
|
||||
m_mode = gen::SelectionMode::DEFAULT;
|
||||
}
|
||||
@ -86,10 +89,18 @@ void SelectTileCommand::onExecute(Context* ctx)
|
||||
pos = snap_to_grid(gridBounds, pos, PreferSnapTo::BoxOrigin);
|
||||
gridBounds.setOrigin(pos);
|
||||
|
||||
if (m_mode != gen::SelectionMode::SUBTRACT)
|
||||
mask->add(gridBounds);
|
||||
else
|
||||
mask->subtract(gridBounds);
|
||||
switch (m_mode) {
|
||||
case gen::SelectionMode::DEFAULT:
|
||||
case gen::SelectionMode::ADD:
|
||||
mask->add(gridBounds);
|
||||
break;
|
||||
case gen::SelectionMode::SUBTRACT:
|
||||
mask->subtract(gridBounds);
|
||||
break;
|
||||
case gen::SelectionMode::INTERSECT:
|
||||
mask->intersect(gridBounds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new mask
|
||||
@ -113,8 +124,11 @@ std::string SelectTileCommand::onGetFriendlyName() const
|
||||
case gen::SelectionMode::SUBTRACT:
|
||||
text = Strings::commands_SelectTile_Subtract();
|
||||
break;
|
||||
case gen::SelectionMode::INTERSECT:
|
||||
text = Strings::commands_SelectTile_Intersect();
|
||||
break;
|
||||
default:
|
||||
text = getBaseFriendlyName();;
|
||||
text = getBaseFriendlyName();
|
||||
break;
|
||||
}
|
||||
return text;
|
||||
|
@ -362,6 +362,7 @@ public:
|
||||
class SelectionInk : public BaseInk {
|
||||
bool m_modify_selection;
|
||||
Mask m_mask;
|
||||
Mask m_intersectMask;
|
||||
Rect m_maxBounds;
|
||||
|
||||
public:
|
||||
@ -390,6 +391,9 @@ public:
|
||||
else if ((modifiers & int(ToolLoopModifiers::kSubtractSelection)) != 0) {
|
||||
m_mask.subtract(gfx::Rect(x1, y, x2-x1+1, 1));
|
||||
}
|
||||
else if ((modifiers & int(ToolLoopModifiers::kIntersectSelection)) != 0) {
|
||||
m_intersectMask.add(gfx::Rect(x1, y, x2-x1+1, 1));
|
||||
}
|
||||
|
||||
m_maxBounds |= gfx::Rect(x1, y, x2-x1+1, 1);
|
||||
}
|
||||
@ -409,6 +413,11 @@ public:
|
||||
m_mask.reserve(loop->sprite()->bounds());
|
||||
}
|
||||
else {
|
||||
int modifiers = int(loop->getModifiers());
|
||||
if ((modifiers & int(ToolLoopModifiers::kIntersectSelection)) != 0) {
|
||||
m_mask.intersect(m_intersectMask);
|
||||
}
|
||||
|
||||
// We can intersect the used bounds in inkHline() calls to
|
||||
// reduce the shrink computation.
|
||||
m_mask.intersect(m_maxBounds);
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -16,10 +17,11 @@ namespace tools {
|
||||
kReplaceSelection = 0x00000001,
|
||||
kAddSelection = 0x00000002,
|
||||
kSubtractSelection = 0x00000004,
|
||||
kMoveOrigin = 0x00000008,
|
||||
kSquareAspect = 0x00000010,
|
||||
kFromCenter = 0x00000020,
|
||||
kRotateShape = 0x00000040,
|
||||
kIntersectSelection = 0x00000008,
|
||||
kMoveOrigin = 0x00000010,
|
||||
kSquareAspect = 0x00000020,
|
||||
kFromCenter = 0x00000040,
|
||||
kRotateShape = 0x00000080,
|
||||
};
|
||||
|
||||
} // namespace tools
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -926,12 +927,13 @@ protected:
|
||||
|
||||
class ContextBar::SelectionModeField : public ButtonSet {
|
||||
public:
|
||||
SelectionModeField() : ButtonSet(3) {
|
||||
SelectionModeField() : ButtonSet(4) {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||
|
||||
addItem(theme->parts.selectionReplace());
|
||||
addItem(theme->parts.selectionAdd());
|
||||
addItem(theme->parts.selectionSubtract());
|
||||
addItem(theme->parts.selectionIntersect());
|
||||
|
||||
setSelectedItem((int)Preferences::instance().selection.mode());
|
||||
}
|
||||
@ -945,6 +947,9 @@ public:
|
||||
|
||||
tooltipManager->addTooltipFor(
|
||||
at(2), key_tooltip("Subtract from selection", KeyAction::SubtractSelection), BOTTOM);
|
||||
|
||||
tooltipManager->addTooltipFor(
|
||||
at(3), key_tooltip("Intersect selection", KeyAction::IntersectSelection), BOTTOM);
|
||||
}
|
||||
|
||||
void setSelectionMode(gen::SelectionMode mode) {
|
||||
@ -1510,6 +1515,8 @@ void ContextBar::updateToolLoopModifiersIndicators(tools::ToolLoopModifiers modi
|
||||
mode = gen::SelectionMode::ADD;
|
||||
else if (int(modifiers) & int(tools::ToolLoopModifiers::kSubtractSelection))
|
||||
mode = gen::SelectionMode::SUBTRACT;
|
||||
else if (int(modifiers) & int(tools::ToolLoopModifiers::kIntersectSelection))
|
||||
mode = gen::SelectionMode::INTERSECT;
|
||||
|
||||
m_selectionMode->setSelectionMode(mode);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -153,7 +154,8 @@ bool DrawingState::onMouseUp(Editor* editor, MouseMessage* msg)
|
||||
if (!m_toolLoop->getInk()->isSelection() ||
|
||||
m_toolLoop->getController()->isOnePoint() ||
|
||||
m_mouseMoveReceived ||
|
||||
editor->getToolLoopModifiers() != tools::ToolLoopModifiers::kReplaceSelection) {
|
||||
(editor->getToolLoopModifiers() != tools::ToolLoopModifiers::kReplaceSelection &&
|
||||
editor->getToolLoopModifiers() != tools::ToolLoopModifiers::kIntersectSelection)) {
|
||||
// Notify the release of the mouse button to the tool loop
|
||||
// manager. This is the correct way to say "the user finishes the
|
||||
// drawing trace correctly".
|
||||
|
@ -1496,7 +1496,8 @@ void Editor::updateToolLoopModifiersIndicators()
|
||||
modifiers |= (int(m_toolLoopModifiers) &
|
||||
(int(tools::ToolLoopModifiers::kReplaceSelection) |
|
||||
int(tools::ToolLoopModifiers::kAddSelection) |
|
||||
int(tools::ToolLoopModifiers::kSubtractSelection)));
|
||||
int(tools::ToolLoopModifiers::kSubtractSelection) |
|
||||
int(tools::ToolLoopModifiers::kIntersectSelection)));
|
||||
|
||||
tools::Controller* controller =
|
||||
(App::instance()->activeToolManager()->selectedTool() ?
|
||||
@ -1535,13 +1536,17 @@ void Editor::updateToolLoopModifiersIndicators()
|
||||
App::instance()->activeToolManager()->selectedTool()->getInk(0)->isSelection())) {
|
||||
mode = gen::SelectionMode::SUBTRACT;
|
||||
}
|
||||
else if (int(action & KeyAction::IntersectSelection)) {
|
||||
mode = gen::SelectionMode::INTERSECT;
|
||||
}
|
||||
else if (int(action & KeyAction::AddSelection)) {
|
||||
mode = gen::SelectionMode::ADD;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
case gen::SelectionMode::INTERSECT: modifiers |= int(tools::ToolLoopModifiers::kIntersectSelection); break;
|
||||
}
|
||||
|
||||
// For move tool
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -386,6 +387,8 @@ bool StandbyState::onDoubleClick(Editor* editor, MouseMessage* msg)
|
||||
params.set("mode", "add");
|
||||
else if (int(editor->getToolLoopModifiers()) & int(tools::ToolLoopModifiers::kSubtractSelection))
|
||||
params.set("mode", "subtract");
|
||||
else if (int(editor->getToolLoopModifiers()) & int(tools::ToolLoopModifiers::kIntersectSelection))
|
||||
params.set("mode", "intersect");
|
||||
|
||||
UIContext::instance()->executeCommand(selectTileCmd, params);
|
||||
return true;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -51,16 +52,17 @@ namespace app {
|
||||
LockAxis = 0x00000010,
|
||||
AddSelection = 0x00000020,
|
||||
SubtractSelection = 0x00000040,
|
||||
AutoSelectLayer = 0x00000080,
|
||||
LeftMouseButton = 0x00000100,
|
||||
RightMouseButton = 0x00000200,
|
||||
StraightLineFromLastPoint = 0x00000400,
|
||||
MoveOrigin = 0x00000800,
|
||||
SquareAspect = 0x00001000,
|
||||
DrawFromCenter = 0x00002000,
|
||||
ScaleFromCenter = 0x00004000,
|
||||
AngleSnapFromLastPoint = 0x00008000,
|
||||
RotateShape = 0x00010000,
|
||||
IntersectSelection = 0x00000080,
|
||||
AutoSelectLayer = 0x00000100,
|
||||
LeftMouseButton = 0x00000200,
|
||||
RightMouseButton = 0x00000400,
|
||||
StraightLineFromLastPoint = 0x00000800,
|
||||
MoveOrigin = 0x00001000,
|
||||
SquareAspect = 0x00002000,
|
||||
DrawFromCenter = 0x00004000,
|
||||
ScaleFromCenter = 0x00008000,
|
||||
AngleSnapFromLastPoint = 0x00010000,
|
||||
RotateShape = 0x00020000,
|
||||
};
|
||||
|
||||
enum class WheelAction {
|
||||
|
@ -1,4 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -47,6 +48,7 @@ namespace {
|
||||
{ "LockAxis" , "Lock Axis" , app::KeyAction::LockAxis },
|
||||
{ "AddSelection" , "Add Selection" , app::KeyAction::AddSelection },
|
||||
{ "SubtractSelection" , "Subtract Selection" , app::KeyAction::SubtractSelection },
|
||||
{ "IntersectSelection" , "Intersect Selection" , app::KeyAction::IntersectSelection },
|
||||
{ "AutoSelectLayer" , "Auto Select Layer" , app::KeyAction::AutoSelectLayer },
|
||||
{ "StraightLineFromLastPoint", "Straight Line from Last Point", app::KeyAction::StraightLineFromLastPoint },
|
||||
{ "AngleSnapFromLastPoint", "Angle Snap from Last Point", app::KeyAction::AngleSnapFromLastPoint },
|
||||
@ -209,6 +211,7 @@ Key::Key(KeyAction action)
|
||||
break;
|
||||
case KeyAction::AddSelection:
|
||||
case KeyAction::SubtractSelection:
|
||||
case KeyAction::IntersectSelection:
|
||||
m_keycontext = KeyContext::SelectionTool;
|
||||
break;
|
||||
case KeyAction::AutoSelectLayer:
|
||||
|
Loading…
x
Reference in New Issue
Block a user