lua: Add support to specify ExportSpriteSheet params

This commit is contained in:
David Capello 2019-01-08 16:42:01 -03:00
parent 271865e13d
commit 4dd7febb99
4 changed files with 234 additions and 82 deletions

View File

@ -27,6 +27,7 @@
#include "app/ui/status_bar.h" #include "app/ui/status_bar.h"
#include "app/ui/timeline/timeline.h" #include "app/ui/timeline/timeline.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/clamp.h"
#include "base/convert_to.h" #include "base/convert_to.h"
#include "base/fs.h" #include "base/fs.h"
#include "base/string.h" #include "base/string.h"
@ -162,12 +163,35 @@ 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<bool> bestFit { this, false, "bestFit" };
Param<std::string> textureFilename { this, std::string(), "textureFilename" };
Param<std::string> dataFilename { this, std::string(), "dataFilename" };
Param<DocExporter::DataFormat> dataFormat { this, DocExporter::DefaultDataFormat, "dataFormat" };
Param<int> borderPadding { this, 0, "borderPadding" };
Param<int> shapePadding { this, 0, "shapePadding" };
Param<int> innerPadding { this, 0, "innerPadding" };
Param<bool> trim { this, false, "trim" };
Param<bool> openGenerated { this, false, "openGenerated" };
Param<std::string> layer { this, std::string(), "layer" };
Param<std::string> tag { this, std::string(), "tag" };
Param<bool> listLayers { this, true, "listLayers" };
Param<bool> listTags { this, true, "listTags" };
Param<bool> listSlices { this, true, "listSlices" };
};
class ExportSpriteSheetWindow : public app::gen::ExportSpriteSheet { class ExportSpriteSheetWindow : public app::gen::ExportSpriteSheet {
public: public:
ExportSpriteSheetWindow(Site& site, DocumentPreferences& docPref) ExportSpriteSheetWindow(Site& site, ExportSpriteSheetParams& params)
: m_site(site) : m_site(site)
, m_sprite(site.sprite()) , m_sprite(site.sprite())
, m_docPref(docPref)
, m_filenameAskOverwrite(true) , m_filenameAskOverwrite(true)
, m_dataFilenameAskOverwrite(true) , m_dataFilenameAskOverwrite(true)
{ {
@ -183,25 +207,25 @@ public:
sheetType()->addItem("Vertical Strip"); sheetType()->addItem("Vertical Strip");
sheetType()->addItem("By Rows"); sheetType()->addItem("By Rows");
sheetType()->addItem("By Columns"); sheetType()->addItem("By Columns");
if (m_docPref.spriteSheet.type() != app::SpriteSheetType::None) if (params.type() != app::SpriteSheetType::None)
sheetType()->setSelectedItemIndex((int)m_docPref.spriteSheet.type()-1); sheetType()->setSelectedItemIndex((int)params.type()-1);
fill_layers_combobox( fill_layers_combobox(
m_sprite, layers(), m_docPref.spriteSheet.layer()); m_sprite, layers(), params.layer());
fill_frames_combobox( fill_frames_combobox(
m_sprite, frames(), m_docPref.spriteSheet.frameTag()); m_sprite, frames(), params.tag());
openGenerated()->setSelected(m_docPref.spriteSheet.openGenerated()); openGenerated()->setSelected(params.openGenerated());
trimEnabled()->setSelected(m_docPref.spriteSheet.trim()); trimEnabled()->setSelected(params.trim());
borderPadding()->setTextf("%d", m_docPref.spriteSheet.borderPadding()); borderPadding()->setTextf("%d", params.borderPadding());
shapePadding()->setTextf("%d", m_docPref.spriteSheet.shapePadding()); shapePadding()->setTextf("%d", params.shapePadding());
innerPadding()->setTextf("%d", m_docPref.spriteSheet.innerPadding()); innerPadding()->setTextf("%d", params.innerPadding());
paddingEnabled()->setSelected( paddingEnabled()->setSelected(
m_docPref.spriteSheet.borderPadding() || params.borderPadding() ||
m_docPref.spriteSheet.shapePadding() || params.shapePadding() ||
m_docPref.spriteSheet.innerPadding()); params.innerPadding());
paddingContainer()->setVisible(paddingEnabled()->isSelected()); paddingContainer()->setVisible(paddingEnabled()->isSelected());
for (int i=2; i<=8192; i*=2) { for (int i=2; i<=8192; i*=2) {
@ -210,36 +234,36 @@ public:
if (i >= m_sprite->height()) fitHeight()->addItem(value); if (i >= m_sprite->height()) fitHeight()->addItem(value);
} }
if (m_docPref.spriteSheet.bestFit()) { if (params.bestFit()) {
bestFit()->setSelected(true); bestFit()->setSelected(true);
onBestFit(); onBestFit();
} }
else { else {
columns()->setTextf("%d", m_docPref.spriteSheet.columns()); columns()->setTextf("%d", params.columns());
rows()->setTextf("%d", m_docPref.spriteSheet.rows()); rows()->setTextf("%d", params.rows());
onColumnsChange(); onColumnsChange();
if (m_docPref.spriteSheet.width() > 0 || m_docPref.spriteSheet.height() > 0) { if (params.width() > 0 || params.height() > 0) {
if (m_docPref.spriteSheet.width() > 0) if (params.width() > 0)
fitWidth()->getEntryWidget()->setTextf("%d", m_docPref.spriteSheet.width()); fitWidth()->getEntryWidget()->setTextf("%d", params.width());
if (m_docPref.spriteSheet.height() > 0) if (params.height() > 0)
fitHeight()->getEntryWidget()->setTextf("%d", m_docPref.spriteSheet.height()); fitHeight()->getEntryWidget()->setTextf("%d", params.height());
onSizeChange(); onSizeChange();
} }
} }
m_filename = m_docPref.spriteSheet.textureFilename(); m_filename = params.textureFilename();
imageEnabled()->setSelected(!m_filename.empty()); imageEnabled()->setSelected(!m_filename.empty());
imageFilename()->setVisible(imageEnabled()->isSelected()); imageFilename()->setVisible(imageEnabled()->isSelected());
m_dataFilename = m_docPref.spriteSheet.dataFilename(); m_dataFilename = params.dataFilename();
dataEnabled()->setSelected(!m_dataFilename.empty()); dataEnabled()->setSelected(!m_dataFilename.empty());
dataFormat()->setSelectedItemIndex(int(m_docPref.spriteSheet.dataFormat())); dataFormat()->setSelectedItemIndex(int(params.dataFormat()));
listLayers()->setSelected(m_docPref.spriteSheet.listLayers()); listLayers()->setSelected(params.listLayers());
listTags()->setSelected(m_docPref.spriteSheet.listFrameTags()); listTags()->setSelected(params.listTags());
listSlices()->setSelected(m_docPref.spriteSheet.listSlices()); listSlices()->setSelected(params.listSlices());
updateDataFields(); updateDataFields();
std::string base = site.document()->filename(); std::string base = site.document()->filename();
@ -575,18 +599,12 @@ private:
Site& m_site; Site& m_site;
Sprite* m_sprite; Sprite* m_sprite;
DocumentPreferences& m_docPref;
std::string m_filename; std::string m_filename;
std::string m_dataFilename; std::string m_dataFilename;
bool m_filenameAskOverwrite; bool m_filenameAskOverwrite;
bool m_dataFilenameAskOverwrite; bool m_dataFilenameAskOverwrite;
}; };
struct ExportSpriteSheetParams : public NewParams {
Param<bool> ui { this, true, "ui" };
Param<bool> askOverwrite { this, true, { "askOverwrite", "ask-overwrite" } };
};
class ExportSpriteSheetCommand : public CommandWithNewParams<ExportSpriteSheetParams> { class ExportSpriteSheetCommand : public CommandWithNewParams<ExportSpriteSheetParams> {
public: public:
ExportSpriteSheetCommand(); ExportSpriteSheetCommand();
@ -612,35 +630,63 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
Doc* document = site.document(); Doc* document = site.document();
Sprite* sprite = site.sprite(); Sprite* sprite = site.sprite();
DocumentPreferences& docPref(Preferences::instance().document(document)); DocumentPreferences& docPref(Preferences::instance().document(document));
auto& params = this->params();
#ifdef ENABLE_UI #ifdef ENABLE_UI
bool askOverwrite = params().askOverwrite(); bool askOverwrite = params.askOverwrite();
if (params().ui() && context->isUIAvailable()) { // Show UI if the user specified it explicitly or the sprite sheet type wasn't specified.
ExportSpriteSheetWindow window(site, docPref); if (context->isUIAvailable() && params.ui() &&
(params.ui.isSet() ||
!params.type() == app::SpriteSheetType::None)) {
// Copy document preferences to undefined params
if (docPref.spriteSheet.defined(true) &&
!params.type.isSet()) {
params.type(docPref.spriteSheet.type());
if (!params.columns.isSet()) params.columns( docPref.spriteSheet.columns());
if (!params.rows.isSet()) params.rows( docPref.spriteSheet.rows());
if (!params.width.isSet()) params.width( docPref.spriteSheet.width());
if (!params.height.isSet()) params.height( docPref.spriteSheet.height());
if (!params.bestFit.isSet()) params.bestFit( docPref.spriteSheet.bestFit());
if (!params.textureFilename.isSet()) params.textureFilename( docPref.spriteSheet.textureFilename());
if (!params.dataFilename.isSet()) params.dataFilename( docPref.spriteSheet.dataFilename());
if (!params.dataFormat.isSet()) params.dataFormat( docPref.spriteSheet.dataFormat());
if (!params.borderPadding.isSet()) params.borderPadding( docPref.spriteSheet.borderPadding());
if (!params.shapePadding.isSet()) params.shapePadding( docPref.spriteSheet.shapePadding());
if (!params.innerPadding.isSet()) params.innerPadding( docPref.spriteSheet.innerPadding());
if (!params.trim.isSet()) params.trim( docPref.spriteSheet.trim());
if (!params.openGenerated.isSet()) params.openGenerated( docPref.spriteSheet.openGenerated());
if (!params.layer.isSet()) params.layer( docPref.spriteSheet.layer());
if (!params.tag.isSet()) params.tag( docPref.spriteSheet.frameTag());
if (!params.listLayers.isSet()) params.listLayers( docPref.spriteSheet.listLayers());
if (!params.listTags.isSet()) params.listTags( docPref.spriteSheet.listFrameTags());
if (!params.listSlices.isSet()) params.listSlices( docPref.spriteSheet.listSlices());
}
ExportSpriteSheetWindow window(site, params);
window.openWindowInForeground(); window.openWindowInForeground();
if (!window.ok()) if (!window.ok())
return; return;
docPref.spriteSheet.defined(true); docPref.spriteSheet.defined(true);
docPref.spriteSheet.type(window.spriteSheetTypeValue()); docPref.spriteSheet.type (params.type (window.spriteSheetTypeValue()));
docPref.spriteSheet.columns(window.columnsValue()); docPref.spriteSheet.columns (params.columns (window.columnsValue()));
docPref.spriteSheet.rows(window.rowsValue()); docPref.spriteSheet.rows (params.rows (window.rowsValue()));
docPref.spriteSheet.width(window.fitWidthValue()); docPref.spriteSheet.width (params.width (window.fitWidthValue()));
docPref.spriteSheet.height(window.fitHeightValue()); docPref.spriteSheet.height (params.height (window.fitHeightValue()));
docPref.spriteSheet.bestFit(window.bestFitValue()); docPref.spriteSheet.bestFit (params.bestFit (window.bestFitValue()));
docPref.spriteSheet.textureFilename(window.filenameValue()); docPref.spriteSheet.textureFilename (params.textureFilename (window.filenameValue()));
docPref.spriteSheet.dataFilename(window.dataFilenameValue()); docPref.spriteSheet.dataFilename (params.dataFilename (window.dataFilenameValue()));
docPref.spriteSheet.dataFormat(window.dataFormatValue()); docPref.spriteSheet.dataFormat (params.dataFormat (window.dataFormatValue()));
docPref.spriteSheet.borderPadding(window.borderPaddingValue()); docPref.spriteSheet.borderPadding (params.borderPadding (window.borderPaddingValue()));
docPref.spriteSheet.shapePadding(window.shapePaddingValue()); docPref.spriteSheet.shapePadding (params.shapePadding (window.shapePaddingValue()));
docPref.spriteSheet.innerPadding(window.innerPaddingValue()); docPref.spriteSheet.innerPadding (params.innerPadding (window.innerPaddingValue()));
docPref.spriteSheet.trim(window.trimValue()); docPref.spriteSheet.trim (params.trim (window.trimValue()));
docPref.spriteSheet.openGenerated(window.openGeneratedValue()); docPref.spriteSheet.openGenerated (params.openGenerated (window.openGeneratedValue()));
docPref.spriteSheet.layer(window.layerValue()); docPref.spriteSheet.layer (params.layer (window.layerValue()));
docPref.spriteSheet.frameTag(window.frameTagValue()); docPref.spriteSheet.frameTag (params.tag (window.frameTagValue()));
docPref.spriteSheet.listLayers(window.listLayersValue()); docPref.spriteSheet.listLayers (params.listLayers (window.listLayersValue()));
docPref.spriteSheet.listFrameTags(window.listFrameTagsValue()); docPref.spriteSheet.listFrameTags (params.listTags (window.listFrameTagsValue()));
docPref.spriteSheet.listSlices(window.listSlicesValue()); docPref.spriteSheet.listSlices (params.listSlices (window.listSlicesValue()));
// Default preferences for future sprites // Default preferences for future sprites
DocumentPreferences& defPref(Preferences::instance().document(nullptr)); DocumentPreferences& defPref(Preferences::instance().document(nullptr));
@ -656,27 +702,24 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
} }
#endif // ENABLE_UI #endif // ENABLE_UI
app::SpriteSheetType type = docPref.spriteSheet.type(); const app::SpriteSheetType type = params.type();
int columns = docPref.spriteSheet.columns(); int columns = params.columns();
int rows = docPref.spriteSheet.rows(); int rows = params.rows();
int width = docPref.spriteSheet.width(); int width = params.width();
int height = docPref.spriteSheet.height(); int height = params.height();
bool bestFit = docPref.spriteSheet.bestFit(); const bool bestFit = params.bestFit();
std::string filename = docPref.spriteSheet.textureFilename(); const std::string filename = params.textureFilename();
std::string dataFilename = docPref.spriteSheet.dataFilename(); const std::string dataFilename = params.dataFilename();
DocExporter::DataFormat dataFormat = docPref.spriteSheet.dataFormat(); const DocExporter::DataFormat dataFormat = params.dataFormat();
std::string layerName = docPref.spriteSheet.layer(); const std::string layerName = params.layer();
std::string frameTagName = docPref.spriteSheet.frameTag(); const std::string tagName = params.tag();
int borderPadding = docPref.spriteSheet.borderPadding(); const int borderPadding = base::clamp(params.borderPadding(), 0, 100);
int shapePadding = docPref.spriteSheet.shapePadding(); const int shapePadding = base::clamp(params.shapePadding(), 0, 100);
int innerPadding = docPref.spriteSheet.innerPadding(); const int innerPadding = base::clamp(params.innerPadding(), 0, 100);
borderPadding = MID(0, borderPadding, 100); const bool trimCels = params.trim();
shapePadding = MID(0, shapePadding, 100); const bool listLayers = params.listLayers();
innerPadding = MID(0, innerPadding, 100); const bool listTags = params.listTags();
const bool trimCels = docPref.spriteSheet.trim(); const bool listSlices = params.listSlices();
const bool listLayers = docPref.spriteSheet.listLayers();
const bool listFrameTags = docPref.spriteSheet.listFrameTags();
const bool listSlices = docPref.spriteSheet.listSlices();
#ifdef ENABLE_UI #ifdef ENABLE_UI
if (context->isUIAvailable() && askOverwrite) { if (context->isUIAvailable() && askOverwrite) {
@ -688,7 +731,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
SelectedFrames selFrames; SelectedFrames selFrames;
FrameTag* frameTag = FrameTag* frameTag =
calculate_selected_frames(site, frameTagName, selFrames); calculate_selected_frames(site, tagName, selFrames);
frame_t nframes = selFrames.size(); frame_t nframes = selFrames.size();
ASSERT(nframes > 0); ASSERT(nframes > 0);
@ -758,7 +801,7 @@ void ExportSpriteSheetCommand::onExecute(Context* context)
exporter.setInnerPadding(innerPadding); exporter.setInnerPadding(innerPadding);
exporter.setTrimCels(trimCels); exporter.setTrimCels(trimCels);
if (listLayers) exporter.setListLayers(true); if (listLayers) exporter.setListLayers(true);
if (listFrameTags) exporter.setListFrameTags(true); if (listTags) exporter.setListFrameTags(true);
if (listSlices) exporter.setListSlices(true); if (listSlices) exporter.setListSlices(true);
exporter.addDocument(document, frameTag, exporter.addDocument(document, frameTag,
(!selLayers.empty() ? &selLayers: nullptr), (!selLayers.empty() ? &selLayers: nullptr),

View File

@ -10,14 +10,59 @@
#include "app/commands/new_params.h" #include "app/commands/new_params.h"
#include "app/doc_exporter.h"
#include "app/script/luacpp.h" #include "app/script/luacpp.h"
#include "app/sprite_sheet_type.h"
#include "base/convert_to.h"
#include "base/string.h"
namespace app { namespace app {
template<> template<>
void Param<bool>::fromString(const std::string& value) void Param<bool>::fromString(const std::string& value)
{ {
m_value = (value == "1" || value == "true"); setValue(value == "1" || value == "true");
}
template<>
void Param<int>::fromString(const std::string& value)
{
setValue(base::convert_to<int>(value));
}
template<>
void Param<std::string>::fromString(const std::string& value)
{
setValue(value);
}
template<>
void Param<app::SpriteSheetType>::fromString(const std::string& value)
{
if (value == "horizontal")
setValue(app::SpriteSheetType::Horizontal);
else if (value == "vertical")
setValue(app::SpriteSheetType::Vertical);
else if (value == "rows")
setValue(app::SpriteSheetType::Rows);
else if (value == "columns")
setValue(app::SpriteSheetType::Columns);
else if (value == "packed")
setValue(app::SpriteSheetType::Packed);
else
setValue(app::SpriteSheetType::None);
}
template<>
void Param<app::DocExporter::DataFormat>::fromString(const std::string& value)
{
// JsonArray, json-array, json_array, etc.
if (base::utf8_icmp(value, "JsonArray") == 0 ||
base::utf8_icmp(value, "json-array") == 0 ||
base::utf8_icmp(value, "json_array") == 0)
setValue(app::DocExporter::JsonArrayDataFormat);
else
setValue(app::DocExporter::JsonHashDataFormat);
} }
#ifdef ENABLE_SCRIPTING #ifdef ENABLE_SCRIPTING
@ -25,7 +70,40 @@ void Param<bool>::fromString(const std::string& value)
template<> template<>
void Param<bool>::fromLua(lua_State* L, int index) void Param<bool>::fromLua(lua_State* L, int index)
{ {
m_value = lua_toboolean(L, index); setValue(lua_toboolean(L, index));
}
template<>
void Param<int>::fromLua(lua_State* L, int index)
{
setValue(lua_tointeger(L, index));
}
template<>
void Param<std::string>::fromLua(lua_State* L, int index)
{
if (const char* s = lua_tostring(L, index))
setValue(s);
else
setValue(std::string());
}
template<>
void Param<app::SpriteSheetType>::fromLua(lua_State* L, int index)
{
if (lua_isstring(L, index))
fromString(lua_tostring(L, index));
else
setValue((app::SpriteSheetType)lua_tointeger(L, index));
}
template<>
void Param<app::DocExporter::DataFormat>::fromLua(lua_State* L, int index)
{
if (lua_isstring(L, index))
fromString(lua_tostring(L, index));
else
setValue((app::DocExporter::DataFormat)lua_tointeger(L, index));
} }
void CommandWithNewParamsBase::onLoadParams(const Params& params) void CommandWithNewParamsBase::onLoadParams(const Params& params)

View File

@ -73,8 +73,13 @@ namespace app {
params->addParam(id, this); params->addParam(id, this);
} }
bool isSet() {
return m_isSet;
}
void resetValue() override { void resetValue() override {
m_value = m_defaultValue; m_value = m_defaultValue;
m_isSet = false;
} }
void fromString(const std::string& value) override; void fromString(const std::string& value) override;
@ -86,13 +91,20 @@ namespace app {
return m_value; return m_value;
} }
void operator()(const T& value) { T& operator()(const T& value) {
m_value = value; m_value = value;
m_isSet = true;
return m_value;
} }
private: private:
void setValue(const T& value) {
operator()(value);
}
T m_defaultValue; T m_defaultValue;
T m_value; T m_value;
bool m_isSet = false;
}; };
class CommandWithNewParamsBase : public Command { class CommandWithNewParamsBase : public Command {

View File

@ -13,9 +13,11 @@
#include "app/app.h" #include "app/app.h"
#include "app/console.h" #include "app/console.h"
#include "app/doc_exporter.h"
#include "app/doc_range.h" #include "app/doc_range.h"
#include "app/script/luacpp.h" #include "app/script/luacpp.h"
#include "app/script/security.h" #include "app/script/security.h"
#include "app/sprite_sheet_type.h"
#include "base/chrono.h" #include "base/chrono.h"
#include "base/file_handle.h" #include "base/file_handle.h"
#include "base/fs.h" #include "base/fs.h"
@ -278,6 +280,23 @@ Engine::Engine()
setfield_integer(L, "CELS", DocRange::kCels); setfield_integer(L, "CELS", DocRange::kCels);
lua_pop(L, 1); lua_pop(L, 1);
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "SpriteSheetType");
setfield_integer(L, "HORIZONTAL", SpriteSheetType::Horizontal);
setfield_integer(L, "VERTICAL", SpriteSheetType::Vertical);
setfield_integer(L, "ROWS", SpriteSheetType::Rows);
setfield_integer(L, "COLUMNS", SpriteSheetType::Columns);
setfield_integer(L, "PACKED", SpriteSheetType::Packed);
lua_pop(L, 1);
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "SpriteSheetDataFormat");
setfield_integer(L, "JSON_HASH", DocExporter::JsonHashDataFormat);
setfield_integer(L, "JSON_ARRAY", DocExporter::JsonArrayDataFormat);
lua_pop(L, 1);
// Register classes/prototypes // Register classes/prototypes
register_cel_class(L); register_cel_class(L);
register_cels_class(L); register_cels_class(L);