From 6b3ac1311edb277134e2b86ab49bbf1c8f5d217d Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Fri, 4 Jul 2025 14:56:35 -0600 Subject: [PATCH] Holdable component HUD --- src/player/hold_component.gd | 18 +++++----- src/player/player.gd | 2 ++ src/player/player.tscn | 1 + src/props/physics/holdable.gd | 24 ++++++++++--- src/ui/hud/hold_hud.gd | 49 ++++++++++++++++++++++++++ src/ui/hud/hold_hud.gd.uid | 1 + src/ui/hud/interact_hud.gd | 3 -- src/ui/hud/player_hud.gd | 2 ++ src/ui/hud/player_hud.tscn | 65 ++++++++++++++++++++++++++++++++--- vault/TODO.md | 2 +- 10 files changed, 143 insertions(+), 24 deletions(-) create mode 100644 src/ui/hud/hold_hud.gd create mode 100644 src/ui/hud/hold_hud.gd.uid diff --git a/src/player/hold_component.gd b/src/player/hold_component.gd index 6270713..eff8a96 100644 --- a/src/player/hold_component.gd +++ b/src/player/hold_component.gd @@ -1,4 +1,4 @@ -extends Node3D +class_name HoldComponent extends Node3D ## Component for managing physics object holding ## Held object position lerp acceleration. @@ -43,6 +43,8 @@ func attach(prop: RigidBody3D, hold_distance: float) -> void: _original_collision_mask = prop.collision_mask prop.collision_mask = hold_collision_physics + Player.instance.hud.hold_hud.prop_held() + func drop() -> void: _held_object.linear_damp = _original_damping @@ -50,6 +52,8 @@ func drop() -> void: _held_object.collision_mask = _original_collision_mask _held_object = null + Player.instance.hud.hold_hud.reset() + func holding_object() -> bool: return !!_held_object @@ -57,17 +61,11 @@ func holding_object() -> bool: func _physics_process(delta: float) -> void: # Object hold action logic - if Input.is_action_just_pressed("interact"): - if _held_object: - drop() - elif interact_ray.is_colliding(): - var body := interact_ray.get_collider() as RigidBody3D - var hold_component := Holdable.get_component(body) - if hold_component: - attach(body, hold_component.hold_distance) + if holding_object() and Input.is_action_just_pressed("interact"): + drop() # Held object logic - if not _held_object: + if not holding_object(): return var diff := hold_point.global_position - (_held_object.global_position) diff --git a/src/player/player.gd b/src/player/player.gd index d74cf41..d9c34bb 100644 --- a/src/player/player.gd +++ b/src/player/player.gd @@ -62,6 +62,8 @@ var _was_on_floor := false @onready var mp3_player: Tool = %MP3Player @onready var sticker_pack: Tool = %StickerPack +@onready var hold_component: HoldComponent = %HoldComponent + @onready var crouch_head_area: Area3D = %CrouchHeadArea @onready var crouch_animation: AnimationPlayer = %CrouchAnimation @onready var grab_animation: AnimationPlayer = %GrabAnimation diff --git a/src/player/player.tscn b/src/player/player.tscn index d948027..415fcec 100644 --- a/src/player/player.tscn +++ b/src/player/player.tscn @@ -685,6 +685,7 @@ parameters/timescale/scale = false script = ExtResource("7_x42xx") [node name="HoldComponent" type="Node3D" parent="CameraPosition/CameraPivot/TransformedPosition/CamRumbler/Camera3D"] +unique_name_in_owner = true script = ExtResource("11_h0enb") hold_accel = 40.0 hold_speed = 20.0 diff --git a/src/props/physics/holdable.gd b/src/props/physics/holdable.gd index 05037cc..52e5959 100644 --- a/src/props/physics/holdable.gd +++ b/src/props/physics/holdable.gd @@ -2,10 +2,24 @@ class_name Holdable extends Node ## Component for holdable elements @export var hold_distance := 1.0 +@export var controller: RigidBody3D -static func get_component(o: Object) -> Holdable: - var n := o as Node - if n and n.has_node("Holdable"): - return n.get_node_or_null("Holdable") as Holdable - return null +func _ready() -> void: + if not controller: + controller = get_parent() as RigidBody3D + assert(controller, "Holdable %s must be a child of a RigidBody3D" % str(self)) + + controller.add_user_signal(Interactive.SELECT_SIGNAL) + controller.connect(Interactive.SELECT_SIGNAL, select) + controller.add_user_signal(Interactive.ACTIVATE_SIGNAL) + controller.connect(Interactive.ACTIVATE_SIGNAL, activate) + + +func select() -> void: + Player.instance.hud.hold_hud.select_prop() + + +func activate() -> void: + if not Player.instance.hold_component.holding_object(): + Player.instance.hold_component.attach(controller, hold_distance) diff --git a/src/ui/hud/hold_hud.gd b/src/ui/hud/hold_hud.gd new file mode 100644 index 0000000..74530fa --- /dev/null +++ b/src/ui/hud/hold_hud.gd @@ -0,0 +1,49 @@ +class_name HoldHUD extends Control + +enum State { + NONE, + SELECTED, + HELD, +} + +var state := State.NONE +var _selected_this_frame := false + +@onready var open_hand: Label = %OpenHand +@onready var closed_hand: Label = %ClosedHand + + +func prop_selected() -> void: + state = State.SELECTED + open_hand.visible = true + closed_hand.visible = false + + +func prop_held() -> void: + state = State.HELD + open_hand.visible = false + closed_hand.visible = true + + +func reset() -> void: + state = State.NONE + open_hand.visible = false + closed_hand.visible = false + + +func select_prop() -> void: + _selected_this_frame = true + if state == State.NONE: + prop_selected() + + +func deselect() -> void: + if state == State.SELECTED: + reset() + + +func _process(_delta: float) -> void: + if not _selected_this_frame: + deselect() + + _selected_this_frame = false diff --git a/src/ui/hud/hold_hud.gd.uid b/src/ui/hud/hold_hud.gd.uid new file mode 100644 index 0000000..f7fcba5 --- /dev/null +++ b/src/ui/hud/hold_hud.gd.uid @@ -0,0 +1 @@ +uid://ctvu31jkk1un2 diff --git a/src/ui/hud/interact_hud.gd b/src/ui/hud/interact_hud.gd index 9a1add2..dd1aecb 100644 --- a/src/ui/hud/interact_hud.gd +++ b/src/ui/hud/interact_hud.gd @@ -25,17 +25,14 @@ func _transition_color(color: Color) -> void: func _to_visible() -> void: - print_debug("in _to_visible") _transition_color(COLOR_VISIBLE) func _to_disabled() -> void: - print_debug("in _to_disabled") _transition_color(COLOR_DISABLED) func _to_invisible() -> void: - print_debug("in _to_invisible") _transition_color(COLOR_INVISIBLE) diff --git a/src/ui/hud/player_hud.gd b/src/ui/hud/player_hud.gd index 809a212..3e6f33d 100644 --- a/src/ui/hud/player_hud.gd +++ b/src/ui/hud/player_hud.gd @@ -1,6 +1,7 @@ class_name PlayerHUD extends Control @onready var interact_hud: InteractHUD = %InteractHUD +@onready var hold_hud: HoldHUD = %HoldHUD @onready var grunk_alert_player: AnimationPlayer = %GrunkAlertPlayer @onready var tank_alert_player: AnimationPlayer = %TankAlertPlayer @@ -12,6 +13,7 @@ func _ready() -> void: World.instance.manager.alert_cleared.connect(_on_clear_alert) + func _on_raise_alert(_new_value: int) -> void: grunk_alert_player.play("grunk_alert") diff --git a/src/ui/hud/player_hud.tscn b/src/ui/hud/player_hud.tscn index bbe0929..68883c7 100644 --- a/src/ui/hud/player_hud.tscn +++ b/src/ui/hud/player_hud.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=3 uid="uid://dq1x21tq06dud"] +[gd_scene load_steps=18 format=3 uid="uid://dq1x21tq06dud"] [ext_resource type="Theme" uid="uid://b07fevr214mmr" path="res://src/ui/hud/hud_theme.tres" id="1_lirk3"] [ext_resource type="Script" uid="uid://lrsv0185bfu" path="res://src/ui/hud/player_hud.gd" id="2_j6lpx"] @@ -6,6 +6,7 @@ [ext_resource type="FontFile" uid="uid://qadtckvw0t3l" path="res://assets/fonts/fontawesome-free-6.7.2-desktop/otfs/Font Awesome 6 Free-Solid-900.otf" id="4_2q5it"] [ext_resource type="PackedScene" uid="uid://b47goj32i6sdh" path="res://src/ui/elements/input_prompt/input_prompt.tscn" id="4_iwjh7"] [ext_resource type="Script" uid="uid://cjs2fen6jo0g0" path="res://src/ui/rumbler.gd" id="4_ud8na"] +[ext_resource type="Script" uid="uid://ctvu31jkk1un2" path="res://src/ui/hud/hold_hud.gd" id="5_65kmv"] [ext_resource type="FontFile" uid="uid://oq8ue2qrfijg" path="res://assets/fonts/Silkscreen/Silkscreen-Regular.ttf" id="7_iwjh7"] [sub_resource type="Animation" id="Animation_iwjh7"] @@ -289,6 +290,60 @@ unique_name_in_owner = true layout_mode = 2 text = "use" +[node name="HoldHUD" type="Control" parent="."] +unique_name_in_owner = true +custom_minimum_size = Vector2(80, 80) +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -20.0 +offset_top = -20.0 +offset_right = 20.0 +offset_bottom = 20.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("5_65kmv") + +[node name="OpenHand" type="Label" parent="HoldHUD"] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -16.0 +offset_top = -16.0 +offset_right = 16.0 +offset_bottom = 16.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_fonts/font = ExtResource("4_2q5it") +text = "" + +[node name="ClosedHand" type="Label" parent="HoldHUD"] +unique_name_in_owner = true +visible = false +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -13.75 +offset_top = -10.012 +offset_right = 26.25 +offset_bottom = 31.3213 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_fonts/font = ExtResource("4_2q5it") +theme_override_font_sizes/font_size = 33 +text = "" + [node name="AlertHUD" type="Control" parent="."] custom_minimum_size = Vector2(800, 600) layout_mode = 1 @@ -372,10 +427,10 @@ anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 -offset_left = -18.3489 -offset_top = -21.6753 -offset_right = -18.3489 -offset_bottom = -21.6753 +offset_left = -23.5555 +offset_top = -20.5418 +offset_right = -23.5555 +offset_bottom = -20.5418 grow_horizontal = 2 grow_vertical = 2 script = ExtResource("4_ud8na") diff --git a/vault/TODO.md b/vault/TODO.md index 81a942f..6d84e90 100644 --- a/vault/TODO.md +++ b/vault/TODO.md @@ -168,7 +168,7 @@ - [ ] etc - [ ] Make sofa cushions separate physics objects - [ ] Object hold UX - - [ ] holdable object HUD icon + - [x] holdable object HUD icon - [ ] highlight holdable objects? - [ ] hide tool UI when holding - [ ] Keep bonus tracks, taco fiesta, maybe stickers in upgrade track. Everything else comes from the [[company store]], as well as upgrades. \ No newline at end of file