diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index 9538c2328..5e578947f 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -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 diff --git a/src/app/commands/cmd_import_sprite_sheet.cpp b/src/app/commands/cmd_import_sprite_sheet.cpp index 9a4b2700d..89861bb57 100644 --- a/src/app/commands/cmd_import_sprite_sheet.cpp +++ b/src/app/commands/cmd_import_sprite_sheet.cpp @@ -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 ui { this, true, "ui" }; + Param type { this, app::SpriteSheetType::None, "type" }; + Param frameBounds { this, gfx::Rect(0, 0, 0, 0), "frameBounds" }; + Param padding { this, gfx::Size(0, 0), "padding" }; + Param 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 { 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 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 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() diff --git a/src/app/commands/commands_list.h b/src/app/commands/commands_list.h index 03b5ea124..760f3bbaa 100644 --- a/src/app/commands/commands_list.h +++ b/src/app/commands/commands_list.h @@ -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) diff --git a/src/app/commands/new_params.cpp b/src/app/commands/new_params.cpp index 1281b52b7..0dd0f6309 100644 --- a/src/app/commands/new_params.cpp +++ b/src/app/commands/new_params.cpp @@ -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::fromString(const std::string& value) setValue(value); } +template<> +void Param::fromString(const std::string& value) +{ + gfx::Size size; + std::vector parts; + base::split_string(value, parts, ","); + if (parts.size() == 2) { + size.w = base::convert_to(parts[0]); + size.h = base::convert_to(parts[1]); + } + setValue(size); +} + template<> void Param::fromString(const std::string& value) { @@ -241,6 +255,12 @@ void Param::fromLua(lua_State* L, int index) setValue(std::string()); } +template<> +void Param::fromLua(lua_State* L, int index) +{ + setValue(script::convert_args_into_size(L, index)); +} + template<> void Param::fromLua(lua_State* L, int index) {