Add option to toggle the selection edges visibility (fix #861)

This commit is contained in:
David Capello 2016-03-24 13:04:35 -03:00
parent d4faf04946
commit 2af47fe907
9 changed files with 239 additions and 127 deletions

View File

@ -111,6 +111,7 @@
<key command="PaletteEditor" shortcut="F4">
<param name="switch" value="true" />
</key>
<key command="ShowExtras" shortcut="Ctrl+H" />
<!-- Tabs -->
<key command="GotoNextTab" shortcut="Ctrl+Tab" />
<key command="GotoPreviousTab" shortcut="Ctrl+Shift+Tab" />
@ -720,11 +721,18 @@
<menu text="&amp;View">
<item command="DuplicateView" text="Duplicate &amp;View" />
<separator />
<item command="ShowPixelGrid" text="Show &amp;Pixel Grid" />
<item command="ShowGrid" text="Show &amp;Grid" />
<item command="SnapToGrid" text="&amp;Snap to Grid" />
<item command="ShowExtras" text="&amp;Extras" />
<menu text="&amp;Show">
<item command="ShowSelectionEdges" text="&amp;Selection Edges" />
<item command="ShowGrid" text="&amp;Grid" />
<item command="ShowPixelGrid" text="&amp;Pixel Grid" />
</menu>
<separator />
<menu text="&amp;Grid">
<item command="GridSettings" text="Gri&amp;d Settings" />
<item command="SelectionAsGrid" text="Select&amp;ion as Grid" />
<item command="SnapToGrid" text="&amp;Snap to Grid" />
</menu>
<menu text="Tiled &amp;Mode">
<item command="TiledMode" text="&amp;None">
<param name="axis" value="none" />

View File

@ -220,14 +220,12 @@
</section>
<section id="grid">
<option id="snap" type="bool" default="false" migrate="Grid.SnapTo" />
<option id="visible" type="bool" default="false" migrate="Grid.Visible" />
<option id="bounds" type="gfx::Rect" default="gfx::Rect(0, 0, 16, 16)" migrate="Grid.Bounds" />
<option id="color" type="app::Color" default="app::Color::fromRgb(0, 0, 255)" migrate="Grid.Color" />
<option id="opacity" type="int" default="160" migrate="Grid.Opacity" />
<option id="auto_opacity" type="bool" default="true" migrate="Grid.AutoOpacity" />
</section>
<section id="pixel_grid">
<option id="visible" type="bool" default="false" migrate="PixelGrid.Visible" />
<option id="color" type="app::Color" default="app::Color::fromRgb(200, 200, 200)" migrate="PixelGrid.Color" />
<option id="opacity" type="int" default="160" migrate="PixelGrid.Opacity" />
<option id="auto_opacity" type="bool" default="true" migrate="PixelGrid.AutoOpacity" />
@ -281,6 +279,11 @@
<option id="scroll" type="gfx::Point" />
<option id="auto_scroll" type="bool" default="true" />
</section>
<section id="show">
<option id="selection_edges" type="bool" default="true" />
<option id="grid" type="bool" default="false" migrate="grid.visible" />
<option id="pixel_grid" type="bool" default="false" migrate="pixel_grid.visible" />
</section>
</document>
</preferences>

View File

@ -254,6 +254,7 @@ add_library(app-lib
commands/cmd_set_palette.cpp
commands/cmd_set_palette_entry_size.cpp
commands/cmd_set_same_ink.cpp
commands/cmd_show.cpp
commands/cmd_sprite_properties.cpp
commands/cmd_sprite_size.cpp
commands/cmd_switch_colors.cpp

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
@ -29,50 +29,6 @@ namespace app {
using namespace ui;
using namespace gfx;
class ShowGridCommand : public Command {
public:
ShowGridCommand()
: Command("ShowGrid",
"Show Grid",
CmdUIOnlyFlag) {
}
Command* clone() const override { return new ShowGridCommand(*this); }
protected:
bool onChecked(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
return docPref.grid.visible();
}
void onExecute(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
docPref.grid.visible(!docPref.grid.visible());
}
};
class ShowPixelGridCommand : public Command {
public:
ShowPixelGridCommand()
: Command("ShowPixelGrid",
"Show Pixel Grid",
CmdUIOnlyFlag) {
}
Command* clone() const override { return new ShowPixelGridCommand(*this); }
protected:
bool onChecked(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
return docPref.pixelGrid.visible();
}
void onExecute(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
docPref.pixelGrid.visible(!docPref.pixelGrid.visible());
}
};
class SnapToGridCommand : public Command {
public:
SnapToGridCommand()
@ -122,8 +78,10 @@ protected:
Preferences::instance().document(ctx->activeDocument());
docPref.grid.bounds(mask->bounds());
if (!docPref.grid.visible())
docPref.grid.visible(true);
// Make grid visible
if (!docPref.show.grid())
docPref.show.grid(true);
}
};
@ -177,19 +135,13 @@ void GridSettingsCommand::onExecute(Context* context)
bounds.h = MAX(bounds.h, 1);
docPref.grid.bounds(bounds);
// Make grid visible
if (!docPref.show.grid())
docPref.show.grid(true);
}
}
Command* CommandFactory::createShowGridCommand()
{
return new ShowGridCommand;
}
Command* CommandFactory::createShowPixelGridCommand()
{
return new ShowPixelGridCommand;
}
Command* CommandFactory::createSnapToGridCommand()
{
return new SnapToGridCommand;

View File

@ -0,0 +1,141 @@
// Aseprite
// 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
// published by the Free Software Foundation.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/commands/command.h"
#include "app/context.h"
#include "app/pref/preferences.h"
namespace app {
class ShowExtrasCommand : public Command {
public:
ShowExtrasCommand()
: Command("ShowExtras",
"Show Extras",
CmdUIOnlyFlag) {
}
Command* clone() const override { return new ShowExtrasCommand(*this); }
protected:
bool onChecked(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
return docPref.show.selectionEdges();
}
void onExecute(Context* ctx) override {
DocumentPreferences& globPref = Preferences::instance().document(nullptr);
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
if (docPref.show.selectionEdges()) {
globPref.show = docPref.show;
docPref.show.selectionEdges(false);
docPref.show.grid(false);
docPref.show.pixelGrid(false);
}
else {
docPref.show.selectionEdges(true);
docPref.show.grid(
docPref.show.grid() ||
globPref.show.grid());
docPref.show.pixelGrid(
docPref.show.pixelGrid() ||
globPref.show.pixelGrid());
}
}
};
class ShowGridCommand : public Command {
public:
ShowGridCommand()
: Command("ShowGrid",
"Show Grid",
CmdUIOnlyFlag) {
}
Command* clone() const override { return new ShowGridCommand(*this); }
protected:
bool onChecked(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
return docPref.show.grid();
}
void onExecute(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
docPref.show.grid(!docPref.show.grid());
}
};
class ShowPixelGridCommand : public Command {
public:
ShowPixelGridCommand()
: Command("ShowPixelGrid",
"Show Pixel Grid",
CmdUIOnlyFlag) {
}
Command* clone() const override { return new ShowPixelGridCommand(*this); }
protected:
bool onChecked(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
return docPref.show.pixelGrid();
}
void onExecute(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
docPref.show.pixelGrid(!docPref.show.pixelGrid());
}
};
class ShowSelectionEdgesCommand : public Command {
public:
ShowSelectionEdgesCommand()
: Command("ShowSelectionEdges",
"Show Selection Edges",
CmdUIOnlyFlag) {
}
Command* clone() const override { return new ShowSelectionEdgesCommand(*this); }
protected:
bool onChecked(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
return docPref.show.selectionEdges();
}
void onExecute(Context* ctx) override {
DocumentPreferences& docPref = Preferences::instance().document(ctx->activeDocument());
docPref.show.selectionEdges(!docPref.show.selectionEdges());
}
};
Command* CommandFactory::createShowExtrasCommand()
{
return new ShowExtrasCommand;
}
Command* CommandFactory::createShowGridCommand()
{
return new ShowGridCommand;
}
Command* CommandFactory::createShowPixelGridCommand()
{
return new ShowPixelGridCommand;
}
Command* CommandFactory::createShowSelectionEdgesCommand()
{
return new ShowSelectionEdgesCommand;
}
} // namespace app

View File

@ -116,9 +116,11 @@ FOR_EACH_COMMAND(SetLoopSection)
FOR_EACH_COMMAND(SetPalette)
FOR_EACH_COMMAND(SetPaletteEntrySize)
FOR_EACH_COMMAND(SetSameInk)
FOR_EACH_COMMAND(ShowExtras)
FOR_EACH_COMMAND(ShowGrid)
FOR_EACH_COMMAND(ShowOnionSkin)
FOR_EACH_COMMAND(ShowPixelGrid)
FOR_EACH_COMMAND(ShowSelectionEdges)
FOR_EACH_COMMAND(SnapToGrid)
FOR_EACH_COMMAND(SpriteProperties)
FOR_EACH_COMMAND(SpriteSize)

View File

@ -153,6 +153,7 @@ Editor::Editor(Document* document, EditorFlags flags)
, m_layer(m_sprite->folder()->getFirstLayer())
, m_frame(frame_t(0))
, m_zoom(1, 1)
, m_docPref(Preferences::instance().document(document))
, m_brushPreview(this)
, m_lastDrawingPosition(-1, -1)
, m_quicktool(NULL)
@ -183,22 +184,23 @@ Editor::Editor(Document* document, EditorFlags flags)
App::instance()->getMainWindow()->getContextBar()->BrushChange.connect(
base::Bind<void>(&Editor::onContextBarBrushChange, this));
DocumentPreferences& docPref = Preferences::instance().document(m_document);
// Restore last site in preferences
frame_t preferredFrame = docPref.site.frame();
Layer* preferredLayer = m_sprite->indexToLayer(docPref.site.layer());
frame_t preferredFrame = m_docPref.site.frame();
Layer* preferredLayer = m_sprite->indexToLayer(m_docPref.site.layer());
if (preferredFrame >= 0 && preferredFrame <= m_sprite->lastFrame())
setFrame(preferredFrame);
if (preferredLayer)
setLayer(preferredLayer);
m_tiledConn = docPref.tiled.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_gridConn = docPref.grid.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_pixelGridConn = docPref.pixelGrid.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_bgConn = docPref.bg.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_onionskinConn = docPref.onionskin.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_tiledConn = m_docPref.tiled.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_gridConn = m_docPref.grid.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_pixelGridConn = m_docPref.pixelGrid.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_bgConn = m_docPref.bg.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_onionskinConn = m_docPref.onionskin.AfterChange.connect(base::Bind<void>(&Editor::invalidate, this));
m_symmetryModeConn = Preferences::instance().symmetryMode.enabled.AfterChange.connect(base::Bind<void>(&Editor::invalidateIfActive, this));
m_showExtrasConn =
m_docPref.show.AfterChange.connect(
base::Bind<void>(&Editor::onShowExtrasChange, this));
m_document->addObserver(this);
@ -208,10 +210,8 @@ Editor::Editor(Document* document, EditorFlags flags)
Editor::~Editor()
{
if (m_document && m_sprite) {
DocumentPreferences& docPref = Preferences::instance()
.document(m_document);
docPref.site.frame(frame());
docPref.site.layer(m_sprite->layerToIndex(layer()));
m_docPref.site.frame(frame());
m_docPref.site.layer(m_sprite->layerToIndex(layer()));
}
m_observers.notifyDestroyEditor(this);
@ -309,8 +309,7 @@ void Editor::setLayer(const Layer* layer)
// If the onion skinning depends on the active layer, we've to
// redraw the whole editor.
if (m_document && changed) {
DocumentPreferences& docPref = Preferences::instance().document(m_document);
if (docPref.onionskin.currentLayer())
if (m_docPref.onionskin.currentLayer())
invalidate();
}
@ -464,26 +463,23 @@ void Editor::drawOneSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& sprite
m_renderEngine.disableOnionskin();
if ((m_flags & kShowOnionskin) == kShowOnionskin) {
DocumentPreferences& docPref = Preferences::instance()
.document(m_document);
if (docPref.onionskin.active()) {
if (m_docPref.onionskin.active()) {
OnionskinOptions opts(
(docPref.onionskin.type() == app::gen::OnionskinType::MERGE ?
(m_docPref.onionskin.type() == app::gen::OnionskinType::MERGE ?
render::OnionskinType::MERGE:
(docPref.onionskin.type() == app::gen::OnionskinType::RED_BLUE_TINT ?
(m_docPref.onionskin.type() == app::gen::OnionskinType::RED_BLUE_TINT ?
render::OnionskinType::RED_BLUE_TINT:
render::OnionskinType::NONE)));
opts.position(docPref.onionskin.position());
opts.prevFrames(docPref.onionskin.prevFrames());
opts.nextFrames(docPref.onionskin.nextFrames());
opts.opacityBase(docPref.onionskin.opacityBase());
opts.opacityStep(docPref.onionskin.opacityStep());
opts.layer(docPref.onionskin.currentLayer() ? m_layer: nullptr);
opts.position(m_docPref.onionskin.position());
opts.prevFrames(m_docPref.onionskin.prevFrames());
opts.nextFrames(m_docPref.onionskin.nextFrames());
opts.opacityBase(m_docPref.onionskin.opacityBase());
opts.opacityStep(m_docPref.onionskin.opacityStep());
opts.layer(m_docPref.onionskin.currentLayer() ? m_layer: nullptr);
FrameTag* tag = nullptr;
if (docPref.onionskin.loopTag())
if (m_docPref.onionskin.loopTag())
tag = m_sprite->frameTags().innerTag(m_frame);
opts.loopTag(tag);
@ -563,10 +559,7 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc)
outside.createSubtraction(outside, gfx::Region(spriteRect));
// Document preferences
DocumentPreferences& docPref =
Preferences::instance().document(m_document);
if (int(docPref.tiled.mode()) & int(filters::TiledMode::X_AXIS)) {
if (int(m_docPref.tiled.mode()) & int(filters::TiledMode::X_AXIS)) {
drawOneSpriteUnclippedRect(g, rc, -spriteRect.w, 0);
drawOneSpriteUnclippedRect(g, rc, +spriteRect.w, 0);
@ -574,7 +567,7 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc)
outside.createSubtraction(outside, gfx::Region(enclosingRect));
}
if (int(docPref.tiled.mode()) & int(filters::TiledMode::Y_AXIS)) {
if (int(m_docPref.tiled.mode()) & int(filters::TiledMode::Y_AXIS)) {
drawOneSpriteUnclippedRect(g, rc, 0, -spriteRect.h);
drawOneSpriteUnclippedRect(g, rc, 0, +spriteRect.h);
@ -582,7 +575,7 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc)
outside.createSubtraction(outside, gfx::Region(enclosingRect));
}
if (docPref.tiled.mode() == filters::TiledMode::BOTH) {
if (m_docPref.tiled.mode() == filters::TiledMode::BOTH) {
drawOneSpriteUnclippedRect(g, rc, -spriteRect.w, -spriteRect.h);
drawOneSpriteUnclippedRect(g, rc, +spriteRect.w, -spriteRect.h);
drawOneSpriteUnclippedRect(g, rc, -spriteRect.w, +spriteRect.h);
@ -610,34 +603,34 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc)
IntersectClip clip(g, cliprc);
// Draw the pixel grid
if ((m_zoom.scale() > 2.0) && docPref.pixelGrid.visible()) {
int alpha = docPref.pixelGrid.opacity();
if ((m_zoom.scale() > 2.0) && m_docPref.show.pixelGrid()) {
int alpha = m_docPref.pixelGrid.opacity();
if (docPref.pixelGrid.autoOpacity()) {
if (m_docPref.pixelGrid.autoOpacity()) {
alpha = int(alpha * (m_zoom.scale()-2.) / (16.-2.));
alpha = MID(0, alpha, 255);
}
drawGrid(g, enclosingRect, Rect(0, 0, 1, 1),
docPref.pixelGrid.color(), alpha);
m_docPref.pixelGrid.color(), alpha);
}
// Draw the grid
if (docPref.grid.visible()) {
gfx::Rect gridrc = docPref.grid.bounds();
if (m_docPref.show.grid()) {
gfx::Rect gridrc = m_docPref.grid.bounds();
if (m_zoom.apply(gridrc.w) > 2 &&
m_zoom.apply(gridrc.h) > 2) {
int alpha = docPref.grid.opacity();
int alpha = m_docPref.grid.opacity();
if (docPref.grid.autoOpacity()) {
if (m_docPref.grid.autoOpacity()) {
double len = (m_zoom.apply(gridrc.w) + m_zoom.apply(gridrc.h)) / 2.;
alpha = int(alpha * len / 32.);
alpha = MID(0, alpha, 255);
}
if (alpha > 8)
drawGrid(g, enclosingRect, docPref.grid.bounds(),
docPref.grid.color(), alpha);
drawGrid(g, enclosingRect, m_docPref.grid.bounds(),
m_docPref.grid.color(), alpha);
}
}
}
@ -647,14 +640,14 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc)
if (isActive() &&
(m_flags & Editor::kShowSymmetryLine) &&
Preferences::instance().symmetryMode.enabled()) {
switch (docPref.symmetry.mode()) {
switch (m_docPref.symmetry.mode()) {
case app::gen::SymmetryMode::NONE:
// Do nothing
break;
case app::gen::SymmetryMode::HORIZONTAL: {
int x = docPref.symmetry.xAxis();
int x = m_docPref.symmetry.xAxis();
if (x > 0) {
gfx::Color color = color_utils::color_for_ui(docPref.grid.color());
gfx::Color color = color_utils::color_for_ui(m_docPref.grid.color());
g->drawVLine(color,
spriteRect.x + m_zoom.apply(x),
enclosingRect.y,
@ -663,9 +656,9 @@ void Editor::drawSpriteUnclippedRect(ui::Graphics* g, const gfx::Rect& _rc)
break;
}
case app::gen::SymmetryMode::VERTICAL: {
int y = docPref.symmetry.yAxis();
int y = m_docPref.symmetry.yAxis();
if (y > 0) {
gfx::Color color = color_utils::color_for_ui(docPref.grid.color());
gfx::Color color = color_utils::color_for_ui(m_docPref.grid.color());
g->drawHLine(color,
enclosingRect.x,
spriteRect.y + m_zoom.apply(y),
@ -722,7 +715,8 @@ void Editor::drawSpriteClipped(const gfx::Region& updateRegion)
*/
void Editor::drawMask(Graphics* g)
{
if ((m_flags & kShowMask) == 0)
if ((m_flags & kShowMask) == 0 ||
!m_docPref.show.selectionEdges())
return;
ASSERT(m_document->getMaskBoundaries());
@ -1447,6 +1441,11 @@ void Editor::onContextBarBrushChange()
m_brushPreview.redraw();
}
void Editor::onShowExtrasChange()
{
invalidate();
}
void Editor::onExposeSpritePixels(doc::DocumentEvent& ev)
{
if (m_state && ev.sprite() == m_sprite)

View File

@ -12,7 +12,7 @@
#include "app/app_render.h"
#include "app/color.h"
#include "app/document.h"
#include "app/pref/option.h"
#include "app/pref/preferences.h"
#include "app/tools/selection_mode.h"
#include "app/ui/color_source.h"
#include "app/ui/editor/brush_preview.h"
@ -234,6 +234,7 @@ namespace app {
void onCurrentToolChange();
void onFgColorChange();
void onContextBarBrushChange();
void onShowExtrasChange();
void onExposeSpritePixels(doc::DocumentEvent& ev) override;
private:
@ -273,6 +274,7 @@ namespace app {
Layer* m_layer; // Active layer in the editor
frame_t m_frame; // Active frame in the editor
render::Zoom m_zoom; // Zoom in the editor
DocumentPreferences& m_docPref;
// Brush preview
BrushPreview m_brushPreview;
@ -302,6 +304,7 @@ namespace app {
base::ScopedConnection m_currentToolChangeConn;
base::ScopedConnection m_fgColorChangeConn;
base::ScopedConnection m_contextBarBrushChangeConn;
base::ScopedConnection m_showExtrasConn;
// Slots listeing document preferences.
base::ScopedConnection m_tiledConn;

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
@ -205,14 +205,14 @@ public:
bool getContiguous() override { return m_contiguous; }
tools::SelectionMode getSelectionMode() override { return m_editor->getSelectionMode(); }
filters::TiledMode getTiledMode() override { return m_docPref.tiled.mode(); }
bool getGridVisible() override { return m_docPref.grid.visible(); }
bool getGridVisible() override { return m_docPref.show.grid(); }
bool getSnapToGrid() override { return m_docPref.grid.snap(); }
bool getStopAtGrid() override {
switch (m_toolPref.floodfill.stopAtGrid()) {
case app::gen::StopAtGrid::NEVER:
return false;
case app::gen::StopAtGrid::IF_VISIBLE:
return m_docPref.grid.visible();
return m_docPref.show.grid();
case app::gen::StopAtGrid::ALWAYS:
return true;
}
@ -357,6 +357,9 @@ public:
else if (getInk()->isSelection()) {
m_document->generateMaskBoundaries();
redraw = true;
// Show selection edges
m_docPref.show.selectionEdges(true);
}
m_transaction.commit();