pub use concinnity_core::ecs::ResourceKind;
fn norm_type(t: &str) -> String {
t.to_lowercase().replace('_', "")
}
fn file_is_mesh(args: &serde_json::Value) -> bool {
args.get("kind")
.and_then(|k| k.as_str())
.and_then(crate::components::FileKind::from_ext)
.map(|fk| fk.is_mesh())
.unwrap_or(false)
}
pub fn mesh_source_block(asset_type: &str, args: &serde_json::Value) -> Option<u8> {
match norm_type(asset_type).as_str() {
"mesh" => Some(0),
"proceduralmesh" => Some(1),
"voxelchunk" | "chunk" => Some(2),
"file" => file_is_mesh(args).then_some(3),
_ => None,
}
}
pub fn is_mesh_source(asset_type: &str, args: &serde_json::Value) -> bool {
mesh_source_block(asset_type, args).is_some()
}
pub fn asset_resource_kind(asset_type: &str) -> Option<ResourceKind> {
let ty = crate::registry::RegisteredType::parse(asset_type)?;
if ty == crate::registry::RegisteredType::Mesh {
return None;
}
ty.resource_kind()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::registry::RegisteredType;
#[test]
fn resource_types_report_a_kind_and_others_do_not() {
for (name, kind) in [
("Texture", ResourceKind::Texture),
("CubemapTexture", ResourceKind::CubemapTexture),
("EnvironmentMap", ResourceKind::EnvironmentMap),
("ColorLut", ResourceKind::ColorLut),
("Font", ResourceKind::Font),
("Material", ResourceKind::Material),
("SkinnedMesh", ResourceKind::SkinnedMesh),
("AudioClip", ResourceKind::AudioClip),
] {
let ty = RegisteredType::parse(name).expect("a declarable type");
assert_eq!(ty.resource_kind(), Some(kind), "{name}");
assert_eq!(asset_resource_kind(name), Some(kind), "{name}");
assert_eq!(ty.discriminant(), None, "{name} is not stored in a column");
}
let prop = RegisteredType::parse("Prop").expect("Prop is registered");
assert_eq!(prop.resource_kind(), None);
assert_eq!(asset_resource_kind("Prop"), None);
assert!(prop.discriminant().is_some());
}
#[test]
fn mesh_is_a_resource_but_not_classified_by_name() {
let mesh = RegisteredType::parse("Mesh").expect("Mesh is registered");
assert_eq!(mesh.resource_kind(), Some(ResourceKind::Mesh));
assert_eq!(asset_resource_kind("Mesh"), None);
assert!(is_mesh_source("Mesh", &serde_json::json!({})));
}
#[test]
fn only_material_is_a_data_resource() {
for &ty in RegisteredType::all() {
let expected = ty.as_str() == "Material";
assert_eq!(ty.is_data(), expected, "{}", ty.as_str());
}
}
#[test]
fn normalized_args_fills_defaults_and_rejects_bad_types() {
let env = RegisteredType::parse("EnvironmentMap").expect("registered");
let out = env
.normalized_args(&serde_json::json!({"source": "studio.hdr"}))
.expect("a source-only EnvironmentMap round-trips");
assert_eq!(out["source"], "studio.hdr");
assert_eq!(out["prefilter_face_size"], 512, "defaults are materialized");
RegisteredType::parse("Font")
.expect("registered")
.normalized_args(&serde_json::json!({"size_px": -5}))
.expect_err("a negative u32 must be rejected");
}
#[test]
fn mesh_source_blocks_follow_the_fixed_order() {
let none = serde_json::json!({});
assert_eq!(mesh_source_block("Mesh", &none), Some(0));
assert_eq!(mesh_source_block("ProceduralMesh", &none), Some(1));
assert_eq!(mesh_source_block("VoxelChunk", &none), Some(2));
assert_eq!(
mesh_source_block("File", &serde_json::json!({"kind": "obj"})),
Some(3)
);
assert_eq!(
mesh_source_block("File", &serde_json::json!({"kind": "png"})),
None
);
assert_eq!(mesh_source_block("PointLight", &none), None);
}
}