Skip to content

Commit

Permalink
Merge commit '056b006d4eade8f1bf75e735ed5eda33d9505c9e' into meshlet
Browse files Browse the repository at this point in the history
  • Loading branch information
JMS55 committed Jan 18, 2024
2 parents 726370a + 056b006 commit d0789ae
Show file tree
Hide file tree
Showing 23 changed files with 1,986 additions and 264 deletions.
25 changes: 24 additions & 1 deletion crates/bevy_ecs/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use crate::{
archetype::{ArchetypeComponentId, ArchetypeId, ArchetypeRow, Archetypes},
bundle::{Bundle, BundleInserter, BundleSpawner, Bundles},
change_detection::{MutUntyped, TicksMut},
component::{Component, ComponentDescriptor, ComponentId, ComponentInfo, Components, Tick},
component::{
Component, ComponentDescriptor, ComponentId, ComponentInfo, ComponentTicks, Components,
Tick,
},
entity::{AllocAtWithoutReplacement, Entities, Entity, EntityLocation},
event::{Event, EventId, Events, SendBatchIds},
query::{DebugCheckedUnwrap, QueryData, QueryEntityError, QueryFilter, QueryState},
Expand Down Expand Up @@ -1255,6 +1258,26 @@ impl World {
.unwrap_or(false)
}

/// Retrieves the change ticks for the given resource.
pub fn get_resource_change_ticks<R: Resource>(&self) -> Option<ComponentTicks> {
self.components
.get_resource_id(TypeId::of::<R>())
.and_then(|component_id| self.get_resource_change_ticks_by_id(component_id))
}

/// Retrieves the change ticks for the given [`ComponentId`].
///
/// **You should prefer to use the typed API [`World::get_resource_change_ticks`] where possible.**
pub fn get_resource_change_ticks_by_id(
&self,
component_id: ComponentId,
) -> Option<ComponentTicks> {
self.storages
.resources
.get(component_id)
.and_then(|resource| resource.get_ticks())
}

/// Gets a reference to the resource of the given type
///
/// # Panics
Expand Down
1 change: 1 addition & 0 deletions crates/bevy_gizmos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.12.0" }
bevy_core_pipeline = { path = "../bevy_core_pipeline", version = "0.12.0" }
bevy_transform = { path = "../bevy_transform", version = "0.12.0" }
bevy_log = { path = "../bevy_log", version = "0.12.0" }
bevy_gizmos_macros = { path = "macros", version = "0.12.0" }

[lints]
workspace = true
19 changes: 19 additions & 0 deletions crates/bevy_gizmos/macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "bevy_gizmos_macros"
version = "0.12.0"
edition = "2021"
description = "Derive implementations for bevy_gizmos"
homepage = "https://bevyengine.org"
repository = "https://github.com/bevyengine/bevy"
license = "MIT OR Apache-2.0"
keywords = ["bevy"]

[lib]
proc-macro = true

[dependencies]
bevy_macro_utils = { path = "../../bevy_macro_utils", version = "0.12.0" }

syn = "2.0"
proc-macro2 = "1.0"
quote = "1.0"
23 changes: 23 additions & 0 deletions crates/bevy_gizmos/macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use bevy_macro_utils::BevyManifest;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, parse_quote, DeriveInput, Path};

#[proc_macro_derive(GizmoConfigGroup)]
pub fn derive_gizmo_config_group(input: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(input as DeriveInput);
let bevy_gizmos_path: Path = BevyManifest::default().get_path("bevy_gizmos");
let bevy_reflect_path: Path = BevyManifest::default().get_path("bevy_reflect");

ast.generics.make_where_clause().predicates.push(
parse_quote! { Self: #bevy_reflect_path::Reflect + #bevy_reflect_path::TypePath + Default},
);

let struct_name = &ast.ident;
let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();

TokenStream::from(quote! {
impl #impl_generics #bevy_gizmos_path::config::GizmoConfigGroup for #struct_name #type_generics #where_clause {
}
})
}
120 changes: 120 additions & 0 deletions crates/bevy_gizmos/src/aabb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//! A module adding debug visualization of [`Aabb`]s.

use crate as bevy_gizmos;

use bevy_app::{Plugin, PostUpdate};
use bevy_ecs::{
component::Component,
entity::Entity,
query::Without,
reflect::ReflectComponent,
schedule::IntoSystemConfigs,
system::{Query, Res},
};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{color::Color, primitives::Aabb};
use bevy_transform::{
components::{GlobalTransform, Transform},
TransformSystem,
};

