Merge pull request #72 from karroffel/texture-format

add `TextureFormat` field to `Texture`
This commit is contained in:
Carter Anderson 2020-07-26 13:14:53 -07:00 committed by GitHub
commit 718f475160
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 383 additions and 153 deletions

View File

@ -1,6 +1,8 @@
use crate::{ use crate::{
app::{App, AppExit},
event::Events,
plugin::{load_plugin, AppPlugin}, plugin::{load_plugin, AppPlugin},
stage, startup_stage, app::{AppExit, App}, event::Events stage, startup_stage,
}; };
use bevy_ecs::{FromResources, IntoQuerySystem, Resources, System, World}; use bevy_ecs::{FromResources, IntoQuerySystem, Resources, System, World};
@ -169,7 +171,9 @@ impl AppBuilder {
stage_name: &'static str, stage_name: &'static str,
system: Box<dyn System>, system: Box<dyn System>,
) -> &mut Self { ) -> &mut Self {
self.app.schedule.add_system_to_stage_front(stage_name, system); self.app
.schedule
.add_system_to_stage_front(stage_name, system);
self self
} }

View File

@ -1,6 +1,6 @@
use crate::AppBuilder;
use libloading::{Library, Symbol}; use libloading::{Library, Symbol};
use std::any::Any; use std::any::Any;
use crate::AppBuilder;
pub trait AppPlugin: Any + Send + Sync { pub trait AppPlugin: Any + Send + Sync {
fn build(&self, app: &mut AppBuilder); fn build(&self, app: &mut AppBuilder);

View File

@ -1,6 +1,10 @@
use super::{App, AppBuilder}; use super::{App, AppBuilder};
use crate::{
app::AppExit,
event::{EventReader, Events},
plugin::AppPlugin,
};
use std::{thread, time::Duration}; use std::{thread, time::Duration};
use crate::{event::{Events, EventReader}, plugin::AppPlugin, app::AppExit};
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum RunMode { pub enum RunMode {

View File

@ -8,7 +8,6 @@ pub mod prelude {
pub use crate::{AudioOutput, AudioSource}; pub use crate::{AudioOutput, AudioSource};
} }
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::AddAsset; use bevy_asset::AddAsset;
use bevy_ecs::IntoQuerySystem; use bevy_ecs::IntoQuerySystem;

View File

@ -2,7 +2,9 @@ use bevy_ecs::prelude::*;
use bevy_property::Properties; use bevy_property::Properties;
use std::{ use std::{
borrow::Cow, borrow::Cow,
collections::{HashMap, HashSet}, ops::{DerefMut, Deref}, fmt::Debug, collections::{HashMap, HashSet},
fmt::Debug,
ops::{Deref, DerefMut},
}; };
#[derive(Default, Properties)] #[derive(Default, Properties)]
@ -21,15 +23,16 @@ impl Debug for Labels {
} }
} }
impl<'a, T, L: Into<Cow<'static, str>>> From<T> for Labels where T: IntoIterator<Item=L> { impl<'a, T, L: Into<Cow<'static, str>>> From<T> for Labels
where
T: IntoIterator<Item = L>,
{
fn from(value: T) -> Self { fn from(value: T) -> Self {
let mut labels = HashSet::new(); let mut labels = HashSet::new();
for label in value { for label in value {
labels.insert(label.into()); labels.insert(label.into());
} }
Self { Self { labels }
labels,
}
} }
} }

View File

@ -1,15 +1,15 @@
mod bytes; mod bytes;
mod float_ord; mod float_ord;
mod time;
mod label; mod label;
mod time;
pub use bytes::*; pub use bytes::*;
pub use float_ord::*; pub use float_ord::*;
pub use time::*;
pub use label::*; pub use label::*;
pub use time::*;
pub mod prelude { pub mod prelude {
pub use crate::{Time, Timer, Labels, EntityLabels}; pub use crate::{EntityLabels, Labels, Time, Timer};
} }
use bevy_app::prelude::*; use bevy_app::prelude::*;

View File

