Files
demo-game/scripts/orientation_gizmo.gd
T
skrueckenandCursor 142968038c Unify pod steering on lateral X tilt for flat and frontal holds.
Replace facing-only roll detection with atan2(x, yz) so left/right works in both orientations without a face gate.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-26 15:28:44 +02:00

82 lines
2.4 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends SubViewportContainer
class_name OrientationGizmo
const MIN_ACCEL_LEN := 1000.0
const SMOOTH := 0.25
const VIEW_SIZE := Vector2(220, 220)
const ACTIVE_MODULATE := Color(1, 1, 1, 1)
const IDLE_MODULATE := Color(0.55, 0.58, 0.65, 0.85)
## Mesh TOP = local −Y.
## Flat accel ≈ +Z → side view, TOP at top of screen
## Facing accel ≈ −Y → TOP face toward camera
## Steer accel ≈ −X → facing + roll left (steering wheel)
var _basis_flat: Basis = Basis(Quaternion(Vector3.RIGHT, PI))
var _basis_facing: Basis = Basis(Quaternion(Vector3.RIGHT, -PI * 0.5))
@onready var _viewport: SubViewport = $SubViewport
@onready var _camera: Camera3D = $SubViewport/Camera3D
@onready var _pod: Node3D = $SubViewport/Pod
var _has_sample := false
var _target_basis := Basis.IDENTITY
func _ready() -> void:
custom_minimum_size = VIEW_SIZE
stretch = true
_viewport.own_world_3d = true
_viewport.transparent_bg = true
_viewport.size = Vector2i(VIEW_SIZE)
_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
_camera.projection = Camera3D.PROJECTION_ORTHOGONAL
_camera.size = 2.6
_camera.near = 0.05
_camera.far = 50.0
_camera.position = Vector3(0.0, 0.0, 3.2)
_camera.look_at(Vector3.ZERO, Vector3.UP)
clear()
func set_accel(v: Vector3) -> void:
if v.length() < MIN_ACCEL_LEN:
return
_has_sample = true
modulate = ACTIVE_MODULATE
_target_basis = _basis_from_accel(v)
func clear() -> void:
_has_sample = false
_target_basis = _basis_flat
if _pod != null:
_pod.basis = _basis_flat
modulate = IDLE_MODULATE
func _process(_delta: float) -> void:
if not _has_sample:
return
_pod.basis = _pod.basis.slerp(_target_basis, SMOOTH)
## Lateral tip in radians about device X.
## Positive = tip toward +X (works for flat left/right tilt and frontal wheel turn).
static func steer_roll(accel: Vector3, deadzone_rad: float = deg_to_rad(8.0)) -> float:
if accel.length() < MIN_ACCEL_LEN:
return 0.0
var n := accel.normalized()
var angle := atan2(n.x, sqrt(n.y * n.y + n.z * n.z))
if absf(angle) <= deadzone_rad:
return 0.0
return signf(angle) * (absf(angle) - deadzone_rad)
func _basis_from_accel(accel: Vector3) -> Basis:
var n := accel.normalized()
# 0 = liegend (+Z), 1 = aufgerichtet / gedreht (wenig +Z)
var face_t := clampf(1.0 - maxf(n.z, 0.0), 0.0, 1.0)
var b := _basis_flat.slerp(_basis_facing, face_t)
var lateral := atan2(n.x, sqrt(n.y * n.y + n.z * n.z))
return Basis(Quaternion(Vector3.BACK, -lateral)) * b