Compare commits

..

2 commits

Author SHA1 Message Date
658adfb766 Add first game demo 2021-03-25 22:47:09 +01:00
2fc0420194 update dialogic 2021-03-25 22:46:46 +01:00
65 changed files with 851 additions and 282 deletions

View file

@ -4,10 +4,14 @@ extends Node
# Called when the node enters the scene tree for the first time.
func _ready():
var new_dialog = Dialogic.start('timeline1')
var new_dialog = Dialogic.start('start')
add_child(new_dialog)
new_dialog.connect('dialogic_signal', self, "_on_Dialogic_signal_received")
new_dialog.connect('event_end', self, "_on_Dialogic_event_end")
func _on_Dialogic_signal_received(value: String):
print('received ' + value)
func _on_Dialogic_event_end(value: String):
print('event_end ' + value)

View file

@ -3,7 +3,7 @@ extends ScrollContainer
var editor_reference
onready var master_tree = get_node('../MasterTree')
var current_section = ''
var current_definition = null
onready var nodes = {
'name' : $VBoxContainer/HBoxContainer/VBoxContainer/Name,
@ -22,19 +22,19 @@ func _ready():
nodes['type'].connect('item_selected', self, '_on_type_selected')
func load_definition(section):
current_section = section
func load_definition(id):
current_definition = DialogicResources.get_default_definition_item(id)
reset_editor()
nodes['name'].editable = true
nodes['name'].text = get_definition('name', 'Unnamed')
var type = get_definition('type', 0)
nodes['name'].text = current_definition['name']
var type = current_definition['type']
nodes['type'].select(type)
if type == 0:
nodes['value'].text = get_definition('value', '')
nodes['value'].text = current_definition['value']
if type == 1:
nodes['extra_title'].text = get_definition('extra_title', '')
nodes['extra_text'].text = get_definition('extra_text', '')
nodes['extra_extra'].text = get_definition('extra_extra', '')
nodes['extra_title'].text = current_definition['title']
nodes['extra_text'].text = current_definition['text']
nodes['extra_extra'].text = current_definition['extra']
show_sub_editor(type)
@ -44,7 +44,10 @@ func reset_editor():
nodes['extra_title'].text = ''
nodes['extra_text'].text = ''
nodes['extra_extra'].text = ''
nodes['type'].select(get_definition('type', 0))
var type = 0
if current_definition != null:
type = current_definition['type']
nodes['type'].select(type)
func _on_name_changed(text):
@ -70,23 +73,16 @@ func show_sub_editor(type):
nodes['extra_editor'].visible = true
func get_definition(key: String, default):
if current_section != '':
return DialogicResources.get_default_definition_key(current_section, key, default)
else:
return default
func new_definition():
var section = DialogicUtil.generate_random_id()
DialogicResources.add_default_definition_variable(section, 'New definition', 0, '')
master_tree.add_definition({'section': section,'name': 'New definition', 'type': 0}, true)
var id = DialogicUtil.generate_random_id()
DialogicResources.set_default_definition_variable(id, 'New definition', '')
master_tree.add_definition({'id': id, 'name': 'New definition', 'type': 0}, true)
func save_definition():
if current_section != '':
if current_definition['id'] != '':
var type: int = nodes['type'].selected
if type == 0:
DialogicResources.set_default_definition_variable(current_section, nodes['name'].text, nodes['value'].text)
DialogicResources.set_default_definition_variable(current_definition['id'], nodes['name'].text, nodes['value'].text)
if type == 1:
DialogicResources.set_default_definition_glossary(current_section, nodes['name'].text, nodes['extra_title'].text, nodes['extra_text'].text, nodes['extra_extra'].text)
DialogicResources.set_default_definition_glossary(current_definition['id'], nodes['name'].text, nodes['extra_title'].text, nodes['extra_text'].text, nodes['extra_extra'].text)

View file

@ -67,9 +67,9 @@ func _on_TimelinePopupMenu_id_pressed(id):
func _on_RemoveTimelineConfirmation_confirmed():
var dir = Directory.new()
var target = $MainPanel/TimelineEditor.working_timeline_file
var target = $MainPanel/TimelineEditor.timeline_file
print('target: ', target)
dir.remove(target)
DialogicResources.delete_timeline(target)
$MainPanel/MasterTree.remove_selected()
$MainPanel/MasterTree.hide_all_editors(true)
@ -99,7 +99,7 @@ func _on_DefinitionPopupMenu_id_pressed(id):
func _on_RemoveDefinitionConfirmation_confirmed():
var target = $MainPanel/DefinitionEditor.current_section
var target = $MainPanel/DefinitionEditor.current_definition['id']
DialogicResources.delete_default_definition(target)
$MainPanel/MasterTree.remove_selected()
$MainPanel/MasterTree.hide_all_editors(true)
@ -114,7 +114,7 @@ func _on_RemoveCharacterConfirmation_confirmed():
func _on_RemoveThemeConfirmation_confirmed():
var filename = $MainPanel/MasterTree.get_selected().get_metadata(0)['file']
DialogicResources.delete_timeline(filename)
DialogicResources.delete_theme(filename)
$MainPanel/MasterTree.remove_selected()
$MainPanel/MasterTree.hide_all_editors(true)

View file

@ -69,7 +69,7 @@ func _ready():
add_character(c)
# Adding Definitions
for d in DialogicUtil.get_default_definition_list():
for d in DialogicUtil.get_default_definitions_list():
add_definition(d)
# Adding Themes
@ -155,7 +155,7 @@ func _on_item_selected():
character_editor.load_character(metadata['file'])
if metadata['editor'] == 'Definition':
definition_editor.visible = true
definition_editor.load_definition(metadata['section'])
definition_editor.load_definition(metadata['id'])
if metadata['editor'] == 'Theme':
theme_editor.load_theme(metadata['file'])
theme_editor.visible = true

View file

@ -12,13 +12,12 @@ func _ready():
func _on_MenuButton_about_to_show():
get_popup().clear()
var index = 0
for d in DialogicUtil.get_default_definition_list():
if d['type'] == 0:
get_popup().add_item(d['name'])
get_popup().set_item_metadata(index, {
'section': d['section'],
})
index += 1
for d in DialogicResources.get_default_definitions()['variables']:
get_popup().add_item(d['name'])
get_popup().set_item_metadata(index, {
'id': d['id'],
})
index += 1
func _on_entry_selected(index):
@ -27,10 +26,10 @@ func _on_entry_selected(index):
text = _text
func load_definition(section):
if section != '':
for d in DialogicUtil.get_default_definition_list():
if d['section'] == section:
func load_definition(id):
if id != '':
for d in DialogicResources.get_default_definitions()['variables']:
if d['id'] == id:
text = d['name']
else:
text = default_text

View file

@ -36,7 +36,7 @@ func load_data(data):
func _on_definition_entry_selected(index):
var metadata = nodes['definition_picker'].get_popup().get_item_metadata(index)
event_data['definition'] = metadata['section']
event_data['definition'] = metadata['id']
func _on_condition_entry_selected(index):

View file

@ -21,7 +21,7 @@ func _ready():
func _on_definition_entry_selected(index):
var metadata = nodes['definition_picker'].get_popup().get_item_metadata(index)
event_data['definition'] = metadata['section']
event_data['definition'] = metadata['id']
func load_data(data):

View file

@ -323,4 +323,4 @@ func _on_Alignment_item_selected(index):
func _on_Preview_text_changed():
DialogicUtil.set_theme_value(current_theme, 'text', 'preview', n['text_preview'].text)
DialogicResources.set_theme_value(current_theme, 'text', 'preview', n['text_preview'].text)

View file

@ -10,15 +10,20 @@ var waiting_for_answer: bool = false
var waiting_for_input: bool = false
var waiting = false
var preview = false
var definitions
var definitions = {}
var definition_visible = false
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)
@ -35,13 +40,15 @@ func _ready():
# Loading the config files
load_config_files()
# Make sure saves are ready
DialogicResources.init_definitions_saves(reset_saves)
# Checking if the dialog should read the code from a external file
if timeline != '':
dialog_script = set_current_dialog(timeline + '.json')
if not timeline.empty():
dialog_script = set_current_dialog(timeline)
elif dialog_script.keys().size() == 0:
dialog_script = {
"events":[{"character":"","portrait":"",
"text":"[Dialogic Error] No timeline specified."}]
}
# Connecting resize signal
get_viewport().connect("size_changed", self, "resize_main")
resize_main()
@ -55,12 +62,17 @@ func _ready():
# Getting the character information
characters = DialogicUtil.get_character_list()
if Engine.is_editor_hint() == false:
if not Engine.is_editor_hint():
load_dialog()
func load_config_files():
definitions = DialogicUtil.get_definition_list()
if not Engine.is_editor_hint():
# Make sure saves are ready
DialogicSingleton.init(reset_saves)
definitions = DialogicSingleton.get_definitions()
else:
definitions = DialogicResources.get_default_definitions()
settings = DialogicResources.get_settings_config()
var theme_file = 'res://addons/dialogic/Editor/ThemeEditor/default-theme.cfg'
if settings.has_section('theme'):
@ -80,7 +92,8 @@ func resize_main():
$TextBubble.rect_position.y = (rect_size.y) - ($TextBubble.rect_size.y) - current_theme.get_value('box', 'bottom_gap', 40)
func set_current_dialog(dialog_path):
func set_current_dialog(dialog_path: String):
current_timeline = dialog_path
var dialog_script = DialogicResources.get_timeline_json(dialog_path)
# All this parse events should be happening in the same loop ideally
# But until performance is not an issue I will probably stay lazy
@ -217,7 +230,6 @@ func parse_branches(dialog_script: Dictionary) -> Dictionary:
func parse_definitions(text: String):
var words = []
var definition_list = DialogicUtil.get_definition_list()
if Engine.is_editor_hint():
# Loading variables again to avoid issues in the preview dialog
load_config_files()
@ -229,11 +241,9 @@ func parse_definitions(text: String):
func _insert_variable_definitions(text: String):
var final_text := text;
for d in definitions:
if d['type'] == 0:
var name : String = d['name'];
var value = DialogicUtil.get_var(name)
final_text = final_text.replace('[' + name + ']', value)
for d in definitions['variables']:
var name : String = d['name'];
final_text = final_text.replace('[' + name + ']', d['value'])
return final_text;
@ -241,13 +251,12 @@ func _insert_glossary_definitions(text: String):
var color = self.current_theme.get_value('definitions', 'color', '#ffbebebe')
var final_text := text;
# I should use regex here, but this is way easier :)
for d in definitions:
if d['type'] == 1:
final_text = final_text.replace(d['name'],
'[url=' + d['section'] + ']' +
'[color=' + color + ']' + d['name'] + '[/color]' +
'[/url]'
)
for d in definitions['glossary']:
final_text = final_text.replace(d['name'],
'[url=' + d['id'] + ']' +
'[color=' + color + ']' + d['name'] + '[/color]' +
'[/url]'
)
return final_text;
@ -309,13 +318,26 @@ func update_text(text):
return true
func on_timeline_start():
if not Engine.is_editor_hint():
DialogicSingleton.save_definitions()
DialogicSingleton.set_current_timeline(current_timeline)
emit_signal("event_start", "timeline", current_timeline)
func on_timeline_end():
if not Engine.is_editor_hint():
DialogicSingleton.save_definitions()
DialogicSingleton.set_current_timeline('')
emit_signal("event_end", "timeline")
func load_dialog(skip_add = false):
# Emitting signals
if dialog_script.has('events'):
if dialog_index == 0:
emit_signal("event_start", "timeline", timeline)
on_timeline_start()
elif dialog_index == dialog_script['events'].size():
emit_signal("event_end", "timeline")
on_timeline_end()
# Hiding definitions popup
definition_visible = false
@ -346,8 +368,6 @@ func get_character(character_id):
func event_handler(event: Dictionary):
# Handling an event and updating the available nodes accordingly.
reset_dialog_extras()
# Updating the settings and definitions in case that they were modified by a timelien
load_config_files()
dprint('[D] Current Event: ', event)
match event:
@ -440,6 +460,7 @@ func event_handler(event: Dictionary):
go_to_next_event()
{'close_dialog'}:
emit_signal("event_start", "close_dialog", event)
on_timeline_end()
queue_free()
{'set_theme'}:
emit_signal("event_start", "set_theme", event)
@ -458,11 +479,12 @@ func event_handler(event: Dictionary):
# Treating this conditional as an option on a regular question event
var def_value = null
var current_question = questions[event['question_id']]
for d in definitions:
if d['section'] == event['definition']:
def_value = DialogicUtil.get_var(d['name'])
var condition_met = self._compare_definitions(def_value, event['value'], event['condition']);
for d in definitions['variables']:
if d['id'] == event['definition']:
def_value = d['value']
var condition_met = def_value != null and _compare_definitions(def_value, event['value'], event['condition']);
current_question['answered'] = !condition_met
if !condition_met:
@ -474,7 +496,7 @@ func event_handler(event: Dictionary):
go_to_next_event()
{'set_value', 'definition'}:
emit_signal("event_start", "set_value", event)
DialogicResources.set_saved_definition_variable_value(event['definition'], event['set_value'])
DialogicSingleton.set_variable_from_id(event['definition'], event['set_value'])
go_to_next_event()
_:
visible = false
@ -570,7 +592,6 @@ func _on_option_selected(option, variable, value):
waiting_for_answer = false
reset_options()
load_dialog()
#print(dialog_resource.custom_variables)
dprint('[!] Option selected: ', option.text, ' value= ' , value)
@ -684,17 +705,16 @@ func load_theme(filename):
func _on_RichTextLabel_meta_hover_started(meta):
var correct_type = false
for d in definitions:
if d['section'] == meta:
if d['type'] == 1:
$DefinitionInfo.load_preview({
'title': d['config'].get_value(d['section'], 'extra_title', ''),
'body': d['config'].get_value(d['section'], 'extra_text', ''),
'extra': d['config'].get_value(d['section'], 'extra_extra', ''),
'color': current_theme.get_value('definitions', 'color', '#ffbebebe'),
})
correct_type = true
print(d)
for d in definitions['glossary']:
if d['id'] == meta:
$DefinitionInfo.load_preview({
'title': d['title'],
'body': d['text'],
'extra': d['extra'],
'color': current_theme.get_value('definitions', 'color', '#ffbebebe'),
})
correct_type = true
print(d)
if correct_type:
definition_visible = true

