immersive-home/app/content/functions/movable.gd

130 lines
3.8 KiB
GDScript3
Raw Normal View History

2023-11-05 22:32:50 +02:00
@tool
extends Function
class_name Movable
2024-01-24 18:43:44 +02:00
signal on_move(position: Vector3, rotation: Vector3)
2024-01-27 16:13:43 +02:00
signal on_moved()
2024-01-24 18:43:44 +02:00
2024-01-16 16:00:30 +02:00
@export var restricted: bool = false
2024-04-30 20:18:49 +03:00
@export var resizable: bool = false
2024-01-16 16:00:30 +02:00
@export var lock_rotation: bool = false
2024-04-30 20:18:49 +03:00
@export var restrict_movement: Callable
2024-04-26 14:58:20 +03:00
@export var disabled: bool = false
2024-04-30 20:18:49 +03:00
2024-04-25 20:09:52 +03:00
var initiator = null
2024-04-30 20:18:49 +03:00
var initiator2 = null
var resizing = false
var relative_transform = Transform3D()
var initial_point = Vector3()
var initial_rotation = Vector3()
# For Scaling
var initial_position = Vector3()
var initial_direction = Vector3()
var initial_up = Vector3()
var initial_transform = Transform3D()
var distances = Vector2()
func _process(delta):
if get_tree().debug_collisions_hint&&resizing:
DebugDraw3D.draw_line(initial_position, initial_position + initial_direction, Color(1, 0, 0))
DebugDraw3D.draw_line(initial_position, initial_position + initial_up, Color(0, 1, 0))
2023-11-05 22:32:50 +02:00
2023-11-27 01:23:19 +02:00
func _on_grab_down(event: EventPointer):
2024-04-26 14:58:20 +03:00
if disabled:
return
2024-04-25 20:09:52 +03:00
if restricted&&event.target != get_parent():
2024-01-16 16:00:30 +02:00
return
2024-04-30 20:18:49 +03:00
if resizing&&initiator2 != null:
return
if resizable&&initiator != null:
initiator2 = event.initiator
resizing = true
distances.y = event.ray.get_collision_point().distance_to(event.ray.global_position)
initial_position = _get_first_ray_point()
initial_direction = _get_second_ray_point() - initial_position
initial_up = -initiator.node.global_transform.basis.z.normalized() * distances.x
initial_transform = get_parent().global_transform
return
if resizable:
distances.x = event.ray.get_collision_point().distance_to(event.ray.global_position)
2024-04-25 20:09:52 +03:00
initiator = event.initiator
2024-04-30 20:18:49 +03:00
_update_relative_transform()
2024-04-25 20:09:52 +03:00
2024-04-30 20:18:49 +03:00
if lock_rotation:
initial_point = get_parent().to_local(event.ray.get_collision_point())
initial_rotation = get_parent().global_rotation
2023-11-05 22:32:50 +02:00
2024-04-25 20:09:52 +03:00
func _on_grab_move(event: EventPointer):
2024-04-30 20:18:49 +03:00
if event.initiator != initiator:
2024-01-24 18:43:44 +02:00
return
2024-04-25 20:09:52 +03:00
2024-04-30 20:18:49 +03:00
if resizing:
var new_position = _get_first_ray_point()
var new_direction = _get_second_ray_point() - new_position
var new_up = -initiator.node.global_transform.basis.z.normalized() * distances.x
if get_tree().debug_collisions_hint:
DebugDraw3D.draw_line(new_position, new_position + new_direction, Color(1, 0, 0))
DebugDraw3D.draw_line(new_position, new_position + new_up, Color(0, 1, 0))
get_parent().global_transform = TransformTools.calc_delta_transform(initial_position, initial_direction, initial_up, new_position, new_direction, new_up) * initial_transform
2024-04-25 20:09:52 +03:00
return
2024-04-30 20:18:49 +03:00
get_parent().global_transform = initiator.node.global_transform * relative_transform
if lock_rotation:
get_parent().global_transform = TransformTools.rotate_around_point(get_parent().global_transform, get_parent().to_global(initial_point), initial_rotation - get_parent().global_rotation)
2024-01-24 18:43:44 +02:00
2023-11-27 01:23:19 +02:00
func _on_grab_up(event: EventPointer):
2024-04-30 20:18:49 +03:00
if event.initiator == initiator2:
initiator2 = null
resizing = false
_update_relative_transform()
2024-04-25 20:09:52 +03:00
return
2024-04-30 20:18:49 +03:00
if event.initiator == initiator:
if initiator2 != null:
initiator = initiator2
initiator2 = null
resizing = false
_update_relative_transform()
else:
initiator = null
initiator2 = null
resizing = false
on_moved.emit()
func _get_first_ray_point():
if initiator == null:
return Vector3()
return initiator.node.global_position - initiator.node.global_transform.basis.z.normalized() * distances.x
func _get_second_ray_point():
if initiator2 == null:
return Vector3()
return initiator2.node.global_position - initiator2.node.global_transform.basis.z.normalized() * distances.y
2024-04-25 20:09:52 +03:00
2024-04-30 20:18:49 +03:00
func _update_relative_transform():
relative_transform = initiator.node.global_transform.affine_inverse() * get_parent().global_transform
2023-11-05 22:32:50 +02:00
func _get_configuration_warnings() -> PackedStringArray:
var warnings := PackedStringArray()
if get_parent() is StaticBody3D == false:
warnings.append("Movable requires a StaticBody3D as parent.")
2023-11-06 16:39:53 +02:00
return warnings