use crate::core::algebra::ComplexField;
use crate::{
core::{
algebra::{Isometry2, Translation2, Vector2},
color::Color,
instant,
pool::{Handle, Pool},
visitor::prelude::*,
},
engine::PhysicsBinder,
resource::texture::Texture,
scene::base::PhysicsBinding,
scene2d::{graph::Graph, node::Node, physics::Physics, physics::PhysicsPerformanceStatistics},
sound::{context::SoundContext, engine::SoundEngine},
};
use std::collections::HashMap;
use std::{
ops::{Index, IndexMut},
sync::{Arc, Mutex},
};
pub mod base;
pub mod camera;
pub mod graph;
pub mod light;
pub mod node;
pub mod physics;
pub mod sprite;
pub mod transform;
#[derive(Clone, Default, Debug)]
pub struct PerformanceStatistics {
pub physics: PhysicsPerformanceStatistics,
pub graph_update_time: f32,
pub sound_update_time: f32,
}
#[derive(Visit, Default)]
pub struct Scene2d {
pub graph: Graph,
pub render_target: Option<Texture>,
pub enabled: bool,
pub ambient_light_color: Color,
pub sound_context: SoundContext,
pub physics: Physics,
pub physics_binder: PhysicsBinder<Node>,
#[visit(skip)]
pub performance_statistics: PerformanceStatistics,
}
impl Scene2d {
pub fn new() -> Self {
Self {
graph: Graph::new(),
render_target: None,
enabled: true,
ambient_light_color: Color::opaque(80, 80, 80),
sound_context: SoundContext::new(),
physics: Default::default(),
physics_binder: Default::default(),
performance_statistics: Default::default(),
}
}
fn update_physics(&mut self) {
self.physics.step();
self.performance_statistics.physics = self.physics.performance_statistics.clone();
self.physics.performance_statistics.reset();
let graph = &mut self.graph;
let physics = &mut self.physics;
self.physics_binder
.retain(|node, body| graph.is_valid_handle(*node) && physics.contains_body(body));
if self.physics_binder.enabled {
for (&node_handle, body) in self.physics_binder.forward_map().iter() {
let body = physics.body_mut(body).unwrap();
let node = &mut self.graph[node_handle];
match node.physics_binding {
PhysicsBinding::NodeWithBody => {
node.local_transform_mut()
.set_position(body.position().translation.vector)
.set_rotation(body.position().rotation.to_polar().1);
}
PhysicsBinding::BodyWithNode => {
let (r, p) = self.graph.isometric_global_rotation_position(node_handle);
body.set_position(
Isometry2 {
rotation: r,
translation: Translation2 { vector: p },
},
true,
);
}
}
}
}
}
pub fn update(&mut self, render_target_size: Vector2<f32>, dt: f32) {
self.update_physics();
let last = instant::Instant::now();
self.graph.update(render_target_size, dt);
self.performance_statistics.graph_update_time =
(instant::Instant::now() - last).as_secs_f32();
self.performance_statistics.sound_update_time = self
.sound_context
.state()
.full_render_duration()
.as_secs_f32();
}
pub(in crate) fn resolve(&mut self) {
self.physics.resolve();
}
pub fn clone<F>(&self, filter: &mut F) -> (Self, HashMap<Handle<Node>, Handle<Node>>)
where
F: FnMut(Handle<Node>, &Node) -> bool,
{
let (graph, old_new_map) = self.graph.clone(filter);
let physics = self.physics.deep_copy();
let mut physics_binder = PhysicsBinder::default();
for (node, &body) in self.physics_binder.forward_map().iter() {
if let Some(&new_node) = old_new_map.get(node) {
physics_binder.bind(new_node, body);
}
}
(
Self {
graph,
physics,
physics_binder,
render_target: Default::default(),
sound_context: self.sound_context.deep_clone(),
performance_statistics: Default::default(),
ambient_light_color: self.ambient_light_color,
enabled: self.enabled,
},
old_new_map,
)
}
}
#[derive(Visit)]
pub struct Scene2dContainer {
pool: Pool<Scene2d>,
sound_engine: Arc<Mutex<SoundEngine>>,
}
impl Scene2dContainer {
pub fn new(sound_engine: Arc<Mutex<SoundEngine>>) -> Self {
Self {
pool: Default::default(),
sound_engine,
}
}
pub fn add(&mut self, scene: Scene2d) -> Handle<Scene2d> {
self.sound_engine
.lock()
.unwrap()
.add_context(scene.sound_context.clone());
self.pool.spawn(scene)
}
pub fn remove(&mut self, scene_handle: Handle<Scene2d>) -> Scene2d {
self.sound_engine
.lock()
.unwrap()
.remove_context(self.pool[scene_handle].sound_context.clone());
self.pool.free(scene_handle)
}
pub fn iter(&self) -> impl Iterator<Item = &Scene2d> {
self.pool.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Scene2d> {
self.pool.iter_mut()
}
pub fn pair_iter(&self) -> impl Iterator<Item = (Handle<Scene2d>, &Scene2d)> {
self.pool.pair_iter()
}
pub fn pair_iter_mut(&mut self) -> impl Iterator<Item = (Handle<Scene2d>, &mut Scene2d)> {
self.pool.pair_iter_mut()
}
pub fn clear(&mut self) {
self.pool.clear();
}
}
impl Index<Handle<Scene2d>> for Scene2dContainer {
type Output = Scene2d;
fn index(&self, index: Handle<Scene2d>) -> &Self::Output {
&self.pool[index]
}
}
impl IndexMut<Handle<Scene2d>> for Scene2dContainer {
fn index_mut(&mut self, index: Handle<Scene2d>) -> &mut Self::Output {
&mut self.pool[index]
}
}