add more doc comments and clean up some public exports
This commit is contained in:
parent
f963cd41dc
commit
3d09459813
@ -1,6 +1,26 @@
|
|||||||
use crate::app_builder::AppBuilder;
|
use crate::app_builder::AppBuilder;
|
||||||
use bevy_ecs::{ParallelExecutor, Resources, Schedule, World};
|
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 struct App {
|
||||||
pub world: World,
|
pub world: World,
|
||||||
pub resources: Resources,
|
pub resources: Resources,
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::{App, AppExit},
|
app::{App, AppExit},
|
||||||
event::Events,
|
event::Events,
|
||||||
plugin::{load_plugin, Plugin},
|
plugin::{dynamically_load_plugin, Plugin},
|
||||||
stage, startup_stage,
|
stage, startup_stage,
|
||||||
};
|
};
|
||||||
use bevy_ecs::{FromResources, IntoQuerySystem, Resources, System, World};
|
use bevy_ecs::{FromResources, IntoQuerySystem, Resources, System, World};
|
||||||
|
|
||||||
|
/// Configure [App]s using the builder pattern
|
||||||
pub struct AppBuilder {
|
pub struct AppBuilder {
|
||||||
pub app: App,
|
pub app: App,
|
||||||
}
|
}
|
||||||
@ -220,7 +221,7 @@ impl AppBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_plugin(&mut self, path: &str) -> &mut Self {
|
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());
|
log::debug!("loaded plugin: {}", plugin.name());
|
||||||
plugin.build(self);
|
plugin.build(self);
|
||||||
self
|
self
|
||||||
|
@ -82,6 +82,7 @@ fn map_instance_event<T>(event_instance: &EventInstance<T>) -> &T {
|
|||||||
&event_instance.event
|
&event_instance.event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads events of type `T` in order and tracks which events have already been read.
|
||||||
pub struct EventReader<T> {
|
pub struct EventReader<T> {
|
||||||
last_event_count: usize,
|
last_event_count: usize,
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
|
/// The names of the default App stages
|
||||||
pub mod stage;
|
pub mod stage;
|
||||||
|
/// The names of the default App startup stages
|
||||||
|
pub mod startup_stage;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod app_builder;
|
mod app_builder;
|
||||||
mod event;
|
mod event;
|
||||||
mod plugin;
|
mod plugin;
|
||||||
mod schedule_runner;
|
mod schedule_runner;
|
||||||
mod startup_stage;
|
|
||||||
|
|
||||||
pub use app::*;
|
pub use app::*;
|
||||||
pub use app_builder::*;
|
pub use app_builder::*;
|
||||||
@ -13,7 +15,6 @@ pub use bevy_derive::DynamicPlugin;
|
|||||||
pub use event::*;
|
pub use event::*;
|
||||||
pub use plugin::*;
|
pub use plugin::*;
|
||||||
pub use schedule_runner::*;
|
pub use schedule_runner::*;
|
||||||
pub use startup_stage::*;
|
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
|
@ -2,6 +2,9 @@ use crate::AppBuilder;
|
|||||||
use libloading::{Library, Symbol};
|
use libloading::{Library, Symbol};
|
||||||
use std::any::Any;
|
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 {
|
pub trait Plugin: Any + Send + Sync {
|
||||||
fn build(&self, app: &mut AppBuilder);
|
fn build(&self, app: &mut AppBuilder);
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
@ -11,7 +14,8 @@ pub trait Plugin: Any + Send + Sync {
|
|||||||
|
|
||||||
pub type CreatePlugin = unsafe fn() -> *mut dyn Plugin;
|
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();
|
let lib = Library::new(path).unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use std::{thread, time::Duration};
|
use std::{thread, time::Duration};
|
||||||
|
|
||||||
|
/// Determines the method used to run an [App]'s `Schedule`
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum RunMode {
|
pub enum RunMode {
|
||||||
Loop { wait: Option<Duration> },
|
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)]
|
#[derive(Default)]
|
||||||
pub struct ScheduleRunnerPlugin {
|
pub struct ScheduleRunnerPlugin {
|
||||||
pub run_mode: RunMode,
|
pub run_mode: RunMode,
|
||||||
|
@ -14,7 +14,10 @@ use std::{
|
|||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// The type used for asset versioning
|
||||||
pub type AssetVersion = usize;
|
pub type AssetVersion = usize;
|
||||||
|
|
||||||
|
/// Errors that occur while loading assets with an AssetServer
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum AssetServerError {
|
pub enum AssetServerError {
|
||||||
#[error("Asset folder path is not a directory.")]
|
#[error("Asset folder path is not a directory.")]
|
||||||
@ -39,13 +42,15 @@ struct LoaderThread {
|
|||||||
requests: Arc<RwLock<Vec<LoadRequest>>>,
|
requests: Arc<RwLock<Vec<LoadRequest>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Info about a specific asset, such as its path and its current load state
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct AssetInfo {
|
pub struct AssetInfo {
|
||||||
handle_id: HandleId,
|
pub handle_id: HandleId,
|
||||||
path: PathBuf,
|
pub path: PathBuf,
|
||||||
load_state: LoadState,
|
pub load_state: LoadState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The load state of an asset
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum LoadState {
|
pub enum LoadState {
|
||||||
Loading(AssetVersion),
|
Loading(AssetVersion),
|
||||||
@ -63,6 +68,7 @@ impl LoadState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Loads assets from the filesystem on background threads
|
||||||
pub struct AssetServer {
|
pub struct AssetServer {
|
||||||
asset_folders: RwLock<Vec<PathBuf>>,
|
asset_folders: RwLock<Vec<PathBuf>>,
|
||||||
loader_threads: RwLock<Vec<LoaderThread>>,
|
loader_threads: RwLock<Vec<LoaderThread>>,
|
||||||
|
@ -7,12 +7,14 @@ use bevy_ecs::{FromResources, IntoQuerySystem, ResMut, Resource};
|
|||||||
use bevy_type_registry::RegisterType;
|
use bevy_type_registry::RegisterType;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
/// Events that happen on assets of type `T`
|
||||||
pub enum AssetEvent<T: Resource> {
|
pub enum AssetEvent<T: Resource> {
|
||||||
Created { handle: Handle<T> },
|
Created { handle: Handle<T> },
|
||||||
Modified { handle: Handle<T> },
|
Modified { handle: Handle<T> },
|
||||||
Removed { handle: Handle<T> },
|
Removed { handle: Handle<T> },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Stores Assets of a given type and tracks changes to them.
|
||||||
pub struct Assets<T: Resource> {
|
pub struct Assets<T: Resource> {
|
||||||
assets: HashMap<Handle<T>, T>,
|
assets: HashMap<Handle<T>, T>,
|
||||||
events: Events<AssetEvent<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 {
|
pub trait AddAsset {
|
||||||
fn add_asset<T>(&mut self) -> &mut Self
|
fn add_asset<T>(&mut self) -> &mut Self
|
||||||
where
|
where
|
||||||
|
@ -2,7 +2,7 @@ use crossbeam_channel::Receiver;
|
|||||||
use notify::{Event, RecommendedWatcher, RecursiveMode, Result, Watcher};
|
use notify::{Event, RecommendedWatcher, RecursiveMode, Result, Watcher};
|
||||||
use std::path::Path;
|
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 struct FilesystemWatcher {
|
||||||
pub watcher: RecommendedWatcher,
|
pub watcher: RecommendedWatcher,
|
||||||
pub receiver: Receiver<Result<Event>>,
|
pub receiver: Receiver<Result<Event>>,
|
||||||
|
@ -8,10 +8,13 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::{any::TypeId, marker::PhantomData};
|
use std::{any::TypeId, marker::PhantomData};
|
||||||
use uuid::Uuid;
|
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)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, Property)]
|
||||||
pub struct HandleId(pub Uuid);
|
pub struct HandleId(pub Uuid);
|
||||||
pub const DEFAULT_HANDLE_ID: HandleId =
|
|
||||||
HandleId(Uuid::from_u128(240940089166493627844978703213080810552));
|
|
||||||
|
|
||||||
impl HandleId {
|
impl HandleId {
|
||||||
pub fn new() -> 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)]
|
#[derive(Properties)]
|
||||||
pub struct Handle<T>
|
pub struct Handle<T>
|
||||||
where
|
where
|
||||||
@ -156,6 +162,9 @@ impl<T> Copy for Handle<T> {}
|
|||||||
unsafe impl<T> Send for Handle<T> {}
|
unsafe impl<T> Send for Handle<T> {}
|
||||||
unsafe impl<T> Sync 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)]
|
#[derive(Hash, Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
pub struct HandleUntyped {
|
pub struct HandleUntyped {
|
||||||
pub id: HandleId,
|
pub id: HandleId,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
#[cfg(feature = "filesystem_watcher")]
|
||||||
|
mod filesystem_watcher;
|
||||||
mod asset_server;
|
mod asset_server;
|
||||||
mod assets;
|
mod assets;
|
||||||
#[cfg(feature = "filesystem_watcher")]
|
|
||||||
pub mod filesystem_watcher;
|
|
||||||
mod handle;
|
mod handle;
|
||||||
mod load_request;
|
mod load_request;
|
||||||
mod loader;
|
mod loader;
|
||||||
@ -12,6 +12,7 @@ pub use handle::*;
|
|||||||
pub use load_request::*;
|
pub use load_request::*;
|
||||||
pub use loader::*;
|
pub use loader::*;
|
||||||
|
|
||||||
|
/// The names of asset stages in an App Schedule
|
||||||
pub mod stage {
|
pub mod stage {
|
||||||
pub const LOAD_ASSETS: &str = "load_assets";
|
pub const LOAD_ASSETS: &str = "load_assets";
|
||||||
pub const ASSET_EVENTS: &str = "asset_events";
|
pub const ASSET_EVENTS: &str = "asset_events";
|
||||||
@ -25,6 +26,8 @@ use bevy_app::{prelude::Plugin, AppBuilder};
|
|||||||
use bevy_ecs::IntoQuerySystem;
|
use bevy_ecs::IntoQuerySystem;
|
||||||
use bevy_type_registry::RegisterType;
|
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)]
|
#[derive(Default)]
|
||||||
pub struct AssetPlugin;
|
pub struct AssetPlugin;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ use fs::File;
|
|||||||
use io::Read;
|
use io::Read;
|
||||||
use std::{fs, io, path::PathBuf};
|
use std::{fs, io, path::PathBuf};
|
||||||
|
|
||||||
|
/// A request from an [AssetServer](crate::AssetServer) to load an asset.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LoadRequest {
|
pub struct LoadRequest {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
@ -13,12 +14,13 @@ pub struct LoadRequest {
|
|||||||
pub version: AssetVersion,
|
pub version: AssetVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handles load requests from an AssetServer
|
||||||
pub trait AssetLoadRequestHandler: Send + Sync + 'static {
|
pub trait AssetLoadRequestHandler: Send + Sync + 'static {
|
||||||
fn handle_request(&self, load_request: &LoadRequest);
|
fn handle_request(&self, load_request: &LoadRequest);
|
||||||
fn extensions(&self) -> &[&str];
|
fn extensions(&self) -> &[&str];
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ChannelAssetHandler<TLoader, TAsset>
|
pub(crate) struct ChannelAssetHandler<TLoader, TAsset>
|
||||||
where
|
where
|
||||||
TLoader: AssetLoader<TAsset>,
|
TLoader: AssetLoader<TAsset>,
|
||||||
TAsset: 'static,
|
TAsset: 'static,
|
||||||
|
@ -10,6 +10,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Errors that occur while loading assets
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum AssetLoadError {
|
pub enum AssetLoadError {
|
||||||
#[error("Encountered an io error while loading asset.")]
|
#[error("Encountered an io error while loading asset.")]
|
||||||
@ -18,6 +19,7 @@ pub enum AssetLoadError {
|
|||||||
LoaderError(#[from] anyhow::Error),
|
LoaderError(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A loader for a given asset of type `T`
|
||||||
pub trait AssetLoader<T>: Send + Sync + 'static {
|
pub trait AssetLoader<T>: Send + Sync + 'static {
|
||||||
fn from_bytes(&self, asset_path: &Path, bytes: Vec<u8>) -> Result<T, anyhow::Error>;
|
fn from_bytes(&self, asset_path: &Path, bytes: Vec<u8>) -> Result<T, anyhow::Error>;
|
||||||
fn extensions(&self) -> &[&str];
|
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 struct AssetResult<T: 'static> {
|
||||||
pub result: Result<T, AssetLoadError>,
|
pub result: Result<T, AssetLoadError>,
|
||||||
pub handle: Handle<T>,
|
pub handle: Handle<T>,
|
||||||
@ -37,6 +40,7 @@ pub struct AssetResult<T: 'static> {
|
|||||||
pub version: AssetVersion,
|
pub version: AssetVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A channel to send and receive [AssetResult]s
|
||||||
pub struct AssetChannel<T: 'static> {
|
pub struct AssetChannel<T: 'static> {
|
||||||
pub sender: Sender<AssetResult<T>>,
|
pub sender: Sender<AssetResult<T>>,
|
||||||
pub receiver: Receiver<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>(
|
pub fn update_asset_storage_system<T: Resource>(
|
||||||
asset_channel: Res<AssetChannel<T>>,
|
asset_channel: Res<AssetChannel<T>>,
|
||||||
asset_server: Res<AssetServer>,
|
asset_server: Res<AssetServer>,
|
||||||
|
@ -4,6 +4,7 @@ use bevy_ecs::Res;
|
|||||||
use rodio::{Decoder, Device, Sink};
|
use rodio::{Decoder, Device, Sink};
|
||||||
use std::{collections::VecDeque, io::Cursor, sync::RwLock};
|
use std::{collections::VecDeque, io::Cursor, sync::RwLock};
|
||||||
|
|
||||||
|
/// Used to play audio on the current "audio device"
|
||||||
pub struct AudioOutput {
|
pub struct AudioOutput {
|
||||||
device: Device,
|
device: Device,
|
||||||
queue: RwLock<VecDeque<Handle<AudioSource>>>,
|
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_sources: Res<Assets<AudioSource>>,
|
||||||
audio_output: Res<AudioOutput>,
|
audio_output: Res<AudioOutput>,
|
||||||
) {
|
) {
|
||||||
|
@ -2,6 +2,7 @@ use anyhow::Result;
|
|||||||
use bevy_asset::AssetLoader;
|
use bevy_asset::AssetLoader;
|
||||||
use std::{path::Path, sync::Arc};
|
use std::{path::Path, sync::Arc};
|
||||||
|
|
||||||
|
/// A source of audio data
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AudioSource {
|
pub struct AudioSource {
|
||||||
pub bytes: Arc<Vec<u8>>,
|
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)]
|
#[derive(Default)]
|
||||||
pub struct Mp3Loader;
|
pub struct Mp3Loader;
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ use bevy_app::prelude::*;
|
|||||||
use bevy_asset::AddAsset;
|
use bevy_asset::AddAsset;
|
||||||
use bevy_ecs::IntoQuerySystem;
|
use bevy_ecs::IntoQuerySystem;
|
||||||
|
|
||||||
|
/// Adds support for audio playback to an App
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct AudioPlugin;
|
pub struct AudioPlugin;
|
||||||
|
|
||||||
|
@ -2,11 +2,16 @@ use bevy_math::{Mat4, Vec2, Vec3, Vec4};
|
|||||||
|
|
||||||
pub use bevy_derive::Bytes;
|
pub use bevy_derive::Bytes;
|
||||||
|
|
||||||
|
/// Converts the implementing type to bytes by writing them to a given buffer
|
||||||
pub trait Bytes {
|
pub trait Bytes {
|
||||||
|
/// Converts the implementing type to bytes by writing them to a given buffer
|
||||||
fn write_bytes(&self, buffer: &mut [u8]);
|
fn write_bytes(&self, buffer: &mut [u8]);
|
||||||
|
|
||||||
|
/// The number of bytes that will be written when calling `write_bytes`
|
||||||
fn byte_len(&self) -> usize;
|
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
|
pub unsafe trait Byteable
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
@ -27,11 +32,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads the implementing type as a byte array reference
|
||||||
pub trait AsBytes {
|
pub trait AsBytes {
|
||||||
|
/// Reads the implementing type as a byte array reference
|
||||||
fn as_bytes(&self) -> &[u8];
|
fn as_bytes(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts a byte array to `Self`
|
||||||
pub trait FromBytes {
|
pub trait FromBytes {
|
||||||
|
/// Converts a byte array to `Self`
|
||||||
fn from_bytes(bytes: &[u8]) -> Self;
|
fn from_bytes(bytes: &[u8]) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,9 @@ use std::{
|
|||||||
ops::Neg,
|
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)]
|
#[derive(Debug, Copy, Clone, PartialOrd)]
|
||||||
pub struct FloatOrd(pub f32);
|
pub struct FloatOrd(pub f32);
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ use std::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A collection of labels
|
||||||
#[derive(Default, Properties)]
|
#[derive(Default, Properties)]
|
||||||
pub struct Labels {
|
pub struct Labels {
|
||||||
labels: HashSet<Cow<'static, str>>,
|
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)]
|
#[derive(Default)]
|
||||||
pub struct EntityLabels {
|
pub struct EntityLabels {
|
||||||
label_entities: HashMap<Cow<'static, str>, Vec<Entity>>,
|
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>,
|
mut entity_labels: ResMut<EntityLabels>,
|
||||||
// TODO: use change tracking when add/remove events are added
|
// TODO: use change tracking when add/remove events are added
|
||||||
// mut query: Query<(Entity, Changed<Labels>)>,
|
// mut query: Query<(Entity, Changed<Labels>)>,
|
||||||
|
@ -17,6 +17,7 @@ use bevy_ecs::prelude::*;
|
|||||||
use bevy_math::{Mat3, Mat4, Quat, Vec2, Vec3};
|
use bevy_math::{Mat3, Mat4, Quat, Vec2, Vec3};
|
||||||
use bevy_type_registry::RegisterType;
|
use bevy_type_registry::RegisterType;
|
||||||
|
|
||||||
|
/// Adds core functionality to Apps.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct CorePlugin;
|
pub struct CorePlugin;
|
||||||
|
|
||||||
@ -32,6 +33,7 @@ impl Plugin for CorePlugin {
|
|||||||
.register_property::<Quat>()
|
.register_property::<Quat>()
|
||||||
.register_property::<Option<String>>()
|
.register_property::<Option<String>>()
|
||||||
.add_system_to_stage(stage::FIRST, time_system.system())
|
.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 bevy_ecs::ResMut;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
/// Tracks elapsed time since the last update and since the App has started
|
||||||
pub struct Time {
|
pub struct Time {
|
||||||
pub delta: Duration,
|
pub delta: Duration,
|
||||||
pub instant: Option<Instant>,
|
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();
|
time.update();
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ use bevy_ecs::prelude::*;
|
|||||||
use bevy_property::Properties;
|
use bevy_property::Properties;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// Tracks elapsed time. Enters the finished state once `duration` is reached.
|
||||||
#[derive(Clone, Debug, Default, Properties)]
|
#[derive(Clone, Debug, Default, Properties)]
|
||||||
pub struct Timer {
|
pub struct Timer {
|
||||||
pub elapsed: f32,
|
pub elapsed: f32,
|
||||||
@ -11,16 +12,16 @@ pub struct Timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Timer {
|
impl Timer {
|
||||||
pub fn from_seconds(seconds: f32) -> Self {
|
pub fn new(duration: Duration) -> Self {
|
||||||
Timer {
|
Timer {
|
||||||
duration: seconds,
|
duration: duration.as_secs_f32(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(duration: Duration) -> Self {
|
pub fn from_seconds(seconds: f32) -> Self {
|
||||||
Timer {
|
Timer {
|
||||||
duration: duration.as_secs_f32(),
|
duration: seconds,
|
||||||
..Default::default()
|
..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() {
|
for mut timer in &mut query.iter() {
|
||||||
timer.tick(time.delta_seconds);
|
timer.tick(time.delta_seconds);
|
||||||
}
|
}
|
||||||
|
@ -11,37 +11,47 @@ mod shader_defs;
|
|||||||
|
|
||||||
use proc_macro::TokenStream;
|
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))]
|
#[proc_macro_derive(FromResources, attributes(as_crate))]
|
||||||
pub fn derive_from_resources(input: TokenStream) -> TokenStream {
|
pub fn derive_from_resources(input: TokenStream) -> TokenStream {
|
||||||
resource::derive_from_resources(input)
|
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))]
|
#[proc_macro_derive(Bytes, attributes(as_crate))]
|
||||||
pub fn derive_bytes(input: TokenStream) -> TokenStream {
|
pub fn derive_bytes(input: TokenStream) -> TokenStream {
|
||||||
bytes::derive_bytes(input)
|
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))]
|
#[proc_macro_derive(RenderResources, attributes(render_resources, as_crate))]
|
||||||
pub fn derive_render_resources(input: TokenStream) -> TokenStream {
|
pub fn derive_render_resources(input: TokenStream) -> TokenStream {
|
||||||
render_resources::derive_render_resources(input)
|
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))]
|
#[proc_macro_derive(RenderResource, attributes(as_crate))]
|
||||||
pub fn derive_render_resource(input: TokenStream) -> TokenStream {
|
pub fn derive_render_resource(input: TokenStream) -> TokenStream {
|
||||||
render_resource::derive_render_resource(input)
|
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))]
|
#[proc_macro_derive(ShaderDefs, attributes(shader_def, as_crate))]
|
||||||
pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
|
pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
|
||||||
shader_defs::derive_shader_defs(input)
|
shader_defs::derive_shader_defs(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the AsVertexBufferDescriptor trait.
|
||||||
#[proc_macro_derive(AsVertexBufferDescriptor, attributes(vertex, as_crate))]
|
#[proc_macro_derive(AsVertexBufferDescriptor, attributes(vertex, as_crate))]
|
||||||
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
||||||
as_vertex_buffer_descriptor::derive_as_vertex_buffer_descriptor(input)
|
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)]
|
#[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)
|
app_plugin::derive_dynamic_plugin(input)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
/// Unique identifier for a [Diagnostic]
|
||||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
|
||||||
pub struct DiagnosticId(pub Uuid);
|
pub struct DiagnosticId(pub Uuid);
|
||||||
|
|
||||||
@ -19,12 +20,15 @@ impl Default for DiagnosticId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A single measurement of a [Diagnostic]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DiagnosticMeasurement {
|
pub struct DiagnosticMeasurement {
|
||||||
pub time: SystemTime,
|
pub time: SystemTime,
|
||||||
pub value: f64,
|
pub value: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A timeline of [DiagnosticMeasurement]s of a specific type.
|
||||||
|
/// Diagnostic examples: frames per second, CPU usage, network latency
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Diagnostic {
|
pub struct Diagnostic {
|
||||||
pub id: DiagnosticId,
|
pub id: DiagnosticId,
|
||||||
@ -97,6 +101,7 @@ impl Diagnostic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A collection of [Diagnostic]s
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Diagnostics {
|
pub struct Diagnostics {
|
||||||
diagnostics: HashMap<DiagnosticId, Diagnostic>,
|
diagnostics: HashMap<DiagnosticId, Diagnostic>,
|
||||||
|
@ -3,6 +3,7 @@ use bevy_app::prelude::*;
|
|||||||
use bevy_core::Time;
|
use bevy_core::Time;
|
||||||
use bevy_ecs::{IntoQuerySystem, Res, ResMut};
|
use bevy_ecs::{IntoQuerySystem, Res, ResMut};
|
||||||
|
|
||||||
|
/// Adds "frame time" diagnostic to an App, specifically "frame time" and "fps"
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct FrameTimeDiagnosticsPlugin;
|
pub struct FrameTimeDiagnosticsPlugin;
|
||||||
|
|
||||||
|
@ -9,8 +9,7 @@ pub use print_diagnostics_plugin::PrintDiagnosticsPlugin;
|
|||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
|
|
||||||
pub struct PrintDiagnostics {}
|
/// Adds core diagnostics resources to an App.
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct DiagnosticsPlugin;
|
pub struct DiagnosticsPlugin;
|
||||||
|
|
||||||
|
@ -4,12 +4,14 @@ use bevy_core::{Time, Timer};
|
|||||||
use bevy_ecs::{IntoQuerySystem, Res, ResMut};
|
use bevy_ecs::{IntoQuerySystem, Res, ResMut};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// An App Plugin that prints diagnostics to the console
|
||||||
pub struct PrintDiagnosticsPlugin {
|
pub struct PrintDiagnosticsPlugin {
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
pub wait_duration: Duration,
|
pub wait_duration: Duration,
|
||||||
pub filter: Option<Vec<DiagnosticId>>,
|
pub filter: Option<Vec<DiagnosticId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State used by the [PrintDiagnosticsPlugin]
|
||||||
pub struct PrintDiagnosticsState {
|
pub struct PrintDiagnosticsState {
|
||||||
timer: Timer,
|
timer: Timer,
|
||||||
filter: Option<Vec<DiagnosticId>>,
|
filter: Option<Vec<DiagnosticId>>,
|
||||||
|
@ -20,6 +20,7 @@ struct SystemProfiles {
|
|||||||
current_start: Option<Instant>,
|
current_start: Option<Instant>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Profiles systems by recording their run duration as diagnostics.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SystemProfiler {
|
pub struct SystemProfiler {
|
||||||
system_profiles: Arc<RwLock<HashMap<Cow<'static, str>, SystemProfiles>>>,
|
system_profiles: Arc<RwLock<HashMap<Cow<'static, str>, SystemProfiles>>>,
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
use super::{FromResources, Resources};
|
use super::{FromResources, Resources};
|
||||||
use crate::{
|
use crate::{
|
||||||
system::{SystemId, TypeAccess},
|
system::{SystemId, TypeAccess},
|
||||||
ResourceIndex,
|
Resource, ResourceIndex,
|
||||||
};
|
};
|
||||||
use core::{
|
use core::{
|
||||||
any::TypeId,
|
any::TypeId,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
ptr::NonNull,
|
ptr::NonNull,
|
||||||
};
|
};
|
||||||
use hecs::{smaller_tuples_too, Component};
|
use hecs::smaller_tuples_too;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
/// Shared borrow of an entity's component
|
/// Shared borrow of a Resource
|
||||||
pub struct Res<'a, T: Component> {
|
pub struct Res<'a, T: Resource> {
|
||||||
value: &'a T,
|
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 {
|
pub unsafe fn new(value: NonNull<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: &*value.as_ptr(),
|
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 {
|
pub trait UnsafeClone {
|
||||||
unsafe fn unsafe_clone(&self) -> Self;
|
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 {
|
unsafe fn unsafe_clone(&self) -> Self {
|
||||||
Self { value: self.value }
|
Self { value: self.value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: Component> Send for Res<'_, T> {}
|
unsafe impl<T: Resource> Send for Res<'_, T> {}
|
||||||
unsafe impl<T: Component> Sync 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;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &T {
|
fn deref(&self) -> &T {
|
||||||
@ -45,13 +46,13 @@ impl<'a, T: Component> Deref for Res<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unique borrow of a resource
|
/// Unique borrow of a Resource
|
||||||
pub struct ResMut<'a, T: Component> {
|
pub struct ResMut<'a, T: Resource> {
|
||||||
_marker: PhantomData<&'a T>,
|
_marker: PhantomData<&'a T>,
|
||||||
value: *mut 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 {
|
pub unsafe fn new(value: NonNull<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: value.as_ptr(),
|
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: Resource> Send for ResMut<'_, T> {}
|
||||||
unsafe impl<T: Component> Sync 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;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &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 {
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
unsafe { &mut *self.value }
|
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 {
|
unsafe fn unsafe_clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: self.value,
|
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,
|
value: *mut T,
|
||||||
_marker: PhantomData<&'a 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 {
|
unsafe fn unsafe_clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: self.value,
|
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;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &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 {
|
fn deref_mut(&mut self) -> &mut T {
|
||||||
unsafe { &mut *self.value }
|
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 {
|
pub trait ResourceQuery {
|
||||||
type Fetch: for<'a> FetchResource<'a>;
|
type Fetch: for<'a> FetchResource<'a>;
|
||||||
|
|
||||||
fn initialize(_resources: &mut Resources, _system_id: Option<SystemId>) {}
|
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 {
|
pub trait FetchResource<'a>: Sized {
|
||||||
/// Type of value to be fetched
|
/// Type of value to be fetched
|
||||||
type Item: UnsafeClone;
|
type Item: UnsafeClone;
|
||||||
@ -130,20 +133,17 @@ pub trait FetchResource<'a>: Sized {
|
|||||||
fn borrow(resources: &Resources);
|
fn borrow(resources: &Resources);
|
||||||
fn release(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;
|
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>;
|
type Fetch = FetchResourceRead<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches a shared resource reference
|
||||||
pub struct FetchResourceRead<T>(NonNull<T>);
|
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>;
|
type Item = Res<'a, T>;
|
||||||
|
|
||||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
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>;
|
type Fetch = FetchResourceWrite<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetches a unique resource reference
|
||||||
pub struct FetchResourceWrite<T>(NonNull<T>);
|
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>;
|
type Item = ResMut<'a, T>;
|
||||||
|
|
||||||
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
|
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>;
|
type Fetch = FetchResourceLocalMut<T>;
|
||||||
|
|
||||||
fn initialize(resources: &mut Resources, id: Option<SystemId>) {
|
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>);
|
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>;
|
type Item = Local<'a, T>;
|
||||||
|
|
||||||
unsafe fn get(resources: &'a Resources, system_id: Option<SystemId>) -> Self::Item {
|
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 hecs::{Archetype, Ref, RefMut, TypeInfo};
|
||||||
use std::{collections::HashMap, ptr::NonNull};
|
use std::{collections::HashMap, ptr::NonNull};
|
||||||
|
|
||||||
|
/// A Resource type
|
||||||
pub trait Resource: Send + Sync + 'static {}
|
pub trait Resource: Send + Sync + 'static {}
|
||||||
impl<T: Send + Sync + 'static> Resource for T {}
|
impl<T: Send + Sync + 'static> Resource for T {}
|
||||||
|
|
||||||
pub struct ResourceData {
|
pub(crate) struct ResourceData {
|
||||||
archetype: Archetype,
|
archetype: Archetype,
|
||||||
default_index: Option<u32>,
|
default_index: Option<u32>,
|
||||||
system_id_to_archetype_index: HashMap<u32, u32>,
|
system_id_to_archetype_index: HashMap<u32, u32>,
|
||||||
@ -18,6 +19,7 @@ pub enum ResourceIndex {
|
|||||||
System(SystemId),
|
System(SystemId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A collection of resource instances identified by their type.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Resources {
|
pub struct Resources {
|
||||||
pub(crate) resource_data: HashMap<TypeId, ResourceData>,
|
pub(crate) resource_data: HashMap<TypeId, ResourceData>,
|
||||||
@ -183,7 +185,9 @@ impl Resources {
|
|||||||
unsafe impl Send for Resources {}
|
unsafe impl Send for Resources {}
|
||||||
unsafe impl Sync for Resources {}
|
unsafe impl Sync for Resources {}
|
||||||
|
|
||||||
|
/// Creates `Self` using data from the `Resources` collection
|
||||||
pub trait FromResources {
|
pub trait FromResources {
|
||||||
|
/// Creates `Self` using data from the `Resources` collection
|
||||||
fn from_resources(resources: &Resources) -> Self;
|
fn from_resources(resources: &Resources) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,14 @@ use std::{
|
|||||||
sync::{Arc, Mutex},
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct ParallelExecutor {
|
pub struct ParallelExecutor {
|
||||||
stages: Vec<ExecutorStage>,
|
stages: Vec<ExecutorStage>,
|
||||||
|
@ -9,6 +9,9 @@ use std::{
|
|||||||
sync::{Arc, Mutex},
|
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)]
|
#[derive(Default)]
|
||||||
pub struct Schedule {
|
pub struct Schedule {
|
||||||
pub(crate) stages: HashMap<Cow<'static, str>, Vec<Arc<Mutex<Box<dyn System>>>>>,
|
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 hecs::{Bundle, Component, DynamicBundle, Entity, World};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
/// A queued command to mutate the current [World] or [Resources]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
WriteWorld(Box<dyn WorldWriter>),
|
WriteWorld(Box<dyn WorldWriter>),
|
||||||
WriteResources(Box<dyn ResourcesWriter>),
|
WriteResources(Box<dyn ResourcesWriter>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A [World] mutation
|
||||||
pub trait WorldWriter: Send + Sync {
|
pub trait WorldWriter: Send + Sync {
|
||||||
fn write(self: Box<Self>, world: &mut World);
|
fn write(self: Box<Self>, world: &mut World);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Spawn<T>
|
pub(crate) struct Spawn<T>
|
||||||
where
|
where
|
||||||
T: DynamicBundle + Send + Sync + 'static,
|
T: DynamicBundle + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
@ -28,7 +30,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SpawnAsEntity<T>
|
pub(crate) struct SpawnAsEntity<T>
|
||||||
where
|
where
|
||||||
T: DynamicBundle + Send + Sync + 'static,
|
T: DynamicBundle + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
@ -45,7 +47,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SpawnBatch<I>
|
pub(crate) struct SpawnBatch<I>
|
||||||
where
|
where
|
||||||
I: IntoIterator,
|
I: IntoIterator,
|
||||||
I::Item: Bundle,
|
I::Item: Bundle,
|
||||||
@ -63,7 +65,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Despawn {
|
pub(crate) struct Despawn {
|
||||||
entity: Entity,
|
entity: Entity,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +92,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InsertOne<T>
|
pub(crate) struct InsertOne<T>
|
||||||
where
|
where
|
||||||
T: Component,
|
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,
|
resource: T,
|
||||||
system_id: SystemId,
|
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)]
|
#[derive(Default, Clone)]
|
||||||
pub struct Commands {
|
pub struct Commands {
|
||||||
pub commands: Arc<Mutex<CommandsInternal>>,
|
pub commands: Arc<Mutex<CommandsInternal>>,
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
use hecs::{Fetch, Query as HecsQuery, World};
|
use hecs::{Fetch, Query as HecsQuery, World};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
pub struct SystemFn<State, F, ThreadLocalF, Init, SetArchetypeAccess>
|
pub(crate) struct SystemFn<State, F, ThreadLocalF, Init, SetArchetypeAccess>
|
||||||
where
|
where
|
||||||
F: FnMut(&World, &Resources, &ArchetypeAccess, &mut State) + Send + Sync,
|
F: FnMut(&World, &Resources, &ArchetypeAccess, &mut State) + Send + Sync,
|
||||||
ThreadLocalF: FnMut(&mut World, &mut Resources, &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> {
|
pub trait IntoForEachSystem<CommandBuffer, R, C> {
|
||||||
fn system(self) -> Box<dyn System>;
|
fn system(self) -> Box<dyn System>;
|
||||||
}
|
}
|
||||||
@ -136,6 +136,7 @@ struct QuerySystemState {
|
|||||||
commands: Commands,
|
commands: Commands,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts `Self` into a Query System
|
||||||
pub trait IntoQuerySystem<Commands, R, Q> {
|
pub trait IntoQuerySystem<Commands, R, Q> {
|
||||||
fn system(self) -> Box<dyn System>;
|
fn system(self) -> Box<dyn System>;
|
||||||
}
|
}
|
||||||
@ -298,6 +299,7 @@ impl_into_systems!(Ra,Rb,Rc,Rd,Re,Rf,Rg,Rh,Ri);
|
|||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
impl_into_systems!(Ra,Rb,Rc,Rd,Re,Rf,Rg,Rh,Ri,Rj);
|
impl_into_systems!(Ra,Rb,Rc,Rd,Re,Rf,Rg,Rh,Ri,Rj);
|
||||||
|
|
||||||
|
/// Converts `Self` into a thread local system
|
||||||
pub trait IntoThreadLocalSystem {
|
pub trait IntoThreadLocalSystem {
|
||||||
fn thread_local_system(self) -> Box<dyn System>;
|
fn thread_local_system(self) -> Box<dyn System>;
|
||||||
}
|
}
|
||||||
@ -324,6 +326,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A thread local system function
|
||||||
pub trait ThreadLocalSystemFn: Send + Sync + 'static {
|
pub trait ThreadLocalSystemFn: Send + Sync + 'static {
|
||||||
fn run(&mut self, world: &mut World, resource: &mut Resources);
|
fn run(&mut self, world: &mut World, resource: &mut Resources);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,9 @@ use crate::Resources;
|
|||||||
use downcast_rs::{impl_downcast, Downcast};
|
use downcast_rs::{impl_downcast, Downcast};
|
||||||
use std::borrow::Cow;
|
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 {
|
pub trait Profiler: Downcast + Send + Sync + 'static {
|
||||||
fn start(&self, scope: Cow<'static, str>);
|
fn start(&self, scope: Cow<'static, str>);
|
||||||
fn stop(&self, scope: Cow<'static, str>);
|
fn stop(&self, scope: Cow<'static, str>);
|
||||||
|
@ -5,12 +5,14 @@ use hecs::{
|
|||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
/// Provides scoped access to a World according to a given [HecsQuery]
|
||||||
pub struct Query<'a, Q: HecsQuery> {
|
pub struct Query<'a, Q: HecsQuery> {
|
||||||
pub(crate) world: &'a World,
|
pub(crate) world: &'a World,
|
||||||
pub(crate) archetype_access: &'a ArchetypeAccess,
|
pub(crate) archetype_access: &'a ArchetypeAccess,
|
||||||
_marker: PhantomData<Q>,
|
_marker: PhantomData<Q>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An error that occurs when using a [Query]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum QueryError {
|
pub enum QueryError {
|
||||||
CannotReadArchetype,
|
CannotReadArchetype,
|
||||||
|
@ -3,6 +3,7 @@ use fixedbitset::FixedBitSet;
|
|||||||
use hecs::{Access, Query, World};
|
use hecs::{Access, Query, World};
|
||||||
use std::{any::TypeId, borrow::Cow, collections::HashSet};
|
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)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
pub enum ThreadLocalExecution {
|
pub enum ThreadLocalExecution {
|
||||||
Immediate,
|
Immediate,
|
||||||
@ -18,6 +19,7 @@ impl SystemId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An ECS system that can be added to a [Schedule](crate::Schedule)
|
||||||
pub trait System: Send + Sync {
|
pub trait System: Send + Sync {
|
||||||
fn name(&self) -> Cow<'static, str>;
|
fn name(&self) -> Cow<'static, str>;
|
||||||
fn id(&self) -> SystemId;
|
fn id(&self) -> SystemId;
|
||||||
@ -30,13 +32,14 @@ pub trait System: Send + Sync {
|
|||||||
fn initialize(&mut self, _resources: &mut Resources) {}
|
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)]
|
#[derive(Default)]
|
||||||
pub struct ArchetypeAccess {
|
pub struct ArchetypeAccess {
|
||||||
pub immutable: FixedBitSet,
|
pub immutable: FixedBitSet,
|
||||||
pub mutable: FixedBitSet,
|
pub mutable: FixedBitSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// credit to Ratysz from the Yaks codebase
|
||||||
impl ArchetypeAccess {
|
impl ArchetypeAccess {
|
||||||
pub fn is_compatible(&self, other: &ArchetypeAccess) -> bool {
|
pub fn is_compatible(&self, other: &ArchetypeAccess) -> bool {
|
||||||
self.mutable.is_disjoint(&other.mutable)
|
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)]
|
#[derive(Debug, Default, Eq, PartialEq, Clone)]
|
||||||
pub struct TypeAccess {
|
pub struct TypeAccess {
|
||||||
pub immutable: HashSet<TypeId>,
|
pub immutable: HashSet<TypeId>,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use hecs::{Bundle, Component, DynamicBundle, Entity, World};
|
use hecs::{Bundle, Component, DynamicBundle, Entity, World};
|
||||||
|
|
||||||
|
/// Converts a reference to `Self` to a [WorldBuilder]
|
||||||
pub trait WorldBuilderSource {
|
pub trait WorldBuilderSource {
|
||||||
fn build(&mut self) -> WorldBuilder;
|
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 struct WorldBuilder<'a> {
|
||||||
pub world: &'a mut World,
|
pub world: &'a mut World,
|
||||||
pub current_entity: Option<Entity>,
|
pub current_entity: Option<Entity>,
|
||||||
|
@ -5,6 +5,7 @@ use bevy_app::prelude::*;
|
|||||||
use bevy_asset::AddAsset;
|
use bevy_asset::AddAsset;
|
||||||
use bevy_render::mesh::Mesh;
|
use bevy_render::mesh::Mesh;
|
||||||
|
|
||||||
|
/// Adds support for GLTF file loading to Apps
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct GltfPlugin;
|
pub struct GltfPlugin;
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@ use gltf::{buffer::Source, iter, mesh::Mode};
|
|||||||
use std::{fs, io, path::Path};
|
use std::{fs, io, path::Path};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Loads meshes from GLTF files into Mesh assets
|
||||||
|
///
|
||||||
|
/// NOTE: eventually this will loading into Scenes instead of Meshes
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct GltfLoader;
|
pub struct GltfLoader;
|
||||||
|
|
||||||
@ -24,6 +27,7 @@ impl AssetLoader<Mesh> for GltfLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An error that occurs when loading a GLTF file
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum GltfError {
|
pub enum GltfError {
|
||||||
#[error("Unsupported primitive mode.")]
|
#[error("Unsupported primitive mode.")]
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::{collections::HashSet, hash::Hash};
|
use std::{collections::HashSet, hash::Hash};
|
||||||
|
|
||||||
|
/// A "press-able" input of type `T`
|
||||||
pub struct Input<T> {
|
pub struct Input<T> {
|
||||||
pressed: HashSet<T>,
|
pressed: HashSet<T>,
|
||||||
just_pressed: HashSet<T>,
|
just_pressed: HashSet<T>,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::Input;
|
use crate::Input;
|
||||||
use bevy_app::prelude::*;
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct KeyboardInput {
|
pub struct KeyboardInput {
|
||||||
pub scan_code: u32,
|
pub scan_code: u32,
|
||||||
@ -9,6 +10,7 @@ pub struct KeyboardInput {
|
|||||||
pub state: ElementState,
|
pub state: ElementState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The current "press" state of an element
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub enum ElementState {
|
pub enum ElementState {
|
||||||
Pressed,
|
Pressed,
|
||||||
@ -24,13 +26,15 @@ impl ElementState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State used by the keyboard input system
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct KeyboardInputState {
|
pub struct KeyboardInputState {
|
||||||
keyboard_input_event_reader: EventReader<KeyboardInput>,
|
keyboard_input_event_reader: EventReader<KeyboardInput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the Input<KeyCode> resource with the latest KeyboardInput events
|
||||||
pub fn keyboard_input_system(
|
pub fn keyboard_input_system(
|
||||||
mut state: ResMut<KeyboardInputState>,
|
mut state: Local<KeyboardInputState>,
|
||||||
mut keyboard_input: ResMut<Input<KeyCode>>,
|
mut keyboard_input: ResMut<Input<KeyCode>>,
|
||||||
keyboard_input_events: Res<Events<KeyboardInput>>,
|
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)]
|
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum KeyCode {
|
pub enum KeyCode {
|
||||||
|
@ -10,13 +10,14 @@ pub mod prelude {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput, KeyboardInputState};
|
use keyboard::{keyboard_input_system, KeyCode, KeyboardInput};
|
||||||
use mouse::{
|
use mouse::{
|
||||||
mouse_button_input_system, MouseButton, MouseButtonInput, MouseButtonInputState, MouseMotion,
|
mouse_button_input_system, MouseButton, MouseButtonInput, MouseMotion,
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy_ecs::IntoQuerySystem;
|
use bevy_ecs::IntoQuerySystem;
|
||||||
|
|
||||||
|
/// Adds keyboard and mouse input to an App
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct InputPlugin;
|
pub struct InputPlugin;
|
||||||
|
|
||||||
@ -26,13 +27,11 @@ impl Plugin for InputPlugin {
|
|||||||
.add_event::<MouseButtonInput>()
|
.add_event::<MouseButtonInput>()
|
||||||
.add_event::<MouseMotion>()
|
.add_event::<MouseMotion>()
|
||||||
.init_resource::<Input<KeyCode>>()
|
.init_resource::<Input<KeyCode>>()
|
||||||
.init_resource::<KeyboardInputState>()
|
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
bevy_app::stage::EVENT_UPDATE,
|
bevy_app::stage::EVENT_UPDATE,
|
||||||
keyboard_input_system.system(),
|
keyboard_input_system.system(),
|
||||||
)
|
)
|
||||||
.init_resource::<Input<MouseButton>>()
|
.init_resource::<Input<MouseButton>>()
|
||||||
.init_resource::<MouseButtonInputState>()
|
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
bevy_app::stage::EVENT_UPDATE,
|
bevy_app::stage::EVENT_UPDATE,
|
||||||
mouse_button_input_system.system(),
|
mouse_button_input_system.system(),
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
use super::keyboard::ElementState;
|
use super::keyboard::ElementState;
|
||||||
use crate::Input;
|
use crate::Input;
|
||||||
use bevy_app::prelude::{EventReader, Events};
|
use bevy_app::prelude::{EventReader, Events};
|
||||||
use bevy_ecs::{Res, ResMut};
|
use bevy_ecs::{Res, ResMut, Local};
|
||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
|
|
||||||
|
/// A mouse button input event
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MouseButtonInput {
|
pub struct MouseButtonInput {
|
||||||
pub button: MouseButton,
|
pub button: MouseButton,
|
||||||
pub state: ElementState,
|
pub state: ElementState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A button on a mouse device
|
||||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum MouseButton {
|
pub enum MouseButton {
|
||||||
Left,
|
Left,
|
||||||
@ -18,18 +20,21 @@ pub enum MouseButton {
|
|||||||
Other(u8),
|
Other(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A mouse motion event
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MouseMotion {
|
pub struct MouseMotion {
|
||||||
pub delta: Vec2,
|
pub delta: Vec2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// State used by the mouse button input system
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct MouseButtonInputState {
|
pub struct MouseButtonInputState {
|
||||||
mouse_button_input_event_reader: EventReader<MouseButtonInput>,
|
mouse_button_input_event_reader: EventReader<MouseButtonInput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Updates the Input<MouseButton> resource with the latest MouseButtonInput events
|
||||||
pub fn mouse_button_input_system(
|
pub fn mouse_button_input_system(
|
||||||
mut state: ResMut<MouseButtonInputState>,
|
mut state: Local<MouseButtonInputState>,
|
||||||
mut mouse_button_input: ResMut<Input<MouseButton>>,
|
mut mouse_button_input: ResMut<Input<MouseButton>>,
|
||||||
mouse_button_input_events: Res<Events<MouseButtonInput>>,
|
mouse_button_input_events: Res<Events<MouseButtonInput>>,
|
||||||
) {
|
) {
|
||||||
|
@ -5,11 +5,13 @@ use bevy_app::{
|
|||||||
};
|
};
|
||||||
use bevy_ecs::{Local, Res, ResMut};
|
use bevy_ecs::{Local, Res, ResMut};
|
||||||
|
|
||||||
|
/// Local "exit on escape" system state
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ExitOnEscapeState {
|
pub struct ExitOnEscapeState {
|
||||||
reader: EventReader<KeyboardInput>,
|
reader: EventReader<KeyboardInput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sends the AppExit event whenever the "esc" key is pressed.
|
||||||
pub fn exit_on_esc_system(
|
pub fn exit_on_esc_system(
|
||||||
mut state: Local<ExitOnEscapeState>,
|
mut state: Local<ExitOnEscapeState>,
|
||||||
keyboard_input_events: Res<Events<KeyboardInput>>,
|
keyboard_input_events: Res<Events<KeyboardInput>>,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use crate::{Mat4, Vec3};
|
use crate::{Mat4, Vec3};
|
||||||
|
|
||||||
|
/// Generates a translation / rotation matrix that faces a given target
|
||||||
pub trait FaceToward {
|
pub trait FaceToward {
|
||||||
|
/// Generates a translation / rotation matrix that faces a given target
|
||||||
fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self;
|
fn face_toward(eye: Vec3, center: Vec3, up: Vec3) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use std::ops::{Add, AddAssign};
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
|
/// A two dimensional "size" as defined by a width and height
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
pub struct Size<T = f32> {
|
pub struct Size<T = f32> {
|
||||||
pub width: T,
|
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)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
pub struct Rect<T> {
|
pub struct Rect<T> {
|
||||||
pub left: T,
|
pub left: T,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use crate::Mat4;
|
use crate::Mat4;
|
||||||
use glam::Vec4;
|
use glam::Vec4;
|
||||||
|
|
||||||
|
/// Produces a "right handed" perspective matrix
|
||||||
pub trait PerspectiveRh {
|
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;
|
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_asset::Handle;
|
||||||
use bevy_ecs::Bundle;
|
use bevy_ecs::Bundle;
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
draw::Draw,
|
draw::Draw,
|
||||||
mesh::Mesh,
|
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};
|
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
||||||
|
|
||||||
|
/// A component bundle for "pbr mesh" entities
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct PbrComponents {
|
pub struct PbrComponents {
|
||||||
pub mesh: Handle<Mesh>,
|
pub mesh: Handle<Mesh>,
|
||||||
@ -54,6 +56,7 @@ impl Default for PbrComponents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A component bundle for "light" entities
|
||||||
#[derive(Bundle, Default)]
|
#[derive(Bundle, Default)]
|
||||||
pub struct LightComponents {
|
pub struct LightComponents {
|
||||||
pub light: Light,
|
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;
|
pub mod render_graph;
|
||||||
|
|
||||||
|
mod entity;
|
||||||
|
mod light;
|
||||||
|
mod material;
|
||||||
|
|
||||||
|
pub use entity::*;
|
||||||
|
pub use light::*;
|
||||||
|
pub use material::*;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use crate::{entity::*, light::Light, material::StandardMaterial};
|
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 bevy_type_registry::RegisterType;
|
||||||
use light::Light;
|
use light::Light;
|
||||||
use material::StandardMaterial;
|
use material::StandardMaterial;
|
||||||
use render_graph::ForwardPbrRenderGraphBuilder;
|
use render_graph::add_pbr_graph;
|
||||||
|
|
||||||
/// NOTE: this isn't PBR yet. consider this name "aspirational" :)
|
/// NOTE: this isn't PBR yet. consider this name "aspirational" :)
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -32,6 +35,6 @@ impl Plugin for PbrPlugin {
|
|||||||
);
|
);
|
||||||
let resources = app.resources();
|
let resources = app.resources();
|
||||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
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 bevy_transform::components::Translation;
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
|
/// A point light
|
||||||
#[derive(Properties)]
|
#[derive(Properties)]
|
||||||
pub struct Light {
|
pub struct Light {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
@ -27,7 +28,7 @@ impl Default for Light {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct LightRaw {
|
pub(crate) struct LightRaw {
|
||||||
pub proj: [[f32; 4]; 4],
|
pub proj: [[f32; 4]; 4],
|
||||||
pub pos: [f32; 4],
|
pub pos: [f32; 4],
|
||||||
pub color: [f32; 4],
|
pub color: [f32; 4],
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use bevy_asset::{self, Handle};
|
use bevy_asset::{self, Handle};
|
||||||
use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, texture::Texture};
|
use bevy_render::{color::Color, renderer::RenderResources, shader::ShaderDefs, texture::Texture};
|
||||||
|
|
||||||
|
/// A material with "standard" properties used in PBR lighting
|
||||||
#[derive(RenderResources, ShaderDefs)]
|
#[derive(RenderResources, ShaderDefs)]
|
||||||
pub struct StandardMaterial {
|
pub struct StandardMaterial {
|
||||||
pub albedo: Color,
|
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> =
|
pub const FORWARD_PIPELINE_HANDLE: Handle<PipelineDescriptor> =
|
||||||
Handle::from_u128(131483623140127713893804825450360211204);
|
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 {
|
PipelineDescriptor {
|
||||||
rasterization_state: Some(RasterizationStateDescriptor {
|
rasterization_state: Some(RasterizationStateDescriptor {
|
||||||
front_face: FrontFace::Ccw,
|
front_face: FrontFace::Ccw,
|
@ -13,6 +13,7 @@ use bevy_render::{
|
|||||||
};
|
};
|
||||||
use bevy_transform::prelude::*;
|
use bevy_transform::prelude::*;
|
||||||
|
|
||||||
|
/// A Render Graph [Node] that write light data from the ECS to GPU buffers
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LightsNode {
|
pub struct LightsNode {
|
||||||
command_queue: CommandQueue,
|
command_queue: CommandQueue,
|
||||||
@ -43,7 +44,7 @@ impl Node for LightsNode {
|
|||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct LightCount {
|
struct LightCount {
|
||||||
pub num_lights: [u32; 4],
|
pub num_lights: [u32; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +66,7 @@ impl SystemNode for LightsNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Local "lights node system" state
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct LightsNodeSystemState {
|
pub struct LightsNodeSystemState {
|
||||||
light_buffer: Option<BufferId>,
|
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 serde::{Deserialize, Serialize};
|
||||||
use std::ops::{Add, AddAssign, Mul, MulAssign};
|
use std::ops::{Add, AddAssign, Mul, MulAssign};
|
||||||
|
|
||||||
|
/// A RGBA color
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Property)]
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Property)]
|
||||||
pub struct Color {
|
pub struct Color {
|
||||||
@ -178,6 +179,7 @@ impl Bytes for ColorSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A source of color
|
||||||
pub enum ColorSource {
|
pub enum ColorSource {
|
||||||
Color(Color),
|
Color(Color),
|
||||||
Texture(Handle<Texture>),
|
Texture(Handle<Texture>),
|
||||||
|
@ -18,6 +18,7 @@ use bevy_property::Properties;
|
|||||||
use std::{any::TypeId, ops::Range, sync::Arc};
|
use std::{any::TypeId, ops::Range, sync::Arc};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// A queued command for the renderer
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub enum RenderCommand {
|
pub enum RenderCommand {
|
||||||
SetPipeline {
|
SetPipeline {
|
||||||
@ -44,6 +45,7 @@ pub enum RenderCommand {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A component that indicates how to draw an entity.
|
||||||
#[derive(Properties)]
|
#[derive(Properties)]
|
||||||
pub struct Draw {
|
pub struct Draw {
|
||||||
pub is_visible: bool,
|
pub is_visible: bool,
|
||||||
|
@ -4,14 +4,12 @@ use crate::{
|
|||||||
render_graph::base,
|
render_graph::base,
|
||||||
Draw, Mesh,
|
Draw, Mesh,
|
||||||
};
|
};
|
||||||
|
use base::MainPass;
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_ecs::Bundle;
|
use bevy_ecs::Bundle;
|
||||||
use bevy_transform::components::{Rotation, Scale, Transform, Translation};
|
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)]
|
#[derive(Bundle, Default)]
|
||||||
pub struct MeshComponents {
|
pub struct MeshComponents {
|
||||||
pub mesh: Handle<Mesh>,
|
pub mesh: Handle<Mesh>,
|
||||||
@ -24,6 +22,7 @@ pub struct MeshComponents {
|
|||||||
pub scale: Scale,
|
pub scale: Scale,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A component bundle for "3d camera" entities
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct Camera3dComponents {
|
pub struct Camera3dComponents {
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
@ -52,6 +51,7 @@ impl Default for Camera3dComponents {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A component bundle for "2d camera" entities
|
||||||
#[derive(Bundle)]
|
#[derive(Bundle)]
|
||||||
pub struct Camera2dComponents {
|
pub struct Camera2dComponents {
|
||||||
pub camera: Camera,
|
pub camera: Camera,
|
||||||
|
@ -27,13 +27,18 @@ pub mod prelude {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use base::Msaa;
|
use base::{MainPass, Msaa};
|
||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_asset::AddAsset;
|
use bevy_asset::AddAsset;
|
||||||
use bevy_ecs::{IntoQuerySystem, IntoThreadLocalSystem};
|
use bevy_ecs::{IntoQuerySystem, IntoThreadLocalSystem};
|
||||||
use bevy_type_registry::RegisterType;
|
use bevy_type_registry::RegisterType;
|
||||||
use camera::{ActiveCameras, Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities};
|
use camera::{
|
||||||
use pipeline::{PipelineCompiler, PipelineDescriptor, VertexBufferDescriptors, ShaderSpecialization, PipelineSpecialization, DynamicBinding, PrimitiveTopology};
|
ActiveCameras, Camera, OrthographicProjection, PerspectiveProjection, VisibleEntities,
|
||||||
|
};
|
||||||
|
use pipeline::{
|
||||||
|
DynamicBinding, PipelineCompiler, PipelineDescriptor, PipelineSpecialization,
|
||||||
|
PrimitiveTopology, ShaderSpecialization, VertexBufferDescriptors,
|
||||||
|
};
|
||||||
use render_graph::{
|
use render_graph::{
|
||||||
base::{self, BaseRenderGraphBuilder, BaseRenderGraphConfig},
|
base::{self, BaseRenderGraphBuilder, BaseRenderGraphConfig},
|
||||||
RenderGraph,
|
RenderGraph,
|
||||||
@ -42,6 +47,7 @@ use renderer::{AssetRenderResourceBindings, RenderResourceBindings};
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use texture::{HdrTextureLoader, ImageTextureLoader, TextureResourceSystemState};
|
use texture::{HdrTextureLoader, ImageTextureLoader, TextureResourceSystemState};
|
||||||
|
|
||||||
|
/// The names of "render" App stages
|
||||||
pub mod stage {
|
pub mod stage {
|
||||||
/// Stage where render resources are set up
|
/// Stage where render resources are set up
|
||||||
pub static RENDER_RESOURCE: &str = "render_resource";
|
pub static RENDER_RESOURCE: &str = "render_resource";
|
||||||
@ -53,6 +59,7 @@ pub mod stage {
|
|||||||
pub static POST_RENDER: &str = "post_render";
|
pub static POST_RENDER: &str = "post_render";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds core render types and systems to an App
|
||||||
pub struct RenderPlugin {
|
pub struct RenderPlugin {
|
||||||
/// configures the "base render graph". If this is not `None`, the "base render graph" will be added
|
/// configures the "base render graph". If this is not `None`, the "base render graph" will be added
|
||||||
pub base_render_graph_config: Option<BaseRenderGraphConfig>,
|
pub base_render_graph_config: Option<BaseRenderGraphConfig>,
|
||||||
|
@ -7,12 +7,16 @@ use crate::{
|
|||||||
LoadOp, Operations, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
LoadOp, Operations, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||||
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
RenderPassDepthStencilAttachmentDescriptor, TextureAttachment,
|
||||||
},
|
},
|
||||||
prelude::MainPass,
|
|
||||||
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||||
Color,
|
Color,
|
||||||
};
|
};
|
||||||
|
use bevy_property::Properties;
|
||||||
use bevy_window::WindowId;
|
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 struct Msaa {
|
||||||
pub samples: u32,
|
pub samples: u32,
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ use super::ShaderLayout;
|
|||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use glsl_to_spirv::compile;
|
use glsl_to_spirv::compile;
|
||||||
use std::{io::Read, marker::Copy};
|
use std::{io::Read, marker::Copy};
|
||||||
|
|
||||||
|
/// The stage of a shader
|
||||||
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)]
|
#[derive(Hash, Eq, PartialEq, Copy, Clone, Debug)]
|
||||||
pub enum ShaderStage {
|
pub enum ShaderStage {
|
||||||
Vertex,
|
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,
|
glsl_source: &str,
|
||||||
stage: ShaderStage,
|
stage: ShaderStage,
|
||||||
shader_defs: Option<&[String]>,
|
shader_defs: Option<&[String]>,
|
||||||
@ -41,6 +43,7 @@ fn bytes_to_words(bytes: &[u8]) -> Vec<u32> {
|
|||||||
words
|
words
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The full "source" of a shader
|
||||||
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
pub enum ShaderSource {
|
pub enum ShaderSource {
|
||||||
Spirv(Vec<u32>),
|
Spirv(Vec<u32>),
|
||||||
@ -53,11 +56,11 @@ impl ShaderSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A shader, as defined by its [ShaderSource] and [ShaderStage]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Shader {
|
pub struct Shader {
|
||||||
pub source: ShaderSource,
|
pub source: ShaderSource,
|
||||||
pub stage: ShaderStage,
|
pub stage: ShaderStage,
|
||||||
// TODO: add "precompile" flag?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Shader {
|
impl Shader {
|
||||||
@ -98,6 +101,7 @@ impl Shader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// All stages in a shader program
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ShaderStages {
|
pub struct ShaderStages {
|
||||||
pub vertex: Handle<Shader>,
|
pub vertex: Handle<Shader>,
|
||||||
|
@ -4,16 +4,19 @@ use crate::{pipeline::RenderPipelines, Texture};
|
|||||||
pub use bevy_derive::ShaderDefs;
|
pub use bevy_derive::ShaderDefs;
|
||||||
use bevy_ecs::{Query, Res};
|
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 {
|
pub trait ShaderDef {
|
||||||
fn is_defined(&self) -> bool;
|
fn is_defined(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A collection of "shader defs", which define compile time definitions for shaders.
|
||||||
pub trait ShaderDefs {
|
pub trait ShaderDefs {
|
||||||
fn shader_defs_len(&self) -> usize;
|
fn shader_defs_len(&self) -> usize;
|
||||||
fn get_shader_def(&self, index: usize) -> Option<&str>;
|
fn get_shader_def(&self, index: usize) -> Option<&str>;
|
||||||
fn iter_shader_defs(&self) -> ShaderDefIterator;
|
fn iter_shader_defs(&self) -> ShaderDefIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Iterates over all [ShaderDef] items in [ShaderDefs]
|
||||||
pub struct ShaderDefIterator<'a> {
|
pub struct ShaderDefIterator<'a> {
|
||||||
shader_defs: &'a dyn ShaderDefs,
|
shader_defs: &'a dyn ShaderDefs,
|
||||||
index: usize,
|
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)>)
|
pub fn shader_defs_system<T>(mut query: Query<(&T, &mut RenderPipelines)>)
|
||||||
where
|
where
|
||||||
T: ShaderDefs + Send + Sync + 'static,
|
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>) {
|
pub fn clear_shader_defs_system(mut query: Query<&mut RenderPipelines>) {
|
||||||
for mut render_pipelines in &mut query.iter() {
|
for mut render_pipelines in &mut query.iter() {
|
||||||
for render_pipeline in render_pipelines.pipelines.iter_mut() {
|
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>(
|
pub fn asset_shader_defs_system<T>(
|
||||||
assets: Res<Assets<T>>,
|
assets: Res<Assets<T>>,
|
||||||
mut query: Query<(&Handle<T>, &mut RenderPipelines)>,
|
mut query: Query<(&Handle<T>, &mut RenderPipelines)>,
|
||||||
|
@ -15,6 +15,7 @@ use spirv_reflect::{
|
|||||||
};
|
};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
/// Defines the memory layout of a shader
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ShaderLayout {
|
pub struct ShaderLayout {
|
||||||
pub bind_groups: Vec<BindGroupDescriptor>,
|
pub bind_groups: Vec<BindGroupDescriptor>,
|
||||||
|
@ -4,6 +4,7 @@ use bevy_asset::AssetLoader;
|
|||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
/// Loads HDR textures as Texture assets
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct HdrTextureLoader;
|
pub struct HdrTextureLoader;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::Texture;
|
use super::Texture;
|
||||||
use crate::pipeline::CompareFunction;
|
use crate::pipeline::CompareFunction;
|
||||||
|
|
||||||
|
/// Describes a sampler
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct SamplerDescriptor {
|
pub struct SamplerDescriptor {
|
||||||
pub address_mode_u: AddressMode,
|
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)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
pub enum AddressMode {
|
pub enum AddressMode {
|
||||||
ClampToEdge = 0,
|
ClampToEdge = 0,
|
||||||
@ -62,6 +64,7 @@ impl Default for AddressMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Texel mixing mode when sampling between texels.
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
pub enum FilterMode {
|
pub enum FilterMode {
|
||||||
Nearest = 0,
|
Nearest = 0,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::{Extent3d, Texture, TextureDimension, TextureFormat, TextureUsage};
|
use super::{Extent3d, Texture, TextureDimension, TextureFormat, TextureUsage};
|
||||||
|
|
||||||
|
/// Describes a texture
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct TextureDescriptor {
|
pub struct TextureDescriptor {
|
||||||
pub size: Extent3d,
|
pub size: Extent3d,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// NOTE: These are currently just copies of the wgpu types, but they might change in the future
|
// 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)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum TextureViewDimension {
|
pub enum TextureViewDimension {
|
||||||
D1,
|
D1,
|
||||||
@ -10,6 +11,7 @@ pub enum TextureViewDimension {
|
|||||||
D3,
|
D3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dimensionality of a texture.
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
pub enum TextureDimension {
|
pub enum TextureDimension {
|
||||||
D1,
|
D1,
|
||||||
@ -25,6 +27,7 @@ pub struct Extent3d {
|
|||||||
pub depth: u32,
|
pub depth: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Type of data shaders will read from a texture.
|
||||||
#[derive(Copy, Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Copy, Hash, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum TextureComponentType {
|
pub enum TextureComponentType {
|
||||||
Float,
|
Float,
|
||||||
@ -37,6 +40,10 @@ pub struct PixelInfo {
|
|||||||
pub num_components: usize,
|
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)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub enum TextureFormat {
|
pub enum TextureFormat {
|
||||||
// Normal 8 bit formats
|
// Normal 8 bit formats
|
||||||
|
@ -7,7 +7,8 @@ use bevy_ecs::Bundle;
|
|||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
mesh::Mesh,
|
mesh::Mesh,
|
||||||
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
pipeline::{DynamicBinding, PipelineSpecialization, RenderPipeline, RenderPipelines},
|
||||||
prelude::{Draw, MainPass},
|
prelude::Draw,
|
||||||
|
render_graph::base::MainPass,
|
||||||
};
|
};
|
||||||
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
use bevy_transform::prelude::{Rotation, Scale, Transform, Translation};
|
||||||
|
|
||||||
|
@ -3,12 +3,14 @@ use bevy::{
|
|||||||
render::{
|
render::{
|
||||||
camera::{ActiveCameras, Camera},
|
camera::{ActiveCameras, Camera},
|
||||||
pass::*,
|
pass::*,
|
||||||
render_graph::{CameraNode, PassNode, RenderGraph, WindowSwapChainNode, WindowTextureNode},
|
render_graph::{
|
||||||
texture::{TextureDescriptor, TextureFormat, TextureUsage},
|
base::MainPass, CameraNode, PassNode, RenderGraph, WindowSwapChainNode,
|
||||||
|
WindowTextureNode,
|
||||||
|
},
|
||||||
|
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||||
},
|
},
|
||||||
window::{CreateWindow, WindowDescriptor, WindowId},
|
window::{CreateWindow, WindowDescriptor, WindowId},
|
||||||
};
|
};
|
||||||
use bevy_render::texture::{Extent3d, TextureDimension};
|
|
||||||
|
|
||||||
/// This example creates a second window and draws a mesh from two different cameras.
|
/// This example creates a second window and draws a mesh from two different cameras.
|
||||||
fn main() {
|
fn main() {
|
||||||
|
Loading…
Reference in New Issue
Block a user