Skip to content

Instantly share code, notes, and snippets.

@dacap dacap/patch.diff Secret
Created Mar 24, 2020

Embed
What would you like to do?
Aseprite incomplete patch for extensions with scripts
modified data/gui.xml
@@ -573,36 +573,44 @@
<item command="NewFile" text="@.file_new" />
<item command="OpenFile" text="@.file_open" />
<item id="recent_list" text="@.file_open_recent" />
+ <section id="file.open" />
<separator />
<item command="SaveFile" text="@.file_save" />
<item command="SaveFileAs" text="@.file_save_as" />
<item command="SaveFileCopyAs" text="@.file_export" />
<item command="CloseFile" text="@.file_close" />
<item command="CloseAllFiles" text="@.file_close_all" />
+ <section id="file.save" />
<separator />
<item command="ImportSpriteSheet" text="@.file_import_sprite_sheet" />
<item command="ExportSpriteSheet" text="@.file_export_sprite_sheet" />
<item command="RepeatLastExport" text="@.file_repeat_last_export" />
+ <section id="file.export" />
<separator id="scripts_menu_separator" />
<menu id="scripts_menu" text="@.file_scripts">
<item command="OpenScriptFolder" text="@.file_open_script_folder" />
+ <section id="file.scripts" />
</menu>
<separator />
+ <section id="file.app" />
<item command="Exit" text="@.file_exit" />
</menu>
<menu text="@.edit">
<item command="Undo" text="@.edit_undo" />
<item command="Redo" text="@.edit_redo" />
<item command="UndoHistory" text="@.edit_undo_history" />
+ <section id="edit.undo" />
<separator />
<item command="Cut" text="@.edit_cut" />
<item command="Copy" text="@.edit_copy" />
<item command="CopyMerged" text="@.edit_copy_merged" />
<item command="Paste" text="@.edit_paste" />
<item command="Clear" text="@.edit_clear" />
+ <section id="edit.copypaste" />
<separator />
<item command="Fill" text="@.edit_fill" />
<item command="Stroke" text="@.edit_stroke" />
+ <section id="edit.fill" />
<separator />
<menu text="@.edit_rotate">
<item command="Rotate" text="@.edit_rotate_180">
@@ -657,9 +665,11 @@
<param name="wrap" value="1" />
</item>
</menu>
+ <section id="edit.transform" />
<separator />
<item command="NewBrush" text="@.edit_new_brush" />
<item command="NewSpriteFromSelection" text="@.edit_new_sprite_from_selection" />
+ <section id="edit.new" />
<separator />
<item command="ReplaceColor" text="@.edit_replace_color" />
<item command="InvertColor" text="@.edit_invert_color" />
@@ -673,6 +683,7 @@
<item command="Despeckle" text="@.edit_fx_despeckle" />
</menu>
<item command="PasteText" text="@.edit_insert_text" />
+ <section id="edit.filters" />
<separator />
<item command="KeyboardShortcuts" text="@.edit_keyboard_shortcuts" />
<item command="Options" text="@.edit_preferences" />
@@ -692,8 +703,10 @@
<separator />
<item command="ChangePixelFormat" text="@.sprite_color_mode_more_options" />
</menu>
+ <section id="sprite.properties" />
<separator />
<item command="DuplicateSprite" text="@.sprite_duplicate" />
+ <section id="sprite.duplicate" />
<separator />
<item command="SpriteSize" text="@.sprite_sprite_size" />
<item command="CanvasSize" text="@.sprite_canvas_size" />
@@ -720,15 +733,18 @@
<param name="orientation" value="vertical" />
</item>
</menu>
+ <section id="sprite.size" />
<separator />
<item command="CropSprite" text="@.sprite_crop" />
<item command="AutocropSprite" text="@.sprite_trim" />
+ <section id="sprite.crop" />
</menu>
<menu text="@.layer">
<item command="LayerProperties" text="@.layer_properties" />
<item command="LayerVisibility" text="@.layer_visible" />
<item command="LayerLock" text="@.layer_lock_layers" />
<item command="OpenGroup" text="@.layer_open_group" />
+ <section id="layer.properties" />
<separator />
<item command="NewLayer" text="@.layer_new_layer" />
<item command="NewLayer" text="@.layer_new_group">
@@ -737,21 +753,25 @@
<item command="RemoveLayer" text="@.layer_delete_layer" />
<item command="BackgroundFromLayer" text="@.layer_background_from_layer" />
<item command="LayerFromBackground" text="@.layer_layer_from_background" />
+ <section id="layer.new" />
<separator />
<item command="DuplicateLayer" text="@.layer_duplicate" />
<item command="MergeDownLayer" text="@.layer_merge_down" />
<item command="FlattenLayers" text="@.layer_flatten" />
+ <section id="layer.merge" />
<separator />
<item command="NewLayer" text="@.layer_add_reference_layer">
<param name="reference" value="true" />
<param name="from-file" value="true" />
</item>
+ <section id="layer.reference" />
</menu>
<menu text="@.frame">
<item command="FrameProperties" text="@.frame_properties">
<param name="frame" value="current" />
</item>
<item command="CelProperties" text="@.frame_cel_properties" />
+ <section id="cel.properties" />
<separator />
<item command="NewFrame" text="@.frame_new_frame" />
<item command="NewFrame" text="@.frame_new_empty_frame">
@@ -764,6 +784,7 @@
<param name="content" value="cel" />
</item>
<item command="RemoveFrame" text="@.frame_delete_frame" />
+ <section id="cel.new" />
<separator />
<menu text="@.frame_tags">
<item command="FrameTagProperties" text="@.frame_tags_tag_properties" />
@@ -780,17 +801,20 @@
<item command="GotoFrame" text="@.frame_go_to_frame" />
</menu>
<item command="PlayAnimation" text="@.frame_play_animation" />
+ <section id="cel.animation" />
<separator />
<item command="FrameProperties" text="@.frame_constant_frame_rate">
<param name="frame" value="all" />
</item>
<item command="ReverseFrames" text="@.frame_reverse_frames" />
+ <section id="cel.frames" />
</menu>
<menu text="@.select">
<item command="MaskAll" text="@.select_all" />
<item command="DeselectMask" text="@.select_deselect" />
<item command="ReselectMask" text="@.select_reselect" />
<item command="InvertMask" text="@.select_inverse" />
+ <section id="select.main" />
<separator />
<item command="MaskByColor" text="@.select_color_range" />
<menu text="@.select_modify">
@@ -804,12 +828,15 @@
<param name="modifier" value="contract" />
</item>
</menu>
+ <section id="select.special" />
<separator />
<item command="LoadMask" text="@.select_load_from_file" />
<item command="SaveMask" text="@.select_save_to_file" />
+ <section id="select.files" />
</menu>
<menu text="@.view">
<item command="DuplicateView" text="@.view_duplicate_view" />
+ <section id="view.new" />
<separator />
<item command="ShowExtras" text="@.view_show_extras" />
<menu text="@.view_show">
@@ -822,6 +849,7 @@
<separator />
<item command="ShowBrushPreview" text="@.view_show_brush_preview" />
</menu>
+ <section id="view.extras" />
<separator />
<menu text="@.view_grid">
<item command="GridSettings" text="@.view_grid_settings" />
@@ -843,9 +871,11 @@
</item>
</menu>
<item command="SymmetryMode" text="@.view_symmetry_options" />
+ <section id="view.canvas_helpers" />
<separator />
<item command="SetLoopSection" text="@.view_set_loop_section" />
<item command="ShowOnionSkin" text="@.view_show_onion_skin" />
+ <section id="view.animation_helpers" />
<separator />
<item command="Timeline" text="@.view_timeline">
<param name="switch" value="true" />
@@ -854,13 +884,16 @@
<item command="AdvancedMode" text="@.view_full_screen_mode" />
<item command="FullscreenPreview" text="@.view_full_screen_preview" />
<item command="Home" text="@.view_home" />
+ <section id="view.controls" />
<separator />
<item command="Refresh" text="@.view_refresh" />
+ <section id="view.screen" />
</menu>
<menu text="@.help" id="help_menu">
<item command="OpenBrowser" text="@.help_readme">
<param name="filename" value="README.md" />
</item>
+ <section id="help.readme" />
<separator />
<item command="Launch" text="@.help_quick_reference">
<param name="type" value="url" />
@@ -874,6 +907,7 @@
<param name="type" value="url" />
<param name="path" value="/tutorial/" />
</item>
+ <section id="help.docs" />
<separator />
<item command="Launch" text="@.help_release_notes">
<param name="type" value="url" />
@@ -883,8 +917,10 @@
<param name="type" value="url" />
<param name="path" value="http://twitter.com/aseprite" />
</item>
+ <section id="help.news" />
<separator />
<item command="About" text="@.help_about" />
+ <section id="help.about" />
</menu>
</menu>
modified src/app/app_menus.cpp
@@ -555,6 +555,14 @@ Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem)
return item;
}
+ // is it a <section>?
+ if (strcmp(elem->Value(), "section") == 0) {
+ auto item = new Widget();
+ item->setVisible(false);
+ if (id) item->setId(id);
+ return item;
+ }
+
const char* command_id = elem->Attribute("command");
Command* command =
command_id ? Commands::instance()->byId(command_id):
@@ -823,8 +831,8 @@ void AppMenus::createNativeSubmenus(os::Menu* osMenu, const ui::Menu* uiMenu)
}
};
}
+ // Ignore this item, might be a hidden widget, like a <section>
else {
- ASSERT(false); // Unsupported menu item type
continue;
}
modified src/app/extensions.cpp
@@ -10,6 +10,7 @@
#include "app/extensions.h"
+#include "app/app.h"
#include "app/ini_file.h"
#include "app/load_matrix.h"
#include "app/pref/preferences.h"
@@ -20,6 +21,10 @@
#include "base/fstream_path.h"
#include "render/dithering_matrix.h"
+#ifdef ENABLE_SCRIPTING
+ #include "app/script/engine.h"
+#endif
+
#include "archive.h"
#include "archive_entry.h"
#include "json11.hpp"
@@ -181,6 +186,9 @@ void write_json_file(const std::string& path, const json11::Json& json)
} // anonymous namespace
+//////////////////////////////////////////////////////////////////////
+// Extension
+
const render::DitheringMatrix& Extension::DitheringMatrixInfo::matrix() const
{
if (!m_matrix) {
@@ -267,6 +275,15 @@ void Extension::enable(const bool state)
flush_config_file();
m_isEnabled = state;
+
+#ifdef ENABLE_SCRIPTING
+ if (m_isEnabled) {
+ runScripts();
+ }
+ else {
+ uninstallScriptHooks();
+ }
+#endif // ENABLE_SCRIPTING
}
void Extension::uninstall()
@@ -363,6 +380,66 @@ bool Extension::isDefaultTheme() const
return (name() == kAsepriteDefaultThemeExtensionName);
}
+#ifdef ENABLE_SCRIPTING
+
+class ScriptEngineDelegate : public script::EngineDelegate {
+public:
+ ScriptEngineDelegate(script::EngineDelegate* subdelegate,
+ Extension* extension)
+ : m_subdelegate(subdelegate),
+ m_extension(extension) {
+ }
+ bool onRunningExtension() override { return true; }
+ void onNewCommand(Command* command) override {
+ m_extension->addCommand(command);
+ }
+ void onNewMenu(AppMenuItem* menuItem) override {
+ m_extension->addMenuItem(menuItem);
+ }
+private:
+ EngineDelegate* m_subdelegate;
+ Extension* m_extension;
+};
+
+void Extension::runScripts()
+{
+ script::Engine* engine = App::instance()->scriptEngine();
+ ScriptEngineDelegate delegate(engine->delegate(), this);
+ script::ScopedEngineDelegate scoped(engine, &delegate);
+
+ for (const auto& script : m_scripts) {
+ engine->evalFile(script);
+ }
+}
+
+void Extension::uninstallScriptHooks()
+{
+ for (AppMenuItem* item : m_menus) {
+ }
+ for (Command* command : m_commands) {
+ }
+}
+
+void Extension::addScript(const std::string& fn)
+{
+ m_scripts.push_back(fn);
+}
+
+void Extension::addMenuItem(AppMenuItem* menuItem)
+{
+ m_menus.push_back(menuItem);
+}
+
+void Extension::addCommand(Command* command)
+{
+ m_commands.push_back(command);
+}
+
+#endif // ENABLE_SCRIPTING
+
+//////////////////////////////////////////////////////////////////////
+// Extensions
+
Extensions::Extensions()
{
// Create and get the user extensions directory
@@ -725,8 +802,32 @@ Extension* Extensions::loadExtension(const std::string& path,
extension->addDitheringMatrix(matId, matPath, matName);
}
}
+
+#ifdef ENABLE_SCRIPTING
+ // Scripts
+ auto scripts = contributes["scripts"];
+ if (scripts.is_array()) {
+ for (const auto& script : scripts.array_items()) {
+ std::string scriptPath = script["path"].string_value();
+ if (scriptPath.empty())
+ continue;
+
+ // The path must be always relative to the extension
+ scriptPath = base::join_path(path, scriptPath);
+
+ LOG("EXT: New script '%s'\n", scriptPath.c_str());
+
+ extension->addScript(scriptPath);
+ }
+ }
+#endif // ENABLE_SCRIPTING
}
+#ifdef ENABLE_SCRIPTING
+ if (extension->hasScripts())
+ extension->runScripts();
+#endif
+
if (extension)
m_extensions.push_back(extension.get());
return extension.release();
modified src/app/extensions.h
@@ -24,6 +24,8 @@ namespace app {
// Value=theme/palette/etc. path
typedef std::map<std::string, std::string> ExtensionItems;
+ class AppMenuItem;
+ class Command;
class Extensions;
struct ExtensionInfo {
@@ -86,6 +88,12 @@ namespace app {
bool hasThemes() const { return !m_themes.empty(); }
bool hasPalettes() const { return !m_palettes.empty(); }
bool hasDitheringMatrices() const { return !m_ditheringMatrices.empty(); }
+#ifdef ENABLE_SCRIPTING
+ bool hasScripts() const { return !m_scripts.empty(); }
+ void addScript(const std::string& fn);
+ void addMenuItem(AppMenuItem* menuItem);
+ void addCommand(Command* command);
+#endif
private:
void enable(const bool state);
@@ -93,11 +101,21 @@ namespace app {
void uninstallFiles(const std::string& path);
bool isCurrentTheme() const;
bool isDefaultTheme() const;
+#ifdef ENABLE_SCRIPTING
+ void runScripts();
+ void uninstallScriptHooks();
+#endif
ExtensionItems m_languages;
ExtensionItems m_themes;
ExtensionItems m_palettes;
std::map<std::string, DitheringMatrixInfo> m_ditheringMatrices;
+#ifdef ENABLE_SCRIPTING
+ std::vector<std::string> m_scripts;
+ std::vector<AppMenuItem*> m_menus;
+ std::vector<Command*> m_commands;
+#endif
+
std::string m_path;
std::string m_name;
std::string m_version;
modified src/app/script/app_object.cpp
@@ -74,6 +74,41 @@ int App_transaction(lua_State* L)
return nresults;
}
+int App_newCommand(lua_State* L)
+{
+ auto engine = App::instance()->scriptEngine();
+ if (!engine->delegate() ||
+ !engine->delegate()->onRunningExtension()) {
+ return luaL_error(L, "You can register commands only from extensions");
+ }
+
+ printf("App_newCommand\n");
+ // if (lua_istable(L, index)) {
+ // lua_getfield(L, index, "x");
+ // lua_getfield(L, index, "y");
+ // lua_getfield(L, index, "width");
+ // lua_getfield(L, index, "height");
+ // rc.x = lua_tointeger(L, -4);
+ // rc.y = lua_tointeger(L, -3);
+ // rc.w = lua_tointeger(L, -2);
+ // rc.h = lua_tointeger(L, -1);
+ // lua_pop(L, 4);
+ // }
+ return 0;
+}
+
+int App_newMenu(lua_State* L)
+{
+ auto engine = App::instance()->scriptEngine();
+ if (!engine->delegate() ||
+ !engine->delegate()->onRunningExtension()) {
+ return luaL_error(L, "You can register menus only from extensions");
+ }
+
+ printf("App_newMenu\n");
+ return 0;
+}
+
int App_undo(lua_State* L)
{
app::Context* ctx = App::instance()->context();
@@ -158,6 +193,8 @@ const luaL_Reg App_methods[] = {
{ "open", App_open },
{ "exit", App_exit },
{ "transaction", App_transaction },
+ { "newCommand", App_newCommand },
+ { "newMenu", App_newMenu },
{ "undo", App_undo },
{ "redo", App_redo },
{ nullptr, nullptr }
modified src/app/script/engine.h
@@ -34,13 +34,19 @@ namespace doc {
}
namespace app {
+ class AppMenuItem;
+ class Command;
class Site;
+
namespace script {
class EngineDelegate {
public:
virtual ~EngineDelegate() { }
- virtual void onConsolePrint(const char* text) = 0;
+ virtual void onConsolePrint(const char* text) { }
+ virtual bool onRunningExtension() { return false; }
+ virtual void onNewCommand(Command* command) { }
+ virtual void onNewMenu(AppMenuItem* menuItem) { }
};
class Engine {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.