@ -140,7 +140,9 @@ impl Archetype {
#[allow(missing_docs)] #[allow(missing_docs)]
#[inline] #[inline]
pub fn get_with_added_and_mutated<T: Component>(&self) -> Option<(NonNull<T>, NonNull<bool>, NonNull<bool>)> { pub fn get_with_added_and_mutated<T: Component>(
&self,
) -> Option<(NonNull<T>, NonNull<bool>, NonNull<bool>)> {
let state = self.state.get(&TypeId::of::<T>())?; let state = self.state.get(&TypeId::of::<T>())?;
Some(unsafe { Some(unsafe {
( (
@ -351,8 +353,10 @@ impl Archetype {
); );
let type_state = self.state.get_mut(&ty.id).unwrap(); let type_state = self.state.get_mut(&ty.id).unwrap();
type_state.mutated_entities[index as usize] = type_state.mutated_entities[last as usize]; type_state.mutated_entities[index as usize] =
type_state.added_entities[index as usize] = type_state.added_entities[last as usize]; type_state.mutated_entities[last as usize];
type_state.added_entities[index as usize] =
type_state.added_entities[last as usize];
} }
} }
self.len = last; self.len = last;
@ -377,7 +381,7 @@ impl Archetype {
.unwrap() .unwrap()
.as_ptr(); .as_ptr();
let type_state = self.state.get(&ty.id).unwrap(); let type_state = self.state.get(&ty.id).unwrap();
let is_added= type_state.added_entities[index as usize]; let is_added = type_state.added_entities[index as usize];
let is_mutated = type_state.mutated_entities[index as usize]; let is_mutated = type_state.mutated_entities[index as usize];
f(moved, ty.id(), ty.layout().size(), is_added, is_mutated); f(moved, ty.id(), ty.layout().size(), is_added, is_mutated);
if index != last { if index != last {
@ -389,8 +393,10 @@ impl Archetype {
ty.layout.size(), ty.layout.size(),
); );
let type_state = self.state.get_mut(&ty.id).unwrap(); let type_state = self.state.get_mut(&ty.id).unwrap();
type_state.added_entities[index as usize] = type_state.added_entities[last as usize]; type_state.added_entities[index as usize] =
type_state.mutated_entities[index as usize] = type_state.mutated_entities[last as usize]; type_state.added_entities[last as usize];
type_state.mutated_entities[index as usize] =
type_state.mutated_entities[last as usize];
} }
} }
self.len -= 1; self.len -= 1;
@ -403,15 +409,22 @@ impl Archetype {
} }
#[allow(missing_docs)] #[allow(missing_docs)]
pub unsafe fn put_dynamic(&mut self, component: *mut u8, ty: TypeId, size: usize, index: u32, added: bool) { pub unsafe fn put_dynamic(
&mut self,
component: *mut u8,
ty: TypeId,
size: usize,
index: u32,
added: bool,
) {
let state = self.state.get_mut(&ty).unwrap(); let state = self.state.get_mut(&ty).unwrap();
if added { if added {
state.added_entities[index as usize] = true; state.added_entities[index as usize] = true;
} }
let ptr = (*self.data.get()) let ptr = (*self.data.get())
.as_ptr() .as_ptr()
.add(state.offset + size * index as usize) .add(state.offset + size * index as usize)
.cast::<u8>(); .cast::<u8>();
ptr::copy_nonoverlapping(component, ptr, size); ptr::copy_nonoverlapping(component, ptr, size);
} }

View File

@ -15,9 +15,10 @@
// modified by Bevy contributors // modified by Bevy contributors
use core::{ use core::{
fmt::Debug,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
ptr::NonNull, ptr::NonNull,
sync::atomic::{AtomicUsize, Ordering}, fmt::Debug, sync::atomic::{AtomicUsize, Ordering},
}; };
use crate::{archetype::Archetype, Component, MissingComponent}; use crate::{archetype::Archetype, Component, MissingComponent};
@ -101,7 +102,10 @@ impl<'a, T: Component> Deref for Ref<'a, T> {
} }
} }
impl<'a, T: Component> Debug for Ref<'a,T> where T: Debug { impl<'a, T: Component> Debug for Ref<'a, T>
where
T: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.deref().fmt(f) self.deref().fmt(f)
} }
@ -161,7 +165,10 @@ impl<'a, T: Component> DerefMut for RefMut<'a, T> {
} }
} }
impl<'a, T: Component> Debug for RefMut<'a,T> where T: Debug { impl<'a, T: Component> Debug for RefMut<'a, T>
where
T: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.deref().fmt(f) self.deref().fmt(f)
} }

View File

@ -319,14 +319,12 @@ impl<'a, T: Component> Fetch<'a> for FetchAdded<T> {
archetype.borrow::<T>(); archetype.borrow::<T>();
} }
unsafe fn get(archetype: &'a Archetype, offset: usize) -> Option<Self> { unsafe fn get(archetype: &'a Archetype, offset: usize) -> Option<Self> {
archetype archetype.get_with_added::<T>().map(|(components, added)| {
.get_with_added::<T>() Self(
.map(|(components, added)| { NonNull::new_unchecked(components.as_ptr().add(offset)),
Self( NonNull::new_unchecked(added.as_ptr().add(offset)),
NonNull::new_unchecked(components.as_ptr().add(offset)), )
NonNull::new_unchecked(added.as_ptr().add(offset)), })
)
})
} }
fn release(archetype: &Archetype) { fn release(archetype: &Archetype) {
archetype.release::<T>(); archetype.release::<T>();
@ -346,7 +344,6 @@ impl<'a, T: Component> Fetch<'a> for FetchAdded<T> {
} }
} }
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct Changed<'a, T> { pub struct Changed<'a, T> {
value: &'a T, value: &'a T,
@ -412,7 +409,6 @@ impl<'a, T: Component> Fetch<'a> for FetchChanged<T> {
} }
} }
#[doc(hidden)] #[doc(hidden)]
pub struct TryFetch<T>(Option<T>); pub struct TryFetch<T>(Option<T>);

View File

@ -336,7 +336,9 @@ impl World {
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn removed<C: Component>(&self) -> &[Entity] { pub fn removed<C: Component>(&self) -> &[Entity] {
self.removed_components.get(&TypeId::of::<C>()).map_or(&[], |entities| entities.as_slice()) self.removed_components
.get(&TypeId::of::<C>())
.map_or(&[], |entities| entities.as_slice())
} }
/// Add `components` to `entity` /// Add `components` to `entity`
@ -501,7 +503,8 @@ impl World {
state.added_entities[target_index as usize] = is_added; state.added_entities[target_index as usize] = is_added;
state.mutated_entities[target_index as usize] = is_mutated; state.mutated_entities[target_index as usize] = is_mutated;
} else { } else {
let removed_entities = removed_components.entry(ty).or_insert_with(|| Vec::new()); let removed_entities =
removed_components.entry(ty).or_insert_with(|| Vec::new());
removed_entities.push(entity); removed_entities.push(entity);
} }
}) })

View File

