]> Untitled Git - wolf-seeking-sheep.git/blob - addons/dialogic/Modules/Choice/event_choice.gd
Initial Godot project with Dialogic 2.0-Alpha-17
[wolf-seeking-sheep.git] / addons / dialogic / Modules / Choice / event_choice.gd
1 @tool
2 class_name DialogicChoiceEvent
3 extends DialogicEvent
4
5 ## Event that allows adding choices. Needs to go after a text event (or another choices EndBranch).
6
7 enum ElseActions {HIDE=0, DISABLE=1, DEFAULT=2}
8
9
10 ### Settings
11 ## The text that is displayed on the choice button.
12 var text := ""
13 ## If not empty this condition will determine if this choice is active.
14 var condition := ""
15 ## Determines what happens if  [condition] is false. Default will use the action set in the settings.
16 var else_action := ElseActions.DEFAULT
17 ## The text that is displayed if [condition] is false and [else_action] is Disable.
18 ## If empty [text] will be used for disabled button as well.
19 var disabled_text := ""
20 ## A dictionary that can be filled with arbitrary information
21 ## This can then be interpreted by a custom choice layer
22 var extra_data := {}
23
24
25 ## UI helper
26 var _has_condition := false
27
28 #endregion
29
30 var regex := RegEx.create_from_string(r'- (?<text>(?>\\\||(?(?=.*\|)[^|]|(?!\[if)[^|]))*)\|?\s*(\[if(?<condition>([^\]\[]|\[[^\]]*\])+)\])?\s*(\[(?<shortcode>[^]]*)\])?')
31
32 #region EXECUTION
33 ################################################################################
34
35 func _execute() -> void:
36         if dialogic.Choices.is_question(dialogic.current_event_idx):
37                 dialogic.Choices.show_current_question(false)
38                 dialogic.current_state = dialogic.States.AWAITING_CHOICE
39
40 #endregion
41
42
43 #region INITIALIZE
44 ################################################################################
45
46 func _init() -> void:
47         event_name = "Choice"
48         set_default_color('Color3')
49         event_category = "Flow"
50         event_sorting_index = 0
51         can_contain_events = true
52         wants_to_group = true
53
54
55 # return a control node that should show on the END BRANCH node
56 func get_end_branch_control() -> Control:
57         return load(get_script().resource_path.get_base_dir().path_join('ui_choice_end.tscn')).instantiate()
58 #endregion
59
60
61 #region SAVING/LOADING
62 ################################################################################
63
64 func to_text() -> String:
65         var result_string := ""
66
67         result_string = "- "+text.strip_edges()
68         var shortcode := store_to_shortcode_parameters()
69         if (condition and _has_condition) or shortcode or extra_data:
70                 result_string += " |"
71         if condition and _has_condition:
72                 result_string += " [if " + condition + "]"
73
74         if shortcode or extra_data:
75                 result_string += " [" + shortcode
76                 if extra_data:
77                         var extra_data_string := ""
78                         for i in extra_data:
79                                 extra_data_string += " " + i + '="' + value_to_string(extra_data[i]) + '"'
80                         if shortcode:
81                                 result_string += " "
82                         result_string += extra_data_string.strip_edges()
83                 result_string += "]"
84
85         return result_string
86
87
88 func from_text(string:String) -> void:
89         var result := regex.search(string.strip_edges())
90         if result == null:
91                 return
92         text = result.get_string('text').strip_edges()
93         condition = result.get_string('condition').strip_edges()
94         _has_condition = not condition.is_empty()
95         if result.get_string('shortcode'):
96                 load_from_shortcode_parameters(result.get_string("shortcode"))
97                 var shortcode := parse_shortcode_parameters(result.get_string('shortcode'))
98                 shortcode.erase("else")
99                 shortcode.erase("alt_text")
100                 extra_data = shortcode.duplicate()
101
102
103 func get_shortcode_parameters() -> Dictionary:
104         return {
105                 "else"                  : {"property": "else_action",           "default": ElseActions.DEFAULT,
106                                                                         "suggestions": func(): return {
107                                                                                 "Default"       :{'value':ElseActions.DEFAULT, 'text_alt':['default']},
108                                                                                 "Hide"          :{'value':ElseActions.HIDE,'text_alt':['hide'] },
109                                                                                 "Disable"       :{'value':ElseActions.DISABLE,'text_alt':['disable']}}},
110                 "alt_text"              : {"property": "disabled_text",         "default": ""},
111                 "extra_data"    : {"property": "extra_data",            "default": {}, "custom_stored":true},
112                 }
113
114
115 func is_valid_event(string:String) -> bool:
116         if string.strip_edges().begins_with("-"):
117                 return true
118         return false
119
120 #endregion
121
122 #region TRANSLATIONS
123 ################################################################################
124
125 func _get_translatable_properties() -> Array:
126         return ['text', 'disabled_text']
127
128
129 func _get_property_original_translation(property:String) -> String:
130         match property:
131                 'text':
132                         return text
133                 'disabled_text':
134                         return disabled_text
135         return ''
136 #endregion
137
138
139 #region EDITOR REPRESENTATION
140 ################################################################################
141
142 func build_event_editor() -> void:
143         add_header_edit("text", ValueType.SINGLELINE_TEXT, {'autofocus':true})
144         add_body_edit("", ValueType.LABEL, {"text":"Condition:"})
145         add_body_edit("_has_condition", ValueType.BOOL_BUTTON, {"editor_icon":["Add", "EditorIcons"], "tooltip":"Add Condition"}, "not _has_condition")
146         add_body_edit("condition", ValueType.CONDITION, {}, "_has_condition")
147         add_body_edit("_has_condition", ValueType.BOOL_BUTTON, {"editor_icon":["Remove", "EditorIcons"], "tooltip":"Remove Condition"}, "_has_condition")
148         add_body_edit("else_action", ValueType.FIXED_OPTIONS, {'left_text':'Else:',
149                 'options': [
150                         {
151                                 'label': 'Default',
152                                 'value': ElseActions.DEFAULT,
153                         },
154                         {
155                                 'label': 'Hide',
156                                 'value': ElseActions.HIDE,
157                         },
158                         {
159                                 'label': 'Disable',
160                                 'value': ElseActions.DISABLE,
161                         }
162                 ]}, '_has_condition')
163         add_body_edit("disabled_text", ValueType.SINGLELINE_TEXT, {
164                         'left_text':'Disabled text:',
165                         'placeholder':'(Empty for same)'}, 'allow_alt_text()')
166         add_body_line_break()
167         add_body_edit("extra_data", ValueType.DICTIONARY, {"left_text":"Extra Data:"})
168
169
170 func allow_alt_text() -> bool:
171         return _has_condition and (
172                 else_action == ElseActions.DISABLE or
173                 (else_action == ElseActions.DEFAULT and
174                 ProjectSettings.get_setting("dialogic/choices/def_false_behaviour", 0) == 1))
175 #endregion
176
177
178 #region  CODE COMPLETION
179 ################################################################################
180
181 func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void:
182         line = CodeCompletionHelper.get_line_untill_caret(line)
183
184         if !'[if' in line:
185                 if symbol == '{':
186                         CodeCompletionHelper.suggest_variables(TextNode)
187                 return
188
189         if symbol == '[':
190                 if !'[if' in line and line.count('[') - line.count(']') == 1:
191                         TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'if', 'if ', TextNode.syntax_highlighter.code_flow_color)
192                 elif '[if' in line:
193                         TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'else', 'else="', TextNode.syntax_highlighter.code_flow_color)
194         if symbol == ' ' and '[else' in line:
195                 TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'alt_text', 'alt_text="', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5))
196         elif symbol == '{':
197                 CodeCompletionHelper.suggest_variables(TextNode)
198         if (symbol == '=' or symbol == '"') and line.count('[') > 1 and !'" ' in line:
199                 TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'default', "default", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), null, '"')
200                 TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'hide', "hide", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), null, '"')
201                 TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'disable', "disable", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), null, '"')
202 #endregion
203
204
205 #region  SYNTAX HIGHLIGHTING
206 ################################################################################
207
208 func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary:
209         var result := regex.search(line)
210
211         dict[0] = {'color':event_color}
212
213         if not result:
214                 return dict
215
216         var condition_begin := result.get_start("condition")
217         var condition_end := result.get_end("condition")
218
219         var shortcode_begin := result.get_start("shortcode")
220
221         dict = Highlighter.color_region(dict, event_color.lerp(Highlighter.variable_color, 0.5), line, '{','}', 0, condition_begin, event_color)
222
223         if condition_begin > 0:
224                 var from := line.find('[if')
225                 dict[from] = {"color":Highlighter.normal_color}
226                 dict[from+1] = {"color":Highlighter.code_flow_color}
227                 dict[condition_begin] = {"color":Highlighter.normal_color}
228                 dict = Highlighter.color_condition(dict, line, condition_begin, condition_end)
229         if shortcode_begin:
230                 dict = Highlighter.color_shortcode_content(dict, line, shortcode_begin, 0, event_color)
231         return dict
232 #endregion