Change Export Sprite Sheet dialog with a tab-like UI

This commit is contained in:
David Capello 2019-10-26 13:24:27 -03:00
parent ad12ec4a0d
commit c0dfd76114
3 changed files with 175 additions and 152 deletions

View File

@ -534,7 +534,14 @@ cancel = &Cancel
[export_sprite_sheet]
title = Export Sprite Sheet
format = Format:
sprite = Sprite
sprite_tooltip = Source of sprite samples to export in the sprite sheet
borders = Borders
borders_tooltip = Add or trim borders from each sprite in the sprite sheet
layout = Layout
layout_tooltip = Arrangement of sprites in the final result
output = Output
output_tooltip = Where to store the sprite sheet
sheet_type = Sheet Type:
sheet_type_tooltip = <<<END
Indicates a specific way to layout sprites in the sprite sheet:
@ -549,7 +556,7 @@ type_vert = Vertical Strip
type_rows = By Rows
type_cols = By Columns
type_pack = Packed
constraints = Constraints
constraints = Constraints:
constraints_tooltip = <<<END
Special constraints for the sprite sheet.
E.g. Fixed number of rows/columns or fixed
@ -561,13 +568,14 @@ constraint_fixed_rows = Fixed # of Rows
constraint_fixed_width = Fixed Width
constraint_fixed_height = Fixed Height
constraint_fixed_size = Fixed Size
padding = Padding
padding_tooltip = Extra space to add between sprites
border = Border:
border = Border Padding:
border_tooltip = Space between each frame and the edge of the sprite sheet
shape = Spacing:
shape_tooltip = Space between each frame in the sprite sheet
inner = Inner:
shape_tooltip = <<<END
Space between each frame in the sprite sheet
(a.k.a "Shape Padding")
END
inner = Inner Padding:
inner_tooltip = Extra space inside frame edges
trim_sprite = Trim Sprite
trim_sprite_tooltip = Trims the whole sprite before its frames are included in the sprite sheet
@ -577,17 +585,16 @@ trim_by_grid = By Grid
trim_by_grid_tooltip = Trims by grid boundaries instead of pixel by pixel
extrude = Extrude
extrude_tooltip = Adds a border to each frame duplicating the pixels of its edges
merge_dups = Merge Dups
merge_dups_tooltip = Merge Duplicate Frames
merge_dups = Merge Duplicates
merge_dups_tooltip = Similar frames can use the same sprite sheet rectangular area
ignore_empty = Ignore Empty
ignore_empty_tooltip = Ignore Empty Frames
ignore_empty_tooltip = Do not include empty/transparent frames in the sprite sheet
layers = Layers:
split_layers = Split Layers
split_layers_tooltip = Generates one sprite for each layer
split_tags = Split Tags
split_tags_tooltip = Generates one sprite for each tag
frames = Frames:
output = Output:
output_file = Output File
json_data = JSON Data
json_data_hash = Hash
@ -604,7 +611,7 @@ how to build each frame. You can use special marks
like {layer}, {frame}, {tag}, {tagframe}, etc.
END
preview = Preview
open_sprite_sheet = Open Generated Sprite Sheet
open_sprite_sheet = Open Sprite Sheet
export = &Export
cancel = &Cancel
generating = Generating...

View File

