diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 98cf899..de1166d 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -29,7 +29,7 @@ jobs:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.7.0
- - run: cargo check --features=all --all-targets
+ - run: cargo check --all-features --all-targets
check-no-defaults:
runs-on: ubuntu-latest
@@ -38,7 +38,7 @@ jobs:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.7.0
- - run: cargo check --no-default-features --all-targets
+ - run: cargo check --no-default-features --all-targets --features=libm
clippy:
runs-on: ubuntu-latest
@@ -48,7 +48,7 @@ jobs:
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.7.0
- run: rustup component add clippy
- - run: cargo clippy --features=all --all-targets -- -D warnings
+ - run: cargo clippy --all-features --all-targets -- -D warnings
doc:
runs-on: ubuntu-latest
@@ -57,7 +57,7 @@ jobs:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.7.0
- - run: cargo doc --features=all --no-deps
+ - run: cargo doc --all-features --no-deps
env:
RUSTDOCFLAGS: -D warnings
@@ -68,7 +68,7 @@ jobs:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.7.0
- - run: cargo test --features=all
+ - run: cargo test --all-features
doctest:
runs-on: ubuntu-latest
@@ -77,4 +77,4 @@ jobs:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2.7.0
- - run: cargo test --features=all --doc
\ No newline at end of file
+ - run: cargo test --all-features --doc
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e07bb1..117f5da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
## UNRELEASED
+### New: `no_std` Support
+
+Thanks to `bushrat011899`'s efforts upstream and in this crate, it is now possible to use the plugin without the rust standard library. This is particularly useful when targeting embedded or console targets.
+
+## v0.9.0 - 2024-12-23
+
### New: `GridCell` Spatial Hashing
Spatial hashing makes fast spatial queries and neighbor lookups possible. This release adds the `GridHashMap`, an automatically updated map of the entities in each grid cell. This makes it possible to query things like:
@@ -37,5 +43,4 @@ The newly added types follow this pattern:
- `GridPartition`: Group of adjacent grid cells.
- `GridPartitionMap`: A map for finding independent partitions of entities.
-
It should now be more clear how all of the `Grid` types are related to each other.
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 2a6ed68..abd7483 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,42 +9,57 @@ repository = "https://github.com/aevyrie/big_space"
documentation = "https://docs.rs/crate/big_space/latest"
[features]
-default = []
-all = ["debug", "camera"] # Can't use all-features, integer type features are incompatible.
-debug = ["bevy_gizmos", "bevy_color"]
-camera = ["bevy_render", "bevy_time", "bevy_input"]
+default = ["std"]
+debug = ["std", "bevy_gizmos", "bevy_color"]
+camera = ["std", "bevy_render", "bevy_time", "bevy_input"]
i8 = []
i16 = []
i32 = []
i64 = []
i128 = []
-[dependencies]
-tracing = "0.1" # Less deps than pulling in bevy_log
-smallvec = "1.13.2" # Already used by bevy in commands
-bevy_app = { version = "0.15.0", default-features = false }
-bevy_ecs = { version = "0.15.0", default-features = true }
-bevy_hierarchy = { version = "0.15.0", default-features = false }
-bevy_math = { version = "0.15.0", default-features = false }
-bevy_reflect = { version = "0.15.0", default-features = false }
-bevy_tasks = { version = "0.15.0", default-features = false }
-bevy_transform = { version = "0.15.0", default-features = false, features = [
- "bevy-support",
-] }
-bevy_utils = { version = "0.15.0", default-features = false }
-# Optional
-bevy_color = { version = "0.15.0", default-features = false, optional = true }
-bevy_gizmos = { version = "0.15.0", default-features = false, optional = true }
-bevy_render = { version = "0.15.0", default-features = false, optional = true }
-bevy_input = { version = "0.15.0", default-features = false, optional = true }
-bevy_time = { version = "0.15.0", default-features = false, optional = true }
+std = [
+ "bevy_app/std",
+ "bevy_ecs/std",
+ "bevy_math/std",
+ "bevy_reflect/std",
+ "bevy_tasks/std",
+ "bevy_transform/std",
+ "bevy_utils/std",
+ "bevy_platform_support/std",
+ "bevy_color?/std",
+ "bevy_input?/std",
+ "bevy_time?/std",
+]
+libm = ["bevy_math/libm", "dep:libm"]
+[dependencies]
+tracing = { version = "0.1", default-features = false } # Less deps than pulling in bevy_log
+smallvec = { version = "1.13.2", default-features = false } # Already used by bevy in commands
+bevy_app = { version = "0.16.0-rc.3", default-features = false, features = ["bevy_reflect"] }
+bevy_ecs = { version = "0.16.0-rc.3", default-features = false }
+bevy_math = { version = "0.16.0-rc.3", default-features = false }
+bevy_reflect = { version = "0.16.0-rc.3", default-features = false, features = ["glam"] }
+bevy_tasks = { version = "0.16.0-rc.3", default-features = false }
+bevy_transform = { version = "0.16.0-rc.3", default-features = false, features = [
+ "bevy-support",
+ "bevy_reflect",
+] }
+bevy_utils = { version = "0.16.0-rc.3", default-features = false }
+bevy_platform_support = { version = "0.16.0-rc.3", default-features = false, features = ["alloc"] }
+# Optional
+bevy_color = { version = "0.16.0-rc.3", default-features = false, optional = true }
+bevy_gizmos = { version = "0.16.0-rc.3", default-features = false, optional = true }
+bevy_render = { version = "0.16.0-rc.3", default-features = false, optional = true }
+bevy_input = { version = "0.16.0-rc.3", default-features = false, optional = true }
+bevy_time = { version = "0.16.0-rc.3", default-features = false, optional = true }
+libm = { version = "0.2", default-features = false, optional = true }
[dev-dependencies]
-big_space = { path = "", features = ["debug", "camera"] }
-bevy = { version = "0.15.0", default-features = false, features = [
+bevy = { version = "0.16.0-rc.3", default-features = false, features = [
"bevy_scene",
"bevy_asset",
+ "bevy_color",
"bevy_gltf",
"bevy_winit",
"default_font",
@@ -61,7 +76,36 @@ noise = "0.9"
turborand = "0.10"
criterion = "0.5"
bytemuck = "1.20"
-bevy_hanabi = "0.14"
+# bevy_hanabi = "0.14" # TODO: Update
+
+[lints.clippy]
+doc_markdown = "warn"
+manual_let_else = "warn"
+match_same_arms = "warn"
+redundant_closure_for_method_calls = "warn"
+redundant_else = "warn"
+semicolon_if_nothing_returned = "warn"
+type_complexity = "allow"
+undocumented_unsafe_blocks = "warn"
+unwrap_or_default = "warn"
+
+ptr_as_ptr = "warn"
+ptr_cast_constness = "warn"
+ref_as_ptr = "warn"
+
+# see: https://github.com/bevyengine/bevy/pull/15375#issuecomment-2366966219
+too_long_first_doc_paragraph = "allow"
+
+std_instead_of_core = "warn"
+std_instead_of_alloc = "warn"
+alloc_instead_of_core = "warn"
+
+[lints.rust]
+missing_docs = "warn"
+unexpected_cfgs = { level = "warn", check-cfg = ['cfg(docsrs_dep)'] }
+unsafe_code = "deny"
+unsafe_op_in_unsafe_fn = "warn"
+unused_qualifications = "warn"
[[bench]]
name = "benchmarks"
@@ -70,18 +114,19 @@ harness = false
[[example]]
name = "debug"
path = "examples/debug.rs"
+required-features = ["debug"]
doc-scrape-examples = false
[[example]]
name = "demo"
path = "examples/demo.rs"
-required-features = ["i128"]
+required-features = ["i128", "camera", "debug"]
doc-scrape-examples = false
-
[[example]]
name = "error_child"
path = "examples/error_child.rs"
+required-features = ["camera", "debug"]
doc-scrape-examples = false
[[example]]
@@ -92,25 +137,41 @@ doc-scrape-examples = false
[[example]]
name = "infinite"
path = "examples/infinite.rs"
-required-features = ["i8"]
+required-features = ["i8", "camera", "debug"]
doc-scrape-examples = false
[[example]]
name = "minimal"
path = "examples/minimal.rs"
+required-features = ["camera"]
doc-scrape-examples = false
-[[example]]
-name = "particles"
-path = "examples/particles.rs"
-doc-scrape-examples = false
+# TODO: Uncomment once bevy_hanabi is updated
+# [[example]]
+# name = "particles"
+# path = "examples/particles.rs"
+# doc-scrape-examples = false
[[example]]
name = "planets"
path = "examples/planets.rs"
+required-features = ["camera"]
+doc-scrape-examples = false
+
+[[example]]
+name = "small_scale"
+path = "examples/small_scale.rs"
+required-features = ["camera", "debug"]
+doc-scrape-examples = false
+
+[[example]]
+name = "spatial_hash"
+path = "examples/spatial_hash.rs"
+required-features = ["camera"]
doc-scrape-examples = false
[[example]]
name = "split_screen"
path = "examples/split_screen.rs"
+required-features = ["camera", "debug"]
doc-scrape-examples = false
diff --git a/README.md b/README.md
index 25fe398..e804efc 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
Huge worlds, high performance, no dependencies, ecosystem compatibility. [Read the docs](https://docs.rs/big_space)
-
+
[](https://crates.io/crates/big_space)
[](https://docs.rs/big_space)
[](https://github.com/aevyrie/big_space/actions/workflows/rust.yml)
@@ -18,11 +18,10 @@ Huge worlds, high performance, no dependencies, ecosystem compatibility. [Read t
- Uses `Transform`, making it compatible with most of the Bevy ecosystem.
- No added dependencies.
- Absolute coordinates without drift, unlike camera-relative or periodic recentering solutions.
-- Chunks the world into integer grids, from `i8` up to `i128`.
-- Grids can be nested.
+- Chunks the world into nestable integer grids, from `i8` up to `i128`.
- Spatial hashing for fast grid cell lookups and neighbor search.
-- Spatial partitioning to group sets of disconnected entities.
-- 3-5x faster than Bevy's transform propagation for wide hierarchies.
+- Spatial partitioning to group sets of connected cells.
+- Great performance scaling and parallelism with massive entity counts.
- 👉 [Extensive documentation you should read.](https://docs.rs/big_space)

@@ -40,7 +39,8 @@ https://github.com/user-attachments/assets/9ce5283f-7d48-47dc-beef-9a7626858ed4
## Bevy Version Support
| bevy | big_space |
-| ---- | --------- |
+|------|-----------|
+| 0.16 | 0.10 |
| 0.15 | 0.8, 0.9 |
| 0.14 | 0.7 |
| 0.13 | 0.5, 0.6 |
diff --git a/benches/benchmarks.rs b/benches/benchmarks.rs
index 325fa26..24ecbc4 100644
--- a/benches/benchmarks.rs
+++ b/benches/benchmarks.rs
@@ -1,9 +1,11 @@
+//! `big_space` benchmarks.
#![allow(clippy::type_complexity)]
+#![allow(missing_docs)]
use bevy::prelude::*;
use big_space::prelude::*;
+use core::{iter::repeat_with, ops::Neg};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
-use std::{iter::repeat_with, ops::Neg};
use turborand::prelude::*;
criterion_group!(
@@ -52,7 +54,7 @@ fn deep_hierarchy(c: &mut Criterion) {
fn translate(mut transforms: Query<&mut Transform>) {
transforms.iter_mut().for_each(|mut transform| {
transform.translation += Vec3::ONE;
- })
+ });
}
let mut app = App::new();
@@ -91,7 +93,7 @@ fn wide_hierarchy(c: &mut Criterion) {
fn translate(mut transforms: Query<&mut Transform>) {
transforms.iter_mut().for_each(|mut transform| {
transform.translation += Vec3::ONE;
- })
+ });
}
let mut app = App::new();
@@ -126,9 +128,9 @@ fn spatial_hashing(c: &mut Criterion) {
let rng = Rng::with_seed(342525);
let values: Vec<_> = repeat_with(|| {
[
- rng.i64(-HALF_WIDTH..=HALF_WIDTH),
- rng.i64(-HALF_WIDTH..=HALF_WIDTH),
- rng.i64(-HALF_WIDTH..=HALF_WIDTH),
+ rng.i64(-HALF_WIDTH..=HALF_WIDTH) as GridPrecision,
+ rng.i64(-HALF_WIDTH..=HALF_WIDTH) as GridPrecision,
+ rng.i64(-HALF_WIDTH..=HALF_WIDTH) as GridPrecision,
]
})
.take(N_SPAWN)
@@ -143,7 +145,7 @@ fn spatial_hashing(c: &mut Criterion) {
fn translate(mut cells: Query<&mut GridCell>) {
cells.iter_mut().take(N_MOVE).for_each(|mut cell| {
*cell += GridCell::ONE;
- })
+ });
}
let mut app = App::new();
@@ -204,7 +206,7 @@ fn spatial_hashing(c: &mut Criterion) {
// });
// });
- fn setup_uniform(mut commands: Commands) {
+ fn setup_uniform(mut commands: Commands) {
commands.spawn_big_space(Grid::new(1.0, 0.0), |root| {
for x in HALF_EXTENT.neg()..HALF_EXTENT {
for y in HALF_EXTENT.neg()..HALF_EXTENT {
@@ -226,7 +228,8 @@ fn spatial_hashing(c: &mut Criterion) {
let parent = app
.world_mut()
.query_filtered::>()
- .single(app.world());
+ .single(app.world())
+ .unwrap();
let spatial_map = app.world().resource::();
let hash = GridHash::__new_manual(parent, &GridCell { x: 0, y: 0, z: 0 });
let entry = spatial_map.get(&hash).unwrap();
@@ -254,7 +257,8 @@ fn spatial_hashing(c: &mut Criterion) {
let parent = app
.world_mut()
.query_filtered::>()
- .single(app.world());
+ .single(app.world())
+ .unwrap();
let spatial_map = app.world().resource::();
let hash = GridHash::__new_manual(parent, &GridCell { x: 0, y: 0, z: 0 });
let entry = spatial_map.get(&hash).unwrap();
@@ -288,9 +292,9 @@ fn hash_filtering(c: &mut Criterion) {
let rng = Rng::with_seed(342525);
let values: Vec<_> = repeat_with(|| {
[
- rng.i64(-HALF_WIDTH..=HALF_WIDTH),
- rng.i64(-HALF_WIDTH..=HALF_WIDTH),
- rng.i64(-HALF_WIDTH..=HALF_WIDTH),
+ rng.i64(-HALF_WIDTH..=HALF_WIDTH) as GridPrecision,
+ rng.i64(-HALF_WIDTH..=HALF_WIDTH) as GridPrecision,
+ rng.i64(-HALF_WIDTH..=HALF_WIDTH) as GridPrecision,
]
})
.take(N_ENTITIES)
diff --git a/examples/debug.rs b/examples/debug.rs
index 5b06c38..98d7839 100644
--- a/examples/debug.rs
+++ b/examples/debug.rs
@@ -1,3 +1,4 @@
+//! Demonstrates debugging visualization for `big_space` components.
#![allow(clippy::type_complexity)]
use bevy::{color::palettes, prelude::*};
@@ -6,9 +7,9 @@ use big_space::prelude::*;
fn main() {
App::new()
.add_plugins((
- DefaultPlugins,
+ DefaultPlugins.build().disable::(),
BigSpacePlugin::default(),
- big_space::debug::FloatingOriginDebugPlugin::default(),
+ FloatingOriginDebugPlugin::default(),
))
.add_systems(Startup, setup)
.add_systems(Update, (movement, rotation))
@@ -26,7 +27,7 @@ fn movement(
Query<&mut Transform, With>>,
Query<&mut Transform, With>>,
)>,
-) {
+) -> Result {
let delta_translation = |offset: f32, scale: f32| -> Vec3 {
let t_1 = time.elapsed_secs() * 0.1 + offset;
let dt = time.delta_secs() * 0.1;
@@ -38,10 +39,12 @@ fn movement(
p1 - p0
};
- q.p0().single_mut().translation += delta_translation(20.0, 1.0);
- q.p1().single_mut().translation += delta_translation(251.0, 1.0);
- q.p2().single_mut().translation += delta_translation(812.0, 1.0);
- q.p3().single_mut().translation += delta_translation(863.0, 0.4);
+ q.p0().single_mut()?.translation += delta_translation(20.0, 1.0);
+ q.p1().single_mut()?.translation += delta_translation(251.0, 1.0);
+ q.p2().single_mut()?.translation += delta_translation(812.0, 1.0);
+ q.p3().single_mut()?.translation += delta_translation(863.0, 0.4);
+
+ Ok(())
}
#[derive(Component)]
diff --git a/examples/demo.rs b/examples/demo.rs
index f6dbd58..802de7d 100644
--- a/examples/demo.rs
+++ b/examples/demo.rs
@@ -1,3 +1,5 @@
+//! Demonstrates using the plugin over a wide range of scales, from protons to the universe.
+
use bevy::{
color::palettes,
prelude::*,
@@ -13,10 +15,10 @@ use big_space::{
fn main() {
App::new()
.add_plugins((
- DefaultPlugins,
+ DefaultPlugins.build().disable::(),
BigSpacePlugin::default(),
FloatingOriginDebugPlugin::default(),
- big_space::camera::CameraControllerPlugin::default(),
+ CameraControllerPlugin::default(),
))
.insert_resource(ClearColor(Color::BLACK))
.add_systems(Startup, (setup, ui_setup))
@@ -79,10 +81,10 @@ fn setup(
}
#[derive(Component, Reflect)]
-pub struct BigSpaceDebugText;
+struct BigSpaceDebugText;
#[derive(Component, Reflect)]
-pub struct FunFactText;
+struct FunFactText;
fn ui_setup(mut commands: Commands) {
commands.spawn((
@@ -125,13 +127,11 @@ fn highlight_nearest_sphere(
cameras: Query<&CameraController>,
objects: Query<&GlobalTransform>,
mut gizmos: Gizmos,
-) {
- let Some((entity, _)) = cameras.single().nearest_object() else {
- return;
- };
- let Ok(transform) = objects.get(entity) else {
- return;
+) -> Result {
+ let Some((entity, _)) = cameras.single()?.nearest_object() else {
+ return Ok(());
};
+ let transform = objects.get(entity)?;
// Ignore rotation due to panicking in gizmos, as of bevy 0.13
let (scale, _, translation) = transform.to_scale_rotation_translation();
gizmos
@@ -141,6 +141,7 @@ fn highlight_nearest_sphere(
Color::Srgba(palettes::basic::RED),
)
.resolution(128);
+ Ok(())
}
#[allow(clippy::type_complexity)]
@@ -155,8 +156,8 @@ fn ui_text_system(
origin: Query<(Entity, GridTransformReadOnly), With>,
camera: Query<&CameraController>,
objects: Query<&Transform, With>,
-) {
- let (origin_entity, origin_pos) = origin.single();
+) -> Result {
+ let (origin_entity, origin_pos) = origin.single()?;
let translation = origin_pos.transform.translation;
let grid_text = format!(
@@ -170,7 +171,7 @@ fn ui_text_system(
);
let Some(grid) = grids.parent_grid(origin_entity) else {
- return;
+ return Ok(());
};
let real_position = grid.grid_position_double(origin_pos.cell, origin_pos.transform);
@@ -183,7 +184,7 @@ fn ui_text_system(
real_position.x as f32, real_position.y as f32, real_position.z as f32
);
- let velocity = camera.single().velocity();
+ let velocity = camera.single()?.velocity();
let speed = velocity.0.length() / time.delta_secs_f64();
let camera_text = if speed > 3.0e8 {
format!("Speed: {:.0e} * speed of light", speed / 3.0e8)
@@ -191,8 +192,8 @@ fn ui_text_system(
format!("Speed: {:.2e} m/s", speed)
};
- let (nearest_text, fact_text) = if let Some(nearest) = camera.single().nearest_object() {
- let dia = objects.get(nearest.0).unwrap().scale.max_element();
+ let (nearest_text, fact_text) = if let Some(nearest) = camera.single()?.nearest_object() {
+ let dia = objects.get(nearest.0)?.scale.max_element();
let (fact_dia, fact) = closest(dia);
let dist = nearest.1;
let multiple = dia / fact_dia;
@@ -206,13 +207,15 @@ fn ui_text_system(
("".into(), "".into())
};
- let mut debug_text = debug_text.single_mut();
+ let mut debug_text = debug_text.single_mut()?;
debug_text.0.0 = format!(
"{grid_text}\n{translation_text}\n\n{real_position_f64_text}\n{real_position_f32_text}\n\n{camera_text}\n{nearest_text}"
);
- fun_text.single_mut().0 = fact_text
+ fun_text.single_mut()?.0 = fact_text;
+
+ Ok(())
}
fn closest<'a>(diameter: f32) -> (f32, &'a str) {
@@ -262,10 +265,8 @@ fn cursor_grab_system(
mut cam: ResMut,
btn: Res>,
key: Res>,
-) {
- let Some(mut window) = windows.get_single_mut().ok() else {
- return;
- };
+) -> Result {
+ let mut window = windows.single_mut()?;
if btn.just_pressed(MouseButton::Left) {
window.cursor_options.grab_mode = CursorGrabMode::Locked;
@@ -280,4 +281,6 @@ fn cursor_grab_system(
// window.mode = WindowMode::Windowed;
cam.defaults_disabled = true;
}
+
+ Ok(())
}
diff --git a/examples/error.rs b/examples/error.rs
index cb08217..7a0b9fd 100644
--- a/examples/error.rs
+++ b/examples/error.rs
@@ -10,7 +10,10 @@ use big_space::prelude::*;
fn main() {
App::new()
- .add_plugins((DefaultPlugins, BigSpacePlugin::default()))
+ .add_plugins((
+ DefaultPlugins.build().disable::(),
+ BigSpacePlugin::default(),
+ ))
.add_systems(Startup, (setup_scene, setup_ui))
.add_systems(Update, (rotator_system, toggle_plugin))
.run();
@@ -22,8 +25,8 @@ fn main() {
/// floating point error when we disable this plugin.
///
/// This plugin can function much further from the origin without any issues. Try setting this to:
-/// 10_000_000_000_000_000 with the default i64 feature, or
-/// 10_000_000_000_000_000_000_000_000_000_000_000_000 with the i128 feature.
+/// `10_000_000_000_000_000` with the default i64 feature, or
+/// `10_000_000_000_000_000_000_000_000_000_000_000_000` with the i128 feature.
const DISTANCE: GridPrecision = 2_000_000;
/// Move the floating origin back to the "true" origin when the user presses the spacebar to emulate
@@ -35,14 +38,16 @@ fn toggle_plugin(
mut text: Query<&mut Text>,
mut disabled: Local,
mut floating_origin: Query<(Entity, &mut GridCell), With>,
-) {
+) -> Result {
if input.just_pressed(KeyCode::Space) {
*disabled = !*disabled;
}
- let this_grid = grids.parent_grid(floating_origin.single().0).unwrap();
+ let this_grid = grids
+ .parent_grid(floating_origin.single().unwrap().0)
+ .unwrap();
- let mut origin_cell = floating_origin.single_mut().1;
+ let mut origin_cell = floating_origin.single_mut()?.1;
let index_max = DISTANCE / this_grid.cell_edge_length() as GridPrecision;
let increment = index_max / 100;
@@ -73,14 +78,16 @@ fn toggle_plugin(
.as_bytes()
.rchunks(3)
.rev()
- .map(std::str::from_utf8)
+ .map(core::str::from_utf8)
.collect::, _>>()
.unwrap()
.join(",") // separator
};
- text.single_mut().0 =
- format!("Press Spacebar to toggle: {msg}\nCamera distance to floating origin: {}\nMesh distance from origin: {}", thousands(dist), thousands(DISTANCE))
+ text.single_mut()?.0 =
+ format!("Press Spacebar to toggle: {msg}\nCamera distance to floating origin: {}\nMesh distance from origin: {}", thousands(dist), thousands(DISTANCE));
+
+ Ok(())
}
#[derive(Component)]
diff --git a/examples/error_child.rs b/examples/error_child.rs
index 50faf9f..7546d5f 100644
--- a/examples/error_child.rs
+++ b/examples/error_child.rs
@@ -1,15 +1,14 @@
//! This example demonstrates error accumulating from parent to children in nested grids.
-use bevy::{math::DVec3, prelude::*};
-use bevy_color::palettes;
+use bevy::{color::palettes, math::DVec3, prelude::*};
use big_space::prelude::*;
fn main() {
App::new()
.add_plugins((
- DefaultPlugins,
+ DefaultPlugins.build().disable::(),
BigSpacePlugin::default(),
- big_space::camera::CameraControllerPlugin::default(),
- big_space::debug::FloatingOriginDebugPlugin::default(),
+ CameraControllerPlugin::default(),
+ FloatingOriginDebugPlugin::default(),
))
.add_systems(Startup, setup_scene)
.run();
@@ -86,7 +85,7 @@ fn setup_scene(
..default()
}),
FloatingOrigin,
- big_space::camera::CameraController::default() // Built-in camera controller
+ CameraController::default() // Built-in camera controller
.with_speed_bounds([10e-18, 10e35])
.with_smoothness(0.9, 0.8)
.with_speed(1.0),
diff --git a/examples/infinite.rs b/examples/infinite.rs
index ab73853..684be7a 100644
--- a/examples/infinite.rs
+++ b/examples/infinite.rs
@@ -1,4 +1,5 @@
-//! Big spaces are infinite, looping back on themselves smoothly.
+//! Big spaces are infinite, looping back on themselves smoothly. This example requires the use of
+//! the `i8` feature, because a small world is needed to be able to see the "edge".
use bevy::prelude::*;
use big_space::prelude::*;
@@ -6,10 +7,10 @@ use big_space::prelude::*;
fn main() {
App::new()
.add_plugins((
- DefaultPlugins,
+ DefaultPlugins.build().disable::(),
BigSpacePlugin::default(),
- FloatingOriginDebugPlugin::default(), // Draws cell AABBs and grids
- big_space::camera::CameraControllerPlugin::default(), // Compatible controller
+ FloatingOriginDebugPlugin::default(),
+ CameraControllerPlugin::default(),
))
.add_systems(Startup, setup_scene)
.run();
@@ -44,7 +45,7 @@ fn setup_scene(
Camera3d::default(),
Transform::from_xyz(0.0, 0.0, 10.0),
FloatingOrigin,
- big_space::camera::CameraController::default()
+ CameraController::default()
.with_speed(10.)
.with_smoothness(0.99, 0.95),
));
diff --git a/examples/minimal.rs b/examples/minimal.rs
index 7946bb0..a4d368d 100644
--- a/examples/minimal.rs
+++ b/examples/minimal.rs
@@ -10,10 +10,10 @@ const BIG_DISTANCE: f64 = 1_000_000_000_000_000_000.0;
fn main() {
App::new()
.add_plugins((
- DefaultPlugins,
+ DefaultPlugins.build().disable::(),
BigSpacePlugin::default(),
FloatingOriginDebugPlugin::default(), // Draws cell AABBs and grids
- big_space::camera::CameraControllerPlugin::default(), // Compatible controller
+ CameraControllerPlugin::default(), // Compatible controller
))
.add_systems(Startup, setup_scene)
.run();
@@ -67,7 +67,7 @@ fn setup_scene(
Transform::from_translation(cell_offset + Vec3::new(0.0, 0.0, 10.0)),
grid_cell,
FloatingOrigin,
- big_space::camera::CameraController::default(),
+ CameraController::default(),
));
});
}
diff --git a/examples/particles.rs b/examples/particles.rs.todo
similarity index 100%
rename from examples/particles.rs
rename to examples/particles.rs.todo
diff --git a/examples/planets.rs b/examples/planets.rs
index 70731e3..aa10271 100644
--- a/examples/planets.rs
+++ b/examples/planets.rs
@@ -1,4 +1,7 @@
-use std::collections::VecDeque;
+//! A practical example of a spare ship on a planet, in a solar system, surrounded by stars.
+extern crate alloc;
+
+use alloc::collections::VecDeque;
use bevy::{
color::palettes,
@@ -15,14 +18,15 @@ use turborand::{rng::Rng, TurboRand};
fn main() {
App::new()
.add_plugins((
- DefaultPlugins,
+ DefaultPlugins.build().disable::(),
BigSpacePlugin::new(true),
- big_space::camera::CameraControllerPlugin::default(),
+ CameraControllerPlugin::default(),
))
.insert_resource(ClearColor(Color::BLACK))
.insert_resource(AmbientLight {
color: Color::WHITE,
brightness: 200.0,
+ ..Default::default()
})
.add_systems(Startup, spawn_solar_system)
.add_systems(
@@ -69,11 +73,12 @@ fn rotate(mut rotate_query: Query<(&mut Transform, &Rotates)>) {
fn lighting(
mut light: Query<(&mut Transform, &mut GlobalTransform), With>,
sun: Query<&GlobalTransform, (With, Without)>,
-) {
- let sun_pos = sun.single().translation();
- let (mut light_tr, mut light_gt) = light.single_mut();
+) -> Result {
+ let sun_pos = sun.single()?.translation();
+ let (mut light_tr, mut light_gt) = light.single_mut()?;
light_tr.look_at(-sun_pos, Vec3::Y);
*light_gt = (*light_tr).into();
+ Ok(())
}
fn springy_ship(
@@ -81,7 +86,7 @@ fn springy_ship(
mut ship: Query<&mut Transform, With>,
mut desired_dir: Local<(Vec3, Quat)>,
mut smoothed_rot: Local>,
-) {
+) -> Result {
desired_dir.0 = DVec3::new(cam_input.right, cam_input.up, -cam_input.forward).as_vec3()
* (1.0 + cam_input.boost as u8 as f32);
@@ -89,7 +94,7 @@ fn springy_ship(
smoothed_rot.push_front(DVec3::new(cam_input.pitch, cam_input.yaw, cam_input.roll).as_vec3());
let avg_rot = smoothed_rot.iter().sum::() / smoothed_rot.len() as f32;
- use std::f32::consts::*;
+ use core::f32::consts::*;
desired_dir.1 = Quat::IDENTITY.slerp(
Quat::from_euler(
EulerRot::XYZ,
@@ -100,12 +105,14 @@ fn springy_ship(
0.2,
) * Quat::from_rotation_y(PI);
- ship.single_mut().translation = ship
- .single_mut()
+ ship.single_mut()?.translation = ship
+ .single_mut()?
.translation
.lerp(desired_dir.0 * Vec3::new(0.5, 0.5, -2.0), 0.02);
- ship.single_mut().rotation = ship.single_mut().rotation.slerp(desired_dir.1, 0.02);
+ ship.single_mut()?.rotation = ship.single_mut()?.rotation.slerp(desired_dir.1, 0.02);
+
+ Ok(())
}
fn spawn_solar_system(
@@ -218,7 +225,7 @@ fn spawn_solar_system(
camera.insert((
FloatingOrigin,
Transform::from_translation(cam_pos).looking_to(Vec3::NEG_Z, Vec3::X),
- big_space::camera::CameraController::default() // Built-in camera controller
+ CameraController::default() // Built-in camera controller
.with_speed_bounds([0.1, 10e35])
.with_smoothness(0.98, 0.98)
.with_speed(1.0),
@@ -244,7 +251,7 @@ fn spawn_solar_system(
camera.with_child((
Spaceship,
SceneRoot(asset_server.load("models/low_poly_spaceship/scene.gltf#Scene0")),
- Transform::from_rotation(Quat::from_rotation_y(std::f32::consts::PI)),
+ Transform::from_rotation(Quat::from_rotation_y(core::f32::consts::PI)),
));
});
});
@@ -276,10 +283,8 @@ fn cursor_grab_system(
mut cam: ResMut,
btn: Res>,
key: Res>,
-) {
- let Some(mut window) = windows.get_single_mut().ok() else {
- return;
- };
+) -> Result<()> {
+ let mut window = windows.single_mut()?;
if btn.just_pressed(MouseButton::Right) {
window.cursor_options.grab_mode = bevy::window::CursorGrabMode::Locked;
@@ -294,4 +299,6 @@ fn cursor_grab_system(
// window.mode = WindowMode::Windowed;
cam.defaults_disabled = true;
}
+
+ Ok(())
}
diff --git a/examples/small_scale.rs b/examples/small_scale.rs
index d7d91ed..2b296df 100644
--- a/examples/small_scale.rs
+++ b/examples/small_scale.rs
@@ -9,6 +9,7 @@
use bevy::prelude::*;
use bevy_math::DVec3;
use big_space::prelude::*;
+use tracing::info;
const UNIVERSE_DIA: f64 = 8.8e26; // Diameter of the observable universe
const PROTON_DIA: f32 = 1.68e-15; // Diameter of a proton
@@ -16,10 +17,10 @@ const PROTON_DIA: f32 = 1.68e-15; // Diameter of a proton
fn main() {
App::new()
.add_plugins((
- DefaultPlugins,
+ DefaultPlugins.build().disable::(),
BigSpacePlugin::default(),
FloatingOriginDebugPlugin::default(), // Draws cell AABBs and grids
- big_space::camera::CameraControllerPlugin::default(), // Compatible controller
+ CameraControllerPlugin::default(), // Compatible controller
))
.add_systems(Startup, setup_scene)
.add_systems(Update, (bounce_atoms, toggle_cam_pos))
@@ -75,14 +76,14 @@ fn setup_scene(
Transform::from_xyz(0.0, 0.0, PROTON_DIA * 2.0),
grid_cell,
FloatingOrigin,
- big_space::camera::CameraController::default(),
+ CameraController::default(),
));
// A space ship
root_grid.spawn_spatial((
SceneRoot(asset_server.load("models/low_poly_spaceship/scene.gltf#Scene0")),
Transform::from_xyz(0.0, 0.0, 2.5)
- .with_rotation(Quat::from_rotation_y(std::f32::consts::PI)),
+ .with_rotation(Quat::from_rotation_y(core::f32::consts::PI)),
grid_cell,
));
});
@@ -104,12 +105,15 @@ fn toggle_cam_pos(
grid: Query<&Grid>,
keyboard: Res>,
protons: Query<&GlobalTransform, With>,
-) {
+) -> Result {
if !keyboard.just_pressed(KeyCode::KeyT) {
- return;
+ return Ok(());
}
- *cam.single_mut() = if *toggle {
- grid.single().translation_to_grid(DVec3::X * UNIVERSE_DIA).0
+ *cam.single_mut()? = if *toggle {
+ grid.single()
+ .unwrap()
+ .translation_to_grid(DVec3::X * UNIVERSE_DIA)
+ .0
} else {
GridCell::ZERO
};
@@ -120,4 +124,5 @@ fn toggle_cam_pos(
for proton in &protons {
info!("Proton x coord: {}", proton.translation().x);
}
+ Ok(())
}
diff --git a/examples/spatial_hash.rs b/examples/spatial_hash.rs
index 4502fc3..9792de9 100644
--- a/examples/spatial_hash.rs
+++ b/examples/spatial_hash.rs
@@ -1,14 +1,14 @@
-use std::hash::Hasher;
+//! Demonstrates the included optional spatial hashing and partitioning of grid cells.
use bevy::{
- core_pipeline::{bloom::Bloom, fxaa::Fxaa, tonemapping::Tonemapping},
+ core_pipeline::{bloom::Bloom, tonemapping::Tonemapping},
prelude::*,
};
-use bevy_ecs::entity::EntityHasher;
+use bevy_ecs::{entity::EntityHasher, relationship::Relationship};
use bevy_math::DVec3;
use big_space::prelude::*;
+use core::hash::Hasher;
use noise::{NoiseFn, Simplex};
-use smallvec::SmallVec;
use turborand::prelude::*;
// Try bumping this up to really stress test. I'm able to push a million entities with an M3 Max.
@@ -21,11 +21,11 @@ const PERCENT_STATIC: f32 = 0.99;
fn main() {
App::new()
.add_plugins((
- DefaultPlugins,
+ DefaultPlugins.build().disable::(),
BigSpacePlugin::default(),
GridHashPlugin::<()>::default(),
GridPartitionPlugin::<()>::default(),
- big_space::camera::CameraControllerPlugin::default(),
+ CameraControllerPlugin::default(),
))
.add_systems(Startup, (spawn, setup_ui))
.add_systems(
@@ -69,7 +69,7 @@ impl FromWorld for MaterialPresets {
let mut meshes = world.resource_mut::>();
let sphere = meshes.add(
- Sphere::new(HALF_WIDTH / (1_000_000_f32).powf(0.33) * 0.5)
+ Sphere::new(HALF_WIDTH / 1_000_000_f32.powf(0.33) * 0.5)
.mesh()
.ico(0)
.unwrap(),
@@ -89,10 +89,12 @@ fn draw_partitions(
partitions: Res,
grids: Query<(&GlobalTransform, &Grid)>,
camera: Query<&GridHash, With>,
-) {
+) -> Result {
+ let camera = camera.single()?;
+
for (id, p) in partitions.iter().take(10_000) {
let Ok((transform, grid)) = grids.get(p.grid()) else {
- return;
+ return Ok(());
};
let l = grid.cell_edge_length();
@@ -102,7 +104,7 @@ fn draw_partitions(
let hue = (f % 360) as f32;
p.iter()
- .filter(|hash| *hash != camera.single())
+ .filter(|hash| *hash != camera)
.take(1_000)
.for_each(|h| {
let center = [h.cell().x as i32, h.cell().y as i32, h.cell().z as i32];
@@ -110,7 +112,7 @@ fn draw_partitions(
.with_scale(Vec3::splat(l));
gizmos.cuboid(
transform.mul_transform(local_trans),
- Hsla::new(hue, 1.0, 0.5, 0.05),
+ Hsla::new(hue, 1.0, 0.5, 0.2),
);
});
@@ -123,19 +125,20 @@ fn draw_partitions(
gizmos.cuboid(
transform.mul_transform(local_trans),
- Hsla::new(hue, 1.0, 0.5, 0.2),
+ Hsla::new(hue, 1.0, 0.5, 0.9),
);
}
+
+ Ok(())
}
#[allow(clippy::too_many_arguments)]
#[allow(clippy::type_complexity)]
fn move_player(
time: Res