Files
scorpion21211-cmd 965f0d7584 Initial commit
2026-10-03 23:29:41 -04:00

95 lines
2.3 KiB
GDScript

extends Node
## Sibling FO. Shift registered world roots.
## Move focus only when it is NOT already under a root (capsule = sibling).
## Never zero velocity.
const THRESHOLD: float = 50000.0
const COOLDOWN: float = 0.25
var focus: Node3D = null
var _shift_roots: Array[Node3D] = []
var _cooldown: float = 0.0
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
func set_focus(node: Node3D) -> void:
focus = node
func register_root(node: Node3D) -> void:
if node == null:
return
if not _shift_roots.has(node):
_shift_roots.append(node)
print("FloatingOrigin registered: ", node.name)
func unregister_root(node: Node3D) -> void:
_shift_roots.erase(node)
func shift(offset: Vector3) -> void:
if offset.length_squared() < 1.0:
return
_apply_shift(offset)
_cooldown = COOLDOWN
func _physics_process(delta: float) -> void:
if _cooldown > 0.0:
_cooldown -= delta
return
if focus == null or not is_instance_valid(focus) or not focus.is_inside_tree():
return
if _shift_roots.is_empty():
return
var fp: Vector3 = focus.global_position
if fp.length() < THRESHOLD:
return
_apply_shift(-fp)
_cooldown = COOLDOWN
func _apply_shift(offset: Vector3) -> void:
for root in _shift_roots:
if is_instance_valid(root) and root.is_inside_tree():
root.global_position += offset
if is_instance_valid(focus) and focus.is_inside_tree() and not _focus_under_a_root():
focus.global_position += offset
_sync_focus_physics()
print("FloatingOrigin shift: ", offset, " focus now: ", focus.global_position if focus else Vector3.ZERO)
func _focus_under_a_root() -> bool:
var n: Node = focus
while n != null:
if n is Node3D and _shift_roots.has(n as Node3D):
return true
n = n.get_parent()
return false
func _sync_focus_physics() -> void:
if focus == null or not is_instance_valid(focus):
return
if not (focus is CharacterBody3D):
return
var body := focus as CharacterBody3D
var saved_vel: Vector3 = body.velocity
PhysicsServer3D.body_set_state(
body.get_rid(),
PhysicsServer3D.BODY_STATE_TRANSFORM,
body.global_transform
)
PhysicsServer3D.body_set_state(
body.get_rid(),
PhysicsServer3D.BODY_STATE_LINEAR_VELOCITY,
saved_vel
)
body.velocity = saved_vel
if body.has_method("reset_physics_interpolation"):
body.reset_physics_interpolation()