From 4ff4274deb800257a93d21c755118adc8203200e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Capello?= Date: Tue, 27 Sep 2022 14:54:06 -0300 Subject: [PATCH 1/6] Refactor some conditional expressions to fix a compiler warning --- src/app/commands/cmd_export_sprite_sheet.cpp | 4 ++-- src/app/ui/layer_frame_comboboxes.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/commands/cmd_export_sprite_sheet.cpp b/src/app/commands/cmd_export_sprite_sheet.cpp index bade60de2..bd11a7c30 100644 --- a/src/app/commands/cmd_export_sprite_sheet.cpp +++ b/src/app/commands/cmd_export_sprite_sheet.cpp @@ -227,8 +227,8 @@ Doc* generate_sprite_sheet_from_params( int i = sprite->allLayersCount(); for (const Layer* layer : sprite->allLayers()) { i--; - if (layer->name() == layerName && layerIndex == -1 || - layer->name() == layerName && layerIndex == i) { + if (layer->name() == layerName && (layerIndex == -1 || + layerIndex == i)) { selLayers.insert(const_cast(layer)); break; } diff --git a/src/app/ui/layer_frame_comboboxes.cpp b/src/app/ui/layer_frame_comboboxes.cpp index ff5568fa3..ec523b8cf 100644 --- a/src/app/ui/layer_frame_comboboxes.cpp +++ b/src/app/ui/layer_frame_comboboxes.cpp @@ -75,8 +75,8 @@ void fill_layers_combobox(const doc::Sprite* sprite, ui::ComboBox* layers, const 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() && defLayerIndex == -1 || - defLayer == layer->name() && defLayerIndex == i-kLayersComboboxExtraInitialItems) + if (defLayer == layer->name() && (defLayerIndex == -1 || + defLayerIndex == i-kLayersComboboxExtraInitialItems)) layers->setSelectedItemIndex(i); } } @@ -135,8 +135,8 @@ void calculate_visible_layers(const Site& site, // TODO add a getLayerByName for (doc::Layer* layer : site.sprite()->allLayers()) { i--; - if (layer->name() == layersValue && layersIndex == -1 || - layer->name() == layersValue && layersIndex == i) { + if (layer->name() == layersValue && (layersIndex == -1 || + layersIndex == i)) { layersVisibility.showLayer(layer); break; } From 022c0c38df9dadccbb696ab02d20ddff1b383a93 Mon Sep 17 00:00:00 2001 From: Gaspar Capello Date: Fri, 16 Sep 2022 20:06:40 -0300 Subject: [PATCH 2/6] Fix dynamics + gradient + no dithering + fg or bg is mask color results in an opaque stroke. Before this fix, dynamic + gradient (pressure or velocity) + no dithering + fg or bg = mask color results in an opaque stroke. --- src/app/tools/point_shapes.h | 46 +++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/app/tools/point_shapes.h b/src/app/tools/point_shapes.h index 21373001e..a2717da5b 100644 --- a/src/app/tools/point_shapes.h +++ b/src/app/tools/point_shapes.h @@ -98,20 +98,39 @@ public: color_t b = m_primaryColor; const float t = pt.gradient; const float ti = 1.0f - pt.gradient; + + auto rgbaGradient = [t, ti](color_t a, color_t b) -> color_t { + if (rgba_geta(a) == 0) + return doc::rgba(rgba_getr(b), + rgba_getg(b), + rgba_getb(b), + int(t*rgba_geta(b))); + else if (rgba_geta(b) == 0) + return doc::rgba(rgba_getr(a), + rgba_getg(a), + rgba_getb(a), + int(ti*rgba_geta(a))); + else + return doc::rgba(int(ti*rgba_getr(a) + t*rgba_getr(b)), + int(ti*rgba_getg(a) + t*rgba_getg(b)), + int(ti*rgba_getb(a) + t*rgba_getb(b)), + int(ti*rgba_geta(a) + t*rgba_geta(b))); + }; + switch (loop->sprite()->pixelFormat()) { case IMAGE_RGB: - if (rgba_geta(a) == 0) a = b; - else if (rgba_geta(b) == 0) b = a; - a = doc::rgba(int(ti*rgba_getr(a) + t*rgba_getr(b)), - int(ti*rgba_getg(a) + t*rgba_getg(b)), - int(ti*rgba_getb(a) + t*rgba_getb(b)), - int(ti*rgba_geta(a) + t*rgba_geta(b))); + a = rgbaGradient(a, b); break; case IMAGE_GRAYSCALE: - if (graya_geta(a) == 0) a = b; - else if (graya_geta(b) == 0) b = a; - a = doc::graya(int(ti*graya_getv(a) + t*graya_getv(b)), - int(ti*graya_geta(a) + t*graya_geta(b))); + if (graya_geta(a) == 0) + a = doc::graya(graya_getv(b), + int(t*graya_geta(b))); + else if (graya_geta(b) == 0) + a = doc::graya(graya_getv(a), + int(ti*graya_geta(a))); + else + a = doc::graya(int(ti*graya_getv(a) + t*graya_getv(b)), + int(ti*graya_geta(a) + t*graya_geta(b))); break; case IMAGE_INDEXED: { int maskIndex = (loop->getLayer()->isBackground() ? -1: loop->sprite()->transparentColor()); @@ -121,12 +140,7 @@ public: if (b == maskIndex) b = 0; else b = loop->getPalette()->getEntry(b); // Same as in RGBA gradient - if (rgba_geta(a) == 0) a = b; - else if (rgba_geta(b) == 0) b = a; - a = doc::rgba(int(ti*rgba_getr(a) + t*rgba_getr(b)), - int(ti*rgba_getg(a) + t*rgba_getg(b)), - int(ti*rgba_getb(a) + t*rgba_getb(b)), - int(ti*rgba_geta(a) + t*rgba_geta(b))); + a = rgbaGradient(a, b); // Convert RGBA to index a = loop->getRgbMap()->mapColor(rgba_getr(a), rgba_getg(a), From c0dfb832d87c369aee22ed08b6702ab55543d382 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 29 Sep 2022 10:57:40 -0300 Subject: [PATCH 3/6] Fix crash if a script modifies the sprite when we're undoing/redoing (fix #3539) To do this the script must be listening the sprite changes (which are generated on undo/redo commands too). --- src/app/doc_undo.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/app/doc_undo.cpp b/src/app/doc_undo.cpp index f31ee1f85..647113ec5 100644 --- a/src/app/doc_undo.cpp +++ b/src/app/doc_undo.cpp @@ -100,16 +100,20 @@ bool DocUndo::canRedo() const void DocUndo::undo() { + const size_t oldSize = m_totalUndoSize; const undo::UndoState* state = nextUndo(); ASSERT(state); - const Cmd* cmd = STATE_CMD(state); - size_t oldSize = m_totalUndoSize; - m_totalUndoSize -= cmd->memSize(); { + const Cmd* cmd = STATE_CMD(state); + m_totalUndoSize -= cmd->memSize(); m_undoHistory.undo(); - notify_observers(&DocUndoObserver::onCurrentUndoStateChange, this); + m_totalUndoSize += cmd->memSize(); } - m_totalUndoSize += cmd->memSize(); + // This notification could execute a script that modifies the sprite + // again (e.g. a script that is listening the "change" event, check + // the SpriteEvents class). If the sprite is modified, the "cmd" is + // not valid anymore. + notify_observers(&DocUndoObserver::onCurrentUndoStateChange, this); if (m_totalUndoSize != oldSize) notify_observers(&DocUndoObserver::onTotalUndoSizeChange, this); } From 5c4024c44f68d5c5a1d5f20b44f2b02f289c3be6 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 29 Sep 2022 11:04:05 -0300 Subject: [PATCH 4/6] Replicate same changes from c0dfb832d87c369aee22ed08b6702ab55543d382 for redo (#3539) --- src/app/doc_undo.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/app/doc_undo.cpp b/src/app/doc_undo.cpp index 647113ec5..238a986ba 100644 --- a/src/app/doc_undo.cpp +++ b/src/app/doc_undo.cpp @@ -101,9 +101,9 @@ bool DocUndo::canRedo() const void DocUndo::undo() { const size_t oldSize = m_totalUndoSize; - const undo::UndoState* state = nextUndo(); - ASSERT(state); { + const undo::UndoState* state = nextUndo(); + ASSERT(state); const Cmd* cmd = STATE_CMD(state); m_totalUndoSize -= cmd->memSize(); m_undoHistory.undo(); @@ -120,16 +120,16 @@ void DocUndo::undo() void DocUndo::redo() { - const undo::UndoState* state = nextRedo(); - ASSERT(state); - const Cmd* cmd = STATE_CMD(state); - size_t oldSize = m_totalUndoSize; - m_totalUndoSize -= cmd->memSize(); + const size_t oldSize = m_totalUndoSize; { + const undo::UndoState* state = nextRedo(); + ASSERT(state); + const Cmd* cmd = STATE_CMD(state); + m_totalUndoSize -= cmd->memSize(); m_undoHistory.redo(); - notify_observers(&DocUndoObserver::onCurrentUndoStateChange, this); + m_totalUndoSize += cmd->memSize(); } - m_totalUndoSize += cmd->memSize(); + notify_observers(&DocUndoObserver::onCurrentUndoStateChange, this); if (m_totalUndoSize != oldSize) notify_observers(&DocUndoObserver::onTotalUndoSizeChange, this); } @@ -226,6 +226,10 @@ Cmd* DocUndo::lastExecutedCmd() const void DocUndo::moveToState(const undo::UndoState* state) { m_undoHistory.moveTo(state); + + // After onCurrentUndoStateChange don't use the "state" argument, it + // might be deleted because some script might have modified the + // sprite on its "change" event. notify_observers(&DocUndoObserver::onCurrentUndoStateChange, this); // Recalculate the total undo size From 6b21fec417f974a6d49d463f75c34c575f39ed73 Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 29 Sep 2022 12:09:06 -0300 Subject: [PATCH 5/6] [lua] Add "ev" args to "change" sprite event, to ask for "ev.fromUndo" In this way we can know if the event was generated from a undo/redo/undo history change and not from the direct user manipulation of the sprite. Useful for scripts like in #3539 --- src/app/script/api_version.h | 2 +- src/app/script/events_class.cpp | 32 +++++++++++++++++++++++++++----- src/app/script/values.cpp | 21 +++++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/src/app/script/api_version.h b/src/app/script/api_version.h index ee813acec..af369050f 100644 --- a/src/app/script/api_version.h +++ b/src/app/script/api_version.h @@ -10,6 +10,6 @@ // Increment this value if the scripting API is modified between two // released Aseprite versions. -#define API_VERSION 20 +#define API_VERSION 21 #endif diff --git a/src/app/script/events_class.cpp b/src/app/script/events_class.cpp index c44b4fc4a..64dc5131e 100644 --- a/src/app/script/events_class.cpp +++ b/src/app/script/events_class.cpp @@ -18,11 +18,14 @@ #include "app/script/docobj.h" #include "app/script/engine.h" #include "app/script/luacpp.h" +#include "app/script/values.h" #include "doc/document.h" #include "doc/sprite.h" #include "ui/app_state.h" +#include #include +#include #include #include @@ -92,7 +95,8 @@ public: } protected: - void call(EventType eventType) { + void call(EventType eventType, + const std::initializer_list>& args = {}) { if (eventType >= m_listeners.size()) return; @@ -101,8 +105,20 @@ protected: try { for (EventListener callbackRef : m_listeners[eventType]) { + // Get user-defined callback function lua_rawgeti(L, LUA_REGISTRYINDEX, callbackRef); - if (lua_pcall(L, 0, 0, 0)) { + + int callbackArgs = 0; + if (args.size() > 0) { + ++callbackArgs; + lua_newtable(L); // Create "ev" argument with fields about the event + for (const auto& kv : args) { + push_value_to_lua(L, kv.second); + lua_setfield(L, -2, kv.first.c_str()); + } + } + + if (lua_pcall(L, callbackArgs, 0, 0)) { if (const char* s = lua_tostring(L, -1)) engine->consolePrint(s); } @@ -233,11 +249,17 @@ public: } } - void onFileNameChanged(Doc* doc) override { call(FilenameChange); } + void onFileNameChanged(Doc* doc) override { + call(FilenameChange); + } // DocUndoObserver impl - void onAddUndoState(DocUndo* history) override { call(Change); } - void onCurrentUndoStateChange(DocUndo* history) override { call(Change); } + void onAddUndoState(DocUndo* history) override { + call(Change); + } + void onCurrentUndoStateChange(DocUndo* history) override { + call(Change, { { "fromUndo", true } }); + } private: diff --git a/src/app/script/values.cpp b/src/app/script/values.cpp index 490b33c81..e33d0f51f 100644 --- a/src/app/script/values.cpp +++ b/src/app/script/values.cpp @@ -14,6 +14,8 @@ #include "app/script/engine.h" #include "app/script/luacpp.h" +#include + namespace app { namespace script { @@ -74,6 +76,25 @@ std::string get_value_from_lua(lua_State* L, int index) { return std::string(); } +// ---------------------------------------------------------------------- +// std::any + +template<> +void push_value_to_lua(lua_State* L, const std::any& value) { + if (!value.has_value()) + lua_pushnil(L); + else if (const bool* v = std::any_cast(&value)) + push_value_to_lua(L, *v); + else if (const int* v = std::any_cast(&value)) + push_value_to_lua(L, *v); + else if (const std::string* v = std::any_cast(&value)) + push_value_to_lua(L, *v); + else { + ASSERT(false); + throw std::runtime_error("Cannot convert type inside std::any"); + } +} + // ---------------------------------------------------------------------- // Color From b6a9a6ce0a7b11386bcc595604cf81675eb0a9ca Mon Sep 17 00:00:00 2001 From: David Capello Date: Thu, 29 Sep 2022 17:16:42 -0300 Subject: [PATCH 6/6] Update laf module --- laf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/laf b/laf index b4ca9e2a0..81622fcbb 160000 --- a/laf +++ b/laf @@ -1 +1 @@ -Subproject commit b4ca9e2a0946c2ecb1efdf3ecb01888f350e3e26 +Subproject commit 81622fcbb9e4a0edc14a02250c387bd6fa878708