From c9876fab6033553c17d20d19071400cdb7748f54 Mon Sep 17 00:00:00 2001 From: Cyril Bissey <53737317+Cykyrios@users.noreply.github.com> Date: Mon, 10 Nov 2025 00:44:45 +0100 Subject: [PATCH] Add plugin dock for module creation --- .gitignore | 3 +- addons/gis_hub/dock/gis_hub_dock.gd | 17 +++++ addons/gis_hub/dock/gis_hub_dock.gd.uid | 1 + addons/gis_hub/dock/gis_hub_dock.tscn | 33 ++++++++ addons/gis_hub/gis_hub.gd | 75 +++++++++++++++++++ addons/gis_hub/gis_hub.gd.uid | 1 + addons/gis_hub/plugin.cfg | 7 ++ modules/module_tab.tscn | 6 +- project.godot | 2 +- .../your_first_module/your_first_module.md | 40 +++++++--- 10 files changed, 168 insertions(+), 17 deletions(-) create mode 100644 addons/gis_hub/dock/gis_hub_dock.gd create mode 100644 addons/gis_hub/dock/gis_hub_dock.gd.uid create mode 100644 addons/gis_hub/dock/gis_hub_dock.tscn create mode 100644 addons/gis_hub/gis_hub.gd create mode 100644 addons/gis_hub/gis_hub.gd.uid create mode 100644 addons/gis_hub/plugin.cfg diff --git a/.gitignore b/.gitignore index 0f0e33b..2760283 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,8 @@ /android/ /.submodules/gdUnit4/ -/addons/ +/addons/* +!/addons/gis_hub/ /build/ diff --git a/addons/gis_hub/dock/gis_hub_dock.gd b/addons/gis_hub/dock/gis_hub_dock.gd new file mode 100644 index 0000000..b2ee976 --- /dev/null +++ b/addons/gis_hub/dock/gis_hub_dock.gd @@ -0,0 +1,17 @@ +@tool +class_name GISHubPluginDock +extends VBoxContainer + +signal new_module_requested(module_name: String) + +@onready var new_module_name: LineEdit = %NewModuleName +@onready var new_module_button: Button = %NewModuleButton +@onready var new_module_label: RichTextLabel = %NewModuleLabel + + +func _ready() -> void: + var _connect := new_module_button.pressed.connect(_on_new_module_button_pressed) + + +func _on_new_module_button_pressed() -> void: + new_module_requested.emit(new_module_name.text.strip_edges()) diff --git a/addons/gis_hub/dock/gis_hub_dock.gd.uid b/addons/gis_hub/dock/gis_hub_dock.gd.uid new file mode 100644 index 0000000..9ef8aa5 --- /dev/null +++ b/addons/gis_hub/dock/gis_hub_dock.gd.uid @@ -0,0 +1 @@ +uid://cdx66sfv8sne diff --git a/addons/gis_hub/dock/gis_hub_dock.tscn b/addons/gis_hub/dock/gis_hub_dock.tscn new file mode 100644 index 0000000..e6dff95 --- /dev/null +++ b/addons/gis_hub/dock/gis_hub_dock.tscn @@ -0,0 +1,33 @@ +[gd_scene load_steps=2 format=3 uid="uid://nvfe0ul5vqcy"] + +[ext_resource type="Script" uid="uid://cdx66sfv8sne" path="res://addons/gis_hub/dock/gis_hub_dock.gd" id="1_srqew"] + +[node name="GIS Hub" type="VBoxContainer"] +offset_right = 106.0 +offset_bottom = 31.0 +script = ExtResource("1_srqew") + +[node name="FoldableContainer" type="FoldableContainer" parent="."] +layout_mode = 2 +title = "New module" + +[node name="VBoxContainer" type="VBoxContainer" parent="FoldableContainer"] +layout_mode = 2 + +[node name="NewModuleName" type="LineEdit" parent="FoldableContainer/VBoxContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +placeholder_text = "Module name" + +[node name="NewModuleButton" type="Button" parent="FoldableContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 4 +text = "Create module" + +[node name="NewModuleLabel" type="RichTextLabel" parent="FoldableContainer/VBoxContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(0, 50) +layout_mode = 2 +bbcode_enabled = true diff --git a/addons/gis_hub/gis_hub.gd b/addons/gis_hub/gis_hub.gd new file mode 100644 index 0000000..c2e447f --- /dev/null +++ b/addons/gis_hub/gis_hub.gd @@ -0,0 +1,75 @@ +@tool +extends EditorPlugin + +const ModuleDock := preload("uid://nvfe0ul5vqcy") + +var module_dock: GISHubPluginDock = null + + +func _enable_plugin() -> void: + # Add autoloads here. + pass + + +func _disable_plugin() -> void: + # Remove autoloads here. + pass + + +func _enter_tree() -> void: + module_dock = ModuleDock.instantiate() + add_control_to_dock(EditorPlugin.DOCK_SLOT_LEFT_UR, module_dock) + var _connect := module_dock.new_module_requested.connect(_on_module_created) + + +func _exit_tree() -> void: + remove_control_from_docks(module_dock) + module_dock.free() + + +func _on_module_created(module_name: String) -> void: + var base_folder := "res://modules" + var folder_name := module_name.to_snake_case() + var folders := DirAccess.get_directories_at(base_folder) + if folder_name in folders: + module_dock.new_module_label.text = ( + "[color=red]ERROR: Attempted to create folder \"%s\",\n" % [folder_name] + + "but it already exists.[/color]" + ) + return + module_dock.new_module_label.text = "" + var error := DirAccess.make_dir_recursive_absolute(base_folder.path_join(folder_name)) + if error != OK: + push_error( + "Failed to create new module folder at %s" % [base_folder.path_join(folder_name)] + ) + return + var target_folder := base_folder.path_join(folder_name) + var scene_path := target_folder.path_join("module_%s.tscn" % [folder_name]) + var script_path := target_folder.path_join("module_%s.gd" % [folder_name]) + error = DirAccess.copy_absolute( + base_folder.path_join(GISHubModuleManager.BASE_MODULE_SCENE_NAME), + scene_path, + ) + if error != OK: + push_error("Failed to copy module scene to folder \"%s\"." % [folder_name]) + return + var script_dialog := get_script_create_dialog() + script_dialog.config("GISModule", script_path, false) + script_dialog.popup_centered() + var _connect := script_dialog.script_created.connect( + _on_module_script_created.bind(module_name, scene_path) + ) + + +func _on_module_script_created(script: Script, module_name: String, scene_path: String) -> void: + get_script_create_dialog().script_created.disconnect(_on_module_script_created) + EditorInterface.open_scene_from_path(scene_path) + var root := EditorInterface.get_edited_scene_root() + root.name = module_name + root.set_script(script) + var error := EditorInterface.save_scene() + if error != OK: + push_error("Failed to save module scene \"%s\"." % [scene_path]) + return + EditorInterface.edit_script(load(script.resource_path) as Script) diff --git a/addons/gis_hub/gis_hub.gd.uid b/addons/gis_hub/gis_hub.gd.uid new file mode 100644 index 0000000..1976ebe --- /dev/null +++ b/addons/gis_hub/gis_hub.gd.uid @@ -0,0 +1 @@ +uid://bt58350kcgd07 diff --git a/addons/gis_hub/plugin.cfg b/addons/gis_hub/plugin.cfg new file mode 100644 index 0000000..2cf5e44 --- /dev/null +++ b/addons/gis_hub/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="GIS Hub" +description="Editor tools for GIS Hub" +author="Cyril Bissey" +version="1.0" +script="gis_hub.gd" diff --git a/modules/module_tab.tscn b/modules/module_tab.tscn index 5461991..099a113 100644 --- a/modules/module_tab.tscn +++ b/modules/module_tab.tscn @@ -1,6 +1,4 @@ -[gd_scene load_steps=2 format=3 uid="uid://dhj24qi3nu38l"] - -[ext_resource type="Script" uid="uid://cn0qo0thcowy8" path="res://src/modules/gis_module.gd" id="1_x1b1q"] +[gd_scene format=3 uid="uid://dhj24qi3nu38l"] [node name="ModuleTab" type="MarginContainer"] anchors_preset = 15 @@ -12,5 +10,3 @@ theme_override_constants/margin_left = 20 theme_override_constants/margin_top = 20 theme_override_constants/margin_right = 20 theme_override_constants/margin_bottom = 20 -script = ExtResource("1_x1b1q") -metadata/_custom_type_script = "uid://cn0qo0thcowy8" diff --git a/project.godot b/project.godot index a1261e7..b1177fb 100644 --- a/project.godot +++ b/project.godot @@ -41,7 +41,7 @@ display_server/driver.linuxbsd="wayland" [editor_plugins] -enabled=PackedStringArray("res://addons/gdUnit4/plugin.cfg", "res://addons/godot_insim/plugin.cfg") +enabled=PackedStringArray("res://addons/gdUnit4/plugin.cfg", "res://addons/gis_hub/plugin.cfg", "res://addons/godot_insim/plugin.cfg") [gdunit4] diff --git a/website/docs/guides/module_development/your_first_module/your_first_module.md b/website/docs/guides/module_development/your_first_module/your_first_module.md index d8d46ae..ab50735 100644 --- a/website/docs/guides/module_development/your_first_module/your_first_module.md +++ b/website/docs/guides/module_development/your_first_module/your_first_module.md @@ -46,22 +46,33 @@ We will now create a very simple module which mirrors the functionality of the ### Creating the module -We will start by creating a new folder in `res://modules` and naming it `my_first_module`. +#### Using the GIS Hub plugin + +GIS Hub includes a plugin, which you should enable in **Project > Project Settings > Plugins** (it should already +be enabled, but you can double-check). In the upper left dock, where you would usually find the **Scene** tab, +you can now find a **GIS Hub** tab, which includes a **New module** section. + +Enter a name for your module, click the **Create module** button, and the plugin will automatically create a new folder +at `res://modules/`, by converting the name you entered to snake_case. + +For this guide, we will create a module named `My First Module`. This should automatically create and open a scene +named `my_first_module.tscn` in the `res://modules/my_first_module` folder, and prompt you to create a new script. +You can enable the GISModule template to get some code for a minimal working module, but we will start from scratch +in this guide. + +#### Manual creation + +You can also create new modules manually. You first need to create a new folder in `res://modules`, which we will name +`my_first_module` here. Since modules are scenes, we can either create a new one, or copy the provided `module_tab.tscn` in the `res://modules` directory. We will do the latter and copy the scene to our newly created folder; then we can rename it to `my_first_module.tscn`. -Open that scene, and you will notice it already has a script attached, of type :class_ref[GISModule]. -Select the root node, and click the **Extend script** button (where you would usually find the -**Add script** button instead; you can also right-click the node and find **Extend script** in the list); -the dialog will automatically make :class_ref[GISModule] the parent class. Name the script `my_first_module.gd` -and open it. We will then add a class name to the script: +Open the new scene, select the root node, click the **Add script** button, and make the new script inherit +:class_ref[GISModule]. -```gdscript -class_name MyFirstModule -extends GISModule -``` +Name the script `my_first_module.gd` and open it. :::tip @@ -71,6 +82,15 @@ we will cover in this tutorial. ::: +### Initializing the module + +We will now add a class name to the script: + +```gdscript +class_name MyFirstModule +extends GISModule +``` + The first thing every module needs to do is declare its name upon initialization; this allows GIS Hub to detect the module and add it to the list of available modules, so you can enable it. To do this, we need to implement the :class_ref[_initialize_module()]{target="GISModule#private_method__initialize_module"} method: -- GitLab