Files
MovementTests/addons/guide/modifiers/guide_modifier_3d_coordinates.gd
2025-05-27 19:20:46 +02:00

54 lines
1.7 KiB
GDScript

## Converts a position input in viewport coordinates (e.g. from the mouse position input)
## into 3D coordinates (e.g. 3D world coordinates). Useful to get a 3D 'world' position.
## Returns a Vector3.INF if no 3D world coordinates can be determined.
@tool
class_name GUIDEModifier3DCoordinates
extends GUIDEModifier
## The maximum depth of the ray cast used to detect the 3D position.
@export var max_depth:float = 1000.0
## Whether the rays cast should collide with areas.
@export var collide_with_areas:bool = false
## Collision mask to use for the ray cast.
@export_flags_3d_physics var collision_mask:int
func _modify_input(input:Vector3, delta:float, value_type:GUIDEAction.GUIDEActionValueType) -> Vector3:
# if we collide with nothing, no need to even try
if collision_mask == 0:
return Vector3.INF
if not input.is_finite():
return Vector3.INF
var viewport = Engine.get_main_loop().root
var camera:Camera3D = viewport.get_camera_3d()
if camera == null:
return Vector3.INF
var input_position:Vector2 = Vector2(input.x, input.y)
var from:Vector3 = camera.project_ray_origin(input_position)
var to:Vector3 = from + camera.project_ray_normal(input_position) * max_depth
var query:= PhysicsRayQueryParameters3D.create(from, to, collision_mask)
query.collide_with_areas = collide_with_areas
var result = viewport.world_3d.direct_space_state.intersect_ray(query)
if result.has("position"):
return result.position
return Vector3.INF
func _editor_name() -> String:
return "3D coordinates"
func _editor_description() -> String:
return "Converts a position input in viewport coordinates (e.g. from the mouse position input)\n" + \
"into 3D coordinates (e.g. 3D world coordinates). Useful to get a 3D 'world' position."