use crate::{
Bundle,
components::{Name, Visible, Ty, SourcePath},
geometry::{
Geometry, GeometryRef, Submesh, VertexGroups
},
transformation::{Bone, PreviousTransformation, Camera, RenderPlane, SkinningUpToDate },
light::{self,
Light,
DirectionalLight,
DirectionalLightBuilder,
DirectionalLightMatrices,
PointLightBuilder,
SpotLight,
SpotLightBuilder,
SpotLightMatrices,
AreaLightBuilder,
AreaLight,
AmbientLight,
PointLight,
shadow},
};
#[cfg(feature="debug_geometry")]
use crate::geometry::DebugGeometryRef;
#[cfg(feature="materials")]
use rin_material::{
MaterialRef, MaterialMultiRef, ShadowMaterialRef,
texture::{TextureRef, SamplerRef, CubemapRef, Sampler, TextureCreationFlags}
};
#[cfg(feature="gl_forward_renderer")]
use crate::renderer::{
self,
FullMaterial, MaterialPool, TexturesPool, ShadowMaterialPool,
light::{
ImageBasedLightBuilder,
},
};
#[cfg(all(not(feature="gl"), feature="materials"))]
use rin_material::Material as FullMaterial;
use crate::bundle::{
UpdateSystem, UpdateSystemThreadLocal, UpdateWrapper,
EventsSystem, EventsSystemThreadLocal, EventsWrapper,
UpdateRenderBarrier,
};
#[cfg(feature="gl")]
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
use crate::immediate_renderer::{RenderSystem, RenderWrapper};
use rinecs::{Component, ComponentSend, ComponentThreadLocal, CreationContextExt, CreationSto, CreationSystem, DebugParameter, Entities, EntitiesCreation, EntitiesCreationExt, EntitiesData, EntitiesExt, EntitiesThreadLocal, Entity, EntityStoragesCreation, EntityStoragesExt, HierarchicalStorage, IntoEntitiesIterator, NToOneComponentSend, NodePtr, NodePtrMut, Not, OneToNComponentSend, OneToNComponentThreadLocal, OneToNStorage, OrderedData, Ptr, PtrMut, ReadGuardRef, Resources, ResourcesCreation, ResourcesCreationExt, ResourcesExt, ResourcesThreadLocal, ResourcesThreadLocalExt, Storage, StorageRef, System, SystemDebug, SystemOnce, SystemOnceThreadLocal, SystemThreadLocal, UnorderedData, World, WriteAndParent, WriteGuardRef, operators::{
ChangedDataSend, EntitiesComponentIter, EntitiesComponentIterMut, OrderedDataSend, ReadOnlyOp,
ReadOnlyOrderedOp, UnorderedDataSend
}, storage::ReadOnlyStorage};
#[cfg(feature="dynamic_systems")]
use rinecs::DynamicSymbol;
#[cfg(feature="async")]
use rinecs::CreationSystemAsync;
use rin_graphics::{Node, CameraExt, Mesh};
use color::{Rgb, color_space::LinearRgb, rgb};
use rin_window::WindowEvents;
use rin_math::{convert, vec2, ToVec};
use rin_util as util;
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
use window::EventsPoll;
#[cfg(gui)]
use rin_graphics::Ttf;
#[cfg(any(gui, feature="dynamic_systems"))]
use std::rc::Rc;
#[cfg(feature="gl")]
use rin_gl as gl;
#[cfg(feature="gl")]
use glin;
use rin_math::{pnt2, Pnt2, Rect};
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
use crate::EventsDispatcher;
#[cfg(not(any(feature="web", feature="desktop", feature="desktop_gles")))]
type EventsDispatcher = ();
use std::{fmt::Debug, marker::PhantomData};
#[cfg(feature="gl_forward_renderer")]
use std::mem;
use std::path::Path;
use hashbrown::HashSet;
use std::any::TypeId;
use crate::geometry::AnimatedGeometry;
use rin_events::{StreamExt, StreamRc, Stream, Property, Priority};
use std::cell::{Cell, UnsafeCell};
#[cfg(gui)]
use rin_gui::{ControlGeometry, ParameterGroup};
use rin_window::{self as window, WindowExt, Events};
#[cfg(gui)]
use crate::gui::{self, Gui};
use std::sync::mpsc;
use rin_graphics::{self as graphics, node::DynamicTransformation};
use crate::physics;
#[cfg(feature="gl")]
use glin::VertexFormat;
#[cfg(not(feature="gl"))]
pub trait VertexFormat{}
#[cfg(not(feature="gl"))]
impl<T: 'static> VertexFormat for T{}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
use crate::renderer::resources::ResourceFuture;
#[cfg(all(feature="gl_forward_renderer", feature="dynamic_systems"))]
use crate::renderer::{OpaqueRenderSurface, OtherRenderSurface, resources::ScreenRenderBuffer};
#[cfg(all(feature="gl_forward_renderer", feature="dynamic_systems"))]
use crate::{RenderStage, render_stage};
#[cfg(feature="dynamic_systems")]
use crate::bundle::DynamicRenderSystem;
#[cfg(feature="dynamic_systems")]
use rinecs::{DynamicFunction, SystemBuilderThreadLocal, SystemBuilder};
#[cfg(feature="gpu_stats")]
use std::time;
#[derive(Default)]
struct VertexRegister{
#[cfg(feature="gl_forward_renderer")]
to_register: Vec<Box<dyn FnMut( &mut World, &mut renderer::DeferredVertexRegister )>>,
registered_vertices: HashSet<TypeId>,
}
impl VertexRegister{
#[cfg(feature="gl_forward_renderer")]
fn register_vertex_type<T>(&mut self) -> bool
where T: glin::VertexFormat + Send + Clone + Copy + Debug + 'static
{
let type_id = TypeId::of::<T>();
if self.registered_vertices.contains(&type_id){
return false
}
let to_register = |
world: &mut World,
deferred_register: &mut renderer::DeferredVertexRegister|
{
deferred_register.register_vertex_type::<T>(world);
};
self.to_register.push(Box::new(to_register));
self.registered_vertices.insert(type_id);
true
}
#[cfg(not(feature="gl_forward_renderer"))]
fn register_vertex_type<T>(&mut self) -> bool
where T: Send + Clone + Copy + Debug + 'static
{
let type_id = TypeId::of::<T>();
if self.registered_vertices.contains(&type_id){
false
}else{
self.registered_vertices.insert(type_id);
true
}
}
#[cfg(feature="gl_forward_renderer")]
pub fn update_registers(&mut self, mut world: &mut World){
let world2: &mut &mut rinecs::World = unsafe{ mem::transmute(&mut world) };
if let Some(mut vertex_register) = world.resource_mut::<renderer::DeferredVertexRegister>() {
for mut registerer in self.to_register.drain(..){
(registerer)(world2, &mut vertex_register)
}
}
}
}
struct DeferUpdateSystem<S>{
system: S,
}
impl<S> Bundle for DeferUpdateSystem<S>
where S: UpdateSystem + 'static
{
type Parameters = ();
fn parameters(&self) -> Option<&Self::Parameters> { None }
fn name(&self) -> &str{
""
}
fn setup(self, world: &mut DeferredScene){
world.add_update_system(self.system);
}
}
struct DeferUpdateSystemThreadLocal<S>{
system: S,
}
impl<S> Bundle for DeferUpdateSystemThreadLocal<S>
where S: UpdateSystemThreadLocal + 'static
{
type Parameters = ();
fn parameters(&self) -> Option<&Self::Parameters> { None }
fn name(&self) -> &str{
""
}
fn setup(self, world: &mut DeferredScene){
world.add_update_system_thread_local(self.system);
}
}
#[cfg(feature="gl")]
struct DeferRenderSystem<S>{
system: S,
}
#[cfg(feature="gl")]
impl<S> Bundle for DeferRenderSystem<S>
where S: RenderSystem + 'static
{
type Parameters = ();
fn parameters(&self) -> Option<&Self::Parameters> { None }
fn name(&self) -> &str{
""
}
fn setup(self, world: &mut DeferredScene){
world.add_render_system(self.system);
}
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
struct RendererAsBundle<R>{
renderer: R
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
impl<R: crate::RendererBundle> Bundle for RendererAsBundle<R>{
type Parameters = <R as crate::RendererBundle>::Parameters;
fn parameters(&self) -> Option<&Self::Parameters> {
self.renderer.parameters()
}
fn name(&self) -> &str{
self.renderer.name()
}
fn setup(self, world: &mut DeferredScene){
self.renderer.setup(world);
}
}
pub struct Scene{
world: World,
update_render_barrier: bool,
registered_builders: HashSet<TypeId>,
registered_bundles: HashSet<TypeId>,
window_events: Priority<'static, window::Event>,
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
events_dispatcher: EventsDispatcher,
}
struct ViewportProperty(Property<'static, Rect<i32>>);
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
pub struct SceneBuilder{
world: World,
events_dispatcher: EventsDispatcher,
update_all: bool,
bundles_to_setup: Vec<Box<dyn FnOnce(&mut DeferredScene,)>>,
bundles_after_all_in: Vec<Box<dyn Fn(&mut Scene)>>,
registered_bundles: HashSet<TypeId>,
window_events: Option<Stream<'static, window::Event>>,
#[cfg(gui)]
gui_font: Option<Rc<Ttf>>,
}
#[cfg(any(feature="desktop", feature="desktop_gles", feature="web"))]
impl SceneBuilder{
pub fn new(events_poll: EventsPoll) -> SceneBuilder {
let mut world = World::new();
world.add_resource_thread_local(VertexRegister::default());
#[cfg(all(feature="gl_forward_renderer", feature="async"))]
{
let (pool, updater) = TexturesPool::new();
world.add_resource_thread_local(pool);
world.add_creation_system_async(updater);
}
#[cfg(all(feature="gl_forward_renderer", not(feature="async")))]
world.add_resource_thread_local(TexturesPool::new());
world.add_resource(events_poll);
let events_dispatcher = EventsDispatcher::new();
SceneBuilder{
world,
events_dispatcher,
update_all: false,
bundles_to_setup: vec![ ],
bundles_after_all_in: vec![],
registered_bundles: HashSet::default(),
window_events: None,
#[cfg(gui)]
gui_font: None,
}
}
pub fn add_resource<T: Send + 'static>(&mut self, resource: T) {
self.world.add_resource(resource);
}
pub fn add_resource_thread_local<T: 'static>(&mut self, resource: T) {
self.world.add_resource_thread_local(resource);
}
pub fn add_resource_as_trait<T, U, F, FMut>(&mut self, resource: (T, F, FMut))
where
T: 'static + Send,
U: 'static + Send + ?Sized,
F: Fn(&T) -> &U + 'static,
FMut: Fn(&mut T) -> &mut U + 'static
{
self.world.add_resource_as_trait(resource)
}
pub fn window_events<S>(&mut self, events: S) -> &mut SceneBuilder
where S: StreamExt<'static, window::Event>
{
self.window_events = Some(events.unique());
self
}
pub fn update_dynamic_transformations_only(&mut self) -> &mut SceneBuilder{
self.update_all = false;
self
}
pub fn update_all_transformations(&mut self) -> &mut SceneBuilder{
self.update_all = true;
self
}
#[cfg(gui)]
pub fn gui_font<T: Into<Rc<Ttf>>>(&mut self, font: T) -> &mut SceneBuilder{
self.gui_font = Some(font.into());
self
}
pub fn add_bundle<B: Bundle + 'static>(&mut self, bundle: B) -> bool {
if !self.registered_bundles.contains(&TypeId::of::<B>()){
#[cfg(not(gui))]
self.bundles_to_setup.push(Box::new(move |scene| bundle.setup(scene) ));
#[cfg(gui)]
self.bundles_to_setup.push(Box::new(move |scene: &mut DeferredScene| {
if let Some(parameters) = bundle.parameters(){
if let Some(gui) = unsafe{ &mut *scene.gui.get() }.as_mut() {
gui.group_from_parameters(bundle.name(), parameters);
}
}
bundle.setup(scene)
}));
self.bundles_after_all_in.push(Box::new(|scene| B::after_all_bundles_registered(scene) ));
self.registered_bundles.insert(TypeId::of::<B>())
}else{
false
}
}
pub fn add_bundle_to_group<B: Bundle + 'static>(&mut self, bundle: B, group: &str) -> bool {
if !self.registered_bundles.contains(&TypeId::of::<B>()){
#[cfg(not(gui))]
self.bundles_to_setup.push(Box::new(move |scene| bundle.setup(scene) ));
#[cfg(gui)]
{
let current_gui_tab = group.to_owned();
self.bundles_to_setup.push(Box::new(move |scene: &mut DeferredScene| {
if let Some(parameters) = bundle.parameters(){
if let Some(gui) = unsafe{ &mut *scene.gui.get() }.as_mut() {
let group = if gui.group(¤t_gui_tab).is_none(){
gui.new_group(¤t_gui_tab)
}else{
gui.group_mut(¤t_gui_tab).unwrap()
};
let group = group.new_foldable_group(bundle.name(), bundle.name().to_owned());
parameters.add_parameters(group);
group.fold();
}
}
scene.gui_tab = Some(current_gui_tab);
bundle.setup(scene)
}));
}
self.bundles_after_all_in.push(Box::new(|scene| B::after_all_bundles_registered(scene) ));
self.registered_bundles.insert(TypeId::of::<B>())
}else{
false
}
}
pub fn add_system<S>(&mut self, system: S)
where S: System + 'static
{
self.world.add_system(system);
}
pub fn add_system_thread_local<S>(&mut self, system: S)
where S: SystemThreadLocal + 'static
{
self.world.add_system_thread_local(system);
}
pub fn add_creation_system<S>(&mut self, system: S)
where S: CreationSystem + 'static
{
self.world.add_creation_system(system);
}
#[cfg(feature = "async")]
pub fn add_creation_system_async<S>(&mut self, system: S)
where S: CreationSystemAsync + 'static
{
self.world.add_creation_system_async(system);
}
pub fn add_debug_system<S>(&mut self, system: S)
where S: SystemDebug + 'static
{
self.world.add_debug_system(system);
}
pub fn add_system_with<S>(&mut self, system: S) -> rinecs::SystemBuilder<S>
where S: System + 'static
{
self.world.add_system_with(system)
}
pub fn add_system_thread_local_with<S>(&mut self, system: S) -> rinecs::SystemBuilderThreadLocal<S>
where S: SystemThreadLocal + 'static
{
self.world.add_system_thread_local_with(system)
}
pub fn add_creation_system_with<S>(&mut self, system: S) -> rinecs::SystemBuilderCreation<S>
where S: CreationSystem + 'static
{
self.world.add_creation_system_with(system)
}
pub fn add_update_system<U>(&mut self, system: U)
where U: UpdateSystem + 'static
{
self.add_bundle(DeferUpdateSystem{ system });
}
pub fn add_update_system_thread_local<U>(&mut self, system: U)
where U: UpdateSystemThreadLocal + 'static
{
self.add_bundle(DeferUpdateSystemThreadLocal{ system });
}
#[cfg(feature="gl")]
pub fn add_render_system<R>(&mut self, system: R)
where R: RenderSystem + 'static
{
self.add_bundle(DeferRenderSystem{ system });
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system(&mut self, system_path: &str) {
self.world.new_dynamic_system(system_path);
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system_thread_local(&mut self, system_path: &str) {
self.world.new_dynamic_system_thread_local(system_path);
}
#[cfg(feature="dynamic_systems")]
pub unsafe fn get_dynamic_symbol<S>(&self, system_path: &str) -> Result<DynamicSymbol<S>, String>{
self.world.get_dynamic_symbol(system_path)
}
#[cfg(feature="dynamic_systems")]
pub fn add_dynamic_symbol_watch(&mut self, system_path: &str) -> Result<(), String>{
self.world.add_dynamic_symbol_watch(system_path)
}
#[cfg(feature="dynamic_systems")]
pub fn preload_dynamic_libraries(&mut self, systems: &[&str]) -> Result<(), String>{
self.world.preload_dynamic_libraries(systems)
}
#[cfg(feature="dynamic_systems")]
pub fn start_dynamic_systems_watch(&mut self) -> Result<(), String>{
self.world.start_dynamic_systems_watch()
}
pub fn add_barrier<B: rinecs::Barrier + 'static>(&mut self) {
self.world.add_barrier::<B>();
}
pub fn send_stream<T: Clone + Debug + 'static>(&mut self) -> (mpsc::Sender<T>, Stream<'static, T>){
self.events_dispatcher.send_stream()
}
pub fn with_renderer<R: crate::RendererBundle + 'static>(mut self, mut renderer: R) -> SceneBuilderWithRenderer{
let viewport = renderer.viewport();
#[cfg(gui)]
let mut priority_events = if let Some(events) = self.window_events.take() {
Priority::new(events.rc())
}else{
Priority::new(renderer.event_stream().rc())
};
#[cfg(gui)]
let mut gui = {
let gui_font = self.gui_font.take();
renderer.window().map(|window| {
let gui_builder = crate::gui::GuiBuilder::new(
priority_events.event_stream(gui::GUI_EVENTS_PREFERENCE),
window
);
if let Some(font) = gui_font{
gui_builder.font(font).build()
}else{
gui_builder.build()
}
})
};
self.world.add_resource(crate::transformation::Viewport::new(*viewport.get()));
if self.world.resource::<super::BackgroundColor>().is_none() {
self.world.add_resource(super::BackgroundColor(rgb!(0.)));
}
let viewport_property = ViewportProperty(viewport);
let window_size = renderer
.event_stream()
.window()
.resized()
.to_property(renderer.window().unwrap().size());
#[cfg(gui)]
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
let _ = if let Some(gui) = gui.as_mut() {
let surface_viewport = viewport_property.0.clone();
let window_viewport = gui.width().clone()
.zip(gui.visible().clone())
.zip(window_size)
.flatten()
.map(|(width, visible, size)| {
let pos = if visible {
pnt2(width as i32, 0)
}else{
Pnt2::origin()
};
Rect{
pos,
width: size.x - pos.x,
height: size.y,
}
});
let map_position = move |pos: Pnt2<f64>|{
let window_ratio = window_viewport.get().width as f64
/ window_viewport.get().height as f64;
let surface_ratio = surface_viewport.get().width as f64
/ surface_viewport.get().height as f64;
if surface_ratio >= window_ratio {
let draw_width = window_viewport.get().width as f64;
let draw_height = draw_width / surface_ratio as f64;
let draw_y = (window_viewport.get().height as f64 - draw_height) / 2.;
let x_ratio = draw_width / surface_viewport.get().width as f64;
let y_ratio = draw_height / surface_viewport.get().height as f64;
let offset: Pnt2<f64> = convert(window_viewport.get().pos);
let pos = pos - offset.to_vec() - vec2(0., draw_y);
pnt2(pos.x / x_ratio, pos.y / y_ratio)
}else{
let draw_height = window_viewport.get().height as f64;
let draw_width = draw_height * surface_ratio as f64;
let draw_x = (window_viewport.get().width as f64 - draw_width) / 2.;
let x_ratio = draw_width / surface_viewport.get().width as f64;
let y_ratio = draw_height / surface_viewport.get().height as f64;
let offset: Pnt2<f64> = convert(window_viewport.get().pos);
let pos = pos - offset.to_vec() - vec2(draw_x, 0.);
pnt2(pos.x / x_ratio, pos.y / y_ratio)
}
};
let gui_non_attended = gui.non_attended().unique().map(move |event|{
match event{
window::Event::MouseMoved{pos} =>
window::Event::MouseMoved{pos: map_position(pos)},
window::Event::MousePressed{pos, button, mods} =>
window::Event::MousePressed{pos: map_position(pos), button, mods},
window::Event::MouseReleased{pos, button, mods} =>
window::Event::MouseReleased{pos: map_position(pos), button, mods},
event => event,
}
}).rc();
priority_events.set_non_attended(gui::GUI_EVENTS_PREFERENCE, gui_non_attended);
};
#[cfg(not(gui))]
let priority_events;
#[cfg(not(gui))]
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
{
let surface_viewport = viewport_property.0.clone();
let window_viewport = window_size.map(|size| Rect{
pos: Pnt2::origin(),
width: size.x,
height: size.y,
});
let map_position = move |pos: Pnt2<f64>|{
let window_ratio = window_viewport.get().width as f64
/ window_viewport.get().height as f64;
let surface_ratio = surface_viewport.get().width as f64
/ surface_viewport.get().height as f64;
if surface_ratio >= window_ratio {
let draw_width = window_viewport.get().width as f64;
let draw_height = draw_width / surface_ratio as f64;
let draw_y = (window_viewport.get().height as f64 - draw_height) / 2.;
let x_ratio = draw_width / surface_viewport.get().width as f64;
let y_ratio = draw_height / surface_viewport.get().height as f64;
let offset: Pnt2<f64> = convert(window_viewport.get().pos);
let pos = pos - offset.to_vec() - vec2(0., draw_y);
pnt2(pos.x / x_ratio, pos.y / y_ratio)
}else{
let draw_height = window_viewport.get().height as f64;
let draw_width = draw_height * surface_ratio as f64;
let draw_x = (window_viewport.get().width as f64 - draw_width) / 2.;
let x_ratio = draw_width / surface_viewport.get().width as f64;
let y_ratio = draw_height / surface_viewport.get().height as f64;
let offset: Pnt2<f64> = convert(window_viewport.get().pos);
let pos = pos - offset.to_vec() - vec2(draw_x, 0.);
pnt2(pos.x / x_ratio, pos.y / y_ratio)
}
};
let events = if let Some(events) = self.window_events.take() {
events
}else{
renderer.event_stream()
}.map(move |event|{
match event{
window::Event::MouseMoved{pos} =>
window::Event::MouseMoved{pos: map_position(pos)},
window::Event::MousePressed{pos, button, mods} =>
window::Event::MousePressed{pos: map_position(pos), button, mods},
window::Event::MouseReleased{pos, button, mods} =>
window::Event::MouseReleased{pos: map_position(pos), button, mods},
event => event,
}
}).rc();
priority_events = Priority::new(events);
}
self.world.add_resource_thread_local(viewport_property);
#[cfg(gui)]
if let Some(gui) = gui.as_mut() {
self.add_bundle_to_group(crate::gui::SaveSystem::new(gui), "core");
}
self.add_bundle_to_group(RendererAsBundle{ renderer }, "core");
self.add_bundle_to_group(crate::time::Time::new(), "core");
SceneBuilderWithRenderer{
world: self.world,
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
events_dispatcher: self.events_dispatcher,
update_all: self.update_all,
bundles_to_setup: self.bundles_to_setup,
bundles_after_all_in: self.bundles_after_all_in,
registered_bundles: self.registered_bundles,
window_events: priority_events,
#[cfg(gui)]
gui,
}
}
}
#[cfg(gui)]
pub trait SceneGuiGroup {
fn new_group(&mut self, name: &str) -> &mut rin_gui::GroupV;
}
#[cfg(gui)]
impl SceneGuiGroup for Gui {
fn new_group(&mut self, name: &str) -> &mut rin_gui::GroupV {
(**self).new_group(name)
}
}
#[cfg(gui)]
impl SceneGuiGroup for rin_gui::GroupV {
fn new_group(&mut self, name: &str) -> &mut rin_gui::GroupV {
let group = self.new_foldable_group(name, name.to_owned());
group.fold();
group
}
}
pub struct SceneBuilderWithRenderer{
world: World,
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
events_dispatcher: EventsDispatcher,
update_all: bool,
bundles_to_setup: Vec<Box<dyn FnOnce(&mut DeferredScene,)>>,
bundles_after_all_in: Vec<Box<dyn Fn(&mut Scene)>>,
registered_bundles: HashSet<TypeId>,
window_events: Priority<'static, window::Event>,
#[cfg(gui)]
gui: Option<Gui>,
}
impl SceneBuilderWithRenderer{
pub fn build(self) -> Scene{
let mut world = self.world;
#[cfg(feature="gl_forward_renderer")]
world.add_resource(light::LightInfo::default());
let mut deferred_scene = DeferredScene{
world: UnsafeCell::new(Some(world)),
bundles_to_setup: UnsafeCell::new(Some(self.bundles_to_setup)),
update_render_barrier: Cell::new(false),
#[cfg(gui)]
gui: UnsafeCell::new(self.gui),
#[cfg(gui)]
gui_tab: None,
window_events: UnsafeCell::new(Some(self.window_events)),
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
events_dispatcher: UnsafeCell::new(Some(self.events_dispatcher)),
};
while deferred_scene.next_bundle(){}
#[cfg(gui)]
{
if let Some(gui) = unsafe{ &mut *deferred_scene.gui.get() }.take(){
gui.setup(&mut deferred_scene);
}
}
let update_render_barrier = deferred_scene.update_render_barrier.get();
let (world, window_events, events_dispatcher) = deferred_scene.into_parts();
let mut scene = Scene {
update_render_barrier,
registered_bundles: self.registered_bundles,
window_events,
world,
registered_builders: HashSet::default(),
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
events_dispatcher,
};
#[cfg(feature="gl_forward_renderer")]
{
if self.update_all {
scene.add_system(graphics::node::update_all);
}else{
scene.add_system(graphics::node::update_dynamic);
}
}
for bundle in self.bundles_after_all_in{
(bundle)(&mut scene)
}
#[cfg(gui)]
Gui::after_all_bundles_registered(&mut scene);
scene
}
}
pub struct DeferredScene{
world: UnsafeCell<Option<World>>,
bundles_to_setup: UnsafeCell<Option<Vec<Box<dyn FnOnce(&mut DeferredScene,)>>>>,
update_render_barrier: Cell<bool>,
#[cfg(gui)]
gui: UnsafeCell<Option<Gui>>,
#[cfg(gui)]
gui_tab: Option<String>,
window_events: UnsafeCell<Option<Priority<'static, window::Event>>>,
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
events_dispatcher: UnsafeCell<Option<EventsDispatcher>>,
}
impl DeferredScene {
fn world(&self) -> &World{
unsafe{ &*self.world.get() }.as_ref().take().unwrap()
}
fn world_mut(&mut self) -> &mut World{
unsafe{ &mut *self.world.get() }.as_mut().take().unwrap()
}
fn into_parts(self) -> (World, Priority<'static, window::Event>, EventsDispatcher){
let world = self.world.into_inner().take().unwrap();
let events = self.window_events.into_inner().unwrap();
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
let events_dispatcher = self.events_dispatcher.into_inner().unwrap();
#[cfg(not(any(feature="web", feature="desktop", feature="desktop_gles")))]
let events_dispatcher = ();
(world, events, events_dispatcher)
}
#[cfg(gui)]
pub fn gui(&self) -> Option<&dyn SceneGuiGroup>{
if let Some(gui_tab) = self.gui_tab.as_ref() {
let gui = unsafe{ (*self.gui.get()).as_mut() };
if let Some(gui) = gui {
if gui.group(gui_tab).is_none(){
Some(gui.new_group(gui_tab) as _)
}else{
gui.group(gui_tab).map(|group| group as _)
}
}else{
None
}
}else{
unsafe{ (*self.gui.get()).as_ref().map(|gui| gui as _) }
}
}
#[cfg(gui)]
pub fn gui_mut(&mut self) -> Option<&mut dyn SceneGuiGroup>{
if let Some(gui_tab) = self.gui_tab.as_ref() {
let gui = unsafe{ (*self.gui.get()).as_mut() };
if let Some(gui) = gui {
if gui.group(gui_tab).is_none(){
Some(gui.new_group(gui_tab) as _)
}else{
gui.group_mut(gui_tab).map(|group| group as _)
}
}else{
None
}
}else{
unsafe{ (*self.gui.get()).as_mut().map(|gui| gui as _) }
}
}
pub fn event_stream(&mut self) -> StreamRc<'static, window::Event>{
unsafe{ &mut *self.window_events.get() }.as_mut().unwrap().event_stream(crate::DEFAULT_EVENTS_PRIORITY)
}
pub fn priority_stream(&mut self, priority: usize) -> StreamRc<'static, window::Event> {
unsafe{ &mut *self.window_events.get() }.as_mut().unwrap().event_stream(priority)
}
pub fn set_non_attended(&mut self, priority: usize, non_attended: StreamRc<'static, window::Event>) {
unsafe{ &mut *self.window_events.get() }.as_mut().unwrap().set_non_attended(priority, non_attended)
}
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
pub fn send_stream<T: Clone + Debug + 'static>(&self) -> (mpsc::Sender<T>, Stream<'static, T>){
unsafe{ &mut *self.events_dispatcher.get() }.as_mut().unwrap().send_stream()
}
#[cfg(not(any(feature="web", feature="desktop", feature="desktop_gles")))]
pub fn send_stream<T: Clone + Debug + 'static>(&self) -> (mpsc::Sender<T>, Stream<'static, T>){
unimplemented!()
}
pub fn add_resource<T: Send + 'static>(&mut self, resource: T){
self.world_mut().add_resource(resource)
}
pub fn add_resource_thread_local<T: 'static>(&mut self, resource: T){
self.world_mut().add_resource_thread_local(resource)
}
pub fn add_resource_as_trait<T, U, F, FMut>(&mut self, resource: (T, F, FMut))
where T: 'static + Send,
U: 'static + Send + ?Sized,
F: Fn(&T) -> &U + 'static,
FMut: Fn(&mut T) -> &mut U + 'static
{
self.world_mut().add_resource_as_trait(resource)
}
pub fn add_resource_as_trait_thread_local<T, U, F, FMut>(&mut self, resource: (T, F, FMut))
where T: 'static,
U: 'static + ?Sized,
F: Fn(&T) -> &U + 'static,
FMut: Fn(&mut T) -> &mut U + 'static
{
self.world_mut().add_resource_as_trait_thread_local(resource)
}
pub fn new_entity(&mut self) -> rinecs::EntityBuilder{
self.world_mut().new_entity()
}
pub fn add_system<S>(&mut self, system: S) -> &mut DeferredScene
where S: System + 'static
{
self.world_mut().add_system(system);
self
}
pub fn add_system_once<S>(&mut self, system: S) -> &mut DeferredScene
where S: SystemOnce + 'static
{
self.world_mut().add_system_once(system);
self
}
pub fn add_system_with_data<S,D>(&mut self, system: S, data: D) -> &mut DeferredScene
where S: FnMut(&mut D, Entities, Resources) + Send + 'static,
D: Send + 'static
{
self.world_mut().add_system_with_data(system, data);
self
}
pub fn add_system_thread_local<S>(&mut self, system: S) -> &mut DeferredScene
where S: SystemThreadLocal + 'static
{
self.world_mut().add_system_thread_local(system);
self
}
pub fn add_system_once_thread_local<S>(&mut self, system: S) -> &mut DeferredScene
where S: SystemOnceThreadLocal + 'static
{
self.world_mut().add_system_once_thread_local(system);
self
}
pub fn add_system_thread_local_with_data<S,D>(&mut self, system: S, data: D) -> &mut DeferredScene
where S: FnMut(&mut D, EntitiesThreadLocal, ResourcesThreadLocal) + 'static,
D: 'static
{
self.world_mut().add_system_thread_local_with_data(system, data);
self
}
pub fn add_creation_system<S>(&mut self, system: S) -> &mut DeferredScene
where S: CreationSystem + 'static
{
self.world_mut().add_creation_system(system);
self
}
#[cfg(feature = "async")]
pub fn add_creation_system_async<S>(&mut self, system: S) -> &mut DeferredScene
where S: CreationSystemAsync + 'static
{
self.world_mut().add_creation_system_async(system);
self
}
pub fn add_debug_system<S>(&mut self, system: S) -> &mut DeferredScene
where S: SystemDebug + 'static
{
self.world_mut().add_debug_system(system);
self
}
pub fn add_system_with<S>(&mut self, system: S) -> rinecs::SystemBuilder<S>
where S: System + 'static
{
self.world_mut().add_system_with(system)
}
pub fn add_system_thread_local_with<S>(&mut self, system: S) -> rinecs::SystemBuilderThreadLocal<S>
where S: SystemThreadLocal + 'static
{
self.world_mut().add_system_thread_local_with(system)
}
pub fn add_creation_system_with<S>(&mut self, system: S) -> rinecs::SystemBuilderCreation<S>
where S: CreationSystem + 'static
{
self.world_mut().add_creation_system_with(system)
}
pub fn add_update_system<U>(&mut self, system: U) -> &mut DeferredScene
where U: UpdateSystem + 'static
{
if !self.update_render_barrier.get() {
self.add_barrier::<UpdateRenderBarrier>();
self.update_render_barrier.set(true);
}
self.add_system(UpdateWrapper(system))
}
pub fn add_update_system_thread_local<U>(&mut self, system: U) -> &mut DeferredScene
where U: UpdateSystemThreadLocal + 'static
{
if !self.update_render_barrier.get() {
self.add_barrier::<UpdateRenderBarrier>();
self.update_render_barrier.set(true);
}
self.add_system_thread_local(UpdateWrapper(system))
}
#[cfg(feature="gl")]
pub fn add_render_system<R>(&mut self, system: R) -> &mut DeferredScene
where R: RenderSystem + 'static
{
if !self.update_render_barrier.get() {
self.add_barrier::<UpdateRenderBarrier>();
self.update_render_barrier.set(true);
}
self.add_system_thread_local(RenderWrapper(system))
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system(&mut self, system_path: &str) {
self.world_mut().new_dynamic_system(system_path);
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system_with(&mut self, system_path: &str)
-> SystemBuilder<DynamicFunction<for<'r, 's> fn(Entities<'r>, Resources<'s>)>>
{
self.world_mut().new_dynamic_system_with(system_path)
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system_with_data<D: Send + 'static>(&mut self, system_path: &str, data: D) {
self.world_mut().new_dynamic_system_with_data(system_path, data);
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system_with_data_with<D: Send + 'static>(&mut self, system_path: &str, data: D)
-> SystemBuilder<(DynamicFunction<for<'r, 's> fn(*mut std::ffi::c_void, Entities<'r>, Resources<'s>)>, D)>
{
self.world_mut().new_dynamic_system_with_data_with(system_path, data)
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system_thread_local(&mut self, system_path: &str) {
self.world_mut().new_dynamic_system_thread_local(system_path);
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system_thread_local_with(&mut self, system_path: &str)
-> SystemBuilderThreadLocal<DynamicFunction<for<'r, 's> fn(EntitiesThreadLocal<'r>, ResourcesThreadLocal<'s>)>>
{
self.world_mut().new_dynamic_system_thread_local_with(system_path)
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system_thread_local_with_data<D: 'static>(&mut self, system_path: &str, data: D) {
self.world_mut().new_dynamic_system_thread_local_with_data(system_path, data);
}
#[cfg(feature="dynamic_systems")]
pub fn new_dynamic_system_thread_local_with_data_with<D: 'static>(&mut self, system_path: &str, data: D)
-> SystemBuilderThreadLocal<(DynamicFunction<for<'r, 's> fn(*mut std::ffi::c_void, EntitiesThreadLocal<'r>, ResourcesThreadLocal<'s>)>, D)>
{
self.world_mut().new_dynamic_system_thread_local_with_data_with(system_path, data)
}
pub fn add_barrier<B: rinecs::Barrier + 'static>(&mut self) -> &mut DeferredScene {
self.world_mut().add_barrier::<B>();
self
}
#[cfg(feature="stats")]
pub fn stats(&mut self) -> impl Iterator<Item = (&str, Property<'static, rinecs::Stat>)>{
self.world_mut().stats()
}
#[cfg(feature="gpu_stats")]
pub fn gpu_stats<'g, C>(&'g mut self, gl: &'g C) -> impl Iterator<Item = (&str, Property<'static, time::Duration>)> + 'g
where C: glin::CreationContext
{
self.world_mut().gpu_stats(gl)
}
#[cfg(feature="stats")]
pub fn enabled_systems(&mut self) -> impl Iterator<Item = (&str, Property<'static, bool>)> {
self.world_mut().enabled_systems()
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_material<M: FullMaterial + 'static>(&mut self, name: &str, material: M) -> MaterialRef{
self.resource_mut::<MaterialPool>().unwrap().register_material(name, material)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_shadow_material<M: FullMaterial + 'static>(&mut self, name: &str, material: M) -> ShadowMaterialRef{
self.resource_mut::<ShadowMaterialPool>().unwrap().register_material(name, material)
}
#[cfg(feature="gl_forward_renderer")]
pub fn find_material(&self, name: &str) -> Option<MaterialRef>{
self.resource::<MaterialPool>().unwrap().find_material(name)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_texture(&mut self, texture: glin::Texture) -> TextureRef{
self.resource_mut::<TexturesPool>().unwrap().insert_texture(texture)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_texture_from_data_format<T: 'static>(&mut self,
format: glin::texture::LoadDataFormat,
creation_flags: TextureCreationFlags,
data: &[T]) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_texture_from_data_format(format, creation_flags, data, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_cubemap(&mut self, cubemap: glin::CubeMap) -> CubemapRef {
self.resource_mut::<TexturesPool>().unwrap().insert_cubemap(cubemap)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_image<I: renderer::Image + Clone>(&mut self,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_image(img, creation_flags, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_named_texture_from_data_format<T: 'static>(&mut self,
name: &str,
creation_flags: TextureCreationFlags,
format: glin::texture::LoadDataFormat,
data: &[T]) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_named_texture_from_data_format(name, format, creation_flags, data, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_named_image<I: renderer::Image + Clone>(&mut self,
name: &str,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_named_image(name, img, creation_flags, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_sampler(&mut self, sampler: Sampler) -> SamplerRef{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_sampler(sampler, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_named_sampler(&mut self, name: &str, sampler: Sampler) -> SamplerRef{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_named_sampler(name, sampler, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn find_texture(&self, name: &str) -> Option<TextureRef>{
self.resource_mut::<TexturesPool>().unwrap()
.find_named_texture(name)
}
#[cfg(feature="gl_forward_renderer")]
pub fn find_cubemap(&self, name: &str) -> Option<CubemapRef>{
self.resource_mut::<TexturesPool>().unwrap()
.find_named_cubemap(name)
}
#[cfg(feature="gl_forward_renderer")]
pub fn find_sampler(&self, name: &str) -> Option<SamplerRef>{
self.resource_mut::<TexturesPool>().unwrap()
.find_named_sampler(name)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
pub fn load_image<P>(&mut self, path: P, flags: TextureCreationFlags) -> util::Result<TextureRef>
where P: AsRef<Path>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
let context = renderer.context();
self.resource_mut::<TexturesPool>().unwrap().load_image(path, flags, &context)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), dds))]
pub fn load_cubemap<P>(&mut self, path: P, flags: TextureCreationFlags) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap().load_cubemap(path, flags, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
pub fn load_equirectangular_cubemap<P>(
&mut self,
path: P,
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.load_equirectangular_cubemap(path, flags, color_format, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
pub fn load_equirectangular_levels_cubemap<P>(
&mut self,
paths: &[P],
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.load_equirectangular_levels_cubemap(paths, flags, color_format, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
pub fn load_image_async<P>(
&mut self,
path: P,
flags: TextureCreationFlags) -> ResourceFuture<TextureRef>
where P: AsRef<Path>
{
self.resource_mut::<TexturesPool>().unwrap().load_image_async(path, flags)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", dds))]
pub fn load_cubemap_async<P>(&mut self, path: P, flags: TextureCreationFlags) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_mut::<TexturesPool>().unwrap().load_cubemap_async(path, flags)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
pub fn load_equirectangular_cubemap_async<P>(
&mut self,
path: P,
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_mut::<TexturesPool>().unwrap()
.load_equirectangular_cubemap_async(path, flags, color_format)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
pub fn load_equirectangular_levels_cubemap_async<P>(
&mut self,
paths: &[P],
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_mut::<TexturesPool>().unwrap()
.load_equirectangular_levels_cubemap_async(paths, flags, color_format)
}
pub fn register_vertex_type<T>(&mut self)
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
let registered = {
let mut vertex_register = self.resource_mut::<VertexRegister>().unwrap();
vertex_register.register_vertex_type::<T>()
};
}
pub fn register_mesh<T>(&mut self, geom: Mesh<T>) -> GeometryRef
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
self.register_vertex_type::<T>();
let entity = self.new_entity()
.add(Geometry::new(geom))
.add(Ty::Mesh)
.build();
GeometryRef::new(entity)
}
pub fn register_named_mesh<T>(&mut self, geom: Mesh<T>, name: &str) -> GeometryRef
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
self.register_vertex_type::<T>();
let entity = self.new_entity()
.add(Name(name.into()))
.add(Geometry::new(geom))
.add(Ty::Mesh)
.build();
GeometryRef::new(entity)
}
pub fn add_model(&mut self, name: &str) -> ModelBuilder{
ModelBuilder{
builder: self.new_entity()
.add(Name(name.to_string()))
.add(Ty::Model),
visible: true,
added_trafo: false,
parent_entity: None,
}
}
pub fn add_component_to<'a, C: ComponentSend>(&mut self, entity: &Entity, component: C)
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.world_mut().add_component_to(entity, component);
}
pub fn add_component_to_thread_local<'a, C: ComponentThreadLocal>(&mut self, entity: &Entity, component: C)
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.world_mut().add_component_to_thread_local(entity, component)
}
pub fn component_for<C: Component>(&self, entity: &Entity) -> Option<rinecs::Ptr<C>>
where for<'s> <C as Component>::Storage: Storage<'s, C>
{
self.world().component_for::<C>(entity)
}
pub fn resource<R: 'static>(&self) -> Option<ReadGuardRef<R>>{
loop{
if let Some(resource) = self.world().resource::<R>(){
return Some(resource);
}else if !self.next_bundle(){
return None
}
}
}
fn resource_mut<R: 'static>(&self) -> Option<WriteGuardRef<R>>{
loop{
if let Some(resource) = self.world().resource_mut::<R>(){
return Some(resource);
}else if !self.next_bundle(){
return None
}
}
}
fn next_bundle(&self) -> bool {
if let Some(bundle) = unsafe{ (&mut *self.bundles_to_setup.get()).as_mut().unwrap().pop() }{
let mut partial_scene = DeferredScene{
world: UnsafeCell::new(unsafe{ (*self.world.get()).take() }),
bundles_to_setup: UnsafeCell::new(unsafe{ (*self.bundles_to_setup.get()).take() }),
update_render_barrier: self.update_render_barrier.clone(),
#[cfg(gui)]
gui: UnsafeCell::new(unsafe{ (*self.gui.get()).take() }),
#[cfg(gui)]
gui_tab: None,
window_events: UnsafeCell::new(unsafe{ (*self.window_events.get()).take() }),
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
events_dispatcher: UnsafeCell::new(unsafe{ (*self.events_dispatcher.get()).take() }),
};
bundle(&mut partial_scene);
unsafe{
*self.bundles_to_setup.get() = partial_scene.bundles_to_setup.into_inner();
*self.world.get() = partial_scene.world.into_inner();
self.update_render_barrier.set(partial_scene.update_render_barrier.get());
*self.window_events.get() = partial_scene.window_events.into_inner();
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
{
*self.events_dispatcher.get() = partial_scene.events_dispatcher.into_inner();
}
#[cfg(gui)]
{
*self.gui.get() = partial_scene.gui.into_inner();
}
}
true
}else{
false
}
}
}
impl Scene{
#[cfg(feature="dynamic_systems")]
pub unsafe fn get_dynamic_symbol<S>(&self, system_path: &str) -> Result<DynamicSymbol<S>, String>{
self.world.get_dynamic_symbol(system_path)
}
#[cfg(all(feature="dynamic_systems", feature="gl_forward_renderer"))]
pub unsafe fn add_dynamic_render_system(&mut self, system_path: &str, render_stage: RenderStage){
let has_render_surface = self.world
.resource::<ScreenRenderBuffer>()
.is_some();
if has_render_surface {
match render_stage {
RenderStage::RenderSurfaceOpaque => {
let system = DynamicRenderSystem::<
&OpaqueRenderSurface,
render_stage::RenderSurfaceOpaque>::new(system_path);
self.add_render_system(system);
},
RenderStage::AfterPostprocessingOpaque =>
{
let system = DynamicRenderSystem::<
&OtherRenderSurface,
render_stage::AfterPostprocessingOpaque>::new(system_path);
self.add_render_system(system);
},
RenderStage::RenderSurfaceTranslucent
| RenderStage::AfterPostprocessing =>
{
let system = DynamicRenderSystem::<
&OtherRenderSurface,
render_stage::RenderSurfaceTranslucent>::new(system_path);
self.add_render_system(system);
},
RenderStage::AfterPostprocessing =>
{
let system = DynamicRenderSystem::<
&OtherRenderSurface,
render_stage::AfterPostprocessing>::new(system_path);
self.add_render_system(system);
},
RenderStage::Window => {
let system = DynamicRenderSystem::<
glin::Screen,
render_stage::Window>::new(system_path);
self.add_render_system(system);
},
}
}else{
match render_stage {
RenderStage::RenderSurfaceOpaque => {
let system = DynamicRenderSystem::<
glin::Screen,
render_stage::RenderSurfaceOpaque>::new(system_path);
self.add_render_system(system);
},
RenderStage::AfterPostprocessingOpaque =>
{
let system = DynamicRenderSystem::<
glin::Screen,
render_stage::AfterPostprocessingOpaque>::new(system_path);
self.add_render_system(system);
},
RenderStage::RenderSurfaceTranslucent
| RenderStage::AfterPostprocessing =>
{
let system = DynamicRenderSystem::<
glin::Screen,
render_stage::RenderSurfaceTranslucent>::new(system_path);
self.add_render_system(system);
},
RenderStage::AfterPostprocessing =>
{
let system = DynamicRenderSystem::<
glin::Screen,
render_stage::AfterPostprocessing>::new(system_path);
self.add_render_system(system);
},
RenderStage::Window => {
let system = DynamicRenderSystem::<
glin::Screen,
render_stage::Window>::new(system_path);
self.add_render_system(system);
},
}
}
self.world.add_dynamic_symbol_watch(system_path).unwrap();
}
#[cfg(all(feature="dynamic_systems", not(feature="gl_forward_renderer")))]
pub unsafe fn add_dynamic_render_system(&mut self, system_path: &str){
let system = DynamicRenderSystem::<glin::Screen>::new(system_path);
self.add_render_system(system);
}
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
pub fn window(&self) -> ReadGuardRef<window::Window> {
self.world.resource::<window::Window>().unwrap()
}
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
pub fn window_mut(&self) -> WriteGuardRef<window::Window> {
self.world.resource_mut::<window::Window>().unwrap()
}
#[cfg(feature="gl")]
pub fn gl_renderer(&self) -> ReadGuardRef<gl::Renderer<'static>> {
self.world.resource::<gl::Renderer<'static>>().unwrap()
}
#[cfg(feature="gl")]
pub fn gl_renderer_mut(&self) -> WriteGuardRef<gl::Renderer<'static>> {
self.world.resource_mut::<gl::Renderer<'static>>().unwrap()
}
#[cfg(feature="gl_forward_renderer")]
pub fn render_surface(&self) -> Option<ReadGuardRef<renderer::ScreenRenderBuffer>> {
self.world.resource::<renderer::ScreenRenderBuffer>()
}
#[cfg(all(feature="gl", any(feature="web", feature="desktop", feature="desktop_gles")))]
#[cfg(feature="gl_forward_renderer")]
pub fn viewport(&self) -> rin_math::Rect<i32> {
self.render_surface()
.map(|surface| surface.viewport().into())
.unwrap_or(self.window().viewport())
}
#[cfg(all(feature="gl", any(feature="web", feature="desktop", feature="desktop_gles")))]
#[cfg(not(feature="gl_forward_renderer"))]
pub fn viewport(&self) -> rin_math::Rect<i32> {
self.window().viewport()
}
pub fn event_stream(&mut self) -> StreamRc<'static, window::Event>{
self.window_events.event_stream(crate::DEFAULT_EVENTS_PRIORITY)
}
pub fn priority_stream(&mut self, priority: usize) -> StreamRc<'static, window::Event>{
self.window_events.event_stream(priority)
}
pub fn set_non_attended(&mut self, priority: usize, stream: StreamRc<'static, window::Event>){
self.window_events.set_non_attended(priority, stream)
}
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
pub fn send_stream<T: Clone + Debug + 'static>(&self) -> (mpsc::Sender<T>, Stream<'static, T>){
self.events().send_stream()
}
#[cfg(not(any(feature="web", feature="desktop", feature="desktop_gles")))]
pub fn send_stream<T: Clone + Debug + 'static>(&self) -> (mpsc::Sender<T>, Stream<'static, T>){
unimplemented!()
}
#[cfg(gui)]
pub fn gui(&self) -> Option<ReadGuardRef<Gui>>{
self.world.resource::<Gui>()
}
#[cfg(gui)]
pub fn gui_mut(&mut self) -> Option<WriteGuardRef<Gui>>{
self.world.resource_mut::<Gui>()
}
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
pub fn events(&self) -> WriteGuardRef<EventsDispatcher>{
self.world.resource_mut::<EventsDispatcher>().unwrap()
}
pub fn set_camera<C: CameraExt + Send + 'static>(&mut self, camera: C){
if let Some(viewport) = self.world.remove_resource::<ViewportProperty>() {
let viewport = viewport.0.stream().unique();
self.world.add_system(crate::transformation::CameraUpdater::new(viewport));
}
let (camera, changed) = Camera::new(camera);
self.world.add_resource_as_trait::<_, dyn CameraExt + Send, _,_>((camera, |c| c, |c| c));
self.world.add_resource(changed);
}
pub fn register_vertex_type<T>(&mut self)
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
let registered = {
let mut vertex_register = self.resource_mut::<VertexRegister>().unwrap();
vertex_register.register_vertex_type::<T>()
};
}
pub fn register_builder<'a, B: Builder<'a>>(&mut self){
if !self.registered_builders.contains(&TypeId::of::<<B as Builder<'a>>::IdType>()) {
B::register(&mut self.world);
self.registered_builders.insert(TypeId::of::<<B as Builder<'a>>::IdType>());
}
}
pub fn add<'a, B: Builder<'a>>(&'a mut self, settings: <B as Builder<'a>>::Settings) -> B{
self.register_builder::<B>();
let (entities, resources) = self.world.entities_and_resources_creation();
let proxy = CreationProxy {
entities,
resources,
};
B::new(proxy, settings)
}
pub fn add_model(&mut self, name: &str) -> ModelBuilder{
ModelBuilder{
builder: self.world.new_entity()
.add(Name(name.to_string()))
.add(Ty::Model),
visible: true,
added_trafo: false,
parent_entity: None,
}
}
pub fn add_child_model(&mut self, name: &str, parent: Entity) -> ModelBuilder{
ModelBuilder{
builder: self.world.new_entity()
.add(Name(name.to_string()))
.add(Ty::Model),
visible: true,
added_trafo: false,
parent_entity: Some(parent),
}
}
pub fn add_empty(&mut self, name: &str) -> EmptyBuilder{
EmptyBuilder{
builder: self.world.new_entity()
.add(Name(name.to_string()))
.add(Ty::Empty),
added_trafo: false,
parent: None,
}
}
pub fn add_child_empty(&mut self, name: &str, parent: Entity) -> EmptyBuilder{
EmptyBuilder{
builder: self.world.new_entity()
.add(Name(name.to_string()))
.add(Ty::Empty),
added_trafo: false,
parent: Some(parent)
}
}
pub fn register_mesh<T>(&mut self, geom: Mesh<T>) -> GeometryRef
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
self.register_vertex_type::<T>();
let entity = self.world.new_entity()
.add(Geometry::new(geom))
.add(Ty::Mesh)
.build();
GeometryRef::new(entity)
}
pub fn register_named_mesh<T>(&mut self, geom: Mesh<T>, name: &str) -> GeometryRef
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
self.register_vertex_type::<T>();
let entity = self.world.new_entity()
.add(Name(name.to_owned()))
.add(Geometry::new(geom))
.add(Ty::Mesh)
.build();
GeometryRef::new(entity)
}
pub fn add_ambient_light(&mut self, diffuse: Rgb<f32, LinearRgb>, specular: Rgb<f32, LinearRgb>) -> Entity{
AmbientLight::new(&mut self.world, diffuse, specular)
}
pub fn add_directional_light<'a>(&'a mut self, name: &'a str) -> DirectionalLightBuilder<'a, World>{
DirectionalLightBuilder::new(&mut self.world, name)
}
pub fn add_spot_light<'a>(&'a mut self, name: &'a str) -> SpotLightBuilder<'a, World>{
SpotLightBuilder::new(&mut self.world, name)
}
pub fn add_point_light<'a>(&'a mut self, name: &'a str) -> PointLightBuilder<'a, World>{
PointLightBuilder::new(&mut self.world, name)
}
pub fn add_area_light<'a>(&'a mut self, name: &'a str) -> AreaLightBuilder<'a, World>{
AreaLightBuilder::new(&mut self.world, name)
}
#[cfg(feature="gl_forward_renderer")]
pub fn add_image_based_light<'a>(&'a mut self, name: &'a str) -> ImageBasedLightBuilder<'a, World>{
ImageBasedLightBuilder::new(&mut self.world, name)
}
pub fn update_all_transformations(&mut self){
let (entities, resources) = self.world.entities_and_resources();
graphics::node::update_all.run(entities, resources);
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_material<M: FullMaterial + 'static>(&mut self, name: &str, material: M) -> MaterialRef{
self.resource_mut::<MaterialPool>().unwrap().register_material(name, material)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_shadow_material<M: FullMaterial + 'static>(&mut self, name: &str, material: M) -> ShadowMaterialRef{
self.resource_mut::<ShadowMaterialPool>().unwrap().register_material(name, material)
}
#[cfg(feature="gl_forward_renderer")]
pub fn find_material(&self, name: &str) -> Option<MaterialRef>{
self.resource_mut::<MaterialPool>().unwrap().find_material(name)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_texture(&mut self, texture: glin::Texture) -> TextureRef{
self.resource_mut::<TexturesPool>().unwrap()
.insert_texture(texture)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_texture_from_data_format<T: 'static>(&mut self,
format: glin::texture::LoadDataFormat,
creation_flags: TextureCreationFlags,
data: &[T]) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_texture_from_data_format(format, creation_flags, data, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_cubemap(&mut self, cubemap: glin::CubeMap) -> CubemapRef {
self.resource_mut::<TexturesPool>().unwrap().insert_cubemap(cubemap)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_named_cubemap(&mut self, name: &str, cubemap: glin::CubeMap) -> CubemapRef {
self.resource_mut::<TexturesPool>().unwrap().insert_named_cubemap(name, cubemap)
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_image<I: renderer::Image + Clone>(&mut self,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_image(img, creation_flags, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_named_texture_from_data_format<T: 'static>(&mut self,
name: &str,
creation_flags: TextureCreationFlags,
format: glin::texture::LoadDataFormat,
data: &[T]) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_named_texture_from_data_format(name, format, creation_flags, data, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_named_image<I: renderer::Image + Clone>(&mut self,
name: &str,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_named_image(name, img, creation_flags, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_sampler(&mut self, sampler: Sampler) -> SamplerRef{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_sampler(sampler, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn register_named_sampler(&mut self, name: &str, sampler: Sampler) -> SamplerRef{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.insert_named_sampler(name, sampler, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
pub fn find_texture(&self, name: &str) -> Option<TextureRef>{
self.resource_mut::<TexturesPool>().unwrap()
.find_named_texture(name)
}
#[cfg(feature="gl_forward_renderer")]
pub fn find_cubemap(&self, name: &str) -> Option<CubemapRef>{
self.resource_mut::<TexturesPool>().unwrap()
.find_named_cubemap(name)
}
#[cfg(feature="gl_forward_renderer")]
pub fn find_sampler(&self, name: &str) -> Option<SamplerRef>{
self.resource_mut::<TexturesPool>().unwrap()
.find_named_sampler(name)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
pub fn load_image<P>(&mut self, path: P, flags: TextureCreationFlags) -> util::Result<TextureRef>
where P: AsRef<Path>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
let context = renderer.context();
self.resource_mut::<TexturesPool>().unwrap().load_image(path, flags, &context)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), dds))]
pub fn load_cubemap<P>(&mut self, path: P, flags: TextureCreationFlags) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap().load_cubemap(path, flags, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
pub fn load_equirectangular_cubemap<P>(
&mut self,
path: P,
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.load_equirectangular_cubemap(path, flags, color_format, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
pub fn load_equirectangular_levels_cubemap<P>(
&mut self,
paths: &[P],
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource::<gl::Renderer<'static>>().unwrap();
self.resource_mut::<TexturesPool>().unwrap()
.load_equirectangular_levels_cubemap(paths, flags, color_format, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
pub fn load_image_async<P>(
&mut self,
path: P,
flags: TextureCreationFlags) -> ResourceFuture<TextureRef>
where P: AsRef<Path>
{
self.resource_mut::<TexturesPool>().unwrap().load_image_async(path, flags)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", dds))]
pub fn load_cubemap_async<P>(&mut self, path: P, flags: TextureCreationFlags) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_mut::<TexturesPool>().unwrap().load_cubemap_async(path, flags)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
pub fn load_equirectangular_cubemap_async<P>(
&mut self,
path: P,
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_mut::<TexturesPool>().unwrap()
.load_equirectangular_cubemap_async(path, flags, color_format)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
pub fn load_equirectangular_levels_cubemap_async<P>(
&mut self,
paths: &[P],
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_mut::<TexturesPool>().unwrap()
.load_equirectangular_levels_cubemap_async(paths, flags, color_format)
}
pub fn reset_clock(&mut self){
crate::time::reset_clock(self.world.resources_thread_local());
}
#[cfg(feature="web")]
pub fn set_web_main_loop<F: FnMut(Scene) + 'static>(self, mut main_loop: F) {
stdweb::web::window().request_animation_frame(move |elapsed| {
crate::time::update_clock_with_wall_time(
self.world.resources_thread_local(),
elapsed / 1000.);
self.window_mut().set_time_millis(elapsed);
main_loop(self);
});
}
pub fn run_once(&mut self) {
#[cfg(not(feature="web"))]
crate::time::update_clock(self.world.resources_thread_local());
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
let (entities, resources) = self.world.entities_and_resources_thread_local();
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
self.events_dispatcher.run(entities, resources);
#[cfg(feature="gl_forward_renderer")]
{
let world: &mut rinecs::World = unsafe{ mem::transmute(&mut self.world) };
let mut vertex_register = self.world.resource_mut::<VertexRegister>().unwrap();
vertex_register.update_registers(world);
}
self.world.run_once()
}
pub fn run_single_threaded(&mut self) {
#[cfg(not(feature="web"))]
crate::time::update_clock(self.world.resources_thread_local());
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
let (entities, resources) = self.world.entities_and_resources_thread_local();
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
self.events_dispatcher.run(entities, resources);
#[cfg(feature="gl_forward_renderer")]
{
let world: &mut rinecs::World = unsafe{ mem::transmute(&mut self.world) };
let mut vertex_register = self.world.resource_mut::<VertexRegister>().unwrap();
vertex_register.update_registers(world);
}
self.world.run_single_threaded();
}
#[cfg(feature="parallel_systems")]
pub fn run_multi_threaded(&mut self) {
#[cfg(not(feature="web"))]
crate::time::update_clock(self.world.resources_thread_local());
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
let (entities, resources) = self.world.entities_and_resources_thread_local();
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
self.events_dispatcher.run(entities, resources);
#[cfg(feature="gl_forward_renderer")]
{
let world: &mut rinecs::World = unsafe{ mem::transmute(&mut self.world) };
let mut vertex_register = self.world.resource_mut::<VertexRegister>().unwrap();
vertex_register.update_registers(world);
}
self.world.run_multi_threaded();
}
pub fn resources(&self) -> rinecs::Resources{
self.world.resources()
}
pub fn remove_resource<T: 'static>(&mut self) -> Option<T> {
self.world.remove_resource()
}
pub fn add_resource<T: Send + 'static>(&mut self, resource: T){
self.world.add_resource(resource)
}
pub fn add_resource_thread_local<T: 'static>(&mut self, resource: T){
self.world.add_resource_thread_local(resource)
}
pub fn resource<T: 'static>(&self) -> Option<ReadGuardRef<T>>{
self.world.resource()
}
pub fn resource_mut<T: 'static>(&self) -> Option<WriteGuardRef<T>>{
self.world.resource_mut()
}
pub fn resources_thread_local(&self) -> rinecs::ResourcesThreadLocal{
self.world.resources_thread_local()
}
pub fn entities_creation(&mut self) -> rinecs::EntitiesCreation{
self.world.entities_creation()
}
pub fn resources_creation(&mut self) -> rinecs::ResourcesCreation{
self.world.resources_creation()
}
pub fn debug_entities(&mut self) -> rinecs::EntitiesDebug{
self.world.debug_entities()
}
pub fn add_system<S>(&mut self, system: S) -> &mut Scene
where S: System + 'static
{
self.world.add_system(system);
self
}
pub fn add_system_once<S>(&mut self, system: S) -> &mut Scene
where S: SystemOnce + 'static
{
self.world.add_system_once(system);
self
}
pub fn add_system_thread_local<S>(&mut self, system: S) -> &mut Scene
where S: SystemThreadLocal + 'static
{
self.world.add_system_thread_local(system);
self
}
pub fn add_system_once_thread_local<S>(&mut self, system: S) -> &mut Scene
where S: SystemOnceThreadLocal + 'static
{
self.world.add_system_once_thread_local(system);
self
}
pub fn add_creation_system<S>(&mut self, system: S) -> &mut Scene
where S: CreationSystem + 'static
{
self.world.add_creation_system(system);
self
}
pub fn add_debug_system<S>(&mut self, system: S) -> &mut Scene
where S: SystemDebug + 'static
{
self.world.add_debug_system(system);
self
}
pub fn add_system_with<S>(&mut self, system: S) -> rinecs::SystemBuilder<S>
where S: System + 'static
{
self.world.add_system_with(system)
}
pub fn add_system_thread_local_with<S>(&mut self, system: S) -> rinecs::SystemBuilderThreadLocal<S>
where S: SystemThreadLocal + 'static
{
self.world.add_system_thread_local_with(system)
}
pub fn add_creation_system_with<S>(&mut self, system: S) -> rinecs::SystemBuilderCreation<S>
where S: CreationSystem + 'static
{
self.world.add_creation_system_with(system)
}
#[cfg(feature = "async")]
pub fn add_creation_system_async<S>(&mut self, system: S) -> &mut Scene
where S: CreationSystemAsync + 'static
{
self.world.add_creation_system_async(system);
self
}
pub fn add_update_system<U>(&mut self, system: U) -> &mut Scene
where U: UpdateSystem + 'static
{
if !self.update_render_barrier {
self.add_barrier::<UpdateRenderBarrier>();
self.update_render_barrier = true;
}
self.add_system(UpdateWrapper(system))
}
pub fn add_update_system_thread_local<U>(&mut self, system: U) -> &mut Scene
where U: UpdateSystemThreadLocal + 'static
{
if !self.update_render_barrier {
self.add_barrier::<UpdateRenderBarrier>();
self.update_render_barrier = true;
}
self.add_system_thread_local(UpdateWrapper(system))
}
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
pub fn add_events_system<S>(&mut self, system: S) -> &mut Scene
where S: EventsSystem + 'static
{
let events = self.resource_mut::<window::Window>().unwrap().event_stream();
self.add_system(EventsWrapper::new(system, events))
}
#[cfg(any(feature="web", feature="desktop", feature="desktop_gles"))]
pub fn add_events_system_thread_local<S>(&mut self, system: S) -> &mut Scene
where S: EventsSystemThreadLocal + 'static
{
let events = self.resource_mut::<window::Window>().unwrap().event_stream();
self.add_system_thread_local(EventsWrapper::new(system, events))
}
#[cfg(feature="gl")]
pub fn add_render_system<R>(&mut self, system: R) -> &mut Scene
where R: RenderSystem + 'static
{
if !self.update_render_barrier {
self.add_barrier::<UpdateRenderBarrier>();
self.update_render_barrier = true;
}
self.add_system_thread_local(RenderWrapper(system))
}
pub fn add_barrier<B: rinecs::Barrier + 'static>(&mut self) -> &mut World {
self.world.add_barrier::<B>()
}
pub fn add_component_to<'a, C: ComponentSend>(&mut self, entity: &Entity, component: C)
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.world.add_component_to(entity, component)
}
pub fn add_component_to_thread_local<'a, C: ComponentThreadLocal>(&mut self, entity: &Entity, component: C)
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.world.add_component_to_thread_local(entity, component)
}
pub fn add_child_component_to<'a, C: ComponentSend>(&mut self, parent: &Entity, entity: &Entity, component: C)
where
for<'b> <C as Component>::Storage: HierarchicalStorage<'b,C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.world.add_child_component_to(parent, entity, component)
}
pub fn add_child_component_to_thread_local<'a, C: ComponentThreadLocal>(&mut self, parent: &Entity, entity: &Entity, component: C)
where
for<'b> <C as Component>::Storage: HierarchicalStorage<'b,C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.world.add_child_component_to_thread_local(parent, entity, component)
}
pub fn add_slice_component_to<'a, C, I>(&mut self, entity: &Entity, component: I)
where
C: OneToNComponentSend,
for<'s> <C as Component>::Storage: OneToNStorage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
I: IntoIterator<Item = C>
{
self.world.add_slice_component_to(entity, component)
}
pub fn add_slice_component_to_thread_local<'a, C, I>(&mut self, entity: &Entity, component: I)
where
C: OneToNComponentThreadLocal,
for<'s> <C as Component>::Storage: OneToNStorage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
I: IntoIterator<Item = C>
{
self.world.add_slice_component_to_thread_local(entity, component)
}
pub fn remove_component_from<'a, C: Component>(&mut self, entity: &Entity)
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.world.remove_component_from::<C>(entity)
}
pub fn remove_entity(&mut self, entity: &Entity){
self.world.remove_entity(entity)
}
pub fn entities(&mut self) -> Entities{
self.world.entities()
}
pub fn entities_and_resources(&mut self) -> (Entities, Resources){
self.world.entities_and_resources()
}
pub fn entities_thread_local(&mut self) -> EntitiesThreadLocal{
self.world.entities_thread_local()
}
pub fn entities_and_resources_thread_local(&mut self) -> (EntitiesThreadLocal, ResourcesThreadLocal){
self.world.entities_and_resources_thread_local()
}
pub fn component_for<C: Component>(&self, entity: &Entity) -> Option<rinecs::Ptr<C>>
where for<'s> <C as Component>::Storage: Storage<'s, C>
{
self.world.component_for::<C>(entity)
}
pub fn component_for_mut<C: Component>(&self, entity: &Entity) -> Option<rinecs::PtrMut<C>>
where for<'s> <C as Component>::Storage: Storage<'s, C>
{
self.world.component_for_mut::<C>(entity)
}
pub fn storage_for<'r, S>(&'r self) -> rinecs::Sto<'r, S>
where S: UnorderedData<'r> + ReadOnlyOp<'r>
{
self.world.storage_for::<S>()
}
pub fn storage_for_mut<'r, S>(&'r mut self) -> rinecs::Sto<'r, S>
where S: UnorderedData<'r>
{
self.world.storage_for_mut::<S>()
}
#[cfg(feature="stats")]
pub fn stats(&mut self) -> impl Iterator<Item = (&str, Property<'static, rinecs::Stat>)>{
self.world.stats()
}
#[cfg(feature="gpu_stats")]
pub fn gpu_stats<'g, C>(&'g mut self, gl: &'g C) -> impl Iterator<Item = (&str, Property<'static, time::Duration>)> + 'g
where C: glin::CreationContext
{
self.world.gpu_stats(gl)
}
#[cfg(feature="stats")]
pub fn enabled_systems(&mut self) -> impl Iterator<Item = (&str, Property<'static, bool>)> {
self.world.enabled_systems()
}
#[cfg(feature="stats")]
pub fn export_tracing_stats<P: AsRef<Path>>(&self, path: P){
self.world.export_tracing_stats(path)
}
#[cfg(feature="stats")]
pub fn total_duration_stats(&self) -> &Property<'static, rinecs::Stat>{
self.world.total_duration_stats()
}
pub fn render_systems_dependency_graph<P: AsRef<Path>>(&mut self, file: P){
self.world.render_systems_dependency_graph(file)
}
}
impl Bundle for () {
type Parameters = ();
fn parameters(&self) -> Option<&Self::Parameters> { None }
fn name(&self) -> &str{
""
}
fn setup(self, _: &mut DeferredScene){}
}
pub trait Builder<'a> {
type Settings;
type IdType: 'static;
type Depends: Bundle + 'static;
fn register(world: &mut rinecs::World);
fn new(world: CreationProxy<'a>, settings: Self::Settings) -> Self;
}
pub struct ModelBuilder<'a>{
builder: rinecs::EntityBuilder<'a>,
added_trafo: bool,
visible: bool,
parent_entity: Option<Entity>,
}
impl<'a> ModelBuilder<'a>{
pub fn transformation<M: Into<Node>>(mut self, model: M) -> ModelBuilder<'a>{
self.builder = if let Some(entity) = self.parent_entity{
self.builder.add_child(&entity, model.into())
}else{
self.builder.add(model.into())
};
self.added_trafo = true;
self
}
pub fn dynamic_transformation<M: Into<Node>>(self, model: M) -> ModelBuilder<'a>{
let mut builder = self.transformation(model);
builder.builder = builder.builder.add_tag::<DynamicTransformation>();
builder
}
#[cfg(feature="materials")]
pub fn material(mut self, material: MaterialRef) -> ModelBuilder<'a>{
self.builder = self.builder.add(material);
self
}
pub fn geometry(mut self, geom: GeometryRef) -> ModelBuilder<'a>{
self.builder = self.builder.add(geom);
self
}
pub fn invisible(mut self) -> ModelBuilder<'a>{
self.visible = false;
self
}
pub fn add<C: Component + Send>(mut self, component: C) -> ModelBuilder<'a>
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.builder = self.builder.add(component);
self
}
pub fn add_thread_local<C: Component>(mut self, component: C) -> ModelBuilder<'a>
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
self.builder = self.builder.add_thread_local(component);
self
}
pub fn add_tag<C: Component + 'a>(mut self) -> Self {
self.builder = self.builder.add_tag::<C>();
self
}
pub fn add_tag_if<C: Component + 'a>(mut self, condition: bool) -> Self {
self.builder = self.builder.add_tag_if::<C>(condition);
self
}
pub fn rigidbody(mut self, shape: physics::Shape, offset: physics::Offset) -> ModelBuilder<'a> {
self.builder = self.builder.add(shape).add(offset);
self
}
pub fn build(self) -> Entity {
let builder = self.builder.add(Visible::new(self.visible));
if !self.added_trafo{
builder.add(Node::identity()).build()
}else{
builder.build()
}
}
}
pub struct EmptyBuilder<'a>{
builder: rinecs::EntityBuilder<'a>,
added_trafo: bool,
parent: Option<Entity>,
}
impl<'a> EmptyBuilder<'a>{
pub fn transformation<M: Into<Node>>(self, model: M) -> EmptyBuilder<'a>{
let builder = if let Some(parent) = self.parent{
self.builder.add_child(&parent, model.into())
}else{
self.builder.add(model.into())
};
EmptyBuilder{
builder,
added_trafo: true,
parent: self.parent,
}
}
pub fn dynamic_transformation<M: Into<Node>>(self, model: M) -> EmptyBuilder<'a>{
let mut builder = self.transformation(model);
builder.builder = builder.builder.add_tag::<DynamicTransformation>();
builder
}
pub fn add<C: Component + Send>(self, component: C) -> EmptyBuilder<'a>
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
EmptyBuilder{
builder: self.builder.add(component),
added_trafo: self.added_trafo,
parent: self.parent,
}
}
pub fn add_thread_local<C: Component>(self, component: C) -> EmptyBuilder<'a>
where
for<'s> <C as Component>::Storage: Storage<'s, C>,
<<C as Component>::Storage as Storage<'a, C>>::Get: DebugParameter,
{
EmptyBuilder{
builder: self.builder.add_thread_local(component),
added_trafo: self.added_trafo,
parent: self.parent,
}
}
pub fn add_tag<C: 'static>(mut self) -> Self {
self.builder = self.builder.add_tag::<C>();
self
}
pub fn add_tag_if<C: 'static>(mut self, condition: bool) -> Self {
self.builder = self.builder.add_tag_if::<C>(condition);
self
}
pub fn build(self) -> Entity {
if !self.added_trafo{
self.builder.add(Node::identity()).build()
}else{
self.builder.build()
}
}
}
pub trait CreationContext<'a>: EntitiesCreationExt<'a> + EntitiesExt<'a> + ResourcesExt + ResourcesThreadLocalExt{
fn add<'e, B: Builder<'e>>(&'e mut self, settings: <B as Builder<'e>>::Settings) -> B where Self: Sized;
fn add_model(&mut self, name: &str) -> ModelBuilder;
fn add_child_model(&mut self, name: &str, parent: Entity) -> ModelBuilder;
fn add_empty(&mut self, name: &str) -> EmptyBuilder;
fn add_child_empty(&mut self, name: &str, parent: Entity) -> EmptyBuilder;
fn register_mesh<T>(&mut self, geom: Mesh<T>) -> GeometryRef
where T: 'static + VertexFormat + Send + Clone + Copy + Debug;
fn register_named_mesh<T>(&mut self, geom: Mesh<T>, name: &str) -> GeometryRef
where T: 'static + VertexFormat + Send + Clone + Copy + Debug;
fn add_ambient_light(&mut self, diffuse: Rgb<f32, LinearRgb>, specular: Rgb<f32, LinearRgb>) -> Entity;
fn add_directional_light<'e>(&'e mut self, name: &'e str) -> DirectionalLightBuilder<'e, Self> where Self: Sized;
fn add_area_light<'e>(&'e mut self, name: &'e str) -> AreaLightBuilder<'e, Self> where Self: Sized;
fn add_spot_light<'e>(&'e mut self, name: &'e str) -> SpotLightBuilder<'e, Self> where Self: Sized;
fn add_point_light<'e>(&'e mut self, name: &'e str) -> PointLightBuilder<'e, Self> where Self: Sized;
fn update_all_transformations(&mut self);
#[cfg(feature="gl_forward_renderer")]
fn add_image_based_light<'e>(&'e mut self, name: &'e str) -> ImageBasedLightBuilder<'e, Self> where Self: Sized;
#[cfg(feature="gl_forward_renderer")]
fn register_material<M: FullMaterial + 'static>(&mut self, name: &str, material: M) -> MaterialRef;
#[cfg(feature="gl_forward_renderer")]
fn register_shadow_material<M: FullMaterial + 'static>(&mut self, name: &str, material: M) -> ShadowMaterialRef;
#[cfg(feature="gl_forward_renderer")]
fn find_material(&self, name: &str) -> Option<MaterialRef>;
#[cfg(feature="gl_forward_renderer")]
fn register_texture(&mut self, texture: glin::Texture) -> TextureRef;
#[cfg(feature="gl_forward_renderer")]
fn register_texture_from_data_format<T: 'static>(&mut self,
format: glin::texture::LoadDataFormat,
creation_flags: TextureCreationFlags,
data: &[T]) -> Result<TextureRef, glin::Error>;
#[cfg(feature="gl_forward_renderer")]
fn register_image<I: renderer::Image + Clone>(&mut self,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>;
#[cfg(feature="gl_forward_renderer")]
#[cfg(feature="squish")]
fn register_compress_image<I: glin::Image<DataType = u8>>(&mut self,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>;
#[cfg(feature="gl_forward_renderer")]
#[cfg(feature="squish")]
fn register_compress_named_image<I: glin::Image<DataType = u8>>(&mut self,
name: &str,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>;
#[cfg(feature="gl_forward_renderer")]
fn register_named_texture_from_data_format<T: 'static>(&mut self,
name: &str,
format: glin::texture::LoadDataFormat,
creation_flags: TextureCreationFlags,
data: &[T]) -> Result<TextureRef, glin::Error>;
#[cfg(feature="gl_forward_renderer")]
fn register_named_image<I: renderer::Image + Clone>(&mut self,
name: &str,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>;
#[cfg(feature="gl_forward_renderer")]
fn register_sampler(&mut self, sampler: Sampler) -> SamplerRef;
#[cfg(feature="gl_forward_renderer")]
fn register_named_sampler(&mut self, name: &str, sampler: Sampler) -> SamplerRef;
#[cfg(feature="gl_forward_renderer")]
fn register_cubemap(&mut self, cubemap: glin::CubeMap) -> CubemapRef;
#[cfg(feature="gl_forward_renderer")]
fn register_named_cubemap(&mut self, name: &str, cubemap: glin::CubeMap) -> CubemapRef;
#[cfg(feature="gl_forward_renderer")]
fn find_named_texture(&self, name: &str) -> Option<TextureRef>;
#[cfg(feature="gl_forward_renderer")]
fn find_named_cubemap(&self, name: &str) -> Option<CubemapRef>;
#[cfg(feature="gl_forward_renderer")]
fn find_named_sampler(&self, name: &str) -> Option<SamplerRef>;
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
fn load_image<P>(&mut self, path: P, flags: TextureCreationFlags) -> util::Result<TextureRef>
where P: AsRef<Path>;
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), dds))]
fn load_cubemap<P>(&mut self, path: P, flags: TextureCreationFlags) -> util::Result<CubemapRef>
where P: AsRef<Path>;
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
fn load_equirectangular_cubemap<P>(
&mut self,
path: P,
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> util::Result<CubemapRef>
where P: AsRef<Path>;
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
fn load_equirectangular_levels_cubemap<P>(
&mut self,
paths: &[P],
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> util::Result<CubemapRef>
where P: AsRef<Path>;
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
fn load_image_async<P>(
&mut self,
path: P,
flags: TextureCreationFlags) -> ResourceFuture<TextureRef>
where P: AsRef<Path>;
#[cfg(all(feature="gl_forward_renderer", feature="async", dds))]
fn load_cubemap_async<P>(&mut self, path: P, flags: TextureCreationFlags) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>;
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
fn load_equirectangular_cubemap_async<P>(
&mut self,
path: P,
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>;
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
fn load_equirectangular_levels_cubemap_async<P>(
&mut self,
paths: &[P],
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>;
fn register_vertex_type<T>(&mut self)
where T: 'static + VertexFormat + Send + Clone + Copy + Debug;
}
impl<'a> CreationContextExt<'a> for Scene {
fn with_entities_and_resources_creation<'e, F, R>(&'e mut self, f: F) -> R
where F: FnOnce(EntitiesCreation<'e>, ResourcesCreation<'e>) -> R
{
self.world.with_entities_and_resources_creation(f)
}
}
impl<'a> CreationContextExt<'a> for CreationProxy<'a> {
fn with_entities_and_resources_creation<'e, F, R>(&'e mut self, f: F) -> R
where F: FnOnce(EntitiesCreation<'e>, ResourcesCreation<'e>) -> R
{
f(self.entities.clone(), self.resources.clone())
}
}
impl<'a, C: CreationContextExt<'a> + EntitiesExt<'a> + ResourcesExt + ResourcesThreadLocalExt> CreationContext<'a> for C {
fn add<'e, B: Builder<'e>>(&'e mut self, settings: <B as Builder<'e>>::Settings) -> B{
self.with_entities_and_resources_creation(|entities, resources| {
let proxy = CreationProxy{
entities,
resources
};
B::new(proxy, settings)
})
}
fn add_model(&mut self, name: &str) -> ModelBuilder{
ModelBuilder{
builder: self.new_entity()
.add(Name(name.to_string()))
.add(Ty::Model),
visible: true,
added_trafo: false,
parent_entity: None,
}
}
fn add_child_model(&mut self, name: &str, parent: Entity) -> ModelBuilder{
ModelBuilder{
builder: self.new_entity()
.add(Name(name.to_string()))
.add(Ty::Model),
visible: true,
added_trafo: false,
parent_entity: Some(parent),
}
}
fn add_empty(&mut self, name: &str) -> EmptyBuilder{
EmptyBuilder{
builder: self.new_entity()
.add(Name(name.to_string()))
.add(Ty::Empty),
added_trafo: false,
parent: None,
}
}
fn add_child_empty(&mut self, name: &str, parent: Entity) -> EmptyBuilder{
EmptyBuilder{
builder: self.new_entity()
.add(Name(name.to_string()))
.add(Ty::Empty),
added_trafo: false,
parent: Some(parent)
}
}
fn register_mesh<T>(&mut self, geom: Mesh<T>) -> GeometryRef
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
self.register_vertex_type::<T>();
let entity = self.new_entity()
.add(Geometry::new(geom))
.add(Ty::Mesh)
.build();
GeometryRef::new(entity)
}
fn register_named_mesh<T>(&mut self, geom: Mesh<T>, name: &str) -> GeometryRef
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
self.register_vertex_type::<T>();
let entity = self.new_entity()
.add(Name(name.to_owned()))
.add(Geometry::new(geom))
.build();
GeometryRef::new(entity)
}
fn add_ambient_light(&mut self, diffuse: Rgb<f32, LinearRgb>, specular: Rgb<f32, LinearRgb>) -> Entity{
AmbientLight::new(self, diffuse, specular)
}
fn add_directional_light<'e>(&'e mut self, name: &'e str) -> DirectionalLightBuilder<'e, Self> where Self: Sized{
DirectionalLightBuilder::new(self, name)
}
fn add_area_light<'e>(&'e mut self, name: &'e str) -> AreaLightBuilder<'e, Self> where Self: Sized{
AreaLightBuilder::new(self, name)
}
fn add_spot_light<'e>(&'e mut self, name: &'e str) -> SpotLightBuilder<'e, Self> where Self: Sized{
SpotLightBuilder::new(self, name)
}
fn add_point_light<'e>(&'e mut self, name: &'e str) -> PointLightBuilder<'e, Self> where Self: Sized{
PointLightBuilder::new(self, name)
}
fn update_all_transformations(&mut self){
for ((trafo, parent), _) in self.ordered_iter_for_mut::<(WriteAndParent<Node>, Not<Bone>)>(){
trafo.update_with_parent(parent);
}
}
#[cfg(feature="gl_forward_renderer")]
fn add_image_based_light<'e>(&'e mut self, name: &'e str) -> ImageBasedLightBuilder<'e, Self> where Self: Sized{
ImageBasedLightBuilder::new(self, name)
}
#[cfg(feature="gl_forward_renderer")]
fn register_material<M: FullMaterial + 'static>(&mut self, name: &str, material: M) -> MaterialRef{
self.resource_thread_local_mut::<MaterialPool>().unwrap().register_material(name, material)
}
#[cfg(feature="gl_forward_renderer")]
fn register_shadow_material<M: FullMaterial + 'static>(&mut self, name: &str, material: M) -> ShadowMaterialRef{
self.resource_thread_local_mut::<ShadowMaterialPool>().unwrap().register_material(name, material)
}
#[cfg(feature="gl_forward_renderer")]
fn find_material(&self, name: &str) -> Option<MaterialRef>{
self.resource_thread_local_mut::<MaterialPool>().unwrap()
.find_material(name)
}
#[cfg(feature="gl_forward_renderer")]
fn register_texture(&mut self, texture: glin::Texture) -> TextureRef{
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_texture(texture)
}
#[cfg(feature="gl_forward_renderer")]
fn register_texture_from_data_format<T: 'static>(&mut self,
format: glin::texture::LoadDataFormat,
creation_flags: TextureCreationFlags,
data: &[T]) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_texture_from_data_format(format, creation_flags, data, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
fn register_image<I: renderer::Image + Clone>(&mut self,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_image(img, creation_flags, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
#[cfg(feature="squish")]
fn register_compress_image<I: glin::Image<DataType = u8>>(&mut self,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_compress_image(img, creation_flags, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
#[cfg(feature="squish")]
fn register_compress_named_image<I: glin::Image<DataType = u8>>(&mut self,
name: &str,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_compress_named_image(name, img, creation_flags, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
fn register_named_texture_from_data_format<T: 'static>(&mut self,
name: &str,
format: glin::texture::LoadDataFormat,
creation_flags: TextureCreationFlags,
data: &[T]) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_named_texture_from_data_format(name, format, creation_flags, data, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
fn register_named_image<I: renderer::Image + Clone>(&mut self,
name: &str,
img: &I,
creation_flags: TextureCreationFlags) -> Result<TextureRef, glin::Error>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_named_image(name, img, creation_flags, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
fn register_sampler(&mut self, sampler: Sampler) -> SamplerRef{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_sampler(sampler, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
fn register_named_sampler(&mut self, name: &str, sampler: Sampler) -> SamplerRef{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.insert_named_sampler(name, sampler, renderer.context())
}
#[cfg(feature="gl_forward_renderer")]
fn register_cubemap(&mut self, cubemap: glin::CubeMap) -> CubemapRef {
self.resource_thread_local_mut::<TexturesPool>().unwrap().insert_cubemap(cubemap)
}
#[cfg(feature="gl_forward_renderer")]
fn register_named_cubemap(&mut self, name: &str, cubemap: glin::CubeMap) -> CubemapRef {
self.resource_thread_local_mut::<TexturesPool>().unwrap().insert_named_cubemap(name, cubemap)
}
#[cfg(feature="gl_forward_renderer")]
fn find_named_texture(&self, name: &str) -> Option<TextureRef>{
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.find_named_texture(name)
}
#[cfg(feature="gl_forward_renderer")]
fn find_named_cubemap(&self, name: &str) -> Option<CubemapRef>{
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.find_named_cubemap(name)
}
#[cfg(feature="gl_forward_renderer")]
fn find_named_sampler(&self, name: &str) -> Option<SamplerRef>{
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.find_named_sampler(name)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
fn load_image<P>(&mut self, path: P, flags: TextureCreationFlags) -> util::Result<TextureRef>
where P: AsRef<Path>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
let context = renderer.context();
self.resource_thread_local_mut::<TexturesPool>().unwrap().load_image(path, flags, &context)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), dds))]
fn load_cubemap<P>(&mut self, path: P, flags: TextureCreationFlags) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap().load_cubemap(path, flags, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
fn load_equirectangular_cubemap<P>(
&mut self,
path: P,
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.load_equirectangular_cubemap(path, flags, color_format, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", not(feature="web"), image_enabled))]
fn load_equirectangular_levels_cubemap<P>(
&mut self,
paths: &[P],
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> util::Result<CubemapRef>
where P: AsRef<Path>
{
let renderer = self.resource_thread_local::<gl::Renderer<'static>>().unwrap();
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.load_equirectangular_levels_cubemap(paths, flags, color_format, &renderer)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
fn load_image_async<P>(
&mut self,
path: P,
flags: TextureCreationFlags) -> ResourceFuture<TextureRef>
where P: AsRef<Path>
{
self.resource_thread_local_mut::<TexturesPool>().unwrap().load_image_async(path, flags)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", dds))]
fn load_cubemap_async<P>(&mut self, path: P, flags: TextureCreationFlags) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_thread_local_mut::<TexturesPool>().unwrap().load_cubemap_async(path, flags)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
fn load_equirectangular_cubemap_async<P>(
&mut self,
path: P,
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.load_equirectangular_cubemap_async(path, flags, color_format)
}
#[cfg(all(feature="gl_forward_renderer", feature="async", image_enabled))]
fn load_equirectangular_levels_cubemap_async<P>(
&mut self,
paths: &[P],
flags: TextureCreationFlags,
color_format: glin::fbo::ColorFormat) -> ResourceFuture<CubemapRef>
where P: AsRef<Path>
{
self.resource_thread_local_mut::<TexturesPool>().unwrap()
.load_equirectangular_levels_cubemap_async(paths, flags, color_format)
}
fn register_vertex_type<T>(&mut self)
where T: 'static + VertexFormat + Send + Clone + Copy + Debug
{
let registered = {
let mut vertex_register = self.resource_thread_local_mut::<VertexRegister>().unwrap();
vertex_register.register_vertex_type::<T>()
};
}
}
impl<'a> rinecs::EntitiesCreationExt<'a> for Scene{
fn new_entity(&mut self) -> rinecs::EntityBuilder{
self.world.new_entity()
}
fn creation_storage<C: Component>(&mut self) -> CreationSto<C> {
self.world.creation_storage()
}
fn with_entities_creation<'e, F, R>(&'e mut self, f: F) -> R
where F: FnOnce(rinecs::EntitiesCreation<'e>) -> R {
self.world.with_entities_creation(f)
}
}
impl ResourcesCreationExt for Scene {
fn with_resources_creation<F, R>(&mut self, f: F) -> R
where F: FnOnce(rinecs::ResourcesCreation) -> R {
self.world.with_resources_creation(f)
}
}
impl<'a> EntitiesExt<'a> for Scene {
fn iter_for<'e, S: UnorderedDataSend<'e> + ReadOnlyOp<'e>>(&'e self) -> <S as UnorderedData<'e>>::Iter {
EntitiesExt::iter_for::<S>(&self.world)
}
fn iter_for_mut<'e, S: UnorderedDataSend<'e>>(&'e mut self) -> <S as UnorderedData<'e>>::IterMut {
EntitiesExt::iter_for_mut::<S>(&mut self.world)
}
fn ordered_iter_for<'e, S: OrderedDataSend<'e> + ReadOnlyOrderedOp<'e>>(&'e self) -> <S as OrderedData<'e>>::Iter{
EntitiesExt::ordered_iter_for::<S>(&self.world)
}
fn ordered_iter_for_mut<'e, S: OrderedDataSend<'e>>(&'e mut self) -> <S as OrderedData<'e>>::Iter{
EntitiesExt::ordered_iter_for_mut::<S>(&mut self.world)
}
fn iter_for_entities<'e, U, E>(&'e self, entities: E) -> E::IntoEntitiesIter
where
E: IntoEntitiesIterator<'e, U::Storage>,
U: UnorderedDataSend<'e>,
U::Storage: ReadOnlyStorage,
{
entities.storage_entities_iter(U::storage(&self.world))
}
fn iter_for_entities_mut<'e, U, E>(&'e mut self, entities: E) -> E::IntoEntitiesIterMut
where
E: IntoEntitiesIterator<'e, U::Storage>,
U: UnorderedDataSend<'e>,
{
entities.storage_entities_iter_mut(U::storage(&self.world))
}
fn iter_for_entities_opt<'e, U, E>(&'e self, entities: E) -> E::IntoEntitiesOptIter
where
E: IntoEntitiesIterator<'e, U::Storage>,
U: UnorderedDataSend<'e>,
U::Storage: ReadOnlyStorage,
{
entities.storage_entities_opt_iter(U::storage(&self.world))
}
fn iter_for_entities_opt_mut<'e, U, E>(&'e mut self, entities: E) -> E::IntoEntitiesOptIterMut
where
E: IntoEntitiesIterator<'e, U::Storage>,
U: UnorderedDataSend<'e>,
{
entities.storage_entities_opt_iter_mut(U::storage(&self.world))
}
fn entity_components<'r, S>(&'r self, entity: &Entity) -> Option<<S as UnorderedData<'r>>::ComponentsRef>
where
S: UnorderedDataSend<'r> + ReadOnlyOp<'r> + 'r,
S::Storage: StorageRef<'r, Component = S::ComponentsRef>
{
EntitiesExt::entity_components::<S>(&self.world, entity)
}
fn entity_components_mut<'r, S>(&'r mut self, entity: &Entity) -> Option<<S as UnorderedData<'r>>::ComponentsRef>
where
S: UnorderedDataSend<'r> + 'r,
S::Storage: StorageRef<'r, Component = S::ComponentsRef>
{
EntitiesExt::entity_components_mut::<S>(&mut self.world, entity)
}
fn component_for<C: ComponentSend>(&self, entity: &Entity) -> Option<Ptr<C>>
where for<'s> <C as Component>::Storage: Storage<'s, C>
{
EntitiesExt::component_for::<C>(&self.world, entity)
}
fn component_for_mut<C: ComponentSend>(&self, entity: &Entity) -> Option<PtrMut<C>>
where for<'s> <C as Component>::Storage: Storage<'s, C>
{
EntitiesExt::component_for_mut::<C>(&self.world, entity)
}
fn has_component<C: 'static>(&self, entity: &Entity) -> bool {
EntitiesExt::has_component::<C>(&self.world, entity)
}
fn tree_node_for<C: ComponentSend>(&self, entity: &Entity) -> Option<NodePtr<C>>
where for<'b> <C as Component>::Storage: HierarchicalStorage<'b, C>
{
EntitiesExt::tree_node_for::<C>(&self.world, entity)
}
fn tree_node_for_mut<C: ComponentSend>(&self, entity: &Entity) -> Option<NodePtrMut<C>>
where for<'b> <C as Component>::Storage: HierarchicalStorage<'b, C>
{
EntitiesExt::tree_node_for_mut::<C>(&self.world, entity)
}
fn changed_iter_for<'r, S>(&'r self) -> EntitiesComponentIter<'r, S::ChangedIter, <S as UnorderedData<'r>>::Storage>
where
S: ChangedDataSend<'r> + EntitiesData + ReadOnlyOp<'r> + 'r,
<S as UnorderedData<'r>>::Storage: StorageRef<'r>
{
let iter = S::changed_iter(&self.world);
S::into_entities_iter(&self.world, iter)
}
fn changed_iter_for_mut<'r, S>(&'r mut self) -> EntitiesComponentIter<'r, S::ChangedIter, <S as UnorderedData<'r>>::Storage>
where
S: ChangedDataSend<'r> + EntitiesData + 'r,
<S as UnorderedData<'r>>::Storage: StorageRef<'r>
{
let iter = S::changed_iter(&self.world);
S::into_entities_iter(&self.world, iter)
}
fn storage_for<'e, S: UnorderedDataSend<'e> + ReadOnlyOp<'e>>(&'e self) -> rinecs::Sto<'e, S> {
EntitiesExt::storage_for::<S>(&self.world)
}
fn storage_for_mut<'e, S>(&'e mut self) -> rinecs::Sto<'e, S>
where S: UnorderedDataSend<'e>
{
EntitiesExt::storage_for_mut::<S>(&mut self.world)
}
}
pub struct CreationProxy<'a> {
entities: EntitiesCreation<'a>,
resources: ResourcesCreation<'a>,
}
impl<'a> CreationProxy<'a> {
pub fn new(entities: EntitiesCreation<'a>, resources: ResourcesCreation<'a>) -> CreationProxy<'a> {
CreationProxy {
entities,
resources,
}
}
pub fn clone(&mut self) -> CreationProxy {
CreationProxy {
entities: self.entities.clone(),
resources: self.resources.clone(),
}
}
pub fn as_storages(&mut self) -> CreationStorages {
CreationStorages {
entities: self.entities.as_storages(),
resources: self.resources.clone(),
}
}
}
impl<'a> EntitiesExt<'a> for CreationProxy<'a> {
fn iter_for<'e,S: UnorderedDataSend<'e> + ReadOnlyOp<'e>>(&'e self) -> S::Iter {
self.entities.iter_for::<S>()
}
fn iter_for_mut<'e,S: UnorderedDataSend<'e>>(&'e mut self) -> S::IterMut {
self.entities.iter_for_mut::<S>()
}
fn ordered_iter_for<'e, S: OrderedDataSend<'e> + ReadOnlyOrderedOp<'e>>(&'e self) -> S::Iter {
self.entities.ordered_iter_for::<S>()
}
fn ordered_iter_for_mut<'e, S: OrderedDataSend<'e>>(&'e mut self) -> S::Iter {
self.entities.ordered_iter_for_mut::<S>()
}
fn entity_components<'r, S>(&'r self, entity: &Entity) -> Option<S::ComponentsRef>
where
S: UnorderedDataSend<'r> + ReadOnlyOp<'r> + 'r,
S::Storage: StorageRef<'r, Component = S::ComponentsRef>
{
self.entities.entity_components::<S>(entity)
}
fn entity_components_mut<'r, S>(&'r mut self, entity: &Entity) -> Option<S::ComponentsRef>
where
S: UnorderedDataSend<'r> + 'r,
S::Storage: StorageRef<'r, Component = S::ComponentsRef>
{
self.entities.entity_components_mut::<S>(entity)
}
fn iter_for_entities<'e, U, E>(&'e self, entities: E) -> E::IntoEntitiesIter
where
E: IntoEntitiesIterator<'e, U::Storage>,
U: UnorderedDataSend<'e>,
U::Storage: ReadOnlyStorage,
{
entities.storage_entities_iter(U::storage(&self.entities))
}
fn iter_for_entities_mut<'e, U, E>(&'e mut self, entities: E) -> E::IntoEntitiesIterMut
where
E: IntoEntitiesIterator<'e, U::Storage>,
U: UnorderedDataSend<'e>,
{
entities.storage_entities_iter_mut(U::storage(&self.entities))
}
fn iter_for_entities_opt<'e, U, E>(&'e self, entities: E) -> E::IntoEntitiesOptIter
where
E: IntoEntitiesIterator<'e, U::Storage>,
U: UnorderedDataSend<'e>,
U::Storage: ReadOnlyStorage,
{
entities.storage_entities_opt_iter(U::storage(&self.entities))
}
fn iter_for_entities_opt_mut<'e, U, E>(&'e mut self, entities: E) -> E::IntoEntitiesOptIterMut
where
E: IntoEntitiesIterator<'e, U::Storage>,
U: UnorderedDataSend<'e>,
{
entities.storage_entities_opt_iter_mut(U::storage(&self.entities))
}
fn component_for<C: ComponentSend>(&self, entity: &Entity) -> Option<Ptr<C>>
where for<'s> C::Storage: Storage<'s, C>
{
self.entities.component_for::<C>(entity)
}
fn component_for_mut<C: ComponentSend>(&self, entity: &Entity) -> Option<PtrMut<C>>
where for<'s> C::Storage: Storage<'s, C>
{
self.entities.component_for_mut::<C>(entity)
}
fn has_component<C: 'static>(&self, entity: &Entity) -> bool {
self.entities.has_component::<C>(entity)
}
fn tree_node_for<C: ComponentSend>(&self, entity: &Entity) -> Option<NodePtr<C>>
where for<'b> C::Storage: HierarchicalStorage<'b, C>
{
self.entities.tree_node_for::<C>(entity)
}
fn tree_node_for_mut<C: ComponentSend>(&self, entity: &Entity) -> Option<NodePtrMut<C>>
where for<'b> C::Storage: HierarchicalStorage<'b, C>
{
self.entities.tree_node_for_mut::<C>(entity)
}
fn changed_iter_for<'r, S>(&'r self) -> EntitiesComponentIter<'r, S::ChangedIter, S::Storage>
where
S: ChangedDataSend<'r> + EntitiesData + ReadOnlyOp<'r> + 'r,
S::Storage: StorageRef<'r>
{
self.entities.changed_iter_for::<S>()
}
fn changed_iter_for_mut<'r, S>(&'r mut self) -> EntitiesComponentIter<'r, S::ChangedIter, S::Storage>
where
S: ChangedDataSend<'r> + EntitiesData + 'r,
S::Storage: StorageRef<'r>
{
self.entities.changed_iter_for_mut::<S>()
}
fn storage_for<'r, S>(&'r self) -> rinecs::Sto<'r, S>
where S: UnorderedDataSend<'r> + ReadOnlyOp<'r>
{
self.entities.storage_for::<S>()
}
fn storage_for_mut<'r, S>(&'r mut self) -> rinecs::Sto<'r, S>
where S: UnorderedDataSend<'r>
{
self.entities.storage_for_mut::<S>()
}
}
impl<'a> EntitiesCreationExt<'a> for CreationProxy<'a> {
fn with_entities_creation<'e, F, R>(&'e mut self, f: F) -> R
where F: FnOnce(EntitiesCreation<'e>) -> R {
self.entities.with_entities_creation(f)
}
fn new_entity(&mut self) -> rinecs::EntityBuilder {
self.entities.new_entity()
}
fn creation_storage<C: Component>(&mut self) -> CreationSto<C> {
self.entities.creation_storage()
}
}
impl<'a> ResourcesCreationExt for CreationProxy<'a> {
fn with_resources_creation<F, R>(&mut self, f: F) -> R
where F: FnOnce(ResourcesCreation) -> R {
self.resources.with_resources_creation(f)
}
}
pub struct CreationStorages<'a> {
entities: EntityStoragesCreation<'a>,
resources: ResourcesCreation<'a>,
}
impl<'a> EntitiesCreationExt<'a> for CreationStorages<'a> {
fn with_entities_creation<'e, F, R>(&'e mut self, f: F) -> R
where F: FnOnce(EntitiesCreation<'e>) -> R {
self.entities.with_entities_creation(f)
}
fn new_entity(&mut self) -> rinecs::EntityBuilder {
self.entities.new_entity()
}
fn creation_storage<C: Component>(&mut self) -> CreationSto<C> {
self.entities.creation_storage()
}
}
impl<'a> ResourcesCreationExt for CreationStorages<'a> {
fn with_resources_creation<F, R>(&mut self, f: F) -> R
where F: FnOnce(ResourcesCreation) -> R {
self.resources.with_resources_creation(f)
}
}
impl<'a> EntityStoragesExt<'a> for CreationStorages<'a> {
fn component_for<C: ComponentSend>(&self, entity: &Entity) -> Option<Ptr<C>>
where for<'s> C::Storage: Storage<'s, C>
{
self.entities.component_for::<C>(entity)
}
fn component_for_mut<C: ComponentSend>(&self, entity: &Entity) -> Option<PtrMut<C>>
where for<'s> C::Storage: Storage<'s, C>
{
self.entities.component_for_mut::<C>(entity)
}
fn has_component<C: 'static>(&self, entity: &Entity) -> bool {
self.entities.has_component::<C>(entity)
}
fn tree_node_for<C: ComponentSend>(&self, entity: &Entity) -> Option<NodePtr<C>>
where for<'b> C::Storage: HierarchicalStorage<'b, C>
{
self.entities.tree_node_for::<C>(entity)
}
fn tree_node_for_mut<C: ComponentSend>(&self, entity: &Entity) -> Option<NodePtrMut<C>>
where for<'b> C::Storage: HierarchicalStorage<'b, C>
{
self.entities.tree_node_for_mut::<C>(entity)
}
fn storage_for<'r, S>(&'r self) -> rinecs::Sto<'r, S>
where S: UnorderedDataSend<'r>
{
self.entities.storage_for::<S>()
}
}
impl ResourcesExt for Scene {
fn resource<T: 'static + Send>(&self) -> Option<ReadGuardRef<T>> {
self.world.resource()
}
fn resource_mut<T: 'static + Send>(&self) -> Option<WriteGuardRef<T>> {
self.world.resource_mut()
}
fn resource_as_trait<T: 'static + Send + ?Sized>(&self) -> Option<ReadGuardRef<T>> {
self.world.resource_as_trait()
}
fn resource_as_trait_mut<T: 'static + Send + ?Sized>(&self) -> Option<WriteGuardRef<T>> {
self.world.resource_as_trait_mut()
}
}
impl ResourcesThreadLocalExt for Scene {
fn resource_thread_local<T: 'static>(&self) -> Option<ReadGuardRef<T>> {
self.world.resource_thread_local()
}
fn resource_thread_local_mut<T: 'static>(&self) -> Option<WriteGuardRef<T>> {
self.world.resource_thread_local_mut()
}
fn resource_as_trait_thread_local<T: 'static + ?Sized>(&self) -> Option<ReadGuardRef<T>> {
self.world.resource_as_trait_thread_local()
}
fn resource_as_trait_thread_local_mut<T: 'static + ?Sized>(&self) -> Option<WriteGuardRef<T>> {
self.world.resource_as_trait_thread_local_mut()
}
}
impl<'a> ResourcesExt for CreationProxy<'a> {
fn resource<T: 'static + Send>(&self) -> Option<ReadGuardRef<T>> {
self.resources.get()
}
fn resource_mut<T: 'static + Send>(&self) -> Option<WriteGuardRef<T>> {
self.resources.get_mut()
}
fn resource_as_trait<T: 'static + Send + ?Sized>(&self) -> Option<ReadGuardRef<T>> {
self.resources.as_trait()
}
fn resource_as_trait_mut<T: 'static + Send + ?Sized>(&self) -> Option<WriteGuardRef<T>> {
self.resources.as_trait_mut()
}
}
impl<'a> ResourcesThreadLocalExt for CreationProxy<'a> {
fn resource_thread_local<T: 'static>(&self) -> Option<ReadGuardRef<T>> {
self.resources.get()
}
fn resource_thread_local_mut<T: 'static>(&self) -> Option<WriteGuardRef<T>> {
self.resources.get_mut()
}
fn resource_as_trait_thread_local<T: 'static + ?Sized>(&self) -> Option<ReadGuardRef<T>> {
self.resources.as_trait()
}
fn resource_as_trait_thread_local_mut<T: 'static + ?Sized>(&self) -> Option<WriteGuardRef<T>> {
self.resources.as_trait_mut()
}
}