First work on dialogic, resized guild, and started implementing portraits.

This commit is contained in:
2025-08-14 10:26:24 -04:00
parent 95a7db036b
commit 3aeb3d44e6
959 changed files with 47688 additions and 46 deletions

View File

@@ -0,0 +1,243 @@
@tool
class_name DialogicSettingEvent
extends DialogicEvent
## Event that allows changing a specific setting.
### Settings
enum Modes {SET, RESET, RESET_ALL}
enum SettingValueType {
STRING,
NUMBER,
VARIABLE,
EXPRESSION
}
## The name of the setting to save to.
var name := ""
var _value_type := 0 :
get:
return _value_type
set(_value):
_value_type = _value
if not _suppress_default_value:
match _value_type:
SettingValueType.STRING, SettingValueType.VARIABLE, SettingValueType.EXPRESSION:
value = ""
SettingValueType.NUMBER:
value = 0
ui_update_needed.emit()
var value: Variant = ""
var mode := Modes.SET
## Used to suppress _value_type from overwriting value with a default value when the type changes
## This is only used when initializing the event_variable.
var _suppress_default_value: bool = false
################################################################################
## INITIALIZE
################################################################################
func _execute() -> void:
if mode == Modes.RESET or mode == Modes.RESET_ALL:
if !name.is_empty() and mode != Modes.RESET_ALL:
dialogic.Settings.reset_setting(name)
else:
dialogic.Settings.reset_all()
else:
match _value_type:
SettingValueType.STRING:
dialogic.Settings.set(name, value)
SettingValueType.NUMBER:
dialogic.Settings.set(name, float(value))
SettingValueType.VARIABLE:
if dialogic.has_subsystem('VAR'):
dialogic.Settings.set(name, dialogic.VAR.get_variable('{'+value+'}'))
SettingValueType.EXPRESSION:
if dialogic.has_subsystem('VAR'):
dialogic.Settings.set(name, dialogic.VAR.get_variable(value))
finish()
################################################################################
## INITIALIZE
################################################################################
func _init() -> void:
event_name = "Setting"
set_default_color('Color9')
event_category = "Helpers"
event_sorting_index = 2
func _get_icon() -> Resource:
return load(self.get_script().get_path().get_base_dir().path_join('icon.svg'))
################################################################################
## SAVING/LOADING
################################################################################
func to_text() -> String:
var string := "setting "
if mode != Modes.SET:
string += "reset "
if !name.is_empty() and mode != Modes.RESET_ALL:
string += '"' + name + '"'
if mode == Modes.SET:
string += " = "
value = str(value)
match _value_type:
SettingValueType.STRING: # String
string += '"'+value.replace('"', '\\"')+'"'
SettingValueType.NUMBER,SettingValueType.EXPRESSION: # Float or Expression
string += str(value)
SettingValueType.VARIABLE: # Variable
string += '{'+value+'}'
return string
func from_text(string:String) -> void:
var reg := RegEx.new()
reg.compile('setting (?<reset>reset)? *("(?<name>[^=+\\-*\\/]*)")?( *= *(?<value>.*))?')
var result := reg.search(string)
if !result:
return
if result.get_string('reset'):
mode = Modes.RESET
name = result.get_string('name').strip_edges()
if name.is_empty() and mode == Modes.RESET:
mode = Modes.RESET_ALL
if result.get_string('value'):
_suppress_default_value = true
value = result.get_string('value').strip_edges()
if value.begins_with('"') and value.ends_with('"') and value.count('"')-value.count('\\"') == 2:
value = result.get_string('value').strip_edges().replace('"', '')
_value_type = SettingValueType.STRING
elif value.begins_with('{') and value.ends_with('}') and value.count('{') == 1:
value = result.get_string('value').strip_edges().trim_suffix('}').trim_prefix('{')
_value_type = SettingValueType.VARIABLE
else:
value = result.get_string('value').strip_edges()
if value.is_valid_float():
_value_type = SettingValueType.NUMBER
else:
_value_type = SettingValueType.EXPRESSION
_suppress_default_value = false
func is_valid_event(string:String) -> bool:
return string.begins_with('setting')
################################################################################
## EDITOR REPRESENTATION
################################################################################
func build_event_editor() -> void:
add_header_edit('mode', ValueType.FIXED_OPTIONS, {
'options': [{
'label': 'Set',
'value': Modes.SET,
'icon': load("res://addons/dialogic/Editor/Images/Dropdown/default.svg")
},{
'label': 'Reset',
'value': Modes.RESET,
'icon': load("res://addons/dialogic/Editor/Images/Dropdown/update.svg")
},{
'label': 'Reset All',
'value': Modes.RESET_ALL,
'icon': load("res://addons/dialogic/Editor/Images/Dropdown/update.svg")
},
]})
add_header_edit('name', ValueType.DYNAMIC_OPTIONS, {'placeholder':'Type setting', 'suggestions_func':get_settings_suggestions}, 'mode != Modes.RESET_ALL')
add_header_edit('_value_type', ValueType.FIXED_OPTIONS, {'left_text':'to',
'options': [
{
'label': 'String',
'icon': ["String", "EditorIcons"],
'value': SettingValueType.STRING
},{
'label': 'Number',
'icon': ["float", "EditorIcons"],
'value': SettingValueType.NUMBER
},{
'label': 'Variable',
'icon': ["ClassList", "EditorIcons"],
'value': SettingValueType.VARIABLE
},{
'label': 'Expression',
'icon': ["Variant", "EditorIcons"],
'value': SettingValueType.EXPRESSION
}],
'symbol_only':true},
'!name.is_empty() and mode == Modes.SET')
add_header_edit('value', ValueType.SINGLELINE_TEXT, {}, '!name.is_empty() and (_value_type == SettingValueType.STRING or _value_type == SettingValueType.EXPRESSION) and mode == Modes.SET')
add_header_edit('value', ValueType.NUMBER, {}, '!name.is_empty() and _value_type == SettingValueType.NUMBER and mode == Modes.SET')
add_header_edit('value', ValueType.DYNAMIC_OPTIONS,
{'suggestions_func' : get_value_suggestions, 'placeholder':'Select Variable'},
'!name.is_empty() and _value_type == SettingValueType.VARIABLE and mode == Modes.SET')
func get_settings_suggestions(filter:String) -> Dictionary:
var suggestions := {filter:{'value':filter, 'editor_icon':["GDScriptInternal", "EditorIcons"]}}
for prop in ProjectSettings.get_property_list():
if prop.name.begins_with('dialogic/settings/'):
suggestions[prop.name.trim_prefix('dialogic/settings/')] = {'value':prop.name.trim_prefix('dialogic/settings/'), 'editor_icon':["GDScript", "EditorIcons"]}
return suggestions
func get_value_suggestions(_filter:String) -> Dictionary:
var suggestions := {}
var vars: Dictionary = ProjectSettings.get_setting('dialogic/variables', {})
for var_path in DialogicUtil.list_variables(vars):
suggestions[var_path] = {'value':var_path, 'editor_icon':["ClassList", "EditorIcons"]}
return suggestions
####################### CODE COMPLETION ########################################
################################################################################
func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void:
if symbol == " " and !"reset" in line and !'=' in line and !'"' in line:
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, "reset", "reset ", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), TextNode.get_theme_icon("RotateLeft", "EditorIcons"))
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, "reset all", "reset \n", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), TextNode.get_theme_icon("ToolRotate", "EditorIcons"))
if (symbol == " " or symbol == '"') and !"=" in line and CodeCompletionHelper.get_line_untill_caret(line).count('"') != 2:
for i in get_settings_suggestions(''):
if i.is_empty():
continue
if symbol == '"':
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, i, event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), TextNode.get_theme_icon("GDScript", "EditorIcons"), '"')
else:
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, i, '"'+i, event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), TextNode.get_theme_icon("GDScript", "EditorIcons"), '"')
func _get_start_code_completion(_CodeCompletionHelper:Node, TextNode:TextEdit) -> void:
TextNode.add_code_completion_option(CodeEdit.KIND_PLAIN_TEXT, 'setting', 'setting ', event_color)
#################### SYNTAX HIGHLIGHTING #######################################
################################################################################
func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary:
dict[line.find('setting')] = {"color":event_color}
dict[line.find('setting')+7] = {"color":Highlighter.normal_color}
dict = Highlighter.color_word(dict, event_color, line, 'reset')
dict = Highlighter.color_region(dict, Highlighter.string_color, line, '"', '"')
dict = Highlighter.color_region(dict, Highlighter.variable_color, line, '{', '}')
return dict

