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