This commit is contained in:
Gonçalo Rica Pais da Silva 2025-07-16 17:44:25 -04:00 committed by GitHub
commit 2cb05fab8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
54 changed files with 274 additions and 226 deletions

View File

@ -222,6 +222,8 @@ jobs:
with: with:
target: wasm32-unknown-unknown target: wasm32-unknown-unknown
- name: Check wasm - name: Check wasm
env:
RUSTFLAGS: --cfg getrandom_backend="wasm_js"
run: cargo check --target wasm32-unknown-unknown run: cargo check --target wasm32-unknown-unknown
build-wasm-atomics: build-wasm-atomics:
@ -247,7 +249,7 @@ jobs:
- name: Check wasm - name: Check wasm
run: cargo check --target wasm32-unknown-unknown -Z build-std=std,panic_abort run: cargo check --target wasm32-unknown-unknown -Z build-std=std,panic_abort
env: env:
RUSTFLAGS: "-C target-feature=+atomics,+bulk-memory" RUSTFLAGS: '-C target-feature=+atomics,+bulk-memory --cfg getrandom_backend="wasm_js"'
markdownlint: markdownlint:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -112,6 +112,8 @@ jobs:
cd ../.. cd ../..
- name: First Wasm build - name: First Wasm build
env:
RUSTFLAGS: --cfg getrandom_backend="wasm_js"
run: | run: |
cargo build --release --example testbed_ui --target wasm32-unknown-unknown cargo build --release --example testbed_ui --target wasm32-unknown-unknown

View File

@ -591,8 +591,8 @@ tracing = { version = "0.1", default-features = false, optional = true }
bevy_dylib = { path = "crates/bevy_dylib", version = "0.17.0-dev", default-features = false, optional = true } bevy_dylib = { path = "crates/bevy_dylib", version = "0.17.0-dev", default-features = false, optional = true }
[dev-dependencies] [dev-dependencies]
rand = "0.8.0" rand = "0.9.0"
rand_chacha = "0.3.1" rand_chacha = "0.9.0"
ron = "0.10" ron = "0.10"
flate2 = "1.0" flate2 = "1.0"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
@ -627,6 +627,9 @@ smol-hyper = "0.1"
ureq = { version = "3.0.8", features = ["json"] } ureq = { version = "3.0.8", features = ["json"] }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies] [target.'cfg(target_arch = "wasm32")'.dev-dependencies]
getrandom = { version = "0.3", default-features = false, features = [
"wasm_js",
] }
wasm-bindgen = { version = "0.2" } wasm-bindgen = { version = "0.2" }
web-sys = { version = "0.3", features = ["Window"] } web-sys = { version = "0.3", features = ["Window"] }

View File

@ -29,9 +29,9 @@ bevy_platform = { path = "../crates/bevy_platform", default-features = false, fe
] } ] }
# Other crates # Other crates
glam = "0.29" glam = "0.30.1"
rand = "0.8" rand = "0.9"
rand_chacha = "0.3" rand_chacha = "0.9"
nonmax = { version = "0.5", default-features = false } nonmax = { version = "0.5", default-features = false }
# Make `bevy_render` compile on Linux with x11 windowing. x11 vs. Wayland does not matter here # Make `bevy_render` compile on Linux with x11 windowing. x11 vs. Wayland does not matter here

View File

