radiant_rs/core/
display.rsuse prelude::*;
use core::*;
use core::builder::*;
use backends::backend;
#[derive(Clone)]
pub struct Display {
pub(crate) handle: backend::Display,
pub(crate) frame: Rc<RefCell<Option<backend::Frame>>>,
pub(crate) input_data: Arc<RwLock<InputData>>,
}
impl Debug for Display {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Display")
}
}
impl Display {
pub fn builder() -> DisplayBuilder {
DisplayBuilder::new()
}
pub fn set_title(self: &Self, title: &str) {
self.handle.set_title(title);
}
pub fn show(self: &Self) {
self.handle.show();
}
pub fn hide(self: &Self) {
self.handle.hide();
}
pub fn set_fullscreen(self: &Self) -> Result<()> {
if let Some(backend_monitor) = backend::MonitorIterator::new(self).next() {
let monitor = Monitor::new(backend_monitor);
self.set_fullscreen_on(monitor)
} else {
Err(Error::FullscreenError("Failed select monitor device.".to_string()))
}
}
pub fn set_fullscreen_on(self: &Self, monitor: Monitor) -> Result<()> {
if !self.handle.set_fullscreen(Some(monitor)) {
self.handle.set_fullscreen(None);
Err(Error::FullscreenError("Failed to switch to fullscreen.".to_string()))
} else {
Ok(())
}
}
pub fn set_windowed(self: &Self) {
self.handle.set_fullscreen(None);
}
pub fn prepare_frame(self: &Self) {
if self.frame.borrow().is_some() {
panic!("Current frame needs to be swapped before a new frame can be prepared.");
}
*self.frame.borrow_mut() = Some(self.handle.draw());
}
pub fn clear_frame(self: &Self, color: Color) {
self.prepare_frame();
if let Some(ref mut frame) = self.frame.borrow_mut().as_mut() {
frame.clear(color);
} else {
panic!("Failed to prepare a frame for clear.");
}
}
pub fn swap_frame(self: &Self) {
let frame = mem::replace(&mut *self.frame.borrow_mut(), None);
if let Some(frame) = frame {
frame.finish();
} else {
panic!("No frame currently prepared, nothing to swap.");
}
}
pub fn grab_cursor(self: &Self) {
let mut input_data = self.input_data.write().unwrap();
if input_data.has_focus {
self.handle.set_cursor_state(CursorState::Grab);
}
input_data.cursor_grabbed = true;
}
pub fn hide_cursor(self: &Self) {
self.handle.set_cursor_state(CursorState::Hide);
self.input_data.write().unwrap().cursor_grabbed = false;
}
pub fn free_cursor(self: &Self) {
self.handle.set_cursor_state(CursorState::Normal);
self.input_data.write().unwrap().cursor_grabbed = false;
}
pub fn set_cursor_position(self: &Self, position: Point2<i32>) {
self.handle.set_cursor_position(position);
}
pub fn dimensions(self: &Self) -> Point2<u32> {
self.handle.framebuffer_dimensions()
}
pub fn monitors(self: &Self) -> Vec<Monitor> {
let iter = backend::MonitorIterator::new(self);
let mut result = Vec::<Monitor>::new();
for monitor in iter {
result.push(Monitor::new(monitor));
}
result
}
pub fn poll_events(self: &Self) -> &Self {
let mut input_data = self.input_data.write().unwrap();
for key_id in 0..NUM_KEYS {
match input_data.key[key_id] {
InputState::Pressed | InputState::Repeat => {
input_data.key[key_id] = InputState::Down;
}
InputState::Released => {
input_data.key[key_id] = InputState::Up;
}
_ => { }
}
}
for button_id in 0..NUM_BUTTONS {
match input_data.button[button_id] {
InputState::Pressed => {
input_data.button[button_id] = InputState::Down;
}
InputState::Released => {
input_data.button[button_id] = InputState::Up;
}
_ => { }
}
}
input_data.mouse_delta = (0, 0);
self.handle.poll_events(|event| {
match event {
Event::KeyboardInput(key_id, down) => {
let currently_down = match input_data.key[key_id] {
InputState::Down | InputState::Pressed | InputState::Repeat => true,
_ => false
};
if !currently_down && down {
input_data.key[key_id] = InputState::Pressed;
} else if currently_down && !down {
input_data.key[key_id] = InputState::Released;
} else if currently_down && down {
input_data.key[key_id] = InputState::Repeat;
}
},
Event::MouseDelta(x, y) => {
input_data.mouse_delta = (x, y);
},
Event::MousePosition(x, y) => {
input_data.mouse = (x, y);
},
Event::MouseInput(button_id, down) => {
let currently_down = match input_data.button[button_id] {
InputState::Down | InputState::Pressed => true,
_ => false
};
if !currently_down && down {
input_data.button[button_id] = InputState::Pressed
} else if currently_down && !down {
input_data.button[button_id] = InputState::Released
}
},
Event::Focus => {
input_data.has_focus = true;
if input_data.cursor_grabbed {
self.handle.set_cursor_state(CursorState::Grab);
}
}
Event::Blur => {
input_data.has_focus = false;
self.handle.set_cursor_state(CursorState::Normal);
}
Event::Close => {
input_data.should_close = true;
}
}
});
input_data.dimensions = self.handle.window_dimensions().into();
self
}
pub fn was_closed(self: &Self) -> bool {
let mut input_data = self.input_data.write().unwrap();
let result = input_data.should_close;
input_data.should_close = false;
result
}
pub(crate) fn new(descriptor: DisplayInfo) -> Result<Display> {
Ok(Display {
handle: backend::Display::new(descriptor)?,
frame: Rc::new(RefCell::new(None)),
input_data: Arc::new(RwLock::new(InputData::new())),
})
}
pub(crate) fn frame<T>(self: &Self, func: T) where T: FnOnce(&mut backend::Frame) {
let mut frame = self.frame.borrow_mut();
func(frame.as_mut().expect(NO_FRAME_PREPARED));
}
}
impl AsRenderTarget for Display {
fn as_render_target(self: &Self) -> RenderTarget {
RenderTarget::frame(&self.frame)
}
}
#[derive(Debug)]
pub enum CursorState {
Normal,
Hide,
Grab,
}
#[derive(Debug, PartialEq)]
pub enum Event {
KeyboardInput(usize, bool),
MouseInput(usize, bool),
MouseDelta(i32, i32),
MousePosition(i32, i32),
Focus,
Blur,
Close,
}
#[derive(Clone, Debug)]
pub struct DisplayInfo {
pub width : u32,
pub height : u32,
pub title : String,
pub transparent : bool,
pub decorations : bool,
pub monitor : Option<Monitor>,
pub vsync : bool,
pub visible : bool,
}
impl Default for DisplayInfo {
fn default() -> DisplayInfo {
DisplayInfo {
width : 640,
height : 480,
title : "".to_string(),
transparent : false,
decorations : true,
monitor : None,
vsync : false,
visible : true,
}
}
}