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

View File

@ -112,6 +112,8 @@ jobs:
cd ../..
- name: First Wasm build
env:
RUSTFLAGS: --cfg getrandom_backend="wasm_js"
run: |
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 }
[dev-dependencies]
rand = "0.8.0"
rand_chacha = "0.3.1"
rand = "0.9.0"
rand_chacha = "0.9.0"
ron = "0.10"
flate2 = "1.0"
serde = { version = "1", features = ["derive"] }
@ -627,6 +627,9 @@ smol-hyper = "0.1"
ureq = { version = "3.0.8", features = ["json"] }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
getrandom = { version = "0.3", default-features = false, features = [
"wasm_js",
] }
wasm-bindgen = { version = "0.2" }
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
glam = "0.29"
rand = "0.8"
rand_chacha = "0.3"
glam = "0.30.1"
rand = "0.9"
rand_chacha = "0.9"
nonmax = { version = "0.5", default-features = false }
# 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> {}
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(|_| {
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();
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>);
}
}

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 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 x: f64 = rng.r#gen();
let x: f64 = rng.random();
let generation = 1.0 + -(1.0 - x).log2() * 2.0;
// 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 bevy_reflect::ParsedPath;
use criterion::{criterion_group, BatchSize, BenchmarkId, Criterion, Throughput};
use rand::{distributions::Uniform, Rng, SeedableRng};
use rand::{distr::Uniform, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
criterion_group!(benches, parse_reflect_path);
@ -18,20 +18,20 @@ fn deterministic_rand() -> ChaCha8Rng {
ChaCha8Rng::seed_from_u64(42)
}
fn random_ident(rng: &mut ChaCha8Rng, f: &mut dyn Write) {
let between = Uniform::from(b'a'..=b'z');
let ident_size = rng.gen_range(1..128);
let between = Uniform::new_inclusive(b'a', b'z').unwrap();
let ident_size = rng.random_range(1..128);
let ident: Vec<u8> = rng.sample_iter(between).take(ident_size).collect();
let ident = str::from_utf8(&ident).unwrap();
let _ = write!(f, "{ident}");
}
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}");
}
fn write_random_access(rng: &mut ChaCha8Rng, f: &mut dyn Write) {
match rng.gen_range(0..4) {
match rng.random_range(0..4) {
0 => {
// Access::Field
f.write_char('.').unwrap();

View File

@ -21,7 +21,7 @@ serde = { version = "1.0", features = [
thiserror = { version = "2", default-features = false }
derive_more = { version = "2", default-features = false, features = ["from"] }
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]
default = ["std", "bevy_reflect", "encase"]

View File

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

View File

@ -66,7 +66,7 @@ enum SimulationSystems {
// The entity will start with an age of 0 frames
// If an entity gets spawned, we increase the counter in the EntityCounter resource
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();
println!(" spawning {entity_id:?}");
entity_counter.value += 1;

View File

@ -37,7 +37,7 @@ struct 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;
println!(" Increased counter value");
}

View File

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

View File

@ -10,7 +10,7 @@ keywords = ["bevy"]
rust-version = "1.85.0"
[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 }
derive_more = { version = "2", default-features = false, features = [
"from",
@ -22,8 +22,8 @@ serde = { version = "1", default-features = false, features = [
], optional = true }
libm = { version = "0.2", optional = true }
approx = { version = "0.5", default-features = false, optional = true }
rand = { version = "0.8", default-features = false, optional = true }
rand_distr = { version = "0.4.3", optional = true }
rand = { version = "0.9", default-features = false, optional = true }
rand_distr = { version = "0.5", optional = true }
smallvec = { version = "1", default-features = false }
bevy_reflect = { path = "../bevy_reflect", version = "0.17.0-dev", default-features = false, features = [
"glam",
@ -33,11 +33,16 @@ variadics_please = "1.1"
[dev-dependencies]
approx = "0.5"
# Supply rngs for examples and tests
rand = "0.8"
rand_chacha = "0.3"
rand = "0.9"
rand_chacha = "0.9"
# Enable the approx feature when testing.
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]
default = ["std", "rand", "curve"]

View File

@ -6,7 +6,10 @@ use crate::{
};
use alloc::vec::Vec;
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.
/// 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::sampling::mesh_sampling::UniformMeshSampler;
/// # use rand::{SeedableRng, rngs::StdRng, distributions::Distribution};
/// # use rand::{SeedableRng, rngs::StdRng, distr::Distribution};
/// let faces = Tetrahedron::default().faces();
/// let sampler = UniformMeshSampler::try_new(faces).unwrap();
/// let rng = StdRng::seed_from_u64(8765309);

View File

@ -8,7 +8,7 @@
//! # use rand::SeedableRng;
//! # use rand::rngs::StdRng;
//! // Get some `Rng`:
//! let rng = &mut StdRng::from_entropy();
//! let rng = &mut StdRng::from_os_rng();
//! // Make a circle of radius 2:
//! let circle = Circle::new(2.0);
//! // Get a point inside this circle uniformly at random:
@ -23,9 +23,9 @@
//! # use bevy_math::{Vec2, ShapeSample};
//! # use rand::SeedableRng;
//! # use rand::rngs::StdRng;
//! # use rand::distributions::Distribution;
//! # let rng1 = StdRng::from_entropy();
//! # let rng2 = StdRng::from_entropy();
//! # use rand::distr::Distribution;
//! # let rng1 = StdRng::from_os_rng();
//! # let rng2 = StdRng::from_os_rng();
//! // Use a rectangle this time:
//! let rectangle = Rectangle::new(1.0, 2.0);
//! // 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 rand::{
distributions::{Distribution, WeightedIndex},
distr::{
uniform::SampleUniform,
weighted::{Weight, WeightedIndex},
Distribution,
},
Rng,
};
use rand_distr::uniform::SampleUniform;
/// Exposes methods to uniformly sample a variety of primitive shapes.
pub trait ShapeSample {
@ -62,7 +65,7 @@ pub trait ShapeSample {
/// let square = Rectangle::new(2.0, 2.0);
///
/// // 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;
@ -77,7 +80,7 @@ pub trait ShapeSample {
///
/// // Returns a Vec2 where one of the coordinates is at ±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;
@ -87,9 +90,9 @@ pub trait ShapeSample {
///
/// ```
/// # use bevy_math::prelude::*;
/// # use rand::distributions::Distribution;
/// # use rand::distr::Distribution;
/// 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:
/// for random_val in square.interior_dist().sample_iter(rng).take(5) {
@ -109,9 +112,9 @@ pub trait ShapeSample {
///
/// ```
/// # use bevy_math::prelude::*;
/// # use rand::distributions::Distribution;
/// # use rand::distr::Distribution;
/// 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:
/// 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 {
// https://mathworld.wolfram.com/DiskPointPicking.html
let theta = rng.gen_range(0.0..TAU);
let r_squared = rng.gen_range(0.0..=(self.radius * self.radius));
let theta = rng.random_range(0.0..TAU);
let r_squared = rng.random_range(0.0..=(self.radius * self.radius));
let r = ops::sqrt(r_squared);
let (sin, cos) = ops::sin_cos(theta);
Vec2::new(r * cos, r * sin)
}
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);
Vec2::new(self.radius * cos, self.radius * sin)
}
@ -170,8 +173,8 @@ impl ShapeSample for Circle {
/// Boundary sampling for unit-spheres
#[inline]
fn sample_unit_sphere_boundary<R: Rng + ?Sized>(rng: &mut R) -> Vec3 {
let z = rng.gen_range(-1f32..=1f32);
let (a_sin, a_cos) = ops::sin_cos(rng.gen_range(-PI..=PI));
let z = rng.random_range(-1f32..=1f32);
let (a_sin, a_cos) = ops::sin_cos(rng.random_range(-PI..=PI));
let c = ops::sqrt(1f32 - z * z);
let x = a_sin * c;
let y = a_cos * c;
@ -183,7 +186,7 @@ impl ShapeSample for Sphere {
type Output = 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);
r * sample_unit_sphere_boundary(rng)
@ -202,9 +205,10 @@ impl ShapeSample for Annulus {
let outer_radius = self.outer_circle.radius;
// 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 theta = rng.gen_range(0.0..TAU);
let theta = rng.random_range(0.0..TAU);
let (sin, cos) = ops::sin_cos(theta);
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;
// 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 {
self.inner_circle.sample_boundary(rng)
} else {
@ -248,17 +252,17 @@ impl ShapeSample for Rectangle {
type Output = 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 y = rng.gen_range(-self.half_size.y..=self.half_size.y);
let x = rng.random_range(-self.half_size.x..=self.half_size.x);
let y = rng.random_range(-self.half_size.y..=self.half_size.y);
Vec2::new(x, y)
}
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec2 {
let primary_side = rng.gen_range(-1.0..1.0);
let other_side = if rng.r#gen() { -1.0 } else { 1.0 };
let primary_side = rng.random_range(-1.0..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 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
} else {
Vec2::new(other_side, primary_side) * self.half_size
@ -273,16 +277,16 @@ impl ShapeSample for Cuboid {
type Output = 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 y = rng.gen_range(-self.half_size.y..=self.half_size.y);
let z = rng.gen_range(-self.half_size.z..=self.half_size.z);
let x = rng.random_range(-self.half_size.x..=self.half_size.x);
let y = rng.random_range(-self.half_size.y..=self.half_size.y);
let z = rng.random_range(-self.half_size.z..=self.half_size.z);
Vec3::new(x, y, z)
}
fn sample_boundary<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
let primary_side1 = rng.gen_range(-1.0..1.0);
let primary_side2 = rng.gen_range(-1.0..1.0);
let other_side = if rng.r#gen() { -1.0 } else { 1.0 };
let primary_side1 = rng.random_range(-1.0..1.0);
let primary_side2 = rng.random_range(-1.0..1.0);
let other_side = if rng.random() { -1.0 } else { 1.0 };
if let Ok(dist) = WeightedIndex::new([
self.half_size.y * self.half_size.z,
@ -314,8 +318,8 @@ where
// Generate random points on a parallelepiped and reflect so that
// we can use the points that lie outside the triangle
let u = rng.gen_range(P::Scalar::ZERO..=P::Scalar::ONE);
let v = rng.gen_range(P::Scalar::ZERO..=P::Scalar::ONE);
let u = rng.random_range(P::Scalar::ZERO..=P::Scalar::ONE);
let v = rng.random_range(P::Scalar::ZERO..=P::Scalar::ONE);
if u + v > P::Scalar::ONE {
let u1 = P::Scalar::ONE - v;
@ -330,7 +334,7 @@ where
fn sample_triangle_boundary<P, R>(vertices: [P; 3], rng: &mut R) -> P
where
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,
{
let [a, b, c] = vertices;
@ -338,7 +342,7 @@ where
let ac = c - a;
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()]) {
match dist.sample(rng) {
@ -386,9 +390,9 @@ impl ShapeSample for Tetrahedron {
// Generate a random point in a cube:
let mut coords: [f32; 3] = [
rng.gen_range(0.0..1.0),
rng.gen_range(0.0..1.0),
rng.gen_range(0.0..1.0),
rng.random_range(0.0..1.0),
rng.random_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,
@ -440,7 +444,7 @@ impl ShapeSample for Cylinder {
fn sample_interior<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
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)
}
@ -448,16 +452,16 @@ impl ShapeSample for Cylinder {
// 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)
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);
if rng.r#gen() {
if rng.random() {
Vec3::new(x, self.half_height, z)
} else {
Vec3::new(x, -self.half_height, z)
}
} else {
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)
}
} else {
@ -474,7 +478,7 @@ impl ShapeSample for Capsule2d {
let capsule_area = rectangle_area + PI * self.radius * self.radius;
if capsule_area > 0.0 {
// 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)
} else {
let circle = Circle::new(self.radius);
@ -495,9 +499,9 @@ impl ShapeSample for Capsule2d {
let rectangle_surface = 4.0 * self.half_length;
let capsule_surface = rectangle_surface + TAU * self.radius;
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 =
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 {
Vec2::new(self.radius, side_distance + self.half_length)
} 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;
if capsule_vol > 0.0 {
// 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)
} else {
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 capsule_surface = cylinder_surface + 4.0 * PI * self.radius * self.radius;
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 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)
} else {
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 {
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)
}
@ -582,7 +586,7 @@ impl<P: Primitive2d + Measured2d + ShapeSample<Output = Vec2>> ShapeSample for E
let base_area = self.base_shape.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 {
x if x < base_area => self.base_shape.sample_interior(rng).extend(self.half_depth),
x if x < 2. * base_area => self
@ -592,7 +596,7 @@ impl<P: Primitive2d + Measured2d + ShapeSample<Output = Vec2>> ShapeSample for E
_ => self
.base_shape
.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
//! 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.
//!
//! 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};
//! let mut rng = StdRng::seed_from_u64(7313429298);
//! // Random direction using thread-local rng
//! let random_direction1: Dir3 = random();
//!
//! // 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
//! let random_direction3 = Dir3::from_rng(&mut rng);
//!
//! // Five random directions, using Standard explicitly
//! let many_random_directions: Vec<Dir3> = rng.sample_iter(Standard).take(5).collect();
//! // Five random directions, using StandardUniform explicitly
//! let many_random_directions: Vec<Dir3> = rng.sample_iter(StandardUniform).take(5).collect();
//! ```
use core::f32::consts::TAU;
@ -28,11 +28,11 @@ use crate::{
Dir2, Dir3, Dir3A, Quat, Rot2, ShapeSample, Vec3A,
};
use rand::{
distributions::{Distribution, Standard},
distr::{Distribution, StandardUniform},
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.
///
/// Example
@ -45,15 +45,15 @@ use rand::{
pub trait FromRng
where
Self: Sized,
Standard: Distribution<Self>,
StandardUniform: Distribution<Self>,
{
/// 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 {
rng.r#gen()
rng.random()
}
}
impl Distribution<Dir2> for Standard {
impl Distribution<Dir2> for StandardUniform {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir2 {
let circle = Circle::new(1.0);
@ -64,7 +64,7 @@ impl Distribution<Dir2> for Standard {
impl FromRng for Dir2 {}
impl Distribution<Dir3> for Standard {
impl Distribution<Dir3> for StandardUniform {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir3 {
let sphere = Sphere::new(1.0);
@ -75,7 +75,7 @@ impl Distribution<Dir3> for Standard {
impl FromRng for Dir3 {}
impl Distribution<Dir3A> for Standard {
impl Distribution<Dir3A> for StandardUniform {
#[inline]
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Dir3A {
let sphere = Sphere::new(1.0);
@ -86,10 +86,10 @@ impl Distribution<Dir3A> for Standard {
impl FromRng for Dir3A {}
impl Distribution<Rot2> for Standard {
impl Distribution<Rot2> for StandardUniform {
#[inline]
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)
}
}

View File

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

View File

@ -22,7 +22,7 @@ std = ["glam/std"]
libm = ["glam/libm", "dep:libm"]
[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 }
[[example]]

View File

@ -65,8 +65,8 @@ rayon = { version = "1", default-features = false, optional = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
web-time = { version = "1.1", default-features = false, optional = true }
getrandom = { version = "0.2.0", default-features = false, optional = true, features = [
"js",
getrandom = { version = "0.3.0", default-features = false, optional = true, features = [
"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]

View File

@ -97,7 +97,7 @@ derive_more = { version = "2", default-features = false, features = ["from"] }
serde = { version = "1", default-features = false, features = ["alloc"] }
assert_type_match = "0.1.1"
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",
], 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 }
derive_more = { version = "2", default-features = false, features = ["from"] }
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.
profiling = { version = "1", features = [
"profile-with-tracing",

View File

@ -102,9 +102,9 @@ fn draw(
if *i == 0 {
// Generate a random color on first run.
*draw_color = Color::linear_rgb(
seeded_rng.0.r#gen(),
seeded_rng.0.r#gen(),
seeded_rng.0.r#gen(),
seeded_rng.0.random(),
seeded_rng.0.random(),
seeded_rng.0.random(),
);
}
@ -129,9 +129,9 @@ fn draw(
let tolerance = 1.0 / 255.0;
if old_color.distance(&draw_color) <= tolerance {
*draw_color = Color::linear_rgb(
seeded_rng.0.r#gen(),
seeded_rng.0.r#gen(),
seeded_rng.0.r#gen(),
seeded_rng.0.random(),
seeded_rng.0.random(),
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 tile_display_size = UVec2::splat(8);
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) })
.collect();
@ -73,8 +73,8 @@ fn update_tilemap(
if timer.just_finished() {
for _ in 0..50 {
let index = rng.gen_range(0..indices.len());
indices[index] = Some(rng.gen_range(0..5));
let index = rng.random_range(0..indices.len());
indices[index] = Some(rng.random_range(0..5));
}
}
}

View File

@ -64,9 +64,9 @@ fn setup(
let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
for i 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: u32 = rng.gen_range(0..360);
let rotation: u32 = rng.random_range(0..360);
let transform = Transform::from_xyz(
(-num_obs + 1) as f32 / 2.0 + i as f32,
-0.2,

View File

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

View File

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

View File

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

View File

@ -59,7 +59,7 @@ fn spawn_tasks(mut commands: Commands) {
// spawn() can be used to poll for the result
let entity = commands.spawn_empty().id();
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. :)
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 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)>) {
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());
info!("New value: {new_component:?} {entity}");
// 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.
fn change_component_2(time: Res<Time>, mut query: Query<(Entity, &mut MyComponent)>) {
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());
info!("New value: {new_component:?} {entity}");
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.
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());
info!("New value: {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::prelude::*;
use rand::distributions::Distribution;
use rand::distr::Distribution;
use rand::SeedableRng;
use rand_chacha::ChaCha8Rng;

View File

@ -91,15 +91,18 @@ fn user_input(
keyboard_input: Res<ButtonInput<KeyCode>>,
asset_server: Res<AssetServer>,
) {
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
if keyboard_input.just_pressed(KeyCode::KeyA) {
let texture = asset_server.load("textures/simplespace/enemy_A.png");
commands.spawn((
Enemy {
origin: Vec2::new(rng.gen_range(-200.0..200.0), rng.gen_range(-200.0..200.0)),
radius: rng.gen_range(50.0..150.0),
rotation: rng.gen_range(0.0..std::f32::consts::TAU),
rotation_speed: rng.gen_range(0.5..1.5),
origin: Vec2::new(
rng.random_range(-200.0..200.0),
rng.random_range(-200.0..200.0),
),
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 {
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.
let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
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 position = Vec3::new(
rng.gen_range(-1.0..1.0),
rng.gen_range(-1.0..1.0),
rng.gen_range(-1.0..1.0),
rng.random_range(-1.0..1.0),
rng.random_range(-1.0..1.0),
rng.random_range(-1.0..1.0),
)
.normalize()
* ops::cbrt(rng.gen_range(0.2f32..1.0))
* ops::cbrt(rng.random_range(0.2f32..1.0))
* 15.;
commands.spawn((
BodyBundle {
mesh: Mesh3d(mesh.clone()),
material: MeshMaterial3d(materials.add(Color::srgb(
rng.gen_range(color_range.clone()),
rng.gen_range(color_range.clone()),
rng.gen_range(color_range.clone()),
rng.random_range(color_range.clone()),
rng.random_range(color_range.clone()),
rng.random_range(color_range.clone()),
))),
mass: Mass(mass_value),
acceleration: Acceleration(Vec3::ZERO),
last_pos: LastPos(
position
- Vec3::new(
rng.gen_range(vel_range.clone()),
rng.gen_range(vel_range.clone()),
rng.gen_range(vel_range.clone()),
rng.random_range(vel_range.clone()),
rng.random_range(vel_range.clone()),
rng.random_range(vel_range.clone()),
) * time.timestep().as_secs_f32(),
),
},

View File

@ -3,7 +3,7 @@
use std::time::Duration;
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() {
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.
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) {
let damage = rng.gen_range(1..20);
let damage = rng.random_range(1..20);
commands.trigger_targets(Attack { damage }, target);
info!("⚔️ Attack for {} damage", damage);
}

View File

@ -52,10 +52,10 @@ impl Mine {
fn random(rand: &mut ChaCha8Rng) -> Self {
Mine {
pos: Vec2::new(
(rand.r#gen::<f32>() - 0.5) * 1200.0,
(rand.r#gen::<f32>() - 0.5) * 600.0,
(rand.random::<f32>() - 0.5) * 1200.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()),
Transform::from_scale(Vec3::splat(0.1))
.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.
ChaCha8Rng::seed_from_u64(19878367467713)
} else {
ChaCha8Rng::from_entropy()
ChaCha8Rng::from_os_rng()
};
// reset the game state
@ -137,7 +137,7 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>, mut game: ResMu
.map(|j| {
(0..BOARD_SIZE_I)
.map(|i| {
let height = rng.gen_range(-0.1..0.1);
let height = rng.random_range(-0.1..0.1);
commands.spawn((
DespawnOnExitState(GameState::Playing),
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
loop {
game.bonus.i = rng.gen_range(0..BOARD_SIZE_I);
game.bonus.j = rng.gen_range(0..BOARD_SIZE_J);
game.bonus.i = rng.random_range(0..BOARD_SIZE_I);
game.bonus.j = rng.random_range(0..BOARD_SIZE_J);
if game.bonus.i != game.player.i || game.bonus.j != game.player.j {
break;
}

View File

@ -96,16 +96,16 @@ fn setup_contributor_selection(
for (name, num_commits) in contribs {
let transform = Transform::from_xyz(
rng.gen_range(-400.0..400.0),
rng.gen_range(0.0..400.0),
rng.r#gen(),
rng.random_range(-400.0..400.0),
rng.random_range(0.0..400.0),
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 hue = name_to_hue(&name);
// Some sprites should be flipped for variety
let flipped = rng.r#gen();
let flipped = rng.random();
let entity = commands
.spawn((
@ -274,7 +274,7 @@ fn collisions(
transform.translation.y = collision_area.min.y;
// 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.
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 {
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;
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;
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;
Vec3::new(x, y, z)
}
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;
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;
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;
Vec3::new(
@ -186,14 +186,14 @@ fn elerp(v1: Vec3, v2: Vec3, t: f32) -> Vec3 {
fn random_rotation(rng: &mut impl Rng) -> Quat {
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)
}
fn random_direction(rng: &mut impl Rng) -> Vec3 {
let height = rng.r#gen::<f32>() * 2. - 1.;
let theta = rng.r#gen::<f32>() * 2. * PI;
let height = rng.random::<f32>() * 2. - 1.;
let theta = rng.random::<f32>() * 2. * PI;
build_direction(height, theta)
}

View File

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

View File

@ -8,7 +8,7 @@ use bevy::{
math::prelude::*,
prelude::*,
};
use rand::{seq::SliceRandom, Rng, SeedableRng};
use rand::{seq::IndexedRandom, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
fn main() {
@ -614,7 +614,7 @@ fn despawn_points(
let rng = &mut random_source.0;
// 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);
counter.0 -= samples
.iter()

View File

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

View File

@ -18,7 +18,7 @@ use bevy::{
window::{PresentMode, WindowResolution},
winit::{UpdateMode, WinitSettings},
};
use rand::{seq::SliceRandom, Rng, SeedableRng};
use rand::{seq::IndexedRandom, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
const BIRDS_PER_SECOND: u32 = 10000;
@ -345,7 +345,7 @@ fn mouse_handler(
let rng = rng.as_mut().unwrap();
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) {
@ -371,7 +371,7 @@ fn bird_velocity_transform(
waves: Option<usize>,
dt: f32,
) -> (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 {
// 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 {
(current_count + count) as f32 * 0.00001
} else {
bird_resources.transform_rng.r#gen::<f32>()
bird_resources.transform_rng.random::<f32>()
};
let (transform, velocity) = bird_velocity_transform(
@ -427,9 +427,9 @@ fn spawn_birds(
let color = if args.vary_per_instance {
Color::linear_rgb(
bird_resources.color_rng.r#gen(),
bird_resources.color_rng.r#gen(),
bird_resources.color_rng.r#gen(),
bird_resources.color_rng.random(),
bird_resources.color_rng.random(),
bird_resources.color_rng.random(),
)
} else {
color
@ -457,7 +457,7 @@ fn spawn_birds(
let bird_z = if args.ordered_z {
(current_count + count) as f32 * 0.00001
} else {
bird_resources.transform_rng.r#gen::<f32>()
bird_resources.transform_rng.random::<f32>()
};
let (transform, velocity) = bird_velocity_transform(
@ -492,9 +492,9 @@ fn spawn_birds(
counter.count += spawn_count;
counter.color = Color::linear_rgb(
bird_resources.color_rng.r#gen(),
bird_resources.color_rng.r#gen(),
bird_resources.color_rng.r#gen(),
bird_resources.color_rng.random(),
bird_resources.color_rng.random(),
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.
let mut color_rng = ChaCha8Rng::seed_from_u64(42);
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(
Extent3d {
width: BIRD_TEXTURE_SIZE as u32,
@ -623,7 +628,7 @@ fn init_materials(
materials.extend(
std::iter::repeat_with(|| {
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(),
alpha_mode,
..default()

View File

@ -55,7 +55,7 @@ fn setup(
) {
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 map_size = Vec2::splat(320.0);
@ -75,11 +75,11 @@ fn setup(
for y in -half_y..half_y {
for x in -half_x..half_x {
let position = Vec2::new(x as f32, y as f32);
let translation = (position * tile_size).extend(rng.r#gen::<f32>());
let rotation = Quat::from_rotation_z(rng.r#gen::<f32>());
let scale = Vec3::splat(rng.r#gen::<f32>() * 2.0);
let translation = (position * tile_size).extend(rng.random::<f32>());
let rotation = Quat::from_rotation_z(rng.random::<f32>());
let scale = Vec3::splat(rng.random::<f32>() * 2.0);
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((
Sprite {

View File

@ -28,7 +28,7 @@ use bevy::{
MinimalPlugins,
};
use rand::prelude::{Rng, SeedableRng, SliceRandom};
use rand::prelude::{IndexedRandom, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
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
let mut schedule = Schedule::new(Update);
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
.choose_multiple(&mut rng, num_access_components)
.copied()
@ -127,7 +127,7 @@ fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
// spawn a bunch of 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
.choose_multiple(&mut rng, num_components)
.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.
let mut values: Vec<ManuallyDrop<u8>> = components
.iter()
.map(|_id| ManuallyDrop::new(rng.gen_range(0..255)))
.map(|_id| ManuallyDrop::new(rng.random_range(0..255)))
.collect();
let ptrs: Vec<OwningPtr> = values
.iter_mut()

View File

@ -25,7 +25,7 @@ use bevy::{
window::{PresentMode, WindowResolution},
winit::{UpdateMode, WinitSettings},
};
use rand::{seq::SliceRandom, Rng, SeedableRng};
use rand::{seq::IndexedRandom, Rng, SeedableRng};
use rand_chacha::ChaCha8Rng;
#[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.
let mut color_rng = ChaCha8Rng::seed_from_u64(42);
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();
color_bytes
.chunks(4)
@ -307,7 +313,11 @@ fn init_materials(
materials.extend(
std::iter::repeat_with(|| {
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(),
..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 variant = 0;
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 {
0 => (
assets.add(Cuboid {

View File

@ -13,7 +13,7 @@ use bevy::{
window::{PresentMode, WindowResolution},
winit::{UpdateMode, WinitSettings},
};
use rand::{thread_rng, Rng};
use rand::{rng, Rng};
fn main() {
App::new()
@ -72,7 +72,7 @@ fn setup(
// Spawn N_LIGHTS many lights
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 unit_sphere_p = spherical_polar_to_cartesian(spherical_polar_theta_phi);
@ -81,7 +81,7 @@ fn setup(
PointLight {
range: LIGHT_RADIUS,
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()
},
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>) {
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 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 x in -half_x..half_x {
let position = Vec2::new(x as f32, y as f32);
let translation = (position * tile_size).extend(rng.r#gen::<f32>());
let rotation = Quat::from_rotation_z(rng.r#gen::<f32>());
let scale = Vec3::splat(rng.r#gen::<f32>() * 2.0);
let translation = (position * tile_size).extend(rng.random::<f32>());
let rotation = Quat::from_rotation_z(rng.random::<f32>());
let scale = Vec3::splat(rng.random::<f32>() * 2.0);
sprites.push((
Sprite {
image: sprite_handle.clone(),
custom_size: Some(tile_size),
color: if color_tint.0 {
COLORS[rng.gen_range(0..3)]
COLORS[rng.random_range(0..3)]
} else {
Color::WHITE
},

View File

@ -12,7 +12,7 @@ use bevy::{
use argh::FromArgs;
use rand::{
seq::{IteratorRandom, SliceRandom},
seq::{IndexedRandom, IteratorRandom},
Rng, SeedableRng,
};
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 x in -half_x..half_x {
let position = Vec2::new(x as f32, y as f32);
let translation = (position * tile_size).extend(rng.r#gen::<f32>());
let rotation = Quat::from_rotation_z(rng.r#gen::<f32>());
let scale = Vec3::splat(rng.r#gen::<f32>() * 2.0);
let color = Hsla::hsl(rng.gen_range(0.0..360.0), 0.8, 0.8);
let translation = (position * tile_size).extend(rng.random::<f32>());
let rotation = Quat::from_rotation_z(rng.random::<f32>());
let scale = Vec3::splat(rng.random::<f32>() * 2.0);
let color = Hsla::hsl(rng.random_range(0.0..360.0), 0.8, 0.8);
text2ds.push((
Text2d(random_text(&mut rng, &args)),

View File

@ -290,7 +290,7 @@ fn setup(mut commands: Commands, cfg: Res<Cfg>) {
}
TestCase::Humanoids { active, inactive } => {
let mut result = InsertResult::default();
let mut rng = rand::thread_rng();
let mut rng = rand::rng();
for _ in 0..active {
result.combine(spawn_tree(
@ -298,8 +298,8 @@ fn setup(mut commands: Commands, cfg: Res<Cfg>) {
&mut commands,
&cfg.update_filter,
Transform::from_xyz(
rng.r#gen::<f32>() * 500.0 - 250.0,
rng.r#gen::<f32>() * 500.0 - 250.0,
rng.random::<f32>() * 500.0 - 250.0,
rng.random::<f32>() * 500.0 - 250.0,
0.0,
),
));
@ -315,8 +315,8 @@ fn setup(mut commands: Commands, cfg: Res<Cfg>) {
..cfg.update_filter
},
Transform::from_xyz(
rng.r#gen::<f32>() * 500.0 - 250.0,
rng.r#gen::<f32>() * 500.0 - 250.0,
rng.random::<f32>() * 500.0 - 250.0,
rng.random::<f32>() * 500.0 - 250.0,
0.0,
),
));
@ -379,7 +379,7 @@ fn spawn_tree(
ents.push(commands.spawn(root_transform).id());
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)
let mut child_idx: Vec<u16> = vec![0; count];
@ -405,7 +405,7 @@ fn spawn_tree(
let mut cmd = commands.spawn_empty();
// 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);
if update {

View File

@ -75,8 +75,8 @@ fn setup(
));
// Initialize random axes
let first = seeded_rng.r#gen();
let second = seeded_rng.r#gen();
let first = seeded_rng.random();
let second = seeded_rng.random();
commands.spawn(RandomAxes(first, second));
// Finally, our ship that is going to rotate
@ -165,8 +165,8 @@ fn handle_keypress(
) {
if keyboard.just_pressed(KeyCode::KeyR) {
// Randomize the target axes
let first = seeded_rng.0.r#gen();
let second = seeded_rng.0.r#gen();
let first = seeded_rng.0.random();
let second = seeded_rng.0.random();
**random_axes = RandomAxes(first, second);
// 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 {
let c = seeded_rng.r#gen::<u8>() as char;
let c = seeded_rng.random::<u8>() as char;
let string = &mut **text;
if !string.contains(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,
"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!(
sh,