From 72bea660828bad6b53bd7cf047b82dbc12627126 Mon Sep 17 00:00:00 2001 From: Rendo Date: Fri, 19 Dec 2025 13:23:41 +0500 Subject: [PATCH] Interaction rework --- scenes/camera_3d.tscn | 4 +- scenes/flask.tscn | 10 ++++- scenes/interactible_object.tscn | 2 +- scenes/substance_jar.tscn | 4 +- src/drag/draggable_camera.gd | 25 ++++++++++--- src/drag/draggable_object.gd | 15 ++++++-- src/interactible/interactible.gd | 4 +- src/interactible/interactible_detector.gd | 37 +++++++++++++++++++ src/interactible/interactible_detector.gd.uid | 1 + src/ui/drag_and_drop.gd | 4 +- src/ui/reagent_drag_and_drop.gd | 7 ++-- 11 files changed, 90 insertions(+), 23 deletions(-) create mode 100644 src/interactible/interactible_detector.gd create mode 100644 src/interactible/interactible_detector.gd.uid diff --git a/scenes/camera_3d.tscn b/scenes/camera_3d.tscn index ee03a43..856c481 100644 --- a/scenes/camera_3d.tscn +++ b/scenes/camera_3d.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=3 format=3 uid="uid://c2vxq6kqhris0"] +[gd_scene load_steps=4 format=3 uid="uid://b8edjit66j7st"] [ext_resource type="Script" uid="uid://crjao0jjv5yqs" path="res://src/drag/draggable_camera.gd" id="1_v4apc"] +[ext_resource type="Script" uid="uid://d77lra3ar60b" path="res://src/interactible/interactible_detector.gd" id="2_nstyr"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_hflkp"] radius = 0.1 @@ -16,6 +17,7 @@ target_position = Vector3(0, 0, -10) [node name="InteractionArea" type="Area3D" parent="."] collision_layer = 0 collision_mask = 4 +script = ExtResource("2_nstyr") [node name="CollisionShape3D" type="CollisionShape3D" parent="InteractionArea"] transform = Transform3D(1, 0, 0, 0, -2.9802322e-08, -1, 0, 1, -2.9802322e-08, 0, 3.5762787e-07, -5.2500005) diff --git a/scenes/flask.tscn b/scenes/flask.tscn index 32ef41d..a5b63c0 100644 --- a/scenes/flask.tscn +++ b/scenes/flask.tscn @@ -1,16 +1,18 @@ -[gd_scene load_steps=5 format=3 uid="uid://bjxjcx2qu16q5"] +[gd_scene load_steps=6 format=3 uid="uid://bjxjcx2qu16q5"] [ext_resource type="Script" uid="uid://bjnv2g1ni0525" path="res://src/drag/draggable_object.gd" id="1_0xufn"] [ext_resource type="PackedScene" uid="uid://b6ydpkle2ol20" path="res://assets/models/FlaskNew.glb" id="2_h7awq"] +[ext_resource type="Script" uid="uid://bl0ojhc0thk1p" path="res://src/interactible/interactible.gd" id="4_dbm1u"] [ext_resource type="Script" uid="uid://82ettbegollp" path="res://src/inventory.gd" id="7_h7awq"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_vcwhe"] radius = 0.1 height = 0.9921875 -[node name="Flask" type="Area3D"] +[node name="Flask" type="Area3D" node_paths=PackedStringArray("interactible")] collision_layer = 5 script = ExtResource("1_0xufn") +interactible = NodePath("Interactible") [node name="DragArea" type="CollisionShape3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) @@ -24,3 +26,7 @@ unique_name_in_owner = true script = ExtResource("7_h7awq") open_on_top = true metadata/_custom_type_script = "uid://82ettbegollp" + +[node name="Interactible" type="ConfirmationDialog" parent="."] +script = ExtResource("4_dbm1u") +interaction_target_groups = PackedStringArray("test") diff --git a/scenes/interactible_object.tscn b/scenes/interactible_object.tscn index 0feef0d..779ee6c 100644 --- a/scenes/interactible_object.tscn +++ b/scenes/interactible_object.tscn @@ -1,6 +1,6 @@ [gd_scene load_steps=5 format=3 uid="uid://q1y0r2rn0qb4"] -[ext_resource type="Script" uid="uid://mjx50qh1bwv3" path="res://src/interactible/interaction_reciever.gd" id="1_auicg"] +[ext_resource type="Script" path="res://src/interactible/interaction_reciever.gd" id="1_auicg"] [ext_resource type="Material" uid="uid://64m17act0kwu" path="res://assets/materials/mat_glass.tres" id="2_mqqtq"] [sub_resource type="CylinderMesh" id="CylinderMesh_nql6a"] diff --git a/scenes/substance_jar.tscn b/scenes/substance_jar.tscn index 441dd3f..35c7d63 100644 --- a/scenes/substance_jar.tscn +++ b/scenes/substance_jar.tscn @@ -13,9 +13,10 @@ resource_local_to_scene = true height = 0.5024414 radius = 0.22460938 -[node name="Flask" type="Area3D"] +[node name="Flask" type="Area3D" node_paths=PackedStringArray("interactible") groups=["test"]] collision_layer = 5 script = ExtResource("1_o7vug") +interactible = NodePath("Interaction") [node name="Jar" type="MeshInstance3D" parent="."] transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) @@ -34,5 +35,4 @@ shape = SubResource("CylinderShape3D_kfk5m") script = ExtResource("7_ymvgp") [node name="Interaction" type="ConfirmationDialog" parent="."] -unique_name_in_owner = true script = ExtResource("5_o7vug") diff --git a/src/drag/draggable_camera.gd b/src/drag/draggable_camera.gd index 5f16484..f2018b6 100644 --- a/src/drag/draggable_camera.gd +++ b/src/drag/draggable_camera.gd @@ -1,11 +1,13 @@ extends Camera3D +class_name DraggableCamera + const SENSITIVITY = 0.01 var interaction_source: DraggableObject var plane_position: Vector3 @onready var drag_raycast: RayCast3D = $DragRaycast -@onready var interaction_area: Area3D = $InteractionArea +@onready var interaction_area: InteractibleDetector = $InteractionArea func _process(_delta: float) -> void: drag_raycast.target_position = project_local_ray_normal(get_viewport().get_mouse_position()) * 10.0 @@ -18,10 +20,21 @@ func _input(event: InputEvent) -> void: global_position += Vector3.FORWARD * event.relative.y * SENSITIVITY if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: - var areas = interaction_area.get_overlapping_areas() - for area in areas: - if area == interaction_source: + for draggable in interaction_area.filtered_draggables: + if draggable == interaction_source: continue - area.try_interact(interaction_source) + interaction_source.interactible.try_interact(draggable) break - interaction_source = null + end_interaction_seeking() + +func start_interaction_seeking(new_interaction_source: DraggableObject) -> void: + if new_interaction_source.interactible == null: + return + interaction_source = new_interaction_source + interaction_area.set_mask(interaction_source.interactible.get_groups()) + +func end_interaction_seeking() -> void: + if interaction_source == null: + return + + interaction_source = null diff --git a/src/drag/draggable_object.gd b/src/drag/draggable_object.gd index c268d29..c9af83f 100644 --- a/src/drag/draggable_object.gd +++ b/src/drag/draggable_object.gd @@ -6,7 +6,17 @@ signal drag_started signal drag_ended var mouse_in: bool = false -var dragged: bool = false +var dragged: bool = false: + set(value): + if dragged != value: + if value: + drag_started.emit() + get_viewport().get_camera_3d().start_interaction_seeking(self) + else: + drag_ended.emit() + dragged = value + +@export var interactible: Interactible func _mouse_enter() -> void: mouse_in = true @@ -24,8 +34,5 @@ func _input(event: InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: if mouse_in and event.pressed: dragged = true - drag_started.emit() - get_viewport().get_camera_3d().interaction_source = self if event.pressed == false: dragged = false - drag_ended.emit() diff --git a/src/interactible/interactible.gd b/src/interactible/interactible.gd index d606560..f0744a1 100644 --- a/src/interactible/interactible.gd +++ b/src/interactible/interactible.gd @@ -16,8 +16,8 @@ func _ready() -> void: canceled.connect(cancel_interaction) func try_interact(draggable: DraggableObject) -> void: - if draggable.get_node("%Interaction") != null: - var interaction: Interactible = draggable.get_node("%Interaction") + if draggable.interactible != null: + var interaction: Interactible = draggable.interactible for group in interaction.get_groups(): if group in interaction_target_groups: current_draggable = draggable diff --git a/src/interactible/interactible_detector.gd b/src/interactible/interactible_detector.gd new file mode 100644 index 0000000..57ae05c --- /dev/null +++ b/src/interactible/interactible_detector.gd @@ -0,0 +1,37 @@ +extends Area3D + +class_name InteractibleDetector + +var mask: PackedStringArray +var contacted_draggables: Array[DraggableObject] +var filtered_draggables: Array[DraggableObject] + +func set_mask(new_mask: PackedStringArray) -> void: + mask.clear() + mask.append_array(new_mask) + filtered_draggables.clear() + for contacted in contacted_draggables: + filtered_draggables.append(contacted) + +func _ready() -> void: + area_entered.connect(on_area_entered) + area_exited.connect(on_area_exited) + +func on_area_entered(area: Area3D) -> void: + if area is DraggableObject: + contacted_draggables.append(area) + if is_in_mask(area.get_groups()): + filtered_draggables.append(area) + +func on_area_exited(area: Area3D) -> void: + if area is DraggableObject: + contacted_draggables.erase(area) + if filtered_draggables.has(area): + filtered_draggables.erase(area) + +func is_in_mask(groups: Array[StringName]) -> bool: + for group in groups: + if group in mask: + return true + return false + diff --git a/src/interactible/interactible_detector.gd.uid b/src/interactible/interactible_detector.gd.uid new file mode 100644 index 0000000..f05efb4 --- /dev/null +++ b/src/interactible/interactible_detector.gd.uid @@ -0,0 +1 @@ +uid://d77lra3ar60b diff --git a/src/ui/drag_and_drop.gd b/src/ui/drag_and_drop.gd index 66d5a80..bb9f590 100644 --- a/src/ui/drag_and_drop.gd +++ b/src/ui/drag_and_drop.gd @@ -5,9 +5,9 @@ extends Button func _on_button_down() -> void: var scene = draggable.scene_to_spawn.instantiate() + get_tree().current_scene.add_child(scene) if scene is DraggableObject: scene.dragged = true scene.mouse_in = true - get_tree().current_scene.add_child(scene) var camera = get_viewport().get_camera_3d() - scene.global_position = camera.project_position(get_global_mouse_position(),1.8) + scene.global_position = camera.plane_position diff --git a/src/ui/reagent_drag_and_drop.gd b/src/ui/reagent_drag_and_drop.gd index c20e3f1..fb65447 100644 --- a/src/ui/reagent_drag_and_drop.gd +++ b/src/ui/reagent_drag_and_drop.gd @@ -8,10 +8,11 @@ func _ready() -> void: func _on_button_down() -> void: var scene = reagent.storage.instantiate() + + scene.get_node("SubstanceData").substance = reagent.substance + get_tree().current_scene.add_child(scene) if scene is DraggableObject: scene.dragged = true scene.mouse_in = true - scene.get_node("SubstanceData").substance = reagent.substance - get_tree().current_scene.add_child(scene) var camera = get_viewport().get_camera_3d() - scene.global_position = camera.project_position(get_global_mouse_position(),1.8) + scene.global_position = camera.plane_position