using Godot; using MaxEffort.Code.Core; namespace MaxEffort.Code.Visuals; [GlobalClass] public partial class LiftSyncController : Node { [ExportGroup("References")] [Export] private AnimatedSprite2D _playerAnim; [Export] private Sprite2D _barbell; [ExportGroup("Configuration")] [Export] private string _animationName = "lift"; [Export] private Godot.Collections.Array _barPositions; [ExportGroup("Rep Settings")] [Export] private bool _simulateReps = true; // TOGGLE THIS ON FOR BENCH PRESS [Export] private float _repSpeed = 2.0f; // How fast you do reps visualy private float _currentRepProgress = 0f; // 0.0 to 1.0 (internal visual cycle) private bool _isLifting = false; public override void _Ready() { EventBus.OnLiftVisualHeight += HandleDirectSync; EventBus.OnLiftEffortApplied += HandleEffort; EventBus.OnFocusRelease += OnFocusRelease; } public override void _ExitTree() { EventBus.OnLiftVisualHeight -= HandleDirectSync; EventBus.OnLiftEffortApplied -= HandleEffort; } public override void _Process(double delta) { if (!_simulateReps) return; var dt = (float)delta; if (_isLifting) { _currentRepProgress += _repSpeed * dt; } else { if (_currentRepProgress > 0) { _currentRepProgress -= _repSpeed * dt; _currentRepProgress = Mathf.Max(0, _currentRepProgress); } } var pingPongValue = Mathf.PingPong(_currentRepProgress, 1.0f); UpdateVisuals(pingPongValue); _isLifting = false; } private void UpdateVisuals(float normalizedHeight) { if (_playerAnim == null || _barbell == null || _barPositions.Count == 0) return; var totalFrames = _barPositions.Count; var frameIndex = Mathf.FloorToInt(normalizedHeight * (totalFrames - 0.01f)); frameIndex = Mathf.Clamp(frameIndex, 0, totalFrames - 1); _playerAnim.Frame = frameIndex; if (_playerAnim.Animation != _animationName) _playerAnim.Play(_animationName); _barbell.Position = _barPositions[frameIndex]; } private void OnFocusRelease() { _isLifting = false; } private void HandleDirectSync(float height) { if (!_simulateReps) { UpdateVisuals(height); } } private void HandleEffort(float delta) { _isLifting = true; } }