View File

@@ -0,0 +1 @@
uid://vv47w4aidpl7

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg width="63.999996" height="63.999996" viewBox="0 0 16.933332 16.933332" version="1.1" id="svg5" inkscape:export-filename="return-icon.svg" inkscape:export-xdpi="96" inkscape:export-ydpi="96" sodipodi:docname="icon.svg" inkscape:version="1.2.2 (732a01da63, 2022-12-09)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview id="namedview7" pagecolor="#464646" bordercolor="#000000" borderopacity="0.25" inkscape:showpageshadow="2" inkscape:pageopacity="0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" showgrid="false" showguides="true" inkscape:zoom="1.5898438" inkscape:cx="16.039312" inkscape:cy="-62.899263" inkscape:window-width="1920" inkscape:window-height="1017" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" inkscape:current-layer="g22577" />
<defs id="defs2" />
<g inkscape:label="Capa 1" inkscape:groupmode="layer" id="layer1">
<g id="g2568" transform="matrix(0.82460302,0,0,0.82460302,1.0713261,2.0200854)" style="stroke-width:1.28345;stroke-dasharray:none">
<g id="g11286" transform="translate(0.10757865,0.26894662)">
<path id="rect18851" style="fill:#ffffff;stroke:#ffffff;stroke-width:0.523063;stroke-linecap:round;stroke-linejoin:round" inkscape:transform-center-y="-4.7623743" d="M 7.8936486,-0.17465501 7.0631377,2.0999802 A 5.7400259,5.7400259 0 0 0 6.2813299,2.4261824 L 4.0831488,1.4036873 3.8755911,1.6112442 2.9230364,2.563799 2.7154794,2.7716383 3.7379737,4.9695371 A 5.7400259,5.7400259 0 0 0 3.4120557,5.7510623 L 1.1371371,6.5818565 v 0.293639 1.3469982 0.2936385 L 3.412339,9.3466428 A 5.7400259,5.7400259 0 0 0 3.7379737,10.12817 l -1.0224943,2.198464 0.207557,0.207559 0.9525547,0.952269 0.2078403,0.207842 2.1981811,-1.022496 a 5.7400259,5.7400259 0 0 0 0.7815252,0.325919 l 0.8305109,2.274634 h 0.2936398 1.346997 0.29364 l 0.8305106,-2.274916 a 5.7400259,5.7400259 0 0 0 0.781525,-0.325637 l 2.198464,1.022211 0.207556,-0.207557 0.952273,-0.952269 0.207839,-0.207842 -1.022493,-2.198463 a 5.7400259,5.7400259 0 0 0 0.325635,-0.7812452 l 2.2752,-0.8307936 V 8.2224937 6.8754955 6.5815749 L 14.311498,5.7519122 A 5.7400259,5.7400259 0 0 0 13.98558,4.9650064 L 15.005812,2.7713551 14.798254,2.563799 13.845981,1.6112442 13.638142,1.4036873 11.444774,2.4239163 A 5.7400259,5.7400259 0 0 0 10.657587,2.0979982 L 9.8276414,-0.17465501 H 9.5342854 8.1872884 Z M 8.8606453,3.9232559 A 3.6255555,3.6255555 0 0 1 12.486242,7.5488532 3.6255555,3.6255555 0 0 1 8.8606453,11.174451 3.6255555,3.6255555 0 0 1 5.2353313,7.5488532 3.6255555,3.6255555 0 0 1 8.8606453,3.9232559 Z" />
<g id="g19581" style="fill:#000000;stroke:#000000" />
<g id="g21754" transform="matrix(0.23576423,0,0,0.23576423,22.48277,9.5952281)">
<g id="g22577" style="fill:#000000" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,44 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cmd8c7g007ei8"
path="res://.godot/imported/icon.svg-d4407cb145fa5c1d965de3d2bd63ce5f.ctex"
metadata={
"has_editor_variant": true,
"vram_texture": false
}
[deps]
source_file="res://addons/dialogic/Modules/Settings/icon.svg"
dest_files=["res://.godot/imported/icon.svg-d4407cb145fa5c1d965de3d2bd63ce5f.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=true
editor/convert_colors_with_editor_theme=true

View File

@@ -0,0 +1,10 @@
@tool
extends DialogicIndexer
func _get_events() -> Array:
return [this_folder.path_join('event_setting.gd')]
func _get_subsystems() -> Array:
return [{'name':'Settings', 'script':this_folder.path_join('subsystem_settings.gd')}]

View File

@@ -0,0 +1 @@
uid://btpoyw3jnv8b6

View File

@@ -0,0 +1,98 @@
extends DialogicSubsystem
## Subsystem that allows setting and getting settings that are automatically saved slot independent.
##
## All settings that are stored in the project settings dialogic/settings section are supported.
## For example the text_speed setting is stored there.
## How to access this subsystem via code:
## ```gd
## Dialogic.Settings.text_speed = 0.05
## ```
##
## Settings stored there can also be changed with the Settings event.
var settings := {}
var _connections := {}
#region MAIN METHODS
####################################################################################################
## Built-in, called by DialogicGameHandler.
func clear_game_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR):
_reload_settings()
func _reload_settings() -> void:
settings = {}
for prop in ProjectSettings.get_property_list():
if prop.name.begins_with('dialogic/settings'):
settings[prop.name.trim_prefix('dialogic/settings/')] = ProjectSettings.get_setting(prop.name)
if dialogic.has_subsystem('Save'):
for i in settings:
settings[i] = dialogic.Save.get_global_info(i, settings[i])
func _set(property:StringName, value:Variant) -> bool:
if not settings.has(property) or settings[property] != value:
_setting_changed(property, value)
settings[property] = value
if dialogic.has_subsystem('Save'):
dialogic.Save.set_global_info(property, value)
return true
func _get(property:StringName) -> Variant:
if property in settings:
return settings[property]
return null
func _setting_changed(property:StringName, value:Variant) -> void:
if !property in _connections:
return
for i in _connections[property]:
if not is_instance_valid(i.get_object()):
var remove := func(): _connections[property].erase(i)
remove.call_deferred()
continue
i.call(value)
#endregion
#region HANDY METHODS
####################################################################################################
## Get a setting named `property`, if it does not exist, falls back to `default`.
func get_setting(property: StringName, default: Variant) -> Variant:
return _get(property) if _get(property) != null else default
## Whether a setting has been set/stored before.
func has_setting(property: StringName) -> bool:
return property in settings
func reset_all() -> void:
for setting in settings:
reset_setting(setting)
func reset_setting(property: StringName) -> void:
if ProjectSettings.has_setting('dialogic/settings/'+property):
settings[property] = ProjectSettings.get_setting('dialogic/settings/'+property)
_setting_changed(property, settings[property])
else:
settings.erase(property)
_setting_changed(property, null)
## If a setting named `property` changes its value, this will emit `Callable`.
func connect_to_change(property: StringName, callable: Callable) -> void:
if not property in _connections:
_connections[property] = []
_connections[property].append(callable)
#endregion

View File

@@ -0,0 +1 @@
uid://e4p0r5ispaj5