bevy_gltf/loader/extensions/
mod.rs1mod khr_materials_anisotropy;
4mod khr_materials_clearcoat;
5mod khr_materials_specular;
6
7use alloc::sync::Arc;
8use async_lock::RwLock;
9
10use bevy_asset::{Handle, LoadContext};
11use bevy_ecs::{
12 entity::Entity,
13 resource::Resource,
14 world::{EntityWorldMut, World},
15};
16use bevy_pbr::StandardMaterial;
17use gltf::Node;
18
19#[cfg(feature = "bevy_animation")]
20use {
21 bevy_animation::AnimationClip,
22 bevy_platform::collections::{HashMap, HashSet},
23};
24
25use crate::GltfMesh;
26
27pub(crate) use self::{
28 khr_materials_anisotropy::AnisotropyExtension, khr_materials_clearcoat::ClearcoatExtension,
29 khr_materials_specular::SpecularExtension,
30};
31
32#[derive(Resource, Default)]
35pub struct GltfExtensionHandlers(pub Arc<RwLock<Vec<Box<dyn GltfExtensionHandler>>>>);
36
37pub trait GltfExtensionHandler: Send + Sync {
64 fn dyn_clone(&self) -> Box<dyn GltfExtensionHandler>;
66
67 #[expect(
70 unused,
71 reason = "default trait implementations do not use the arguments because they are no-ops"
72 )]
73 fn on_root(&mut self, gltf: &gltf::Gltf) {}
74
75 #[cfg(feature = "bevy_animation")]
76 #[expect(
77 unused,
78 reason = "default trait implementations do not use the arguments because they are no-ops"
79 )]
80 fn on_animation(&mut self, gltf_animation: &gltf::Animation, handle: Handle<AnimationClip>) {}
82
83 #[cfg(feature = "bevy_animation")]
84 #[expect(
85 unused,
86 reason = "default trait implementations do not use the arguments because they are no-ops"
87 )]
88 fn on_animations_collected(
93 &mut self,
94 load_context: &mut LoadContext<'_>,
95 animations: &[Handle<AnimationClip>],
96 named_animations: &HashMap<Box<str>, Handle<AnimationClip>>,
97 animation_roots: &HashSet<usize>,
98 ) {
99 }
100
101 #[expect(
103 unused,
104 reason = "default trait implementations do not use the arguments because they are no-ops"
105 )]
106 fn on_texture(&mut self, gltf_texture: &gltf::Texture, texture: Handle<bevy_image::Image>) {}
107
108 #[expect(
110 unused,
111 reason = "default trait implementations do not use the arguments because they are no-ops"
112 )]
113 fn on_material(
114 &mut self,
115 load_context: &mut LoadContext<'_>,
116 gltf_material: &gltf::Material,
117 material: Handle<StandardMaterial>,
118 ) {
119 }
120
121 #[expect(
123 unused,
124 reason = "default trait implementations do not use the arguments because they are no-ops"
125 )]
126 fn on_gltf_mesh(
127 &mut self,
128 load_context: &mut LoadContext<'_>,
129 gltf_mesh: &gltf::Mesh,
130 mesh: Handle<GltfMesh>,
131 ) {
132 }
133
134 #[expect(
138 unused,
139 reason = "default trait implementations do not use the arguments because they are no-ops"
140 )]
141 fn on_spawn_mesh_and_material(
142 &mut self,
143 load_context: &mut LoadContext<'_>,
144 primitive: &gltf::Primitive,
145 mesh: &gltf::Mesh,
146 material: &gltf::Material,
147 entity: &mut EntityWorldMut,
148 ) {
149 }
150
151 #[expect(
153 unused,
154 reason = "default trait implementations do not use the arguments because they are no-ops"
155 )]
156 fn on_scene_completed(
157 &mut self,
158 load_context: &mut LoadContext<'_>,
159 scene: &gltf::Scene,
160 world_root_id: Entity,
161 scene_world: &mut World,
162 ) {
163 }
164
165 #[expect(
167 unused,
168 reason = "default trait implementations do not use the arguments because they are no-ops"
169 )]
170 fn on_gltf_node(
171 &mut self,
172 load_context: &mut LoadContext<'_>,
173 gltf_node: &Node,
174 entity: &mut EntityWorldMut,
175 ) {
176 }
177
178 #[expect(
182 unused,
183 reason = "default trait implementations do not use the arguments because they are no-ops"
184 )]
185 fn on_spawn_light_directional(
186 &mut self,
187 load_context: &mut LoadContext<'_>,
188 gltf_node: &Node,
189 entity: &mut EntityWorldMut,
190 ) {
191 }
192 #[expect(
196 unused,
197 reason = "default trait implementations do not use the arguments because they are no-ops"
198 )]
199 fn on_spawn_light_point(
200 &mut self,
201 load_context: &mut LoadContext<'_>,
202 gltf_node: &Node,
203 entity: &mut EntityWorldMut,
204 ) {
205 }
206 #[expect(
210 unused,
211 reason = "default trait implementations do not use the arguments because they are no-ops"
212 )]
213 fn on_spawn_light_spot(
214 &mut self,
215 load_context: &mut LoadContext<'_>,
216 gltf_node: &Node,
217 entity: &mut EntityWorldMut,
218 ) {
219 }
220}
221
222impl Clone for Box<dyn GltfExtensionHandler> {
223 fn clone(&self) -> Self {
224 self.dyn_clone()
225 }
226}