Merge pull request #72 from karroffel/texture-format
add `TextureFormat` field to `Texture`
This commit is contained in:
commit
718f475160
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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::*;
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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>);
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@ -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::*;
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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::*;
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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::*;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
mod world_builder;
|
mod world_builder;
|
||||||
|
|
||||||
pub use world_builder::*;
|
pub use world_builder::*;
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
@ -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};
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -2,4 +2,4 @@ mod mesh;
|
|||||||
mod vertex;
|
mod vertex;
|
||||||
|
|
||||||
pub use mesh::*;
|
pub use mesh::*;
|
||||||
pub use vertex::*;
|
pub use vertex::*;
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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"];
|
||||||
|
|||||||
@ -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(
|
||||||
|
|||||||
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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),
|
||||||
|
|||||||
@ -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::*;
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
pub struct Button;
|
pub struct Button;
|
||||||
|
|||||||
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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() {
|
||||||
|
|||||||
@ -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()
|
||||||
})
|
});
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,
|
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user