Adding simple dialog system
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
extends CanvasLayer
|
||||
|
||||
var _interactables: Array[Node] = []
|
||||
var _active_interactable: Node = null
|
||||
var _dialog_visible := false
|
||||
|
||||
var _prompt_label: Label
|
||||
var _dialog_panel: PanelContainer
|
||||
var _dialog_label: RichTextLabel
|
||||
|
||||
func _ready() -> void:
|
||||
layer = 50
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
_setup_ui()
|
||||
_set_dialog_visible(false)
|
||||
_update_prompt_visibility()
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if Input.is_action_just_pressed("interact"):
|
||||
if _dialog_visible:
|
||||
_set_dialog_visible(false)
|
||||
return
|
||||
if _active_interactable != null:
|
||||
_open_dialog_for(_active_interactable)
|
||||
|
||||
|
||||
func register_interactable(interactable: Node) -> void:
|
||||
if interactable == null:
|
||||
return
|
||||
if _interactables.has(interactable):
|
||||
return
|
||||
_interactables.append(interactable)
|
||||
_refresh_active_interactable()
|
||||
|
||||
|
||||
func unregister_interactable(interactable: Node) -> void:
|
||||
if interactable == null:
|
||||
return
|
||||
_interactables.erase(interactable)
|
||||
if _active_interactable == interactable and _dialog_visible:
|
||||
_set_dialog_visible(false)
|
||||
_refresh_active_interactable()
|
||||
|
||||
|
||||
func _refresh_active_interactable() -> void:
|
||||
while _interactables.size() > 0 and not is_instance_valid(_interactables[_interactables.size() - 1]):
|
||||
_interactables.pop_back()
|
||||
_active_interactable = _interactables[_interactables.size() - 1] if _interactables.size() > 0 else null
|
||||
if _dialog_visible and _active_interactable != null:
|
||||
_dialog_label.text = _get_dialog_text(_active_interactable)
|
||||
_update_prompt_visibility()
|
||||
|
||||
|
||||
func _open_dialog_for(interactable: Node) -> void:
|
||||
if _dialog_label:
|
||||
_dialog_label.text = _get_dialog_text(interactable)
|
||||
_set_dialog_visible(true)
|
||||
|
||||
|
||||
func show_text(text: String) -> void:
|
||||
if _dialog_label:
|
||||
_dialog_label.text = text
|
||||
_set_dialog_visible(true)
|
||||
|
||||
|
||||
func close_if_text(expected_text: String) -> void:
|
||||
if not _dialog_visible:
|
||||
return
|
||||
if _dialog_label == null:
|
||||
return
|
||||
if _dialog_label.text != expected_text:
|
||||
return
|
||||
_set_dialog_visible(false)
|
||||
|
||||
|
||||
func _set_dialog_visible(dialog_open: bool) -> void:
|
||||
_dialog_visible = dialog_open
|
||||
if _dialog_panel:
|
||||
_dialog_panel.visible = _dialog_visible
|
||||
_update_prompt_visibility()
|
||||
|
||||
|
||||
func _update_prompt_visibility() -> void:
|
||||
if _prompt_label == null:
|
||||
return
|
||||
var has_active := _active_interactable != null
|
||||
_prompt_label.visible = has_active and not _dialog_visible
|
||||
if _prompt_label.visible:
|
||||
_prompt_label.text = _get_prompt_text(_active_interactable)
|
||||
|
||||
|
||||
func _get_prompt_text(interactable: Node) -> String:
|
||||
if interactable == null:
|
||||
return ""
|
||||
if interactable.has_method("get_dialog_prompt"):
|
||||
return String(interactable.call("get_dialog_prompt"))
|
||||
return "Press E to interact"
|
||||
|
||||
|
||||
func _get_dialog_text(interactable: Node) -> String:
|
||||
if interactable == null:
|
||||
return ""
|
||||
if interactable.has_method("get_dialog_text"):
|
||||
return String(interactable.call("get_dialog_text"))
|
||||
return "..."
|
||||
|
||||
|
||||
func _setup_ui() -> void:
|
||||
var root := Control.new()
|
||||
root.name = "DialogRoot"
|
||||
root.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
root.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
add_child(root)
|
||||
|
||||
_prompt_label = Label.new()
|
||||
_prompt_label.name = "PromptLabel"
|
||||
_prompt_label.set_anchors_preset(Control.PRESET_CENTER_BOTTOM)
|
||||
_prompt_label.offset_left = -140.0
|
||||
_prompt_label.offset_top = -64.0
|
||||
_prompt_label.offset_right = 140.0
|
||||
_prompt_label.offset_bottom = -36.0
|
||||
_prompt_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
_prompt_label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_prompt_label.text = "Press E to interact"
|
||||
root.add_child(_prompt_label)
|
||||
|
||||
_dialog_panel = PanelContainer.new()
|
||||
_dialog_panel.name = "DialogPanel"
|
||||
_dialog_panel.visible = false
|
||||
_dialog_panel.set_anchors_preset(Control.PRESET_CENTER_BOTTOM)
|
||||
_dialog_panel.offset_left = -300.0
|
||||
_dialog_panel.offset_top = -220.0
|
||||
_dialog_panel.offset_right = 300.0
|
||||
_dialog_panel.offset_bottom = -80.0
|
||||
_dialog_panel.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
root.add_child(_dialog_panel)
|
||||
|
||||
_dialog_label = RichTextLabel.new()
|
||||
_dialog_label.name = "DialogText"
|
||||
_dialog_label.custom_minimum_size = Vector2(560.0, 120.0)
|
||||
_dialog_label.fit_content = true
|
||||
_dialog_label.scroll_active = false
|
||||
_dialog_label.bbcode_enabled = true
|
||||
_dialog_label.text = ""
|
||||
_dialog_panel.add_child(_dialog_label)
|
||||
@@ -0,0 +1 @@
|
||||
uid://be24usagr8kml
|
||||
Reference in New Issue
Block a user