#![allow(
clippy::type_complexity,
clippy::unwrap_or_default,
dead_code,
unused_variables,
unused_imports,
unused_mut,
unused_parens
)]
pub mod error;
pub mod kvasir;
mod material;
pub use material::builtins;
pub use material::{CompiledMaterial, MaterialCompiler, MaterialError, MaterialGraph, MaterialOp};
pub mod accessibility;
pub mod ai;
mod api;
pub mod draw;
pub mod filter;
pub mod passes;
pub mod pyramid;
pub mod renderer;
mod surtr_util;
pub mod types;
pub mod vertex;
pub mod heim;
pub use heim::SkylinePacker;
pub mod subsystems;
pub use subsystems::RendererConfig;
#[cfg(test)]
mod tests {
use super::*;
use super::heim::SkylinePacker;
#[test]
fn test_shelf_packer_basic() {
let mut packer = SkylinePacker::new(100, 100);
assert_eq!(packer.pack(10, 10), Some((0, 0)));
assert_eq!(packer.pack(20, 15), Some((10, 0)));
}
#[test]
fn test_shelf_packer_wrap() {
let mut packer = SkylinePacker::new(100, 100);
packer.pack(60, 10);
assert_eq!(packer.pack(50, 20), Some((0, 10)));
}
#[test]
fn test_parse_svg_animations() {
let svg = r##"
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="spinner">
<animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="2s" />
</g>
<circle id="pulse">
<animate attributeName="opacity" from="0.5" to="1.0" dur="0.5s" />
</circle>
<!-- Edge cases: xlink:href, ms suffix, values list -->
<rect>
<animate xlink:href="#myRect" attributeName="x" values="10; 20; 30" dur="500ms" />
</rect>
</svg>
"##;
let anims = draw::parse_svg_animations(svg.as_bytes());
assert_eq!(anims.len(), 3);
assert_eq!(anims[0].target_id, "spinner");
assert_eq!(anims[0].keyframe_values, vec![0.0, 360.0]);
assert_eq!(anims[1].target_id, "pulse");
assert_eq!(anims[1].attribute_name, "opacity");
assert_eq!(anims[1].duration, 0.5);
assert_eq!(anims[1].keyframe_values, vec![0.5, 1.0]);
assert_eq!(anims[2].target_id, "myRect");
assert_eq!(anims[2].attribute_name, "x");
assert_eq!(anims[2].duration, 0.5); assert_eq!(anims[2].keyframe_values, vec![10.0, 20.0, 30.0]);
}
#[test]
fn test_shelf_packer_full() {
let mut packer = SkylinePacker::new(10, 10);
assert_eq!(packer.pack(11, 5), None);
assert_eq!(packer.pack(5, 11), None);
}
}
#[cfg(target_arch = "wasm32")]
pub(crate) const WGSL_COMMON: &str = include_str!("shaders/common_wasm.wgsl");
#[cfg(not(target_arch = "wasm32"))]
pub(crate) const WGSL_COMMON: &str = include_str!("shaders/common.wgsl");
pub(crate) const WGSL_SHAPES: &str = include_str!("shaders/shapes.wgsl");
#[cfg(target_arch = "wasm32")]
pub(crate) const WGSL_MATERIAL_OPAQUE: &str = include_str!("shaders/material_opaque_wasm.wgsl");
#[cfg(not(target_arch = "wasm32"))]
pub(crate) const WGSL_MATERIAL_OPAQUE: &str = include_str!("shaders/material_opaque.wgsl");
pub(crate) const WGSL_MATERIAL_GLASS: &str = include_str!("shaders/material_glass.wgsl");
pub(crate) const WGSL_MATERIAL_PBR: &str = include_str!("shaders/material_pbr.wgsl");
pub(crate) const WGSL_MATERIAL_SHADOW: &str = include_str!("shaders/material_shadow.wgsl");
pub(crate) const WGSL_BIFROST: &str = include_str!("shaders/bifrost.wgsl");
#[cfg(target_arch = "wasm32")]
pub(crate) const WGSL_BLOOM: &str = include_str!("shaders/bloom_wasm.wgsl");
#[cfg(not(target_arch = "wasm32"))]
pub(crate) const WGSL_BLOOM: &str = include_str!("shaders/bloom.wgsl");
pub(crate) const WGSL_COLOR_BLIND: &str = include_str!("shaders/color_blind.wgsl");
pub(crate) const WGSL_TONEMAP: &str = include_str!("shaders/tonemap.wgsl");
pub(crate) const WGSL_PARTICLES: &str = include_str!("shaders/particles.wgsl");
pub mod color_blindness;
pub use color_blindness::ColorBlindMode;
pub use accesskit::{
ActionHandler, ActionRequest, ActivationHandler, DeactivationHandler, Node, NodeId, Role, Tree,
TreeId, TreeUpdate,
};
pub use accesskit_winit::Adapter as ShieldWallAdapter;
pub use cvkg_core::{ColorTheme, SceneUniforms};
pub use renderer::GpuRenderer;
pub use types::{SvgAnimation, SvgModel};
pub use vertex::{InstanceData, InstanceData3D, Vertex};
pub use cvkg_core::PassNode;
pub const MANIFEST: cvkg_core::FrameManifest = cvkg_core::FrameManifest {
phase_contributions: &[
cvkg_core::FramePhase::Render,
cvkg_core::FramePhase::Composite,
],
pass_nodes: &[
cvkg_core::PassNodeDescriptor {
id: "geometry",
label: "Geometry Pass (Opaque)",
inputs: &[],
outputs: &["scene_color", "scene_depth"],
after: &[],
constructor: || -> Box<dyn cvkg_core::PassNode> {
Box::new(crate::passes::geometry::GeometryNode::new())
},
},
cvkg_core::PassNodeDescriptor {
id: "shadow",
label: "Shadow Pass (Depth-Only)",
inputs: &[],
outputs: &["shadow_map"],
after: &[],
constructor: || -> Box<dyn cvkg_core::PassNode> {
Box::new(crate::passes::shadow::ShadowNode {
light: crate::passes::shadow::DirectionalLight::default(),
shadow_map: crate::kvasir::ResourceId(0),
mesh_instances: Vec::new(),
cascade_splits: [8.0, 25.0, 70.0, 200.0],
camera_view_proj: glam::Mat4::IDENTITY,
})
},
},
cvkg_core::PassNodeDescriptor {
id: "opaque3d",
label: "Opaque 3D Pass (PBR + Shadows)",
inputs: &["shadow_map"],
outputs: &["scene_color"],
after: &["shadow"],
constructor: || -> Box<dyn cvkg_core::PassNode> {
Box::new(crate::passes::opaque3d::Opaque3dNode {
mesh_instances: Vec::new(),
light: crate::passes::shadow::DirectionalLight::default(),
shadow_map: crate::kvasir::ResourceId(0),
})
},
},
cvkg_core::PassNodeDescriptor {
id: "ui",
label: "UI Compositing",
inputs: &["scene_color", "scene_depth"],
outputs: &["ui_output"],
after: &["geometry"],
constructor: || -> Box<dyn cvkg_core::PassNode> {
Box::new(crate::passes::ui::UINode::new())
},
},
cvkg_core::PassNodeDescriptor {
id: "bloom_extract",
label: "Bloom Extract",
inputs: &["ui_output"],
outputs: &["bloom_src"],
after: &["ui"],
constructor: || -> Box<dyn cvkg_core::PassNode> {
Box::new(crate::passes::bloom::BloomExtractNode::new())
},
},
cvkg_core::PassNodeDescriptor {
id: "volumetric",
label: "Volumetric Raymarching",
inputs: &["scene_color"],
outputs: &["scene_color"],
after: &["geometry"],
constructor: || -> Box<dyn cvkg_core::PassNode> {
Box::new(crate::passes::volumetric::VolumetricNode::new())
},
},
cvkg_core::PassNodeDescriptor {
id: "accessibility",
label: "Accessibility Transform",
inputs: &["scene_color"],
outputs: &["scene_color"],
after: &["bloom_extract"],
constructor: || -> Box<dyn cvkg_core::PassNode> {
Box::new(crate::passes::accessibility::AccessibilityNode::new())
},
},
],
time_budget_requests: &[
cvkg_core::TimeBudgetRequest {
phase: cvkg_core::FramePhase::Render,
time_slice_us: 8000,
skippable: false,
name: "render_gpu",
},
cvkg_core::TimeBudgetRequest {
phase: cvkg_core::FramePhase::Composite,
time_slice_us: 4000,
skippable: false,
name: "composite_gpu",
},
],
};