No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DialogicResources.gd 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. tool
  2. class_name DialogicResources
  3. const RESOURCES_DIR: String = "res://dialogic" # Readonly, used for static data
  4. const WORKING_DIR: String = "user://dialogic" # Readwrite, used for saves
  5. static func load_json(path: String, default: Dictionary={}) -> Dictionary:
  6. # An easy function to load json files and handle common errors.
  7. var file := File.new()
  8. if file.open(path, File.READ) != OK:
  9. file.close()
  10. return default
  11. var data_text: String = file.get_as_text()
  12. file.close()
  13. if data_text.empty():
  14. return default
  15. var data_parse: JSONParseResult = JSON.parse(data_text)
  16. if data_parse.error != OK:
  17. return default
  18. var final_data = data_parse.result
  19. if typeof(final_data) == TYPE_DICTIONARY:
  20. return final_data
  21. # If everything else fails
  22. return default
  23. static func init_dialogic_files() -> void:
  24. # This functions makes sure that the needed files and folders
  25. # exists when the plugin is loaded. If they don't, we create
  26. # them.
  27. # WARNING: only call while in the editor
  28. var directory = Directory.new()
  29. var paths = get_working_directories()
  30. var files = get_config_files_paths()
  31. # Create directories
  32. for dir in paths:
  33. if not directory.dir_exists(paths[dir]):
  34. directory.make_dir_recursive(paths[dir])
  35. # Create empty files
  36. for f in files:
  37. if not directory.file_exists(files[f]):
  38. create_empty_file(files[f])
  39. static func get_working_directories() -> Dictionary:
  40. return {
  41. 'RESOURCES_DIR': RESOURCES_DIR,
  42. 'WORKING_DIR': WORKING_DIR,
  43. 'TIMELINE_DIR': RESOURCES_DIR + "/timelines",
  44. 'THEME_DIR': RESOURCES_DIR + "/themes",
  45. 'CHAR_DIR': RESOURCES_DIR + "/characters",
  46. }
  47. static func get_config_files_paths() -> Dictionary:
  48. return {
  49. 'SETTINGS_FILE': RESOURCES_DIR + "/settings.cfg",
  50. 'DEFAULT_DEFINITIONS_FILE': RESOURCES_DIR + "/definitions.json",
  51. 'SAVED_DEFINITIONS_FILE': WORKING_DIR + "/definitions.json",
  52. 'SAVED_STATE_FILE': WORKING_DIR + "/state.json",
  53. }
  54. static func init_saves():
  55. var err = init_working_dir()
  56. var paths := get_config_files_paths()
  57. if err == OK:
  58. init_state_saves()
  59. init_definitions_saves()
  60. else:
  61. print('[Dialogic] Error creating working directory: ' + str(err))
  62. static func init_working_dir():
  63. var directory := Directory.new()
  64. return directory.make_dir_recursive(get_working_directories()['WORKING_DIR'])
  65. static func init_state_saves():
  66. var file := File.new()
  67. var paths := get_config_files_paths()
  68. var err = file.open(paths["SAVED_STATE_FILE"], File.WRITE)
  69. if err == OK:
  70. file.store_string('')
  71. file.close()
  72. else:
  73. print('[Dialogic] Error opening saved state file: ' + str(err))
  74. static func init_definitions_saves():
  75. var directory := Directory.new()
  76. var source := File.new()
  77. var sink := File.new()
  78. var paths := get_config_files_paths()
  79. var err = sink.open(paths["SAVED_DEFINITIONS_FILE"], File.WRITE)
  80. print('[Dialogic] Saved definitions not present, creating file: ' + str(err))
  81. if err == OK:
  82. sink.store_string('')
  83. sink.close()
  84. else:
  85. print('[Dialogic] Error opening saved definitions file: ' + str(err))
  86. err = sink.open(paths["SAVED_DEFINITIONS_FILE"], File.READ_WRITE)
  87. if err == OK:
  88. err = source.open(paths["DEFAULT_DEFINITIONS_FILE"], File.READ)
  89. if err == OK:
  90. sink.store_string(source.get_as_text())
  91. else:
  92. print('[Dialogic] Error opening default definitions file: ' + str(err))
  93. else:
  94. print('[Dialogic] Error opening saved definitions file: ' + str(err))
  95. source.close()
  96. sink.close()
  97. static func get_path(name: String, extra: String ='') -> String:
  98. var paths: Dictionary = get_working_directories()
  99. if extra != '':
  100. return paths[name] + '/' + extra
  101. else:
  102. return paths[name]
  103. static func get_filename_from_path(path: String, extension = false) -> String:
  104. var file_name: String = path.split('/')[-1]
  105. if extension == false:
  106. file_name = file_name.split('.')[0]
  107. return file_name
  108. static func listdir(path: String) -> Array:
  109. # https://docs.godotengine.org/en/stable/classes/class_directory.html#description
  110. var files: Array = []
  111. var dir := Directory.new()
  112. var err = dir.open(path)
  113. if err == OK:
  114. dir.list_dir_begin()
  115. var file_name = dir.get_next()
  116. while file_name != "":
  117. if not dir.current_is_dir() and not file_name.begins_with("."):
  118. files.append(file_name)
  119. file_name = dir.get_next()
  120. dir.list_dir_end()
  121. else:
  122. print("[Dialogic] Error while accessing path " + path + " - Error: " + str(err))
  123. return files
  124. static func create_empty_file(path):
  125. var file = File.new()
  126. file.open(path, File.WRITE)
  127. file.store_string('')
  128. file.close()
  129. static func copy_file(path_from, path_to):
  130. if (path_from == ''):
  131. push_error("[Dialogic] Could not copy empty filename")
  132. return ERR_FILE_BAD_PATH
  133. if (path_to == ''):
  134. push_error("[Dialogic] Could not copy to empty filename")
  135. return ERR_FILE_BAD_PATH
  136. var dir = Directory.new()
  137. if (not dir.file_exists(path_from)):
  138. push_error("[Dialogic] Could not copy file %s, File does not exists" % [ path_from ])
  139. return ERR_FILE_NOT_FOUND
  140. if (dir.file_exists(path_to)):
  141. push_error("[Dialogic] Could not copy file to %s, file already exists" % [ path_to ])
  142. return ERR_ALREADY_EXISTS
  143. var error = dir.copy(path_from, path_to)
  144. if (error):
  145. push_error("[Dialogic] Error while copying %s to %s" % [ path_from, path_to ])
  146. push_error(error)
  147. return error
  148. return OK
  149. pass
  150. # CONFIG UTIL
  151. static func get_config(id: String) -> ConfigFile:
  152. var paths := get_config_files_paths()
  153. var config := ConfigFile.new()
  154. if id in paths.keys():
  155. var err = config.load(paths[id])
  156. if err != OK:
  157. print("[Dialogic] Error while opening config file " + paths[id] + ". Error: " + str(err))
  158. return config
  159. # FILE UTIL
  160. static func remove_file(path: String):
  161. var dir = Directory.new()
  162. var _err = dir.remove(path)
  163. if _err != OK:
  164. print("[D] There was an error when deleting file at {filepath}. Error: {error}".format(
  165. {"filepath":path,"error":_err}
  166. ))
  167. # JSON UTIL
  168. static func set_json(path: String, data: Dictionary):
  169. var file = File.new()
  170. var err = file.open(path, File.WRITE)
  171. if err == OK:
  172. file.store_line(JSON.print(data, '\t', true))
  173. file.close()
  174. return err
  175. # TIMELINE
  176. # Can only be edited in the editor
  177. static func get_timeline_json(path: String):
  178. return load_json(get_path('TIMELINE_DIR', path))
  179. static func set_timeline(timeline: Dictionary):
  180. # WARNING: For use in the editor only
  181. set_json(get_path('TIMELINE_DIR', timeline['metadata']['file']), timeline)
  182. static func delete_timeline(filename: String):
  183. # WARNING: For use in the editor only
  184. remove_file(get_path('TIMELINE_DIR', filename))
  185. # CHARACTER
  186. # Can only be edited in the editor
  187. static func get_character_json(path: String):
  188. return load_json(get_path('CHAR_DIR', path))
  189. static func set_character(character: Dictionary):
  190. # WARNING: For use in the editor only
  191. set_json(get_path('CHAR_DIR', character['id']), character)
  192. static func delete_character(filename: String):
  193. # WARNING: For use in the editor only
  194. remove_file(get_path('CHAR_DIR', filename))
  195. # THEME
  196. # Can only be edited in the editor
  197. static func get_theme_config(filename: String):
  198. var config = ConfigFile.new()
  199. var path
  200. if filename.begins_with('res://'):
  201. path = filename
  202. else:
  203. path = get_path('THEME_DIR', filename)
  204. var err = config.load(path)
  205. if err == OK:
  206. return config
  207. static func set_theme_value(filename, section, key, value):
  208. # WARNING: For use in the editor only
  209. var config = get_theme_config(filename)
  210. config.set_value(section, key, value)
  211. config.save(get_path('THEME_DIR', filename))
  212. static func add_theme(filename: String):
  213. create_empty_file(get_path('THEME_DIR', filename))
  214. static func delete_theme(filename: String):
  215. remove_file(get_path('THEME_DIR', filename))
  216. static func duplicate_theme(from_filename: String, to_filename: String):
  217. copy_file(get_path('THEME_DIR', from_filename), get_path('THEME_DIR', to_filename))
  218. # SETTINGS
  219. # Can only be edited in the editor
  220. static func get_settings_config() -> ConfigFile:
  221. return get_config("SETTINGS_FILE")
  222. static func set_settings_value(section: String, key: String, value):
  223. var config = get_settings_config()
  224. config.set_value(section, key, value)
  225. config.save(get_config_files_paths()['SETTINGS_FILE'])
  226. # STATE
  227. static func get_saved_state() -> Dictionary:
  228. return load_json(get_config_files_paths()['SAVED_STATE_FILE'], {'general': {}})
  229. static func save_saved_state_config(data: Dictionary):
  230. init_working_dir()
  231. set_json(get_config_files_paths()['SAVED_STATE_FILE'], data)
  232. # DEFAULT DEFINITIONS
  233. # Can only be edited in the editor
  234. static func get_default_definitions() -> Dictionary:
  235. return load_json(get_config_files_paths()['DEFAULT_DEFINITIONS_FILE'], {'variables': [], 'glossary': []})
  236. static func save_default_definitions(data: Dictionary):
  237. set_json(get_config_files_paths()['DEFAULT_DEFINITIONS_FILE'], data)
  238. static func get_default_definition_item(id: String):
  239. var data = get_default_definitions()
  240. return DialogicDefinitionsUtil.get_definition_by_id(data, id)
  241. static func set_default_definition_variable(id: String, name: String, value):
  242. # WARNING: For use in the editor only
  243. var data = get_default_definitions()
  244. DialogicDefinitionsUtil.set_definition_variable(data, id, name, value)
  245. save_default_definitions(data)
  246. static func set_default_definition_glossary(id: String, name: String, extra_title: String, extra_text: String, extra_extra: String):
  247. # WARNING: For use in the editor only
  248. var data = get_default_definitions()
  249. DialogicDefinitionsUtil.set_definition_glossary(data, id, name, extra_title, extra_text, extra_extra)
  250. save_default_definitions(data)
  251. static func delete_default_definition(id: String):
  252. # WARNING: For use in the editor only
  253. var data = get_default_definitions()
  254. DialogicDefinitionsUtil.delete_definition(data, id)
  255. save_default_definitions(data)
  256. # SAVED DEFINITIONS
  257. # Can be edited at runtime, and will persist across runs
  258. static func get_saved_definitions(default: Dictionary = {'variables': [], 'glossary': []}) -> Dictionary:
  259. return load_json(get_config_files_paths()['SAVED_DEFINITIONS_FILE'], default)
  260. static func save_saved_definitions(data: Dictionary):
  261. init_working_dir()
  262. return set_json(get_config_files_paths()['SAVED_DEFINITIONS_FILE'], data)