feat(ui): dialogue UI hardening and examine result overlay (#174)
Confrontation options use RichTextLabel with italic tags for first-person voice (D-063). Examine result overlay auto-dismisses after 5s with confidence-based color tinting. Dismisses when dialogue opens. D-062 invisible locked options confirmed correct. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
extends Control
|
||||
|
||||
## Examine result display — #174, D-061 adjacent.
|
||||
##
|
||||
## Shows the character-filtered text returned by the Examine verb (#242).
|
||||
## Non-interactive overlay. Auto-dismisses after DISMISS_DELAY seconds.
|
||||
## Diegetic: reads as the neural insert processing what the character observed.
|
||||
##
|
||||
## Positioned in InsertOverlay (CanvasLayer 10, z-layer 6).
|
||||
## Only one examine result is shown at a time — new result replaces old.
|
||||
|
||||
const DISMISS_DELAY: float = 5.0 # Auto-dismiss after 5 seconds
|
||||
const FADE_IN: float = 0.18
|
||||
const FADE_OUT: float = 0.35
|
||||
|
||||
# Confidence → alpha modifier: Direct is brightest, Suspects is dimmest
|
||||
const CONFIDENCE_ALPHA: Dictionary = {
|
||||
"Direct": 1.0,
|
||||
"KnowsDetails": 0.9,
|
||||
"KnowsOf": 0.75,
|
||||
"Suspects": 0.6,
|
||||
}
|
||||
|
||||
@onready var panel: PanelContainer = $PanelContainer
|
||||
@onready var text_label: RichTextLabel = $PanelContainer/MarginContainer/TextLabel
|
||||
|
||||
var _dismiss_tween: Tween = null
|
||||
var _active: bool = false
|
||||
|
||||
func _ready() -> void:
|
||||
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
modulate.a = 0.0
|
||||
visible = false
|
||||
|
||||
|
||||
## Show an examine result. Called from main.gd when GameState.current_examine_result is set.
|
||||
## result: {entity_id, text, confidence}
|
||||
func show_result(result: Dictionary) -> void:
|
||||
var text: String = result.get("text", "")
|
||||
var confidence: String = result.get("confidence", "KnowsOf")
|
||||
|
||||
if text.is_empty():
|
||||
return
|
||||
|
||||
# Cancel any in-progress dismiss
|
||||
if _dismiss_tween and _dismiss_tween.is_valid():
|
||||
_dismiss_tween.kill()
|
||||
|
||||
# Apply confidence-based alpha to the insert color
|
||||
var alpha: float = CONFIDENCE_ALPHA.get(confidence, 0.75)
|
||||
var col := Color(Constants.INSERT_COLOR_TEXT.r, Constants.INSERT_COLOR_TEXT.g,
|
||||
Constants.INSERT_COLOR_TEXT.b, alpha)
|
||||
text_label.add_theme_color_override("default_color", col)
|
||||
text_label.text = text
|
||||
|
||||
visible = true
|
||||
_active = true
|
||||
modulate.a = 0.0
|
||||
|
||||
# Fade in, then auto-dismiss
|
||||
_dismiss_tween = create_tween()
|
||||
_dismiss_tween.tween_property(self, "modulate:a", 1.0, FADE_IN)
|
||||
_dismiss_tween.tween_interval(DISMISS_DELAY)
|
||||
_dismiss_tween.tween_callback(_start_fade_out)
|
||||
|
||||
|
||||
func _start_fade_out() -> void:
|
||||
if not _active:
|
||||
return
|
||||
var t := create_tween()
|
||||
t.tween_property(self, "modulate:a", 0.0, FADE_OUT)
|
||||
t.tween_callback(func():
|
||||
visible = false
|
||||
_active = false
|
||||
)
|
||||
|
||||
|
||||
## Dismiss immediately (e.g. when dialogue opens).
|
||||
func dismiss() -> void:
|
||||
if not _active:
|
||||
return
|
||||
if _dismiss_tween and _dismiss_tween.is_valid():
|
||||
_dismiss_tween.kill()
|
||||
_start_fade_out()
|
||||
|
||||
|
||||
func is_active() -> bool:
|
||||
return _active
|
||||
Reference in New Issue
Block a user