improve error handling
This commit is contained in:
parent
cb7a5058dc
commit
0b32f9ec0c
5 changed files with 112 additions and 54 deletions
|
@ -81,7 +81,8 @@ impl Entity for EntityImpl {
|
|||
fn get_component<C: Component>(&self) -> Option<&C> {
|
||||
let type_id = TypeId::of::<C>();
|
||||
if let Some(&bit) = COMPONENT_REGISTRY.lock().unwrap().get(&type_id) {
|
||||
self.components.get(&bit)
|
||||
self.components
|
||||
.get(&bit)
|
||||
.and_then(|boxed| boxed.as_any().downcast_ref::<C>())
|
||||
} else {
|
||||
None
|
||||
|
@ -107,7 +108,6 @@ impl Entity for EntityImpl {
|
|||
components: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub struct ECS {
|
||||
|
@ -167,4 +167,4 @@ impl ECS {
|
|||
}
|
||||
self.next_entity_id = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,33 +48,39 @@ fn process_panic(info: &std::panic::PanicHookInfo<'_>) -> Result<(), Box<dyn Err
|
|||
writeln!(file, "{}", render_backtrace().sanitize_path())?;
|
||||
|
||||
let panic_msg = format!(
|
||||
"Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report.
|
||||
r#"Zenyx had a problem and crashed. To help us diagnose the problem you can send us a crash report.
|
||||
|
||||
We have generated a report file at '{}'. Submit an issue or email with the subject of 'Zenyx Crash Report' and include the report as an attachment.
|
||||
|
||||
To submit the crash report:
|
||||
|
||||
https://github.com/Zenyx-Engine/Zenyx/issues
|
||||
|
||||
We take privacy seriously, and do not perform any automated error collection. In order to improve the software, we rely on people to submit reports.
|
||||
|
||||
Thank you kindly!", log_path.display());
|
||||
println!("{}", panic_msg.red().bold());
|
||||
println!(
|
||||
"\nFor future reference, the error summary is as follows:\n{}",
|
||||
payload_str.red().bold()
|
||||
Thank you kindly!"#,
|
||||
log_path.display()
|
||||
);
|
||||
if let Err(e ) = MessageDialog::new()
|
||||
.set_type(MessageType::Error)
|
||||
.set_title(&format!("{}",payload_str))
|
||||
// wont display properly if not debug formatted??
|
||||
.set_text(&format!("{:#?}", panic_msg))
|
||||
.show_alert() {
|
||||
error!("{e}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let final_msg = format!(
|
||||
r#"{}
|
||||
|
||||
For future reference, the error summary is as follows:
|
||||
{}"#,
|
||||
panic_msg, payload_str
|
||||
);
|
||||
|
||||
println!("{}", final_msg.red().bold());
|
||||
|
||||
MessageDialog::new()
|
||||
.set_type(MessageType::Error)
|
||||
.set_title("A fatal error in Zenyx has occurred")
|
||||
.set_text(&final_msg)
|
||||
.show_alert()
|
||||
.map_err(|e| {
|
||||
error!("Failed to show error dialog: {}", e);
|
||||
e.into()
|
||||
})
|
||||
}
|
||||
fn render_backtrace() -> String {
|
||||
const HEX_WIDTH: usize = mem::size_of::<usize>() * 2 + 2;
|
||||
const NEXT_SYMBOL_PADDING: usize = HEX_WIDTH + 6;
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::time::Instant;
|
|||
use cgmath::{Deg, Matrix4, Point3, Rad, SquareMatrix, Vector3, perspective};
|
||||
use futures::executor::block_on;
|
||||
use thiserror::Error;
|
||||
use tracing::{error, info, trace};
|
||||
use tracing::{debug, error, info, trace};
|
||||
use wgpu::TextureUsages;
|
||||
use wgpu::{Backends, InstanceDescriptor, util::DeviceExt};
|
||||
use wgpu_text::glyph_brush::ab_glyph::FontRef;
|
||||
|
@ -333,7 +333,7 @@ struct FontState {
|
|||
impl<'window> Renderer<'window> {
|
||||
pub async fn new(window: Arc<Window>) -> Result<Self, RenderContextError> {
|
||||
let instance = wgpu::Instance::new(&InstanceDescriptor {
|
||||
backends: Backends::from_comma_list("dx12,metal,opengl,webgpu"),
|
||||
backends: Backends::from_comma_list("dx12,metal,opengl,webgpu,vulkan"),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
|
@ -458,23 +458,31 @@ impl<'window> Renderer<'window> {
|
|||
let camera = Camera::new(&device, &camera_bind_group_layout, width, height);
|
||||
|
||||
let surface_caps = surface.get_capabilities(&adapter);
|
||||
let present_mode = [
|
||||
wgpu::PresentMode::Immediate,
|
||||
wgpu::PresentMode::Mailbox,
|
||||
wgpu::PresentMode::AutoNoVsync,
|
||||
]
|
||||
.iter()
|
||||
.copied()
|
||||
.find(|mode| surface_caps.present_modes.contains(mode))
|
||||
.unwrap_or(wgpu::PresentMode::Fifo);
|
||||
|
||||
debug!("Using {:#?} present mode.", present_mode);
|
||||
|
||||
let surface_config = wgpu::SurfaceConfiguration {
|
||||
width,
|
||||
height,
|
||||
format: surface_caps.formats[0],
|
||||
present_mode: wgpu::PresentMode::AutoNoVsync,
|
||||
present_mode,
|
||||
alpha_mode: wgpu::CompositeAlphaMode::Auto,
|
||||
view_formats: vec![],
|
||||
usage: TextureUsages::RENDER_ATTACHMENT,
|
||||
desired_maximum_frame_latency: 3,
|
||||
};
|
||||
surface.configure(&device, &surface_config);
|
||||
let (depth_texture, depth_texture_view) = create_depth_texture(
|
||||
&device,
|
||||
surface_config.width,
|
||||
surface_config.height,
|
||||
// surface_config.format,
|
||||
);
|
||||
let (depth_texture, depth_texture_view) =
|
||||
create_depth_texture(&device, surface_config.width, surface_config.height);
|
||||
|
||||
let font_bytes = include_bytes!("DejaVuSans.ttf");
|
||||
let font = FontRef::try_from_slice(font_bytes).map_err(|e| {
|
||||
|
@ -706,7 +714,6 @@ fn create_depth_texture(
|
|||
device: &wgpu::Device,
|
||||
width: u32,
|
||||
height: u32,
|
||||
// format: wgpu::TextureFormat,
|
||||
) -> (wgpu::Texture, wgpu::TextureView) {
|
||||
let size = wgpu::Extent3d {
|
||||
width,
|
||||
|
|
|
@ -5,12 +5,15 @@ use ctx::{Renderer, Vertex};
|
|||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use tobj::Mesh;
|
||||
use tobj::{LoadOptions, Model};
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use wgpu::rwh::HasWindowHandle;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::{KeyEvent, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||
use winit::monitor::MonitorHandle;
|
||||
use winit::window::Fullscreen;
|
||||
use winit::window::Window;
|
||||
use winit::window::WindowId;
|
||||
|
||||
|
@ -42,16 +45,16 @@ pub struct App<'window> {
|
|||
static CUBE_OBJ: &str = "
|
||||
# Blender 4.2.3 LTS
|
||||
# www.blender.org
|
||||
mtllib cube.mtl
|
||||
mtllib untitled.mtl
|
||||
o Cube
|
||||
v 1.000000 1.000000 -1.000000
|
||||
v 1.000000 -1.000000 -1.000000
|
||||
v 1.000000 1.000000 1.000000
|
||||
v 1.000000 -1.000000 1.000000
|
||||
v -1.000000 1.000000 -1.000000
|
||||
v -1.000000 -1.000000 -1.000000
|
||||
v -1.000000 1.000000 1.000000
|
||||
v -1.000000 -1.000000 1.000000
|
||||
v 0.645975 0.645975 -0.645975
|
||||
v 0.645975 -0.645975 -0.645975
|
||||
v 0.645975 0.645975 0.645975
|
||||
v 0.645975 -0.645975 0.645975
|
||||
v -0.645975 0.645975 -0.645975
|
||||
v -0.645975 -0.645975 -0.645975
|
||||
v -0.645975 0.645975 0.645975
|
||||
v -0.645975 -0.645975 0.645975
|
||||
vn -0.0000 1.0000 -0.0000
|
||||
vn -0.0000 -0.0000 1.0000
|
||||
vn -1.0000 -0.0000 -0.0000
|
||||
|
@ -80,6 +83,7 @@ f 8/8/3 7/9/3 5/10/3 6/11/3
|
|||
f 6/12/4 2/13/4 4/5/4 8/14/4
|
||||
f 2/13/5 1/1/5 3/4/5 4/5/5
|
||||
f 6/11/6 5/10/6 1/1/6 2/13/6
|
||||
|
||||
";
|
||||
|
||||
impl App<'_> {
|
||||
|
@ -101,10 +105,22 @@ impl App<'_> {
|
|||
) {
|
||||
Ok(obj) => obj,
|
||||
Err(e) => {
|
||||
error!("{e}");
|
||||
panic!()
|
||||
error!("Failed to load Pumpkin.obj: {e}");
|
||||
// Fallback to CUBE_OBJ
|
||||
let fallback_obj = CUBE_OBJ.to_string();
|
||||
tobj::load_obj_buf(
|
||||
&mut fallback_obj.as_bytes(),
|
||||
&LoadOptions {
|
||||
triangulate: true,
|
||||
single_index: true,
|
||||
..Default::default()
|
||||
},
|
||||
|_| Ok(Default::default()),
|
||||
)
|
||||
.expect("Failed to load fallback CUBE_OBJ")
|
||||
}
|
||||
};
|
||||
|
||||
let (combined_vertices, combined_indices) = parse_obj(&obj.0);
|
||||
|
||||
wgpu_ctx.add_model(&combined_vertices, &combined_indices);
|
||||
|
@ -119,10 +135,10 @@ impl App<'_> {
|
|||
);
|
||||
info!("Main window created: {:?}", window_id);
|
||||
}
|
||||
Err(e) => error!("Failed to create WGPU context: {:?}", e),
|
||||
Err(e) => error!("Failed to create WGPU context: {:}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Failed to create main window: {:?}", e),
|
||||
Err(e) => error!("Failed to create main window: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,6 +167,7 @@ impl App<'_> {
|
|||
winit::keyboard::KeyCode::Escape => {
|
||||
self.spawn_child_window(event_loop);
|
||||
}
|
||||
winit::keyboard::KeyCode::F11 => self.toggle_fullscreen(window_id),
|
||||
other => error!("Unimplemented keycode: {:?}", other),
|
||||
},
|
||||
_ => debug!("Received a keyboard event with no physical key"),
|
||||
|
@ -180,6 +197,23 @@ impl App<'_> {
|
|||
warn!("No window context for toggling background: {:?}", window_id);
|
||||
}
|
||||
}
|
||||
fn toggle_fullscreen(&mut self, window_id: WindowId) {
|
||||
if let Some(ctx) = self.windows.get_mut(&window_id) {
|
||||
let is_fullscreen = ctx.window.fullscreen().is_some();
|
||||
let fullscreen_mode = if is_fullscreen {
|
||||
None
|
||||
} else {
|
||||
ctx.window
|
||||
.current_monitor()
|
||||
.map(|monitor| Fullscreen::Borderless(Some(monitor)))
|
||||
};
|
||||
|
||||
ctx.window.set_fullscreen(fullscreen_mode);
|
||||
debug!("Fullscreen toggled for window: {:?}", window_id);
|
||||
} else {
|
||||
warn!("No window found for fullscreen toggle: {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_child_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
|
||||
|
@ -202,7 +236,7 @@ impl App<'_> {
|
|||
let mut tmp_path: PathBuf = env::temp_dir();
|
||||
tmp_path.push("cube.obj");
|
||||
if let Err(e) = fs::write(&tmp_path, CUBE_OBJ) {
|
||||
error!("Failed to write cube OBJ to temp: {:?}", e);
|
||||
error!("Failed to write cube OBJ to temp: {}", e);
|
||||
}
|
||||
|
||||
let load_options = tobj::LoadOptions {
|
||||
|
@ -217,7 +251,7 @@ impl App<'_> {
|
|||
wgpu_ctx.add_model(&cube_vertices, &cube_indices);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to load cube OBJ from temp file: {:?}", e)
|
||||
error!("Failed to load cube OBJ from temp file: {:#}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,10 +265,10 @@ impl App<'_> {
|
|||
);
|
||||
debug!("Spawned new child window: {:?}", window_id);
|
||||
}
|
||||
Err(e) => error!("Failed to create WGPU context for child window: {:?}", e),
|
||||
Err(e) => error!("Failed to create WGPU context for child window: {}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Failed to create child window: {:?}", e),
|
||||
Err(e) => error!("Failed to create child window: {}", e),
|
||||
}
|
||||
} else {
|
||||
error!("No main window found. Cannot spawn a child window.");
|
||||
|
@ -350,6 +384,6 @@ pub fn init_renderer(event_loop: EventLoop<()>) {
|
|||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
let mut app = App::default();
|
||||
if let Err(e) = event_loop.run_app(&mut app) {
|
||||
error!("Failed to run application: {:?}", e);
|
||||
error!("Failed to run application: {}", e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,18 +33,29 @@ async fn main() -> anyhow::Result<()> {
|
|||
setup();
|
||||
|
||||
let repl_thread = std::thread::spawn(|| {
|
||||
let rt = runtime::Builder::new_current_thread()
|
||||
let rt = match runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap();
|
||||
.build() {
|
||||
Ok(rt) => rt,
|
||||
Err(e) => {
|
||||
error!("A fatal error has occured: {e}");
|
||||
std::process::exit(1)
|
||||
},
|
||||
};
|
||||
rt.block_on(core::repl::input::handle_repl())
|
||||
});
|
||||
|
||||
let event_loop = EventLoop::new().unwrap();
|
||||
splash::print_splash();
|
||||
info!("Type 'help' for a list of commands.");
|
||||
|
||||
core::render::init_renderer(event_loop);
|
||||
match EventLoop::new() {
|
||||
Ok(event_loop) => {
|
||||
core::render::init_renderer(event_loop);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("{e}")
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(_) = repl_thread.join() {
|
||||
eprintln!("REPL thread panicked");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue