diff options
| author | Irene Knapp <ireneista@irenes.space> | 2026-08-09 20:09:35 -0700 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2026-08-09 20:23:13 -0700 |
| commit | bbe9d5993bb922ad6b33a21c3557143cecaf960d (patch) | |
| tree | 387488a0a6b35aa5ba1fef1adcdc400d0f4935b6 | |
| parent | 677b697eb18b9abb252eacff320aa48314075a0e (diff) | |
abstract over bundled assets
yay build script stuff :) Force-Push: yes Change-Id: I694651febb02f42dac904f0dfbf4089c33ef937e
| -rw-r--r-- | build.rs | 128 | ||||
| -rw-r--r-- | src/files/obj.rs | 4 | ||||
| -rw-r--r-- | src/files/png.rs | 4 | ||||
| -rw-r--r-- | src/graphics/render.rs | 7 | ||||
| -rw-r--r-- | src/main.rs | 9 |
5 files changed, 129 insertions, 23 deletions
diff --git a/build.rs b/build.rs index ce74854..a6c5756 100644 --- a/build.rs +++ b/build.rs @@ -1,8 +1,31 @@ +use std::collections::BTreeSet; use std::env; -use std::fs; -use std::path::Path; +use std::fs::{ self, File }; +use std::io::Write; +use std::path::{ Path, PathBuf }; use std::process::Command; +struct Error(String); +impl std::fmt::Display for Error { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) + -> std::result::Result<(), std::fmt::Error> + { + fmt.write_str(&self.0) + } +} +impl From<std::io::Error> for Error { + fn from(e: std::io::Error) -> Self { + Error(format!("System I/O error: {}", e)) + } +} +impl From<std::path::StripPrefixError> for Error { + fn from(e: std::path::StripPrefixError) -> Self { + Error(format!("Can't strip path prefix: {}", e)) + } +} +type Result<T> = std::result::Result<T, Error>; + + fn main() { match process_all() { Err(error) => println!("cargo-error={}", error), @@ -11,18 +34,25 @@ fn main() { } -fn process_all() -> std::io::Result<()> { - process_shaders()?; - process_textures()?; - process_models()?; +fn process_all() -> Result<()> { + let mut asset_paths: BTreeSet<PathBuf> = BTreeSet::new(); + + process_shaders(&mut asset_paths)?; + process_textures(&mut asset_paths)?; + process_models(&mut asset_paths)?; + + generate_asset_module(asset_paths)?; Ok(()) } -fn process_shaders() -> std::io::Result<()> { +fn process_shaders(asset_paths: &mut BTreeSet<PathBuf>) -> Result<()> +{ let out_dir = env::var_os("OUT_DIR").unwrap(); + fs::create_dir_all(Path::new(&out_dir).join("shaders/"))?; + for input in fs::read_dir("shaders")? { let input_path = input?.path(); if !input_path.is_file() { @@ -38,14 +68,14 @@ fn process_shaders() -> std::io::Result<()> { let output_path = Path::new(&out_dir) - .join(format!("{}.spv", + .join(format!("shaders/{}.spv", input_path.file_name().unwrap().to_str().unwrap())); let result = Command::new("glslang") .arg("-V") .arg(&input_path) .arg("-o") - .arg(output_path) + .arg(&output_path) .output()?; if !result.status.success() { println!("cargo::error=Failed to compile shader {}; details follow.", @@ -56,13 +86,15 @@ fn process_shaders() -> std::io::Result<()> { } println!("cargo::rerun-if-changed={}", input_path.display()); + + asset_paths.insert(output_path.to_path_buf()); } Ok(()) } -fn process_textures() -> std::io::Result<()> { +fn process_textures(asset_paths: &mut BTreeSet<PathBuf>) -> Result<()> { for input in fs::read_dir("textures")? { let input_path = input?.path(); if !input_path.is_file() { @@ -76,14 +108,26 @@ fn process_textures() -> std::io::Result<()> { continue; } + if let Some(Some(extension)) = input_path.extension() + .map(|a| a.to_str()) + { + if extension != "png" { + continue; + } + } else { + continue; + } + println!("cargo::rerun-if-changed={}", input_path.display()); + + asset_paths.insert(input_path.to_path_buf()); } Ok(()) } -fn process_models() -> std::io::Result<()> { +fn process_models(asset_paths: &mut BTreeSet<PathBuf>) -> Result<()> { for input in fs::read_dir("models")? { let input_path = input?.path(); if !input_path.is_file() { @@ -97,9 +141,71 @@ fn process_models() -> std::io::Result<()> { continue; } + if let Some(Some(extension)) = input_path.extension() + .map(|a| a.to_str()) + { + if extension != "obj" { + continue; + } + } else { + continue; + } + println!("cargo::rerun-if-changed={}", input_path.display()); + + asset_paths.insert(input_path.to_path_buf()); } Ok(()) } + +fn generate_asset_module(asset_paths: BTreeSet<PathBuf>) -> Result<()> { + let out_dir = env::var_os("OUT_DIR") + .ok_or(Error("Don't have $OUT_DIR.".to_string()))?; + let output_path = Path::new(&out_dir).join("assets.rs"); + let mut file = File::create(output_path)?; + + let source_dir = env::current_dir()?; + + println!("cargo::warning=assets {:?}", asset_paths); + writeln!(file, "#[deny(unsafe_code)]")?; + writeln!(file, "pub fn asset(name: &str) -> crate::error::Result<&[u8]> {{"); + writeln!(file, " match name {{"); + + for asset_path in asset_paths { + let name = if asset_path.starts_with(&out_dir) { + asset_path.strip_prefix(&out_dir)? + } else { + &asset_path + }.to_str() + .ok_or(Error("Can't stringify path - weird filesystem?".to_string()))?; + + let include_path = if asset_path.is_absolute() { + asset_path.to_path_buf() + } else { + Path::new(&source_dir).join(&asset_path).to_path_buf() + }; + let mut include_path = include_path.to_path_buf(); + include_path = include_path.strip_prefix(&source_dir)?.to_path_buf(); + for _ in Path::new(&out_dir).strip_prefix(&source_dir)?.components() { + include_path = Path::new("../").join(include_path).to_path_buf(); + } + let include_path = include_path + .to_str() + .ok_or(Error("Can't stringify path - weird filesystem?" + .to_string()))?; + + writeln!(file, " \"{}\" => Ok(include_bytes!(\"{}\")),", + name.escape_default(), + include_path.escape_default()); + } + + writeln!(file, " _ => Err(crate::error::Error {{"); + writeln!(file, " message: format!(\"No such asset {{:?}}\", name)"); + writeln!(file, " }})"); + writeln!(file, " }}"); + writeln!(file, "}}"); + + Ok(()) +} diff --git a/src/files/obj.rs b/src/files/obj.rs index af2ce03..3ccc2ec 100644 --- a/src/files/obj.rs +++ b/src/files/obj.rs @@ -9,9 +9,7 @@ use std::io::Cursor; use tobj::{ load_obj_buf, LoadOptions }; -pub fn load_obj(permanent: &Permanent) -> Result<Model> { - let obj = include_bytes!("../../models/teapot.obj"); - +pub fn load_obj(obj: &[u8], permanent: &Permanent) -> Result<Model> { let load_options = LoadOptions { single_index: true, triangulate: true, diff --git a/src/files/png.rs b/src/files/png.rs index c164613..ce24292 100644 --- a/src/files/png.rs +++ b/src/files/png.rs @@ -7,9 +7,7 @@ use std::io::Cursor; use png::Decoder; -pub fn load_png(permanent: &Permanent) -> Result<(Texture, u32)> { - let png = include_bytes!("../../textures/forest_leaves_04_diff.png"); - +pub fn load_png(png: &[u8], permanent: &Permanent) -> Result<(Texture, u32)> { let decoder = Decoder::new(Cursor::new(png)); let mut reader = decoder.read_info()?; diff --git a/src/graphics/render.rs b/src/graphics/render.rs index 0b4a12a..7318574 100644 --- a/src/graphics/render.rs +++ b/src/graphics/render.rs @@ -1,5 +1,6 @@ #![deny(unsafe_code)] use crate::error::*; +use crate::assets::asset; use crate::graphics::{ Permanent, ForReinit, WindowDressing, Model, Texture }; use crate::shader_data::{ Vertex, UniformBlock, VertexPushBlock }; @@ -260,10 +261,8 @@ fn init_pipeline(device: &Device, render_pass: &vk::RenderPass) -> Result<(vk::PipelineLayout, vk::Pipeline)> { - let vertex_binary = include_bytes!( - concat!(env!("OUT_DIR"), "/shader.vert.spv")); - let fragment_binary = include_bytes!( - concat!(env!("OUT_DIR"), "/shader.frag.spv")); + let vertex_binary = asset("shaders/shader.vert.spv")?; + let fragment_binary = asset("shaders/shader.frag.spv")?; let vertex_module = Permanent::load_spirv_shader_module( device, vertex_binary)?; diff --git a/src/main.rs b/src/main.rs index b4f7970..607b0d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![deny(unsafe_code)] use crate::error::*; +use crate::assets::asset; use crate::graphics::{ Permanent, ForReinit, Render, Model, Texture }; use crate::graphics::scene::generate_scene_commands; use crate::graphics::window_dressing::{ @@ -22,6 +23,7 @@ use winit::event::WindowEvent; use winit::event_loop::{ ActiveEventLoop, EventLoop }; use winit::window::WindowId; +mod assets { include!(concat!(env!("OUT_DIR"), "/assets.rs")); } mod error; mod files; mod graphics; @@ -68,14 +70,17 @@ impl Surreality { let (permanent, for_reinit, enable_anisotropy, enable_swapchain) = Permanent::new(event_loop)?; - let (texture, mip_count) = load_png(&permanent)?; + let png = asset("textures/forest_leaves_04_diff.png")?; + let (texture, mip_count) = load_png(png, &permanent)?; if enable_swapchain.0 { let window_dressing = WindowDressing::new(&permanent, &for_reinit, enable_anisotropy, mip_count)?; let mut render = Render::new(&permanent, &for_reinit, &window_dressing, &texture)?; - let model = load_obj(&permanent)?; + + let obj = asset("models/teapot.obj")?; + let model = load_obj(obj, &permanent)?; render.set_model(model); *self.window_dressing.get_mut() = Some(window_dressing); |