mirror of
https://github.com/aseprite/aseprite.git
synced 2024-09-02 04:59:24 +00:00
Add MoveTaskCommand: now you can move the selection with Shift+arrow keys
This commit is contained in:
parent
6d1602f278
commit
626ec1d2ba
26
data/gui.xml
26
data/gui.xml
@ -153,6 +153,32 @@
|
||||
<param name="units" value="zoomed-tile-height" />
|
||||
<param name="quantity" value="1" />
|
||||
</key>
|
||||
|
||||
<!-- Move selection with arrows -->
|
||||
<key command="MoveMask" shortcut="Shift+Left">
|
||||
<param name="target" value="content" />
|
||||
<param name="direction" value="left" />
|
||||
<param name="units" value="pixel" />
|
||||
<param name="quantity" value="1" />
|
||||
</key>
|
||||
<key command="MoveMask" shortcut="Shift+Right">
|
||||
<param name="target" value="content" />
|
||||
<param name="direction" value="right" />
|
||||
<param name="units" value="pixel" />
|
||||
<param name="quantity" value="1" />
|
||||
</key>
|
||||
<key command="MoveMask" shortcut="Shift+Up">
|
||||
<param name="target" value="content" />
|
||||
<param name="direction" value="up" />
|
||||
<param name="units" value="pixel" />
|
||||
<param name="quantity" value="1" />
|
||||
</key>
|
||||
<key command="MoveMask" shortcut="Shift+Down">
|
||||
<param name="target" value="content" />
|
||||
<param name="direction" value="down" />
|
||||
<param name="units" value="pixel" />
|
||||
<param name="quantity" value="1" />
|
||||
</key>
|
||||
</commands>
|
||||
|
||||
<!-- Keyboard shortcuts to select tools -->
|
||||
|
@ -52,6 +52,7 @@ add_library(app-lib
|
||||
commands/cmd_mask_by_color.cpp
|
||||
commands/cmd_merge_down_layer.cpp
|
||||
commands/cmd_move_cel.cpp
|
||||
commands/cmd_move_mask.cpp
|
||||
commands/cmd_new_file.cpp
|
||||
commands/cmd_new_frame.cpp
|
||||
commands/cmd_new_layer.cpp
|
||||
|
155
src/app/commands/cmd_move_mask.cpp
Normal file
155
src/app/commands/cmd_move_mask.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/commands/cmd_move_mask.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/commands/params.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/document_api.h"
|
||||
#include "app/modules/editors.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/settings/document_settings.h"
|
||||
#include "app/settings/settings.h"
|
||||
#include "app/ui/editor/editor.h"
|
||||
#include "app/undo_transaction.h"
|
||||
#include "app/undoers/set_mask_position.h"
|
||||
#include "raster/mask.h"
|
||||
#include "raster/sprite.h"
|
||||
#include "ui/view.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
MoveMaskCommand::MoveMaskCommand()
|
||||
: Command("MoveMask",
|
||||
"Move Mask",
|
||||
CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
void MoveMaskCommand::onLoadParams(Params* params)
|
||||
{
|
||||
std::string target = params->get("target");
|
||||
if (target == "outline") m_target = Outline;
|
||||
else if (target == "content") m_target = Content;
|
||||
|
||||
std::string direction = params->get("direction");
|
||||
if (direction == "left") m_direction = Left;
|
||||
else if (direction == "right") m_direction = Right;
|
||||
else if (direction == "up") m_direction = Up;
|
||||
else if (direction == "down") m_direction = Down;
|
||||
|
||||
std::string units = params->get("units");
|
||||
if (units == "pixel") m_units = Pixel;
|
||||
else if (units == "tile-width") m_units = TileWidth;
|
||||
else if (units == "tile-height") m_units = TileHeight;
|
||||
else if (units == "zoomed-pixel") m_units = ZoomedPixel;
|
||||
else if (units == "zoomed-tile-width") m_units = ZoomedTileWidth;
|
||||
else if (units == "zoomed-tile-height") m_units = ZoomedTileHeight;
|
||||
else if (units == "viewport-width") m_units = ViewportWidth;
|
||||
else if (units == "viewport-height") m_units = ViewportHeight;
|
||||
|
||||
int quantity = params->get_as<int>("quantity");
|
||||
m_quantity = std::max<int>(1, quantity);
|
||||
}
|
||||
|
||||
bool MoveMaskCommand::onEnabled(Context* context)
|
||||
{
|
||||
return context->checkFlags(ContextFlags::HasActiveDocument |
|
||||
ContextFlags::HasVisibleMask);
|
||||
}
|
||||
|
||||
void MoveMaskCommand::onExecute(Context* context)
|
||||
{
|
||||
IDocumentSettings* docSettings = context->settings()->getDocumentSettings(context->activeDocument());
|
||||
ui::View* view = ui::View::getView(current_editor);
|
||||
gfx::Rect vp = view->getViewportBounds();
|
||||
gfx::Point scroll = view->getViewScroll();
|
||||
gfx::Rect gridBounds = docSettings->getGridBounds();
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
int pixels = 0;
|
||||
|
||||
switch (m_units) {
|
||||
case Pixel:
|
||||
pixels = 1;
|
||||
break;
|
||||
case TileWidth:
|
||||
pixels = gridBounds.w;
|
||||
break;
|
||||
case TileHeight:
|
||||
pixels = gridBounds.h;
|
||||
break;
|
||||
case ZoomedPixel:
|
||||
pixels = 1 << current_editor->zoom();
|
||||
break;
|
||||
case ZoomedTileWidth:
|
||||
pixels = gridBounds.w << current_editor->zoom();
|
||||
break;
|
||||
case ZoomedTileHeight:
|
||||
pixels = gridBounds.h << current_editor->zoom();
|
||||
break;
|
||||
case ViewportWidth:
|
||||
pixels = vp.h;
|
||||
break;
|
||||
case ViewportHeight:
|
||||
pixels = vp.w;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (m_direction) {
|
||||
case Left: dx = -m_quantity * pixels; break;
|
||||
case Right: dx = +m_quantity * pixels; break;
|
||||
case Up: dy = -m_quantity * pixels; break;
|
||||
case Down: dy = +m_quantity * pixels; break;
|
||||
}
|
||||
|
||||
switch (m_target) {
|
||||
|
||||
case Outline: {
|
||||
ContextWriter writer(context);
|
||||
Document* document(writer.document());
|
||||
{
|
||||
UndoTransaction undo(writer.context(), "Move Selection", undo::DoesntModifyDocument);
|
||||
gfx::Point pt = document->mask()->bounds().getOrigin();
|
||||
document->getApi().setMaskPosition(pt.x+dx, pt.y+dy);
|
||||
undo.commit();
|
||||
}
|
||||
|
||||
document->generateMaskBoundaries();
|
||||
update_screen_for_document(document);
|
||||
break;
|
||||
}
|
||||
|
||||
case Content: {
|
||||
current_editor->startSelectionTransformation(gfx::Point(dx, dy));
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Command* CommandFactory::createMoveMaskCommand()
|
||||
{
|
||||
return new MoveMaskCommand;
|
||||
}
|
||||
|
||||
} // namespace app
|
62
src/app/commands/cmd_move_mask.h
Normal file
62
src/app/commands/cmd_move_mask.h
Normal file
@ -0,0 +1,62 @@
|
||||
/* Aseprite
|
||||
* Copyright (C) 2001-2014 David Capello
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef APP_COMMANDS_CMD_EXPORT_SPRITE_SHEET_H_INCLUDED
|
||||
#define APP_COMMANDS_CMD_EXPORT_SPRITE_SHEET_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/commands/command.h"
|
||||
#include "base/compiler_specific.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
class MoveMaskCommand : public Command {
|
||||
public:
|
||||
enum Target { Outline, Content };
|
||||
enum Direction { Left, Up, Right, Down, }; // TODO join this enum with scroll command
|
||||
enum Units {
|
||||
Pixel,
|
||||
TileWidth,
|
||||
TileHeight,
|
||||
ZoomedPixel,
|
||||
ZoomedTileWidth,
|
||||
ZoomedTileHeight,
|
||||
ViewportWidth,
|
||||
ViewportHeight
|
||||
};
|
||||
|
||||
MoveMaskCommand();
|
||||
Command* clone() const OVERRIDE { return new MoveMaskCommand(*this); }
|
||||
|
||||
Target getTarget() const { return m_target; }
|
||||
|
||||
protected:
|
||||
void onLoadParams(Params* params);
|
||||
bool onEnabled(Context* context);
|
||||
void onExecute(Context* context);
|
||||
|
||||
private:
|
||||
Target m_target;
|
||||
Direction m_direction;
|
||||
Units m_units;
|
||||
int m_quantity;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif
|
@ -70,6 +70,7 @@ FOR_EACH_COMMAND(MaskAll)
|
||||
FOR_EACH_COMMAND(MaskByColor)
|
||||
FOR_EACH_COMMAND(MergeDownLayer)
|
||||
FOR_EACH_COMMAND(MoveCel)
|
||||
FOR_EACH_COMMAND(MoveMask)
|
||||
FOR_EACH_COMMAND(NewFile)
|
||||
FOR_EACH_COMMAND(NewFrame)
|
||||
FOR_EACH_COMMAND(NewLayer)
|
||||
|
@ -76,7 +76,7 @@ void Context::executeCommand(Command* command, Params* params)
|
||||
ASSERT(command != NULL);
|
||||
|
||||
PRINTF("Executing '%s' command.\n", command->short_name());
|
||||
BeforeCommandExecution();
|
||||
BeforeCommandExecution(command);
|
||||
|
||||
try {
|
||||
m_flags.update(this);
|
||||
@ -87,7 +87,7 @@ void Context::executeCommand(Command* command, Params* params)
|
||||
if (command->isEnabled(this)) {
|
||||
command->execute(this);
|
||||
|
||||
AfterCommandExecution();
|
||||
AfterCommandExecution(command);
|
||||
}
|
||||
}
|
||||
catch (base::Exception& e) {
|
||||
|
@ -65,8 +65,8 @@ namespace app {
|
||||
|
||||
virtual void executeCommand(Command* command, Params* params = NULL);
|
||||
|
||||
Signal0<void> BeforeCommandExecution;
|
||||
Signal0<void> AfterCommandExecution;
|
||||
Signal1<void, Command*> BeforeCommandExecution;
|
||||
Signal1<void, Command*> AfterCommandExecution;
|
||||
|
||||
protected:
|
||||
virtual void onCreateDocument(doc::CreateDocumentArgs* args) OVERRIDE;
|
||||
|
@ -170,6 +170,8 @@ Editor::Editor(Document* document, EditorFlags flags)
|
||||
UIContext::instance()->settings()
|
||||
->getDocumentSettings(m_document)
|
||||
->addObserver(this);
|
||||
|
||||
m_state->onAfterChangeState(this);
|
||||
}
|
||||
|
||||
Editor::~Editor()
|
||||
@ -1209,6 +1211,16 @@ void Editor::pasteImage(const Image* image, int x, int y)
|
||||
setState(EditorStatePtr(new MovingPixelsState(this, NULL, pixelsMovement, NoHandle)));
|
||||
}
|
||||
|
||||
void Editor::startSelectionTransformation(const gfx::Point& move)
|
||||
{
|
||||
if (MovingPixelsState* movingPixels = dynamic_cast<MovingPixelsState*>(m_state.get())) {
|
||||
movingPixels->translate(move.x, move.y);
|
||||
}
|
||||
else if (StandbyState* standby = dynamic_cast<StandbyState*>(m_state.get())) {
|
||||
standby->startSelectionTransformation(this, move);
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::notifyScrollChanged()
|
||||
{
|
||||
m_observers.notifyScrollChanged(this);
|
||||
|
@ -175,6 +175,8 @@ namespace app {
|
||||
|
||||
void pasteImage(const Image* image, int x, int y);
|
||||
|
||||
void startSelectionTransformation(const gfx::Point& move);
|
||||
|
||||
// Used by EditorView to notify changes in the view's scroll
|
||||
// position.
|
||||
void notifyScrollChanged();
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "app/app.h"
|
||||
#include "app/color_utils.h"
|
||||
#include "app/commands/cmd_flip.h"
|
||||
#include "app/commands/cmd_move_mask.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/commands/commands.h"
|
||||
#include "app/modules/gui.h"
|
||||
@ -117,6 +118,16 @@ MovingPixelsState::~MovingPixelsState()
|
||||
m_currentEditor->document()->generateMaskBoundaries();
|
||||
}
|
||||
|
||||
void MovingPixelsState::translate(int dx, int dy)
|
||||
{
|
||||
if (m_pixelsMovement->isDragging())
|
||||
m_pixelsMovement->dropImageTemporarily();
|
||||
|
||||
m_pixelsMovement->catchImageAgain(0, 0, MoveHandle);
|
||||
m_pixelsMovement->moveImage(dx, dy, PixelsMovement::NormalMovement);
|
||||
m_pixelsMovement->dropImageTemporarily();
|
||||
}
|
||||
|
||||
EditorState::BeforeChangeAction MovingPixelsState::onBeforeChangeState(Editor* editor, EditorState* newState)
|
||||
{
|
||||
ASSERT(m_pixelsMovement != NULL);
|
||||
@ -387,8 +398,14 @@ bool MovingPixelsState::onUpdateStatusBar(Editor* editor)
|
||||
}
|
||||
|
||||
// Before executing any command, we drop the pixels (go back to standby).
|
||||
void MovingPixelsState::onBeforeCommandExecution()
|
||||
void MovingPixelsState::onBeforeCommandExecution(Command* command)
|
||||
{
|
||||
// We don't need to drop the pixels if a MoveMaskCommand of Content is executed.
|
||||
if (MoveMaskCommand* moveMaskCmd = dynamic_cast<MoveMaskCommand*>(command)) {
|
||||
if (moveMaskCmd->getTarget() == MoveMaskCommand::Content)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_pixelsMovement)
|
||||
dropPixels(m_currentEditor);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ namespace raster {
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class Command;
|
||||
class Editor;
|
||||
|
||||
class MovingPixelsState
|
||||
@ -44,6 +45,8 @@ namespace app {
|
||||
MovingPixelsState(Editor* editor, ui::MouseMessage* msg, PixelsMovementPtr pixelsMovement, HandleType handle);
|
||||
virtual ~MovingPixelsState();
|
||||
|
||||
void translate(int dx, int dy);
|
||||
|
||||
// EditorState
|
||||
virtual BeforeChangeAction onBeforeChangeState(Editor* editor, EditorState* newState) OVERRIDE;
|
||||
virtual void onCurrentToolChange(Editor* editor) OVERRIDE;
|
||||
@ -65,7 +68,7 @@ namespace app {
|
||||
|
||||
private:
|
||||
// ContextObserver
|
||||
void onBeforeCommandExecution();
|
||||
void onBeforeCommandExecution(Command* command);
|
||||
|
||||
void setTransparentColor(const app::Color& color);
|
||||
void dropPixels(Editor* editor);
|
||||
|
@ -521,6 +521,14 @@ gfx::Transformation StandbyState::getTransformation(Editor* editor)
|
||||
return editor->document()->getTransformation();
|
||||
}
|
||||
|
||||
void StandbyState::startSelectionTransformation(Editor* editor, const gfx::Point& move)
|
||||
{
|
||||
transformSelection(editor, NULL, NoHandle);
|
||||
|
||||
if (MovingPixelsState* movingPixels = dynamic_cast<MovingPixelsState*>(editor->getState().get()))
|
||||
movingPixels->translate(move.x, move.y);
|
||||
}
|
||||
|
||||
void StandbyState::transformSelection(Editor* editor, MouseMessage* msg, HandleType handle)
|
||||
{
|
||||
try {
|
||||
|
@ -51,6 +51,8 @@ namespace app {
|
||||
|
||||
virtual gfx::Transformation getTransformation(Editor* editor);
|
||||
|
||||
void startSelectionTransformation(Editor* editor, const gfx::Point& move);
|
||||
|
||||
protected:
|
||||
// Returns true and changes to ScrollingState when "msg" says "the
|
||||
// user wants to scroll".
|
||||
|
@ -926,7 +926,7 @@ paintNoDoc:;
|
||||
drawPart(g, getClientBounds(), NULL, m_timelinePaddingStyle);
|
||||
}
|
||||
|
||||
void Timeline::onAfterCommandExecution()
|
||||
void Timeline::onAfterCommandExecution(Command* command)
|
||||
{
|
||||
if (!m_document)
|
||||
return;
|
||||
|
@ -48,6 +48,7 @@ namespace ui {
|
||||
namespace app {
|
||||
using namespace raster;
|
||||
|
||||
class Command;
|
||||
class ConfigureTimelinePopup;
|
||||
class Context;
|
||||
class Document;
|
||||
@ -107,7 +108,7 @@ namespace app {
|
||||
void onRemoveFrame(doc::DocumentEvent& ev) OVERRIDE;
|
||||
|
||||
// app::Context slots.
|
||||
void onAfterCommandExecution();
|
||||
void onAfterCommandExecution(Command* command);
|
||||
|
||||
// DocumentsObserver impl.
|
||||
void onRemoveDocument(doc::Document* document) OVERRIDE;
|
||||
|
Loading…
Reference in New Issue
Block a user