2 class_name DialogicVariableEvent
5 ## Event that allows changing a dialogic variable or a property of an autoload.
8 enum Operations {SET, ADD, SUBSTRACT, MULTIPLY, DIVIDE}
20 ## Name/Path of the variable that should be changed.
24 if Engine.is_editor_hint() and not value:
25 match DialogicUtil.get_variable_type(name):
26 DialogicUtil.VarTypes.ANY, DialogicUtil.VarTypes.STRING:
27 _value_type = VarValueType.STRING
28 DialogicUtil.VarTypes.FLOAT, DialogicUtil.VarTypes.INT:
29 _value_type = VarValueType.NUMBER
30 DialogicUtil.VarTypes.BOOL:
31 _value_type = VarValueType.BOOL
32 ui_update_needed.emit()
33 update_editor_warning()
35 ## The operation to perform.
36 var operation := Operations.SET:
39 if operation != Operations.SET and _value_type == VarValueType.STRING:
40 _value_type = VarValueType.NUMBER
41 ui_update_needed.emit()
42 update_editor_warning()
44 ## The value that is used. Can be a variable as well.
45 var value: Variant = ""
46 var _value_type := 0 :
49 if not _suppress_default_value:
51 VarValueType.STRING, VarValueType.VARIABLE, VarValueType.EXPRESSION:
57 VarValueType.RANDOM_NUMBER:
59 ui_update_needed.emit()
60 update_editor_warning()
62 ## If true, a random number between [random_min] and [random_max] is used instead of [value].
63 var random_min: int = 0
64 var random_max: int = 100
66 ## Used to suppress _value_type from overwriting value with a default value when the type changes
67 ## This is only used when initializing the event_variable.
68 var _suppress_default_value := false
71 ################################################################################
73 ################################################################################
75 func _execute() -> void:
77 var original_value: Variant = dialogic.VAR.get_variable(name, null, operation == Operations.SET and "[" in name)
79 if value != null and (original_value != null or (operation == Operations.SET and "[" in name)):
81 var interpreted_value: Variant
86 interpreted_value = dialogic.VAR.get_variable('"' + value + '"')
87 VarValueType.VARIABLE:
88 interpreted_value = dialogic.VAR.get_variable('{' + value + '}')
89 VarValueType.NUMBER, VarValueType.BOOL, VarValueType.EXPRESSION, VarValueType.RANDOM_NUMBER:
90 interpreted_value = dialogic.VAR.get_variable(str(value))
92 if operation != Operations.SET and (not str(original_value).is_valid_float() or not str(interpreted_value).is_valid_float()):
93 printerr("[Dialogic] Set Variable event failed because one value wasn't a float! [", original_value, ", ",interpreted_value,"]")
97 if operation == Operations.SET:
98 result = interpreted_value
101 original_value = float(original_value)
102 interpreted_value = float(interpreted_value)
106 result = original_value + interpreted_value
107 Operations.SUBSTRACT:
108 result = original_value - interpreted_value
110 result = original_value * interpreted_value
112 result = original_value / interpreted_value
114 dialogic.VAR.set_variable(name, result)
115 dialogic.VAR.variable_was_set.emit(
118 'value' : interpreted_value,
120 'orig_value' : original_value,
121 'new_value' : result,
125 printerr("[Dialogic] Set Variable event failed because one value wasn't set!")
130 ################################################################################
132 ################################################################################
134 func _init() -> void:
135 event_name = "Set Variable"
136 set_default_color('Color6')
137 event_category = "Logic"
138 event_sorting_index = 0
139 help_page_path = "https://docs.dialogic.pro/variables.html#23-set-variable-event"
142 ################################################################################
144 ################################################################################
146 func to_text() -> String:
149 string += "{" + name.trim_prefix('{').trim_suffix('}') + "}"
155 Operations.SUBSTRACT:
164 VarValueType.STRING: # String
165 string += '"'+value.replace('"', '\\"')+'"'
166 VarValueType.NUMBER,VarValueType.BOOL,VarValueType.EXPRESSION: # Float Bool, or Expression
168 VarValueType.VARIABLE: # Variable
169 string += '{'+value+'}'
170 VarValueType.RANDOM_NUMBER:
171 string += 'range('+str(random_min)+','+str(random_max)+').pick_random()'
176 func from_text(string:String) -> void:
177 var reg := RegEx.new()
178 reg.compile("set(?<name>[^=+\\-*\\/]*)?(?<operation>=|\\+=|-=|\\*=|\\/=)?(?<value>.*)")
179 var result := reg.search(string)
182 name = result.get_string('name').strip_edges().replace("{", "").replace("}", "")
183 match result.get_string('operation').strip_edges():
185 operation = Operations.SET
187 operation = Operations.SUBSTRACT
189 operation = Operations.ADD
191 operation = Operations.MULTIPLY
193 operation = Operations.DIVIDE
195 _suppress_default_value = true
196 value = result.get_string('value').strip_edges()
197 if not value.is_empty():
198 if value.begins_with('"') and value.ends_with('"') and value.count('"')-value.count('\\"') == 2:
199 value = result.get_string('value').strip_edges().replace('"', '')
200 _value_type = VarValueType.STRING
201 elif value.begins_with('{') and value.ends_with('}') and value.count('{') == 1:
202 value = result.get_string('value').strip_edges().trim_suffix('}').trim_prefix('{')
203 _value_type = VarValueType.VARIABLE
204 elif value in ["true", "false"]:
205 value = value == "true"
206 _value_type = VarValueType.BOOL
207 elif value.begins_with('range(') and value.ends_with(').pick_random()'):
208 _value_type = VarValueType.RANDOM_NUMBER
209 var randinf := str(value).trim_prefix('range(').trim_suffix(').pick_random()').split(',')
210 random_min = int(randinf[0])
211 random_max = int(randinf[1])
213 value = result.get_string('value').strip_edges()
214 if value.is_valid_float():
215 _value_type = VarValueType.NUMBER
217 _value_type = VarValueType.EXPRESSION
220 _suppress_default_value = false
223 func is_valid_event(string:String) -> bool:
224 return string.begins_with('set')
227 ################################################################################
228 ## EDITOR REPRESENTATION
229 ################################################################################
231 func build_event_editor() -> void:
232 add_header_edit('name', ValueType.DYNAMIC_OPTIONS, {
234 'suggestions_func' : get_var_suggestions,
235 'icon' : load("res://addons/dialogic/Editor/Images/Pieces/variable.svg"),
236 'placeholder' :'Select Variable'}
238 add_header_edit('operation', ValueType.FIXED_OPTIONS, {
242 'icon': load("res://addons/dialogic/Editor/Images/Dropdown/set.svg"),
243 'value': Operations.SET
245 'label': 'to itself plus',
246 'icon': load("res://addons/dialogic/Editor/Images/Dropdown/plus.svg"),
247 'value': Operations.ADD
249 'label': 'to itself minus',
250 'icon': load("res://addons/dialogic/Editor/Images/Dropdown/minus.svg"),
251 'value': Operations.SUBSTRACT
253 'label': 'to itself multiplied by',
254 'icon': load("res://addons/dialogic/Editor/Images/Dropdown/multiply.svg"),
255 'value': Operations.MULTIPLY
257 'label': 'to itself divided by',
258 'icon': load("res://addons/dialogic/Editor/Images/Dropdown/divide.svg"),
259 'value': Operations.DIVIDE
262 }, '!name.is_empty()')
263 add_header_edit('_value_type', ValueType.FIXED_OPTIONS, {
267 'icon': ["String", "EditorIcons"],
268 'value': VarValueType.STRING
271 'icon': ["float", "EditorIcons"],
272 'value': VarValueType.NUMBER
275 'icon': load("res://addons/dialogic/Editor/Images/Pieces/variable.svg"),
276 'value': VarValueType.VARIABLE
279 'icon': ["bool", "EditorIcons"],
280 'value': VarValueType.BOOL
282 'label': 'Expression',
283 'icon': ["Variant", "EditorIcons"],
284 'value': VarValueType.EXPRESSION
286 'label': 'Random Number',
287 'icon': ["RandomNumberGenerator", "EditorIcons"],
288 'value': VarValueType.RANDOM_NUMBER
292 add_header_edit('value', ValueType.SINGLELINE_TEXT, {}, '!name.is_empty() and (_value_type == VarValueType.STRING or _value_type == VarValueType.EXPRESSION) ')
293 add_header_edit('value', ValueType.BOOL, {}, '!name.is_empty() and (_value_type == VarValueType.BOOL) ')
294 add_header_edit('value', ValueType.NUMBER, {}, '!name.is_empty() and _value_type == VarValueType.NUMBER')
295 add_header_edit('value', ValueType.DYNAMIC_OPTIONS,
296 {'suggestions_func' : get_value_suggestions, 'placeholder':'Select Variable'},
297 '!name.is_empty() and _value_type == VarValueType.VARIABLE')
298 add_header_label('a number between', '_value_type == VarValueType.RANDOM_NUMBER')
299 add_header_edit('random_min', ValueType.NUMBER, {'right_text':'and', 'mode':1}, '!name.is_empty() and _value_type == VarValueType.RANDOM_NUMBER')
300 add_header_edit('random_max', ValueType.NUMBER, {'mode':1}, '!name.is_empty() and _value_type == VarValueType.RANDOM_NUMBER')
301 add_header_button('', _on_variable_editor_pressed, 'Variable Editor', ["ExternalLink", "EditorIcons"])
304 func get_var_suggestions(filter:String) -> Dictionary:
305 var suggestions := {}
307 suggestions[filter] = {'value':filter, 'editor_icon':["GuiScrollArrowRight", "EditorIcons"]}
308 for var_path in DialogicUtil.list_variables(DialogicUtil.get_default_variables()):
309 suggestions[var_path] = {'value':var_path, 'icon':load("res://addons/dialogic/Editor/Images/Pieces/variable.svg")}
313 func get_value_suggestions(_filter:String) -> Dictionary:
314 var suggestions := {}
316 for var_path in DialogicUtil.list_variables(DialogicUtil.get_default_variables()):
317 suggestions[var_path] = {'value':var_path, 'icon':load("res://addons/dialogic/Editor/Images/Pieces/variable.svg")}
321 func _on_variable_editor_pressed() -> void:
322 var editor_manager := editor_node.find_parent('EditorsManager')
324 editor_manager.open_editor(editor_manager.editors['VariablesEditor']['node'], true)
327 func update_editor_warning() -> void:
328 if _value_type == VarValueType.STRING and operation != Operations.SET:
329 ui_update_warning.emit('You cannot do this operation with a string!')
330 elif operation != Operations.SET:
331 var type := DialogicUtil.get_variable_type(name)
332 if not type in [DialogicUtil.VarTypes.INT, DialogicUtil.VarTypes.FLOAT, DialogicUtil.VarTypes.ANY]:
333 ui_update_warning.emit('The selected variable is not a number!')
335 ui_update_warning.emit('')
337 ui_update_warning.emit('')
341 ####################### CODE COMPLETION ########################################
342 ################################################################################
344 func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void:
345 if CodeCompletionHelper.get_line_untill_caret(line) == 'set ':
346 TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, '{', '{', TextNode.syntax_highlighter.variable_color)
348 CodeCompletionHelper.suggest_variables(TextNode)
351 func _get_start_code_completion(_CodeCompletionHelper:Node, TextNode:TextEdit) -> void:
352 TextNode.add_code_completion_option(CodeEdit.KIND_PLAIN_TEXT, 'set', 'set ', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5))
355 #################### SYNTAX HIGHLIGHTING #######################################
356 ################################################################################
358 func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary:
359 dict[line.find('set')] = {"color":event_color.lerp(Highlighter.normal_color, 0.5)}
360 dict[line.find('set')+3] = {"color":Highlighter.normal_color}
361 dict = Highlighter.color_region(dict, Highlighter.string_color, line, '"', '"', line.find('set'))
362 dict = Highlighter.color_region(dict, Highlighter.variable_color, line, '{', '}', line.find('set'))