use bevy::ecs::{error::warn, world::DeferredWorld};
use bevy::math::sampling::UniformMeshSampler;
use bevy::prelude::*;
use rand::distr::Distribution;
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;
fn main() {
let mut app = App::new();
app.set_error_handler(warn);
app.add_plugins(DefaultPlugins);
#[cfg(feature = "bevy_mesh_picking_backend")]
app.add_plugins(MeshPickingPlugin);
app.add_systems(Startup, setup);
app.add_systems(Startup, failing_commands);
app.add_systems(
PostStartup,
failing_system.pipe(|result: In<Result>| {
let _ = result.0.inspect_err(|err| info!("captured error: {err}"));
}),
);
app.add_observer(fallible_observer);
app.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) -> Result {
let mut seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
commands.spawn((
Mesh3d(meshes.add(Plane3d::default().mesh().size(12.0, 12.0))),
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
Transform::from_xyz(0.0, -2.5, 0.0),
));
commands.spawn((
PointLight {
shadows_enabled: true,
..default()
},
Transform::from_xyz(4.0, 8.0, 4.0),
));
commands.spawn((
Camera3d::default(),
Transform::from_xyz(-2.0, 3.0, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
));
let mut sphere_mesh = Sphere::new(1.0).mesh().ico(7)?;
sphere_mesh.generate_tangents()?;
let mut sphere = commands.spawn((
Mesh3d(meshes.add(sphere_mesh.clone())),
MeshMaterial3d(materials.add(StandardMaterial::default())),
Transform::from_xyz(-1.0, 1.0, 0.0),
));
let triangles = sphere_mesh.triangles()?;
let distribution = UniformMeshSampler::try_new(triangles)?;
let point_mesh = meshes.add(Sphere::new(0.01).mesh().ico(3)?);
let point_material = materials.add(StandardMaterial {
base_color: Srgba::RED.into(),
emissive: LinearRgba::rgb(1.0, 0.0, 0.0),
..default()
});
for point in distribution.sample_iter(&mut seeded_rng).take(10000) {
sphere.with_child((
Mesh3d(point_mesh.clone()),
MeshMaterial3d(point_material.clone()),
Transform::from_translation(point),
));
}
Ok(())
}
fn fallible_observer(
pointer_move: On<Pointer<Move>>,
mut world: DeferredWorld,
mut step: Local<f32>,
) -> Result {
let mut transform = world
.get_mut::<Transform>(pointer_move.entity)
.ok_or("No transform found.")?;
*step = if transform.translation.x > 3. {
-0.1
} else if transform.translation.x < -3. || *step == 0. {
0.1
} else {
*step
};
transform.translation.x += *step;
Ok(())
}
#[derive(Resource)]
struct UninitializedResource;
fn failing_system(world: &mut World) -> Result {
world
.get_resource::<UninitializedResource>()
.ok_or("Resource not initialized")?;
Ok(())
}
fn failing_commands(mut commands: Commands) {
commands
.entity(Entity::from_raw_u32(12345678).unwrap())
.insert(Transform::default());
commands.queue_handled(
|world: &mut World| -> Result {
world
.get_resource::<UninitializedResource>()
.ok_or("Resource not initialized when accessed in a command")?;
Ok(())
},
|error, context| {
error!("{error}, {context}");
},
);
}