use log::info;
use std;
use wgpu;
use crate::graphics::render;
use crate::resources::color::Color;
use crate::resources::sprite::SpriteTexture;
#[derive(Debug)]
pub enum WindowError {
GeneralError(String),
RenderError(render::RenderError),
}
impl<S> std::convert::From<S> for WindowError
where
S: std::string::ToString,
{
fn from(s: S) -> Self {
WindowError::GeneralError(s.to_string())
}
}
impl std::convert::From<render::RenderError> for WindowError {
fn from(e: render::RenderError) -> Self {
WindowError::RenderError(e)
}
}
pub enum FilterMethod {
NearestNeighbor,
Linear,
}
impl From<FilterMethod> for wgpu::FilterMode {
fn from(f: FilterMethod) -> Self {
match f {
FilterMethod::NearestNeighbor => wgpu::FilterMode::Nearest,
FilterMethod::Linear => wgpu::FilterMode::Linear,
}
}
}
pub struct WindowBuilder<'a> {
window_title: &'a str,
width: u32,
height: u32,
sprite_texture: &'a SpriteTexture,
vsync: bool,
resizable: bool,
full_screen: bool,
clear_color: Color,
filter_method: FilterMethod,
}
impl<'a> WindowBuilder<'a> {
pub fn new(
window_title: &'a str,
width: u32,
height: u32,
sprite_texture: &'a SpriteTexture,
) -> Self {
WindowBuilder {
window_title: window_title,
width: width,
height: height,
sprite_texture: sprite_texture,
vsync: true,
resizable: false,
full_screen: false,
clear_color: [0, 255, 0].into(),
filter_method: FilterMethod::NearestNeighbor,
}
}
pub fn with_vsync(mut self, enable: bool) -> Self {
self.vsync = enable;
self
}
pub fn with_resizable(mut self, enable: bool) -> Self {
self.resizable = enable;
self
}
pub fn enable_full_screen(mut self) -> Self {
self.full_screen = true;
self
}
pub fn with_clear_color(mut self, c: Color) -> Self {
self.clear_color = c;
self
}
pub fn with_filter_method(mut self, f: FilterMethod) -> Self {
self.filter_method = f.into();
self
}
pub fn build(self) -> Result<Window, WindowError> {
let screen_width = (self.width * self.sprite_texture.sprite_width() as u32) as f32;
let screen_height = (self.height * self.sprite_texture.sprite_height() as u32) as f32;
info!("Screen dimensions {}x{}", screen_width, screen_height);
let screen_dimensions = winit::dpi::LogicalSize::<f32>::from_physical(
winit::dpi::PhysicalSize::new(screen_width, screen_height),
1.0,
);
info!("logical size: {:?}", screen_dimensions);
let event_loop = winit::event_loop::EventLoop::new();
let window = winit::window::WindowBuilder::new()
.with_title(self.window_title.to_string())
.with_inner_size(screen_dimensions)
.with_maximized(self.full_screen)
.with_decorations(!self.full_screen)
.with_resizable(self.resizable)
.with_visible(false)
.build(&event_loop)?;
let renderer = crate::graphics::render::Renderer::new(
Some(&window),
(self.width as _, self.height as _),
self.sprite_texture,
self.clear_color.into(),
self.filter_method.into(),
if self.vsync {
wgpu::PresentMode::Fifo
} else {
wgpu::PresentMode::Mailbox
},
)?;
Ok(Window {
width: self.width,
height: self.height,
window: window,
event_loop: event_loop,
renderer: renderer,
})
}
}
pub struct Window {
pub(crate) renderer: render::Renderer,
pub(crate) window: winit::window::Window,
pub(crate) event_loop: winit::event_loop::EventLoop<()>,
pub(crate) width: u32,
pub(crate) height: u32,
}
impl Window {
pub(crate) fn render(&mut self) -> Result<(), WindowError> {
unimplemented!();
}
pub(crate) fn renderer_mut(&mut self) -> &mut render::Renderer {
&mut self.renderer
}
pub(crate) fn renderer(&self) -> &render::Renderer {
&self.renderer
}
}