123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- tool
- class_name DialogicResources
-
-
- const RESOURCES_DIR: String = "res://dialogic" # Readonly, used for static data
- const WORKING_DIR: String = "user://dialogic" # Readwrite, used for saves
-
-
- static func load_json(path: String, default: Dictionary={}) -> Dictionary:
- # An easy function to load json files and handle common errors.
- var file := File.new()
- if file.open(path, File.READ) != OK:
- file.close()
- return default
- var data_text: String = file.get_as_text()
- file.close()
- if data_text.empty():
- return default
- var data_parse: JSONParseResult = JSON.parse(data_text)
- if data_parse.error != OK:
- return default
-
- var final_data = data_parse.result
- if typeof(final_data) == TYPE_DICTIONARY:
- return final_data
-
- # If everything else fails
- return default
-
-
- static func init_dialogic_files() -> void:
- # This functions makes sure that the needed files and folders
- # exists when the plugin is loaded. If they don't, we create
- # them.
- # WARNING: only call while in the editor
- var directory = Directory.new()
- var paths = get_working_directories()
- var files = get_config_files_paths()
- # Create directories
- for dir in paths:
- if not directory.dir_exists(paths[dir]):
- directory.make_dir_recursive(paths[dir])
- # Create empty files
- for f in files:
- if not directory.file_exists(files[f]):
- create_empty_file(files[f])
-
-
- static func get_working_directories() -> Dictionary:
- return {
- 'RESOURCES_DIR': RESOURCES_DIR,
- 'WORKING_DIR': WORKING_DIR,
- 'TIMELINE_DIR': RESOURCES_DIR + "/timelines",
- 'THEME_DIR': RESOURCES_DIR + "/themes",
- 'CHAR_DIR': RESOURCES_DIR + "/characters",
- }
-
-
- static func get_config_files_paths() -> Dictionary:
- return {
- 'SETTINGS_FILE': RESOURCES_DIR + "/settings.cfg",
- 'DEFAULT_DEFINITIONS_FILE': RESOURCES_DIR + "/definitions.json",
- 'SAVED_DEFINITIONS_FILE': WORKING_DIR + "/definitions.json",
- 'SAVED_STATE_FILE': WORKING_DIR + "/state.json",
- }
-
-
- static func init_saves():
- var err = init_working_dir()
- var paths := get_config_files_paths()
-
- if err == OK:
- init_state_saves()
- init_definitions_saves()
- else:
- print('[Dialogic] Error creating working directory: ' + str(err))
-
-
- static func init_working_dir():
- var directory := Directory.new()
- return directory.make_dir_recursive(get_working_directories()['WORKING_DIR'])
-
-
- static func init_state_saves():
- var file := File.new()
- var paths := get_config_files_paths()
- var err = file.open(paths["SAVED_STATE_FILE"], File.WRITE)
- if err == OK:
- file.store_string('')
- file.close()
- else:
- print('[Dialogic] Error opening saved state file: ' + str(err))
-
-
- static func init_definitions_saves():
- var directory := Directory.new()
- var source := File.new()
- var sink := File.new()
- var paths := get_config_files_paths()
- var err = sink.open(paths["SAVED_DEFINITIONS_FILE"], File.WRITE)
- print('[Dialogic] Saved definitions not present, creating file: ' + str(err))
- if err == OK:
- sink.store_string('')
- sink.close()
- else:
- print('[Dialogic] Error opening saved definitions file: ' + str(err))
-
- err = sink.open(paths["SAVED_DEFINITIONS_FILE"], File.READ_WRITE)
- if err == OK:
- err = source.open(paths["DEFAULT_DEFINITIONS_FILE"], File.READ)
- if err == OK:
- sink.store_string(source.get_as_text())
- else:
- print('[Dialogic] Error opening default definitions file: ' + str(err))
- else:
- print('[Dialogic] Error opening saved definitions file: ' + str(err))
-
- source.close()
- sink.close()
-
-
- static func get_path(name: String, extra: String ='') -> String:
- var paths: Dictionary = get_working_directories()
- if extra != '':
- return paths[name] + '/' + extra
- else:
- return paths[name]
-
-
- static func get_filename_from_path(path: String, extension = false) -> String:
- var file_name: String = path.split('/')[-1]
- if extension == false:
- file_name = file_name.split('.')[0]
- return file_name
-
-
- static func listdir(path: String) -> Array:
- # https://docs.godotengine.org/en/stable/classes/class_directory.html#description
- var files: Array = []
- var dir := Directory.new()
- var err = dir.open(path)
- if err == OK:
- dir.list_dir_begin()
- var file_name = dir.get_next()
- while file_name != "":
- if not dir.current_is_dir() and not file_name.begins_with("."):
- files.append(file_name)
- file_name = dir.get_next()
- dir.list_dir_end()
- else:
- print("[Dialogic] Error while accessing path " + path + " - Error: " + str(err))
- return files
-
-
- static func create_empty_file(path):
- var file = File.new()
- file.open(path, File.WRITE)
- file.store_string('')
- file.close()
-
-
- static func copy_file(path_from, path_to):
- if (path_from == ''):
- push_error("[Dialogic] Could not copy empty filename")
- return ERR_FILE_BAD_PATH
-
- if (path_to == ''):
- push_error("[Dialogic] Could not copy to empty filename")
- return ERR_FILE_BAD_PATH
-
- var dir = Directory.new()
- if (not dir.file_exists(path_from)):
- push_error("[Dialogic] Could not copy file %s, File does not exists" % [ path_from ])
- return ERR_FILE_NOT_FOUND
-
- if (dir.file_exists(path_to)):
- push_error("[Dialogic] Could not copy file to %s, file already exists" % [ path_to ])
- return ERR_ALREADY_EXISTS
-
- var error = dir.copy(path_from, path_to)
- if (error):
- push_error("[Dialogic] Error while copying %s to %s" % [ path_from, path_to ])
- push_error(error)
- return error
-
- return OK
- pass
-
- # CONFIG UTIL
-
-
- static func get_config(id: String) -> ConfigFile:
- var paths := get_config_files_paths()
- var config := ConfigFile.new()
- if id in paths.keys():
- var err = config.load(paths[id])
- if err != OK:
- print("[Dialogic] Error while opening config file " + paths[id] + ". Error: " + str(err))
- return config
-
-
- # FILE UTIL
-
-
- static func remove_file(path: String):
- var dir = Directory.new()
- var _err = dir.remove(path)
-
- if _err != OK:
- print("[D] There was an error when deleting file at {filepath}. Error: {error}".format(
- {"filepath":path,"error":_err}
- ))
-
-
- # JSON UTIL
-
-
- static func set_json(path: String, data: Dictionary):
- var file = File.new()
- var err = file.open(path, File.WRITE)
- if err == OK:
- file.store_line(JSON.print(data, '\t', true))
- file.close()
- return err
-
-
- # TIMELINE
- # Can only be edited in the editor
-
-
- static func get_timeline_json(path: String):
- return load_json(get_path('TIMELINE_DIR', path))
-
-
- static func set_timeline(timeline: Dictionary):
- # WARNING: For use in the editor only
- set_json(get_path('TIMELINE_DIR', timeline['metadata']['file']), timeline)
-
-
- static func delete_timeline(filename: String):
- # WARNING: For use in the editor only
- remove_file(get_path('TIMELINE_DIR', filename))
-
-
- # CHARACTER
- # Can only be edited in the editor
-
-
- static func get_character_json(path: String):
- return load_json(get_path('CHAR_DIR', path))
-
-
- static func set_character(character: Dictionary):
- # WARNING: For use in the editor only
- set_json(get_path('CHAR_DIR', character['id']), character)
-
-
- static func delete_character(filename: String):
- # WARNING: For use in the editor only
- remove_file(get_path('CHAR_DIR', filename))
-
-
- # THEME
- # Can only be edited in the editor
-
-
- static func get_theme_config(filename: String):
- var config = ConfigFile.new()
- var path
- if filename.begins_with('res://'):
- path = filename
- else:
- path = get_path('THEME_DIR', filename)
- var err = config.load(path)
- if err == OK:
- return config
-
-
- static func set_theme_value(filename, section, key, value):
- # WARNING: For use in the editor only
- var config = get_theme_config(filename)
- config.set_value(section, key, value)
- config.save(get_path('THEME_DIR', filename))
-
-
- static func add_theme(filename: String):
- create_empty_file(get_path('THEME_DIR', filename))
-
-
- static func delete_theme(filename: String):
- remove_file(get_path('THEME_DIR', filename))
-
-
- static func duplicate_theme(from_filename: String, to_filename: String):
- copy_file(get_path('THEME_DIR', from_filename), get_path('THEME_DIR', to_filename))
-
- # SETTINGS
- # Can only be edited in the editor
-
-
- static func get_settings_config() -> ConfigFile:
- return get_config("SETTINGS_FILE")
-
-
- static func set_settings_value(section: String, key: String, value):
- var config = get_settings_config()
- config.set_value(section, key, value)
- config.save(get_config_files_paths()['SETTINGS_FILE'])
-
-
- # STATE
-
-
- static func get_saved_state() -> Dictionary:
- return load_json(get_config_files_paths()['SAVED_STATE_FILE'], {'general': {}})
-
-
- static func save_saved_state_config(data: Dictionary):
- init_working_dir()
- set_json(get_config_files_paths()['SAVED_STATE_FILE'], data)
-
-
- # DEFAULT DEFINITIONS
- # Can only be edited in the editor
-
-
- static func get_default_definitions() -> Dictionary:
- return load_json(get_config_files_paths()['DEFAULT_DEFINITIONS_FILE'], {'variables': [], 'glossary': []})
-
-
- static func save_default_definitions(data: Dictionary):
- set_json(get_config_files_paths()['DEFAULT_DEFINITIONS_FILE'], data)
-
-
- static func get_default_definition_item(id: String):
- var data = get_default_definitions()
- return DialogicDefinitionsUtil.get_definition_by_id(data, id)
-
-
- static func set_default_definition_variable(id: String, name: String, value):
- # WARNING: For use in the editor only
- var data = get_default_definitions()
- DialogicDefinitionsUtil.set_definition_variable(data, id, name, value)
- save_default_definitions(data)
-
-
- static func set_default_definition_glossary(id: String, name: String, extra_title: String, extra_text: String, extra_extra: String):
- # WARNING: For use in the editor only
- var data = get_default_definitions()
- DialogicDefinitionsUtil.set_definition_glossary(data, id, name, extra_title, extra_text, extra_extra)
- save_default_definitions(data)
-
-
- static func delete_default_definition(id: String):
- # WARNING: For use in the editor only
- var data = get_default_definitions()
- DialogicDefinitionsUtil.delete_definition(data, id)
- save_default_definitions(data)
-
-
- # SAVED DEFINITIONS
- # Can be edited at runtime, and will persist across runs
-
-
- static func get_saved_definitions(default: Dictionary = {'variables': [], 'glossary': []}) -> Dictionary:
- return load_json(get_config_files_paths()['SAVED_DEFINITIONS_FILE'], default)
-
-
- static func save_saved_definitions(data: Dictionary):
- init_working_dir()
- return set_json(get_config_files_paths()['SAVED_DEFINITIONS_FILE'], data)
|