[lua] Add app.command.ImportSpriteSheet()

Feature request: https://community.aseprite.org/t/8482
This commit is contained in:
David Capello 2021-04-09 17:28:20 -03:00
parent 3769d91125
commit 2df3cd8a80
4 changed files with 94 additions and 41 deletions

View File

@ -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
@ -231,7 +231,6 @@ if(ENABLE_UI)
commands/cmd_goto_tab.cpp
commands/cmd_grid.cpp
commands/cmd_home.cpp
commands/cmd_import_sprite_sheet.cpp
commands/cmd_invert_mask.cpp
commands/cmd_keyboard_shortcuts.cpp
commands/cmd_launch.cpp
@ -503,6 +502,7 @@ add_library(app-lib
commands/cmd_export_sprite_sheet.cpp
commands/cmd_flatten_layers.cpp
commands/cmd_flip.cpp
commands/cmd_import_sprite_sheet.cpp
commands/cmd_layer_from_background.cpp
commands/cmd_load_palette.cpp
commands/cmd_merge_down_layer.cpp

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2021 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This program is distributed under the terms of
@ -12,7 +12,7 @@
#include "app/app.h"
#include "app/commands/command.h"
#include "app/commands/commands.h"
#include "app/commands/params.h"
#include "app/commands/new_params.h"
#include "app/context.h"
#include "app/context_access.h"
#include "app/doc_access.h"
@ -44,6 +44,14 @@ namespace app {
using namespace ui;
struct ImportSpriteSheetParams : public NewParams {
Param<bool> ui { this, true, "ui" };
Param<app::SpriteSheetType> type { this, app::SpriteSheetType::None, "type" };
Param<gfx::Rect> frameBounds { this, gfx::Rect(0, 0, 0, 0), "frameBounds" };
Param<gfx::Size> padding { this, gfx::Size(0, 0), "padding" };
Param<bool> partialTiles { this, false, "partialTiles" };
};
class ImportSpriteSheetWindow : public app::gen::ImportSpriteSheet
, public SelectBoxDelegate {
public:
@ -127,6 +135,17 @@ public:
return m_padding;
}
void updateParams(ImportSpriteSheetParams& params) {
params.type(sheetTypeValue());
params.frameBounds(frameBounds());
params.partialTiles(partialTilesValue());
if (paddingEnabledValue())
params.padding(paddingThickness());
else
params.padding(gfx::Size(0, 0));
}
protected:
void onSheetTypeChange() {
@ -372,7 +391,7 @@ private:
DocumentPreferences* m_docPref;
};
class ImportSpriteSheetCommand : public Command {
class ImportSpriteSheetCommand : public CommandWithNewParams<ImportSpriteSheetParams> {
public:
ImportSpriteSheetCommand();
@ -381,29 +400,44 @@ protected:
};
ImportSpriteSheetCommand::ImportSpriteSheetCommand()
: Command(CommandId::ImportSpriteSheet(), CmdRecordableFlag)
: CommandWithNewParams(CommandId::ImportSpriteSheet(), CmdRecordableFlag)
{
}
void ImportSpriteSheetCommand::onExecute(Context* context)
{
ImportSpriteSheetWindow window(context);
Doc* document;
auto& params = this->params();
window.openWindowInForeground();
if (!window.ok())
return;
#ifdef ENABLE_UI
if (context->isUIAvailable() && params.ui()) {
// TODO use params as input values for the ImportSpriteSheetWindow
Doc* document = window.document();
DocumentPreferences* docPref = window.docPref();
gfx::Rect frameBounds = window.frameBounds();
gfx::Size padThickness = window.paddingThickness();
bool partialTiles = window.partialTilesValue();
bool paddingEnable = window.paddingEnabledValue();
auto sheetType = window.sheetTypeValue();
ImportSpriteSheetWindow window(context);
window.openWindowInForeground();
if (!window.ok())
return;
ASSERT(document);
if (!document)
return;
document = window.document();
if (!document)
return;
window.updateParams(params);
DocumentPreferences* docPref = window.docPref();
docPref->importSpriteSheet.type(params.type());
docPref->importSpriteSheet.bounds(params.frameBounds());
docPref->importSpriteSheet.partialTiles(params.partialTiles());
docPref->importSpriteSheet.paddingBounds(params.padding());
docPref->importSpriteSheet.paddingEnabled(window.paddingEnabledValue());
}
else // We import the sprite sheet from the active document if there is no UI
#endif
{
document = context->activeDocument();
if (!document)
return;
}
// The list of frames imported from the sheet
std::vector<ImageRef> animation;
@ -411,39 +445,44 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
try {
Sprite* sprite = document->sprite();
frame_t currentFrame = context->activeSite().frame();
gfx::Rect frameBounds = params.frameBounds();
const gfx::Size padding = params.padding();
render::Render render;
render.setNewBlend(Preferences::instance().experimental.newBlend());
if (frameBounds.isEmpty())
frameBounds = sprite->bounds();
// Each sprite in the sheet
std::vector<gfx::Rect> tileRects;
int widthStop = sprite->width();
int heightStop = sprite->height();
if (partialTiles) {
if (params.partialTiles()) {
widthStop += frameBounds.w-1;
heightStop += frameBounds.h-1;
}
switch (sheetType) {
switch (params.type()) {
case app::SpriteSheetType::Horizontal:
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.w) {
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padding.w) {
tileRects.push_back(gfx::Rect(x, frameBounds.y, frameBounds.w, frameBounds.h));
}
break;
case app::SpriteSheetType::Vertical:
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.h) {
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padding.h) {
tileRects.push_back(gfx::Rect(frameBounds.x, y, frameBounds.w, frameBounds.h));
}
break;
case app::SpriteSheetType::Rows:
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.h) {
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.w) {
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padding.h) {
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padding.w) {
tileRects.push_back(gfx::Rect(x, y, frameBounds.w, frameBounds.h));
}
}
break;
case app::SpriteSheetType::Columns:
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padThickness.w) {
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padThickness.h) {
for (int x=frameBounds.x; x+frameBounds.w<=widthStop; x+=frameBounds.w+padding.w) {
for (int y=frameBounds.y; y+frameBounds.h<=heightStop; y+=frameBounds.h+padding.h) {
tileRects.push_back(gfx::Rect(x, y, frameBounds.w, frameBounds.h));
}
}
@ -504,21 +543,15 @@ void ImportSpriteSheetCommand::onExecute(Context* context)
api.setSpriteSize(sprite, frameBounds.w, frameBounds.h);
tx.commit();
ASSERT(docPref);
if (docPref) {
docPref->importSpriteSheet.type(sheetType);
docPref->importSpriteSheet.bounds(frameBounds);
docPref->importSpriteSheet.partialTiles(partialTiles);
docPref->importSpriteSheet.paddingBounds(padThickness);
docPref->importSpriteSheet.paddingEnabled(paddingEnable);
}
}
catch (...) {
throw;
}
update_screen_for_document(document);
#ifdef ENABLE_UI
if (context->isUIAvailable())
update_screen_for_document(document);
#endif
}
Command* CommandFactory::createImportSpriteSheetCommand()

View File

@ -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
@ -22,6 +22,7 @@ FOR_EACH_COMMAND(ExportSpriteSheet)
FOR_EACH_COMMAND(FlattenLayers)
FOR_EACH_COMMAND(Flip)
FOR_EACH_COMMAND(HueSaturation)
FOR_EACH_COMMAND(ImportSpriteSheet)
FOR_EACH_COMMAND(InvertColor)
FOR_EACH_COMMAND(LayerFromBackground)
FOR_EACH_COMMAND(LoadPalette)
@ -86,7 +87,6 @@ FOR_EACH_COMMAND(GotoPreviousLayer)
FOR_EACH_COMMAND(GotoPreviousTab)
FOR_EACH_COMMAND(GridSettings)
FOR_EACH_COMMAND(Home)
FOR_EACH_COMMAND(ImportSpriteSheet)
FOR_EACH_COMMAND(InvertMask)
FOR_EACH_COMMAND(KeyboardShortcuts)
FOR_EACH_COMMAND(Launch)

View File

@ -1,5 +1,5 @@
// Aseprite
// Copyright (C) 2019-2020 Igara Studio S.A.
// Copyright (C) 2019-2021 Igara Studio S.A.
//
// This program is distributed under the terms of
// the End-User License Agreement for Aseprite.
@ -24,6 +24,7 @@
#include "filters/outline_filter.h"
#include "filters/tiled_mode.h"
#include "gfx/rect.h"
#include "gfx/size.h"
#ifdef ENABLE_SCRIPTING
#include "app/script/engine.h"
@ -61,6 +62,19 @@ void Param<std::string>::fromString(const std::string& value)
setValue(value);
}
template<>
void Param<gfx::Size>::fromString(const std::string& value)
{
gfx::Size size;
std::vector<std::string> parts;
base::split_string(value, parts, ",");
if (parts.size() == 2) {
size.w = base::convert_to<int>(parts[0]);
size.h = base::convert_to<int>(parts[1]);
}
setValue(size);
}
template<>
void Param<gfx::Rect>::fromString(const std::string& value)
{
@ -241,6 +255,12 @@ void Param<std::string>::fromLua(lua_State* L, int index)
setValue(std::string());
}
template<>
void Param<gfx::Size>::fromLua(lua_State* L, int index)
{
setValue(script::convert_args_into_size(L, index));
}
template<>
void Param<gfx::Rect>::fromLua(lua_State* L, int index)
{