Add Edit > Shift commands (fix #681)

This commit is contained in:
David Capello 2015-07-06 18:48:55 -03:00
parent 115b5d36f4
commit 8fd756c32a
9 changed files with 247 additions and 6 deletions

View File

@ -481,6 +481,36 @@
</item> </item>
<item command="MaskContent" text="Transfor&amp;m" /> <item command="MaskContent" text="Transfor&amp;m" />
<item command="NewBrush" text="New &amp;Brush" /> <item command="NewBrush" text="New &amp;Brush" />
<menu text="Shift">
<item command="MoveMask" text="&amp;Left">
<param name="target" value="content" />
<param name="direction" value="left" />
<param name="units" value="pixel" />
<param name="quantity" value="1" />
<param name="wrap" value="1" />
</item>
<item command="MoveMask" text="&amp;Right">
<param name="target" value="content" />
<param name="direction" value="right" />
<param name="units" value="pixel" />
<param name="quantity" value="1" />
<param name="wrap" value="1" />
</item>
<item command="MoveMask" text="&amp;Up">
<param name="target" value="content" />
<param name="direction" value="up" />
<param name="units" value="pixel" />
<param name="quantity" value="1" />
<param name="wrap" value="1" />
</item>
<item command="MoveMask" text="&amp;Down">
<param name="target" value="content" />
<param name="direction" value="down" />
<param name="units" value="pixel" />
<param name="quantity" value="1" />
<param name="wrap" value="1" />
</item>
</menu>
<separator /> <separator />
<item command="ReplaceColor" text="R&amp;eplace Color..." /> <item command="ReplaceColor" text="R&amp;eplace Color..." />
<item command="InvertColor" text="&amp;Invert" /> <item command="InvertColor" text="&amp;Invert" />

View File

@ -114,9 +114,9 @@ add_library(app-lib
cmd/set_frame_tag_name.cpp cmd/set_frame_tag_name.cpp
cmd/set_frame_tag_range.cpp cmd/set_frame_tag_range.cpp
cmd/set_layer_blend_mode.cpp cmd/set_layer_blend_mode.cpp
cmd/set_layer_opacity.cpp
cmd/set_layer_flags.cpp cmd/set_layer_flags.cpp
cmd/set_layer_name.cpp cmd/set_layer_name.cpp
cmd/set_layer_opacity.cpp
cmd/set_mask.cpp cmd/set_mask.cpp
cmd/set_mask_position.cpp cmd/set_mask_position.cpp
cmd/set_palette.cpp cmd/set_palette.cpp
@ -124,6 +124,7 @@ add_library(app-lib
cmd/set_sprite_size.cpp cmd/set_sprite_size.cpp
cmd/set_total_frames.cpp cmd/set_total_frames.cpp
cmd/set_transparent_color.cpp cmd/set_transparent_color.cpp
cmd/shift_masked_cel.cpp
cmd/unlink_cel.cpp cmd/unlink_cel.cpp
cmd/with_cel.cpp cmd/with_cel.cpp
cmd/with_document.cpp cmd/with_document.cpp

View File

@ -0,0 +1,61 @@
// 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.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "app/cmd/shift_masked_cel.h"
#include "app/document.h"
#include "doc/algorithm/shift_image.h"
#include "doc/cel.h"
#include "doc/image.h"
#include "doc/layer.h"
#include "doc/mask.h"
namespace app {
namespace cmd {
ShiftMaskedCel::ShiftMaskedCel(Cel* cel, int dx, int dy)
: WithCel(cel)
, m_dx(dx)
, m_dy(dy)
{
}
void ShiftMaskedCel::onExecute()
{
shift(m_dx, m_dy);
}
void ShiftMaskedCel::onUndo()
{
shift(-m_dx, -m_dy);
}
void ShiftMaskedCel::shift(int dx, int dy)
{
Cel* cel = this->cel();
Image* image = cel->image();
Mask* mask = static_cast<app::Document*>(cel->document())->mask();
ASSERT(mask->bitmap());
if (!mask->bitmap())
return;
int x = cel->x();
int y = cel->y();
mask->offsetOrigin(-x, -y);
doc::algorithm::shift_image_with_mask(image, mask, dx, dy);
mask->offsetOrigin(x, y);
image->incrementVersion();
}
} // namespace cmd
} // namespace app

View File

@ -0,0 +1,40 @@
// 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_CMD_SHIFT_MASKED_CEL_H_INCLUDED
#define APP_CMD_SHIFT_MASKED_CEL_H_INCLUDED
#pragma once
#include "app/cmd.h"
#include "app/cmd/with_cel.h"
namespace app {
namespace cmd {
using namespace doc;
class ShiftMaskedCel : public Cmd
, public WithCel {
public:
ShiftMaskedCel(Cel* cel, int dx, int dy);
protected:
void onExecute() override;
void onUndo() override;
size_t onMemSize() const override {
return sizeof(*this);
}
private:
void shift(int dx, int dy);
int m_dx, m_dy;
};
} // namespace cmd
} // namespace app
#endif

View File

@ -10,6 +10,7 @@
#endif #endif
#include "app/app.h" #include "app/app.h"
#include "app/cmd/shift_masked_cel.h"
#include "app/commands/cmd_move_mask.h" #include "app/commands/cmd_move_mask.h"
#include "app/commands/command.h" #include "app/commands/command.h"
#include "app/commands/params.h" #include "app/commands/params.h"
@ -58,12 +59,34 @@ void MoveMaskCommand::onLoadParams(const Params& params)
int quantity = params.get_as<int>("quantity"); int quantity = params.get_as<int>("quantity");
m_quantity = std::max<int>(1, quantity); m_quantity = std::max<int>(1, quantity);
if (params.has_param("wrap"))
m_wrap = params.get_as<bool>("wrap");
else
m_wrap = false;
} }
bool MoveMaskCommand::onEnabled(Context* context) bool MoveMaskCommand::onEnabled(Context* context)
{ {
return context->checkFlags(ContextFlags::HasActiveDocument | switch (m_target) {
ContextFlags::HasVisibleMask);
case Boundaries:
return context->checkFlags(ContextFlags::HasActiveDocument |
ContextFlags::HasVisibleMask);
case Content:
if (m_wrap)
return context->checkFlags(ContextFlags::ActiveDocumentIsWritable |
ContextFlags::HasVisibleMask |
ContextFlags::HasActiveImage);
else
return context->checkFlags(ContextFlags::HasActiveDocument |
ContextFlags::HasVisibleMask |
ContextFlags::HasActiveImage);
}
return false;
} }
void MoveMaskCommand::onExecute(Context* context) void MoveMaskCommand::onExecute(Context* context)
@ -127,10 +150,21 @@ void MoveMaskCommand::onExecute(Context* context)
break; break;
} }
case Content: { case Content:
current_editor->startSelectionTransformation(gfx::Point(dx, dy)); if (m_wrap) {
ContextWriter writer(context);
if (writer.cel()) {
// Rotate content
Transaction transaction(writer.context(), "Shift Pixels");
transaction.execute(new cmd::ShiftMaskedCel(writer.cel(), dx, dy));
transaction.commit();
}
update_screen_for_document(writer.document());
}
else {
current_editor->startSelectionTransformation(gfx::Point(dx, dy));
}
break; break;
}
} }
} }

