Skip to content

Commit

Permalink
Merge pull request #395 from CorneliusCornbread/main
Browse files Browse the repository at this point in the history
Arbitrary Extension API
  • Loading branch information
alteous authored Nov 13, 2023
2 parents 875faf4 + d11049a commit 14b34f2
Show file tree
Hide file tree
Showing 25 changed files with 502 additions and 16 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ byteorder = "1.3"
gltf-json = { path = "gltf-json", version = "1.3.0" }
lazy_static = "1"
urlencoding = { optional = true, version = "2.1" }
serde_json = { features = ["raw_value"], version = "1.0" }

[dependencies.image]
default-features = false
Expand All @@ -37,6 +38,7 @@ version = "0.24"

[features]
default = ["import", "utils", "names"]
extensions = ["gltf-json/extensions"]
extras = ["gltf-json/extras"]
names = ["gltf-json/names"]
utils = []
Expand Down
1 change: 1 addition & 0 deletions gltf-json/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ serde_json = { features = ["raw_value"], version = "1.0" }
[features]
default = []
names = []
extensions = []
extras = []
KHR_lights_punctual = []
KHR_materials_ior = []
Expand Down
8 changes: 7 additions & 1 deletion gltf-json/src/extensions/accessor.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// Contains data structures for sparse storage.
pub mod sparse {
Expand All @@ -21,4 +23,8 @@ pub mod sparse {

/// A typed view into a buffer view.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Accessor {}
pub struct Accessor {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
8 changes: 7 additions & 1 deletion gltf-json/src/extensions/animation.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// A keyframe animation.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct Animation {}
pub struct Animation {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// Targets an animation's sampler at a node's property.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
Expand Down
14 changes: 12 additions & 2 deletions gltf-json/src/extensions/buffer.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// A buffer points to binary data representing geometry, animations, or skins.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Buffer {}
pub struct Buffer {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// A view into a buffer generally representing a subset of the buffer.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct View {}
pub struct View {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
20 changes: 17 additions & 3 deletions gltf-json/src/extensions/camera.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// A camera's projection.
///
/// A node can reference a camera to apply a transform to place the camera in the
/// scene.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Camera {}
pub struct Camera {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// Values for an orthographic camera.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Orthographic {}
pub struct Orthographic {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// Values for a perspective camera.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Perspective {}
pub struct Perspective {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
8 changes: 7 additions & 1 deletion gltf-json/src/extensions/image.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// Image data used to create a texture.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Image {}
pub struct Image {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
28 changes: 25 additions & 3 deletions gltf-json/src/extensions/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
use crate::{material::StrengthFactor, texture, validation::Validate, Extras};
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// The material appearance of a primitive.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
Expand Down Expand Up @@ -61,12 +63,20 @@ pub struct Material {
skip_serializing_if = "Option::is_none"
)]
pub emissive_strength: Option<EmissiveStrength>,

#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// A set of parameter values that are used to define the metallic-roughness
/// material model from Physically-Based Rendering (PBR) methodology.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct PbrMetallicRoughness {}
pub struct PbrMetallicRoughness {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// A set of parameter values that are used to define the specular-glossiness
/// material model from Physically-Based Rendering (PBR) methodology.
Expand Down Expand Up @@ -114,6 +124,10 @@ pub struct PbrSpecularGlossiness {
#[serde(skip_serializing_if = "Option::is_none")]
pub specular_glossiness_texture: Option<texture::Info>,

#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,

/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
Expand All @@ -122,11 +136,19 @@ pub struct PbrSpecularGlossiness {

/// Defines the normal texture of a material.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct NormalTexture {}
pub struct NormalTexture {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// Defines the occlusion texture of a material.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct OcclusionTexture {}
pub struct OcclusionTexture {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// The diffuse factor of a material.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
Expand Down
11 changes: 10 additions & 1 deletion gltf-json/src/extensions/mesh.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// A set of primitives to be rendered.
///
/// A node can contain one or more meshes and its transform places the meshes in
/// the scene.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Mesh {}
pub struct Mesh {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// Geometry to be rendered with the given material.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
Expand All @@ -18,6 +24,9 @@ pub struct Primitive {
skip_serializing_if = "Option::is_none"
)]
pub khr_materials_variants: Option<KhrMaterialsVariants>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

#[cfg(feature = "KHR_materials_variants")]
Expand Down
6 changes: 6 additions & 0 deletions gltf-json/src/extensions/root.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// The root object of a glTF 2.0 asset.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
Expand All @@ -19,6 +21,10 @@ pub struct Root {
skip_serializing_if = "Option::is_none"
)]
pub khr_materials_variants: Option<KhrMaterialsVariants>,

#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

#[cfg(feature = "KHR_lights_punctual")]
Expand Down
12 changes: 11 additions & 1 deletion gltf-json/src/extensions/scene.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// A node in the node hierarchy. When the node contains `skin`, all
/// `mesh.primitives` must contain `JOINTS_0` and `WEIGHTS_0` attributes.
Expand All @@ -20,6 +22,10 @@ pub struct Node {
skip_serializing_if = "Option::is_none"
)]
pub khr_lights_punctual: Option<khr_lights_punctual::KhrLightsPunctual>,

#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

#[cfg(feature = "KHR_lights_punctual")]
Expand Down Expand Up @@ -224,4 +230,8 @@ pub mod khr_materials_variants {

/// The root `Node`s of a scene.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Scene {}
pub struct Scene {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
8 changes: 7 additions & 1 deletion gltf-json/src/extensions/skin.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// Joints and matrices defining a skin.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Skin {}
pub struct Skin {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
17 changes: 15 additions & 2 deletions gltf-json/src/extensions/texture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@
use crate::{extras::Extras, validation::Validate};
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// Texture sampler properties for filtering and wrapping modes.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Sampler {}
pub struct Sampler {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// A texture and its sampler.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Texture {}
pub struct Texture {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
/// Reference to a `Texture`.
Expand All @@ -21,6 +31,9 @@ pub struct Info {
skip_serializing_if = "Option::is_none"
)]
pub texture_transform: Option<TextureTransform>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

/// Many techniques can be used to optimize resource usage for a 3d scene.
Expand Down
13 changes: 13 additions & 0 deletions gltf-json/src/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,19 @@ impl<K: ToString + Validate, V: Validate> Validate for BTreeMap<K, V> {
}
}

impl Validate for serde_json::Map<String, serde_json::Value> {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
for (key, value) in self.iter() {
key.validate(root, || path().key(&key.to_string()), report);
value.validate(root, || path().key(&key.to_string()), report);
}
}
}

impl<T: Validate> Validate for Option<T> {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
Expand Down
18 changes: 18 additions & 0 deletions src/accessor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ use crate::{buffer, Document};

pub use json::accessor::ComponentType as DataType;
pub use json::accessor::Type as Dimensions;
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};

/// Utility functions.
#[cfg(feature = "utils")]
Expand Down Expand Up @@ -138,6 +140,22 @@ impl<'a> Accessor<'a> {
self.json.component_type.unwrap().0
}

/// Returns the extension values map
#[cfg(feature = "extensions")]
#[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
pub fn extensions(&self) -> Option<&Map<String, Value>> {
let ext = self.json.extensions.as_ref()?;
Some(&ext.others)
}

/// Return a value for a given extension name
#[cfg(feature = "extensions")]
#[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
let ext = self.json.extensions.as_ref()?;
ext.others.get(ext_name)
}

/// Optional application specific data.
pub fn extras(&self) -> &'a json::Extras {
&self.json.extras
Expand Down
Loading

0 comments on commit 14b34f2

Please sign in to comment.