Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ✨ Mod directory creation from template #45

Merged
merged 7 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions addons/mod_tool/global/store.gd
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ var error_color := ""

var name_mod_dir := "" setget set_name_mod_dir
var path_mod_dir := ""
var path_current_template_dir := "res://addons/mod_tool/templates/default/"
var path_export_dir := ""
var path_temp_dir := ""
var path_manifest := ""
var path_global_export_dir := ""
var path_global_project_dir := ""
var path_global_temp_dir := ""
var path_addon_dir := "res://addons/mod_tool/"
var path_global_addon_dir := ""
var path_global_seven_zip := ""
var path_global_final_zip := ""
Expand All @@ -30,18 +32,15 @@ var path_mod_files := []

# ModManifest instance
var manifest_data : ModManifest
# Dictionary retrieved from ModManifest
var manifest_dict : Dictionary
# Pure json data from manifest.json
var manifest_dict_json : Dictionary


func _ready() -> void:
load_store()


func _exit_tree() -> void:
save_store()
if not name_mod_dir == "":
save_store()


func set_base_theme(new_base_theme: Theme) -> void:
Expand All @@ -56,6 +55,7 @@ func set_name_mod_dir(new_name_mod_dir: String) -> void:
func init(store: Dictionary) -> void:
name_mod_dir = store.name_mod_dir
path_mod_dir = "res://mods-unpacked/" + store.name_mod_dir
path_current_template_dir = store.path_current_template_dir
path_export_dir = "res://zips/"
path_global_export_dir = ProjectSettings.globalize_path(path_export_dir)
path_global_project_dir = ProjectSettings.globalize_path(ModLoaderUtils.get_local_folder_dir())
Expand All @@ -80,6 +80,7 @@ func save_store() -> void:
var save_data := {
"name_mod_dir": name_mod_dir,
"path_mod_dir": path_mod_dir,
"path_current_template_dir": path_current_template_dir,
"path_export_dir": path_export_dir,
"path_global_project_dir": path_global_project_dir,
"path_temp_dir": path_temp_dir,
Expand Down
4 changes: 3 additions & 1 deletion addons/mod_tool/global/utils.gd
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ static func remove_recursive(path: String) -> void:
# p_match is a string that filters the list of files.
# If p_match_is_regex is false, p_match is directly string-searched against the FILENAME.
# If it is true, a regex object compiles p_match and runs it against the FILEPATH.
static func get_flat_view_dict(p_dir := "res://", p_match := "", p_match_is_regex := false) -> PoolStringArray:
static func get_flat_view_dict(p_dir := "res://", p_match := "", p_match_is_regex := false, include_empty_dirs := false) -> PoolStringArray:
var data: PoolStringArray = []
var regex: RegEx

Expand All @@ -133,6 +133,8 @@ static func get_flat_view_dict(p_dir := "res://", p_match := "", p_match_is_rege
if dir.open(dir_name) == OK:
var _dirlist_error: int = dir.list_dir_begin()
var file_name := dir.get_next()
if include_empty_dirs and not dir_name == p_dir:
data.append(dir_name)
while file_name != "":
if not dir_name == "res://":
first = false
Expand Down
49 changes: 38 additions & 11 deletions addons/mod_tool/interface/create_mod/create_mod.gd
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,58 @@ func add_mod() -> void:
ModToolUtils.output_error('Invalid name or namespace: "%s". You may only use letters, numbers, underscores and at least 3 characters for each.' % ModToolStore.name_mod_dir)
return

# Check if mods-unpacked dir exists
if not ModLoaderUtils.dir_exists("res://mods-unpacked"):
# If not create it
var success := ModToolUtils.make_dir_recursive("res://mods-unpacked")
if not success:
return

# Check if mod dir exists
if not ModLoaderUtils.dir_exists(ModToolStore.path_mod_dir):
# If not - create it
var success := ModToolUtils.make_dir_recursive(ModToolStore.path_mod_dir)
if not success:
return

# Create mod_main.gd
ModToolUtils.file_copy(ModToolStore.PATH_TEMPLATES_DIR + "mod_main.gd", ModToolStore.path_mod_dir + "/mod_main.gd")
# Get Template files
var template_paths := ModToolUtils.get_flat_view_dict(ModToolStore.path_current_template_dir, "", false, true)

# Create manifest.json
ModToolUtils.file_copy(ModToolStore.PATH_TEMPLATES_DIR + "manifest.json", ModToolStore.path_mod_dir + "/manifest.json")
# Copy current selected template dir files and folders to res://mods-unpacked
for path in template_paths:
var template_local_path := path.trim_prefix(ModToolStore.path_current_template_dir) as String
if ModLoaderUtils.file_exists(path):
ModToolUtils.file_copy(path, ModToolStore.path_mod_dir.plus_file(template_local_path))
else:
ModToolUtils.make_dir_recursive(ModToolStore.path_mod_dir.plus_file(template_local_path))

# Update FileSystem
ModToolStore.editor_file_system.scan()
# Wait for the scan to finish
yield(ModToolStore.editor_file_system, "filesystem_changed")

# Navigate to the new mod dir in the FileSystem pannel
ModToolStore.editor_plugin.get_editor_interface().get_file_system_dock().navigate_to_path(ModToolStore.path_mod_dir.plus_file("mod_main.gd"))

# Output info
ModToolUtils.output_info("Added base mod files to " + ModToolStore.path_mod_dir)

# Open mod_main.gd in the code editor
var mod_main_script := load(ModToolStore.path_mod_dir.plus_file("mod_main.gd"))
ModToolStore.editor_plugin.get_editor_interface().edit_script(mod_main_script)
ModToolStore.editor_plugin.get_editor_interface().set_main_screen_editor("Script")

# Split the new mod id
var name_mod_dir_split := ModToolStore.name_mod_dir.split("-")

# Update the namespace in the manifest
ModToolStore.manifest_data.namespace = name_mod_dir_split[0]

# Update the mod name in the manifest
ModToolStore.manifest_data.name = name_mod_dir_split[1]

# Update manifest editor ui
ModToolStore.editor_plugin.dock.manifest_editor.update_ui()

# Open manifest editor
ModToolStore.editor_plugin.dock.show_manifest_editor()

# Save the manifest
ModToolStore.editor_plugin.dock.manifest_editor.save_manifest()

else:
# If so - show error and ask if user wants to connect with the mod instead
ModToolUtils.output_error("Mod directory at %s already exists." % ModToolStore.path_mod_dir)
Expand Down
17 changes: 16 additions & 1 deletion addons/mod_tool/interface/dock/dock.gd
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ var tab_parent_bottom_panel: PanelContainer
var log_richtext_label: RichTextLabel
var log_dock_button: ToolButton

onready var tab_container = $TabContainer
onready var popup := $"%Popup"
onready var create_mod := $"%CreateMod"
onready var file_dialog = $FileDialog
onready var label_output := $"%Output"
onready var mod_id := $"%ModId"
onready var manifest_editor = $"%ManifestEditor"
Expand Down Expand Up @@ -89,7 +91,11 @@ func discard_last_console_error() -> void:


func show_output() -> void:
$TabContainer.current_tab = 0
tab_container.current_tab = 0


func show_manifest_editor() -> void:
tab_container.current_tab = 1


func _update_ui():
Expand Down Expand Up @@ -174,3 +180,12 @@ func _on_store_loaded() -> void:
if ModLoaderUtils.file_exists(ModToolStore.path_manifest):
manifest_editor.load_manifest()
manifest_editor.update_ui()


func _on_SelectTemplate_pressed():
file_dialog.show()
file_dialog.current_dir = ModToolStore.path_addon_dir.plus_file("templates")


func _on_FileDialog_dir_selected(dir):
ModToolStore.path_current_template_dir = dir
22 changes: 22 additions & 0 deletions addons/mod_tool/interface/dock/dock.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ margin_right = 321.0
margin_bottom = 44.0
text = "Export Mod"

[node name="SelectTemplate" type="Button" parent="TabContainer/Export/HSplit/Settings/Buttons/VBox"]
margin_top = 48.0
margin_right = 321.0
margin_bottom = 68.0
text = "Select Template"

[node name="ManifestEditor" parent="TabContainer" instance=ExtResource( 2 )]
visible = false

Expand Down Expand Up @@ -328,17 +334,33 @@ margin_right = 373.0
[node name="btn_create_mod" parent="Popup/CreateMod/Settings/Buttons/VBox" index="0"]
margin_right = 366.0

[node name="FileDialog" type="FileDialog" parent="."]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -350.0
margin_top = -200.0
margin_right = 350.0
margin_bottom = 200.0
rect_min_size = Vector2( 500, 300 )
window_title = "Open a Directory"
resizable = true
mode = 2

[connection signal="visibility_changed" from="." to="." method="_on_mod_tools_dock_visibility_changed"]
[connection signal="pressed" from="TabContainer/Export/HSplit/Console/HBox/CopyOutput" to="." method="_on_copy_output_pressed"]
[connection signal="pressed" from="TabContainer/Export/HSplit/Console/HBox/ClearOutput" to="." method="_on_clear_output_pressed"]
[connection signal="input_text_changed" from="TabContainer/Export/HSplit/Settings/Scroll/VBox/ModId" to="." method="_on_ModId_input_text_changed"]
[connection signal="pressed" from="TabContainer/Export/HSplit/Settings/Buttons/VBox/CreateMod" to="." method="_on_export_settings_create_new_mod_pressed"]
[connection signal="pressed" from="TabContainer/Export/HSplit/Settings/Buttons/VBox/Export" to="." method="_on_export_pressed"]
[connection signal="pressed" from="TabContainer/Export/HSplit/Settings/Buttons/VBox/SelectTemplate" to="." method="_on_SelectTemplate_pressed"]
[connection signal="pressed" from="TabContainer/Default Configuration/VBox/HBox/SaveConfig" to="." method="_on_save_config_pressed"]
[connection signal="cursor_changed" from="TabContainer/Default Configuration/VBox/ConfigEditor" to="TabContainer/Default Configuration/VBox/ConfigEditor" method="_on_cursor_changed"]
[connection signal="text_changed" from="TabContainer/Default Configuration/VBox/ConfigEditor" to="TabContainer/Default Configuration/VBox/ConfigEditor" method="_on_text_changed"]
[connection signal="timeout" from="TabContainer/Default Configuration/VBox/ConfigEditor/ValidationDelay" to="TabContainer/Default Configuration/VBox/ConfigEditor" method="_on_ValidationDelay_timeout"]
[connection signal="mod_dir_created" from="Popup/CreateMod" to="." method="_on_CreateMod_mod_dir_created"]
[connection signal="input_text_changed" from="Popup/CreateMod/Settings/Scroll/VBox/ModId" to="." method="_on_ModId_input_text_changed"]
[connection signal="dir_selected" from="FileDialog" to="." method="_on_FileDialog_dir_selected"]

[editable path="Popup/CreateMod"]
9 changes: 4 additions & 5 deletions addons/mod_tool/interface/manifest_editor/manifest_editor.gd
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ func _ready() -> void:


func load_manifest() -> void:
ModToolStore.manifest_dict_json = ModLoaderUtils.get_json_as_dict(ModToolStore.path_manifest)
ModToolStore.manifest_data = ModManifest.new(ModToolStore.manifest_dict_json)
ModToolStore.manifest_dict = ModToolStore.manifest_data.get_as_dict()
var manifest_dict_json := ModLoaderUtils.get_json_as_dict(ModToolStore.path_manifest)
ModToolStore.manifest_data = ModManifest.new(manifest_dict_json)
ModToolUtils.output_info("Loaded manifest from " + ModToolStore.path_manifest)


Expand All @@ -36,8 +35,8 @@ func update_ui() -> void:
# For each input field
for input in input_fields:
# Check if the key used in the InputString instance is in the data_dict.
if ModToolStore.manifest_dict.has(input.key):
var value = ModToolStore.manifest_dict[input.key]
if ModToolStore.manifest_data.get(input.key):
var value = ModToolStore.manifest_data.get(input.key)

# If the value is an Array create a comma separated list
if value is PoolStringArray:
Expand Down