use crate::{
config::{GizmoConfigGroup, GizmoConfigStore},
gizmos::Gizmos,
AppGizmoBuilder,
};

/// A [`Plugin`] that provides visualization of [`Aabb`]s for debugging.
pub struct AabbGizmoPlugin;

impl Plugin for AabbGizmoPlugin {
fn build(&self, app: &mut bevy_app::App) {
app.register_type::<AabbGizmoConfigGroup>()
.init_gizmo_group::<AabbGizmoConfigGroup>()
.add_systems(
PostUpdate,
(
draw_aabbs,
draw_all_aabbs.run_if(|config: Res<GizmoConfigStore>| {
config.config::<AabbGizmoConfigGroup>().1.draw_all
}),
)
.after(TransformSystem::TransformPropagate),
);
}
}
/// The [`GizmoConfigGroup`] used for debug visualizations of [`Aabb`] components on entities
#[derive(Clone, Default, Reflect, GizmoConfigGroup)]
pub struct AabbGizmoConfigGroup {
/// Draws all bounding boxes in the scene when set to `true`.
///
/// To draw a specific entity's bounding box, you can add the [`ShowAabbGizmo`] component.
///
/// Defaults to `false`.
pub draw_all: bool,
/// The default color for bounding box gizmos.
///
/// A random color is chosen per box if `None`.
///
/// Defaults to `None`.
pub default_color: Option<Color>,
}

/// Add this [`Component`] to an entity to draw its [`Aabb`] component.
#[derive(Component, Reflect, Default, Debug)]
#[reflect(Component, Default)]
pub struct ShowAabbGizmo {
/// The color of the box.
///
/// The default color from the [`AabbGizmoConfigGroup`] config is used if `None`,
pub color: Option<Color>,
}

fn draw_aabbs(
query: Query<(Entity, &Aabb, &GlobalTransform, &ShowAabbGizmo)>,
mut gizmos: Gizmos<AabbGizmoConfigGroup>,
) {
for (entity, &aabb, &transform, gizmo) in &query {
let color = gizmo
.color
.or(gizmos.config_ext.default_color)
.unwrap_or_else(|| color_from_entity(entity));
gizmos.cuboid(aabb_transform(aabb, transform), color);
}
}

fn draw_all_aabbs(
query: Query<(Entity, &Aabb, &GlobalTransform), Without<ShowAabbGizmo>>,
mut gizmos: Gizmos<AabbGizmoConfigGroup>,
) {
for (entity, &aabb, &transform) in &query {
let color = gizmos
.config_ext
.default_color
.unwrap_or_else(|| color_from_entity(entity));
gizmos.cuboid(aabb_transform(aabb, transform), color);
}
}

fn color_from_entity(entity: Entity) -> Color {
let index = entity.index();

// from https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/
//
// See https://en.wikipedia.org/wiki/Low-discrepancy_sequence
// Map a sequence of integers (eg: 154, 155, 156, 157, 158) into the [0.0..1.0] range,
// so that the closer the numbers are, the larger the difference of their image.
const FRAC_U32MAX_GOLDEN_RATIO: u32 = 2654435769; // (u32::MAX / Φ) rounded up
const RATIO_360: f32 = 360.0 / u32::MAX as f32;
let hue = index.wrapping_mul(FRAC_U32MAX_GOLDEN_RATIO) as f32 * RATIO_360;

Color::hsl(hue, 1., 0.5)
}

fn aabb_transform(aabb: Aabb, transform: GlobalTransform) -> GlobalTransform {
transform
* GlobalTransform::from(
Transform::from_translation(aabb.center.into())
.with_scale((aabb.half_extents * 2.).into()),
)
}
17 changes: 10 additions & 7 deletions crates/bevy_gizmos/src/arcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
//! and assorted support items.

use crate::circles::DEFAULT_CIRCLE_SEGMENTS;
use crate::prelude::Gizmos;
use crate::prelude::{GizmoConfigGroup, Gizmos};
use bevy_math::Vec2;
use bevy_render::color::Color;
use std::f32::consts::TAU;

