mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-29 19:20:09 +00:00
Merge branch 'export' into beta
This commit is contained in:
commit
2f34e25f06
20
data/gui.xml
20
data/gui.xml
@ -455,6 +455,9 @@
|
||||
<key command="NewSpriteFromSelection" shortcut="Ctrl+Alt+N" mac="Cmd+Alt+N" />
|
||||
|
||||
<!-- Commands not associated to menu items and without shortcuts by default -->
|
||||
<key command="ExportSpriteSheet">
|
||||
<param name="source" value="tileset" />
|
||||
</key>
|
||||
<key command="NewLayer">
|
||||
<param name="tilemap" value="true" />
|
||||
</key>
|
||||
@ -669,14 +672,21 @@
|
||||
</menu>
|
||||
<separator />
|
||||
<item command="SaveFile" text="@.file_save" />
|
||||
<item command="SaveFileAs" text="@.file_save_as" />
|
||||
<item command="SaveFileCopyAs" text="@.file_export" group="file_save" />
|
||||
<item command="SaveFileAs" text="@.file_save_as" group="file_save" />
|
||||
<item command="CloseFile" text="@.file_close" />
|
||||
<item command="CloseAllFiles" text="@.file_close_all" group="file_close" />
|
||||
<separator />
|
||||
<item command="ImportSpriteSheet" text="@.file_import_sprite_sheet" group="file_import" />
|
||||
<item command="ExportSpriteSheet" text="@.file_export_sprite_sheet" group="file_export" />
|
||||
<item command="RepeatLastExport" text="@.file_repeat_last_export" />
|
||||
<menu text="@.file_export" group="file_export">
|
||||
<item command="SaveFileCopyAs" text="@.file_export_as" />
|
||||
<item command="ExportSpriteSheet" text="@.file_export_sprite_sheet" group="file_export_1" />
|
||||
<separator />
|
||||
<item command="ExportTileset" text="@.file_export_tileset" group="file_export_2" />
|
||||
<separator />
|
||||
<item command="RepeatLastExport" text="@.file_repeat_last_export" group="file_export_last" />
|
||||
</menu>
|
||||
<menu text="@.file_import" group="file_import">
|
||||
<item command="ImportSpriteSheet" text="@.file_import_sprite_sheet" group="file_import_1" />
|
||||
</menu>
|
||||
<separator id="scripts_menu_separator" />
|
||||
<menu id="scripts_menu" text="@.file_scripts" group="file_scripts">
|
||||
<item command="OpenScriptFolder" text="@.file_open_script_folder" />
|
||||
|
@ -508,6 +508,7 @@
|
||||
<section id="save_copy" canclear="true">
|
||||
<option id="filename" type="std::string" />
|
||||
<option id="resize_scale" type="double" default="1" />
|
||||
<option id="area" type="std::string" />
|
||||
<option id="layer" type="std::string" />
|
||||
<option id="frame_tag" type="std::string" />
|
||||
<option id="ani_dir" type="doc::AniDir" default="doc::AniDir::FORWARD" />
|
||||
@ -539,6 +540,7 @@
|
||||
<option id="frame_tag" type="std::string" />
|
||||
<option id="split_layers" type="bool" default="false" />
|
||||
<option id="split_tags" type="bool" default="false" />
|
||||
<option id="split_grid" type="bool" default="false" />
|
||||
<option id="list_layers" type="bool" default="true" />
|
||||
<option id="list_frame_tags" type="bool" default="true" />
|
||||
<option id="list_slices" type="bool" default="true" />
|
||||
|
@ -307,6 +307,7 @@ DuplicateSprite = Duplicate Sprite
|
||||
DuplicateView = Duplicate View
|
||||
Exit = Exit
|
||||
ExportSpriteSheet = Export Sprite Sheet
|
||||
ExportTileset = Export Tileset
|
||||
Eyedropper = Eyedropper
|
||||
Fill = Fill Selection with Foreground Color
|
||||
FitScreen = Fit on Screen
|
||||
@ -630,6 +631,7 @@ sensors_tweaks = Sensor Threshold
|
||||
title = Export File
|
||||
output_file = Output File:
|
||||
resize = Resize:
|
||||
area = Area:
|
||||
layers = Layers:
|
||||
frames = Frames:
|
||||
anidir = Animation Direction:
|
||||
@ -705,6 +707,7 @@ merge_dups = Merge Duplicates
|
||||
merge_dups_tooltip = Similar frames can use the same sprite sheet rectangular area
|
||||
ignore_empty = Ignore Empty
|
||||
ignore_empty_tooltip = Do not include empty/transparent frames in the sprite sheet
|
||||
source = Source:
|
||||
layers = Layers:
|
||||
split_layers = Split Layers
|
||||
split_layers_tooltip = Generates one sprite for each layer
|
||||
@ -885,12 +888,15 @@ file_no_recent_file = No Recent File
|
||||
file_clear_recent_files = &Clear Recent Files
|
||||
file_save = &Save
|
||||
file_save_as = Save &As...
|
||||
file_export = Expor&t...
|
||||
file_close = &Close
|
||||
file_close_all = Close All
|
||||
file_import_sprite_sheet = &Import Sprite Sheet
|
||||
file_export_sprite_sheet = &Export Sprite Sheet
|
||||
file_export = &Export
|
||||
file_export_as = &Export As...
|
||||
file_export_sprite_sheet = Export &Sprite Sheet
|
||||
file_export_tileset = Export &Tileset
|
||||
file_repeat_last_export = Repeat &Last Export
|
||||
file_import = &Import
|
||||
file_import_sprite_sheet = &Import Sprite Sheet
|
||||
file_scripts = Scri&pts
|
||||
file_open_script_folder = &Open Scripts Folder
|
||||
file_rescan_script_folder = &Rescan Scripts Folder
|
||||
|
@ -9,21 +9,24 @@
|
||||
<button id="output_filename_browse" text="..." style="mini_button" />
|
||||
|
||||
<label id="resize_label" text="@.resize" />
|
||||
<combobox id="resize" editable="true" suffix="%"
|
||||
cell_align="horizontal" cell_hspan="2">
|
||||
<listitem text="25" />
|
||||
<listitem text="50" />
|
||||
<listitem text="100" />
|
||||
<listitem text="200" />
|
||||
<listitem text="300" />
|
||||
<listitem text="400" />
|
||||
<listitem text="500" />
|
||||
<listitem text="600" />
|
||||
<listitem text="700" />
|
||||
<listitem text="800" />
|
||||
<listitem text="900" />
|
||||
<listitem text="1000" />
|
||||
</combobox>
|
||||
<hbox cell_hspan="2" cell_align="horizontal">
|
||||
<combobox id="resize" editable="true" suffix="%" expansive="true">
|
||||
<listitem text="25" />
|
||||
<listitem text="50" />
|
||||
<listitem text="100" />
|
||||
<listitem text="200" />
|
||||
<listitem text="300" />
|
||||
<listitem text="400" />
|
||||
<listitem text="500" />
|
||||
<listitem text="600" />
|
||||
<listitem text="700" />
|
||||
<listitem text="800" />
|
||||
<listitem text="900" />
|
||||
<listitem text="1000" />
|
||||
</combobox>
|
||||
<label id="area_label" text="@.area" />
|
||||
<combobox id="area" text="" cell_align="horizontal" cell_hspan="2" expansive="true" />
|
||||
</hbox>
|
||||
|
||||
<label id="layers_label" text="@.layers" />
|
||||
<combobox id="layers" text="" cell_align="horizontal" cell_hspan="2" />
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!-- Aseprite -->
|
||||
<!-- Copyright (C) 2019 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2019-2022 Igara Studio S.A. -->
|
||||
<!-- Copyright (C) 2001-2018 David Capello -->
|
||||
<gui>
|
||||
<window id="export_sprite_sheet" text="@.title">
|
||||
@ -50,6 +50,10 @@
|
||||
<button id="close_sprite_section" icon="window_close_icon" />
|
||||
</hbox>
|
||||
<grid id="section_sprite" columns="4" expansive="true">
|
||||
<label text="@.source" />
|
||||
<combobox id="source" text="" cell_hspan="2" cell_align="horizontal" />
|
||||
<boxfiller />
|
||||
|
||||
<label text="@.layers" />
|
||||
<combobox id="layers" text="" cell_hspan="2" cell_align="horizontal" />
|
||||
<check id="split_layers" text="@.split_layers" tooltip="@.split_layers_tooltip" tooltip_dir="bottom" />
|
||||
|
@ -570,6 +570,7 @@ add_library(app-lib
|
||||
commands/command.cpp
|
||||
commands/commands.cpp
|
||||
commands/convert_layer.cpp
|
||||
commands/export_tileset.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-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -49,6 +49,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
|
||||
, m_splitLayers(m_po.add("split-layers").description("Save each visible layer of sprites\nas separated images in the sheet\n"))
|
||||
, m_splitTags(m_po.add("split-tags").description("Save each tag as a separated file"))
|
||||
, m_splitSlices(m_po.add("split-slices").description("Save each slice as a separated file"))
|
||||
, m_splitGrid(m_po.add("split-grid").description("Save each grid tile as a separated file"))
|
||||
, m_layer(m_po.add("layer").alias("import-layer").requiresValue("<name>").description("Include just the given layer in the sheet\nor save as operation"))
|
||||
, m_allLayers(m_po.add("all-layers").description("Make all layers visible\nBy default hidden layers will be ignored"))
|
||||
, m_ignoreLayer(m_po.add("ignore-layer").requiresValue("<name>").description("Exclude the given layer in the sheet\nor save as operation"))
|
||||
@ -62,6 +63,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
|
||||
, m_trim(m_po.add("trim").description("Trim whole sprite for --save-as\nor individual frames for --sheet"))
|
||||
, m_trimSprite(m_po.add("trim-sprite").description("Trim the whole sprite (for --save-as and --sheet)"))
|
||||
, m_trimByGrid(m_po.add("trim-by-grid").description("Trim all images by its correspondent grid boundaries before exporting"))
|
||||
, m_extrude(m_po.add("extrude").description("Extrude all images duplicating all edges one pixel"))
|
||||
, m_crop(m_po.add("crop").requiresValue("x,y,width,height").description("Crop all the images to the given rectangle"))
|
||||
, m_slice(m_po.add("slice").requiresValue("<name>").description("Crop the sprite to the given slice area"))
|
||||
, m_filenameFormat(m_po.add("filename-format").requiresValue("<fmt>").description("Special format to generate filenames"))
|
||||
@ -73,6 +75,7 @@ AppOptions::AppOptions(int argc, const char* argv[])
|
||||
, m_listTags(m_po.add("list-tags").description("List tags of the next given sprite\nor include frame tags in JSON data"))
|
||||
, m_listSlices(m_po.add("list-slices").description("List slices of the next given sprite\nor include slices in JSON data"))
|
||||
, m_oneFrame(m_po.add("oneframe").description("Load just the first frame"))
|
||||
, m_exportTileset(m_po.add("export-tileset").description("Export only tilesets from visible tilemap layers"))
|
||||
, m_verbose(m_po.add("verbose").mnemonic('v').description("Explain what is being done"))
|
||||
, m_debug(m_po.add("debug").description("Extreme verbose mode and\ncopy log to desktop"))
|
||||
#ifdef _WIN32
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2018-2019 Igara Studio S.A.
|
||||
// Copyright (C) 2018-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2001-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -65,6 +65,7 @@ public:
|
||||
const Option& splitLayers() const { return m_splitLayers; }
|
||||
const Option& splitTags() const { return m_splitTags; }
|
||||
const Option& splitSlices() const { return m_splitSlices; }
|
||||
const Option& splitGrid() const { return m_splitGrid; }
|
||||
const Option& layer() const { return m_layer; }
|
||||
const Option& allLayers() const { return m_allLayers; }
|
||||
const Option& ignoreLayer() const { return m_ignoreLayer; }
|
||||
@ -78,6 +79,7 @@ public:
|
||||
const Option& trim() const { return m_trim; }
|
||||
const Option& trimSprite() const { return m_trimSprite; }
|
||||
const Option& trimByGrid() const { return m_trimByGrid; }
|
||||
const Option& extrude() const { return m_extrude; }
|
||||
const Option& crop() const { return m_crop; }
|
||||
const Option& slice() const { return m_slice; }
|
||||
const Option& filenameFormat() const { return m_filenameFormat; }
|
||||
@ -89,6 +91,7 @@ public:
|
||||
const Option& listTags() const { return m_listTags; }
|
||||
const Option& listSlices() const { return m_listSlices; }
|
||||
const Option& oneFrame() const { return m_oneFrame; }
|
||||
const Option& exportTileset() const { return m_exportTileset; }
|
||||
|
||||
bool hasExporterParams() const;
|
||||
#ifdef _WIN32
|
||||
@ -131,6 +134,7 @@ private:
|
||||
Option& m_splitLayers;
|
||||
Option& m_splitTags;
|
||||
Option& m_splitSlices;
|
||||
Option& m_splitGrid;
|
||||
Option& m_layer;
|
||||
Option& m_allLayers;
|
||||
Option& m_ignoreLayer;
|
||||
@ -144,6 +148,7 @@ private:
|
||||
Option& m_trim;
|
||||
Option& m_trimSprite;
|
||||
Option& m_trimByGrid;
|
||||
Option& m_extrude;
|
||||
Option& m_crop;
|
||||
Option& m_slice;
|
||||
Option& m_filenameFormat;
|
||||
@ -155,6 +160,7 @@ private:
|
||||
Option& m_listTags;
|
||||
Option& m_listSlices;
|
||||
Option& m_oneFrame;
|
||||
Option& m_exportTileset;
|
||||
|
||||
Option& m_verbose;
|
||||
Option& m_debug;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -19,25 +19,6 @@
|
||||
|
||||
namespace app {
|
||||
|
||||
CliOpenFile::CliOpenFile()
|
||||
{
|
||||
document = nullptr;
|
||||
fromFrame = -1;
|
||||
toFrame = -1;
|
||||
splitLayers = false;
|
||||
splitTags = false;
|
||||
splitSlices = false;
|
||||
allLayers = false;
|
||||
listLayers = false;
|
||||
listTags = false;
|
||||
listSlices = false;
|
||||
ignoreEmpty = false;
|
||||
trim = false;
|
||||
trimByGrid = false;
|
||||
oneFrame = false;
|
||||
crop = gfx::Rect();
|
||||
}
|
||||
|
||||
FileOpROI CliOpenFile::roi() const
|
||||
{
|
||||
ASSERT(document);
|
||||
@ -47,6 +28,7 @@ FileOpROI CliOpenFile::roi() const
|
||||
selFrames.insert(fromFrame, toFrame);
|
||||
|
||||
return FileOpROI(document,
|
||||
gfx::Rect(),
|
||||
slice,
|
||||
tag,
|
||||
selFrames,
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2017 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -21,29 +21,30 @@ namespace app {
|
||||
class FileOpROI;
|
||||
|
||||
struct CliOpenFile {
|
||||
Doc* document;
|
||||
Doc* document = nullptr;
|
||||
std::string filename;
|
||||
std::string filenameFormat;
|
||||
std::string tag;
|
||||
std::string slice;
|
||||
std::vector<std::string> includeLayers;
|
||||
std::vector<std::string> excludeLayers;
|
||||
doc::frame_t fromFrame, toFrame;
|
||||
bool splitLayers;
|
||||
bool splitTags;
|
||||
bool splitSlices;
|
||||
bool allLayers;
|
||||
bool listLayers;
|
||||
bool listTags;
|
||||
bool listSlices;
|
||||
bool ignoreEmpty;
|
||||
bool trim;
|
||||
bool trimByGrid;
|
||||
bool oneFrame;
|
||||
doc::frame_t fromFrame = -1;
|
||||
doc::frame_t toFrame = -1;
|
||||
bool splitLayers = false;
|
||||
bool splitTags = false;
|
||||
bool splitSlices = false;
|
||||
bool splitGrid = false;
|
||||
bool allLayers = false;
|
||||
bool listLayers = false;
|
||||
bool listTags = false;
|
||||
bool listSlices = false;
|
||||
bool ignoreEmpty = false;
|
||||
bool trim = false;
|
||||
bool trimByGrid = false;
|
||||
bool oneFrame = false;
|
||||
bool exportTileset = false;
|
||||
gfx::Rect crop;
|
||||
|
||||
CliOpenFile();
|
||||
|
||||
bool hasTag() const {
|
||||
return (!tag.empty());
|
||||
}
|
||||
|
@ -283,6 +283,10 @@ int CliProcessor::process(Context* ctx)
|
||||
else if (opt == &m_options.splitSlices()) {
|
||||
cof.splitSlices = true;
|
||||
}
|
||||
// --split-grid
|
||||
else if (opt == &m_options.splitGrid()) {
|
||||
cof.splitGrid = true;
|
||||
}
|
||||
// --layer <layer-name>
|
||||
else if (opt == &m_options.layer()) {
|
||||
cof.includeLayers.push_back(value.value());
|
||||
@ -357,6 +361,11 @@ int CliProcessor::process(Context* ctx)
|
||||
m_exporter->setTrimByGrid(true);
|
||||
}
|
||||
}
|
||||
// --extrude
|
||||
else if (opt == &m_options.extrude()) {
|
||||
if (m_exporter)
|
||||
m_exporter->setExtrude(true);
|
||||
}
|
||||
// --crop x,y,width,height
|
||||
else if (opt == &m_options.crop()) {
|
||||
std::vector<std::string> parts;
|
||||
@ -578,6 +587,10 @@ int CliProcessor::process(Context* ctx)
|
||||
else if (opt == &m_options.oneFrame()) {
|
||||
cof.oneFrame = true;
|
||||
}
|
||||
// --export-tileset
|
||||
else if (opt == &m_options.exportTileset()) {
|
||||
cof.exportTileset = true;
|
||||
}
|
||||
}
|
||||
// File names aren't associated to any option
|
||||
else {
|
||||
@ -677,12 +690,20 @@ bool CliProcessor::openFile(Context* ctx, CliOpenFile& cof)
|
||||
if (cof.hasLayersFilter())
|
||||
filterLayers(doc->sprite(), cof, filteredLayers);
|
||||
|
||||
m_exporter->addDocumentSamples(
|
||||
doc, tag,
|
||||
cof.splitLayers,
|
||||
cof.splitTags,
|
||||
(cof.hasLayersFilter() ? &filteredLayers: nullptr),
|
||||
(!selFrames.empty() ? &selFrames: nullptr));
|
||||
if (cof.exportTileset) {
|
||||
m_exporter->addTilesetsSamples(
|
||||
doc,
|
||||
(cof.hasLayersFilter() ? &filteredLayers: nullptr));
|
||||
}
|
||||
else {
|
||||
m_exporter->addDocumentSamples(
|
||||
doc, tag,
|
||||
cof.splitLayers,
|
||||
cof.splitTags,
|
||||
cof.splitGrid,
|
||||
(cof.hasLayersFilter() ? &filteredLayers: nullptr),
|
||||
(!selFrames.empty() ? &selFrames: nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
#endif
|
||||
|
||||
#include "app/app.h"
|
||||
#include "app/commands/new_params.h"
|
||||
#include "app/commands/cmd_export_sprite_sheet.h"
|
||||
#include "app/context.h"
|
||||
#include "app/context_access.h"
|
||||
#include "app/doc.h"
|
||||
@ -37,7 +37,10 @@
|
||||
#include "base/string.h"
|
||||
#include "base/thread.h"
|
||||
#include "doc/layer.h"
|
||||
#include "doc/layer_tilemap.h"
|
||||
#include "doc/tag.h"
|
||||
#include "doc/tileset.h"
|
||||
#include "doc/tilesets.h"
|
||||
#include "fmt/format.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/system.h"
|
||||
@ -53,37 +56,6 @@ using namespace ui;
|
||||
|
||||
namespace {
|
||||
|
||||
struct ExportSpriteSheetParams : public NewParams {
|
||||
Param<bool> ui { this, true, "ui" };
|
||||
Param<bool> askOverwrite { this, true, { "askOverwrite", "ask-overwrite" } };
|
||||
Param<app::SpriteSheetType> type { this, app::SpriteSheetType::None, "type" };
|
||||
Param<int> columns { this, 0, "columns" };
|
||||
Param<int> rows { this, 0, "rows" };
|
||||
Param<int> width { this, 0, "width" };
|
||||
Param<int> height { this, 0, "height" };
|
||||
Param<std::string> textureFilename { this, std::string(), "textureFilename" };
|
||||
Param<std::string> dataFilename { this, std::string(), "dataFilename" };
|
||||
Param<SpriteSheetDataFormat> dataFormat { this, SpriteSheetDataFormat::Default, "dataFormat" };
|
||||
Param<std::string> filenameFormat { this, std::string(), "filenameFormat" };
|
||||
Param<int> borderPadding { this, 0, "borderPadding" };
|
||||
Param<int> shapePadding { this, 0, "shapePadding" };
|
||||
Param<int> innerPadding { this, 0, "innerPadding" };
|
||||
Param<bool> trimSprite { this, false, "trimSprite" };
|
||||
Param<bool> trim { this, false, "trim" };
|
||||
Param<bool> trimByGrid { this, false, "trimByGrid" };
|
||||
Param<bool> extrude { this, false, "extrude" };
|
||||
Param<bool> ignoreEmpty { this, false, "ignoreEmpty" };
|
||||
Param<bool> mergeDuplicates { this, false, "mergeDuplicates" };
|
||||
Param<bool> openGenerated { this, false, "openGenerated" };
|
||||
Param<std::string> layer { this, std::string(), "layer" };
|
||||
Param<std::string> tag { this, std::string(), "tag" };
|
||||
Param<bool> splitLayers { this, false, "splitLayers" };
|
||||
Param<bool> splitTags { this, false, "splitTags" };
|
||||
Param<bool> listLayers { this, true, "listLayers" };
|
||||
Param<bool> listTags { this, true, "listTags" };
|
||||
Param<bool> listSlices { this, true, "listSlices" };
|
||||
};
|
||||
|
||||
#ifdef ENABLE_UI
|
||||
|
||||
enum Section {
|
||||
@ -93,6 +65,12 @@ enum Section {
|
||||
kSectionOutput,
|
||||
};
|
||||
|
||||
enum Source {
|
||||
kSource_Sprite,
|
||||
kSource_SpriteGrid,
|
||||
kSource_Tilesets,
|
||||
};
|
||||
|
||||
enum ConstraintType {
|
||||
kConstraintType_None,
|
||||
kConstraintType_Cols,
|
||||
@ -194,9 +172,11 @@ Doc* generate_sprite_sheet_from_params(
|
||||
const bool mergeDuplicates = params.mergeDuplicates();
|
||||
const bool splitLayers = params.splitLayers();
|
||||
const bool splitTags = params.splitTags();
|
||||
const bool splitGrid = params.splitGrid();
|
||||
const bool listLayers = params.listLayers();
|
||||
const bool listTags = params.listTags();
|
||||
const bool listSlices = params.listSlices();
|
||||
const bool fromTilesets = params.fromTilesets();
|
||||
|
||||
SelectedFrames selFrames;
|
||||
Tag* tag = calculate_selected_frames(site, tagName, selFrames);
|
||||
@ -226,10 +206,20 @@ Doc* generate_sprite_sheet_from_params(
|
||||
}
|
||||
|
||||
exporter.reset();
|
||||
exporter.addDocumentSamples(
|
||||
doc, tag, splitLayers, splitTags,
|
||||
!selLayers.empty() ? &selLayers: nullptr,
|
||||
!selFrames.empty() ? &selFrames: nullptr);
|
||||
|
||||
// Use each tileset from tilemap layers as a sprite
|
||||
if (fromTilesets) {
|
||||
exporter.addTilesetsSamples(
|
||||
doc,
|
||||
!selLayers.empty() ? &selLayers: nullptr);
|
||||
}
|
||||
// Use the whole canvas as a sprite
|
||||
else {
|
||||
exporter.addDocumentSamples(
|
||||
doc, tag, splitLayers, splitTags, splitGrid,
|
||||
!selLayers.empty() ? &selLayers: nullptr,
|
||||
!selFrames.empty() ? &selFrames: nullptr);
|
||||
}
|
||||
|
||||
if (saveData) {
|
||||
if (!filename.empty())
|
||||
@ -373,6 +363,18 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
static_assert(kSource_Sprite == 0 &&
|
||||
kSource_SpriteGrid == 1 &&
|
||||
kSource_Tilesets == 2,
|
||||
"Source enum has changed");
|
||||
source()->addItem(new ListItem("Sprite"));
|
||||
source()->addItem(new ListItem("Sprite Grid"));
|
||||
source()->addItem(new ListItem("Tilesets"));
|
||||
if (params.splitGrid())
|
||||
source()->setSelectedItemIndex(int(kSource_SpriteGrid));
|
||||
else if (params.fromTilesets())
|
||||
source()->setSelectedItemIndex(int(kSource_Tilesets));
|
||||
|
||||
fill_layers_combobox(
|
||||
m_sprite, layers(), params.layer());
|
||||
|
||||
@ -446,6 +448,7 @@ public:
|
||||
trimSpriteEnabled()->Click.connect([this]{ onTrimEnabledChange(); });
|
||||
trimEnabled()->Click.connect([this]{ onTrimEnabledChange(); });
|
||||
gridTrimEnabled()->Click.connect([this]{ generatePreview(); });
|
||||
source()->Change.connect([this]{ generatePreview(); });
|
||||
layers()->Change.connect([this]{ generatePreview(); });
|
||||
splitLayers()->Click.connect([this]{ onSplitLayersOrFrames(); });
|
||||
splitTags()->Click.connect([this]{ onSplitLayersOrFrames(); });
|
||||
@ -536,6 +539,8 @@ public:
|
||||
params.listLayers (listLayersValue());
|
||||
params.listTags (listTagsValue());
|
||||
params.listSlices (listSlicesValue());
|
||||
params.splitGrid (source()->getSelectedItemIndex() == int(kSource_SpriteGrid));
|
||||
params.fromTilesets (source()->getSelectedItemIndex() == int(kSource_Tilesets));
|
||||
}
|
||||
|
||||
private:
|
||||
@ -727,6 +732,10 @@ private:
|
||||
return splitTags()->isSelected();
|
||||
}
|
||||
|
||||
bool splitGridValue() const {
|
||||
return (source()->getSelectedItemIndex() == int(kSource_SpriteGrid));
|
||||
}
|
||||
|
||||
bool listLayersValue() const {
|
||||
return listLayers()->isSelected();
|
||||
}
|
||||
@ -1169,16 +1178,8 @@ private:
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
class ExportSpriteSheetCommand : public CommandWithNewParams<ExportSpriteSheetParams> {
|
||||
public:
|
||||
ExportSpriteSheetCommand();
|
||||
protected:
|
||||
bool onEnabled(Context* context) override;
|
||||
void onExecute(Context* context) override;
|
||||
};
|
||||
|
||||
ExportSpriteSheetCommand::ExportSpriteSheetCommand()
|
||||
: CommandWithNewParams(CommandId::ExportSpriteSheet(), CmdRecordableFlag)
|
||||
ExportSpriteSheetCommand::ExportSpriteSheetCommand(const char* id)
|
||||
: CommandWithNewParams(id, CmdRecordableFlag)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1236,6 +1237,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
if (!params.tag.isSet()) params.tag( defPref.spriteSheet.frameTag());
|
||||
if (!params.splitLayers.isSet()) params.splitLayers( defPref.spriteSheet.splitLayers());
|
||||
if (!params.splitTags.isSet()) params.splitTags( defPref.spriteSheet.splitTags());
|
||||
if (!params.splitGrid.isSet()) params.splitGrid( defPref.spriteSheet.splitGrid());
|
||||
if (!params.listLayers.isSet()) params.listLayers( defPref.spriteSheet.listLayers());
|
||||
if (!params.listTags.isSet()) params.listTags( defPref.spriteSheet.listFrameTags());
|
||||
if (!params.listSlices.isSet()) params.listSlices( defPref.spriteSheet.listSlices());
|
||||
@ -1282,6 +1284,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
|
||||
docPref.spriteSheet.frameTag (params.tag());
|
||||
docPref.spriteSheet.splitLayers (params.splitLayers());
|
||||
docPref.spriteSheet.splitTags (params.splitTags());
|
||||
docPref.spriteSheet.splitGrid (params.splitGrid());
|
||||
docPref.spriteSheet.listLayers (params.listLayers());
|
||||
docPref.spriteSheet.listFrameTags (params.listTags());
|
||||
docPref.spriteSheet.listSlices (params.listSlices());
|
||||
|
63
src/app/commands/cmd_export_sprite_sheet.h
Normal file
63
src/app/commands/cmd_export_sprite_sheet.h
Normal file
@ -0,0 +1,63 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
|
||||
#ifndef APP_COMMANDS_CMD_EXPORT_SPRITE_SHEET_H_INCLUDED
|
||||
#define APP_COMMANDS_CMD_EXPORT_SPRITE_SHEET_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "app/commands/new_params.h"
|
||||
#include "app/sprite_sheet_data_format.h"
|
||||
#include "app/sprite_sheet_type.h"
|
||||
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
namespace app {
|
||||
|
||||
struct ExportSpriteSheetParams : public NewParams {
|
||||
Param<bool> ui { this, true, "ui" };
|
||||
Param<bool> askOverwrite { this, true, { "askOverwrite", "ask-overwrite" } };
|
||||
Param<app::SpriteSheetType> type { this, app::SpriteSheetType::None, "type" };
|
||||
Param<int> columns { this, 0, "columns" };
|
||||
Param<int> rows { this, 0, "rows" };
|
||||
Param<int> width { this, 0, "width" };
|
||||
Param<int> height { this, 0, "height" };
|
||||
Param<std::string> textureFilename { this, std::string(), "textureFilename" };
|
||||
Param<std::string> dataFilename { this, std::string(), "dataFilename" };
|
||||
Param<SpriteSheetDataFormat> dataFormat { this, SpriteSheetDataFormat::Default, "dataFormat" };
|
||||
Param<std::string> filenameFormat { this, std::string(), "filenameFormat" };
|
||||
Param<int> borderPadding { this, 0, "borderPadding" };
|
||||
Param<int> shapePadding { this, 0, "shapePadding" };
|
||||
Param<int> innerPadding { this, 0, "innerPadding" };
|
||||
Param<bool> trimSprite { this, false, "trimSprite" };
|
||||
Param<bool> trim { this, false, "trim" };
|
||||
Param<bool> trimByGrid { this, false, "trimByGrid" };
|
||||
Param<bool> extrude { this, false, "extrude" };
|
||||
Param<bool> ignoreEmpty { this, false, "ignoreEmpty" };
|
||||
Param<bool> mergeDuplicates { this, false, "mergeDuplicates" };
|
||||
Param<bool> openGenerated { this, false, "openGenerated" };
|
||||
Param<std::string> layer { this, std::string(), "layer" };
|
||||
Param<std::string> tag { this, std::string(), "tag" };
|
||||
Param<bool> splitLayers { this, false, "splitLayers" };
|
||||
Param<bool> splitTags { this, false, "splitTags" };
|
||||
Param<bool> splitGrid { this, false, "splitGrid" };
|
||||
Param<bool> listLayers { this, true, "listLayers" };
|
||||
Param<bool> listTags { this, true, "listTags" };
|
||||
Param<bool> listSlices { this, true, "listSlices" };
|
||||
Param<bool> fromTilesets { this, false, "fromTilesets" };
|
||||
};
|
||||
|
||||
class ExportSpriteSheetCommand : public CommandWithNewParams<ExportSpriteSheetParams> {
|
||||
public:
|
||||
ExportSpriteSheetCommand(const char* id = CommandId::ExportSpriteSheet());
|
||||
protected:
|
||||
bool onEnabled(Context* context) override;
|
||||
void onExecute(Context* context) override;
|
||||
};
|
||||
|
||||
} // namespace app
|
||||
|
||||
#endif // APP_COMMANDS_CMD_EXPORT_SPRITE_SHEET_H_INCLUDED
|
@ -37,6 +37,7 @@
|
||||
#include "base/fs.h"
|
||||
#include "base/scoped_value.h"
|
||||
#include "base/thread.h"
|
||||
#include "doc/mask.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tag.h"
|
||||
#include "fmt/format.h"
|
||||
@ -204,7 +205,12 @@ void SaveFileBaseCommand::saveDocumentInBackground(
|
||||
}
|
||||
}
|
||||
|
||||
FileOpROI roi(document, params().slice(), params().tag(),
|
||||
gfx::Rect bounds;
|
||||
if (params().bounds.isSet())
|
||||
bounds = params().bounds();
|
||||
|
||||
FileOpROI roi(document, bounds,
|
||||
params().slice(), params().tag(),
|
||||
m_selFrames, m_adjustFramesByTag);
|
||||
|
||||
std::unique_ptr<FileOp> fop(
|
||||
@ -346,6 +352,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
std::string frames = kAllFrames;
|
||||
bool applyPixelRatio = false;
|
||||
double scale = params().scale();
|
||||
gfx::Rect bounds = params().bounds();
|
||||
doc::AniDir aniDirValue = params().aniDir();
|
||||
bool isForTwitter = false;
|
||||
|
||||
@ -382,6 +389,13 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
if (params().scale.isSet()) win.setResizeScale(scale);
|
||||
if (params().aniDir.isSet()) win.setAniDir(aniDirValue);
|
||||
|
||||
if (params().slice.isSet()) win.setArea(params().slice());
|
||||
else if (params().bounds.isSet() &&
|
||||
doc->isMaskVisible() &&
|
||||
doc->mask()->bounds() == params().bounds()) {
|
||||
win.setArea(kSelectedCanvas);
|
||||
}
|
||||
|
||||
win.remapWindow();
|
||||
load_window_pos(&win, "ExportFile");
|
||||
again:;
|
||||
@ -410,6 +424,9 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
layers = win.layersValue();
|
||||
frames = win.framesValue();
|
||||
scale = win.resizeValue();
|
||||
params().slice(win.areaValue()); // Set slice
|
||||
if (win.areaValue() == kSelectedCanvas && doc->isMaskVisible())
|
||||
bounds = doc->mask()->bounds();
|
||||
applyPixelRatio = win.applyPixelRatio();
|
||||
aniDirValue = win.aniDirValue();
|
||||
isForTwitter = win.isForTwitter();
|
||||
@ -480,8 +497,10 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
|
||||
m_adjustFramesByTag = false;
|
||||
}
|
||||
|
||||
// Set ani dir
|
||||
// Set other parameters
|
||||
params().aniDir(aniDirValue);
|
||||
if (!bounds.isEmpty())
|
||||
params().bounds(bounds);
|
||||
|
||||
// TODO This should be set as options for the specific encoder
|
||||
GifEncoderDurationFix fixGif(isForTwitter);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "doc/anidir.h"
|
||||
#include "doc/selected_frames.h"
|
||||
#include "gfx/point.h"
|
||||
#include "gfx/rect.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -31,6 +32,7 @@ namespace app {
|
||||
Param<doc::frame_t> toFrame { this, 0, { "toFrame", "to-frame" } };
|
||||
Param<bool> ignoreEmpty { this, false, "ignoreEmpty" };
|
||||
Param<double> scale { this, 1.0, "scale" };
|
||||
Param<gfx::Rect> bounds { this, gfx::Rect(), "bounds" };
|
||||
};
|
||||
|
||||
class SaveFileBaseCommand : public CommandWithNewParams<SaveFileParams> {
|
||||
|
@ -21,6 +21,7 @@ FOR_EACH_COMMAND(CopyTiles)
|
||||
FOR_EACH_COMMAND(CropSprite)
|
||||
FOR_EACH_COMMAND(Despeckle)
|
||||
FOR_EACH_COMMAND(ExportSpriteSheet)
|
||||
FOR_EACH_COMMAND(ExportTileset)
|
||||
FOR_EACH_COMMAND(Fill)
|
||||
FOR_EACH_COMMAND(FlattenLayers)
|
||||
FOR_EACH_COMMAND(Flip)
|
||||
|
65
src/app/commands/export_tileset.cpp
Normal file
65
src/app/commands/export_tileset.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2022 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/commands/cmd_export_sprite_sheet.h"
|
||||
#include "app/commands/command_ids.h"
|
||||
#include "app/context.h"
|
||||
#include "app/site.h"
|
||||
#include "app/ui/layer_frame_comboboxes.h"
|
||||
#include "doc/layer.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
class ExportTilesetCommand : public ExportSpriteSheetCommand {
|
||||
public:
|
||||
ExportTilesetCommand();
|
||||
protected:
|
||||
void onResetValues() override;
|
||||
bool onEnabled(Context* context) override;
|
||||
void onExecute(Context* context) override;
|
||||
};
|
||||
|
||||
ExportTilesetCommand::ExportTilesetCommand()
|
||||
: ExportSpriteSheetCommand(CommandId::ExportTileset())
|
||||
{
|
||||
}
|
||||
|
||||
void ExportTilesetCommand::onResetValues()
|
||||
{
|
||||
ExportSpriteSheetCommand::onResetValues();
|
||||
|
||||
// Default values for Export Tileset
|
||||
params().fromTilesets(true);
|
||||
params().layer(kSelectedLayers);
|
||||
params().dataFormat(SpriteSheetDataFormat::JsonArray);
|
||||
}
|
||||
|
||||
bool ExportTilesetCommand::onEnabled(Context* ctx)
|
||||
{
|
||||
if (ExportSpriteSheetCommand::onEnabled(ctx) &&
|
||||
ctx->checkFlags(ContextFlags::HasActiveLayer)) {
|
||||
Site site = ctx->activeSite();
|
||||
if (site.layer() && site.layer()->isTilemap())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ExportTilesetCommand::onExecute(Context* ctx)
|
||||
{
|
||||
ExportSpriteSheetCommand::onExecute(ctx);
|
||||
}
|
||||
|
||||
Command* CommandFactory::createExportTilesetCommand()
|
||||
{
|
||||
return new ExportTilesetCommand;
|
||||
}
|
||||
|
||||
} // namespace app
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
// the End-User License Agreement for Aseprite.
|
||||
@ -139,7 +139,7 @@ namespace app {
|
||||
T& params() { return m_params; }
|
||||
const T& params() const { return m_params; }
|
||||
|
||||
private:
|
||||
protected:
|
||||
void onResetValues() override {
|
||||
m_params.resetValues();
|
||||
}
|
||||
@ -148,6 +148,7 @@ namespace app {
|
||||
return m_params.getParam(k);
|
||||
}
|
||||
|
||||
private:
|
||||
T m_params;
|
||||
};
|
||||
|
||||
|
@ -96,29 +96,25 @@ typedef std::shared_ptr<gfx::Rect> SharedRectPtr;
|
||||
DocExporter::Item::Item(Doc* doc,
|
||||
const doc::Tag* tag,
|
||||
const doc::SelectedLayers* selLayers,
|
||||
const doc::SelectedFrames* selFrames)
|
||||
const doc::SelectedFrames* selFrames,
|
||||
const bool splitGrid)
|
||||
: doc(doc)
|
||||
, tag(tag)
|
||||
, selLayers(selLayers ? new doc::SelectedLayers(*selLayers): nullptr)
|
||||
, selFrames(selFrames ? new doc::SelectedFrames(*selFrames): nullptr)
|
||||
, selLayers(selLayers ? std::make_unique<doc::SelectedLayers>(*selLayers): nullptr)
|
||||
, selFrames(selFrames ? std::make_unique<doc::SelectedFrames>(*selFrames): nullptr)
|
||||
, splitGrid(splitGrid)
|
||||
{
|
||||
}
|
||||
|
||||
DocExporter::Item::Item(Item&& other)
|
||||
: doc(other.doc)
|
||||
, tag(other.tag)
|
||||
, selLayers(other.selLayers)
|
||||
, selFrames(other.selFrames)
|
||||
DocExporter::Item::Item(Doc* doc,
|
||||
const doc::ImageRef& image)
|
||||
: doc(doc)
|
||||
, image(image)
|
||||
{
|
||||
other.selLayers = nullptr;
|
||||
other.selFrames = nullptr;
|
||||
}
|
||||
|
||||
DocExporter::Item::~Item()
|
||||
{
|
||||
delete selLayers;
|
||||
delete selFrames;
|
||||
}
|
||||
DocExporter::Item::Item(Item&& other) = default;
|
||||
DocExporter::Item::~Item() = default;
|
||||
|
||||
int DocExporter::Item::frames() const
|
||||
{
|
||||
@ -142,6 +138,8 @@ doc::SelectedFrames DocExporter::Item::getSelectedFrames() const
|
||||
frames.insert(std::clamp(tag->fromFrame(), 0, doc->sprite()->lastFrame()),
|
||||
std::clamp(tag->toFrame(), 0, doc->sprite()->lastFrame()));
|
||||
}
|
||||
else if (isOneImageOnly())
|
||||
frames.insert(0);
|
||||
else {
|
||||
frames.insert(0, doc->sprite()->lastFrame());
|
||||
}
|
||||
@ -150,7 +148,11 @@ doc::SelectedFrames DocExporter::Item::getSelectedFrames() const
|
||||
|
||||
class DocExporter::Sample {
|
||||
public:
|
||||
Sample(Doc* document, Sprite* sprite, SelectedLayers* selLayers,
|
||||
Sample(const gfx::Size& size,
|
||||
Doc* document,
|
||||
Sprite* sprite,
|
||||
const ImageRef& image,
|
||||
SelectedLayers* selLayers,
|
||||
frame_t frame,
|
||||
const Tag* tag,
|
||||
const std::string& filename,
|
||||
@ -158,6 +160,7 @@ public:
|
||||
const bool extrude) :
|
||||
m_document(document),
|
||||
m_sprite(sprite),
|
||||
m_image(image),
|
||||
m_selLayers(selLayers),
|
||||
m_frame(frame),
|
||||
m_tag(tag),
|
||||
@ -166,9 +169,9 @@ public:
|
||||
m_extrude(extrude),
|
||||
m_isLinked(false),
|
||||
m_isDuplicated(false),
|
||||
m_originalSize(sprite->width(), sprite->height()),
|
||||
m_trimmedBounds(0, 0, sprite->width(), sprite->height()),
|
||||
m_inTextureBounds(std::make_shared<gfx::Rect>(0, 0, sprite->width(), sprite->height())) {
|
||||
m_originalSize(size),
|
||||
m_trimmedBounds(size),
|
||||
m_inTextureBounds(std::make_shared<gfx::Rect>(size)) {
|
||||
}
|
||||
|
||||
Doc* document() const { return m_document; }
|
||||
@ -234,6 +237,11 @@ public:
|
||||
ImageRef createRender(ImageBufferPtr& imageBuf) {
|
||||
ASSERT(m_sprite);
|
||||
|
||||
// We use the m_image as it is, it doesn't require a special
|
||||
// render.
|
||||
if (m_image)
|
||||
return m_image;
|
||||
|
||||
ImageRef render(
|
||||
Image::create(m_sprite->pixelFormat(),
|
||||
m_trimmedBounds.w,
|
||||
@ -279,19 +287,32 @@ public:
|
||||
for (int j=0; j<3; ++j) {
|
||||
for (int i=0; i<3; ++i) {
|
||||
gfx::Clip clip(x+dx[i], y+dy[j], gfx::RectT<int>(srcx[i], srcy[j], szx[i], szy[j]));
|
||||
render.renderSprite(dst, m_sprite, m_frame, clip);
|
||||
if (m_image) {
|
||||
dst->copy(m_image.get(), clip);
|
||||
}
|
||||
else {
|
||||
render.renderSprite(dst, m_sprite, m_frame, clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
gfx::Clip clip(x, y, m_trimmedBounds);
|
||||
render.renderSprite(dst, m_sprite, m_frame, clip);
|
||||
if (m_image) {
|
||||
dst->copy(m_image.get(), clip);
|
||||
}
|
||||
else {
|
||||
render.renderSprite(dst, m_sprite, m_frame, clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Doc* m_document;
|
||||
Sprite* m_sprite;
|
||||
// In case that this Sample references just one image to export
|
||||
// (e.g. like a Tileset tile image) this can be != nullptr.
|
||||
ImageRef m_image;
|
||||
SelectedLayers* m_selLayers;
|
||||
frame_t m_frame;
|
||||
const Tag* m_tag;
|
||||
@ -360,7 +381,7 @@ public:
|
||||
int shapePadding,
|
||||
int& width, int& height,
|
||||
base::task_token& token) override {
|
||||
DX_TRACE("SimpleLayoutSamples type", (int)m_type, width, height);
|
||||
DX_TRACE("DX: SimpleLayoutSamples type", (int)m_type, width, height);
|
||||
|
||||
const bool breakBands =
|
||||
(m_type == SpriteSheetType::Columns ||
|
||||
@ -492,7 +513,7 @@ public:
|
||||
++i;
|
||||
}
|
||||
|
||||
DX_TRACE("-> SimpleLayoutSamples", width, height);
|
||||
DX_TRACE("DX: -> SimpleLayoutSamples", width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -688,7 +709,7 @@ Doc* DocExporter::exportSheet(Context* ctx, base::task_token& token)
|
||||
|
||||
// Save the image files.
|
||||
if (!m_textureFilename.empty()) {
|
||||
DX_TRACE("DocExporter::exportSheet", m_textureFilename);
|
||||
DX_TRACE("DX: exportSheet", m_textureFilename);
|
||||
textureDocument->setFilename(m_textureFilename.c_str());
|
||||
int ret = save_document(ctx, textureDocument.get());
|
||||
if (ret == 0)
|
||||
@ -713,11 +734,19 @@ void DocExporter::addDocument(
|
||||
Doc* doc,
|
||||
const doc::Tag* tag,
|
||||
const doc::SelectedLayers* selLayers,
|
||||
const doc::SelectedFrames* selFrames)
|
||||
const doc::SelectedFrames* selFrames,
|
||||
const bool splitGrid)
|
||||
{
|
||||
DX_TRACE("DocExporter::addDocument doc=", doc, "tag=", tag);
|
||||
DX_TRACE("DX: addDocument doc=", doc, "tag=", tag);
|
||||
m_documents.push_back(Item(doc, tag, selLayers, selFrames, splitGrid));
|
||||
}
|
||||
|
||||
m_documents.push_back(Item(doc, tag, selLayers, selFrames));
|
||||
void DocExporter::addImage(
|
||||
Doc* doc,
|
||||
const doc::ImageRef& image)
|
||||
{
|
||||
DX_TRACE("DX: addImage doc=", doc, "image=", image.get());
|
||||
m_documents.push_back(Item(doc, image));
|
||||
}
|
||||
|
||||
int DocExporter::addDocumentSamples(
|
||||
@ -725,10 +754,11 @@ int DocExporter::addDocumentSamples(
|
||||
const doc::Tag* thisTag,
|
||||
const bool splitLayers,
|
||||
const bool splitTags,
|
||||
const bool splitGrid,
|
||||
const doc::SelectedLayers* selLayers,
|
||||
const doc::SelectedFrames* selFrames)
|
||||
{
|
||||
DX_TRACE("DocExporter::addDocumentSamples");
|
||||
DX_TRACE("DX: addDocumentSamples");
|
||||
|
||||
std::vector<const Tag*> tags;
|
||||
|
||||
@ -793,7 +823,7 @@ int DocExporter::addDocumentSamples(
|
||||
|
||||
SelectedLayers oneLayer;
|
||||
oneLayer.insert(layer);
|
||||
addDocument(doc, tag, &oneLayer, thisSelFrames);
|
||||
addDocument(doc, tag, &oneLayer, thisSelFrames, splitGrid);
|
||||
++items;
|
||||
}
|
||||
}
|
||||
@ -804,19 +834,49 @@ int DocExporter::addDocumentSamples(
|
||||
|
||||
SelectedLayers oneLayer;
|
||||
oneLayer.insert(layer);
|
||||
addDocument(doc, tag, &oneLayer, thisSelFrames);
|
||||
addDocument(doc, tag, &oneLayer, thisSelFrames, splitGrid);
|
||||
++items;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
addDocument(doc, tag, selLayers, thisSelFrames);
|
||||
addDocument(doc, tag, selLayers, thisSelFrames, splitGrid);
|
||||
++items;
|
||||
}
|
||||
}
|
||||
return std::max(1, items);
|
||||
}
|
||||
|
||||
int DocExporter::addTilesetsSamples(
|
||||
Doc* doc,
|
||||
const doc::SelectedLayers* selLayers)
|
||||
{
|
||||
LayerList layers;
|
||||
if (selLayers)
|
||||
layers = selLayers->toAllLayersList();
|
||||
else
|
||||
layers = doc->sprite()->allVisibleLayers();
|
||||
|
||||
std::set<doc::ObjectId> alreadyExported;
|
||||
int items = 0;
|
||||
for (auto& layer : layers) {
|
||||
if (layer->isTilemap()) {
|
||||
Tileset* ts = dynamic_cast<LayerTilemap*>(layer)->tileset();
|
||||
|
||||
if (alreadyExported.find(ts->id()) == alreadyExported.end()) {
|
||||
for (const ImageRef& image : *ts) {
|
||||
addImage(doc, image);
|
||||
++items;
|
||||
}
|
||||
alreadyExported.insert(ts->id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DX_TRACE("DX: addTilesetsSamples items=", items);
|
||||
return items;
|
||||
}
|
||||
|
||||
void DocExporter::captureSamples(Samples& samples,
|
||||
base::task_token& token)
|
||||
{
|
||||
@ -847,24 +907,34 @@ void DocExporter::captureSamples(Samples& samples,
|
||||
(tag != nullptr)); // Has tag
|
||||
}
|
||||
|
||||
gfx::Rect spriteBounds = sprite->bounds();
|
||||
if (m_trimSprite) {
|
||||
if (m_cache.spriteId == sprite->id() &&
|
||||
m_cache.spriteVer == sprite->version() &&
|
||||
m_cache.trimmedByGrid == m_trimByGrid) {
|
||||
spriteBounds = m_cache.trimmedBounds;
|
||||
}
|
||||
else {
|
||||
spriteBounds = get_trimmed_bounds(sprite, m_trimByGrid);
|
||||
if (spriteBounds.isEmpty())
|
||||
spriteBounds = gfx::Rect(0, 0, 1, 1);
|
||||
gfx::Rect spriteBounds;
|
||||
|
||||
// Cache trimmed bounds so we don't have to recalculate them
|
||||
// in the next iteration/preview.
|
||||
m_cache.spriteId = sprite->id();
|
||||
m_cache.spriteVer = sprite->version();
|
||||
m_cache.trimmedByGrid = m_trimByGrid;
|
||||
m_cache.trimmedBounds = spriteBounds;
|
||||
// This item is only one image (e.g. a tileset tile)
|
||||
if (item.isOneImageOnly()) {
|
||||
ASSERT(item.image);
|
||||
spriteBounds = item.image->bounds();
|
||||
}
|
||||
// This item comes from the sprite canvas
|
||||
else {
|
||||
spriteBounds = sprite->bounds();
|
||||
if (m_trimSprite) {
|
||||
if (m_cache.spriteId == sprite->id() &&
|
||||
m_cache.spriteVer == sprite->version() &&
|
||||
m_cache.trimmedByGrid == m_trimByGrid) {
|
||||
spriteBounds = m_cache.trimmedBounds;
|
||||
}
|
||||
else {
|
||||
spriteBounds = get_trimmed_bounds(sprite, m_trimByGrid);
|
||||
if (spriteBounds.isEmpty())
|
||||
spriteBounds = gfx::Rect(0, 0, 1, 1);
|
||||
|
||||
// Cache trimmed bounds so we don't have to recalculate them
|
||||
// in the next iteration/preview.
|
||||
m_cache.spriteId = sprite->id();
|
||||
m_cache.spriteVer = sprite->version();
|
||||
m_cache.trimmedByGrid = m_trimByGrid;
|
||||
m_cache.trimmedBounds = spriteBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -891,8 +961,12 @@ void DocExporter::captureSamples(Samples& samples,
|
||||
std::string filename = filename_formatter(format, fnInfo);
|
||||
|
||||
Sample sample(
|
||||
doc, sprite, item.selLayers, frame, innerTag,
|
||||
filename, m_innerPadding, m_extrude);
|
||||
(item.image ? item.image->size():
|
||||
item.splitGrid ? sprite->gridBounds().size():
|
||||
sprite->size()),
|
||||
doc, sprite, item.image, item.selLayers.get(),
|
||||
frame, innerTag, filename,
|
||||
m_innerPadding, m_extrude);
|
||||
Cel* cel = nullptr;
|
||||
Cel* link = nullptr;
|
||||
bool done = false;
|
||||
@ -905,7 +979,8 @@ void DocExporter::captureSamples(Samples& samples,
|
||||
|
||||
// Re-use linked samples
|
||||
bool alreadyTrimmed = false;
|
||||
if (link && m_mergeDuplicates) {
|
||||
if (link && m_mergeDuplicates &&
|
||||
!item.isOneImageOnly()) {
|
||||
for (const Sample& other : samples) {
|
||||
if (token.canceled())
|
||||
return;
|
||||
@ -928,7 +1003,8 @@ void DocExporter::captureSamples(Samples& samples,
|
||||
ASSERT(done || (!done && tag));
|
||||
}
|
||||
|
||||
if (!done && (m_ignoreEmptyCels || m_trimCels)) {
|
||||
if (!done && (m_ignoreEmptyCels || m_trimCels) &&
|
||||
!item.isOneImageOnly()) {
|
||||
// Ignore empty cels
|
||||
if (layer && layer->isImage() && !cel && m_ignoreEmptyCels)
|
||||
continue;
|
||||
@ -994,7 +1070,23 @@ void DocExporter::captureSamples(Samples& samples,
|
||||
if (!alreadyTrimmed && m_trimSprite)
|
||||
sample.setTrimmedBounds(spriteBounds);
|
||||
|
||||
samples.addSample(sample);
|
||||
if (item.splitGrid) {
|
||||
const gfx::Rect& gridBounds = sprite->gridBounds();
|
||||
gfx::Point initPos(0, 0), pos;
|
||||
initPos = pos = snap_to_grid(gridBounds, initPos, PreferSnapTo::BoxOrigin);
|
||||
|
||||
for (; pos.y+gridBounds.h <= spriteBounds.h; pos.y+=gridBounds.h) {
|
||||
for (pos.x=initPos.x; pos.x+gridBounds.w <= spriteBounds.w; pos.x+=gridBounds.w) {
|
||||
const gfx::Rect cellBounds(pos, gridBounds.size());
|
||||
sample.setTrimmedBounds(cellBounds);
|
||||
sample.setSharedBounds(std::make_shared<gfx::Rect>(sample.inTextureBounds()));
|
||||
samples.addSample(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
samples.addSample(sample);
|
||||
}
|
||||
|
||||
DX_TRACE("DX: - Sample:",
|
||||
sample.document()->filename(),
|
||||
@ -1319,6 +1411,9 @@ void DocExporter::createDataFile(const Samples& samples,
|
||||
|
||||
bool firstTag = true;
|
||||
for (auto& item : m_documents) {
|
||||
if (item.isOneImageOnly())
|
||||
continue;
|
||||
|
||||
Doc* doc = item.doc;
|
||||
Sprite* sprite = doc->sprite();
|
||||
|
||||
@ -1350,6 +1445,9 @@ void DocExporter::createDataFile(const Samples& samples,
|
||||
if (m_listLayers) {
|
||||
LayerList metaLayers;
|
||||
for (auto& item : m_documents) {
|
||||
if (item.isOneImageOnly())
|
||||
continue;
|
||||
|
||||
Doc* doc = item.doc;
|
||||
Sprite* sprite = doc->sprite();
|
||||
Layer* root = sprite->root();
|
||||
@ -1445,6 +1543,9 @@ void DocExporter::createDataFile(const Samples& samples,
|
||||
|
||||
bool firstSlice = true;
|
||||
for (auto& item : m_documents) {
|
||||
if (item.isOneImageOnly())
|
||||
continue;
|
||||
|
||||
Doc* doc = item.doc;
|
||||
Sprite* sprite = doc->sprite();
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "base/disable_copying.h"
|
||||
#include "base/task.h"
|
||||
#include "doc/frame.h"
|
||||
#include "doc/image_ref.h"
|
||||
#include "doc/image_buffer.h"
|
||||
#include "doc/object_id.h"
|
||||
#include "doc/object_version.h"
|
||||
@ -21,6 +22,7 @@
|
||||
#include "gfx/rect.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -75,20 +77,23 @@ namespace app {
|
||||
void setListLayers(bool value) { m_listLayers = value; }
|
||||
void setListSlices(bool value) { m_listSlices = value; }
|
||||
|
||||
void addDocument(
|
||||
void addImage(
|
||||
Doc* doc,
|
||||
const doc::Tag* tag,
|
||||
const doc::SelectedLayers* selLayers,
|
||||
const doc::SelectedFrames* selFrames);
|
||||
const doc::ImageRef& image);
|
||||
|
||||
int addDocumentSamples(
|
||||
Doc* doc,
|
||||
const doc::Tag* tag,
|
||||
const bool splitLayers,
|
||||
const bool splitTags,
|
||||
const bool splitGrid,
|
||||
const doc::SelectedLayers* selLayers,
|
||||
const doc::SelectedFrames* selFrames);
|
||||
|
||||
int addTilesetsSamples(
|
||||
Doc* doc,
|
||||
const doc::SelectedLayers* selLayers);
|
||||
|
||||
Doc* exportSheet(Context* ctx, base::task_token& token);
|
||||
gfx::Size calculateSheetSize();
|
||||
|
||||
@ -99,6 +104,12 @@ namespace app {
|
||||
class SimpleLayoutSamples;
|
||||
class BestFitLayoutSamples;
|
||||
|
||||
void addDocument(
|
||||
Doc* doc,
|
||||
const doc::Tag* tag,
|
||||
const doc::SelectedLayers* selLayers,
|
||||
const doc::SelectedFrames* selFrames,
|
||||
const bool splitGrid);
|
||||
void captureSamples(Samples& samples,
|
||||
base::task_token& token);
|
||||
void layoutSamples(Samples& samples,
|
||||
@ -116,15 +127,20 @@ namespace app {
|
||||
|
||||
class Item {
|
||||
public:
|
||||
Doc* doc;
|
||||
const doc::Tag* tag;
|
||||
doc::SelectedLayers* selLayers;
|
||||
doc::SelectedFrames* selFrames;
|
||||
Doc* doc = nullptr;
|
||||
const doc::Tag* tag = nullptr;
|
||||
std::unique_ptr<doc::SelectedLayers> selLayers;
|
||||
std::unique_ptr<doc::SelectedFrames> selFrames;
|
||||
bool splitGrid = false;
|
||||
doc::ImageRef image;
|
||||
|
||||
Item(Doc* doc,
|
||||
const doc::Tag* tag,
|
||||
const doc::SelectedLayers* selLayers,
|
||||
const doc::SelectedFrames* selFrames);
|
||||
const doc::SelectedFrames* selFrames,
|
||||
const bool splitGrid);
|
||||
Item(Doc* doc,
|
||||
const doc::ImageRef& image);
|
||||
Item(Item&& other);
|
||||
~Item();
|
||||
|
||||
@ -134,6 +150,8 @@ namespace app {
|
||||
|
||||
int frames() const;
|
||||
doc::SelectedFrames getSelectedFrames() const;
|
||||
|
||||
bool isOneImageOnly() const { return image != nullptr; }
|
||||
};
|
||||
typedef std::vector<Item> Items;
|
||||
|
||||
|
@ -65,9 +65,9 @@ public:
|
||||
ASSERT(m_doc && m_sprite);
|
||||
}
|
||||
|
||||
void setSliceBounds(const gfx::Rect& sliceBounds) {
|
||||
m_spec.setWidth(sliceBounds.w * m_scale.x);
|
||||
m_spec.setHeight(sliceBounds.h * m_scale.y);
|
||||
void setSpecSize(const gfx::Size& size) {
|
||||
m_spec.setWidth(size.w * m_scale.x);
|
||||
m_spec.setHeight(size.h * m_scale.y);
|
||||
}
|
||||
|
||||
void setUnscaledImage(const doc::frame_t frame,
|
||||
@ -233,7 +233,7 @@ int save_document(Context* context, Doc* document)
|
||||
std::unique_ptr<FileOp> fop(
|
||||
FileOp::createSaveDocumentOperation(
|
||||
context,
|
||||
FileOpROI(document, "", "", SelectedFrames(), false),
|
||||
FileOpROI(document, gfx::Rect(), "", "", SelectedFrames(), false),
|
||||
document->filename(), "",
|
||||
false));
|
||||
if (!fop)
|
||||
@ -269,11 +269,13 @@ FileOpROI::FileOpROI()
|
||||
}
|
||||
|
||||
FileOpROI::FileOpROI(const Doc* doc,
|
||||
const gfx::Rect& bounds,
|
||||
const std::string& sliceName,
|
||||
const std::string& tagName,
|
||||
const doc::SelectedFrames& selFrames,
|
||||
const bool adjustByTag)
|
||||
: m_document(doc)
|
||||
, m_bounds(bounds)
|
||||
, m_slice(nullptr)
|
||||
, m_tag(nullptr)
|
||||
, m_selFrames(selFrames)
|
||||
@ -916,23 +918,35 @@ void FileOp::operate(IFileOpProgress* progress)
|
||||
|
||||
frame_t outputFrame = 0;
|
||||
for (frame_t frame : m_roi.selectedFrames()) {
|
||||
// Draw the "frame" in "m_seq.image"
|
||||
gfx::Rect bounds;
|
||||
|
||||
// Export bounds of specific slice
|
||||
if (m_roi.slice()) {
|
||||
const SliceKey* key = m_roi.slice()->getByFrame(frame);
|
||||
if (!key || key->isEmpty())
|
||||
continue; // Skip frame because there is no slice key
|
||||
|
||||
bounds = key->bounds();
|
||||
}
|
||||
// Export specific bounds
|
||||
else if (!m_roi.bounds().isEmpty()) {
|
||||
bounds = m_roi.bounds();
|
||||
}
|
||||
|
||||
// Draw the "frame" in "m_seq.image" with the given bounds
|
||||
// (bounds can be the selection bounds or a slice key bounds)
|
||||
if (!bounds.isEmpty()) {
|
||||
if (m_abstractImage)
|
||||
m_abstractImage->setSliceBounds(key->bounds());
|
||||
m_abstractImage->setSpecSize(bounds.size());
|
||||
|
||||
m_seq.image.reset(
|
||||
Image::create(sprite->pixelFormat(),
|
||||
key->bounds().w,
|
||||
key->bounds().h));
|
||||
bounds.w,
|
||||
bounds.h));
|
||||
|
||||
render.renderSprite(
|
||||
m_seq.image.get(), sprite, frame,
|
||||
gfx::Clip(gfx::Point(0, 0), key->bounds()));
|
||||
gfx::Clip(gfx::Point(0, 0), bounds));
|
||||
}
|
||||
else {
|
||||
render.renderSprite(m_seq.image.get(), sprite, frame);
|
||||
|
@ -72,12 +72,14 @@ namespace app {
|
||||
public:
|
||||
FileOpROI();
|
||||
FileOpROI(const Doc* doc,
|
||||
const gfx::Rect& bounds,
|
||||
const std::string& sliceName,
|
||||
const std::string& tagName,
|
||||
const doc::SelectedFrames& selFrames,
|
||||
const bool adjustByTag);
|
||||
|
||||
const Doc* document() const { return m_document; }
|
||||
const gfx::Rect& bounds() const { return m_bounds; }
|
||||
doc::Slice* slice() const { return m_slice; }
|
||||
doc::Tag* tag() const { return m_tag; }
|
||||
doc::frame_t fromFrame() const { return m_selFrames.firstFrame(); }
|
||||
@ -90,6 +92,7 @@ namespace app {
|
||||
|
||||
private:
|
||||
const Doc* m_document;
|
||||
gfx::Rect m_bounds;
|
||||
doc::Slice* m_slice;
|
||||
doc::Tag* m_tag;
|
||||
doc::SelectedFrames m_selFrames;
|
||||
|
@ -52,6 +52,7 @@ ExportFileWindow::ExportFileWindow(const Doc* doc)
|
||||
|
||||
// Default export configuration
|
||||
setResizeScale(m_docPref.saveCopy.resizeScale());
|
||||
fill_area_combobox(m_doc->sprite(), area(), m_docPref.saveCopy.area());
|
||||
fill_layers_combobox(m_doc->sprite(), layers(), m_docPref.saveCopy.layer());
|
||||
fill_frames_combobox(m_doc->sprite(), frames(), m_docPref.saveCopy.frameTag());
|
||||
fill_anidir_combobox(anidir(), m_docPref.saveCopy.aniDir());
|
||||
@ -97,6 +98,7 @@ void ExportFileWindow::savePref()
|
||||
{
|
||||
m_docPref.saveCopy.filename(outputFilenameValue());
|
||||
m_docPref.saveCopy.resizeScale(resizeValue());
|
||||
m_docPref.saveCopy.area(areaValue());
|
||||
m_docPref.saveCopy.layer(layersValue());
|
||||
m_docPref.saveCopy.aniDir(aniDirValue());
|
||||
m_docPref.saveCopy.frameTag(framesValue());
|
||||
@ -116,6 +118,11 @@ double ExportFileWindow::resizeValue() const
|
||||
return std::clamp(value, 0.001, 100000000.0);
|
||||
}
|
||||
|
||||
std::string ExportFileWindow::areaValue() const
|
||||
{
|
||||
return area()->getValue();
|
||||
}
|
||||
|
||||
std::string ExportFileWindow::layersValue() const
|
||||
{
|
||||
return layers()->getValue();
|
||||
@ -146,6 +153,11 @@ void ExportFileWindow::setResizeScale(double scale)
|
||||
resize()->setValue(fmt::format("{:.2f}", 100.0 * scale));
|
||||
}
|
||||
|
||||
void ExportFileWindow::setArea(const std::string& areaValue)
|
||||
{
|
||||
area()->setValue(areaValue);
|
||||
}
|
||||
|
||||
void ExportFileWindow::setAniDir(const doc::AniDir aniDir)
|
||||
{
|
||||
anidir()->setSelectedItemIndex(int(aniDir));
|
||||
|
@ -28,6 +28,7 @@ namespace app {
|
||||
|
||||
std::string outputFilenameValue() const;
|
||||
double resizeValue() const;
|
||||
std::string areaValue() const;
|
||||
std::string layersValue() const;
|
||||
std::string framesValue() const;
|
||||
doc::AniDir aniDirValue() const;
|
||||
@ -36,6 +37,7 @@ namespace app {
|
||||
|
||||
void setOutputFilename(const std::string& pathAndFilename);
|
||||
void setResizeScale(const double scale);
|
||||
void setArea(const std::string& area);
|
||||
void setAniDir(const doc::AniDir aniDir);
|
||||
|
||||
obs::signal<std::string()> SelectOutputFile;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -17,17 +17,27 @@
|
||||
#include "doc/layer.h"
|
||||
#include "doc/selected_frames.h"
|
||||
#include "doc/selected_layers.h"
|
||||
#include "doc/slice.h"
|
||||
#include "doc/sprite.h"
|
||||
#include "doc/tag.h"
|
||||
#include "ui/combobox.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
const char* kWholeCanvas = "";
|
||||
const char* kAllLayers = "";
|
||||
const char* kAllFrames = "";
|
||||
const char* kSelectedCanvas = "**selected-canvas**";
|
||||
const char* kSelectedLayers = "**selected-layers**";
|
||||
const char* kSelectedFrames = "**selected-frames**";
|
||||
|
||||
SliceListItem::SliceListItem(doc::Slice* slice)
|
||||
: ListItem("Slice: " + slice->name())
|
||||
, m_slice(slice)
|
||||
{
|
||||
setValue(m_slice->name());
|
||||
}
|
||||
|
||||
LayerListItem::LayerListItem(doc::Layer* layer)
|
||||
: ListItem(buildName(layer))
|
||||
, m_layer(layer)
|
||||
@ -57,6 +67,26 @@ FrameListItem::FrameListItem(doc::Tag* tag)
|
||||
setValue(m_tag->name());
|
||||
}
|
||||
|
||||
void fill_area_combobox(const doc::Sprite* sprite, ui::ComboBox* area, const std::string& defArea)
|
||||
{
|
||||
int i = area->addItem("Canvas");
|
||||
dynamic_cast<ui::ListItem*>(area->getItem(i))->setValue(kWholeCanvas);
|
||||
|
||||
i = area->addItem("Selection");
|
||||
dynamic_cast<ui::ListItem*>(area->getItem(i))->setValue(kSelectedCanvas);
|
||||
if (defArea == kSelectedCanvas)
|
||||
area->setSelectedItemIndex(i);
|
||||
|
||||
for (auto slice : sprite->slices()) {
|
||||
if (slice->name().empty())
|
||||
continue;
|
||||
|
||||
i = area->addItem(new SliceListItem(slice));
|
||||
if (defArea == slice->name())
|
||||
area->setSelectedItemIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer)
|
||||
{
|
||||
int i = layers->addItem("Visible layers");
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite
|
||||
// Copyright (C) 2019 Igara Studio S.A.
|
||||
// Copyright (C) 2019-2022 Igara Studio S.A.
|
||||
// Copyright (C) 2016-2018 David Capello
|
||||
//
|
||||
// This program is distributed under the terms of
|
||||
@ -18,6 +18,7 @@ namespace doc {
|
||||
class Layer;
|
||||
class SelectedFrames;
|
||||
class SelectedLayers;
|
||||
class Slice;
|
||||
class Sprite;
|
||||
class Tag;
|
||||
}
|
||||
@ -30,11 +31,21 @@ namespace app {
|
||||
class RestoreVisibleLayers;
|
||||
class Site;
|
||||
|
||||
extern const char* kWholeCanvas;
|
||||
extern const char* kAllLayers;
|
||||
extern const char* kAllFrames;
|
||||
extern const char* kSelectedCanvas;
|
||||
extern const char* kSelectedLayers;
|
||||
extern const char* kSelectedFrames;
|
||||
|
||||
class SliceListItem : public ui::ListItem {
|
||||
public:
|
||||
SliceListItem(doc::Slice* slice);
|
||||
doc::Slice* slice() const { return m_slice; }
|
||||
private:
|
||||
doc::Slice* m_slice;
|
||||
};
|
||||
|
||||
class LayerListItem : public ui::ListItem {
|
||||
public:
|
||||
LayerListItem(doc::Layer* layer);
|
||||
@ -52,6 +63,7 @@ namespace app {
|
||||
doc::Tag* m_tag;
|
||||
};
|
||||
|
||||
void fill_area_combobox(const doc::Sprite* sprite, ui::ComboBox* area, const std::string& defArea);
|
||||
void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer);
|
||||
void fill_frames_combobox(const doc::Sprite* sprite, ui::ComboBox* frames, const std::string& defFrame);
|
||||
void fill_anidir_combobox(ui::ComboBox* anidir, doc::AniDir defAnidir);
|
||||
|
Loading…
x
Reference in New Issue
Block a user