@ -66,7 +66,7 @@ pub fn event_propagation(criterion: &mut Criterion) {
struct TestEvent<const N: usize> {} struct TestEvent<const N: usize> {}
fn send_events<const N: usize, const N_EVENTS: usize>(world: &mut World, leaves: &[Entity]) { fn send_events<const N: usize, const N_EVENTS: usize>(world: &mut World, leaves: &[Entity]) {
let target = leaves.iter().choose(&mut rand::thread_rng()).unwrap(); let target = leaves.iter().choose(&mut rand::rng()).unwrap();
(0..N_EVENTS).for_each(|_| { (0..N_EVENTS).for_each(|_| {
world.trigger_targets(TestEvent::<N> {}, *target); world.trigger_targets(TestEvent::<N> {}, *target);
@ -107,7 +107,7 @@ fn add_listeners_to_hierarchy<const DENSITY: usize, const N: usize>(
} }
let mut rng = deterministic_rand(); let mut rng = deterministic_rand();
for e in nodes.iter() { for e in nodes.iter() {
if rng.gen_bool(DENSITY as f64 / 100.0) { if rng.random_bool(DENSITY as f64 / 100.0) {
world.entity_mut(*e).observe(empty_listener::<N>); world.entity_mut(*e).observe(empty_listener::<N>);
} }
} }

View File

@ -11,9 +11,9 @@ fn make_entity(rng: &mut impl Rng, size: usize) -> Entity {
// * For ids, half are in [0, size), half are unboundedly larger. // * For ids, half are in [0, size), half are unboundedly larger.
// * For generations, half are in [1, 3), half are unboundedly larger. // * For generations, half are in [1, 3), half are unboundedly larger.
let x: f64 = rng.r#gen(); let x: f64 = rng.random();
let id = -(1.0 - x).log2() * (size as f64); let id = -(1.0 - x).log2() * (size as f64);
let x: f64 = rng.r#gen(); let x: f64 = rng.random();
let generation = 1.0 + -(1.0 - x).log2() * 2.0; let generation = 1.0 + -(1.0 - x).log2() * 2.0;
// this is not reliable, but we're internal so a hack is ok // this is not reliable, but we're internal so a hack is ok

View File

@ -3,7 +3,7 @@ use core::{fmt::Write, hint::black_box, str, time::Duration};
use benches::bench; use benches::bench;
use bevy_reflect::ParsedPath; use bevy_reflect::ParsedPath;
use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion, Throughput}; use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion, Throughput};
use rand::{distributions::Uniform, Rng, SeedableRng}; use rand::{distr::Uniform, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
criterion_group!(benches, parse_reflect_path); criterion_group!(benches, parse_reflect_path);
@ -18,20 +18,20 @@ fn deterministic_rand() -> ChaCha8Rng {
ChaCha8Rng::seed_from_u64(42) ChaCha8Rng::seed_from_u64(42)
} }
fn random_ident(rng: &mut ChaCha8Rng, f: &mut dyn Write) { fn random_ident(rng: &mut ChaCha8Rng, f: &mut dyn Write) {
let between = Uniform::from(b'a'..=b'z'); let between = Uniform::new_inclusive(b'a', b'z').unwrap();
let ident_size = rng.gen_range(1..128); let ident_size = rng.random_range(1..128);
let ident: Vec<u8> = rng.sample_iter(between).take(ident_size).collect(); let ident: Vec<u8> = rng.sample_iter(between).take(ident_size).collect();
let ident = str::from_utf8(&ident).unwrap(); let ident = str::from_utf8(&ident).unwrap();
let _ = write!(f, "{ident}"); let _ = write!(f, "{ident}");
} }
fn random_index(rng: &mut ChaCha8Rng, f: &mut dyn Write) { fn random_index(rng: &mut ChaCha8Rng, f: &mut dyn Write) {
let index = rng.gen_range(1..128); let index = rng.random_range(1..128);
let _ = write!(f, "{index}"); let _ = write!(f, "{index}");
} }
fn write_random_access(rng: &mut ChaCha8Rng, f: &mut dyn Write) { fn write_random_access(rng: &mut ChaCha8Rng, f: &mut dyn Write) {
match rng.gen_range(0..4) { match rng.random_range(0..4) {
0 => { 0 => {
// Access::Field // Access::Field
f.write_char('.').unwrap(); f.write_char('.').unwrap();

View File

@ -21,7 +21,7 @@ serde = { version = "1.0", features = [
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
derive_more = { version = "2", default-features = false, features = ["from"] } derive_more = { version = "2", default-features = false, features = ["from"] }
wgpu-types = { version = "25", default-features = false, optional = true } wgpu-types = { version = "25", default-features = false, optional = true }
encase = { version = "0.10", default-features = false, optional = true } encase = { version = "0.11", default-features = false, optional = true }
[features] [features]
default = ["std", "bevy_reflect", "encase"] default = ["std", "bevy_reflect", "encase"]

View File

@ -131,7 +131,7 @@ concurrent-queue = { version = "2.5.0", default-features = false, features = [
] } ] }
[dev-dependencies] [dev-dependencies]
rand = "0.8" rand = "0.9"
static_assertions = "1.1.0" static_assertions = "1.1.0"
serde_test = "1.0" serde_test = "1.0"

View File

@ -66,7 +66,7 @@ enum SimulationSystems {
// The entity will start with an age of 0 frames // The entity will start with an age of 0 frames
// If an entity gets spawned, we increase the counter in the EntityCounter resource // If an entity gets spawned, we increase the counter in the EntityCounter resource
fn spawn_entities(mut commands: Commands, mut entity_counter: ResMut<EntityCounter>) { fn spawn_entities(mut commands: Commands, mut entity_counter: ResMut<EntityCounter>) {
if rand::thread_rng().gen_bool(0.6) { if rand::rng().random_bool(0.6) {
let entity_id = commands.spawn(Age::default()).id(); let entity_id = commands.spawn(Age::default()).id();
println!(" spawning {entity_id:?}"); println!(" spawning {entity_id:?}");
entity_counter.value += 1; entity_counter.value += 1;

View File

@ -37,7 +37,7 @@ struct Counter {
} }
fn increase_counter(mut counter: ResMut<Counter>) { fn increase_counter(mut counter: ResMut<Counter>) {
if rand::thread_rng().gen_bool(0.5) { if rand::rng().random_bool(0.5) {
counter.value += 1; counter.value += 1;
println!(" Increased counter value"); println!(" Increased counter value");
} }

View File

@ -13,7 +13,7 @@ proc-macro = true
[dependencies] [dependencies]
bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.17.0-dev" } bevy_macro_utils = { path = "../bevy_macro_utils", version = "0.17.0-dev" }
encase_derive_impl = "0.10" encase_derive_impl = "0.11"
[lints] [lints]
workspace = true workspace = true

View File

@ -10,7 +10,7 @@ keywords = ["bevy"]
rust-version = "1.85.0" rust-version = "1.85.0"
[dependencies] [dependencies]
glam = { version = "0.29.3", default-features = false, features = ["bytemuck"] } glam = { version = "0.30.1", default-features = false, features = ["bytemuck"] }
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
derive_more = { version = "2", default-features = false, features = [ derive_more = { version = "2", default-features = false, features = [
"from", "from",
@ -22,8 +22,8 @@ serde = { version = "1", default-features = false, features = [
], optional = true } ], optional = true }
libm = { version = "0.2", optional = true } libm = { version = "0.2", optional = true }
approx = { version = "0.5", default-features = false, optional = true } approx = { version = "0.5", default-features = false, optional = true }
rand = { version = "0.8", default-features = false, optional = true } rand = { version = "0.9", default-features = false, optional = true }
rand_distr = { version = "0.4.3", optional = true } rand_distr = { version = "0.5", optional = true }
smallvec = { version = "1", default-features = false } smallvec = { version = "1", default-features = false }
bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev", default-features = false, features = [ bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev", default-features = false, features = [
"glam", "glam",
@ -33,11 +33,16 @@ variadics_please = "1.1"
[dev-dependencies] [dev-dependencies]
approx = "0.5" approx = "0.5"
# Supply rngs for examples and tests # Supply rngs for examples and tests
rand = "0.8" rand = "0.9"
rand_chacha = "0.3" rand_chacha = "0.9"
# Enable the approx feature when testing. # Enable the approx feature when testing.
bevy_math = { path = ".", default-features = false, features = ["approx"] } bevy_math = { path = ".", default-features = false, features = ["approx"] }
glam = { version = "0.29.3", default-features = false, features = ["approx"] } glam = { version = "0.30.1", default-features = false, features = ["approx"] }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
getrandom = { version = "0.3", default-features = false, features = [
"wasm_js",
] }
[features] [features]
default = ["std", "rand", "curve"] default = ["std", "rand", "curve"]

View File

@ -6,7 +6,10 @@ use crate::{
}; };
use alloc::vec::Vec; use alloc::vec::Vec;
use rand::Rng; use rand::Rng;
use rand_distr::{Distribution, WeightedAliasIndex, WeightedError}; use rand_distr::{
weighted::{Error as WeightedError, WeightedAliasIndex},
Distribution,
};
/// A [distribution] that caches data to allow fast sampling from a collection of triangles. /// A [distribution] that caches data to allow fast sampling from a collection of triangles.
/// Generally used through [`sample`] or [`sample_iter`]. /// Generally used through [`sample`] or [`sample_iter`].
@ -19,7 +22,7 @@ use rand_distr::{Distribution, WeightedAliasIndex, WeightedError};
/// ``` /// ```
/// # use bevy_math::{Vec3, primitives::*}; /// # use bevy_math::{Vec3, primitives::*};
/// # use bevy_math::sampling::mesh_sampling::UniformMeshSampler; /// # use bevy_math::sampling::mesh_sampling::UniformMeshSampler;
/// # use rand::{SeedableRng, rngs::StdRng, distributions::Distribution}; /// # use rand::{SeedableRng, rngs::StdRng, distr::Distribution};
/// let faces = Tetrahedron::default().faces(); /// let faces = Tetrahedron::default().faces();
/// let sampler = UniformMeshSampler::try_new(faces).unwrap(); /// let sampler = UniformMeshSampler::try_new(faces).unwrap();
/// let rng = StdRng::seed_from_u64(8765309); /// let rng = StdRng::seed_from_u64(8765309);

View File

@ -8,7 +8,7 @@
//! # use rand::SeedableRng; //! # use rand::SeedableRng;
//! # use rand::rngs::StdRng; //! # use rand::rngs::StdRng;
//! // Get some `Rng`: //! // Get some `Rng`:
//! let rng = &mut StdRng::from_entropy(); //! let rng = &mut StdRng::from_os_rng();
//! // Make a circle of radius 2: //! // Make a circle of radius 2:
//! let circle = Circle::new(2.0); //! let circle = Circle::new(2.0);
//! // Get a point inside this circle uniformly at random: //! // Get a point inside this circle uniformly at random:
@ -23,9 +23,9 @@
//! # use bevy_math::{Vec2, ShapeSample}; //! # use bevy_math::{Vec2, ShapeSample};
//! # use rand::SeedableRng; //! # use rand::SeedableRng;
//! # use rand::rngs::StdRng; //! # use rand::rngs::StdRng;
//! # use rand::distributions::Distribution; //! # use rand::distr::Distribution;
//! # let rng1 = StdRng::from_entropy(); //! # let rng1 = StdRng::from_os_rng();
//! # let rng2 = StdRng::from_entropy(); //! # let rng2 = StdRng::from_os_rng();
//! // Use a rectangle this time: //! // Use a rectangle this time:
//! let rectangle = Rectangle::new(1.0, 2.0); //! let rectangle = Rectangle::new(1.0, 2.0);
//! // Get an iterator that spits out random interior points: //! // Get an iterator that spits out random interior points:
@ -42,10 +42,13 @@ use core::f32::consts::{PI, TAU};
use crate::{ops, primitives::*, NormedVectorSpace, ScalarField, Vec2, Vec3}; use crate::{ops, primitives::*, NormedVectorSpace, ScalarField, Vec2, Vec3};
use rand::{ use rand::{
distributions::{Distribution, WeightedIndex}, distr::{
uniform::SampleUniform,
weighted::{Weight, WeightedIndex},
Distribution,
},
Rng, Rng,
}; };
use rand_distr::uniform::SampleUniform;
/// Exposes methods to uniformly sample a variety of primitive shapes. /// Exposes methods to uniformly sample a variety of primitive shapes.
pub trait ShapeSample { pub trait ShapeSample {
@ -62,7 +65,7 @@ pub trait ShapeSample {
/// let square = Rectangle::new(2.0, 2.0); /// let square = Rectangle::new(2.0, 2.0);
/// ///
/// // Returns a Vec2 with both x and y between -1 and 1. /// // Returns a Vec2 with both x and y between -1 and 1.
/// println!("{}", square.sample_interior(&mut rand::thread_rng())); /// println!("{}", square.sample_interior(&mut rand::rng()));
/// ``` /// ```
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::Output; fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::Output;
@ -77,7 +80,7 @@ pub trait ShapeSample {
/// ///
/// // Returns a Vec2 where one of the coordinates is at ±1, /// // Returns a Vec2 where one of the coordinates is at ±1,
/// // and the other is somewhere between -1 and 1. /// // and the other is somewhere between -1 and 1.
/// println!("{}", square.sample_boundary(&mut rand::thread_rng())); /// println!("{}", square.sample_boundary(&mut rand::rng()));
/// ``` /// ```
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::Output; fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::Output;
@ -87,9 +90,9 @@ pub trait ShapeSample {
/// ///
/// ``` /// ```
/// # use bevy_math::prelude::*; /// # use bevy_math::prelude::*;
/// # use rand::distributions::Distribution; /// # use rand::distr::Distribution;
/// let square = Rectangle::new(2.0, 2.0); /// let square = Rectangle::new(2.0, 2.0);
/// let rng = rand::thread_rng(); /// let rng = rand::rng();
/// ///
/// // Iterate over points randomly drawn from `square`'s interior: /// // Iterate over points randomly drawn from `square`'s interior:
/// for random_val in square.interior_dist().sample_iter(rng).take(5) { /// for random_val in square.interior_dist().sample_iter(rng).take(5) {
@ -109,9 +112,9 @@ pub trait ShapeSample {
/// ///
/// ``` /// ```
/// # use bevy_math::prelude::*; /// # use bevy_math::prelude::*;
/// # use rand::distributions::Distribution; /// # use rand::distr::Distribution;
/// let square = Rectangle::new(2.0, 2.0); /// let square = Rectangle::new(2.0, 2.0);
/// let rng = rand::thread_rng(); /// let rng = rand::rng();
/// ///
/// // Iterate over points randomly drawn from `square`'s boundary: /// // Iterate over points randomly drawn from `square`'s boundary:
/// for random_val in square.boundary_dist().sample_iter(rng).take(5) { /// for random_val in square.boundary_dist().sample_iter(rng).take(5) {
@ -153,15 +156,15 @@ impl ShapeSample for Circle {
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 { fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 {
// https://mathworld.wolfram.com/DiskPointPicking.html // https://mathworld.wolfram.com/DiskPointPicking.html
let theta = rng.gen_range(0.0..TAU); let theta = rng.random_range(0.0..TAU);
let r_squared = rng.gen_range(0.0..=(self.radius * self.radius)); let r_squared = rng.random_range(0.0..=(self.radius * self.radius));
let r = ops::sqrt(r_squared); let r = ops::sqrt(r_squared);
let (sin, cos) = ops::sin_cos(theta); let (sin, cos) = ops::sin_cos(theta);
Vec2::new(r * cos, r * sin) Vec2::new(r * cos, r * sin)
} }
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 { fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 {
let theta = rng.gen_range(0.0..TAU); let theta = rng.random_range(0.0..TAU);
let (sin, cos) = ops::sin_cos(theta); let (sin, cos) = ops::sin_cos(theta);
Vec2::new(self.radius * cos, self.radius * sin) Vec2::new(self.radius * cos, self.radius * sin)
} }
@ -170,8 +173,8 @@ impl ShapeSample for Circle {
/// Boundary sampling for unit-spheres /// Boundary sampling for unit-spheres
#[inline] #[inline]
fn sample_unit_sphere_boundary<R: Rng + ?Sized>(rng: &mut R) -> Vec3 { fn sample_unit_sphere_boundary<R: Rng + ?Sized>(rng: &mut R) -> Vec3 {
let z = rng.gen_range(-1f32..=1f32); let z = rng.random_range(-1f32..=1f32);
let (a_sin, a_cos) = ops::sin_cos(rng.gen_range(-PI..=PI)); let (a_sin, a_cos) = ops::sin_cos(rng.random_range(-PI..=PI));
let c = ops::sqrt(1f32 - z * z); let c = ops::sqrt(1f32 - z * z);
let x = a_sin * c; let x = a_sin * c;
let y = a_cos * c; let y = a_cos * c;
@ -183,7 +186,7 @@ impl ShapeSample for Sphere {
type Output = Vec3; type Output = Vec3;
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 { fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
let r_cubed = rng.gen_range(0.0..=(self.radius * self.radius * self.radius)); let r_cubed = rng.random_range(0.0..=(self.radius * self.radius * self.radius));
let r = ops::cbrt(r_cubed); let r = ops::cbrt(r_cubed);
r * sample_unit_sphere_boundary(rng) r * sample_unit_sphere_boundary(rng)
@ -202,9 +205,10 @@ impl ShapeSample for Annulus {
let outer_radius = self.outer_circle.radius; let outer_radius = self.outer_circle.radius;
// Like random sampling for a circle, radius is weighted by the square. // Like random sampling for a circle, radius is weighted by the square.
let r_squared = rng.gen_range((inner_radius * inner_radius)..(outer_radius * outer_radius)); let r_squared =
rng.random_range((inner_radius * inner_radius)..(outer_radius * outer_radius));
let r = ops::sqrt(r_squared); let r = ops::sqrt(r_squared);
let theta = rng.gen_range(0.0..TAU); let theta = rng.random_range(0.0..TAU);
let (sin, cos) = ops::sin_cos(theta); let (sin, cos) = ops::sin_cos(theta);
Vec2::new(r * cos, r * sin) Vec2::new(r * cos, r * sin)
@ -215,7 +219,7 @@ impl ShapeSample for Annulus {
let inner_prob = (self.inner_circle.perimeter() / total_perimeter) as f64; let inner_prob = (self.inner_circle.perimeter() / total_perimeter) as f64;
// Sample from boundary circles, choosing which one by weighting by perimeter: // Sample from boundary circles, choosing which one by weighting by perimeter:
let inner = rng.gen_bool(inner_prob); let inner = rng.random_bool(inner_prob);
if inner { if inner {
self.inner_circle.sample_boundary(rng) self.inner_circle.sample_boundary(rng)
} else { } else {
@ -248,17 +252,17 @@ impl ShapeSample for Rectangle {
type Output = Vec2; type Output = Vec2;
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 { fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 {
let x = rng.gen_range(-self.half_size.x..=self.half_size.x); let x = rng.random_range(-self.half_size.x..=self.half_size.x);
let y = rng.gen_range(-self.half_size.y..=self.half_size.y); let y = rng.random_range(-self.half_size.y..=self.half_size.y);
Vec2::new(x, y) Vec2::new(x, y)
} }
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 { fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 {
let primary_side = rng.gen_range(-1.0..1.0); let primary_side = rng.random_range(-1.0..1.0);
let other_side = if rng.r#gen() { -1.0 } else { 1.0 }; let other_side = if rng.random() { -1.0 } else { 1.0 };
if self.half_size.x + self.half_size.y > 0.0 { if self.half_size.x + self.half_size.y > 0.0 {
if rng.gen_bool((self.half_size.x / (self.half_size.x + self.half_size.y)) as f64) { if rng.random_bool((self.half_size.x / (self.half_size.x + self.half_size.y)) as f64) {
Vec2::new(primary_side, other_side) * self.half_size Vec2::new(primary_side, other_side) * self.half_size
} else { } else {
Vec2::new(other_side, primary_side) * self.half_size Vec2::new(other_side, primary_side) * self.half_size
@ -273,16 +277,16 @@ impl ShapeSample for Cuboid {
type Output = Vec3; type Output = Vec3;
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 { fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
let x = rng.gen_range(-self.half_size.x..=self.half_size.x); let x = rng.random_range(-self.half_size.x..=self.half_size.x);
let y = rng.gen_range(-self.half_size.y..=self.half_size.y); let y = rng.random_range(-self.half_size.y..=self.half_size.y);
let z = rng.gen_range(-self.half_size.z..=self.half_size.z); let z = rng.random_range(-self.half_size.z..=self.half_size.z);
Vec3::new(x, y, z) Vec3::new(x, y, z)
} }
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 { fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
let primary_side1 = rng.gen_range(-1.0..1.0); let primary_side1 = rng.random_range(-1.0..1.0);
let primary_side2 = rng.gen_range(-1.0..1.0); let primary_side2 = rng.random_range(-1.0..1.0);
let other_side = if rng.r#gen() { -1.0 } else { 1.0 }; let other_side = if rng.random() { -1.0 } else { 1.0 };
if let Ok(dist) = WeightedIndex::new([ if let Ok(dist) = WeightedIndex::new([
self.half_size.y * self.half_size.z, self.half_size.y * self.half_size.z,
@ -314,8 +318,8 @@ where
// Generate random points on a parallelepiped and reflect so that // Generate random points on a parallelepiped and reflect so that
// we can use the points that lie outside the triangle // we can use the points that lie outside the triangle
let u = rng.gen_range(P::Scalar::ZERO..=P::Scalar::ONE); let u = rng.random_range(P::Scalar::ZERO..=P::Scalar::ONE);
let v = rng.gen_range(P::Scalar::ZERO..=P::Scalar::ONE); let v = rng.random_range(P::Scalar::ZERO..=P::Scalar::ONE);
if u + v > P::Scalar::ONE { if u + v > P::Scalar::ONE {
let u1 = P::Scalar::ONE - v; let u1 = P::Scalar::ONE - v;
@ -330,7 +334,7 @@ where
fn sample_triangle_boundary<P, R>(vertices: [P; 3], rng: &mut R) -> P fn sample_triangle_boundary<P, R>(vertices: [P; 3], rng: &mut R) -> P
where where
P: NormedVectorSpace, P: NormedVectorSpace,
P::Scalar: SampleUniform + PartialOrd + for<'a> ::core::ops::AddAssign<&'a P::Scalar>, P::Scalar: Weight + SampleUniform + PartialOrd + for<'a> ::core::ops::AddAssign<&'a P::Scalar>,
R: Rng + ?Sized, R: Rng + ?Sized,
{ {
let [a, b, c] = vertices; let [a, b, c] = vertices;
@ -338,7 +342,7 @@ where
let ac = c - a; let ac = c - a;
let bc = c - b; let bc = c - b;
let t = rng.gen_range(P::Scalar::ZERO..=P::Scalar::ONE); let t = rng.random_range(<P::Scalar as ScalarField>::ZERO..=P::Scalar::ONE);
if let Ok(dist) = WeightedIndex::new([ab.norm(), ac.norm(), bc.norm()]) { if let Ok(dist) = WeightedIndex::new([ab.norm(), ac.norm(), bc.norm()]) {
match dist.sample(rng) { match dist.sample(rng) {
@ -386,9 +390,9 @@ impl ShapeSample for Tetrahedron {
// Generate a random point in a cube: // Generate a random point in a cube:
let mut coords: [f32; 3] = [ let mut coords: [f32; 3] = [
rng.gen_range(0.0..1.0), rng.random_range(0.0..1.0),
rng.gen_range(0.0..1.0), rng.random_range(0.0..1.0),
rng.gen_range(0.0..1.0), rng.random_range(0.0..1.0),
]; ];
// The cube is broken into six tetrahedra of the form 0 <= c_0 <= c_1 <= c_2 <= 1, // The cube is broken into six tetrahedra of the form 0 <= c_0 <= c_1 <= c_2 <= 1,
@ -440,7 +444,7 @@ impl ShapeSample for Cylinder {
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 { fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
let Vec2 { x, y: z } = self.base().sample_interior(rng); let Vec2 { x, y: z } = self.base().sample_interior(rng);
let y = rng.gen_range(-self.half_height..=self.half_height); let y = rng.random_range(-self.half_height..=self.half_height);
Vec3::new(x, y, z) Vec3::new(x, y, z)
} }
@ -448,16 +452,16 @@ impl ShapeSample for Cylinder {
// This uses the area of the ends divided by the overall surface area (optimized) // This uses the area of the ends divided by the overall surface area (optimized)
// [2 (\pi r^2)]/[2 (\pi r^2) + 2 \pi r h] = r/(r + h) // [2 (\pi r^2)]/[2 (\pi r^2) + 2 \pi r h] = r/(r + h)
if self.radius + 2.0 * self.half_height > 0.0 { if self.radius + 2.0 * self.half_height > 0.0 {
if rng.gen_bool((self.radius / (self.radius + 2.0 * self.half_height)) as f64) { if rng.random_bool((self.radius / (self.radius + 2.0 * self.half_height)) as f64) {
let Vec2 { x, y: z } = self.base().sample_interior(rng); let Vec2 { x, y: z } = self.base().sample_interior(rng);
if rng.r#gen() { if rng.random() {
Vec3::new(x, self.half_height, z) Vec3::new(x, self.half_height, z)
} else { } else {
Vec3::new(x, -self.half_height, z) Vec3::new(x, -self.half_height, z)
} }
} else { } else {
let Vec2 { x, y: z } = self.base().sample_boundary(rng); let Vec2 { x, y: z } = self.base().sample_boundary(rng);
let y = rng.gen_range(-self.half_height..=self.half_height); let y = rng.random_range(-self.half_height..=self.half_height);
Vec3::new(x, y, z) Vec3::new(x, y, z)
} }
} else { } else {
@ -474,7 +478,7 @@ impl ShapeSample for Capsule2d {
let capsule_area = rectangle_area + PI * self.radius * self.radius; let capsule_area = rectangle_area + PI * self.radius * self.radius;
if capsule_area > 0.0 { if capsule_area > 0.0 {
// Check if the random point should be inside the rectangle // Check if the random point should be inside the rectangle
if rng.gen_bool((rectangle_area / capsule_area) as f64) { if rng.random_bool((rectangle_area / capsule_area) as f64) {
self.to_inner_rectangle().sample_interior(rng) self.to_inner_rectangle().sample_interior(rng)
} else { } else {
let circle = Circle::new(self.radius); let circle = Circle::new(self.radius);
@ -495,9 +499,9 @@ impl ShapeSample for Capsule2d {
let rectangle_surface = 4.0 * self.half_length; let rectangle_surface = 4.0 * self.half_length;
let capsule_surface = rectangle_surface + TAU * self.radius; let capsule_surface = rectangle_surface + TAU * self.radius;
if capsule_surface > 0.0 { if capsule_surface > 0.0 {
if rng.gen_bool((rectangle_surface / capsule_surface) as f64) { if rng.random_bool((rectangle_surface / capsule_surface) as f64) {
let side_distance = let side_distance =
rng.gen_range((-2.0 * self.half_length)..=(2.0 * self.half_length)); rng.random_range((-2.0 * self.half_length)..=(2.0 * self.half_length));
if side_distance < 0.0 { if side_distance < 0.0 {
Vec2::new(self.radius, side_distance + self.half_length) Vec2::new(self.radius, side_distance + self.half_length)
} else { } else {
@ -528,7 +532,7 @@ impl ShapeSample for Capsule3d {
let capsule_vol = cylinder_vol + 4.0 / 3.0 * PI * self.radius * self.radius * self.radius; let capsule_vol = cylinder_vol + 4.0 / 3.0 * PI * self.radius * self.radius * self.radius;
if capsule_vol > 0.0 { if capsule_vol > 0.0 {
// Check if the random point should be inside the cylinder // Check if the random point should be inside the cylinder
if rng.gen_bool((cylinder_vol / capsule_vol) as f64) { if rng.random_bool((cylinder_vol / capsule_vol) as f64) {
self.to_cylinder().sample_interior(rng) self.to_cylinder().sample_interior(rng)
} else { } else {
let sphere = Sphere::new(self.radius); let sphere = Sphere::new(self.radius);
@ -549,9 +553,9 @@ impl ShapeSample for Capsule3d {
let cylinder_surface = TAU * self.radius * 2.0 * self.half_length; let cylinder_surface = TAU * self.radius * 2.0 * self.half_length;
let capsule_surface = cylinder_surface + 4.0 * PI * self.radius * self.radius; let capsule_surface = cylinder_surface + 4.0 * PI * self.radius * self.radius;
if capsule_surface > 0.0 { if capsule_surface > 0.0 {
if rng.gen_bool((cylinder_surface / capsule_surface) as f64) { if rng.random_bool((cylinder_surface / capsule_surface) as f64) {
let Vec2 { x, y: z } = Circle::new(self.radius).sample_boundary(rng); let Vec2 { x, y: z } = Circle::new(self.radius).sample_boundary(rng);
let y = rng.gen_range(-self.half_length..=self.half_length); let y = rng.random_range(-self.half_length..=self.half_length);
Vec3::new(x, y, z) Vec3::new(x, y, z)
} else { } else {
let sphere = Sphere::new(self.radius); let sphere = Sphere::new(self.radius);
@ -574,7 +578,7 @@ impl<P: Primitive2d + Measured2d + ShapeSample<Output = Vec2>> ShapeSample for E
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::Output { fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Self::Output {
let base_point = self.base_shape.sample_interior(rng); let base_point = self.base_shape.sample_interior(rng);
let depth = rng.gen_range(-self.half_depth..self.half_depth); let depth = rng.random_range(-self.half_depth..self.half_depth);
base_point.extend(depth) base_point.extend(depth)
} }
@ -582,7 +586,7 @@ impl<P: Primitive2d + Measured2d + ShapeSample<Output = Vec2>> ShapeSample for E
let base_area = self.base_shape.area(); let base_area = self.base_shape.area();
let total_area = self.area(); let total_area = self.area();
let random = rng.gen_range(0.0..total_area); let random = rng.random_range(0.0..total_area);
match random { match random {
x if x < base_area => self.base_shape.sample_interior(rng).extend(self.half_depth), x if x < base_area => self.base_shape.sample_interior(rng).extend(self.half_depth),
x if x < 2. * base_area => self x if x < 2. * base_area => self
@ -592,7 +596,7 @@ impl<P: Primitive2d + Measured2d + ShapeSample<Output = Vec2>> ShapeSample for E
_ => self _ => self
.base_shape .base_shape
.sample_boundary(rng) .sample_boundary(rng)
.extend(rng.gen_range(-self.half_depth..self.half_depth)), .extend(rng.random_range(-self.half_depth..self.half_depth)),
} }
} }
} }

View File

@ -1,24 +1,24 @@
//! This module holds local implementations of the [`Distribution`] trait for [`Standard`], which //! This module holds local implementations of the [`Distribution`] trait for [`StandardUniform`], which
//! allow certain Bevy math types (those whose values can be randomly generated without additional //! allow certain Bevy math types (those whose values can be randomly generated without additional
//! input other than an [`Rng`]) to be produced using [`rand`]'s APIs. It also holds [`FromRng`], //! input other than an [`Rng`]) to be produced using [`rand`]'s APIs. It also holds [`FromRng`],
//! an ergonomic extension to that functionality which permits the omission of type annotations. //! an ergonomic extension to that functionality which permits the omission of type annotations.
//! //!
//! For instance: //! For instance:
//! ``` //! ```
//! # use rand::{random, Rng, SeedableRng, rngs::StdRng, distributions::Standard}; //! # use rand::{random, Rng, SeedableRng, rngs::StdRng, distr::StandardUniform};
//! # use bevy_math::{Dir3, sampling::FromRng}; //! # use bevy_math::{Dir3, sampling::FromRng};
//! let mut rng = StdRng::seed_from_u64(7313429298); //! let mut rng = StdRng::seed_from_u64(7313429298);
//! // Random direction using thread-local rng //! // Random direction using thread-local rng
//! let random_direction1: Dir3 = random(); //! let random_direction1: Dir3 = random();
//! //!
//! // Random direction using the rng constructed above //! // Random direction using the rng constructed above
//! let random_direction2: Dir3 = rng.r#gen(); //! let random_direction2: Dir3 = rng.random();
//! //!
//! // The same as the previous but with different syntax //! // The same as the previous but with different syntax
//! let random_direction3 = Dir3::from_rng(&mut rng); //! let random_direction3 = Dir3::from_rng(&mut rng);
//! //!
//! // Five random directions, using Standard explicitly //! // Five random directions, using StandardUniform explicitly
//! let many_random_directions: Vec<Dir3> = rng.sample_iter(Standard).take(5).collect(); //! let many_random_directions: Vec<Dir3> = rng.sample_iter(StandardUniform).take(5).collect();
//! ``` //! ```
use core::f32::consts::TAU; use core::f32::consts::TAU;
@ -28,11 +28,11 @@ use crate::{
Dir2, Dir3, Dir3A, Quat, Rot2, ShapeSample, Vec3A, Dir2, Dir3, Dir3A, Quat, Rot2, ShapeSample, Vec3A,
}; };
use rand::{ use rand::{
distributions::{Distribution, Standard}, distr::{Distribution, StandardUniform},
Rng, Rng,
}; };
/// Ergonomics trait for a type with a [`Standard`] distribution, allowing values to be generated /// Ergonomics trait for a type with a [`StandardUniform`] distribution, allowing values to be generated
/// uniformly from an [`Rng`] by a method in its own namespace. /// uniformly from an [`Rng`] by a method in its own namespace.
/// ///
/// Example /// Example
@ -45,15 +45,15 @@ use rand::{
pub trait FromRng pub trait FromRng
where where
Self: Sized, Self: Sized,
Standard: Distribution<Self>, StandardUniform: Distribution<Self>,
{ {
/// Construct a value of this type uniformly at random using `rng` as the source of randomness. /// Construct a value of this type uniformly at random using `rng` as the source of randomness.
fn from_rng<R: Rng + ?Sized>(rng: &mut R) -> Self { fn from_rng<R: Rng + ?Sized>(rng: &mut R) -> Self {
rng.r#gen() rng.random()
} }
} }
impl Distribution<Dir2> for Standard { impl Distribution<Dir2> for StandardUniform {
#[inline] #[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir2 { fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir2 {
let circle = Circle::new(1.0); let circle = Circle::new(1.0);
@ -64,7 +64,7 @@ impl Distribution<Dir2> for Standard {
impl FromRng for Dir2 {} impl FromRng for Dir2 {}
impl Distribution<Dir3> for Standard { impl Distribution<Dir3> for StandardUniform {
#[inline] #[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir3 { fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir3 {
let sphere = Sphere::new(1.0); let sphere = Sphere::new(1.0);
@ -75,7 +75,7 @@ impl Distribution<Dir3> for Standard {
impl FromRng for Dir3 {} impl FromRng for Dir3 {}
impl Distribution<Dir3A> for Standard { impl Distribution<Dir3A> for StandardUniform {
#[inline] #[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir3A { fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir3A {
let sphere = Sphere::new(1.0); let sphere = Sphere::new(1.0);
@ -86,10 +86,10 @@ impl Distribution<Dir3A> for Standard {
impl FromRng for Dir3A {} impl FromRng for Dir3A {}
impl Distribution<Rot2> for Standard { impl Distribution<Rot2> for StandardUniform {
#[inline] #[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Rot2 { fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Rot2 {
let angle = rng.gen_range(0.0..TAU); let angle = rng.random_range(0.0..TAU);
Rot2::radians(angle) Rot2::radians(angle)
} }
} }

View File

@ -30,7 +30,7 @@ wgpu-types = { version = "25", default-features = false }
serde = { version = "1", default-features = false, features = [ serde = { version = "1", default-features = false, features = [
"derive", "derive",
], optional = true } ], optional = true }
hexasphere = "15.0" hexasphere = "16.0"
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
tracing = { version = "0.1", default-features = false, features = ["std"] } tracing = { version = "0.1", default-features = false, features = ["std"] }
derive_more = { version = "2", default-features = false, features = ["from"] } derive_more = { version = "2", default-features = false, features = ["from"] }

View File

@ -22,7 +22,7 @@ std = ["glam/std"]
libm = ["glam/libm", "dep:libm"] libm = ["glam/libm", "dep:libm"]
[dependencies] [dependencies]
glam = { version = "0.29.3", default-features = false } glam = { version = "0.30.1", default-features = false }
libm = { version = "0.2", default-features = false, optional = true } libm = { version = "0.2", default-features = false, optional = true }
[[example]] [[example]]

View File

@ -65,8 +65,8 @@ rayon = { version = "1", default-features = false, optional = true }
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
web-time = { version = "1.1", default-features = false, optional = true } web-time = { version = "1.1", default-features = false, optional = true }
getrandom = { version = "0.2.0", default-features = false, optional = true, features = [ getrandom = { version = "0.3.0", default-features = false, optional = true, features = [
"js", "wasm_js",
] } ] }
[target.'cfg(not(all(target_has_atomic = "8", target_has_atomic = "16", target_has_atomic = "32", target_has_atomic = "64", target_has_atomic = "ptr")))'.dependencies] [target.'cfg(not(all(target_has_atomic = "8", target_has_atomic = "16", target_has_atomic = "32", target_has_atomic = "64", target_has_atomic = "ptr")))'.dependencies]

View File

@ -97,7 +97,7 @@ derive_more = { version = "2", default-features = false, features = ["from"] }
serde = { version = "1", default-features = false, features = ["alloc"] } serde = { version = "1", default-features = false, features = ["alloc"] }
assert_type_match = "0.1.1" assert_type_match = "0.1.1"
smallvec = { version = "1", default-features = false, optional = true } smallvec = { version = "1", default-features = false, optional = true }
glam = { version = "0.29.3", default-features = false, features = [ glam = { version = "0.30.1", default-features = false, features = [
"serde", "serde",
], optional = true } ], optional = true }
petgraph = { version = "0.8", features = ["serde-1"], optional = true } petgraph = { version = "0.8", features = ["serde-1"], optional = true }

View File

@ -108,7 +108,7 @@ downcast-rs = { version = "2", default-features = false, features = ["std"] }
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
derive_more = { version = "2", default-features = false, features = ["from"] } derive_more = { version = "2", default-features = false, features = ["from"] }
futures-lite = "2.0.1" futures-lite = "2.0.1"
encase = { version = "0.10", features = ["glam"] } encase = { version = "0.11", features = ["glam"] }
# For wgpu profiling using tracing. Use `RUST_LOG=info` to also capture the wgpu spans. # For wgpu profiling using tracing. Use `RUST_LOG=info` to also capture the wgpu spans.
profiling = { version = "1", features = [ profiling = { version = "1", features = [
"profile-with-tracing", "profile-with-tracing",

View File

@ -102,9 +102,9 @@ fn draw(
if *i == 0 { if *i == 0 {
// Generate a random color on first run. // Generate a random color on first run.
*draw_color = Color::linear_rgb( *draw_color = Color::linear_rgb(
seeded_rng.0.r#gen(), seeded_rng.0.random(),
seeded_rng.0.r#gen(), seeded_rng.0.random(),
seeded_rng.0.r#gen(), seeded_rng.0.random(),
); );
} }
@ -129,9 +129,9 @@ fn draw(
let tolerance = 1.0 / 255.0; let tolerance = 1.0 / 255.0;
if old_color.distance(&draw_color) <= tolerance { if old_color.distance(&draw_color) <= tolerance {
*draw_color = Color::linear_rgb( *draw_color = Color::linear_rgb(
seeded_rng.0.r#gen(), seeded_rng.0.random(),
seeded_rng.0.r#gen(), seeded_rng.0.random(),
seeded_rng.0.r#gen(), seeded_rng.0.random(),
); );
} }

View File

@ -29,7 +29,7 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>) {
let chunk_size = UVec2::splat(64); let chunk_size = UVec2::splat(64);
let tile_display_size = UVec2::splat(8); let tile_display_size = UVec2::splat(8);
let indices: Vec<Option<u16>> = (0..chunk_size.element_product()) let indices: Vec<Option<u16>> = (0..chunk_size.element_product())
.map(|_| rng.gen_range(0..5)) .map(|_| rng.random_range(0..5))
.map(|i| if i == 0 { None } else { Some(i - 1) }) .map(|i| if i == 0 { None } else { Some(i - 1) })
.collect(); .collect();
@ -73,8 +73,8 @@ fn update_tilemap(
if timer.just_finished() { if timer.just_finished() {
for _ in 0..50 { for _ in 0..50 {
let index = rng.gen_range(0..indices.len()); let index = rng.random_range(0..indices.len());
indices[index] = Some(rng.gen_range(0..5)); indices[index] = Some(rng.random_range(0..5));
} }
} }
} }

View File

@ -64,9 +64,9 @@ fn setup(
let mut rng = ChaCha8Rng::seed_from_u64(19878367467713); let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
for i in 0..num_obs { for i in 0..num_obs {
for j in 0..num_obs { for j in 0..num_obs {
let rotation_axis: [f32; 3] = rng.r#gen(); let rotation_axis: [f32; 3] = rng.random();
let rotation_vec: Vec3 = rotation_axis.into(); let rotation_vec: Vec3 = rotation_axis.into();
let rotation: u32 = rng.gen_range(0..360); let rotation: u32 = rng.random_range(0..360);
let transform = Transform::from_xyz( let transform = Transform::from_xyz(
(-num_obs + 1) as f32 / 2.0 + i as f32, (-num_obs + 1) as f32 / 2.0 + i as f32,
-0.2, -0.2,

View File

@ -57,9 +57,9 @@ fn setup(
commands.spawn_batch( commands.spawn_batch(
std::iter::repeat_with(move || { std::iter::repeat_with(move || {
let x = rng.gen_range(-5.0..5.0); let x = rng.random_range(-5.0..5.0);
let y = rng.gen_range(0.0..3.0); let y = rng.random_range(0.0..3.0);
let z = rng.gen_range(-5.0..5.0); let z = rng.random_range(-5.0..5.0);
( (
Mesh3d(cube_mesh.clone()), Mesh3d(cube_mesh.clone()),

View File

@ -50,14 +50,14 @@ fn observe_on_step(
let translation = transforms.get(trigger.target()).unwrap().translation(); let translation = transforms.get(trigger.target()).unwrap().translation();
// Spawn a bunch of particles. // Spawn a bunch of particles.
for _ in 0..14 { for _ in 0..14 {
let horizontal = seeded_rng.0.r#gen::<Dir2>() * seeded_rng.0.gen_range(8.0..12.0); let horizontal = seeded_rng.0.random::<Dir2>() * seeded_rng.0.random_range(8.0..12.0);
let vertical = seeded_rng.0.gen_range(0.0..4.0); let vertical = seeded_rng.0.random_range(0.0..4.0);
let size = seeded_rng.0.gen_range(0.2..1.0); let size = seeded_rng.0.random_range(0.2..1.0);
commands.spawn(( commands.spawn((
Particle { Particle {
lifetime_timer: Timer::from_seconds( lifetime_timer: Timer::from_seconds(
seeded_rng.0.gen_range(0.2..0.6), seeded_rng.0.random_range(0.2..0.6),
TimerMode::Once, TimerMode::Once,
), ),
size, size,

View File

@ -169,9 +169,9 @@ fn setup(
Mesh3d(mesh.clone()), Mesh3d(mesh.clone()),
MeshMaterial3d(materials.add(StandardMaterial { MeshMaterial3d(materials.add(StandardMaterial {
base_color: Color::srgb( base_color: Color::srgb(
rng.gen_range(0.0..1.0), rng.random_range(0.0..1.0),
rng.gen_range(0.0..1.0), rng.random_range(0.0..1.0),
rng.gen_range(0.0..1.0), rng.random_range(0.0..1.0),
), ),
base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")), base_color_texture: Some(asset_server.load("textures/uv_checker_bw.png")),
..default() ..default()

View File

@ -59,7 +59,7 @@ fn spawn_tasks(mut commands: Commands) {
// spawn() can be used to poll for the result // spawn() can be used to poll for the result
let entity = commands.spawn_empty().id(); let entity = commands.spawn_empty().id();
let task = thread_pool.spawn(async move { let task = thread_pool.spawn(async move {
let duration = Duration::from_secs_f32(rand::thread_rng().gen_range(0.05..5.0)); let duration = Duration::from_secs_f32(rand::rng().random_range(0.05..5.0));
// Pretend this is a time-intensive function. :) // Pretend this is a time-intensive function. :)
async_std::task::sleep(duration).await; async_std::task::sleep(duration).await;

View File

@ -36,7 +36,7 @@ fn setup(mut commands: Commands) {
// This is where you could connect to an external data source // This is where you could connect to an external data source
// This will block until the previous value has been read in system `read_stream` // This will block until the previous value has been read in system `read_stream`
tx.send(rng.gen_range(0..2000)).unwrap(); tx.send(rng.random_range(0..2000)).unwrap();
} }
}); });

View File

@ -34,7 +34,7 @@ fn setup(mut commands: Commands) {
fn change_component(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) { fn change_component(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) {
for (entity, mut component) in &mut query { for (entity, mut component) in &mut query {
if rand::thread_rng().gen_bool(0.1) { if rand::rng().random_bool(0.1) {
let new_component = MyComponent(time.elapsed_secs().round()); let new_component = MyComponent(time.elapsed_secs().round());
info!("New value: {new_component:?} {entity}"); info!("New value: {new_component:?} {entity}");
// Change detection occurs on mutable dereference, and does not consider whether or not // Change detection occurs on mutable dereference, and does not consider whether or not
@ -51,7 +51,7 @@ fn change_component(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)
/// locations. /// locations.
fn change_component_2(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) { fn change_component_2(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) {
for (entity, mut component) in &mut query { for (entity, mut component) in &mut query {
if rand::thread_rng().gen_bool(0.1) { if rand::rng().random_bool(0.1) {
let new_component = MyComponent(time.elapsed_secs().round()); let new_component = MyComponent(time.elapsed_secs().round());
info!("New value: {new_component:?} {entity}"); info!("New value: {new_component:?} {entity}");
component.set_if_neq(new_component); component.set_if_neq(new_component);
@ -61,7 +61,7 @@ fn change_component_2(time: Res<Time>, mut query: Query<(Entity, &mut MyComponen
/// Change detection concepts for components apply similarly to resources. /// Change detection concepts for components apply similarly to resources.
fn change_resource(time: Res<Time>, mut my_resource: ResMut<MyResource>) { fn change_resource(time: Res<Time>, mut my_resource: ResMut<MyResource>) {
if rand::thread_rng().gen_bool(0.1) { if rand::rng().random_bool(0.1) {
let new_resource = MyResource(time.elapsed_secs().round()); let new_resource = MyResource(time.elapsed_secs().round());
info!("New value: {new_resource:?}"); info!("New value: {new_resource:?}");
my_resource.set_if_neq(new_resource); my_resource.set_if_neq(new_resource);

View File

@ -5,7 +5,7 @@ use bevy::ecs::{error::warn, world::DeferredWorld};
use bevy::math::sampling::UniformMeshSampler; use bevy::math::sampling::UniformMeshSampler;
use bevy::prelude::*; use bevy::prelude::*;
use rand::distributions::Distribution; use rand::distr::Distribution;
use rand::SeedableRng; use rand::SeedableRng;
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;

View File

@ -91,15 +91,18 @@ fn user_input(
keyboard_input: Res<ButtonInput<KeyCode>>, keyboard_input: Res<ButtonInput<KeyCode>>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
) { ) {
let mut rng = rand::thread_rng(); let mut rng = rand::rng();
if keyboard_input.just_pressed(KeyCode::KeyA) { if keyboard_input.just_pressed(KeyCode::KeyA) {
let texture = asset_server.load("textures/simplespace/enemy_A.png"); let texture = asset_server.load("textures/simplespace/enemy_A.png");
commands.spawn(( commands.spawn((
Enemy { Enemy {
origin: Vec2::new(rng.gen_range(-200.0..200.0), rng.gen_range(-200.0..200.0)), origin: Vec2::new(
radius: rng.gen_range(50.0..150.0), rng.random_range(-200.0..200.0),
rotation: rng.gen_range(0.0..std::f32::consts::TAU), rng.random_range(-200.0..200.0),
rotation_speed: rng.gen_range(0.5..1.5), ),
radius: rng.random_range(50.0..150.0),
rotation: rng.random_range(0.0..std::f32::consts::TAU),
rotation_speed: rng.random_range(0.5..1.5),
}, },
Sprite { Sprite {
image: texture, image: texture,

View File

@ -50,34 +50,34 @@ fn generate_bodies(
// This isn't strictly required in practical use unless you need your app to be deterministic. // This isn't strictly required in practical use unless you need your app to be deterministic.
let mut rng = ChaCha8Rng::seed_from_u64(19878367467713); let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
for _ in 0..NUM_BODIES { for _ in 0..NUM_BODIES {
let radius: f32 = rng.gen_range(0.1..0.7); let radius: f32 = rng.random_range(0.1..0.7);
let mass_value = FloatPow::cubed(radius) * 10.; let mass_value = FloatPow::cubed(radius) * 10.;
let position = Vec3::new( let position = Vec3::new(
rng.gen_range(-1.0..1.0), rng.random_range(-1.0..1.0),
rng.gen_range(-1.0..1.0), rng.random_range(-1.0..1.0),
rng.gen_range(-1.0..1.0), rng.random_range(-1.0..1.0),
) )
.normalize() .normalize()
* ops::cbrt(rng.gen_range(0.2f32..1.0)) * ops::cbrt(rng.random_range(0.2f32..1.0))
* 15.; * 15.;
commands.spawn(( commands.spawn((
BodyBundle { BodyBundle {
mesh: Mesh3d(mesh.clone()), mesh: Mesh3d(mesh.clone()),
material: MeshMaterial3d(materials.add(Color::srgb( material: MeshMaterial3d(materials.add(Color::srgb(
rng.gen_range(color_range.clone()), rng.random_range(color_range.clone()),
rng.gen_range(color_range.clone()), rng.random_range(color_range.clone()),
rng.gen_range(color_range.clone()), rng.random_range(color_range.clone()),
))), ))),
mass: Mass(mass_value), mass: Mass(mass_value),
acceleration: Acceleration(Vec3::ZERO), acceleration: Acceleration(Vec3::ZERO),
last_pos: LastPos( last_pos: LastPos(
position position
- Vec3::new( - Vec3::new(
rng.gen_range(vel_range.clone()), rng.random_range(vel_range.clone()),
rng.gen_range(vel_range.clone()), rng.random_range(vel_range.clone()),
rng.gen_range(vel_range.clone()), rng.random_range(vel_range.clone()),
) * time.timestep().as_secs_f32(), ) * time.timestep().as_secs_f32(),
), ),
}, },

View File

@ -3,7 +3,7 @@
use std::time::Duration; use std::time::Duration;
use bevy::{log::LogPlugin, prelude::*, time::common_conditions::on_timer}; use bevy::{log::LogPlugin, prelude::*, time::common_conditions::on_timer};
use rand::{seq::IteratorRandom, thread_rng, Rng}; use rand::{rng, seq::IteratorRandom, Rng};
fn main() { fn main() {
App::new() App::new()
@ -69,9 +69,9 @@ struct Armor(u16);
/// A normal bevy system that attacks a piece of the goblin's armor on a timer. /// A normal bevy system that attacks a piece of the goblin's armor on a timer.
fn attack_armor(entities: Query<Entity, With<Armor>>, mut commands: Commands) { fn attack_armor(entities: Query<Entity, With<Armor>>, mut commands: Commands) {
let mut rng = thread_rng(); let mut rng = rng();
if let Some(target) = entities.iter().choose(&mut rng) { if let Some(target) = entities.iter().choose(&mut rng) {
let damage = rng.gen_range(1..20); let damage = rng.random_range(1..20);
commands.trigger_targets(Attack { damage }, target); commands.trigger_targets(Attack { damage }, target);
info!("⚔️ Attack for {} damage", damage); info!("⚔️ Attack for {} damage", damage);
} }

View File

@ -52,10 +52,10 @@ impl Mine {
fn random(rand: &mut ChaCha8Rng) -> Self { fn random(rand: &mut ChaCha8Rng) -> Self {
Mine { Mine {
pos: Vec2::new( pos: Vec2::new(
(rand.r#gen::<f32>() - 0.5) * 1200.0, (rand.random::<f32>() - 0.5) * 1200.0,
(rand.r#gen::<f32>() - 0.5) * 600.0, (rand.random::<f32>() - 0.5) * 600.0,
), ),
size: 4.0 + rand.r#gen::<f32>() * 16.0, size: 4.0 + rand.random::<f32>() * 16.0,
} }
} }
} }

View File

@ -19,7 +19,7 @@ fn spawn_system(mut commands: Commands, asset_server: Res<AssetServer>) {
Sprite::from_image(texture.clone()), Sprite::from_image(texture.clone()),
Transform::from_scale(Vec3::splat(0.1)) Transform::from_scale(Vec3::splat(0.1))
.with_translation(Vec2::splat(0.0).extend(z as f32)), .with_translation(Vec2::splat(0.0).extend(z as f32)),
Velocity(20.0 * Vec2::new(rng.r#gen::<f32>() - 0.5, rng.r#gen::<f32>() - 0.5)), Velocity(20.0 * Vec2::new(rng.random::<f32>() - 0.5, rng.random::<f32>() - 0.5)),
)); ));
} }
} }

View File

@ -109,7 +109,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut game: ResMu
// This isn't strictly required in practical use unless you need your app to be deterministic. // This isn't strictly required in practical use unless you need your app to be deterministic.
ChaCha8Rng::seed_from_u64(19878367467713) ChaCha8Rng::seed_from_u64(19878367467713)
} else { } else {
ChaCha8Rng::from_entropy() ChaCha8Rng::from_os_rng()
}; };
// reset the game state // reset the game state
@ -137,7 +137,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut game: ResMu
.map(|j| { .map(|j| {
(0..BOARD_SIZE_I) (0..BOARD_SIZE_I)
.map(|i| { .map(|i| {
let height = rng.gen_range(-0.1..0.1); let height = rng.random_range(-0.1..0.1);
commands.spawn(( commands.spawn((
DespawnOnExitState(GameState::Playing), DespawnOnExitState(GameState::Playing),
Transform::from_xyz(i as f32, height - 0.2, j as f32), Transform::from_xyz(i as f32, height - 0.2, j as f32),
@ -330,8 +330,8 @@ fn spawn_bonus(
// ensure bonus doesn't spawn on the player // ensure bonus doesn't spawn on the player
loop { loop {
game.bonus.i = rng.gen_range(0..BOARD_SIZE_I); game.bonus.i = rng.random_range(0..BOARD_SIZE_I);
game.bonus.j = rng.gen_range(0..BOARD_SIZE_J); game.bonus.j = rng.random_range(0..BOARD_SIZE_J);
if game.bonus.i != game.player.i || game.bonus.j != game.player.j { if game.bonus.i != game.player.i || game.bonus.j != game.player.j {
break; break;
} }

View File

@ -96,16 +96,16 @@ fn setup_contributor_selection(
for (name, num_commits) in contribs { for (name, num_commits) in contribs {
let transform = Transform::from_xyz( let transform = Transform::from_xyz(
rng.gen_range(-400.0..400.0), rng.random_range(-400.0..400.0),
rng.gen_range(0.0..400.0), rng.random_range(0.0..400.0),
rng.r#gen(), rng.random(),
); );
let dir = rng.gen_range(-1.0..1.0); let dir = rng.random_range(-1.0..1.0);
let velocity = Vec3::new(dir * 500.0, 0.0, 0.0); let velocity = Vec3::new(dir * 500.0, 0.0, 0.0);
let hue = name_to_hue(&name); let hue = name_to_hue(&name);
// Some sprites should be flipped for variety // Some sprites should be flipped for variety
let flipped = rng.r#gen(); let flipped = rng.random();
let entity = commands let entity = commands
.spawn(( .spawn((
@ -274,7 +274,7 @@ fn collisions(
transform.translation.y = collision_area.min.y; transform.translation.y = collision_area.min.y;
// How high this birb will bounce. // How high this birb will bounce.
let bounce_height = rng.gen_range(min_bounce_height..=max_bounce_height); let bounce_height = rng.random_range(min_bounce_height..=max_bounce_height);
// Apply the velocity that would bounce the birb up to bounce_height. // Apply the velocity that would bounce the birb up to bounce_height.
velocity.translation.y = (bounce_height * GRAVITY * 2.).sqrt(); velocity.translation.y = (bounce_height * GRAVITY * 2.).sqrt();

View File

@ -147,22 +147,22 @@ fn random_transform(rng: &mut impl Rng) -> Transform {
} }
fn random_translation(rng: &mut impl Rng) -> Vec3 { fn random_translation(rng: &mut impl Rng) -> Vec3 {
let x = rng.r#gen::<f32>() * (TRANSLATION_BOUND_UPPER_X - TRANSLATION_BOUND_LOWER_X) let x = rng.random::<f32>() * (TRANSLATION_BOUND_UPPER_X - TRANSLATION_BOUND_LOWER_X)
+ TRANSLATION_BOUND_LOWER_X; + TRANSLATION_BOUND_LOWER_X;
let y = rng.r#gen::<f32>() * (TRANSLATION_BOUND_UPPER_Y - TRANSLATION_BOUND_LOWER_Y) let y = rng.random::<f32>() * (TRANSLATION_BOUND_UPPER_Y - TRANSLATION_BOUND_LOWER_Y)
+ TRANSLATION_BOUND_LOWER_Y; + TRANSLATION_BOUND_LOWER_Y;
let z = rng.r#gen::<f32>() * (TRANSLATION_BOUND_UPPER_Z - TRANSLATION_BOUND_LOWER_Z) let z = rng.random::<f32>() * (TRANSLATION_BOUND_UPPER_Z - TRANSLATION_BOUND_LOWER_Z)
+ TRANSLATION_BOUND_LOWER_Z; + TRANSLATION_BOUND_LOWER_Z;
Vec3::new(x, y, z) Vec3::new(x, y, z)
} }
fn random_scale(rng: &mut impl Rng) -> Vec3 { fn random_scale(rng: &mut impl Rng) -> Vec3 {
let x_factor_log = rng.r#gen::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG) let x_factor_log = rng.random::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG)
+ SCALING_BOUND_LOWER_LOG; + SCALING_BOUND_LOWER_LOG;
let y_factor_log = rng.r#gen::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG) let y_factor_log = rng.random::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG)
+ SCALING_BOUND_LOWER_LOG; + SCALING_BOUND_LOWER_LOG;
let z_factor_log = rng.r#gen::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG) let z_factor_log = rng.random::<f32>() * (SCALING_BOUND_UPPER_LOG - SCALING_BOUND_LOWER_LOG)
+ SCALING_BOUND_LOWER_LOG; + SCALING_BOUND_LOWER_LOG;
Vec3::new( Vec3::new(
@ -186,14 +186,14 @@ fn elerp(v1: Vec3, v2: Vec3, t: f32) -> Vec3 {
fn random_rotation(rng: &mut impl Rng) -> Quat { fn random_rotation(rng: &mut impl Rng) -> Quat {
let dir = random_direction(rng); let dir = random_direction(rng);
let angle = rng.r#gen::<f32>() * 2. * PI; let angle = rng.random::<f32>() * 2. * PI;
Quat::from_axis_angle(dir, angle) Quat::from_axis_angle(dir, angle)
} }
fn random_direction(rng: &mut impl Rng) -> Vec3 { fn random_direction(rng: &mut impl Rng) -> Vec3 {
let height = rng.r#gen::<f32>() * 2. - 1.; let height = rng.random::<f32>() * 2. - 1.;
let theta = rng.r#gen::<f32>() * 2. * PI; let theta = rng.random::<f32>() * 2. * PI;
build_direction(height, theta) build_direction(height, theta)
} }

View File

@ -6,7 +6,7 @@ use bevy::{
prelude::*, prelude::*,
render::mesh::SphereKind, render::mesh::SphereKind,
}; };
use rand::{distributions::Distribution, SeedableRng}; use rand::{distr::Distribution, SeedableRng};
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
fn main() { fn main() {

View File

@ -8,7 +8,7 @@ use bevy::{
math::prelude::*, math::prelude::*,
prelude::*, prelude::*,
}; };
use rand::{seq::SliceRandom, Rng, SeedableRng}; use rand::{seq::IndexedRandom, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
fn main() { fn main() {
@ -614,7 +614,7 @@ fn despawn_points(
let rng = &mut random_source.0; let rng = &mut random_source.0;
// Skip a random amount of points to ensure random despawning // Skip a random amount of points to ensure random despawning
let skip = rng.gen_range(0..counter.0); let skip = rng.random_range(0..counter.0);
let despawn_amount = (counter.0 - MAX_POINTS).min(100); let despawn_amount = (counter.0 - MAX_POINTS).min(100);
counter.0 -= samples counter.0 -= samples
.iter() .iter()

View File

@ -87,8 +87,7 @@ fn update(
1.0, 1.0,
] ]
}) })
.collect::<Vec<[f32; 4]>>() .collect::<Vec<[f32; 4]>>(),
.as_slice(),
); );
} }

View File

@ -18,7 +18,7 @@ use bevy::{
window::{PresentMode, WindowResolution}, window::{PresentMode, WindowResolution},
winit::{UpdateMode, WinitSettings}, winit::{UpdateMode, WinitSettings},
}; };
use rand::{seq::SliceRandom, Rng, SeedableRng}; use rand::{seq::IndexedRandom, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
const BIRDS_PER_SECOND: u32 = 10000; const BIRDS_PER_SECOND: u32 = 10000;
@ -345,7 +345,7 @@ fn mouse_handler(
let rng = rng.as_mut().unwrap(); let rng = rng.as_mut().unwrap();
if mouse_button_input.just_released(MouseButton::Left) { if mouse_button_input.just_released(MouseButton::Left) {
counter.color = Color::linear_rgb(rng.r#gen(), rng.r#gen(), rng.r#gen()); counter.color = Color::linear_rgb(rng.random(), rng.random(), rng.random());
} }
if mouse_button_input.pressed(MouseButton::Left) { if mouse_button_input.pressed(MouseButton::Left) {
@ -371,7 +371,7 @@ fn bird_velocity_transform(
waves: Option<usize>, waves: Option<usize>,
dt: f32, dt: f32,
) -> (Transform, Vec3) { ) -> (Transform, Vec3) {
let mut velocity = Vec3::new(MAX_VELOCITY * (velocity_rng.r#gen::<f32>() - 0.5), 0., 0.); let mut velocity = Vec3::new(MAX_VELOCITY * (velocity_rng.random::<f32>() - 0.5), 0., 0.);
if let Some(waves) = waves { if let Some(waves) = waves {
// Step the movement and handle collisions as if the wave had been spawned at fixed time intervals // Step the movement and handle collisions as if the wave had been spawned at fixed time intervals
@ -414,7 +414,7 @@ fn spawn_birds(
let bird_z = if args.ordered_z { let bird_z = if args.ordered_z {
(current_count + count) as f32 * 0.00001 (current_count + count) as f32 * 0.00001
} else { } else {
bird_resources.transform_rng.r#gen::<f32>() bird_resources.transform_rng.random::<f32>()
}; };
let (transform, velocity) = bird_velocity_transform( let (transform, velocity) = bird_velocity_transform(
@ -427,9 +427,9 @@ fn spawn_birds(
let color = if args.vary_per_instance { let color = if args.vary_per_instance {
Color::linear_rgb( Color::linear_rgb(
bird_resources.color_rng.r#gen(), bird_resources.color_rng.random(),
bird_resources.color_rng.r#gen(), bird_resources.color_rng.random(),
bird_resources.color_rng.r#gen(), bird_resources.color_rng.random(),
) )
} else { } else {
color color
@ -457,7 +457,7 @@ fn spawn_birds(
let bird_z = if args.ordered_z { let bird_z = if args.ordered_z {
(current_count + count) as f32 * 0.00001 (current_count + count) as f32 * 0.00001
} else { } else {
bird_resources.transform_rng.r#gen::<f32>() bird_resources.transform_rng.random::<f32>()
}; };
let (transform, velocity) = bird_velocity_transform( let (transform, velocity) = bird_velocity_transform(
@ -492,9 +492,9 @@ fn spawn_birds(
counter.count += spawn_count; counter.count += spawn_count;
counter.color = Color::linear_rgb( counter.color = Color::linear_rgb(
bird_resources.color_rng.r#gen(), bird_resources.color_rng.random(),
bird_resources.color_rng.r#gen(), bird_resources.color_rng.random(),
bird_resources.color_rng.r#gen(), bird_resources.color_rng.random(),
); );
} }
@ -575,7 +575,12 @@ fn init_textures(textures: &mut Vec<Handle<Image>>, args: &Args, images: &mut As
// This isn't strictly required in practical use unless you need your app to be deterministic. // This isn't strictly required in practical use unless you need your app to be deterministic.
let mut color_rng = ChaCha8Rng::seed_from_u64(42); let mut color_rng = ChaCha8Rng::seed_from_u64(42);
while textures.len() < args.material_texture_count { while textures.len() < args.material_texture_count {
let pixel = [color_rng.r#gen(), color_rng.r#gen(), color_rng.r#gen(), 255]; let pixel = [
color_rng.random(),
color_rng.random(),
color_rng.random(),
255,
];
textures.push(images.add(Image::new_fill( textures.push(images.add(Image::new_fill(
Extent3d { Extent3d {
width: BIRD_TEXTURE_SIZE as u32, width: BIRD_TEXTURE_SIZE as u32,
@ -623,7 +628,7 @@ fn init_materials(
materials.extend( materials.extend(
std::iter::repeat_with(|| { std::iter::repeat_with(|| {
assets.add(ColorMaterial { assets.add(ColorMaterial {
color: Color::srgb_u8(color_rng.r#gen(), color_rng.r#gen(), color_rng.r#gen()), color: Color::srgb_u8(color_rng.random(), color_rng.random(), color_rng.random()),
texture: textures.choose(&mut texture_rng).cloned(), texture: textures.choose(&mut texture_rng).cloned(),
alpha_mode, alpha_mode,
..default() ..default()

View File

@ -55,7 +55,7 @@ fn setup(
) { ) {
warn!(include_str!("warning_string.txt")); warn!(include_str!("warning_string.txt"));
let mut rng = rand::thread_rng(); let mut rng = rand::rng();
let tile_size = Vec2::splat(64.0); let tile_size = Vec2::splat(64.0);
let map_size = Vec2::splat(320.0); let map_size = Vec2::splat(320.0);
@ -75,11 +75,11 @@ fn setup(
for y in -half_y..half_y { for y in -half_y..half_y {
for x in -half_x..half_x { for x in -half_x..half_x {
let position = Vec2::new(x as f32, y as f32); let position = Vec2::new(x as f32, y as f32);
let translation = (position * tile_size).extend(rng.r#gen::<f32>()); let translation = (position * tile_size).extend(rng.random::<f32>());
let rotation = Quat::from_rotation_z(rng.r#gen::<f32>()); let rotation = Quat::from_rotation_z(rng.random::<f32>());
let scale = Vec3::splat(rng.r#gen::<f32>() * 2.0); let scale = Vec3::splat(rng.random::<f32>() * 2.0);
let mut timer = Timer::from_seconds(0.1, TimerMode::Repeating); let mut timer = Timer::from_seconds(0.1, TimerMode::Repeating);
timer.set_elapsed(Duration::from_secs_f32(rng.r#gen::<f32>())); timer.set_elapsed(Duration::from_secs_f32(rng.random::<f32>()));
commands.spawn(( commands.spawn((
Sprite { Sprite {

View File

@ -28,7 +28,7 @@ use bevy::{
MinimalPlugins, MinimalPlugins,
}; };
use rand::prelude::{Rng, SeedableRng, SliceRandom}; use rand::prelude::{IndexedRandom, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
use std::{alloc::Layout, mem::ManuallyDrop, num::Wrapping}; use std::{alloc::Layout, mem::ManuallyDrop, num::Wrapping};
@ -106,7 +106,7 @@ fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
// fill the schedule with systems // fill the schedule with systems
let mut schedule = Schedule::new(Update); let mut schedule = Schedule::new(Update);
for _ in 1..=num_systems { for _ in 1..=num_systems {
let num_access_components = rng.gen_range(1..10); let num_access_components = rng.random_range(1..10);
let access_components: Vec<ComponentId> = component_ids let access_components: Vec<ComponentId> = component_ids
.choose_multiple(&mut rng, num_access_components) .choose_multiple(&mut rng, num_access_components)
.copied() .copied()
@ -127,7 +127,7 @@ fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
// spawn a bunch of entities // spawn a bunch of entities
for _ in 1..=num_entities { for _ in 1..=num_entities {
let num_components = rng.gen_range(1..10); let num_components = rng.random_range(1..10);
let components: Vec<ComponentId> = component_ids let components: Vec<ComponentId> = component_ids
.choose_multiple(&mut rng, num_components) .choose_multiple(&mut rng, num_components)
.copied() .copied()
@ -139,7 +139,7 @@ fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
// But we do want to deallocate the memory when values is dropped. // But we do want to deallocate the memory when values is dropped.
let mut values: Vec<ManuallyDrop<u8>> = components let mut values: Vec<ManuallyDrop<u8>> = components
.iter() .iter()
.map(|_id| ManuallyDrop::new(rng.gen_range(0..255))) .map(|_id| ManuallyDrop::new(rng.random_range(0..255)))
.collect(); .collect();
let ptrs: Vec<OwningPtr> = values let ptrs: Vec<OwningPtr> = values
.iter_mut() .iter_mut()

View File

@ -25,7 +25,7 @@ use bevy::{
window::{PresentMode, WindowResolution}, window::{PresentMode, WindowResolution},
winit::{UpdateMode, WinitSettings}, winit::{UpdateMode, WinitSettings},
}; };
use rand::{seq::SliceRandom, Rng, SeedableRng}; use rand::{seq::IndexedRandom, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
#[derive(FromArgs, Resource)] #[derive(FromArgs, Resource)]
@ -262,7 +262,13 @@ fn init_textures(args: &Args, images: &mut Assets<Image>) -> Vec<Handle<Image>>
// This isn't strictly required in practical use unless you need your app to be deterministic. // This isn't strictly required in practical use unless you need your app to be deterministic.
let mut color_rng = ChaCha8Rng::seed_from_u64(42); let mut color_rng = ChaCha8Rng::seed_from_u64(42);
let color_bytes: Vec<u8> = (0..(args.material_texture_count * 4)) let color_bytes: Vec<u8> = (0..(args.material_texture_count * 4))
.map(|i| if (i % 4) == 3 { 255 } else { color_rng.r#gen() }) .map(|i| {
if (i % 4) == 3 {
255
} else {
color_rng.random()
}
})
.collect(); .collect();
color_bytes color_bytes
.chunks(4) .chunks(4)
@ -307,7 +313,11 @@ fn init_materials(
materials.extend( materials.extend(
std::iter::repeat_with(|| { std::iter::repeat_with(|| {
assets.add(StandardMaterial { assets.add(StandardMaterial {
base_color: Color::srgb_u8(color_rng.r#gen(), color_rng.r#gen(), color_rng.r#gen()), base_color: Color::srgb_u8(
color_rng.random(),
color_rng.random(),
color_rng.random(),
),
base_color_texture: textures.choose(&mut texture_rng).cloned(), base_color_texture: textures.choose(&mut texture_rng).cloned(),
..default() ..default()
}) })
@ -326,7 +336,7 @@ fn init_meshes(args: &Args, assets: &mut Assets<Mesh>) -> Vec<(Handle<Mesh>, Tra
let mut radius_rng = ChaCha8Rng::seed_from_u64(42); let mut radius_rng = ChaCha8Rng::seed_from_u64(42);
let mut variant = 0; let mut variant = 0;
std::iter::repeat_with(|| { std::iter::repeat_with(|| {
let radius = radius_rng.gen_range(0.25f32..=0.75f32); let radius = radius_rng.random_range(0.25f32..=0.75f32);
let (handle, transform) = match variant % 15 { let (handle, transform) = match variant % 15 {
0 => ( 0 => (
assets.add(Cuboid { assets.add(Cuboid {

View File

@ -13,7 +13,7 @@ use bevy::{
window::{PresentMode, WindowResolution}, window::{PresentMode, WindowResolution},
winit::{UpdateMode, WinitSettings}, winit::{UpdateMode, WinitSettings},
}; };
use rand::{thread_rng, Rng}; use rand::{rng, Rng};
fn main() { fn main() {
App::new() App::new()
@ -72,7 +72,7 @@ fn setup(
// Spawn N_LIGHTS many lights // Spawn N_LIGHTS many lights
commands.spawn_batch((0..N_LIGHTS).map(move |i| { commands.spawn_batch((0..N_LIGHTS).map(move |i| {
let mut rng = thread_rng(); let mut rng = rng();
let spherical_polar_theta_phi = fibonacci_spiral_on_sphere(golden_ratio, i, N_LIGHTS); let spherical_polar_theta_phi = fibonacci_spiral_on_sphere(golden_ratio, i, N_LIGHTS);
let unit_sphere_p = spherical_polar_to_cartesian(spherical_polar_theta_phi); let unit_sphere_p = spherical_polar_to_cartesian(spherical_polar_theta_phi);
@ -81,7 +81,7 @@ fn setup(
PointLight { PointLight {
range: LIGHT_RADIUS, range: LIGHT_RADIUS,
intensity: LIGHT_INTENSITY, intensity: LIGHT_INTENSITY,
color: Color::hsl(rng.gen_range(0.0..360.0), 1.0, 0.5), color: Color::hsl(rng.random_range(0.0..360.0), 1.0, 0.5),
..default() ..default()
}, },
Transform::from_translation((RADIUS as f64 * unit_sphere_p).as_vec3()), Transform::from_translation((RADIUS as f64 * unit_sphere_p).as_vec3()),

View File

@ -58,7 +58,7 @@ fn main() {
fn setup(mut commands: Commands, assets: Res<AssetServer>, color_tint: Res<ColorTint>) { fn setup(mut commands: Commands, assets: Res<AssetServer>, color_tint: Res<ColorTint>) {
warn!(include_str!("warning_string.txt")); warn!(include_str!("warning_string.txt"));
let mut rng = rand::thread_rng(); let mut rng = rand::rng();
let tile_size = Vec2::splat(64.0); let tile_size = Vec2::splat(64.0);
let map_size = Vec2::splat(320.0); let map_size = Vec2::splat(320.0);
@ -77,16 +77,16 @@ fn setup(mut commands: Commands, assets: Res<AssetServer>, color_tint: Res<Color
for y in -half_y..half_y { for y in -half_y..half_y {
for x in -half_x..half_x { for x in -half_x..half_x {
let position = Vec2::new(x as f32, y as f32); let position = Vec2::new(x as f32, y as f32);
let translation = (position * tile_size).extend(rng.r#gen::<f32>()); let translation = (position * tile_size).extend(rng.random::<f32>());
let rotation = Quat::from_rotation_z(rng.r#gen::<f32>()); let rotation = Quat::from_rotation_z(rng.random::<f32>());
let scale = Vec3::splat(rng.r#gen::<f32>() * 2.0); let scale = Vec3::splat(rng.random::<f32>() * 2.0);
sprites.push(( sprites.push((
Sprite { Sprite {
image: sprite_handle.clone(), image: sprite_handle.clone(),
custom_size: Some(tile_size), custom_size: Some(tile_size),
color: if color_tint.0 { color: if color_tint.0 {
COLORS[rng.gen_range(0..3)] COLORS[rng.random_range(0..3)]
} else { } else {
Color::WHITE Color::WHITE
}, },

View File

@ -12,7 +12,7 @@ use bevy::{
use argh::FromArgs; use argh::FromArgs;
use rand::{ use rand::{
seq::{IteratorRandom, SliceRandom}, seq::{IndexedRandom, IteratorRandom},
Rng, SeedableRng, Rng, SeedableRng,
}; };
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
@ -122,10 +122,10 @@ fn setup(mut commands: Commands, font: Res<FontHandle>, args: Res<Args>) {
for y in -half_y..half_y { for y in -half_y..half_y {
for x in -half_x..half_x { for x in -half_x..half_x {
let position = Vec2::new(x as f32, y as f32); let position = Vec2::new(x as f32, y as f32);
let translation = (position * tile_size).extend(rng.r#gen::<f32>()); let translation = (position * tile_size).extend(rng.random::<f32>());
let rotation = Quat::from_rotation_z(rng.r#gen::<f32>()); let rotation = Quat::from_rotation_z(rng.random::<f32>());
let scale = Vec3::splat(rng.r#gen::<f32>() * 2.0); let scale = Vec3::splat(rng.random::<f32>() * 2.0);
let color = Hsla::hsl(rng.gen_range(0.0..360.0), 0.8, 0.8); let color = Hsla::hsl(rng.random_range(0.0..360.0), 0.8, 0.8);
text2ds.push(( text2ds.push((
Text2d(random_text(&mut rng, &args)), Text2d(random_text(&mut rng, &args)),

View File

@ -290,7 +290,7 @@ fn setup(mut commands: Commands, cfg: Res<Cfg>) {
} }
TestCase::Humanoids { active, inactive } => { TestCase::Humanoids { active, inactive } => {
let mut result = InsertResult::default(); let mut result = InsertResult::default();
let mut rng = rand::thread_rng(); let mut rng = rand::rng();
for _ in 0..active { for _ in 0..active {
result.combine(spawn_tree( result.combine(spawn_tree(
@ -298,8 +298,8 @@ fn setup(mut commands: Commands, cfg: Res<Cfg>) {
&mut commands, &mut commands,
&cfg.update_filter, &cfg.update_filter,
Transform::from_xyz( Transform::from_xyz(
rng.r#gen::<f32>() * 500.0 - 250.0, rng.random::<f32>() * 500.0 - 250.0,
rng.r#gen::<f32>() * 500.0 - 250.0, rng.random::<f32>() * 500.0 - 250.0,
0.0, 0.0,
), ),
)); ));
@ -315,8 +315,8 @@ fn setup(mut commands: Commands, cfg: Res<Cfg>) {
..cfg.update_filter ..cfg.update_filter
}, },
Transform::from_xyz( Transform::from_xyz(
rng.r#gen::<f32>() * 500.0 - 250.0, rng.random::<f32>() * 500.0 - 250.0,
rng.r#gen::<f32>() * 500.0 - 250.0, rng.random::<f32>() * 500.0 - 250.0,
0.0, 0.0,
), ),
)); ));
@ -379,7 +379,7 @@ fn spawn_tree(
ents.push(commands.spawn(root_transform).id()); ents.push(commands.spawn(root_transform).id());
let mut result = InsertResult::default(); let mut result = InsertResult::default();
let mut rng = rand::thread_rng(); let mut rng = rand::rng();
// used to count through the number of children (used only for visual layout) // used to count through the number of children (used only for visual layout)
let mut child_idx: Vec<u16> = vec![0; count]; let mut child_idx: Vec<u16> = vec![0; count];
@ -405,7 +405,7 @@ fn spawn_tree(
let mut cmd = commands.spawn_empty(); let mut cmd = commands.spawn_empty();
// check whether or not to update this node // check whether or not to update this node
let update = (rng.r#gen::<f32>() <= update_filter.probability) let update = (rng.random::<f32>() <= update_filter.probability)
&& (depth >= update_filter.min_depth && depth <= update_filter.max_depth); && (depth >= update_filter.min_depth && depth <= update_filter.max_depth);
if update { if update {

View File

@ -75,8 +75,8 @@ fn setup(
)); ));
// Initialize random axes // Initialize random axes
let first = seeded_rng.r#gen(); let first = seeded_rng.random();
let second = seeded_rng.r#gen(); let second = seeded_rng.random();
commands.spawn(RandomAxes(first, second)); commands.spawn(RandomAxes(first, second));
// Finally, our ship that is going to rotate // Finally, our ship that is going to rotate
@ -165,8 +165,8 @@ fn handle_keypress(
) { ) {
if keyboard.just_pressed(KeyCode::KeyR) { if keyboard.just_pressed(KeyCode::KeyR) {
// Randomize the target axes // Randomize the target axes
let first = seeded_rng.0.r#gen(); let first = seeded_rng.0.random();
let second = seeded_rng.0.r#gen(); let second = seeded_rng.0.random();
**random_axes = RandomAxes(first, second); **random_axes = RandomAxes(first, second);
// Stop the ship and set it up to transform from its present orientation to the new one // Stop the ship and set it up to transform from its present orientation to the new one

View File

@ -74,7 +74,7 @@ fn text_update_system(
} }
for mut text in &mut query { for mut text in &mut query {
let c = seeded_rng.r#gen::<u8>() as char; let c = seeded_rng.random::<u8>() as char;
let string = &mut **text; let string = &mut **text;
if !string.contains(c) { if !string.contains(c) {
string.push(c); string.push(c);

View File

@ -0,0 +1,10 @@
---
title: Updated `glam` and `rand` versions.
pull_requests: [18047]
---
With newer versions of `glam` & `encase`, the updated versions don't seem to have introduced breakages, though as always, best to consult their docs [1](https://docs.rs/glam/latest/glam/) [2](https://docs.rs/encase/0.11.0/encase/) for any changes.
`rand` changes are more extensive, with changes such as `thread_rng()` -> `rng()`, `from_entropy()` -> `from_os_rng()`, and so forth. `RngCore` is now split into infallible `RngCore` and fallible `TryRngCore`, and the `distributions` module has been renamed to `distr`. Most of this affects only internals, and doesn't directly affect Bevy's APIs. For the full set of changes, see `rand` [migration notes](https://rust-random.github.io/book/update-0.9.html).
`getrandom` is also updated, and will require additional configuration when building Bevy for WASM/Web (if also using `rand`). The full details of how to do this is in the `getrandom` docs [1](https://github.com/rust-random/getrandom?tab=readme-ov-file#opt-in-backends) [2](https://github.com/rust-random/getrandom?tab=readme-ov-file#webassembly-support).

View File

@ -89,7 +89,9 @@ fn main() {
sh, sh,
"cargo build {parameters...} --target wasm32-unknown-unknown --example {example}" "cargo build {parameters...} --target wasm32-unknown-unknown --example {example}"
); );
cmd.run().expect("Error building example"); cmd.env("RUSTFLAGS", "--cfg getrandom_backend=\"wasm_js\"")
.run()
.expect("Error building example");
cmd!( cmd!(
sh, sh,