use std::collections::HashMap;
use astrelis_core::geometry::Size;
use astrelis_render::{GraphicsContext, WindowContext, WindowContextDescriptor};
use astrelis_winit::window::Window;
use astrelis_winit::WindowId;
use crate::plugin::Plugin;
use crate::resource::Resources;
pub struct RenderContexts {
graphics: Option<&'static GraphicsContext>,
contexts: HashMap<WindowId, WindowContext>,
}
impl Default for RenderContexts {
fn default() -> Self {
Self::new()
}
}
impl RenderContexts {
pub fn new() -> Self {
Self {
graphics: None,
contexts: HashMap::new(),
}
}
pub fn with_graphics(graphics: &'static GraphicsContext) -> Self {
Self {
graphics: Some(graphics),
contexts: HashMap::new(),
}
}
pub fn create_for_window(&mut self, window: Window) -> &mut WindowContext {
let graphics = self
.graphics
.expect("RenderContexts must be initialized with a GraphicsContext");
self.create_for_window_with(window, graphics, WindowContextDescriptor::default())
}
pub fn create_for_window_with(
&mut self,
window: Window,
graphics: &'static GraphicsContext,
descriptor: WindowContextDescriptor,
) -> &mut WindowContext {
let window_id = window.id();
if !self.contexts.contains_key(&window_id) {
let context = WindowContext::new(window, graphics, descriptor);
self.contexts.insert(window_id, context);
}
self.contexts.get_mut(&window_id).unwrap()
}
pub fn get(&self, window_id: WindowId) -> Option<&WindowContext> {
self.contexts.get(&window_id)
}
pub fn get_mut(&mut self, window_id: WindowId) -> Option<&mut WindowContext> {
self.contexts.get_mut(&window_id)
}
pub fn remove(&mut self, window_id: WindowId) -> Option<WindowContext> {
self.contexts.remove(&window_id)
}
pub fn contains(&self, window_id: WindowId) -> bool {
self.contexts.contains_key(&window_id)
}
pub fn resized(&mut self, window_id: WindowId, new_size: Size<u32>) {
if let Some(context) = self.contexts.get_mut(&window_id) {
context.resized(new_size);
}
}
pub fn graphics(&self) -> Option<&'static GraphicsContext> {
self.graphics
}
}
pub struct RenderPlugin;
impl Plugin for RenderPlugin {
fn name(&self) -> &'static str {
"RenderPlugin"
}
fn build(&self, resources: &mut Resources) {
let graphics: &'static GraphicsContext = GraphicsContext::new_sync();
tracing::info!(
"RenderPlugin: GraphicsContext created (backend: {:?})",
graphics.info().backend
);
resources.insert(graphics);
resources.insert(RenderContexts::with_graphics(graphics));
}
}
#[cfg(test)]
mod tests {
#[test]
#[ignore = "Requires GPU"]
fn test_render_plugin() {
use super::*;
use crate::EngineBuilder;
let engine = EngineBuilder::new().add_plugin(RenderPlugin).build();
assert!(engine.get::<&'static GraphicsContext>().is_some());
assert!(engine.get::<RenderContexts>().is_some());
}
}