Lots of little tweaks and fixes
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
class_name ConfirmDialog extends ClosableMenu
|
||||
|
||||
signal confirmed
|
||||
|
||||
@export var btnYes:Button
|
||||
@export var btnNo:Button
|
||||
|
||||
func _ready() -> void:
|
||||
close()
|
||||
btnYes.pressed.connect(_onYes)
|
||||
btnNo.pressed.connect(close)
|
||||
btnYes.focus_neighbor_top = btnNo.get_path()
|
||||
btnYes.focus_neighbor_bottom = btnNo.get_path()
|
||||
btnNo.focus_neighbor_top = btnYes.get_path()
|
||||
btnNo.focus_neighbor_bottom = btnYes.get_path()
|
||||
|
||||
func _onYes() -> void:
|
||||
close()
|
||||
confirmed.emit()
|
||||
|
||||
func open() -> void:
|
||||
super.open()
|
||||
btnNo.grab_focus()
|
||||
|
||||
func _unhandled_input(event:InputEvent) -> void:
|
||||
if !isOpen:
|
||||
return
|
||||
if event.is_action_pressed("ui_cancel"):
|
||||
close()
|
||||
get_viewport().set_input_as_handled()
|
||||
@@ -5,8 +5,7 @@ const SCENE:PackedScene = preload("res://ui/component/DialogueTextbox.tscn")
|
||||
enum AdvancementMode { PLAYER, TIMED }
|
||||
|
||||
const LINES_PER_PAGE:int = 4
|
||||
const CHARS_PER_SECOND:float = 20.0
|
||||
const SPEEDUP_MULTIPLIER:float = 4.0
|
||||
const CHARS_PER_SECOND:float = 24.0
|
||||
const PAUSE_COMMA:float = 0.15
|
||||
const PAUSE_SENTENCE:float = 0.4
|
||||
const PAUSE_ELLIPSIS_DOT:float = 0.3
|
||||
@@ -24,7 +23,6 @@ var _pauseTimer:float = 0.0
|
||||
var _autoAdvanceTimer:float = 0.0
|
||||
var _isRevealing:bool = false
|
||||
var _isWaitingForInput:bool = false
|
||||
var _hasLetGoOfInteract:bool = true
|
||||
var _advancementMode:AdvancementMode = AdvancementMode.PLAYER
|
||||
|
||||
@onready var _speakerLabel:Label = $VBoxContainer/SpeakerLabel
|
||||
@@ -68,7 +66,6 @@ func setup(line:DialogueLine, entity:Entity, mode:AdvancementMode = AdvancementM
|
||||
_autoAdvanceTimer = 0.0
|
||||
_isRevealing = true
|
||||
_isWaitingForInput = false
|
||||
_hasLetGoOfInteract = !Input.is_action_pressed("interact")
|
||||
|
||||
_updateWorldPosition()
|
||||
visible = true
|
||||
@@ -85,9 +82,10 @@ func _process(delta:float) -> void:
|
||||
return
|
||||
|
||||
_updateWorldPosition()
|
||||
_advanceIndicator.visible = _isWaitingForInput
|
||||
if _isWaitingForInput:
|
||||
_advanceIndicator.modulate.a = 0.5 + 0.5 * sin(Time.get_ticks_msec() / 300.0)
|
||||
else:
|
||||
_advanceIndicator.modulate.a = 0.0
|
||||
|
||||
if _isRevealing:
|
||||
_processReveal(delta)
|
||||
@@ -119,16 +117,13 @@ func _buildPreWrappedText(parsed:String) -> String:
|
||||
return result
|
||||
|
||||
func _processReveal(delta:float) -> void:
|
||||
if Input.is_action_just_released("interact"):
|
||||
_hasLetGoOfInteract = true
|
||||
|
||||
var speedMult:float = SPEEDUP_MULTIPLIER if (_hasLetGoOfInteract and Input.is_action_pressed("interact")) else 1.0
|
||||
var scaledDelta:float = delta * SETTINGS.textSpeed
|
||||
|
||||
if _pauseTimer > 0.0:
|
||||
_pauseTimer -= delta * speedMult
|
||||
_pauseTimer -= scaledDelta
|
||||
return
|
||||
|
||||
_revealTimer += delta * speedMult
|
||||
_revealTimer += scaledDelta
|
||||
|
||||
while _revealTimer >= 1.0 / CHARS_PER_SECOND:
|
||||
_revealTimer -= 1.0 / CHARS_PER_SECOND
|
||||
@@ -185,12 +180,6 @@ func _onRevealComplete() -> void:
|
||||
_isWaitingForInput = true
|
||||
|
||||
func _processAdvanceInput() -> void:
|
||||
if Input.is_action_just_released("interact"):
|
||||
_hasLetGoOfInteract = true
|
||||
|
||||
if not _hasLetGoOfInteract:
|
||||
return
|
||||
|
||||
if Input.is_action_just_pressed("interact"):
|
||||
_advance()
|
||||
|
||||
@@ -200,8 +189,7 @@ func _processAutoAdvance(delta:float) -> void:
|
||||
_advance()
|
||||
|
||||
func _advance() -> void:
|
||||
_advanceIndicator.visible = false
|
||||
_advanceIndicator.modulate.a = 1.0
|
||||
_advanceIndicator.modulate.a = 0.0
|
||||
var totalLines:int = _parsedText.count("\n") + 1
|
||||
var hasMorePages:bool = _startLine + _linesPerPage < totalLines
|
||||
if hasMorePages:
|
||||
|
||||
@@ -28,6 +28,6 @@ autowrap_mode = 3
|
||||
|
||||
[node name="AdvanceIndicator" type="Label" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
modulate = Color(1, 1, 1, 0)
|
||||
text = "▼"
|
||||
horizontal_alignment = 2
|
||||
visible = false
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
class_name InteractIndicator extends PanelContainer
|
||||
|
||||
var _entity:Entity = null
|
||||
|
||||
func _enter_tree() -> void:
|
||||
UI.interactIndicator = self
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if UI.interactIndicator == self:
|
||||
UI.interactIndicator = null
|
||||
|
||||
func _ready() -> void:
|
||||
visible = false
|
||||
DialogueManager.dialogue_started.connect(_onDialogueStarted)
|
||||
DialogueManager.dialogue_ended.connect(_onDialogueEnded)
|
||||
|
||||
func setEntity(entity:Entity) -> void:
|
||||
if is_instance_valid(_entity):
|
||||
_entity.tree_exiting.disconnect(_onEntityExiting)
|
||||
_entity = entity
|
||||
_entity.tree_exiting.connect(_onEntityExiting)
|
||||
visible = _canShow()
|
||||
if visible:
|
||||
updateWorldPosition()
|
||||
|
||||
func clear() -> void:
|
||||
if is_instance_valid(_entity):
|
||||
_entity.tree_exiting.disconnect(_onEntityExiting)
|
||||
_entity = null
|
||||
visible = false
|
||||
|
||||
func _canShow() -> bool:
|
||||
return _entity != null and not UI.dialogueActive
|
||||
|
||||
func _onEntityExiting() -> void:
|
||||
_entity = null
|
||||
visible = false
|
||||
|
||||
func _onDialogueStarted(_resource:DialogueResource) -> void:
|
||||
visible = false
|
||||
|
||||
func _onDialogueEnded(_resource:DialogueResource) -> void:
|
||||
visible = _canShow()
|
||||
if visible:
|
||||
updateWorldPosition()
|
||||
|
||||
func updateWorldPosition() -> void:
|
||||
var camera:Camera3D = get_viewport().get_camera_3d()
|
||||
if camera == null:
|
||||
return
|
||||
var worldPos:Vector3 = _entity.global_position + Vector3(0, 2.5, 0)
|
||||
var screenPos:Vector2 = camera.unproject_position(worldPos)
|
||||
var viewportSize:Vector2 = get_viewport().get_visible_rect().size
|
||||
position = screenPos - size * 0.5
|
||||
position.x = clamp(position.x, 0.0, viewportSize.x - size.x)
|
||||
position.y = clamp(position.y, 0.0, viewportSize.y - size.y)
|
||||
@@ -0,0 +1 @@
|
||||
uid://xrcb2e7jwlm0
|
||||
@@ -0,0 +1,13 @@
|
||||
[gd_scene load_steps=3 format=3]
|
||||
|
||||
[ext_resource type="Theme" path="res://ui/UI Theme.tres" id="1"]
|
||||
[ext_resource type="Script" path="res://ui/component/InteractIndicator.gd" id="2"]
|
||||
|
||||
[node name="InteractIndicator" type="PanelContainer"]
|
||||
mouse_filter = 2
|
||||
theme = ExtResource("1")
|
||||
script = ExtResource("2")
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
text = "INTERACT"
|
||||
@@ -0,0 +1,38 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bmmc3x8n1d7qp"]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/component/ConfirmDialog.gd" id="1_mmcd"]
|
||||
|
||||
[node name="MainMenuConfirmDialog" type="Control" node_paths=PackedStringArray("btnYes", "btnNo")]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
process_mode = 3
|
||||
script = ExtResource("1_mmcd")
|
||||
btnYes = NodePath("VBoxContainer/Yes")
|
||||
btnNo = NodePath("VBoxContainer/No")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Return to main menu?"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="Yes" type="Button" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Yes"
|
||||
|
||||
[node name="No" type="Button" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "No"
|
||||
@@ -0,0 +1,48 @@
|
||||
class_name ModalBackdrop extends ColorRect
|
||||
|
||||
# Tracks which overlays are currently open. Each entry must be a direct sibling
|
||||
# (child of the same parent). The backdrop repositions itself in the scene tree
|
||||
# to sit immediately below whichever open overlay has the highest tree index,
|
||||
# so only one backdrop is ever visible regardless of how many overlays are open.
|
||||
var _openOverlays:Array[Control] = []
|
||||
|
||||
func _ready() -> void:
|
||||
visible = false
|
||||
|
||||
func register(overlay:Control) -> void:
|
||||
assert(overlay.get_parent() == get_parent(), "ModalBackdrop: overlay must be a sibling")
|
||||
assert(overlay.has_signal("opened") and overlay.has_signal("closed"),
|
||||
"ModalBackdrop: overlay must have opened/closed signals")
|
||||
overlay.connect("opened", func(): _onOpened(overlay))
|
||||
overlay.connect("closed", func(): _onClosed(overlay))
|
||||
|
||||
func _onOpened(overlay:Control) -> void:
|
||||
if overlay not in _openOverlays:
|
||||
_openOverlays.append(overlay)
|
||||
_reposition()
|
||||
|
||||
func _onClosed(overlay:Control) -> void:
|
||||
_openOverlays.erase(overlay)
|
||||
_reposition()
|
||||
|
||||
func _reposition() -> void:
|
||||
if _openOverlays.is_empty():
|
||||
visible = false
|
||||
return
|
||||
visible = true
|
||||
var top := _topOverlay()
|
||||
var topIdx := top.get_index()
|
||||
var myIdx := get_index()
|
||||
if myIdx == topIdx - 1:
|
||||
return
|
||||
if myIdx < topIdx:
|
||||
get_parent().move_child(self, topIdx - 1)
|
||||
else:
|
||||
get_parent().move_child(self, topIdx)
|
||||
|
||||
func _topOverlay() -> Control:
|
||||
var top:Control = _openOverlays[0]
|
||||
for overlay in _openOverlays:
|
||||
if overlay.get_index() > top.get_index():
|
||||
top = overlay
|
||||
return top
|
||||
@@ -0,0 +1,5 @@
|
||||
class_name QuitConfirmDialog extends ConfirmDialog
|
||||
|
||||
func _ready() -> void:
|
||||
super._ready()
|
||||
confirmed.connect(func(): get_tree().quit())
|
||||
@@ -0,0 +1 @@
|
||||
uid://deov3ob0lojyo
|
||||
@@ -0,0 +1,38 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cqdf1x7m2canp"]
|
||||
|
||||
[ext_resource type="Script" path="res://ui/component/QuitConfirmDialog.gd" id="1_qcd"]
|
||||
|
||||
[node name="QuitConfirmDialog" type="Control" node_paths=PackedStringArray("btnYes", "btnNo")]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
process_mode = 3
|
||||
script = ExtResource("1_qcd")
|
||||
btnYes = NodePath("VBoxContainer/Yes")
|
||||
btnNo = NodePath("VBoxContainer/No")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchors_preset = 8
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Quit to desktop?"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="Yes" type="Button" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Yes"
|
||||
|
||||
[node name="No" type="Button" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "No"
|
||||
Reference in New Issue
Block a user