]> Untitled Git - wolf-seeking-sheep.git/blob - addons/dialogic/Modules/Glossary/subsystem_glossary.gd
Squashed commit of the following:
[wolf-seeking-sheep.git] / addons / dialogic / Modules / Glossary / subsystem_glossary.gd
1 extends DialogicSubsystem
2
3 ## Subsystem that handles glossaries.
4
5 ## List of glossary resources that are used.
6 var glossaries := []
7 ## If false, no parsing will be done.
8 var enabled := true
9
10 ## Any key in this dictionary will overwrite the color for any item with that name.
11 var color_overrides := {}
12
13 const SETTING_DEFAULT_COLOR := 'dialogic/glossary/default_color'
14
15
16 #region STATE
17 ####################################################################################################
18
19 func clear_game_state(_clear_flag := DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void:
20         glossaries = []
21
22         for path: String in ProjectSettings.get_setting('dialogic/glossary/glossary_files', []):
23                 add_glossary(path)
24
25 #endregion
26
27
28 #region MAIN METHODS
29 ####################################################################################################
30
31 func parse_glossary(text: String) -> String:
32         if not enabled:
33                 return text
34
35         var def_case_sensitive: bool = ProjectSettings.get_setting('dialogic/glossary/default_case_sensitive', true)
36         var def_color: Color = ProjectSettings.get_setting(SETTING_DEFAULT_COLOR, Color.POWDER_BLUE)
37         var regex := RegEx.new()
38
39         for glossary: DialogicGlossary in glossaries:
40
41                 if !glossary.enabled:
42                         continue
43
44                 for entry_value: Variant in glossary.entries.values():
45
46                         if not entry_value is Dictionary:
47                                 continue
48
49                         var entry: Dictionary = entry_value
50                         var entry_key: String = entry.get(DialogicGlossary.NAME_PROPERTY, "")
51
52                         # Older versions of the glossary resource do not have a property
53                         # for their name, we must skip these.
54                         # They can be updated by opening the resource in the glossary
55                         # editor.
56                         if entry_key.is_empty():
57                                 continue
58
59                         if not entry.get('enabled', true):
60                                 continue
61
62                         var regex_options := glossary.get_set_regex_option(entry_key)
63
64                         if regex_options.is_empty():
65                                 continue
66
67                         var pattern: String = '(?<=\\W|^)(?<!\\\\)(?<word>' + regex_options + ')(?!])(?=\\W|$)'
68
69                         if entry.get('case_sensitive', def_case_sensitive):
70                                 regex.compile(pattern)
71
72                         else:
73                                 regex.compile('(?i)'+pattern)
74
75                         var color: String = entry.get('color', def_color).to_html()
76
77                         if entry_key in color_overrides:
78                                 color = color_overrides[entry_key].to_html()
79
80                         text = regex.sub(text,
81                                 '[url=' + entry_key + ']' +
82                                 '[color=' + color + ']${word}[/color]' +
83                                 '[/url]',
84                                 true
85                                 )
86
87         return text
88
89
90 func add_glossary(path:String) -> void:
91         if ResourceLoader.exists(path):
92                 var resource: DialogicGlossary = load(path)
93
94                 if resource is DialogicGlossary:
95                         glossaries.append(resource)
96         else:
97                 printerr('[Dialogic] The glossary file "' + path + '" is missing. Make sure it exists.')
98
99
100 ## Iterates over all glossaries and returns the first one that matches the
101 ## [param entry_key].
102 ##
103 ## Runtime complexity:
104 ## O(n), where n is the number of glossaries.
105 func find_glossary(entry_key: String) -> DialogicGlossary:
106         for glossary: DialogicGlossary in glossaries:
107
108                 if glossary.entries.has(entry_key):
109                         return glossary
110
111         return null
112
113
114 ## Returns the first match for a given entry key.
115 ## If translation is available and enabled, it will be translated
116 func get_entry(entry_key: String) -> Dictionary:
117         var glossary: DialogicGlossary = dialogic.Glossary.find_glossary(entry_key)
118
119         var result := {
120                 "title": "",
121                 "text": "",
122                 "extra": "",
123                 "color": Color.WHITE,
124                 }
125
126         if glossary == null:
127                 return {}
128
129         var is_translation_enabled: bool = ProjectSettings.get_setting('dialogic/translation/enabled', false)
130
131         var entry := glossary.get_entry(entry_key)
132
133         if entry.is_empty():
134                 return {}
135
136         result.color = entry.get("color")
137         if result.color == null:
138                 result.color = ProjectSettings.get_setting(SETTING_DEFAULT_COLOR, Color.POWDER_BLUE)
139
140         if is_translation_enabled and not glossary._translation_id.is_empty():
141                 var translation_key: String = glossary._translation_keys.get(entry_key)
142                 var last_slash := translation_key.rfind('/')
143
144                 if last_slash == -1:
145                         return {}
146
147                 var tr_base := translation_key.substr(0, last_slash)
148
149                 result.title = translate(tr_base, "title", entry)
150                 result.text = translate(tr_base, "text", entry)
151                 result.extra = translate(tr_base, "extra", entry)
152         else:
153                 result.title = entry.get("title", "")
154                 result.text = entry.get("text", "")
155                 result.extra = entry.get("extra", "")
156
157         ## PARSE TEXTS FOR VARIABLES
158         result.title = dialogic.VAR.parse_variables(result.title)
159         result.text = dialogic.VAR.parse_variables(result.text)
160         result.extra = dialogic.VAR.parse_variables(result.extra)
161
162         return result
163
164
165
166 ## Tries to translate the property with the given
167 func translate(tr_base: String, property: StringName, fallback_entry: Dictionary) -> String:
168         var tr_key := tr_base.path_join(property)
169         var tr_value := tr(tr_key)
170
171         if tr_key == tr_value:
172                 tr_value = fallback_entry.get(property, "")
173
174         return tr_value