Add "Auto Select Layer" check box to Move Tool (close #527)

This commit is contained in:
David Capello 2014-11-16 18:33:31 -03:00
parent 7b4cd3e136
commit c64ee5729b
19 changed files with 190 additions and 12 deletions

View File

@ -344,7 +344,7 @@
tool without changing the current one -->
<quicktools>
<key tool="eyedropper" shortcut="Alt" />
<key tool="move" shortcut="Ctrl" />
<key tool="move" shortcut="Ctrl" mac="Cmd" />
<key tool="hand" shortcut="Space" />
</quicktools>
@ -373,6 +373,9 @@
<!-- Modifiers for selection tool -->
<key action="AddSelection" shortcut="Shift" />
<key action="SubtractSelection" shortcut="Alt" />
<!-- Modifiers for move tool -->
<key action="AutoSelectLayer" shortcut="Ctrl" mac="Cmd" />
</actions>
</keyboard>
@ -782,6 +785,9 @@
ink="scroll"
controller="freehand"
/>
</group>
<group id="move_tools" text="Move Tools">
<tool id="move"
text="Move Tool"
ink="move"

View File

@ -24,6 +24,7 @@
#include "app/document_location.h"
#include "gfx/point.h"
#include "raster/cel.h"
#include "raster/image.h"
#include "raster/primitives.h"
#include "raster/sprite.h"
@ -32,6 +33,7 @@ namespace app {
ColorPicker::ColorPicker()
: m_alpha(0)
, m_layer(NULL)
{
}
@ -45,6 +47,11 @@ void ColorPicker::pickColor(const DocumentLocation& location, int x, int y, Mode
m_color = app::Color::fromImage(
location.sprite()->pixelFormat(),
location.sprite()->getPixel(x, y, location.frame()));
raster::CelList cels;
location.sprite()->pickCels(x, y, location.frame(), 128, cels);
if (!cels.empty())
m_layer = cels.front()->layer();
}
else { // Pick from the current layer
int u, v;
@ -64,6 +71,7 @@ void ColorPicker::pickColor(const DocumentLocation& location, int x, int y, Mode
}
m_color = app::Color::fromImage(image->pixelFormat(), imageColor);
m_layer = const_cast<Layer*>(location.layer());
}
}
}

View File

@ -21,6 +21,7 @@
#pragma once
#include "app/color.h"
#include "raster/layer.h"
namespace app {
class DocumentLocation;
@ -35,10 +36,12 @@ namespace app {
app::Color color() const { return m_color; }
int alpha() const { return m_alpha; }
raster::Layer* layer() const { return m_layer; }
private:
app::Color m_color;
int m_alpha;
raster::Layer* m_layer;
};
} // namespace app

View File

@ -367,6 +367,9 @@ private:
case KeyContext::MovingPixels:
text = "Moving pixels context: " + text;
break;
case KeyContext::MoveTool:
text = "Move tool: " + text;
break;
}
KeyItem* keyItem = new KeyItem(text, key, NULL, 0);

View File

