mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
add more doc comments and clean up some public exports
This commit is contained in:
parent
f963cd41dc
commit
3d09459813
74 changed files with 360 additions and 163 deletions
|
@ -1,6 +1,26 @@
|
|||
use crate::app_builder::AppBuilder;
|
||||
use bevy_ecs::{ParallelExecutor, Resources, Schedule, World};
|
||||
|
||||
/// Containers of app logic and data
|
||||
///
|
||||
/// App store the ECS World, Resources, Schedule, and Executor. They also store the "run" function of the App, which
|
||||
/// by default executes the App schedule once. Apps are constructed using the builder pattern.
|
||||
///
|
||||
/// ## Example
|
||||
/// Here is a simple "Hello World" Bevy app:
|
||||
/// ```
|
||||
///use bevy::prelude::*;
|
||||
///
|
||||
///fn main() {
|
||||
/// App::build()
|
||||
/// .add_system(hello_world_system.system())
|
||||
/// .run();
|
||||
///}
|
||||
///
|
||||
///fn hello_world_system() {
|
||||
/// println!("hello world");
|
||||
///}
|
||||
/// ```
|
||||
pub struct App {
|
||||
pub world: World,
|
||||
pub resources: Resources,
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
use crate::{
|
||||
app::{App, AppExit},
|
||||
event::Events,
|
||||
plugin::{load_plugin, Plugin},
|
||||
plugin::{dynamically_load_plugin, Plugin},
|
||||
stage, startup_stage,
|
||||
};
|
||||
use bevy_ecs::{FromResources, IntoQuerySystem, Resources, System, World};
|
||||
|
||||
/// Configure [App]s using the builder pattern
|
||||
pub struct AppBuilder {
|
||||
pub app: App,
|
||||
}
|
||||
|
@ -220,7 +221,7 @@ impl AppBuilder {
|
|||
}
|
||||
|
||||
pub fn load_plugin(&mut self, path: &str) -> &mut Self {
|
||||
let (_lib, plugin) = load_plugin(path);
|
||||
let (_lib, plugin) = dynamically_load_plugin(path);
|
||||
log::debug!("loaded plugin: {}", plugin.name());
|
||||
plugin.build(self);
|
||||
self
|
||||
|
|
|
@ -82,6 +82,7 @@ fn map_instance_event<T>(event_instance: &EventInstance<T>) -> &T {
|
|||
&event_instance.event
|
||||
}
|
||||
|
||||
/// Reads events of type `T` in order and tracks which events have already been read.
|
||||
pub struct EventReader<T> {
|
||||
last_event_count: usize,
|
||||
_marker: PhantomData<T>,
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/// The names of the default App stages
|
||||
pub mod stage;
|
||||
/// The names of the default App startup stages
|
||||
pub mod startup_stage;
|
||||
|
||||
mod app;
|
||||
mod app_builder;
|
||||
mod event;
|
||||
mod plugin;
|
||||
mod schedule_runner;
|
||||
mod startup_stage;
|
||||
|
||||
pub use app::*;
|
||||
pub use app_builder::*;
|
||||
|
@ -13,7 +15,6 @@ pub use bevy_derive::DynamicPlugin;
|
|||
pub use event::*;
|
||||
pub use plugin::*;
|
||||
pub use schedule_runner::*;
|
||||
pub use startup_stage::*;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{
|
||||
|
|
|
@ -2,6 +2,9 @@ use crate::AppBuilder;
|
|||
use libloading::{Library, Symbol};
|
||||
use std::any::Any;
|
||||
|
||||
/// A collection of Bevy App logic and configuration
|
||||
///
|
||||
/// Plugins use [AppBuilder] to configure an [App](crate::App). When an [App](crate::App) registers a plugin, the plugin's [Plugin::build] function is run.
|
||||
pub trait Plugin: Any + Send + Sync {
|
||||
fn build(&self, app: &mut AppBuilder);
|
||||
fn name(&self) -> &str {
|
||||
|
@ -11,7 +14,8 @@ pub trait Plugin: Any + Send + Sync {
|
|||
|
||||
pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin;
|
||||
|
||||
pub fn load_plugin(path: &str) -> (Library, Box<dyn Plugin>) {
|
||||
/// Dynamically links a plugin a the given path. The plugin must export the [CreatePlugin] function.
|
||||
pub fn dynamically_load_plugin(path: &str) -> (Library, Box<dyn Plugin>) {
|
||||
let lib = Library::new(path).unwrap();
|
||||
|
||||
unsafe {
|
||||
|
|
|
@ -6,6 +6,7 @@ use crate::{
|
|||
};
|
||||
use std::{thread, time::Duration};
|
||||
|
||||
/// Determines the method used to run an [App]'s `Schedule`
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RunMode {
|
||||
Loop { wait: Option<Duration> },
|
||||
|
@ -18,6 +19,7 @@ impl Default for RunMode {
|
|||
}
|
||||
}
|
||||
|
||||
/// Configures an App to run its [Schedule](bevy_ecs::Schedule) according to a given [RunMode]
|
||||
#[derive(Default)]
|
||||
pub struct ScheduleRunnerPlugin {
|
||||
pub run_mode: RunMode,
|
||||
|
|
|
@ -14,7 +14,10 @@ use std::{
|
|||
};
|
||||
use thiserror::Error;
|
||||
|
||||
/// The type used for asset versioning
|
||||
pub type AssetVersion = usize;
|
||||
|
||||
/// Errors that occur while loading assets with an AssetServer
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AssetServerError {
|
||||
#[error("Asset folder path is not a directory.")]
|
||||
|
@ -39,13 +42,15 @@ struct LoaderThread {
|
|||
requests: Arc<RwLock<Vec<LoadRequest>>>,
|
||||
}
|
||||
|
||||
/// Info about a specific asset, such as its path and its current load state
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AssetInfo {
|
||||
handle_id: HandleId,
|
||||
path: PathBuf,
|
||||
load_state: LoadState,
|
||||
pub handle_id: HandleId,
|
||||
pub path: PathBuf,
|
||||
pub load_state: LoadState,
|
||||
}
|
||||
|
||||
/// The load state of an asset
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum LoadState {
|
||||
Loading(AssetVersion),
|
||||
|
@ -63,6 +68,7 @@ impl LoadState {
|
|||
}
|
||||
}
|
||||
|
||||
/// Loads assets from the filesystem on background threads
|
||||
pub struct AssetServer {
|
||||
asset_folders: RwLock<Vec<PathBuf>>,
|
||||
loader_threads: RwLock<Vec<LoaderThread>>,
|
||||
|
|
|
@ -7,12 +7,14 @@ use bevy_ecs::{FromResources, IntoQuerySystem, ResMut, Resource};
|
|||
use bevy_type_registry::RegisterType;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Events that happen on assets of type `T`
|
||||
pub enum AssetEvent<T: Resource> {
|
||||
Created { handle: Handle<T> },
|
||||
Modified { handle: Handle<T> },
|
||||
Removed { handle: Handle<T> },
|
||||
}
|
||||
|
||||
/// Stores Assets of a given type and tracks changes to them.
|
||||
pub struct Assets<T: Resource> {
|
||||
assets: HashMap<Handle<T>, T>,
|
||||
events: Events<AssetEvent<T>>,
|
||||
|
@ -108,6 +110,7 @@ impl<T: Resource> Assets<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// [AppBuilder] extension methods for adding new asset types
|
||||
pub trait AddAsset {
|
||||
fn add_asset<T>(&mut self) -> &mut Self
|
||||
where
|
||||
|
|
|
@ -2,7 +2,7 @@ use crossbeam_channel::Receiver;
|
|||
use notify::{Event, RecommendedWatcher, RecursiveMode, Result, Watcher};
|
||||
use std::path::Path;
|
||||
|
||||
/// Watches for changes to assets on the filesystem and informs the `AssetServer` to reload them
|
||||
/// Watches for changes to assets on the filesystem. This is used by the `AssetServer` to reload them
|
||||
pub struct FilesystemWatcher {
|
||||
pub watcher: RecommendedWatcher,
|
||||
pub receiver: Receiver<Result<Event>>,
|
||||
|
|
|
@ -8,10 +8,13 @@ use serde::{Deserialize, Serialize};
|
|||
use std::{any::TypeId, marker::PhantomData};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// The ID of the "default" asset
|
||||
pub(crate) const DEFAULT_HANDLE_ID: HandleId =
|
||||
HandleId(Uuid::from_u128(240940089166493627844978703213080810552));
|
||||
|
||||
/// A unique id that corresponds to a specific asset in the [Assets](crate::Assets) collection.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, Property)]
|
||||
pub struct HandleId(pub Uuid);
|
||||
pub const DEFAULT_HANDLE_ID: HandleId =
|
||||
HandleId(Uuid::from_u128(240940089166493627844978703213080810552));
|
||||
|
||||
impl HandleId {
|
||||
pub fn new() -> HandleId {
|
||||
|
@ -19,6 +22,9 @@ impl HandleId {
|
|||
}
|
||||
}
|
||||
|
||||
/// A handle into a specific Asset of type `T`
|
||||
///
|
||||
/// Handles contain a unique id that corresponds to a specific asset in the [Assets](crate::Assets) collection.
|
||||
#[derive(Properties)]
|
||||
pub struct Handle<T>
|
||||
where
|
||||
|
@ -156,6 +162,9 @@ impl<T> Copy for Handle<T> {}
|
|||
unsafe impl<T> Send for Handle<T> {}
|
||||
unsafe impl<T> Sync for Handle<T> {}
|
||||
|
||||
/// A non-generic version of [Handle]
|
||||
///
|
||||
/// This allows handles to be mingled in a cross asset context. For example, storing `Handle<A>` and `Handle<B>` in the same `HashSet<HandleUntyped>`.
|
||||
#[derive(Hash, Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub struct HandleUntyped {
|
||||
pub id: HandleId,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#[cfg(feature = "filesystem_watcher")]
|
||||
mod filesystem_watcher;
|
||||
mod asset_server;
|
||||
mod assets;
|
||||
#[cfg(feature = "filesystem_watcher")]
|
||||
pub mod filesystem_watcher;
|
||||
mod handle;
|
||||
mod load_request;
|
||||
mod loader;
|
||||
|
@ -12,6 +12,7 @@ pub use handle::*;
|
|||
pub use load_request::*;
|
||||
pub use loader::*;
|
||||
|
||||
/// The names of asset stages in an App Schedule
|
||||
pub mod stage {
|
||||
pub const LOAD_ASSETS: &str = "load_assets";
|
||||
pub const ASSET_EVENTS: &str = "asset_events";
|
||||
|
@ -25,6 +26,8 @@ use bevy_app::{prelude::Plugin, AppBuilder};
|
|||
use bevy_ecs::IntoQuerySystem;
|
||||
use bevy_type_registry::RegisterType;
|
||||
|
||||
/// Adds support for Assets to an App. Assets are typed collections with change tracking, which are added as App Resources.
|
||||
/// Examples of assets: textures, sounds, 3d models, maps, scenes
|
||||
#[derive(Default)]
|
||||
pub struct AssetPlugin;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ use fs::File;
|
|||
use io::Read;
|
||||
use std::{fs, io, path::PathBuf};
|
||||
|
||||
/// A request from an [AssetServer](crate::AssetServer) to load an asset.
|
||||
#[derive(Debug)]
|
||||
pub struct LoadRequest {
|
||||
pub path: PathBuf,
|
||||
|
@ -13,12 +14,13 @@ pub struct LoadRequest {
|
|||
pub version: AssetVersion,
|
||||
}
|
||||
|
||||
/// Handles load requests from an AssetServer
|
||||
pub trait AssetLoadRequestHandler: Send + Sync + 'static {
|
||||
fn handle_request(&self, load_request: &LoadRequest);
|
||||
fn extensions(&self) -> &[&str];
|
||||
}
|
||||
|
||||
pub struct ChannelAssetHandler<TLoader, TAsset>
|
||||
pub(crate) struct ChannelAssetHandler<TLoader, TAsset>
|
||||
where
|
||||
TLoader: AssetLoader<TAsset>,
|
||||
TAsset: 'static,
|
||||
|
|
|
@ -10,6 +10,7 @@ use std::{
|
|||
};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Errors that occur while loading assets
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AssetLoadError {
|
||||
#[error("Encountered an io error while loading asset.")]
|
||||
|
@ -18,6 +19,7 @@ pub enum AssetLoadError {
|
|||
LoaderError(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
/// A loader for a given asset of type `T`
|
||||
pub trait AssetLoader<T>: Send + Sync + 'static {
|
||||
fn from_bytes(&self, asset_path: &Path, bytes: Vec<u8>) -> Result<T, anyhow::Error>;
|
||||
fn extensions(&self) -> &[&str];
|
||||
|
@ -30,6 +32,7 @@ pub trait AssetLoader<T>: Send + Sync + 'static {
|
|||
}
|
||||
}
|
||||
|
||||
/// The result of loading an asset of type `T`
|
||||
pub struct AssetResult<T: 'static> {
|
||||
pub result: Result<T, AssetLoadError>,
|
||||
pub handle: Handle<T>,
|
||||
|
@ -37,6 +40,7 @@ pub struct AssetResult<T: 'static> {
|
|||
pub version: AssetVersion,
|
||||
}
|
||||
|
||||
/// A channel to send and receive [AssetResult]s
|
||||
pub struct AssetChannel<T: 'static> {
|
||||
pub sender: Sender<AssetResult<T>>,
|
||||
pub receiver: Receiver<AssetResult<T>>,
|
||||
|
@ -49,6 +53,7 @@ impl<T> AssetChannel<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Reads [AssetResult]s from an [AssetChannel] and updates the [Assets] collection and [LoadState] accordingly
|
||||
pub fn update_asset_storage_system<T: Resource>(
|
||||
asset_channel: Res<AssetChannel<T>>,
|
||||
asset_server: Res<AssetServer>,
|
||||
|
|
|
@ -4,6 +4,7 @@ use bevy_ecs::Res;
|
|||
use rodio::{Decoder, Device, Sink};
|
||||
use std::{collections::VecDeque, io::Cursor, sync::RwLock};
|
||||
|
||||
/// Used to play audio on the current "audio device"
|
||||
pub struct AudioOutput {
|
||||
device: Device,
|
||||
queue: RwLock<VecDeque<Handle<AudioSource>>>,
|
||||
|
@ -46,7 +47,8 @@ impl AudioOutput {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn play_queued_audio_system(
|
||||
/// Plays audio currently queued in the [AudioOutput] resource
|
||||
pub(crate) fn play_queued_audio_system(
|
||||
audio_sources: Res<Assets<AudioSource>>,
|
||||
audio_output: Res<AudioOutput>,
|
||||
) {
|
||||
|
|
|
@ -2,6 +2,7 @@ use anyhow::Result;
|
|||
use bevy_asset::AssetLoader;
|
||||
use std::{path::Path, sync::Arc};
|
||||
|
||||
/// A source of audio data
|
||||
#[derive(Clone)]
|
||||
pub struct AudioSource {
|
||||
pub bytes: Arc<Vec<u8>>,
|
||||
|
@ -13,6 +14,7 @@ impl AsRef<[u8]> for AudioSource {
|
|||
}
|
||||
}
|
||||
|
||||
/// Loads mp3 files as [AudioSource] [Assets](bevy_asset::Assets)
|
||||
#[derive(Default)]
|
||||
pub struct Mp3Loader;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ use bevy_app::prelude::*;
|
|||
use bevy_asset::AddAsset;
|
||||
use bevy_ecs::IntoQuerySystem;
|
||||
|
||||
/// Adds support for audio playback to an App
|
||||
#[derive(Default)]
|
||||
pub struct AudioPlugin;
|
||||
|
||||
|
|
|
@ -2,11 +2,16 @@ use bevy_math::{Mat4, Vec2, Vec3, Vec4};
|
|||
|
||||
pub use bevy_derive::Bytes;
|
||||
|
||||
/// Converts the implementing type to bytes by writing them to a given buffer
|
||||
pub trait Bytes {
|
||||
/// Converts the implementing type to bytes by writing them to a given buffer
|
||||
fn write_bytes(&self, buffer: &mut [u8]);
|
||||
|
||||
/// The number of bytes that will be written when calling `write_bytes`
|
||||
fn byte_len(&self) -> usize;
|
||||
}
|
||||
|
||||
/// A trait that indicates that it is safe to cast the type to a byte array reference.
|
||||
pub unsafe trait Byteable
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -27,11 +32,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Reads the implementing type as a byte array reference
|
||||
pub trait AsBytes {
|
||||
/// Reads the implementing type as a byte array reference
|
||||
fn as_bytes(&self) -> &[u8];
|
||||
}
|
||||
|
||||
/// Converts a byte array to `Self`
|
||||
pub trait FromBytes {
|
||||
/// Converts a byte array to `Self`
|
||||
fn from_bytes(bytes: &[u8]) -> Self;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@ use std::{
|
|||
ops::Neg,
|
||||
};
|
||||
|
||||
// working around the famous "rust float ordering" problem
|
||||
/// A wrapper type that enables ordering floats. This is a work around for the famous "rust float ordering" problem.
|
||||
/// By using it, you acknowledge that sorting NaN is undefined according to spec. This implementation treats NaN as the
|
||||
/// "smallest" float.
|
||||
#[derive(Debug, Copy, Clone, PartialOrd)]
|
||||
pub struct FloatOrd(pub f32);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::{
|
|||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
/// A collection of labels
|
||||
#[derive(Default, Properties)]
|
||||
pub struct Labels {
|
||||
labels: HashSet<Cow<'static, str>>,
|
||||
|
@ -50,6 +51,7 @@ impl Labels {
|
|||
}
|
||||
}
|
||||
|
||||
/// Maintains a mapping from [Entity](bevy_ecs::prelude::Entity) ids to entity labels and entity labels to [Entities](bevy_ecs::prelude::Entity).
|
||||
#[derive(Default)]
|
||||
pub struct EntityLabels {
|
||||
label_entities: HashMap<Cow<'static, str>, Vec<Entity>>,
|
||||
|
@ -64,7 +66,7 @@ impl EntityLabels {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn entity_labels_system(
|
||||
pub(crate) fn entity_labels_system(
|
||||
mut entity_labels: ResMut<EntityLabels>,
|
||||
// TODO: use change tracking when add/remove events are added
|
||||
// mut query: Query<(Entity, Changed<Labels>)>,
|
||||
|
|
|
@ -17,6 +17,7 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_math::{Mat3, Mat4, Quat, Vec2, Vec3};
|
||||
use bevy_type_registry::RegisterType;
|
||||
|
||||
/// Adds core functionality to Apps.
|
||||
#[derive(Default)]
|
||||
pub struct CorePlugin;
|
||||
|
||||
|
@ -32,6 +33,7 @@ impl Plugin for CorePlugin {
|
|||
.register_property::<Quat>()
|
||||
.register_property::<Option<String>>()
|
||||
.add_system_to_stage(stage::FIRST, time_system.system())
|
||||
.add_system_to_stage(stage::FIRST, timer_system.system());
|
||||
.add_system_to_stage(stage::FIRST, timer_system.system())
|
||||
.add_system_to_stage(stage::PRE_UPDATE, entity_labels_system.system());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use bevy_ecs::ResMut;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
/// Tracks elapsed time since the last update and since the App has started
|
||||
pub struct Time {
|
||||
pub delta: Duration,
|
||||
pub instant: Option<Instant>,
|
||||
|
@ -42,6 +43,6 @@ impl Time {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn time_system(mut time: ResMut<Time>) {
|
||||
pub(crate) fn time_system(mut time: ResMut<Time>) {
|
||||
time.update();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use bevy_ecs::prelude::*;
|
|||
use bevy_property::Properties;
|
||||
use std::time::Duration;
|
||||
|
||||
/// Tracks elapsed time. Enters the finished state once `duration` is reached.
|
||||
#[derive(Clone, Debug, Default, Properties)]
|
||||
pub struct Timer {
|
||||
pub elapsed: f32,
|
||||
|
@ -11,16 +12,16 @@ pub struct Timer {
|
|||
}
|
||||
|
||||
impl Timer {
|
||||
pub fn from_seconds(seconds: f32) -> Self {
|
||||
pub fn new(duration: Duration) -> Self {
|
||||
Timer {
|
||||
duration: seconds,
|
||||
duration: duration.as_secs_f32(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(duration: Duration) -> Self {
|
||||
pub fn from_seconds(seconds: f32) -> Self {
|
||||
Timer {
|
||||
duration: duration.as_secs_f32(),
|
||||
duration: seconds,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +39,7 @@ impl Timer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn timer_system(time: Res<Time>, mut query: Query<&mut Timer>) {
|
||||
pub(crate) fn timer_system(time: Res<Time>, mut query: Query<&mut Timer>) {
|
||||
for mut timer in &mut query.iter() {
|
||||
timer.tick(time.delta_seconds);
|
||||
}
|
||||
|
|
|
@ -11,37 +11,47 @@ mod shader_defs;
|
|||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
/// Derives the FromResources trait. Each field must also implement the FromResources trait or this will fail. FromResources is
|
||||
/// automatically implemented for types that implement Default.
|
||||
#[proc_macro_derive(FromResources, attributes(as_crate))]
|
||||
pub fn derive_from_resources(input: TokenStream) -> TokenStream {
|
||||
resource::derive_from_resources(input)
|
||||
}
|
||||
|
||||
/// Derives the Bytes trait. Each field must also implements Bytes or this will fail.
|
||||
#[proc_macro_derive(Bytes, attributes(as_crate))]
|
||||
pub fn derive_bytes(input: TokenStream) -> TokenStream {
|
||||
bytes::derive_bytes(input)
|
||||
}
|
||||
|
||||
/// Derives the RenderResources trait. Each field must implement RenderResource or this will fail.
|
||||
/// You can ignore fields using `#[render_resources(ignore)]`.
|
||||
#[proc_macro_derive(RenderResources, attributes(render_resources, as_crate))]
|
||||
pub fn derive_render_resources(input: TokenStream) -> TokenStream {
|
||||
render_resources::derive_render_resources(input)
|
||||
}
|
||||
|
||||
/// Derives the RenderResource trait. The type must also implement `Bytes` or this will fail.
|
||||
#[proc_macro_derive(RenderResource, attributes(as_crate))]
|
||||
pub fn derive_render_resource(input: TokenStream) -> TokenStream {
|
||||
render_resource::derive_render_resource(input)
|
||||
}
|
||||
|
||||
/// Derives the ShaderDefs trait. Each field must implement ShaderDef or this will fail.
|
||||
/// You can ignore fields using `#[shader_defs(ignore)]`.
|
||||
#[proc_macro_derive(ShaderDefs, attributes(shader_def, as_crate))]
|
||||
pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
|
||||
shader_defs::derive_shader_defs(input)
|
||||
}
|
||||
|
||||
/// Derives the AsVertexBufferDescriptor trait.
|
||||
#[proc_macro_derive(AsVertexBufferDescriptor, attributes(vertex, as_crate))]
|
||||
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
||||
as_vertex_buffer_descriptor::derive_as_vertex_buffer_descriptor(input)
|
||||
}
|
||||
|
||||
/// Generates a dynamic plugin entry point function for the given `Plugin` type.
|
||||
#[proc_macro_derive(DynamicPlugin)]
|
||||
pub fn derive_app_plugin(input: TokenStream) -> TokenStream {
|
||||
pub fn derive_dynamic_plugin(input: TokenStream) -> TokenStream {
|
||||
app_plugin::derive_dynamic_plugin(input)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Unique identifier for a [Diagnostic]
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
|
||||
pub struct DiagnosticId(pub Uuid);
|
||||
|
||||
|
@ -19,12 +20,15 @@ impl Default for DiagnosticId {
|
|||
}
|
||||
}
|
||||
|
||||
/// A single measurement of a [Diagnostic]
|
||||
#[derive(Debug)]
|
||||
pub struct DiagnosticMeasurement {
|
||||
pub time: SystemTime,
|
||||
pub value: f64,
|
||||
}
|
||||
|
||||
/// A timeline of [DiagnosticMeasurement]s of a specific type.
|
||||
/// Diagnostic examples: frames per second, CPU usage, network latency
|
||||
#[derive(Debug)]
|
||||
pub struct Diagnostic {
|
||||
pub id: DiagnosticId,
|
||||
|
@ -97,6 +101,7 @@ impl Diagnostic {
|
|||
}
|
||||
}
|
||||
|
||||
/// A collection of [Diagnostic]s
|
||||
#[derive(Default)]
|
||||
pub struct Diagnostics {
|
||||
diagnostics: HashMap<DiagnosticId, Diagnostic>,
|
||||
|
|
|
@ -3,6 +3,7 @@ use bevy_app::prelude::*;
|
|||
use bevy_core::Time;
|
||||
use bevy_ecs::{IntoQuerySystem, Res, ResMut};
|
||||
|
||||
/// Adds "frame time" diagnostic to an App, specifically "frame time" and "fps"
|
||||
#[derive(Default)]
|
||||
pub struct FrameTimeDiagnosticsPlugin;
|
||||
|
||||
|
|
|
@ -9,8 +9,7 @@ pub use print_diagnostics_plugin::PrintDiagnosticsPlugin;
|
|||
|
||||
use bevy_app::prelude::*;
|
||||
|
||||
pub struct PrintDiagnostics {}
|
||||
|
||||
/// Adds core diagnostics resources to an App.
|
||||
#[derive(Default)]
|
||||
pub struct DiagnosticsPlugin;
|
||||
|
||||
|
|
|
@ -4,12 +4,14 @@ use bevy_core::{Time, Timer};
|
|||
use bevy_ecs::{IntoQuerySystem, Res, ResMut};
|
||||
use std::time::Duration;
|
||||
|
||||
/// An App Plugin that prints diagnostics to the console
|
||||
pub struct PrintDiagnosticsPlugin {
|
||||
pub debug: bool,
|
||||
pub wait_duration: Duration,
|
||||
pub filter: Option<Vec<DiagnosticId>>,
|
||||
}
|
||||
|
||||
/// State used by the [PrintDiagnosticsPlugin]
|
||||
pub struct PrintDiagnosticsState {
|
||||
timer: Timer,
|
||||
filter: Option<Vec<DiagnosticId>>,
|
||||
|
|
|
@ -20,6 +20,7 @@ struct SystemProfiles {
|
|||
current_start: Option<Instant>,
|
||||
}
|
||||
|
||||
/// Profiles systems by recording their run duration as diagnostics.
|
||||
#[derive(Default)]
|
||||
pub struct SystemProfiler {
|
||||
system_profiles: Arc<RwLock<HashMap<Cow<'static, str>, SystemProfiles>>>,
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
use super::{FromResources, Resources};
|
||||
use crate::{
|
||||
system::{SystemId, TypeAccess},
|
||||
ResourceIndex,
|
||||
Resource, ResourceIndex,
|
||||
};
|
||||
use core::{
|
||||
any::TypeId,
|
||||
ops::{Deref, DerefMut},
|
||||
ptr::NonNull,
|
||||
};
|
||||
use hecs::{smaller_tuples_too, Component};
|
||||
use hecs::smaller_tuples_too;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Shared borrow of an entity's component
|
||||
pub struct Res<'a, T: Component> {
|
||||
/// Shared borrow of a Resource
|
||||
pub struct Res<'a, T: Resource> {
|
||||
value: &'a T,
|
||||
}
|
||||
|
||||
impl<'a, T: Component> Res<'a, T> {
|
||||
impl<'a, T: Resource> Res<'a, T> {
|
||||
pub unsafe fn new(value: NonNull<T>) -> Self {
|
||||
Self {
|
||||
value: &*value.as_ptr(),
|
||||
|
@ -24,20 +24,21 @@ impl<'a, T: Component> Res<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A clone that is unsafe to perform. You probably shouldn't use this.
|
||||
pub trait UnsafeClone {
|
||||
unsafe fn unsafe_clone(&self) -> Self;
|
||||
}
|
||||
|
||||
impl<'a, T: Component> UnsafeClone for Res<'a, T> {
|
||||
impl<'a, T: Resource> UnsafeClone for Res<'a, T> {
|
||||
unsafe fn unsafe_clone(&self) -> Self {
|
||||
Self { value: self.value }
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Component> Send for Res<'_, T> {}
|
||||
unsafe impl<T: Component> Sync for Res<'_, T> {}
|
||||
unsafe impl<T: Resource> Send for Res<'_, T> {}
|
||||
unsafe impl<T: Resource> Sync for Res<'_, T> {}
|
||||
|
||||
impl<'a, T: Component> Deref for Res<'a, T> {
|
||||
impl<'a, T: Resource> Deref for Res<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
|
@ -45,13 +46,13 @@ impl<'a, T: Component> Deref for Res<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Unique borrow of a resource
|
||||
pub struct ResMut<'a, T: Component> {
|
||||
/// Unique borrow of a Resource
|
||||
pub struct ResMut<'a, T: Resource> {
|
||||
_marker: PhantomData<&'a T>,
|
||||
value: *mut T,
|
||||
}
|
||||
|
||||
impl<'a, T: Component> ResMut<'a, T> {
|
||||
impl<'a, T: Resource> ResMut<'a, T> {
|
||||
pub unsafe fn new(value: NonNull<T>) -> Self {
|
||||
Self {
|
||||
value: value.as_ptr(),
|
||||
|
@ -60,10 +61,10 @@ impl<'a, T: Component> ResMut<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Component> Send for ResMut<'_, T> {}
|
||||
unsafe impl<T: Component> Sync for ResMut<'_, T> {}
|
||||
unsafe impl<T: Resource> Send for ResMut<'_, T> {}
|
||||
unsafe impl<T: Resource> Sync for ResMut<'_, T> {}
|
||||
|
||||
impl<'a, T: Component> Deref for ResMut<'a, T> {
|
||||
impl<'a, T: Resource> Deref for ResMut<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
|
@ -71,13 +72,13 @@ impl<'a, T: Component> Deref for ResMut<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component> DerefMut for ResMut<'a, T> {
|
||||
impl<'a, T: Resource> DerefMut for ResMut<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.value }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component> UnsafeClone for ResMut<'a, T> {
|
||||
impl<'a, T: Resource> UnsafeClone for ResMut<'a, T> {
|
||||
unsafe fn unsafe_clone(&self) -> Self {
|
||||
Self {
|
||||
value: self.value,
|
||||
|
@ -86,12 +87,14 @@ impl<'a, T: Component> UnsafeClone for ResMut<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Local<'a, T: Component + FromResources> {
|
||||
/// Local<T> resources are unique per-system. Two instances of the same system will each have their own resource.
|
||||
/// Local resources are automatically initialized using the FromResources trait.
|
||||
pub struct Local<'a, T: Resource + FromResources> {
|
||||
value: *mut T,
|
||||
_marker: PhantomData<&'a T>,
|
||||
}
|
||||
|
||||
impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
|
||||
impl<'a, T: Resource + FromResources> UnsafeClone for Local<'a, T> {
|
||||
unsafe fn unsafe_clone(&self) -> Self {
|
||||
Self {
|
||||
value: self.value,
|
||||
|
@ -100,7 +103,7 @@ impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component + FromResources> Deref for Local<'a, T> {
|
||||
impl<'a, T: Resource + FromResources> Deref for Local<'a, T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
|
@ -108,20 +111,20 @@ impl<'a, T: Component + FromResources> Deref for Local<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component + FromResources> DerefMut for Local<'a, T> {
|
||||
impl<'a, T: Resource + FromResources> DerefMut for Local<'a, T> {
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
unsafe { &mut *self.value }
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of component types to fetch from a `World`
|
||||
/// A collection of resource types fetch from a `Resources` collection
|
||||
pub trait ResourceQuery {
|
||||
type Fetch: for<'a> FetchResource<'a>;
|
||||
|
||||
fn initialize(_resources: &mut Resources, _system_id: Option<SystemId>) {}
|
||||
}
|
||||
|
||||
/// Streaming iterators over contiguous homogeneous ranges of components
|
||||
/// Streaming iterators over contiguous homogeneous ranges of resources
|
||||
pub trait FetchResource<'a>: Sized {
|
||||
/// Type of value to be fetched
|
||||
type Item: UnsafeClone;
|
||||
|
@ -130,20 +133,17 @@ pub trait FetchResource<'a>: Sized {
|
|||
fn borrow(resources: &Resources);
|
||||
fn release(resources: &Resources);
|
||||
|
||||
/// Construct a `Fetch` for `archetype` if it should be traversed
|
||||
///
|
||||
/// # Safety
|
||||
/// `offset` must be in bounds of `archetype`
|
||||
unsafe fn get(resources: &'a Resources, system_id: Option<SystemId>) -> Self::Item;
|
||||
}
|
||||
|
||||
impl<'a, T: Component> ResourceQuery for Res<'a, T> {
|
||||
impl<'a, T: Resource> ResourceQuery for Res<'a, T> {
|
||||
type Fetch = FetchResourceRead<T>;
|
||||
}
|
||||
|
||||
/// Fetches a shared resource reference
|
||||
pub struct FetchResourceRead<T>(NonNull<T>);
|
||||
|
||||
impl<'a, T: Component> FetchResource<'a> for FetchResourceRead<T> {
|
||||
impl<'a, T: Resource> FetchResource<'a> for FetchResourceRead<T> {
|
||||
type Item = Res<'a, T>;
|
||||
|
||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
||||
|
@ -165,13 +165,14 @@ impl<'a, T: Component> FetchResource<'a> for FetchResourceRead<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component> ResourceQuery for ResMut<'a, T> {
|
||||
impl<'a, T: Resource> ResourceQuery for ResMut<'a, T> {
|
||||
type Fetch = FetchResourceWrite<T>;
|
||||
}
|
||||
|
||||
/// Fetches a unique resource reference
|
||||
pub struct FetchResourceWrite<T>(NonNull<T>);
|
||||
|
||||
impl<'a, T: Component> FetchResource<'a> for FetchResourceWrite<T> {
|
||||
impl<'a, T: Resource> FetchResource<'a> for FetchResourceWrite<T> {
|
||||
type Item = ResMut<'a, T>;
|
||||
|
||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
||||
|
@ -193,7 +194,7 @@ impl<'a, T: Component> FetchResource<'a> for FetchResourceWrite<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Component + FromResources> ResourceQuery for Local<'a, T> {
|
||||
impl<'a, T: Resource + FromResources> ResourceQuery for Local<'a, T> {
|
||||
type Fetch = FetchResourceLocalMut<T>;
|
||||
|
||||
fn initialize(resources: &mut Resources, id: Option<SystemId>) {
|
||||
|
@ -203,9 +204,10 @@ impl<'a, T: Component + FromResources> ResourceQuery for Local<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Fetches a `Local<T>` resource reference
|
||||
pub struct FetchResourceLocalMut<T>(NonNull<T>);
|
||||
|
||||
impl<'a, T: Component + FromResources> FetchResource<'a> for FetchResourceLocalMut<T> {
|
||||
impl<'a, T: Resource + FromResources> FetchResource<'a> for FetchResourceLocalMut<T> {
|
||||
type Item = Local<'a, T>;
|
||||
|
||||
unsafe fn get(resources: &'a Resources, system_id: Option<SystemId>) -> Self::Item {
|
||||
|
|
|
@ -4,10 +4,11 @@ use core::any::TypeId;
|
|||
use hecs::{Archetype, Ref, RefMut, TypeInfo};
|
||||
use std::{collections::HashMap, ptr::NonNull};
|
||||
|
||||
/// A Resource type
|
||||
pub trait Resource: Send + Sync + 'static {}
|
||||
impl<T: Send + Sync + 'static> Resource for T {}
|
||||
|
||||
pub struct ResourceData {
|
||||
pub(crate) struct ResourceData {
|
||||
archetype: Archetype,
|
||||
default_index: Option<u32>,
|
||||
system_id_to_archetype_index: HashMap<u32, u32>,
|
||||
|
@ -18,6 +19,7 @@ pub enum ResourceIndex {
|
|||
System(SystemId),
|
||||
}
|
||||
|
||||
/// A collection of resource instances identified by their type.
|
||||
#[derive(Default)]
|
||||
pub struct Resources {
|
||||
pub(crate) resource_data: HashMap<TypeId, ResourceData>,
|
||||
|
@ -183,7 +185,9 @@ impl Resources {
|
|||
unsafe impl Send for Resources {}
|
||||
unsafe impl Sync for Resources {}
|
||||
|
||||
/// Creates `Self` using data from the `Resources` collection
|
||||
pub trait FromResources {
|
||||
/// Creates `Self` using data from the `Resources` collection
|
||||
fn from_resources(resources: &Resources) -> Self;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,14 @@ use std::{
|
|||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
/// Executes each schedule stage in parallel by analyzing system dependencies.
|
||||
/// System execution order is undefined except under the following conditions:
|
||||
/// * systems in earlier stages run before systems in later stages
|
||||
/// * in a given stage, systems that mutate archetype X cannot run before systems registered before them that read/write archetype X
|
||||
/// * in a given stage, systems the read archetype X cannot run before systems registered before them that write archetype X
|
||||
/// * in a given stage, systems that mutate resource Y cannot run before systems registered before them that read/write resource Y
|
||||
/// * in a given stage, systems the read resource Y cannot run before systems registered before them that write resource Y
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ParallelExecutor {
|
||||
stages: Vec<ExecutorStage>,
|
||||
|
|
|
@ -9,6 +9,9 @@ use std::{
|
|||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
/// An ordered collection of stages, which each contain an ordered list of [System]s.
|
||||
/// Schedules are essentially the "execution plan" for an App's systems.
|
||||
/// They are run on a given [World] and [Resources] reference.
|
||||
#[derive(Default)]
|
||||
pub struct Schedule {
|
||||
pub(crate) stages: HashMap<Cow<'static, str>, Vec<Arc<Mutex<Box<dyn System>>>>>,
|
||||
|
|
|
@ -3,16 +3,18 @@ use crate::resource::{Resource, Resources};
|
|||
use hecs::{Bundle, Component, DynamicBundle, Entity, World};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
/// A queued command to mutate the current [World] or [Resources]
|
||||
pub enum Command {
|
||||
WriteWorld(Box<dyn WorldWriter>),
|
||||
WriteResources(Box<dyn ResourcesWriter>),
|
||||
}
|
||||
|
||||
/// A [World] mutation
|
||||
pub trait WorldWriter: Send + Sync {
|
||||
fn write(self: Box<Self>, world: &mut World);
|
||||
}
|
||||
|
||||
pub struct Spawn<T>
|
||||
pub(crate) struct Spawn<T>
|
||||
where
|
||||
T: DynamicBundle + Send + Sync + 'static,
|
||||
{
|
||||
|
@ -28,7 +30,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SpawnAsEntity<T>
|
||||
pub(crate) struct SpawnAsEntity<T>
|
||||
where
|
||||
T: DynamicBundle + Send + Sync + 'static,
|
||||
{
|
||||
|
@ -45,7 +47,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct SpawnBatch<I>
|
||||
pub(crate) struct SpawnBatch<I>
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Bundle,
|
||||
|
@ -63,7 +65,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Despawn {
|
||||
pub(crate) struct Despawn {
|
||||
entity: Entity,
|
||||
}
|
||||
|
||||
|
@ -90,7 +92,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
pub struct InsertOne<T>
|
||||
pub(crate) struct InsertOne<T>
|
||||
where
|
||||
T: Component,
|
||||
{
|
||||
|
@ -121,7 +123,7 @@ impl<T: Resource> ResourcesWriter for InsertResource<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct InsertLocalResource<T: Resource> {
|
||||
pub(crate) struct InsertLocalResource<T: Resource> {
|
||||
resource: T,
|
||||
system_id: SystemId,
|
||||
}
|
||||
|
@ -194,6 +196,7 @@ impl CommandsInternal {
|
|||
}
|
||||
}
|
||||
|
||||
/// A queue of [Command]s to run on the current [World] and [Resources]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Commands {
|
||||
pub commands: Arc<Mutex<CommandsInternal>>,
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
use hecs::{Fetch, Query as HecsQuery, World};
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub struct SystemFn<State, F, ThreadLocalF, Init, SetArchetypeAccess>
|
||||
pub(crate) struct SystemFn<State, F, ThreadLocalF, Init, SetArchetypeAccess>
|
||||
where
|
||||
F: FnMut(&World, &Resources, &ArchetypeAccess, &mut State) + Send + Sync,
|
||||
ThreadLocalF: FnMut(&mut World, &mut Resources, &mut State) + Send + Sync,
|
||||
|
@ -74,7 +74,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Converts `Self` into a For-Each system
|
||||
pub trait IntoForEachSystem<CommandBuffer, R, C> {
|
||||
fn system(self) -> Box<dyn System>;
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ struct QuerySystemState {
|
|||
commands: Commands,
|
||||
}
|
||||
|
||||
/// Converts `Self` into a Query System
|
||||
pub trait IntoQuerySystem<Commands, R, Q> {
|
||||
fn system(self) -> Box<dyn System>;
|
||||
}
|
||||
|
@ -298,6 +299,7 @@ impl_into_systems!(Ra,Rb,Rc,Rd,Re,Rf,Rg,Rh,Ri);
|
|||
#[rustfmt::skip]
|
||||
impl_into_systems!(Ra,Rb,Rc,Rd,Re,Rf,Rg,Rh,Ri,Rj);
|
||||
|
||||
/// Converts `Self` into a thread local system
|
||||
pub trait IntoThreadLocalSystem {
|
||||
fn thread_local_system(self) -> Box<dyn System>;
|
||||
}
|
||||
|
@ -324,6 +326,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// A thread local system function
|
||||
pub trait ThreadLocalSystemFn: Send + Sync + 'static {
|
||||
fn run(&mut self, world: &mut World, resource: &mut Resources);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ use crate::Resources;
|
|||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Runs at the start and end of each system
|
||||
///
|
||||
/// Profilers are used to collect diagnostics about system execution.
|
||||
pub trait Profiler: Downcast + Send + Sync + 'static {
|
||||
fn start(&self, scope: Cow<'static, str>);
|
||||
fn stop(&self, scope: Cow<'static, str>);
|
||||
|
|
|
@ -5,12 +5,14 @@ use hecs::{
|
|||
};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// Provides scoped access to a World according to a given [HecsQuery]
|
||||
pub struct Query<'a, Q: HecsQuery> {
|
||||
pub(crate) world: &'a World,
|
||||
pub(crate) archetype_access: &'a ArchetypeAccess,
|
||||
_marker: PhantomData<Q>,
|
||||
}
|
||||
|
||||
/// An error that occurs when using a [Query]
|
||||
#[derive(Debug)]
|
||||
pub enum QueryError {
|
||||
CannotReadArchetype,
|
||||
|
|
|
@ -3,6 +3,7 @@ use fixedbitset::FixedBitSet;
|
|||
use hecs::{Access, Query, World};
|
||||
use std::{any::TypeId, borrow::Cow, collections::HashSet};
|
||||
|
||||
/// Determines the strategy used to run the `run_thread_local` function in a [System]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
pub enum ThreadLocalExecution {
|
||||
Immediate,
|
||||
|
@ -18,6 +19,7 @@ impl SystemId {
|
|||
}
|
||||
}
|
||||
|
||||
/// An ECS system that can be added to a [Schedule](crate::Schedule)
|
||||
pub trait System: Send + Sync {
|
||||
fn name(&self) -> Cow<'static, str>;
|
||||
fn id(&self) -> SystemId;
|
||||
|
@ -30,13 +32,14 @@ pub trait System: Send + Sync {
|
|||
fn initialize(&mut self, _resources: &mut Resources) {}
|
||||
}
|
||||
|
||||
// credit to Ratysz from the Yaks codebase
|
||||
/// Provides information about the archetypes a [System] reads and writes
|
||||
#[derive(Default)]
|
||||
pub struct ArchetypeAccess {
|
||||
pub immutable: FixedBitSet,
|
||||
pub mutable: FixedBitSet,
|
||||
}
|
||||
|
||||
// credit to Ratysz from the Yaks codebase
|
||||
impl ArchetypeAccess {
|
||||
pub fn is_compatible(&self, other: &ArchetypeAccess) -> bool {
|
||||
self.mutable.is_disjoint(&other.mutable)
|
||||
|
@ -73,6 +76,7 @@ impl ArchetypeAccess {
|
|||
}
|
||||
}
|
||||
|
||||
/// Provides information about the types a [System] reads and writes
|
||||
#[derive(Debug, Default, Eq, PartialEq, Clone)]
|
||||
pub struct TypeAccess {
|
||||
pub immutable: HashSet<TypeId>,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use hecs::{Bundle, Component, DynamicBundle, Entity, World};
|
||||
|
||||
/// Converts a reference to `Self` to a [WorldBuilder]
|
||||
pub trait WorldBuilderSource {
|
||||
fn build(&mut self) -> WorldBuilder;
|
||||
}
|
||||
|
@ -13,6 +14,7 @@ impl WorldBuilderSource for World {
|
|||
}
|
||||
}
|
||||
|
||||
/// Modify a [World] using the builder pattern
|
||||
pub struct WorldBuilder<'a> {
|
||||
pub world: &'a mut World,
|
||||
pub current_entity: Option<Entity>,
|
||||
|
|
|
@ -5,6 +5,7 @@ use bevy_app::prelude::*;
|
|||
use bevy_asset::AddAsset;
|
||||
use bevy_render::mesh::Mesh;
|
||||
|
||||
/// Adds support for GLTF file loading to Apps
|
||||
#[derive(Default)]
|
||||
pub struct GltfPlugin;
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ use gltf::{buffer::Source, iter, mesh::Mode};
|
|||
use std::{fs, io, path::Path};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Loads meshes from GLTF files into Mesh assets
|
||||
///
|
||||
/// NOTE: eventually this will loading into Scenes instead of Meshes
|
||||
#[derive(Default)]
|
||||
pub struct GltfLoader;
|
||||
|
||||
|
@ -24,6 +27,7 @@ impl AssetLoader<Mesh> for GltfLoader {
|
|||
}
|
||||
}
|
||||
|
||||
/// An error that occurs when loading a GLTF file
|
||||
#[derive(Error, Debug)]
|
||||
pub enum GltfError {
|
||||
#[error("Unsupported primitive mode.")]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::{collections::HashSet, hash::Hash};
|
||||
|
||||
/// A "press-able" input of type `T`
|
||||
pub struct Input<T> {
|
||||
pressed: HashSet<T>,
|
||||
just_pressed: HashSet<T>,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use crate::Input;
|
||||
use bevy_app::prelude::*;
|
||||
use bevy_ecs::{Res, ResMut};
|
||||
use bevy_ecs::{Res, ResMut, Local};
|
||||
|
||||
/// A key input event from a keyboard device
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct KeyboardInput {
|
||||
pub scan_code: u32,
|
||||
|
@ -9,6 +10,7 @@ pub struct KeyboardInput {
|
|||
pub state: ElementState,
|
||||
}
|
||||
|
||||
/// The current "press" state of an element
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum ElementState {
|
||||
Pressed,
|
||||
|
@ -24,13 +26,15 @@ impl ElementState {
|
|||
}
|
||||
}
|
||||
|
||||
/// State used by the keyboard input system
|
||||
#[derive(Default)]
|
||||
pub struct KeyboardInputState {
|
||||
keyboard_input_event_reader: EventReader<KeyboardInput>,
|
||||
}
|
||||
|
||||
/// Updates the Input<KeyCode> resource with the latest KeyboardInput events
|
||||
pub fn keyboard_input_system(
|
||||
mut state: ResMut<KeyboardInputState>,
|
||||
mut state: Local<KeyboardInputState>,
|
||||
mut keyboard_input: ResMut<Input<KeyCode>>,
|
||||
keyboard_input_events: Res<Events<KeyboardInput>>,
|
||||
) {
|
||||
|
@ -53,6 +57,7 @@ pub fn keyboard_input_system(
|
|||
}
|
||||
}
|
||||
|
||||
/// The key code of a keyboard input.
|
||||
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
|
||||
#[repr(u32)]
|
||||
pub enum KeyCode {
|
||||
|
|
|
@ -10,13 +10,14 @@ pub mod prelude {
|
|||
}
|
||||
|
||||
use bevy_app::prelude::*;
|
||||
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput, KeyboardInputState};
|
||||
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput};
|
||||
use mouse::{
|
||||
mouse_button_input_system, MouseButton, MouseButtonInput, MouseButtonInputState, MouseMotion,
|
||||
mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion,
|
||||
};
|
||||
|
||||
use bevy_ecs::IntoQuerySystem;
|
||||
|
||||
/// Adds keyboard and mouse input to an App
|
||||
#[derive(Default)]
|
||||
pub struct InputPlugin;
|
||||
|
||||
|
@ -26,13 +27,11 @@ impl Plugin for InputPlugin {
|
|||
.add_event::<MouseButtonInput>()
|
||||
.add_event::<MouseMotion>()
|
||||
.init_resource::<Input<KeyCode>>()
|
||||
.init_resource::<KeyboardInputState>()
|
||||
.add_system_to_stage(
|
||||
bevy_app::stage::EVENT_UPDATE,
|
||||
keyboard_input_system.system(),
|
||||
)
|
||||
.init_resource::<Input<MouseButton>>()
|
||||
.init_resource::<MouseButtonInputState>()
|
||||
.add_system_to_stage(
|
||||
bevy_app::stage::EVENT_UPDATE,
|
||||
mouse_button_input_system.system(),
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
use super::keyboard::ElementState;
|
||||
use crate::Input;
|
||||
use bevy_app::prelude::{EventReader, Events};
|
||||
use bevy_ecs::{Res, ResMut};
|
||||
use bevy_ecs::{Res, ResMut, Local};
|
||||
use bevy_math::Vec2;
|
||||
|
||||
/// A mouse button input event
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MouseButtonInput {
|
||||
pub button: MouseButton,
|
||||
pub state: ElementState,
|
||||
}
|
||||
|
||||
/// A button on a mouse device
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum MouseButton {
|
||||
Left,
|
||||
|
@ -18,18 +20,21 @@ pub enum MouseButton {
|
|||
Other(u8),
|
||||
}
|
||||
|
||||
/// A mouse motion event
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MouseMotion {
|
||||
pub delta: Vec2,
|
||||
}
|
||||
|
||||
/// State used by the mouse button input system
|
||||
#[derive(Default)]
|
||||
pub struct MouseButtonInputState {
|
||||
mouse_button_input_event_reader: EventReader<MouseButtonInput>,
|
||||
}
|
||||
|
||||
/// Updates the Input<MouseButton> resource with the latest MouseButtonInput events
|
||||
pub fn mouse_button_input_system(
|
||||
mut state: ResMut<MouseButtonInputState>,
|
||||
mut state: Local<MouseButtonInputState>,
|
||||
mut mouse_button_input: ResMut<Input<MouseButton>>,
|
||||
mouse_button_input_events: Res<Events<MouseButtonInput>>,
|
||||
) {
|
||||
|
|
|
@ -5,11 +5,13 @@ use bevy_app::{
|
|||
};
|
||||
use bevy_ecs::{Local, Res, ResMut};
|
||||
|
||||
/// Local "exit on escape" system state
|
||||
#[derive(Default)]
|
||||
pub struct ExitOnEscapeState {
|
||||
reader: EventReader<KeyboardInput>,
|
||||
}
|
||||
|
||||
/// Sends the AppExit event whenever the "esc" key is pressed.
|
||||
pub fn exit_on_esc_system(
|
||||
mut state: Local<ExitOnEscapeState>,
|
||||
keyboard_input_events: Res<Events<KeyboardInput>>,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use crate::{Mat4, Vec3};
|
||||
|
||||
/// Generates a translation / rotation matrix that faces a given target
|
||||
pub trait FaceToward {
|
||||
/// Generates a translation / rotation matrix that faces a given target
|
||||
fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use glam::Vec2;
|
||||
use std::ops::{Add, AddAssign};
|
||||
|
||||
/// A two dimensional "size" as defined by a width and height
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct Size<T = f32> {
|
||||
pub width: T,
|
||||
|
@ -22,6 +23,7 @@ impl<T: Default> Default for Size<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A rect, as defined by its "side" locations
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct Rect<T> {
|
||||
pub left: T,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use crate::Mat4;
|
||||
use glam::Vec4;
|
||||
|
||||
/// Produces a "right handed" perspective matrix
|
||||
pub trait PerspectiveRh {
|
||||
/// Produces a "right handed" perspective matrix
|
||||
fn perspective_rh(fov_y_radians: f32, aspect_ratio: f32, z_near: f32, z_far: f32) -> Self;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
use crate::{light::Light, material::StandardMaterial, pipelines::FORWARD_PIPELINE_HANDLE};
|
||||
use crate::{light::Light, material::StandardMaterial, render_graph::FORWARD_PIPELINE_HANDLE};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_ecs::Bundle;
|
||||
use bevy_render::{
|
||||
draw::Draw,
|
||||
mesh::Mesh,
|
||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines}, prelude::MainPass,
|
||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
||||
render_graph::base::MainPass,
|
||||
};
|
||||
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
||||
|
||||
/// A component bundle for "pbr mesh" entities
|
||||
#[derive(Bundle)]
|
||||
pub struct PbrComponents {
|
||||
pub mesh: Handle<Mesh>,
|
||||
|
@ -54,6 +56,7 @@ impl Default for PbrComponents {
|
|||
}
|
||||
}
|
||||
|
||||
/// A component bundle for "light" entities
|
||||
#[derive(Bundle, Default)]
|
||||
pub struct LightComponents {
|
||||
pub light: Light,
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
pub mod entity;
|
||||
pub mod light;
|
||||
pub mod material;
|
||||
pub mod nodes;
|
||||
pub mod pipelines;
|
||||
pub mod render_graph;
|
||||
|
||||
mod entity;
|
||||
mod light;
|
||||
mod material;
|
||||
|
||||
pub use entity::*;
|
||||
pub use light::*;
|
||||
pub use material::*;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::{entity::*, light::Light, material::StandardMaterial};
|
||||
}
|
||||
|
@ -16,7 +19,7 @@ use bevy_render::{render_graph::RenderGraph, shader};
|
|||
use bevy_type_registry::RegisterType;
|
||||
use light::Light;
|
||||
use material::StandardMaterial;
|
||||
use render_graph::ForwardPbrRenderGraphBuilder;
|
||||
use render_graph::add_pbr_graph;
|
||||
|
||||
/// NOTE: this isn't PBR yet. consider this name "aspirational" :)
|
||||
#[derive(Default)]
|
||||
|
@ -32,6 +35,6 @@ impl Plugin for PbrPlugin {
|
|||
);
|
||||
let resources = app.resources();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.add_pbr_graph(resources);
|
||||
add_pbr_graph(&mut render_graph, resources);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use bevy_render::{
|
|||
use bevy_transform::components::Translation;
|
||||
use std::ops::Range;
|
||||
|
||||
/// A point light
|
||||
#[derive(Properties)]
|
||||
pub struct Light {
|
||||
pub color: Color,
|
||||
|
@ -27,7 +28,7 @@ impl Default for Light {
|
|||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct LightRaw {
|
||||
pub(crate) struct LightRaw {
|
||||
pub proj: [[f32; 4]; 4],
|
||||
pub pos: [f32; 4],
|
||||
pub color: [f32; 4],
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use bevy_asset::{self, Handle};
|
||||
use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, texture::Texture};
|
||||
|
||||
/// A material with "standard" properties used in PBR lighting
|
||||
#[derive(RenderResources, ShaderDefs)]
|
||||
pub struct StandardMaterial {
|
||||
pub albedo: Color,
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
mod lights_node;
|
||||
|
||||
pub use lights_node::*;
|
|
@ -1,3 +0,0 @@
|
|||
mod forward;
|
||||
|
||||
pub use forward::*;
|
|
@ -1,53 +0,0 @@
|
|||
use crate::{
|
||||
material::StandardMaterial,
|
||||
nodes::LightsNode,
|
||||
pipelines::{build_forward_pipeline, FORWARD_PIPELINE_HANDLE},
|
||||
};
|
||||
use bevy_asset::Assets;
|
||||
use bevy_ecs::Resources;
|
||||
use bevy_render::{
|
||||
pipeline::PipelineDescriptor,
|
||||
render_graph::{base, AssetRenderResourcesNode, RenderGraph, RenderResourcesNode},
|
||||
shader::Shader,
|
||||
};
|
||||
use bevy_transform::prelude::Transform;
|
||||
|
||||
pub mod node {
|
||||
pub const TRANSFORM: &str = "transform";
|
||||
pub const STANDARD_MATERIAL: &str = "standard_material";
|
||||
pub const LIGHTS: &str = "lights";
|
||||
}
|
||||
|
||||
pub mod uniform {
|
||||
pub const LIGHTS: &str = "Lights";
|
||||
}
|
||||
|
||||
pub trait ForwardPbrRenderGraphBuilder {
|
||||
fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ForwardPbrRenderGraphBuilder for RenderGraph {
|
||||
fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||
self.add_system_node(node::TRANSFORM, RenderResourcesNode::<Transform>::new(true));
|
||||
self.add_system_node(
|
||||
node::STANDARD_MATERIAL,
|
||||
AssetRenderResourcesNode::<StandardMaterial>::new(true),
|
||||
);
|
||||
self.add_system_node(node::LIGHTS, LightsNode::new(10));
|
||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
||||
pipelines.set(
|
||||
FORWARD_PIPELINE_HANDLE,
|
||||
build_forward_pipeline(&mut shaders),
|
||||
);
|
||||
|
||||
// TODO: replace these with "autowire" groups
|
||||
self.add_node_edge(node::STANDARD_MATERIAL, base::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
self.add_node_edge(node::TRANSFORM, base::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
self.add_node_edge(node::LIGHTS, base::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
self
|
||||
}
|
||||
}
|
|
@ -11,7 +11,8 @@ use bevy_render::{
|
|||
|
||||
pub const FORWARD_PIPELINE_HANDLE: Handle<PipelineDescriptor> =
|
||||
Handle::from_u128(131483623140127713893804825450360211204);
|
||||
pub fn build_forward_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
||||
|
||||
pub(crate) fn build_forward_pipeline(shaders: &mut Assets<Shader>) -> PipelineDescriptor {
|
||||
PipelineDescriptor {
|
||||
rasterization_state: Some(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
|
@ -13,6 +13,7 @@ use bevy_render::{
|
|||
};
|
||||
use bevy_transform::prelude::*;
|
||||
|
||||
/// A Render Graph [Node] that write light data from the ECS to GPU buffers
|
||||
#[derive(Default)]
|
||||
pub struct LightsNode {
|
||||
command_queue: CommandQueue,
|
||||
|
@ -43,7 +44,7 @@ impl Node for LightsNode {
|
|||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct LightCount {
|
||||
struct LightCount {
|
||||
pub num_lights: [u32; 4],
|
||||
}
|
||||
|
||||
|
@ -65,6 +66,7 @@ impl SystemNode for LightsNode {
|
|||
}
|
||||
}
|
||||
|
||||
/// Local "lights node system" state
|
||||
#[derive(Default)]
|
||||
pub struct LightsNodeSystemState {
|
||||
light_buffer: Option<BufferId>,
|
50
crates/bevy_pbr/src/render_graph/mod.rs
Normal file
50
crates/bevy_pbr/src/render_graph/mod.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
mod forward_pipeline;
|
||||
mod lights_node;
|
||||
|
||||
pub use forward_pipeline::*;
|
||||
pub use lights_node::*;
|
||||
|
||||
/// the names of pbr graph nodes
|
||||
pub mod node {
|
||||
pub const TRANSFORM: &str = "transform";
|
||||
pub const STANDARD_MATERIAL: &str = "standard_material";
|
||||
pub const LIGHTS: &str = "lights";
|
||||
}
|
||||
|
||||
/// the names of pbr uniforms
|
||||
pub mod uniform {
|
||||
pub const LIGHTS: &str = "Lights";
|
||||
}
|
||||
|
||||
use bevy_asset::Assets;
|
||||
use bevy_ecs::Resources;
|
||||
use bevy_render::{
|
||||
pipeline::PipelineDescriptor,
|
||||
render_graph::{base, AssetRenderResourcesNode, RenderGraph, RenderResourcesNode},
|
||||
shader::Shader,
|
||||
};
|
||||
use bevy_transform::prelude::Transform;
|
||||
use crate::prelude::StandardMaterial;
|
||||
|
||||
pub(crate) fn add_pbr_graph(graph: &mut RenderGraph, resources: &Resources) {
|
||||
graph.add_system_node(node::TRANSFORM, RenderResourcesNode::<Transform>::new(true));
|
||||
graph.add_system_node(
|
||||
node::STANDARD_MATERIAL,
|
||||
AssetRenderResourcesNode::<StandardMaterial>::new(true),
|
||||
);
|
||||
graph.add_system_node(node::LIGHTS, LightsNode::new(10));
|
||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
||||
pipelines.set(
|
||||
FORWARD_PIPELINE_HANDLE,
|
||||
build_forward_pipeline(&mut shaders),
|
||||
);
|
||||
|
||||
// TODO: replace these with "autowire" groups
|
||||
graph.add_node_edge(node::STANDARD_MATERIAL, base::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
graph.add_node_edge(node::TRANSFORM, base::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
graph.add_node_edge(node::LIGHTS, base::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
}
|
|
@ -10,6 +10,7 @@ use bevy_property::Property;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::{Add, AddAssign, Mul, MulAssign};
|
||||
|
||||
/// A RGBA color
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Property)]
|
||||
pub struct Color {
|
||||
|
@ -178,6 +179,7 @@ impl Bytes for ColorSource {
|
|||
}
|
||||
}
|
||||
|
||||
/// A source of color
|
||||
pub enum ColorSource {
|
||||
Color(Color),
|
||||
Texture(Handle<Texture>),
|
||||
|
|
|
@ -18,6 +18,7 @@ use bevy_property::Properties;
|
|||
use std::{any::TypeId, ops::Range, sync::Arc};
|
||||
use thiserror::Error;
|
||||
|
||||
/// A queued command for the renderer
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum RenderCommand {
|
||||
SetPipeline {
|
||||
|
@ -44,6 +45,7 @@ pub enum RenderCommand {
|
|||
},
|
||||
}
|
||||
|
||||
/// A component that indicates how to draw an entity.
|
||||
#[derive(Properties)]
|
||||
pub struct Draw {
|
||||
pub is_visible: bool,
|
||||
|
|
|
@ -4,14 +4,12 @@ use crate::{
|
|||
render_graph::base,
|
||||
Draw, Mesh,
|
||||
};
|
||||
use base::MainPass;
|
||||
use bevy_asset::Handle;
|
||||
use bevy_ecs::Bundle;
|
||||
use bevy_transform::components::{Rotation, Scale, Transform, Translation};
|
||||
use bevy_property::Properties;
|
||||
|
||||
#[derive(Default, Properties)]
|
||||
pub struct MainPass;
|
||||
|
||||
/// A component bundle for "mesh" entities
|
||||
#[derive(Bundle, Default)]
|
||||
pub struct MeshComponents {
|
||||
pub mesh: Handle<Mesh>,
|
||||
|
@ -24,6 +22,7 @@ pub struct MeshComponents {
|
|||
pub scale: Scale,
|
||||
}
|
||||
|
||||
/// A component bundle for "3d camera" entities
|
||||
#[derive(Bundle)]
|
||||
pub struct Camera3dComponents {
|
||||
pub camera: Camera,
|
||||
|
@ -52,6 +51,7 @@ impl Default for Camera3dComponents {
|
|||
}
|
||||
}
|
||||
|
||||
/// A component bundle for "2d camera" entities
|
||||
#[derive(Bundle)]
|
||||
pub struct Camera2dComponents {
|
||||
pub camera: Camera,
|
||||
|
|
|
@ -27,13 +27,18 @@ pub mod prelude {
|
|||
}
|
||||
|
||||
use crate::prelude::*;
|
||||
use base::Msaa;
|
||||
use base::{MainPass, Msaa};
|
||||
use bevy_app::prelude::*;
|
||||
use bevy_asset::AddAsset;
|
||||
use bevy_ecs::{IntoQuerySystem, IntoThreadLocalSystem};
|
||||
use bevy_type_registry::RegisterType;
|
||||
use camera::{ActiveCameras, Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities};
|
||||
use pipeline::{PipelineCompiler, PipelineDescriptor, VertexBufferDescriptors, ShaderSpecialization, PipelineSpecialization, DynamicBinding, PrimitiveTopology};
|
||||
use camera::{
|
||||
ActiveCameras, Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities,
|
||||
};
|
||||
use pipeline::{
|
||||
DynamicBinding, PipelineCompiler, PipelineDescriptor, PipelineSpecialization,
|
||||
PrimitiveTopology, ShaderSpecialization, VertexBufferDescriptors,
|
||||
};
|
||||
use render_graph::{
|
||||
base::{self, BaseRenderGraphBuilder, BaseRenderGraphConfig},
|
||||
RenderGraph,
|
||||
|
@ -42,6 +47,7 @@ use renderer::{AssetRenderResourceBindings, RenderResourceBindings};
|
|||
use std::ops::Range;
|
||||
use texture::{HdrTextureLoader, ImageTextureLoader, TextureResourceSystemState};
|
||||
|
||||
/// The names of "render" App stages
|
||||
pub mod stage {
|
||||
/// Stage where render resources are set up
|
||||
pub static RENDER_RESOURCE: &str = "render_resource";
|
||||
|
@ -53,6 +59,7 @@ pub mod stage {
|
|||
pub static POST_RENDER: &str = "post_render";
|
||||
}
|
||||
|
||||
/// Adds core render types and systems to an App
|
||||
pub struct RenderPlugin {
|
||||
/// configures the "base render graph". If this is not `None`, the "base render graph" will be added
|
||||
pub base_render_graph_config: Option<BaseRenderGraphConfig>,
|
||||
|
|
|
@ -7,12 +7,16 @@ use crate::{
|
|||
LoadOp, Operations, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
||||
},
|
||||
prelude::MainPass,
|
||||
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||
Color,
|
||||
};
|
||||
use bevy_property::Properties;
|
||||
use bevy_window::WindowId;
|
||||
|
||||
/// A component that indicates that an entity should be drawn in the "main pass"
|
||||
#[derive(Default, Properties)]
|
||||
pub struct MainPass;
|
||||
|
||||
pub struct Msaa {
|
||||
pub samples: u32,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ use super::ShaderLayout;
|
|||
use bevy_asset::Handle;
|
||||
use glsl_to_spirv::compile;
|
||||
use std::{io::Read, marker::Copy};
|
||||
|
||||
/// The stage of a shader
|
||||
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)]
|
||||
pub enum ShaderStage {
|
||||
Vertex,
|
||||
|
@ -19,7 +21,7 @@ impl Into<glsl_to_spirv::ShaderType> for ShaderStage {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn glsl_to_spirv(
|
||||
fn glsl_to_spirv(
|
||||
glsl_source: &str,
|
||||
stage: ShaderStage,
|
||||
shader_defs: Option<&[String]>,
|
||||
|
@ -41,6 +43,7 @@ fn bytes_to_words(bytes: &[u8]) -> Vec<u32> {
|
|||
words
|
||||
}
|
||||
|
||||
/// The full "source" of a shader
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum ShaderSource {
|
||||
Spirv(Vec<u32>),
|
||||
|
@ -53,11 +56,11 @@ impl ShaderSource {
|
|||
}
|
||||
}
|
||||
|
||||
/// A shader, as defined by its [ShaderSource] and [ShaderStage]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Shader {
|
||||
pub source: ShaderSource,
|
||||
pub stage: ShaderStage,
|
||||
// TODO: add "precompile" flag?
|
||||
}
|
||||
|
||||
impl Shader {
|
||||
|
@ -98,6 +101,7 @@ impl Shader {
|
|||
}
|
||||
}
|
||||
|
||||
/// All stages in a shader program
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ShaderStages {
|
||||
pub vertex: Handle<Shader>,
|
||||
|
|
|
@ -4,16 +4,19 @@ use crate::{pipeline::RenderPipelines, Texture};
|
|||
pub use bevy_derive::ShaderDefs;
|
||||
use bevy_ecs::{Query, Res};
|
||||
|
||||
/// Something that can either be "defined" or "not defined". This is used to determine if a "shader def" should be considered "defined"
|
||||
pub trait ShaderDef {
|
||||
fn is_defined(&self) -> bool;
|
||||
}
|
||||
|
||||
/// A collection of "shader defs", which define compile time definitions for shaders.
|
||||
pub trait ShaderDefs {
|
||||
fn shader_defs_len(&self) -> usize;
|
||||
fn get_shader_def(&self, index: usize) -> Option<&str>;
|
||||
fn iter_shader_defs(&self) -> ShaderDefIterator;
|
||||
}
|
||||
|
||||
/// Iterates over all [ShaderDef] items in [ShaderDefs]
|
||||
pub struct ShaderDefIterator<'a> {
|
||||
shader_defs: &'a dyn ShaderDefs,
|
||||
index: usize,
|
||||
|
@ -56,6 +59,7 @@ impl ShaderDef for Option<Handle<Texture>> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Updates [RenderPipelines] with the latest [ShaderDefs]
|
||||
pub fn shader_defs_system<T>(mut query: Query<(&T, &mut RenderPipelines)>)
|
||||
where
|
||||
T: ShaderDefs + Send + Sync + 'static,
|
||||
|
@ -73,6 +77,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Clears each [RenderPipelines]' shader defs collection
|
||||
pub fn clear_shader_defs_system(mut query: Query<&mut RenderPipelines>) {
|
||||
for mut render_pipelines in &mut query.iter() {
|
||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
||||
|
@ -85,6 +90,7 @@ pub fn clear_shader_defs_system(mut query: Query<&mut RenderPipelines>) {
|
|||
}
|
||||
}
|
||||
|
||||
/// Updates [RenderPipelines] with the latest [ShaderDefs] from a given asset type
|
||||
pub fn asset_shader_defs_system<T>(
|
||||
assets: Res<Assets<T>>,
|
||||
mut query: Query<(&Handle<T>, &mut RenderPipelines)>,
|
||||
|
|
|
@ -15,6 +15,7 @@ use spirv_reflect::{
|
|||
};
|
||||
use std::collections::HashSet;
|
||||
|
||||
/// Defines the memory layout of a shader
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct ShaderLayout {
|
||||
pub bind_groups: Vec<BindGroupDescriptor>,
|
||||
|
|
|
@ -4,6 +4,7 @@ use bevy_asset::AssetLoader;
|
|||
use bevy_math::Vec2;
|
||||
use std::path::Path;
|
||||
|
||||
/// Loads HDR textures as Texture assets
|
||||
#[derive(Clone, Default)]
|
||||
pub struct HdrTextureLoader;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::Texture;
|
||||
use crate::pipeline::CompareFunction;
|
||||
|
||||
/// Describes a sampler
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SamplerDescriptor {
|
||||
pub address_mode_u: AddressMode,
|
||||
|
@ -49,6 +50,7 @@ impl From<&Texture> for SamplerDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
/// How edges should be handled in texture addressing.
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum AddressMode {
|
||||
ClampToEdge = 0,
|
||||
|
@ -62,6 +64,7 @@ impl Default for AddressMode {
|
|||
}
|
||||
}
|
||||
|
||||
/// Texel mixing mode when sampling between texels.
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum FilterMode {
|
||||
Nearest = 0,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use super::{Extent3d, Texture, TextureDimension, TextureFormat, TextureUsage};
|
||||
|
||||
/// Describes a texture
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct TextureDescriptor {
|
||||
pub size: Extent3d,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// NOTE: These are currently just copies of the wgpu types, but they might change in the future
|
||||
|
||||
/// Dimensions of a particular texture view.
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum TextureViewDimension {
|
||||
D1,
|
||||
|
@ -10,6 +11,7 @@ pub enum TextureViewDimension {
|
|||
D3,
|
||||
}
|
||||
|
||||
/// Dimensionality of a texture.
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum TextureDimension {
|
||||
D1,
|
||||
|
@ -25,6 +27,7 @@ pub struct Extent3d {
|
|||
pub depth: u32,
|
||||
}
|
||||
|
||||
/// Type of data shaders will read from a texture.
|
||||
#[derive(Copy, Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum TextureComponentType {
|
||||
Float,
|
||||
|
@ -37,6 +40,10 @@ pub struct PixelInfo {
|
|||
pub num_components: usize,
|
||||
}
|
||||
|
||||
/// Underlying texture data format.
|
||||
///
|
||||
/// If there is a conversion in the format (such as srgb -> linear), The conversion listed is for
|
||||
/// loading from texture in a shader. When writing to the texture, the opposite conversion takes place.
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub enum TextureFormat {
|
||||
// Normal 8 bit formats
|
||||
|
|
|
@ -7,7 +7,8 @@ use bevy_ecs::Bundle;
|
|||
use bevy_render::{
|
||||
mesh::Mesh,
|
||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
||||
prelude::{Draw, MainPass},
|
||||
prelude::Draw,
|
||||
render_graph::base::MainPass,
|
||||
};
|
||||
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
||||
|
||||
|
|
|
@ -3,12 +3,14 @@ use bevy::{
|
|||
render::{
|
||||
camera::{ActiveCameras, Camera},
|
||||
pass::*,
|
||||
render_graph::{CameraNode, PassNode, RenderGraph, WindowSwapChainNode, WindowTextureNode},
|
||||
texture::{TextureDescriptor, TextureFormat, TextureUsage},
|
||||
render_graph::{
|
||||
base::MainPass, CameraNode, PassNode, RenderGraph, WindowSwapChainNode,
|
||||
WindowTextureNode,
|
||||
},
|
||||
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||
},
|
||||
window::{CreateWindow, WindowDescriptor, WindowId},
|
||||
};
|
||||
use bevy_render::texture::{Extent3d, TextureDimension};
|
||||
|
||||
/// This example creates a second window and draws a mesh from two different cameras.
|
||||
fn main() {
|
||||
|
|
Loading…
Reference in a new issue