use crate::vpx::gameitem::light::Light;
use crate::vpx::gameitem::primitive::Primitive;
use crate::vpx::version::Version;
const VPX_10_8: u32 = 1080;
#[inline]
fn is_pre_10_8(version: &Version) -> bool {
version.u32() < VPX_10_8
}
pub fn primitive_is_visible(primitive: &Primitive, version: &Version) -> bool {
if is_pre_10_8(version) && primitive.is_playfield() {
return true;
}
primitive.is_visible
}
#[allow(dead_code)] pub fn primitive_static_rendering(primitive: &Primitive, version: &Version) -> bool {
if is_pre_10_8(version) && primitive.is_playfield() {
return true;
}
primitive.static_rendering
}
#[allow(dead_code)] pub fn primitive_depth_bias(primitive: &Primitive, version: &Version) -> f32 {
if is_pre_10_8(version) && primitive.is_playfield() {
return 100_000.0;
}
primitive.depth_bias
}
#[allow(dead_code)] pub fn primitive_backfaces_enabled(primitive: &Primitive, version: &Version) -> Option<bool> {
if is_pre_10_8(version) && primitive.is_playfield() {
return Some(false);
}
primitive.backfaces_enabled
}
pub fn primitive_disable_lighting_below(
primitive: &Primitive,
material_opacity: Option<(bool, f32)>,
version: &Version,
) -> Option<f32> {
if is_pre_10_8(version) {
if primitive.is_playfield() {
return Some(1.0);
}
if let Some((opacity_active, opacity)) = material_opacity
&& (!opacity_active || opacity == 1.0)
{
return Some(1.0);
}
}
primitive.disable_lighting_below
}
pub fn light_height(light: &Light, version: &Version) -> Option<f32> {
if is_pre_10_8(version) {
return Some(if light.is_bulb_light {
light.bulb_halo_height
} else {
0.0
});
}
light.height
}
pub fn light_show_bulb_mesh(light: &Light, version: &Version) -> bool {
if is_pre_10_8(version) {
if !light.is_bulb_light {
return false;
}
if !light.visible.unwrap_or(true) {
return false;
}
}
light.show_bulb_mesh
}
#[allow(dead_code)] pub fn light_show_reflection_on_ball(light: &Light, version: &Version) -> bool {
if is_pre_10_8(version) && !light.is_bulb_light {
return false;
}
light.show_reflection_on_ball
}
#[allow(dead_code)] pub fn glass_bottom_height(
glass_top_height: f32,
glass_bottom_height: Option<f32>,
version: &Version,
) -> f32 {
if is_pre_10_8(version) {
return glass_top_height;
}
glass_bottom_height.unwrap_or(glass_top_height)
}
#[cfg(test)]
mod tests {
use super::*;
fn version(v: &str) -> Version {
Version::parse(v).unwrap()
}
fn primitive(name: &str) -> Primitive {
Primitive {
name: name.to_string(),
..Primitive::default()
}
}
#[test]
fn pre_10_8_forces_playfield_visible_only() {
let mut p = primitive("playfield_mesh");
p.is_visible = false;
assert!(primitive_is_visible(&p, &version("1072")));
let mut other = primitive("SomePrimitive");
other.is_visible = false;
assert!(!primitive_is_visible(&other, &version("1072")));
}
#[test]
fn post_10_8_honours_stored_visibility() {
let mut p = primitive("playfield_mesh");
p.is_visible = false;
for v in ["1080", "1081"] {
assert!(!primitive_is_visible(&p, &version(v)));
}
}
#[test]
fn playfield_match_is_case_insensitive() {
let p = primitive("Playfield_Mesh");
assert!(primitive_is_visible(&p, &version("1072")));
}
#[test]
fn pre_10_8_forces_playfield_static_depth_backfaces() {
let p = primitive("playfield_mesh");
assert!(primitive_static_rendering(&p, &version("1072")));
assert_eq!(primitive_depth_bias(&p, &version("1072")), 100_000.0);
assert_eq!(
primitive_backfaces_enabled(&p, &version("1072")),
Some(false)
);
}
#[test]
fn post_10_8_keeps_stored_static_depth_backfaces() {
let mut p = primitive("playfield_mesh");
p.static_rendering = false;
p.depth_bias = 42.0;
p.backfaces_enabled = Some(true);
assert!(!primitive_static_rendering(&p, &version("1080")));
assert_eq!(primitive_depth_bias(&p, &version("1080")), 42.0);
assert_eq!(
primitive_backfaces_enabled(&p, &version("1080")),
Some(true)
);
}
#[test]
fn pre_10_8_disable_lighting_below_playfield() {
let p = primitive("playfield_mesh");
assert_eq!(
primitive_disable_lighting_below(&p, Some((true, 0.5)), &version("1072")),
Some(1.0)
);
}
#[test]
fn pre_10_8_disable_lighting_below_opaque_material() {
let p = primitive("Other");
assert_eq!(
primitive_disable_lighting_below(&p, Some((true, 1.0)), &version("1072")),
Some(1.0)
);
assert_eq!(
primitive_disable_lighting_below(&p, Some((false, 0.5)), &version("1072")),
Some(1.0)
);
let mut p2 = primitive("Other");
p2.disable_lighting_below = Some(0.25);
assert_eq!(
primitive_disable_lighting_below(&p2, Some((true, 0.5)), &version("1072")),
Some(0.25)
);
}
#[test]
fn pre_10_8_missing_material_does_not_force() {
let p = primitive("Other");
assert_eq!(
primitive_disable_lighting_below(&p, None, &version("1072")),
None
);
}
#[test]
fn post_10_8_disable_lighting_below_passes_through() {
let mut p = primitive("playfield_mesh");
p.disable_lighting_below = Some(0.5);
assert_eq!(
primitive_disable_lighting_below(&p, Some((true, 1.0)), &version("1080")),
Some(0.5)
);
}
fn light_with(is_bulb: bool, visible: Option<bool>) -> Light {
Light {
is_bulb_light: is_bulb,
visible,
show_bulb_mesh: true,
show_reflection_on_ball: true,
bulb_halo_height: 50.0,
height: Some(99.0),
..Light::default()
}
}
#[test]
fn pre_10_8_light_height_classic_is_zero() {
let l = light_with(false, Some(true));
assert_eq!(light_height(&l, &version("1072")), Some(0.0));
}
#[test]
fn pre_10_8_light_height_bulb_uses_halo_height() {
let l = light_with(true, Some(true));
assert_eq!(light_height(&l, &version("1072")), Some(50.0));
}
#[test]
fn post_10_8_light_height_passes_through() {
let l = light_with(false, Some(true));
assert_eq!(light_height(&l, &version("1080")), Some(99.0));
}
#[test]
fn pre_10_8_classic_lights_drop_bulb_mesh_and_reflection() {
let l = light_with(false, Some(true));
assert!(!light_show_bulb_mesh(&l, &version("1072")));
assert!(!light_show_reflection_on_ball(&l, &version("1072")));
}
#[test]
fn pre_10_8_invisible_lights_drop_bulb_mesh() {
let l = light_with(true, Some(false));
assert!(!light_show_bulb_mesh(&l, &version("1072")));
assert!(light_show_reflection_on_ball(&l, &version("1072")));
}
#[test]
fn post_10_8_lights_pass_through() {
let l = light_with(false, Some(false));
assert!(light_show_bulb_mesh(&l, &version("1080")));
assert!(light_show_reflection_on_ball(&l, &version("1080")));
}
#[test]
fn pre_10_8_glass_is_horizontal() {
assert_eq!(
glass_bottom_height(210.0, Some(100.0), &version("1072")),
210.0
);
assert_eq!(glass_bottom_height(210.0, None, &version("1072")), 210.0);
}
#[test]
fn post_10_8_glass_uses_stored_bottom() {
assert_eq!(
glass_bottom_height(210.0, Some(100.0), &version("1080")),
100.0
);
assert_eq!(glass_bottom_height(210.0, None, &version("1080")), 210.0);
}
}