use facet::Facet;
use glam::{Mat4, Quat, Vec3, Vec4};
use crate::bounds::Aabb;
use crate::components::{GpuMaterial, GpuMesh, GpuRenderPipeline};
use crate::input::{InputEvent, InputEvents};
#[derive(Facet)]
pub struct DepthLoadOpProxy {
#[facet(skip_serializing_if = Option::is_none)]
pub clear: Option<f32>,
}
impl From<&wgpu::LoadOp<f32>> for DepthLoadOpProxy {
fn from(op: &wgpu::LoadOp<f32>) -> Self {
Self {
clear: match op {
wgpu::LoadOp::Clear(value) => Some(*value),
wgpu::LoadOp::Load => None,
_ => None,
},
}
}
}
impl From<DepthLoadOpProxy> for wgpu::LoadOp<f32> {
fn from(proxy: DepthLoadOpProxy) -> Self {
match proxy.clear {
Some(value) => Self::Clear(value),
None => Self::Load,
}
}
}
#[derive(Facet)]
pub struct StencilLoadOpProxy {
#[facet(skip_serializing_if = Option::is_none)]
pub clear: Option<u32>,
}
impl From<&wgpu::LoadOp<u32>> for StencilLoadOpProxy {
fn from(op: &wgpu::LoadOp<u32>) -> Self {
Self {
clear: match op {
wgpu::LoadOp::Clear(value) => Some(*value),
wgpu::LoadOp::Load => None,
_ => None,
},
}
}
}
impl From<StencilLoadOpProxy> for wgpu::LoadOp<u32> {
fn from(proxy: StencilLoadOpProxy) -> Self {
match proxy.clear {
Some(value) => Self::Clear(value),
None => Self::Load,
}
}
}
#[derive(Facet)]
pub struct ColorLoadOpProxy {
#[facet(skip_serializing_if = Option::is_none)]
pub clear: Option<[f64; 4]>,
}
impl From<&wgpu::LoadOp<wgpu::Color>> for ColorLoadOpProxy {
fn from(op: &wgpu::LoadOp<wgpu::Color>) -> Self {
Self {
clear: match op {
wgpu::LoadOp::Clear(color) => Some([color.r, color.g, color.b, color.a]),
wgpu::LoadOp::Load => None,
_ => None,
},
}
}
}
impl From<ColorLoadOpProxy> for wgpu::LoadOp<wgpu::Color> {
fn from(proxy: ColorLoadOpProxy) -> Self {
match proxy.clear {
Some([r, g, b, a]) => Self::Clear(wgpu::Color { r, g, b, a }),
None => Self::Load,
}
}
}
#[derive(Facet)]
pub struct GpuMeshProxy {
#[facet(default)]
pub count: u32,
#[facet(default)]
pub first: u32,
#[facet(default)]
pub base_vertex: u32,
#[facet(default)]
pub indexed: bool,
#[facet(default)]
pub morph_targets: u32,
#[facet(default)]
pub skinned: bool,
#[facet(default)]
pub aabb: AabbProxy,
}
#[derive(Facet, Default)]
pub struct AabbProxy {
#[facet(default)]
pub center: [f32; 3],
#[facet(default)]
pub half_extents: [f32; 3],
}
impl From<&Aabb> for AabbProxy {
fn from(aabb: &Aabb) -> Self {
Self {
center: aabb.center.to_array(),
half_extents: aabb.half_extents.to_array(),
}
}
}
impl From<&GpuMesh> for GpuMeshProxy {
fn from(mesh: &GpuMesh) -> Self {
Self {
count: mesh.count,
first: mesh.first,
base_vertex: mesh.base_vertex,
indexed: mesh.indexed,
morph_targets: mesh.morph_targets,
skinned: mesh.skinned,
aabb: AabbProxy::from(&mesh.aabb),
}
}
}
impl TryFrom<GpuMeshProxy> for GpuMesh {
type Error = String;
fn try_from(_proxy: GpuMeshProxy) -> Result<Self, Self::Error> {
Err("GpuMesh is read-only; allocate one with allocate_unlit_mesh".to_string())
}
}
#[derive(Facet)]
pub struct GpuMaterialProxy {
#[facet(default)]
pub bind_group: u32,
}
impl From<&GpuMaterial> for GpuMaterialProxy {
fn from(material: &GpuMaterial) -> Self {
Self {
bind_group: material.bind_group_id.index() as u32,
}
}
}
impl TryFrom<GpuMaterialProxy> for GpuMaterial {
type Error = String;
fn try_from(_proxy: GpuMaterialProxy) -> Result<Self, Self::Error> {
Err("GpuMaterial is read-only; allocate one with allocate_unlit_material".to_string())
}
}
#[derive(Facet)]
#[facet(transparent)]
pub struct GpuRenderPipelineProxy(#[facet(default)] pub String);
impl<Key> From<&GpuRenderPipeline<Key>> for GpuRenderPipelineProxy {
fn from(_pipeline: &GpuRenderPipeline<Key>) -> Self {
Self("unlit".to_string())
}
}
impl<Key> TryFrom<GpuRenderPipelineProxy> for GpuRenderPipeline<Key> {
type Error = String;
fn try_from(_proxy: GpuRenderPipelineProxy) -> Result<Self, Self::Error> {
Err("a pipeline is read-only; it is created with a mesh".to_string())
}
}
#[derive(Facet, Default)]
pub struct InputEventsProxy {
#[facet(default)]
pub events: Vec<InputEvent>,
#[facet(default)]
pub pointer: Option<[f32; 2]>,
#[facet(default)]
pub cursor: Option<[f32; 2]>,
#[facet(default)]
pub pointer_down: bool,
#[facet(default)]
pub buttons: u8,
#[facet(default)]
pub focused: bool,
#[facet(default)]
pub size_px: [u32; 2],
#[facet(default)]
pub scale_factor: f32,
#[facet(default)]
pub touches: Vec<(u64, [f32; 2])>,
}
impl From<&InputEvents> for InputEventsProxy {
fn from(events: &InputEvents) -> Self {
let state = events.with_state(|state| Self {
events: Vec::new(),
pointer: state.pointer,
cursor: state.cursor,
pointer_down: state.pointer_down,
buttons: state.buttons.bits(),
focused: state.focused,
size_px: [state.size_px.0, state.size_px.1],
scale_factor: state.scale_factor,
touches: state.touches.clone(),
});
Self {
events: events.with_batch(|batch| batch.to_vec()),
..state
}
}
}
impl TryFrom<InputEventsProxy> for InputEvents {
type Error = String;
fn try_from(_proxy: InputEventsProxy) -> Result<Self, Self::Error> {
Err("InputEvents is built by a world's own tick; feed it with send_input".to_string())
}
}
#[derive(Facet)]
#[facet(transparent)]
pub struct Vec3Proxy(pub [f32; 3]);
impl From<Vec3Proxy> for Vec3 {
fn from(proxy: Vec3Proxy) -> Self {
Vec3::from_array(proxy.0)
}
}
impl From<&Vec3> for Vec3Proxy {
fn from(value: &Vec3) -> Self {
Self(value.to_array())
}
}
#[derive(Facet)]
#[facet(transparent)]
pub struct Vec4Proxy(pub [f32; 4]);
impl From<Vec4Proxy> for Vec4 {
fn from(proxy: Vec4Proxy) -> Self {
Vec4::from_array(proxy.0)
}
}
impl From<&Vec4> for Vec4Proxy {
fn from(value: &Vec4) -> Self {
Self(value.to_array())
}
}
#[derive(Facet)]
#[facet(transparent)]
pub struct QuatProxy(pub [f32; 4]);
impl From<QuatProxy> for Quat {
fn from(proxy: QuatProxy) -> Self {
Quat::from_array(proxy.0)
}
}
impl From<&Quat> for QuatProxy {
fn from(value: &Quat) -> Self {
Self(value.to_array())
}
}
#[derive(Facet)]
#[facet(transparent)]
pub struct Mat4Proxy(pub [f32; 16]);
impl From<Mat4Proxy> for Mat4 {
fn from(proxy: Mat4Proxy) -> Self {
Mat4::from_cols_array(&proxy.0)
}
}
impl From<&Mat4> for Mat4Proxy {
fn from(value: &Mat4) -> Self {
Self(value.to_cols_array())
}
}
#[derive(Facet)]
#[facet(transparent)]
pub struct Mat4VecProxy(pub Vec<[f32; 16]>);
impl From<Mat4VecProxy> for Vec<Mat4> {
fn from(proxy: Mat4VecProxy) -> Self {
proxy.0.iter().map(Mat4::from_cols_array).collect()
}
}
impl From<&Vec<Mat4>> for Mat4VecProxy {
fn from(value: &Vec<Mat4>) -> Self {
Self(value.iter().map(Mat4::to_cols_array).collect())
}
}