diff --git a/addons/godot-plugin-refresher/plugin.cfg b/addons/godot-plugin-refresher/plugin.cfg new file mode 100644 index 0000000..960ce89 --- /dev/null +++ b/addons/godot-plugin-refresher/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Godot Plugin Refresher" +description="A toolbar addition to facilitate toggling off/on a selected plugin." +author="willnationsdev" +version="1.0" +script="plugin_refresher_plugin.gd" diff --git a/addons/godot-plugin-refresher/plugin_refresher.gd b/addons/godot-plugin-refresher/plugin_refresher.gd new file mode 100644 index 0000000..eafcddd --- /dev/null +++ b/addons/godot-plugin-refresher/plugin_refresher.gd @@ -0,0 +1,53 @@ +tool +extends HBoxContainer + +signal request_refresh_plugin(p_name) +signal confirm_refresh_plugin(p_name) + +onready var options = $OptionButton + +func _ready(): + $RefreshButton.icon = get_icon('Reload', 'EditorIcons') + +func update_items(p_plugins): + if not options: + return + options.clear() + var plugin_dirs = p_plugins.keys() + for idx in plugin_dirs.size(): + var plugin_dirname = plugin_dirs[idx] + var plugin_name = p_plugins[plugin_dirname] + options.add_item(plugin_name, idx) + options.set_item_metadata(idx, plugin_dirname) + +func select_plugin(p_name): + if not options: + return + if p_name == null or p_name.empty(): + return + + for idx in options.get_item_count(): + var plugin = options.get_item_metadata(idx) + if plugin == p_name: + options.selected = options.get_item_id(idx) + break + +func _on_RefreshButton_pressed(): + if options.selected == -1: + return # nothing selected + + var plugin = options.get_item_metadata(options.selected) + if not plugin or plugin.empty(): + return + emit_signal("request_refresh_plugin", plugin) + +func show_warning(p_name): + $ConfirmationDialog.dialog_text = """ + Plugin `%s` is currently disabled.\n + Do you want to enable it now? + """ % [p_name] + $ConfirmationDialog.popup_centered() + +func _on_ConfirmationDialog_confirmed(): + var plugin = options.get_item_metadata(options.selected) + emit_signal('confirm_refresh_plugin', plugin) diff --git a/addons/godot-plugin-refresher/plugin_refresher.tscn b/addons/godot-plugin-refresher/plugin_refresher.tscn new file mode 100644 index 0000000..71981fe --- /dev/null +++ b/addons/godot-plugin-refresher/plugin_refresher.tscn @@ -0,0 +1,32 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/godot-plugin-refresher/plugin_refresher.gd" type="Script" id=1] + +[node name="HBoxContainer" type="HBoxContainer"] +margin_right = 40.0 +margin_bottom = 40.0 +script = ExtResource( 1 ) + +[node name="VSeparator" type="VSeparator" parent="."] +margin_right = 4.0 +margin_bottom = 40.0 + +[node name="OptionButton" type="OptionButton" parent="."] +margin_left = 8.0 +margin_right = 158.0 +margin_bottom = 40.0 +rect_min_size = Vector2( 150, 0 ) + +[node name="RefreshButton" type="ToolButton" parent="."] +margin_left = 162.0 +margin_right = 174.0 +margin_bottom = 40.0 + +[node name="ConfirmationDialog" type="ConfirmationDialog" parent="."] +margin_right = 278.0 +margin_bottom = 110.0 +rect_min_size = Vector2( 300, 70 ) +window_title = "Plugin Refresher" +dialog_autowrap = true +[connection signal="pressed" from="RefreshButton" to="." method="_on_RefreshButton_pressed"] +[connection signal="confirmed" from="ConfirmationDialog" to="." method="_on_ConfirmationDialog_confirmed"] diff --git a/addons/godot-plugin-refresher/plugin_refresher_plugin.gd b/addons/godot-plugin-refresher/plugin_refresher_plugin.gd new file mode 100644 index 0000000..d8127ec --- /dev/null +++ b/addons/godot-plugin-refresher/plugin_refresher_plugin.gd @@ -0,0 +1,125 @@ +tool +extends EditorPlugin + +const ADDONS_PATH = "res://addons/" +const PLUGIN_CONFIG_DIR = 'plugins/plugin_refresher' +const PLUGIN_CONFIG = 'settings.cfg' +const SETTINGS = 'settings' +const SETTING_RECENT = 'recently_used' + +var plugin_config = ConfigFile.new() +var refresher + +func _enter_tree(): + refresher = preload("plugin_refresher.tscn").instance() + add_control_to_container(CONTAINER_TOOLBAR, refresher) + + # Watch whether any plugin is changed, added or removed on the filesystem + var efs = get_editor_interface().get_resource_filesystem() + efs.connect("filesystem_changed", self, "_on_filesystem_changed") + + refresher.connect("request_refresh_plugin", self, "_on_request_refresh_plugin") + refresher.connect("confirm_refresh_plugin", self, "_on_confirm_refresh_plugin") + + _reload_plugins_list() + _load_settings() + +func _exit_tree(): + remove_control_from_container(CONTAINER_TOOLBAR, refresher) + refresher.free() + +func _reload_plugins_list(): + var refresher_dir = get_plugin_path().get_file() + var plugins = {} + var origins = {} + + var dir = Directory.new() + dir.open(ADDONS_PATH) + dir.list_dir_begin(true, true) + var file = dir.get_next() + while file: + var addon_dir = ADDONS_PATH.plus_file(file) + if dir.dir_exists(addon_dir) and file != refresher_dir: + var display_name = file + var plugin_config_path = addon_dir.plus_file("plugin.cfg") + if not dir.file_exists(plugin_config_path): + continue # not a plugin + var plugin_cfg = ConfigFile.new() + plugin_cfg.load(plugin_config_path) + display_name = plugin_cfg.get_value("plugin", "name", file) + if not display_name in origins: + origins[display_name] = [file] + else: + origins[display_name].append(file) + plugins[file] = display_name + file = dir.get_next() + + # Specify the exact plugin name in parenthesis in case of naming collisions. + for display_name in origins: + var plugin_names = origins[display_name] + if plugin_names.size() > 1: + for n in plugin_names: + plugins[n] = "%s (%s)" % [display_name, n] + + refresher.update_items(plugins) + +func _load_settings(): + var path = get_config_path() + + var fs = Directory.new() + if not fs.file_exists(path): + # Create new if running for the first time + var config = ConfigFile.new() + fs.make_dir_recursive(path.get_base_dir()) + config.save(path) + else: + plugin_config.load(path) + +func _save_settings(): + plugin_config.save(get_config_path()) + +func get_config_path(): + var dir = get_editor_interface().get_editor_settings().get_project_settings_dir() + var home = dir.plus_file(PLUGIN_CONFIG_DIR) + var path = home.plus_file(PLUGIN_CONFIG) + + return path + +func _on_filesystem_changed(): + if refresher: + _reload_plugins_list() + refresher.select_plugin(get_recent_plugin()) + +func get_recent_plugin(): + if not plugin_config.has_section_key(SETTINGS, SETTING_RECENT): + return null # not saved yet + + var recent = plugin_config.get_value(SETTINGS, SETTING_RECENT) + return recent + +func _on_request_refresh_plugin(p_name): + assert(not p_name.empty()) + + var disabled = not get_editor_interface().is_plugin_enabled(p_name) + if disabled: + refresher.show_warning(p_name) + else: + refresh_plugin(p_name) + +func _on_confirm_refresh_plugin(p_name): + refresh_plugin(p_name) + +func get_plugin_path(): + return get_script().resource_path.get_base_dir() + +func refresh_plugin(p_name): + print("Refreshing plugin: ", p_name) + + var enabled = get_editor_interface().is_plugin_enabled(p_name) + if enabled: # can only disable an active plugin + get_editor_interface().set_plugin_enabled(p_name, false) + + get_editor_interface().set_plugin_enabled(p_name, true) + + plugin_config.set_value(SETTINGS, SETTING_RECENT, p_name) + _save_settings() diff --git a/project.godot b/project.godot index 5f68cf9..fd3d202 100644 --- a/project.godot +++ b/project.godot @@ -135,7 +135,7 @@ window/size/height=720 [editor_plugins] -enabled=PoolStringArray( "draw_gd" ) +enabled=PoolStringArray( "draw_gd", "godot-plugin-refresher" ) [importer_defaults]