mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-15 21:40:34 +00:00
Add CopyMerged command (Ctrl+Shift+C) (fix #824)
This commit is contained in:
parent
fda9abce33
commit
0f3252a80b
@ -12,7 +12,7 @@
|
||||
<key command="OpenFile" shortcut="Ctrl+O" mac="Cmd+O" />
|
||||
<key command="SaveFile" shortcut="Ctrl+S" mac="Cmd+S" />
|
||||
<key command="SaveFileAs" shortcut="Ctrl+Shift+S" mac="Cmd+Shift+S" />
|
||||
<key command="SaveFileCopyAs" shortcut="Ctrl+Shift+C" mac="Cmd+Shift+C" />
|
||||
<key command="SaveFileCopyAs" shortcut="Ctrl+Alt+Shift+S" mac="Cmd+Alt+Shift+S" />
|
||||
<key command="CloseFile" shortcut="Ctrl+W" mac="Cmd+W" />
|
||||
<key command="CloseAllFiles" shortcut="Ctrl+Shift+W" mac="Cmd+Shift+W" />
|
||||
<key command="ImportSpriteSheet" shortcut="Ctrl+I" mac="Cmd+I" />
|
||||
@ -35,6 +35,7 @@
|
||||
<key command="Cut" shortcut="Shift+Del" />
|
||||
<key command="Copy" shortcut="Ctrl+C" mac="Cmd+C" />
|
||||
<key command="Copy" shortcut="Ctrl+Ins" mac="Cmd+Ins" />
|
||||
<key command="CopyMerged" shortcut="Ctrl+Shift+C" mac="Cmd+Shift+C" />
|
||||
<key command="Paste" shortcut="Ctrl+V" mac="Cmd+V" />
|
||||
<key command="Paste" shortcut="Shift+Ins" />
|
||||
<key command="Clear" shortcut="Del" />
|
||||
@ -530,6 +531,7 @@
|
||||
<separator />
|
||||
<item command="Cut" text="Cu&t" />
|
||||
<item command="Copy" text="&Copy" />
|
||||
<item command="CopyMerged" text="Copy Mer&ged" />
|
||||
<item command="Paste" text="&Paste" />
|
||||
<item command="Clear" text="C&lear" />
|
||||
<separator />
|
||||
|
@ -180,6 +180,7 @@ add_library(app-lib
|
||||
commands/cmd_color_quantization.cpp
|
||||
commands/cmd_copy.cpp
|
||||
commands/cmd_copy_cel.cpp
|
||||
commands/cmd_copy_merged.cpp
|
||||
commands/cmd_crop.cpp
|
||||
commands/cmd_cut.cpp
|
||||
commands/cmd_deselect_mask.cpp
|
||||
|
51
src/app/commands/cmd_copy_merged.cpp
Normal file
51
src/app/commands/cmd_copy_merged.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 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_access.h"
|
||||
#include "app/util/clipboard.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
class CopyMergedCommand : public Command {
|
||||
public:
|
||||
CopyMergedCommand();
|
||||
Command* clone() const override { return new CopyMergedCommand(*this); }
|
||||
|
||||
protected:
|
||||
bool onEnabled(Context* ctx) override;
|
||||
void onExecute(Context* ctx) override;
|
||||
};
|
||||
|
||||
CopyMergedCommand::CopyMergedCommand()
|
||||
: Command("CopyMerged",
|
||||
"Copy Merged",
|
||||
CmdUIOnlyFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool CopyMergedCommand::onEnabled(Context* ctx)
|
||||
{
|
||||
return ctx->checkFlags(ContextFlags::ActiveDocumentIsReadable);
|
||||
}
|
||||
|
||||
void CopyMergedCommand::onExecute(Context* ctx)
|
||||
{
|
||||
ContextReader reader(ctx);
|
||||
clipboard::copy_merged(reader);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createCopyMergedCommand()
|
||||
{
|
||||
return new CopyMergedCommand;
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -25,6 +25,7 @@ FOR_EACH_COMMAND(ColorQuantization)
|
||||
FOR_EACH_COMMAND(ConvolutionMatrix)
|
||||
FOR_EACH_COMMAND(Copy)
|
||||
FOR_EACH_COMMAND(CopyCel)
|
||||
FOR_EACH_COMMAND(CopyMerged)
|
||||
FOR_EACH_COMMAND(CropSprite)
|
||||
FOR_EACH_COMMAND(Cut)
|
||||
FOR_EACH_COMMAND(DeselectMask)
|
||||
|
@ -157,20 +157,17 @@ static void set_clipboard_image(Image* image,
|
||||
clipboard_range.invalidate();
|
||||
}
|
||||
|
||||
static bool copy_from_document(const Site& site)
|
||||
static bool copy_from_document(const Site& site, bool merged = false)
|
||||
{
|
||||
const app::Document* document = static_cast<const app::Document*>(site.document());
|
||||
ASSERT(document);
|
||||
|
||||
ASSERT(document != NULL);
|
||||
ASSERT(document->isMaskVisible());
|
||||
|
||||
Image* image = new_image_from_mask(site);
|
||||
const Mask* mask = document->mask();
|
||||
Image* image = new_image_from_mask(site, mask, merged);
|
||||
if (!image)
|
||||
return false;
|
||||
|
||||
const Mask* mask = document->mask();
|
||||
const Palette* pal = document->sprite()->palette(site.frame());
|
||||
|
||||
set_clipboard_image(
|
||||
image,
|
||||
(mask ? new Mask(*mask): nullptr),
|
||||
@ -250,6 +247,13 @@ void copy(const ContextReader& reader)
|
||||
}
|
||||
}
|
||||
|
||||
void copy_merged(const ContextReader& reader)
|
||||
{
|
||||
ASSERT(reader.document() != NULL);
|
||||
|
||||
copy_from_document(*reader.site(), true);
|
||||
}
|
||||
|
||||
void copy_range(const ContextReader& reader, const DocumentRange& range)
|
||||
{
|
||||
ASSERT(reader.document() != NULL);
|
||||
|
@ -21,6 +21,7 @@ namespace doc {
|
||||
}
|
||||
|
||||
namespace app {
|
||||
class Document;
|
||||
class ContextReader;
|
||||
class ContextWriter;
|
||||
class DocumentRange;
|
||||
@ -51,6 +52,7 @@ namespace app {
|
||||
void clear_content();
|
||||
void cut(ContextWriter& context);
|
||||
void copy(const ContextReader& context);
|
||||
void copy_merged(const ContextReader& context);
|
||||
void copy_range(const ContextReader& context, const DocumentRange& range);
|
||||
void copy_image(const Image* image, const Mask* mask, const Palette* palette);
|
||||
void copy_palette(const Palette* palette, const PalettePicks& picks);
|
||||
|
@ -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
|
||||
@ -15,7 +15,9 @@
|
||||
#include "base/unique_ptr.h"
|
||||
#include "doc/image_impl.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/primitives.h"
|
||||
#include "doc/site.h"
|
||||
#include "render/render.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
@ -27,45 +29,69 @@ Image* new_image_from_mask(const Site& site)
|
||||
return new_image_from_mask(site, srcMask);
|
||||
}
|
||||
|
||||
doc::Image* new_image_from_mask(const doc::Site& site, const doc::Mask* srcMask)
|
||||
doc::Image* new_image_from_mask(const doc::Site& site,
|
||||
const doc::Mask* srcMask,
|
||||
bool merged)
|
||||
{
|
||||
const Sprite* srcSprite = site.sprite();
|
||||
const Image* srcMaskBitmap = srcMask->bitmap();
|
||||
const gfx::Rect& srcBounds = srcMask->bounds();
|
||||
const Image* srcMaskBitmap = (srcMask ? srcMask->bitmap(): nullptr);
|
||||
gfx::Rect srcBounds = (srcMask ? srcMask->bounds(): srcSprite->bounds());
|
||||
int x, y, u, v, getx, gety;
|
||||
const Image *src = site.image(&x, &y);
|
||||
|
||||
ASSERT(srcSprite);
|
||||
ASSERT(srcMask);
|
||||
ASSERT(srcMaskBitmap);
|
||||
|
||||
base::UniquePtr<Image> dst(Image::create(srcSprite->pixelFormat(), srcBounds.w, srcBounds.h));
|
||||
if (!dst)
|
||||
return nullptr;
|
||||
|
||||
// Clear the new image
|
||||
dst->setMaskColor(src ? src->maskColor(): srcSprite->transparentColor());
|
||||
dst->setMaskColor(srcSprite->transparentColor());
|
||||
clear_image(dst, dst->maskColor());
|
||||
|
||||
const Image* src = nullptr;
|
||||
if (merged) {
|
||||
render::Render render;
|
||||
render.renderSprite(dst, srcSprite, site.frame(),
|
||||
gfx::Clip(0, 0, srcBounds));
|
||||
|
||||
src = dst;
|
||||
}
|
||||
else {
|
||||
src = site.image(&x, &y);
|
||||
}
|
||||
|
||||
// Copy the masked zones
|
||||
if (src) {
|
||||
const LockImageBits<BitmapTraits> maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h));
|
||||
LockImageBits<BitmapTraits>::const_iterator mask_it = maskBits.begin();
|
||||
if (srcMaskBitmap) {
|
||||
// Copy active layer with mask
|
||||
const LockImageBits<BitmapTraits> maskBits(srcMaskBitmap, gfx::Rect(0, 0, srcBounds.w, srcBounds.h));
|
||||
LockImageBits<BitmapTraits>::const_iterator mask_it = maskBits.begin();
|
||||
|
||||
for (v=0; v<srcBounds.h; ++v) {
|
||||
for (u=0; u<srcBounds.w; ++u, ++mask_it) {
|
||||
ASSERT(mask_it != maskBits.end());
|
||||
for (v=0; v<srcBounds.h; ++v) {
|
||||
for (u=0; u<srcBounds.w; ++u, ++mask_it) {
|
||||
ASSERT(mask_it != maskBits.end());
|
||||
|
||||
if (*mask_it) {
|
||||
getx = u+srcBounds.x-x;
|
||||
gety = v+srcBounds.y-y;
|
||||
if (src != dst) {
|
||||
if (*mask_it) {
|
||||
getx = u+srcBounds.x-x;
|
||||
gety = v+srcBounds.y-y;
|
||||
|
||||
if ((getx >= 0) && (getx < src->width()) &&
|
||||
(gety >= 0) && (gety < src->height()))
|
||||
dst->putPixel(u, v, src->getPixel(getx, gety));
|
||||
if ((getx >= 0) && (getx < src->width()) &&
|
||||
(gety >= 0) && (gety < src->height()))
|
||||
dst->putPixel(u, v, src->getPixel(getx, gety));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!*mask_it) {
|
||||
dst->putPixel(u, v, dst->maskColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (src != dst) {
|
||||
copy_image(dst, src, -srcBounds.x, -srcBounds.y);
|
||||
}
|
||||
}
|
||||
|
||||
return dst.release();
|
||||
|
@ -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
|
||||
@ -18,7 +18,9 @@ namespace doc {
|
||||
namespace app {
|
||||
|
||||
doc::Image* new_image_from_mask(const doc::Site& site);
|
||||
doc::Image* new_image_from_mask(const doc::Site& site, const doc::Mask* mask);
|
||||
doc::Image* new_image_from_mask(const doc::Site& site,
|
||||
const doc::Mask* mask,
|
||||
bool merged = false);
|
||||
|
||||
} // namespace app
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user