@ -3,106 +3,137 @@
<!-- Copyright (C) 2001-2018 David Capello -->
<gui>
<window id="export_sprite_sheet" text="@.title">
<grid columns="4" expansive="true">
<separator horizontal="true" text="@.format" cell_hspan="4" />
<vbox expansive="true">
<label text="@.sheet_type" />
<combobox id="sheet_type" expansive="true" cell_hspan="2" cell_align="horizontal"
tooltip="@.sheet_type_tooltip" />
<check id="show_constraints" text="@.constraints"
tooltip="@.constraints_tooltip" />
<!-- Tabs -->
<label id="constraints_label" text="@.constraints" />
<hbox id="constraints_placeholder" cell_hspan="3">
<combobox id="constraint_type" />
<expr id="width_constraint" />
<expr id="height_constraint" />
<hbox>
<separator horizontal="true" expansive="true" />
<buttonset id="section_tabs" columns="4">
<item id="sectin_sprite_tab" text="@.sprite" tooltip="@.sprite_tooltip" tooltip_dir="bottom" selected="true" />
<item id="sectin_borders_tab" text="@.borders" tooltip="@.borders_tooltip" tooltip_dir="bottom" />
<item id="sectin_layout_tab" text="@.layout" tooltip="@.layout_tooltip" tooltip_dir="bottom" />
<item id="sectin_output_tab" text="@.output" tooltip="@.output_tooltip" tooltip_dir="bottom" />
</buttonset>
<separator horizontal="true" expansive="true" />
</hbox>
<label text="@.layers" />
<combobox id="layers" text="" cell_hspan="2" />
<check id="split_layers" text="@.split_layers" tooltip="@.split_layers_tooltip" />
<panel id="panel" expansive="true">
<label text="@.frames" />
<combobox id="frames" text="" cell_hspan="2" />
<check id="split_tags" text="@.split_tags" tooltip="@.split_tags_tooltip" />
<!-- Sprite -->
<hbox />
<hbox cell_hspan="3">
<vbox>
<check id="trim_sprite_enabled" text="@.trim_sprite" tooltip="@.trim_sprite_tooltip" />
<check id="trim_enabled" text="@.trim" tooltip="@.trim_tooltip" />
<vbox id="trim_container" cell_hspan="2">
<check id="grid_trim_enabled"
text="@.trim_by_grid"
tooltip="@.trim_by_grid_tooltip" />
</vbox>
</vbox>
<separator vertical="true" />
<vbox>
<check id="padding_enabled" text="@.padding" tooltip="@.padding_tooltip" />
<check id="extrude_enabled"
text="@.extrude"
tooltip="@.extrude_tooltip" />
</vbox>
<vbox>
<grid columns="2" id="padding_container">
<label text="@.border" />
<expr id="border_padding" text="0" tooltip="@.border_tooltip" />
<label text="@.shape" />
<expr id="shape_padding" text="0" tooltip="@.shape_tooltip" />
<label text="@.inner" />
<expr id="inner_padding" text="0" tooltip="@.inner_tooltip" />
</grid>
</vbox>
<separator id="padding_separator" vertical="true" />
<vbox>
<check id="merge_dups" text="@.merge_dups" tooltip="@.merge_dups_tooltip" />
<check id="ignore_empty" text="@.ignore_empty" tooltip="@.ignore_empty_tooltip" />
</vbox>
</hbox>
<grid id="section_sprite" columns="4" expansive="true">
<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" />
<separator horizontal="true" text="@.output" cell_hspan="4" cell_align="horizontal" />
<label text="@.frames" />
<combobox id="frames" text="" cell_hspan="2" cell_align="horizontal" />
<check id="split_tags" text="@.split_tags" tooltip="@.split_tags_tooltip" tooltip_dir="top" />
</grid>
<check id="image_enabled" text="@.output_file" />
<button id="image_filename" cell_hspan="3" />
<!-- Borders -->
<check id="data_enabled" text="@.json_data" />
<button id="data_filename" cell_hspan="3" />
<grid id="section_borders" columns="4" expansive="true">
<hbox />
<hbox id="data_meta" cell_hspan="3" cell_align="horizontal">
<combobox id="data_format">
<listitem text="@.json_data_hash" value="0" />
<listitem text="@.json_data_array" value="1" />
</combobox>
<label text="@.meta" />
<check id="list_layers" text="@.meta_layers" />
<check id="list_tags" text="@.meta_tags" />
<check id="list_slices" text="@.meta_slices" />
</hbox>
<hbox />
<hbox cell_hspan="3">
<vbox>
<grid columns="2">
<label text="@.border" />
<expr id="border_padding" text="0" tooltip="@.border_tooltip" />
<label text="@.shape" />
<expr id="shape_padding" text="0" tooltip="@.shape_tooltip" />
<label text="@.inner" />
<expr id="inner_padding" text="0" tooltip="@.inner_tooltip" />
</grid>
</vbox>
<separator vertical="true" />
<vbox>
<check id="trim_sprite_enabled" text="@.trim_sprite" tooltip="@.trim_sprite_tooltip" />
<check id="trim_enabled" text="@.trim" tooltip="@.trim_tooltip" />
<vbox id="trim_container" cell_hspan="2">
<check id="grid_trim_enabled"
text="@.trim_by_grid"
tooltip="@.trim_by_grid_tooltip" />
</vbox>
</vbox>
<separator vertical="true" />
<vbox>
<check id="extrude_enabled"
text="@.extrude"
tooltip="@.extrude_tooltip" />
</vbox>
</hbox>
<hbox />
<hbox id="data_filename_format_placeholder" cell_hspan="3" cell_align="horizontal">
<label text="@.data_filename_format" />
<entry id="data_filename_format" maxsize="1024" maxwidth="256" expansive="true"
tooltip="@.data_filename_format_tooltip" />
<link text="(?)" url="https://www.aseprite.org/docs/cli/#filename-format" />
</hbox>
</grid>
<!-- Layout -->
<grid id="section_layout" columns="4" expansive="true">
<label text="@.sheet_type" />
<combobox id="sheet_type" expansive="true" cell_hspan="3" cell_align="horizontal"
tooltip="@.sheet_type_tooltip" tooltip_dir="bottom" />
<label text="@.constraints" />
<hbox cell_hspan="3">
<combobox id="constraint_type" tooltip="@.constraints_tooltip" />
<expr id="width_constraint" />
<expr id="height_constraint" />
</hbox>
<hbox />
<hbox cell_hspan="3">
<check id="merge_dups" text="@.merge_dups" tooltip="@.merge_dups_tooltip" />
<check id="ignore_empty" text="@.ignore_empty" tooltip="@.ignore_empty_tooltip" />
</hbox>
</grid>
<!-- Output -->
<grid id="section_output" columns="4" expansive="true">
<check id="image_enabled" text="@.output_file" />
<button id="image_filename" cell_hspan="3" cell_align="horizontal" />
<check id="data_enabled" text="@.json_data" />
<button id="data_filename" cell_hspan="3" cell_align="horizontal" />
<hbox />
<hbox id="data_meta" cell_hspan="3" cell_align="horizontal">
<combobox id="data_format">
<listitem text="@.json_data_hash" value="0" />
<listitem text="@.json_data_array" value="1" />
</combobox>
<label text="@.meta" />
<check id="list_layers" text="@.meta_layers" />
<check id="list_tags" text="@.meta_tags" />
<check id="list_slices" text="@.meta_slices" />
</hbox>
<hbox />
<hbox id="data_filename_format_placeholder" cell_hspan="3" cell_align="horizontal">
<label text="@.data_filename_format" />
<entry id="data_filename_format" maxsize="1024" maxwidth="256" expansive="true"
tooltip="@.data_filename_format_tooltip" />
<link text="(?)" url="https://www.aseprite.org/docs/cli/#filename-format" />
</hbox>
</grid>
</panel>
<separator horizontal="true" cell_hspan="4" />
<hbox cell_hspan="4">
<boxfiller />
<hbox>
<check id="open_generated" text="@.open_sprite_sheet" cell_hspan="3" />
<check id="open_generated" text="@.open_sprite_sheet" cell_hspan="3" />
<check id="preview" text="@.preview" cell_hspan="1" />
</hbox>
<boxfiller />
<hbox homogeneous="true">
<button text="@.export" minwidth="60" id="export_button" magnet="true" />
<button text="@.cancel" minwidth="60" closewindow="true" />
</hbox>
</hbox>
</grid>
</vbox>
</window>
</gui>

