1use std::error;
2use std::fmt;
3
4use super::{
5 AnimationError, AssetError, BuildError, Error, ImportError, InstantiateError, LookupError,
6 NotPreparedReason, PrepareError, RenderError,
7};
8
9impl fmt::Display for Error {
10 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
11 match self {
12 Self::Build(error) => error.fmt(formatter),
13 Self::Asset(error) => error.fmt(formatter),
14 Self::Import(error) => error.fmt(formatter),
15 Self::Instantiate(error) => error.fmt(formatter),
16 Self::Prepare(error) => error.fmt(formatter),
17 Self::Render(error) => error.fmt(formatter),
18 Self::Lookup(error) => error.fmt(formatter),
19 Self::Animation(error) => error.fmt(formatter),
20 }
21 }
22}
23
24impl fmt::Display for BuildError {
25 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
26 match self {
27 Self::InvalidTargetSize { width, height } => {
28 write!(formatter, "invalid render target size {width}x{height}")
29 }
30 Self::AsyncSurfaceRequired { backend } => {
31 write!(
32 formatter,
33 "attached surface initialization for {backend:?} requires async construction"
34 )
35 }
36 Self::CreateSurface { backend } => {
37 write!(formatter, "failed to create GPU surface for {backend:?}")
38 }
39 Self::NoAdapter { backend } => {
40 write!(formatter, "no compatible GPU adapter found for {backend:?}")
41 }
42 Self::RequestDevice { backend } => {
43 write!(formatter, "failed to request GPU device for {backend:?}")
44 }
45 Self::SurfaceUnsupported { backend } => {
46 write!(
47 formatter,
48 "no compatible surface configuration found for {backend:?}"
49 )
50 }
51 Self::UnsupportedBackend { backend } => {
52 write!(
53 formatter,
54 "backend {backend:?} is not supported on this target"
55 )
56 }
57 }
58 }
59}
60
61impl fmt::Display for AssetError {
62 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
63 match self {
64 Self::NotFound { path } => write!(formatter, "asset was not found: {path}"),
65 Self::Io { path, reason } => {
66 write!(formatter, "failed to read asset {path}: {reason}")
67 }
68 Self::Parse { path, reason } => {
69 write!(formatter, "failed to parse asset {path}: {reason}")
70 }
71 Self::UnsupportedRequiredExtension { path, extension } => write!(
72 formatter,
73 "asset {path} requires unsupported extension {extension}"
74 ),
75 Self::UnsupportedOptionalExtensionUsed {
76 path,
77 extension,
78 help,
79 } => write!(
80 formatter,
81 "asset {path} uses unsupported optional extension {extension}: {help}"
82 ),
83 Self::MissingTexture {
84 path,
85 material_slot,
86 texture_index,
87 help,
88 } => write!(
89 formatter,
90 "asset {path} references missing texture index {texture_index} in material slot {material_slot}: {help}"
91 ),
92 Self::UnsupportedTextureFormat { path, help } => {
93 write!(
94 formatter,
95 "texture {path} uses an unsupported format: {help}"
96 )
97 }
98 Self::Cancelled { path, help } => {
99 write!(formatter, "asset load for {path} was cancelled: {help}")
100 }
101 Self::UnsupportedEnvironmentFormat { path, help } => {
102 write!(
103 formatter,
104 "environment {path} uses an unsupported format: {help}"
105 )
106 }
107 Self::ReloadRequiresRetain { path, help } => {
108 write!(formatter, "asset {path} cannot be reloaded: {help}")
109 }
110 Self::GeometryHandleNotFound { geometry } => {
111 write!(
112 formatter,
113 "geometry handle {geometry:?} was not found in Assets"
114 )
115 }
116 Self::MaterialHandleNotFound { material } => {
117 write!(
118 formatter,
119 "material handle {material:?} was not found in Assets"
120 )
121 }
122 Self::TextureHandleNotFound { texture } => {
123 write!(
124 formatter,
125 "texture handle {texture:?} was not found in Assets"
126 )
127 }
128 Self::EnvironmentHandleNotFound { environment } => {
129 write!(
130 formatter,
131 "environment handle {environment:?} was not found in Assets"
132 )
133 }
134 }
135 }
136}
137
138impl fmt::Display for ImportError {
139 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
140 match self {
141 Self::Asset(error) => error.fmt(formatter),
142 Self::Instantiate(error) => error.fmt(formatter),
143 }
144 }
145}
146
147impl From<AssetError> for ImportError {
148 fn from(error: AssetError) -> Self {
149 Self::Asset(error)
150 }
151}
152
153impl From<InstantiateError> for ImportError {
154 fn from(error: InstantiateError) -> Self {
155 Self::Instantiate(error)
156 }
157}
158
159impl fmt::Display for InstantiateError {
160 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
161 match self {
162 Self::InvalidChildIndex { parent, child } => write!(
163 formatter,
164 "glTF node {parent} references invalid child node index {child}"
165 ),
166 Self::InvalidSkinIndex { node, skin } => {
167 write!(
168 formatter,
169 "glTF node {node} references invalid skin index {skin}"
170 )
171 }
172 Self::InvalidSkinJointIndex { skin, joint } => write!(
173 formatter,
174 "glTF skin {skin} references invalid joint node index {joint}"
175 ),
176 Self::InvalidAnchorExtras { node, reason } => {
177 write!(
178 formatter,
179 "glTF node {node} has invalid anchor extras: {reason}"
180 )
181 }
182 Self::UnsupportedCoordinateSystem {
183 coordinate_system,
184 reason,
185 } => write!(
186 formatter,
187 "source coordinate system {coordinate_system:?} is not supported for this import: {reason}"
188 ),
189 }
190 }
191}
192
193impl fmt::Display for PrepareError {
194 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
195 match self {
196 Self::InvalidTargetSize { width, height } => {
197 write!(formatter, "invalid render target size {width}x{height}")
198 }
199 Self::AssetsRequired { node } => {
200 write!(
201 formatter,
202 "node {node:?} references asset handles; call prepare_with_assets"
203 )
204 }
205 Self::GeometryNotFound { node, geometry } => {
206 write!(
207 formatter,
208 "node {node:?} references missing geometry handle {geometry:?}"
209 )
210 }
211 Self::MaterialNotFound { node, material } => {
212 write!(
213 formatter,
214 "node {node:?} references missing material handle {material:?}"
215 )
216 }
217 Self::TextureNotFound {
218 node,
219 material,
220 texture,
221 slot,
222 } => {
223 write!(
224 formatter,
225 "node {node:?} material {material:?} references missing texture handle {texture:?} in slot {slot}"
226 )
227 }
228 Self::EnvironmentAssetsRequired { environment } => {
229 write!(
230 formatter,
231 "environment handle {environment:?} requires prepare_with_assets"
232 )
233 }
234 Self::EnvironmentNotFound { environment } => {
235 write!(
236 formatter,
237 "active environment handle {environment:?} was not found in assets"
238 )
239 }
240 Self::UnsupportedGeometryTopology { node, topology } => {
241 write!(
242 formatter,
243 "node {node:?} uses unsupported geometry topology {topology:?}"
244 )
245 }
246 Self::UnsupportedMaterialKind { node, kind } => {
247 write!(
248 formatter,
249 "node {node:?} uses unsupported material kind {kind:?}"
250 )
251 }
252 Self::UnsupportedAlphaMode { node, alpha_mode } => {
253 write!(
254 formatter,
255 "node {node:?} uses unsupported alpha mode {alpha_mode:?}"
256 )
257 }
258 Self::UnsupportedModelNode { node } => {
259 write!(
260 formatter,
261 "node {node:?} is a model node; model preparation is not implemented"
262 )
263 }
264 Self::MultipleShadowedDirectionalLights { first, second } => write!(
265 formatter,
266 "only one shadowed directional light is supported; nodes {first:?} and {second:?} both cast shadows"
267 ),
268 Self::InvalidSkinGeometry { node, reason } => {
269 write!(
270 formatter,
271 "node {node:?} has invalid skin geometry: {reason}"
272 )
273 }
274 Self::BackendCapabilityMismatch {
275 feature,
276 backend,
277 help,
278 } => {
279 write!(
280 formatter,
281 "backend {backend:?} cannot provide required feature {feature}: {help}"
282 )
283 }
284 Self::GpuResourceUpload { backend, reason } => {
285 write!(
286 formatter,
287 "backend {backend:?} failed during explicit GPU resource upload: {reason}"
288 )
289 }
290 }
291 }
292}
293
294impl fmt::Display for RenderError {
295 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
296 match self {
297 Self::NotPrepared { reason } => write!(formatter, "renderer is not prepared: {reason}"),
298 Self::NoActiveCamera => write!(formatter, "scene has no active camera"),
299 Self::CameraNotFound(_) => write!(formatter, "camera key does not exist in the scene"),
300 Self::InvalidSurfaceSize { width, height } => {
301 write!(formatter, "invalid surface size {width}x{height}")
302 }
303 Self::SurfaceLost { recoverable } => {
304 write!(
305 formatter,
306 "render surface was lost; recoverable={recoverable}"
307 )
308 }
309 Self::ContextLost { recoverable } => {
310 write!(
311 formatter,
312 "render context was lost; recoverable={recoverable}"
313 )
314 }
315 Self::GpuDeviceLost { recoverable } => {
316 write!(formatter, "GPU device was lost; recoverable={recoverable}")
317 }
318 Self::GpuResourcesNotPrepared { backend } => {
319 write!(formatter, "GPU resources for {backend:?} were not prepared")
320 }
321 Self::GpuReadback { backend } => {
322 write!(formatter, "failed to read rendered output for {backend:?}")
323 }
324 }
325 }
326}
327
328impl fmt::Display for NotPreparedReason {
329 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
330 match self {
331 Self::NeverPrepared => write!(formatter, "prepare has not been called"),
332 Self::DifferentScene => write!(formatter, "prepare was called for a different scene"),
333 Self::SceneChanged {
334 prepared_revision,
335 current_revision,
336 change,
337 }
338 | Self::EnvironmentChanged {
339 prepared_revision,
340 current_revision,
341 change,
342 } => write!(
343 formatter,
344 "prepared state changed after prepare ({prepared_revision} -> {current_revision}, {change:?})"
345 ),
346 Self::TargetChanged {
347 prepared_revision,
348 current_revision,
349 change,
350 } => write!(
351 formatter,
352 "render target changed after prepare ({prepared_revision} -> {current_revision}, {change:?})"
353 ),
354 Self::RendererChanged {
355 prepared_revision,
356 current_revision,
357 change,
358 } => write!(
359 formatter,
360 "renderer setting changed after prepare ({prepared_revision} -> {current_revision}, {change:?}); call prepare again"
361 ),
362 }
363 }
364}
365
366impl fmt::Display for LookupError {
367 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
368 match self {
369 Self::NodeNotFound(_) => write!(formatter, "node key does not exist in the scene"),
370 Self::NodeNameNotFound { name } => {
371 write!(formatter, "imported scene has no node named '{name}'")
372 }
373 Self::AmbiguousNodeName { name, matches } => write!(
374 formatter,
375 "imported scene node name '{name}' is ambiguous across {} nodes",
376 matches.len()
377 ),
378 Self::AnchorNotFound { name } => {
379 write!(formatter, "imported scene has no anchor named '{name}'")
380 }
381 Self::AmbiguousAnchorName { name, hosts } => write!(
382 formatter,
383 "imported scene anchor name '{name}' is ambiguous across {} host nodes",
384 hosts.len()
385 ),
386 Self::ConnectorNotFound { name } => {
387 write!(formatter, "imported scene has no connector named '{name}'")
388 }
389 Self::AmbiguousConnectorName { name, hosts } => write!(
390 formatter,
391 "imported scene connector name '{name}' is ambiguous across {} host nodes",
392 hosts.len()
393 ),
394 Self::ClipNotFound { name } => {
395 write!(
396 formatter,
397 "imported scene has no animation clip named '{name}'"
398 )
399 }
400 Self::VariantNotFound { name } => write!(
401 formatter,
402 "imported scene has no KHR_materials_variants variant named '{name}'"
403 ),
404 Self::AmbiguousClipName { name, matches } => write!(
405 formatter,
406 "imported scene animation clip name '{name}' is ambiguous across {} clips",
407 matches.len()
408 ),
409 Self::PathNotFound { path } => {
410 write!(formatter, "imported scene path '{path}' was not found")
411 }
412 Self::InvalidViewport { width, height } => {
413 write!(
414 formatter,
415 "viewport {width}x{height} is invalid; width and height must be non-zero"
416 )
417 }
418 Self::ImportHasNoBounds => {
419 write!(
420 formatter,
421 "imported scene has no renderable bounds to frame"
422 )
423 }
424 Self::StaleImport => write!(formatter, "scene import has been invalidated"),
425 Self::NodeIsNotMesh { node } => write!(formatter, "node {node:?} is not a mesh node"),
426 Self::NonInvertibleParentTransform { node, parent } => write!(
427 formatter,
428 "node {node:?} cannot be placed in world space because parent {parent:?} has a non-invertible transform"
429 ),
430 Self::GeometryNotFound { node, .. } => {
431 write!(
432 formatter,
433 "geometry for mesh node {node:?} was not found in Assets"
434 )
435 }
436 Self::CameraNotFound(_) => write!(formatter, "camera key does not exist in the scene"),
437 Self::ClippingPlaneNotFound(_) => {
438 write!(formatter, "clipping plane key does not exist in the scene")
439 }
440 Self::InstanceSetNotFound(_) => {
441 write!(formatter, "instance set key does not exist in the scene")
442 }
443 Self::LabelNotFound(_) => write!(formatter, "label key does not exist in the scene"),
444 }
445 }
446}
447
448impl fmt::Display for AnimationError {
449 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
450 match self {
451 Self::ClipNotFound { name } => {
452 write!(
453 formatter,
454 "imported scene has no animation clip named '{name}'"
455 )
456 }
457 Self::MixerNotFound(_) => write!(formatter, "animation mixer key does not exist"),
458 Self::StaleMixer(_) => write!(
459 formatter,
460 "animation mixer is stale because its source import was replaced"
461 ),
462 }
463 }
464}
465
466impl error::Error for Error {}
467impl error::Error for BuildError {}
468impl error::Error for AssetError {}
469impl error::Error for ImportError {}
470impl error::Error for InstantiateError {}
471impl error::Error for PrepareError {}
472impl error::Error for RenderError {}
473impl error::Error for LookupError {}
474impl error::Error for AnimationError {}