Skip to content

Instantly share code, notes, and snippets.

@willnationsdev
Last active December 26, 2017 16:24
Show Gist options
  • Save willnationsdev/00d97aa8339138fd7ef0d6bd42748f6e to your computer and use it in GitHub Desktop.
Save willnationsdev/00d97aa8339138fd7ef0d6bd42748f6e to your computer and use it in GitHub Desktop.
Create flat or tiered view dictionaries of directories in Godot Engine.
# A collection of static functions for searching through the res:// directory.
tool
extends Reference
##### CLASSES #####
##### SIGNALS #####
##### CONSTANTS #####
enum Mode { SORT_FILESYSTEM, SORT_CUSTOM }
##### EXPORTS #####
##### MEMBERS #####
##### NOTIFICATIONS #####
##### OVERRIDES #####
##### VIRTUALS #####
##### PUBLIC METHODS #####
# 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):
var regex = null
if p_match_is_regex:
regex = RegEx.new()
regex.compile(p_match)
if not regex.is_valid():
print("regex failed to compile: ", p_regex)
return []
var dirs = [p_dir]
var first = true
var data = []
while not dirs.empty():
var dir = Directory.new()
var dir_name = dirs.back()
dirs.pop_back()
if dir.open(dir_name) == OK:
dir.list_dir_begin()
var file_name = dir.get_next()
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() in ["tmp", "import"]:
# 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:
data.append(path)
# grab matching strings
elif not p_match_is_regex and file_name.find(p_match, 0) != -1:
data.append(path)
# grab matching regex
else:
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
static func get_tiered_view_dict(p_dir = "res://", p_sort = SORT_FILESYSTEM, p_match = "", p_match_is_regex = false, p_funcref = null):
# Initialize the tree dict
var r_root = {
"children": {}
}
if p_sort == SORT_CUSTOM and not p_funcref:
print("Invalid function reference in custom res tiered view.")
return r_root
if not Mode.has(p_sort):
print("Unrecognized mode in res tiered view")
return r_root
# fetch all new files from res://
var this = load("res://res_utility.gd")
assert(this)
var temp_files = this.get_flat_view_dict(p_dir, p_match, p_match_is_regex)
match p_sort:
Mode.SORT_FILESYSTEM:
# for each file path in res
for a_filepath in temp_files:
var file = r_root
# get the names of items that should exist along that file path
var file_names = a_filepath.replace("res://","").split("/")
file_names.invert()
# keep going till we've exhausted every item in the list
while file_names.size():
var file_name = file_names[file_names.size()-1]
var found_file = null
# check to see if any children share a name with the current item
for a_file in file["children"]:
if a_file.get_file() == file_name:
found_file = file["children"][a_file]
break
# if not, we need to create this item
if not found_file:
found_file = {
"children": {}
}
file["children"][path] = found_file
file = found_file
# Remove this item from our list
file_names.resize(file_names.size()-1)
Mode.SORT_CUSTOM, _:
for a_filepath in temp_files:
# let the function decide how to populate r_root with the file path.
p_funcref.call_func(r_root, a_filepath)
return r_root
##### PRIVATE METHODS #####
##### CONNECTIONS #####
##### SETTERS AND GETTERS #####
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment