oxihuman-viewer 0.2.1

wgpu/WebGPU rendering adapter for OxiHuman
Documentation
// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
// SPDX-License-Identifier: Apache-2.0
#![allow(dead_code)]

//! Rack focus transition view stub.

/// Rack focus view configuration.
#[derive(Debug, Clone)]
pub struct RackFocusView {
    pub near_focus_dist: f32,
    pub far_focus_dist: f32,
    pub focus_progress: f32,
    pub transition_speed: f32,
    pub blur_amount: f32,
    pub enabled: bool,
}

impl RackFocusView {
    pub fn new() -> Self {
        RackFocusView {
            near_focus_dist: 1.0,
            far_focus_dist: 10.0,
            focus_progress: 0.0,
            transition_speed: 1.0,
            blur_amount: 0.5,
            enabled: true,
        }
    }
}

impl Default for RackFocusView {
    fn default() -> Self {
        Self::new()
    }
}

/// Create a new rack focus view.
pub fn new_rack_focus_view() -> RackFocusView {
    RackFocusView::new()
}

/// Compute current focus distance by interpolating near/far.
pub fn rfv_current_focus_dist(rfv: &RackFocusView) -> f32 {
    /* Stub: linearly interpolates between near and far focus distance */
    rfv.near_focus_dist + (rfv.far_focus_dist - rfv.near_focus_dist) * rfv.focus_progress
}

/// Advance focus progress.
pub fn rfv_set_focus_progress(rfv: &mut RackFocusView, progress: f32) {
    rfv.focus_progress = progress.clamp(0.0, 1.0);
}

/// Set transition speed.
pub fn rfv_set_speed(rfv: &mut RackFocusView, speed: f32) {
    rfv.transition_speed = speed.max(0.0);
}

/// Set blur amount.
pub fn rfv_set_blur(rfv: &mut RackFocusView, blur: f32) {
    rfv.blur_amount = blur.clamp(0.0, 1.0);
}

/// Enable or disable.
pub fn rfv_set_enabled(rfv: &mut RackFocusView, enabled: bool) {
    rfv.enabled = enabled;
}

/// Serialize to JSON-like string.
pub fn rfv_to_json(rfv: &RackFocusView) -> String {
    format!(
        r#"{{"near_focus":{},"far_focus":{},"progress":{},"blur":{},"enabled":{}}}"#,
        rfv.near_focus_dist, rfv.far_focus_dist, rfv.focus_progress, rfv.blur_amount, rfv.enabled
    )
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_default_near_focus() {
        let r = new_rack_focus_view();
        assert!((r.near_focus_dist - 1.0).abs() < 1e-5, /* default near focus must be 1.0 */);
    }

    #[test]
    fn test_focus_at_near_when_progress_zero() {
        let r = new_rack_focus_view();
        let dist = rfv_current_focus_dist(&r);
        assert!((dist - r.near_focus_dist).abs() < 1e-5, /* focus at progress=0 must be near */);
    }

    #[test]
    fn test_focus_at_far_when_progress_one() {
        let mut r = new_rack_focus_view();
        rfv_set_focus_progress(&mut r, 1.0);
        let dist = rfv_current_focus_dist(&r);
        assert!((dist - r.far_focus_dist).abs() < 1e-5, /* focus at progress=1 must be far */);
    }

    #[test]
    fn test_set_speed() {
        let mut r = new_rack_focus_view();
        rfv_set_speed(&mut r, 2.0);
        assert!((r.transition_speed - 2.0).abs() < 1e-5, /* speed must be set */);
    }

    #[test]
    fn test_set_blur_clamped() {
        let mut r = new_rack_focus_view();
        rfv_set_blur(&mut r, 2.0);
        assert!((r.blur_amount - 1.0).abs() < 1e-6, /* blur clamped to 1.0 */);
    }

    #[test]
    fn test_set_progress_clamped() {
        let mut r = new_rack_focus_view();
        rfv_set_focus_progress(&mut r, -0.5);
        assert!((r.focus_progress).abs() < 1e-6, /* progress clamped to 0 */);
    }

    #[test]
    fn test_set_enabled() {
        let mut r = new_rack_focus_view();
        rfv_set_enabled(&mut r, false);
        assert!(!r.enabled /* must be disabled */,);
    }

    #[test]
    fn test_to_json_contains_near_focus() {
        let r = new_rack_focus_view();
        let j = rfv_to_json(&r);
        assert!(j.contains("\"near_focus\""), /* json must contain near_focus */);
    }

    #[test]
    fn test_enabled_default() {
        let r = new_rack_focus_view();
        assert!(r.enabled /* must be enabled by default */,);
    }

    #[test]
    fn test_focus_midpoint() {
        let mut r = new_rack_focus_view();
        rfv_set_focus_progress(&mut r, 0.5);
        let dist = rfv_current_focus_dist(&r);
        let mid = (r.near_focus_dist + r.far_focus_dist) / 2.0;
        assert!((dist - mid).abs() < 1e-4, /* focus at progress=0.5 must be midpoint */);
    }
}