Initial Android commit
This commit is contained in:
commit
1e2b80c13d
8521 changed files with 231475 additions and 0 deletions
536
addons/dialogic/Other/DialogicClass.gd
Normal file
536
addons/dialogic/Other/DialogicClass.gd
Normal file
|
@ -0,0 +1,536 @@
|
|||
extends Node
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class_name Dialogic
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func start(timeline:String = "", default_timeline:String = "", dialog_scene_path:String = "res://addons/dialogic/Nodes/DialogNode.tscn", use_canvas_instead = true):
|
||||
var dialog_scene = load(dialog_scene_path)
|
||||
var dialog_node = null
|
||||
var canvas_dialog_node = null
|
||||
var returned_dialog_node = null
|
||||
|
||||
if use_canvas_instead:
|
||||
var canvas_dialog_script = load("res://addons/dialogic/Nodes/canvas_dialog_node.gd")
|
||||
canvas_dialog_node = canvas_dialog_script.new()
|
||||
canvas_dialog_node.set_dialog_node_scene(dialog_scene)
|
||||
dialog_node = canvas_dialog_node.dialog_node
|
||||
else :
|
||||
dialog_node = dialog_scene.instance()
|
||||
|
||||
returned_dialog_node = dialog_node if not canvas_dialog_node else canvas_dialog_node
|
||||
|
||||
|
||||
if timeline == "":
|
||||
if (Engine.get_main_loop().has_meta("last_dialog_state")
|
||||
and not Engine.get_main_loop().get_meta("last_dialog_state").empty()
|
||||
and not Engine.get_main_loop().get_meta("last_dialog_state").get("timeline", "").empty()):
|
||||
|
||||
dialog_node.resume_state_from_info(Engine.get_main_loop().get_meta("last_dialog_state"))
|
||||
return returned_dialog_node
|
||||
|
||||
|
||||
elif (Engine.get_main_loop().has_meta("current_timeline")
|
||||
and not Engine.get_main_loop().get_meta("current_timeline").empty()):
|
||||
timeline = Engine.get_main_loop().get_meta("current_timeline")
|
||||
|
||||
|
||||
else :
|
||||
timeline = default_timeline
|
||||
|
||||
|
||||
|
||||
|
||||
if timeline.ends_with(".json"):
|
||||
for t in DialogicUtil.get_timeline_list():
|
||||
if t["file"] == timeline:
|
||||
dialog_node.timeline = t["file"]
|
||||
return returned_dialog_node
|
||||
|
||||
dialog_node.dialog_script = {
|
||||
"events":[
|
||||
{"event_id":"dialogic_001",
|
||||
"character":"",
|
||||
"portrait":"",
|
||||
"text":"[Dialogic Error] Loading dialog [color=red]" + timeline + "[/color]. It seems like the timeline doesn't exists. Maybe the name is wrong?"
|
||||
}]
|
||||
}
|
||||
return returned_dialog_node
|
||||
|
||||
|
||||
var timeline_file = _get_timeline_file_from_name(timeline)
|
||||
if timeline_file:
|
||||
dialog_node.timeline = timeline_file
|
||||
return returned_dialog_node
|
||||
|
||||
|
||||
return returned_dialog_node
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func change_timeline(timeline:String)->void :
|
||||
|
||||
set_current_timeline(timeline)
|
||||
|
||||
|
||||
if has_current_dialog_node():
|
||||
var dialog_node = Engine.get_main_loop().get_meta("latest_dialogic_node")
|
||||
|
||||
|
||||
var timeline_file = _get_timeline_file_from_name(timeline)
|
||||
|
||||
dialog_node.change_timeline(timeline_file)
|
||||
else :
|
||||
print("[D] Tried to change timeline, but no DialogNode exists!")
|
||||
|
||||
|
||||
|
||||
|
||||
static func next_event(discreetly:bool = false):
|
||||
|
||||
|
||||
if has_current_dialog_node():
|
||||
var dialog_node = Engine.get_main_loop().get_meta("latest_dialogic_node")
|
||||
|
||||
dialog_node.next_event(discreetly)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func timeline_exists(timeline:String):
|
||||
var timeline_file = _get_timeline_file_from_name(timeline)
|
||||
if timeline_file:
|
||||
return true
|
||||
else :
|
||||
return false
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func load(slot_name:String = ""):
|
||||
_load_from_slot(slot_name)
|
||||
Engine.get_main_loop().set_meta("current_save_slot", slot_name)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func save(slot_name:String = "", is_autosave = false)->void :
|
||||
|
||||
if is_autosave and not get_autosave():
|
||||
return
|
||||
|
||||
|
||||
var current_dialog_info = {}
|
||||
if has_current_dialog_node():
|
||||
current_dialog_info = Engine.get_main_loop().get_meta("latest_dialogic_node").get_current_state_info()
|
||||
|
||||
var game_state = {}
|
||||
if Engine.get_main_loop().has_meta("game_state"):
|
||||
game_state = Engine.get_main_loop().get_meta("game_state")
|
||||
|
||||
var save_data = {
|
||||
"game_state":game_state,
|
||||
"dialog_state":current_dialog_info
|
||||
}
|
||||
|
||||
|
||||
_save_state_and_definitions(slot_name, save_data)
|
||||
|
||||
|
||||
|
||||
static func get_slot_names()->Array:
|
||||
return DialogicResources.get_saves_folders()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func erase_slot(slot_name:String)->void :
|
||||
DialogicResources.remove_save_folder(slot_name)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func has_current_dialog_node()->bool:
|
||||
return Engine.get_main_loop().has_meta("latest_dialogic_node") and is_instance_valid(Engine.get_main_loop().get_meta("latest_dialogic_node"))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func reset_saves(slot_name:String = "", reload: = true)->void :
|
||||
DialogicResources.reset_save(slot_name)
|
||||
if reload:_load_from_slot(slot_name)
|
||||
|
||||
|
||||
|
||||
static func get_current_slot():
|
||||
if Engine.get_main_loop().has_meta("current_save_slot"):
|
||||
return Engine.get_main_loop().get_meta("current_save_slot")
|
||||
else :
|
||||
return ""
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func export (dialog_node = null)->Dictionary:
|
||||
|
||||
var current_dialog_info = {}
|
||||
if dialog_node == null and has_current_dialog_node():
|
||||
dialog_node = Engine.get_main_loop().get_meta("latest_dialogic_node")
|
||||
if dialog_node:
|
||||
current_dialog_info = dialog_node.get_current_state_info()
|
||||
|
||||
|
||||
return {
|
||||
"definitions":_get_definitions(),
|
||||
"state":Engine.get_main_loop().get_meta("game_state"),
|
||||
"dialog_state":current_dialog_info
|
||||
}
|
||||
|
||||
|
||||
|
||||
static func import(data:Dictionary)->void :
|
||||
|
||||
Engine.get_main_loop().set_meta("current_save_lot", "/")
|
||||
|
||||
|
||||
Engine.get_main_loop().set_meta("definitions", data["definitions"])
|
||||
Engine.get_main_loop().set_meta("game_state", data["state"])
|
||||
Engine.get_main_loop().set_meta("last_dialog_state", data.get("dialog_state", null))
|
||||
set_current_timeline(get_saved_state_general_key("timeline"))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func clear_all_variables():
|
||||
for d in _get_definitions()["variables"]:
|
||||
d["value"] = ""
|
||||
|
||||
|
||||
static func set_variable(name:String, value):
|
||||
var exists = false
|
||||
|
||||
if "/" in name:
|
||||
var variable_id = _get_variable_from_file_name(name)
|
||||
if variable_id != "":
|
||||
for d in _get_definitions()["variables"]:
|
||||
if d["id"] == variable_id:
|
||||
d["value"] = str(value)
|
||||
exists = true
|
||||
else :
|
||||
for d in _get_definitions()["variables"]:
|
||||
if d["name"] == name:
|
||||
d["value"] = str(value)
|
||||
exists = true
|
||||
if exists == false:
|
||||
|
||||
|
||||
print("[Dialogic] Warning! the variable [" + name + "] doesn't exists. Create it from the Dialogic editor.")
|
||||
return value
|
||||
|
||||
|
||||
static func get_variable(name:String, default = null):
|
||||
if "/" in name:
|
||||
var variable_id = _get_variable_from_file_name(name)
|
||||
for d in _get_definitions()["variables"]:
|
||||
if d["id"] == variable_id:
|
||||
return d["value"]
|
||||
print("[Dialogic] Warning! the variable [" + name + "] doesn't exists.")
|
||||
return default
|
||||
else :
|
||||
for d in _get_definitions()["variables"]:
|
||||
if d["name"] == name:
|
||||
return d["value"]
|
||||
print("[Dialogic] Warning! the variable [" + name + "] doesn't exists.")
|
||||
return default
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_saved_state_general_key(key:String, default = "")->String:
|
||||
if not Engine.get_main_loop().has_meta("game_state"):
|
||||
return default
|
||||
if key in Engine.get_main_loop().get_meta("game_state").keys():
|
||||
return Engine.get_main_loop().get_meta("game_state")[key]
|
||||
else :
|
||||
return default
|
||||
|
||||
|
||||
|
||||
static func set_saved_state_general_key(key:String, value)->void :
|
||||
if not Engine.get_main_loop().has_meta("game_state"):
|
||||
Engine.get_main_loop().set_meta("game_state", {})
|
||||
Engine.get_main_loop().get_meta("game_state")[key] = str(value)
|
||||
save("", true)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func toggle_history():
|
||||
if has_current_dialog_node():
|
||||
var dialog_node = Engine.get_main_loop().get_meta("latest_dialogic_node")
|
||||
dialog_node.HistoryTimeline._on_toggle_history()
|
||||
else :
|
||||
print("[D] Tried to toggle history, but no dialog node exists.")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_autosave()->bool:
|
||||
if Engine.get_main_loop().has_meta("autoload"):
|
||||
return Engine.get_main_loop().get_meta("autoload")
|
||||
return true
|
||||
|
||||
|
||||
static func set_autosave(autoload):
|
||||
Engine.get_main_loop().set_meta("autoload", autoload)
|
||||
|
||||
|
||||
static func set_current_timeline(timeline):
|
||||
Engine.get_main_loop().set_meta("current_timeline", timeline)
|
||||
return timeline
|
||||
|
||||
|
||||
static func get_current_timeline():
|
||||
var timeline
|
||||
timeline = Engine.get_main_loop().get_meta("current_timeline")
|
||||
if timeline == null:
|
||||
timeline = ""
|
||||
return timeline
|
||||
|
||||
|
||||
|
||||
static func get_action_button():
|
||||
return DialogicResources.get_settings_value("input", "default_action_key", "dialogic_default_action")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func _load_from_slot(slot_name:String = "")->Dictionary:
|
||||
Engine.get_main_loop().set_meta("definitions", DialogicResources.get_saved_definitions(slot_name))
|
||||
|
||||
var state_info = DialogicResources.get_saved_state_info(slot_name)
|
||||
Engine.get_main_loop().set_meta("last_dialog_state", state_info.get("dialog_state", null))
|
||||
Engine.get_main_loop().set_meta("game_state", state_info.get("game_state", null))
|
||||
|
||||
return state_info.get("dialog_state", {})
|
||||
|
||||
|
||||
|
||||
static func _save_state_and_definitions(save_name:String, state_info:Dictionary)->void :
|
||||
DialogicResources.save_definitions(save_name, _get_definitions())
|
||||
DialogicResources.save_state_info(save_name, state_info)
|
||||
|
||||
|
||||
|
||||
static func _get_definitions()->Dictionary:
|
||||
var definitions
|
||||
if Engine.get_main_loop().has_meta("definitions"):
|
||||
definitions = Engine.get_main_loop().get_meta("definitions")
|
||||
else :
|
||||
definitions = DialogicResources.get_default_definitions()
|
||||
Engine.get_main_loop().set_meta("definitions", definitions)
|
||||
return definitions
|
||||
|
||||
|
||||
|
||||
static func set_glossary_from_id(id:String, title:String, text:String, extra:String)->void :
|
||||
var target_def:Dictionary;
|
||||
for d in _get_definitions()["glossary"]:
|
||||
if d["id"] == id:
|
||||
target_def = d;
|
||||
if target_def != null:
|
||||
if title and title != "[No Change]":
|
||||
target_def["title"] = title
|
||||
if text and text != "[No Change]":
|
||||
target_def["text"] = text
|
||||
if extra and extra != "[No Change]":
|
||||
target_def["extra"] = extra
|
||||
|
||||
|
||||
static func set_variable_from_id(id:String, value:String, operation:String)->void :
|
||||
var target_def:Dictionary;
|
||||
for d in _get_definitions()["variables"]:
|
||||
if d["id"] == id:
|
||||
target_def = d;
|
||||
if target_def != null:
|
||||
var converted_set_value = value
|
||||
var converted_target_value = target_def["value"]
|
||||
var is_number = converted_set_value.is_valid_float() and converted_target_value.is_valid_float()
|
||||
if is_number:
|
||||
converted_set_value = float(value)
|
||||
converted_target_value = float(target_def["value"])
|
||||
var result = target_def["value"]
|
||||
|
||||
match operation:
|
||||
"=":
|
||||
result = converted_set_value
|
||||
"+":
|
||||
result = converted_target_value + converted_set_value
|
||||
"-":
|
||||
if is_number:
|
||||
result = converted_target_value - converted_set_value
|
||||
"*":
|
||||
if is_number:
|
||||
result = converted_target_value * converted_set_value
|
||||
"/":
|
||||
if is_number:
|
||||
result = converted_target_value / converted_set_value
|
||||
target_def["value"] = str(result)
|
||||
|
||||
|
||||
static func _get_timeline_file_from_name(timeline_name_path:String)->String:
|
||||
var timelines = DialogicUtil.get_full_resource_folder_structure()["folders"]["Timelines"]
|
||||
|
||||
|
||||
if "/" in timeline_name_path:
|
||||
|
||||
if (timeline_name_path.left(1) != "/"):
|
||||
timeline_name_path = "/" + timeline_name_path
|
||||
var parts = timeline_name_path.split("/", false)
|
||||
|
||||
|
||||
if parts.size() == 1:
|
||||
for t in DialogicUtil.get_timeline_list():
|
||||
for f in timelines["files"]:
|
||||
if t["file"] == f and t["name"] == parts[0]:
|
||||
return t["file"]
|
||||
if parts.size() > 1:
|
||||
var current_data
|
||||
var current_depth = 0
|
||||
for p in parts:
|
||||
if current_depth == 0:
|
||||
|
||||
if (timelines["folders"].has(p)):
|
||||
current_data = timelines["folders"][p]
|
||||
else :
|
||||
return ""
|
||||
elif current_depth == parts.size() - 1:
|
||||
|
||||
for t in DialogicUtil.get_timeline_list():
|
||||
for f in current_data["files"]:
|
||||
if t["file"] == f and t["name"] == p:
|
||||
return t["file"]
|
||||
|
||||
else :
|
||||
|
||||
if (current_data["folders"].size() > 0):
|
||||
if p in current_data["folders"]:
|
||||
current_data = current_data["folders"][p]
|
||||
else :
|
||||
return ""
|
||||
else :
|
||||
return ""
|
||||
current_depth += 1
|
||||
return ""
|
||||
else :
|
||||
|
||||
for t in DialogicUtil.get_timeline_list():
|
||||
if t["name"] == timeline_name_path:
|
||||
return t["file"]
|
||||
return ""
|
||||
|
||||
static func _get_variable_from_file_name(variable_name_path:String)->String:
|
||||
|
||||
if (variable_name_path.left(1) != "/"):
|
||||
variable_name_path = "/" + variable_name_path
|
||||
|
||||
var definitions = DialogicUtil.get_full_resource_folder_structure()["folders"]["Definitions"]
|
||||
var parts = variable_name_path.split("/", false)
|
||||
|
||||
|
||||
if parts.size() == 1:
|
||||
for t in _get_definitions()["variables"]:
|
||||
for f in definitions["files"]:
|
||||
if t["id"] == f and t["name"] == parts[0]:
|
||||
return t["id"]
|
||||
if parts.size() > 1:
|
||||
var current_data
|
||||
var current_depth = 0
|
||||
|
||||
for p in parts:
|
||||
if current_depth == 0:
|
||||
|
||||
|
||||
if (definitions["folders"].has(p)):
|
||||
current_data = definitions["folders"][p]
|
||||
else :
|
||||
return ""
|
||||
elif current_depth == parts.size() - 1:
|
||||
|
||||
for t in _get_definitions()["variables"]:
|
||||
for f in current_data["files"]:
|
||||
if t["id"] == f and t["name"] == p:
|
||||
return t["id"]
|
||||
|
||||
else :
|
||||
|
||||
if (current_data["folders"].size() > 0):
|
||||
if p in current_data["folders"]:
|
||||
current_data = current_data["folders"][p]
|
||||
else :
|
||||
return ""
|
||||
else :
|
||||
return ""
|
||||
current_depth += 1
|
||||
return ""
|
72
addons/dialogic/Other/DialogicDefinitionsUtil.gd
Normal file
72
addons/dialogic/Other/DialogicDefinitionsUtil.gd
Normal file
|
@ -0,0 +1,72 @@
|
|||
extends Node
|
||||
class_name DialogicDefinitionsUtil
|
||||
|
||||
|
||||
|
||||
static func get_definition_by_key(data:Dictionary, key:String, value:String):
|
||||
var variables:Array = data["variables"]
|
||||
var glossary:Array = data["glossary"]
|
||||
for v in variables:
|
||||
if v[key] == value:
|
||||
return v
|
||||
for g in glossary:
|
||||
if g[key] == value:
|
||||
return g
|
||||
return null
|
||||
|
||||
|
||||
static func get_definition_by_id(data:Dictionary, id:String):
|
||||
return get_definition_by_key(data, "id", id)
|
||||
|
||||
|
||||
static func get_definition_by_name(data:Dictionary, id:String):
|
||||
return get_definition_by_key(data, "name", id)
|
||||
|
||||
|
||||
static func set_definition(section:String, data:Dictionary, elem:Dictionary):
|
||||
delete_definition(data, elem["id"])
|
||||
var array:Array = data[section]
|
||||
var found = false;
|
||||
for e in array:
|
||||
if e["id"] == elem["id"]:
|
||||
found = true
|
||||
array.erase(e)
|
||||
array.append(elem)
|
||||
break
|
||||
if not found:
|
||||
array.append(elem)
|
||||
|
||||
|
||||
static func set_definition_variable(data:Dictionary, id:String, name:String, value):
|
||||
set_definition("variables", data, {
|
||||
"id":id,
|
||||
"name":name,
|
||||
"value":value,
|
||||
"type":0
|
||||
})
|
||||
|
||||
|
||||
static func set_definition_glossary(data:Dictionary, id:String, name:String, title:String, text:String, extra:String):
|
||||
set_definition("glossary", data, {
|
||||
"id":id,
|
||||
"name":name,
|
||||
"title":title,
|
||||
"text":text,
|
||||
"extra":extra,
|
||||
"type":1
|
||||
})
|
||||
|
||||
|
||||
static func delete_definition(data:Dictionary, id:String):
|
||||
var variables:Array = data["variables"]
|
||||
var glossary:Array = data["glossary"]
|
||||
var item = get_definition_by_id(data, id);
|
||||
if item != null:
|
||||
if (item["type"] == 0):
|
||||
variables.erase(item)
|
||||
else :
|
||||
glossary.erase(item)
|
||||
|
||||
|
||||
static func definitions_json_to_array(data:Dictionary)->Array:
|
||||
return data["variables"] + data["glossary"]
|
462
addons/dialogic/Other/DialogicResources.gd
Normal file
462
addons/dialogic/Other/DialogicResources.gd
Normal file
|
@ -0,0 +1,462 @@
|
|||
tool
|
||||
class_name DialogicResources
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const RESOURCES_DIR:String = "res://dialogic"
|
||||
const WORKING_DIR:String = "user://dialogic"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func load_json(path:String, default:Dictionary = {})->Dictionary:
|
||||
|
||||
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
|
||||
|
||||
|
||||
return default
|
||||
|
||||
|
||||
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, " ", true))
|
||||
file.close()
|
||||
return err
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func init_dialogic_files()->void :
|
||||
|
||||
|
||||
|
||||
|
||||
var directory = Directory.new()
|
||||
var paths = get_working_directories()
|
||||
var files = get_config_files_paths()
|
||||
|
||||
for dir in paths:
|
||||
if not directory.dir_exists(paths[dir]):
|
||||
directory.make_dir_recursive(paths[dir])
|
||||
if dir == "THEME_DIR":
|
||||
directory.copy("res://addons/dialogic/Editor/ThemeEditor/default-theme.cfg", str(paths[dir], "/default-theme.cfg"))
|
||||
|
||||
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",
|
||||
"CUSTOM_EVENTS_DIR":RESOURCES_DIR + "/custom-events",
|
||||
"SOUNDS":RESOURCES_DIR + "/sounds"
|
||||
}
|
||||
|
||||
|
||||
static func get_config_files_paths()->Dictionary:
|
||||
return {
|
||||
"SETTINGS_FILE":RESOURCES_DIR + "/settings.cfg",
|
||||
"DEFAULT_DEFINITIONS_FILE":RESOURCES_DIR + "/definitions.json",
|
||||
"FOLDER_STRUCTURE_FILE":RESOURCES_DIR + "/folder_structure.json",
|
||||
"DEFINITIONS_DEFAULT_SAVE":WORKING_DIR + "/definitions_default_save.json",
|
||||
"STATE_DEFAULT_SAVE":WORKING_DIR + "/state_default_save.json"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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:
|
||||
|
||||
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 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}
|
||||
))
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_timeline_json(path:String):
|
||||
return load_json(get_path("TIMELINE_DIR", path))
|
||||
|
||||
|
||||
static func set_timeline(timeline:Dictionary):
|
||||
|
||||
set_json(get_path("TIMELINE_DIR", timeline["metadata"]["file"]), timeline)
|
||||
|
||||
|
||||
static func delete_timeline(filename:String):
|
||||
|
||||
remove_file(get_path("TIMELINE_DIR", filename))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_character_json(path:String):
|
||||
return load_json(get_path("CHAR_DIR", path))
|
||||
|
||||
|
||||
static func set_character(character:Dictionary):
|
||||
|
||||
set_json(get_path("CHAR_DIR", character["id"]), character)
|
||||
|
||||
|
||||
static func delete_character(filename:String):
|
||||
|
||||
remove_file(get_path("CHAR_DIR", filename))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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:String, section:String, key:String, value):
|
||||
|
||||
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))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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"])
|
||||
|
||||
static func get_settings_value(section:String, key:String, default):
|
||||
var config = get_settings_config()
|
||||
return config.get_value(section, key, default)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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):
|
||||
|
||||
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):
|
||||
|
||||
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):
|
||||
|
||||
var data = get_default_definitions()
|
||||
DialogicDefinitionsUtil.delete_definition(data, id)
|
||||
save_default_definitions(data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_saves_folders()->Array:
|
||||
var save_folders = []
|
||||
var directory: = Directory.new()
|
||||
if directory.open(WORKING_DIR) != OK:
|
||||
print("[D] Error: Failed to access working directory.")
|
||||
return []
|
||||
|
||||
directory.list_dir_begin()
|
||||
var file_name = directory.get_next()
|
||||
while file_name != "":
|
||||
if directory.current_is_dir() and not file_name.begins_with("."):
|
||||
save_folders.append(file_name)
|
||||
file_name = directory.get_next()
|
||||
|
||||
return save_folders
|
||||
|
||||
|
||||
static func add_save_folder(save_name:String)->void :
|
||||
var directory: = Directory.new()
|
||||
if directory.open(WORKING_DIR) != OK:
|
||||
print("[D] Error: Failed to access working directory.")
|
||||
return
|
||||
directory.make_dir(save_name)
|
||||
|
||||
var file: = File.new()
|
||||
if file.open(WORKING_DIR + "/" + save_name + "/definitions.json", File.WRITE) == OK:
|
||||
file.store_string("")
|
||||
file.close()
|
||||
if file.open(WORKING_DIR + "/" + save_name + "/state.json", File.WRITE) == OK:
|
||||
file.store_string("")
|
||||
file.close()
|
||||
|
||||
|
||||
static func remove_save_folder(save_name:String)->void :
|
||||
var directory: = Directory.new()
|
||||
if directory.open(WORKING_DIR + "/" + save_name) != OK:
|
||||
print("[D] Error: Failed to access save folder '" + save_name + "'.")
|
||||
return
|
||||
|
||||
directory.list_dir_begin()
|
||||
var file_name = directory.get_next()
|
||||
while file_name != "":
|
||||
directory.remove(file_name)
|
||||
file_name = directory.get_next()
|
||||
directory.remove(WORKING_DIR + "/" + save_name)
|
||||
|
||||
|
||||
static func reset_save(save_name:String = "")->void :
|
||||
save_state_info(save_name, {})
|
||||
save_definitions(save_name, get_default_definitions())
|
||||
|
||||
|
||||
static func save_state_info(save_name:String, state_info:Dictionary)->void :
|
||||
if save_name == "":
|
||||
set_json(get_config_files_paths()["STATE_DEFAULT_SAVE"], state_info)
|
||||
return
|
||||
|
||||
if not save_name in get_saves_folders():
|
||||
add_save_folder(save_name)
|
||||
|
||||
set_json(WORKING_DIR + "/" + save_name + "/state.json", state_info)
|
||||
|
||||
|
||||
static func get_saved_state_info(save_name:String)->Dictionary:
|
||||
if save_name == "":
|
||||
return load_json(get_config_files_paths()["STATE_DEFAULT_SAVE"], {})
|
||||
|
||||
if not save_name in get_saves_folders():
|
||||
return {}
|
||||
|
||||
return load_json(WORKING_DIR + "/" + save_name + "/state.json", {})
|
||||
|
||||
|
||||
static func save_definitions(save_name:String, definitions_info:Dictionary)->void :
|
||||
if save_name == "":
|
||||
set_json(get_config_files_paths()["DEFINITIONS_DEFAULT_SAVE"], definitions_info)
|
||||
return
|
||||
|
||||
if not save_name in get_saves_folders():
|
||||
add_save_folder(save_name)
|
||||
|
||||
set_json(WORKING_DIR + "/" + save_name + "/definitions.json", definitions_info)
|
||||
|
||||
|
||||
static func get_saved_definitions(save_name:String = "")->Dictionary:
|
||||
if save_name == "":
|
||||
return load_json(get_config_files_paths()["DEFINITIONS_DEFAULT_SAVE"], get_default_definitions())
|
||||
|
||||
if not save_name in get_saves_folders():
|
||||
print("[D] Wasn't able to find save '" + save_name + "'. Loaded the default definitions.")
|
||||
return get_default_definitions()
|
||||
|
||||
return load_json(WORKING_DIR + "/" + save_name + "/definitions.json", {})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_resource_folder_structure()->Dictionary:
|
||||
var configFileDict = get_config_files_paths();
|
||||
return load_json(configFileDict["FOLDER_STRUCTURE_FILE"],
|
||||
{"folders":
|
||||
{"Timelines":
|
||||
{
|
||||
"folders":{},
|
||||
"files":[],
|
||||
"metadata":{"color":null, "folded":false}
|
||||
},
|
||||
"Characters":
|
||||
{
|
||||
"folders":{},
|
||||
"files":[],
|
||||
"metadata":{"color":null, "folded":false}
|
||||
},
|
||||
"Definitions":
|
||||
{
|
||||
"folders":{},
|
||||
"files":[],
|
||||
"metadata":{"color":null, "folded":false}
|
||||
},
|
||||
"Themes":
|
||||
{
|
||||
"folders":{},
|
||||
"files":[],
|
||||
"metadata":{"color":null, "folded":false}
|
||||
},
|
||||
},
|
||||
"files":[]
|
||||
})
|
||||
|
||||
static func save_resource_folder_structure(data):
|
||||
set_json(get_config_files_paths()["FOLDER_STRUCTURE_FILE"], data)
|
628
addons/dialogic/Other/DialogicUtil.gd
Normal file
628
addons/dialogic/Other/DialogicUtil.gd
Normal file
|
@ -0,0 +1,628 @@
|
|||
tool
|
||||
class_name DialogicUtil
|
||||
|
||||
|
||||
|
||||
|
||||
static func list_to_dict(list):
|
||||
var dict: = {}
|
||||
for val in list:
|
||||
dict[val["file"]] = val
|
||||
return dict
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_character_list()->Array:
|
||||
var characters:Array = []
|
||||
for file in DialogicResources.listdir(DialogicResources.get_path("CHAR_DIR")):
|
||||
if ".json" in file:
|
||||
var data:Dictionary = DialogicResources.get_character_json(file)
|
||||
|
||||
characters.append({
|
||||
"name":data.get("name", data["id"]),
|
||||
"color":Color(data.get("color", "#ffffff")),
|
||||
"file":file,
|
||||
"portraits":data.get("portraits", []),
|
||||
"display_name":data.get("display_name", ""),
|
||||
"nickname":data.get("nickname", ""),
|
||||
"data":data
|
||||
})
|
||||
return characters
|
||||
|
||||
|
||||
|
||||
static func get_characters_dict():
|
||||
return list_to_dict(get_character_list())
|
||||
|
||||
|
||||
static func get_sorted_character_list():
|
||||
var array = get_character_list()
|
||||
array.sort_custom(DialgicSorter, "sort_resources")
|
||||
return array
|
||||
|
||||
|
||||
|
||||
static func get_character(character_id):
|
||||
var characters = get_character_list()
|
||||
for c in characters:
|
||||
if c["file"] == character_id:
|
||||
return c
|
||||
return {}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_timeline_list()->Array:
|
||||
var timelines:Array = []
|
||||
for file in DialogicResources.listdir(DialogicResources.get_path("TIMELINE_DIR")):
|
||||
if ".json" in file:
|
||||
var data = DialogicResources.get_timeline_json(file)
|
||||
if data.has("error") == false:
|
||||
if data.has("metadata"):
|
||||
var metadata = data["metadata"]
|
||||
var color = Color("#ffffff")
|
||||
if metadata.has("name"):
|
||||
timelines.append({"name":metadata["name"], "color":color, "file":file})
|
||||
else :
|
||||
timelines.append({"name":file.split(".")[0], "color":color, "file":file})
|
||||
return timelines
|
||||
|
||||
|
||||
static func get_timeline_dict()->Dictionary:
|
||||
return list_to_dict(get_timeline_list())
|
||||
|
||||
|
||||
static func get_sorted_timeline_list():
|
||||
var array = get_timeline_list()
|
||||
array.sort_custom(DialgicSorter, "sort_resources")
|
||||
return array
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_theme_list()->Array:
|
||||
var themes:Array = []
|
||||
for file in DialogicResources.listdir(DialogicResources.get_path("THEME_DIR")):
|
||||
if ".cfg" in file:
|
||||
var config = DialogicResources.get_theme_config(file)
|
||||
themes.append({
|
||||
"file":file,
|
||||
"name":config.get_value("settings", "name", file),
|
||||
"config":config
|
||||
})
|
||||
return themes
|
||||
|
||||
|
||||
static func get_theme_dict()->Dictionary:
|
||||
return list_to_dict(get_theme_list())
|
||||
|
||||
|
||||
static func get_sorted_theme_list():
|
||||
var array = get_theme_list()
|
||||
array.sort_custom(DialgicSorter, "sort_resources")
|
||||
return array
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_default_definitions_list()->Array:
|
||||
return DialogicDefinitionsUtil.definitions_json_to_array(DialogicResources.get_default_definitions())
|
||||
|
||||
|
||||
static func get_default_definitions_dict():
|
||||
var dict = {}
|
||||
for val in get_default_definitions_list():
|
||||
dict[val["id"]] = val
|
||||
return dict
|
||||
|
||||
|
||||
static func get_sorted_default_definitions_list():
|
||||
var array = get_default_definitions_list()
|
||||
array.sort_custom(DialgicSorter, "sort_resources")
|
||||
return array
|
||||
|
||||
|
||||
static func compare_definitions(def_value:String, event_value:String, condition:String):
|
||||
var definitions
|
||||
if not Engine.is_editor_hint():
|
||||
if Engine.get_main_loop().has_meta("definitions"):
|
||||
definitions = Engine.get_main_loop().get_meta("definitions")
|
||||
else :
|
||||
definitions = DialogicResources.get_default_definitions()
|
||||
Engine.get_main_loop().set_meta("definitions", definitions)
|
||||
else :
|
||||
definitions = DialogicResources.get_default_definitions()
|
||||
var condition_met = false
|
||||
if def_value != null and event_value != null:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var converted_def_value = def_value
|
||||
var converted_event_value = event_value
|
||||
if def_value.is_valid_float() and event_value.is_valid_float():
|
||||
converted_def_value = float(def_value)
|
||||
converted_event_value = float(event_value)
|
||||
if condition == "":
|
||||
condition = "=="
|
||||
match condition:
|
||||
"==":
|
||||
condition_met = converted_def_value == converted_event_value
|
||||
"!=":
|
||||
condition_met = converted_def_value != converted_event_value
|
||||
">":
|
||||
condition_met = converted_def_value > converted_event_value
|
||||
">=":
|
||||
condition_met = converted_def_value >= converted_event_value
|
||||
"<":
|
||||
condition_met = converted_def_value < converted_event_value
|
||||
"<=":
|
||||
condition_met = converted_def_value <= converted_event_value
|
||||
return condition_met
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_parent_path(path:String):
|
||||
return path.replace("/" + path.split("/")[ - 1], "")
|
||||
|
||||
|
||||
|
||||
|
||||
static func get_full_resource_folder_structure():
|
||||
return DialogicResources.get_resource_folder_structure()
|
||||
|
||||
static func get_timelines_folder_structure():
|
||||
return get_folder_at_path("Timelines")
|
||||
|
||||
static func get_characters_folder_structure():
|
||||
return get_folder_at_path("Characters")
|
||||
|
||||
static func get_definitions_folder_structure():
|
||||
return get_folder_at_path("Definitions")
|
||||
|
||||
static func get_theme_folder_structure():
|
||||
return get_folder_at_path("Themes")
|
||||
|
||||
|
||||
|
||||
static func get_folder_at_path(path):
|
||||
var folder_data = get_full_resource_folder_structure()
|
||||
|
||||
for folder in path.split("/"):
|
||||
if folder:
|
||||
folder_data = folder_data["folders"][folder]
|
||||
|
||||
if folder_data == null:
|
||||
folder_data = {"folders":{}, "files":[]}
|
||||
return folder_data
|
||||
|
||||
|
||||
|
||||
static func set_folder_content_recursive(path_array:Array, orig_data:Dictionary, new_data:Dictionary)->Dictionary:
|
||||
if len(path_array) == 1:
|
||||
if path_array[0] in orig_data["folders"].keys():
|
||||
if new_data.empty():
|
||||
orig_data["folders"].erase(path_array[0])
|
||||
else :
|
||||
orig_data["folders"][path_array[0]] = new_data
|
||||
else :
|
||||
var current_folder = path_array.pop_front()
|
||||
orig_data["folders"][current_folder] = set_folder_content_recursive(path_array, orig_data["folders"][current_folder], new_data)
|
||||
return orig_data
|
||||
|
||||
static func set_folder_at_path(path:String, data:Dictionary):
|
||||
var orig_structure = get_full_resource_folder_structure()
|
||||
var new_data = set_folder_content_recursive(path.split("/"), orig_structure, data)
|
||||
DialogicResources.save_resource_folder_structure(new_data)
|
||||
return OK
|
||||
|
||||
|
||||
static func set_folder_meta(folder_path:String, key:String, value):
|
||||
var data = get_folder_at_path(folder_path)
|
||||
data["metadata"][key] = value
|
||||
set_folder_at_path(folder_path, data)
|
||||
|
||||
static func get_folder_meta(folder_path:String, key:String):
|
||||
return get_folder_at_path(folder_path)["metadata"][key]
|
||||
|
||||
|
||||
|
||||
static func add_folder(path:String, folder_name:String):
|
||||
|
||||
if folder_name in get_folder_at_path(path)["folders"].keys():
|
||||
print("[D] A folder with the name '" + folder_name + "' already exists in the target folder '" + path + "'.")
|
||||
return ERR_ALREADY_EXISTS
|
||||
|
||||
var folder_data = get_folder_at_path(path)
|
||||
folder_data["folders"][folder_name] = {"folders":{}, "files":[], "metadata":{"color":null, "folded":false}}
|
||||
set_folder_at_path(path, folder_data)
|
||||
|
||||
return OK
|
||||
|
||||
static func remove_folder(folder_path:String, delete_files:bool = true):
|
||||
|
||||
for folder in get_folder_at_path(folder_path)["folders"]:
|
||||
remove_folder(folder_path + "/" + folder, delete_files)
|
||||
|
||||
if delete_files:
|
||||
for file in get_folder_at_path(folder_path)["files"]:
|
||||
|
||||
match folder_path.split("/")[0]:
|
||||
"Timelines":
|
||||
DialogicResources.delete_timeline(file)
|
||||
"Characters":
|
||||
DialogicResources.delete_character(file)
|
||||
"Definitions":
|
||||
DialogicResources.delete_default_definition(file)
|
||||
"Themes":
|
||||
DialogicResources.delete_theme(file)
|
||||
set_folder_at_path(folder_path, {})
|
||||
|
||||
static func rename_folder(path:String, new_folder_name:String):
|
||||
|
||||
if new_folder_name in get_folder_at_path(get_parent_path(path))["folders"].keys():
|
||||
print("[D] A folder with the name '" + new_folder_name + "' already exists in the target folder '" + get_parent_path(path) + "'.")
|
||||
return ERR_ALREADY_EXISTS
|
||||
elif new_folder_name.empty():
|
||||
return ERR_PRINTER_ON_FIRE
|
||||
|
||||
|
||||
|
||||
var folder_content = get_folder_at_path(path)
|
||||
|
||||
|
||||
remove_folder(path, false)
|
||||
|
||||
|
||||
add_folder(get_parent_path(path), new_folder_name)
|
||||
var new_path = get_parent_path(path) + "/" + new_folder_name
|
||||
set_folder_at_path(new_path, folder_content)
|
||||
|
||||
return OK
|
||||
|
||||
static func move_folder_to_folder(orig_path, target_folder):
|
||||
|
||||
if orig_path.split("/")[ - 1] in get_folder_at_path(target_folder)["folders"].keys():
|
||||
print("[D] A folder with the name '" + orig_path.split("/")[ - 1] + "' already exists in the target folder '" + target_folder + "'.")
|
||||
return ERR_ALREADY_EXISTS
|
||||
|
||||
|
||||
var folder_content = get_folder_at_path(orig_path)
|
||||
|
||||
|
||||
|
||||
remove_folder(orig_path, false)
|
||||
|
||||
|
||||
var folder_name = orig_path.split("/")[ - 1]
|
||||
add_folder(target_folder, folder_name)
|
||||
var new_path = target_folder + "/" + folder_name
|
||||
set_folder_at_path(new_path, folder_content)
|
||||
|
||||
return OK
|
||||
|
||||
|
||||
static func move_file_to_folder(file_name, orig_folder, target_folder):
|
||||
remove_file_from_folder(orig_folder, file_name)
|
||||
add_file_to_folder(target_folder, file_name)
|
||||
|
||||
static func add_file_to_folder(folder_path, file_name):
|
||||
var folder_data = get_folder_at_path(folder_path)
|
||||
folder_data["files"].append(file_name)
|
||||
set_folder_at_path(folder_path, folder_data)
|
||||
|
||||
static func remove_file_from_folder(folder_path, file_name):
|
||||
var folder_data = get_folder_at_path(folder_path)
|
||||
folder_data["files"].erase(file_name)
|
||||
set_folder_at_path(folder_path, folder_data)
|
||||
|
||||
|
||||
|
||||
|
||||
static func update_resource_folder_structure():
|
||||
var character_files = DialogicResources.listdir(DialogicResources.get_path("CHAR_DIR"))
|
||||
var timeline_files = DialogicResources.listdir(DialogicResources.get_path("TIMELINE_DIR"))
|
||||
var theme_files = DialogicResources.listdir(DialogicResources.get_path("THEME_DIR"))
|
||||
var definition_files = get_default_definitions_dict().keys()
|
||||
|
||||
var folder_structure = DialogicResources.get_resource_folder_structure()
|
||||
|
||||
folder_structure["folders"]["Timelines"] = check_folders_section(folder_structure["folders"]["Timelines"], timeline_files)
|
||||
folder_structure["folders"]["Characters"] = check_folders_section(folder_structure["folders"]["Characters"], character_files)
|
||||
folder_structure["folders"]["Themes"] = check_folders_section(folder_structure["folders"]["Themes"], theme_files)
|
||||
folder_structure["folders"]["Definitions"] = check_folders_section(folder_structure["folders"]["Definitions"], definition_files)
|
||||
|
||||
DialogicResources.save_resource_folder_structure(folder_structure)
|
||||
|
||||
|
||||
static func check_folders_section(section_structure:Dictionary, section_files:Array):
|
||||
var result = check_folders_recursive(section_structure, section_files)
|
||||
section_structure = result[0]
|
||||
section_structure["files"] += result[1]
|
||||
return section_structure
|
||||
|
||||
static func check_folders_recursive(folder_data:Dictionary, file_names:Array):
|
||||
if not folder_data.has("metadata"):
|
||||
folder_data["metadata"] = {"color":null, "folded":false}
|
||||
for folder in folder_data["folders"].keys():
|
||||
var result = check_folders_recursive(folder_data["folders"][folder], file_names)
|
||||
folder_data["folders"][folder] = result[0]
|
||||
file_names = result[1]
|
||||
for file in folder_data["files"]:
|
||||
if not file in file_names:
|
||||
folder_data["files"].erase(file)
|
||||
|
||||
else :
|
||||
file_names.erase(file)
|
||||
return [folder_data, file_names]
|
||||
|
||||
|
||||
static func beautify_filename(animation_name:String)->String:
|
||||
if animation_name == "[Default]" or animation_name == "[No Animation]":
|
||||
return animation_name
|
||||
var a_string = animation_name.get_file().trim_suffix(".gd")
|
||||
if "-" in a_string:
|
||||
a_string = a_string.split("-")[1].capitalize()
|
||||
else :
|
||||
a_string = a_string.capitalize()
|
||||
return a_string
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static func generate_random_id()->String:
|
||||
return str(OS.get_unix_time()) + "-" + str(100 + randi() % 899 + 1)
|
||||
|
||||
|
||||
static func compare_dicts(dict_1:Dictionary, dict_2:Dictionary)->bool:
|
||||
|
||||
|
||||
if str(dict_1) != "Null" and str(dict_2) != "Null":
|
||||
if str(dict_1) == str(dict_2):
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
static func path_fixer_load(path):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
match path:
|
||||
"res://addons/dialogic/Fonts/DefaultFont.tres":
|
||||
return load("res://addons/dialogic/Example Assets/Fonts/DefaultFont.tres")
|
||||
"res://addons/dialogic/Fonts/GlossaryFont.tres":
|
||||
return load("res://addons/dialogic/Example Assets/Fonts/GlossaryFont.tres")
|
||||
"res://addons/dialogic/Images/background/background-1.png":
|
||||
return load("res://addons/dialogic/Example Assets/backgrounds/background-1.png")
|
||||
"res://addons/dialogic/Images/background/background-2.png":
|
||||
return load("res://addons/dialogic/Example Assets/backgrounds/background-2.png")
|
||||
"res://addons/dialogic/Images/next-indicator.png":
|
||||
return load("res://addons/dialogic/Example Assets/next-indicator/next-indicator.png")
|
||||
|
||||
return load(path)
|
||||
|
||||
|
||||
|
||||
static func resource_fixer():
|
||||
var update_index = DialogicResources.get_settings_config().get_value("updates", "updatenumber", 0)
|
||||
|
||||
if update_index < 1:
|
||||
print("[D] Update NR. " + str(update_index) + " | Adds event ids. Don't worry about this.")
|
||||
for timeline_info in get_timeline_list():
|
||||
var timeline = DialogicResources.get_timeline_json(timeline_info["file"])
|
||||
|
||||
var events = timeline["events"]
|
||||
for i in events:
|
||||
if not i.has("event_id"):
|
||||
match i:
|
||||
|
||||
|
||||
{"text", "character", "portrait"}:
|
||||
i["event_id"] = "dialogic_001"
|
||||
|
||||
{"character", "action", "position", "portrait", ..}:
|
||||
i["event_id"] = "dialogic_002"
|
||||
|
||||
{"character", "action"}:
|
||||
i["event_id"] = "dialogic_003"
|
||||
|
||||
|
||||
|
||||
{"question", "options", ..}:
|
||||
i["event_id"] = "dialogic_010"
|
||||
|
||||
{"choice", ..}:
|
||||
i["event_id"] = "dialogic_011"
|
||||
|
||||
{"condition", "definition", "value"}:
|
||||
i["event_id"] = "dialogic_012"
|
||||
|
||||
{"endbranch"}:
|
||||
i["event_id"] = "dialogic_013"
|
||||
|
||||
{"set_value", "definition", ..}:
|
||||
i["event_id"] = "dialogic_014"
|
||||
|
||||
|
||||
|
||||
{"change_timeline"}:
|
||||
i["event_id"] = "dialogic_020"
|
||||
|
||||
{"background"}:
|
||||
i["event_id"] = "dialogic_021"
|
||||
|
||||
{"close_dialog", ..}:
|
||||
i["event_id"] = "dialogic_022"
|
||||
|
||||
{"wait_seconds"}:
|
||||
i["event_id"] = "dialogic_023"
|
||||
|
||||
{"set_theme"}:
|
||||
i["event_id"] = "dialogic_024"
|
||||
|
||||
|
||||
|
||||
{"audio", "file", ..}:
|
||||
i["event_id"] = "dialogic_030"
|
||||
|
||||
{"background-music", "file", ..}:
|
||||
i["event_id"] = "dialogic_031"
|
||||
|
||||
|
||||
|
||||
{"emit_signal"}:
|
||||
i["event_id"] = "dialogic_040"
|
||||
|
||||
{"change_scene"}:
|
||||
i["event_id"] = "dialogic_041"
|
||||
|
||||
{"call_node"}:
|
||||
i["event_id"] = "dialogic_042"
|
||||
timeline["events"] = events
|
||||
DialogicResources.set_timeline(timeline)
|
||||
if update_index < 2:
|
||||
|
||||
print("[D] Update NR. " + str(update_index) + " | Changes how some theme values are saved. No need to worry about this.")
|
||||
for theme_info in get_theme_list():
|
||||
var theme = DialogicResources.get_theme_config(theme_info["file"])
|
||||
|
||||
match theme.get_value("text", "alignment", "Left"):
|
||||
"Left":
|
||||
DialogicResources.set_theme_value(theme_info["file"], "text", "alignment", 0)
|
||||
"Center":
|
||||
DialogicResources.set_theme_value(theme_info["file"], "text", "alignment", 1)
|
||||
"Right":
|
||||
DialogicResources.set_theme_value(theme_info["file"], "text", "alignment", 2)
|
||||
|
||||
if update_index < 3:
|
||||
|
||||
print("[D] Update NR. " + str(update_index) + " | Removes Character Join and Character Leave events in favor of the new 'Character' event. No need to worry about this.")
|
||||
for timeline_info in get_timeline_list():
|
||||
var timeline = DialogicResources.get_timeline_json(timeline_info["file"])
|
||||
var events = timeline["events"]
|
||||
for i in range(len(events)):
|
||||
if events[i]["event_id"] == "dialogic_002":
|
||||
var new_event = {
|
||||
"event_id":"dialogic_002",
|
||||
"type":0,
|
||||
"character":events[i].get("character", ""),
|
||||
"portrait":events[i].get("portrait", "Default"),
|
||||
"position":events[i].get("position"),
|
||||
"animation":"[Default]",
|
||||
"animation_length":0.5,
|
||||
"mirror_portrait":events[i].get("mirror", false),
|
||||
"z_index":events[i].get("z_index", 0),
|
||||
}
|
||||
if new_event["portrait"].empty():new_event["portrait"] = "Default"
|
||||
events[i] = new_event
|
||||
elif events[i]["event_id"] == "dialogic_003":
|
||||
var new_event = {
|
||||
"event_id":"dialogic_002",
|
||||
"type":1,
|
||||
"character":events[i].get("character", ""),
|
||||
"animation":"[Default]",
|
||||
"animation_length":0.5,
|
||||
"mirror_portrait":events[i].get("mirror", false),
|
||||
"z_index":events[i].get("z_index", 0),
|
||||
}
|
||||
events[i] = new_event
|
||||
timeline["events"] = events
|
||||
DialogicResources.set_timeline(timeline)
|
||||
|
||||
DialogicResources.set_settings_value("updates", "updatenumber", 3)
|
||||
|
||||
if not ProjectSettings.has_setting("input/dialogic_default_action"):
|
||||
print("[D] Added the 'dialogic_default_action' to the InputMap. This is the default if you didn't select a different one in the dialogic settings. You will have to force the InputMap editor to update before you can see the action (reload project or add a new input action).")
|
||||
var input_enter = InputEventKey.new()
|
||||
input_enter.scancode = KEY_ENTER
|
||||
var input_left_click = InputEventMouseButton.new()
|
||||
input_left_click.button_index = BUTTON_LEFT
|
||||
input_left_click.pressed = true
|
||||
var input_space = InputEventKey.new()
|
||||
input_space.scancode = KEY_SPACE
|
||||
var input_x = InputEventKey.new()
|
||||
input_x.scancode = KEY_X
|
||||
var input_controller = InputEventJoypadButton.new()
|
||||
input_controller.button_index = JOY_BUTTON_0
|
||||
|
||||
ProjectSettings.set_setting("input/dialogic_default_action", {"deadzone":0.5, "events":[input_enter, input_left_click, input_space, input_x, input_controller]})
|
||||
ProjectSettings.save()
|
||||
if DialogicResources.get_settings_value("input", "default_action_key", "[Default]") == "[Default]":
|
||||
DialogicResources.set_settings_value("input", "default_action_key", "dialogic_default_action")
|
||||
|
||||
static func get_editor_scale(ref)->float:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var _scale = ref.get_constant("inspector_margin", "Editor")
|
||||
_scale = _scale * 0.125
|
||||
|
||||
return _scale
|
||||
|
||||
|
||||
static func list_dir(path:String)->Array:
|
||||
var files = []
|
||||
var dir = Directory.new()
|
||||
dir.open(path)
|
||||
dir.list_dir_begin(true)
|
||||
|
||||
var file = dir.get_next()
|
||||
while file != "":
|
||||
files += [file]
|
||||
file = dir.get_next()
|
||||
return files
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class DialgicSorter:
|
||||
|
||||
static func key_available(key, a:Dictionary)->bool:
|
||||
return key in a.keys() and not a[key].empty()
|
||||
|
||||
static func get_compare_value(a:Dictionary)->String:
|
||||
if key_available("display_name", a):
|
||||
return a["display_name"]
|
||||
|
||||
if key_available("name", a):
|
||||
return a["name"]
|
||||
|
||||
if key_available("id", a):
|
||||
return a["id"]
|
||||
|
||||
if "metadata" in a.keys():
|
||||
var a_metadata = a["metadata"]
|
||||
if key_available("name", a_metadata):
|
||||
return a_metadata["name"]
|
||||
if key_available("file", a_metadata):
|
||||
return a_metadata["file"]
|
||||
return ""
|
||||
|
||||
static func sort_resources(a:Dictionary, b:Dictionary):
|
||||
return get_compare_value(a).to_lower() < get_compare_value(b).to_lower()
|
28
addons/dialogic/Other/export_plugin.gd
Normal file
28
addons/dialogic/Other/export_plugin.gd
Normal file
|
@ -0,0 +1,28 @@
|
|||
extends EditorExportPlugin
|
||||
|
||||
func _export_begin(features:PoolStringArray, is_debug:bool, path:String, flags:int)->void :
|
||||
|
||||
for feature in features:
|
||||
if feature == "Android":
|
||||
return
|
||||
|
||||
var file = File.new()
|
||||
var directory = Directory.new()
|
||||
|
||||
var paths = DialogicResources.get_working_directories()
|
||||
|
||||
|
||||
|
||||
for dir in paths:
|
||||
if directory.open(paths[dir]) == OK:
|
||||
directory.list_dir_begin()
|
||||
var file_name = directory.get_next()
|
||||
while file_name != "":
|
||||
if not directory.current_is_dir():
|
||||
var file_lower = file_name.to_lower()
|
||||
if ".json" in file_lower or ".cfg" in file_lower:
|
||||
var file_path = paths[dir] + "/" + file_name
|
||||
if file.open(file_path, File.READ) == OK:
|
||||
add_file(file_path, file.get_buffer(file.get_len()), false)
|
||||
file.close()
|
||||
file_name = directory.get_next()
|
37
addons/dialogic/Other/inspector_timeline_picker.gd
Normal file
37
addons/dialogic/Other/inspector_timeline_picker.gd
Normal file
|
@ -0,0 +1,37 @@
|
|||
extends EditorInspectorPlugin
|
||||
|
||||
var TimelinePicker = preload("res://addons/dialogic/Other/timeline_picker.gd")
|
||||
var dialogic_editor_plugin = null
|
||||
var dialogic_editor_view = null
|
||||
|
||||
|
||||
func can_handle(object):
|
||||
|
||||
return true
|
||||
|
||||
|
||||
func parse_property(object, type, path, hint, hint_text, usage):
|
||||
|
||||
if hint_text == "TimelineDropdown":
|
||||
|
||||
if type == TYPE_STRING:
|
||||
|
||||
|
||||
var picker = TimelinePicker.new()
|
||||
picker.editor_inspector_plugin = self
|
||||
add_property_editor(path, picker)
|
||||
|
||||
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func switch_to_dialogic_timeline(timeline:String):
|
||||
if (dialogic_editor_plugin != null):
|
||||
var master_tree = dialogic_editor_view.get_node("MainPanel/MasterTreeContainer/MasterTree")
|
||||
dialogic_editor_plugin.get_editor_interface().set_main_screen_editor("Dialogic")
|
||||
|
||||
master_tree.timeline_editor.batches.clear()
|
||||
master_tree.timeline_editor.load_timeline(timeline)
|
||||
|
||||
master_tree.show_timeline_editor()
|
109
addons/dialogic/Other/timeline_picker.gd
Normal file
109
addons/dialogic/Other/timeline_picker.gd
Normal file
|
@ -0,0 +1,109 @@
|
|||
tool
|
||||
extends EditorProperty
|
||||
|
||||
|
||||
var timelines_dropdown = MenuButton.new()
|
||||
var container = HBoxContainer.new()
|
||||
var edit_button = Button.new()
|
||||
|
||||
|
||||
var editor_inspector_plugin = null
|
||||
|
||||
|
||||
var current_value = ""
|
||||
|
||||
var updating = false
|
||||
|
||||
|
||||
func get_tooltip_text():
|
||||
return "Click to select a Dialogic timeline.\nPress the tool button to directly switch to the editor"
|
||||
|
||||
|
||||
func _ready():
|
||||
edit_button.icon = get_icon("Tools", "EditorIcons")
|
||||
|
||||
|
||||
func _init():
|
||||
|
||||
timelines_dropdown.rect_min_size.x = 80
|
||||
timelines_dropdown.set_h_size_flags(SIZE_EXPAND_FILL)
|
||||
timelines_dropdown.clip_text = true
|
||||
container.add_child(timelines_dropdown)
|
||||
container.add_child(edit_button)
|
||||
edit_button.flat = true
|
||||
edit_button.hint_tooltip = "Edit Timeline"
|
||||
edit_button.disabled = true
|
||||
|
||||
|
||||
add_child(container)
|
||||
|
||||
|
||||
add_focusable(timelines_dropdown)
|
||||
|
||||
|
||||
timelines_dropdown.connect("about_to_show", self, "_about_to_show_menu")
|
||||
timelines_dropdown.get_popup().connect("index_pressed", self, "_on_timeline_selected")
|
||||
edit_button.connect("pressed", self, "_on_editTimelineButton_pressed")
|
||||
|
||||
|
||||
func _about_to_show_menu():
|
||||
|
||||
if (updating):
|
||||
return
|
||||
|
||||
|
||||
timelines_dropdown.get_popup().clear()
|
||||
var index = 0
|
||||
for c in DialogicUtil.get_sorted_timeline_list():
|
||||
timelines_dropdown.get_popup().add_item(c["name"])
|
||||
timelines_dropdown.get_popup().set_item_metadata(index, {"file":c["file"], "color":c["color"]})
|
||||
index += 1
|
||||
|
||||
|
||||
func _on_timeline_selected(index):
|
||||
var text = timelines_dropdown.get_popup().get_item_text(index)
|
||||
var metadata = timelines_dropdown.get_popup().get_item_metadata(index)
|
||||
current_value = metadata["file"]
|
||||
timelines_dropdown.text = text
|
||||
timelines_dropdown.hint_tooltip = text
|
||||
_update_edit_button(current_value)
|
||||
emit_changed(get_edited_property(), current_value)
|
||||
|
||||
|
||||
func _on_editTimelineButton_pressed():
|
||||
if (current_value != "" and editor_inspector_plugin != null):
|
||||
editor_inspector_plugin.switch_to_dialogic_timeline(current_value)
|
||||
|
||||
|
||||
func update_property():
|
||||
|
||||
var new_value = get_edited_object()[get_edited_property()]
|
||||
_update_edit_button(new_value)
|
||||
|
||||
if (new_value == current_value):
|
||||
return
|
||||
|
||||
|
||||
updating = true
|
||||
current_value = new_value
|
||||
|
||||
timelines_dropdown.text = ""
|
||||
|
||||
if (current_value == ""):
|
||||
timelines_dropdown.hint_tooltip = "Click to select a timeline"
|
||||
|
||||
for c in DialogicUtil.get_timeline_list():
|
||||
if c["file"] == current_value:
|
||||
timelines_dropdown.text = c["name"]
|
||||
timelines_dropdown.hint_tooltip = c["name"]
|
||||
|
||||
updating = false
|
||||
|
||||
_update_edit_button(current_value)
|
||||
|
||||
|
||||
func _update_edit_button(value):
|
||||
if (value == ""):
|
||||
edit_button.disabled = true
|
||||
else :
|
||||
edit_button.disabled = false
|
Loading…
Add table
Add a link
Reference in a new issue