View file

@ -1,29 +1,137 @@
extends Node
## 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
static func start(timeline: String, dialog_scene_path: String="res://addons/dialogic/Dialog.tscn", debug_mode: bool=false):
var dialog = load(dialog_scene_path)
## 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
d.debug_mode = debug_mode
for t in DialogicUtil.get_timeline_list():
if t['name'] == timeline:
d.timeline = t['file'].replace('.json', '')
return d
d.dialog_script = {
"events":[{"character":"","portrait":"",
"text":"[Dialogic Error] Loading dialog [color=red]" + timeline + "[/color]. It seems like the timeline doesn't exists. Maybe the name is wrong?"}]
}
if not timeline.empty():
for t in DialogicUtil.get_timeline_list():
if t['name'] == timeline or t['file'] == timeline:
d.timeline = t['file']
return d
d.dialog_script = {
"events":[{"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 d
static func reset_saves():
DialogicResources.init_definitions_saves(true)
## 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()
static func get_var(variable: String):
return DialogicUtil.get_var(variable)
## Gets currently saved values for definitions.
##
## @returns Dictionary in the format {'variables': [], 'glossary': []}
static func get_definitions() -> Dictionary:
return DialogicSingleton.get_definitions()
static func set_var(variable: String, value):
DialogicUtil.set_var(variable, value)
## 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():
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()

View file

@ -0,0 +1,71 @@
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']

View file

@ -6,24 +6,26 @@ 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) -> Dictionary:
static func load_json(path: String, default: Dictionary={}) -> Dictionary:
# An easy function to load json files and handle common errors.
var file:File = File.new()
var file := File.new()
if file.open(path, File.READ) != OK:
file.close()
return {'error':'file read error'}
return default
var data_text: String = file.get_as_text()
file.close()
var data_parse:JSONParseResult = JSON.parse(data_text)
if data_text.empty():
return default
var data_parse: JSONParseResult = JSON.parse(data_text)
if data_parse.error != OK:
return {'error':'data parse error'}
return default
var final_data = data_parse.result
if typeof(final_data) == TYPE_DICTIONARY:
return final_data
# If everything else fails
return {'error':'data parse error'}
return default
static func init_dialogic_files() -> void:
@ -57,43 +59,68 @@ static func get_working_directories() -> Dictionary:
static func get_config_files_paths() -> Dictionary:
return {
'SETTINGS_FILE': RESOURCES_DIR + "/settings.cfg",
'DEFAULT_DEFINITIONS_FILE': RESOURCES_DIR + "/definitions.cfg",
'SAVED_DEFINITIONS_FILE': WORKING_DIR + "/definitions.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(overwrite: bool=true):
var err = init_working_dir()
var paths := get_config_files_paths()
if err == OK:
init_state_saves(overwrite)
init_definitions_saves(overwrite)
else:
print('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(overwrite: bool=true):
var file := File.new()
var paths := get_config_files_paths()
if not file.file_exists(paths["SAVED_STATE_FILE"]) or overwrite:
var err = file.open(paths["SAVED_STATE_FILE"], File.WRITE)
if err == OK:
file.store_string('')
file.close()
else:
print('Error opening saved state file: ' + str(err))
static func init_definitions_saves(overwrite: bool=true):
var directory := Directory.new()
var source := File.new()
var sink := File.new()
var paths := get_config_files_paths()
var err := directory.make_dir_recursive(get_working_directories()['WORKING_DIR'])
if err == OK:
if not directory.file_exists(paths["SAVED_DEFINITIONS_FILE"]):
err = sink.open(paths["SAVED_DEFINITIONS_FILE"], File.WRITE)
print('Saved definitions not present, creating file: ' + str(err))
if err == OK:
sink.store_string('')
sink.close()
else:
print('Error opening saved definitions file: ' + str(err))
err = sink.open(paths["SAVED_DEFINITIONS_FILE"], File.READ_WRITE)
var err
if not directory.file_exists(paths["SAVED_DEFINITIONS_FILE"]):
err = sink.open(paths["SAVED_DEFINITIONS_FILE"], File.WRITE)
print('Saved definitions not present, creating file: ' + str(err))
if err == OK:
if overwrite or sink.get_len() == 0:
err = source.open(paths["DEFAULT_DEFINITIONS_FILE"], File.READ)
if err == OK:
sink.store_string(source.get_as_text())
else:
print('Error opening default definitions file: ' + str(err))
else:
print('Did not overwrite previous saved definitions')
sink.store_string('')
sink.close()
else:
print('Error opening saved definitions file: ' + str(err))
err = sink.open(paths["SAVED_DEFINITIONS_FILE"], File.READ_WRITE)
if err == OK:
if overwrite or sink.get_len() == 0:
err = source.open(paths["DEFAULT_DEFINITIONS_FILE"], File.READ)
if err == OK:
sink.store_string(source.get_as_text())
else:
print('Error opening default definitions file: ' + str(err))
else:
print('Did not overwrite previous saved definitions')
else:
print('Error creating working directory: ' + str(err))
print('Error opening saved definitions file: ' + str(err))
source.close()
sink.close()
@ -163,30 +190,26 @@ static func remove_file(path: String):
# JSON UTIL
static func get_json(dir_id: String, path: String):
return load_json(get_path(dir_id, path))
static func set_json(dir_id: String, path: String, data: Dictionary):
var directory = Directory.new()
var base_path := get_path(dir_id)
if not directory.dir_exists(base_path):
directory.make_dir_recursive(base_path)
static func set_json(path: String, data: Dictionary):
var file = File.new()
file.open(get_path(dir_id, 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
# Can only be edited in the editor
static func get_timeline_json(path: String):
return get_json('TIMELINE_DIR', path)
return load_json(get_path('TIMELINE_DIR', path))
static func set_timeline(timeline: Dictionary):
# WARNING: For use in the editor only
set_json('TIMELINE_DIR', timeline['metadata']['file'], timeline)
set_json(get_path('TIMELINE_DIR', timeline['metadata']['file']), timeline)
static func delete_timeline(filename: String):
@ -195,15 +218,16 @@ static func delete_timeline(filename: String):
# CHARACTER
# Can only be edited in the editor
static func get_character_json(path: String):
return get_json('CHAR_DIR', path)
return load_json(get_path('CHAR_DIR', path))
static func set_character(character: Dictionary):
# WARNING: For use in the editor only
set_json('CHAR_DIR', character['id'], character)
set_json(get_path('CHAR_DIR', character['id']), character)
static func delete_character(filename: String):
@ -212,6 +236,7 @@ static func delete_character(filename: String):
# THEME
# Can only be edited in the editor
static func get_theme_config(filename: String):
@ -228,8 +253,6 @@ static func get_theme_config(filename: String):
static func set_theme_value(filename, section, key, value):
# WARNING: For use in the editor only
print('=> theme update')
print(filename)
var config = get_theme_config(filename)
config.set_value(section, key, value)
config.save(get_path('THEME_DIR', filename))
@ -239,10 +262,14 @@ 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))
# SETTINGS
# Can only be edited in the editor
static func get_settings_config():
static func get_settings_config() -> ConfigFile:
return get_config("SETTINGS_FILE")
@ -252,98 +279,76 @@ static func set_settings_value(section: String, key: String, value):
config.save(get_config_files_paths()['SETTINGS_FILE'])
# DEFINITIONS UTIL
# used by default and saved definitions
# STATE
static func get_definition_key(config_id: String, section: String, key: String, default):
var config = get_config(config_id)
if config.has_section(section):
return config.get_value(section, key, default)
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):
set_json(get_config_files_paths()['SAVED_STATE_FILE'], data)
static func get_saved_state_general_key(key: String) -> String:
var data = get_saved_state()
if key in data['general'].keys():
return data['general'][key]
else:
return default
return ''
static func set_definition_variable(config_id: String, section: String, name: String, value):
var config = get_config(config_id)
config.set_value(section, 'name', name)
config.set_value(section, 'type', 0)
config.set_value(section, 'value', str(value))
return config.save(get_config_files_paths()[config_id])
static func set_definition_glossary(config_id: String, section: String, name: String, extra_title: String, extra_text: String, extra_extra: String):
var config = get_config(config_id)
config.set_value(section, 'name', name)
config.set_value(section, 'type', 1)
config.set_value(section, 'extra_title', extra_title)
config.set_value(section, 'extra_text', extra_text)
config.set_value(section, 'extra_extra', extra_extra)
return config.save(get_config_files_paths()[config_id])
static func add_definition_variable(config_id: String, section: String, name: String, type: int, value):
var config = get_config(config_id)
config.set_value(section, 'name', name)
config.set_value(section, 'type', type)
config.set_value(section, 'value', str(value))
return config.save(get_config_files_paths()[config_id])
static func delete_definition(config_id: String, section: String):
var config = get_config(config_id)
config.erase_section(section)
return config.save(get_config_files_paths()[config_id])
static func set_saved_state_general_key(key: String, value):
var data = get_saved_state()
data['general'][key] = str(value)
save_saved_state_config(data)
# DEFAULT DEFINITIONS
# Can only be edited in the editor
static func get_default_definitions_config():
return get_config('DEFAULT_DEFINITIONS_FILE')
static func get_default_definitions() -> Dictionary:
return load_json(get_config_files_paths()['DEFAULT_DEFINITIONS_FILE'], {'variables': [], 'glossary': []})
static func get_default_definition_key(section: String, key: String, default):
return get_definition_key('DEFAULT_DEFINITIONS_FILE', section, key, default)
static func save_default_definitions(data: Dictionary):
set_json(get_config_files_paths()['DEFAULT_DEFINITIONS_FILE'], data)
static func set_default_definition_variable(section: String, name: String, value):
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
return set_definition_variable('DEFAULT_DEFINITIONS_FILE', section, name, value)
var data = get_default_definitions()
DialogicDefinitionsUtil.set_definition_variable(data, id, name, value)
save_default_definitions(data)
static func set_default_definition_glossary(section: String, name: String, extra_title: String, extra_text: String, extra_extra: String):
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
return set_definition_glossary('DEFAULT_DEFINITIONS_FILE', section, name, extra_title, extra_text, extra_extra)
var data = get_default_definitions()
DialogicDefinitionsUtil.set_definition_glossary(data, id, name, extra_title, extra_text, extra_extra)
save_default_definitions(data)
static func add_default_definition_variable(section: String, name: String, type: int, value):
static func delete_default_definition(id: String):
# WARNING: For use in the editor only
return add_definition_variable('DEFAULT_DEFINITIONS_FILE', section, name, type, value)
static func delete_default_definition(section: String):
# WARNING: For use in the editor only
return delete_definition('DEFAULT_DEFINITIONS_FILE', section)
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_config():
return get_config("SAVED_DEFINITIONS_FILE")
static func get_saved_definitions() -> Dictionary:
return load_json(get_config_files_paths()['SAVED_DEFINITIONS_FILE'], {'variables': [], 'glossary': []})
static func set_saved_definition_variable(section: String, name: String, value):
return set_definition_variable('SAVED_DEFINITIONS_FILE', section, name, value)
static func set_saved_definition_variable_value(section: String, value):
var config = get_saved_definitions_config()
return set_definition_variable('SAVED_DEFINITIONS_FILE', section, config.get_value(section, 'name', section), value)
static func set_saved_definition_glossary(section: String, name: String, extra_title: String, extra_text: String, extra_extra: String):
return set_definition_glossary('SAVED_DEFINITIONS_FILE', section, name, extra_title, extra_text, extra_extra)
static func save_saved_definitions(data: Dictionary):
return set_json(get_config_files_paths()['SAVED_DEFINITIONS_FILE'], data)

View file

@ -0,0 +1,86 @@
extends Node
var current_definitions := {}
var default_definitions := {}
var current_timeline := ''
func _init() -> void:
init(false)
func init(reset: bool=false) -> void:
# Loads saved definitions into memory
DialogicResources.init_saves(reset)
current_definitions = DialogicResources.get_saved_definitions()
default_definitions = DialogicResources.get_default_definitions()
current_timeline = DialogicResources.get_saved_state_general_key('timeline')
func get_definitions_list() -> Array:
return DialogicDefinitionsUtil.definitions_json_to_array(current_definitions)
func get_definitions() -> Dictionary:
return current_definitions
func get_default_definitions() -> Dictionary:
return default_definitions
func get_default_definitions_list() -> Array:
return DialogicDefinitionsUtil.definitions_json_to_array(default_definitions)
func save_definitions():
return DialogicResources.save_saved_definitions(current_definitions)
func get_variable(name: String) -> String:
for d in current_definitions['variables']:
if d['name'] == name:
return d['value']
return ''
func set_variable(name: String, value) -> void:
for d in current_definitions['variables']:
if d['name'] == name:
d['value'] = str(value)
func set_variable_from_id(id: String, value) -> void:
for d in current_definitions['variables']:
if d['id'] == id:
d['value'] = str(value)
func get_glossary(name: String) -> Dictionary:
for d in current_definitions['glossary']:
if d['name'] == name:
return d
return {
'title': '',
'text': '',
'extra': ''
}
func set_glossary(name: String, title: String, text: String, extra: String) -> void:
for d in current_definitions['glossary']:
if d['name'] == name:
d['title'] = title
d['text'] = text
d['extra'] = extra
func set_current_timeline(timeline: String):
current_timeline = timeline
DialogicResources.set_saved_state_general_key('timeline', timeline)
func get_current_timeline() -> String:
return current_timeline

View file

@ -68,43 +68,8 @@ static func get_theme_list() -> Array:
return themes
static func get_default_definition_list() -> Array:
var definitions: Array = []
var config = DialogicResources.get_default_definitions_config()
for section in config.get_sections():
definitions.append({
'section': section,
'name': config.get_value(section, 'name', section),
'config': config,
'type': config.get_value(section, 'type', 0),
})
return definitions
static func get_definition_list() -> Array:
var definitions: Array = []
var config = DialogicResources.get_saved_definitions_config()
for section in config.get_sections():
definitions.append({
'section': section,
'name': config.get_value(section, 'name', section),
'config': config,
'type': config.get_value(section, 'type', 0),
})
return definitions
static func get_var(variable: String) -> String:
for d in get_definition_list():
if d['name'] == variable:
return d['config'].get_value(d['section'], 'value')
return ''
static func set_var(variable: String, value) -> void:
for d in get_definition_list():
if d['name'] == variable:
DialogicResources.set_saved_definition_variable(d['section'], d['name'], value)
static func get_default_definitions_list() -> Array:
return DialogicDefinitionsUtil.definitions_json_to_array(DialogicResources.get_default_definitions())
static func generate_random_id() -> String:

View file

@ -36,7 +36,7 @@ func _about_to_show_menu():
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'].replace('.json', '')
current_value = metadata['file']
timelines_dropdown.text = text
emit_changed(get_edited_property(), current_value)
@ -52,6 +52,6 @@ func update_property():
current_value = new_value
# Checking for the display name
for c in DialogicUtil.get_timeline_list():
if c['file'].replace('.json', '') == current_value:
if c['file'] == current_value:
timelines_dropdown.text = c['name']
updating = false

View file

@ -4,6 +4,13 @@ extends EditorPlugin
var _editor_view
var _parts_inspector
func _init():
if Engine.editor_hint:
# Make sure the core files exist
DialogicResources.init_dialogic_files()
add_autoload_singleton('DialogicSingleton', "res://addons/dialogic/Other/DialogicSingleton.gd")
func _enter_tree() -> void:
_parts_inspector = load("res://addons/dialogic/Other/inspector_timeline_picker.gd").new()
add_inspector_plugin(_parts_inspector)
@ -14,8 +21,6 @@ func _enter_tree() -> void:
func _ready():
if Engine.editor_hint:
# Make sure the core files exist
DialogicResources.init_dialogic_files()
# Force Godot to show the dialogic folder
get_editor_interface().get_resource_filesystem().scan()

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

View file

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/office_background.jpg-42bc677e065caec0aeab01b8e18c8700.stex"
path="res://.import/bureauGroupe-1.jpg-0dc405592548e966b13d86dd866638b8.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://backgrounds/office_background.jpg"
dest_files=[ "res://.import/office_background.jpg-42bc677e065caec0aeab01b8e18c8700.stex" ]
source_file="res://backgrounds/bureauGroupe-1.jpg"
dest_files=[ "res://.import/bureauGroupe-1.jpg-0dc405592548e966b13d86dd866638b8.stex" ]
[params]

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/bureauGroupe-2.jpg-f67d7630d95f3b61812b59646045a0e0.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://backgrounds/bureauGroupe-2.jpg"
dest_files=[ "res://.import/bureauGroupe-2.jpg-f67d7630d95f3b61812b59646045a0e0.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
backgrounds/bureauPerso.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/bureauPerso.jpg-5ec35b1af2f96c3601d568f7387fc5af.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://backgrounds/bureauPerso.jpg"
dest_files=[ "res://.import/bureauPerso.jpg-5ec35b1af2f96c3601d568f7387fc5af.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
backgrounds/coffeeRoom.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/coffeeRoom.jpg-44880b917a2f8a0fb5af3c9cca393fbf.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://backgrounds/coffeeRoom.jpg"
dest_files=[ "res://.import/coffeeRoom.jpg-44880b917a2f8a0fb5af3c9cca393fbf.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
backgrounds/meetingRoom.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/meetingRoom.jpg-500810c5ffda23e06c2191b203ebbac5.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://backgrounds/meetingRoom.jpg"
dest_files=[ "res://.import/meetingRoom.jpg-500810c5ffda23e06c2191b203ebbac5.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

BIN
characters/evelyne.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/evelyne.png-e623fd09067e06fb5b240164e28ba4ed.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://characters/evelyne.png"
dest_files=[ "res://.import/evelyne.png-e623fd09067e06fb5b240164e28ba4ed.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
characters/jean-michel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/jean-michel.png-b22b3a757f0e52ef000ed620f76bd814.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://characters/jean-michel.png"
dest_files=[ "res://.import/jean-michel.png-b22b3a757f0e52ef000ed620f76bd814.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
characters/mail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -2,15 +2,15 @@
importer="texture"
type="StreamTexture"
path="res://.import/df-2.png-1f29f4d1e6a1f1242da97614da8b7f6c.stex"
path="res://.import/mail.png-9bbff9b311755a12e665ccac1f3b6424.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://characters/df-2.png"
dest_files=[ "res://.import/df-2.png-1f29f4d1e6a1f1242da97614da8b7f6c.stex" ]
source_file="res://characters/mail.png"
dest_files=[ "res://.import/mail.png-9bbff9b311755a12e665ccac1f3b6424.stex" ]
[params]

View file

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/patrick.png-c4707025251b6341b4d90d043c7d9382.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://characters/patrick.png"
dest_files=[ "res://.import/patrick.png-c4707025251b6341b4d90d043c7d9382.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

BIN
characters/phone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View file

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/phone.png-99c235d679d5ec7af25c62aa3b85e727.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://characters/phone.png"
dest_files=[ "res://.import/phone.png-99c235d679d5ec7af25c62aa3b85e727.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=0
flags/filter=true
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
stream=false
size_limit=0
detect_3d=true
svg/scale=1.0

View file

@ -1 +0,0 @@
{"color":"#ffbe1616","default_speaker":true,"description":"","display_name":"","display_name_bool":false,"id":"character-1615932195.json","name":"Test","offset_x":0,"offset_y":0,"portraits":[{"name":"Default","path":"res://characters/df-2.png"}],"scale":100}

View file

@ -0,0 +1 @@
{"color":"#ffffffff","default_speaker":false,"description":"C'est moi","display_name":"","display_name_bool":false,"id":"character-1616658355.json","name":"Moi","offset_x":0,"offset_y":0,"portraits":[{"name":"Default","path":""}],"scale":100}

View file

@ -0,0 +1 @@
{"color":"#ff488f39","default_speaker":false,"description":"L'écolo","display_name":"","display_name_bool":false,"id":"character-1616658373.json","name":"Evelyne","offset_x":0,"offset_y":200,"portraits":[{"name":"Default","path":"res://characters/evelyne.png"}],"scale":30}

View file

@ -0,0 +1 @@
{"color":"#ffbaa324","default_speaker":false,"description":"capitalistos <3 moula","display_name":"","display_name_bool":false,"id":"character-1616658403.json","name":"Jean-Michel","offset_x":0,"offset_y":250,"portraits":[{"name":"Default","path":"res://characters/jean-michel.png"}],"scale":100}

View file

@ -0,0 +1 @@
{"color":"#ff929292","default_speaker":false,"description":"neutre, sans valeur ajoutée, suisse mais pas sur","display_name":"","display_name_bool":false,"id":"character-1616658435.json","name":"Patrick","offset_x":0,"offset_y":100,"portraits":[{"name":"Default","path":"res://characters/patrick.png"}],"scale":100}

View file

@ -0,0 +1 @@
{"color":"#ff1b2f99","default_speaker":false,"description":"bip bip nouveau mail","display_name":"","display_name_bool":false,"id":"character-1616658471.json","name":"Mail","offset_x":0,"offset_y":100,"portraits":[{"name":"Default","path":"res://characters/mail.png"}],"scale":100}

View file

@ -0,0 +1 @@
{"color":"#ff07b99c","default_speaker":false,"description":"Les notifications de partout","display_name":"","display_name_bool":false,"id":"character-1616660196.json","name":"Téléphone","offset_x":0,"offset_y":200,"portraits":[{"name":"Default","path":"res://characters/phone.png"}],"scale":100}

View file

@ -1,8 +0,0 @@
[1615930196-648]
name="Hello"
type=1
value=""
extra_title="Hello"
extra_text="When you say hi"
extra_extra=""

View file

@ -0,0 +1 @@
{"glossary":[],"variables":[{"id":"1616657225-648","name":"tel_ouvert","type":0,"value":"0"}]}

View file

@ -1,3 +1,3 @@
[theme]
default="theme-1615930210.cfg"
default="theme-1616657657.cfg"

View file

@ -5,3 +5,8 @@ size=Vector2( 910, 167 )
[text]
margin=Vector2( 20, 10 )
color="#ffd11515"
[settings]
name="theme_questions"

View file

@ -0,0 +1,9 @@
[settings]
name="theme_normal"
[buttons]
use_background_color=false
background_color="#ff3c7c11"
text_color="#ff30c3f0"

View file

@ -1 +0,0 @@
{"events":[{"background":"res://backgrounds/office_background.jpg"},{"action":"join","character":"character-1615932195.json","portrait":"","position":{"0":false,"1":true,"2":false,"3":false,"4":false}},{"character":"character-1615932195.json","portrait":"","text":"Hello"},{"character":"character-1615932195.json","portrait":"happy","text":"Hi"},{"character":"character-1615932195.json","portrait":"","text":"Bye"},{"action":"leaveall","character":"[All]"},{"wait_seconds":1},{"close_dialog":""}],"metadata":{"dialogic-version":"1.0","file":"timeline-1615930166.json","name":"timeline1"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/bureauGroupe-2.jpg"},{"set_theme":"theme-1616657657.cfg"},{"options":[],"question":"Il est 10 heures, ce ne serait pas l'heure de la pause ?"},{"choice":"oui, j'ai soif !"},{"choice":"un petit café ne me ferait pas de mal"},{"choice":"Je vais voir mes merveilleux collègues !"},{"endbranch":""},{"change_timeline":"timeline-1616657347.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616656510.json","name":"question-cafe"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/coffeeRoom.jpg"},{"action":"join","character":"character-1616658373.json","portrait":"","position":{"0":false,"1":true,"2":false,"3":false,"4":false}},{"character":"","portrait":"","text":"Vous arrivez à la machine à café, Evelyne est déjà là"},{"definition":"1616657225-648","set_value":"5"},{"emit_signal":"value increment 10"},{"character":"character-1616658373.json","portrait":"","text":"Coucou !\nMoi cest Evelyne, je suis dans ton service!\nJai hâte de travailler avec toi, nous allons faire de belles choses ensemble !\nJai entendu que le boss tavais mis sur le projet du nouveau téléphone.\nCest un gros projet pour commencer."},{"character":"character-1616658355.json","portrait":"","text":"Ouais cest super mais ça me met la pression.\nEn plus je dois essayer de me démarquer des téléphones des autres entreprises en ajoutant de nouvelles fonctionnalités."},{"character":"character-1616658373.json","portrait":"","text":"Justement je voulais te parler dun truc que jai en tête depuis un moment, je nai jamais eu loccasion de le mettre en application, mais ton projet est parfait pour ça.\nAs-tu déjà entendu parlé du recyclage de pièces de téléphone ?"},{"options":[],"question":"Le recyclage, ça vous dit quelquechose ?"},{"choice":"Très brièvement…"},{"choice":"On m'en a parlé un peu"},{"character":"character-1616658355.json","portrait":"","text":"Quelquun men a parlé il y a longtemps mais je ne men souviens pas vraiment … "},{"endbranch":""},{"character":"character-1616658373.json","portrait":"","text":"En gros, contrairement aux derniers modèles de téléphones, le principe est que ton téléphone est démontable.\nDu coup, si tu as un problème sur une certaine pièce, comme la batterie, tu peux simplement la changer.\nÇa évite de devoir faire réparer ton téléphone entier ou den racheter un nouveau.\nTu peux imaginer léconomie que tu fais non seulement pour ton porte-monnaie, mais aussi pour la planète.\nSi tu lappliques pour ton projet ça permettrait de donner une image éco-responsable de lentreprise mais aussi de te démarquer de toutes ces marques qui poussent à la surconsommation."},{"options":[],"question":"Qu'en pensez vous ?"},{"choice":"Cest vrai que cest intéressant je vais y réfléchir!"},{"character":"character-1616658373.json","portrait":"","text":"Super !"},{"choice":"Mouais…"},{"character":"character-1616658373.json","portrait":"","text":"Réfléchis-y, c'est important !"},{"endbranch":""},{"character":"character-1616658373.json","portrait":"","text":"Bon courage et à une prochaine pause café !"},{"action":"leaveall","character":"[All]"},{"wait_seconds":0},{"change_timeline":"timeline-1616659153.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616657347.json","name":"info-evelyne"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/bureauGroupe-2.jpg"},{"character":"","portrait":"","text":"Vous vous dirigez vers votre bureau"},{"action":"join","character":"character-1616658435.json","portrait":"","position":{"0":false,"1":false,"2":false,"3":true,"4":false}},{"character":"character-1616658435.json","portrait":"","text":"Salut toi ! Bienvenue parmi nous. Tu viens doù mon ami ?"},{"character":"character-1616658355.json","portrait":"","text":"Oh rien doriginal je viens de région parisienne et toi ?"},{"character":"character-1616658435.json","portrait":"","text":"Alors … Cest compliqué … Je crois que je suis suisse."},{"character":"character-1616658355.json","portrait":"","text":"Tu crois ?"},{"character":"character-1616658435.json","portrait":"","text":"Je ne suis pas sûr … Bisous ! Bienvenue parmi nous"},{"action":"leaveall","character":"[All]"},{"change_timeline":"timeline-1616659608.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616659153.json","name":"merde-patrick-1"}}

View file

@ -0,0 +1 @@
{"events":[{"change_timeline":"timeline-1616656510.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616659306.json","name":"start"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/bureauPerso.jpg"},{"character":"","portrait":"","text":"Vous arrivez à votre bureau."},{"action":"join","character":"character-1616658471.json","portrait":"","position":{"0":false,"1":false,"2":true,"3":false,"4":false}},{"character":"","portrait":"","text":"Vous avez reçu un mail du Boss !"},{"options":[],"question":"Le lire ?"},{"choice":"oui"},{"choice":"non"},{"character":"","portrait":"","text":"C'est un mail du Boss, il faudrait le lire quand même."},{"endbranch":""},{"character":"character-1616658471.json","portrait":"","text":"Bonjour\nJespère que tout se passe bien pour vous au sein de notre entreprise.\nJe viens vers vous pour vous rappeler que votre premier projet est le développement dun nouveau téléphone portable.\nCe projet est dune très grande importance pour lentreprise et représente un très grand investissement.\nEn effet, il sera difficile pour lentreprise de survivre à un échec commercial de ce produit. \nCest pourquoi, il est vital que le projet soit non seulement un succès, mais également quil nous crée une clientèle nombreuse et fidèle.\nSi nous arrivons à fidéliser nos clients à notre téléphone, nous nous assurons un succès pour de possibles futures nouvelles versions de ce dernier.\nDès lors quil deviendra obsolète, ou encore si ses composants sabîment, ces mêmes clients n'hésiteront pas à acheter la nouvelle version.\nJespère que vous mesurez donc limportance de la réussite de ce projet et des impacts que cela pourrait avoir sur le chiffre d'affaires de lentreprise.\nCordialement, The boss."},{"action":"leaveall","character":"[All]"},{"change_timeline":"timeline-1616659917.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616659608.json","name":"mail-ouverture"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/bureauPerso.jpg"},{"action":"join","character":"character-1616658435.json","portrait":"","position":{"0":false,"1":true,"2":false,"3":false,"4":false}},{"character":"character-1616658435.json","portrait":"","text":"Tu savais que lescargot le plus gros du monde peut peser jusquà 1,5 kg ?"},{"character":"character-1616658355.json","portrait":"","text":"Oh cest toi ! Tu mas fait peur... Mais non je ne savais pas cest impressionnant !"},{"character":"character-1616658435.json","portrait":"","text":"Tu te coucheras moins bête ce soir !\nBisous !\nÀ plus dans le bus !"},{"action":"leaveall","character":"[All]"},{"wait_seconds":1},{"character":"character-1616658355.json","portrait":"","text":"Étrange collègue ce Patrick."},{"change_timeline":"timeline-1616660188.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616659917.json","name":"merde-patrick-2"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/bureauPerso.jpg"},{"action":"join","character":"character-1616660196.json","portrait":"","position":{"0":false,"1":false,"2":true,"3":false,"4":false}},{"character":"","portrait":"","text":"Vous avez reçu une notification dun article parlant du recyclage des pièces en cas de panne des téléphones."},{"character":"character-1616660196.json","portrait":"","text":"Le dépannage représente également une alternative idéale au gaspillage généré par la consommation excessive dappareils électroniques.\nDe plus en plus denseignes se consacrent à la réparation de smartphones et/ou commercialisent des pièces de rechange.\n Si auparavant, la plupart des utilisateurs de smartphones laissaient leur appareil à labandon suite à une panne quelconque, le constat nest plus le même aujourdhui.\nEn effet, les pièces de rechange, majoritairement issus du processus de recyclage, sont vendues à des prix très abordables.\nFace à la concurrence grandissante dans le domaine du dépannage de mobile, le coût des services est à la baisse.\nAu plus grand profit des utilisateurs de smartphones.\nFaire réparer son smartphone constitue une alternative plus économique que dinvestir dans lacquisition dun nouvel appareil. "},{"action":"leaveall","character":"[All]"},{"change_timeline":"timeline-1616660446.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616660188.json","name":"notification-1"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/bureauPerso.jpg"},{"action":"join","character":"character-1616658403.json","portrait":"","position":{"0":false,"1":true,"2":false,"3":false,"4":false}},{"character":"","portrait":"","text":"Une personne rentre dans votre bureau..."},{"character":"character-1616658403.json","portrait":"","text":"Salut ça va ?\n Bienvenue !\nJe mappelle Jean-Michel.\nDis moi, t'as déjà une idée de design pour le téléphone ?"},{"options":[],"question":"Avez vous une idée ?"},{"choice":"Pas vraiment"},{"choice":"Quelques unes"},{"endbranch":""},{"character":"character-1616658403.json","portrait":"","text":"De mon côté jai plein didées de designs vraiment cools qui pourraient plaire à tout le monde.\nEn plus, ça prendrait en compte toutes les fonctionnalités que le téléphone aura, comme un lecteur dempreintes digitales."},{"character":"character-1616658355.json","portrait":"","text":"Super !\nPar contre, Evelyne ma parlé dune idée qui me plait et je sais pas si ça serait compatible avec tes designs."},{"character":"character-1616658403.json","portrait":"","text":"Houla !\nCest quoi cette idée encore ?"},{"character":"character-1616658355.json","portrait":"","text":"Elle ma parlé du fait de pouvoir ouvrir le téléphone et donc que la coque soit amovible..."},{"character":"character-1616658403.json","portrait":"","text":"Mais tu ne peux pas faire ça !\nLes designs différents cest ce qui fera que le téléphone se distinguera des autres.\nPareil pour les fonctionnalités !\nToutes les marques concurrentes ont un lecteur dempreintes.\nAvec cette modification, impossible de faire ça, et les utilisateurs diront que nous sommes à la traîne au niveau des technologies utilisées."},{"options":[],"question":"Qu'en pensez vous ?"},{"choice":"Tu nas pas tord"},{"choice":"Je ny ai pas encore réfléchi"},{"endbranch":""},{"character":"character-1616658403.json","portrait":"","text":"Fais attention des décisions comme celles-ci pourraient avoir de grandes conséquences pour lentreprise…\nBonnes ou mauvaises !"},{"action":"leaveall","character":"[All]"},{"wait_seconds":0},{"change_timeline":"timeline-1616660984.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616660446.json","name":"info-jm"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/bureauPerso.jpg"},{"action":"join","character":"character-1616658471.json","portrait":"","position":{"0":false,"1":false,"2":true,"3":false,"4":false}},{"character":"","portrait":"","text":"Vous avez reçu un mail !"},{"character":"character-1616658471.json","portrait":"","text":"Bravo !\nVous êtes le gagnant de la tombola de lécole maternelle des coquelicots en fleurs !\nVous avez gagné un jambon entier félicitations ! \nPour récupérer votre prix, veuillez vous présenter au bureau de la directrice.\nLassociation des parents délèves des coquelicots."},{"options":[],"question":"..."},{"choice":"C'est dommage je suis végétarien..."},{"character":"character-1616658355.json","portrait":"","text":"J'en parlerai à la directrice."},{"choice":"Miam !"},{"character":"character-1616658355.json","portrait":"","text":"Tous ces apéros en perspective !\nJe vais me régaler."},{"endbranch":""},{"action":"leaveall","character":"[All]"},{"wait_seconds":1},{"change_timeline":"timeline-1616661304.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616660984.json","name":"merde-mail-1"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/bureauPerso.jpg"},{"character":"","portrait":"","text":"C'est l'heure de passer au travail !\nIl est temps de décider du design du téléphone.\nVoulez vous permettre l'ouverture du téléphone ?\nOu plutot le verrouiller ? "},{"options":[],"question":"Téléphone verrouillé ou ouvert ?"},{"choice":"Ouvert"},{"character":"character-1616658355.json","portrait":"","text":"Un téléphone ouvert me semble être la meilleure solution.\nJe vais voir ce que mes collègues en pensent, je suis sûr qu'Evelyne me soutiendra !"},{"definition":"1616657225-648","set_value":"1"},{"choice":"Verrouillé"},{"character":"character-1616658355.json","portrait":"","text":"Un téléphone verrouillé me semble être la meilleure solution.\nJe vais voir ce que mes collègues en pensent, je suis sûr que Jean-Michel sera ravi !"},{"definition":"1616657225-648","set_value":"0"},{"endbranch":""},{"character":"","portrait":"","text":"Vous annoncez votre décision par mail à vos collègues.\nVous les rejoignez ensuite dans la salle de réunion."},{"wait_seconds":1},{"condition":"==","definition":"1616657225-648","value":"1"},{"change_timeline":"timeline-1616661658.json"},{"endbranch":""},{"condition":"==","definition":"1616657225-648","value":"0"},{"change_timeline":"timeline-1616661685.json"},{"endbranch":""}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616661304.json","name":"question-tel-ouvert"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/meetingRoom.jpg"},{"action":"join","character":"character-1616658403.json","portrait":"","position":{"0":false,"1":true,"2":false,"3":false,"4":false}},{"character":"character-1616658403.json","portrait":"","text":"On peut discuter une minute ?"},{"character":"character-1616658355.json","portrait":"","text":"Euh oui pas de soucis quest ce quil se passe ?"},{"character":"character-1616658403.json","portrait":"","text":"Je viens dapprendre que ton projet vient dêtre validé mais que cest le projet de développer un téléphone que lutilisateur peut ouvrir !\nTu as une idée des répercussions sur lentreprise que cela va avoir ?\nLentreprise va perdre beaucoup dargent à laisser la possibilité aux gens de réparer leurs téléphones en leur laissant laccès aux composants !\nEt toutes les idées dont je tavais parlé de technologies innovantes et de designs incroyables sont réduits à néant !\nFranchement je ne sais pas ce qui tes passé par la tête mais ça me laisse sans voix …\nSur ce je nai plus rien à dire au revoir."},{"action":"leaveall","character":"[All]"},{"action":"join","character":"character-1616658373.json","portrait":"","position":{"0":false,"1":false,"2":false,"3":true,"4":false}},{"character":"character-1616658373.json","portrait":"","text":"Re-bonjour ! Quelle belle journée aujourdhui !\nJai appris que tu avais repris mon idée de pouvoir ouvrir le téléphone dans ton projet de développement.\nCest une sage décision qui va engendrer tellement de choses positives pour lentreprise.\nCest le début dune nouvelle ère technologique responsable, crois moi !\nOui au recyclage et oui à la seconde vie des appareils !"},{"character":"character-1616658355.json","portrait":"","text":"Je suis content que ce projet provoque un tel enthousiasme en toi !"},{"action":"join","character":"character-1616658435.json","portrait":"","position":{"0":true,"1":false,"2":false,"3":false,"4":false}},{"character":"character-1616658435.json","portrait":"","text":"Il se passe quoi ici ?"},{"character":"character-1616658355.json","portrait":"","text":"Tu n'as pas vu mon mail ?"},{"character":"character-1616658435.json","portrait":"","text":"Ah non.."},{"wait_seconds":1},{"character":"character-1616658435.json","portrait":"","text":"J'ai perdu mon mot de passe\n...\n..."},{"wait_seconds":1},{"action":"leaveall","character":"character-1616658435.json"},{"character":"character-1616658373.json","portrait":"","text":"...\nBon\nEn tout cas je suis ravie de ton choix !\nJe te laisse jai une réunion dans 10 min à bientôt !"},{"action":"leaveall","character":"[All]"},{"change_timeline":"timeline-1616662258.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616661658.json","name":"conseq-tel-ouvert-1"}}

View file

@ -0,0 +1 @@
{"events":[{"background":"res://backgrounds/meetingRoom.jpg"},{"action":"join","character":"character-1616658471.json","portrait":"","position":{"0":false,"1":false,"2":true,"3":false,"4":false}},{"character":"","portrait":"","text":"Vous avez reçu un mail du Boss !"},{"character":"character-1616658471.json","portrait":"","text":"Bonjour,\nJe souhaitais vous féliciter concernant votre projet de téléphone.\nJai récemment appris que vous aviez hésité concernant la possibilité douvrir le téléphone ou non.\nSachez que je suis plus que satisfait de votre choix.\nEn effet, le fait davoir fermé le téléphone nous permettra daugmenter notre chiffre daffaires de manière significative.\nDune part grâce à de nouveaux designs innovants et attractifs, mais également grâce à une fidélisation de la clientèle, je ne peux quapprouver votre choix.\nContinuez sur cette lancée !\nEn vous souhaitant une bonne journée.\nCordialement, The boss"},{"action":"leaveall","character":"character-1616658471.json"},{"wait_seconds":0},{"action":"join","character":"character-1616658373.json","portrait":"","position":{"0":false,"1":true,"2":false,"3":false,"4":false}},{"character":"character-1616658373.json","portrait":"","text":"Re\nJe croyais que tu avais compris ce que je tavais dit concernant le recyclage des composants des téléphones.\nEn fermant le téléphone, tu condamnes les utilisateurs à devoir changer leur téléphone au moindre problème.\nEn faisant ceci, tu deviens partisan de la surconsommation et donc de la pollution de notre planète.\nTu crois que le chiffre daffaires de lentreprise importera quand nous naurons même plus un endroit où vivre ?"},{"action":"join","character":"character-1616658403.json","portrait":"","position":{"0":false,"1":false,"2":false,"3":true,"4":false}},{"character":"character-1616658403.json","portrait":"","text":"Hey !\nUn petit golf samedi ?"},{"character":"character-1616658373.json","portrait":"","text":"Tu permets ?\nNous sommes en pleine discussion."},{"character":"character-1616658403.json","portrait":"","text":"Okay, faut pas être tendue comme ça..."},{"action":"leaveall","character":"character-1616658403.json"},{"character":"character-1616658373.json","portrait":"","text":"Bref\nJe te laisse réfléchir à ça je dois y aller il me reste 1h de pause je vais aller courir un peu…"},{"action":"leaveall","character":"[All]"},{"change_timeline":"timeline-1616662258.json"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616661685.json","name":"conseq-tel-ouvert-2"}}

View file

@ -0,0 +1 @@
{"events":[{"wait_seconds":0},{"character":"","portrait":"","text":"Fin de la démo, merci d'avoir joué !"},{"action":"join","character":"character-1616658435.json","portrait":"","position":{"0":false,"1":false,"2":false,"3":false,"4":true}},{"character":"character-1616658435.json","portrait":"","text":"À bientôt dans l'métro !"},{"action":"leaveall","character":"[All]"}],"metadata":{"dialogic-version":"1.0","file":"timeline-1616662258.json","name":"end"}}

View file

@ -5,7 +5,7 @@ platform="Linux/X11"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter="*.json"
include_filter="*.json, *.cfg"
exclude_filter=""
export_path="build/linux/Pir-serious-game-ethics.x86_64"
patch_list=PoolStringArray( )
@ -31,9 +31,9 @@ platform="HTML5"
runnable=true
custom_features=""
export_filter="all_resources"
include_filter="*.json"
include_filter="*.json, *.cfg"
exclude_filter=""
export_path="build/html/Pir-serious-game-ethics.html"
export_path="../../Web/dialogic/index.html"
patch_list=PoolStringArray( )
script_export_mode=1
script_encryption_key=""

View file

@ -14,6 +14,11 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://addons/dialogic/Other/DialogicClass.gd"
}, {
"base": "Node",
"class": "DialogicDefinitionsUtil",
"language": "GDScript",
"path": "res://addons/dialogic/Other/DialogicDefinitionsUtil.gd"
}, {
"base": "Reference",
"class": "DialogicResources",
"language": "GDScript",
@ -26,6 +31,7 @@ _global_script_classes=[ {
} ]
_global_script_class_icons={
"Dialogic": "",
"DialogicDefinitionsUtil": "",
"DialogicResources": "",
"DialogicUtil": ""
}
@ -36,6 +42,14 @@ config/name="Pir-serious-game-ethics"
run/main_scene="res://Main.tscn"
config/icon="res://icon.png"
[autoload]
DialogicSingleton="*res://addons/dialogic/Other/DialogicSingleton.gd"
[display]
window/size/resizable=false
[editor_plugins]
enabled=PoolStringArray( "Todo_Manager", "dialogic" )