From 11f61d62f4f4d3ba7ad3fe7bcce790ac9710a5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojte=CC=8Cch=20Struha=CC=81r?= Date: Tue, 11 Feb 2025 00:27:08 +0100 Subject: [PATCH] Walking through a portal (buggy) --- .../scripts/collision_disable_area.gd | 146 +++++++++--------- .../scripts/simple_portal_teleport.gd | 11 +- main.tscn | 44 +++++- 3 files changed, 122 insertions(+), 79 deletions(-) diff --git a/addons/simple-portal-system/scripts/collision_disable_area.gd b/addons/simple-portal-system/scripts/collision_disable_area.gd index 9b55c5e..ab01910 100644 --- a/addons/simple-portal-system/scripts/collision_disable_area.gd +++ b/addons/simple-portal-system/scripts/collision_disable_area.gd @@ -1,10 +1,10 @@ """ - Asset: Godot Simple Portal System - File: collision_disable_area.gd - Description: An area in which collisions are disabled for physics bodies based on the "disabled_collision_masks" metadata array. - Instructions: For detailed documentation, see the README or visit: https://github.com/Donitzo/godot-simple-portal-system - Repository: https://github.com/Donitzo/godot-simple-portal-system - License: CC0 License + Asset: Godot Simple Portal System + File: collision_disable_area.gd + Description: An area in which collisions are disabled for physics bodies based on the "disabled_collision_masks" metadata array. + Instructions: For detailed documentation, see the README or visit: https://github.com/Donitzo/godot-simple-portal-system + Repository: https://github.com/Donitzo/godot-simple-portal-system + License: CC0 License """ extends Area3D @@ -17,79 +17,79 @@ class_name CollisionDisableArea var _disables:Array = [] func _ready() -> void: - connect("body_entered", _on_body_entered) - connect("body_exited", _on_body_exited) + connect("body_entered", _on_body_entered) + connect("body_exited", _on_body_exited) func _process(delta:float) -> void: - for i in range(_disables.size() - 1, -1, -1): - var disable_info:Dictionary = _disables[i] - - if not is_instance_valid(disable_info.body): - # Body has been freed, remove disable info - _disables.remove_at(i) - continue - - if not disable_info.left: - # The body has yet to leave the area - continue + for i in range(_disables.size() - 1, -1, -1): + var disable_info:Dictionary = _disables[i] + + if not is_instance_valid(disable_info.body): + # Body has been freed, remove disable info + _disables.remove_at(i) + continue + + if not disable_info.left: + # The body has yet to leave the area + continue - # The body left the area, so reduce its timeout before removal - disable_info.seconds_until_enable -= delta - if disable_info.seconds_until_enable > 0: - continue - - _disables.remove_at(i) - - # Re-enable collision masks - for layer_number in disable_info.disabled_layers: - # Only consider layers which were enabled to begin with - if disable_info.disable_count.has(layer_number): - # Decrement disables so only the final area actually disables the mask - disable_info.disable_count[layer_number] -= 1 - if disable_info.disable_count[layer_number] == 0: - # Final disable, so re-enable the collision mask - disable_info.body.set_collision_mask_value(layer_number, true) - + # The body left the area, so reduce its timeout before removal + disable_info.seconds_until_enable -= delta + if disable_info.seconds_until_enable > 0: + continue + + _disables.remove_at(i) + + # Re-enable collision masks + for layer_number in disable_info.disabled_layers: + # Only consider layers which were enabled to begin with + if disable_info.disable_count.has(layer_number): + # Decrement disables so only the final area actually disables the mask + disable_info.disable_count[layer_number] -= 1 + if disable_info.disable_count[layer_number] == 0: + # Final disable, so re-enable the collision mask + disable_info.body.set_collision_mask_value(layer_number, true) + func _on_body_entered(body:PhysicsBody3D) -> void: - if not body.has_meta("disabled_collision_masks"): - return + if not body.has_meta("disabled_collision_masks"): + return - # Is the body already disabled by this area? - for disable_info in _disables: - if disable_info.body == body: - # Reset left and timeout - disable_info.left = false - disable_info.seconds_until_enable = re_enable_delay_seconds - return + # Is the body already disabled by this area? + for disable_info in _disables: + if disable_info.body == body: + # Reset left and timeout + disable_info.left = false + disable_info.seconds_until_enable = re_enable_delay_seconds + return - # Keep track of the number of times each collision mask is disabled in a meta field - if not body.has_meta("collision_disable_count"): - body.set_meta("collision_disable_count", {}) - var disable_count:Dictionary = body.get_meta("collision_disable_count") + # Keep track of the number of times each collision mask is disabled in a meta field + if not body.has_meta("collision_disable_count"): + body.set_meta("collision_disable_count", {}) + var disable_count:Dictionary = body.get_meta("collision_disable_count") - # Disable the collision masks specified in the "disabled_collision_masks" metadata array - var disabled_layers:Array = body.get_meta("disabled_collision_masks") - for layer_number in disabled_layers: - # Only consider layers which were enabled to begin with - if disable_count.has(layer_number) or body.get_collision_mask_value(layer_number): - # Increment disables so only the first area actually disables the mask - disable_count[layer_number] = 1 if not disable_count.has(layer_number) else disable_count[layer_number] + 1 - if disable_count[layer_number] == 1: - # First disable, so disable the collision mask - body.set_collision_mask_value(layer_number, false) - - # Keep a reference to all current disables in the area - _disables.push_back({ - "body": body, - "disabled_layers": disabled_layers, - "disable_count": disable_count, - "seconds_until_enable": re_enable_delay_seconds, - "left": false, - }) + # Disable the collision masks specified in the "disabled_collision_masks" metadata array + var disabled_layers:Array = body.get_meta("disabled_collision_masks") + for layer_number in disabled_layers: + # Only consider layers which were enabled to begin with + if disable_count.has(layer_number) or body.get_collision_mask_value(layer_number): + # Increment disables so only the first area actually disables the mask + disable_count[layer_number] = 1 if not disable_count.has(layer_number) else disable_count[layer_number] + 1 + if disable_count[layer_number] == 1: + # First disable, so disable the collision mask + body.set_collision_mask_value(layer_number, false) + + # Keep a reference to all current disables in the area + _disables.push_back({ + "body": body, + "disabled_layers": disabled_layers, + "disable_count": disable_count, + "seconds_until_enable": re_enable_delay_seconds, + "left": false, + }) func _on_body_exited(body:PhysicsBody3D) -> void: - if body.has_meta("disabled_collision_masks"): - for disable_info in _disables: - if disable_info.body == body: - # Mark the body as having left the area - disable_info.left = true + if body.has_meta("disabled_collision_masks"): + for disable_info in _disables: + if disable_info.body == body: + # Mark the body as having left the area + disable_info.left = true diff --git a/addons/simple-portal-system/scripts/simple_portal_teleport.gd b/addons/simple-portal-system/scripts/simple_portal_teleport.gd index 5eb2cb3..a79c3d1 100644 --- a/addons/simple-portal-system/scripts/simple_portal_teleport.gd +++ b/addons/simple-portal-system/scripts/simple_portal_teleport.gd @@ -10,16 +10,21 @@ extends Area3D class_name SimplePortalTeleport -var _parent_portal:Portal +var _parent_portal: Portal func _ready(): _parent_portal = get_parent() as Portal if _parent_portal == null: push_error("The PortalTeleport \"%s\" is not a child of a Portal instance" % name) - connect("area_entered", _on_area_entered) + area_entered.connect(_on_area_entered) + body_entered.connect(_on_body_entered) -func _on_area_entered(area:Area3D): +func _on_area_entered(area: Area3D) -> void: if area.has_meta("teleportable_root"): var root:Node3D = area.get_node(area.get_meta("teleportable_root")) root.global_transform = _parent_portal.real_to_exit_transform(root.global_transform) + +func _on_body_entered(body: Node3D) -> void: + if body.has_meta("teleportable"): + body.global_transform = _parent_portal.real_to_exit_transform(body.global_transform) diff --git a/main.tscn b/main.tscn index 4760118..892aa3c 100644 --- a/main.tscn +++ b/main.tscn @@ -1,7 +1,10 @@ -[gd_scene load_steps=7 format=3 uid="uid://dpatwnepecl8r"] +[gd_scene load_steps=13 format=3 uid="uid://dpatwnepecl8r"] [ext_resource type="MeshLibrary" uid="uid://bedqgubx1g1uf" path="res://prototypes.tres" id="1_ig7tw"] [ext_resource type="Script" uid="uid://bp1bo57yqtv65" path="res://player.gd" id="2_0xm2m"] +[ext_resource type="ArrayMesh" uid="uid://bqilnvlfws6xh" path="res://portal-mesh.tres" id="3_1bvp3"] +[ext_resource type="Script" uid="uid://d2bvvjsibau8c" path="res://addons/simple-portal-system/scripts/portal.gd" id="4_lquwl"] +[ext_resource type="Script" uid="uid://bkv7t4hw21byg" path="res://addons/simple-portal-system/scripts/simple_portal_teleport.gd" id="5_lquwl"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_ig7tw"] sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1) @@ -13,13 +16,19 @@ sky_material = SubResource("ProceduralSkyMaterial_ig7tw") [sub_resource type="Environment" id="Environment_h2yge"] background_mode = 2 sky = SubResource("Sky_0xm2m") -tonemap_mode = 2 glow_enabled = true [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_0xm2m"] -radius = 0.4 +radius = 0.05 height = 1.75 +[sub_resource type="Environment" id="Environment_lquwl"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_1bvp3"] +size = Vector3(2, 2.5, 0.2) + +[sub_resource type="Environment" id="Environment_7mycd"] + [node name="Main" type="Node3D"] [node name="WorldEnvironment" type="WorldEnvironment" parent="."] @@ -60,6 +69,7 @@ omni_range = 4.0 [node name="Player" type="CharacterBody3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.28597, -3) script = ExtResource("2_0xm2m") +metadata/teleportable = true [node name="Camera3D" type="Camera3D" parent="Player"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.32153, 0) @@ -67,3 +77,31 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.32153, 0) [node name="CollisionShape3D" type="CollisionShape3D" parent="Player"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.875, 0) shape = SubResource("CapsuleShape3D_0xm2m") + +[node name="P_white_wide" type="MeshInstance3D" parent="." node_paths=PackedStringArray("exit_portal")] +transform = Transform3D(1.1, 0, 0, 0, 1.1, 0, 0, 0, 1.1, 0, 2, -6.5) +mesh = ExtResource("3_1bvp3") +script = ExtResource("4_lquwl") +exit_environment = SubResource("Environment_lquwl") +exit_portal = NodePath("../P_green_wide") + +[node name="Teleport" type="Area3D" parent="P_white_wide"] +script = ExtResource("5_lquwl") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="P_white_wide/Teleport"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.1) +shape = SubResource("BoxShape3D_1bvp3") + +[node name="P_green_wide" type="MeshInstance3D" parent="." node_paths=PackedStringArray("exit_portal")] +transform = Transform3D(1.1, 0, 0, 0, 1.1, 0, 0, 0, 1.1, 16, 2, -6.5) +mesh = ExtResource("3_1bvp3") +script = ExtResource("4_lquwl") +exit_environment = SubResource("Environment_7mycd") +exit_portal = NodePath("../P_white_wide") + +[node name="Teleport" type="Area3D" parent="P_green_wide"] +script = ExtResource("5_lquwl") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="P_green_wide/Teleport"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.1) +shape = SubResource("BoxShape3D_1bvp3")