Add helper type for fixed-point layer sorts

This commit is contained in:
Tad Hardesty 2019-11-16 21:54:17 -08:00
parent 2710462812
commit 1d55bacd9b
4 changed files with 55 additions and 22 deletions

View file

@ -335,7 +335,7 @@ impl RenderPop {
ofs_x: sprite.ofs_x,
ofs_y: sprite.ofs_y,
plane: sprite.plane,
layer: sprite.layer,
layer: sprite.layer.encode(),
})
}

View file

@ -158,7 +158,7 @@ pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result<Image, ()> {
};
if !aboveground.is_empty() {
add_overlay!(aboveground);
atom.sprite.layer = -5_000;
atom.sprite.layer = Layer::from(-5);
}
} else if subtype(p, "/obj/machinery/power/apc/") {
use dmi::*;
@ -460,6 +460,39 @@ impl<'a> GetVar<'a> for TypeRef<'a> {
// ----------------------------------------------------------------------------
// Renderer-agnostic sprite structure
/// A guaranteed sortable representation of a `layer` float.
#[derive(Default, Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Layer {
whole: i16,
frac: u16,
}
impl Layer {
/// Encode this layer as an `i32` for FFI representation.
pub fn encode(self) -> i32 {
((self.whole as i32) << 16) | (self.frac as i32)
}
}
impl From<i16> for Layer {
fn from(whole: i16) -> Layer {
Layer { whole, frac: 0 }
}
}
impl From<i32> for Layer {
fn from(whole: i32) -> Layer {
use std::convert::TryFrom;
Layer { whole: i16::try_from(whole).expect("layer out of range"), frac: 0 }
}
}
impl From<f32> for Layer {
fn from(f: f32) -> Layer {
Layer { whole: f as i16, frac: ((f.fract() + 1.).fract() * 65536.) as u16 }
}
}
/// A Sprite is a fragment of an atom's appearance.
///
/// Every atom has a default sprite, which may be disabled, and a list of
@ -481,7 +514,7 @@ pub struct Sprite<'s> {
// sorting
pub plane: i32,
pub layer: i32,
pub layer: Layer,
}
impl<'s> Sprite<'s> {
@ -518,7 +551,7 @@ impl<'s> Default for Sprite<'s> {
ofs_x: 0,
ofs_y: 0,
plane: 0,
layer: 0,
layer: Layer::default(),
}
}
}
@ -547,13 +580,13 @@ fn plane_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom: &T) -> i3
}
}
fn layer_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom: &T) -> i32 {
fn layer_of<'s, T: GetVar<'s> + ?Sized>(objtree: &'s ObjectTree, atom: &T) -> Layer {
match atom.get_var("layer", objtree) {
&Constant::Int(i) => (i % 1000) * 1000,
&Constant::Float(f) => ((f % 1000.) * 1000.) as i32,
&Constant::Int(i) => Layer::from(i),
&Constant::Float(f) => Layer::from(f),
other => {
eprintln!("not a layer: {:?} on {:?}", other, atom.get_path());
2_000
Layer::from(2)
}
}
}

View file

@ -1,6 +1,6 @@
use dm::objtree::*;
use dm::constants::Constant;
use minimap::{Atom, GetVar, Sprite};
use minimap::{Atom, GetVar, Sprite, Layer};
pub mod transit_tube;
pub mod random;
@ -287,30 +287,30 @@ impl RenderPass for FancyLayers {
}
}
fn fancy_layer_for_path(p: &str) -> Option<i32> {
fn fancy_layer_for_path(p: &str) -> Option<Layer> {
use dm::objtree::subpath as subtype;
Some(if subtype(p, "/turf/open/floor/plating/") || subtype(p, "/turf/open/space/") {
-10_000 // under everything
Layer::from(-10) // under everything
} else if subtype(p, "/turf/closed/mineral/") {
-3_000 // above hidden stuff and plating but below walls
Layer::from(-3) // above hidden stuff and plating but below walls
} else if subtype(p, "/turf/open/floor/") || subtype(p, "/turf/closed/") {
-2_000 // above hidden pipes and wires
Layer::from(-2) // above hidden pipes and wires
} else if subtype(p, "/turf/") {
-10_000 // under everything
Layer::from(-10) // under everything
} else if subtype(p, "/obj/effect/turf_decal/") {
-1_000 // above turfs
Layer::from(-1) // above turfs
} else if subtype(p, "/obj/structure/disposalpipe/") {
-6_000
Layer::from(-6)
} else if subtype(p, "/obj/machinery/atmospherics/pipe/") && !p.contains("visible") {
-5_000
Layer::from(-5)
} else if subtype(p, "/obj/structure/cable/") {
-4_000
Layer::from(-4)
} else if subtype(p, "/obj/machinery/power/terminal/") {
-3_500
Layer::from(-3.5)
} else if subtype(p, "/obj/structure/lattice/") {
-8_000
Layer::from(-8)
} else if subtype(p, "/obj/machinery/navbeacon/") {
-3_000
Layer::from(-3)
} else {
return None
})

View file

@ -66,7 +66,7 @@ impl RenderPass for GravityGen {
sprite.icon_state = icon_state;
sprite.plane = 0; // TODO: figure out plane handling for real
if count <= 3 {
sprite.layer = 4_250; // WALL_OBJ_LAYER
sprite.layer = Layer::from(4.25); // WALL_OBJ_LAYER
}
if count == 5 {
// energy overlay goes above the middle part