#![deny(missing_docs)]
extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;
extern crate shader_version;
extern crate glutin_window;
use glutin_window::GlutinWindow;
pub use shader_version::OpenGL;
pub use graphics::*;
pub use piston::window::*;
pub use piston::input::*;
pub use piston::event_loop::*;
pub use gfx_graphics::{ GlyphError, Texture, TextureSettings, Flip };
use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;
use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };
pub type GfxEncoder = gfx::Encoder<gfx_device_gl::Resources,
gfx_device_gl::CommandBuffer>;
pub type Glyphs = gfx_graphics::GlyphCache<gfx_device_gl::Resources,
gfx_device_gl::Factory>;
pub type G2d<'a> = GfxGraphics<'a,
gfx_device_gl::Resources,
gfx_device_gl::CommandBuffer>;
pub type G2dTexture<'a> = Texture<gfx_device_gl::Resources>;
pub struct PistonWindow<T = (), W: Window = GlutinWindow> {
pub window: Rc<RefCell<W>>,
pub encoder: Rc<RefCell<GfxEncoder>>,
pub device: Rc<RefCell<gfx_device_gl::Device>>,
pub output_color: Rc<gfx::handle::RenderTargetView<
gfx_device_gl::Resources, gfx::format::Srgba8>>,
pub output_stencil: Rc<gfx::handle::DepthStencilView<
gfx_device_gl::Resources, gfx::format::DepthStencil>>,
pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
pub events: Rc<RefCell<WindowEvents>>,
pub event: Option<Event<W::Event>>,
pub app: Rc<RefCell<T>>,
pub factory: Rc<RefCell<gfx_device_gl::Factory>>,
}
impl<W> BuildFromWindowSettings for PistonWindow<(), W>
where W: Window + OpenGLWindow + BuildFromWindowSettings,
W::Event: GenericEvent
{
fn build_from_window_settings(mut settings: WindowSettings)
-> Result<PistonWindow<(), W>, String> {
settings = settings.srgb(true);
let opengl = settings.get_maybe_opengl().unwrap_or(OpenGL::V3_2);
let samples = settings.get_samples();
Ok(PistonWindow::new(opengl, samples,
Rc::new(RefCell::new(try!(settings.build()))), empty_app()))
}
}
impl<T, W> Clone for PistonWindow<T, W>
where W: Window, W::Event: Clone
{
fn clone(&self) -> Self {
PistonWindow {
window: self.window.clone(),
encoder: self.encoder.clone(),
device: self.device.clone(),
output_color: self.output_color.clone(),
output_stencil: self.output_stencil.clone(),
g2d: self.g2d.clone(),
events: self.events.clone(),
event: self.event.clone(),
app: self.app.clone(),
factory: self.factory.clone(),
}
}
}
fn create_main_targets(dim: gfx::tex::Dimensions) ->
(Rc<gfx::handle::RenderTargetView<
gfx_device_gl::Resources, gfx::format::Srgba8>>,
Rc<gfx::handle::DepthStencilView<
gfx_device_gl::Resources, gfx::format::DepthStencil>>) {
use gfx::core::factory::Typed;
use gfx::format::{DepthStencil, Format, Formatted, Srgba8};
let color_format: Format = <Srgba8 as Formatted>::get_format();
let depth_format: Format = <DepthStencil as Formatted>::get_format();
let (output_color, output_stencil) =
gfx_device_gl::create_main_targets_raw(dim,
color_format.0,
depth_format.0);
let output_color = Typed::new(output_color);
let output_stencil = Typed::new(output_stencil);
(Rc::new(output_color), Rc::new(output_stencil))
}
impl<T, W> PistonWindow<T, W>
where W: Window, W::Event: GenericEvent
{
pub fn new(
opengl: OpenGL,
samples: u8,
window: Rc<RefCell<W>>,
app: Rc<RefCell<T>>
) -> Self
where W: OpenGLWindow
{
use piston::event_loop::Events;
use piston::window::{ OpenGLWindow, Window };
use gfx::core::factory::Typed;
let (device, mut factory) =
gfx_device_gl::create(|s|
window.borrow_mut().get_proc_address(s) as *const _);
let (output_color, output_stencil) = {
let aa = samples as gfx::tex::NumSamples;
let draw_size = window.borrow().draw_size();
let dim = (draw_size.width as u16, draw_size.height as u16,
1, aa.into());
create_main_targets(dim)
};
let g2d = Gfx2d::new(opengl, &mut factory);
let encoder = factory.create_command_buffer().into();
PistonWindow {
window: window.clone(),
encoder: Rc::new(RefCell::new(encoder)),
device: Rc::new(RefCell::new(device)),
output_color: output_color,
output_stencil: output_stencil,
g2d: Rc::new(RefCell::new(g2d)),
events: Rc::new(RefCell::new(window.borrow().events())),
event: None,
app: app,
factory: Rc::new(RefCell::new(factory)),
}
}
pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<U, W> {
PistonWindow {
window: self.window,
encoder: self.encoder,
device: self.device,
output_color: self.output_color,
output_stencil: self.output_stencil,
g2d: self.g2d,
events: self.events,
event: self.event,
app: app,
factory: self.factory,
}
}
#[inline(always)]
pub fn app_by_value<U>(self, app: U) -> PistonWindow<U, W> {
self.app(Rc::new(RefCell::new(app)))
}
pub fn draw_2d<F>(&self, f: F) where
F: FnOnce(Context, &mut G2d)
{
use piston::input::RenderEvent;
if let Some(ref e) = self.event {
if let Some(args) = e.render_args() {
let mut encoder = self.encoder.borrow_mut();
self.g2d.borrow_mut().draw(
&mut encoder,
&self.output_color,
&self.output_stencil,
args.viewport(),
f
);
let mut device = self.device.borrow_mut();
encoder.flush(&mut *device);
}
}
}
pub fn draw_3d<F>(&self, f: F) where
F: FnOnce(&mut GfxEncoder)
{
use piston::input::RenderEvent;
if let Some(ref e) = self.event {
if let Some(_) = e.render_args() {
let mut encoder = self.encoder.borrow_mut();
f(&mut *encoder);
let mut device = self.device.borrow_mut();
encoder.flush(&mut *device);
}
}
}
}
impl<T, W> Iterator for PistonWindow<T, W>
where W: Window, W::Event: GenericEvent
{
type Item = PistonWindow<T, W>;
fn next(&mut self) -> Option<PistonWindow<T, W>> {
use piston::input::*;
use gfx::core::factory::Typed;
let window = &mut *self.window.borrow_mut();
if let Some(e) = self.events.borrow_mut().next(window) {
if let Some(_) = e.after_render_args() {
self.device.borrow_mut().cleanup();
}
let dim = self.output_color.raw().get_dimensions();
let (w, h) = (dim.0, dim.1);
let draw_size = window.draw_size();
let (output_color, output_stencil) =
if w != draw_size.width as u16 || h != draw_size.height as u16 {
let dim = (draw_size.width as u16,
draw_size.height as u16,
dim.2, dim.3);
create_main_targets(dim)
} else {
(self.output_color.clone(), self.output_stencil.clone())
};
Some(PistonWindow {
window: self.window.clone(),
encoder: self.encoder.clone(),
device: self.device.clone(),
output_color: output_color,
output_stencil: output_stencil,
g2d: self.g2d.clone(),
events: self.events.clone(),
event: Some(e),
app: self.app.clone(),
factory: self.factory.clone(),
})
} else { None }
}
}
impl<T, W> GenericEvent for PistonWindow<T, W>
where W: Window, W::Event: GenericEvent
{
fn event_id(&self) -> EventId {
match self.event {
Some(ref e) => e.event_id(),
None => EventId("")
}
}
fn with_args<'a, F, U>(&'a self, f: F) -> U
where F: FnMut(&Any) -> U
{
self.event.as_ref().unwrap().with_args(f)
}
fn from_args(
event_id: EventId,
any: &Any,
old_event: &Self
) -> Option<Self> {
if let Some(ref e) = old_event.event {
match GenericEvent::from_args(event_id, any, e) {
Some(e) => {
Some(PistonWindow {
window: old_event.window.clone(),
encoder: old_event.encoder.clone(),
device: old_event.device.clone(),
output_color: old_event.output_color.clone(),
output_stencil: old_event.output_stencil.clone(),
g2d: old_event.g2d.clone(),
events: old_event.events.clone(),
event: Some(e),
app: old_event.app.clone(),
factory: old_event.factory.clone(),
})
}
None => None
}
} else { None }
}
}
impl<T, W> Window for PistonWindow<T, W>
where W: Window
{
type Event = <W as Window>::Event;
fn should_close(&self) -> bool { self.window.borrow().should_close() }
fn set_should_close(&mut self, value: bool) {
self.window.borrow_mut().set_should_close(value)
}
fn size(&self) -> Size { self.window.borrow().size() }
fn draw_size(&self) -> Size { self.window.borrow().draw_size() }
fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
fn poll_event(&mut self) -> Option<Self::Event> {
Window::poll_event(&mut *self.window.borrow_mut())
}
}
impl<T, W> AdvancedWindow for PistonWindow<T, W>
where W: AdvancedWindow
{
fn get_title(&self) -> String { self.window.borrow().get_title() }
fn set_title(&mut self, title: String) {
self.window.borrow_mut().set_title(title)
}
fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
fn set_exit_on_esc(&mut self, value: bool) {
self.window.borrow_mut().set_exit_on_esc(value)
}
fn set_capture_cursor(&mut self, value: bool) {
self.window.borrow_mut().set_capture_cursor(value)
}
}
impl<T, W> EventLoop for PistonWindow<T, W>
where W: Window
{
fn set_ups(&mut self, frames: u64) {
self.events.borrow_mut().set_ups(frames);
}
fn set_max_fps(&mut self, frames: u64) {
self.events.borrow_mut().set_max_fps(frames);
}
fn set_swap_buffers(&mut self, enable: bool) {
self.events.borrow_mut().set_swap_buffers(enable);
}
fn set_bench_mode(&mut self, enable: bool) {
self.events.borrow_mut().set_bench_mode(enable);
}
}
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }