diff --git a/editor/src/settings/mod.rs b/editor/src/settings/mod.rs index c085cedf1..e6c00f1fa 100644 --- a/editor/src/settings/mod.rs +++ b/editor/src/settings/mod.rs @@ -32,6 +32,7 @@ use ron::ser::PrettyConfig; use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, + fmt::Display, fs::File, io::Write, ops::{Deref, DerefMut}, @@ -151,6 +152,18 @@ pub enum SettingsError { Ron(ron::Error), } +impl std::error::Error for SettingsError {} + +impl Display for SettingsError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SettingsError::Io(error) => Display::fmt(error, f), + SettingsError::RonSpanned(error) => Display::fmt(error, f), + SettingsError::Ron(error) => Display::fmt(error, f), + } + } +} + impl From for SettingsError { fn from(e: std::io::Error) -> Self { Self::Io(e) diff --git a/fyrox-core/src/log.rs b/fyrox-core/src/log.rs index fb0dc0127..3df6aed6e 100644 --- a/fyrox-core/src/log.rs +++ b/fyrox-core/src/log.rs @@ -315,13 +315,10 @@ impl Log { /// be in the log. pub fn verify(result: Result) where - E: Debug, + E: Display, { if let Err(e) = result { - Self::writeln( - MessageKind::Error, - format!("Operation failed! Reason: {e:?}"), - ); + Self::writeln(MessageKind::Error, format!("Operation failed! Reason: {e}")); } } diff --git a/fyrox-core/src/pool/multiborrow.rs b/fyrox-core/src/pool/multiborrow.rs index 8538a5be8..d6ddc7d81 100644 --- a/fyrox-core/src/pool/multiborrow.rs +++ b/fyrox-core/src/pool/multiborrow.rs @@ -143,6 +143,8 @@ pub enum MultiBorrowError { InvalidHandleGeneration(Handle), } +impl std::error::Error for MultiBorrowError {} + impl Debug for MultiBorrowError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { Display::fmt(self, f) diff --git a/fyrox-core/src/reflect.rs b/fyrox-core/src/reflect.rs index 14a85d3e6..d0ac35a8c 100644 --- a/fyrox-core/src/reflect.rs +++ b/fyrox-core/src/reflect.rs @@ -90,6 +90,21 @@ pub enum CastError { }, } +impl std::error::Error for CastError {} + +impl Display for CastError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + CastError::TypeMismatch { property_name, .. } => { + write!( + f, + "Given type does not match expected for property {property_name:?}" + ) + } + } + } +} + #[derive(Debug)] pub struct FieldMetadata<'s> { /// A name of the property. @@ -529,6 +544,8 @@ pub enum ReflectPathError<'a> { NotAnArray, } +impl std::error::Error for ReflectPathError<'_> {} + impl Display for ReflectPathError<'_> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { @@ -870,6 +887,7 @@ impl ResolvePath for dyn Reflect { } } +#[derive(Debug)] pub enum SetFieldError { NoSuchField { name: String, @@ -881,6 +899,26 @@ pub enum SetFieldError { }, } +impl std::error::Error for SetFieldError {} + +impl Display for SetFieldError { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + SetFieldError::NoSuchField { name, value } => { + write!(f, "No such field as {name:?} for value {value:?}") + } + SetFieldError::InvalidValue { + field_type_name, + value, + } => write!( + f, + "Invalid value for field type {field_type_name}: {value:?}" + ), + } + } +} + +#[derive(Debug)] pub enum SetFieldByPathError<'p> { InvalidPath { value: Box, @@ -893,6 +931,25 @@ pub enum SetFieldByPathError<'p> { SetFieldError(SetFieldError), } +impl std::error::Error for SetFieldByPathError<'_> {} + +impl Display for SetFieldByPathError<'_> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + SetFieldByPathError::InvalidPath { value, reason } => { + write!(f, "Invalid path: {value:?}. Reason: {reason}") + } + SetFieldByPathError::InvalidValue { + field_type_name, + value, + } => { + write!(f, "Invalid value: {value:?}. Type: {field_type_name}") + } + SetFieldByPathError::SetFieldError(set_field_error) => Display::fmt(set_field_error, f), + } + } +} + /// Type-erased API impl dyn Reflect { pub fn downcast(self: Box) -> Result, Box> { diff --git a/fyrox-core/src/variable.rs b/fyrox-core/src/variable.rs index b9dc5c594..98296fd85 100644 --- a/fyrox-core/src/variable.rs +++ b/fyrox-core/src/variable.rs @@ -30,7 +30,7 @@ use bitflags::bitflags; use std::{ any::{Any, TypeId}, cell::Cell, - fmt::Debug, + fmt::{Debug, Display}, ops::{Deref, DerefMut}, }; @@ -83,6 +83,24 @@ pub enum InheritError { }, } +impl std::error::Error for InheritError {} + +impl Display for InheritError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + InheritError::TypesMismatch { + left_type, + right_type, + } => { + write!( + f, + "Child type ({left_type}) does not match parent type ({right_type})" + ) + } + } + } +} + /// A wrapper for a variable that hold additional flag that tells that initial value was changed in runtime. /// /// InheritableVariables are used for resource inheritance system. Resource inheritance may just sound weird, diff --git a/fyrox-graphics/src/error.rs b/fyrox-graphics/src/error.rs index 223d4251b..5939be80f 100644 --- a/fyrox-graphics/src/error.rs +++ b/fyrox-graphics/src/error.rs @@ -85,6 +85,8 @@ pub enum FrameworkError { GraphicsServerUnavailable, } +impl std::error::Error for FrameworkError {} + impl Display for FrameworkError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { diff --git a/fyrox-impl/src/engine/error.rs b/fyrox-impl/src/engine/error.rs index 19226dac3..3424563a0 100644 --- a/fyrox-impl/src/engine/error.rs +++ b/fyrox-impl/src/engine/error.rs @@ -35,6 +35,8 @@ pub enum EngineError { Custom(String), } +impl std::error::Error for EngineError {} + impl Display for EngineError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { diff --git a/fyrox-impl/src/resource/fbx/error.rs b/fyrox-impl/src/resource/fbx/error.rs index 3eef401f6..62146d815 100644 --- a/fyrox-impl/src/resource/fbx/error.rs +++ b/fyrox-impl/src/resource/fbx/error.rs @@ -69,6 +69,8 @@ pub enum FbxError { FileLoadError(FileError), } +impl std::error::Error for FbxError {} + impl Display for FbxError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { diff --git a/fyrox-impl/src/scene/skybox.rs b/fyrox-impl/src/scene/skybox.rs index 84826bfc6..3cef0efd5 100644 --- a/fyrox-impl/src/scene/skybox.rs +++ b/fyrox-impl/src/scene/skybox.rs @@ -20,6 +20,8 @@ //! Skybox is a huge box around a camera. See [`SkyBox`] docs for more info. +use std::fmt::Display; + use crate::{ asset::{builtin::BuiltInResource, embedded_data_source, untyped::ResourceKind}, core::{log::Log, reflect::prelude::*, uuid_provider, visitor::prelude::*}, @@ -377,6 +379,39 @@ pub enum SkyBoxError { }, } +impl std::error::Error for SkyBoxError {} + +impl Display for SkyBoxError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + SkyBoxError::UnsupportedTextureKind(texture_kind) => { + write!(f, "Unsupported texture kind: {texture_kind:?}") + } + SkyBoxError::UnableToBuildCubeMap => f.write_str("Cube map was failed to build."), + SkyBoxError::NonSquareTexture { + index, + width, + height, + } => write!( + f, + "Input texture is not square. Index: {index}, width: {width}, height: {height}" + ), + SkyBoxError::DifferentTexture { + expected_width, + expected_height, + expected_pixel_kind, + index, + actual_width, + actual_height, + actual_pixel_kind, + } => write!(f, "Some input texture differs in size or pixel kind. Index: {index}. \ + Expected width: {expected_width}, height: {expected_height}, kind: {expected_pixel_kind:?}. \ + Actual width: {actual_width}, height: {actual_height}, kind: {actual_pixel_kind:?}."), + SkyBoxError::TextureIsNotReady { index } => write!(f, "Input texture is not loaded. Index: {index}"), + } + } +} + /// SkyBox builder is used to create new skybox in declarative manner. pub struct SkyBoxBuilder { /// Texture for front face. diff --git a/fyrox-impl/src/utils/lightmap.rs b/fyrox-impl/src/utils/lightmap.rs index 54c610a52..eca4ed9c6 100644 --- a/fyrox-impl/src/utils/lightmap.rs +++ b/fyrox-impl/src/utils/lightmap.rs @@ -309,6 +309,8 @@ pub enum LightmapGenerationError { InvalidData(VertexFetchError), } +impl std::error::Error for LightmapGenerationError {} + impl Display for LightmapGenerationError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { diff --git a/fyrox-resource/src/options.rs b/fyrox-resource/src/options.rs index d4f612132..b9146b4bc 100644 --- a/fyrox-resource/src/options.rs +++ b/fyrox-resource/src/options.rs @@ -47,13 +47,17 @@ pub trait ImportOptions: { /// Saves import options into a specified file. fn save_internal(&self, path: &Path) -> bool { - if let Ok(mut file) = File::create(path) { - if let Ok(string) = ron::ser::to_string_pretty(self, PrettyConfig::default()) { - Log::verify(file.write_all(string.as_bytes())); - return true; - } + fn write(this: &T, path: &Path) -> std::io::Result<()> { + let mut file = File::create(path)?; + let string = ron::ser::to_string_pretty(this, PrettyConfig::default()) + .map_err(|e| std::io::Error::new(ErrorKind::InvalidData, e))?; + file.write_all(string.as_bytes())?; + Ok(()) } - false + let result = write(self, path); + let is_ok = result.is_ok(); + Log::verify(result); + is_ok } } @@ -79,10 +83,8 @@ where Ok(options) => Some(options), Err(e) => { Log::warn(format!( - "Malformed options file {} for {} resource, fallback to defaults! Reason: {:?}", - settings_path.display(), - resource_path.display(), - e + "Malformed options file {:?}, fallback to defaults! Reason: {}", + settings_path, e )); None @@ -99,10 +101,8 @@ where } Log::warn(format!( - "Unable to load options file {} for {} resource, fallback to defaults! Reason: {:?}", - settings_path.display(), - resource_path.display(), - e + "Unable to load options file {:?}, fallback to defaults! Reason: {}", + settings_path, e )); None diff --git a/fyrox-ui/src/inspector/mod.rs b/fyrox-ui/src/inspector/mod.rs index 2c93beb6b..e94586ff1 100644 --- a/fyrox-ui/src/inspector/mod.rs +++ b/fyrox-ui/src/inspector/mod.rs @@ -58,7 +58,7 @@ use fyrox_graph::{ }; use std::{ any::{Any, TypeId}, - fmt::{Debug, Formatter}, + fmt::{Debug, Display, Formatter}, ops::{Deref, DerefMut}, sync::Arc, }; @@ -131,6 +131,26 @@ pub enum PropertyAction { Revert, } +impl Display for PropertyAction { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + PropertyAction::Modify { value } => write!( + f, + "A property needs to be modified with given value: {value:?}" + ), + PropertyAction::AddItem { value } => write!( + f, + "An item needs to be added to a collection property: {value:?}" + ), + PropertyAction::RemoveItem { index } => write!( + f, + "An item needs to be removed from a collection property. Index: {index}" + ), + PropertyAction::Revert => f.write_str("Revert value to parent"), + } + } +} + impl PropertyAction { /// Creates action from a field definition. It is recursive action, it traverses the tree /// until there is either FieldKind::Object or FieldKind::Collection. FieldKind::Inspectable @@ -647,14 +667,13 @@ impl Inspector { if let Some(inspector) = ui.try_get_of_type::(inspector) { let ctx = inspector.context.clone(); - Log::verify(ctx.sync( - object, - ui, - 0, - true, - Default::default(), - Default::default(), - )); + if let Err(errs) = + ctx.sync(object, ui, 0, true, Default::default(), Default::default()) + { + for err in errs { + Log::err(err.to_string()); + } + } } } } @@ -710,6 +729,27 @@ pub enum InspectorError { Group(Vec), } +impl std::error::Error for InspectorError {} + +impl Display for InspectorError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + InspectorError::CastError(cast_error) => Display::fmt(cast_error, f), + InspectorError::OutOfSync => f.write_str( + "The object type has changed and the inspector context is no longer valid.", + ), + InspectorError::Custom(message) => f.write_str(message), + InspectorError::Group(inspector_errors) => { + f.write_str("Multiple errors:\n")?; + for err in inspector_errors { + writeln!(f, " {err}")?; + } + Ok(()) + } + } + } +} + impl From for InspectorError { fn from(e: CastError) -> Self { Self::CastError(e) diff --git a/project-manager/src/settings.rs b/project-manager/src/settings.rs index cb5f58c4e..c7956654a 100644 --- a/project-manager/src/settings.rs +++ b/project-manager/src/settings.rs @@ -302,14 +302,18 @@ impl SettingsWindow { .context() .clone(); - Log::verify(ctx.sync( + if let Err(errs) = ctx.sync( &**settings, ui, 0, true, Default::default(), Default::default(), - )); + ) { + for err in errs { + Log::err(err.to_string()); + } + } } } diff --git a/template-core/src/lib.rs b/template-core/src/lib.rs index ac25b9429..7a0e33caf 100644 --- a/template-core/src/lib.rs +++ b/template-core/src/lib.rs @@ -67,6 +67,8 @@ pub enum NameError { InvalidCharacter(char), } +impl std::error::Error for NameError {} + impl Display for NameError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self {