mirror of
https://gitlab.com/MaddoScientisto/cirnogodot.git
synced 2026-06-17 18:13:47 +00:00
Updated dialogic
This commit is contained in:
parent
1d11462073
commit
cbb82512ee
483 changed files with 5743 additions and 2177 deletions
|
|
@ -37,6 +37,10 @@ func _execute() -> void:
|
|||
dialogic.Choices.show_current_question(false)
|
||||
dialogic.current_state = dialogic.States.AWAITING_CHOICE
|
||||
|
||||
|
||||
func _is_branch_starter() -> bool:
|
||||
return dialogic.Choices.is_question(dialogic.current_timeline_events.find(self))
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
|
@ -53,7 +57,7 @@ func _init() -> void:
|
|||
|
||||
|
||||
# return a control node that should show on the END BRANCH node
|
||||
func get_end_branch_control() -> Control:
|
||||
func _get_end_branch_control() -> Control:
|
||||
return load(get_script().resource_path.get_base_dir().path_join('ui_choice_end.tscn')).instantiate()
|
||||
#endregion
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
uid://evfcdip3607c
|
||||
uid://cltu1tykths0n
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
uid://cpp7qjji6ck8p
|
||||
uid://bo0dqybasbqd
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
uid://bijk2aslmrx2r
|
||||
uid://b1stj4ljd2vo7
|
||||
|
|
|
|||
|
|
@ -1,15 +1,28 @@
|
|||
class_name DialogicNode_ChoiceButton
|
||||
extends Button
|
||||
## The button allows the player to make a choice in the Dialogic system.
|
||||
## This 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.
|
||||
## When a choice is reached Dialogic will automatically show ChoiceButtons
|
||||
## and call their [code]_load_info()[/code] method which will display the choices.
|
||||
## You will need to ensure that enough choice buttons are available in the tree
|
||||
## to display all choices.[br]
|
||||
##
|
||||
## [br]
|
||||
## You can extend this node and implement some custom logic by overwriting
|
||||
## the [code]_load_info(info:Dictionary)[/code] method. [br]
|
||||
## [br]
|
||||
## If you need RichText support, consider adding a RichTextLabel child and setting it as the [member text_node].[br]
|
||||
##
|
||||
## [br]
|
||||
## DialogicChoiceButtons will grab the focus when hovered to avoid a confusing
|
||||
## focus style being present for players who use the mouse.[br]
|
||||
## To avoid the opposite situation, when the focus is changed by the player
|
||||
## and a different button is still hovered the mouse pointer will be moved
|
||||
## to the now focused button as well.
|
||||
|
||||
|
||||
## Emitted when the choice is selected. Unless overridden, this is when the button or its shortcut is pressed.
|
||||
signal choice_selected
|
||||
|
||||
|
||||
## Used to identify what choices to put on. If you leave it at -1, choices will be distributed automatically.
|
||||
|
|
@ -21,7 +34,9 @@ extends Button
|
|||
@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.
|
||||
|
||||
## If set, the text will be set on this node's `text` property instead.
|
||||
## This can be used to have a custom text rendering child, like a RichTextLabel.
|
||||
@export var text_node: Node
|
||||
|
||||
|
||||
|
|
@ -29,8 +44,34 @@ func _ready() -> void:
|
|||
add_to_group('dialogic_choice_button')
|
||||
shortcut_in_tooltip = false
|
||||
hide()
|
||||
|
||||
# For players who use a mouse to make choices, mouse hover should grab focus.
|
||||
# Otherwise the auto-focused button will always show a highlighted color when
|
||||
# the mouse cursor is hovering on another button.
|
||||
if not mouse_entered.is_connected(grab_focus):
|
||||
mouse_entered.connect(grab_focus)
|
||||
if not focus_entered.is_connected(_on_choice_button_focus_entred):
|
||||
focus_entered.connect(_on_choice_button_focus_entred.bind(self))
|
||||
|
||||
|
||||
## Custom choice buttons can override this for specialized behavior when the choice button is pressed.
|
||||
func _pressed():
|
||||
choice_selected.emit()
|
||||
|
||||
|
||||
## Custom choice buttons can override this if their behavior should change
|
||||
## based on event data. If the custom choice button does not override
|
||||
## visibility, disabled-ness, nor the choice text, consider
|
||||
## calling super(choice_info) at the start of the override.
|
||||
##
|
||||
## The choice_info Dictionary has the following keys:
|
||||
## - event_index: The index of the choice event in the timeline.
|
||||
## - button_index: The relative index of the choice (starts from 1).
|
||||
## - visible: If the choice should be visible.
|
||||
## - disabled: If the choice should be selectable.
|
||||
## - text: The text of the choice.
|
||||
## - visited_before: If the choice has been selected before. Only available is the History submodule is enabled.
|
||||
## - *: Information from the event's additional info.
|
||||
func _load_info(choice_info: Dictionary) -> void:
|
||||
set_choice_text(choice_info.text)
|
||||
visible = choice_info.visible
|
||||
|
|
@ -43,3 +84,37 @@ func set_choice_text(new_text: String) -> void:
|
|||
text_node.text = new_text
|
||||
else:
|
||||
text = new_text
|
||||
|
||||
|
||||
## This method moves the mouse to the focused choice when the focus changes
|
||||
## while a choice button was hovered. [br]
|
||||
## For players who use many devices (mouse/keyboard/gamepad, etc) at the same time to make choices,
|
||||
## a grabing-focus triggered by keyboard/gamepad should also change the mouse cursor's
|
||||
## position otherwise two buttons will have highlighted color(one highlighted button
|
||||
## triggered by mouse hover and another highlighted button triggered by other devices' choice).
|
||||
func _on_choice_button_focus_entred(focused_button: Button):
|
||||
var global_mouse_pos = get_global_mouse_position()
|
||||
var focused_button_rect = focused_button.get_global_rect()
|
||||
if focused_button_rect.has_point(global_mouse_pos):
|
||||
return
|
||||
# Only change mouse curor position when an unfocused button' rect has the cursor.
|
||||
for node in get_tree().get_nodes_in_group('dialogic_choice_button'):
|
||||
if node is Button:
|
||||
if node != focused_button and node.get_global_rect().has_point(global_mouse_pos):
|
||||
# We prefer to change only mouse_position.y or mouse_position.x to warp the
|
||||
# mouse to the focused button's rect to achieve the best visual effect.
|
||||
var modify_y_pos = Vector2(global_mouse_pos.x, focused_button.get_global_rect().get_center().y)
|
||||
if focused_button_rect.has_point(modify_y_pos):
|
||||
get_viewport().warp_mouse(modify_y_pos)
|
||||
return
|
||||
|
||||
var modify_x_pos = Vector2(focused_button.get_global_rect().get_center().x, global_mouse_pos.y)
|
||||
if focused_button_rect.has_point(modify_x_pos):
|
||||
get_viewport().warp_mouse(modify_x_pos)
|
||||
return
|
||||
|
||||
# Maybe the buttons are not aligned as vertically or horizontlly.
|
||||
# Or perhaps the length difference between the two buttons is quite large.
|
||||
# So we just make the cursor hover on the center of the focused button.
|
||||
get_viewport().warp_mouse(focused_button.get_global_rect().get_center())
|
||||
return
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
uid://bcirqrep7rvr4
|
||||
uid://bldt7xlfum7ov
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
uid://cyog6egbjdhg0
|
||||
uid://dbbbq1hcbhmi2
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=5 format=3 uid="uid://uarvgnbrcltm"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://cyog6egbjdhg0" path="res://addons/dialogic/Modules/Choice/settings_choices.gd" id="2"]
|
||||
[ext_resource type="Script" uid="uid://dbbbq1hcbhmi2" 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_xvnnc"]
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@ func post_install() -> void:
|
|||
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)
|
||||
if node.choice_selected.is_connected(_on_choice_selected):
|
||||
node.choice_selected.disconnect(_on_choice_selected)
|
||||
|
||||
|
||||
## Collects information on all the choices of the current question.
|
||||
|
|
@ -120,7 +120,7 @@ func get_current_question_info() -> Dictionary:
|
|||
if not hide:
|
||||
button_idx += 1
|
||||
|
||||
choice_info.text = dialogic.Text.parse_text(choice_info.text, true, true, false, true, false, false)
|
||||
choice_info.text = dialogic.Text.parse_text(choice_info.text, 1)
|
||||
|
||||
choice_info.merge(choice_event.extra_data)
|
||||
|
||||
|
|
@ -128,6 +128,7 @@ func get_current_question_info() -> Dictionary:
|
|||
choice_info['visited_before'] = dialogic.History.has_event_been_visited(choice_index)
|
||||
|
||||
question_info['choices'].append(choice_info)
|
||||
last_question_info['choices'].append(choice_info['text'])
|
||||
|
||||
return question_info
|
||||
|
||||
|
|
@ -155,7 +156,7 @@ func show_current_question(instant:=true) -> void:
|
|||
var question_info := get_current_question_info()
|
||||
|
||||
for choice in question_info.choices:
|
||||
var node: DialogicNode_ChoiceButton = get_choice_button_node(choice.button_index)
|
||||
var node: DialogicNode_ChoiceButton = get_choice_button(choice.button_index)
|
||||
|
||||
if not node:
|
||||
missing_button = true
|
||||
|
|
@ -181,9 +182,9 @@ func show_current_question(instant:=true) -> void:
|
|||
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))
|
||||
if node.choice_selected.is_connected(_on_choice_selected):
|
||||
node.choice_selected.disconnect(_on_choice_selected)
|
||||
node.choice_selected.connect(_on_choice_selected.bind(choice))
|
||||
|
||||
_choice_blocker.start(block_delay)
|
||||
question_shown.emit(question_info)
|
||||
|
|
@ -192,8 +193,24 @@ func show_current_question(instant:=true) -> void:
|
|||
printerr("[Dialogic] The layout you are using doesn't have enough Choice Buttons for the choices you are trying to display.")
|
||||
|
||||
|
||||
func focus_choice(button_index:int) -> void:
|
||||
var node: DialogicNode_ChoiceButton = get_choice_button(button_index)
|
||||
if node:
|
||||
node.grab_focus()
|
||||
|
||||
func get_choice_button_node(button_index:int) -> DialogicNode_ChoiceButton:
|
||||
|
||||
func select_choice(button_index:int) -> void:
|
||||
var node: DialogicNode_ChoiceButton = get_choice_button(button_index)
|
||||
if node:
|
||||
node.choice_selected.emit()
|
||||
|
||||
|
||||
func select_focused_choice() -> void:
|
||||
if get_viewport().gui_get_focus_owner() is DialogicNode_ChoiceButton:
|
||||
(get_viewport().gui_get_focus_owner() as DialogicNode_ChoiceButton).choice_selected.emit()
|
||||
|
||||
|
||||
func get_choice_button(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():
|
||||
|
|
@ -227,33 +244,29 @@ func _on_choice_selected(choice_info := {}) -> void:
|
|||
dialogic.handle_event(choice_info.event_index + 1)
|
||||
|
||||
|
||||
|
||||
## Returns the indexes of the choice events related to the current question.
|
||||
func get_current_choice_indexes() -> Array:
|
||||
var choices := []
|
||||
var evt_idx := dialogic.current_event_idx
|
||||
var ignore := 0
|
||||
var index := dialogic.current_event_idx-1
|
||||
while true:
|
||||
if evt_idx >= len(dialogic.current_timeline_events):
|
||||
index += 1
|
||||
if index >= len(dialogic.current_timeline_events):
|
||||
break
|
||||
|
||||
var event: DialogicEvent = dialogic.current_timeline_events[index]
|
||||
if event is DialogicChoiceEvent:
|
||||
choices.append(index)
|
||||
index = event.get_end_branch_index()
|
||||
else:
|
||||
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
|
||||
|
||||
|
||||
## Forward the dialogic action to the focused button
|
||||
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()
|
||||
if use_input_action and not dialogic.Inputs.input_was_mouse_input:
|
||||
select_focused_choice()
|
||||
|
||||
|
||||
#endregion
|
||||
|
|
@ -262,20 +275,27 @@ func _on_dialogic_action() -> void:
|
|||
#region HELPERS
|
||||
####################################################################################################
|
||||
|
||||
## Returns `true` if the given index is a text event before a question or the first choice event of a question.
|
||||
func is_question(index:int) -> bool:
|
||||
if dialogic.current_timeline_events[index] is DialogicTextEvent:
|
||||
var event: DialogicEvent = dialogic.current_timeline_events[index]
|
||||
if event is DialogicTextEvent:
|
||||
if len(dialogic.current_timeline_events)-1 != index:
|
||||
if dialogic.current_timeline_events[index+1] is DialogicChoiceEvent:
|
||||
var next_event: DialogicEvent = dialogic.current_timeline_events[index+1]
|
||||
if next_event 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
|
||||
if event is DialogicChoiceEvent:
|
||||
if index == 0:
|
||||
return true
|
||||
var prev_event: DialogicEvent = dialogic.current_timeline_events[index-1]
|
||||
if not prev_event is DialogicEndBranchEvent:
|
||||
return true
|
||||
var prev_event_opener: DialogicEvent = dialogic.current_timeline_events[prev_event.get_opening_index()]
|
||||
if prev_event_opener is DialogicChoiceEvent:
|
||||
return false
|
||||
else:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
#endregion
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
uid://70q8j1ji8wm
|
||||
uid://cewv4d3aw0kj3
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
uid://yt5h64x4n67s
|
||||
uid://d28x7h2ufh3dd
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://cn0wbb2lk0s22"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://yt5h64x4n67s" path="res://addons/dialogic/Modules/Choice/ui_choice_end.gd" id="1_7qd85"]
|
||||
[ext_resource type="Script" uid="uid://d28x7h2ufh3dd" path="res://addons/dialogic/Modules/Choice/ui_choice_end.gd" id="1_7qd85"]
|
||||
|
||||
[node name="Choice_End" type="HBoxContainer"]
|
||||
anchors_preset = 15
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue