121 lines
5.4 KiB
GDScript
121 lines
5.4 KiB
GDScript
class_name DialogicNode_ChoiceButton
|
|
extends Button
|
|
## This button allows the player to make a choice in the Dialogic system.
|
|
##
|
|
## 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.
|
|
@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.
|
|
## This can be used to have a custom text rendering child, like a RichTextLabel.
|
|
@export var text_node: Node
|
|
|
|
|
|
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
|
|
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
|
|
|
|
|
|
## 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
|