Document and test Events. Rename EventHandle to EventReader. Fix buffer indexing. Customizable bevy path for proc macros
This commit is contained in:
parent
8a759d3b18
commit
f6f8ba2cb6
@ -11,6 +11,7 @@ proc-macro = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
syn = "1.0"
|
syn = "1.0"
|
||||||
|
proc-macro2 = "1.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
Inflector = { version = "0.11.4", default-features = false }
|
Inflector = { version = "0.11.4", default-features = false }
|
||||||
darling = "0.10.2"
|
darling = "0.10.2"
|
||||||
|
|||||||
@ -3,6 +3,7 @@ extern crate proc_macro;
|
|||||||
use darling::FromMeta;
|
use darling::FromMeta;
|
||||||
use inflector::Inflector;
|
use inflector::Inflector;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::Span;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Ident, Type};
|
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Ident, Type};
|
||||||
|
|
||||||
@ -82,12 +83,31 @@ struct UniformAttributeArgs {
|
|||||||
pub instance: Option<bool>,
|
pub instance: Option<bool>,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub vertex: Option<bool>,
|
pub vertex: Option<bool>,
|
||||||
|
#[darling(default)]
|
||||||
|
pub bevy_path: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Uniforms, attributes(uniform))]
|
#[proc_macro_derive(Uniforms, attributes(uniform))]
|
||||||
pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
||||||
static UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
|
static UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
|
||||||
let ast = parse_macro_input!(input as DeriveInput);
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
|
let mut bevy_path_name = "bevy".to_string();
|
||||||
|
let struct_attribute_args = ast
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == UNIFORM_ATTRIBUTE_NAME)
|
||||||
|
.map(|a| {
|
||||||
|
UniformAttributeArgs::from_meta(&a.parse_meta().unwrap())
|
||||||
|
.unwrap_or_else(|_err| UniformAttributeArgs::default())
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(struct_attribute_args) = struct_attribute_args {
|
||||||
|
if let Some(attribute_bevy_path) = struct_attribute_args.bevy_path {
|
||||||
|
bevy_path_name = attribute_bevy_path.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let bevy_path = Ident::new(&bevy_path_name, Span::call_site());
|
||||||
|
|
||||||
let fields = match &ast.data {
|
let fields = match &ast.data {
|
||||||
Data::Struct(DataStruct {
|
Data::Struct(DataStruct {
|
||||||
@ -195,20 +215,11 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
let vertex_buffer_field_names_pascal = vertex_buffer_fields
|
let vertex_buffer_field_names_pascal = vertex_buffer_fields
|
||||||
.map(|(f, (instance, _vertex))| {
|
.map(|(f, (instance, _vertex))| {
|
||||||
let pascal_field = f.ident.as_ref().unwrap().to_string().to_pascal_case();
|
let pascal_field = f.ident.as_ref().unwrap().to_string().to_pascal_case();
|
||||||
if instance {
|
if instance {
|
||||||
format!(
|
format!("I_{}_{}", struct_name, pascal_field)
|
||||||
"I_{}_{}",
|
|
||||||
struct_name,
|
|
||||||
pascal_field
|
|
||||||
)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
format!(
|
format!("{}_{}", struct_name, pascal_field)
|
||||||
"{}_{}",
|
|
||||||
struct_name,
|
|
||||||
pascal_field
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
@ -242,7 +253,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
},
|
},
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
quote!(bevy::render::shader::FieldInfo {
|
quote!(#bevy_path::render::shader::FieldInfo {
|
||||||
name: #field_name,
|
name: #field_name,
|
||||||
uniform_name: #uniform,
|
uniform_name: #uniform,
|
||||||
texture_name: #texture,
|
texture_name: #texture,
|
||||||
@ -252,13 +263,13 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
});
|
});
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
static #field_infos_ident: &[bevy::render::shader::FieldInfo] = &[
|
static #field_infos_ident: &[#bevy_path::render::shader::FieldInfo] = &[
|
||||||
#(#field_infos,)*
|
#(#field_infos,)*
|
||||||
];
|
];
|
||||||
|
|
||||||
static #vertex_buffer_descriptor_ident: bevy::once_cell::sync::Lazy<bevy::render::pipeline::VertexBufferDescriptor> =
|
static #vertex_buffer_descriptor_ident: #bevy_path::once_cell::sync::Lazy<#bevy_path::render::pipeline::VertexBufferDescriptor> =
|
||||||
bevy::once_cell::sync::Lazy::new(|| {
|
#bevy_path::once_cell::sync::Lazy::new(|| {
|
||||||
use bevy::render::pipeline::{VertexFormat, AsVertexFormats, VertexAttributeDescriptor};
|
use #bevy_path::render::pipeline::{VertexFormat, AsVertexFormats, VertexAttributeDescriptor};
|
||||||
|
|
||||||
let mut vertex_formats: Vec<(&str,&[VertexFormat])> = vec![
|
let mut vertex_formats: Vec<(&str,&[VertexFormat])> = vec![
|
||||||
#((#vertex_buffer_field_names_pascal, <#vertex_buffer_field_types>::as_vertex_formats()),)*
|
#((#vertex_buffer_field_names_pascal, <#vertex_buffer_field_types>::as_vertex_formats()),)*
|
||||||
@ -286,21 +297,21 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
}).collect::<Vec<VertexAttributeDescriptor>>()
|
}).collect::<Vec<VertexAttributeDescriptor>>()
|
||||||
}).flatten().collect::<Vec<VertexAttributeDescriptor>>();
|
}).flatten().collect::<Vec<VertexAttributeDescriptor>>();
|
||||||
|
|
||||||
bevy::render::pipeline::VertexBufferDescriptor {
|
#bevy_path::render::pipeline::VertexBufferDescriptor {
|
||||||
attributes: vertex_attribute_descriptors,
|
attributes: vertex_attribute_descriptors,
|
||||||
name: #struct_name_string.to_string(),
|
name: #struct_name_string.to_string(),
|
||||||
step_mode: bevy::render::pipeline::InputStepMode::Instance,
|
step_mode: #bevy_path::render::pipeline::InputStepMode::Instance,
|
||||||
stride: offset,
|
stride: offset,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
impl bevy::render::shader::AsUniforms for #struct_name {
|
impl #bevy_path::render::shader::AsUniforms for #struct_name {
|
||||||
fn get_field_infos() -> &'static [bevy::render::shader::FieldInfo] {
|
fn get_field_infos() -> &'static [#bevy_path::render::shader::FieldInfo] {
|
||||||
#field_infos_ident
|
#field_infos_ident
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_field_bind_type(&self, name: &str) -> Option<bevy::render::shader::FieldBindType> {
|
fn get_field_bind_type(&self, name: &str) -> Option<#bevy_path::render::shader::FieldBindType> {
|
||||||
use bevy::render::shader::AsFieldBindType;
|
use #bevy_path::render::shader::AsFieldBindType;
|
||||||
match name {
|
match name {
|
||||||
#(#active_uniform_field_name_strings => self.#active_uniform_field_names.get_field_bind_type(),)*
|
#(#active_uniform_field_name_strings => self.#active_uniform_field_names.get_field_bind_type(),)*
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -308,7 +319,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
|
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
|
||||||
use bevy::core::bytes::GetBytes;
|
use #bevy_path::core::bytes::GetBytes;
|
||||||
match name {
|
match name {
|
||||||
#(#uniform_name_strings => Some(self.#active_uniform_field_names.get_bytes()),)*
|
#(#uniform_name_strings => Some(self.#active_uniform_field_names.get_bytes()),)*
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -316,15 +327,15 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]> {
|
fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]> {
|
||||||
use bevy::core::bytes::GetBytes;
|
use #bevy_path::core::bytes::GetBytes;
|
||||||
match name {
|
match name {
|
||||||
#(#uniform_name_strings => self.#active_uniform_field_names.get_bytes_ref(),)*
|
#(#uniform_name_strings => self.#active_uniform_field_names.get_bytes_ref(),)*
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_uniform_texture(&self, name: &str) -> Option<bevy::asset::Handle<bevy::render::texture::Texture>> {
|
fn get_uniform_texture(&self, name: &str) -> Option<#bevy_path::asset::Handle<#bevy_path::render::texture::Texture>> {
|
||||||
use bevy::render::shader::GetTexture;
|
use #bevy_path::render::shader::GetTexture;
|
||||||
match name {
|
match name {
|
||||||
#(#texture_and_sampler_name_strings => self.#texture_and_sampler_name_idents.get_texture(),)*
|
#(#texture_and_sampler_name_strings => self.#texture_and_sampler_name_idents.get_texture(),)*
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -335,7 +346,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
// TODO: this will be very allocation heavy. find a way to either make this allocation free
|
// TODO: this will be very allocation heavy. find a way to either make this allocation free
|
||||||
// or alternatively only run it when the shader_defs have changed
|
// or alternatively only run it when the shader_defs have changed
|
||||||
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
||||||
use bevy::render::shader::ShaderDefSuffixProvider;
|
use #bevy_path::render::shader::ShaderDefSuffixProvider;
|
||||||
let mut potential_shader_defs: Vec<(&'static str, Option<&'static str>)> = vec![
|
let mut potential_shader_defs: Vec<(&'static str, Option<&'static str>)> = vec![
|
||||||
#((#shader_def_field_names_screaming_snake, self.#shader_def_field_names.get_shader_def()),)*
|
#((#shader_def_field_names_screaming_snake, self.#shader_def_field_names.get_shader_def()),)*
|
||||||
];
|
];
|
||||||
@ -346,7 +357,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
.collect::<Vec<String>>())
|
.collect::<Vec<String>>())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_vertex_buffer_descriptor() -> Option<&'static bevy::render::pipeline::VertexBufferDescriptor> {
|
fn get_vertex_buffer_descriptor() -> Option<&'static #bevy_path::render::pipeline::VertexBufferDescriptor> {
|
||||||
if #vertex_buffer_descriptor_ident.attributes.len() == 0 {
|
if #vertex_buffer_descriptor_ident.attributes.len() == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -17,11 +17,11 @@ fn event_trigger_system() -> Box<dyn Schedulable> {
|
|||||||
let mut elapsed = 0.0;
|
let mut elapsed = 0.0;
|
||||||
SystemBuilder::new("event_trigger")
|
SystemBuilder::new("event_trigger")
|
||||||
.read_resource::<Time>()
|
.read_resource::<Time>()
|
||||||
.write_resource::<Event<MyEvent>>()
|
.write_resource::<Events<MyEvent>>()
|
||||||
.build(move |_, _, (time, my_event), _| {
|
.build(move |_, _, (time, my_events), _| {
|
||||||
elapsed += time.delta_seconds;
|
elapsed += time.delta_seconds;
|
||||||
if elapsed > 1.0 {
|
if elapsed > 1.0 {
|
||||||
my_event.send(MyEvent {
|
my_events.send(MyEvent {
|
||||||
message: "Hello World".to_string(),
|
message: "Hello World".to_string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -31,11 +31,11 @@ fn event_trigger_system() -> Box<dyn Schedulable> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn event_listener_system(resources: &mut Resources) -> Box<dyn Schedulable> {
|
fn event_listener_system(resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||||
let mut my_event_handle = resources.get_event_handle::<MyEvent>();
|
let mut my_event_reader = resources.get_event_reader::<MyEvent>();
|
||||||
SystemBuilder::new("event_listener")
|
SystemBuilder::new("event_listener")
|
||||||
.read_resource::<Event<MyEvent>>()
|
.read_resource::<Events<MyEvent>>()
|
||||||
.build(move |_, _, my_events, _| {
|
.build(move |_, _, my_events, _| {
|
||||||
for my_event in my_events.iter(&mut my_event_handle) {
|
for my_event in my_events.iter(&mut my_event_reader) {
|
||||||
println!("{}", my_event.message);
|
println!("{}", my_event.message);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use crate::{
|
|||||||
plugin::{load_plugin, AppPlugin},
|
plugin::{load_plugin, AppPlugin},
|
||||||
system_stage, App,
|
system_stage, App,
|
||||||
},
|
},
|
||||||
core::{CorePlugin, Event},
|
core::{CorePlugin, Events},
|
||||||
legion::prelude::{Resources, Runnable, Schedulable, Schedule, Universe, World},
|
legion::prelude::{Resources, Runnable, Schedulable, Schedule, Universe, World},
|
||||||
render::RenderPlugin,
|
render::RenderPlugin,
|
||||||
ui::UiPlugin,
|
ui::UiPlugin,
|
||||||
@ -177,8 +177,8 @@ impl AppBuilder {
|
|||||||
where
|
where
|
||||||
T: Send + Sync + 'static,
|
T: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
self.add_resource(Event::<T>::default())
|
self.add_resource(Events::<T>::default())
|
||||||
.add_system_to_stage(system_stage::EVENT_UPDATE, Event::<T>::update_system())
|
.add_system_to_stage(system_stage::EVENT_UPDATE, Events::<T>::build_update_system())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_resource<T>(mut self, resource: T) -> Self
|
pub fn add_resource<T>(mut self, resource: T) -> Self
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use super::{CreateWindow, Time, WindowCreated, WindowResized, Windows, Event, WindowDescriptor};
|
use super::{CreateWindow, Time, WindowCreated, WindowResized, Windows, Events, WindowDescriptor};
|
||||||
use crate::app::{plugin::AppPlugin, AppBuilder};
|
use crate::app::{plugin::AppPlugin, AppBuilder};
|
||||||
use bevy_transform::transform_system_bundle;
|
use bevy_transform::transform_system_bundle;
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ impl AppPlugin for CorePlugin {
|
|||||||
.add_resource(Time::new());
|
.add_resource(Time::new());
|
||||||
|
|
||||||
if let Some(ref primary_window_descriptor) = self.primary_window {
|
if let Some(ref primary_window_descriptor) = self.primary_window {
|
||||||
let mut create_window_event = app.resources.get_mut::<Event<CreateWindow>>().unwrap();
|
let mut create_window_event = app.resources.get_mut::<Events<CreateWindow>>().unwrap();
|
||||||
create_window_event.send(CreateWindow {
|
create_window_event.send(CreateWindow {
|
||||||
descriptor: primary_window_descriptor.clone(),
|
descriptor: primary_window_descriptor.clone(),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -12,7 +12,49 @@ enum State {
|
|||||||
B,
|
B,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Event<T>
|
/// An event collection that represents the events that occurred within the last two [Events::update] calls. Events can be cheaply read using
|
||||||
|
/// an [EventReader]. This collection is meant to be paired with a system that calls [Events::update] exactly once per update/frame. [Events::build_update_system]
|
||||||
|
/// will produce a system that does this. [EventReader]s are expected to read events from this collection at least once per update/frame. If events are not handled
|
||||||
|
/// within one frame/update, they will be dropped.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// use bevy::core::event::Events;
|
||||||
|
///
|
||||||
|
/// struct MyEvent {
|
||||||
|
/// value: usize
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // setup
|
||||||
|
/// let mut events = Events::<MyEvent>::default();
|
||||||
|
/// let mut reader = events.get_reader();
|
||||||
|
///
|
||||||
|
/// // run this once per update/frame
|
||||||
|
/// events.update();
|
||||||
|
///
|
||||||
|
/// // somewhere else: send an event
|
||||||
|
/// events.send(MyEvent { value: 1 });
|
||||||
|
///
|
||||||
|
/// // somewhere else: read the events
|
||||||
|
/// for event in events.iter(&mut reader) {
|
||||||
|
/// assert_eq!(event.value, 1)
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // events are only processed once per reader
|
||||||
|
/// assert_eq!(events.iter(&mut reader).count(), 0);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Details
|
||||||
|
///
|
||||||
|
/// [Events] is implemented using a double buffer. Each call to [Events::update] swaps buffers and clears out the oldest buffer.
|
||||||
|
/// [EventReader]s that read at least once per update will never drop events. [EventReader]s that read once within two updates might
|
||||||
|
/// still receive some events. [EventReader]s that read after two updates are guaranteed to drop all events that occurred before those updates.
|
||||||
|
///
|
||||||
|
/// The buffers in [Events] will grow indefinitely if [Events::update] is never called.
|
||||||
|
///
|
||||||
|
/// An alternative call pattern would be to call [Events::update] manually across frames to control when events are cleared. However
|
||||||
|
/// this complicates consumption
|
||||||
|
pub struct Events<T>
|
||||||
where
|
where
|
||||||
T: Send + Sync + 'static,
|
T: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
@ -24,12 +66,12 @@ where
|
|||||||
state: State,
|
state: State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Default for Event<T>
|
impl<T> Default for Events<T>
|
||||||
where
|
where
|
||||||
T: Send + Sync + 'static,
|
T: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Event {
|
Events {
|
||||||
a_start_event_count: 0,
|
a_start_event_count: 0,
|
||||||
b_start_event_count: 0,
|
b_start_event_count: 0,
|
||||||
event_count: 0,
|
event_count: 0,
|
||||||
@ -47,15 +89,16 @@ where
|
|||||||
&event_instance.event
|
&event_instance.event
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventHandle<T> {
|
pub struct EventReader<T> {
|
||||||
last_event_count: usize,
|
last_event_count: usize,
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Event<T>
|
impl<T> Events<T>
|
||||||
where
|
where
|
||||||
T: Send + Sync + 'static,
|
T: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
/// "Sends" an `event` by writing it to the current event buffer. [EventReader]s can then read the event.
|
||||||
pub fn send(&mut self, event: T) {
|
pub fn send(&mut self, event: T) {
|
||||||
let event_instance = EventInstance {
|
let event_instance = EventInstance {
|
||||||
event,
|
event,
|
||||||
@ -70,10 +113,21 @@ where
|
|||||||
self.event_count += 1;
|
self.event_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self, event_handle: &mut EventHandle<T>) -> impl DoubleEndedIterator<Item = &T> {
|
/// Iterates over the events the `event_reader` has not seen yet.
|
||||||
let a_index = self.a_start_event_count - event_handle.last_event_count;
|
pub fn iter(&self, event_reader: &mut EventReader<T>) -> impl DoubleEndedIterator<Item = &T> {
|
||||||
let b_index = self.b_start_event_count - event_handle.last_event_count;
|
// if the reader has seen some of the events in a buffer, find the proper index offset.
|
||||||
event_handle.last_event_count = self.event_count;
|
// otherwise read all events in the buffer
|
||||||
|
let a_index = if event_reader.last_event_count > self.a_start_event_count {
|
||||||
|
event_reader.last_event_count - self.a_start_event_count
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
let b_index = if event_reader.last_event_count > self.b_start_event_count {
|
||||||
|
event_reader.last_event_count - self.b_start_event_count
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
event_reader.last_event_count = self.event_count;
|
||||||
match self.state {
|
match self.state {
|
||||||
State::A => self
|
State::A => self
|
||||||
.events_b
|
.events_b
|
||||||
@ -104,13 +158,23 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_handle(&self) -> EventHandle<T> {
|
/// Gets a new [EventReader]. This will include all events already in the event buffers.
|
||||||
EventHandle {
|
pub fn get_reader(&self) -> EventReader<T> {
|
||||||
|
EventReader {
|
||||||
last_event_count: 0,
|
last_event_count: 0,
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a new [EventReader]. This will ignore all events already in the event buffers. It will read all future events.
|
||||||
|
pub fn get_reader_current(&self) -> EventReader<T> {
|
||||||
|
EventReader {
|
||||||
|
last_event_count: self.event_count,
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swaps the event buffers and clears the oldest event buffer. In general, this should be called once per frame/update.
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
match self.state {
|
match self.state {
|
||||||
State::A => {
|
State::A => {
|
||||||
@ -126,27 +190,136 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_system() -> Box<dyn Schedulable> {
|
/// Builds a system that calls [Events::update] once per frame.
|
||||||
SystemBuilder::new(format!("EventUpdate::{}", std::any::type_name::<T>()))
|
pub fn build_update_system() -> Box<dyn Schedulable> {
|
||||||
|
SystemBuilder::new(format!("events_update::{}", std::any::type_name::<T>()))
|
||||||
.write_resource::<Self>()
|
.write_resource::<Self>()
|
||||||
.build(|_, _, event, _| event.update())
|
.build(|_, _, events, _| events.update())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GetEventHandle {
|
pub trait GetEventReader {
|
||||||
fn get_event_handle<T>(&self) -> EventHandle<T>
|
/// returns an [EventReader] of the given type
|
||||||
|
fn get_event_reader<T>(&self) -> EventReader<T>
|
||||||
where
|
where
|
||||||
T: Send + Sync + 'static;
|
T: Send + Sync + 'static;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetEventHandle for Resources {
|
impl GetEventReader for Resources {
|
||||||
fn get_event_handle<T>(&self) -> EventHandle<T>
|
fn get_event_reader<T>(&self) -> EventReader<T>
|
||||||
where
|
where
|
||||||
T: Send + Sync + 'static,
|
T: Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let my_event = self
|
let my_event = self
|
||||||
.get::<Event<T>>()
|
.get::<Events<T>>()
|
||||||
.unwrap_or_else(|| panic!("Event does not exist: {}", std::any::type_name::<T>()));
|
.unwrap_or_else(|| panic!("Event does not exist: {}", std::any::type_name::<T>()));
|
||||||
my_event.get_handle()
|
my_event.get_reader()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
|
struct TestEvent {
|
||||||
|
i: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_events() {
|
||||||
|
let mut events = Events::<TestEvent>::default();
|
||||||
|
let event_0 = TestEvent { i: 0 };
|
||||||
|
let event_1 = TestEvent { i: 1 };
|
||||||
|
let event_2 = TestEvent { i: 2 };
|
||||||
|
|
||||||
|
// this reader will miss event_0 and event_1 because it wont read them over the course of two updates
|
||||||
|
let mut reader_missed = events.get_reader();
|
||||||
|
|
||||||
|
let mut reader_a = events.get_reader();
|
||||||
|
|
||||||
|
events.send(event_0);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_a),
|
||||||
|
vec![event_0],
|
||||||
|
"reader_a created before event receives event"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_a),
|
||||||
|
vec![],
|
||||||
|
"second iteration of reader_a created before event results in zero events"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut reader_b = events.get_reader();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_b),
|
||||||
|
vec![event_0],
|
||||||
|
"reader_b created after event receives event"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_b),
|
||||||
|
vec![],
|
||||||
|
"second iteration of reader_b created after event results in zero events"
|
||||||
|
);
|
||||||
|
|
||||||
|
events.send(event_1);
|
||||||
|
|
||||||
|
let mut reader_c = events.get_reader();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_c),
|
||||||
|
vec![event_0, event_1],
|
||||||
|
"reader_c created after two events receives both events"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_c),
|
||||||
|
vec![],
|
||||||
|
"second iteration of reader_c created after two event results in zero events"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_a),
|
||||||
|
vec![event_1],
|
||||||
|
"reader_a receives next unread event"
|
||||||
|
);
|
||||||
|
|
||||||
|
events.update();
|
||||||
|
|
||||||
|
let mut reader_d = events.get_reader();
|
||||||
|
|
||||||
|
events.send(event_2);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_a),
|
||||||
|
vec![event_2],
|
||||||
|
"reader_a receives event created after update"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_b),
|
||||||
|
vec![event_1, event_2],
|
||||||
|
"reader_b receives events created before and after update"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_d),
|
||||||
|
vec![event_0, event_1, event_2],
|
||||||
|
"reader_d receives all events created before and after update"
|
||||||
|
);
|
||||||
|
|
||||||
|
events.update();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
get_events(&events, &mut reader_missed),
|
||||||
|
vec![event_2],
|
||||||
|
"reader_missed missed events unread after to update() calls"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_events(
|
||||||
|
events: &Events<TestEvent>,
|
||||||
|
reader: &mut EventReader<TestEvent>,
|
||||||
|
) -> Vec<TestEvent> {
|
||||||
|
events.iter(reader).cloned().collect::<Vec<TestEvent>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,12 +27,12 @@ impl AppPlugin for WinitPlugin {
|
|||||||
pub fn winit_runner(mut app: App) {
|
pub fn winit_runner(mut app: App) {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let event_loop = EventLoop::new();
|
let event_loop = EventLoop::new();
|
||||||
let mut create_window_event_handle = app.resources.get_event_handle::<CreateWindow>();
|
let mut create_window_event_reader = app.resources.get_event_reader::<CreateWindow>();
|
||||||
|
|
||||||
handle_create_window_events(
|
handle_create_window_events(
|
||||||
&mut app.resources,
|
&mut app.resources,
|
||||||
&event_loop,
|
&event_loop,
|
||||||
&mut create_window_event_handle,
|
&mut create_window_event_reader,
|
||||||
);
|
);
|
||||||
|
|
||||||
log::debug!("Entering render loop");
|
log::debug!("Entering render loop");
|
||||||
@ -59,7 +59,7 @@ pub fn winit_runner(mut app: App) {
|
|||||||
window.width = size.width;
|
window.width = size.width;
|
||||||
window.height = size.height;
|
window.height = size.height;
|
||||||
|
|
||||||
let mut resize_event = app.resources.get_mut::<Event<WindowResized>>().unwrap();
|
let mut resize_event = app.resources.get_mut::<Events<WindowResized>>().unwrap();
|
||||||
resize_event.send(WindowResized {
|
resize_event.send(WindowResized {
|
||||||
id: window_id,
|
id: window_id,
|
||||||
height: window.height,
|
height: window.height,
|
||||||
@ -86,7 +86,7 @@ pub fn winit_runner(mut app: App) {
|
|||||||
handle_create_window_events(
|
handle_create_window_events(
|
||||||
&mut app.resources,
|
&mut app.resources,
|
||||||
event_loop,
|
event_loop,
|
||||||
&mut create_window_event_handle,
|
&mut create_window_event_reader,
|
||||||
);
|
);
|
||||||
app.update();
|
app.update();
|
||||||
}
|
}
|
||||||
@ -98,13 +98,13 @@ pub fn winit_runner(mut app: App) {
|
|||||||
fn handle_create_window_events(
|
fn handle_create_window_events(
|
||||||
resources: &mut Resources,
|
resources: &mut Resources,
|
||||||
event_loop: &EventLoopWindowTarget<()>,
|
event_loop: &EventLoopWindowTarget<()>,
|
||||||
create_window_event_handle: &mut EventHandle<CreateWindow>,
|
create_window_event_reader: &mut EventReader<CreateWindow>,
|
||||||
) {
|
) {
|
||||||
let mut winit_windows = resources.get_mut::<WinitWindows>().unwrap();
|
let mut winit_windows = resources.get_mut::<WinitWindows>().unwrap();
|
||||||
let mut windows = resources.get_mut::<Windows>().unwrap();
|
let mut windows = resources.get_mut::<Windows>().unwrap();
|
||||||
let create_window_events = resources.get::<Event<CreateWindow>>().unwrap();
|
let create_window_events = resources.get::<Events<CreateWindow>>().unwrap();
|
||||||
let mut window_created_events = resources.get_mut::<Event<WindowCreated>>().unwrap();
|
let mut window_created_events = resources.get_mut::<Events<WindowCreated>>().unwrap();
|
||||||
for create_window_event in create_window_events.iter(create_window_event_handle) {
|
for create_window_event in create_window_events.iter(create_window_event_reader) {
|
||||||
let window = Window::new(&create_window_event.descriptor);
|
let window = Window::new(&create_window_event.descriptor);
|
||||||
winit_windows.create_window(event_loop, &window);
|
winit_windows.create_window(event_loop, &window);
|
||||||
let window_id = window.id;
|
let window_id = window.id;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
pub use crate::{
|
pub use crate::{
|
||||||
app::{plugin::AppPlugin, App, AppBuilder},
|
app::{plugin::AppPlugin, App, AppBuilder},
|
||||||
asset::{Asset, AssetStorage, Handle},
|
asset::{Asset, AssetStorage, Handle},
|
||||||
core::{Event, EventHandle, GetEventHandle, Time, Window, Windows, WindowDescriptor},
|
core::{Events, EventReader, GetEventReader, Time, Window, Windows, WindowDescriptor},
|
||||||
diagnostic::DiagnosticsPlugin,
|
diagnostic::DiagnosticsPlugin,
|
||||||
ecs,
|
ecs,
|
||||||
ecs::{
|
ecs::{
|
||||||
|
|||||||
@ -34,10 +34,10 @@ impl RenderPlugin {
|
|||||||
.add_draw_target(AssignedMeshesDrawTarget::default())
|
.add_draw_target(AssignedMeshesDrawTarget::default())
|
||||||
.add_draw_target(UiDrawTarget::default())
|
.add_draw_target(UiDrawTarget::default())
|
||||||
.add_resource_provider(CameraResourceProvider::new(
|
.add_resource_provider(CameraResourceProvider::new(
|
||||||
app.resources.get_event_handle::<WindowResized>(),
|
app.resources.get_event_reader::<WindowResized>(),
|
||||||
))
|
))
|
||||||
.add_resource_provider(Camera2dResourceProvider::new(
|
.add_resource_provider(Camera2dResourceProvider::new(
|
||||||
app.resources.get_event_handle::<WindowResized>(),
|
app.resources.get_event_reader::<WindowResized>(),
|
||||||
))
|
))
|
||||||
.add_resource_provider(LightResourceProvider::new(10))
|
.add_resource_provider(LightResourceProvider::new(10))
|
||||||
.add_resource_provider(UiResourceProvider::new())
|
.add_resource_provider(UiResourceProvider::new())
|
||||||
|
|||||||
@ -13,15 +13,15 @@ use zerocopy::AsBytes;
|
|||||||
pub struct Camera2dResourceProvider {
|
pub struct Camera2dResourceProvider {
|
||||||
pub camera_buffer: Option<RenderResource>,
|
pub camera_buffer: Option<RenderResource>,
|
||||||
pub tmp_buffer: Option<RenderResource>,
|
pub tmp_buffer: Option<RenderResource>,
|
||||||
pub window_resized_event_handle: EventHandle<WindowResized>,
|
pub window_resized_event_reader: EventReader<WindowResized>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Camera2dResourceProvider {
|
impl Camera2dResourceProvider {
|
||||||
pub fn new(window_resized_event_handle: EventHandle<WindowResized>) -> Self {
|
pub fn new(window_resized_event_reader: EventReader<WindowResized>) -> Self {
|
||||||
Camera2dResourceProvider {
|
Camera2dResourceProvider {
|
||||||
camera_buffer: None,
|
camera_buffer: None,
|
||||||
tmp_buffer: None,
|
tmp_buffer: None,
|
||||||
window_resized_event_handle,
|
window_resized_event_reader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,9 +46,9 @@ impl ResourceProvider for Camera2dResourceProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
|
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
|
||||||
let window_resized_events = resources.get::<Event<WindowResized>>().unwrap();
|
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
|
||||||
let primary_window_resized_event = window_resized_events
|
let primary_window_resized_event = window_resized_events
|
||||||
.iter(&mut self.window_resized_event_handle)
|
.iter(&mut self.window_resized_event_reader)
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|event| event.is_primary)
|
.filter(|event| event.is_primary)
|
||||||
.next();
|
.next();
|
||||||
|
|||||||
@ -15,15 +15,15 @@ use zerocopy::AsBytes;
|
|||||||
pub struct CameraResourceProvider {
|
pub struct CameraResourceProvider {
|
||||||
pub camera_buffer: Option<RenderResource>,
|
pub camera_buffer: Option<RenderResource>,
|
||||||
pub tmp_buffer: Option<RenderResource>,
|
pub tmp_buffer: Option<RenderResource>,
|
||||||
pub window_resized_event_handle: EventHandle<WindowResized>,
|
pub window_resized_event_reader: EventReader<WindowResized>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CameraResourceProvider {
|
impl CameraResourceProvider {
|
||||||
pub fn new(window_resized_event_handle: EventHandle<WindowResized>) -> Self {
|
pub fn new(window_resized_event_reader: EventReader<WindowResized>) -> Self {
|
||||||
CameraResourceProvider {
|
CameraResourceProvider {
|
||||||
camera_buffer: None,
|
camera_buffer: None,
|
||||||
tmp_buffer: None,
|
tmp_buffer: None,
|
||||||
window_resized_event_handle,
|
window_resized_event_reader,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,9 +48,9 @@ impl ResourceProvider for CameraResourceProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
|
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
|
||||||
let window_resized_events = resources.get::<Event<WindowResized>>().unwrap();
|
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
|
||||||
let primary_window_resized_event = window_resized_events
|
let primary_window_resized_event = window_resized_events
|
||||||
.iter(&mut self.window_resized_event_handle)
|
.iter(&mut self.window_resized_event_reader)
|
||||||
.rev()
|
.rev()
|
||||||
.filter(|event| event.is_primary)
|
.filter(|event| event.is_primary)
|
||||||
.next();
|
.next();
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
use crate as bevy;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ecs,
|
ecs,
|
||||||
prelude::Node,
|
prelude::Node,
|
||||||
@ -19,6 +18,7 @@ use zerocopy::{AsBytes, FromBytes};
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug, AsBytes, FromBytes, Uniforms)]
|
#[derive(Clone, Copy, Debug, AsBytes, FromBytes, Uniforms)]
|
||||||
|
#[uniform(bevy_path="crate")]
|
||||||
pub struct Rect {
|
pub struct Rect {
|
||||||
#[uniform(instance)]
|
#[uniform(instance)]
|
||||||
pub position: [f32; 2],
|
pub position: [f32; 2],
|
||||||
|
|||||||
@ -9,7 +9,7 @@ pub use wgpu_resources::*;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{plugin::AppPlugin, system_stage, AppBuilder},
|
app::{plugin::AppPlugin, system_stage, AppBuilder},
|
||||||
core::{Event, WindowCreated, WindowResized},
|
core::{Events, WindowCreated, WindowResized},
|
||||||
render::renderer::Renderer,
|
render::renderer::Renderer,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -29,11 +29,11 @@ impl AppPlugin for WgpuRendererPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn wgpu_render_system(resources: &Resources) -> impl FnMut(&mut World, &mut Resources) {
|
pub fn wgpu_render_system(resources: &Resources) -> impl FnMut(&mut World, &mut Resources) {
|
||||||
let window_resized_event = resources.get::<Event<WindowResized>>().unwrap();
|
let window_resized_event = resources.get::<Events<WindowResized>>().unwrap();
|
||||||
let window_created_event = resources.get::<Event<WindowCreated>>().unwrap();
|
let window_created_event = resources.get::<Events<WindowCreated>>().unwrap();
|
||||||
let mut wgpu_renderer = futures::executor::block_on(WgpuRenderer::new(
|
let mut wgpu_renderer = futures::executor::block_on(WgpuRenderer::new(
|
||||||
window_resized_event.get_handle(),
|
window_resized_event.get_reader(),
|
||||||
window_created_event.get_handle(),
|
window_created_event.get_reader(),
|
||||||
));
|
));
|
||||||
move |world, resources| {
|
move |world, resources| {
|
||||||
wgpu_renderer.update(world, resources);
|
wgpu_renderer.update(world, resources);
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use super::{wgpu_type_converter::OwnedWgpuVertexBufferDescriptor, WgpuRenderPass
|
|||||||
use crate::{
|
use crate::{
|
||||||
asset::{AssetStorage, Handle},
|
asset::{AssetStorage, Handle},
|
||||||
core::{
|
core::{
|
||||||
winit::WinitWindows, Event, EventHandle, Window, WindowCreated, WindowResized, Windows,
|
winit::WinitWindows, Events, EventReader, Window, WindowCreated, WindowResized, Windows,
|
||||||
},
|
},
|
||||||
legion::prelude::*,
|
legion::prelude::*,
|
||||||
render::{
|
render::{
|
||||||
@ -34,15 +34,15 @@ pub struct WgpuRenderer {
|
|||||||
pub encoder: Option<wgpu::CommandEncoder>,
|
pub encoder: Option<wgpu::CommandEncoder>,
|
||||||
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||||
pub wgpu_resources: WgpuResources,
|
pub wgpu_resources: WgpuResources,
|
||||||
pub window_resized_event_handle: EventHandle<WindowResized>,
|
pub window_resized_event_reader: EventReader<WindowResized>,
|
||||||
pub window_created_event_handle: EventHandle<WindowCreated>,
|
pub window_created_event_reader: EventReader<WindowCreated>,
|
||||||
pub intialized: bool,
|
pub intialized: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WgpuRenderer {
|
impl WgpuRenderer {
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
window_resized_event_handle: EventHandle<WindowResized>,
|
window_resized_event_reader: EventReader<WindowResized>,
|
||||||
window_created_event_handle: EventHandle<WindowCreated>,
|
window_created_event_reader: EventReader<WindowCreated>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let adapter = wgpu::Adapter::request(
|
let adapter = wgpu::Adapter::request(
|
||||||
&wgpu::RequestAdapterOptions {
|
&wgpu::RequestAdapterOptions {
|
||||||
@ -66,8 +66,8 @@ impl WgpuRenderer {
|
|||||||
device: Rc::new(RefCell::new(device)),
|
device: Rc::new(RefCell::new(device)),
|
||||||
queue,
|
queue,
|
||||||
encoder: None,
|
encoder: None,
|
||||||
window_resized_event_handle,
|
window_resized_event_reader,
|
||||||
window_created_event_handle,
|
window_created_event_reader,
|
||||||
intialized: false,
|
intialized: false,
|
||||||
wgpu_resources: WgpuResources::default(),
|
wgpu_resources: WgpuResources::default(),
|
||||||
render_pipelines: HashMap::new(),
|
render_pipelines: HashMap::new(),
|
||||||
@ -381,12 +381,12 @@ impl WgpuRenderer {
|
|||||||
|
|
||||||
pub fn handle_window_resized_events(&mut self, resources: &mut Resources) {
|
pub fn handle_window_resized_events(&mut self, resources: &mut Resources) {
|
||||||
let windows = resources.get::<Windows>().unwrap();
|
let windows = resources.get::<Windows>().unwrap();
|
||||||
let window_resized_events = resources.get::<Event<WindowResized>>().unwrap();
|
let window_resized_events = resources.get::<Events<WindowResized>>().unwrap();
|
||||||
let mut handled_windows = HashSet::new();
|
let mut handled_windows = HashSet::new();
|
||||||
// iterate in reverse order so we can handle the latest window resize event first for each window.
|
// iterate in reverse order so we can handle the latest window resize event first for each window.
|
||||||
// we skip earlier events for the same window because it results in redundant work
|
// we skip earlier events for the same window because it results in redundant work
|
||||||
for window_resized_event in window_resized_events
|
for window_resized_event in window_resized_events
|
||||||
.iter(&mut self.window_resized_event_handle)
|
.iter(&mut self.window_resized_event_reader)
|
||||||
.rev()
|
.rev()
|
||||||
{
|
{
|
||||||
if handled_windows.contains(&window_resized_event.id) {
|
if handled_windows.contains(&window_resized_event.id) {
|
||||||
@ -406,9 +406,9 @@ impl WgpuRenderer {
|
|||||||
pub fn handle_window_created_events(&mut self, resources: &mut Resources) {
|
pub fn handle_window_created_events(&mut self, resources: &mut Resources) {
|
||||||
let windows = resources.get::<Windows>().unwrap();
|
let windows = resources.get::<Windows>().unwrap();
|
||||||
let winit_windows = resources.get::<WinitWindows>().unwrap();
|
let winit_windows = resources.get::<WinitWindows>().unwrap();
|
||||||
let window_created_events = resources.get::<Event<WindowCreated>>().unwrap();
|
let window_created_events = resources.get::<Events<WindowCreated>>().unwrap();
|
||||||
for window_created_event in
|
for window_created_event in
|
||||||
window_created_events.iter(&mut self.window_created_event_handle)
|
window_created_events.iter(&mut self.window_created_event_reader)
|
||||||
{
|
{
|
||||||
let window = windows
|
let window = windows
|
||||||
.get(window_created_event.id)
|
.get(window_created_event.id)
|
||||||
|
|||||||
@ -3,10 +3,10 @@ use crate::{
|
|||||||
render::{texture::Texture, Color},
|
render::{texture::Texture, Color},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate as bevy; // for macro imports
|
|
||||||
use bevy_derive::Uniforms;
|
use bevy_derive::Uniforms;
|
||||||
|
|
||||||
#[derive(Uniforms)]
|
#[derive(Uniforms)]
|
||||||
|
#[uniform(bevy_path="crate")]
|
||||||
pub struct StandardMaterial {
|
pub struct StandardMaterial {
|
||||||
#[uniform(instance)]
|
#[uniform(instance)]
|
||||||
pub albedo: Color,
|
pub albedo: Color,
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use zerocopy::{AsBytes, FromBytes};
|
use zerocopy::{AsBytes, FromBytes};
|
||||||
|
|
||||||
use crate as bevy;
|
|
||||||
use bevy_derive::Uniforms;
|
use bevy_derive::Uniforms;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, AsBytes, FromBytes, Uniforms)]
|
#[derive(Clone, Copy, AsBytes, FromBytes, Uniforms)]
|
||||||
|
#[uniform(bevy_path="crate")]
|
||||||
pub struct Vertex {
|
pub struct Vertex {
|
||||||
#[uniform(vertex)]
|
#[uniform(vertex)]
|
||||||
pub position: [f32; 4],
|
pub position: [f32; 4],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user