Implement fancy rendering for smart cables

Closes #107.
This commit is contained in:
Tad Hardesty 2019-11-17 18:25:58 -08:00
parent ac626acab5
commit 575dda72a6
2 changed files with 101 additions and 0 deletions

View file

@ -6,11 +6,13 @@ mod transit_tube;
mod random;
mod structures;
mod icon_smoothing;
mod smart_cables;
pub use self::transit_tube::TransitTube;
pub use self::random::Random;
pub use self::structures::{GravityGen, Spawners};
pub use self::icon_smoothing::IconSmoothing;
pub use self::smart_cables::SmartCables;
/// A map rendering pass.
///
@ -102,6 +104,7 @@ pub const RENDER_PASSES: &[RenderPassInfo] = &[
pass!(Pipes, "only-pipenet", "Render only atmospheric pipes.", false),
pass!(FancyLayers, "fancy-layers", "Layer atoms according to in-game rules.", true),
pass!(IconSmoothing, "icon-smoothing", "Emulate the icon smoothing subsystem.", true),
pass!(SmartCables, "smart-cables", "Handle smart cable layout.", true),
];
pub fn configure(include: &str, exclude: &str) -> Vec<Box<dyn RenderPass>> {

View file

@ -0,0 +1,98 @@
use std::fmt::Write;
use dmi::Dir;
use super::*;
#[derive(Default)]
pub struct SmartCables;
impl RenderPass for SmartCables {
fn neighborhood_appearance<'a>(&self,
atom: &Atom<'a>,
objtree: &'a ObjectTree,
neighborhood: &Neighborhood<'a, '_>,
output: &mut Vec<Sprite<'a>>,
bump: &'a bumpalo::Bump,
) -> bool {
if !atom.istype("/obj/structure/cable/") {
return true;
}
let cable_layer = atom.get_var("cable_layer", objtree).as_str().unwrap_or("l2");
let mut under_smes = false;
let mut under_terminal = false;
for atom in neighborhood.center() {
if atom.istype("/obj/machinery/power/terminal/") {
under_terminal = true;
} else if atom.istype("/obj/machinery/power/smes/") {
under_smes = true;
}
}
// calculate linked dirs
let mut linked_dirs = 0;
'dir: for &check_dir in Dir::CARDINALS {
let turf = neighborhood.offset(check_dir);
// Don't link between SMES and terminal
if under_smes {
for atom in turf {
if atom.istype("/obj/machinery/power/terminal/") {
continue 'dir;
}
}
} else if under_terminal {
for atom in turf {
if atom.istype("/obj/machinery/power/smes/") {
continue 'dir;
}
}
}
for atom in turf {
if atom.istype("/obj/structure/cable/") {
if atom.get_var("cable_layer", objtree).as_str().unwrap_or("l2") == cable_layer {
linked_dirs |= check_dir.to_int();
break;
}
}
}
}
// calculate icon state
let mut icon_state;
if linked_dirs == 0 {
icon_state = bumpalo::format!(in bump, "{}-noconnection", cable_layer);
} else {
icon_state = bumpalo::format!(in bump, "{}", cable_layer);
let mut count = 0;
for &check_dir in Dir::CARDINALS {
if linked_dirs & check_dir.to_int() != 0 {
let _ = write!(icon_state, "-{}", check_dir.to_int());
count += 1;
}
}
if count > 1 && should_have_node(neighborhood.center()) {
let _ = write!(icon_state, "-node");
}
};
output.push(Sprite {
icon_state: icon_state.into_bump_str(),
.. atom.sprite
});
false
}
}
fn should_have_node(turf: &[Atom]) -> bool {
for atom in turf {
if atom.istype("/obj/structure/grille/") || atom.istype("/obj/structure/cable_bridge/") {
return true;
} else if atom.istype("/obj/machinery/power/") {
// TODO: more detailed type-specific checks
return true;
}
}
false
}