First work on dialogic, resized guild, and started implementing portraits.
This commit is contained in:
232
addons/dialogic/Modules/Choice/event_choice.gd
Normal file
232
addons/dialogic/Modules/Choice/event_choice.gd
Normal file
@@ -0,0 +1,232 @@
|
||||
@tool
|
||||
class_name DialogicChoiceEvent
|
||||
extends DialogicEvent
|
||||
|
||||
## Event that allows adding choices. Needs to go after a text event (or another choices EndBranch).
|
||||
|
||||
enum ElseActions {HIDE=0, DISABLE=1, DEFAULT=2}
|
||||
|
||||
|
||||
### Settings
|
||||
## The text that is displayed on the choice button.
|
||||
var text := ""
|
||||
## If not empty this condition will determine if this choice is active.
|
||||
var condition := ""
|
||||
## Determines what happens if [condition] is false. Default will use the action set in the settings.
|
||||
var else_action := ElseActions.DEFAULT
|
||||
## The text that is displayed if [condition] is false and [else_action] is Disable.
|
||||
## If empty [text] will be used for disabled button as well.
|
||||
var disabled_text := ""
|
||||
## A dictionary that can be filled with arbitrary information
|
||||
## This can then be interpreted by a custom choice layer
|
||||
var extra_data := {}
|
||||
|
||||
|
||||
## UI helper
|
||||
var _has_condition := false
|
||||
|
||||
#endregion
|
||||
|
||||
var regex := RegEx.create_from_string(r'- (?<text>(?>\\\||(?(?=.*\|)[^|]|(?!\[if)[^|]))*)\|?\s*(\[if(?<condition>([^\]\[]|\[[^\]]*\])+)\])?\s*(\[(?<shortcode>[^]]*)\])?')
|
||||
|
||||
#region EXECUTION
|
||||
################################################################################
|
||||
|
||||
func _execute() -> void:
|
||||
if dialogic.Choices.is_question(dialogic.current_event_idx):
|
||||
dialogic.Choices.show_current_question(false)
|
||||
dialogic.current_state = dialogic.States.AWAITING_CHOICE
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region INITIALIZE
|
||||
################################################################################
|
||||
|
||||
func _init() -> void:
|
||||
event_name = "Choice"
|
||||
set_default_color('Color3')
|
||||
event_category = "Flow"
|
||||
event_sorting_index = 0
|
||||
can_contain_events = true
|
||||
wants_to_group = true
|
||||
|
||||
|
||||
# return a control node that should show on the END BRANCH node
|
||||
func get_end_branch_control() -> Control:
|
||||
return load(get_script().resource_path.get_base_dir().path_join('ui_choice_end.tscn')).instantiate()
|
||||
#endregion
|
||||
|
||||
|
||||
#region SAVING/LOADING
|
||||
################################################################################
|
||||
|
||||
func to_text() -> String:
|
||||
var result_string := ""
|
||||
|
||||
result_string = "- "+text.strip_edges()
|
||||
var shortcode := store_to_shortcode_parameters()
|
||||
if (condition and _has_condition) or shortcode or extra_data:
|
||||
result_string += " |"
|
||||
if condition and _has_condition:
|
||||
result_string += " [if " + condition + "]"
|
||||
|
||||
if shortcode or extra_data:
|
||||
result_string += " [" + shortcode
|
||||
if extra_data:
|
||||
var extra_data_string := ""
|
||||
for i in extra_data:
|
||||
extra_data_string += " " + i + '="' + value_to_string(extra_data[i]) + '"'
|
||||
if shortcode:
|
||||
result_string += " "
|
||||
result_string += extra_data_string.strip_edges()
|
||||
result_string += "]"
|
||||
|
||||
return result_string
|
||||
|
||||
|
||||
func from_text(string:String) -> void:
|
||||
var result := regex.search(string.strip_edges())
|
||||
if result == null:
|
||||
return
|
||||
text = result.get_string('text').strip_edges()
|
||||
condition = result.get_string('condition').strip_edges()
|
||||
_has_condition = not condition.is_empty()
|
||||
if result.get_string('shortcode'):
|
||||
load_from_shortcode_parameters(result.get_string("shortcode"))
|
||||
var shortcode := parse_shortcode_parameters(result.get_string('shortcode'))
|
||||
shortcode.erase("else")
|
||||
shortcode.erase("alt_text")
|
||||
extra_data = shortcode.duplicate()
|
||||
|
||||
|
||||
func get_shortcode_parameters() -> Dictionary:
|
||||
return {
|
||||
"else" : {"property": "else_action", "default": ElseActions.DEFAULT,
|
||||
"suggestions": func(): return {
|
||||
"Default" :{'value':ElseActions.DEFAULT, 'text_alt':['default']},
|
||||
"Hide" :{'value':ElseActions.HIDE,'text_alt':['hide'] },
|
||||
"Disable" :{'value':ElseActions.DISABLE,'text_alt':['disable']}}},
|
||||
"alt_text" : {"property": "disabled_text", "default": ""},
|
||||
"extra_data" : {"property": "extra_data", "default": {}, "custom_stored":true},
|
||||
}
|
||||
|
||||
|
||||
func is_valid_event(string:String) -> bool:
|
||||
if string.strip_edges().begins_with("-"):
|
||||
return true
|
||||
return false
|
||||
|
||||
#endregion
|
||||
|
||||
#region TRANSLATIONS
|
||||
################################################################################
|
||||
|
||||
func _get_translatable_properties() -> Array:
|
||||
return ['text', 'disabled_text']
|
||||
|
||||
|
||||
func _get_property_original_translation(property:String) -> String:
|
||||
match property:
|
||||
'text':
|
||||
return text
|
||||
'disabled_text':
|
||||
return disabled_text
|
||||
return ''
|
||||
#endregion
|
||||
|
||||
|
||||
#region EDITOR REPRESENTATION
|
||||
################################################################################
|
||||
|
||||
func build_event_editor() -> void:
|
||||
add_header_edit("text", ValueType.SINGLELINE_TEXT, {'autofocus':true})
|
||||
add_body_edit("", ValueType.LABEL, {"text":"Condition:"})
|
||||
add_body_edit("_has_condition", ValueType.BOOL_BUTTON, {"editor_icon":["Add", "EditorIcons"], "tooltip":"Add Condition"}, "not _has_condition")
|
||||
add_body_edit("condition", ValueType.CONDITION, {}, "_has_condition")
|
||||
add_body_edit("_has_condition", ValueType.BOOL_BUTTON, {"editor_icon":["Remove", "EditorIcons"], "tooltip":"Remove Condition"}, "_has_condition")
|
||||
add_body_edit("else_action", ValueType.FIXED_OPTIONS, {'left_text':'Else:',
|
||||
'options': [
|
||||
{
|
||||
'label': 'Default',
|
||||
'value': ElseActions.DEFAULT,
|
||||
},
|
||||
{
|
||||
'label': 'Hide',
|
||||
'value': ElseActions.HIDE,
|
||||
},
|
||||
{
|
||||
'label': 'Disable',
|
||||
'value': ElseActions.DISABLE,
|
||||
}
|
||||
]}, '_has_condition')
|
||||
add_body_edit("disabled_text", ValueType.SINGLELINE_TEXT, {
|
||||
'left_text':'Disabled text:',
|
||||
'placeholder':'(Empty for same)'}, 'allow_alt_text()')
|
||||
add_body_line_break()
|
||||
add_body_edit("extra_data", ValueType.DICTIONARY, {"left_text":"Extra Data:"})
|
||||
|
||||
|
||||
func allow_alt_text() -> bool:
|
||||
return _has_condition and (
|
||||
else_action == ElseActions.DISABLE or
|
||||
(else_action == ElseActions.DEFAULT and
|
||||
ProjectSettings.get_setting("dialogic/choices/def_false_behaviour", 0) == 1))
|
||||
#endregion
|
||||
|
||||
|
||||
#region CODE COMPLETION
|
||||
################################################################################
|
||||
|
||||
func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:String, _word:String, symbol:String) -> void:
|
||||
line = CodeCompletionHelper.get_line_untill_caret(line)
|
||||
|
||||
if !'[if' in line:
|
||||
if symbol == '{':
|
||||
CodeCompletionHelper.suggest_variables(TextNode)
|
||||
return
|
||||
|
||||
if symbol == '[':
|
||||
if !'[if' in line and line.count('[') - line.count(']') == 1:
|
||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'if', 'if ', TextNode.syntax_highlighter.code_flow_color)
|
||||
elif '[if' in line:
|
||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'else', 'else="', TextNode.syntax_highlighter.code_flow_color)
|
||||
if symbol == ' ' and '[else' in line:
|
||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'alt_text', 'alt_text="', event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5))
|
||||
elif symbol == '{':
|
||||
CodeCompletionHelper.suggest_variables(TextNode)
|
||||
if (symbol == '=' or symbol == '"') and line.count('[') > 1 and !'" ' in line:
|
||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'default', "default", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), null, '"')
|
||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'hide', "hide", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), null, '"')
|
||||
TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, 'disable', "disable", event_color.lerp(TextNode.syntax_highlighter.normal_color, 0.5), null, '"')
|
||||
#endregion
|
||||
|
||||
|
||||
#region SYNTAX HIGHLIGHTING
|
||||
################################################################################
|
||||
|
||||
func _get_syntax_highlighting(Highlighter:SyntaxHighlighter, dict:Dictionary, line:String) -> Dictionary:
|
||||
var result := regex.search(line)
|
||||
|
||||
dict[0] = {'color':event_color}
|
||||
|
||||
if not result:
|
||||
return dict
|
||||
|
||||
var condition_begin := result.get_start("condition")
|
||||
var condition_end := result.get_end("condition")
|
||||
|
||||
var shortcode_begin := result.get_start("shortcode")
|
||||
|
||||
dict = Highlighter.color_region(dict, event_color.lerp(Highlighter.variable_color, 0.5), line, '{','}', 0, condition_begin, event_color)
|
||||
|
||||
if condition_begin > 0:
|
||||
var from := line.find('[if')
|
||||
dict[from] = {"color":Highlighter.normal_color}
|
||||
dict[from+1] = {"color":Highlighter.code_flow_color}
|
||||
dict[condition_begin] = {"color":Highlighter.normal_color}
|
||||
dict = Highlighter.color_condition(dict, line, condition_begin, condition_end)
|
||||
if shortcode_begin:
|
||||
dict = Highlighter.color_shortcode_content(dict, line, shortcode_begin, 0, event_color)
|
||||
return dict
|
||||
#endregion
|
||||
1
addons/dialogic/Modules/Choice/event_choice.gd.uid
Normal file
1
addons/dialogic/Modules/Choice/event_choice.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://36134yfesahe
|
||||
10
addons/dialogic/Modules/Choice/icon.svg
Normal file
10
addons/dialogic/Modules/Choice/icon.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<?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="choice-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.0544998" inkscape:cx="-184.44765" inkscape:cy="-1.8966339" inkscape:window-width="1920" inkscape:window-height="1017" inkscape:window-x="-8" inkscape:window-y="-8" inkscape:window-maximized="1" inkscape:current-layer="svg5" />
|
||||
<defs id="defs2" />
|
||||
<rect style="stroke-width:3.57045;stroke-dasharray:none;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:0;stroke-opacity:1" id="rect26013" width="58.831448" height="24.065563" x="-167.86046" y="-31.618748" ry="12.032781" transform="matrix(0.15519359,0,0,0.15519359,31.232208,8.9372117)" />
|
||||
<path sodipodi:type="star" style="stroke-width:8.16565;stroke-dasharray:none;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-linecap:round;stroke-linejoin:round;stroke-dashoffset:0;stroke-opacity:1" id="path26015" inkscape:flatsided="false" sodipodi:sides="3" sodipodi:cx="-138.47092" sodipodi:cy="-7.3761749" sodipodi:r1="20.010386" sodipodi:r2="10.457433" sodipodi:arg1="0.52359878" sodipodi:arg2="1.5707963" inkscape:rounded="0.02640344" inkscape:randomized="0" d="m -121.14141,2.6290179 c -0.22886,0.3963922 -16.87179,0.4522399 -17.32951,0.4522399 -0.45771,0 -17.10064,-0.055848 -17.3295,-0.45224 -0.22886,-0.3963922 8.04424,-14.8375168 8.2731,-15.2339088 0.22886,-0.396392 8.59869,-14.781669 9.0564,-14.781669 0.45772,0 8.82755,14.385276 9.05641,14.781668 0.22885,0.396393 8.50195,14.8375177 8.2731,15.2339099 z" transform="matrix(0,-0.07693147,-0.06541836,0,2.2708052,-4.7551753)" inkscape:transform-center-x="-0.73902511" />
|
||||
<path id="path28608" style="stroke-width:3.3313;stroke-dasharray:none;fill:#ffffff;color:#000000;fill-opacity:0.45;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none" d="m -155.82823,2.6553184 c -7.56011,0 -13.69881,6.1387113 -13.69881,13.6988156 0,7.560104 6.1387,13.698816 13.69881,13.698816 h 34.76649 c 7.56011,0 13.69882,-6.138712 13.69882,-13.698816 0,-7.5601043 -6.13871,-13.6988156 -13.69882,-13.6988156 z" transform="matrix(0.15519359,0,0,0.15519359,31.232208,8.9372117)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
44
addons/dialogic/Modules/Choice/icon.svg.import
Normal file
44
addons/dialogic/Modules/Choice/icon.svg.import
Normal file
@@ -0,0 +1,44 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://wd4fnxjfmj5m"
|
||||
path="res://.godot/imported/icon.svg-372a9bfce8bea67fff1988d7acf09a9a.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/dialogic/Modules/Choice/icon.svg"
|
||||
dest_files=["res://.godot/imported/icon.svg-372a9bfce8bea67fff1988d7acf09a9a.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
|
||||
14
addons/dialogic/Modules/Choice/index.gd
Normal file
14
addons/dialogic/Modules/Choice/index.gd
Normal file
@@ -0,0 +1,14 @@
|
||||
@tool
|
||||
extends DialogicIndexer
|
||||
|
||||
|
||||
func _get_events() -> Array:
|
||||
return [this_folder.path_join('event_choice.gd')]
|
||||
|
||||
|
||||
func _get_subsystems() -> Array:
|
||||
return [{'name':'Choices', 'script':this_folder.path_join('subsystem_choices.gd')}]
|
||||
|
||||
|
||||
func _get_settings_pages() -> Array:
|
||||
return [this_folder.path_join('settings_choices.tscn')]
|
||||
1
addons/dialogic/Modules/Choice/index.gd.uid
Normal file
1
addons/dialogic/Modules/Choice/index.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dtuq2nsgm734q
|
||||
52
addons/dialogic/Modules/Choice/node_button_sound.gd
Normal file
52
addons/dialogic/Modules/Choice/node_button_sound.gd
Normal file
@@ -0,0 +1,52 @@
|
||||
class_name DialogicNode_ButtonSound
|
||||
extends AudioStreamPlayer
|
||||
|
||||
## Node that is used for playing sound effects on hover/focus/press of sibling DialogicNode_ChoiceButtons.
|
||||
|
||||
## Sound to be played if one of the sibling ChoiceButtons is pressed.
|
||||
## If sibling ChoiceButton has a sound_pressed set, that is prioritized.
|
||||
@export var sound_pressed: AudioStream
|
||||
## Sound to be played on hover. See [sound_pressed] for more.
|
||||
@export var sound_hover: AudioStream
|
||||
## Sound to be played on focus. See [sound_pressed] for more.
|
||||
@export var sound_focus: AudioStream
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group('dialogic_button_sound')
|
||||
_connect_all_buttons()
|
||||
|
||||
#basic play sound
|
||||
func play_sound(sound) -> void:
|
||||
if sound != null:
|
||||
stream = sound
|
||||
play()
|
||||
|
||||
func _connect_all_buttons() -> void:
|
||||
for child in get_parent().get_children():
|
||||
if child is DialogicNode_ChoiceButton:
|
||||
child.button_up.connect(_on_pressed.bind(child.sound_pressed))
|
||||
child.mouse_entered.connect(_on_hover.bind(child.sound_hover))
|
||||
child.focus_entered.connect(_on_focus.bind(child.sound_focus))
|
||||
|
||||
|
||||
#the custom_sound argument comes from the specifec button and get used
|
||||
#if none are found, it uses the above sounds
|
||||
|
||||
func _on_pressed(custom_sound) -> void:
|
||||
if custom_sound != null:
|
||||
play_sound(custom_sound)
|
||||
else:
|
||||
play_sound(sound_pressed)
|
||||
|
||||
func _on_hover(custom_sound) -> void:
|
||||
if custom_sound != null:
|
||||
play_sound(custom_sound)
|
||||
else:
|
||||
play_sound(sound_hover)
|
||||
|
||||
func _on_focus(custom_sound) -> void:
|
||||
if custom_sound != null:
|
||||
play_sound(custom_sound)
|
||||
else:
|
||||
play_sound(sound_focus)
|
||||
|
||||
1
addons/dialogic/Modules/Choice/node_button_sound.gd.uid
Normal file
1
addons/dialogic/Modules/Choice/node_button_sound.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://t60dglopoihw
|
||||
45
addons/dialogic/Modules/Choice/node_choice_button.gd
Normal file
45
addons/dialogic/Modules/Choice/node_choice_button.gd
Normal file
@@ -0,0 +1,45 @@
|
||||
class_name DialogicNode_ChoiceButton
|
||||
extends Button
|
||||
## The button allows the player to make a choice in the Dialogic system.
|
||||
##
|
||||
## This class is used in the Choice Layer. [br]
|
||||
## You may change the [member text_node] to any [class Node] that has a
|
||||
## `text` property. [br]
|
||||
## If you don't set the [member text_node], the text will be set on this
|
||||
## button instead.
|
||||
##
|
||||
## Using a different node may allow using rich text effects; they are
|
||||
## not supported on buttons at this point.
|
||||
|
||||
|
||||
## Used to identify what choices to put on. If you leave it at -1, choices will be distributed automatically.
|
||||
@export var choice_index: int = -1
|
||||
|
||||
## Can be set to play this sound when pressed. Requires a sibling DialogicNode_ButtonSound node.
|
||||
@export var sound_pressed: AudioStream
|
||||
## Can be set to play this sound when hovered. Requires a sibling DialogicNode_ButtonSound node.
|
||||
@export var sound_hover: AudioStream
|
||||
## Can be set to play this sound when focused. Requires a sibling DialogicNode_ButtonSound node.
|
||||
@export var sound_focus: AudioStream
|
||||
## If set, the text will be set on this node's `text` property instead.
|
||||
@export var text_node: Node
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
add_to_group('dialogic_choice_button')
|
||||
shortcut_in_tooltip = false
|
||||
hide()
|
||||
|
||||
|
||||
func _load_info(choice_info: Dictionary) -> void:
|
||||
set_choice_text(choice_info.text)
|
||||
visible = choice_info.visible
|
||||
disabled = choice_info.disabled
|
||||
|
||||
|
||||
## Called when the text changes.
|
||||
func set_choice_text(new_text: String) -> void:
|
||||
if text_node:
|
||||
text_node.text = new_text
|
||||
else:
|
||||
text = new_text
|
||||
1
addons/dialogic/Modules/Choice/node_choice_button.gd.uid
Normal file
1
addons/dialogic/Modules/Choice/node_choice_button.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dr1w31s5eps7h
|
||||
67
addons/dialogic/Modules/Choice/settings_choices.gd
Normal file
67
addons/dialogic/Modules/Choice/settings_choices.gd
Normal file
@@ -0,0 +1,67 @@
|
||||
@tool
|
||||
extends DialogicSettingsPage
|
||||
|
||||
func _refresh() -> void:
|
||||
%Autofocus.button_pressed = ProjectSettings.get_setting('dialogic/choices/autofocus_first', true)
|
||||
%Delay.value = ProjectSettings.get_setting('dialogic/choices/delay', 0.2)
|
||||
%FalseBehaviour.select(ProjectSettings.get_setting('dialogic/choices/def_false_behaviour', 0))
|
||||
%HotkeyType.select(ProjectSettings.get_setting('dialogic/choices/hotkey_behaviour', 0))
|
||||
|
||||
var reveal_delay: float = ProjectSettings.get_setting('dialogic/choices/reveal_delay', 0)
|
||||
var reveal_by_input: bool = ProjectSettings.get_setting('dialogic/choices/reveal_by_input', false)
|
||||
if not reveal_by_input and reveal_delay == 0:
|
||||
_on_appear_mode_item_selected(0)
|
||||
if not reveal_by_input and reveal_delay != 0:
|
||||
_on_appear_mode_item_selected(1)
|
||||
if reveal_by_input and reveal_delay == 0:
|
||||
_on_appear_mode_item_selected(2)
|
||||
if reveal_by_input and reveal_delay != 0:
|
||||
_on_appear_mode_item_selected(3)
|
||||
|
||||
%RevealDelay.value = reveal_delay
|
||||
|
||||
func _on_Autofocus_toggled(button_pressed: bool) -> void:
|
||||
ProjectSettings.set_setting('dialogic/choices/autofocus_first', button_pressed)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
func _on_FalseBehaviour_item_selected(index) -> void:
|
||||
ProjectSettings.set_setting('dialogic/choices/def_false_behaviour', index)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
func _on_HotkeyType_item_selected(index) -> void:
|
||||
ProjectSettings.set_setting('dialogic/choices/hotkey_behaviour', index)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
func _on_Delay_value_changed(value) -> void:
|
||||
ProjectSettings.set_setting('dialogic/choices/delay', value)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
func _on_reveal_delay_value_changed(value) -> void:
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_delay', value)
|
||||
ProjectSettings.save()
|
||||
|
||||
|
||||
func _on_appear_mode_item_selected(index:int) -> void:
|
||||
%AppearMode.selected = index
|
||||
match index:
|
||||
0:
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_delay', 0)
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_by_input', false)
|
||||
%RevealDelay.hide()
|
||||
1:
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_delay', %RevealDelay.value)
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_by_input', false)
|
||||
%RevealDelay.show()
|
||||
2:
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_delay', 0)
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_by_input', true)
|
||||
%RevealDelay.hide()
|
||||
3:
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_delay', %RevealDelay.value)
|
||||
ProjectSettings.set_setting('dialogic/choices/reveal_by_input', true)
|
||||
%RevealDelay.show()
|
||||
ProjectSettings.save()
|
||||
1
addons/dialogic/Modules/Choice/settings_choices.gd.uid
Normal file
1
addons/dialogic/Modules/Choice/settings_choices.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://kd85nvljwky3
|
||||
176
addons/dialogic/Modules/Choice/settings_choices.tscn
Normal file
176
addons/dialogic/Modules/Choice/settings_choices.tscn
Normal file
@@ -0,0 +1,176 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://uarvgnbrcltm"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/dialogic/Modules/Choice/settings_choices.gd" id="2"]
|
||||
[ext_resource type="PackedScene" uid="uid://dbpkta2tjsqim" path="res://addons/dialogic/Editor/Common/hint_tooltip_icon.tscn" id="2_nxutt"]
|
||||
|
||||
[sub_resource type="Image" id="Image_2imc3"]
|
||||
data = {
|
||||
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
|
||||
"format": "RGBA8",
|
||||
"height": 16,
|
||||
"mipmaps": false,
|
||||
"width": 16
|
||||
}
|
||||
|
||||
[sub_resource type="ImageTexture" id="ImageTexture_udy8i"]
|
||||
image = SubResource("Image_2imc3")
|
||||
|
||||
[node name="Choices" type="VBoxContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_bottom = -227.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("2")
|
||||
|
||||
[node name="VBoxContainer2" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Title" type="Label" parent="VBoxContainer2"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Behaviour"
|
||||
|
||||
[node name="VBoxContainer" type="GridContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
columns = 2
|
||||
|
||||
[node name="AutofocusLabel" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/AutofocusLabel"]
|
||||
layout_mode = 2
|
||||
text = "Autofocus first choice"
|
||||
|
||||
[node name="Autofocus" type="CheckBox" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AppearModeLabel" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label2" type="Label" parent="VBoxContainer/AppearModeLabel"]
|
||||
layout_mode = 2
|
||||
text = "Choices appear"
|
||||
|
||||
[node name="HintTooltip" parent="VBoxContainer/AppearModeLabel" instance=ExtResource("2_nxutt")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Choices can appear either instantly when the text finished, after a delay, a click or either."
|
||||
texture = SubResource("ImageTexture_udy8i")
|
||||
hint_text = "Choices can appear either instantly when the text finished, after a delay, a click or either."
|
||||
|
||||
[node name="RevealDelayLabel" type="HBoxContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AppearMode" type="OptionButton" parent="VBoxContainer/RevealDelayLabel"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
item_count = 4
|
||||
selected = 0
|
||||
fit_to_longest_item = false
|
||||
popup/item_0/text = "Instantly"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "After delay"
|
||||
popup/item_1/id = 1
|
||||
popup/item_2/text = "After another click"
|
||||
popup/item_2/id = 2
|
||||
popup/item_3/text = "After delay or click"
|
||||
popup/item_3/id = 3
|
||||
|
||||
[node name="RevealDelay" type="SpinBox" parent="VBoxContainer/RevealDelayLabel"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
tooltip_text = "Delay after which choices will appear (in seconds)."
|
||||
step = 0.01
|
||||
|
||||
[node name="DelayLabel" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label2" type="Label" parent="VBoxContainer/DelayLabel"]
|
||||
layout_mode = 2
|
||||
text = "Delay before choices can be pressed"
|
||||
|
||||
[node name="HintTooltip2" parent="VBoxContainer/DelayLabel" instance=ExtResource("2_nxutt")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Adding a small delay before choices can be activated can prevent accidentally choosing an option."
|
||||
texture = SubResource("ImageTexture_udy8i")
|
||||
hint_text = "Adding a small delay before choices can be activated can prevent accidentally choosing an option."
|
||||
|
||||
[node name="Delay" type="SpinBox" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
step = 0.01
|
||||
|
||||
[node name="DefaultFalseBehaviourLabel" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label3" type="Label" parent="VBoxContainer/DefaultFalseBehaviourLabel"]
|
||||
layout_mode = 2
|
||||
text = "Default behaviour for false choices"
|
||||
|
||||
[node name="HintTooltip3" parent="VBoxContainer/DefaultFalseBehaviourLabel" instance=ExtResource("2_nxutt")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "Define the default behaviour (hide or disable) for choices that have a condition that isn't met.
|
||||
|
||||
Choices can overwrite this setting individually."
|
||||
texture = SubResource("ImageTexture_udy8i")
|
||||
hint_text = "Define the default behaviour (hide or disable) for choices that have a condition that isn't met.
|
||||
|
||||
Choices can overwrite this setting individually."
|
||||
|
||||
[node name="FalseBehaviour" type="OptionButton" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
item_count = 2
|
||||
selected = 0
|
||||
popup/item_0/text = "Hide"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Disable"
|
||||
popup/item_1/id = 1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HotkeySelection" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Title2" type="Label" parent="HotkeySelection"]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"DialogicSettingsSection"
|
||||
text = "Choice Hotkeys"
|
||||
|
||||
[node name="HintTooltip4" parent="HotkeySelection" instance=ExtResource("2_nxutt")]
|
||||
layout_mode = 2
|
||||
tooltip_text = "You can add more complex hotkeys (or individual ones) by editing the choice buttons of your layout scene."
|
||||
texture = SubResource("ImageTexture_udy8i")
|
||||
hint_text = "You can add more complex hotkeys (or individual ones) by editing the choice buttons of your layout scene."
|
||||
|
||||
[node name="VBoxContainer3" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Label4" type="Label" parent="VBoxContainer3"]
|
||||
layout_mode = 2
|
||||
text = "Hotkey type"
|
||||
|
||||
[node name="HotkeyType" type="OptionButton" parent="VBoxContainer3"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 4
|
||||
item_count = 2
|
||||
selected = 0
|
||||
popup/item_0/text = "No Hotkeys"
|
||||
popup/item_0/id = 0
|
||||
popup/item_1/text = "Default (1-9)"
|
||||
popup/item_1/id = 1
|
||||
|
||||
[connection signal="toggled" from="VBoxContainer/Autofocus" to="." method="_on_Autofocus_toggled"]
|
||||
[connection signal="item_selected" from="VBoxContainer/RevealDelayLabel/AppearMode" to="." method="_on_appear_mode_item_selected"]
|
||||
[connection signal="value_changed" from="VBoxContainer/RevealDelayLabel/RevealDelay" to="." method="_on_reveal_delay_value_changed"]
|
||||
[connection signal="value_changed" from="VBoxContainer/Delay" to="." method="_on_Delay_value_changed"]
|
||||
[connection signal="item_selected" from="VBoxContainer/FalseBehaviour" to="." method="_on_FalseBehaviour_item_selected"]
|
||||
[connection signal="item_selected" from="VBoxContainer3/HotkeyType" to="." method="_on_HotkeyType_item_selected"]
|
||||
281
addons/dialogic/Modules/Choice/subsystem_choices.gd
Normal file
281
addons/dialogic/Modules/Choice/subsystem_choices.gd
Normal file
@@ -0,0 +1,281 @@
|
||||
extends DialogicSubsystem
|
||||
|
||||
## Subsystem that manages showing and activating of choices.
|
||||
|
||||
## Emitted when a choice button was pressed. Info includes the keys 'button_index', 'text', 'event_index'.
|
||||
signal choice_selected(info:Dictionary)
|
||||
## Emitted when a set of choices is reached and shown.
|
||||
## Info includes the keys 'choices' (an array of dictionaries with infos on all the choices).
|
||||
signal question_shown(info:Dictionary)
|
||||
|
||||
## Contains information on the latest question.
|
||||
var last_question_info := {}
|
||||
|
||||
## The delay between the text finishing revealing and the choices appearing
|
||||
var reveal_delay := 0.0
|
||||
## If true the player has to click to reveal choices when they are reached
|
||||
var reveal_by_input := false
|
||||
## The delay between the choices becoming visible and being clickable. Can prevent accidental selection.
|
||||
var block_delay := 0.2
|
||||
## If true, the first (top-most) choice will be focused
|
||||
var autofocus_first_choice := true
|
||||
## If true the dialogic input action is used to trigger choices.
|
||||
## However mouse events will be ignored no matter what.
|
||||
var use_input_action := false
|
||||
|
||||
enum FalseBehaviour {HIDE=0, DISABLE=1}
|
||||
## The behaviour of choices with a false condition and else_action set to DEFAULT.
|
||||
var default_false_behaviour := FalseBehaviour.HIDE
|
||||
|
||||
enum HotkeyBehaviour {NONE, NUMBERS}
|
||||
## Will add some hotkeys to the choices if different then HotkeyBehaviour.NONE.
|
||||
var hotkey_behaviour := HotkeyBehaviour.NONE
|
||||
|
||||
|
||||
### INTERNALS
|
||||
|
||||
## Used to block choices from being clicked for a couple of seconds (if delay is set in settings).
|
||||
var _choice_blocker := Timer.new()
|
||||
|
||||
#region STATE
|
||||
####################################################################################################
|
||||
|
||||
func clear_game_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void:
|
||||
hide_all_choices()
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_choice_blocker.one_shot = true
|
||||
DialogicUtil.update_timer_process_callback(_choice_blocker)
|
||||
add_child(_choice_blocker)
|
||||
|
||||
reveal_delay = float(ProjectSettings.get_setting('dialogic/choices/reveal_delay', reveal_delay))
|
||||
reveal_by_input = ProjectSettings.get_setting('dialogic/choices/reveal_by_input', reveal_by_input)
|
||||
block_delay = ProjectSettings.get_setting('dialogic/choices/delay', block_delay)
|
||||
autofocus_first_choice = ProjectSettings.get_setting('dialogic/choices/autofocus_first', autofocus_first_choice)
|
||||
hotkey_behaviour = ProjectSettings.get_setting('dialogic/choices/hotkey_behaviour', hotkey_behaviour)
|
||||
default_false_behaviour = ProjectSettings.get_setting('dialogic/choices/def_false_behaviour', default_false_behaviour)
|
||||
|
||||
|
||||
func post_install() -> void:
|
||||
dialogic.Inputs.dialogic_action.connect(_on_dialogic_action)
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MAIN METHODS
|
||||
####################################################################################################
|
||||
|
||||
## Hides all choice buttons.
|
||||
func hide_all_choices() -> void:
|
||||
for node in get_tree().get_nodes_in_group('dialogic_choice_button'):
|
||||
node.hide()
|
||||
if node.is_connected('button_up', _on_choice_selected):
|
||||
node.disconnect('button_up', _on_choice_selected)
|
||||
|
||||
|
||||
## Collects information on all the choices of the current question.
|
||||
## The result is a dictionary like this:
|
||||
## {'choices':
|
||||
## [
|
||||
## {'event_index':10, 'button_index':1, 'disabled':false, 'text':"My Choice", 'visible':true},
|
||||
## {'event_index':15, 'button_index':2, 'disabled':false, 'text':"My Choice2", 'visible':true},
|
||||
## ]
|
||||
func get_current_question_info() -> Dictionary:
|
||||
var question_info := {'choices':[]}
|
||||
|
||||
var button_idx := 1
|
||||
last_question_info = {'choices':[]}
|
||||
|
||||
for choice_index in get_current_choice_indexes():
|
||||
var event: DialogicEvent = dialogic.current_timeline_events[choice_index]
|
||||
|
||||
if not event is DialogicChoiceEvent:
|
||||
continue
|
||||
|
||||
var choice_event: DialogicChoiceEvent = event
|
||||
var choice_info := {}
|
||||
choice_info['event_index'] = choice_index
|
||||
choice_info['button_index'] = button_idx
|
||||
|
||||
# Check Condition
|
||||
var condition: String = choice_event.condition
|
||||
|
||||
if condition.is_empty() or dialogic.Expressions.execute_condition(choice_event.condition):
|
||||
choice_info['disabled'] = false
|
||||
choice_info['text'] = choice_event.get_property_translated('text')
|
||||
choice_info['visible'] = true
|
||||
button_idx += 1
|
||||
else:
|
||||
choice_info['disabled'] = true
|
||||
if not choice_event.disabled_text.is_empty():
|
||||
choice_info['text'] = choice_event.get_property_translated('disabled_text')
|
||||
else:
|
||||
choice_info['text'] = choice_event.get_property_translated('text')
|
||||
|
||||
var hide := choice_event.else_action == DialogicChoiceEvent.ElseActions.HIDE
|
||||
hide = hide or choice_event.else_action == DialogicChoiceEvent.ElseActions.DEFAULT and default_false_behaviour == DialogicChoiceEvent.ElseActions.HIDE
|
||||
choice_info['visible'] = not hide
|
||||
|
||||
if not hide:
|
||||
button_idx += 1
|
||||
|
||||
choice_info.text = dialogic.Text.parse_text(choice_info.text, true, true, false, true, false, false)
|
||||
|
||||
choice_info.merge(choice_event.extra_data)
|
||||
|
||||
if dialogic.has_subsystem('History'):
|
||||
choice_info['visited_before'] = dialogic.History.has_event_been_visited(choice_index)
|
||||
|
||||
question_info['choices'].append(choice_info)
|
||||
|
||||
return question_info
|
||||
|
||||
|
||||
## Lists all current choices and shows buttons.
|
||||
func show_current_question(instant:=true) -> void:
|
||||
hide_all_choices()
|
||||
_choice_blocker.stop()
|
||||
|
||||
if !instant and (reveal_delay != 0 or reveal_by_input):
|
||||
if reveal_delay != 0:
|
||||
_choice_blocker.start(reveal_delay)
|
||||
_choice_blocker.timeout.connect(show_current_question)
|
||||
if reveal_by_input:
|
||||
dialogic.Inputs.dialogic_action.connect(show_current_question)
|
||||
return
|
||||
|
||||
if _choice_blocker.timeout.is_connected(show_current_question):
|
||||
_choice_blocker.timeout.disconnect(show_current_question)
|
||||
if dialogic.Inputs.dialogic_action.is_connected(show_current_question):
|
||||
dialogic.Inputs.dialogic_action.disconnect(show_current_question)
|
||||
|
||||
var missing_button := false
|
||||
|
||||
var question_info := get_current_question_info()
|
||||
|
||||
for choice in question_info.choices:
|
||||
var node: DialogicNode_ChoiceButton = get_choice_button_node(choice.button_index)
|
||||
|
||||
if not node:
|
||||
missing_button = true
|
||||
continue
|
||||
|
||||
node._load_info(choice)
|
||||
|
||||
if choice.button_index == 1 and autofocus_first_choice:
|
||||
node.grab_focus()
|
||||
|
||||
match hotkey_behaviour:
|
||||
## Add 1 to 9 as shortcuts if it's enabled
|
||||
HotkeyBehaviour.NUMBERS:
|
||||
if choice.button_index > 0 or choice.button_index < 10:
|
||||
var shortcut: Shortcut
|
||||
if node.shortcut != null:
|
||||
shortcut = node.shortcut
|
||||
else:
|
||||
shortcut = Shortcut.new()
|
||||
|
||||
var input_key := InputEventKey.new()
|
||||
input_key.keycode = OS.find_keycode_from_string(str(choice.button_index))
|
||||
shortcut.events.append(input_key)
|
||||
node.shortcut = shortcut
|
||||
|
||||
if node.pressed.is_connected(_on_choice_selected):
|
||||
node.pressed.disconnect(_on_choice_selected)
|
||||
node.pressed.connect(_on_choice_selected.bind(choice))
|
||||
|
||||
_choice_blocker.start(block_delay)
|
||||
question_shown.emit(question_info)
|
||||
|
||||
if missing_button:
|
||||
printerr("[Dialogic] The layout you are using doesn't have enough Choice Buttons for the choices you are trying to display.")
|
||||
|
||||
|
||||
|
||||
func get_choice_button_node(button_index:int) -> DialogicNode_ChoiceButton:
|
||||
var idx := 1
|
||||
for node: DialogicNode_ChoiceButton in get_tree().get_nodes_in_group('dialogic_choice_button'):
|
||||
if !node.get_parent().is_visible_in_tree():
|
||||
continue
|
||||
if node.choice_index == button_index or (node.choice_index == -1 and idx == button_index):
|
||||
return node
|
||||
|
||||
if node.choice_index > 0:
|
||||
idx = node.choice_index
|
||||
idx += 1
|
||||
|
||||
return null
|
||||
|
||||
|
||||
func _on_choice_selected(choice_info := {}) -> void:
|
||||
if dialogic.paused or not _choice_blocker.is_stopped():
|
||||
return
|
||||
|
||||
if dialogic.has_subsystem('History'):
|
||||
var all_choices: Array = dialogic.Choices.last_question_info['choices']
|
||||
if dialogic.has_subsystem('VAR'):
|
||||
dialogic.History.store_simple_history_entry(dialogic.VAR.parse_variables(choice_info.text), "Choice", {'all_choices': all_choices})
|
||||
else:
|
||||
dialogic.History.store_simple_history_entry(choice_info.text, "Choice", {'all_choices': all_choices})
|
||||
if dialogic.has_subsystem("History"):
|
||||
dialogic.History.mark_event_as_visited(choice_info.event_index)
|
||||
|
||||
choice_selected.emit(choice_info)
|
||||
hide_all_choices()
|
||||
dialogic.current_state = dialogic.States.IDLE
|
||||
dialogic.handle_event(choice_info.event_index + 1)
|
||||
|
||||
|
||||
|
||||
func get_current_choice_indexes() -> Array:
|
||||
var choices := []
|
||||
var evt_idx := dialogic.current_event_idx
|
||||
var ignore := 0
|
||||
while true:
|
||||
if evt_idx >= len(dialogic.current_timeline_events):
|
||||
break
|
||||
if dialogic.current_timeline_events[evt_idx] is DialogicChoiceEvent:
|
||||
if ignore == 0:
|
||||
choices.append(evt_idx)
|
||||
ignore += 1
|
||||
elif dialogic.current_timeline_events[evt_idx].can_contain_events:
|
||||
ignore += 1
|
||||
else:
|
||||
if ignore == 0:
|
||||
break
|
||||
|
||||
if dialogic.current_timeline_events[evt_idx] is DialogicEndBranchEvent:
|
||||
ignore -= 1
|
||||
evt_idx += 1
|
||||
return choices
|
||||
|
||||
|
||||
func _on_dialogic_action() -> void:
|
||||
if get_viewport().gui_get_focus_owner() is DialogicNode_ChoiceButton and use_input_action and not dialogic.Inputs.input_was_mouse_input:
|
||||
get_viewport().gui_get_focus_owner().pressed.emit()
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region HELPERS
|
||||
####################################################################################################
|
||||
|
||||
func is_question(index:int) -> bool:
|
||||
if dialogic.current_timeline_events[index] is DialogicTextEvent:
|
||||
if len(dialogic.current_timeline_events)-1 != index:
|
||||
if dialogic.current_timeline_events[index+1] is DialogicChoiceEvent:
|
||||
return true
|
||||
|
||||
if dialogic.current_timeline_events[index] is DialogicChoiceEvent:
|
||||
if index != 0 and dialogic.current_timeline_events[index-1] is DialogicEndBranchEvent:
|
||||
if dialogic.current_timeline_events[dialogic.current_timeline_events[index-1].find_opening_index(index-1)] is DialogicChoiceEvent:
|
||||
return false
|
||||
else:
|
||||
return true
|
||||
else:
|
||||
return true
|
||||
return false
|
||||
|
||||
#endregion
|
||||
1
addons/dialogic/Modules/Choice/subsystem_choices.gd.uid
Normal file
1
addons/dialogic/Modules/Choice/subsystem_choices.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bi55xu42c0n1w
|
||||
28
addons/dialogic/Modules/Choice/ui_choice_end.gd
Normal file
28
addons/dialogic/Modules/Choice/ui_choice_end.gd
Normal file
@@ -0,0 +1,28 @@
|
||||
@tool
|
||||
extends HBoxContainer
|
||||
|
||||
var parent_resource: DialogicChoiceEvent = null
|
||||
|
||||
func refresh() -> void:
|
||||
$AddChoice.icon = get_theme_icon("Add", "EditorIcons")
|
||||
|
||||
if parent_resource is DialogicChoiceEvent:
|
||||
show()
|
||||
if len(parent_resource.text) > 12:
|
||||
$Label.text = "End of choice ("+parent_resource.text.substr(0,12)+"...)"
|
||||
else:
|
||||
$Label.text = "End of choice ("+parent_resource.text+")"
|
||||
else:
|
||||
hide()
|
||||
|
||||
|
||||
func _on_add_choice_pressed() -> void:
|
||||
var timeline := find_parent('VisualEditor')
|
||||
if timeline:
|
||||
var resource := DialogicChoiceEvent.new()
|
||||
resource.created_by_button = true
|
||||
timeline.add_event_undoable(resource, get_parent().get_index()+1)
|
||||
timeline.indent_events()
|
||||
timeline.something_changed()
|
||||
# Prevent focusing on future redos
|
||||
resource.created_by_button = false
|
||||
1
addons/dialogic/Modules/Choice/ui_choice_end.gd.uid
Normal file
1
addons/dialogic/Modules/Choice/ui_choice_end.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bb3j445woxpnm
|
||||
20
addons/dialogic/Modules/Choice/ui_choice_end.tscn
Normal file
20
addons/dialogic/Modules/Choice/ui_choice_end.tscn
Normal file
@@ -0,0 +1,20 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cn0wbb2lk0s22"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/dialogic/Modules/Choice/ui_choice_end.gd" id="1_7qd85"]
|
||||
|
||||
[node name="Choice_End" type="HBoxContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_bottom = -625.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_7qd85")
|
||||
|
||||
[node name="AddChoice" type="Button" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[connection signal="pressed" from="AddChoice" to="." method="_on_add_choice_pressed"]
|
||||
Reference in New Issue
Block a user