mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-29 21:33:12 +00:00
Add new ConvertLayer command ("Layer > Convert To" menu item)
Now we have an easy way to convert between: Background <-> Layers <-> Tilemaps Deprecated (they are kept only for backward compatibility): BackgroundFromLayer LayerFromBackground
This commit is contained in:
parent
b6987a0262
commit
44437e0d1f
28
data/gui.xml
28
data/gui.xml
@ -840,9 +840,17 @@
|
||||
</item>
|
||||
</menu>
|
||||
<item command="RemoveLayer" text="@.layer_delete_layer" group="layer_remove" />
|
||||
<menu text="@.layer_convert">
|
||||
<item command="BackgroundFromLayer" text="@.layer_background_from_layer" />
|
||||
<item command="LayerFromBackground" text="@.layer_layer_from_background" group="layer_background" />
|
||||
<menu text="@.layer_convert_to">
|
||||
<item command="ConvertLayer" text="@.layer_convert_to_background">
|
||||
<param name="to" value="background" />
|
||||
</item>
|
||||
<item command="ConvertLayer" text="@.layer_convert_to_layer">
|
||||
<param name="to" value="layer" />
|
||||
</item>
|
||||
<separator />
|
||||
<item command="ConvertLayer" text="@.layer_convert_to_tilemap">
|
||||
<param name="to" value="tilemap" />
|
||||
</item>
|
||||
</menu>
|
||||
<separator />
|
||||
<item command="DuplicateLayer" text="@.layer_duplicate" group="layer_duplicate" />
|
||||
@ -1018,9 +1026,17 @@
|
||||
<param name="group" value="true" />
|
||||
</item>
|
||||
<item command="RemoveLayer" text="@main_menu.layer_delete_layer" />
|
||||
<menu text="@main_menu.layer_convert">
|
||||
<item command="BackgroundFromLayer" text="@main_menu.layer_background_from_layer" />
|
||||
<item command="LayerFromBackground" text="@main_menu.layer_layer_from_background" group="layer_popup_background" />
|
||||
<menu text="@main_menu.layer_convert_to">
|
||||
<item command="ConvertLayer" text="@main_menu.layer_convert_to_background">
|
||||
<param name="to" value="background" />
|
||||
</item>
|
||||
<item command="ConvertLayer" text="@main_menu.layer_convert_to_layer">
|
||||
<param name="to" value="layer" />
|
||||
</item>
|
||||
<separator />
|
||||
<item command="ConvertLayer" text="@main_menu.layer_convert_to_tilemap">
|
||||
<param name="to" value="tilemap" />
|
||||
</item>
|
||||
</menu>
|
||||
<separator />
|
||||
<item command="DuplicateLayer" text="@main_menu.layer_duplicate" />
|
||||
|
@ -273,6 +273,10 @@ ClearCel = Clear Cel
|
||||
ClearRecentFiles = Clear Recent Files
|
||||
CloseAllFiles = Close All Files
|
||||
CloseFile = Close File
|
||||
ConvertLayer = Convert Layer
|
||||
ConvertLayer_Background = Convert to Background
|
||||
ConvertLayer_Layer = Convert to Transparent Layer
|
||||
ConvertLayer_Tilemap = Convert to Tilemap
|
||||
ColorCurve = Color Curve
|
||||
ColorQuantization = Create Palette from Current Sprite (Color Quantization)
|
||||
ContiguousFill = Switch Contiguous Fill
|
||||
@ -925,9 +929,10 @@ layer_new_layer_via_cut = New Layer via Cu&t
|
||||
layer_new_reference_layer_from_file = New &Reference Layer from File
|
||||
layer_new_tilemap_layer = New Tilemap Layer
|
||||
layer_delete_layer = Delete Laye&r
|
||||
layer_convert = Conv&ert
|
||||
layer_background_from_layer = &Background from Layer
|
||||
layer_layer_from_background = &Layer from Background
|
||||
layer_convert_to = Conv&ert To...
|
||||
layer_convert_to_background = &Background
|
||||
layer_convert_to_layer = &Layer
|
||||
layer_convert_to_tilemap = &Tilemap
|
||||
layer_duplicate = &Duplicate
|
||||
layer_merge_down = &Merge Down
|
||||
layer_flatten = &Flatten
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Aseprite
|
||||
# Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
# Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
# Copyright (C) 2001-2018 David Capello
|
||||
|
||||
# Generate a ui::Widget for each widget in a XML file
|
||||
@ -535,6 +535,7 @@ add_library(app-lib
|
||||
commands/cmd_undo.cpp
|
||||
commands/command.cpp
|
||||
commands/commands.cpp
|
||||
commands/convert_layer.cpp
|
||||
commands/filters/cmd_brightness_contrast.cpp
|
||||
commands/filters/cmd_color_curve.cpp
|
||||
commands/filters/cmd_convolution_matrix.cpp
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -14,6 +14,7 @@ FOR_EACH_COMMAND(CelOpacity)
|
||||
FOR_EACH_COMMAND(ChangePixelFormat)
|
||||
FOR_EACH_COMMAND(ColorCurve)
|
||||
FOR_EACH_COMMAND(ColorQuantization)
|
||||
FOR_EACH_COMMAND(ConvertLayer)
|
||||
FOR_EACH_COMMAND(ConvolutionMatrix)
|
||||
FOR_EACH_COMMAND(CopyColors)
|
||||
FOR_EACH_COMMAND(CopyTiles)
|
||||
|
258
src/app/commands/convert_layer.cpp
Normal file
258
src/app/commands/convert_layer.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2021 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "app/cmd/add_cel.h"
|
||||
#include "app/cmd/add_layer.h"
|
||||
#include "app/cmd/add_tileset.h"
|
||||
#include "app/cmd/background_from_layer.h"
|
||||
#include "app/cmd/copy_cel.h"
|
||||
#include "app/cmd/layer_from_background.h"
|
||||
#include "app/cmd/remove_layer.h"
|
||||
#include "app/commands/command.h"
|
||||
#include "app/commands/new_params.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/i18n/strings.h"
|
||||
#include "app/modules/gui.h"
|
||||
#include "app/tx.h"
|
||||
#include "app/util/cel_ops.h"
|
||||
#include "doc/grid.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/layer_tilemap.h"
|
||||
#include "doc/tileset.h"
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
#include "app/script/luacpp.h"
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace app {
|
||||
|
||||
enum class ConvertLayerParam { None, Background, Layer, Tilemap };
|
||||
|
||||
template<>
|
||||
void Param<ConvertLayerParam>::fromString(const std::string& value)
|
||||
{
|
||||
if (value == "background")
|
||||
setValue(ConvertLayerParam::Background);
|
||||
else if (value == "layer")
|
||||
setValue(ConvertLayerParam::Layer);
|
||||
else if (value == "tilemap")
|
||||
setValue(ConvertLayerParam::Tilemap);
|
||||
else
|
||||
setValue(ConvertLayerParam::None);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SCRIPTING
|
||||
template<>
|
||||
void Param<ConvertLayerParam>::fromLua(lua_State* L, int index)
|
||||
{
|
||||
fromString(lua_tostring(L, index));
|
||||
}
|
||||
#endif // ENABLE_SCRIPTING
|
||||
|
||||
struct ConvertLayerParams : public NewParams {
|
||||
Param<ConvertLayerParam> to { this, ConvertLayerParam::None, "to" };
|
||||
};
|
||||
|
||||
class ConvertLayerCommand : public CommandWithNewParams<ConvertLayerParams> {
|
||||
public:
|
||||
ConvertLayerCommand();
|
||||
|
||||
private:
|
||||
bool onEnabled(Context* context) override;
|
||||
void onExecute(Context* context) override;
|
||||
std::string onGetFriendlyName() const override;
|
||||
|
||||
void copyCels(Tx& tx,
|
||||
Layer* srcLayer,
|
||||
Layer* newLayer);
|
||||
};
|
||||
|
||||
ConvertLayerCommand::ConvertLayerCommand()
|
||||
: CommandWithNewParams<ConvertLayerParams>(CommandId::ConvertLayer(), CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
bool ConvertLayerCommand::onEnabled(Context* ctx)
|
||||
{
|
||||
if (!ctx->checkFlags(ContextFlags::ActiveDocumentIsWritable |
|
||||
ContextFlags::HasActiveSprite |
|
||||
ContextFlags::HasActiveLayer |
|
||||
ContextFlags::ActiveLayerIsVisible |
|
||||
ContextFlags::ActiveLayerIsEditable))
|
||||
return false;
|
||||
|
||||
// TODO add support to convert reference layers into regular layers or tilemaps
|
||||
if (ctx->checkFlags(ContextFlags::ActiveLayerIsReference))
|
||||
return false;
|
||||
|
||||
switch (params().to()) {
|
||||
|
||||
case ConvertLayerParam::Background:
|
||||
return
|
||||
// Doesn't have a background layer
|
||||
!ctx->checkFlags(ContextFlags::HasBackgroundLayer) &&
|
||||
// Convert a regular layer or tilemap into background
|
||||
ctx->checkFlags(ContextFlags::ActiveLayerIsImage) &&
|
||||
// TODO add support for background tliemaps
|
||||
!ctx->checkFlags(ContextFlags::ActiveLayerIsTilemap);
|
||||
|
||||
case ConvertLayerParam::Layer:
|
||||
return
|
||||
// Convert a background layer into a transparent layer
|
||||
ctx->checkFlags(ContextFlags::ActiveLayerIsImage |
|
||||
ContextFlags::ActiveLayerIsBackground) ||
|
||||
// or a tilemap into a regular layer
|
||||
ctx->checkFlags(ContextFlags::ActiveLayerIsTilemap);
|
||||
|
||||
case ConvertLayerParam::Tilemap:
|
||||
return
|
||||
ctx->checkFlags(ContextFlags::ActiveLayerIsImage) &&
|
||||
!ctx->checkFlags(ContextFlags::ActiveLayerIsTilemap) &&
|
||||
// TODO add support for background tliemaps
|
||||
!ctx->checkFlags(ContextFlags::ActiveLayerIsBackground);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ConvertLayerCommand::onExecute(Context* ctx)
|
||||
{
|
||||
ContextWriter writer(ctx);
|
||||
Doc* document(writer.document());
|
||||
{
|
||||
Tx tx(ctx, friendlyName());
|
||||
Site site = ctx->activeSite();
|
||||
Sprite* sprite = site.sprite();
|
||||
Layer* srcLayer = site.layer();
|
||||
|
||||
switch (params().to()) {
|
||||
|
||||
case ConvertLayerParam::Background:
|
||||
// Layer -> Background
|
||||
if (srcLayer->isTransparent()) {
|
||||
ASSERT(srcLayer->isImage());
|
||||
tx(new cmd::BackgroundFromLayer(static_cast<LayerImage*>(srcLayer)));
|
||||
}
|
||||
// Tilemap -> Background
|
||||
else if (srcLayer->isTilemap()) {
|
||||
auto newLayer = new LayerImage(sprite);
|
||||
newLayer->configureAsBackground();
|
||||
newLayer->setName(Strings::commands_NewFile_BackgroundLayer());
|
||||
newLayer->setContinuous(srcLayer->isContinuous());
|
||||
tx(new cmd::AddLayer(srcLayer->parent(), newLayer, srcLayer));
|
||||
|
||||
CelList srcCels;
|
||||
srcLayer->getCels(srcCels);
|
||||
for (Cel* srcCel : srcCels)
|
||||
create_cel_copy(tx, srcCel, sprite, newLayer, srcCel->frame());
|
||||
|
||||
tx(new cmd::RemoveLayer(srcLayer));
|
||||
}
|
||||
break;
|
||||
|
||||
case ConvertLayerParam::Layer:
|
||||
// Background -> Layer
|
||||
if (srcLayer->isBackground()) {
|
||||
tx(new cmd::LayerFromBackground(srcLayer));
|
||||
}
|
||||
// Background -> Tilemap
|
||||
else if (srcLayer->isTilemap()) {
|
||||
auto newLayer = new LayerImage(sprite);
|
||||
newLayer->setName(srcLayer->name());
|
||||
newLayer->setContinuous(srcLayer->isContinuous());
|
||||
tx(new cmd::AddLayer(srcLayer->parent(), newLayer, srcLayer));
|
||||
|
||||
copyCels(tx, srcLayer, newLayer);
|
||||
|
||||
tx(new cmd::RemoveLayer(srcLayer));
|
||||
}
|
||||
break;
|
||||
|
||||
case ConvertLayerParam::Tilemap:
|
||||
// Background or Transparent Layer -> Tilemap
|
||||
if (srcLayer->isImage() &&
|
||||
(srcLayer->isBackground() ||
|
||||
srcLayer->isTransparent())) {
|
||||
auto tileset = new Tileset(sprite, site.grid(), 1);
|
||||
|
||||
auto addTileset = new cmd::AddTileset(sprite, tileset);
|
||||
tx(addTileset);
|
||||
tileset_index tsi = addTileset->tilesetIndex();
|
||||
|
||||
auto newLayer = new LayerTilemap(sprite, tsi);
|
||||
newLayer->setName(srcLayer->name());
|
||||
newLayer->setContinuous(srcLayer->isContinuous());
|
||||
tx(new cmd::AddLayer(srcLayer->parent(), newLayer, srcLayer));
|
||||
|
||||
copyCels(tx, srcLayer, newLayer);
|
||||
|
||||
tx(new cmd::RemoveLayer(srcLayer));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
tx.commit();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
if (ctx->isUIAvailable())
|
||||
update_screen_for_document(document);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConvertLayerCommand::copyCels(Tx& tx,
|
||||
Layer* srcLayer,
|
||||
Layer* newLayer)
|
||||
{
|
||||
std::map<doc::ObjectId, doc::Cel*> linkedCels;
|
||||
|
||||
CelList srcCels;
|
||||
srcLayer->getCels(srcCels);
|
||||
for (Cel* srcCel : srcCels) {
|
||||
frame_t frame = srcCel->frame();
|
||||
|
||||
// Keep linked cels in the new layer
|
||||
Cel* linkedSrcCel = srcCel->link();
|
||||
if (linkedSrcCel) {
|
||||
auto it = linkedCels.find(linkedSrcCel->id());
|
||||
if (it != linkedCels.end()) {
|
||||
tx(new cmd::CopyCel(
|
||||
newLayer, linkedSrcCel->frame(),
|
||||
newLayer, frame, true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Cel* newCel = create_cel_copy(tx, srcCel, srcLayer->sprite(), newLayer, frame);
|
||||
tx(new cmd::AddCel(newLayer, newCel));
|
||||
|
||||
linkedCels[srcCel->id()] = newCel;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ConvertLayerCommand::onGetFriendlyName() const
|
||||
{
|
||||
switch (params().to()) {
|
||||
case ConvertLayerParam::Background: return Strings::commands_ConvertLayer_Background(); break;
|
||||
case ConvertLayerParam::Layer: return Strings::commands_ConvertLayer_Layer(); break;
|
||||
case ConvertLayerParam::Tilemap: return Strings::commands_ConvertLayer_Tilemap(); break;
|
||||
default: return getBaseFriendlyName();
|
||||
}
|
||||
}
|
||||
|
||||
Command* CommandFactory::createConvertLayerCommand()
|
||||
{
|
||||
return new ConvertLayerCommand;
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019-2020 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2021 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -87,8 +87,12 @@ bool AppMenuItem::onProcessMessage(Message* msg)
|
||||
switch (msg->type()) {
|
||||
|
||||
case kCloseMessage:
|
||||
// disable the menu (the keyboard shortcuts are processed by "manager_msg_proc")
|
||||
setEnabled(false);
|
||||
// Don't disable items with submenus
|
||||
if (!hasSubmenu()) {
|
||||
// Disable the menu item (the keyboard shortcuts are processed
|
||||
// by "manager_msg_proc")
|
||||
setEnabled(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user