mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
Add Events. add WindowResize event to WgpuRenderer. remove Renderer from App
This commit is contained in:
parent
4435d536e8
commit
5eb789ff77
12 changed files with 248 additions and 37 deletions
|
@ -1,4 +1,4 @@
|
|||
use crate::{app::AppBuilder, core::Time, render::renderer::Renderer};
|
||||
use crate::{app::AppBuilder, core::Time};
|
||||
use legion::prelude::*;
|
||||
|
||||
pub struct App {
|
||||
|
@ -6,7 +6,6 @@ pub struct App {
|
|||
pub world: World,
|
||||
pub resources: Resources,
|
||||
pub run: Option<Box<dyn Fn(App)>>,
|
||||
pub renderer: Option<Box<dyn Renderer>>,
|
||||
pub schedule: Schedule,
|
||||
}
|
||||
|
||||
|
@ -17,13 +16,11 @@ impl App {
|
|||
resources: Resources,
|
||||
schedule: Schedule,
|
||||
run: Option<Box<dyn Fn(App)>>,
|
||||
renderer: Option<Box<dyn Renderer>>,
|
||||
) -> App {
|
||||
App {
|
||||
universe,
|
||||
world,
|
||||
schedule,
|
||||
renderer,
|
||||
run,
|
||||
resources,
|
||||
}
|
||||
|
@ -39,10 +36,6 @@ impl App {
|
|||
}
|
||||
self.schedule.execute(&mut self.world, &mut self.resources);
|
||||
|
||||
if let Some(ref mut renderer) = self.renderer {
|
||||
renderer.update(&mut self.world, &mut self.resources);
|
||||
}
|
||||
|
||||
if let Some(mut time) = self.resources.get_mut::<Time>() {
|
||||
time.stop();
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ use crate::{
|
|||
plugin::{load_plugin, AppPlugin},
|
||||
system_stage, App,
|
||||
},
|
||||
core::{winit::WinitPlugin, CorePlugin},
|
||||
core::{winit::WinitPlugin, CorePlugin, Event},
|
||||
legion::prelude::{Resources, Runnable, Schedulable, Schedule, Universe, World},
|
||||
render::{
|
||||
renderer::{renderers::wgpu_renderer::WgpuRendererPlugin, Renderer},
|
||||
renderer::{renderers::wgpu_renderer::WgpuRendererPlugin},
|
||||
RenderPlugin,
|
||||
},
|
||||
ui::UiPlugin,
|
||||
|
@ -18,12 +18,13 @@ pub struct AppBuilder {
|
|||
pub world: World,
|
||||
pub resources: Resources,
|
||||
pub universe: Universe,
|
||||
pub renderer: Option<Box<dyn Renderer>>,
|
||||
pub run: Option<Box<dyn Fn(App)>>,
|
||||
pub schedule: Option<Schedule>,
|
||||
pub setup_systems: Vec<Box<dyn Schedulable>>,
|
||||
// TODO: these separate lists will produce incorrect ordering
|
||||
pub system_stages: HashMap<String, Vec<Box<dyn Schedulable>>>,
|
||||
pub runnable_stages: HashMap<String, Vec<Box<dyn Runnable>>>,
|
||||
pub thread_local_stages: HashMap<String, Vec<Box<dyn FnMut(&mut World, &mut Resources)>>>,
|
||||
pub stage_order: Vec<String>,
|
||||
}
|
||||
|
||||
|
@ -36,12 +37,12 @@ impl AppBuilder {
|
|||
universe,
|
||||
world,
|
||||
resources,
|
||||
renderer: None,
|
||||
run: None,
|
||||
schedule: None,
|
||||
setup_systems: Vec::new(),
|
||||
system_stages: HashMap::new(),
|
||||
runnable_stages: HashMap::new(),
|
||||
thread_local_stages: HashMap::new(),
|
||||
stage_order: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +73,16 @@ impl AppBuilder {
|
|||
|
||||
schedule_builder = schedule_builder.flush();
|
||||
}
|
||||
|
||||
if let Some((_name, stage_thread_locals)) =
|
||||
self.thread_local_stages.remove_entry(stage_name)
|
||||
{
|
||||
for system in stage_thread_locals {
|
||||
schedule_builder = schedule_builder.add_thread_local_fn(system);
|
||||
}
|
||||
|
||||
schedule_builder = schedule_builder.flush();
|
||||
}
|
||||
}
|
||||
|
||||
self.schedule = Some(schedule_builder.build());
|
||||
|
@ -88,7 +99,6 @@ impl AppBuilder {
|
|||
self.resources,
|
||||
self.schedule.take().unwrap(),
|
||||
self.run.take(),
|
||||
self.renderer.take(),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -141,6 +151,28 @@ impl AppBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn add_thread_local_to_stage(
|
||||
mut self,
|
||||
stage_name: &str,
|
||||
f: impl FnMut(&mut World, &mut Resources) + 'static,
|
||||
) -> Self {
|
||||
if let None = self.thread_local_stages.get(stage_name) {
|
||||
self.thread_local_stages
|
||||
.insert(stage_name.to_string(), Vec::new());
|
||||
// TODO: this is so broken
|
||||
self.stage_order.push(stage_name.to_string());
|
||||
}
|
||||
|
||||
let thread_local_stages = self.thread_local_stages.get_mut(stage_name).unwrap();
|
||||
thread_local_stages.push(Box::new(f));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_event<T>(self) -> Self where T: Send + Sync + 'static {
|
||||
self.add_resource(Event::<T>::default())
|
||||
.add_system_to_stage(system_stage::EVENT_UPDATE, Event::<T>::update_system())
|
||||
}
|
||||
|
||||
pub fn add_resource<T>(mut self, resource: T) -> Self
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
pub const FIRST: &str = "first";
|
||||
pub const EVENT_UPDATE: &str = "event_update";
|
||||
pub const UPDATE: &str = "update";
|
||||
pub const RENDER: &str = "render";
|
||||
pub const LAST: &str = "last";
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use super::{Time, Window};
|
||||
use super::{Time, Window, WindowResize};
|
||||
use crate::{app::{AppBuilder, plugin::AppPlugin}};
|
||||
use bevy_transform::transform_system_bundle;
|
||||
|
||||
|
@ -11,7 +11,8 @@ impl AppPlugin for CorePlugin {
|
|||
app = app.add_system(transform_system);
|
||||
}
|
||||
|
||||
app.add_resource(Window::default())
|
||||
app.add_event::<WindowResize>()
|
||||
.add_resource(Window::default())
|
||||
.add_resource(Time::new())
|
||||
}
|
||||
|
||||
|
|
133
src/core/event.rs
Normal file
133
src/core/event.rs
Normal file
|
@ -0,0 +1,133 @@
|
|||
use legion::prelude::{Schedulable, SystemBuilder};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct EventInstance<T> {
|
||||
pub event_count: usize,
|
||||
pub event: T,
|
||||
}
|
||||
|
||||
enum State {
|
||||
A,
|
||||
B,
|
||||
}
|
||||
|
||||
pub struct Event<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
events_a: Vec<EventInstance<T>>,
|
||||
events_b: Vec<EventInstance<T>>,
|
||||
a_start_event_count: usize,
|
||||
b_start_event_count: usize,
|
||||
event_count: usize,
|
||||
state: State,
|
||||
}
|
||||
|
||||
impl<T> Default for Event<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Event {
|
||||
a_start_event_count: 0,
|
||||
b_start_event_count: 0,
|
||||
event_count: 0,
|
||||
events_a: Vec::new(),
|
||||
events_b: Vec::new(),
|
||||
state: State::A,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn map_event_instance<T>(event_instance: &EventInstance<T>) -> &T
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
&event_instance.event
|
||||
}
|
||||
|
||||
pub struct EventHandle<T> {
|
||||
last_event_count: usize,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Event<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
pub fn raise(&mut self, event: T) {
|
||||
let event_instance = EventInstance {
|
||||
event,
|
||||
event_count: self.event_count,
|
||||
};
|
||||
|
||||
match self.state {
|
||||
State::A => self.events_a.push(event_instance),
|
||||
State::B => self.events_b.push(event_instance),
|
||||
}
|
||||
|
||||
self.event_count += 1;
|
||||
}
|
||||
|
||||
pub fn iter(&self, event_handle: &mut EventHandle<T>) -> impl Iterator<Item = &T> {
|
||||
let a_index = self.a_start_event_count - event_handle.last_event_count;
|
||||
let b_index = self.b_start_event_count - event_handle.last_event_count;
|
||||
event_handle.last_event_count = self.event_count;
|
||||
match self.state {
|
||||
State::A => self
|
||||
.events_b
|
||||
.get(b_index..)
|
||||
.unwrap_or_else(|| &[])
|
||||
.iter()
|
||||
.map(map_event_instance)
|
||||
.chain(
|
||||
self.events_a
|
||||
.get(a_index..)
|
||||
.unwrap_or_else(|| &[])
|
||||
.iter()
|
||||
.map(map_event_instance),
|
||||
),
|
||||
State::B => self
|
||||
.events_a
|
||||
.get(a_index..)
|
||||
.unwrap_or_else(|| &[])
|
||||
.iter()
|
||||
.map(map_event_instance)
|
||||
.chain(
|
||||
self.events_b
|
||||
.get(b_index..)
|
||||
.unwrap_or_else(|| &[])
|
||||
.iter()
|
||||
.map(map_event_instance),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_handle(&self) -> EventHandle<T> {
|
||||
EventHandle {
|
||||
last_event_count: self.event_count,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
match self.state {
|
||||
State::A => {
|
||||
self.events_b = Vec::new();
|
||||
self.state = State::B;
|
||||
self.b_start_event_count = self.event_count;
|
||||
}
|
||||
State::B => {
|
||||
self.events_a = Vec::new();
|
||||
self.state = State::A;
|
||||
self.a_start_event_count = self.event_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_system() -> Box<dyn Schedulable> {
|
||||
SystemBuilder::new(format!("EventUpdate::{}", std::any::type_name::<T>()))
|
||||
.write_resource::<Self>()
|
||||
.build(|_, _, event, _| event.update())
|
||||
}
|
||||
}
|
|
@ -2,8 +2,10 @@ pub mod bytes;
|
|||
mod time;
|
||||
pub mod window;
|
||||
mod core_plugin;
|
||||
pub mod event;
|
||||
|
||||
pub use bytes::*;
|
||||
pub use time::*;
|
||||
pub use window::*;
|
||||
pub use core_plugin::*;
|
||||
pub use core_plugin::*;
|
||||
pub use event::*;
|
|
@ -13,6 +13,13 @@ pub struct Window {
|
|||
pub vsync: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WindowResize {
|
||||
pub id: Uuid,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl Default for Window {
|
||||
fn default() -> Self {
|
||||
Window {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use crate::{
|
||||
app::{App, AppBuilder}, app::plugin::AppPlugin,
|
||||
};
|
||||
use crate::{core::Event, app::{plugin::AppPlugin, App, AppBuilder}};
|
||||
|
||||
use super::Window;
|
||||
use super::{Window, WindowResize};
|
||||
use winit::{
|
||||
event,
|
||||
event::WindowEvent,
|
||||
|
@ -52,15 +50,16 @@ pub fn get_winit_run() -> Box<dyn Fn(App) + Send + Sync> {
|
|||
event: WindowEvent::Resized(size),
|
||||
..
|
||||
} => {
|
||||
if let Some(ref mut renderer) = app.renderer {
|
||||
{
|
||||
let mut window = app.resources.get_mut::<Window>().unwrap();
|
||||
window.width = size.width;
|
||||
window.height = size.height;
|
||||
}
|
||||
let mut window = app.resources.get_mut::<Window>().unwrap();
|
||||
window.width = size.width;
|
||||
window.height = size.height;
|
||||
|
||||
renderer.resize(&mut app.world, &mut app.resources);
|
||||
}
|
||||
let mut resize_event = app.resources.get_mut::<Event<WindowResize>>().unwrap();
|
||||
resize_event.raise(WindowResize {
|
||||
id: window.id,
|
||||
height: window.height,
|
||||
width: window.width,
|
||||
});
|
||||
}
|
||||
event::Event::WindowEvent { event, .. } => match event {
|
||||
WindowEvent::KeyboardInput {
|
||||
|
|
|
@ -24,6 +24,7 @@ pub use bevy_transform::prelude::*;
|
|||
pub use glam as math;
|
||||
pub use legion::{
|
||||
prelude::*,
|
||||
prelude::Event as LegionEvent,
|
||||
systems::{
|
||||
schedule::{Builder, Schedulable},
|
||||
SubWorld, SystemBuilder,
|
||||
|
|
|
@ -7,17 +7,31 @@ pub use wgpu_render_pass::*;
|
|||
pub use wgpu_renderer::*;
|
||||
pub use wgpu_resources::*;
|
||||
|
||||
use crate::{app::AppBuilder, app::plugin::AppPlugin};
|
||||
use crate::{
|
||||
app::{plugin::AppPlugin, AppBuilder, system_stage},
|
||||
core::{Event, WindowResize},
|
||||
render::renderer::Renderer,
|
||||
};
|
||||
|
||||
use legion::prelude::*;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WgpuRendererPlugin;
|
||||
|
||||
impl AppPlugin for WgpuRendererPlugin {
|
||||
fn build(&self, mut app: AppBuilder) -> AppBuilder {
|
||||
app.renderer = Some(Box::new(WgpuRenderer::new()));
|
||||
app
|
||||
fn build(&self, app: AppBuilder) -> AppBuilder {
|
||||
let render_system = wgpu_render_system(&app.resources);
|
||||
app.add_thread_local_to_stage(system_stage::RENDER, render_system)
|
||||
}
|
||||
fn name(&self) -> &'static str {
|
||||
"WgpuRenderer"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wgpu_render_system(resources: &Resources) -> impl FnMut(&mut World, &mut Resources) {
|
||||
let window_resize_event = resources.get::<Event<WindowResize>>().unwrap();
|
||||
let mut wgpu_renderer = WgpuRenderer::new(window_resize_event.get_handle());
|
||||
move |world, resources| {
|
||||
wgpu_renderer.update(world, resources);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use super::{wgpu_type_converter::OwnedWgpuVertexBufferDescriptor, WgpuRenderPass, WgpuResources};
|
||||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
core::Window,
|
||||
core::{Event, EventHandle, Window, WindowResize},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
pass::{
|
||||
|
@ -28,11 +28,12 @@ pub struct WgpuRenderer {
|
|||
pub encoder: Option<wgpu::CommandEncoder>,
|
||||
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||
pub wgpu_resources: WgpuResources,
|
||||
pub window_resize_handle: EventHandle<WindowResize>,
|
||||
pub intialized: bool,
|
||||
}
|
||||
|
||||
impl WgpuRenderer {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(window_resize_event: EventHandle<WindowResize>) -> Self {
|
||||
let adapter = wgpu::Adapter::request(
|
||||
&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::Default,
|
||||
|
@ -53,6 +54,7 @@ impl WgpuRenderer {
|
|||
queue,
|
||||
surface: None,
|
||||
encoder: None,
|
||||
window_resize_handle: window_resize_event,
|
||||
intialized: false,
|
||||
wgpu_resources: WgpuResources::default(),
|
||||
render_pipelines: HashMap::new(),
|
||||
|
@ -366,7 +368,13 @@ impl Renderer for WgpuRenderer {
|
|||
resources.insert(swap_chain);
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
for resource_provider in render_graph.resource_providers.iter_mut() {
|
||||
resource_provider.resize(self, world, resources, swap_chain_descriptor.width, swap_chain_descriptor.height);
|
||||
resource_provider.resize(
|
||||
self,
|
||||
world,
|
||||
resources,
|
||||
swap_chain_descriptor.width,
|
||||
swap_chain_descriptor.height,
|
||||
);
|
||||
}
|
||||
|
||||
// consume current encoder
|
||||
|
@ -380,6 +388,19 @@ impl Renderer for WgpuRenderer {
|
|||
|
||||
fn update(&mut self, world: &mut World, resources: &mut Resources) {
|
||||
self.initialize(world, resources);
|
||||
|
||||
let resized =
|
||||
resources
|
||||
.get::<Event<WindowResize>>()
|
||||
.unwrap()
|
||||
.iter(&mut self.window_resize_handle)
|
||||
.last()
|
||||
.map(|_| ())
|
||||
.is_some();
|
||||
|
||||
if resized {
|
||||
self.resize(world, resources);
|
||||
}
|
||||
// TODO: this self.encoder handoff is a bit gross, but its here to give resource providers access to buffer copies without
|
||||
// exposing the wgpu renderer internals to ResourceProvider traits. if this can be made cleaner that would be pretty cool.
|
||||
self.encoder = Some(
|
||||
|
@ -616,7 +637,11 @@ impl Renderer for WgpuRenderer {
|
|||
render_resource_assignments,
|
||||
);
|
||||
} else {
|
||||
log::trace!("reusing RenderResourceSet {:?} for bind group {}", render_resource_set_id, bind_group.index);
|
||||
log::trace!(
|
||||
"reusing RenderResourceSet {:?} for bind group {}",
|
||||
render_resource_set_id,
|
||||
bind_group.index
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
pub fn ui_update_system() -> Box<dyn Schedulable> {
|
||||
SystemBuilder::new("ui_update_system")
|
||||
SystemBuilder::new("ui_update")
|
||||
.read_resource::<Window>()
|
||||
.with_query(<(Write<Node>,)>::query().filter(!component::<Parent>()))
|
||||
.write_component::<Node>()
|
||||
|
|
Loading…
Add table
Reference in a new issue