Switch ecs to edict #1
|
@ -264,6 +264,12 @@ version = "1.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
|
checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomicell"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "157342dd84c64f16899b4b16c1fb2cce54b887990362aac3c590b3d13810890f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -534,6 +540,42 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "edict"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d85bf7cde5687ce04b093bfe183453fa12996b6bdfd2567a0262ebd621761d77"
|
||||||
|
dependencies = [
|
||||||
|
"atomicell",
|
||||||
|
"edict-proc",
|
||||||
|
"hashbrown 0.13.2",
|
||||||
|
"parking_lot",
|
||||||
|
"smallvec",
|
||||||
|
"tiny-fn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "edict-proc"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c94d80dc0f05250a9082bb9455bbf3d6c6c51db388b060df914aebcfb4a9b9f1"
|
||||||
|
dependencies = [
|
||||||
|
"edict-proc-lib",
|
||||||
|
"syn 2.0.26",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "edict-proc-lib"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52d98f9931a4f71c7eb7d85cf4ef1271b27014625c85a65376a52c10ac4ffaea"
|
||||||
|
dependencies = [
|
||||||
|
"proc-easy",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.26",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
@ -1036,8 +1078,10 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-std",
|
"async-std",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"atomicell",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"edict",
|
||||||
"gilrs-core",
|
"gilrs-core",
|
||||||
"glam",
|
"glam",
|
||||||
"hecs",
|
"hecs",
|
||||||
|
@ -1492,6 +1536,17 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-easy"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ea59c637cd0e6b71ae18e589854e9de9b7cb17fefdbf2047e42bd38e24285b19"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.26",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
|
@ -1780,6 +1835,12 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiny-fn"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af7b2c33e09916c65a15c92c1e583946052527e06102689ed11c6125f64fa8ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-skia"
|
name = "tiny-skia"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
|
|
@ -27,3 +27,5 @@ petgraph = "0.6.3"
|
||||||
gilrs-core = "0.5.6"
|
gilrs-core = "0.5.6"
|
||||||
syn = "2.0.26"
|
syn = "2.0.26"
|
||||||
quote = "1.0.29"
|
quote = "1.0.29"
|
||||||
|
edict = "0.5.0"
|
||||||
|
atomicell = "0.1.9"
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
use edict::Component;
|
||||||
use winit::dpi::PhysicalSize;
|
use winit::dpi::PhysicalSize;
|
||||||
|
|
||||||
use crate::{math::{Angle, OPENGL_TO_WGPU_MATRIX, Transform}, render::camera::CameraProjectionMode};
|
use crate::{math::{Angle, OPENGL_TO_WGPU_MATRIX, Transform}, render::camera::CameraProjectionMode};
|
||||||
|
|
||||||
|
#[derive(Clone, Component)]
|
||||||
pub struct CameraComponent {
|
pub struct CameraComponent {
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
pub fov: Angle,
|
pub fov: Angle,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
use edict::Component;
|
||||||
|
|
||||||
use crate::render::{vertex::Vertex, mesh::Mesh, material::Material};
|
use crate::render::{vertex::Vertex, mesh::Mesh, material::Material};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Component)]
|
||||||
pub struct MeshComponent {
|
pub struct MeshComponent {
|
||||||
pub mesh: Mesh,
|
pub mesh: Mesh,
|
||||||
pub material: Material,
|
pub material: Material,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
use edict::Component;
|
||||||
|
|
||||||
use crate::math::Transform;
|
use crate::math::Transform;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Component)]
|
||||||
pub struct TransformComponent {
|
pub struct TransformComponent {
|
||||||
pub transform: Transform,
|
pub transform: Transform,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,8 @@ use tracing::warn;
|
||||||
use crate::game::Controls;
|
use crate::game::Controls;
|
||||||
|
|
||||||
pub mod components;
|
pub mod components;
|
||||||
pub mod world;
|
|
||||||
pub mod resources;
|
pub mod resources;
|
||||||
|
|
||||||
use world::World;
|
|
||||||
|
|
||||||
/// A trait that represents a simple system
|
/// A trait that represents a simple system
|
||||||
pub trait SimpleSystem {
|
pub trait SimpleSystem {
|
||||||
fn setup(&mut self, controls: &mut Controls) -> anyhow::Result<()> {
|
fn setup(&mut self, controls: &mut Controls) -> anyhow::Result<()> {
|
||||||
|
@ -22,7 +19,7 @@ pub trait SimpleSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> SimpleSystem for S
|
impl<S> SimpleSystem for S
|
||||||
where S: FnMut(&mut World) -> anyhow::Result<()>
|
where S: FnMut(&mut edict::World) -> anyhow::Result<()>
|
||||||
{
|
{
|
||||||
fn execute_mut(&mut self, controls: &mut Controls) -> anyhow::Result<()> {
|
fn execute_mut(&mut self, controls: &mut Controls) -> anyhow::Result<()> {
|
||||||
self(controls.world)
|
self(controls.world)
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
use std::{collections::{HashMap, VecDeque}, any::{TypeId, Any}, cell::{RefCell, Ref, RefMut}};
|
||||||
|
|
||||||
|
use super::{CastableAny, Events, Event};
|
||||||
|
|
||||||
|
pub struct EventQueue {
|
||||||
|
events: HashMap<TypeId, RefCell<Box<dyn CastableAny>>>,
|
||||||
|
event_write_queue: HashMap<TypeId, RefCell<Box<dyn CastableAny>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventQueue {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
event_write_queue: HashMap::new(),
|
||||||
|
events: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trigger an event
|
||||||
|
pub fn trigger_event<E>(&mut self, event: E)
|
||||||
|
where
|
||||||
|
E: Event
|
||||||
|
{
|
||||||
|
// the compiler wants me to explicit right here for some reason
|
||||||
|
let default = || RefCell::new(Box::new(Events::<E>::new()) as Box<dyn CastableAny>);
|
||||||
|
|
||||||
|
// Get, or create, a list of events of this type
|
||||||
|
let type_id = event.type_id();
|
||||||
|
let mut events = self.event_write_queue.entry(type_id)
|
||||||
|
.or_insert_with(default)
|
||||||
|
.borrow_mut();
|
||||||
|
|
||||||
|
// downcast resource as an events storage
|
||||||
|
let e: &mut Events<E> = events.as_mut().as_any_mut().downcast_mut().unwrap();
|
||||||
|
e.push_back(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear events, this should happen at the start of every tick since events are cloned
|
||||||
|
// before being given to the reader.
|
||||||
|
pub fn update_events(&mut self) {
|
||||||
|
self.events.clear();
|
||||||
|
|
||||||
|
// get all keys of events
|
||||||
|
let keys: Vec<TypeId> = self.event_write_queue.keys().map(|k| k.clone()).collect();
|
||||||
|
|
||||||
|
// remove all elements from self.event_write_queue and insert them to events
|
||||||
|
for k in keys.into_iter() {
|
||||||
|
let v = self.event_write_queue.remove(&k).unwrap();
|
||||||
|
self.events.insert(k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_events<E>(&self) -> Option<Events<E>>
|
||||||
|
where
|
||||||
|
E: Event
|
||||||
|
{
|
||||||
|
if let Some(event ) = self.events.get(&TypeId::of::<E>()) {
|
||||||
|
let eref = event.borrow();
|
||||||
|
Some(eref.as_ref().as_any().downcast_ref::<Events<E>>().unwrap().clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,53 +1,6 @@
|
||||||
use std::{collections::VecDeque, ops::{Deref, DerefMut}};
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use super::Resource;
|
|
||||||
|
|
||||||
pub trait Event: Clone + Send + Sync + 'static {}
|
pub trait Event: Clone + Send + Sync + 'static {}
|
||||||
impl<T: Clone + Send + Sync + 'static> Event for T {}
|
impl<T: Clone + Send + Sync + 'static> Event for T {}
|
||||||
|
|
||||||
#[derive(Clone)]
|
pub type Events<T> = VecDeque<T>;
|
||||||
pub struct Events<T: Event> {
|
|
||||||
inner: VecDeque<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Event> Events<T> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
inner: VecDeque::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Event> Deref for Events<T> {
|
|
||||||
type Target = VecDeque<T>;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Event> DerefMut for Events<T> {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Event> Resource for Events<T> {
|
|
||||||
fn as_any(&self) -> &dyn std::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait EventHolder {
|
|
||||||
fn get_data<T>() -> T;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct EventStorage<T> {
|
|
||||||
data: T,
|
|
||||||
is_future: bool,
|
|
||||||
}
|
|
|
@ -8,22 +8,16 @@ pub use window_state::*;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
pub use events::*;
|
pub use events::*;
|
||||||
|
|
||||||
pub trait Resource: Send + Sync + 'static {
|
pub mod event_queue;
|
||||||
|
pub use event_queue::*;
|
||||||
|
|
||||||
|
pub trait CastableAny: Send + Sync + 'static {
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for WindowEvent<'static> {
|
/// Implements this trait for anything that fits the type bounds
|
||||||
fn as_any(&self) -> &dyn Any {
|
impl<T: Send + Sync + 'static> CastableAny for T {
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Sync + Send + 'static> Resource for VecDeque<T> {
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
use super::Resource;
|
use super::CastableAny;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct WindowState {
|
pub struct WindowState {
|
||||||
|
@ -12,14 +12,4 @@ impl WindowState {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Resource for WindowState {
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
185
src/ecs/world.rs
185
src/ecs/world.rs
|
@ -1,185 +0,0 @@
|
||||||
use std::{any::{TypeId, Any}, collections::{HashMap, HashSet, VecDeque}, ops::{Deref, DerefMut}, cell::{RefCell, Ref, RefMut}};
|
|
||||||
|
|
||||||
use tracing::debug;
|
|
||||||
|
|
||||||
use super::resources::{Resource, Events};
|
|
||||||
|
|
||||||
pub struct World {
|
|
||||||
inner: hecs::World,
|
|
||||||
resources: HashMap<TypeId, Box<RefCell<dyn Resource>>>,
|
|
||||||
updated_resources: HashSet<TypeId>,
|
|
||||||
|
|
||||||
// a boolean that flip flops to clear events every other frame
|
|
||||||
events_flipflop: bool,
|
|
||||||
events: HashMap<TypeId, Box<RefCell<dyn Resource>>>,
|
|
||||||
event_write_queue: HashMap<TypeId, Box<RefCell<dyn Resource>>>,//VecDeque<(TypeId, Box<dyn Resource>)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for World {
|
|
||||||
type Target = hecs::World;
|
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for World {
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
&mut self.inner
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
impl World {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::from_hecs(hecs::World::new())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_hecs(hecs_world: hecs::World) -> Self {
|
|
||||||
Self {
|
|
||||||
inner: hecs_world,
|
|
||||||
resources: HashMap::new(),
|
|
||||||
updated_resources: HashSet::new(),
|
|
||||||
events_flipflop: false,
|
|
||||||
events: HashMap::new(),
|
|
||||||
event_write_queue: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempts to query a resource, or will create it when its not found.
|
|
||||||
///
|
|
||||||
/// The resource will be created by a function passed in `default`.
|
|
||||||
pub fn query_or_insert_res<R>(&mut self, default: impl Fn() -> Box<RefCell<dyn Resource + 'static>>) -> RefMut<R>
|
|
||||||
where
|
|
||||||
R: Resource,
|
|
||||||
{
|
|
||||||
let type_id = TypeId::of::<R>();
|
|
||||||
let r = self.resources.entry(type_id)
|
|
||||||
.or_insert_with(default)
|
|
||||||
.borrow_mut();
|
|
||||||
|
|
||||||
RefMut::map(r, |r| r.as_any_mut().downcast_mut::<R>().unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Insert a resource into the World. You can only have one resource of the same type.
|
|
||||||
/// If you attempt to add another resource of the same type, it will be replaced.
|
|
||||||
///
|
|
||||||
/// This will also mark the resource as updated in this frame.
|
|
||||||
pub fn insert_resource<R>(&mut self, res: R)
|
|
||||||
where
|
|
||||||
R: Resource
|
|
||||||
{
|
|
||||||
let type_id = res.type_id();
|
|
||||||
self.resources.insert(type_id, Box::new(RefCell::new(res)));
|
|
||||||
self.updated_resources.insert(type_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if a resource was updated this frame.
|
|
||||||
pub fn was_res_updated<R>(&self) -> bool
|
|
||||||
where
|
|
||||||
R: Resource
|
|
||||||
{
|
|
||||||
self.updated_resources.contains(&TypeId::of::<R>())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn clear_updated_resources(&mut self) {
|
|
||||||
self.updated_resources.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trigger an event
|
|
||||||
pub fn trigger_event<E>(&mut self, event: E)
|
|
||||||
where
|
|
||||||
E: Clone + Send + Sync + 'static
|
|
||||||
{
|
|
||||||
// the compiler wants me to explicit right here for some reason
|
|
||||||
let default = || Box::new(RefCell::new(Events::<E>::new())) as Box<RefCell<(dyn Resource + 'static)>>;
|
|
||||||
|
|
||||||
// Get, or create, a list of events of this type
|
|
||||||
let type_id = event.type_id();
|
|
||||||
let events = self.event_write_queue.entry(type_id)
|
|
||||||
.or_insert_with(default)
|
|
||||||
.borrow_mut();
|
|
||||||
|
|
||||||
// downcast resource as an events storage
|
|
||||||
let mut events: RefMut<Events<E>> = RefMut::map(events, |e| e.as_any_mut().downcast_mut().unwrap());
|
|
||||||
|
|
||||||
events.push_back(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clear events, this should happen at the start of every tick since events are cloned
|
|
||||||
/// before being given to the reader.
|
|
||||||
pub fn update_events(&mut self) {
|
|
||||||
self.events.clear();
|
|
||||||
|
|
||||||
// get all keys of events
|
|
||||||
let keys: Vec<TypeId> = self.event_write_queue.keys().map(|k| k.clone()).collect();
|
|
||||||
|
|
||||||
// remove all elements from self.event_write_queue and insert them to events
|
|
||||||
for k in keys.into_iter() {
|
|
||||||
let v = self.event_write_queue.remove(&k).unwrap();
|
|
||||||
self.events.insert(k, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_events<E>(&self) -> Option<Ref<Events<E>>>
|
|
||||||
where
|
|
||||||
E: Clone + Send + Sync + 'static
|
|
||||||
{
|
|
||||||
if let Some(event ) = self.events.get(&TypeId::of::<E>()) {
|
|
||||||
//.or_else(|| self.event_write_queue.get(&TypeId::of::<E>())) {
|
|
||||||
let eref = event.borrow();
|
|
||||||
|
|
||||||
Some(Ref::map(eref, |x| x.as_any().downcast_ref::<Events<E>>().unwrap()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if let Some(event) = self.events.get(&TypeId::of::<E>()) {
|
|
||||||
let eref = event.borrow();
|
|
||||||
|
|
||||||
Some(Ref::map(eref, |x| x.as_any().downcast_ref::<Events<E>>().unwrap()))
|
|
||||||
} else if let Some(event) = self.events.get(&TypeId::of::<E>()) {
|
|
||||||
None
|
|
||||||
} */
|
|
||||||
|
|
||||||
/* self.events.get(&TypeId::of::<E>())
|
|
||||||
//.map(|r| r.borrow().as_any().downcast_ref::<Events<E>>())
|
|
||||||
.map(|r| r.borrow().as_any().do)
|
|
||||||
.flatten() */
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Query a resource.
|
|
||||||
///
|
|
||||||
/// This is O(1), resources are stored in HashMaps.
|
|
||||||
pub fn query_res<R>(&self) -> Option<Ref<R>>
|
|
||||||
where
|
|
||||||
R: Resource
|
|
||||||
{
|
|
||||||
self.resources
|
|
||||||
.get(&TypeId::of::<R>())
|
|
||||||
.map(|r| {
|
|
||||||
let r = r.borrow();
|
|
||||||
Ref::map(r, |r| r.as_any().downcast_ref().unwrap())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Query a resource mutably.
|
|
||||||
///
|
|
||||||
/// This will mark the resource as changed, even if it actually wasn't modified when mutably borrowed.
|
|
||||||
/// This is O(1), resources are stored in HashMaps.
|
|
||||||
pub fn query_res_mut<R>(&mut self) -> Option<RefMut<R>>
|
|
||||||
where
|
|
||||||
R: Resource
|
|
||||||
{
|
|
||||||
self.resources
|
|
||||||
.get_mut(&TypeId::of::<R>())
|
|
||||||
.map(|r| {
|
|
||||||
// update resource
|
|
||||||
self.updated_resources.insert(TypeId::of::<R>());
|
|
||||||
|
|
||||||
let r = r.borrow_mut();
|
|
||||||
|
|
||||||
RefMut::map(r, |r| r.as_any_mut().downcast_mut::<R>().unwrap())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
50
src/game.rs
50
src/game.rs
|
@ -1,4 +1,4 @@
|
||||||
use std::{sync::Arc, cell::RefCell, borrow::Borrow, collections::VecDeque};
|
use std::sync::Arc;
|
||||||
|
|
||||||
use async_std::{task::block_on, sync::Mutex};
|
use async_std::{task::block_on, sync::Mutex};
|
||||||
|
|
||||||
|
@ -13,10 +13,10 @@ use tracing_subscriber::{
|
||||||
|
|
||||||
use winit::{window::{WindowBuilder, Window}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, DeviceEvent}, event_loop::{EventLoop, ControlFlow}};
|
use winit::{window::{WindowBuilder, Window}, event::{Event, WindowEvent, KeyboardInput, ElementState, VirtualKeyCode, DeviceEvent}, event_loop::{EventLoop, ControlFlow}};
|
||||||
|
|
||||||
use crate::{render::{renderer::{Renderer, BasicRenderer}, render_job::RenderJob}, input_event::InputEvent, ecs::{components::{mesh::MeshComponent, transform::TransformComponent}, SimpleSystem, SystemDispatcher, world::World, resources::{WindowState, Events}}, input::InputEventUpdater};
|
use crate::{render::renderer::{Renderer, BasicRenderer}, input_event::InputEvent, ecs::{SimpleSystem, SystemDispatcher, resources::{WindowState, Events, EventQueue}}};
|
||||||
|
|
||||||
pub struct Controls<'a> {
|
pub struct Controls<'a> {
|
||||||
pub world: &'a mut World,
|
pub world: &'a mut edict::World,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TickCounter {
|
struct TickCounter {
|
||||||
|
@ -78,7 +78,7 @@ struct GameLoop {
|
||||||
window: Arc<Window>,
|
window: Arc<Window>,
|
||||||
renderer: Box<dyn Renderer>,
|
renderer: Box<dyn Renderer>,
|
||||||
|
|
||||||
world: Arc<Mutex<World>>,
|
world: Arc<Mutex<edict::World>>,
|
||||||
/// higher priority systems
|
/// higher priority systems
|
||||||
engine_sys_dispatcher: SystemDispatcher,
|
engine_sys_dispatcher: SystemDispatcher,
|
||||||
user_sys_dispatcher: SystemDispatcher,
|
user_sys_dispatcher: SystemDispatcher,
|
||||||
|
@ -86,7 +86,13 @@ struct GameLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameLoop {
|
impl GameLoop {
|
||||||
pub async fn new(window: Arc<Window>, world: Arc<Mutex<World>>, user_systems: SystemDispatcher) -> GameLoop {
|
pub async fn new(window: Arc<Window>, world: Arc<Mutex<edict::World>>, user_systems: SystemDispatcher) -> GameLoop {
|
||||||
|
// Create the EventQueue resource in the world
|
||||||
|
{
|
||||||
|
let mut world = world.lock().await;
|
||||||
|
world.insert_resource(EventQueue::new());
|
||||||
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
window: Arc::clone(&window),
|
window: Arc::clone(&window),
|
||||||
renderer: Box::new(BasicRenderer::create_with_window(window).await),
|
renderer: Box::new(BasicRenderer::create_with_window(window).await),
|
||||||
|
@ -99,7 +105,7 @@ impl GameLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
pub async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||||
self.renderer.on_resize(new_size).await;
|
self.renderer.on_resize(new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_sync(&mut self, event: Event<()>, control_flow: &mut ControlFlow) {
|
pub fn run_sync(&mut self, event: Event<()>, control_flow: &mut ControlFlow) {
|
||||||
|
@ -142,7 +148,7 @@ impl GameLoop {
|
||||||
InputEvent::CursorEntered { .. } => {
|
InputEvent::CursorEntered { .. } => {
|
||||||
let mut world = self.world.lock().await;
|
let mut world = self.world.lock().await;
|
||||||
|
|
||||||
let mut state = world.query_or_insert_res::<WindowState>(|| Box::new(RefCell::new(WindowState::new())));
|
let mut state = world.with_resource(|| WindowState::new());
|
||||||
state.is_cursor_inside_window = true;
|
state.is_cursor_inside_window = true;
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -151,7 +157,7 @@ impl GameLoop {
|
||||||
InputEvent::CursorLeft { .. } => {
|
InputEvent::CursorLeft { .. } => {
|
||||||
let mut world = self.world.lock().await;
|
let mut world = self.world.lock().await;
|
||||||
|
|
||||||
let mut state = world.query_or_insert_res::<WindowState>(|| Box::new(RefCell::new(WindowState::new())));
|
let mut state = world.with_resource(|| WindowState::new());
|
||||||
state.is_cursor_inside_window = false;
|
state.is_cursor_inside_window = false;
|
||||||
|
|
||||||
None
|
None
|
||||||
|
@ -186,14 +192,13 @@ impl GameLoop {
|
||||||
let mut world = self.world.lock().await;
|
let mut world = self.world.lock().await;
|
||||||
|
|
||||||
// make sure that the mouse is inside the window and the mouse has focus before reporting mouse motion
|
// make sure that the mouse is inside the window and the mouse has focus before reporting mouse motion
|
||||||
let trigger = match world.query_res::<WindowState>() {
|
let trigger = match world.get_resource::<WindowState>() {
|
||||||
Some(window_state) if window_state.is_focused && window_state.is_cursor_inside_window => true,
|
Some(window_state) if window_state.is_focused && window_state.is_cursor_inside_window => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if trigger {
|
if trigger {
|
||||||
let mut event_queue = world.query_or_insert_res::<Events<InputEvent>>
|
let event_queue = world.with_resource(|| Events::<InputEvent>::new());
|
||||||
(|| Box::new(RefCell::new(Events::<InputEvent>::new())));
|
|
||||||
|
|
||||||
let input_event = InputEvent::MouseMotion { device_id, delta, };
|
let input_event = InputEvent::MouseMotion { device_id, delta, };
|
||||||
event_queue.push_back(input_event);
|
event_queue.push_back(input_event);
|
||||||
|
@ -212,8 +217,10 @@ impl GameLoop {
|
||||||
// Its possible to receive multiple input events before the update event for
|
// Its possible to receive multiple input events before the update event for
|
||||||
// the InputSystem is called, so we must use a queue for the events.
|
// the InputSystem is called, so we must use a queue for the events.
|
||||||
{
|
{
|
||||||
let mut world = self.world.lock().await;
|
let world = self.world.lock().await;
|
||||||
world.trigger_event(input_event.clone());
|
if let Some(mut event_queue) = world.get_resource_mut::<EventQueue>() {
|
||||||
|
event_queue.trigger_event(input_event.clone());
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(new_control) = self.input_update(&input_event).await {
|
if let Some(new_control) = self.input_update(&input_event).await {
|
||||||
|
@ -238,7 +245,7 @@ impl GameLoop {
|
||||||
WindowEvent::Focused(is_focused) => {
|
WindowEvent::Focused(is_focused) => {
|
||||||
let mut world = self.world.lock().await;
|
let mut world = self.world.lock().await;
|
||||||
|
|
||||||
let mut state = world.query_or_insert_res::<WindowState>(|| Box::new(RefCell::new(WindowState::new())));
|
let mut state = world.with_resource(|| WindowState::new());
|
||||||
state.is_focused = *is_focused;
|
state.is_focused = *is_focused;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -257,12 +264,13 @@ impl GameLoop {
|
||||||
} */
|
} */
|
||||||
|
|
||||||
let mut world = self.world.lock().await;
|
let mut world = self.world.lock().await;
|
||||||
self.renderer.as_mut().prepare(&mut world).await;
|
self.renderer.as_mut().prepare(&mut world);
|
||||||
world.clear_updated_resources();
|
if let Some(mut event_queue) = world.get_resource_mut::<EventQueue>() {
|
||||||
world.update_events();
|
event_queue.update_events();
|
||||||
|
}
|
||||||
drop(world);
|
drop(world);
|
||||||
|
|
||||||
match self.renderer.as_mut().render().await {
|
match self.renderer.as_mut().render() {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
// Reconfigure the surface if lost
|
// Reconfigure the surface if lost
|
||||||
Err(wgpu::SurfaceError::Lost) => self.on_resize(self.renderer.as_ref().surface_size()).await,
|
Err(wgpu::SurfaceError::Lost) => self.on_resize(self.renderer.as_ref().surface_size()).await,
|
||||||
|
@ -282,7 +290,7 @@ impl GameLoop {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Game {
|
pub struct Game {
|
||||||
world: Option<Arc<Mutex<World>>>,
|
world: Option<Arc<Mutex<edict::World>>>,
|
||||||
system_dispatcher: Option<SystemDispatcher>
|
system_dispatcher: Option<SystemDispatcher>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,13 +320,13 @@ impl Game {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_world(&mut self, world: World) -> &mut Self {
|
pub fn with_world(&mut self, world: edict::World) -> &mut Self {
|
||||||
self.world = Some(Arc::new(Mutex::new(world)));
|
self.world = Some(Arc::new(Mutex::new(world)));
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_world_arc(&mut self, world: Arc<Mutex<World>>) -> &mut Self {
|
pub fn with_world_arc(&mut self, world: Arc<Mutex<edict::World>>) -> &mut Self {
|
||||||
self.world = Some(world);
|
self.world = Some(world);
|
||||||
|
|
||||||
self
|
self
|
||||||
|
|
76
src/input.rs
76
src/input.rs
|
@ -5,7 +5,7 @@ use glam::Vec2;
|
||||||
use tracing::{warn, debug};
|
use tracing::{warn, debug};
|
||||||
use winit::event::{VirtualKeyCode, ElementState, MouseScrollDelta};
|
use winit::event::{VirtualKeyCode, ElementState, MouseScrollDelta};
|
||||||
|
|
||||||
use crate::{ecs::{SimpleSystem, resources::{Resource, Events}, world::World}, input_event::InputEvent};
|
use crate::{ecs::{SimpleSystem, resources::{CastableAny, Events, EventQueue}}, input_event::InputEvent};
|
||||||
|
|
||||||
pub type KeyCode = winit::event::VirtualKeyCode;
|
pub type KeyCode = winit::event::VirtualKeyCode;
|
||||||
|
|
||||||
|
@ -100,16 +100,6 @@ pub struct Touches {
|
||||||
pub touches: Vec<Touch>,
|
pub touches: Vec<Touch>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for Touches {
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Touches {
|
impl Touches {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -152,16 +142,6 @@ pub struct InputButtons<T: Clone + Hash + Eq + PartialEq + 'static> {
|
||||||
button_events: HashMap<u64, ButtonEvent<T>>,
|
button_events: HashMap<u64, ButtonEvent<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Sync + Send + Clone + Hash + Eq + PartialEq + 'static> Resource for InputButtons<T> {
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone + Hash + Eq + PartialEq + 'static> InputButtons<T> {
|
impl<T: Clone + Hash + Eq + PartialEq + 'static> InputButtons<T> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -279,12 +259,19 @@ impl InputEventUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, event: &InputEvent, world: &mut World) -> bool {
|
pub fn update(&mut self, event: &InputEvent, world: &mut edict::World) -> bool {
|
||||||
|
let event_queue = world.get_resource_mut::<EventQueue>();
|
||||||
|
if event_queue.is_none() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let mut event_queue = event_queue.unwrap();
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
InputEvent::KeyboardInput { input, .. } => {
|
InputEvent::KeyboardInput { input, .. } => {
|
||||||
if let Some(code) = input.virtual_keycode {
|
if let Some(code) = input.virtual_keycode {
|
||||||
let mut e = world.query_or_insert_res::<InputButtons<KeyCode>>
|
drop(event_queue);
|
||||||
(|| Box::new(RefCell::new(InputButtons::<KeyCode>::new())));
|
let mut e = world.with_resource(|| InputButtons::<KeyCode>::new());
|
||||||
|
//let mut e = with_resource_mut(world, || InputButtons::<KeyCode>::new());
|
||||||
e.add_input_from_winit(code, input.state);
|
e.add_input_from_winit(code, input.state);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -293,22 +280,22 @@ impl InputEventUpdater {
|
||||||
delta: Vec2::new(delta.0 as f32, delta.1 as f32)
|
delta: Vec2::new(delta.0 as f32, delta.1 as f32)
|
||||||
};
|
};
|
||||||
|
|
||||||
world.trigger_event(delta);
|
event_queue.trigger_event(delta);
|
||||||
},
|
},
|
||||||
InputEvent::CursorMoved { position, .. } => {
|
InputEvent::CursorMoved { position, .. } => {
|
||||||
let exact = MouseExact {
|
let exact = MouseExact {
|
||||||
pos: Vec2::new(position.x as f32, position.y as f32)
|
pos: Vec2::new(position.x as f32, position.y as f32)
|
||||||
};
|
};
|
||||||
|
|
||||||
world.trigger_event(exact);
|
event_queue.trigger_event(exact);
|
||||||
},
|
},
|
||||||
InputEvent::CursorEntered { .. } => {
|
InputEvent::CursorEntered { .. } => {
|
||||||
let event = CursorEnteredWindow {};
|
let event = CursorEnteredWindow {};
|
||||||
world.trigger_event(event);
|
event_queue.trigger_event(event);
|
||||||
},
|
},
|
||||||
InputEvent::CursorLeft { .. } => {
|
InputEvent::CursorLeft { .. } => {
|
||||||
let event = CursorLeftWindow {};
|
let event = CursorLeftWindow {};
|
||||||
world.trigger_event(event);
|
event_queue.trigger_event(event);
|
||||||
},
|
},
|
||||||
InputEvent::MouseWheel { delta, .. } => {
|
InputEvent::MouseWheel { delta, .. } => {
|
||||||
let event = match delta {
|
let event = match delta {
|
||||||
|
@ -320,7 +307,7 @@ impl InputEventUpdater {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
world.trigger_event(event);
|
event_queue.trigger_event(event);
|
||||||
}, //MouseButton
|
}, //MouseButton
|
||||||
InputEvent::MouseInput { button, state, .. } => {
|
InputEvent::MouseInput { button, state, .. } => {
|
||||||
let button_event = match button {
|
let button_event = match button {
|
||||||
|
@ -330,13 +317,15 @@ impl InputEventUpdater {
|
||||||
winit::event::MouseButton::Other(v) => MouseButton::Other(*v),
|
winit::event::MouseButton::Other(v) => MouseButton::Other(*v),
|
||||||
};
|
};
|
||||||
|
|
||||||
world.trigger_event(button_event.clone());
|
event_queue.trigger_event(button_event.clone());
|
||||||
|
drop(event_queue);
|
||||||
|
|
||||||
let mut e = world.query_or_insert_res::<InputButtons<MouseButton>>
|
let mut e = world.with_resource(|| InputButtons::<MouseButton>::new());
|
||||||
(|| Box::new(RefCell::new(InputButtons::<MouseButton>::new())));
|
|
||||||
e.add_input_from_winit(button_event, state.clone());
|
e.add_input_from_winit(button_event, state.clone());
|
||||||
},
|
},
|
||||||
InputEvent::Touch(t) => {
|
InputEvent::Touch(t) => {
|
||||||
|
drop(event_queue);
|
||||||
|
|
||||||
let touch = Touch {
|
let touch = Touch {
|
||||||
phase: TouchPhase::from(t.phase),
|
phase: TouchPhase::from(t.phase),
|
||||||
location: Vec2::new(t.location.x as f32, t.location.y as f32),
|
location: Vec2::new(t.location.x as f32, t.location.y as f32),
|
||||||
|
@ -347,9 +336,7 @@ impl InputEventUpdater {
|
||||||
finger_id: t.id,
|
finger_id: t.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut touches = world.query_or_insert_res::<Touches>
|
let mut touches = world.with_resource(|| Touches::new());
|
||||||
(|| Box::new(RefCell::new(Touches::new())));
|
|
||||||
|
|
||||||
touches.touches.push(touch);
|
touches.touches.push(touch);
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
|
@ -363,32 +350,19 @@ impl SimpleSystem for InputEventUpdater {
|
||||||
fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> {
|
fn execute_mut(&mut self, controls: &mut crate::game::Controls) -> anyhow::Result<()> {
|
||||||
let world = &mut controls.world;
|
let world = &mut controls.world;
|
||||||
|
|
||||||
let queue = world.read_events::<InputEvent>();
|
let queue = world.get_resource_mut::<EventQueue>()
|
||||||
|
.map(|q| q.read_events::<InputEvent>()).flatten();
|
||||||
|
|
||||||
if queue.is_none() {
|
if queue.is_none() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let queue = queue.unwrap();
|
let mut events = queue.unwrap();
|
||||||
|
|
||||||
// borrow checker isn't happy when I query multiple things :(
|
|
||||||
let mut events = queue.clone();
|
|
||||||
drop(queue);
|
|
||||||
|
|
||||||
while let Some(event) = events.pop_front() {
|
while let Some(event) = events.pop_front() {
|
||||||
self.update(&event, world);
|
self.update(&event, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if let Some(queue) = world.read_events::<InputEvent>() {
|
|
||||||
// Clone the queue, then clear it
|
|
||||||
let mut events = queue.clone();
|
|
||||||
drop(queue);
|
|
||||||
|
|
||||||
while let Some(event) = events.pop_front() {
|
|
||||||
self.update(&event, world);
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use winit::{event::{DeviceId, KeyboardInput, ModifiersState, MouseScrollDelta, TouchPhase, MouseButton, AxisId, Touch, WindowEvent, ElementState}, dpi::PhysicalPosition};
|
use winit::{event::{DeviceId, KeyboardInput, ModifiersState, MouseScrollDelta, TouchPhase, MouseButton, AxisId, Touch, WindowEvent, ElementState}, dpi::PhysicalPosition};
|
||||||
|
|
||||||
use crate::ecs::resources::Resource;
|
use crate::ecs::resources::CastableAny;
|
||||||
|
|
||||||
/// Wrapper around events from `winit::WindowEvent` that are specific to input related events.
|
/// Wrapper around events from `winit::WindowEvent` that are specific to input related events.
|
||||||
///
|
///
|
||||||
|
@ -220,14 +220,4 @@ impl<'a> TryFrom<&'a WindowEvent<'a>> for InputEvent {
|
||||||
_ => Err(InputEventConversionError::FromError(value))
|
_ => Err(InputEventConversionError::FromError(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Resource for InputEvent {
|
|
||||||
fn as_any(&self) -> &dyn std::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
26
src/main.rs
26
src/main.rs
|
@ -6,16 +6,15 @@ mod ecs;
|
||||||
mod math;
|
mod math;
|
||||||
mod input;
|
mod input;
|
||||||
|
|
||||||
use std::cell::Ref;
|
use atomicell::Ref;
|
||||||
|
|
||||||
use ecs::components::mesh::MeshComponent;
|
use ecs::components::mesh::MeshComponent;
|
||||||
|
|
||||||
use ecs::components::transform::TransformComponent;
|
use ecs::components::transform::TransformComponent;
|
||||||
|
use edict::QueryIter;
|
||||||
use game::Game;
|
use game::Game;
|
||||||
use input_event::InputEvent;
|
use input_event::InputEvent;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::ecs::world::World;
|
|
||||||
use crate::input::{InputEventUpdater, KeyCode, MouseMotion, MouseExact, CursorEnteredWindow, MouseScroll, CursorLeftWindow, MouseButton, InputButtons};
|
use crate::input::{InputEventUpdater, KeyCode, MouseMotion, MouseExact, CursorEnteredWindow, MouseScroll, CursorLeftWindow, MouseButton, InputButtons};
|
||||||
use crate::render::material::Material;
|
use crate::render::material::Material;
|
||||||
use crate::render::texture::Texture;
|
use crate::render::texture::Texture;
|
||||||
|
@ -68,7 +67,7 @@ impl Point3d {
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let mut world = World::new();
|
let mut world = edict::World::new();
|
||||||
|
|
||||||
//world.spawn((Point2d::new(10, 10), Point3d::new(50, 50, 50)));
|
//world.spawn((Point2d::new(10, 10), Point3d::new(50, 50, 50)));
|
||||||
|
|
||||||
|
@ -91,10 +90,8 @@ async fn main() {
|
||||||
camera.transform.rotate_z(Angle::Degrees(-90.0));
|
camera.transform.rotate_z(Angle::Degrees(-90.0));
|
||||||
world.spawn((camera,));
|
world.spawn((camera,));
|
||||||
|
|
||||||
let jiggle_system = |world: &mut World| -> anyhow::Result<()> {
|
let jiggle_system = |world: &mut edict::World| -> anyhow::Result<()> {
|
||||||
//let input: &InputEventUpdater = world.query_res().unwrap();
|
let keys = world.get_resource();
|
||||||
|
|
||||||
let keys = world.query_res();
|
|
||||||
if keys.is_none() {
|
if keys.is_none() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -124,7 +121,16 @@ async fn main() {
|
||||||
|
|
||||||
drop(keys);
|
drop(keys);
|
||||||
|
|
||||||
for (_eid, (transform, )) in world.query_mut::<(&mut TransformComponent,)>() {
|
for transform in world.query_mut::<(&mut TransformComponent,)>().iter_mut() {
|
||||||
|
let t = &mut transform.transform;
|
||||||
|
//debug!("Translation: {}", t.translation);
|
||||||
|
|
||||||
|
/* t.translation += glam::Vec3::new(0.0, 0.001, 0.0);
|
||||||
|
t.translation.x *= -1.0; */
|
||||||
|
t.translation.x += dir_x;
|
||||||
|
t.translation.y += dir_y;
|
||||||
|
}
|
||||||
|
/* for (transform,) in world.query_mut::<(TransformComponent, )>().iter() {
|
||||||
let t = &mut transform.transform;
|
let t = &mut transform.transform;
|
||||||
|
|
||||||
/* debug!("Translation: {}", t.translation);
|
/* debug!("Translation: {}", t.translation);
|
||||||
|
@ -133,7 +139,7 @@ async fn main() {
|
||||||
t.translation.x *= -1.0 */
|
t.translation.x *= -1.0 */
|
||||||
t.translation.x += dir_x;
|
t.translation.x += dir_x;
|
||||||
t.translation.y += dir_y;
|
t.translation.y += dir_y;
|
||||||
}
|
} */
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@ pub fn radians_to_degrees(radians: f32) -> f32 {
|
||||||
radians * 180.0 / PI
|
radians * 180.0 / PI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Angle {
|
pub enum Angle {
|
||||||
Degrees(f32),
|
Degrees(f32),
|
||||||
Radians(f32),
|
Radians(f32),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use hecs::Entity;
|
use edict::EntityId;
|
||||||
|
|
||||||
use crate::math::Transform;
|
use crate::math::Transform;
|
||||||
|
|
||||||
|
@ -7,14 +7,14 @@ use super::{mesh::Mesh, material::Material};
|
||||||
pub struct RenderJob {
|
pub struct RenderJob {
|
||||||
mesh: Mesh,
|
mesh: Mesh,
|
||||||
material: Material,
|
material: Material,
|
||||||
entity: Entity,
|
entity: EntityId,
|
||||||
|
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
last_transform: Option<Transform>, // TODO: render interpolation
|
last_transform: Option<Transform>, // TODO: render interpolation
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderJob {
|
impl RenderJob {
|
||||||
pub fn new(mesh: Mesh, material: Material, entity: Entity, transform: Transform, last_transform: Option<Transform>) -> Self {
|
pub fn new(mesh: Mesh, material: Material, entity: EntityId, transform: Transform, last_transform: Option<Transform>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
mesh,
|
mesh,
|
||||||
material,
|
material,
|
||||||
|
@ -32,7 +32,7 @@ impl RenderJob {
|
||||||
&self.material
|
&self.material
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn entity(&self)-> Entity {
|
pub fn entity(&self)-> EntityId {
|
||||||
self.entity
|
self.entity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,16 @@ use std::borrow::Cow;
|
||||||
use async_std::sync::Mutex;
|
use async_std::sync::Mutex;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
|
use atomicell::{AtomicCell, RefMut};
|
||||||
|
use edict::{EntityId, Entities};
|
||||||
use tracing::{debug, warn};
|
use tracing::{debug, warn};
|
||||||
use wgpu::{BindGroup, BindGroupLayout};
|
use wgpu::{BindGroup, BindGroupLayout};
|
||||||
use wgpu::util::DeviceExt;
|
use wgpu::util::DeviceExt;
|
||||||
use winit::window::Window;
|
use winit::window::Window;
|
||||||
|
|
||||||
use hecs::Entity;
|
|
||||||
|
|
||||||
use crate::ecs::components::camera::CameraComponent;
|
use crate::ecs::components::camera::CameraComponent;
|
||||||
use crate::ecs::components::mesh::MeshComponent;
|
use crate::ecs::components::mesh::MeshComponent;
|
||||||
use crate::ecs::components::transform::TransformComponent;
|
use crate::ecs::components::transform::TransformComponent;
|
||||||
use crate::ecs::world::World;
|
|
||||||
use crate::math::{Transform, Angle};
|
use crate::math::{Transform, Angle};
|
||||||
use crate::resources;
|
use crate::resources;
|
||||||
|
|
||||||
|
@ -25,11 +24,10 @@ use super::desc_buf_lay::DescVertexBufferLayout;
|
||||||
use super::texture::RenderTexture;
|
use super::texture::RenderTexture;
|
||||||
use super::{render_pipeline::FullRenderPipeline, vertex::{VERTICES}, render_buffer::BufferStorage, render_job::RenderJob, mesh::Mesh};
|
use super::{render_pipeline::FullRenderPipeline, vertex::{VERTICES}, render_buffer::BufferStorage, render_job::RenderJob, mesh::Mesh};
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
pub trait Renderer {
|
pub trait Renderer {
|
||||||
async fn prepare(&mut self, main_world: &mut World);
|
fn prepare(&mut self, main_world: &mut edict::World);
|
||||||
async fn render(&mut self) -> Result<(), wgpu::SurfaceError>;
|
fn render(&mut self) -> Result<(), wgpu::SurfaceError>;
|
||||||
async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>);
|
fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>);
|
||||||
|
|
||||||
fn surface_size(&self) -> winit::dpi::PhysicalSize<u32>;
|
fn surface_size(&self) -> winit::dpi::PhysicalSize<u32>;
|
||||||
fn add_render_pipeline(&mut self, shader_id: u32, pipeline: Arc<FullRenderPipeline>);
|
fn add_render_pipeline(&mut self, shader_id: u32, pipeline: Arc<FullRenderPipeline>);
|
||||||
|
@ -57,7 +55,7 @@ pub struct BasicRenderer {
|
||||||
pub render_pipelines: HashMap<u32, Arc<FullRenderPipeline>>,
|
pub render_pipelines: HashMap<u32, Arc<FullRenderPipeline>>,
|
||||||
pub render_jobs: VecDeque<RenderJob>,
|
pub render_jobs: VecDeque<RenderJob>,
|
||||||
|
|
||||||
buffer_storage: HashMap<Entity, RenderBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
buffer_storage: HashMap<EntityId, RenderBufferStorage>, // TODO: clean up left over buffers from deleted entities/components
|
||||||
|
|
||||||
transform_buffer: wgpu::Buffer,
|
transform_buffer: wgpu::Buffer,
|
||||||
transform_bind_group: wgpu::BindGroup,
|
transform_bind_group: wgpu::BindGroup,
|
||||||
|
@ -346,10 +344,10 @@ impl BasicRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl Renderer for BasicRenderer {
|
impl Renderer for BasicRenderer {
|
||||||
async fn prepare(&mut self, main_world: &mut World) {
|
fn prepare(&mut self, main_world: &mut edict::World) {
|
||||||
for (entity, (model, transform)) in main_world.query::<(&MeshComponent, &TransformComponent)>().iter() {
|
|
||||||
|
for (entity, model, transform) in main_world.query::<(Entities, &MeshComponent, &TransformComponent)>().iter() {
|
||||||
// Create the render job and push it to the queue
|
// Create the render job and push it to the queue
|
||||||
let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity, transform.transform, None);
|
let job = RenderJob::new(model.mesh.clone(), model.material.clone(), entity, transform.transform, None);
|
||||||
self.render_jobs.push_back(job);
|
self.render_jobs.push_back(job);
|
||||||
|
@ -360,8 +358,7 @@ impl Renderer for BasicRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the active camera
|
if let Some(camera) = main_world.query_mut::<(&mut CameraComponent,)>().into_iter().next() {
|
||||||
if let Some((_e, (camera,))) = main_world.query_mut::<(&mut CameraComponent,)>().into_iter().next() {
|
|
||||||
let view_proj = self.inuse_camera.update_view_projection(camera);
|
let view_proj = self.inuse_camera.update_view_projection(camera);
|
||||||
self.queue.write_buffer(&self.camera_buffer, 0, bytemuck::cast_slice(&[view_proj.clone()]));
|
self.queue.write_buffer(&self.camera_buffer, 0, bytemuck::cast_slice(&[view_proj.clone()]));
|
||||||
} else {
|
} else {
|
||||||
|
@ -369,7 +366,7 @@ impl Renderer for BasicRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
|
||||||
let output = self.surface.get_current_texture()?;
|
let output = self.surface.get_current_texture()?;
|
||||||
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
||||||
|
|
||||||
|
@ -434,7 +431,7 @@ impl Renderer for BasicRenderer {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
fn on_resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||||
if new_size.width > 0 && new_size.height > 0 {
|
if new_size.width > 0 && new_size.height > 0 {
|
||||||
self.size = new_size;
|
self.size = new_size;
|
||||||
self.config.width = new_size.width;
|
self.config.width = new_size.width;
|
||||||
|
|
Loading…
Reference in New Issue