codecraft 0.1.1

A minimalist 3D game engine built on parts of Bevy (ECS, color) with wgpu and winit: OpenPBR materials, clustered lighting, an immediate-mode UI, audio and gamepad haptics
Documentation
//! The icons compiled into the binary.
//!
//! `assets/icons` holds fifteen hundred of them and six megabytes; a binary
//! that runs from any working directory cannot carry all of that for the
//! twenty it draws. So [`path`](super::path) is the catalogue of what
//! *ships*, and this is the subset that is *built in* -- adding one is a line
//! here, and forgetting to is a warning in the log and a blank where the icon
//! should be, never a wrong icon.

macro_rules! embed {
    ($($path:expr),* $(,)?) => {
        /// Every embedded icon, as (path, svg).
        pub const ALL: &[(&str, &str)] = &[
            $((
                $path,
                include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/assets/", $path)),
            ),)*
        ];

        /// The SVG behind an icon path, if it is one of the ones built in.
        pub fn source(path: &str) -> Option<&'static str> {
            ALL.iter()
                .find(|(known, _)| *known == path)
                .map(|(_, svg)| *svg)
        }
    };
}

embed![
    // Scene objects. The pieces first: a chess set has no icon of its own in
    // the set, so each piece takes the nearest thing that reads as its shape.
    "icons/crown.svg",         // the king
    "icons/crown-simple.svg",  // the queen
    "icons/castle-turret.svg", // the rook
    "icons/horse.svg",         // the knight
    "icons/church.svg",        // the bishop
    "icons/circle.svg",        // the pawn
    "icons/cube.svg",
    "icons/shapes.svg",
    "icons/lightbulb.svg",
    "icons/sun.svg",
    "icons/lamp.svg",
    "icons/camera.svg",
    "icons/grid-four.svg",
    // Panels and menus.
    "icons/list-bullets.svg",
    "icons/sliders.svg",
    "icons/cards-three.svg",
    "icons/clock.svg",
    "icons/play.svg",
    "icons/pencil.svg",
    "icons/plug.svg",
    "icons/gear.svg",
    "icons/info.svg",
    "icons/sign-out.svg",
    "icons/folder.svg",
    "icons/floppy-disk.svg",
    "icons/export.svg",
    "icons/image.svg",
    "icons/monitor.svg",
    "icons/target.svg",
    "icons/eye.svg",
    "icons/eye-slash.svg",
    "icons/plus.svg",
    "icons/x.svg",
    // The carets a menu wears: what a button opens, and which way.
    "icons/caret-up.svg",
    "icons/caret-down.svg",
    "icons/caret-left.svg",
    "icons/caret-right.svg",
    "icons/wrench.svg",
    // Ours, not Phosphor's -- see `icons::ours`.
    "ui/pointer-up.svg",
    "ui/pointer-down.svg",
    "ui/pointer-left.svg",
    "ui/pointer-right.svg",
];

#[cfg(test)]
mod tests {
    /// An embedded path that is not in the catalogue is a path nobody can
    /// name -- the `path::` constants are how the rest of the code asks for
    /// an icon, and a mismatch means the icon is compiled in and unreachable.
    #[test]
    fn every_embedded_icon_has_a_name() {
        for (path, _) in super::ALL {
            // Ours are named in `icons::ours` instead; they are not
            // Phosphor's and have no business in its catalogue.
            if crate::ui::icons::ours::ALL.contains(path) {
                continue;
            }
            assert!(
                crate::ui::icons::path::ALL
                    .iter()
                    .any(|(_, known)| known == path),
                "{path} is embedded but is not in `path::ALL`",
            );
        }
    }
}