Resolve (most) internal system ambiguities (#1606)
* Adds labels and orderings to systems that need them (uses the new many-to-many labels for InputSystem) * Removes the Event, PreEvent, Scene, and Ui stages in favor of First, PreUpdate, and PostUpdate (there is more collapsing potential, such as the Asset stages and _maybe_ removing First, but those have more nuance so they should be handled separately) * Ambiguity detection now prints component conflicts * Removed broken change filters from flex calculation (which implicitly relied on the z-update system always modifying translation.z). This will require more work to make it behave as expected so i just removed it (and it was already doing this work every frame).
This commit is contained in:
parent
1e42de64af
commit
be1c317d4e
@ -211,7 +211,8 @@ impl AppBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_default_stages(&mut self) -> &mut Self {
|
pub fn add_default_stages(&mut self) -> &mut Self {
|
||||||
self.add_stage(
|
self.add_stage(CoreStage::First, SystemStage::parallel())
|
||||||
|
.add_stage(
|
||||||
CoreStage::Startup,
|
CoreStage::Startup,
|
||||||
Schedule::default()
|
Schedule::default()
|
||||||
.with_run_criteria(RunOnce::default())
|
.with_run_criteria(RunOnce::default())
|
||||||
@ -219,9 +220,6 @@ impl AppBuilder {
|
|||||||
.with_stage(StartupStage::Startup, SystemStage::parallel())
|
.with_stage(StartupStage::Startup, SystemStage::parallel())
|
||||||
.with_stage(StartupStage::PostStartup, SystemStage::parallel()),
|
.with_stage(StartupStage::PostStartup, SystemStage::parallel()),
|
||||||
)
|
)
|
||||||
.add_stage(CoreStage::First, SystemStage::parallel())
|
|
||||||
.add_stage(CoreStage::PreEvent, SystemStage::parallel())
|
|
||||||
.add_stage(CoreStage::Event, SystemStage::parallel())
|
|
||||||
.add_stage(CoreStage::PreUpdate, SystemStage::parallel())
|
.add_stage(CoreStage::PreUpdate, SystemStage::parallel())
|
||||||
.add_stage(CoreStage::Update, SystemStage::parallel())
|
.add_stage(CoreStage::Update, SystemStage::parallel())
|
||||||
.add_stage(CoreStage::PostUpdate, SystemStage::parallel())
|
.add_stage(CoreStage::PostUpdate, SystemStage::parallel())
|
||||||
@ -233,7 +231,7 @@ impl AppBuilder {
|
|||||||
T: Component,
|
T: Component,
|
||||||
{
|
{
|
||||||
self.insert_resource(Events::<T>::default())
|
self.insert_resource(Events::<T>::default())
|
||||||
.add_system_to_stage(CoreStage::Event, Events::<T>::update_system.system())
|
.add_system_to_stage(CoreStage::First, Events::<T>::update_system.system())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts a resource to the current [App] and overwrites any resource previously added of the same type.
|
/// Inserts a resource to the current [App] and overwrites any resource previously added of the same type.
|
||||||
|
|||||||
@ -3,7 +3,11 @@ use bevy_ecs::{
|
|||||||
system::{Local, Res, ResMut, SystemParam},
|
system::{Local, Res, ResMut, SystemParam},
|
||||||
};
|
};
|
||||||
use bevy_utils::tracing::trace;
|
use bevy_utils::tracing::trace;
|
||||||
use std::{fmt, marker::PhantomData};
|
use std::{
|
||||||
|
fmt::{self},
|
||||||
|
hash::Hash,
|
||||||
|
marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
/// An `EventId` uniquely identifies an event.
|
/// An `EventId` uniquely identifies an event.
|
||||||
///
|
///
|
||||||
|
|||||||
@ -31,10 +31,6 @@ pub enum CoreStage {
|
|||||||
Startup,
|
Startup,
|
||||||
/// Name of app stage that runs before all other app stages
|
/// Name of app stage that runs before all other app stages
|
||||||
First,
|
First,
|
||||||
/// Name of app stage that runs before EVENT
|
|
||||||
PreEvent,
|
|
||||||
/// Name of app stage that updates events. Runs before UPDATE
|
|
||||||
Event,
|
|
||||||
/// Name of app stage responsible for performing setup before an update. Runs before UPDATE.
|
/// Name of app stage responsible for performing setup before an update. Runs before UPDATE.
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
/// Name of app stage responsible for doing most app logic. Systems should be registered here by default.
|
/// Name of app stage responsible for doing most app logic. Systems should be registered here by default.
|
||||||
|
|||||||
@ -17,7 +17,11 @@ pub mod prelude {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_ecs::{entity::Entity, system::IntoSystem};
|
use bevy_ecs::{
|
||||||
|
entity::Entity,
|
||||||
|
schedule::{ExclusiveSystemDescriptorCoercion, SystemLabel},
|
||||||
|
system::{IntoExclusiveSystem, IntoSystem},
|
||||||
|
};
|
||||||
use bevy_utils::HashSet;
|
use bevy_utils::HashSet;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
@ -25,6 +29,12 @@ use std::ops::Range;
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct CorePlugin;
|
pub struct CorePlugin;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemLabel)]
|
||||||
|
pub enum CoreSystem {
|
||||||
|
/// Updates the elapsed time. Any system that interacts with [Time] component should run after this.
|
||||||
|
Time,
|
||||||
|
}
|
||||||
|
|
||||||
impl Plugin for CorePlugin {
|
impl Plugin for CorePlugin {
|
||||||
fn build(&self, app: &mut AppBuilder) {
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
// Setup the default bevy task pools
|
// Setup the default bevy task pools
|
||||||
@ -44,7 +54,11 @@ impl Plugin for CorePlugin {
|
|||||||
.register_type::<Labels>()
|
.register_type::<Labels>()
|
||||||
.register_type::<Range<f32>>()
|
.register_type::<Range<f32>>()
|
||||||
.register_type::<Timer>()
|
.register_type::<Timer>()
|
||||||
.add_system_to_stage(CoreStage::First, time_system.system())
|
// time system is added as an "exclusive system" to ensure it runs before other systems in CoreStage::First
|
||||||
|
.add_system_to_stage(
|
||||||
|
CoreStage::First,
|
||||||
|
time_system.exclusive_system().label(CoreSystem::Time),
|
||||||
|
)
|
||||||
.add_startup_system_to_stage(StartupStage::PostStartup, entity_labels_system.system())
|
.add_startup_system_to_stage(StartupStage::PostStartup, entity_labels_system.system())
|
||||||
.add_system_to_stage(CoreStage::PostUpdate, entity_labels_system.system());
|
.add_system_to_stage(CoreStage::PostUpdate, entity_labels_system.system());
|
||||||
|
|
||||||
|
|||||||
@ -198,3 +198,35 @@ impl<T: SparseSetIndex> Default for FilteredAccessSet<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::query::Access;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn access_get_conflicts() {
|
||||||
|
let mut access_a = Access::<usize>::default();
|
||||||
|
access_a.add_read(0);
|
||||||
|
access_a.add_read(1);
|
||||||
|
|
||||||
|
let mut access_b = Access::<usize>::default();
|
||||||
|
access_b.add_read(0);
|
||||||
|
access_b.add_write(1);
|
||||||
|
|
||||||
|
assert_eq!(access_a.get_conflicts(&access_b), vec![1]);
|
||||||
|
|
||||||
|
let mut access_c = Access::<usize>::default();
|
||||||
|
access_c.add_write(0);
|
||||||
|
access_c.add_write(1);
|
||||||
|
|
||||||
|
assert_eq!(access_a.get_conflicts(&access_c), vec![0, 1]);
|
||||||
|
assert_eq!(access_b.get_conflicts(&access_c), vec![0, 1]);
|
||||||
|
|
||||||
|
let mut access_d = Access::<usize>::default();
|
||||||
|
access_d.add_read(0);
|
||||||
|
|
||||||
|
assert_eq!(access_d.get_conflicts(&access_a), vec![]);
|
||||||
|
assert_eq!(access_d.get_conflicts(&access_b), vec![]);
|
||||||
|
assert_eq!(access_d.get_conflicts(&access_c), vec![0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
component::ComponentId,
|
||||||
schedule::{
|
schedule::{
|
||||||
BoxedSystemLabel, ExclusiveSystemContainer, InsertionPoint, ParallelExecutor,
|
BoxedSystemLabel, ExclusiveSystemContainer, InsertionPoint, ParallelExecutor,
|
||||||
ParallelSystemContainer, ParallelSystemExecutor, RunCriteria, ShouldRun,
|
ParallelSystemContainer, ParallelSystemExecutor, RunCriteria, ShouldRun,
|
||||||
@ -263,15 +264,16 @@ impl SystemStage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Logs execution order ambiguities between systems. System orders must be fresh.
|
/// Logs execution order ambiguities between systems. System orders must be fresh.
|
||||||
fn report_ambiguities(&self) {
|
fn report_ambiguities(&self, world: &World) {
|
||||||
debug_assert!(!self.systems_modified);
|
debug_assert!(!self.systems_modified);
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
fn write_display_names_of_pairs(
|
fn write_display_names_of_pairs(
|
||||||
string: &mut String,
|
string: &mut String,
|
||||||
systems: &[impl SystemContainer],
|
systems: &[impl SystemContainer],
|
||||||
mut ambiguities: Vec<(usize, usize)>,
|
mut ambiguities: Vec<(usize, usize, Vec<ComponentId>)>,
|
||||||
|
world: &World,
|
||||||
) {
|
) {
|
||||||
for (index_a, index_b) in ambiguities.drain(..) {
|
for (index_a, index_b, conflicts) in ambiguities.drain(..) {
|
||||||
writeln!(
|
writeln!(
|
||||||
string,
|
string,
|
||||||
" -- {:?} and {:?}",
|
" -- {:?} and {:?}",
|
||||||
@ -279,6 +281,13 @@ impl SystemStage {
|
|||||||
systems[index_b].name()
|
systems[index_b].name()
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
if !conflicts.is_empty() {
|
||||||
|
let names = conflicts
|
||||||
|
.iter()
|
||||||
|
.map(|id| world.components().get_info(*id).unwrap().name())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
writeln!(string, " conflicts: {:?}", names).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let parallel = find_ambiguities(&self.parallel);
|
let parallel = find_ambiguities(&self.parallel);
|
||||||
@ -295,11 +304,16 @@ impl SystemStage {
|
|||||||
.to_owned();
|
.to_owned();
|
||||||
if !parallel.is_empty() {
|
if !parallel.is_empty() {
|
||||||
writeln!(string, " * Parallel systems:").unwrap();
|
writeln!(string, " * Parallel systems:").unwrap();
|
||||||
write_display_names_of_pairs(&mut string, &self.parallel, parallel);
|
write_display_names_of_pairs(&mut string, &self.parallel, parallel, world);
|
||||||
}
|
}
|
||||||
if !at_start.is_empty() {
|
if !at_start.is_empty() {
|
||||||
writeln!(string, " * Exclusive systems at start of stage:").unwrap();
|
writeln!(string, " * Exclusive systems at start of stage:").unwrap();
|
||||||
write_display_names_of_pairs(&mut string, &self.exclusive_at_start, at_start);
|
write_display_names_of_pairs(
|
||||||
|
&mut string,
|
||||||
|
&self.exclusive_at_start,
|
||||||
|
at_start,
|
||||||
|
world,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if !before_commands.is_empty() {
|
if !before_commands.is_empty() {
|
||||||
writeln!(string, " * Exclusive systems before commands of stage:").unwrap();
|
writeln!(string, " * Exclusive systems before commands of stage:").unwrap();
|
||||||
@ -307,11 +321,12 @@ impl SystemStage {
|
|||||||
&mut string,
|
&mut string,
|
||||||
&self.exclusive_before_commands,
|
&self.exclusive_before_commands,
|
||||||
before_commands,
|
before_commands,
|
||||||
|
world,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if !at_end.is_empty() {
|
if !at_end.is_empty() {
|
||||||
writeln!(string, " * Exclusive systems at end of stage:").unwrap();
|
writeln!(string, " * Exclusive systems at end of stage:").unwrap();
|
||||||
write_display_names_of_pairs(&mut string, &self.exclusive_at_end, at_end);
|
write_display_names_of_pairs(&mut string, &self.exclusive_at_end, at_end, world);
|
||||||
}
|
}
|
||||||
info!("{}", string);
|
info!("{}", string);
|
||||||
}
|
}
|
||||||
@ -454,9 +469,10 @@ fn topological_order(
|
|||||||
Ok(sorted)
|
Ok(sorted)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns vector containing all pairs of indices of systems with ambiguous execution order.
|
/// Returns vector containing all pairs of indices of systems with ambiguous execution order,
|
||||||
|
/// along with specific components that have triggered the warning.
|
||||||
/// Systems must be topologically sorted beforehand.
|
/// Systems must be topologically sorted beforehand.
|
||||||
fn find_ambiguities(systems: &[impl SystemContainer]) -> Vec<(usize, usize)> {
|
fn find_ambiguities(systems: &[impl SystemContainer]) -> Vec<(usize, usize, Vec<ComponentId>)> {
|
||||||
let mut ambiguity_set_labels = HashMap::default();
|
let mut ambiguity_set_labels = HashMap::default();
|
||||||
for set in systems.iter().flat_map(|c| c.ambiguity_sets()) {
|
for set in systems.iter().flat_map(|c| c.ambiguity_sets()) {
|
||||||
let len = ambiguity_set_labels.len();
|
let len = ambiguity_set_labels.len();
|
||||||
@ -511,9 +527,17 @@ fn find_ambiguities(systems: &[impl SystemContainer]) -> Vec<(usize, usize)> {
|
|||||||
{
|
{
|
||||||
if !processed.contains(index_b)
|
if !processed.contains(index_b)
|
||||||
&& all_ambiguity_sets[index_a].is_disjoint(&all_ambiguity_sets[index_b])
|
&& all_ambiguity_sets[index_a].is_disjoint(&all_ambiguity_sets[index_b])
|
||||||
&& !systems[index_a].is_compatible(&systems[index_b])
|
|
||||||
{
|
{
|
||||||
ambiguities.push((index_a, index_b));
|
let a_access = systems[index_a].component_access();
|
||||||
|
let b_access = systems[index_b].component_access();
|
||||||
|
if let (Some(a), Some(b)) = (a_access, b_access) {
|
||||||
|
let conflicts = a.get_conflicts(b);
|
||||||
|
if !conflicts.is_empty() {
|
||||||
|
ambiguities.push((index_a, index_b, conflicts))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ambiguities.push((index_a, index_b, Vec::new()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
processed.insert(index_a);
|
processed.insert(index_a);
|
||||||
@ -549,7 +573,7 @@ impl Stage for SystemStage {
|
|||||||
self.executor.rebuild_cached_data(&self.parallel);
|
self.executor.rebuild_cached_data(&self.parallel);
|
||||||
self.executor_modified = false;
|
self.executor_modified = false;
|
||||||
if world.contains_resource::<ReportExecutionOrderAmbiguities>() {
|
if world.contains_resource::<ReportExecutionOrderAmbiguities>() {
|
||||||
self.report_ambiguities();
|
self.report_ambiguities(world);
|
||||||
}
|
}
|
||||||
} else if self.executor_modified {
|
} else if self.executor_modified {
|
||||||
self.executor.rebuild_cached_data(&self.parallel);
|
self.executor.rebuild_cached_data(&self.parallel);
|
||||||
@ -1184,7 +1208,7 @@ mod tests {
|
|||||||
) -> Vec<(BoxedSystemLabel, BoxedSystemLabel)> {
|
) -> Vec<(BoxedSystemLabel, BoxedSystemLabel)> {
|
||||||
find_ambiguities(systems)
|
find_ambiguities(systems)
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|(index_a, index_b)| {
|
.map(|(index_a, index_b, _conflicts)| {
|
||||||
(
|
(
|
||||||
systems[index_a].labels()[0].clone(),
|
systems[index_a].labels()[0].clone(),
|
||||||
systems[index_b].labels()[0].clone(),
|
systems[index_b].labels()[0].clone(),
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
component::ComponentId,
|
||||||
|
query::Access,
|
||||||
schedule::{
|
schedule::{
|
||||||
BoxedAmbiguitySetLabel, BoxedSystemLabel, ExclusiveSystemDescriptor,
|
BoxedAmbiguitySetLabel, BoxedSystemLabel, ExclusiveSystemDescriptor,
|
||||||
ParallelSystemDescriptor,
|
ParallelSystemDescriptor,
|
||||||
@ -16,7 +18,7 @@ pub(super) trait SystemContainer {
|
|||||||
fn before(&self) -> &[BoxedSystemLabel];
|
fn before(&self) -> &[BoxedSystemLabel];
|
||||||
fn after(&self) -> &[BoxedSystemLabel];
|
fn after(&self) -> &[BoxedSystemLabel];
|
||||||
fn ambiguity_sets(&self) -> &[BoxedAmbiguitySetLabel];
|
fn ambiguity_sets(&self) -> &[BoxedAmbiguitySetLabel];
|
||||||
fn is_compatible(&self, other: &Self) -> bool;
|
fn component_access(&self) -> Option<&Access<ComponentId>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) struct ExclusiveSystemContainer {
|
pub(super) struct ExclusiveSystemContainer {
|
||||||
@ -81,8 +83,8 @@ impl SystemContainer for ExclusiveSystemContainer {
|
|||||||
&self.ambiguity_sets
|
&self.ambiguity_sets
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_compatible(&self, _: &Self) -> bool {
|
fn component_access(&self) -> Option<&Access<ComponentId>> {
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,9 +180,7 @@ impl SystemContainer for ParallelSystemContainer {
|
|||||||
&self.ambiguity_sets
|
&self.ambiguity_sets
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_compatible(&self, other: &Self) -> bool {
|
fn component_access(&self) -> Option<&Access<ComponentId>> {
|
||||||
self.system()
|
Some(self.system().component_access())
|
||||||
.component_access()
|
|
||||||
.is_compatible(other.system().component_access())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,8 @@ pub use system_param::*;
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::any::TypeId;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
archetype::Archetypes,
|
archetype::Archetypes,
|
||||||
bundle::Bundles,
|
bundle::Bundles,
|
||||||
@ -415,4 +417,25 @@ mod tests {
|
|||||||
// ensure the system actually ran
|
// ensure the system actually ran
|
||||||
assert_eq!(*world.get_resource::<bool>().unwrap(), true);
|
assert_eq!(*world.get_resource::<bool>().unwrap(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_system_conflicts() {
|
||||||
|
fn sys_x(_: Res<A>, _: Res<B>, _: Query<(&C, &D)>) {}
|
||||||
|
|
||||||
|
fn sys_y(_: Res<A>, _: ResMut<B>, _: Query<(&C, &mut D)>) {}
|
||||||
|
|
||||||
|
let mut world = World::default();
|
||||||
|
let mut x = sys_x.system();
|
||||||
|
let mut y = sys_y.system();
|
||||||
|
x.initialize(&mut world);
|
||||||
|
y.initialize(&mut world);
|
||||||
|
|
||||||
|
let conflicts = x.component_access().get_conflicts(y.component_access());
|
||||||
|
let b_id = world
|
||||||
|
.components()
|
||||||
|
.get_resource_id(TypeId::of::<B>())
|
||||||
|
.unwrap();
|
||||||
|
let d_id = world.components().get_id(TypeId::of::<D>()).unwrap();
|
||||||
|
assert_eq!(conflicts, vec![b_id, d_id]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -248,6 +248,7 @@ impl<'a, T: Component> SystemParam for Option<Res<'a, T>> {
|
|||||||
|
|
||||||
unsafe impl<T: Component> SystemParamState for OptionResState<T> {
|
unsafe impl<T: Component> SystemParamState for OptionResState<T> {
|
||||||
type Config = ();
|
type Config = ();
|
||||||
|
|
||||||
fn init(world: &mut World, system_state: &mut SystemState, _config: Self::Config) -> Self {
|
fn init(world: &mut World, system_state: &mut SystemState, _config: Self::Config) -> Self {
|
||||||
Self(ResState::init(world, system_state, ()))
|
Self(ResState::init(world, system_state, ()))
|
||||||
}
|
}
|
||||||
@ -383,6 +384,7 @@ impl<'a, T: Component> SystemParam for Option<ResMut<'a, T>> {
|
|||||||
|
|
||||||
unsafe impl<T: Component> SystemParamState for OptionResMutState<T> {
|
unsafe impl<T: Component> SystemParamState for OptionResMutState<T> {
|
||||||
type Config = ();
|
type Config = ();
|
||||||
|
|
||||||
fn init(world: &mut World, system_state: &mut SystemState, _config: Self::Config) -> Self {
|
fn init(world: &mut World, system_state: &mut SystemState, _config: Self::Config) -> Self {
|
||||||
Self(ResMutState::init(world, system_state, ()))
|
Self(ResMutState::init(world, system_state, ()))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,7 @@ impl Plugin for GilrsPlugin {
|
|||||||
gilrs_event_startup_system.exclusive_system(),
|
gilrs_event_startup_system.exclusive_system(),
|
||||||
)
|
)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
CoreStage::PreEvent,
|
CoreStage::PreUpdate,
|
||||||
gilrs_event_system.exclusive_system(),
|
gilrs_event_system.exclusive_system(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,10 @@ pub mod system;
|
|||||||
pub mod touch;
|
pub mod touch;
|
||||||
|
|
||||||
pub use axis::*;
|
pub use axis::*;
|
||||||
use bevy_ecs::system::IntoSystem;
|
use bevy_ecs::{
|
||||||
|
schedule::{ParallelSystemDescriptorCoercion, SystemLabel},
|
||||||
|
system::IntoSystem,
|
||||||
|
};
|
||||||
pub use input::*;
|
pub use input::*;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
@ -37,27 +40,46 @@ use gamepad::{
|
|||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct InputPlugin;
|
pub struct InputPlugin;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Hash, SystemLabel)]
|
||||||
|
pub struct InputSystem;
|
||||||
|
|
||||||
impl Plugin for InputPlugin {
|
impl Plugin for InputPlugin {
|
||||||
fn build(&self, app: &mut AppBuilder) {
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
app.add_event::<KeyboardInput>()
|
app
|
||||||
|
// keyboard
|
||||||
|
.add_event::<KeyboardInput>()
|
||||||
|
.init_resource::<Input<KeyCode>>()
|
||||||
|
.add_system_to_stage(
|
||||||
|
CoreStage::PreUpdate,
|
||||||
|
keyboard_input_system.system().label(InputSystem),
|
||||||
|
)
|
||||||
|
// mouse
|
||||||
.add_event::<MouseButtonInput>()
|
.add_event::<MouseButtonInput>()
|
||||||
.add_event::<MouseMotion>()
|
.add_event::<MouseMotion>()
|
||||||
.add_event::<MouseWheel>()
|
.add_event::<MouseWheel>()
|
||||||
.init_resource::<Input<KeyCode>>()
|
|
||||||
.add_system_to_stage(CoreStage::Event, keyboard_input_system.system())
|
|
||||||
.init_resource::<Input<MouseButton>>()
|
.init_resource::<Input<MouseButton>>()
|
||||||
.add_system_to_stage(CoreStage::Event, mouse_button_input_system.system())
|
.add_system_to_stage(
|
||||||
|
CoreStage::PreUpdate,
|
||||||
|
mouse_button_input_system.system().label(InputSystem),
|
||||||
|
)
|
||||||
|
// gamepad
|
||||||
.add_event::<GamepadEvent>()
|
.add_event::<GamepadEvent>()
|
||||||
.add_event::<GamepadEventRaw>()
|
.add_event::<GamepadEventRaw>()
|
||||||
.init_resource::<GamepadSettings>()
|
.init_resource::<GamepadSettings>()
|
||||||
.init_resource::<Input<GamepadButton>>()
|
.init_resource::<Input<GamepadButton>>()
|
||||||
.init_resource::<Axis<GamepadAxis>>()
|
.init_resource::<Axis<GamepadAxis>>()
|
||||||
.init_resource::<Axis<GamepadButton>>()
|
.init_resource::<Axis<GamepadButton>>()
|
||||||
.add_system_to_stage(CoreStage::Event, gamepad_event_system.system())
|
.add_system_to_stage(
|
||||||
.add_startup_system_to_stage(StartupStage::Startup, gamepad_event_system.system())
|
CoreStage::PreUpdate,
|
||||||
|
gamepad_event_system.system().label(InputSystem),
|
||||||
|
)
|
||||||
|
// touch
|
||||||
.add_event::<TouchInput>()
|
.add_event::<TouchInput>()
|
||||||
.init_resource::<Touches>()
|
.init_resource::<Touches>()
|
||||||
.add_system_to_stage(CoreStage::Event, touch_screen_input_system.system());
|
.add_system_to_stage(
|
||||||
|
CoreStage::PreUpdate,
|
||||||
|
touch_screen_input_system.system().label(InputSystem),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,9 +13,10 @@ pub mod texture;
|
|||||||
pub mod wireframe;
|
pub mod wireframe;
|
||||||
|
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
schedule::SystemStage,
|
schedule::{ParallelSystemDescriptorCoercion, SystemStage},
|
||||||
system::{IntoExclusiveSystem, IntoSystem},
|
system::{IntoExclusiveSystem, IntoSystem},
|
||||||
};
|
};
|
||||||
|
use bevy_transform::TransformSystem;
|
||||||
use draw::Visible;
|
use draw::Visible;
|
||||||
pub use once_cell;
|
pub use once_cell;
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ use crate::prelude::*;
|
|||||||
use base::Msaa;
|
use base::Msaa;
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_asset::{AddAsset, AssetStage};
|
use bevy_asset::{AddAsset, AssetStage};
|
||||||
use bevy_ecs::schedule::StageLabel;
|
use bevy_ecs::schedule::{StageLabel, SystemLabel};
|
||||||
use camera::{
|
use camera::{
|
||||||
ActiveCameras, Camera, DepthCalculation, OrthographicProjection, PerspectiveProjection,
|
ActiveCameras, Camera, DepthCalculation, OrthographicProjection, PerspectiveProjection,
|
||||||
RenderLayers, ScalingMode, VisibleEntities, WindowOrigin,
|
RenderLayers, ScalingMode, VisibleEntities, WindowOrigin,
|
||||||
@ -57,6 +58,11 @@ use texture::HdrTextureLoader;
|
|||||||
#[cfg(feature = "png")]
|
#[cfg(feature = "png")]
|
||||||
use texture::ImageTextureLoader;
|
use texture::ImageTextureLoader;
|
||||||
|
|
||||||
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
|
||||||
|
pub enum RenderSystem {
|
||||||
|
VisibleEntities,
|
||||||
|
}
|
||||||
|
|
||||||
/// The names of "render" App stages
|
/// The names of "render" App stages
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
|
||||||
pub enum RenderStage {
|
pub enum RenderStage {
|
||||||
@ -157,16 +163,22 @@ impl Plugin for RenderPlugin {
|
|||||||
)
|
)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
CoreStage::PostUpdate,
|
CoreStage::PostUpdate,
|
||||||
camera::camera_system::<OrthographicProjection>.system(),
|
camera::camera_system::<OrthographicProjection>
|
||||||
|
.system()
|
||||||
|
.before(RenderSystem::VisibleEntities),
|
||||||
)
|
)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
CoreStage::PostUpdate,
|
CoreStage::PostUpdate,
|
||||||
camera::camera_system::<PerspectiveProjection>.system(),
|
camera::camera_system::<PerspectiveProjection>
|
||||||
|
.system()
|
||||||
|
.before(RenderSystem::VisibleEntities),
|
||||||
)
|
)
|
||||||
// registration order matters here. this must come after all camera_system::<T> systems
|
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
CoreStage::PostUpdate,
|
CoreStage::PostUpdate,
|
||||||
camera::visible_entities_system.system(),
|
camera::visible_entities_system
|
||||||
|
.system()
|
||||||
|
.label(RenderSystem::VisibleEntities)
|
||||||
|
.after(TransformSystem::TransformPropagate),
|
||||||
)
|
)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
RenderStage::RenderResource,
|
RenderStage::RenderResource,
|
||||||
|
|||||||
@ -233,13 +233,10 @@ pub struct Mesh {
|
|||||||
impl Mesh {
|
impl Mesh {
|
||||||
/// Per vertex coloring. Use in conjunction with [`Mesh::set_attribute`]
|
/// Per vertex coloring. Use in conjunction with [`Mesh::set_attribute`]
|
||||||
pub const ATTRIBUTE_COLOR: &'static str = "Vertex_Color";
|
pub const ATTRIBUTE_COLOR: &'static str = "Vertex_Color";
|
||||||
|
|
||||||
/// The direction the vertex normal is facing in. Use in conjunction with [`Mesh::set_attribute`]
|
/// The direction the vertex normal is facing in. Use in conjunction with [`Mesh::set_attribute`]
|
||||||
pub const ATTRIBUTE_NORMAL: &'static str = "Vertex_Normal";
|
pub const ATTRIBUTE_NORMAL: &'static str = "Vertex_Normal";
|
||||||
|
|
||||||
/// Where the vertex is located in space. Use in conjunction with [`Mesh::set_attribute`]
|
/// Where the vertex is located in space. Use in conjunction with [`Mesh::set_attribute`]
|
||||||
pub const ATTRIBUTE_POSITION: &'static str = "Vertex_Position";
|
pub const ATTRIBUTE_POSITION: &'static str = "Vertex_Position";
|
||||||
|
|
||||||
/// Texture coordinates for the vertex. Use in conjunction with [`Mesh::set_attribute`]
|
/// Texture coordinates for the vertex. Use in conjunction with [`Mesh::set_attribute`]
|
||||||
pub const ATTRIBUTE_UV_0: &'static str = "Vertex_Uv";
|
pub const ATTRIBUTE_UV_0: &'static str = "Vertex_Uv";
|
||||||
|
|
||||||
|
|||||||
@ -19,33 +19,20 @@ pub mod prelude {
|
|||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_asset::AddAsset;
|
use bevy_asset::AddAsset;
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{schedule::ExclusiveSystemDescriptorCoercion, system::IntoExclusiveSystem};
|
||||||
schedule::{StageLabel, SystemStage},
|
|
||||||
system::IntoExclusiveSystem,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ScenePlugin;
|
pub struct ScenePlugin;
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
|
|
||||||
enum SceneStage {
|
|
||||||
SceneStage,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Plugin for ScenePlugin {
|
impl Plugin for ScenePlugin {
|
||||||
fn build(&self, app: &mut AppBuilder) {
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
app.add_asset::<DynamicScene>()
|
app.add_asset::<DynamicScene>()
|
||||||
.add_asset::<Scene>()
|
.add_asset::<Scene>()
|
||||||
.init_asset_loader::<SceneLoader>()
|
.init_asset_loader::<SceneLoader>()
|
||||||
.init_resource::<SceneSpawner>()
|
.init_resource::<SceneSpawner>()
|
||||||
.add_stage_after(
|
|
||||||
CoreStage::Event,
|
|
||||||
SceneStage::SceneStage,
|
|
||||||
SystemStage::parallel(),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
SceneStage::SceneStage,
|
CoreStage::PreUpdate,
|
||||||
scene_spawner_system.exclusive_system(),
|
scene_spawner_system.exclusive_system().at_end(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,6 +102,6 @@ impl Default for TextStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Copy, Clone, Debug)]
|
#[derive(Default, Copy, Clone, Debug)]
|
||||||
pub struct CalculatedSize {
|
pub struct Text2dSize {
|
||||||
pub size: Size,
|
pub size: Size,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,9 +18,7 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
|
|||||||
use bevy_window::Windows;
|
use bevy_window::Windows;
|
||||||
use glyph_brush_layout::{HorizontalAlign, VerticalAlign};
|
use glyph_brush_layout::{HorizontalAlign, VerticalAlign};
|
||||||
|
|
||||||
use crate::{
|
use crate::{DefaultTextPipeline, DrawableText, Font, FontAtlasSet, Text, Text2dSize, TextError};
|
||||||
CalculatedSize, DefaultTextPipeline, DrawableText, Font, FontAtlasSet, Text, TextError,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The bundle of components needed to draw text in a 2D scene via the Camera2dBundle.
|
/// The bundle of components needed to draw text in a 2D scene via the Camera2dBundle.
|
||||||
#[derive(Bundle, Clone, Debug)]
|
#[derive(Bundle, Clone, Debug)]
|
||||||
@ -31,7 +29,7 @@ pub struct Text2dBundle {
|
|||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
pub global_transform: GlobalTransform,
|
pub global_transform: GlobalTransform,
|
||||||
pub main_pass: MainPass,
|
pub main_pass: MainPass,
|
||||||
pub calculated_size: CalculatedSize,
|
pub text_2d_size: Text2dSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Text2dBundle {
|
impl Default for Text2dBundle {
|
||||||
@ -48,7 +46,7 @@ impl Default for Text2dBundle {
|
|||||||
transform: Default::default(),
|
transform: Default::default(),
|
||||||
global_transform: Default::default(),
|
global_transform: Default::default(),
|
||||||
main_pass: MainPass {},
|
main_pass: MainPass {},
|
||||||
calculated_size: CalculatedSize {
|
text_2d_size: Text2dSize {
|
||||||
size: Size::default(),
|
size: Size::default(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -72,7 +70,7 @@ pub fn draw_text2d_system(
|
|||||||
&Visible,
|
&Visible,
|
||||||
&Text,
|
&Text,
|
||||||
&GlobalTransform,
|
&GlobalTransform,
|
||||||
&CalculatedSize,
|
&Text2dSize,
|
||||||
),
|
),
|
||||||
With<MainPass>,
|
With<MainPass>,
|
||||||
>,
|
>,
|
||||||
@ -138,7 +136,7 @@ pub fn text2d_system(
|
|||||||
mut text_pipeline: ResMut<DefaultTextPipeline>,
|
mut text_pipeline: ResMut<DefaultTextPipeline>,
|
||||||
mut text_queries: QuerySet<(
|
mut text_queries: QuerySet<(
|
||||||
Query<Entity, (With<MainPass>, Changed<Text>)>,
|
Query<Entity, (With<MainPass>, Changed<Text>)>,
|
||||||
Query<(&Text, &mut CalculatedSize), With<MainPass>>,
|
Query<(&Text, &mut Text2dSize), With<MainPass>>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
// Adds all entities where the text or the style has changed to the local queue
|
// Adds all entities where the text or the style has changed to the local queue
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use super::Node;
|
|||||||
use crate::{
|
use crate::{
|
||||||
render::UI_PIPELINE_HANDLE,
|
render::UI_PIPELINE_HANDLE,
|
||||||
widget::{Button, Image},
|
widget::{Button, Image},
|
||||||
FocusPolicy, Interaction, Style,
|
CalculatedSize, FocusPolicy, Interaction, Style,
|
||||||
};
|
};
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_ecs::bundle::Bundle;
|
use bevy_ecs::bundle::Bundle;
|
||||||
@ -14,7 +14,7 @@ use bevy_render::{
|
|||||||
prelude::Visible,
|
prelude::Visible,
|
||||||
};
|
};
|
||||||
use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
|
use bevy_sprite::{ColorMaterial, QUAD_HANDLE};
|
||||||
use bevy_text::{CalculatedSize, Text};
|
use bevy_text::Text;
|
||||||
use bevy_transform::prelude::{GlobalTransform, Transform};
|
use bevy_transform::prelude::{GlobalTransform, Transform};
|
||||||
|
|
||||||
#[derive(Bundle, Clone, Debug)]
|
#[derive(Bundle, Clone, Debug)]
|
||||||
|
|||||||
@ -1,15 +1,14 @@
|
|||||||
mod convert;
|
mod convert;
|
||||||
|
|
||||||
use crate::{Node, Style};
|
use crate::{CalculatedSize, Node, Style};
|
||||||
use bevy_app::EventReader;
|
use bevy_app::EventReader;
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
query::{Changed, FilterFetch, Flags, With, Without, WorldQuery},
|
query::{Changed, FilterFetch, With, Without, WorldQuery},
|
||||||
system::{Query, Res, ResMut},
|
system::{Query, Res, ResMut},
|
||||||
};
|
};
|
||||||
use bevy_log::warn;
|
use bevy_log::warn;
|
||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
use bevy_text::CalculatedSize;
|
|
||||||
use bevy_transform::prelude::{Children, Parent, Transform};
|
use bevy_transform::prelude::{Children, Parent, Transform};
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
use bevy_window::{Window, WindowId, WindowScaleFactorChanged, Windows};
|
use bevy_window::{Window, WindowId, WindowScaleFactorChanged, Windows};
|
||||||
@ -201,13 +200,7 @@ pub fn flex_node_system(
|
|||||||
(With<Node>, Changed<CalculatedSize>),
|
(With<Node>, Changed<CalculatedSize>),
|
||||||
>,
|
>,
|
||||||
children_query: Query<(Entity, &Children), (With<Node>, Changed<Children>)>,
|
children_query: Query<(Entity, &Children), (With<Node>, Changed<Children>)>,
|
||||||
mut node_transform_query: Query<(
|
mut node_transform_query: Query<(Entity, &mut Node, &mut Transform, Option<&Parent>)>,
|
||||||
Entity,
|
|
||||||
&mut Node,
|
|
||||||
&mut Transform,
|
|
||||||
Option<(&Parent, Flags<Parent>)>,
|
|
||||||
Flags<Transform>,
|
|
||||||
)>,
|
|
||||||
) {
|
) {
|
||||||
// update window root nodes
|
// update window root nodes
|
||||||
for window in windows.iter() {
|
for window in windows.iter() {
|
||||||
@ -272,9 +265,8 @@ pub fn flex_node_system(
|
|||||||
|
|
||||||
let to_logical = |v| (physical_to_logical_factor * v as f64) as f32;
|
let to_logical = |v| (physical_to_logical_factor * v as f64) as f32;
|
||||||
|
|
||||||
for (entity, mut node, mut transform, parent, transform_flags) in
|
// PERF: try doing this incrementally
|
||||||
node_transform_query.iter_mut()
|
for (entity, mut node, mut transform, parent) in node_transform_query.iter_mut() {
|
||||||
{
|
|
||||||
let layout = flex_surface.get_layout(entity).unwrap();
|
let layout = flex_surface.get_layout(entity).unwrap();
|
||||||
node.size = Vec2::new(
|
node.size = Vec2::new(
|
||||||
to_logical(layout.size.width),
|
to_logical(layout.size.width),
|
||||||
@ -283,8 +275,7 @@ pub fn flex_node_system(
|
|||||||
let position = &mut transform.translation;
|
let position = &mut transform.translation;
|
||||||
position.x = to_logical(layout.location.x + layout.size.width / 2.0);
|
position.x = to_logical(layout.location.x + layout.size.width / 2.0);
|
||||||
position.y = to_logical(layout.location.y + layout.size.height / 2.0);
|
position.y = to_logical(layout.location.y + layout.size.height / 2.0);
|
||||||
if let Some((parent, parent_flags)) = parent {
|
if let Some(parent) = parent {
|
||||||
if parent_flags.changed() || transform_flags.changed() {
|
|
||||||
if let Ok(parent_layout) = flex_surface.get_layout(parent.0) {
|
if let Ok(parent_layout) = flex_surface.get_layout(parent.0) {
|
||||||
position.x -= to_logical(parent_layout.size.width / 2.0);
|
position.x -= to_logical(parent_layout.size.width / 2.0);
|
||||||
position.y -= to_logical(parent_layout.size.height / 2.0);
|
position.y -= to_logical(parent_layout.size.height / 2.0);
|
||||||
@ -292,4 +283,3 @@ pub fn flex_node_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
mod anchors;
|
mod anchors;
|
||||||
pub mod entity;
|
|
||||||
mod flex;
|
mod flex;
|
||||||
mod focus;
|
mod focus;
|
||||||
mod margins;
|
mod margins;
|
||||||
mod render;
|
mod render;
|
||||||
mod ui_node;
|
mod ui_node;
|
||||||
|
|
||||||
|
pub mod entity;
|
||||||
pub mod update;
|
pub mod update;
|
||||||
pub mod widget;
|
pub mod widget;
|
||||||
|
|
||||||
pub use anchors::*;
|
pub use anchors::*;
|
||||||
use bevy_math::{Rect, Size};
|
|
||||||
use bevy_render::RenderStage;
|
|
||||||
pub use flex::*;
|
pub use flex::*;
|
||||||
pub use focus::*;
|
pub use focus::*;
|
||||||
pub use margins::*;
|
pub use margins::*;
|
||||||
@ -23,28 +22,24 @@ pub mod prelude {
|
|||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
schedule::{ParallelSystemDescriptorCoercion, StageLabel, SystemLabel, SystemStage},
|
schedule::{ParallelSystemDescriptorCoercion, SystemLabel},
|
||||||
system::IntoSystem,
|
system::IntoSystem,
|
||||||
};
|
};
|
||||||
|
use bevy_input::InputSystem;
|
||||||
|
use bevy_math::{Rect, Size};
|
||||||
|
use bevy_render::RenderStage;
|
||||||
|
use bevy_transform::TransformSystem;
|
||||||
use update::ui_z_system;
|
use update::ui_z_system;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct UiPlugin;
|
pub struct UiPlugin;
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, StageLabel)]
|
|
||||||
pub enum UiStage {
|
|
||||||
Ui,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
|
||||||
pub enum UiSystem {
|
pub enum UiSystem {
|
||||||
|
/// After this label, the ui flex state has been updated
|
||||||
Flex,
|
Flex,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod system {
|
|
||||||
pub const FLEX: &str = "flex";
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Plugin for UiPlugin {
|
impl Plugin for UiPlugin {
|
||||||
fn build(&self, app: &mut AppBuilder) {
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
app.init_resource::<FlexSurface>()
|
app.init_resource::<FlexSurface>()
|
||||||
@ -63,19 +58,33 @@ impl Plugin for UiPlugin {
|
|||||||
.register_type::<Rect<Val>>()
|
.register_type::<Rect<Val>>()
|
||||||
.register_type::<Style>()
|
.register_type::<Style>()
|
||||||
.register_type::<Val>()
|
.register_type::<Val>()
|
||||||
.add_stage_before(CoreStage::PostUpdate, UiStage::Ui, SystemStage::parallel())
|
.add_system_to_stage(
|
||||||
.add_system_to_stage(CoreStage::PreUpdate, ui_focus_system.system())
|
CoreStage::PreUpdate,
|
||||||
|
ui_focus_system.system().after(InputSystem),
|
||||||
|
)
|
||||||
// add these stages to front because these must run before transform update systems
|
// add these stages to front because these must run before transform update systems
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
UiStage::Ui,
|
CoreStage::PostUpdate,
|
||||||
widget::text_system.system().before(UiSystem::Flex),
|
widget::text_system.system().before(UiSystem::Flex),
|
||||||
)
|
)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
UiStage::Ui,
|
CoreStage::PostUpdate,
|
||||||
widget::image_node_system.system().before(UiSystem::Flex),
|
widget::image_node_system.system().before(UiSystem::Flex),
|
||||||
)
|
)
|
||||||
.add_system_to_stage(UiStage::Ui, flex_node_system.system().label(UiSystem::Flex))
|
.add_system_to_stage(
|
||||||
.add_system_to_stage(UiStage::Ui, ui_z_system.system())
|
CoreStage::PostUpdate,
|
||||||
|
flex_node_system
|
||||||
|
.system()
|
||||||
|
.label(UiSystem::Flex)
|
||||||
|
.before(TransformSystem::TransformPropagate),
|
||||||
|
)
|
||||||
|
.add_system_to_stage(
|
||||||
|
CoreStage::PostUpdate,
|
||||||
|
ui_z_system
|
||||||
|
.system()
|
||||||
|
.after(UiSystem::Flex)
|
||||||
|
.before(TransformSystem::TransformPropagate),
|
||||||
|
)
|
||||||
.add_system_to_stage(RenderStage::Draw, widget::draw_text_system.system());
|
.add_system_to_stage(RenderStage::Draw, widget::draw_text_system.system());
|
||||||
|
|
||||||
crate::render::add_ui_graph(app.world_mut());
|
crate::render::add_ui_graph(app.world_mut());
|
||||||
|
|||||||
@ -250,3 +250,8 @@ impl Default for FlexWrap {
|
|||||||
FlexWrap::NoWrap
|
FlexWrap::NoWrap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Copy, Clone, Debug)]
|
||||||
|
pub struct CalculatedSize {
|
||||||
|
pub size: Size,
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use crate::CalculatedSize;
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
query::With,
|
query::With,
|
||||||
@ -6,7 +7,6 @@ use bevy_ecs::{
|
|||||||
use bevy_math::Size;
|
use bevy_math::Size;
|
||||||
use bevy_render::texture::Texture;
|
use bevy_render::texture::Texture;
|
||||||
use bevy_sprite::ColorMaterial;
|
use bevy_sprite::ColorMaterial;
|
||||||
use bevy_text::CalculatedSize;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Image {
|
pub enum Image {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::{Node, Style, Val};
|
use crate::{CalculatedSize, Node, Style, Val};
|
||||||
use bevy_asset::Assets;
|
use bevy_asset::Assets;
|
||||||
use bevy_ecs::{
|
use bevy_ecs::{
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
@ -14,9 +14,7 @@ use bevy_render::{
|
|||||||
texture::Texture,
|
texture::Texture,
|
||||||
};
|
};
|
||||||
use bevy_sprite::{TextureAtlas, QUAD_HANDLE};
|
use bevy_sprite::{TextureAtlas, QUAD_HANDLE};
|
||||||
use bevy_text::{
|
use bevy_text::{DefaultTextPipeline, DrawableText, Font, FontAtlasSet, Text, TextError};
|
||||||
CalculatedSize, DefaultTextPipeline, DrawableText, Font, FontAtlasSet, Text, TextError,
|
|
||||||
};
|
|
||||||
use bevy_transform::prelude::GlobalTransform;
|
use bevy_transform::prelude::GlobalTransform;
|
||||||
use bevy_window::Windows;
|
use bevy_window::Windows;
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use bevy_input::{
|
|||||||
pub use winit_config::*;
|
pub use winit_config::*;
|
||||||
pub use winit_windows::*;
|
pub use winit_windows::*;
|
||||||
|
|
||||||
use bevy_app::{App, AppBuilder, AppExit, Events, ManualEventReader, Plugin};
|
use bevy_app::{App, AppBuilder, AppExit, CoreStage, Events, ManualEventReader, Plugin};
|
||||||
use bevy_ecs::{system::IntoExclusiveSystem, world::World};
|
use bevy_ecs::{system::IntoExclusiveSystem, world::World};
|
||||||
use bevy_math::{ivec2, Vec2};
|
use bevy_math::{ivec2, Vec2};
|
||||||
use bevy_utils::tracing::{error, trace, warn};
|
use bevy_utils::tracing::{error, trace, warn};
|
||||||
@ -42,7 +42,7 @@ impl Plugin for WinitPlugin {
|
|||||||
fn build(&self, app: &mut AppBuilder) {
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
app.init_resource::<WinitWindows>()
|
app.init_resource::<WinitWindows>()
|
||||||
.set_runner(winit_runner)
|
.set_runner(winit_runner)
|
||||||
.add_system(change_window.exclusive_system());
|
.add_system_to_stage(CoreStage::PostUpdate, change_window.exclusive_system());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user