-
-
Save dacap/ad8c6cc9afcd5e027203c96fbd627227 to your computer and use it in GitHub Desktop.
Aseprite incomplete patch for extensions with scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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