Replace separate accel/tap push handling with input messages, set_input_stream, and a single set_stream on port 8081. Co-authored-by: Cursor <cursoragent@cursor.com>
150 lines
3.7 KiB
GDScript
150 lines
3.7 KiB
GDScript
extends Control
|
||
|
||
signal calibration_finished(calibration: AccelCalibration)
|
||
|
||
enum Phase { WAITING, RIGHT, LEFT, DONE }
|
||
|
||
const TRAVEL_PX := 140.0
|
||
const PHASE_DURATION := 4.5
|
||
const CIRCLE_RADIUS := 44.0
|
||
const NEEDLE_LEN := 58.0
|
||
|
||
var _phase := Phase.WAITING
|
||
var _phase_time := 0.0
|
||
var _guide_offset := Vector2.ZERO
|
||
var _instruction := ""
|
||
var _calibration := AccelCalibration.new()
|
||
var _connection_notified := false
|
||
|
||
@onready var _hint_label: Label = $HintLabel
|
||
@onready var _start_button: Button = $StartButton
|
||
|
||
|
||
func _ready() -> void:
|
||
set_anchors_preset(Control.PRESET_FULL_RECT)
|
||
mouse_filter = Control.MOUSE_FILTER_PASS
|
||
_start_button.pressed.connect(_on_start_pressed)
|
||
_show_waiting()
|
||
|
||
|
||
func start() -> void:
|
||
_calibration.reset()
|
||
_connection_notified = false
|
||
_phase = Phase.WAITING
|
||
_phase_time = 0.0
|
||
_guide_offset = Vector2.ZERO
|
||
visible = true
|
||
_start_button.visible = true
|
||
_show_waiting()
|
||
queue_redraw()
|
||
|
||
|
||
func is_active() -> bool:
|
||
return _phase != Phase.DONE
|
||
|
||
|
||
func feed_accel(accel: Vector3i) -> void:
|
||
match _phase:
|
||
Phase.RIGHT:
|
||
_calibration.record_right(accel)
|
||
Phase.LEFT:
|
||
_calibration.record_left(accel)
|
||
|
||
|
||
func notify_connected() -> void:
|
||
if _phase != Phase.WAITING or _connection_notified:
|
||
return
|
||
_hint_label.text = "Verbunden – tippe „Kalibrierung starten“ oder warte…"
|
||
# Automatisch starten sobald verbunden
|
||
begin_calibration()
|
||
|
||
|
||
func begin_calibration() -> void:
|
||
if _phase == Phase.RIGHT or _phase == Phase.LEFT:
|
||
return
|
||
_connection_notified = true
|
||
_start_button.visible = false
|
||
_begin_phase(Phase.RIGHT)
|
||
|
||
|
||
func _on_start_pressed() -> void:
|
||
begin_calibration()
|
||
|
||
|
||
func _process(delta: float) -> void:
|
||
if _phase == Phase.WAITING or _phase == Phase.DONE:
|
||
return
|
||
|
||
_phase_time += delta
|
||
var t := clampf(_phase_time / PHASE_DURATION, 0.0, 1.0)
|
||
var ease := t * t * (3.0 - 2.0 * t)
|
||
|
||
match _phase:
|
||
Phase.RIGHT:
|
||
_guide_offset.x = TRAVEL_PX * ease
|
||
_instruction = "Neige das Gerät nach rechts – folge dem Kreis →"
|
||
if _phase_time >= PHASE_DURATION:
|
||
_begin_phase(Phase.LEFT)
|
||
Phase.LEFT:
|
||
_guide_offset.x = -TRAVEL_PX * ease
|
||
_instruction = "Neige das Gerät nach links – folge dem Kreis ←"
|
||
if _phase_time >= PHASE_DURATION:
|
||
_finish()
|
||
|
||
_hint_label.text = _instruction
|
||
queue_redraw()
|
||
|
||
|
||
func _begin_phase(phase: Phase) -> void:
|
||
_phase = phase
|
||
_phase_time = 0.0
|
||
_guide_offset = Vector2.ZERO
|
||
match phase:
|
||
Phase.RIGHT:
|
||
_instruction = "Neige das Gerät nach rechts – folge dem Kreis →"
|
||
Phase.LEFT:
|
||
_instruction = "Neige das Gerät nach links – folge dem Kreis ←"
|
||
_hint_label.text = _instruction
|
||
queue_redraw()
|
||
|
||
|
||
func _finish() -> void:
|
||
_phase = Phase.DONE
|
||
visible = false
|
||
if _calibration.analyze():
|
||
calibration_finished.emit(_calibration)
|
||
else:
|
||
_hint_label.text = "Kalibrierung fehlgeschlagen – zu wenig Daten"
|
||
visible = true
|
||
_start_button.visible = true
|
||
_show_waiting()
|
||
|
||
|
||
func _show_waiting() -> void:
|
||
_instruction = "Warte auf Verbindung zu localhost:8081…"
|
||
_hint_label.text = _instruction + "\n(Oder „Kalibrierung starten“ ohne Verbindung)"
|
||
|
||
|
||
func _screen_center() -> Vector2:
|
||
return get_viewport_rect().size * 0.5
|
||
|
||
|
||
func _draw() -> void:
|
||
if _phase == Phase.DONE:
|
||
return
|
||
|
||
var pos := _screen_center() + _guide_offset
|
||
|
||
draw_circle(pos, CIRCLE_RADIUS, Color(0.25, 0.72, 0.95, 0.2))
|
||
draw_arc(pos, CIRCLE_RADIUS, 0.0, TAU, 64, Color(0.35, 0.82, 1.0), 2.5)
|
||
|
||
var needle_tip := pos + Vector2(0.0, -NEEDLE_LEN)
|
||
draw_line(pos, needle_tip, Color(1.0, 1.0, 1.0, 0.95), 3.0)
|
||
draw_circle(needle_tip, 5.0, Color(1.0, 1.0, 1.0))
|
||
|
||
var center := _screen_center()
|
||
if _phase == Phase.RIGHT:
|
||
draw_line(center, center + Vector2(TRAVEL_PX, 0.0), Color(1.0, 1.0, 1.0, 0.12), 1.0)
|
||
elif _phase == Phase.LEFT:
|
||
draw_line(center, center + Vector2(-TRAVEL_PX, 0.0), Color(1.0, 1.0, 1.0, 0.12), 1.0)
|