@ -68,6 +68,7 @@ namespace app {
virtual bool getShowSpriteEditorScrollbars() = 0;
virtual RightClickMode getRightClickMode() = 0;
virtual bool getGrabAlpha() = 0;
virtual bool getAutoSelectLayer() = 0;
virtual app::Color getFgColor() = 0;
virtual app::Color getBgColor() = 0;
virtual tools::Tool* getCurrentTool() = 0;
@ -77,6 +78,7 @@ namespace app {
virtual void setShowSpriteEditorScrollbars(bool state) = 0;
virtual void setRightClickMode(RightClickMode mode) = 0;
virtual void setGrabAlpha(bool state) = 0;
virtual void setAutoSelectLayer(bool state) = 0;
virtual void setFgColor(const app::Color& color) = 0;
virtual void setBgColor(const app::Color& color) = 0;
virtual void setCurrentTool(tools::Tool* tool) = 0;

View File

@ -75,6 +75,7 @@ namespace app {
virtual void onSetShowSpriteEditorScrollbars(bool state) {}
virtual void onSetGrabAlpha(bool state) {}
virtual void onSetAutoSelectLayer(bool state) {}
virtual void onSetFgColor(app::Color newColor) {}
virtual void onSetBgColor(app::Color newColor) {}
virtual void onSetCurrentTool(tools::Tool* newTool) {}

View File

@ -287,6 +287,7 @@ UISettingsImpl::UISettingsImpl()
, m_zoomWithScrollWheel(get_config_bool("Options", "ZoomWithMouseWheel", true))
, m_showSpriteEditorScrollbars(get_config_bool("Options", "ShowScrollbars", true))
, m_grabAlpha(get_config_bool("Options", "GrabAlpha", false))
, m_autoSelectLayer(get_config_bool("Options", "AutoSelectLayer", false))
, m_rightClickMode(static_cast<RightClickMode>(get_config_int("Options", "RightClickMode",
static_cast<int>(RightClickMode::Default))))
{
@ -302,6 +303,7 @@ UISettingsImpl::~UISettingsImpl()
set_config_bool("Options", "ZoomWithMouseWheel", m_zoomWithScrollWheel);
set_config_bool("Options", "ShowScrollbars", m_showSpriteEditorScrollbars);
set_config_bool("Options", "GrabAlpha", m_grabAlpha);
set_config_bool("Options", "AutoSelectLayer", m_autoSelectLayer);
set_config_int("Options", "RightClickMode", static_cast<int>(m_rightClickMode));
for (auto it : m_docSettings)
@ -366,6 +368,11 @@ bool UISettingsImpl::getGrabAlpha()
return m_grabAlpha;
}
bool UISettingsImpl::getAutoSelectLayer()
{
return m_autoSelectLayer;
}
app::Color UISettingsImpl::getFgColor()
{
return ColorBar::instance()->getFgColor();
@ -413,6 +420,13 @@ void UISettingsImpl::setGrabAlpha(bool state)
notifyObservers<bool>(&GlobalSettingsObserver::onSetGrabAlpha, state);
}
void UISettingsImpl::setAutoSelectLayer(bool state)
{
m_autoSelectLayer = state;
notifyObservers<bool>(&GlobalSettingsObserver::onSetAutoSelectLayer, state);
}
void UISettingsImpl::setFgColor(const app::Color& color)
{
ColorBar::instance()->setFgColor(color);

View File

@ -57,6 +57,7 @@ namespace app {
bool getShowSpriteEditorScrollbars() override;
RightClickMode getRightClickMode() override;
bool getGrabAlpha() override;
bool getAutoSelectLayer() override;
app::Color getFgColor() override;
app::Color getBgColor() override;
tools::Tool* getCurrentTool() override;
@ -66,6 +67,7 @@ namespace app {
void setShowSpriteEditorScrollbars(bool state) override;
void setRightClickMode(RightClickMode mode) override;
void setGrabAlpha(bool state) override;
void setAutoSelectLayer(bool state) override;
void setFgColor(const app::Color& color) override;
void setBgColor(const app::Color& color) override;
void setCurrentTool(tools::Tool* tool) override;
@ -103,6 +105,7 @@ namespace app {
bool m_zoomWithScrollWheel;
bool m_showSpriteEditorScrollbars;
bool m_grabAlpha;
bool m_autoSelectLayer;
RightClickMode m_rightClickMode;
std::map<doc::ObjectId, IDocumentSettings*> m_docSettings;
};

View File

@ -721,6 +721,23 @@ protected:
}
};
class ContextBar::AutoSelectLayerField : public CheckBox
{
public:
AutoSelectLayerField() : CheckBox("Auto Select Layer") {
setup_mini_font(this);
}
protected:
void onClick(Event& ev) override {
CheckBox::onClick(ev);
UIContext::instance()->settings()->setAutoSelectLayer(isSelected());
releaseFocus();
}
};
ContextBar::ContextBar()
: Box(JI_HORIZONTAL)
, m_toolSettings(NULL)
@ -751,6 +768,8 @@ ContextBar::ContextBar()
addChild(m_grabAlpha = new GrabAlphaField());
addChild(m_autoSelectLayer = new AutoSelectLayerField());
// addChild(new InkChannelTargetField());
// addChild(new InkShadeField());
// addChild(new InkSelectionField());
@ -878,6 +897,7 @@ void ContextBar::updateFromTool(tools::Tool* tool)
m_inkOpacity->setTextf("%d", toolSettings->getOpacity());
m_grabAlpha->setSelected(settings->getGrabAlpha());
m_autoSelectLayer->setSelected(settings->getAutoSelectLayer());
m_freehandAlgo->setFreehandAlgorithm(toolSettings->getFreehandAlgorithm());
m_sprayWidth->setValue(toolSettings->getSprayWidth());
@ -894,6 +914,11 @@ void ContextBar::updateFromTool(tools::Tool* tool)
(tool->getInk(0)->isEyedropper() ||
tool->getInk(1)->isEyedropper());
// True if the current tool is move tool.
bool isMove =
(tool->getInk(0)->isCelMovement() ||
tool->getInk(1)->isCelMovement());
// True if it makes sense to change the ink property for the current
// tool.
bool hasInk = hasOpacity;
@ -921,6 +946,7 @@ void ContextBar::updateFromTool(tools::Tool* tool)
m_inkType->setVisible(hasInk);
m_inkOpacity->setVisible(hasOpacity);
m_grabAlpha->setVisible(isEyedropper);
m_autoSelectLayer->setVisible(isMove);
m_freehandBox->setVisible(isFreehand && hasOpacity);
m_toleranceLabel->setVisible(hasTolerance);
m_tolerance->setVisible(hasTolerance);
@ -946,7 +972,7 @@ void ContextBar::updateForMovingPixels()
layout();
}
void ContextBar::updateForSelectionMode(SelectionMode mode)
void ContextBar::updateSelectionMode(SelectionMode mode)
{
if (!m_selectionMode->isVisible())
return;
@ -954,4 +980,12 @@ void ContextBar::updateForSelectionMode(SelectionMode mode)
m_selectionMode->setSelectionMode(mode);
}
void ContextBar::updateAutoSelectLayer(bool state)
{
if (!m_autoSelectLayer->isVisible())
return;
m_autoSelectLayer->setSelected(state);
}
} // namespace app

View File

@ -47,7 +47,8 @@ namespace app {
void updateFromTool(tools::Tool* tool);
void updateForMovingPixels();
void updateForSelectionMode(SelectionMode mode);
void updateSelectionMode(SelectionMode mode);
void updateAutoSelectLayer(bool state);
protected:
bool onProcessMessage(ui::Message* msg) override;
@ -77,6 +78,7 @@ namespace app {
class FreehandAlgorithmField;
class GrabAlphaField;
class DropPixelsField;
class AutoSelectLayerField;
IToolSettings* m_toolSettings;
BrushTypeField* m_brushType;
@ -89,6 +91,7 @@ namespace app {
ui::Label* m_opacityLabel;
InkOpacityField* m_inkOpacity;
GrabAlphaField* m_grabAlpha;
AutoSelectLayerField* m_autoSelectLayer;
ui::Box* m_freehandBox;
FreehandAlgorithmField* m_freehandAlgo;
ui::Box* m_sprayBox;

View File

@ -110,6 +110,10 @@ public:
return isKeyActionPressed(KeyAction::SubtractSelection);
}
bool isAutoSelectLayerPressed() override {
return isKeyActionPressed(KeyAction::AutoSelectLayer);
}
protected:
bool onProcessMessage(Message* msg) override {
switch (msg->type()) {

View File

@ -1047,12 +1047,16 @@ void Editor::updateQuicktool()
}
}
void Editor::updateSelectionMode()
void Editor::updateContextBarFromModifiers()
{
// We update the selection mode only if we're not selecting.
if (hasCapture())
return;
ContextBar* ctxBar = App::instance()->getMainWindow()->getContextBar();
// Selection mode
SelectionMode mode = UIContext::instance()->settings()->selection()->getSelectionMode();
if (m_customizationDelegate && m_customizationDelegate->isAddSelectionPressed())
@ -1064,9 +1068,19 @@ void Editor::updateSelectionMode()
if (mode != m_selectionMode) {
m_selectionMode = mode;
ctxBar->updateSelectionMode(mode);
}
App::instance()->getMainWindow()->getContextBar()
->updateForSelectionMode(mode);
// Move tool options
bool autoSelectLayer = UIContext::instance()->settings()->getAutoSelectLayer();
if (m_customizationDelegate && m_customizationDelegate->isAutoSelectLayerPressed())
autoSelectLayer = true;
if (m_autoSelectLayer != autoSelectLayer) {
m_autoSelectLayer = autoSelectLayer;
ctxBar->updateAutoSelectLayer(autoSelectLayer);
}
}
@ -1096,7 +1110,7 @@ bool Editor::onProcessMessage(Message* msg)
case kMouseEnterMessage:
updateQuicktool();
updateSelectionMode();
updateContextBarFromModifiers();
break;
case kMouseLeaveMessage:
@ -1113,7 +1127,7 @@ bool Editor::onProcessMessage(Message* msg)
m_secondaryButton = mouseMsg->right();
updateQuicktool();
updateSelectionMode();
updateContextBarFromModifiers();
editor_setcursor();
}
@ -1138,7 +1152,7 @@ bool Editor::onProcessMessage(Message* msg)
m_secondaryButton = false;
updateQuicktool();
updateSelectionMode();
updateContextBarFromModifiers();
editor_setcursor();
}
@ -1154,7 +1168,7 @@ bool Editor::onProcessMessage(Message* msg)
if (hasMouse()) {
updateQuicktool();
updateSelectionMode();
updateContextBarFromModifiers();
editor_setcursor();
}
@ -1170,7 +1184,7 @@ bool Editor::onProcessMessage(Message* msg)
if (hasMouse()) {
updateQuicktool();
updateSelectionMode();
updateContextBarFromModifiers();
editor_setcursor();
}

View File

@ -177,6 +177,7 @@ namespace app {
tools::Ink* getCurrentEditorInk();
SelectionMode getSelectionMode() const { return m_selectionMode; }
bool isAutoSelectLayer() const { return m_autoSelectLayer; }
bool isSecondaryButton() const { return m_secondaryButton; }
@ -219,7 +220,7 @@ namespace app {
private:
void setStateInternal(const EditorStatePtr& newState);
void updateQuicktool();
void updateSelectionMode();
void updateContextBarFromModifiers();
void drawBrushPreview(int x, int y, bool refresh = true);
void moveBrushPreview(int x, int y, bool refresh = true);
void clearBrushPreview(bool refresh = true);
@ -272,6 +273,7 @@ namespace app {
tools::Tool* m_quicktool;
SelectionMode m_selectionMode;
bool m_autoSelectLayer;
// Offset for the sprite
int m_offset_x;

View File

@ -60,6 +60,8 @@ namespace app {
virtual bool isAddSelectionPressed() = 0;
virtual bool isSubtractSelectionPressed() = 0;
virtual bool isAutoSelectLayerPressed() = 0;
};
} // namespace app

View File

@ -176,6 +176,26 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
// Move cel X,Y coordinates
if (clickedInk->isCelMovement()) {
// Handle "Auto Select Layer"
if (editor->isAutoSelectLayer()) {
ColorPicker picker;
int x, y;
editor->screenToEditor(
msg->position().x,
msg->position().y, &x, &y);
picker.pickColor(location, x, y, ColorPicker::FromComposition);
if (layer != picker.layer()) {
layer = picker.layer();
if (layer) {
editor->setLayer(layer);
editor->flashCurrentLayer();
}
}
}
if ((layer) &&
(layer->type() == OBJECT_LAYER_IMAGE)) {
// TODO you can move the `Background' with tiled mode
@ -192,6 +212,7 @@ bool StandbyState::onMouseDown(Editor* editor, MouseMessage* msg)
editor->setState(EditorStatePtr(new MovingCelState(editor, msg)));
}
}
return true;
}

View File

@ -55,6 +55,7 @@ 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 },
{ "LeftMouseButton" , "Trigger Left Mouse Button" , app::KeyAction::LeftMouseButton },
{ "RightMouseButton" , "Trigger Right Mouse Button" , app::KeyAction::RightMouseButton },
{ NULL , NULL , app::KeyAction::None }
@ -174,6 +175,9 @@ Key::Key(KeyAction action)
case KeyAction::SubtractSelection:
m_keycontext = KeyContext::Selection;
break;
case KeyAction::AutoSelectLayer:
m_keycontext = KeyContext::MoveTool;
break;
case KeyAction::LeftMouseButton:
m_keycontext = KeyContext::Any;
break;
@ -532,6 +536,9 @@ void KeyboardShortcuts::exportAccel(TiXmlElement& parent, Key* key, const ui::Ac
case KeyContext::MovingPixels:
keycontextStr = "MovingPixels";
break;
case KeyContext::MoveTool:
keycontextStr = "MoveTool";
break;
}
if (keycontextStr)

View File

@ -45,6 +45,7 @@ namespace app {
Normal,
Selection,
MovingPixels,
MoveTool,
};
enum class KeySource {
@ -68,6 +69,7 @@ namespace app {
LockAxis,
AddSelection,
SubtractSelection,
AutoSelectLayer,
LeftMouseButton,
RightMouseButton
};

View File

@ -491,6 +491,53 @@ int Sprite::getPixel(int x, int y, FrameNumber frame) const
return color;
}
void Sprite::pickCels(int x, int y, FrameNumber frame, int opacityThreshold, CelList& cels) const
{
std::vector<Layer*> layers;
getLayersList(layers);
for (int i=(int)layers.size()-1; i>=0; --i) {
Layer* layer = layers[i];
if (!layer->isImage())
continue;
Cel* cel = static_cast<LayerImage*>(layer)->getCel(frame);
if (!cel)
continue;
Image* image = cel->image();
if (!image)
continue;
if (!cel->bounds().contains(gfx::Point(x, y)))
continue;
color_t color = get_pixel(image,
x - cel->x(),
y - cel->y());
bool isOpaque = true;
switch (image->pixelFormat()) {
case IMAGE_RGB:
isOpaque = (rgba_geta(color) >= opacityThreshold);
break;
case IMAGE_INDEXED:
isOpaque = (color != image->maskColor());
break;
case IMAGE_GRAYSCALE:
isOpaque = (graya_geta(color) >= opacityThreshold);
break;
}
if (!isOpaque)
continue;
cels.push_back(cel);
}
fflush(stdout);
}
//////////////////////////////////////////////////////////////////////
static Layer* index2layer(const Layer* layer, const LayerIndex& index, int* index_count)

View File

@ -144,6 +144,8 @@ namespace raster {
// return the 0 color (the mask-color).
int getPixel(int x, int y, FrameNumber frame) const;
void pickCels(int x, int y, FrameNumber frame, int opacityThreshold, CelList& cels) const;
private:
Sprite* m_self; // pointer to the Sprite
PixelFormat m_format; // pixel format