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 command="MaskContent" text="Transfor&m" />
|
||||
<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 />
|
||||
<item command="ReplaceColor" text="R&eplace Color..." />
|
||||
<item command="InvertColor" text="&Invert" />
|
||||
|
@ -114,9 +114,9 @@ add_library(app-lib
|
||||
cmd/set_frame_tag_name.cpp
|
||||
cmd/set_frame_tag_range.cpp
|
||||
cmd/set_layer_blend_mode.cpp
|
||||
cmd/set_layer_opacity.cpp
|
||||
cmd/set_layer_flags.cpp
|
||||
cmd/set_layer_name.cpp
|
||||
cmd/set_layer_opacity.cpp
|
||||
cmd/set_mask.cpp
|
||||
cmd/set_mask_position.cpp
|
||||
cmd/set_palette.cpp
|
||||
@ -124,6 +124,7 @@ add_library(app-lib
|
||||
cmd/set_sprite_size.cpp
|
||||
cmd/set_total_frames.cpp
|
||||
cmd/set_transparent_color.cpp
|
||||
cmd/shift_masked_cel.cpp
|
||||
cmd/unlink_cel.cpp
|
||||
cmd/with_cel.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
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/cmd/shift_masked_cel.h"
|
||||
#include "app/commands/cmd_move_mask.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/commands/params.h"
|
||||
@ -58,12 +59,34 @@ void MoveMaskCommand::onLoadParams(const Params& params)
|
||||
|
||||
int quantity = params.get_as<int>("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)
|
||||
{
|
||||
return context->checkFlags(ContextFlags::HasActiveDocument |
|
||||
ContextFlags::HasVisibleMask);
|
||||
switch (m_target) {
|
||||
|
||||
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)
|
||||
@ -127,10 +150,21 @@ void MoveMaskCommand::onExecute(Context* context)
|
||||
break;
|
||||
}
|
||||
|
||||
case Content: {
|
||||
current_editor->startSelectionTransformation(gfx::Point(dx, dy));
|
||||
case Content:
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ namespace app {
|
||||
Direction m_direction;
|
||||
Units m_units;
|
||||
int m_quantity;
|
||||
bool m_wrap;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
@ -9,6 +9,7 @@ add_library(doc-lib
|
||||
algorithm/resize_image.cpp
|
||||
algorithm/rotate.cpp
|
||||
algorithm/rotsprite.cpp
|
||||
algorithm/shift_image.cpp
|
||||
algorithm/shrink_bounds.cpp
|
||||
blend_funcs.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