use std::collections::HashMap;
use std::sync::Arc;
use crate::buf::{OpaqueValue, RasterBuf, ScalarField, SpriteSheet};
use crate::value::ScalarValue;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TileId {
pub z: u8,
pub x: u32,
pub y: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct CanvasInfo {
pub tile_w: u32,
pub tile_h: u32,
pub pad: u32,
}
impl CanvasInfo {
pub fn square(tile_size: u32, pad: u32) -> Self {
Self {
tile_w: tile_size,
tile_h: tile_size,
pad,
}
}
pub fn padded_w(&self) -> u32 {
self.tile_w + 2 * self.pad
}
pub fn padded_h(&self) -> u32 {
self.tile_h + 2 * self.pad
}
pub fn padded_dims(&self) -> (u32, u32) {
(self.padded_w(), self.padded_h())
}
}
#[derive(Debug, Clone)]
pub enum Asset {
Image(Arc<RasterBuf>),
Brush(OpaqueValue),
Features(OpaqueValue),
ScalarField(Arc<ScalarField>),
Sprite(Arc<SpriteSheet>),
Font(OpaqueValue),
Glyphs(OpaqueValue),
}
#[derive(Debug, thiserror::Error)]
pub enum AssetError {
#[error("asset not found: `{0}`")]
NotFound(String),
#[error("asset decode failed for `{src}`: {msg}")]
Decode { src: String, msg: String },
#[error("asset error: {0}")]
Other(String),
}
pub trait AssetLoader: Send + Sync {
fn load(&self, name: &str) -> Result<Asset, AssetError>;
fn hash(&self, _name: &str) -> u128 {
0
}
}
pub struct NoAssets;
impl AssetLoader for NoAssets {
fn load(&self, name: &str) -> Result<Asset, AssetError> {
Err(AssetError::NotFound(name.to_string()))
}
}
#[derive(Debug, Default, Clone)]
pub struct ParamValues {
pub values: HashMap<String, ScalarValue>,
}
impl ParamValues {
pub fn new() -> Self {
Self::default()
}
pub fn set(&mut self, name: impl Into<String>, value: ScalarValue) {
self.values.insert(name.into(), value);
}
pub fn get(&self, name: &str) -> Option<ScalarValue> {
self.values.get(name).copied()
}
}
#[derive(Clone, Copy)]
pub struct EvalCtx<'a> {
pub tile: TileId,
pub canvas: CanvasInfo,
pub assets: &'a dyn AssetLoader,
pub params: &'a ParamValues,
pub rng_seed: u64,
pub influence_pad: u32,
}
impl EvalCtx<'_> {
pub fn cull_rect(&self) -> Option<(f64, f64, f64, f64)> {
if self.influence_pad == u32::MAX {
return None;
}
let m = self.influence_pad as f64;
Some((
-m,
-m,
self.canvas.padded_w() as f64 + m,
self.canvas.padded_h() as f64 + m,
))
}
}
#[derive(Debug, thiserror::Error)]
pub enum EvalError {
#[error("input port `{0}` was not supplied")]
MissingInput(String),
#[error("input `{port}` has wrong kind: expected {expected:?}, got {got:?}")]
InputKindMismatch {
port: String,
expected: crate::port::PortKind,
got: crate::port::PortKind,
},
#[error(transparent)]
Asset(#[from] AssetError),
#[error("{0}")]
Other(String),
}