Repository: derkork/godot-resource-groups
Pull request #25: Rebuilding resources on request from another plugin
Author: login: Odebe
Created: 2025-05-08T10:08:32Z | Merged: 2025-05-10T09:15:44Z

Hi.

In my project, I create some resources through a custom plugin and realized that it is inconvenient to manually call the resource rebuild through the menu.
That's why I added a signal to the plugin. I think it's a convenient and useful feature.

I don't really like the implementation via `static var instance`, but creating an event bus and registering through `Engine.register_singleton` seems redundant and not so convenient

Really like the plugin, thanks for your work.


Diff:
diff --git a/README.md b/README.md
index 4ee1018..548b1e6 100644
--- a/README.md
+++ b/README.md
@@ -185,6 +185,24 @@ Also check out the loading examples for [GDScript](godot_resource_groups_example
 
 There is also a variant `load_matching_in_background` which works similarly, but only loads a subset of the resources.
 
+## Using in plugins
+
+### Rebuilding resources on request from another plugin
+
+If you create resources using editor scripting, you can trigger a rebuild of all resource groups from your plugin:
+
+```gdscript
+ResourceGroupsPlugin.rebuild_resource_groups()
+```
+
+Similarly from C#:
+
+```csharp
+ResourceGroupsPlugin.RebuildResourceGroups();
+```
+
+Please note, that this will only work in the editor. If you call this function at runtime it will print an error message and do nothing.
+
 ## FAQ
 
 ### How do I select all but a few resources?
diff --git a/addons/godot_resource_groups/csharp/ResourceGroupsPlugin.cs b/addons/godot_resource_groups/csharp/ResourceGroupsPlugin.cs
new file mode 100644
index 0000000..f2031f7
--- /dev/null
+++ b/addons/godot_resource_groups/csharp/ResourceGroupsPlugin.cs
@@ -0,0 +1,28 @@
+﻿using Godot;
+
+namespace GodotResourceGroups;
+
+public class ResourceGroupsPlugin
+{
+    /// <summary>
+    /// Rebuilds all resource groups. Useful if you have custom editor scripts that create or modify resources
+    /// and want to update the resource groups via script.
+    /// </summary>
+    public static void RebuildResourceGroups()
+    {
+        if (!Engine.IsEditorHint())
+		{
+			GD.PushError("ResourceGroupsPlugin.RebuildResourceGroups() can only be called inside of the editor.");
+			return;
+		}
+        
+        var plugin = Engine.GetSingleton("ResourceGroupsPlugin");
+        if (plugin == null)
+        {
+	        GD.PushError("Resource group plugin is not active, please check if it is enabled in the project settings.");
+	        return;
+        }
+
+        plugin.Call("_rebuild_resource_groups");
+    }
+}
\ No newline at end of file
diff --git a/addons/godot_resource_groups/godot_resource_groups.gd b/addons/godot_resource_groups/godot_resource_groups.gd
index bc8fa82..a3e3f40 100644
--- a/addons/godot_resource_groups/godot_resource_groups.gd
+++ b/addons/godot_resource_groups/godot_resource_groups.gd
@@ -9,8 +9,10 @@ const REBUILD_SETTING: StringName = "godot_resource_groups/auto_rebuild"
 var _group_scanner: ResourceGroupScanner
 var _export_plugin: ResourceGroupsExportPlugin
 
-
 func _enter_tree():
+	# make the plugin singleton available to the rest of the engine
+	Engine.register_singleton("ResourceGroupsPlugin", self)
+	
 	add_tool_menu_item("Rebuild project resource groups", _rebuild_resource_groups)
 	_group_scanner = ResourceGroupScanner.new(get_editor_interface().get_resource_filesystem())
 	
@@ -32,6 +34,7 @@ func _enter_tree():
 
 
 func _exit_tree():
+	Engine.unregister_singleton("ResourceGroupsPlugin")
 	remove_tool_menu_item("Rebuild project resource groups")
 	remove_export_plugin(_export_plugin)
 
diff --git a/addons/godot_resource_groups/resource_groups_plugin.gd b/addons/godot_resource_groups/resource_groups_plugin.gd
new file mode 100644
index 0000000..65d65ae
--- /dev/null
+++ b/addons/godot_resource_groups/resource_groups_plugin.gd
@@ -0,0 +1,14 @@
+﻿class_name ResourceGroupsPlugin
+
+## Rebuilds all resource groups. Useful if you have custom editor scripts that create or modify resources
+## and want to update the resource groups via script.
+static func rebuild_resource_groups():
+	if not Engine.is_editor_hint():
+		push_error("ResourceGroupsPlugin.rebuild_resource_groups() can only be called inside of the editor.")
+		return
+
+	var plugin = Engine.get_singleton("ResourceGroupsPlugin")
+	if not is_instance_valid(plugin):
+		push_error("Resource group plugin is not active, please check if it is enabled in the project settings.")
+		return
+	plugin._rebuild_resource_groups()


Reviews:
user: login: derkork
body: Thanks a lot for taking the time to submit this! I think it is a very useful improvement. I had a look at the changes and there are a few things that will need a bit of brushing. I'm going to commit a few fixes shortly. Let me know  what you think! Thanks again!
state: COMMENTED
author_association: OWNER
submitted_at: 2025-05-09T06:46:58Z
user: login: Odebe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T11:17:08Z
user: login: Odebe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T11:21:18Z

Review comments:
diff_hunk: @@ -9,8 +10,14 @@ const REBUILD_SETTING: StringName = "godot_resource_groups/auto_rebuild"
 var _group_scanner: ResourceGroupScanner
 var _export_plugin: ResourceGroupsExportPlugin
 
+static var instance : EditorPlugin
path: addons/godot_resource_groups/godot_resource_groups.gd
user: login: derkork
body: Static variables are a Godot 4.2+ feature and would break compatibility with Godot 4.0 and 4.1.
created_at: 2025-05-09T06:29:56Z
author_association: OWNER
diff_hunk: @@ -9,8 +10,14 @@ const REBUILD_SETTING: StringName = "godot_resource_groups/auto_rebuild"
 var _group_scanner: ResourceGroupScanner
 var _export_plugin: ResourceGroupsExportPlugin
 
+static var instance : EditorPlugin
+
+signal rebuild_resources
path: addons/godot_resource_groups/godot_resource_groups.gd
user: login: derkork
body: Signals usually work the other way around, e.g. the object providing a signal is the one that emits it. I feel that having the user's emit a signal belonging to an object outside of their codebase would be confusing.
created_at: 2025-05-09T06:31:18Z
author_association: OWNER
diff_hunk: @@ -185,6 +185,23 @@ Also check out the loading examples for [GDScript](godot_resource_groups_example
 
 There is also a variant `load_matching_in_background` which works similarly, but only loads a subset of the resources.
 
+## Using in plugins
+
+### Rebuilding resources on request from another plugin
+
+If you create resources using a custom plugin, you can trigger group rebuilding from that plugin using a signal:
+
+```gdscript
+var resource_group_plugin = ResourceGroupsPlugin.instance
+
+if resource_group_plugin != null:
+	resource_group_plugin.rebuild_resources.emit()
+```
+
+**Important:**: Implemented only for GDScript
path: README.md
user: login: derkork
body: The plugin supports C# and I think it would be really good if the feature set between GDScript and C# does not diverge.
created_at: 2025-05-09T06:46:08Z
author_association: OWNER
diff_hunk: @@ -185,6 +185,23 @@ Also check out the loading examples for [GDScript](godot_resource_groups_example
 
 There is also a variant `load_matching_in_background` which works similarly, but only loads a subset of the resources.
 
+## Using in plugins
+
+### Rebuilding resources on request from another plugin
+
+If you create resources using a custom plugin, you can trigger group rebuilding from that plugin using a signal:
+
+```gdscript
+var resource_group_plugin = ResourceGroupsPlugin.instance
+
+if resource_group_plugin != null:
+	resource_group_plugin.rebuild_resources.emit()
+```
+
+**Important:**: Implemented only for GDScript
path: README.md
user: login: Odebe
body: Agreed, but I have little experience with C#. Thanks for adding that.
created_at: 2025-05-09T11:17:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -9,8 +10,14 @@ const REBUILD_SETTING: StringName = "godot_resource_groups/auto_rebuild"
 var _group_scanner: ResourceGroupScanner
 var _export_plugin: ResourceGroupsExportPlugin
 
+static var instance : EditorPlugin
+
+signal rebuild_resources
path: addons/godot_resource_groups/godot_resource_groups.gd
user: login: Odebe
body: Got it. Your solution looks more elegant and convenient.
created_at: 2025-05-09T11:21:18Z
author_association: CONTRIBUTOR

PR comments:
user: login: Odebe
created_at: 2025-05-09T11:29:24Z
body: I agree with your comments and the improvements look good.

I'll drag the approach with the facade containing static functions to access plugin singletons into my project. It never even occurred to me to do it that way
author_association: CONTRIBUTOR
user: login: derkork
created_at: 2025-05-10T09:16:14Z
body: Great, thanks a lot for contributing this! I'll add it to the next release!
author_association: OWNER