diff --git a/data/pref.xml b/data/pref.xml
index b5cca015c..253b7be8a 100644
--- a/data/pref.xml
+++ b/data/pref.xml
@@ -485,6 +485,7 @@
+
@@ -512,6 +513,7 @@
+
diff --git a/src/app/commands/cmd_export_sprite_sheet.cpp b/src/app/commands/cmd_export_sprite_sheet.cpp
index 22828172f..bade60de2 100644
--- a/src/app/commands/cmd_export_sprite_sheet.cpp
+++ b/src/app/commands/cmd_export_sprite_sheet.cpp
@@ -76,6 +76,12 @@ struct ExportSpriteSheetParams : public NewParams {
Param mergeDuplicates { this, false, "mergeDuplicates" };
Param openGenerated { this, false, "openGenerated" };
Param layer { this, std::string(), "layer" };
+ // TODO The layerIndex parameter is for internal use only, layers
+ // are counted in the same order as they are displayed in the
+ // Timeline or in the Export Sprite Sheet combobox. But this
+ // index is different to the one specified in the .aseprite
+ // file spec (where layers are counted from bottom to top).
+ Param layerIndex { this, -1, "_layerIndex" };
Param tag { this, std::string(), "tag" };
Param splitLayers { this, false, "splitLayers" };
Param splitTags { this, false, "splitTags" };
@@ -182,6 +188,7 @@ Doc* generate_sprite_sheet_from_params(
const SpriteSheetDataFormat dataFormat = params.dataFormat();
const std::string filenameFormat = params.filenameFormat();
const std::string layerName = params.layer();
+ const int layerIndex = params.layerIndex();
const std::string tagName = params.tag();
const int borderPadding = std::clamp(params.borderPadding(), 0, 100);
const int shapePadding = std::clamp(params.shapePadding(), 0, 100);
@@ -212,13 +219,16 @@ Doc* generate_sprite_sheet_from_params(
// If the user choose to render selected layers only, we can
// temporaly make them visible and hide the other ones.
RestoreVisibleLayers layersVisibility;
- calculate_visible_layers(site, layerName, layersVisibility);
+ calculate_visible_layers(site, layerName, layerIndex, layersVisibility);
SelectedLayers selLayers;
if (layerName != kSelectedLayers) {
// TODO add a getLayerByName
+ int i = sprite->allLayersCount();
for (const Layer* layer : sprite->allLayers()) {
- if (layer->name() == layerName) {
+ i--;
+ if (layer->name() == layerName && layerIndex == -1 ||
+ layer->name() == layerName && layerIndex == i) {
selLayers.insert(const_cast(layer));
break;
}
@@ -374,7 +384,7 @@ public:
}
fill_layers_combobox(
- m_sprite, layers(), params.layer());
+ m_sprite, layers(), params.layer(), params.layerIndex());
fill_frames_combobox(
m_sprite, frames(), params.tag());
@@ -530,6 +540,7 @@ public:
params.ignoreEmpty (ignoreEmptyValue());
params.openGenerated (openGeneratedValue());
params.layer (layerValue());
+ params.layerIndex (layerIndex());
params.tag (tagValue());
params.splitLayers (splitLayersValue());
params.splitTags (splitTagsValue());
@@ -714,6 +725,11 @@ private:
return layers()->getValue();
}
+ int layerIndex() const {
+ int i = layers()->getSelectedItemIndex() - kLayersComboboxExtraInitialItems;
+ return i < 0 ? -1 : i;
+ }
+
std::string tagValue() const {
return frames()->getValue();
}
@@ -1235,6 +1251,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
if (!params.ignoreEmpty.isSet()) params.ignoreEmpty( defPref.spriteSheet.ignoreEmpty());
if (!params.openGenerated.isSet()) params.openGenerated( defPref.spriteSheet.openGenerated());
if (!params.layer.isSet()) params.layer( defPref.spriteSheet.layer());
+ if (!params.layerIndex.isSet()) params.layerIndex( defPref.spriteSheet.layerIndex());
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());
@@ -1281,6 +1298,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
docPref.spriteSheet.ignoreEmpty (params.ignoreEmpty());
docPref.spriteSheet.openGenerated (params.openGenerated());
docPref.spriteSheet.layer (params.layer());
+ docPref.spriteSheet.layerIndex (params.layerIndex());
docPref.spriteSheet.frameTag (params.tag());
docPref.spriteSheet.splitLayers (params.splitLayers());
docPref.spriteSheet.splitTags (params.splitTags());
diff --git a/src/app/commands/cmd_save_file.cpp b/src/app/commands/cmd_save_file.cpp
index 92bf030bb..6966f8cf1 100644
--- a/src/app/commands/cmd_save_file.cpp
+++ b/src/app/commands/cmd_save_file.cpp
@@ -343,6 +343,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
Doc* doc = context->activeDocument();
std::string outputFilename = params().filename();
std::string layers = kAllLayers;
+ int layersIndex = -1;
std::string frames = kAllFrames;
bool applyPixelRatio = false;
double scale = params().scale();
@@ -408,6 +409,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
win.savePref();
layers = win.layersValue();
+ layersIndex = win.layersIndex();
frames = win.framesValue();
scale = win.resizeValue();
applyPixelRatio = win.applyPixelRatio();
@@ -464,6 +466,7 @@ void SaveFileCopyAsCommand::onExecute(Context* context)
// Selected layers to export
calculate_visible_layers(site,
layers,
+ layersIndex,
layersVisibility);
// m_selFrames is not empty if fromFrame/toFrame parameters are
diff --git a/src/app/ui/export_file_window.cpp b/src/app/ui/export_file_window.cpp
index c547e54a0..20f7ba33e 100644
--- a/src/app/ui/export_file_window.cpp
+++ b/src/app/ui/export_file_window.cpp
@@ -52,7 +52,7 @@ ExportFileWindow::ExportFileWindow(const Doc* doc)
// Default export configuration
setResizeScale(m_docPref.saveCopy.resizeScale());
- fill_layers_combobox(m_doc->sprite(), layers(), m_docPref.saveCopy.layer());
+ fill_layers_combobox(m_doc->sprite(), layers(), m_docPref.saveCopy.layer(), m_docPref.saveCopy.layerIndex());
fill_frames_combobox(m_doc->sprite(), frames(), m_docPref.saveCopy.frameTag());
fill_anidir_combobox(anidir(), m_docPref.saveCopy.aniDir());
pixelRatio()->setSelected(m_docPref.saveCopy.applyPixelRatio());
@@ -98,6 +98,7 @@ void ExportFileWindow::savePref()
m_docPref.saveCopy.filename(outputFilenameValue());
m_docPref.saveCopy.resizeScale(resizeValue());
m_docPref.saveCopy.layer(layersValue());
+ m_docPref.saveCopy.layerIndex(layersIndex());
m_docPref.saveCopy.aniDir(aniDirValue());
m_docPref.saveCopy.frameTag(framesValue());
m_docPref.saveCopy.applyPixelRatio(applyPixelRatio());
@@ -121,6 +122,12 @@ std::string ExportFileWindow::layersValue() const
return layers()->getValue();
}
+int ExportFileWindow::layersIndex() const
+{
+ int i = layers()->getSelectedItemIndex() - kLayersComboboxExtraInitialItems;
+ return i < 0 ? -1 : i;
+}
+
std::string ExportFileWindow::framesValue() const
{
return frames()->getValue();
diff --git a/src/app/ui/export_file_window.h b/src/app/ui/export_file_window.h
index f5670d10b..ae20748bc 100644
--- a/src/app/ui/export_file_window.h
+++ b/src/app/ui/export_file_window.h
@@ -29,6 +29,7 @@ namespace app {
std::string outputFilenameValue() const;
double resizeValue() const;
std::string layersValue() const;
+ int layersIndex() const;
std::string framesValue() const;
doc::AniDir aniDirValue() const;
bool applyPixelRatio() const;
diff --git a/src/app/ui/layer_frame_comboboxes.cpp b/src/app/ui/layer_frame_comboboxes.cpp
index 4da19a6e6..ff5568fa3 100644
--- a/src/app/ui/layer_frame_comboboxes.cpp
+++ b/src/app/ui/layer_frame_comboboxes.cpp
@@ -57,7 +57,7 @@ FrameListItem::FrameListItem(doc::Tag* tag)
setValue(m_tag->name());
}
-void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer)
+void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer, const int defLayerIndex)
{
int i = layers->addItem("Visible layers");
dynamic_cast(layers->getItem(i))->setValue(kAllLayers);
@@ -67,11 +67,16 @@ void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const
if (defLayer == kSelectedLayers)
layers->setSelectedItemIndex(i);
+ assert(layers->getItemCount() == kLayersComboboxExtraInitialItems);
+ static_assert(kLayersComboboxExtraInitialItems == 2,
+ "Update kLayersComboboxExtraInitialItems value to match the number of initial items in layers combobox");
+
doc::LayerList layersList = sprite->allLayers();
for (auto it=layersList.rbegin(), end=layersList.rend(); it!=end; ++it) {
doc::Layer* layer = *it;
i = layers->addItem(new LayerListItem(layer));
- if (defLayer == layer->name())
+ if (defLayer == layer->name() && defLayerIndex == -1 ||
+ defLayer == layer->name() && defLayerIndex == i-kLayersComboboxExtraInitialItems)
layers->setSelectedItemIndex(i);
}
}
@@ -112,6 +117,7 @@ void fill_anidir_combobox(ui::ComboBox* anidir, doc::AniDir defAnidir)
void calculate_visible_layers(const Site& site,
const std::string& layersValue,
+ const int layersIndex,
RestoreVisibleLayers& layersVisibility)
{
if (layersValue == kSelectedLayers) {
@@ -124,10 +130,13 @@ void calculate_visible_layers(const Site& site,
layersVisibility.showLayer(const_cast(site.layer()));
}
}
- else if (layersValue != kAllFrames) {
+ else if (layersValue != kAllLayers) {
+ int i = site.sprite()->allLayersCount();
// TODO add a getLayerByName
for (doc::Layer* layer : site.sprite()->allLayers()) {
- if (layer->name() == layersValue) {
+ i--;
+ if (layer->name() == layersValue && layersIndex == -1 ||
+ layer->name() == layersValue && layersIndex == i) {
layersVisibility.showLayer(layer);
break;
}
diff --git a/src/app/ui/layer_frame_comboboxes.h b/src/app/ui/layer_frame_comboboxes.h
index c7d3afd61..2f4744705 100644
--- a/src/app/ui/layer_frame_comboboxes.h
+++ b/src/app/ui/layer_frame_comboboxes.h
@@ -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
@@ -35,6 +35,8 @@ namespace app {
extern const char* kSelectedLayers;
extern const char* kSelectedFrames;
+ constexpr const int kLayersComboboxExtraInitialItems = 2;
+
class LayerListItem : public ui::ListItem {
public:
LayerListItem(doc::Layer* layer);
@@ -52,12 +54,13 @@ namespace app {
doc::Tag* m_tag;
};
- void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer);
+ void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const std::string& defLayer, const int defLayerIndex);
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);
void calculate_visible_layers(const Site& site,
const std::string& layersValue,
+ const int layersIndex,
RestoreVisibleLayers& layersVisibility);
doc::Tag* calculate_selected_frames(const Site& site,