concinnity_world/
source_args.rs1use concinnity_core::platform::Platform;
10
11pub(crate) fn stage_source_path(args: &serde_json::Value, platform: Platform) -> Option<String> {
15 if let Some(obj) = args.get("sources").and_then(|v| v.as_object())
16 && let Some(src) = obj.get(platform.key()).and_then(|v| v.as_str())
17 {
18 return Some(src.to_string());
19 }
20 let src = args
21 .get("source")
22 .and_then(|v| v.as_str())
23 .filter(|s| !s.is_empty())?;
24 let ext = std::path::Path::new(src)
25 .extension()
26 .and_then(|e| e.to_str())
27 .unwrap_or("");
28 if platform.accepts_ext(ext) {
29 Some(src.to_string())
30 } else {
31 None
32 }
33}
34
35pub fn resolve_source_from_args(args: &serde_json::Value) -> Option<String> {
38 stage_source_path(args, Platform::current())
39}
40
41pub(crate) fn sdf_volume_source_path(
45 args: &serde_json::Value,
46 platform: Platform,
47) -> Option<String> {
48 if let Some(obj) = args.get("fragment_shaders").and_then(|v| v.as_object())
49 && let Some(src) = obj
50 .get(platform.key())
51 .and_then(|v| v.as_str())
52 .filter(|s| !s.is_empty())
53 {
54 return Some(src.to_string());
55 }
56 let src = args
57 .get("fragment_shader")
58 .and_then(|v| v.as_str())
59 .filter(|s| !s.is_empty())?;
60 let ext = std::path::Path::new(src)
61 .extension()
62 .and_then(|e| e.to_str())
63 .unwrap_or("");
64 if platform.accepts_ext(ext) {
65 Some(src.to_string())
66 } else {
67 None
68 }
69}
70
71pub fn current_platform_source_arg(args: &serde_json::Value) -> Option<String> {
74 sdf_volume_source_path(args, Platform::current())
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use serde_json::json;
81
82 #[test]
83 fn shader_source_path_selects_per_platform() {
84 let args = json!({"sources": {"metal": "a.metal", "hlsl": "a.hlsl", "glsl": "a.glsl"}});
86 assert_eq!(
87 stage_source_path(&args, Platform::Metal),
88 Some("a.metal".to_string())
89 );
90 assert_eq!(
91 stage_source_path(&args, Platform::Hlsl),
92 Some("a.hlsl".to_string())
93 );
94 assert_eq!(
95 stage_source_path(&args, Platform::Glsl),
96 Some("a.glsl".to_string())
97 );
98
99 let metal_only = json!({"source": "s.metal"});
102 assert_eq!(
103 stage_source_path(&metal_only, Platform::Metal),
104 Some("s.metal".to_string())
105 );
106 assert_eq!(stage_source_path(&metal_only, Platform::Hlsl), None);
107
108 assert_eq!(
110 stage_source_path(&json!({"kind": "vertex"}), Platform::Metal),
111 None
112 );
113 }
114
115 #[test]
116 fn sdf_source_path_prefers_map_over_single() {
117 let args = json!({
118 "fragment_shader": "shaders/single.metal",
119 "fragment_shaders": { "metal": "shaders/from_map.metal" },
120 });
121 assert_eq!(
122 sdf_volume_source_path(&args, Platform::Metal).as_deref(),
123 Some("shaders/from_map.metal")
124 );
125 }
126}