impl<'s> Gizmos<'s> {
impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
/// Draw an arc, which is a part of the circumference of a circle, in 2D.
///
/// This should be called for each frame the arc needs to be rendered.
Expand Down Expand Up @@ -46,7 +46,7 @@ impl<'s> Gizmos<'s> {
arc_angle: f32,
radius: f32,
color: Color,
) -> Arc2dBuilder<'_, 's> {
) -> Arc2dBuilder<'_, 'w, 's, T> {
Arc2dBuilder {
gizmos: self,
position,
Expand All @@ -60,8 +60,8 @@ impl<'s> Gizmos<'s> {
}

/// A builder returned by [`Gizmos::arc_2d`].
pub struct Arc2dBuilder<'a, 's> {
gizmos: &'a mut Gizmos<'s>,
pub struct Arc2dBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
gizmos: &'a mut Gizmos<'w, 's, T>,
position: Vec2,
direction_angle: f32,
arc_angle: f32,
Expand All @@ -70,16 +70,19 @@ pub struct Arc2dBuilder<'a, 's> {
segments: Option<usize>,
}

impl Arc2dBuilder<'_, '_> {
impl<T: GizmoConfigGroup> Arc2dBuilder<'_, '_, '_, T> {
/// Set the number of line-segments for this arc.
pub fn segments(mut self, segments: usize) -> Self {
self.segments = Some(segments);
self
}
}

impl Drop for Arc2dBuilder<'_, '_> {
impl<T: GizmoConfigGroup> Drop for Arc2dBuilder<'_, '_, '_, T> {
fn drop(&mut self) {
if !self.gizmos.enabled {
return;
}
let segments = match self.segments {
Some(segments) => segments,
// Do a linear interpolation between 1 and `DEFAULT_CIRCLE_SEGMENTS`
Expand Down
24 changes: 16 additions & 8 deletions crates/bevy_gizmos/src/arrows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
//! Includes the implementation of [`Gizmos::arrow`] and [`Gizmos::arrow_2d`],
//! and assorted support items.

use crate::prelude::Gizmos;
use crate::prelude::{GizmoConfigGroup, Gizmos};
use bevy_math::{Quat, Vec2, Vec3};
use bevy_render::color::Color;

/// A builder returned by [`Gizmos::arrow`] and [`Gizmos::arrow_2d`]
pub struct ArrowBuilder<'a, 's> {
gizmos: &'a mut Gizmos<'s>,
pub struct ArrowBuilder<'a, 'w, 's, T: GizmoConfigGroup> {
gizmos: &'a mut Gizmos<'w, 's, T>,
start: Vec3,
end: Vec3,
color: Color,
tip_length: f32,
}

impl ArrowBuilder<'_, '_> {
impl<T: GizmoConfigGroup> ArrowBuilder<'_, '_, '_, T> {
/// Change the length of the tips to be `length`.
/// The default tip length is [length of the arrow]/10.
///
Expand All @@ -37,9 +37,12 @@ impl ArrowBuilder<'_, '_> {
}
}

impl Drop for ArrowBuilder<'_, '_> {
impl<T: GizmoConfigGroup> Drop for ArrowBuilder<'_, '_, '_, T> {
/// Draws the arrow, by drawing lines with the stored [`Gizmos`]
fn drop(&mut self) {
if !self.gizmos.enabled {
return;
}
// first, draw the body of the arrow
self.gizmos.line(self.start, self.end, self.color);
// now the hard part is to draw the head in a sensible way
Expand All @@ -63,7 +66,7 @@ impl Drop for ArrowBuilder<'_, '_> {
}
}

impl<'s> Gizmos<'s> {
impl<'w, 's, T: GizmoConfigGroup> Gizmos<'w, 's, T> {
/// Draw an arrow in 3D, from `start` to `end`. Has four tips for convienent viewing from any direction.
///
/// This should be called for each frame the arrow needs to be rendered.
Expand All @@ -78,7 +81,7 @@ impl<'s> Gizmos<'s> {
/// }
/// # bevy_ecs::system::assert_is_system(system);
/// ```
pub fn arrow(&mut self, start: Vec3, end: Vec3, color: Color) -> ArrowBuilder<'_, 's> {
pub fn arrow(&mut self, start: Vec3, end: Vec3, color: Color) -> ArrowBuilder<'_, 'w, 's, T> {
let length = (end - start).length();
ArrowBuilder {
gizmos: self,
Expand All @@ -103,7 +106,12 @@ impl<'s> Gizmos<'s> {
/// }
/// # bevy_ecs::system::assert_is_system(system);
/// ```
pub fn arrow_2d(&mut self, start: Vec2, end: Vec2, color: Color) -> ArrowBuilder<'_, 's> {
pub fn arrow_2d(
&mut self,
start: Vec2,
end: Vec2,
color: Color,
) -> ArrowBuilder<'_, 'w, 's, T> {
self.arrow(start.extend(0.), end.extend(0.), color)
}
}
Loading

0 comments on commit d0789ae

Please sign in to comment.