From 946719c77ee1bfda2cdf15711e9e6e9adf07c639 Mon Sep 17 00:00:00 2001 From: atomicbeef Date: Thu, 7 Mar 2024 12:11:26 +0200 Subject: [PATCH] Update GlobalTransform when changing FloatingOrigin (#10) Currently, when the `FloatingOrigin` component is removed from one entity and added to another, no `GlobalTransform`s are updated. This can cause problems for things like switching between playable characters that are in different `GridCell`s. --------- Co-authored-by: Aevyrie --- .github/workflows/rust.yml | 19 ++++++-- Cargo.toml | 18 +++++++ examples/demo.rs | 2 +- src/lib.rs | 98 ++++++++++++++++++++++++++++++++++++-- src/propagation.rs | 8 +++- 5 files changed, 134 insertions(+), 11 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 31faeae..998ce14 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 --all-features + - 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 + - run: cargo check --no-default-features --all-targets 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 --all-features -- -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 --all-features + - run: cargo doc --all-features --no-deps env: RUSTDOCFLAGS: -D warnings @@ -68,4 +68,13 @@ jobs: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2.7.0 - - run: cargo test --all-features + - run: cargo test --all-features --all-targets + + doctest: + runs-on: ubuntu-latest + needs: [setup] + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2.7.0 + - run: cargo test --all-features --doc \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 2380671..15c508d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,3 +29,21 @@ default = ["debug", "camera", "bevy_render"] debug = ["bevy/bevy_gizmos"] bevy_render = ["bevy/bevy_render"] camera = ["bevy_render"] + +[[example]] +name = "demo" +path = "examples/demo.rs" +required-features = ["default"] +doc-scrape-examples = true + +[[example]] +name = "debug" +path = "examples/debug.rs" +required-features = ["default"] +doc-scrape-examples = true + +[[example]] +name = "error" +path = "examples/error.rs" +required-features = ["default"] +doc-scrape-examples = true diff --git a/examples/demo.rs b/examples/demo.rs index 87fc0ec..f7b82e0 100644 --- a/examples/demo.rs +++ b/examples/demo.rs @@ -1,7 +1,7 @@ use bevy::{ prelude::*, transform::TransformSystem, - window::{CursorGrabMode, PrimaryWindow, Window, WindowMode}, + window::{CursorGrabMode, PrimaryWindow, WindowMode}, }; use big_space::{ camera::{CameraController, CameraInput}, diff --git a/src/lib.rs b/src/lib.rs index 432a5da..d1540fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,7 +86,7 @@ #![allow(clippy::type_complexity)] #![deny(missing_docs)] -use bevy::{math::DVec3, prelude::*, reflect::TypePath, transform::TransformSystem}; +use bevy::{math::DVec3, prelude::*, transform::TransformSystem}; use propagation::propagate_transforms; use std::marker::PhantomData; @@ -311,7 +311,7 @@ pub fn recenter_transform_on_grid( /// Compute the `GlobalTransform` relative to the floating origin's cell. pub fn update_global_from_grid( settings: Res, - origin: Query>, With>, + origin: Query<(Ref>, Ref)>, mut entities: ParamSet<( Query< (&Transform, &mut GlobalTransform, &GridCell

), @@ -320,9 +320,9 @@ pub fn update_global_from_grid( Query<(&Transform, &mut GlobalTransform, &GridCell

)>, )>, ) { - let origin_cell = origin.single(); + let (origin_cell, floating_origin) = origin.single(); - if origin_cell.is_changed() { + if origin_cell.is_changed() || floating_origin.is_changed() { let mut all_entities = entities.p1(); all_entities .par_iter_mut() @@ -372,3 +372,93 @@ pub fn sync_simple_transforms( *global_transform = GlobalTransform::from(*transform); }); } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn changing_floating_origin_updates_global_transform() { + let mut app = App::new(); + app.add_plugins(FloatingOriginPlugin::::default()); + + let first = app + .world + .spawn(( + TransformBundle::from_transform(Transform::from_translation(Vec3::new( + 150.0, 0.0, 0.0, + ))), + GridCell::::new(5, 0, 0), + FloatingOrigin, + )) + .id(); + + let second = app + .world + .spawn(( + TransformBundle::from_transform(Transform::from_translation(Vec3::new( + 0.0, 0.0, 300.0, + ))), + GridCell::::new(0, -15, 0), + )) + .id(); + + app.update(); + + app.world.entity_mut(first).remove::(); + app.world.entity_mut(second).insert(FloatingOrigin); + + app.update(); + + let second_global_transform = app.world.get::(second).unwrap(); + + assert_eq!( + second_global_transform.translation(), + Vec3::new(0.0, 0.0, 300.0) + ); + } + + #[test] + fn child_global_transforms_are_updated_when_floating_origin_changes() { + let mut app = App::new(); + app.add_plugins(FloatingOriginPlugin::::default()); + + let first = app + .world + .spawn(( + TransformBundle::from_transform(Transform::from_translation(Vec3::new( + 150.0, 0.0, 0.0, + ))), + GridCell::::new(5, 0, 0), + FloatingOrigin, + )) + .id(); + + let second = app + .world + .spawn(( + TransformBundle::from_transform(Transform::from_translation(Vec3::new( + 0.0, 0.0, 300.0, + ))), + GridCell::::new(0, -15, 0), + )) + .with_children(|parent| { + parent.spawn((TransformBundle::from_transform( + Transform::from_translation(Vec3::new(0.0, 0.0, 300.0)), + ),)); + }) + .id(); + + app.update(); + + app.world.entity_mut(first).remove::(); + app.world.entity_mut(second).insert(FloatingOrigin); + + app.update(); + + let child = app.world.get::(second).unwrap()[0]; + let child_transform = app.world.get::(child).unwrap(); + + assert_eq!(child_transform.translation(), Vec3::new(0.0, 0.0, 600.0)); + } +} diff --git a/src/propagation.rs b/src/propagation.rs index c9c9ca9..3422c75 100644 --- a/src/propagation.rs +++ b/src/propagation.rs @@ -8,7 +8,13 @@ use bevy::prelude::*; /// Update [`GlobalTransform`] component of entities based on entity hierarchy and /// [`Transform`] component. pub fn propagate_transforms( - origin_moved: Query<(), (Changed>, With)>, + origin_moved: Query< + (), + ( + Or<(Changed>, Changed)>, + With, + ), + >, mut root_query: Query< ( Entity,