@ -343,24 +343,64 @@ fn remove_tracking() {
let b = world.spawn(("abc", 123)); let b = world.spawn(("abc", 123));
world.despawn(a).unwrap(); world.despawn(a).unwrap();
assert_eq!(world.removed::<i32>(), &[a], "despawning results in 'removed component' state"); assert_eq!(
assert_eq!(world.removed::<&'static str>(), &[a], "despawning results in 'removed component' state"); world.removed::<i32>(),
&[a],
"despawning results in 'removed component' state"
);
assert_eq!(
world.removed::<&'static str>(),
&[a],
"despawning results in 'removed component' state"
);
world.insert_one(b, 10.0).unwrap(); world.insert_one(b, 10.0).unwrap();
assert_eq!(world.removed::<i32>(), &[a], "archetype moves does not result in 'removed component' state"); assert_eq!(
world.removed::<i32>(),
&[a],
"archetype moves does not result in 'removed component' state"
);
world.remove_one::<i32>(b).unwrap(); world.remove_one::<i32>(b).unwrap();
assert_eq!(world.removed::<i32>(), &[a, b], "removing a component results in a 'removed component' state"); assert_eq!(
world.removed::<i32>(),
&[a, b],
"removing a component results in a 'removed component' state"
);
world.clear_trackers(); world.clear_trackers();
assert_eq!(world.removed::<i32>(), &[], "clearning trackers clears removals"); assert_eq!(
assert_eq!(world.removed::<&'static str>(), &[], "clearning trackers clears removals"); world.removed::<i32>(),
assert_eq!(world.removed::<f64>(), &[], "clearning trackers clears removals"); &[],
"clearning trackers clears removals"
);
assert_eq!(
world.removed::<&'static str>(),
&[],
"clearning trackers clears removals"
);
assert_eq!(
world.removed::<f64>(),
&[],
"clearning trackers clears removals"
);
let c = world.spawn(("abc", 123)); let c = world.spawn(("abc", 123));
let d = world.spawn(("abc", 123)); let d = world.spawn(("abc", 123));
world.clear(); world.clear();
assert_eq!(world.removed::<i32>(), &[c, d], "world clears result in 'removed component' states"); assert_eq!(
assert_eq!(world.removed::<&'static str>(), &[c, d, b], "world clears result in 'removed component' states"); world.removed::<i32>(),
assert_eq!(world.removed::<f64>(), &[b], "world clears result in 'removed component' states"); &[c, d],
} "world clears result in 'removed component' states"
);
assert_eq!(
world.removed::<&'static str>(),
&[c, d, b],
"world clears result in 'removed component' states"
);
assert_eq!(
world.removed::<f64>(),
&[b],
"world clears result in 'removed component' states"
);
}

View File

@ -2,4 +2,4 @@ mod resource_query;
mod resources; mod resources;
pub use resource_query::*; pub use resource_query::*;
pub use resources::*; pub use resources::*;

View File

@ -67,11 +67,17 @@ impl Resources {
let archetype = &mut data.archetype; let archetype = &mut data.archetype;
let mut added = false; let mut added = false;
let index = match resource_index { let index = match resource_index {
ResourceIndex::Global => *data.default_index.get_or_insert_with(|| { added = true; archetype.len() }), ResourceIndex::Global => *data.default_index.get_or_insert_with(|| {
added = true;
archetype.len()
}),
ResourceIndex::System(id) => *data ResourceIndex::System(id) => *data
.system_id_to_archetype_index .system_id_to_archetype_index
.entry(id.0) .entry(id.0)
.or_insert_with(|| { added = true; archetype.len() }), .or_insert_with(|| {
added = true;
archetype.len()
}),
}; };
if index == archetype.len() { if index == archetype.len() {
@ -82,7 +88,13 @@ impl Resources {
unsafe { unsafe {
let resource_ptr = (&mut resource as *mut T).cast::<u8>(); let resource_ptr = (&mut resource as *mut T).cast::<u8>();
archetype.put_dynamic(resource_ptr, type_id, core::mem::size_of::<T>(), index, added); archetype.put_dynamic(
resource_ptr,
type_id,
core::mem::size_of::<T>(),
index,
added,
);
std::mem::forget(resource); std::mem::forget(resource);
} }
} }

View File

@ -2,4 +2,4 @@ mod parallel_executor;
mod schedule; mod schedule;
pub use parallel_executor::*; pub use parallel_executor::*;
pub use schedule::*; pub use schedule::*;

View File

@ -1,12 +1,13 @@
use crate::{ use crate::{
system::{System, ThreadLocalExecution, SystemId}, resource::Resources, resource::Resources,
system::{System, SystemId, ThreadLocalExecution},
}; };
use hecs::World;
use std::{ use std::{
borrow::Cow, borrow::Cow,
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use hecs::World;
#[derive(Default)] #[derive(Default)]
pub struct Schedule { pub struct Schedule {

View File

@ -157,10 +157,11 @@ impl<'a, Q: HecsQuery> Query<'a, Q> {
if self if self
.archetype_access .archetype_access
.immutable .immutable
.contains(location.archetype as usize) || self
.archetype_access
.mutable
.contains(location.archetype as usize) .contains(location.archetype as usize)
|| self
.archetype_access
.mutable
.contains(location.archetype as usize)
{ {
self.world self.world
.get(entity) .get(entity)

View File

@ -8,4 +8,4 @@ pub use commands::*;
pub use into_system::*; pub use into_system::*;
#[cfg(feature = "profiler")] #[cfg(feature = "profiler")]
pub use profiler::*; pub use profiler::*;
pub use system::*; pub use system::*;

View File

@ -100,9 +100,9 @@ impl TypeAccess {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{ArchetypeAccess, TypeAccess}; use super::{ArchetypeAccess, TypeAccess};
use crate::resource::{FetchResource, Res, ResMut, ResourceQuery};
use hecs::World; use hecs::World;
use std::any::TypeId; use std::any::TypeId;
use crate::resource::{Res, ResourceQuery, ResMut, FetchResource};
struct A; struct A;
struct B; struct B;

View File

@ -1,3 +1,3 @@
mod world_builder; mod world_builder;
pub use world_builder::*; pub use world_builder::*;

View File

@ -1,6 +1,6 @@
use crate::Input; use crate::Input;
use bevy_ecs::{Res, ResMut};
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_ecs::{Res, ResMut};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct KeyboardInput { pub struct KeyboardInput {

View File

@ -9,7 +9,7 @@ impl PerspectiveRh for Mat4 {
fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self { fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self {
let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos(); let (sin_fov, cos_fov) = (0.5 * fov_y_radians).sin_cos();
let h = cos_fov / sin_fov; let h = cos_fov / sin_fov;
let w = h /aspect_ratio; let w = h / aspect_ratio;
let r = z_far / (z_near - z_far); let r = z_far / (z_near - z_far);
Mat4::from_cols( Mat4::from_cols(
Vec4::new(w, 0.0, 0.0, 0.0), Vec4::new(w, 0.0, 0.0, 0.0),

View File

@ -1,4 +1,4 @@
use bevy_math::{PerspectiveRh, Mat4}; use bevy_math::{Mat4, PerspectiveRh};
use bevy_property::{Properties, Property}; use bevy_property::{Properties, Property};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View File

@ -61,7 +61,7 @@ pub struct Camera2dComponents {
impl Default for Camera2dComponents { impl Default for Camera2dComponents {
fn default() -> Self { fn default() -> Self {
// we want 0 to be "closest" and +far to be "farthest" in 2d, so we offset // we want 0 to be "closest" and +far to be "farthest" in 2d, so we offset
// the camera's translation by far and use a right handed coordinate system // the camera's translation by far and use a right handed coordinate system
let far = 1000.0; let far = 1000.0;
Camera2dComponents { Camera2dComponents {
camera: Camera { camera: Camera {

View File

@ -2,4 +2,4 @@ mod mesh;
mod vertex; mod vertex;
pub use mesh::*; pub use mesh::*;
pub use vertex::*; pub use vertex::*;

View File

@ -35,7 +35,7 @@ impl Node for TextureCopyNode {
let texture_descriptor: TextureDescriptor = texture.into(); let texture_descriptor: TextureDescriptor = texture.into();
let width = texture.size.x() as usize; let width = texture.size.x() as usize;
let aligned_width = get_aligned(texture.size.x()); let aligned_width = get_aligned(texture.size.x());
let format_size = 4; // TODO: this will be incorrect for some formats let format_size = texture.format.pixel_size();
let mut aligned_data = let mut aligned_data =
vec![0; format_size * aligned_width * texture.size.y() as usize]; vec![0; format_size * aligned_width * texture.size.y() as usize];
texture texture

View File

@ -1,4 +1,4 @@
use super::Texture; use super::{Texture, TextureFormat};
use anyhow::Result; use anyhow::Result;
use bevy_asset::AssetLoader; use bevy_asset::AssetLoader;
use bevy_math::Vec2; use bevy_math::Vec2;
@ -13,10 +13,11 @@ impl AssetLoader<Texture> for PngTextureLoader {
let (info, mut reader) = decoder.read_info()?; let (info, mut reader) = decoder.read_info()?;
let mut data = vec![0; info.buffer_size()]; let mut data = vec![0; info.buffer_size()];
reader.next_frame(&mut data)?; reader.next_frame(&mut data)?;
Ok(Texture { Ok(Texture::new(
Vec2::new(info.width as f32, info.height as f32),
data, data,
size: Vec2::new(info.width as f32, info.height as f32), TextureFormat::Rgba8UnormSrgb,
}) ))
} }
fn extensions(&self) -> &[&str] { fn extensions(&self) -> &[&str] {
static EXTENSIONS: &[&str] = &["png"]; static EXTENSIONS: &[&str] = &["png"];

View File

@ -1,4 +1,4 @@
use super::{SamplerDescriptor, TextureDescriptor}; use super::{SamplerDescriptor, TextureDescriptor, TextureFormat};
use crate::renderer::{ use crate::renderer::{
RenderResource, RenderResourceContext, RenderResourceId, RenderResourceType, RenderResource, RenderResourceContext, RenderResourceId, RenderResourceType,
}; };
@ -11,22 +11,48 @@ use std::collections::HashSet;
pub const TEXTURE_ASSET_INDEX: usize = 0; pub const TEXTURE_ASSET_INDEX: usize = 0;
pub const SAMPLER_ASSET_INDEX: usize = 1; pub const SAMPLER_ASSET_INDEX: usize = 1;
#[derive(Default, Clone)] #[derive(Clone)]
pub struct Texture { pub struct Texture {
pub data: Vec<u8>, pub data: Vec<u8>,
pub size: Vec2, pub size: Vec2,
pub format: TextureFormat,
} }
const FORMAT_SIZE: usize = 4; // TODO: get this from an actual format type impl Default for Texture {
fn default() -> Self {
Texture {
data: Default::default(),
size: Default::default(),
format: TextureFormat::Rgba8UnormSrgb,
}
}
}
impl Texture { impl Texture {
pub fn new(data: Vec<u8>, size: Vec2) -> Self { pub fn new(size: Vec2, data: Vec<u8>, format: TextureFormat) -> Self {
Self { data, size } debug_assert_eq!(
size.x() as usize * size.y() as usize * format.pixel_size(),
data.len(),
"Pixel data, size and format have to match",
);
Self { data, size, format }
} }
pub fn new_fill(size: Vec2, pixel: &[u8]) -> Self { pub fn new_fill(size: Vec2, pixel: &[u8], format: TextureFormat) -> Self {
let mut value = Self::default(); let mut value = Self::default();
value.format = format;
value.resize(size); value.resize(size);
debug_assert_eq!(
pixel.len() % format.pixel_size(),
0,
"Must not have incomplete pixel data"
);
debug_assert!(
pixel.len() <= value.data.len(),
"Fill data must fit within pixel buffer"
);
for current_pixel in value.data.chunks_exact_mut(pixel.len()) { for current_pixel in value.data.chunks_exact_mut(pixel.len()) {
current_pixel.copy_from_slice(&pixel); current_pixel.copy_from_slice(&pixel);
} }
@ -41,7 +67,7 @@ impl Texture {
self.size = size; self.size = size;
let width = size.x() as usize; let width = size.x() as usize;
let height = size.y() as usize; let height = size.y() as usize;
self.data.resize(width * height * FORMAT_SIZE, 0); self.data.resize(width * height * self.format.pixel_size(), 0);
} }
pub fn texture_resource_system( pub fn texture_resource_system(

View File

@ -21,7 +21,7 @@ impl From<&Texture> for TextureDescriptor {
mip_level_count: 1, mip_level_count: 1,
sample_count: 1, sample_count: 1,
dimension: TextureDimension::D2, dimension: TextureDimension::D2,
format: TextureFormat::Rgba8UnormSrgb, format: texture.format,
usage: TextureUsage::SAMPLED | TextureUsage::COPY_DST, usage: TextureUsage::SAMPLED | TextureUsage::COPY_DST,
} }
} }

View File

@ -32,6 +32,11 @@ pub enum TextureComponentType {
Uint, Uint,
} }
pub struct PixelInfo {
pub type_size: usize,
pub num_components: usize,
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
pub enum TextureFormat { pub enum TextureFormat {
// Normal 8 bit formats // Normal 8 bit formats
@ -87,6 +92,113 @@ pub enum TextureFormat {
Depth24PlusStencil8 = 37, Depth24PlusStencil8 = 37,
} }
impl TextureFormat {
pub fn pixel_info(&self) -> PixelInfo {
let type_size = match self {
// 8bit
TextureFormat::R8Unorm
| TextureFormat::R8Snorm
| TextureFormat::R8Uint
| TextureFormat::R8Sint
| TextureFormat::Rg8Unorm
| TextureFormat::Rg8Snorm
| TextureFormat::Rg8Uint
| TextureFormat::Rg8Sint
| TextureFormat::Rgba8Unorm
| TextureFormat::Rgba8UnormSrgb
| TextureFormat::Rgba8Snorm
| TextureFormat::Rgba8Uint
| TextureFormat::Rgba8Sint
| TextureFormat::Bgra8Unorm
| TextureFormat::Bgra8UnormSrgb => 1,
// 16bit
TextureFormat::R16Uint
| TextureFormat::R16Sint
| TextureFormat::R16Float
| TextureFormat::Rg16Uint
| TextureFormat::Rg16Sint
| TextureFormat::Rg16Float
| TextureFormat::Rgba16Uint
| TextureFormat::Rgba16Sint
| TextureFormat::Rgba16Float => 2,
// 32bit
TextureFormat::R32Uint
| TextureFormat::R32Sint
| TextureFormat::R32Float
| TextureFormat::Rg32Uint
| TextureFormat::Rg32Sint
| TextureFormat::Rg32Float
| TextureFormat::Rgba32Uint
| TextureFormat::Rgba32Sint
| TextureFormat::Rgba32Float
| TextureFormat::Depth32Float => 4,
// special cases
TextureFormat::Rgb10a2Unorm => 4,
TextureFormat::Rg11b10Float => 4,
TextureFormat::Depth24Plus => 3, // FIXME is this correct?
TextureFormat::Depth24PlusStencil8 => 4,
};
let components = match self {
TextureFormat::R8Unorm
| TextureFormat::R8Snorm
| TextureFormat::R8Uint
| TextureFormat::R8Sint
| TextureFormat::R16Uint
| TextureFormat::R16Sint
| TextureFormat::R16Float
| TextureFormat::R32Uint
| TextureFormat::R32Sint
| TextureFormat::R32Float => 1,
TextureFormat::Rg8Unorm
| TextureFormat::Rg8Snorm
| TextureFormat::Rg8Uint
| TextureFormat::Rg8Sint
| TextureFormat::Rg16Uint
| TextureFormat::Rg16Sint
| TextureFormat::Rg16Float
| TextureFormat::Rg32Uint
| TextureFormat::Rg32Sint
| TextureFormat::Rg32Float => 2,
TextureFormat::Rgba8Unorm
| TextureFormat::Rgba8UnormSrgb
| TextureFormat::Rgba8Snorm
| TextureFormat::Rgba8Uint
| TextureFormat::Rgba8Sint
| TextureFormat::Bgra8Unorm
| TextureFormat::Bgra8UnormSrgb
| TextureFormat::Rgba16Uint
| TextureFormat::Rgba16Sint
| TextureFormat::Rgba16Float
| TextureFormat::Rgba32Uint
| TextureFormat::Rgba32Sint
| TextureFormat::Rgba32Float => 4,
// special cases
TextureFormat::Rgb10a2Unorm
| TextureFormat::Rg11b10Float
| TextureFormat::Depth32Float
| TextureFormat::Depth24Plus
| TextureFormat::Depth24PlusStencil8 => 1,
};
PixelInfo {
type_size,
num_components: components,
}
}
pub fn pixel_size(&self) -> usize {
let info = self.pixel_info();
info.type_size * info.num_components
}
}
bitflags::bitflags! { bitflags::bitflags! {
#[repr(transparent)] #[repr(transparent)]
pub struct TextureUsage: u32 { pub struct TextureUsage: u32 {

View File

@ -10,7 +10,6 @@ pub struct DynamicTextureAtlasBuilder {
pub atlas_allocator: AtlasAllocator, pub atlas_allocator: AtlasAllocator,
} }
const FORMAT_SIZE: usize = 4; // TODO: get this from an actual format type
impl DynamicTextureAtlasBuilder { impl DynamicTextureAtlasBuilder {
pub fn new(size: Vec2) -> Self { pub fn new(size: Vec2) -> Self {
Self { Self {
@ -70,12 +69,13 @@ impl DynamicTextureAtlasBuilder {
let rect = allocation.rectangle; let rect = allocation.rectangle;
let atlas_width = atlas_texture.size.x() as usize; let atlas_width = atlas_texture.size.x() as usize;
let rect_width = rect.width() as usize; let rect_width = rect.width() as usize;
let format_size = atlas_texture.format.pixel_size();
for (texture_y, bound_y) in (rect.min.y..rect.max.y).map(|i| i as usize).enumerate() { for (texture_y, bound_y) in (rect.min.y..rect.max.y).map(|i| i as usize).enumerate() {
let begin = (bound_y * atlas_width + rect.min.x as usize) * FORMAT_SIZE; let begin = (bound_y * atlas_width + rect.min.x as usize) * format_size;
let end = begin + rect_width * FORMAT_SIZE; let end = begin + rect_width * format_size;
let texture_begin = texture_y * rect_width * FORMAT_SIZE; let texture_begin = texture_y * rect_width * format_size;
let texture_end = texture_begin + rect_width * FORMAT_SIZE; let texture_end = texture_begin + rect_width * format_size;
atlas_texture.data[begin..end] atlas_texture.data[begin..end]
.copy_from_slice(&texture.data[texture_begin..texture_end]); .copy_from_slice(&texture.data[texture_begin..texture_end]);
} }

View File

@ -1,7 +1,7 @@
use crate::{Rect, TextureAtlas}; use crate::{Rect, TextureAtlas};
use bevy_asset::{Assets, Handle}; use bevy_asset::{Assets, Handle};
use bevy_math::Vec2; use bevy_math::Vec2;
use bevy_render::texture::Texture; use bevy_render::texture::{Texture, TextureFormat};
use rectangle_pack::{ use rectangle_pack::{
contains_smallest_box, pack_rects, volume_heuristic, GroupedRectsToPlace, PackedLocation, contains_smallest_box, pack_rects, volume_heuristic, GroupedRectsToPlace, PackedLocation,
RectToInsert, TargetBin, RectToInsert, TargetBin,
@ -28,7 +28,6 @@ pub enum RectanglePackError {
NotEnoughSpace, NotEnoughSpace,
} }
const FORMAT_SIZE: usize = 4; // TODO: get this from an actual format type
impl TextureAtlasBuilder { impl TextureAtlasBuilder {
pub fn new(initial_size: Vec2, max_size: Vec2) -> Self { pub fn new(initial_size: Vec2, max_size: Vec2) -> Self {
Self { Self {
@ -58,12 +57,13 @@ impl TextureAtlasBuilder {
let rect_x = packed_location.x() as usize; let rect_x = packed_location.x() as usize;
let rect_y = packed_location.y() as usize; let rect_y = packed_location.y() as usize;
let atlas_width = atlas_texture.size.x() as usize; let atlas_width = atlas_texture.size.x() as usize;
let format_size = atlas_texture.format.pixel_size();
for (texture_y, bound_y) in (rect_y..rect_y + rect_height).enumerate() { for (texture_y, bound_y) in (rect_y..rect_y + rect_height).enumerate() {
let begin = (bound_y * atlas_width + rect_x) * FORMAT_SIZE; let begin = (bound_y * atlas_width + rect_x) * format_size;
let end = begin + rect_width * FORMAT_SIZE; let end = begin + rect_width * format_size;
let texture_begin = texture_y * rect_width * FORMAT_SIZE; let texture_begin = texture_y * rect_width * format_size;
let texture_end = texture_begin + rect_width * FORMAT_SIZE; let texture_end = texture_begin + rect_width * format_size;
atlas_texture.data[begin..end] atlas_texture.data[begin..end]
.copy_from_slice(&texture.data[texture_begin..texture_end]); .copy_from_slice(&texture.data[texture_begin..texture_end]);
} }
@ -93,6 +93,7 @@ impl TextureAtlasBuilder {
atlas_texture = Texture::new_fill( atlas_texture = Texture::new_fill(
Vec2::new(current_width as f32, current_height as f32), Vec2::new(current_width as f32, current_height as f32),
&[0, 0, 0, 0], &[0, 0, 0, 0],
TextureFormat::Rgba8UnormSrgb,
); );
rect_placements = match pack_rects( rect_placements = match pack_rects(
&self.rects_to_place, &self.rects_to_place,

View File

@ -1,7 +1,7 @@
use crate::{Font, FontAtlasSet}; use crate::{Font, FontAtlasSet};
use ab_glyph::{FontVec, Glyph, PxScale, PxScaleFont, ScaleFont}; use ab_glyph::{FontVec, Glyph, PxScale, PxScaleFont, ScaleFont};
use bevy_asset::Assets; use bevy_asset::Assets;
use bevy_math::{Mat4, Vec3, Vec2}; use bevy_math::{Mat4, Vec2, Vec3};
use bevy_render::{ use bevy_render::{
color::Color, color::Color,
draw::{Draw, DrawContext, DrawError, Drawable}, draw::{Draw, DrawContext, DrawError, Drawable},
@ -112,9 +112,12 @@ impl<'a> Drawable for DrawableText<'a> {
match self.style.align { match self.style.align {
TextAlign::Left => { /* already aligned left by default */ } TextAlign::Left => { /* already aligned left by default */ }
TextAlign::Center => { TextAlign::Center => {
*caret.x_mut() += self.container_size.x() / 2.0 - get_text_width(&self.text, &scaled_font) / 2.0 *caret.x_mut() +=
self.container_size.x() / 2.0 - get_text_width(&self.text, &scaled_font) / 2.0
}
TextAlign::Right => {
*caret.x_mut() += self.container_size.x() - get_text_width(&self.text, &scaled_font)
} }
TextAlign::Right => *caret.x_mut() += self.container_size.x() - get_text_width(&self.text, &scaled_font),
} }
let mut last_glyph: Option<Glyph> = None; let mut last_glyph: Option<Glyph> = None;

View File

@ -1,6 +1,9 @@
use ab_glyph::{FontVec, Glyph, InvalidFont, OutlinedGlyph, Point, PxScale, ScaleFont}; use ab_glyph::{FontVec, Glyph, InvalidFont, OutlinedGlyph, Point, PxScale, ScaleFont};
use bevy_math::Vec2; use bevy_math::Vec2;
use bevy_render::{color::Color, texture::Texture}; use bevy_render::{
color::Color,
texture::{Texture, TextureFormat},
};
pub struct Font { pub struct Font {
pub font: FontVec, pub font: FontVec,
@ -32,6 +35,7 @@ impl Font {
(color.b * 255.0) as u8, (color.b * 255.0) as u8,
]; ];
Texture::new( Texture::new(
Vec2::new(width as f32, height as f32),
alpha alpha
.iter() .iter()
.map(|a| { .map(|a| {
@ -44,7 +48,7 @@ impl Font {
}) })
.flatten() .flatten()
.collect::<Vec<u8>>(), .collect::<Vec<u8>>(),
Vec2::new(width as f32, height as f32), TextureFormat::Rgba8UnormSrgb,
) )
} }
@ -96,6 +100,7 @@ impl Font {
} }
Texture::new( Texture::new(
Vec2::new(width as f32, height as f32),
alpha alpha
.iter() .iter()
.map(|a| { .map(|a| {
@ -108,7 +113,7 @@ impl Font {
}) })
.flatten() .flatten()
.collect::<Vec<u8>>(), .collect::<Vec<u8>>(),
Vec2::new(width as f32, height as f32), TextureFormat::Rgba8UnormSrgb,
) )
} }
} }

View File

@ -1,6 +1,6 @@
use bevy_asset::{Assets, Handle}; use bevy_asset::{Assets, Handle};
use bevy_math::Vec2; use bevy_math::Vec2;
use bevy_render::texture::Texture; use bevy_render::texture::{Texture, TextureFormat};
use bevy_sprite::{DynamicTextureAtlasBuilder, TextureAtlas}; use bevy_sprite::{DynamicTextureAtlasBuilder, TextureAtlas};
use std::collections::HashMap; use std::collections::HashMap;
@ -16,7 +16,11 @@ impl FontAtlas {
texture_atlases: &mut Assets<TextureAtlas>, texture_atlases: &mut Assets<TextureAtlas>,
size: Vec2, size: Vec2,
) -> FontAtlas { ) -> FontAtlas {
let atlas_texture = textures.add(Texture::new_fill(size, &[0, 0, 0, 0])); let atlas_texture = textures.add(Texture::new_fill(
size,
&[0, 0, 0, 0],
TextureFormat::Rgba8UnormSrgb,
));
let texture_atlas = TextureAtlas::new_empty(atlas_texture, size); let texture_atlas = TextureAtlas::new_empty(atlas_texture, size);
Self { Self {
texture_atlas: texture_atlases.add(texture_atlas), texture_atlas: texture_atlases.add(texture_atlas),

View File

@ -11,7 +11,7 @@ pub use font_atlas_set::*;
pub use font_loader::*; pub use font_loader::*;
pub mod prelude { pub mod prelude {
pub use crate::{Font, TextStyle, TextAlign}; pub use crate::{Font, TextAlign, TextStyle};
} }
use bevy_app::prelude::*; use bevy_app::prelude::*;

View File

@ -1,7 +1,7 @@
use bevy_ecs::Entity; use bevy_ecs::Entity;
use bevy_property::Properties; use bevy_property::Properties;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::ops::{DerefMut, Deref}; use std::ops::{Deref, DerefMut};
#[derive(Default, Clone, Properties, Debug)] #[derive(Default, Clone, Properties, Debug)]
pub struct Children(pub SmallVec<[Entity; 8]>); pub struct Children(pub SmallVec<[Entity; 8]>);
@ -23,4 +23,4 @@ impl DerefMut for Children {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,6 +1,9 @@
use bevy_math::Mat4; use bevy_math::Mat4;
use bevy_property::Properties; use bevy_property::Properties;
use std::{ops::{DerefMut, Deref}, fmt}; use std::{
fmt,
ops::{Deref, DerefMut},
};
#[derive(Debug, PartialEq, Clone, Copy, Properties)] #[derive(Debug, PartialEq, Clone, Copy, Properties)]
pub struct LocalTransform(pub Mat4); pub struct LocalTransform(pub Mat4);
@ -34,4 +37,4 @@ impl DerefMut for LocalTransform {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,6 +1,9 @@
use bevy_math::Vec3; use bevy_math::Vec3;
use bevy_property::Properties; use bevy_property::Properties;
use std::{ops::{DerefMut, Deref}, fmt}; use std::{
fmt,
ops::{Deref, DerefMut},
};
#[derive(Debug, PartialEq, Clone, Copy, Properties)] #[derive(Debug, PartialEq, Clone, Copy, Properties)]
pub struct NonUniformScale(pub Vec3); pub struct NonUniformScale(pub Vec3);
@ -53,4 +56,4 @@ impl DerefMut for NonUniformScale {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,6 +1,6 @@
use bevy_ecs::{FromResources, Entity}; use bevy_ecs::{Entity, FromResources};
use bevy_property::Properties; use bevy_property::Properties;
use std::ops::{DerefMut, Deref}; use std::ops::{Deref, DerefMut};
#[derive(Debug, Copy, Clone, Eq, PartialEq, Properties)] #[derive(Debug, Copy, Clone, Eq, PartialEq, Properties)]
pub struct Parent(pub Entity); pub struct Parent(pub Entity);
@ -11,7 +11,7 @@ pub struct Parent(pub Entity);
// ways to handle cases like this. // ways to handle cases like this.
impl FromResources for Parent { impl FromResources for Parent {
fn from_resources(_resources: &bevy_ecs::Resources) -> Self { fn from_resources(_resources: &bevy_ecs::Resources) -> Self {
Parent(Entity::from_id(u32::MAX)) Parent(Entity::from_id(u32::MAX))
} }
} }
@ -29,4 +29,4 @@ impl DerefMut for Parent {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }

View File

@ -34,4 +34,4 @@ impl DerefMut for Rotation {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,5 +1,8 @@
use bevy_property::Properties; use bevy_property::Properties;
use std::{ops::{DerefMut, Deref}, fmt}; use std::{
fmt,
ops::{Deref, DerefMut},
};
#[derive(Debug, PartialEq, Clone, Copy, Properties)] #[derive(Debug, PartialEq, Clone, Copy, Properties)]
pub struct Scale(pub f32); pub struct Scale(pub f32);
@ -41,4 +44,4 @@ impl DerefMut for Scale {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,6 +1,6 @@
use bevy_math::Vec3; use bevy_math::Vec3;
use bevy_property::Properties; use bevy_property::Properties;
use std::ops::{DerefMut, Deref}; use std::ops::{Deref, DerefMut};
#[derive(Debug, PartialEq, Copy, Clone, Properties)] #[derive(Debug, PartialEq, Copy, Clone, Properties)]
pub struct Translation(pub Vec3); pub struct Translation(pub Vec3);
@ -40,4 +40,4 @@ impl DerefMut for Translation {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0 &mut self.0
} }
} }

View File

@ -1,4 +1,4 @@
use crate::prelude::{LocalTransform, Parent, PreviousParent, Children}; use crate::prelude::{Children, LocalTransform, Parent, PreviousParent};
use bevy_ecs::{Component, DynamicBundle, Entity, WorldBuilder}; use bevy_ecs::{Component, DynamicBundle, Entity, WorldBuilder};
pub struct WorldChildBuilder<'a, 'b> { pub struct WorldChildBuilder<'a, 'b> {

View File

@ -11,7 +11,9 @@ pub mod prelude {
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_ecs::prelude::*; use bevy_ecs::prelude::*;
use bevy_type_registry::RegisterType; use bevy_type_registry::RegisterType;
use prelude::{Children, LocalTransform, NonUniformScale, Rotation, Scale, Transform, Translation, Parent}; use prelude::{
Children, LocalTransform, NonUniformScale, Parent, Rotation, Scale, Transform, Translation,
};
pub(crate) fn transform_systems() -> Vec<Box<dyn System>> { pub(crate) fn transform_systems() -> Vec<Box<dyn System>> {
let mut systems = Vec::with_capacity(5); let mut systems = Vec::with_capacity(5);

View File

@ -50,4 +50,4 @@ impl AppPlugin for UiPlugin {
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap(); let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
render_graph.add_ui_graph(resources); render_graph.add_ui_graph(resources);
} }
} }

View File

@ -1 +1 @@
pub struct Button; pub struct Button;

View File

@ -72,4 +72,4 @@ pub fn draw_text_system(
}; };
drawable_text.draw(&mut draw, &mut draw_context).unwrap(); drawable_text.draw(&mut draw, &mut draw_context).unwrap();
} }
} }

View File

@ -267,9 +267,14 @@ impl RenderResourceContext for WgpuRenderResourceContext {
if let Some(texture_id) = self.try_next_swap_chain_texture(window.id) { if let Some(texture_id) = self.try_next_swap_chain_texture(window.id) {
texture_id texture_id
} else { } else {
self.resources.window_swap_chains.write().unwrap().remove(&window.id); self.resources
.window_swap_chains
.write()
.unwrap()
.remove(&window.id);
self.create_swap_chain(window); self.create_swap_chain(window);
self.try_next_swap_chain_texture(window.id).expect("Failed to acquire next swap chain texture!") self.try_next_swap_chain_texture(window.id)
.expect("Failed to acquire next swap chain texture!")
} }
} }

View File

@ -13,7 +13,7 @@ impl WindowId {
} }
pub fn is_primary(&self) -> bool { pub fn is_primary(&self) -> bool {
*self == WindowId::primary() *self == WindowId::primary()
} }
pub fn to_string(&self) -> String { pub fn to_string(&self) -> String {

View File

@ -91,9 +91,7 @@ pub fn winit_runner(mut app: App) {
let windows = app.resources.get_mut::<Windows>().unwrap(); let windows = app.resources.get_mut::<Windows>().unwrap();
let winit_windows = app.resources.get_mut::<WinitWindows>().unwrap(); let winit_windows = app.resources.get_mut::<WinitWindows>().unwrap();
let window_id = winit_windows.get_window_id(winit_window_id).unwrap(); let window_id = winit_windows.get_window_id(winit_window_id).unwrap();
window_close_requested_events.send(WindowCloseRequested { window_close_requested_events.send(WindowCloseRequested { id: window_id });
id: window_id,
});
} }
WindowEvent::KeyboardInput { ref input, .. } => { WindowEvent::KeyboardInput { ref input, .. } => {
let mut keyboard_input_events = let mut keyboard_input_events =
@ -108,7 +106,7 @@ pub fn winit_runner(mut app: App) {
let window = winit_windows.get_window(window_id).unwrap(); let window = winit_windows.get_window(window_id).unwrap();
let inner_size = window.inner_size(); let inner_size = window.inner_size();
// move origin to bottom left // move origin to bottom left
let y_position = inner_size.height as f32 - position.y as f32; let y_position = inner_size.height as f32 - position.y as f32;
cursor_moved_events.send(CursorMoved { cursor_moved_events.send(CursorMoved {
id: window_id, id: window_id,
position: Vec2::new(position.x as f32, y_position as f32), position: Vec2::new(position.x as f32, y_position as f32),
@ -161,8 +159,6 @@ fn handle_create_window_events(
winit_windows.create_window(event_loop, &window); winit_windows.create_window(event_loop, &window);
let window_id = window.id; let window_id = window.id;
windows.add(window); windows.add(window);
window_created_events.send(WindowCreated { window_created_events.send(WindowCreated { id: window_id });
id: window_id,
});
} }
} }

View File

@ -1,9 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
fn main() { fn main() {
App::build() App::build().add_system(hello_world_system.system()).run();
.add_system(hello_world_system.system())
.run();
} }
fn hello_world_system() { fn hello_world_system() {

View File

@ -239,6 +239,5 @@ fn setup(
.spawn(NodeComponents { .spawn(NodeComponents {
material: materials.add(Color::rgb(1.0, 0.0, 0.0).into()), material: materials.add(Color::rgb(1.0, 0.0, 0.0).into()),
..Default::default() ..Default::default()
}) });
;
} }

View File

@ -1,20 +1,6 @@
pub use crate::{ pub use crate::{
app::prelude::*, app::prelude::*, asset::prelude::*, audio::prelude::*, core::prelude::*, ecs::prelude::*,
asset::prelude::*, input::prelude::*, math::prelude::*, pbr::prelude::*, property::prelude::*, render::prelude::*,
audio::prelude::*, scene::prelude::*, sprite::prelude::*, text::prelude::*, transform::prelude::*,
core::prelude::*, type_registry::RegisterType, ui::prelude::*, window::prelude::*, AddDefaultPlugins,
ecs::prelude::*,
input::prelude::*,
math::prelude::*,
pbr::prelude::*,
property::prelude::*,
render::prelude::*,
scene::prelude::*,
sprite::prelude::*,
text::prelude::*,
transform::prelude::*,
type_registry::RegisterType,
window::prelude::*,
ui::prelude::*,
AddDefaultPlugins,
}; };