110 lines
3.1 KiB
GDScript3
110 lines
3.1 KiB
GDScript3
|
|
extends Control
|
||
|
|
|
||
|
|
# #122: what the guide says during the prologue.
|
||
|
|
#
|
||
|
|
# A banner rather than a dialogue box: the player is flying while they read
|
||
|
|
# it, so it sits across the top out of the way of the fleet and never takes
|
||
|
|
# a press to dismiss. The SCRIPT decides when a line is done, not the player
|
||
|
|
# - a prologue that waits for a tap is a prologue that can be sat in.
|
||
|
|
#
|
||
|
|
# Lines queue rather than replacing each other, so a beat that fires while
|
||
|
|
# the previous line is still up does not silently eat it.
|
||
|
|
|
||
|
|
const HOLD_SECONDS: float = 4.5
|
||
|
|
const FADE_SECONDS: float = 0.5
|
||
|
|
const TEXT_COLOR: Color = Color(0.82, 0.92, 1.0)
|
||
|
|
const FRAME_COLOR: Color = Color(0.45, 0.68, 0.95)
|
||
|
|
|
||
|
|
var label: Label
|
||
|
|
var queued: Array = []
|
||
|
|
var current: String = ""
|
||
|
|
var time_left: float = 0.0
|
||
|
|
|
||
|
|
|
||
|
|
func _ready() -> void:
|
||
|
|
_ensure_label()
|
||
|
|
|
||
|
|
|
||
|
|
# The director is a world node and this banner lives under the UI layer,
|
||
|
|
# which readies afterwards - so the first line can arrive before _ready().
|
||
|
|
# Building on demand is simpler than making the director wait a frame, and
|
||
|
|
# it cannot be got wrong twice.
|
||
|
|
func _ensure_label() -> void:
|
||
|
|
if label != null:
|
||
|
|
return
|
||
|
|
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
|
|
visible = false
|
||
|
|
label = Label.new()
|
||
|
|
label.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||
|
|
label.add_theme_font_size_override("font_size", 30)
|
||
|
|
label.add_theme_color_override("font_color", TEXT_COLOR)
|
||
|
|
label.add_theme_color_override("font_outline_color", Color(0.01, 0.02, 0.06, 0.95))
|
||
|
|
label.add_theme_constant_override("outline_size", 4)
|
||
|
|
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||
|
|
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||
|
|
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||
|
|
add_child(label)
|
||
|
|
resized.connect(_layout)
|
||
|
|
_layout()
|
||
|
|
|
||
|
|
|
||
|
|
func _layout() -> void:
|
||
|
|
if label == null:
|
||
|
|
return
|
||
|
|
label.position = Vector2(24.0, 0.0)
|
||
|
|
label.size = Vector2(maxf(size.x - 48.0, 0.0), size.y)
|
||
|
|
|
||
|
|
|
||
|
|
# Says one line. Held for `hold` seconds, then the next in the queue.
|
||
|
|
func say(line: String, hold: float = HOLD_SECONDS) -> void:
|
||
|
|
_ensure_label()
|
||
|
|
queued.append({"line": line, "hold": maxf(hold, 0.1)})
|
||
|
|
if current == "":
|
||
|
|
_advance()
|
||
|
|
|
||
|
|
|
||
|
|
func clear() -> void:
|
||
|
|
queued.clear()
|
||
|
|
current = ""
|
||
|
|
time_left = 0.0
|
||
|
|
visible = false
|
||
|
|
|
||
|
|
|
||
|
|
func is_speaking() -> bool:
|
||
|
|
return current != "" or not queued.is_empty()
|
||
|
|
|
||
|
|
|
||
|
|
func _advance() -> void:
|
||
|
|
if queued.is_empty():
|
||
|
|
current = ""
|
||
|
|
time_left = 0.0
|
||
|
|
visible = false
|
||
|
|
return
|
||
|
|
var next: Dictionary = queued.pop_front()
|
||
|
|
current = String(next.line)
|
||
|
|
time_left = float(next.hold)
|
||
|
|
label.text = current
|
||
|
|
visible = true
|
||
|
|
queue_redraw()
|
||
|
|
|
||
|
|
|
||
|
|
func _process(delta: float) -> void:
|
||
|
|
if current == "":
|
||
|
|
return
|
||
|
|
time_left -= delta
|
||
|
|
queue_redraw()
|
||
|
|
if time_left <= 0.0:
|
||
|
|
_advance()
|
||
|
|
|
||
|
|
|
||
|
|
func _draw() -> void:
|
||
|
|
if current == "":
|
||
|
|
return
|
||
|
|
# Fades out over its last moments so lines hand over rather than cutting.
|
||
|
|
var alpha: float = clampf(time_left / FADE_SECONDS, 0.0, 1.0)
|
||
|
|
label.modulate.a = alpha
|
||
|
|
draw_rect(Rect2(Vector2.ZERO, size), Color(0.02, 0.05, 0.12, 0.72 * alpha))
|
||
|
|
NeonDraw.draw_glowing_line(self, Vector2(0.0, size.y), Vector2(size.x, size.y),
|
||
|
|
Color(FRAME_COLOR, alpha), 0.7, 0.55)
|
||
|
|
NeonDraw.draw_glowing_line(self, Vector2(0.0, 0.0), Vector2(size.x, 0.0),
|
||
|
|
Color(FRAME_COLOR, alpha * 0.6), 0.5, 0.4)
|