Initial commit
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
[remap]
|
||||
|
||||
importer="mp3"
|
||||
type="AudioStreamMP3"
|
||||
uid="uid://fk8girwmung3"
|
||||
path="res://.godot/imported/unatco.mp3-883b932c9cb4cdcb692fc0f711f7f84e.mp3str"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://shared/audio/music/unatco.mp3"
|
||||
dest_files=["res://.godot/imported/unatco.mp3-883b932c9cb4cdcb692fc0f711f7f84e.mp3str"]
|
||||
|
||||
[params]
|
||||
|
||||
loop=true
|
||||
loop_offset=0.0
|
||||
bpm=0.0
|
||||
beat_count=0
|
||||
bar_beats=4
|
||||
@@ -0,0 +1,9 @@
|
||||
[gd_scene format=3 uid="uid://ci42q3y8u6ves"]
|
||||
|
||||
[ext_resource type="AudioStream" uid="uid://fk8girwmung3" path="res://shared/audio/music/unatco.mp3" id="1_mppfb"]
|
||||
|
||||
[node name="Unatco" type="Node" unique_id=1231749188]
|
||||
|
||||
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="." unique_id=1253179788]
|
||||
stream = ExtResource("1_mppfb")
|
||||
autoplay = true
|
||||
Binary file not shown.
@@ -0,0 +1,36 @@
|
||||
[remap]
|
||||
|
||||
importer="font_data_dynamic"
|
||||
type="FontFile"
|
||||
uid="uid://cih8meutgemo1"
|
||||
path="res://.godot/imported/Roboto-VariableFont_wdth,wght.ttf-64b35459266686c67cc4bfdc1e7c6493.fontdata"
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://shared/fonts/Roboto-VariableFont_wdth,wght.ttf"
|
||||
dest_files=["res://.godot/imported/Roboto-VariableFont_wdth,wght.ttf-64b35459266686c67cc4bfdc1e7c6493.fontdata"]
|
||||
|
||||
[params]
|
||||
|
||||
Rendering=null
|
||||
antialiasing=1
|
||||
generate_mipmaps=false
|
||||
disable_embedded_bitmaps=true
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
allow_system_fallback=true
|
||||
force_autohinter=false
|
||||
modulate_color_glyphs=false
|
||||
hinting=3
|
||||
subpixel_positioning=4
|
||||
keep_rounding_remainders=true
|
||||
oversampling=0.0
|
||||
Fallbacks=null
|
||||
fallbacks=[]
|
||||
Compress=null
|
||||
compress=true
|
||||
preload=[]
|
||||
language_support={}
|
||||
script_support={}
|
||||
opentype_features={}
|
||||
@@ -0,0 +1,148 @@
|
||||
extends CanvasLayer
|
||||
|
||||
|
||||
@onready var audio_stream_player: AudioStreamPlayer = $AudioStreamPlayer
|
||||
@onready var dialogue_label: DialogueLabel = $DialogueLabel
|
||||
@onready var responses_menu: DialogueResponsesMenu = %DialogueResponsesMenu
|
||||
|
||||
|
||||
## The dialogue resource
|
||||
var resource: DialogueResource
|
||||
|
||||
## Temporary game states
|
||||
var temporary_game_states: Array = []
|
||||
|
||||
## See if we are waiting for the player
|
||||
var is_waiting_for_input: bool = false
|
||||
|
||||
# Who is talking
|
||||
var dialogue_marker: DialogueMarker
|
||||
|
||||
## The current line
|
||||
var dialogue_line: DialogueLine:
|
||||
set(value):
|
||||
if not value:
|
||||
queue_free()
|
||||
else:
|
||||
dialogue_line = value
|
||||
update_dialogue_line()
|
||||
get:
|
||||
return dialogue_line
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
dialogue_label.hide()
|
||||
|
||||
Engine.get_singleton("DialogueManager").mutated.connect(_on_mutated)
|
||||
|
||||
|
||||
func _unhandled_input(_event: InputEvent) -> void:
|
||||
# Only the balloon is allowed to handle input while it's showing
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
## Start some dialogue
|
||||
func start(dialogue_resource: DialogueResource, title: String, extra_game_states: Array = []) -> void:
|
||||
if not is_node_ready():
|
||||
await ready
|
||||
temporary_game_states = extra_game_states
|
||||
is_waiting_for_input = false
|
||||
resource = dialogue_resource
|
||||
dialogue_line = await resource.get_next_dialogue_line(title, temporary_game_states)
|
||||
|
||||
|
||||
## Go to the next line
|
||||
func next(next_id: String) -> void:
|
||||
dialogue_line = await resource.get_next_dialogue_line(next_id, temporary_game_states)
|
||||
|
||||
|
||||
#region Helpers
|
||||
|
||||
|
||||
func update_dialogue_line() -> void:
|
||||
responses_menu.responses = []
|
||||
|
||||
dialogue_line.text = dialogue_line.text
|
||||
|
||||
dialogue_label.hide()
|
||||
dialogue_label.dialogue_line = dialogue_line
|
||||
|
||||
# Set the colour and attach the dialogue to the character
|
||||
dialogue_marker = DialogueMarker.find_for_character(dialogue_line.character)
|
||||
if is_instance_valid(dialogue_marker):
|
||||
dialogue_label.set("theme_override_colors/default_color", dialogue_marker.color)
|
||||
dialogue_label.set("theme_override_colors/font_outline_color", dialogue_marker.color.darkened(0.4))
|
||||
dialogue_label.global_position = dialogue_marker.global_position - Vector2(dialogue_label.size.x * 0.5, dialogue_label.get_content_height())
|
||||
|
||||
dialogue_label.show()
|
||||
dialogue_label.type_out()
|
||||
|
||||
# Play sound and wait for sound to finish
|
||||
var voice_path: String = "res://l10n/voice/en/%s.ogg" % [dialogue_line.static_id]
|
||||
if ResourceLoader.exists(voice_path):
|
||||
var stream = load(voice_path)
|
||||
audio_stream_player.stream = stream
|
||||
audio_stream_player.play()
|
||||
|
||||
Events.character_started_talking.emit(dialogue_line.character)
|
||||
await audio_stream_player.finished
|
||||
Events.character_finished_talking.emit(dialogue_line.character)
|
||||
else:
|
||||
printerr("Voice missing: %s" % [voice_path])
|
||||
Events.character_started_talking.emit(dialogue_line.character)
|
||||
await get_tree().create_timer(dialogue_line.text.length() * 0.05).timeout
|
||||
Events.character_finished_talking.emit(dialogue_line.character)
|
||||
|
||||
dialogue_label.hide()
|
||||
|
||||
if dialogue_line.responses.size() == 0:
|
||||
next(dialogue_line.next_id)
|
||||
else:
|
||||
responses_menu.responses = dialogue_line.responses
|
||||
for item: RichTextLabel in responses_menu.get_menu_items():
|
||||
item.mouse_entered.connect(_on_response_mouse_entered.bind(item))
|
||||
item.focus_entered.connect(_on_response_focus_entered.bind(item))
|
||||
item.focus_exited.connect(_on_response_focus_exited.bind(item))
|
||||
item.gui_input.connect(_on_response_gui_input.bind(item))
|
||||
_on_response_focus_entered(responses_menu.get_menu_items()[0])
|
||||
|
||||
#endregion
|
||||
|
||||
#region Signals
|
||||
|
||||
|
||||
func _on_mutated(_mutation: Dictionary) -> void:
|
||||
is_waiting_for_input = false
|
||||
|
||||
|
||||
func _on_response_mouse_entered(item: Control) -> void:
|
||||
if "Disallowed" in item.name: return
|
||||
|
||||
item.grab_focus()
|
||||
|
||||
|
||||
func _on_response_gui_input(event: InputEvent, item: Control) -> void:
|
||||
if "Disallowed" in item.name: return
|
||||
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
if event is InputEventMouseButton and event.is_pressed() and event.button_index == 1:
|
||||
next(dialogue_line.responses[item.get_index()].next_id)
|
||||
elif event.is_action_pressed("ui_accept") and item in responses_menu.get_menu_items():
|
||||
next(dialogue_line.responses[item.get_index()].next_id)
|
||||
|
||||
|
||||
func _on_response_focus_entered(item):
|
||||
item.set("theme_override_colors/default_color", DialogueMarker.find_for_character("Jimmy").color)
|
||||
|
||||
|
||||
func _on_response_focus_exited(item):
|
||||
item.set("theme_override_colors/default_color", Color.WHITE)
|
||||
|
||||
|
||||
func _on_dialogue_label_resized() -> void:
|
||||
if is_instance_valid(dialogue_marker):
|
||||
dialogue_label.global_position = dialogue_marker.global_position - Vector2(dialogue_label.size.x * 0.5, dialogue_label.get_content_height())
|
||||
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://dgfws7wit3bm8
|
||||
@@ -0,0 +1,65 @@
|
||||
[gd_scene format=3 uid="uid://fuap5c0yodp"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dgfws7wit3bm8" path="res://shared/helpers/baloon.gd" id="1_wstok"]
|
||||
[ext_resource type="Script" uid="uid://g32um0mltv5d" path="res://addons/dialogue_manager/nodes/dialogue_label/dialogue_label.gd" id="2_o0tk5"]
|
||||
[ext_resource type="Script" uid="uid://bb52rsfwhkxbn" path="res://addons/dialogue_manager/nodes/responses_menu/dialogue_responses_menu.gd" id="3_8ed8v"]
|
||||
|
||||
[sub_resource type="Theme" id="Theme_npl72"]
|
||||
default_font_size = 26
|
||||
|
||||
[sub_resource type="Theme" id="Theme_cpad0"]
|
||||
default_font_size = 26
|
||||
|
||||
[node name="Baloon" type="CanvasLayer" unique_id=202010879]
|
||||
layer = 128
|
||||
script = ExtResource("1_wstok")
|
||||
|
||||
[node name="AudioStreamPlayer2D" type="AudioStreamPlayer2D" parent="." unique_id=893187917]
|
||||
|
||||
[node name="DialogueLabel" type="RichTextLabel" parent="." unique_id=1902386087]
|
||||
clip_contents = false
|
||||
offset_right = 668.0
|
||||
offset_bottom = 107.0
|
||||
theme = SubResource("Theme_npl72")
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 5
|
||||
bbcode_enabled = true
|
||||
text = "usey ipsum dolor sit amet. When you get lost in your imaginatory vagueness, your foresight will become a nimble vagrant. Go with the feeling of the nature. Take it easy. Know why you're here. And remember to balance your internal energy with the environment."
|
||||
fit_content = true
|
||||
scroll_active = false
|
||||
horizontal_alignment = 1
|
||||
script = ExtResource("2_o0tk5")
|
||||
seconds_per_step = 0.0
|
||||
skip_pause_at_abbreviations = PackedStringArray("Mr", "Mrs", "Ms", "Dr", "etc", "eg", "ex")
|
||||
metadata/_custom_type_script = "uid://g32um0mltv5d"
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="." unique_id=299096319]
|
||||
offset_top = 880.0
|
||||
offset_right = 1920.0
|
||||
offset_bottom = 1080.0
|
||||
color = Color(0, 0, 0, 0.3137255)
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="ColorRect" unique_id=163990779]
|
||||
layout_mode = 0
|
||||
offset_right = 1920.0
|
||||
offset_bottom = 200.0
|
||||
theme_override_constants/margin_left = 20
|
||||
|
||||
[node name="DialogueResponsesMenu" type="VBoxContainer" parent="ColorRect/MarginContainer" unique_id=1800274106 node_paths=PackedStringArray("response_template")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
script = ExtResource("3_8ed8v")
|
||||
response_template = NodePath("../RichTextLabel")
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="ColorRect/MarginContainer" unique_id=666364923]
|
||||
custom_minimum_size = Vector2(0, 32)
|
||||
clip_contents = false
|
||||
layout_mode = 2
|
||||
theme = SubResource("Theme_cpad0")
|
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
|
||||
theme_override_constants/outline_size = 5
|
||||
text = "Response"
|
||||
fit_content = true
|
||||
scroll_active = false
|
||||
meta_underlined = false
|
||||
hint_underlined = false
|
||||
@@ -0,0 +1,218 @@
|
||||
extends CanvasLayer
|
||||
## A basic dialogue balloon for use with Dialogue Manager.
|
||||
|
||||
|
||||
## The dialogue resource
|
||||
@export var dialogue_resource: DialogueResource
|
||||
|
||||
## Start from a given cue when using balloon as a [Node] in a scene.
|
||||
@export var start_from_cue: String = ""
|
||||
|
||||
## If running as a [Node] in a scene then auto start the dialogue.
|
||||
@export var auto_start: bool = false
|
||||
|
||||
## If all other input is blocked as long as dialogue is shown.
|
||||
@export var will_block_other_input: bool = true
|
||||
|
||||
## The action to use for advancing the dialogue
|
||||
@export var next_action: StringName = &"ui_accept"
|
||||
|
||||
## The action to use to skip typing the dialogue
|
||||
@export var skip_action: StringName = &"ui_cancel"
|
||||
|
||||
## A sound player for voice lines (if they exist).
|
||||
@onready var audio_stream_player: AudioStreamPlayer = %AudioStreamPlayer
|
||||
|
||||
## Temporary game states
|
||||
var temporary_game_states: Array = []
|
||||
|
||||
## See if we are waiting for the player
|
||||
var is_waiting_for_input: bool = false
|
||||
|
||||
## See if we are running a long mutation and should hide the balloon
|
||||
var will_hide_balloon: bool = false
|
||||
|
||||
## A dictionary to store any ephemeral variables
|
||||
var locals: Dictionary = {}
|
||||
|
||||
var _locale: String = TranslationServer.get_locale()
|
||||
|
||||
## The current line
|
||||
var dialogue_line: DialogueLine:
|
||||
set(value):
|
||||
if value:
|
||||
dialogue_line = value
|
||||
apply_dialogue_line()
|
||||
else:
|
||||
# The dialogue has finished so close the balloon
|
||||
if owner == null:
|
||||
queue_free()
|
||||
else:
|
||||
hide()
|
||||
get:
|
||||
return dialogue_line
|
||||
|
||||
## A cooldown timer for delaying the balloon hide when encountering a mutation.
|
||||
var mutation_cooldown: Timer = Timer.new()
|
||||
|
||||
## The base balloon anchor
|
||||
@onready var balloon: Control = %Balloon
|
||||
|
||||
## The label showing the name of the currently speaking character
|
||||
@onready var character_label: RichTextLabel = %CharacterLabel
|
||||
|
||||
## The label showing the currently spoken dialogue
|
||||
@onready var dialogue_label: DialogueLabel = %DialogueLabel
|
||||
|
||||
## The menu of responses
|
||||
@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu
|
||||
|
||||
## Indicator to show that player can progress dialogue.
|
||||
@onready var progress: Polygon2D = %Progress
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
balloon.hide()
|
||||
Engine.get_singleton("DialogueManager").mutated.connect(_on_mutated)
|
||||
|
||||
# If the responses menu doesn't have a next action set, use this one
|
||||
if responses_menu.next_action.is_empty():
|
||||
responses_menu.next_action = next_action
|
||||
|
||||
mutation_cooldown.timeout.connect(_on_mutation_cooldown_timeout)
|
||||
add_child(mutation_cooldown)
|
||||
|
||||
if auto_start:
|
||||
if not is_instance_valid(dialogue_resource):
|
||||
assert(false, DMConstants.get_error_message(DMConstants.ERR_MISSING_RESOURCE_FOR_AUTOSTART))
|
||||
start()
|
||||
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if is_instance_valid(dialogue_line):
|
||||
progress.visible = not dialogue_label.is_typing and dialogue_line.responses.size() == 0 and not dialogue_line.has_tag("voice")
|
||||
|
||||
|
||||
func _unhandled_input(_event: InputEvent) -> void:
|
||||
# Only the balloon is allowed to handle input while it's showing
|
||||
if will_block_other_input:
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
## Detect a change of locale and update the current dialogue line to show the new language
|
||||
if what == NOTIFICATION_TRANSLATION_CHANGED and _locale != TranslationServer.get_locale() and is_instance_valid(dialogue_label):
|
||||
_locale = TranslationServer.get_locale()
|
||||
var visible_ratio: float = dialogue_label.visible_ratio
|
||||
await dialogue_line.refresh()
|
||||
if visible_ratio < 1:
|
||||
dialogue_label.skip_typing()
|
||||
|
||||
|
||||
## Start some dialogue
|
||||
func start(with_dialogue_resource: DialogueResource = null, cue: String = "", extra_game_states: Array = []) -> void:
|
||||
temporary_game_states = [self] + extra_game_states
|
||||
is_waiting_for_input = false
|
||||
if is_instance_valid(with_dialogue_resource):
|
||||
dialogue_resource = with_dialogue_resource
|
||||
if not cue.is_empty():
|
||||
start_from_cue = cue
|
||||
dialogue_line = await dialogue_resource.get_next_dialogue_line(start_from_cue, temporary_game_states)
|
||||
show()
|
||||
|
||||
|
||||
## Apply any changes to the balloon given a new [DialogueLine].
|
||||
func apply_dialogue_line() -> void:
|
||||
mutation_cooldown.stop()
|
||||
|
||||
progress.hide()
|
||||
is_waiting_for_input = false
|
||||
balloon.focus_mode = Control.FOCUS_ALL
|
||||
balloon.grab_focus()
|
||||
|
||||
character_label.visible = not dialogue_line.character.is_empty()
|
||||
character_label.text = tr(dialogue_line.character, "dialogue")
|
||||
|
||||
dialogue_label.hide()
|
||||
dialogue_label.dialogue_line = dialogue_line
|
||||
|
||||
responses_menu.hide()
|
||||
responses_menu.responses = dialogue_line.responses
|
||||
|
||||
# Show our balloon
|
||||
balloon.show()
|
||||
will_hide_balloon = false
|
||||
|
||||
dialogue_label.show()
|
||||
if not dialogue_line.text.is_empty():
|
||||
dialogue_label.type_out()
|
||||
await dialogue_label.finished_typing
|
||||
|
||||
# Wait for next line
|
||||
if dialogue_line.has_tag("voice"):
|
||||
audio_stream_player.stream = load(dialogue_line.get_tag_value("voice"))
|
||||
audio_stream_player.play()
|
||||
await audio_stream_player.finished
|
||||
next(dialogue_line.next_id)
|
||||
elif dialogue_line.responses.size() > 0:
|
||||
balloon.focus_mode = Control.FOCUS_NONE
|
||||
responses_menu.show()
|
||||
elif dialogue_line.time != "":
|
||||
var time: float = dialogue_line.text.length() * 0.02 if dialogue_line.time == "auto" else dialogue_line.time.to_float()
|
||||
await get_tree().create_timer(time).timeout
|
||||
next(dialogue_line.next_id)
|
||||
else:
|
||||
is_waiting_for_input = true
|
||||
balloon.focus_mode = Control.FOCUS_ALL
|
||||
balloon.grab_focus()
|
||||
|
||||
|
||||
## Go to the next line
|
||||
func next(next_id: String) -> void:
|
||||
dialogue_line = await dialogue_resource.get_next_dialogue_line(next_id, temporary_game_states)
|
||||
|
||||
|
||||
#region Signals
|
||||
|
||||
|
||||
func _on_mutation_cooldown_timeout() -> void:
|
||||
if will_hide_balloon:
|
||||
will_hide_balloon = false
|
||||
balloon.hide()
|
||||
|
||||
|
||||
func _on_mutated(mutation: Dictionary) -> void:
|
||||
if not mutation.is_inline:
|
||||
is_waiting_for_input = false
|
||||
will_hide_balloon = true
|
||||
mutation_cooldown.start(0.1)
|
||||
|
||||
|
||||
func _on_balloon_gui_input(event: InputEvent) -> void:
|
||||
# See if we need to skip typing of the dialogue
|
||||
if dialogue_label.is_typing:
|
||||
var mouse_was_clicked: bool = event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed()
|
||||
var skip_button_was_pressed: bool = event.is_action_pressed(skip_action)
|
||||
if mouse_was_clicked or skip_button_was_pressed:
|
||||
get_viewport().set_input_as_handled()
|
||||
dialogue_label.skip_typing()
|
||||
return
|
||||
|
||||
if not is_waiting_for_input: return
|
||||
if dialogue_line.responses.size() > 0: return
|
||||
|
||||
# When there are no response options the balloon itself is the clickable thing
|
||||
get_viewport().set_input_as_handled()
|
||||
|
||||
if event is InputEventMouseButton and event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT:
|
||||
next(dialogue_line.next_id)
|
||||
elif event.is_action_pressed(next_action) and get_viewport().gui_get_focus_owner() == balloon:
|
||||
next(dialogue_line.next_id)
|
||||
|
||||
|
||||
func _on_responses_menu_response_selected(response: DialogueResponse) -> void:
|
||||
next(response.next_id)
|
||||
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://c3e8iahlgql5h
|
||||
@@ -0,0 +1,207 @@
|
||||
[gd_scene format=3 uid="uid://l5tlat8en4ms"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://c3e8iahlgql5h" path="res://shared/helpers/baloon/balloon.gd" id="1_36de5"]
|
||||
[ext_resource type="PackedScene" uid="uid://ckvgyvclnwggo" path="res://addons/dialogue_manager/nodes/dialogue_label/dialogue_label.tscn" id="2_a8ve6"]
|
||||
[ext_resource type="Script" uid="uid://bb52rsfwhkxbn" path="res://addons/dialogue_manager/nodes/responses_menu/dialogue_responses_menu.gd" id="3_72ixx"]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_spyqn"]
|
||||
content_margin_left = 20.0
|
||||
content_margin_top = 10.0
|
||||
content_margin_right = 20.0
|
||||
content_margin_bottom = 10.0
|
||||
bg_color = Color(0, 0, 0, 1)
|
||||
border_width_left = 3
|
||||
border_width_top = 3
|
||||
border_width_right = 3
|
||||
border_width_bottom = 3
|
||||
border_color = Color(0.329412, 0.329412, 0.329412, 1)
|
||||
corner_radius_top_left = 5
|
||||
corner_radius_top_right = 5
|
||||
corner_radius_bottom_right = 5
|
||||
corner_radius_bottom_left = 5
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ri4m3"]
|
||||
content_margin_left = 20.0
|
||||
content_margin_top = 10.0
|
||||
content_margin_right = 20.0
|
||||
content_margin_bottom = 10.0
|
||||
bg_color = Color(0.121569, 0.121569, 0.121569, 1)
|
||||
border_width_left = 3
|
||||
border_width_top = 3
|
||||
border_width_right = 3
|
||||
border_width_bottom = 3
|
||||
border_color = Color(1, 1, 1, 1)
|
||||
corner_radius_top_left = 5
|
||||
corner_radius_top_right = 5
|
||||
corner_radius_bottom_right = 5
|
||||
corner_radius_bottom_left = 5
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_e0njw"]
|
||||
content_margin_left = 20.0
|
||||
content_margin_top = 10.0
|
||||
content_margin_right = 20.0
|
||||
content_margin_bottom = 10.0
|
||||
bg_color = Color(0, 0, 0, 1)
|
||||
border_width_left = 3
|
||||
border_width_top = 3
|
||||
border_width_right = 3
|
||||
border_width_bottom = 3
|
||||
border_color = Color(0.6, 0.6, 0.6, 1)
|
||||
corner_radius_top_left = 5
|
||||
corner_radius_top_right = 5
|
||||
corner_radius_bottom_right = 5
|
||||
corner_radius_bottom_left = 5
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qkmqt"]
|
||||
bg_color = Color(0, 0, 0, 1)
|
||||
border_width_left = 3
|
||||
border_width_top = 3
|
||||
border_width_right = 3
|
||||
border_width_bottom = 3
|
||||
corner_radius_top_left = 5
|
||||
corner_radius_top_right = 5
|
||||
corner_radius_bottom_right = 5
|
||||
corner_radius_bottom_left = 5
|
||||
|
||||
[sub_resource type="Theme" id="Theme_qq3yp"]
|
||||
default_font_size = 20
|
||||
Button/styles/disabled = SubResource("StyleBoxFlat_spyqn")
|
||||
Button/styles/focus = SubResource("StyleBoxFlat_ri4m3")
|
||||
Button/styles/hover = SubResource("StyleBoxFlat_e0njw")
|
||||
Button/styles/normal = SubResource("StyleBoxFlat_e0njw")
|
||||
MarginContainer/constants/margin_bottom = 15
|
||||
MarginContainer/constants/margin_left = 30
|
||||
MarginContainer/constants/margin_right = 30
|
||||
MarginContainer/constants/margin_top = 15
|
||||
PanelContainer/styles/panel = SubResource("StyleBoxFlat_qkmqt")
|
||||
|
||||
[sub_resource type="Animation" id="Animation_nlsx6"]
|
||||
length = 0.001
|
||||
tracks/0/type = "bezier"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Progress:position:y")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"handle_modes": PackedInt32Array(0),
|
||||
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0),
|
||||
"times": PackedFloat32Array(0)
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_qkmqt"]
|
||||
resource_name = "progress"
|
||||
loop_mode = 1
|
||||
step = 0.1
|
||||
tracks/0/type = "bezier"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("Progress:position:y")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"handle_modes": PackedInt32Array(0, 0, 0, 0, 0),
|
||||
"points": PackedFloat32Array(0, -0.25, 0, 0.25, 0, 0, -0.25, 0, 0.2, -0.0157438, -4, -0.2, 0.0112069, 0.25, 0, -4, -0.25, 0, 0.25, 0, 0, -0.2, 0.00299701, 0.25, 0),
|
||||
"times": PackedFloat32Array(0, 0.1, 0.5, 0.6, 1)
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_1337t"]
|
||||
_data = {
|
||||
&"RESET": SubResource("Animation_nlsx6"),
|
||||
&"progress": SubResource("Animation_qkmqt")
|
||||
}
|
||||
|
||||
[node name="ExampleBalloon" type="CanvasLayer" unique_id=38036521]
|
||||
layer = 100
|
||||
script = ExtResource("1_36de5")
|
||||
|
||||
[node name="Balloon" type="Control" parent="." unique_id=154399927]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
theme = SubResource("Theme_qq3yp")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="Balloon" unique_id=1302081376]
|
||||
layout_mode = 1
|
||||
anchors_preset = 12
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
offset_top = -219.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 0
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="Balloon/MarginContainer" unique_id=2145270309]
|
||||
clip_children = 2
|
||||
layout_mode = 2
|
||||
mouse_filter = 1
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="Balloon/MarginContainer/PanelContainer" unique_id=903640783]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Balloon/MarginContainer/PanelContainer/MarginContainer" unique_id=1685890612]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Balloon/MarginContainer/PanelContainer/MarginContainer/HBoxContainer" unique_id=1890134056]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="CharacterLabel" type="RichTextLabel" parent="Balloon/MarginContainer/PanelContainer/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1567782692]
|
||||
unique_name_in_owner = true
|
||||
modulate = Color(1, 1, 1, 0.501961)
|
||||
layout_mode = 2
|
||||
mouse_filter = 1
|
||||
bbcode_enabled = true
|
||||
text = "Character"
|
||||
fit_content = true
|
||||
scroll_active = false
|
||||
|
||||
[node name="DialogueLabel" parent="Balloon/MarginContainer/PanelContainer/MarginContainer/HBoxContainer/VBoxContainer" unique_id=1301798052 instance=ExtResource("2_a8ve6")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
text = "Dialogue..."
|
||||
|
||||
[node name="Control" type="Control" parent="Balloon/MarginContainer/PanelContainer/MarginContainer/HBoxContainer" unique_id=418507161]
|
||||
custom_minimum_size = Vector2(20, 10)
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 8
|
||||
|
||||
[node name="Progress" type="Polygon2D" parent="Balloon/MarginContainer/PanelContainer/MarginContainer/HBoxContainer/Control" unique_id=2091292889]
|
||||
unique_name_in_owner = true
|
||||
polygon = PackedVector2Array(0, 0, 10, 10, 20, 0)
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="Balloon/MarginContainer/PanelContainer/MarginContainer/HBoxContainer/Control" unique_id=1602634471]
|
||||
libraries/ = SubResource("AnimationLibrary_1337t")
|
||||
autoplay = &"progress"
|
||||
|
||||
[node name="CenterContainer" type="CenterContainer" parent="Balloon" unique_id=1087901387]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="ResponsesMenu" type="VBoxContainer" parent="Balloon/CenterContainer" unique_id=1801308483 node_paths=PackedStringArray("response_template")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 8
|
||||
theme_override_constants/separation = 2
|
||||
alignment = 1
|
||||
script = ExtResource("3_72ixx")
|
||||
response_template = NodePath("ResponseExample")
|
||||
|
||||
[node name="ResponseExample" type="Button" parent="Balloon/CenterContainer/ResponsesMenu" unique_id=1446810977]
|
||||
layout_mode = 2
|
||||
text = "Response example"
|
||||
|
||||
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="." unique_id=1162558754]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[connection signal="gui_input" from="Balloon" to="." method="_on_balloon_gui_input"]
|
||||
[connection signal="response_selected" from="Balloon/CenterContainer/ResponsesMenu" to="." method="_on_responses_menu_response_selected"]
|
||||
@@ -0,0 +1,4 @@
|
||||
class_name DialogueMarker extends DialogueMarker2D
|
||||
|
||||
|
||||
@export var color: Color
|
||||
@@ -0,0 +1 @@
|
||||
uid://bp4pd1ek1cqnn
|
||||
@@ -0,0 +1,49 @@
|
||||
@tool
|
||||
|
||||
class_name Hotspot extends DialogueActionable2D
|
||||
|
||||
var inside = false
|
||||
func _enter_tree() -> void:
|
||||
#Input.set_custom_mouse_cursor(preload("res://helpers/pointers/arrow.svg"))
|
||||
#Input.set_custom_mouse_cursor(preload("res://helpers/pointers/target.svg"), Input.CURSOR_POINTING_HAND)
|
||||
#
|
||||
#mouse_entered.connect(_on_mouse_entered)
|
||||
#mouse_exited.connect(_on_mouse_exited)
|
||||
#
|
||||
input_event.connect(_on_input_event)
|
||||
body_entered.connect(_on_body_entered)
|
||||
body_exited.connect(_on_body_exited)
|
||||
|
||||
|
||||
#region Signals
|
||||
|
||||
|
||||
func _on_body_entered(body: Node2D) -> void:
|
||||
$Label.visible = true
|
||||
inside = true
|
||||
|
||||
|
||||
func _on_body_exited(body: Node2D) -> void:
|
||||
$Label.visible = false
|
||||
inside = true
|
||||
|
||||
#func _on_mouse_entered() -> void:
|
||||
#Input.set_custom_mouse_cursor(preload("res://helpers/pointers/target.svg"))
|
||||
#
|
||||
#
|
||||
#func _on_mouse_exited() -> void:
|
||||
#Input.set_custom_mouse_cursor(preload("res://helpers/pointers/arrow.svg"))
|
||||
#
|
||||
#
|
||||
func _input(event):
|
||||
if inside and Input.is_action_just_pressed("interact"):
|
||||
$Label.visible = false
|
||||
action()
|
||||
|
||||
func _on_input_event(_view_port: Node, event: InputEvent, _shape_idx: int) -> void:
|
||||
if Input.is_action_just_pressed("interact"):
|
||||
$Label.visible = false
|
||||
action()
|
||||
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://e22lo1h2ovr7
|
||||
@@ -0,0 +1,19 @@
|
||||
[gd_scene format=3 uid="uid://pokhp7j2kahn"]
|
||||
|
||||
[ext_resource type="LabelSettings" uid="uid://dkpp84p885g8h" path="res://shared/resources/standard_label_settings.tres" id="1_870w0"]
|
||||
|
||||
[sub_resource type="RectangleShape2D" id="RectangleShape2D_5t4nn"]
|
||||
size = Vector2(74, 110)
|
||||
|
||||
[node name="Interaction" type="Area2D" unique_id=1786805095]
|
||||
|
||||
[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=770966100]
|
||||
position = Vector2(37, 55)
|
||||
shape = SubResource("RectangleShape2D_5t4nn")
|
||||
|
||||
[node name="ToolTip" type="Label" parent="." unique_id=103743226]
|
||||
offset_top = -39.0
|
||||
offset_right = 61.0
|
||||
offset_bottom = -1.0
|
||||
text = "Text"
|
||||
label_settings = ExtResource("1_870w0")
|
||||
@@ -0,0 +1,11 @@
|
||||
[gd_resource type="LabelSettings" format=3 uid="uid://dkpp84p885g8h"]
|
||||
|
||||
[ext_resource type="FontFile" uid="uid://cih8meutgemo1" path="res://shared/fonts/Roboto-VariableFont_wdth,wght.ttf" id="1_dmljj"]
|
||||
|
||||
[resource]
|
||||
font = ExtResource("1_dmljj")
|
||||
font_size = 32
|
||||
outline_size = 10
|
||||
outline_color = Color(0, 0, 0, 1)
|
||||
shadow_size = 5
|
||||
shadow_color = Color(0, 0, 0, 1)
|
||||
@@ -0,0 +1,13 @@
|
||||
extends Node
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
|
||||
var player_entrance_name: String = ""
|
||||
@@ -0,0 +1 @@
|
||||
uid://5qv3gwwiq6hf
|
||||
@@ -0,0 +1,5 @@
|
||||
extends Node
|
||||
|
||||
|
||||
signal character_started_talking(character_name: String)
|
||||
signal character_finished_talking(character_name: String)
|
||||
@@ -0,0 +1 @@
|
||||
uid://bam75tp2cvnnv
|
||||
Reference in New Issue
Block a user