reaction 0.2.0

Universal low-latency input handling for game engines
Documentation
use crate::optimization::jitter::JitterReducer;
use crate::optimization::pacing::AdaptiveFramePacer;
use crate::optimization::polling::HighFrequencyInputPoller;
use crate::optimization::prediction::InputPredictor;

pub struct UniversalLatencyOptimizer {
    pub poller: HighFrequencyInputPoller,
    pub pacer: AdaptiveFramePacer,
    pub predictor: InputPredictor,
    pub jitter_reducer: JitterReducer,

    // Configuration
    pub prediction_enabled: bool,
    pub jitter_reduction_enabled: bool,
}

impl UniversalLatencyOptimizer {
    pub fn new(target_hz: u32, target_fps: u32) -> Self {
        Self {
            poller: HighFrequencyInputPoller::new(target_hz),
            pacer: AdaptiveFramePacer::new(target_fps),
            predictor: InputPredictor::new(),
            jitter_reducer: JitterReducer::new(0.5), // Default moderate smoothing
            prediction_enabled: false,
            jitter_reduction_enabled: false,
        }
    }

    /// Called when raw input is received (e.g. from OS event loop)
    pub fn on_raw_input(&mut self, timestamp: f64, mouse_x: f32, mouse_y: f32) {
        // Record for prediction/polling
        // Note: poll.record_snapshot requires full snapshot, for now simplified update
        self.predictor.add_sample(mouse_x, mouse_y, timestamp);
    }

    pub fn get_optimized_mouse_pos(
        &mut self,
        current_time: f64,
        raw_x: f32,
        raw_y: f32,
    ) -> (f32, f32) {
        let mut x = raw_x;
        let mut y = raw_y;

        if self.prediction_enabled {
            let (px, py) = self.predictor.predict_at(current_time);
            // Blend or replace? Usually replace
            x = px;
            y = py;
        }

        if self.jitter_reduction_enabled {
            let (jx, jy) = self.jitter_reducer.process(x, y);
            x = jx;
            y = jy;
        }

        (x, y)
    }
}