use super::{Scene, DeferredScene};
use rinecs::{
System, SystemThreadLocal, Entities, Resources, EntitiesThreadLocal, ResourcesThreadLocal,
SystemConditionSend, SystemConditionThreadLocal, SystemId, Read, barrier, StorageRegistry
};
use crate::time::Clock;
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
use rin_window::Window;
use rin_window::{self as window, events::{Event, MouseEvent, KeyEvent, WindowEvent}, WindowExt};
use rin_events::{StreamExt, Stream, TryIter, Property};
use rin_math::Rect;
use std::any::TypeId;
use std::path::PathBuf;
#[cfg(gui)]
use rin_gui::ParameterGroup;
#[cfg(feature = "dynamic_systems")]
use std::marker::PhantomData;
#[cfg(feature="web")]
use rin_window::events::WebFile;
pub trait Bundle{
#[cfg(gui)]
type Parameters: ParameterGroup;
#[cfg(not(gui))]
type Parameters;
fn parameters(&self) -> Option<&Self::Parameters>;
fn name(&self) -> &str;
fn setup(self, scene: &mut DeferredScene);
fn after_all_bundles_registered(_: &mut Scene){}
}
#[barrier(name = "barrier (update | render)")]
pub struct UpdateRenderBarrier;
pub trait UpdateSystem: Send{
fn update(&mut self, clock: &Clock, entities: Entities, resources: Resources);
fn checks(_: &mut StorageRegistry) -> Option<SystemConditionSend> where Self: Sized { None }
fn name() -> Option<&'static str> where Self: Sized { None }
fn before() -> Vec<SystemId> where Self: Sized { vec![] }
fn after() -> Vec<SystemId> where Self: Sized { vec![] }
fn updates() -> Vec<TypeId> where Self: Sized { vec![] }
fn needs() -> Vec<TypeId> where Self: Sized { vec![] }
fn reads() -> Vec<TypeId> where Self: Sized { vec![] }
fn writes() -> Vec<TypeId> where Self: Sized { vec![] }
fn file_line_info(&self) -> &'static str { "" }
}
impl<F> UpdateSystem for F
where F: Fn(&Clock, Entities, Resources) + Send
{
fn update(&mut self, clock: &Clock, entities: Entities, resources: Resources) {
(*self)(clock, entities, resources)
}
}
pub struct UpdateWrapper<U>(pub(crate) U);
impl<U: UpdateSystem> System for UpdateWrapper<U> {
fn run(&mut self, entities: Entities, resources: Resources){
let clock = resources.get::<Clock>().unwrap();
self.0.update(&clock, entities, resources)
}
fn checks(e: &mut StorageRegistry) -> Option<SystemConditionSend> where Self: Sized {
U::checks(e)
}
fn name() -> Option<&'static str> where Self: Sized { U::name() }
fn before() -> Vec<SystemId> where Self: Sized {
let mut before = U::before();
before.push(SystemId::barrier::<UpdateRenderBarrier>());
before
}
fn after() -> Vec<SystemId> where Self: Sized { U::after() }
fn updates() -> Vec<TypeId> where Self: Sized { U::updates() }
fn needs() -> Vec<TypeId> where Self: Sized {
let mut needs = U::needs();
needs.push(TypeId::of::<Clock>());
needs
}
fn reads() -> Vec<TypeId> where Self: Sized { U::reads() }
fn writes() -> Vec<TypeId> where Self: Sized { U::writes() }
}
pub trait UpdateSystemThreadLocal {
fn update(
&mut self,
clock: &Clock,
entities: EntitiesThreadLocal,
resources: ResourcesThreadLocal);
fn checks(_: &mut StorageRegistry) -> Option<SystemConditionThreadLocal> where Self: Sized {
None
}
fn name() -> Option<&'static str> where Self: Sized { None }
fn before() -> Vec<SystemId> where Self: Sized { vec![] }
fn after() -> Vec<SystemId> where Self: Sized { vec![] }
fn updates() -> Vec<TypeId> where Self: Sized { vec![] }
fn needs() -> Vec<TypeId> where Self: Sized { vec![] }
fn reads() -> Vec<TypeId> where Self: Sized { vec![] }
fn writes() -> Vec<TypeId> where Self: Sized { vec![] }
fn file_line_info(&self) -> &'static str { "" }
}
impl<F> UpdateSystemThreadLocal for F
where F: Fn(&Clock, EntitiesThreadLocal, ResourcesThreadLocal) + Send
{
fn update(
&mut self,
clock: &Clock,
entities: EntitiesThreadLocal,
resources: ResourcesThreadLocal)
{
(*self)(clock, entities, resources)
}
}
impl<U: UpdateSystemThreadLocal> SystemThreadLocal for UpdateWrapper<U> {
fn run(&mut self, entities: EntitiesThreadLocal, resources: ResourcesThreadLocal){
let clock = resources.get::<Clock>().unwrap();
self.0.update(&clock, entities, resources)
}
fn checks(e: &mut StorageRegistry) -> Option<SystemConditionThreadLocal> where Self: Sized {
U::checks(e)
}
fn name() -> Option<&'static str> where Self: Sized { U::name() }
fn before() -> Vec<SystemId> where Self: Sized {
let mut before = U::before();
before.push(SystemId::barrier::<UpdateRenderBarrier>());
before
}
fn after() -> Vec<SystemId> where Self: Sized { U::after() }
fn updates() -> Vec<TypeId> where Self: Sized { U::updates() }
fn needs() -> Vec<TypeId> where Self: Sized {
let mut needs = U::needs();
needs.push(TypeId::of::<Clock>());
needs
}
fn reads() -> Vec<TypeId> where Self: Sized { U::reads() }
fn writes() -> Vec<TypeId> where Self: Sized { U::writes() }
fn file_line_info(&self) -> &'static str { "" }
}
pub trait EventsSystem: Send{
fn mouse(&mut self, _: &MouseEvent, _: Entities, _: Resources){}
fn key(&mut self, _: &KeyEvent, _: Entities, _: Resources){}
fn window(&mut self, _: &WindowEvent, _: Entities, _: Resources){}
fn dropped(&mut self, _: &[PathBuf], _: Entities, _: Resources){}
#[cfg(feature="web")]
fn dropped_web_file(&mut self, _: &WebFile, _: Entities, _: Resources){}
fn focus_gained(&mut self, _: Entities, _: Resources){}
fn focus_lost(&mut self, _: Entities, _: Resources){}
fn checks(_: &mut StorageRegistry) -> Option<SystemConditionSend> where Self: Sized { None }
fn name() -> Option<&'static str> where Self: Sized { None }
fn before() -> Vec<SystemId> where Self: Sized { vec![] }
fn after() -> Vec<SystemId> where Self: Sized { vec![] }
fn updates() -> Vec<TypeId> where Self: Sized { vec![] }
fn needs() -> Vec<TypeId> where Self: Sized { vec![] }
fn reads() -> Vec<TypeId> where Self: Sized { vec![] }
fn writes() -> Vec<TypeId> where Self: Sized { vec![] }
fn file_line_info(&self) -> &'static str { "" }
}
pub trait EventsSystemThreadLocal{
fn mouse(&mut self, _: &MouseEvent, _: EntitiesThreadLocal, _: ResourcesThreadLocal){}
fn key(&mut self, _: &KeyEvent, _: EntitiesThreadLocal, _: ResourcesThreadLocal){}
fn window(&mut self, _: &WindowEvent, _: EntitiesThreadLocal, _: ResourcesThreadLocal){}
fn dropped(&mut self, _: &[PathBuf], _: EntitiesThreadLocal, _: ResourcesThreadLocal){}
#[cfg(feature="web")]
fn dropped_web_file(&mut self, _: &WebFile, _: EntitiesThreadLocal, _: ResourcesThreadLocal){}
fn focus_gained(&mut self, _: EntitiesThreadLocal, _: ResourcesThreadLocal){}
fn focus_lost(&mut self, _: EntitiesThreadLocal, _: ResourcesThreadLocal){}
fn checks(_: EntitiesThreadLocal) -> Option<SystemConditionThreadLocal> where Self: Sized {
None
}
fn name() -> Option<&'static str> where Self: Sized { None }
fn before() -> Vec<SystemId> where Self: Sized { vec![] }
fn after() -> Vec<SystemId> where Self: Sized { vec![] }
fn updates() -> Vec<TypeId> where Self: Sized { vec![] }
fn needs() -> Vec<TypeId> where Self: Sized { vec![] }
fn reads() -> Vec<TypeId> where Self: Sized { vec![] }
fn writes() -> Vec<TypeId> where Self: Sized { vec![] }
fn file_line_info(&self) -> &'static str { "" }
}
pub struct EventsWrapper<S>{
system: S,
window_events: TryIter<'static, Event>,
}
impl<S> EventsWrapper<S>{
pub fn new<E>(system: S, window_events: E) -> EventsWrapper<S>
where E: StreamExt<'static, Event> + 'static
{
EventsWrapper{
system,
window_events: window_events.try_iter(),
}
}
}
impl<S: EventsSystem> System for EventsWrapper<S>{
fn run(&mut self, mut entities: Entities, resources: Resources){
for event in self.window_events.by_ref(){
match event {
Event::MousePressed{ pos, button, mods } =>
self.system.mouse(&MouseEvent::Pressed{pos, button, mods}, entities.clone(), resources.clone()),
Event::MouseReleased{ pos, button, mods } =>
self.system.mouse(&MouseEvent::Released{pos, button, mods}, entities.clone(), resources.clone()),
Event::MouseMoved{ pos } =>
self.system.mouse(&MouseEvent::Moved{pos}, entities.clone(), resources.clone()),
Event::Scroll{ scroll } =>
self.system.mouse(&MouseEvent::Scrolled{scroll}, entities.clone(), resources.clone()),
Event::KeyPressed{ key, mods, repeat } =>
self.system.key(&KeyEvent::Pressed{key, mods, repeat}, entities.clone(), resources.clone()),
Event::KeyReleased{ key } =>
self.system.key(&KeyEvent::Released{key}, entities.clone(), resources.clone()),
Event::Char{character} =>
self.system.key(&KeyEvent::Char{character}, entities.clone(), resources.clone()),
Event::WindowMoved{ pos } =>
self.system.window(&WindowEvent::Moved{ pos }, entities.clone(), resources.clone()),
Event::WindowResized{ size } =>
self.system.window(&WindowEvent::Resized{ size }, entities.clone(), resources.clone()),
Event::WindowClosing =>
self.system.window(&WindowEvent::Closing, entities.clone(), resources.clone()),
Event::Dropped{paths} =>
self.system.dropped(&paths, entities.clone(), resources.clone()),
#[cfg(feature="web")]
Event::DroppedWebFile{file} =>
self.system.dropped_web_file(&file, entities, resources),
Event::Update{..} => (),
Event::FocusLost =>
self.system.focus_lost(entities.clone(), resources.clone()),
Event::FocusGained =>
self.system.focus_gained(entities.clone(), resources.clone()),
}
}
}
fn checks(e: &mut StorageRegistry) -> Option<SystemConditionSend> where Self: Sized {
S::checks(e)
}
fn name() -> Option<&'static str> where Self: Sized { S::name() }
fn before() -> Vec<SystemId> where Self: Sized { S::before() }
fn after() -> Vec<SystemId> where Self: Sized { S::after() }
fn updates() -> Vec<TypeId> where Self: Sized { S::updates() }
fn needs() -> Vec<TypeId> where Self: Sized {
let mut needs = S::needs();
needs.push(TypeId::of::<Clock>());
needs
}
fn reads() -> Vec<TypeId> where Self: Sized { S::reads() }
fn writes() -> Vec<TypeId> where Self: Sized { S::writes() }
}
impl<S: EventsSystemThreadLocal> SystemThreadLocal for EventsWrapper<S>{
fn run(&mut self, mut entities: EntitiesThreadLocal, resources: ResourcesThreadLocal){
for event in self.window_events.by_ref(){
match event {
Event::MousePressed{ pos, button, mods } =>
self.system.mouse(&MouseEvent::Pressed{pos, button, mods}, entities.clone(), resources.clone()),
Event::MouseReleased{ pos, button, mods } =>
self.system.mouse(&MouseEvent::Released{pos, button, mods}, entities.clone(), resources.clone()),
Event::MouseMoved{ pos } =>
self.system.mouse(&MouseEvent::Moved{pos}, entities.clone(), resources.clone()),
Event::Scroll{ scroll } =>
self.system.mouse(&MouseEvent::Scrolled{scroll}, entities.clone(), resources.clone()),
Event::KeyPressed{ key, mods, repeat } =>
self.system.key(&KeyEvent::Pressed{key, mods, repeat}, entities.clone(), resources.clone()),
Event::KeyReleased{ key } =>
self.system.key(&KeyEvent::Released{key}, entities.clone(), resources.clone()),
Event::Char{character} =>
self.system.key(&KeyEvent::Char{character}, entities.clone(), resources.clone()),
Event::WindowMoved{ pos } =>
self.system.window(&WindowEvent::Moved{ pos }, entities.clone(), resources.clone()),
Event::WindowResized{ size } =>
self.system.window(&WindowEvent::Resized{ size }, entities.clone(), resources.clone()),
Event::WindowClosing =>
self.system.window(&WindowEvent::Closing, entities.clone(), resources.clone()),
Event::Dropped{paths} =>
self.system.dropped(&paths, entities.clone(), resources.clone()),
#[cfg(feature="web")]
Event::DroppedWebFile{file} =>
self.system.dropped_web_file(&file, entities, resources),
Event::Update{..} => (),
Event::FocusLost =>
self.system.focus_lost(entities.clone(), resources.clone()),
Event::FocusGained =>
self.system.focus_gained(entities.clone(), resources.clone()),
}
}
}
fn checks(_: &mut StorageRegistry) -> Option<SystemConditionThreadLocal> where Self: Sized {
None
}
fn name() -> Option<&'static str> where Self: Sized { None }
fn before() -> Vec<SystemId> where Self: Sized { vec![] }
fn after() -> Vec<SystemId> where Self: Sized { vec![] }
fn updates() -> Vec<TypeId> where Self: Sized { vec![] }
fn needs() -> Vec<TypeId> where Self: Sized { vec![] }
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
pub trait RendererBundle {
#[cfg(feature="gui")]
type Parameters: ParameterGroup;
#[cfg(not(feature="gui"))]
type Parameters;
fn parameters(&self) -> Option<&Self::Parameters>{ None }
fn name(&self) -> &str{ std::any::type_name::<Self>() }
fn setup(self, scene: &mut DeferredScene);
fn viewport(&mut self) -> Property<'static, Rect<i32>>;
fn window(&self) -> Option<&Window>;
fn window_mut(&mut self) -> Option<&mut Window>;
fn event_stream(&mut self) -> Stream<'static, window::Event>;
fn file_line_info(&self) -> &'static str { "" }
}
pub enum RenderStage{
RenderSurfaceOpaque,
AfterPostprocessingOpaque,
RenderSurfaceTranslucent,
AfterPostprocessing,
Window,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum RendersTo{
MainRenderSurface,
RenderPlane(rinecs::Entity),
}
impl RendersTo{
pub(crate) fn entity(&self) -> Option<&rinecs::Entity>{
match self{
RendersTo::MainRenderSurface => None,
RendersTo::RenderPlane(e) => Some(e),
}
}
}
pub mod render_stage{
pub struct RenderSurfaceOpaque;
pub struct AfterRenderSurfaceOpaque;
pub struct PostprocessingOpaque;
pub struct AfterPostprocessingOpaque;
pub struct RenderSurfaceTranslucent;
pub struct AfterRenderSurfaceTranslucent;
pub struct Postprocessing;
pub struct AfterPostprocessing;
pub struct FinalSurface;
pub struct FinalSurfaceBlit;
pub struct Window;
}