Skip to content

Commit ffcaef3

Browse files
committed
Merge branch 'main' of https://github.com/bevyengine/bevy into frustum_culling
2 parents 549b5f6 + 45b2db7 commit ffcaef3

File tree

125 files changed

+4227
-1897
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+4227
-1897
lines changed

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ path = "examples/3d/orthographic.rs"
135135
name = "parenting"
136136
path = "examples/3d/parenting.rs"
137137

138+
[[example]]
139+
name = "pbr"
140+
path = "examples/3d/pbr.rs"
141+
138142
[[example]]
139143
name = "spawner"
140144
path = "examples/3d/spawner.rs"
@@ -302,6 +306,10 @@ path = "examples/input/gamepad_input_events.rs"
302306
name = "keyboard_input"
303307
path = "examples/input/keyboard_input.rs"
304308

309+
[[example]]
310+
name = "keyboard_modifiers"
311+
path = "examples/input/keyboard_modifiers.rs"
312+
305313
[[example]]
306314
name = "keyboard_input_events"
307315
path = "examples/input/keyboard_input_events.rs"

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ Before contributing or participating in discussions with the community, you shou
5151
We recommend checking out [The Bevy Book](https://bevyengine.org/learn/book/introduction) for a full tutorial.
5252

5353
Follow the [Setup guide](https://bevyengine.org/learn/book/getting-started/setup/) to ensure your development environment is set up correctly.
54-
Once set up, you can quickly try out the [examples](/examples) by cloning this repo and running the following command:
54+
Once set up, you can quickly try out the [examples](https://github.com/bevyengine/bevy/tree/latest/examples) by cloning this repo and running the following commands:
5555

5656
```sh
57+
# Switch to the correct version (latest release, default is main development branch)
58+
git checkout latest
5759
# Runs the "breakout" example
5860
cargo run --example breakout
5961
```

assets/shaders/hot.vert

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
layout(location = 0) in vec3 Vertex_Position;
44

5-
layout(set = 0, binding = 0) uniform Camera {
5+
layout(set = 0, binding = 0) uniform CameraViewProj {
66
mat4 ViewProj;
77
};
88

crates/bevy_app/src/app_builder.rs

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
use bevy_ecs::{
88
component::Component,
99
schedule::{
10-
RunOnce, Schedule, Stage, StageLabel, StateStage, SystemDescriptor, SystemSet, SystemStage,
10+
RunOnce, Schedule, Stage, StageLabel, State, SystemDescriptor, SystemSet, SystemStage,
1111
},
1212
system::{IntoExclusiveSystem, IntoSystem},
1313
world::{FromWorld, World},
@@ -177,37 +177,18 @@ impl AppBuilder {
177177
self
178178
}
179179

180-
pub fn on_state_enter<T: Clone + Component>(
181-
&mut self,
182-
stage: impl StageLabel,
183-
state: T,
184-
system: impl Into<SystemDescriptor>,
185-
) -> &mut Self {
186-
self.stage(stage, |stage: &mut StateStage<T>| {
187-
stage.on_state_enter(state, system)
188-
})
180+
pub fn add_state<T: Component + Clone + Eq>(&mut self, initial: T) -> &mut Self {
181+
self.insert_resource(State::new(initial))
182+
.add_system_set(State::<T>::make_driver())
189183
}
190184

191-
pub fn on_state_update<T: Clone + Component>(
185+
pub fn add_state_to_stage<T: Component + Clone + Eq>(
192186
&mut self,
193187
stage: impl StageLabel,
194-
state: T,
195-
system: impl Into<SystemDescriptor>,
196-
) -> &mut Self {
197-
self.stage(stage, |stage: &mut StateStage<T>| {
198-
stage.on_state_update(state, system)
199-
})
200-
}
201-
202-
pub fn on_state_exit<T: Clone + Component>(
203-
&mut self,
204-
stage: impl StageLabel,
205-
state: T,
206-
system: impl Into<SystemDescriptor>,
188+
initial: T,
207189
) -> &mut Self {
208-
self.stage(stage, |stage: &mut StateStage<T>| {
209-
stage.on_state_exit(state, system)
210-
})
190+
self.insert_resource(State::new(initial))
191+
.add_system_set_to_stage(stage, State::<T>::make_driver())
211192
}
212193

213194
pub fn add_default_stages(&mut self) -> &mut Self {
@@ -226,6 +207,10 @@ impl AppBuilder {
226207
.add_stage(CoreStage::Last, SystemStage::parallel())
227208
}
228209

210+
/// Setup the application to manage events of type `T`.
211+
///
212+
/// This is done by adding a `Resource` of type `Events::<T>`,
213+
/// and inserting a `Events::<T>::update_system` system into `CoreStage::First`.
229214
pub fn add_event<T>(&mut self) -> &mut Self
230215
where
231216
T: Component,

crates/bevy_app/src/event.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,23 @@ enum State {
5656
}
5757

5858
/// An event collection that represents the events that occurred within the last two
59-
/// [Events::update] calls. Events can be cheaply read using an [EventReader]. This collection is
60-
/// meant to be paired with a system that calls [Events::update] exactly once per update/frame.
61-
/// [Events::update_system] is a system that does this. [EventReader]s are expected to read events
62-
/// from this collection at least once per update/frame. If events are not handled within one
63-
/// frame/update, they will be dropped.
59+
/// [`Events::update`] calls.
60+
/// Events can be written to using an [`EventWriter`]
61+
/// and are typically cheaply read using an [`EventReader`].
62+
///
63+
/// Each event can be consumed by multiple systems, in parallel,
64+
/// with consumption tracked by the [`EventReader`] on a per-system basis.
65+
///
66+
/// This collection is meant to be paired with a system that calls
67+
/// [`Events::update`] exactly once per update/frame.
68+
///
69+
/// [`Events::update_system`] is a system that does this, typically intialized automatically using
70+
/// [`AppBuilder::add_event`]. [EventReader]s are expected to read events from this collection at
71+
/// least once per loop/frame.
72+
/// Events will persist across a single frame boundary and so ordering of event producers and
73+
/// consumers is not critical (although poorly-planned ordering may cause accumulating lag).
74+
/// If events are not handled by the end of the frame after they are updated, they will be
75+
/// dropped silently.
6476
///
6577
/// # Example
6678
/// ```
@@ -100,7 +112,9 @@ enum State {
100112
/// The buffers in [Events] will grow indefinitely if [Events::update] is never called.
101113
///
102114
/// An alternative call pattern would be to call [Events::update] manually across frames to control
103-
/// when events are cleared. However this complicates consumption
115+
/// when events are cleared.
116+
/// This complicates consumption and risks ever-expanding memory usage if not cleaned up,
117+
/// but can be done by adding your event as a resource instead of using [`AppBuilder::add_event`].
104118
#[derive(Debug)]
105119
pub struct Events<T> {
106120
events_a: Vec<EventInstance<T>>,

crates/bevy_asset/src/asset_server.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,13 @@ impl AssetServer {
435435
AssetPath::new_ref(&load_context.path, label.as_ref().map(|l| l.as_str()));
436436
asset_lifecycle.create_asset(asset_path.into(), asset_value, load_context.version);
437437
} else {
438-
panic!("Failed to find AssetLifecycle for label {:?}, which has an asset type {:?}. Are you sure that is a registered asset type?", label, asset_value.type_uuid());
438+
panic!(
439+
"Failed to find AssetLifecycle for label '{:?}', which has an asset type {} (UUID {:?}). \
440+
Are you sure this asset type has been added to your app builder?",
441+
label,
442+
asset_value.type_name(),
443+
asset_value.type_uuid(),
444+
);
439445
}
440446
}
441447
}
@@ -465,7 +471,7 @@ impl AssetServer {
465471
}
466472
}
467473

468-
assets.set(result.id, result.asset);
474+
let _ = assets.set(result.id, result.asset);
469475
}
470476
Ok(AssetLifecycleEvent::Free(handle_id)) => {
471477
if let HandleId::AssetPathId(id) = handle_id {

crates/bevy_asset/src/assets.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,10 @@ impl<T: Asset> Assets<T> {
7272
self.get_handle(id)
7373
}
7474

75+
#[must_use = "not using the returned strong handle may result in the unexpected release of the asset"]
7576
pub fn set<H: Into<HandleId>>(&mut self, handle: H, asset: T) -> Handle<T> {
7677
let id: HandleId = handle.into();
77-
if self.assets.insert(id, asset).is_some() {
78-
self.events.send(AssetEvent::Modified {
79-
handle: Handle::weak(id),
80-
});
81-
} else {
82-
self.events.send(AssetEvent::Created {
83-
handle: Handle::weak(id),
84-
});
85-
}
86-
78+
self.set_untracked(id, asset);
8779
self.get_handle(id)
8880
}
8981

crates/bevy_core/src/task_pool_options.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl TaskPoolThreadAssignmentPolicy {
2727
// Clamp by min_threads, max_threads. (This may result in us using more threads than are
2828
// available, this is intended. An example case where this might happen is a device with
2929
// <= 2 threads.
30-
bevy_math::clamp(desired, self.min_threads, self.max_threads)
30+
desired.clamp(self.min_threads, self.max_threads)
3131
}
3232
}
3333

@@ -94,11 +94,8 @@ impl DefaultTaskPoolOptions {
9494

9595
/// Inserts the default thread pools into the given resource map based on the configured values
9696
pub fn create_default_pools(&self, world: &mut World) {
97-
let total_threads = bevy_math::clamp(
98-
bevy_tasks::logical_core_count(),
99-
self.min_total_threads,
100-
self.max_total_threads,
101-
);
97+
let total_threads =
98+
bevy_tasks::logical_core_count().clamp(self.min_total_threads, self.max_total_threads);
10299
trace!("Assigning {} cores to default task pools", total_threads);
103100

104101
let mut remaining_threads = total_threads;

crates/bevy_core/src/time/fixed_timestep.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,8 @@ impl System for FixedTimestep {
196196
);
197197
}
198198
}
199+
200+
fn check_change_tick(&mut self, change_tick: u32) {
201+
self.internal_system.check_change_tick(change_tick);
202+
}
199203
}

crates/bevy_ecs/macros/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,11 +270,12 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
270270
#[inline]
271271
unsafe fn get_param(
272272
state: &'a mut Self,
273-
_system_state: &'a SystemState,
273+
system_state: &'a SystemState,
274274
world: &'a World,
275+
change_tick: u32,
275276
) -> Self::Item {
276277
let (#(#query,)*) = &state.0;
277-
QuerySet((#(Query::new(world, #query),)*))
278+
QuerySet((#(Query::new(world, #query, system_state.last_change_tick, change_tick),)*))
278279
}
279280
}
280281

@@ -402,9 +403,10 @@ pub fn derive_system_param(input: TokenStream) -> TokenStream {
402403
state: &'a mut Self,
403404
system_state: &'a #path::system::SystemState,
404405
world: &'a #path::world::World,
406+
change_tick: u32,
405407
) -> Self::Item {
406408
#struct_name {
407-
#(#fields: <<#field_types as SystemParam>::Fetch as #path::system::SystemParamFetch>::get_param(&mut state.state.#field_indices, system_state, world),)*
409+
#(#fields: <<#field_types as SystemParam>::Fetch as #path::system::SystemParamFetch>::get_param(&mut state.state.#field_indices, system_state, world, change_tick),)*
408410
#(#ignored_fields: <#ignored_field_types>::default(),)*
409411
}
410412
}

crates/bevy_ecs/src/archetype.rs

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
use crate::{
22
bundle::BundleId,
3-
component::{ComponentFlags, ComponentId, StorageType},
3+
component::{ComponentId, StorageType},
44
entity::{Entity, EntityLocation},
55
storage::{Column, SparseArray, SparseSet, SparseSetIndex, TableId},
66
};
7-
use std::{borrow::Cow, collections::HashMap, hash::Hash};
7+
use std::{
8+
borrow::Cow,
9+
collections::HashMap,
10+
hash::Hash,
11+
ops::{Index, IndexMut},
12+
};
813

914
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
1015
pub struct ArchetypeId(usize);
@@ -31,9 +36,14 @@ impl ArchetypeId {
3136
}
3237
}
3338

39+
pub enum ComponentStatus {
40+
Added,
41+
Mutated,
42+
}
43+
3444
pub struct FromBundle {
3545
pub archetype_id: ArchetypeId,
36-
pub bundle_flags: Vec<ComponentFlags>,
46+
pub bundle_status: Vec<ComponentStatus>,
3747
}
3848

3949
#[derive(Default)]
@@ -65,13 +75,13 @@ impl Edges {
6575
&mut self,
6676
bundle_id: BundleId,
6777
archetype_id: ArchetypeId,
68-
bundle_flags: Vec<ComponentFlags>,
78+
bundle_status: Vec<ComponentStatus>,
6979
) {
7080
self.from_bundle.insert(
7181
bundle_id,
7282
FromBundle {
7383
archetype_id,
74-
bundle_flags,
84+
bundle_status,
7585
},
7686
);
7787
}
@@ -443,27 +453,11 @@ impl Archetypes {
443453
self.archetypes.get(id.index())
444454
}
445455

446-
/// # Safety
447-
/// `id` must be valid
448-
#[inline]
449-
pub unsafe fn get_unchecked(&self, id: ArchetypeId) -> &Archetype {
450-
debug_assert!(id.index() < self.archetypes.len());
451-
self.archetypes.get_unchecked(id.index())
452-
}
453-
454456
#[inline]
455457
pub fn get_mut(&mut self, id: ArchetypeId) -> Option<&mut Archetype> {
456458
self.archetypes.get_mut(id.index())
457459
}
458460

459-
/// # Safety
460-
/// `id` must be valid
461-
#[inline]
462-
pub unsafe fn get_unchecked_mut(&mut self, id: ArchetypeId) -> &mut Archetype {
463-
debug_assert!(id.index() < self.archetypes.len());
464-
self.archetypes.get_unchecked_mut(id.index())
465-
}
466-
467461
#[inline]
468462
pub fn iter(&self) -> impl Iterator<Item = &Archetype> {
469463
self.archetypes.iter()
@@ -522,3 +516,19 @@ impl Archetypes {
522516
self.archetype_component_count
523517
}
524518
}
519+
520+
impl Index<ArchetypeId> for Archetypes {
521+
type Output = Archetype;
522+
523+
#[inline]
524+
fn index(&self, index: ArchetypeId) -> &Self::Output {
525+
&self.archetypes[index.index()]
526+
}
527+
}
528+
529+
impl IndexMut<ArchetypeId> for Archetypes {
530+
#[inline]
531+
fn index_mut(&mut self, index: ArchetypeId) -> &mut Self::Output {
532+
&mut self.archetypes[index.index()]
533+
}
534+
}

0 commit comments

Comments
 (0)