use nightshade_api::nightshade::prelude::nalgebra_glm::Quat;
use nightshade_api::prelude::*;
struct Coverage {
instances: Entity,
phase: f32,
}
fn main() {
run(
|world| {
set_title(world, "Facade Coverage");
set_background(world, Background::Nebula);
set_bloom(world, true);
orbit_camera(world, vec3(0.0, 0.5, 0.0), 14.0);
set_orbit_view(world, vec3(0.0, 0.5, 0.0), 14.0, 0.7, 0.5);
spawn_floor(world, 30.0);
build_widgets(world);
let instances = build_instanced_city(world);
scatter_decals(world);
spawn_particle_emitter(
world,
ParticleEmitter::firework_explosion(vec3(0.0, 4.0, 0.0), vec3(1.0, 0.6, 0.2), 200),
);
bake_navmesh_with(
world,
&RecastNavMeshConfig {
agent_radius: 0.6,
walkable_slope_angle: 50.0,
..Default::default()
},
);
Coverage {
instances,
phase: 0.0,
}
},
|world, state| {
state.phase += delta_time(world);
let transforms = city_transforms(state.phase);
set_instances(world, state.instances, transforms);
},
)
.unwrap();
}
fn build_widgets(world: &mut World) {
let panel = spawn_panel(world, ScreenAnchor::TopLeft, 320.0, 560.0);
panel_heading(world, panel, "Facade widgets");
panel_separator(world, panel);
panel_label(world, panel, "Tree");
let tree = panel_tree_view(world, panel, false);
let content = tree_content(world, tree);
let root = tree_node(world, tree, content, "World", 0, 0);
set_tree_node_expanded(world, root, true);
let children = tree_node_children(world, root);
tree_node(world, tree, children, "Buildings", 1, 1);
tree_node(world, tree, children, "Lights", 1, 2);
panel_label(world, panel, "Table");
let grid = panel_data_grid(world, panel, &[("Name", 120.0), ("Value", 80.0)], 8);
set_data_grid_rows(world, grid, 3);
for row in 0..3 {
set_data_grid_cell(world, grid, row, 0, &format!("item {row}"));
set_data_grid_cell(world, grid, row, 1, &format!("{}", row * 10));
}
panel_label(world, panel, "Inputs");
panel_color_picker_hsv(world, panel, [0.2, 0.6, 1.0, 1.0]);
panel_drag_value(world, panel, 0.0, 100.0, 25.0);
panel_multi_select(world, panel, &["alpha", "beta", "gamma"]);
panel_date_picker(world, panel, 2026, 6, 15);
panel_text_area(world, panel, "notes...", 3);
panel_breadcrumb(world, panel, &["home", "scene", "node"]);
panel_spinner(world, panel);
}
fn build_instanced_city(world: &mut World) -> Entity {
let pixels = checker_pixels(8, [60, 70, 110, 255], [200, 210, 255, 255]);
register_texture(world, "coverage::windows", 8, 8, &pixels);
register_material(
world,
"coverage::glass",
Material {
base_color: [0.4, 0.55, 0.8, 1.0],
metallic: 0.6,
roughness: 0.25,
..Default::default()
},
);
spawn_instanced_with_material(world, Shape::Cube, city_transforms(0.0), "coverage::glass")
}
fn city_transforms(phase: f32) -> Vec<InstanceTransform> {
let mut transforms = Vec::new();
for column in 0..6 {
for row in 0..6 {
let x = column as f32 * 1.6 - 4.0;
let z = row as f32 * 1.6 - 4.0;
let height = 1.5 + ((column + row) as f32 + phase).sin().abs() * 2.5;
transforms.push(InstanceTransform::new(
vec3(x, height * 0.5, z),
Quat::identity(),
vec3(0.6, height, 0.6),
));
}
}
transforms
}
fn scatter_decals(world: &mut World) {
let pixels = checker_pixels(4, [255, 120, 40, 255], [255, 200, 60, 255]);
register_texture(world, "coverage::decal", 4, 4, &pixels);
for index in 0..4 {
let offset = index as f32 * 2.0 - 3.0;
spawn_decal(
world,
"coverage::decal",
vec3(offset, 0.02, 5.0),
vec3(0.0, 1.0, 0.0),
1.5,
);
}
}
fn checker_pixels(size: usize, a: [u8; 4], b: [u8; 4]) -> Vec<u8> {
let mut pixels = Vec::with_capacity(size * size * 4);
for row in 0..size {
for column in 0..size {
let color = if (row + column) % 2 == 0 { a } else { b };
pixels.extend_from_slice(&color);
}
}
pixels
}