mirror of
https://github.com/JHDev2006/Super-Mario-Bros.-Remastered-Public.git
synced 2025-10-22 15:38:14 +00:00
244 lines
7.4 KiB
GDScript
244 lines
7.4 KiB
GDScript
@tool
|
|
extends Node
|
|
class_name ModToolUtils
|
|
|
|
|
|
# Utility functions used across the ModTool.
|
|
|
|
|
|
# ! Not used currently. This can overwrite existing text very easily if the wrong script is shown in the text editor.
|
|
static func reload_script(script: Script, mod_tool_store: ModToolStore) -> void:
|
|
var pending_reloads := mod_tool_store.pending_reloads
|
|
|
|
if script.resource_path in pending_reloads:
|
|
var source_code_from_disc := FileAccess.open(script.resource_path, FileAccess.READ).get_as_text()
|
|
|
|
var script_editor := EditorInterface.get_script_editor()
|
|
var text_edit: CodeEdit = script_editor.get_current_editor().get_base_editor()
|
|
|
|
var column := text_edit.get_caret_column()
|
|
var row := text_edit.get_caret_line()
|
|
var scroll_position_h := text_edit.get_h_scroll_bar().value
|
|
var scroll_position_v := text_edit.get_v_scroll_bar().value
|
|
|
|
text_edit.text = source_code_from_disc
|
|
text_edit.set_caret_column(column)
|
|
text_edit.set_caret_line(row)
|
|
text_edit.scroll_horizontal = scroll_position_h
|
|
text_edit.scroll_vertical = scroll_position_v
|
|
|
|
text_edit.tag_saved_version()
|
|
|
|
pending_reloads.erase(script.resource_path)
|
|
|
|
|
|
# Takes a file path and an array of file extensions [.txt, .tscn, ..]
|
|
static func is_file_extension(path: String, excluded_extensions: PackedStringArray) -> bool:
|
|
var is_extension := false
|
|
|
|
for extension in excluded_extensions:
|
|
var file_name := path.get_file()
|
|
if(extension in file_name):
|
|
is_extension = true
|
|
break
|
|
else:
|
|
is_extension = false
|
|
|
|
return is_extension
|
|
|
|
|
|
# Returns the content of the file from the given path as a string.
|
|
static func file_get_as_text(path: String) -> String:
|
|
var file_access := FileAccess.open(path, FileAccess.READ)
|
|
var content := file_access.get_as_text()
|
|
file_access.close()
|
|
return content
|
|
|
|
|
|
# Copies a file from a given src to the specified dst path.
|
|
# src = path/to/file.extension
|
|
# dst = other/path/to/file.extension
|
|
static func file_copy(src: String, dst: String) -> void:
|
|
var dst_dir := dst.get_base_dir()
|
|
|
|
if not DirAccess.dir_exists_absolute(dst_dir):
|
|
DirAccess.make_dir_recursive_absolute(dst_dir)
|
|
|
|
DirAccess.copy_absolute(src, dst)
|
|
|
|
|
|
# Log error messages
|
|
static func output_error(message) -> void:
|
|
printerr("ModTool Error: " + str(message))
|
|
|
|
|
|
static func output_info(message) -> void:
|
|
print("ModTool: " + str(message))
|
|
|
|
|
|
static func save_to_manifest_json(manifest_data: ModManifest, path_manifest: String) -> bool:
|
|
var is_success := _ModLoaderFile._save_string_to_file(
|
|
manifest_data.to_json(),
|
|
path_manifest
|
|
)
|
|
|
|
if is_success:
|
|
output_info("Successfully saved manifest.json file!")
|
|
|
|
return is_success
|
|
|
|
|
|
static func make_dir_recursive(dst_dir: String) -> bool:
|
|
var error := DirAccess.make_dir_recursive_absolute(dst_dir)
|
|
if not error == OK:
|
|
output_error("Failed creating directory at %s with error \"%s\"" % [dst_dir, error_string(error)])
|
|
return false
|
|
return true
|
|
|
|
|
|
# Takes a directory path to get removed.
|
|
# https://www.davidepesce.com/2019/11/04/essential-guide-to-godot-filesystem-api/
|
|
static func remove_recursive(path: String) -> void:
|
|
var directory := DirAccess.open(path)
|
|
|
|
if not directory:
|
|
print("Error removing " + path)
|
|
return
|
|
|
|
# List directory content
|
|
directory.list_dir_begin()
|
|
var file_name := directory.get_next()
|
|
while file_name != "":
|
|
if directory.current_is_dir():
|
|
remove_recursive(path + "/" + file_name)
|
|
else:
|
|
directory.remove(file_name)
|
|
file_name = directory.get_next()
|
|
|
|
# Remove current path
|
|
directory.remove(path)
|
|
|
|
|
|
static func check_for_hooked_script(script_paths: Array[String], mod_tool_store: ModToolStore) -> int:
|
|
var count := 0
|
|
|
|
for script_path in script_paths:
|
|
if mod_tool_store.hooked_scripts.has(script_path):
|
|
count += 1
|
|
|
|
return count
|
|
|
|
|
|
static func quote_string(string: String) -> String:
|
|
var settings: EditorSettings = EditorInterface.get_editor_settings()
|
|
if settings.get_setting("text_editor/completion/use_single_quotes"):
|
|
return "'%s'" % string
|
|
return "\"%s\"" % string
|
|
|
|
|
|
static func script_has_method(script_path: String, method: String) -> bool:
|
|
var script: Script = load(script_path)
|
|
|
|
for script_method in script.get_script_method_list():
|
|
if script_method.name == method:
|
|
return true
|
|
|
|
if method in script.source_code:
|
|
return true
|
|
|
|
return false
|
|
|
|
|
|
static func get_index_at_method_end(method_name: String, text: String) -> int:
|
|
var starting_index := text.rfind(method_name)
|
|
|
|
# Find the end of the method
|
|
var next_method_line_index := text.find("func ", starting_index)
|
|
var method_end := -1
|
|
|
|
if next_method_line_index == -1:
|
|
# Backtrack empty lines from the end of the file
|
|
method_end = text.length() -1
|
|
else:
|
|
# Get the line before the next function line
|
|
method_end = text.rfind("\n", next_method_line_index)
|
|
|
|
# Backtrack to the last non-empty line
|
|
var last_non_empty_line_index := method_end
|
|
while last_non_empty_line_index > starting_index:
|
|
last_non_empty_line_index -= 1
|
|
# Remove spaces, tabs and newlines (whitespace) to check if the line really is empty
|
|
if text[last_non_empty_line_index].rstrip("\t\n "):
|
|
break # encountered a filled line
|
|
|
|
return last_non_empty_line_index +1
|
|
|
|
# Slightly modified version of:
|
|
# https://gist.github.com/willnationsdev/00d97aa8339138fd7ef0d6bd42748f6e
|
|
# Removed .import from the extension filter.
|
|
# 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_file_extensions: Array[StringName] = [],
|
|
p_match_is_regex := false,
|
|
include_empty_dirs := false,
|
|
ignored_dirs: Array[StringName] = []
|
|
) -> PackedStringArray:
|
|
var data: PackedStringArray = []
|
|
var regex: RegEx
|
|
|
|
if p_match_is_regex:
|
|
regex = RegEx.new()
|
|
var _compile_error: int = regex.compile(p_match)
|
|
if not regex.is_valid():
|
|
return data
|
|
|
|
var dirs := [p_dir]
|
|
var first := true
|
|
while not dirs.is_empty():
|
|
var dir_name : String = dirs.back()
|
|
var dir := DirAccess.open(dir_name)
|
|
dirs.pop_back()
|
|
|
|
if dir_name.lstrip("res://").get_slice("/", 0) in ignored_dirs:
|
|
continue
|
|
|
|
if dir:
|
|
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
|
|
# ignore hidden, temporary, or system content
|
|
if not file_name.begins_with(".") and not file_name.get_extension() == "tmp":
|
|
# If a directory, then add to list of directories to visit
|
|
if dir.current_is_dir():
|
|
dirs.push_back(dir.get_current_dir() + "/" + file_name)
|
|
# If a file, check if we already have a record for the same name
|
|
else:
|
|
var path := dir.get_current_dir() + ("/" if not first else "") + file_name
|
|
# grab all
|
|
if not p_match and not p_match_file_extensions:
|
|
data.append(path)
|
|
# grab matching strings
|
|
elif not p_match_is_regex and p_match and file_name.contains(p_match):
|
|
data.append(path)
|
|
# garb matching file extension
|
|
elif p_match_file_extensions and file_name.get_extension() in p_match_file_extensions:
|
|
data.append(path)
|
|
# grab matching regex
|
|
elif p_match_is_regex:
|
|
var regex_match := regex.search(path)
|
|
if regex_match != null:
|
|
data.append(path)
|
|
# Move on to the next file in this directory
|
|
file_name = dir.get_next()
|
|
# We've exhausted all files in this directory. Close the iterator.
|
|
dir.list_dir_end()
|
|
return data
|