initial shit
This commit is contained in:
135
addons/orchestrator/scenes/dialogue_message.gd
Normal file
135
addons/orchestrator/scenes/dialogue_message.gd
Normal file
@@ -0,0 +1,135 @@
|
||||
## This file is part of the Godot Orchestrator project.
|
||||
##
|
||||
## Copyright (c) 2023-present Crater Crash Studios LLC and its contributors.
|
||||
##
|
||||
## Licensed under the Apache License, Version 2.0 (the "License");
|
||||
## you may not use this file except in compliance with the License.
|
||||
## You may obtain a copy of the License at
|
||||
##
|
||||
## http://www.apache.org/licenses/LICENSE-2.0
|
||||
##
|
||||
## Unless required by applicable law or agreed to in writing, software
|
||||
## distributed under the License is distributed on an "AS IS" BASIS,
|
||||
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
## See the License for the specific language governing permissions and
|
||||
## limitations under the License.
|
||||
##
|
||||
extends CanvasLayer
|
||||
|
||||
## A required signal that should be emitted when the Dialogue UI completes
|
||||
## all its user interactions. This informs Orchestrator that it is then
|
||||
## safe to proceed to the next node/step in the visual script workflow.
|
||||
signal show_message_finished()
|
||||
|
||||
## The speed that the text will be rendered, i.e. typewriter
|
||||
const TEXT_SPEED = 0.03
|
||||
|
||||
## Holds data passed by Orchestrator the Dialogue UI
|
||||
##
|
||||
## By default attributes are passed into this dictionary as:
|
||||
## "character_name" -> the name of the character speaking
|
||||
## "message" -> the text to be shown
|
||||
## "options" -> an array of text to be shown as choices
|
||||
##
|
||||
var dialogue_data : Dictionary
|
||||
|
||||
## Requirede by Orchestrator, passes the selected choice from
|
||||
## the Dialogue UI back to the OrchestratorScript.
|
||||
var selection : int
|
||||
|
||||
var _current_tween : Tween
|
||||
var _current_choices : Dictionary
|
||||
var _mouse_mode : Input.MouseMode
|
||||
|
||||
@onready var speaker = $MarginContainer/PanelContainer/MarginContainer/VBoxContainer/Speaker
|
||||
@onready var speaker_text = $MarginContainer/PanelContainer/MarginContainer/VBoxContainer/SpeakerText
|
||||
@onready var response_tpl = $MarginContainer/PanelContainer/MarginContainer/VBoxContainer/ResponseTemplate
|
||||
@onready var next_button = $MarginContainer/PanelContainer/MarginContainer/VBoxContainer/NextButton
|
||||
|
||||
func _ready() -> void:
|
||||
response_tpl.visible = false
|
||||
next_button.visible = false
|
||||
visible = false
|
||||
|
||||
## If the mouse is currently hidden, make it visible until the
|
||||
## player makes a selection in the dialog scene
|
||||
_mouse_mode = Input.mouse_mode
|
||||
if _mouse_mode == Input.MOUSE_MODE_HIDDEN:
|
||||
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||
|
||||
## Setup what to do if there are no options and the next button
|
||||
## is shown, which is "Continue". In this case the selection is
|
||||
## set as -1 and the signal gets emitted.
|
||||
var button_handler := func():
|
||||
selection = -1
|
||||
_dialogue_finished()
|
||||
next_button.pressed.connect(button_handler)
|
||||
|
||||
## Grab data from Orchestrator dictionary to present the UI
|
||||
var character_name = dialogue_data["character_name"]
|
||||
var message = dialogue_data["message"]
|
||||
var options = dialogue_data["options"]
|
||||
show_message(character_name, message, options)
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event is InputEventKey:
|
||||
if event.is_pressed() and _should_end_typing(event.keycode):
|
||||
if _current_tween.is_running():
|
||||
_current_tween.stop()
|
||||
speaker_text.visible_characters = speaker_text.text.length()
|
||||
_on_tween_finished(_current_choices)
|
||||
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
# ShowMessage is only allowed to process input when visible
|
||||
_disable_player_movement()
|
||||
|
||||
|
||||
func show_message(speaker_name: String, message: String, choices: Dictionary) -> void:
|
||||
speaker.text = speaker_name
|
||||
speaker_text.text = message
|
||||
_current_choices = choices
|
||||
await get_tree().process_frame
|
||||
|
||||
var duration = speaker_text.text.length() * TEXT_SPEED
|
||||
_current_tween = get_tree().create_tween()
|
||||
_current_tween.tween_property(speaker_text, "visible_characters", speaker_text.text.length(), duration)
|
||||
_current_tween.finished.connect(Callable(_on_tween_finished).bind(choices))
|
||||
show()
|
||||
|
||||
## Callback when the tween typing has finished.
|
||||
## This allows presenting the user choice options or Continue button.
|
||||
func _on_tween_finished(choices: Dictionary) -> void:
|
||||
if choices.size() > 0:
|
||||
for key in choices.keys():
|
||||
var button = response_tpl.duplicate()
|
||||
button.text = choices[key]
|
||||
button.visible = true
|
||||
speaker_text.get_parent().add_child(button)
|
||||
var button_handler := func():
|
||||
selection = key
|
||||
_dialogue_finished()
|
||||
button.pressed.connect(button_handler)
|
||||
else:
|
||||
next_button.show()
|
||||
|
||||
|
||||
## Handles canceling the typing effect based on key codes
|
||||
func _should_end_typing(keycode:int) -> bool:
|
||||
return keycode == KEY_ESCAPE or keycode == KEY_SPACE
|
||||
|
||||
|
||||
## Prevent user movement when the dialogue UI is shown
|
||||
func _disable_player_movement() -> void:
|
||||
var actions = InputMap.get_actions()
|
||||
for action in actions:
|
||||
Input.action_release(action)
|
||||
|
||||
func _dialogue_finished():
|
||||
## If the mouse was previously hidden, restore state
|
||||
if _mouse_mode == Input.MOUSE_MODE_HIDDEN:
|
||||
Input.mouse_mode = _mouse_mode
|
||||
show_message_finished.emit()
|
||||
queue_free()
|
||||
|
||||
1
addons/orchestrator/scenes/dialogue_message.gd.uid
Normal file
1
addons/orchestrator/scenes/dialogue_message.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ctygulsjpm0ix
|
||||
75
addons/orchestrator/scenes/dialogue_message.tscn
Normal file
75
addons/orchestrator/scenes/dialogue_message.tscn
Normal file
@@ -0,0 +1,75 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dg7kqpda74ttw"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/orchestrator/scenes/dialogue_message.gd" id="1_08qvw"]
|
||||
|
||||
[node name="DialogueMessage" type="CanvasLayer"]
|
||||
layer = 100
|
||||
script = ExtResource("1_08qvw")
|
||||
|
||||
[node name="BlockMouseInteractions" type="MarginContainer" parent="."]
|
||||
editor_description = "Prevents interacting with other objects when dialogue starts."
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
anchors_preset = 7
|
||||
anchor_left = 0.5
|
||||
anchor_top = 1.0
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -58.5
|
||||
offset_top = -82.0
|
||||
offset_right = 58.5
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
size_flags_horizontal = 4
|
||||
size_flags_vertical = 3
|
||||
mouse_filter = 0
|
||||
theme_override_constants/margin_bottom = 25
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 8
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/PanelContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/PanelContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Speaker" type="Label" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Speaker Name"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SpeakerText" type="Label" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
custom_minimum_size = Vector2(700, 0)
|
||||
layout_mode = 2
|
||||
text = "Speaker Text that will be shown."
|
||||
vertical_alignment = 1
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ResponseTemplate" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
text = "Some Response (If choices are provided)"
|
||||
alignment = 0
|
||||
|
||||
[node name="NextButton" type="Button" parent="MarginContainer/PanelContainer/MarginContainer/VBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 8
|
||||
text = "Continue"
|
||||
alignment = 2
|
||||
Reference in New Issue
Block a user