GDScript formatting
Thanks, VS Code (:
This commit is contained in:
parent
1e100bee4d
commit
42490ddad9
@ -11,16 +11,16 @@ extends Area3D
|
|||||||
class_name AdvancedPortalTeleport
|
class_name AdvancedPortalTeleport
|
||||||
|
|
||||||
## Checks if the node is moving TOWARDS the portal before teleporting it.
|
## Checks if the node is moving TOWARDS the portal before teleporting it.
|
||||||
@export var velocity_check:bool = true
|
@export var velocity_check: bool = true
|
||||||
## An additional velocity push given to RigidBody3Ds/CharacterBody3D exiting the portal.
|
## An additional velocity push given to RigidBody3Ds/CharacterBody3D exiting the portal.
|
||||||
@export var exit_push_velocity:float = 0
|
@export var exit_push_velocity: float = 0
|
||||||
## Seconds to keep portal clones visible after the node leaves the teleporter.
|
## Seconds to keep portal clones visible after the node leaves the teleporter.
|
||||||
@export var clone_keep_alive_seconds:float = 0.1
|
@export var clone_keep_alive_seconds: float = 0.1
|
||||||
|
|
||||||
var _parent_portal:Portal
|
var _parent_portal: Portal
|
||||||
|
|
||||||
# Info about the nodes currently crossing the portal
|
# Info about the nodes currently crossing the portal
|
||||||
var _crossing_nodes:Array = []
|
var _crossing_nodes: Array = []
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
_parent_portal = get_parent() as Portal
|
_parent_portal = get_parent() as Portal
|
||||||
@ -30,10 +30,10 @@ func _ready() -> void:
|
|||||||
connect("area_entered", _on_area_entered)
|
connect("area_entered", _on_area_entered)
|
||||||
connect("area_exited", _on_area_exited)
|
connect("area_exited", _on_area_exited)
|
||||||
|
|
||||||
func _process(delta:float) -> void:
|
func _process(delta: float) -> void:
|
||||||
# Update nodes crossing the portal
|
# Update nodes crossing the portal
|
||||||
for i in range(_crossing_nodes.size() - 1, -1, -1):
|
for i in range(_crossing_nodes.size() - 1, -1, -1):
|
||||||
var crossing_node:Dictionary = _crossing_nodes[i]
|
var crossing_node: Dictionary = _crossing_nodes[i]
|
||||||
|
|
||||||
if not is_instance_valid(crossing_node.node):
|
if not is_instance_valid(crossing_node.node):
|
||||||
# Node has been freed, remove crossing_node
|
# Node has been freed, remove crossing_node
|
||||||
@ -61,17 +61,17 @@ func _process(delta:float) -> void:
|
|||||||
_crossing_nodes.remove_at(i)
|
_crossing_nodes.remove_at(i)
|
||||||
|
|
||||||
# Try to teleport the crossing node, and return false otherwise
|
# Try to teleport the crossing node, and return false otherwise
|
||||||
func _try_teleport(crossing_node:Dictionary) -> bool:
|
func _try_teleport(crossing_node: Dictionary) -> bool:
|
||||||
var node:Node3D = crossing_node.node
|
var node: Node3D = crossing_node.node
|
||||||
|
|
||||||
# Check if the node is moving towards the portal
|
# Check if the node is moving towards the portal
|
||||||
if velocity_check:
|
if velocity_check:
|
||||||
if node is RigidBody3D:
|
if node is RigidBody3D:
|
||||||
var local_velocity:Vector3 = _parent_portal.global_transform.basis.inverse() * node.linear_velocity
|
var local_velocity: Vector3 = _parent_portal.global_transform.basis.inverse() * node.linear_velocity
|
||||||
if local_velocity.z >= 0:
|
if local_velocity.z >= 0:
|
||||||
return false
|
return false
|
||||||
elif node is CharacterBody3D:
|
elif node is CharacterBody3D:
|
||||||
var local_velocity:Vector3 = _parent_portal.global_transform.basis.inverse() * node.velocity
|
var local_velocity: Vector3 = _parent_portal.global_transform.basis.inverse() * node.velocity
|
||||||
if local_velocity.z >= 0:
|
if local_velocity.z >= 0:
|
||||||
return false
|
return false
|
||||||
else:
|
else:
|
||||||
@ -88,7 +88,7 @@ func _try_teleport(crossing_node:Dictionary) -> bool:
|
|||||||
|
|
||||||
# Additional push when exiting the portal
|
# Additional push when exiting the portal
|
||||||
if exit_push_velocity > 0:
|
if exit_push_velocity > 0:
|
||||||
var exit_forward:Vector3 = _parent_portal.exit_portal.global_transform.basis.z.normalized()
|
var exit_forward: Vector3 = _parent_portal.exit_portal.global_transform.basis.z.normalized()
|
||||||
node.linear_velocity += exit_forward * exit_push_velocity
|
node.linear_velocity += exit_forward * exit_push_velocity
|
||||||
|
|
||||||
# Handle CharacterBody3D physics
|
# Handle CharacterBody3D physics
|
||||||
@ -98,7 +98,7 @@ func _try_teleport(crossing_node:Dictionary) -> bool:
|
|||||||
|
|
||||||
# Additional push when exiting the portal
|
# Additional push when exiting the portal
|
||||||
if exit_push_velocity > 0:
|
if exit_push_velocity > 0:
|
||||||
var exit_forward:Vector3 = _parent_portal.exit_portal.global_transform.basis.z.normalized()
|
var exit_forward: Vector3 = _parent_portal.exit_portal.global_transform.basis.z.normalized()
|
||||||
node.velocity += exit_forward * exit_push_velocity
|
node.velocity += exit_forward * exit_push_velocity
|
||||||
|
|
||||||
# Transform the position and orientation
|
# Transform the position and orientation
|
||||||
@ -106,24 +106,23 @@ func _try_teleport(crossing_node:Dictionary) -> bool:
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func _on_area_entered(area:Area3D) -> void:
|
func _on_area_entered(area: Area3D) -> void:
|
||||||
if area.has_meta("teleportable_root"):
|
if area.has_meta("teleportable_root"):
|
||||||
# The node may not teleport immediately if it's not heading TOWARDS the portal,
|
# The node may not teleport immediately if it's not heading TOWARDS the portal,
|
||||||
# so we keep a reference to it until it teleports or leaves.
|
# so we keep a reference to it until it teleports or leaves.
|
||||||
# This also allows us to hide its portal clone after it leaves.
|
# This also allows us to hide its portal clone after it leaves.
|
||||||
|
var root: Node3D = area.get_node(area.get_meta("teleportable_root"))
|
||||||
|
|
||||||
var root:Node3D = area.get_node(area.get_meta("teleportable_root"))
|
var crossing_node: Dictionary
|
||||||
|
|
||||||
var crossing_node:Dictionary
|
|
||||||
if root.has_meta("crossing_node"):
|
if root.has_meta("crossing_node"):
|
||||||
# Node is crossing another portal, erase it from that portal and start using this one instead
|
# Node is crossing another portal, erase it from that portal and start using this one instead
|
||||||
crossing_node = root.get_meta("crossing_node")
|
crossing_node = root.get_meta("crossing_node")
|
||||||
crossing_node.teleporter._crossing_nodes.erase(crossing_node)
|
crossing_node.teleporter._crossing_nodes.erase(crossing_node)
|
||||||
else:
|
else:
|
||||||
# First portal
|
# First portal
|
||||||
var clone:Node3D = area.get_node(area.get_meta("portal_clone")) if area.has_meta("portal_clone") else null
|
var clone: Node3D = area.get_node(area.get_meta("portal_clone")) if area.has_meta("portal_clone") else null
|
||||||
crossing_node = {
|
crossing_node = {
|
||||||
"node": root,
|
"node": root,
|
||||||
"clone": clone,
|
"clone": clone,
|
||||||
"clone_portal": null,
|
"clone_portal": null,
|
||||||
"teleporter": null,
|
"teleporter": null,
|
||||||
@ -151,10 +150,10 @@ func _on_area_entered(area:Area3D) -> void:
|
|||||||
crossing_node.clone_portal = _parent_portal.exit_portal
|
crossing_node.clone_portal = _parent_portal.exit_portal
|
||||||
crossing_node.left = true
|
crossing_node.left = true
|
||||||
|
|
||||||
func _on_area_exited(area:Area3D) -> void:
|
func _on_area_exited(area: Area3D) -> void:
|
||||||
if area.has_meta("teleportable_root"):
|
if area.has_meta("teleportable_root"):
|
||||||
var root:Node3D = area.get_node(area.get_meta("teleportable_root"))
|
var root: Node3D = area.get_node(area.get_meta("teleportable_root"))
|
||||||
var crossing_node:Dictionary = root.get_meta("crossing_node")
|
var crossing_node: Dictionary = root.get_meta("crossing_node")
|
||||||
|
|
||||||
if crossing_node.teleporter == self:
|
if crossing_node.teleporter == self:
|
||||||
# The node left the enter portal without teleporting (but don't erase it yet)
|
# The node left the enter portal without teleporting (but don't erase it yet)
|
||||||
|
@ -11,18 +11,18 @@ extends Area3D
|
|||||||
class_name CollisionDisableArea
|
class_name CollisionDisableArea
|
||||||
|
|
||||||
## Seconds until collisions are re-enabled after the body leaves the area.
|
## Seconds until collisions are re-enabled after the body leaves the area.
|
||||||
@export var re_enable_delay_seconds:float = 0.1
|
@export var re_enable_delay_seconds: float = 0.1
|
||||||
|
|
||||||
# Info about the disabled bodies
|
# Info about the disabled bodies
|
||||||
var _disables:Array = []
|
var _disables: Array = []
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
connect("body_entered", _on_body_entered)
|
connect("body_entered", _on_body_entered)
|
||||||
connect("body_exited", _on_body_exited)
|
connect("body_exited", _on_body_exited)
|
||||||
|
|
||||||
func _process(delta:float) -> void:
|
func _process(delta: float) -> void:
|
||||||
for i in range(_disables.size() - 1, -1, -1):
|
for i in range(_disables.size() - 1, -1, -1):
|
||||||
var disable_info:Dictionary = _disables[i]
|
var disable_info: Dictionary = _disables[i]
|
||||||
|
|
||||||
if not is_instance_valid(disable_info.body):
|
if not is_instance_valid(disable_info.body):
|
||||||
# Body has been freed, remove disable info
|
# Body has been freed, remove disable info
|
||||||
@ -50,7 +50,7 @@ func _process(delta:float) -> void:
|
|||||||
# Final disable, so re-enable the collision mask
|
# Final disable, so re-enable the collision mask
|
||||||
disable_info.body.set_collision_mask_value(layer_number, true)
|
disable_info.body.set_collision_mask_value(layer_number, true)
|
||||||
|
|
||||||
func _on_body_entered(body:PhysicsBody3D) -> void:
|
func _on_body_entered(body: PhysicsBody3D) -> void:
|
||||||
if not body.has_meta("disabled_collision_masks"):
|
if not body.has_meta("disabled_collision_masks"):
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -65,10 +65,10 @@ func _on_body_entered(body:PhysicsBody3D) -> void:
|
|||||||
# Keep track of the number of times each collision mask is disabled in a meta field
|
# Keep track of the number of times each collision mask is disabled in a meta field
|
||||||
if not body.has_meta("collision_disable_count"):
|
if not body.has_meta("collision_disable_count"):
|
||||||
body.set_meta("collision_disable_count", {})
|
body.set_meta("collision_disable_count", {})
|
||||||
var disable_count:Dictionary = body.get_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
|
# Disable the collision masks specified in the "disabled_collision_masks" metadata array
|
||||||
var disabled_layers:Array = body.get_meta("disabled_collision_masks")
|
var disabled_layers: Array = body.get_meta("disabled_collision_masks")
|
||||||
for layer_number in disabled_layers:
|
for layer_number in disabled_layers:
|
||||||
# Only consider layers which were enabled to begin with
|
# Only consider layers which were enabled to begin with
|
||||||
if disable_count.has(layer_number) or body.get_collision_mask_value(layer_number):
|
if disable_count.has(layer_number) or body.get_collision_mask_value(layer_number):
|
||||||
@ -87,7 +87,7 @@ func _on_body_entered(body:PhysicsBody3D) -> void:
|
|||||||
"left": false,
|
"left": false,
|
||||||
})
|
})
|
||||||
|
|
||||||
func _on_body_exited(body:PhysicsBody3D) -> void:
|
func _on_body_exited(body: PhysicsBody3D) -> void:
|
||||||
if body.has_meta("disabled_collision_masks"):
|
if body.has_meta("disabled_collision_masks"):
|
||||||
for disable_info in _disables:
|
for disable_info in _disables:
|
||||||
if disable_info.body == body:
|
if disable_info.body == body:
|
||||||
|
@ -9,16 +9,16 @@
|
|||||||
extends RigidBody3D
|
extends RigidBody3D
|
||||||
class_name Hoverable
|
class_name Hoverable
|
||||||
|
|
||||||
@onready var _mesh:MeshInstance3D = $Mesh
|
@onready var _mesh: MeshInstance3D = $Mesh
|
||||||
|
|
||||||
var hovered:bool
|
var hovered: bool
|
||||||
|
|
||||||
var _strength:float
|
var _strength: float
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
_mesh.material_override = _mesh.mesh.surface_get_material(0).duplicate()
|
_mesh.material_override = _mesh.mesh.surface_get_material(0).duplicate()
|
||||||
|
|
||||||
func _process(delta:float) -> void:
|
func _process(delta: float) -> void:
|
||||||
_strength = min(1, _strength + delta * 10) if hovered else max(0, _strength - delta * 10)
|
_strength = min(1, _strength + delta * 10) if hovered else max(0, _strength - delta * 10)
|
||||||
|
|
||||||
_mesh.material_override.albedo_color = lerp(Color.WHITE, Color.RED, _strength)
|
_mesh.material_override.albedo_color = lerp(Color.WHITE, Color.RED, _strength)
|
||||||
|
@ -9,15 +9,15 @@
|
|||||||
extends MeshInstance3D
|
extends MeshInstance3D
|
||||||
class_name LineRenderer
|
class_name LineRenderer
|
||||||
|
|
||||||
@export var material:Material
|
@export var material: Material
|
||||||
|
|
||||||
var _lines:Array
|
var _lines: Array
|
||||||
var _dirty:bool
|
var _dirty: bool
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
mesh = ImmediateMesh.new()
|
mesh = ImmediateMesh.new()
|
||||||
|
|
||||||
func add_line(from:Vector3, to:Vector3, color:Color = Color.WHITE) -> void:
|
func add_line(from: Vector3, to: Vector3, color: Color = Color.WHITE) -> void:
|
||||||
_lines.push_back([from, to, color])
|
_lines.push_back([from, to, color])
|
||||||
_dirty = true
|
_dirty = true
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ func clear_lines() -> void:
|
|||||||
_lines.clear()
|
_lines.clear()
|
||||||
_dirty = true
|
_dirty = true
|
||||||
|
|
||||||
func _process(_delta:float) -> void:
|
func _process(_delta: float) -> void:
|
||||||
if not _dirty:
|
if not _dirty:
|
||||||
return
|
return
|
||||||
_dirty = false
|
_dirty = false
|
||||||
|
@ -8,18 +8,18 @@
|
|||||||
|
|
||||||
extends MeshInstance3D
|
extends MeshInstance3D
|
||||||
|
|
||||||
const _MOUSE_PAN_THRESHOLD:float = 0.4;
|
const _MOUSE_PAN_THRESHOLD: float = 0.4;
|
||||||
const _MOUSE_PAN_SPEED:float = 200
|
const _MOUSE_PAN_SPEED: float = 200
|
||||||
|
|
||||||
const _MOVE_SPEED:float = 4
|
const _MOVE_SPEED: float = 4
|
||||||
|
|
||||||
var _mouse_look:Vector2
|
var _mouse_look: Vector2
|
||||||
|
|
||||||
@onready var _line_renderer:LineRenderer = $"../LineRenderer"
|
@onready var _line_renderer: LineRenderer = $"../LineRenderer"
|
||||||
@onready var _camera:Camera3D = $Camera
|
@onready var _camera: Camera3D = $Camera
|
||||||
@onready var _pip_camera:Camera3D = $PipViewport1/Camera
|
@onready var _pip_camera: Camera3D = $PipViewport1/Camera
|
||||||
|
|
||||||
@onready var _handle_raycast_callable:Callable = Callable(self, "_handle_raycast")
|
@onready var _handle_raycast_callable: Callable = Callable(self, "_handle_raycast")
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
set_layer_mask_value(1, false)
|
set_layer_mask_value(1, false)
|
||||||
@ -27,16 +27,16 @@ func _ready() -> void:
|
|||||||
|
|
||||||
_camera.set_cull_mask_value(2, false)
|
_camera.set_cull_mask_value(2, false)
|
||||||
|
|
||||||
func _process(delta:float) -> void:
|
func _process(delta: float) -> void:
|
||||||
var viewport:Viewport = get_viewport()
|
var viewport: Viewport = get_viewport()
|
||||||
var mouse_position:Vector2 = viewport.get_mouse_position()
|
var mouse_position: Vector2 = viewport.get_mouse_position()
|
||||||
var viewport_size:Vector2i = viewport.size
|
var viewport_size: Vector2i = viewport.size
|
||||||
var normalized_mouse_position:Vector2 = mouse_position / Vector2(viewport_size)
|
var normalized_mouse_position: Vector2 = mouse_position / Vector2(viewport_size)
|
||||||
|
|
||||||
var horizontal_speed:float = 0
|
var horizontal_speed: float = 0
|
||||||
var vertical_speed:float = 0
|
var vertical_speed: float = 0
|
||||||
|
|
||||||
if normalized_mouse_position.x > 0 and normalized_mouse_position.x < 1 and\
|
if normalized_mouse_position.x > 0 and normalized_mouse_position.x < 1 and \
|
||||||
normalized_mouse_position.y > 0 and normalized_mouse_position.y < 1:
|
normalized_mouse_position.y > 0 and normalized_mouse_position.y < 1:
|
||||||
if normalized_mouse_position.x < _MOUSE_PAN_THRESHOLD:
|
if normalized_mouse_position.x < _MOUSE_PAN_THRESHOLD:
|
||||||
horizontal_speed = lerp(0, 1, _MOUSE_PAN_THRESHOLD - normalized_mouse_position.x)
|
horizontal_speed = lerp(0, 1, _MOUSE_PAN_THRESHOLD - normalized_mouse_position.x)
|
||||||
@ -53,15 +53,15 @@ func _process(delta:float) -> void:
|
|||||||
rotation_degrees = Vector3(0, _mouse_look.x, 0)
|
rotation_degrees = Vector3(0, _mouse_look.x, 0)
|
||||||
_camera.rotation_degrees = Vector3(_mouse_look.y, 0, 0)
|
_camera.rotation_degrees = Vector3(_mouse_look.y, 0, 0)
|
||||||
|
|
||||||
var right:Vector3 = (global_transform.basis.x * Vector3(1, 0, 1)).normalized()
|
var right: Vector3 = (global_transform.basis.x * Vector3(1, 0, 1)).normalized()
|
||||||
var forward:Vector3 = (global_transform.basis.z * Vector3(1, 0, 1)).normalized()
|
var forward: Vector3 = (global_transform.basis.z * Vector3(1, 0, 1)).normalized()
|
||||||
|
|
||||||
if Input.is_key_pressed(KEY_LEFT) or Input.is_key_pressed(KEY_A):
|
if Input.is_key_pressed(KEY_LEFT) or Input.is_key_pressed(KEY_A):
|
||||||
global_translate(-right * _MOVE_SPEED * delta)
|
global_translate(- right * _MOVE_SPEED * delta)
|
||||||
if Input.is_key_pressed(KEY_RIGHT) or Input.is_key_pressed(KEY_D):
|
if Input.is_key_pressed(KEY_RIGHT) or Input.is_key_pressed(KEY_D):
|
||||||
global_translate(right * _MOVE_SPEED * delta)
|
global_translate(right * _MOVE_SPEED * delta)
|
||||||
if Input.is_key_pressed(KEY_UP) or Input.is_key_pressed(KEY_W):
|
if Input.is_key_pressed(KEY_UP) or Input.is_key_pressed(KEY_W):
|
||||||
global_translate(-forward * _MOVE_SPEED * delta)
|
global_translate(- forward * _MOVE_SPEED * delta)
|
||||||
if Input.is_key_pressed(KEY_DOWN) or Input.is_key_pressed(KEY_S):
|
if Input.is_key_pressed(KEY_DOWN) or Input.is_key_pressed(KEY_S):
|
||||||
global_translate(forward * _MOVE_SPEED * delta)
|
global_translate(forward * _MOVE_SPEED * delta)
|
||||||
|
|
||||||
@ -75,38 +75,38 @@ func _process(delta:float) -> void:
|
|||||||
_pip_camera.global_position = _camera.to_global(Vector3(0, 1.5, 1.5))
|
_pip_camera.global_position = _camera.to_global(Vector3(0, 1.5, 1.5))
|
||||||
_pip_camera.global_rotation = _camera.global_rotation
|
_pip_camera.global_rotation = _camera.global_rotation
|
||||||
|
|
||||||
var origin:Vector3 = _camera.project_ray_origin(mouse_position)
|
var origin: Vector3 = _camera.project_ray_origin(mouse_position)
|
||||||
var end:Vector3 = origin + _camera.project_ray_normal(mouse_position) * 100
|
var end: Vector3 = origin + _camera.project_ray_normal(mouse_position) * 100
|
||||||
|
|
||||||
_line_renderer.clear_lines()
|
_line_renderer.clear_lines()
|
||||||
|
|
||||||
Portal.raycast(get_tree(), origin, (end - origin).normalized(), _handle_raycast_callable)
|
Portal.raycast(get_tree(), origin, (end - origin).normalized(), _handle_raycast_callable)
|
||||||
|
|
||||||
func _handle_raycast(from:Vector3, dir:Vector3, segment_distance:float, _recursive_distance:float, recursions:int) -> bool:
|
func _handle_raycast(from: Vector3, dir: Vector3, segment_distance: float, _recursive_distance: float, recursions: int) -> bool:
|
||||||
var distance:float = min(100, segment_distance)
|
var distance: float = min(100, segment_distance)
|
||||||
var target:Vector3 = from + dir * distance
|
var target: Vector3 = from + dir * distance
|
||||||
|
|
||||||
_line_renderer.add_line(from, target, Color.GREEN)
|
_line_renderer.add_line(from, target, Color.GREEN)
|
||||||
for i in 16:
|
for i in 16:
|
||||||
_line_renderer.add_line(target, target + Vector3(
|
_line_renderer.add_line(target, target + Vector3(
|
||||||
randf_range(-0.1, 0.1),
|
randf_range(-0.1, 0.1),
|
||||||
randf_range(-0.1, 0.1),
|
randf_range(-0.1, 0.1),
|
||||||
randf_range(-0.1, 0.1)), Color.RED)
|
randf_range(-0.1, 0.1)), Color.RED)
|
||||||
if recursions > 0:
|
if recursions > 0:
|
||||||
_line_renderer.add_line(from, from + Vector3(
|
_line_renderer.add_line(from, from + Vector3(
|
||||||
randf_range(-0.1, 0.1),
|
randf_range(-0.1, 0.1),
|
||||||
randf_range(-0.1, 0.1),
|
randf_range(-0.1, 0.1),
|
||||||
randf_range(-0.1, 0.1)), Color.BLUE)
|
randf_range(-0.1, 0.1)), Color.BLUE)
|
||||||
|
|
||||||
var space_state:PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
|
var space_state: PhysicsDirectSpaceState3D = get_world_3d().direct_space_state
|
||||||
var query:PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.create(from, from + dir * distance)
|
var query: PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.create(from, from + dir * distance)
|
||||||
var result:Dictionary = space_state.intersect_ray(query)
|
var result: Dictionary = space_state.intersect_ray(query)
|
||||||
if not result.is_empty() and result.collider is Hoverable:
|
if not result.is_empty() and result.collider is Hoverable:
|
||||||
result.collider.hovered = true
|
result.collider.hovered = true
|
||||||
for i in 16:
|
for i in 16:
|
||||||
_line_renderer.add_line(result.position, result.position + Vector3(
|
_line_renderer.add_line(result.position, result.position + Vector3(
|
||||||
randf_range(-0.1, 0.1),
|
randf_range(-0.1, 0.1),
|
||||||
randf_range(-0.1, 0.1),
|
randf_range(-0.1, 0.1),
|
||||||
randf_range(-0.1, 0.1)), Color.GREEN)
|
randf_range(-0.1, 0.1)), Color.GREEN)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -12,56 +12,56 @@ class_name Portal
|
|||||||
## The portal represents a single portal mesh in a pair of portals.
|
## The portal represents a single portal mesh in a pair of portals.
|
||||||
|
|
||||||
## The delay between the main viewport changing size and the portal viewport resizing.
|
## The delay between the main viewport changing size and the portal viewport resizing.
|
||||||
const _RESIZE_THROTTLE_SECONDS:float = 0.1
|
const _RESIZE_THROTTLE_SECONDS: float = 0.1
|
||||||
|
|
||||||
## The minimum camera near clipping distance.
|
## The minimum camera near clipping distance.
|
||||||
const _EXIT_CAMERA_NEAR_MIN:float = 0.01
|
const _EXIT_CAMERA_NEAR_MIN: float = 0.01
|
||||||
|
|
||||||
## The portal mesh's local bounding box.
|
## The portal mesh's local bounding box.
|
||||||
@onready var _mesh_aabb:AABB = mesh.get_aabb()
|
@onready var _mesh_aabb: AABB = mesh.get_aabb()
|
||||||
|
|
||||||
## The vertical resolution of the portal viewport which covers the entire screen not just the portal mesh. Use 0 to use the real resolution.
|
## The vertical resolution of the portal viewport which covers the entire screen not just the portal mesh. Use 0 to use the real resolution.
|
||||||
@export var vertical_viewport_resolution:int = 512
|
@export var vertical_viewport_resolution: int = 512
|
||||||
|
|
||||||
## Disable viewport distance. Portals further away than this won't have their viewports rendered.
|
## Disable viewport distance. Portals further away than this won't have their viewports rendered.
|
||||||
@export var disable_viewport_distance:float = 11
|
@export var disable_viewport_distance: float = 11
|
||||||
## Whether to destroy the disabled viewport to save texture memory. Useful when you have a lot of portals. The viewport is re/-created when within disable_viewport_distance and visible.
|
## Whether to destroy the disabled viewport to save texture memory. Useful when you have a lot of portals. The viewport is re/-created when within disable_viewport_distance and visible.
|
||||||
@export var destroy_disabled_viewport:bool = true
|
@export var destroy_disabled_viewport: bool = true
|
||||||
|
|
||||||
## The maximum fade-out distance.
|
## The maximum fade-out distance.
|
||||||
@export var fade_out_distance_max:float = 10
|
@export var fade_out_distance_max: float = 10
|
||||||
## The minimum fade-out distance.
|
## The minimum fade-out distance.
|
||||||
@export var fade_out_distance_min:float = 8
|
@export var fade_out_distance_min: float = 8
|
||||||
## The fade-out color.
|
## The fade-out color.
|
||||||
@export var fade_out_color:Color = Color.WHITE
|
@export var fade_out_color: Color = Color.WHITE
|
||||||
|
|
||||||
## The scale of the exit side of the portal. < 1 means the exit is smaller than the entrance.
|
## The scale of the exit side of the portal. < 1 means the exit is smaller than the entrance.
|
||||||
@export var exit_scale:float = 1.0
|
@export var exit_scale: float = 1.0
|
||||||
## A value subtracted from the exit camera near clipping plane. Useful for handling clipping issues.
|
## A value subtracted from the exit camera near clipping plane. Useful for handling clipping issues.
|
||||||
@export var exit_near_subtract:float = 0.05
|
@export var exit_near_subtract: float = 0.05
|
||||||
|
|
||||||
## The main camera. Leave unset to use the default 3D camera.
|
## The main camera. Leave unset to use the default 3D camera.
|
||||||
@export var main_camera:Camera3D
|
@export var main_camera: Camera3D
|
||||||
|
|
||||||
## An environment set for the exit camera. Leave unset to use the default environment.
|
## An environment set for the exit camera. Leave unset to use the default environment.
|
||||||
@export var exit_environment:Environment
|
@export var exit_environment: Environment
|
||||||
## The cull mask for the exit camera. Use it to hide certain objects in the exit camera.
|
## The cull mask for the exit camera. Use it to hide certain objects in the exit camera.
|
||||||
@export_flags_3d_render var exit_cull_mask:int = 0b11111111111111111111
|
@export_flags_3d_render var exit_cull_mask: int = 0b11111111111111111111
|
||||||
|
|
||||||
## The exit portal. Leave unset to use this portal as an exit only.
|
## The exit portal. Leave unset to use this portal as an exit only.
|
||||||
@export var exit_portal:Portal
|
@export var exit_portal: Portal
|
||||||
|
|
||||||
## An environment set for the exit camera. Leave unset to use the default environment.
|
## An environment set for the exit camera. Leave unset to use the default environment.
|
||||||
@export var portal_shader:Shader = preload("res://addons/simple-portal-system/shaders/portal.gdshader")
|
@export var portal_shader: Shader = preload("res://addons/simple-portal-system/shaders/portal.gdshader")
|
||||||
|
|
||||||
# The viewport rendering the portal surface
|
# The viewport rendering the portal surface
|
||||||
var _viewport:SubViewport
|
var _viewport: SubViewport
|
||||||
|
|
||||||
# The exit camera copies the main camera's position relative to the exit portal
|
# The exit camera copies the main camera's position relative to the exit portal
|
||||||
var _exit_camera:Camera3D
|
var _exit_camera: Camera3D
|
||||||
|
|
||||||
# The number of seconds until the viewport updates its size
|
# The number of seconds until the viewport updates its size
|
||||||
var _seconds_until_resize:float
|
var _seconds_until_resize: float
|
||||||
|
|
||||||
func _enter_tree() -> void:
|
func _enter_tree() -> void:
|
||||||
add_to_group("portals")
|
add_to_group("portals")
|
||||||
@ -81,7 +81,7 @@ func _ready() -> void:
|
|||||||
|
|
||||||
# Non-uniform parent scaling can introduce skew which isn't compensated for
|
# Non-uniform parent scaling can introduce skew which isn't compensated for
|
||||||
if get_parent() != null:
|
if get_parent() != null:
|
||||||
var parent_scale:Vector3 = get_parent().global_transform.basis.get_scale()
|
var parent_scale: Vector3 = get_parent().global_transform.basis.get_scale()
|
||||||
if abs(parent_scale.x - parent_scale.y) > 0.01 or abs(parent_scale.x - parent_scale.z) > 0.01:
|
if abs(parent_scale.x - parent_scale.y) > 0.01 or abs(parent_scale.x - parent_scale.z) > 0.01:
|
||||||
push_warning("The parent of \"%s\" is not uniformly scaled. The portal will not work correctly." % name)
|
push_warning("The parent of \"%s\" is not uniformly scaled. The portal will not work correctly." % name)
|
||||||
|
|
||||||
@ -100,12 +100,12 @@ func _ready() -> void:
|
|||||||
material_override.shader = portal_shader
|
material_override.shader = portal_shader
|
||||||
material_override.set_shader_parameter("fade_out_distance_max", fade_out_distance_max)
|
material_override.set_shader_parameter("fade_out_distance_max", fade_out_distance_max)
|
||||||
material_override.set_shader_parameter("fade_out_distance_min", fade_out_distance_min)
|
material_override.set_shader_parameter("fade_out_distance_min", fade_out_distance_min)
|
||||||
material_override.set_shader_parameter("fade_out_color", fade_out_color)
|
material_override.set_shader_parameter("fade_out_color", fade_out_color)
|
||||||
|
|
||||||
# Create the viewport when _ready if it's not destroyed when disabled.
|
# Create the viewport when _ready if it's not destroyed when disabled.
|
||||||
# This may potentially get rid of the initial lag when the viewport is first created at the cost of texture memory.
|
# This may potentially get rid of the initial lag when the viewport is first created at the cost of texture memory.
|
||||||
if not destroy_disabled_viewport:
|
if not destroy_disabled_viewport:
|
||||||
_create_viewport()
|
_createa_viewport()
|
||||||
|
|
||||||
get_viewport().connect("size_changed", _handle_resize)
|
get_viewport().connect("size_changed", _handle_resize)
|
||||||
|
|
||||||
@ -130,9 +130,9 @@ func _create_viewport() -> void:
|
|||||||
# Resize the viewport on the next _process
|
# Resize the viewport on the next _process
|
||||||
_seconds_until_resize = 0
|
_seconds_until_resize = 0
|
||||||
|
|
||||||
func _process(delta:float) -> void:
|
func _process(delta: float) -> void:
|
||||||
# Disable the viewport if the portal is further away than disable_viewport_distance or if the portal is invisible in the scene tree
|
# Disable the viewport if the portal is further away than disable_viewport_distance or if the portal is invisible in the scene tree
|
||||||
var disable_viewport:bool = not is_visible_in_tree() or\
|
var disable_viewport: bool = not is_visible_in_tree() or \
|
||||||
main_camera.global_position.distance_squared_to(global_position) > disable_viewport_distance * disable_viewport_distance
|
main_camera.global_position.distance_squared_to(global_position) > disable_viewport_distance * disable_viewport_distance
|
||||||
|
|
||||||
# Enable or disable 3D rendering for the viewport (if it exists)
|
# Enable or disable 3D rendering for the viewport (if it exists)
|
||||||
@ -163,13 +163,13 @@ func _process(delta:float) -> void:
|
|||||||
if _seconds_until_resize <= 0:
|
if _seconds_until_resize <= 0:
|
||||||
_seconds_until_resize = NAN
|
_seconds_until_resize = NAN
|
||||||
|
|
||||||
var viewport_size:Vector2i = get_viewport().size
|
var viewport_size: Vector2i = get_viewport().size
|
||||||
if vertical_viewport_resolution == 0:
|
if vertical_viewport_resolution == 0:
|
||||||
# Resize the viewport to the main viewport size
|
# Resize the viewport to the main viewport size
|
||||||
_viewport.size = viewport_size
|
_viewport.size = viewport_size
|
||||||
else:
|
else:
|
||||||
# Resize the viewport to the fixed height vertical_viewport_resolution and dynamic width
|
# Resize the viewport to the fixed height vertical_viewport_resolution and dynamic width
|
||||||
var aspect_ratio:float = float(viewport_size.x) / viewport_size.y
|
var aspect_ratio: float = float(viewport_size.x) / viewport_size.y
|
||||||
_viewport.size = Vector2i(int(vertical_viewport_resolution * aspect_ratio + 0.5), vertical_viewport_resolution)
|
_viewport.size = Vector2i(int(vertical_viewport_resolution * aspect_ratio + 0.5), vertical_viewport_resolution)
|
||||||
|
|
||||||
# Move the exit camera relative to the exit portal based on the main camera's position relative to the entrance portal
|
# Move the exit camera relative to the exit portal based on the main camera's position relative to the entrance portal
|
||||||
@ -177,18 +177,18 @@ func _process(delta:float) -> void:
|
|||||||
|
|
||||||
# Get the four X, Y corners of the scaled entrance portal bounding box clamped to Z=0 (portal surface) relative to the exit portal.
|
# Get the four X, Y corners of the scaled entrance portal bounding box clamped to Z=0 (portal surface) relative to the exit portal.
|
||||||
# The entrance portal bounding box is used since the entrance portal mesh does not need to match the exit portal mesh.
|
# The entrance portal bounding box is used since the entrance portal mesh does not need to match the exit portal mesh.
|
||||||
var corner_1:Vector3 = exit_portal.to_global(Vector3(_mesh_aabb.position.x, _mesh_aabb.position.y, 0) * exit_scale)
|
var corner_1: Vector3 = exit_portal.to_global(Vector3(_mesh_aabb.position.x, _mesh_aabb.position.y, 0) * exit_scale)
|
||||||
var corner_2:Vector3 = exit_portal.to_global(Vector3(_mesh_aabb.position.x + _mesh_aabb.size.x, _mesh_aabb.position.y, 0) * exit_scale)
|
var corner_2: Vector3 = exit_portal.to_global(Vector3(_mesh_aabb.position.x + _mesh_aabb.size.x, _mesh_aabb.position.y, 0) * exit_scale)
|
||||||
var corner_3:Vector3 = exit_portal.to_global(Vector3(_mesh_aabb.position.x + _mesh_aabb.size.x, _mesh_aabb.position.y + _mesh_aabb.size.y, 0) * exit_scale)
|
var corner_3: Vector3 = exit_portal.to_global(Vector3(_mesh_aabb.position.x + _mesh_aabb.size.x, _mesh_aabb.position.y + _mesh_aabb.size.y, 0) * exit_scale)
|
||||||
var corner_4:Vector3 = exit_portal.to_global(Vector3(_mesh_aabb.position.x, _mesh_aabb.position.y + _mesh_aabb.size.y, 0) * exit_scale)
|
var corner_4: Vector3 = exit_portal.to_global(Vector3(_mesh_aabb.position.x, _mesh_aabb.position.y + _mesh_aabb.size.y, 0) * exit_scale)
|
||||||
|
|
||||||
# Calculate the distance along the exit camera forward vector at which each of the portal corners projects
|
# Calculate the distance along the exit camera forward vector at which each of the portal corners projects
|
||||||
var camera_forward:Vector3 = -_exit_camera.global_transform.basis.z.normalized()
|
var camera_forward: Vector3 = - _exit_camera.global_transform.basis.z.normalized()
|
||||||
|
|
||||||
var d_1:float = (corner_1 - _exit_camera.global_position).dot(camera_forward)
|
var d_1: float = (corner_1 - _exit_camera.global_position).dot(camera_forward)
|
||||||
var d_2:float = (corner_2 - _exit_camera.global_position).dot(camera_forward)
|
var d_2: float = (corner_2 - _exit_camera.global_position).dot(camera_forward)
|
||||||
var d_3:float = (corner_3 - _exit_camera.global_position).dot(camera_forward)
|
var d_3: float = (corner_3 - _exit_camera.global_position).dot(camera_forward)
|
||||||
var d_4:float = (corner_4 - _exit_camera.global_position).dot(camera_forward)
|
var d_4: float = (corner_4 - _exit_camera.global_position).dot(camera_forward)
|
||||||
|
|
||||||
# The near clip distance is the shortest distance which still contains all the corners
|
# The near clip distance is the shortest distance which still contains all the corners
|
||||||
_exit_camera.near = max(_EXIT_CAMERA_NEAR_MIN, min(d_1, d_2, d_3, d_4) - exit_near_subtract)
|
_exit_camera.near = max(_EXIT_CAMERA_NEAR_MIN, min(d_1, d_2, d_3, d_4) - exit_near_subtract)
|
||||||
@ -197,60 +197,60 @@ func _process(delta:float) -> void:
|
|||||||
_exit_camera.keep_aspect = main_camera.keep_aspect
|
_exit_camera.keep_aspect = main_camera.keep_aspect
|
||||||
|
|
||||||
## Return a new Transform3D relative to the exit portal based on the real Transform3D relative to this portal.
|
## Return a new Transform3D relative to the exit portal based on the real Transform3D relative to this portal.
|
||||||
func real_to_exit_transform(real:Transform3D) -> Transform3D:
|
func real_to_exit_transform(real: Transform3D) -> Transform3D:
|
||||||
# Convert from global space to local space at the entrance (this) portal
|
# Convert from global space to local space at the entrance (this) portal
|
||||||
var local:Transform3D = global_transform.affine_inverse() * real
|
var local: Transform3D = global_transform.affine_inverse() * real
|
||||||
# Compensate for any scale the entrance portal may have
|
# Compensate for any scale the entrance portal may have
|
||||||
var unscaled:Transform3D = local.scaled(global_transform.basis.get_scale())
|
var unscaled: Transform3D = local.scaled(global_transform.basis.get_scale())
|
||||||
# Flip it (the portal always flips the view 180 degrees)
|
# Flip it (the portal always flips the view 180 degrees)
|
||||||
var flipped:Transform3D = unscaled.rotated(Vector3.UP, PI)
|
var flipped: Transform3D = unscaled.rotated(Vector3.UP, PI)
|
||||||
# Apply any scale the exit portal may have (and apply custom exit scale)
|
# Apply any scale the exit portal may have (and apply custom exit scale)
|
||||||
var exit_scale_vector:Vector3 = exit_portal.global_transform.basis.get_scale()
|
var exit_scale_vector: Vector3 = exit_portal.global_transform.basis.get_scale()
|
||||||
var scaled_at_exit:Transform3D = flipped.scaled(Vector3.ONE / exit_scale_vector * exit_scale)
|
var scaled_at_exit: Transform3D = flipped.scaled(Vector3.ONE / exit_scale_vector * exit_scale)
|
||||||
# Convert from local space at the exit portal to global space
|
# Convert from local space at the exit portal to global space
|
||||||
var local_at_exit:Transform3D = exit_portal.global_transform * scaled_at_exit
|
var local_at_exit: Transform3D = exit_portal.global_transform * scaled_at_exit
|
||||||
return local_at_exit
|
return local_at_exit
|
||||||
|
|
||||||
## Return a new position relative to the exit portal based on the real position relative to this portal.
|
## Return a new position relative to the exit portal based on the real position relative to this portal.
|
||||||
func real_to_exit_position(real:Vector3) -> Vector3:
|
func real_to_exit_position(real: Vector3) -> Vector3:
|
||||||
# Convert from global space to local space at the entrance (this) portal
|
# Convert from global space to local space at the entrance (this) portal
|
||||||
var local:Vector3 = global_transform.affine_inverse() * real
|
var local: Vector3 = global_transform.affine_inverse() * real
|
||||||
# Compensate for any scale the entrance portal may have
|
# Compensate for any scale the entrance portal may have
|
||||||
var unscaled:Vector3 = local * global_transform.basis.get_scale()
|
var unscaled: Vector3 = local * global_transform.basis.get_scale()
|
||||||
# Apply any scale the exit portal may have (and apply custom exit scale)
|
# Apply any scale the exit portal may have (and apply custom exit scale)
|
||||||
var exit_scale_vector:Vector3 = Vector3(-1, 1, 1) * exit_portal.global_transform.basis.get_scale()
|
var exit_scale_vector: Vector3 = Vector3(-1, 1, 1) * exit_portal.global_transform.basis.get_scale()
|
||||||
var scaled_at_exit:Vector3 = unscaled / exit_scale_vector * exit_scale
|
var scaled_at_exit: Vector3 = unscaled / exit_scale_vector * exit_scale
|
||||||
# Convert from local space at the exit portal to global space
|
# Convert from local space at the exit portal to global space
|
||||||
var local_at_exit:Vector3 = exit_portal.global_transform * scaled_at_exit
|
var local_at_exit: Vector3 = exit_portal.global_transform * scaled_at_exit
|
||||||
return local_at_exit
|
return local_at_exit
|
||||||
|
|
||||||
## Return a new direction relative to the exit portal based on the real direction relative to this portal.
|
## Return a new direction relative to the exit portal based on the real direction relative to this portal.
|
||||||
func real_to_exit_direction(real:Vector3) -> Vector3:
|
func real_to_exit_direction(real: Vector3) -> Vector3:
|
||||||
# Convert from global to local space at the entrance (this) portal
|
# Convert from global to local space at the entrance (this) portal
|
||||||
var local:Vector3 = global_transform.basis.inverse() * real
|
var local: Vector3 = global_transform.basis.inverse() * real
|
||||||
# Compensate for any scale the entrance portal may have
|
# Compensate for any scale the entrance portal may have
|
||||||
var unscaled:Vector3 = local * global_transform.basis.get_scale()
|
var unscaled: Vector3 = local * global_transform.basis.get_scale()
|
||||||
# Flip it (the portal always flips the view 180 degrees)
|
# Flip it (the portal always flips the view 180 degrees)
|
||||||
var flipped:Vector3 = unscaled.rotated(Vector3.UP, PI)
|
var flipped: Vector3 = unscaled.rotated(Vector3.UP, PI)
|
||||||
# Apply any scale the exit portal may have (and apply custom exit scale)
|
# Apply any scale the exit portal may have (and apply custom exit scale)
|
||||||
var exit_scale_vector:Vector3 = exit_portal.global_transform.basis.get_scale()
|
var exit_scale_vector: Vector3 = exit_portal.global_transform.basis.get_scale()
|
||||||
var scaled_at_exit:Vector3 = flipped / exit_scale_vector * exit_scale
|
var scaled_at_exit: Vector3 = flipped / exit_scale_vector * exit_scale
|
||||||
# Convert from local space at the exit portal to global space
|
# Convert from local space at the exit portal to global space
|
||||||
var local_at_exit:Vector3 = exit_portal.global_transform.basis * scaled_at_exit
|
var local_at_exit: Vector3 = exit_portal.global_transform.basis * scaled_at_exit
|
||||||
return local_at_exit
|
return local_at_exit
|
||||||
|
|
||||||
## Raycast against portals (See instructions).
|
## Raycast against portals (See instructions).
|
||||||
static func raycast(tree:SceneTree, from:Vector3, dir:Vector3, handle_raycast:Callable,
|
static func raycast(tree: SceneTree, from: Vector3, dir: Vector3, handle_raycast: Callable,
|
||||||
max_distance:float = INF, max_recursions:int = 16, ignore_backside:bool = true) -> void:
|
max_distance: float = INF, max_recursions: int = 16, ignore_backside: bool = true) -> void:
|
||||||
var portals:Array = tree.get_nodes_in_group("portals")
|
var portals: Array = tree.get_nodes_in_group("portals")
|
||||||
var ignore_portal:Portal = null
|
var ignore_portal: Portal = null
|
||||||
var recursive_distance:float = 0
|
var recursive_distance: float = 0
|
||||||
|
|
||||||
for r in max_recursions + 1:
|
for r in max_recursions + 1:
|
||||||
var closest_hit:Vector3
|
var closest_hit: Vector3
|
||||||
var closest_dir:Vector3
|
var closest_dir: Vector3
|
||||||
var closest_portal:Portal
|
var closest_portal: Portal
|
||||||
var closest_distance_sqr:float = INF
|
var closest_distance_sqr: float = INF
|
||||||
|
|
||||||
# Find the closest portal the ray intersects
|
# Find the closest portal the ray intersects
|
||||||
for portal in portals:
|
for portal in portals:
|
||||||
@ -258,8 +258,8 @@ static func raycast(tree:SceneTree, from:Vector3, dir:Vector3, handle_raycast:Ca
|
|||||||
if portal == ignore_portal or not portal.is_inside_tree() or tree != portal.get_tree() or not portal.is_visible_in_tree():
|
if portal == ignore_portal or not portal.is_inside_tree() or tree != portal.get_tree() or not portal.is_visible_in_tree():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
var local_from:Vector3 = portal.to_local(from)
|
var local_from: Vector3 = portal.to_local(from)
|
||||||
var local_dir:Vector3 = portal.global_transform.basis.inverse() * dir
|
var local_dir: Vector3 = portal.global_transform.basis.inverse() * dir
|
||||||
|
|
||||||
# Check if ray is parallel to the portal
|
# Check if ray is parallel to the portal
|
||||||
if local_dir.z == 0:
|
if local_dir.z == 0:
|
||||||
@ -270,22 +270,22 @@ static func raycast(tree:SceneTree, from:Vector3, dir:Vector3, handle_raycast:Ca
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Get the intersection point of the ray with the Z axis
|
# Get the intersection point of the ray with the Z axis
|
||||||
var t:float = -local_from.z / local_dir.z
|
var t: float = - local_from.z / local_dir.z
|
||||||
|
|
||||||
# Is the intersection behind the start position?
|
# Is the intersection behind the start position?
|
||||||
if t < 0:
|
if t < 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check if the ray hit inside the portal bounding box (ignoring Z)
|
# Check if the ray hit inside the portal bounding box (ignoring Z)
|
||||||
var local_hit:Vector3 = local_from + t * local_dir
|
var local_hit: Vector3 = local_from + t * local_dir
|
||||||
var aabb:AABB = portal._mesh_aabb
|
var aabb: AABB = portal._mesh_aabb
|
||||||
if local_hit.x < aabb.position.x or local_hit.x > aabb.position.x + aabb.size.x or\
|
if local_hit.x < aabb.position.x or local_hit.x > aabb.position.x + aabb.size.x or \
|
||||||
local_hit.y < aabb.position.y or local_hit.y > aabb.position.y + aabb.size.y:
|
local_hit.y < aabb.position.y or local_hit.y > aabb.position.y + aabb.size.y:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check if this was the closest portal
|
# Check if this was the closest portal
|
||||||
var hit:Vector3 = portal.to_global(local_hit)
|
var hit: Vector3 = portal.to_global(local_hit)
|
||||||
var distance_sqr:float = hit.distance_squared_to(from)
|
var distance_sqr: float = hit.distance_squared_to(from)
|
||||||
if distance_sqr < closest_distance_sqr:
|
if distance_sqr < closest_distance_sqr:
|
||||||
closest_hit = hit
|
closest_hit = hit
|
||||||
closest_dir = dir
|
closest_dir = dir
|
||||||
@ -293,7 +293,7 @@ static func raycast(tree:SceneTree, from:Vector3, dir:Vector3, handle_raycast:Ca
|
|||||||
closest_portal = portal
|
closest_portal = portal
|
||||||
|
|
||||||
# Calculate the ray distance
|
# Calculate the ray distance
|
||||||
var hit_distance:float = INF if is_inf(closest_distance_sqr) else sqrt(closest_distance_sqr)
|
var hit_distance: float = INF if is_inf(closest_distance_sqr) else sqrt(closest_distance_sqr)
|
||||||
|
|
||||||
# Call the user-defined raycast function
|
# Call the user-defined raycast function
|
||||||
if handle_raycast.call(from, dir, hit_distance, recursive_distance, r):
|
if handle_raycast.call(from, dir, hit_distance, recursive_distance, r):
|
||||||
|
@ -22,7 +22,7 @@ func _ready():
|
|||||||
|
|
||||||
func _on_area_entered(area: Area3D) -> void:
|
func _on_area_entered(area: Area3D) -> void:
|
||||||
if area.has_meta("teleportable_root"):
|
if area.has_meta("teleportable_root"):
|
||||||
var root:Node3D = area.get_node(area.get_meta("teleportable_root"))
|
var root: Node3D = area.get_node(area.get_meta("teleportable_root"))
|
||||||
print("[%f] Teleporting %s to %s" % [roundi(Time.get_ticks_msec() / 100) / 10.0, root.name, _parent_portal.exit_portal.name])
|
print("[%f] Teleporting %s to %s" % [roundi(Time.get_ticks_msec() / 100) / 10.0, root.name, _parent_portal.exit_portal.name])
|
||||||
root.global_transform = _parent_portal.real_to_exit_transform(root.global_transform)
|
root.global_transform = _parent_portal.real_to_exit_transform(root.global_transform)
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ config/name="DP Konzultace"
|
|||||||
run/main_scene="uid://cim3ul77o0ipr"
|
run/main_scene="uid://cim3ul77o0ipr"
|
||||||
config/features=PackedStringArray("4.4", "Forward Plus")
|
config/features=PackedStringArray("4.4", "Forward Plus")
|
||||||
config/icon="res://icon.svg"
|
config/icon="res://icon.svg"
|
||||||
|
config/tags=PackedStringArray("dp")
|
||||||
|
|
||||||
[display]
|
[display]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user