mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 13:30:07 +01:00
105 lines
2.9 KiB
GDScript
105 lines
2.9 KiB
GDScript
extends Test
|
|
|
|
|
|
const OPTION_TEST_CASE_HIT_FROM_INSIDE = "Test case/Hit from inside"
|
|
|
|
var _hit_from_inside: bool = false
|
|
var _do_raycasts: bool = false
|
|
|
|
@onready var _raycast_visuals := ImmediateMesh.new()
|
|
@onready var _material := StandardMaterial3D.new()
|
|
|
|
|
|
func _ready() -> void:
|
|
var options: OptionMenu = $Options
|
|
|
|
options.add_menu_item(OPTION_TEST_CASE_HIT_FROM_INSIDE, true, false)
|
|
|
|
options.option_changed.connect(_on_option_changed)
|
|
|
|
_material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
|
|
_material.vertex_color_use_as_albedo = true
|
|
|
|
var raycast_mesh_instance := MeshInstance3D.new()
|
|
raycast_mesh_instance.mesh = _raycast_visuals
|
|
add_child(raycast_mesh_instance)
|
|
move_child(raycast_mesh_instance, get_child_count())
|
|
|
|
await start_timer(0.5).timeout
|
|
if is_timer_canceled():
|
|
return
|
|
|
|
_do_raycasts = true
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
super._physics_process(delta)
|
|
|
|
if not _do_raycasts:
|
|
return
|
|
|
|
_do_raycasts = false
|
|
|
|
Log.print_log("* Start Raycasting...")
|
|
|
|
_raycast_visuals.clear_surfaces()
|
|
_raycast_visuals.surface_begin(Mesh.PRIMITIVE_LINES)
|
|
|
|
for shape in $Shapes.get_children():
|
|
var body: PhysicsBody3D = shape
|
|
var space_state := body.get_world_3d().direct_space_state
|
|
|
|
Log.print_log("* Testing: %s" % body.name)
|
|
|
|
var center := body.global_transform.origin
|
|
|
|
# Raycast entering from the top.
|
|
var res := _add_raycast(space_state, center + Vector3(0.0, 2.0, 0.0), center)
|
|
Log.print_log("Raycast in: %s" % ("HIT" if res else "NO HIT"))
|
|
|
|
# Raycast exiting from inside.
|
|
center.x -= 0.2
|
|
res = _add_raycast(space_state, center, center - Vector3(0.0, 3.0, 0.0))
|
|
Log.print_log("Raycast out: %s" % ("HIT" if res else "NO HIT"))
|
|
|
|
# Raycast all inside.
|
|
center.x += 0.4
|
|
res = _add_raycast(space_state, center, center - Vector3(0.0, 0.8, 0.0))
|
|
Log.print_log("Raycast inside: %s" % ("HIT" if res else "NO HIT"))
|
|
|
|
_raycast_visuals.surface_end()
|
|
|
|
_raycast_visuals.surface_set_material(0, _material)
|
|
|
|
|
|
func _on_option_changed(option: String, checked: bool) -> void:
|
|
match option:
|
|
OPTION_TEST_CASE_HIT_FROM_INSIDE:
|
|
_hit_from_inside = checked
|
|
_do_raycasts = true
|
|
|
|
|
|
func _add_raycast(space_state: PhysicsDirectSpaceState3D, pos_start: Vector3, pos_end: Vector3) -> Dictionary:
|
|
var params := PhysicsRayQueryParameters3D.new()
|
|
params.from = pos_start
|
|
params.to = pos_end
|
|
params.hit_from_inside = _hit_from_inside
|
|
|
|
var result := space_state.intersect_ray(params)
|
|
if result:
|
|
_raycast_visuals.surface_set_color(Color.GREEN)
|
|
else:
|
|
_raycast_visuals.surface_set_color(Color.BLACK)
|
|
|
|
# Draw raycast line.
|
|
_raycast_visuals.surface_add_vertex(pos_start)
|
|
_raycast_visuals.surface_add_vertex(pos_end)
|
|
|
|
# Draw raycast arrow.
|
|
_raycast_visuals.surface_add_vertex(pos_end)
|
|
_raycast_visuals.surface_add_vertex(pos_end + Vector3(-0.05, 0.1, 0.0))
|
|
_raycast_visuals.surface_add_vertex(pos_end)
|
|
_raycast_visuals.surface_add_vertex(pos_end + Vector3(0.05, 0.1, 0.0))
|
|
|
|
return result
|