diff --git a/README.md b/README.md index 0ac2e4f40..f61d7fff9 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,20 @@ The plugin is not production ready, this means that it will not work in your gam --- -## Changelog +## Contents -### πŸ†• v1.0 - WIP +- [Changleog](#-changelog) +- [Installation](#-installation) +- [Basic Usage](#-basic-usage) +- [Documentation](#-v1.0-documentation) +- [FAQ](#-faq) +- [Source structure](#-source-structure) +- [Credits](#-credits) + + +## πŸ†• Changelog + +### v1.0 - WIP - When upgrading from 0.9 to the current version things might not work as expected: - ⚠ **PLEASE MAKE A BACKUP OF YOUR PROJECT BEFORE UPGRADING** ⚠ - Glossary variables will be lost @@ -47,9 +58,9 @@ To view the full changelog [click here](https://github.com/coppolaemilio/dialogi --- -## Installation +## βš™ Installation -### Downloading the plugin +### ⬇ Downloading the plugin To install a Dialogic, download it as a ZIP archive. All releases are listed here: https://github.com/coppolaemilio/dialogic/releases. Then extract the ZIP archive and move the `addons/` folder it contains into your project folder. Then, enable the plugin in project settings. @@ -57,13 +68,13 @@ If you want to know more about installing plugins you can read the [official doc You can also install Dialogic using the **AssetLib** tab in the editor, but the version here will not be the latest one available since it takes some time for it to be approved. -### Preparing the export +### πŸ“¦ Preparing the export When you export a project using Dialogic, you need to add `*.json, *.cfg` on the Resources tab (see the image below). This allows Godot to pack the files from the `/dialogic` folder. ![Screenshot](https://coppolaemilio.com/images/dialogic/exporting-2.png?v2) -## Basic Usage +## βœ… Basic Usage After installing the plugin, you will find a new **Dialogic** tab at the top, next to the Assets Lib. Clicking on it will display the Dialogic editor. @@ -78,44 +89,166 @@ Using the buttons on the top left, you can create 4 types of objects: Dialogic is very simple to use, try it a bit and you will quickly understand how to master it. -## v1.0 Documentation +## πŸ“– v1.0 Documentation **Note:** ⚠️ This documentation is valid only for the v1.0 branch. ⚠️ The `Dialogic` class exposes methods allowing you to control the plugin: -* Node `start(timeline: String, dialog_scene_path: String, debug_mode: bool)` +### πŸ”Ά start + +```gdscript +start( + timeline: String, + reset_saves: bool=true, + dialog_scene_path: String="res://addons/dialogic/Dialog.tscn", + debug_mode: bool=false + ) +``` Starts the dialog for the given timeline and returns a Dialog node. You must then add it manually to the scene to display the dialog. -If you made a custom Dialog scene or moved it from its default path, you can specify its new path here. Debug is disabled by default but can be enabled if needed. +Example: +```gdscript +var new_dialog = Dialogic.start('Your Timeline Name Here') +add_child(new_dialog) +``` + +This is exactly the same as using the editor: you can drag and drop the scene located at /addons/dialogic/Dialog.tscn and set the current timeline via the inspector. + +- **@param** `timeline` The timeline to load. You can provide the timeline name or the filename. +- **@param** `reset_saves` True to reset dialogic saved data such as definitions. +- **@param** `dialog_scene_path` If you made a custom Dialog scene or moved it from its default path, you can specify its new path here. +- **@param** `debug_mode` Debug is disabled by default but can be enabled if needed. +- **@returns** A Dialog node to be added into the scene tree. -Example usage: +### πŸ”Ά reset_saves +```gdscript +start_from_save( + initial_timeline: String, + dialog_scene_path: String="res://addons/dialogic/Dialog.tscn", + debug_mode: bool=false + ) ``` -var new_dialog = Dialogic.start('Your Timeline Name Here') -add_child(new_dialog) + +Same as the start method above, but using the last timeline saved. + +### πŸ”Ά get_default_definitions + +```gdscript +get_default_definitions() ``` -This is exactly the same as using the editor: you can drag and drop the scene located at `/addons/dialogic/Dialog.tscn` and set the current timeline via the inspector. +Gets default values for definitions. + +- **@returns** Dictionary in the format `{'variables': [], 'glossary': []}` -* void `reset_saves()` -Resets saved data (definitions) to the default values you set in the editor. Definitions are saved across runs in `user://dialogic/definitions.cfg`, calling this function will clear this file. Useful for a `New Game` behavior. +### πŸ”Ά get_definitions + +```gdscript +get_definitions() +``` + +Gets currently saved values for definitions. + +- **@returns** Dictionary in the format `{'variables': [], 'glossary': []}` + + +### πŸ”Ά save_definitions + +```gdscript +save_definitions() +``` + +Save current definitions to the filesystem. Definitions are automatically saved on timeline start/end. + +- **@returns** Error status, `OK` if all went well + + +### πŸ”Ά reset_saves + +```gdscript +reset_saves() +``` + +Resets data to default values. This is the same as calling start with reset_saves to true. -* String `get_var(variable: String)` -Gets the value associated to the given variable. Currently, only variable definitions can be queried. +### πŸ”Ά get_variable + +```gdscript +get_variable(name: String) +``` + +Gets the value for the variable with the given name. The returned value is a String but can be easily converted into a number using Godot built-in methods: [`is_valid_float`](https://docs.godotengine.org/en/stable/classes/class_string.html#class-string-method-is-valid-float) and [`float()`](https://docs.godotengine.org/en/stable/classes/class_float.html#class-float-method-float). -* String `set_var(variable: String, value)` +- **@param** `name` The name of the variable to find. +- **@returns** The variable's value as string, or an empty string if not found. + + +### πŸ”Ά set_variable + +```gdscript +set_variable(name: String, value) +``` + +Sets the value for the variable with the given name. + +The given value will be converted to string using the [`str()`](https://docs.godotengine.org/en/stable/classes/class_string.html) function. + +- **@param** `name` The name of the variable to edit. +- **@param** `value` The value to set the variable to. +- **@returns** The variable's value as string, or an empty string if not found. + + +### πŸ”Ά get_glossary + +```gdscript +get_glossary(name: String) +``` + +Gets the glossary data for the definition with the given name. + +Returned format: `{ title': '', 'text' : '', 'extra': '' }` + +- **@param** `name` The name of the glossary to find. +- **@returns** The glossary data as a Dictionary. A structure with empty strings is returned if the glossary was not found. + + +### πŸ”Ά set_glossary + +```gdscript +set_glossary(name: String, title: String, text: String, extra: String) +``` + +Sets the data for the glossary of the given name. + +Returned format: `{ title': '', 'text' : '', 'extra': '' }` + +- **@param** `name` The name of the glossary to edit. +- **@param** `title ` The title to show in the information box. +- **@param** `text` The text to show in the information box. +- **@param** `extra` The extra information at the bottom of the box. + + +### πŸ”Ά get_current_timeline + +```gdscript +get_current_timeline() +``` + +Gets the currently saved timeline. + +Timeline saves are set on timeline start, and cleared on end. This means you can keep track of timeline changes and detect when the dialog ends. -Sets the value associated to the given variable. Currently, only variable definitions can be set. +- **@returns** The current timeline filename, or an empty string if none was saved. -The given value will be converted to string using the [`str()`](https://docs.godotengine.org/en/stable/classes/class_string.html) function. -## FAQ +## ❔ FAQ ### πŸ”· How can I make a dialog show up in game? There are two ways of doing this; using gdscript or the scene editor. @@ -146,7 +279,7 @@ You probably can, but I have no idea how to πŸ˜“. If you know your way around C# --- -## Source structure +## 🌳 Source structure ### / (At the root level) `plugin.cgf` - The required file to be recognized by Godot. @@ -211,7 +344,7 @@ All icons are `.svg` files so they can scale nicely. I tried reusing many of the --- -## Credits +## ❀ Credits Code made by [Emilio Coppola](https://github.com/coppolaemilio). Contributors: [Toen](https://twitter.com/ToenAndreMC), Γ’scar, [Arnaud](https://github.com/arnaudvergnet), [and more!](https://github.com/coppolaemilio/dialogic/graphs/contributors) diff --git a/addons/dialogic/Nodes/dialog_node.gd b/addons/dialogic/Nodes/dialog_node.gd index 5fcb16d48..39fa0fc46 100644 --- a/addons/dialogic/Nodes/dialog_node.gd +++ b/addons/dialogic/Nodes/dialog_node.gd @@ -17,9 +17,13 @@ var settings var current_theme var current_timeline := '' +## The timeline to load when starting the scene export(String, "TimelineDropdown") var timeline: String +## Should we clear saved data (definitions and timeline progress) on start? export(bool) var reset_saves = true +## Should we show debug information when running? export(bool) var debug_mode = true + signal event_start(type, event) signal event_end(type) signal dialogic_signal(value) diff --git a/addons/dialogic/Other/DialogicClass.gd b/addons/dialogic/Other/DialogicClass.gd index 84d367fea..b8c7c88e4 100644 --- a/addons/dialogic/Other/DialogicClass.gd +++ b/addons/dialogic/Other/DialogicClass.gd @@ -1,17 +1,35 @@ extends Node -class_name Dialogic -# TODO save definitions on timeline end +## Exposed and safe to use methods for Dialogic +## See documentation here: +## https://github.com/coppolaemilio/dialogic -# Exposed and safe to use methods for Dialogic -# See documentation here: -# https://github.com/coppolaemilio/dialogic +## ### /!\ ### +## Do not use methods from other classes as it could break the plugin's integrity +## ### /!\ ### +## +## Trying to follow this documentation convention: https://github.com/godotengine/godot/pull/41095 +class_name Dialogic -# ### /!\ ### -# Do not use methods from other classes as it could break the plugin's integrity -# ### /!\ ### +## Starts the dialog for the given timeline and returns a Dialog node. +## You must then add it manually to the scene to display the dialog. +## +## Example: +## var new_dialog = Dialogic.start('Your Timeline Name Here') +## add_child(new_dialog) +## +## This is exactly the same as using the editor: +## you can drag and drop the scene located at /addons/dialogic/Dialog.tscn +## and set the current timeline via the inspector. +## +## @param timeline The timeline to load. You can provide the timeline name or the filename. +## @param reset_saves True to reset dialogic saved data such as definitions. +## @param dialog_scene_path If you made a custom Dialog scene or moved it from its default path, you can specify its new path here. +## @param debug_mode Debug is disabled by default but can be enabled if needed. +## @returns A Dialog node to be added into the scene tree. static func start(timeline: String, reset_saves: bool=true, dialog_scene_path: String="res://addons/dialogic/Dialog.tscn", debug_mode: bool=false): + var dialog: = load(dialog_scene_path) var d = dialog.instance() d.reset_saves = reset_saves @@ -28,44 +46,92 @@ static func start(timeline: String, reset_saves: bool=true, dialog_scene_path: S return d +## Same as the start method above, but using the last timeline saved. +## +## @param initial_timeline The timeline to load in case no save is found. +## @param dialog_scene_path If you made a custom Dialog scene or moved it from its default path, you can specify its new path here. +## @param debug_mode Debug is disabled by default but can be enabled if needed. +## @returns A Dialog node to be added into the scene tree. static func start_from_save(initial_timeline: String, dialog_scene_path: String="res://addons/dialogic/Dialog.tscn", debug_mode: bool=false): var current := get_current_timeline() if current.empty(): current = initial_timeline return start(current, false, dialog_scene_path, debug_mode) - +## Gets default values for definitions. +## +## @returns Dictionary in the format {'variables': [], 'glossary': []} static func get_default_definitions() -> Dictionary: return DialogicSingleton.get_default_definitions() +## Gets currently saved values for definitions. +## +## @returns Dictionary in the format {'variables': [], 'glossary': []} static func get_definitions() -> Dictionary: - return DialogicSingleton.get_default_definitions() + return DialogicSingleton.get_definitions() +## Save current definitions to the filesystem. +## Definitions are automatically saved on timeline start/end +## +## @returns Error status, OK if all went well func save_definitions(): return DialogicSingleton.save_definitions() +## Resets data to default values. This is the same as calling start with reset_saves to true func reset_saves(): - return DialogicSingleton.init(true) + DialogicSingleton.init(true) +## Gets the value for the variable with the given name. +## The returned value is a String but can be easily converted into a number +## using Godot built-in methods: +## [`is_valid_float`](https://docs.godotengine.org/en/stable/classes/class_string.html#class-string-method-is-valid-float) +## [`float()`](https://docs.godotengine.org/en/stable/classes/class_float.html#class-float-method-float). +## +## @param name The name of the variable to find. +## @returns The variable's value as string, or an empty string if not found. static func get_variable(name: String) -> String: return DialogicSingleton.get_variable(name) +## Sets the value for the variable with the given name. +## The given value will be converted to string using the +## [`str()`](https://docs.godotengine.org/en/stable/classes/class_string.html) function. +## +## @param name The name of the variable to edit. +## @param value The value of the variable to set. static func set_variable(name: String, value) -> void: DialogicSingleton.set_variable(name, value) +## Gets the glossary data for the definition with the given name. +## Returned format: +## { title': '', 'text' : '', 'extra': '' } +## +## @param name The name of the glossary to find. +## @returns The glossary data as a Dictionary. +## A structure with empty strings is returned if the glossary was not found. static func get_glossary(name: String) -> Dictionary: return DialogicSingleton.get_glossary(name) +## Sets the data for the glossary of the given name. +## +## @param name The name of the glossary to edit. +## @param title The title to show in the information box. +## @param text The text to show in the information box. +## @param extra The extra information at the bottom of the box. static func set_glossary(name: String, title: String, text: String, extra: String) -> void: DialogicSingleton.set_glossary(name, title, text, extra) +## Gets the currently saved timeline. +## Timeline saves are set on timeline start, and cleared on end. +## This means you can keep track of timeline changes and detect when the dialog ends. +## +## @returns The current timeline filename, or an empty string if none was saved. static func get_current_timeline() -> String: return DialogicSingleton.get_current_timeline() diff --git a/addons/dialogic/Other/DialogicResources.gd b/addons/dialogic/Other/DialogicResources.gd index 90044b35d..94a108a0c 100644 --- a/addons/dialogic/Other/DialogicResources.gd +++ b/addons/dialogic/Other/DialogicResources.gd @@ -192,9 +192,11 @@ static func remove_file(path: String): static func set_json(path: String, data: Dictionary): var file = File.new() - file.open(path, File.WRITE) - file.store_line(to_json(data)) - file.close() + var err = file.open(path, File.WRITE) + if err == OK: + file.store_line(to_json(data)) + file.close() + return err # TIMELINE