mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-30 15:32:38 +00:00
Add Edit > Shift commands (fix #681)
This commit is contained in:
parent
115b5d36f4
commit
8fd756c32a
30
data/gui.xml
30
data/gui.xml
@ -481,6 +481,36 @@
|
|||||||
</item>
|
</item>
|
||||||
<item command="MaskContent" text="Transfor&m" />
|
<item command="MaskContent" text="Transfor&m" />
|
||||||
<item command="NewBrush" text="New &Brush" />
|
<item command="NewBrush" text="New &Brush" />
|
||||||
|
<menu text="Shift">
|
||||||
|
<item command="MoveMask" text="&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="&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="&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="&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&eplace Color..." />
|
<item command="ReplaceColor" text="R&eplace Color..." />
|
||||||
<item command="InvertColor" text="&Invert" />
|
<item command="InvertColor" text="&Invert" />
|
||||||
|
@ -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
|
||||||
|
61
src/app/cmd/shift_masked_cel.cpp
Normal file
61
src/app/cmd/shift_masked_cel.cpp
Normal 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
|
40
src/app/cmd/shift_masked_cel.h
Normal file
40
src/app/cmd/shift_masked_cel.h
Normal 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
|
@ -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;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
51
src/doc/algorithm/shift_image.cpp
Normal file
51
src/doc/algorithm/shift_image.cpp
Normal 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
|
22
src/doc/algorithm/shift_image.h
Normal file
22
src/doc/algorithm/shift_image.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user