View File

@ -44,6 +44,7 @@ namespace app {
Direction m_direction; Direction m_direction;
Units m_units; Units m_units;
int m_quantity; int m_quantity;
bool m_wrap;
}; };
} // namespace app } // namespace app

View File

@ -9,6 +9,7 @@ add_library(doc-lib
algorithm/resize_image.cpp algorithm/resize_image.cpp
algorithm/rotate.cpp algorithm/rotate.cpp
algorithm/rotsprite.cpp algorithm/rotsprite.cpp
algorithm/shift_image.cpp
algorithm/shrink_bounds.cpp algorithm/shrink_bounds.cpp
blend_funcs.cpp blend_funcs.cpp
brush.cpp brush.cpp

View File

@ -0,0 +1,51 @@
// Aseprite Document Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "doc/algorithm/shift_image.h"
#include "base/unique_ptr.h"
#include "gfx/rect.h"
#include "doc/image.h"
#include "doc/mask.h"
#include "doc/primitives.h"
#include <vector>
namespace doc {
namespace algorithm {
void shift_image_with_mask(Image* image, const Mask* mask, int dx, int dy)
{
gfx::Rect bounds = mask->bounds();
if (bounds.isEmpty())
return;
// To simplify the algorithm we use a copy of the original image, we
// could avoid this copy swapping rows and columns.
ImageRef crop(crop_image(image, bounds.x, bounds.y, bounds.w, bounds.h,
image->maskColor()));
int u = dx;
int v = dy;
while (u < 0) u += bounds.w;
while (v < 0) v += bounds.h;
for (int y=0; y<bounds.h; ++y) {
for (int x=0; x<bounds.w; ++x) {
put_pixel(image,
bounds.x + ((u + x) % bounds.w),
bounds.y + ((v + y) % bounds.h),
get_pixel(crop.get(), x, y));
}
}
}
} // namespace algorithm
} // namespace doc

View File

@ -0,0 +1,22 @@
// Aseprite Document Library
// Copyright (c) 2001-2015 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef DOC_ALGORITHM_SHIFT_IMAGE_H_INCLUDED
#define DOC_ALGORITHM_SHIFT_IMAGE_H_INCLUDED
#pragma once
namespace doc {
class Image;
class Mask;
namespace algorithm {
void shift_image_with_mask(Image* image, const Mask* mask, int dx, int dy);
}
}
#endif