View File

@ -85,6 +85,13 @@ struct ExportSpriteSheetParams : public NewParams {
#ifdef ENABLE_UI
enum Section {
kSectionSprite,
kSectionBorders,
kSectionLayout,
kSectionOutput,
};
enum ConstraintType {
kConstraintType_None,
kConstraintType_Cols,
@ -294,6 +301,8 @@ public:
, m_executionID(0)
, m_filenameFormat(params.filenameFormat())
{
sectionTabs()->ItemChange.connect(base::Bind<void>(&ExportSpriteSheetWindow::onChangeSection, this));
static_assert(
(int)app::SpriteSheetType::None == 0 &&
(int)app::SpriteSheetType::Horizontal == 1 &&
@ -346,11 +355,6 @@ public:
borderPadding()->setTextf("%d", params.borderPadding());
shapePadding()->setTextf("%d", params.shapePadding());
innerPadding()->setTextf("%d", params.innerPadding());
paddingEnabled()->setSelected(
params.borderPadding() ||
params.shapePadding() ||
params.innerPadding());
paddingContainer()->setVisible(paddingEnabled()->isSelected());
m_filename = params.textureFilename();
imageEnabled()->setSelected(!m_filename.empty());
@ -387,7 +391,6 @@ public:
exportButton()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::onExport, this));
sheetType()->Change.connect(&ExportSpriteSheetWindow::onSheetTypeChange, this);
showConstraints()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::onSheetTypeChange, this));
constraintType()->Change.connect(&ExportSpriteSheetWindow::onConstraintTypeChange, this);
widthConstraint()->Change.connect(&ExportSpriteSheetWindow::generatePreview, this);
heightConstraint()->Change.connect(&ExportSpriteSheetWindow::generatePreview, this);
@ -404,7 +407,6 @@ public:
trimSpriteEnabled()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::onTrimEnabledChange, this));
trimEnabled()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::onTrimEnabledChange, this));
gridTrimEnabled()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::generatePreview, this));
paddingEnabled()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::onPaddingEnabledChange, this));
layers()->Change.connect(base::Bind<void>(&ExportSpriteSheetWindow::generatePreview, this));
splitLayers()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::onSplitLayersOrFrames, this));
splitTags()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::onSplitLayersOrFrames, this));
@ -414,6 +416,7 @@ public:
preview()->Click.connect(base::Bind<void>(&ExportSpriteSheetWindow::generatePreview, this));
m_genTimer.Tick.connect(base::Bind<void>(&ExportSpriteSheetWindow::onGenTimerTick, this));
onChangeSection();
onSheetTypeChange();
onFileNamesChange();
updateExportButton();
@ -473,13 +476,24 @@ private:
targets.push_back(View::getView(m_editor));
}
void onChangeSection() {
Widget* section = nullptr;
switch (sectionTabs()->selectedItem()) {
case kSectionSprite: section = sectionSprite(); break;
case kSectionBorders: section = sectionBorders(); break;
case kSectionLayout: section = sectionLayout(); break;
case kSectionOutput: section = sectionOutput(); break;
}
panel()->showChild(section);
resize();
}
app::SpriteSheetType spriteSheetTypeValue() const {
return (app::SpriteSheetType)(sheetType()->getSelectedItemIndex()+1);
}
int columnsValue() const {
if (showConstraints()->isSelected() &&
spriteSheetTypeValue() == app::SpriteSheetType::Rows &&
if (spriteSheetTypeValue() == app::SpriteSheetType::Rows &&
constraintType()->getSelectedItemIndex() == (int)kConstraintType_Cols) {
return widthConstraint()->textInt();
}
@ -488,8 +502,7 @@ private:
}
int rowsValue() const {
if (showConstraints()->isSelected() &&
spriteSheetTypeValue() == app::SpriteSheetType::Columns &&
if (spriteSheetTypeValue() == app::SpriteSheetType::Columns &&
constraintType()->getSelectedItemIndex() == (int)kConstraintType_Rows) {
return heightConstraint()->textInt();
}
@ -498,8 +511,7 @@ private:
}
int widthValue() const {
if (showConstraints()->isSelected() &&
(spriteSheetTypeValue() == app::SpriteSheetType::Rows ||
if ((spriteSheetTypeValue() == app::SpriteSheetType::Rows ||
spriteSheetTypeValue() == app::SpriteSheetType::Packed) &&
(constraintType()->getSelectedItemIndex() == (int)kConstraintType_Width ||
constraintType()->getSelectedItemIndex() == (int)kConstraintType_Size)) {
@ -510,8 +522,7 @@ private:
}
int heightValue() const {
if (showConstraints()->isSelected() &&
(spriteSheetTypeValue() == app::SpriteSheetType::Columns ||
if ((spriteSheetTypeValue() == app::SpriteSheetType::Columns ||
spriteSheetTypeValue() == app::SpriteSheetType::Packed) &&
(constraintType()->getSelectedItemIndex() == (int)kConstraintType_Height ||
constraintType()->getSelectedItemIndex() == (int)kConstraintType_Size)) {
@ -551,30 +562,18 @@ private:
}
int borderPaddingValue() const {
if (paddingEnabled()->isSelected()) {
int value = borderPadding()->textInt();
return base::clamp(value, 0, 100);
}
else
return 0;
int value = borderPadding()->textInt();
return base::clamp(value, 0, 100);
}
int shapePaddingValue() const {
if (paddingEnabled()->isSelected()) {
int value = shapePadding()->textInt();
return base::clamp(value, 0, 100);
}
else
return 0;
int value = shapePadding()->textInt();
return base::clamp(value, 0, 100);
}
int innerPaddingValue() const {
if (paddingEnabled()->isSelected()) {
int value = innerPadding()->textInt();
return base::clamp(value, 0, 100);
}
else
return 0;
int value = innerPadding()->textInt();
return base::clamp(value, 0, 100);
}
bool trimSpriteValue() const {
@ -646,57 +645,49 @@ private:
}
void onSheetTypeChange() {
for (int i=0; i<constraintType()->getItemCount(); ++i)
for (int i=1; i<constraintType()->getItemCount(); ++i)
constraintType()->getItem(i)->setVisible(false);
mergeDups()->setEnabled(true);
const ConstraintType selectConstraint =
(ConstraintType)constraintType()->getSelectedItemIndex();
bool constraints = true;
switch (spriteSheetTypeValue()) {
case app::SpriteSheetType::Horizontal:
case app::SpriteSheetType::Vertical:
constraints = false;
constraintType()->setSelectedItemIndex(kConstraintType_None);
break;
case app::SpriteSheetType::Rows:
constraintType()->getItem(kConstraintType_Cols)->setVisible(true);
constraintType()->getItem(kConstraintType_Width)->setVisible(true);
if (selectConstraint != kConstraintType_Cols &&
if (selectConstraint != kConstraintType_None &&
selectConstraint != kConstraintType_Cols &&
selectConstraint != kConstraintType_Width)
constraintType()->setSelectedItemIndex((int)kConstraintType_Cols);
constraintType()->setSelectedItemIndex(kConstraintType_None);
break;
case app::SpriteSheetType::Columns:
constraintType()->getItem(kConstraintType_Rows)->setVisible(true);
constraintType()->getItem(kConstraintType_Height)->setVisible(true);
if (selectConstraint != kConstraintType_Rows &&
if (selectConstraint != kConstraintType_None &&
selectConstraint != kConstraintType_Rows &&
selectConstraint != kConstraintType_Height)
constraintType()->setSelectedItemIndex((int)kConstraintType_Rows);
constraintType()->setSelectedItemIndex(kConstraintType_None);
break;
case app::SpriteSheetType::Packed:
constraintType()->getItem(kConstraintType_Width)->setVisible(true);
constraintType()->getItem(kConstraintType_Height)->setVisible(true);
constraintType()->getItem(kConstraintType_Size)->setVisible(true);
if (selectConstraint != kConstraintType_Width &&
if (selectConstraint != kConstraintType_None &&
selectConstraint != kConstraintType_Width &&
selectConstraint != kConstraintType_Height &&
selectConstraint != kConstraintType_Size) {
constraintType()->setSelectedItemIndex((int)kConstraintType_Size);
constraintType()->setSelectedItemIndex(kConstraintType_None);
}
mergeDups()->setSelected(true);
mergeDups()->setEnabled(false);
break;
}
showConstraints()->setVisible(constraints);
constraints = (constraints &&
showConstraints()->isSelected());
constraintsLabel()->setVisible(constraints);
constraintsPlaceholder()->setVisible(constraints);
if (constraints)
onConstraintTypeChange();
else {
resize();
generatePreview();
}
onConstraintTypeChange();
}
void onConstraintTypeChange() {
@ -793,12 +784,6 @@ private:
generatePreview();
}
void onPaddingEnabledChange() {
paddingContainer()->setVisible(paddingEnabled()->isSelected());
resize();
generatePreview();
}
void onSplitLayersOrFrames() {
updateDefaultDataFilenameFormat();
generatePreview();