diff --git a/examples/noise.rs b/examples/noise.rs index 28a3155..55131b0 100644 --- a/examples/noise.rs +++ b/examples/noise.rs @@ -6,15 +6,26 @@ const WIDTH: usize = 640; const HEIGHT: usize = 360; fn main() { - let mut noise; - let mut carry; - let mut seed = 0xbeefu32; + //let mut noise; + //let mut carry; + //let mut seed = 0xbeefu32; - let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT]; + //let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT]; - let mut mfb = Minifb::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT).unwrap(); + let window = match macos::Window::new("Noise Test - Press ESC to exit", + WIDTH, + HEIGHT, + Scale::X1, + Vsync::No) { + Ok(window) => window, + Err(info) => { + println!("{}", info); + return; + } + }; - while mfb.update(&buffer) { + loop { + /* for i in buffer.iter_mut() { noise = seed; noise >>= 3; @@ -26,5 +37,6 @@ fn main() { noise &= 0xFF; *i = (noise << 16) | (noise << 8) | noise; } + */ } } diff --git a/src/lib.rs b/src/lib.rs index afe32cc..2713803 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,20 +11,119 @@ extern crate cocoa; extern crate core_foundation; #[cfg(target_os = "macos")] -/// Error that can happen while creating a window or a headless renderer. -#[derive(Debug)] -pub enum CreationError { - OsError(String), - NotSupported, +/// Scale will scale the frame buffer and the window that is being sent in when calling the update +/// function. This is useful if you for example want to display a 320 x 256 window on a screen with +/// much higher resolution which would result in that the window is very small. +pub enum Scale { + /// This mode checks your current screen resolution and will caluclate the largest window size + /// that can be used within that limit and resize it. Useful if you have a small buffer to + /// display on a high resolution screen. + FitScreen, + /// 1X scale (which means leave the corrdinates sent into Window::new untouched) + X1, + /// 2X window scale (Example: 320 x 200 -> 640 x 400) + X2, + /// 4X window scale (Example: 320 x 200 -> 1280 x 800) + X4, + /// 8X window scale (Example: 320 x 200 -> 2560 x 1600) + X8, + /// 16X window scale (Example: 320 x 200 -> 5120 x 3200) + X16, + /// 32 window scale (Example: 320 x 200 -> 10240 x 6400) + X32, } -impl CreationError { - fn to_string(&self) -> &str { - match *self { - CreationError::OsError(ref text) => &text, - CreationError::NotSupported => "Some of the requested attributes are not supported", - } - } +/// Vsync will allow syncronized rendering with the screen refresh rate. +pub enum Vsync { + /// No vsync + No, + /// Require accurate vsync. Notice that if the library is unable to to setup an accurate + /// syncing the window creation will fail. + Accurate, + /// Setup a best guess syncing with the screen. This will always succesed but may not be + /// accurate. What this means is if the lib is unable to create a accurate syncing approach + /// a 'emulated' one will be used (for example using a timer to approximate syncing) + BestGuess, +} + +/// +pub enum Key { + Space, + /// The '1' key over the letters. + Key1, + /// The '2' key over the letters. + Key2, + /// The '3' key over the letters. + Key3, + /// The '4' key over the letters. + Key4, + /// The '5' key over the letters. + Key5, + /// The '6' key over the letters. + Key6, + /// The '7' key over the letters. + Key7, + /// The '8' key over the letters. + Key8, + /// The '9' key over the letters. + Key9, + /// The '0' key over the 'O' and 'P' keys. + Key0, + + A, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + + Escape, + + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + F13, + F14, + F15, + + ArrowLeft, + ArrowRight, + ArrowUp, + ArrowDown, + + Backspace, + Delete, + Comma, + Semicollon } #[cfg(target_os = "windows")] @@ -38,77 +137,3 @@ pub mod macos; pub use macos::*; -/* - -#[cfg(target_os = "macos")] -#[link(name = "Cocoa", kind = "framework")] -extern { - fn mfb_open(name: *const c_char, width: c_int, height: c_int) -> c_int; - fn mfb_update(buffer: *mut c_void) -> c_int; - fn mfb_close(); -} - -/* -#[cfg(target_os = "windows")] -#[link(name = "gdi32")] -extern { - fn mfb_open(name: *const c_char, width: c_int, height: c_int) -> c_int; - fn mfb_update(buffer: *mut c_void) -> c_int; - fn mfb_close(); -} -*/ - -#[cfg(target_os = "linux")] -#[link(name = "X11")] -extern { - fn mfb_open(name: *const c_char, width: c_int, height: c_int) -> c_int; - fn mfb_update(buffer: *mut c_void) -> c_int; - fn mfb_close(); -} - -/// -/// Open up a window -/// -#[cfg(any(target_os = "linux", target_os = "mac"))] -pub fn open(name: &str, width: usize, height: usize) -> bool { - let s = CString::new(name).unwrap(); - let ret; - - unsafe { - ret = mfb_open(s.as_ptr(), width as c_int, height as c_int); - } - - match ret { - 0 => false, - _ => true, - } -} - -/// -/// Update -/// -#[cfg(any(target_os = "linux", target_os = "mac"))] -pub fn update(buffer: &[u32]) -> bool { - let ret; - unsafe { - ret = mfb_update(transmute(buffer.as_ptr())); - } - - if ret < 0 { - return false; - } else { - return true; - } -} - -/// -/// Close -/// -#[cfg(any(target_os = "linux", target_os = "mac"))] -pub fn close() { - unsafe { - mfb_close(); - } -} - -*/ diff --git a/src/macos.rs b/src/macos.rs index d1a6596..b634b84 100644 --- a/src/macos.rs +++ b/src/macos.rs @@ -1,36 +1,69 @@ #![cfg(target_os = "macos")] -use CreationError; -use CreationError::OsError; +use Scale; +use Vsync; +use Key; -use libc; -use cocoa::appkit; +//use libc; +//use cocoa::appkit; use cocoa::appkit::*; -use cocoa::appkit::NSEventSubtype::*; +//use cocoa::appkit::NSEventSubtype::*; +#[allow(unused_imports)] use cocoa::base::{id, nil}; +#[allow(unused_imports)] use objc::runtime::{Class, Object, Sel, BOOL, YES, NO}; +#[allow(unused_imports)] use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize, NSString, NSUInteger}; +use std::ops::Deref; -struct Minifb { - temp: isize, +pub struct Window { + view: IdRef, + window: IdRef, } -impl Minifb { - pub unsafe fn new(name: &str, width: isize, height: isize) -> Result { - let app = match Self::create_app() { - Some(app) => app, - None => { return Err(OsError(format!("Couldn't create NSApplication"))); }, - }; +impl Window { + pub fn new(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result { + unsafe { + let app = match Self::create_app() { + Some(app) => app, + None => { + return Err("Couldn't create NSApplication"); + }, + }; - let masks = 0u64; + let window = match Self::create_window(name, width, height) { + Some(window) => window, + None => { + return Err("Unable to create NSWindow"); + } + }; - //let masks = NSResizableWindowMask as NSUInteger | - // NSClosableWindowMask as NSUInteger | - // NSTitledWindowMaskas as NSUInteger; + let view = match Self::create_view(*window) { + Some(view) => view, + None => { + return Err("Unable to create NSView"); + } + }; + + app.activateIgnoringOtherApps_(YES); + + println!("Created window and view"); + + return Ok(Window { + window: window, + view: view + }); + } + } + + unsafe fn create_window(name: &str, width: usize, height: usize) -> Option { + let masks = NSResizableWindowMask as NSUInteger | + NSClosableWindowMask as NSUInteger | + NSTitledWindowMask as NSUInteger; let frame = NSRect::new(NSPoint::new(0., 0.), NSSize::new(width as f64, height as f64)); @@ -41,9 +74,34 @@ impl Minifb { NO, )); - if window.is_nil() { - return Err(OsError(format!("Unable to create window"))); - } + window.non_nil().map(|window| { + let title = IdRef::new(NSString::alloc(nil).init_str(name)); + window.setTitle_(*title); + window.center(); + window + }) + } + + unsafe fn create_view(window: id) -> Option { + let view = IdRef::new(NSView::alloc(nil).init()); + view.non_nil().map(|view| { + window.setContentView_(*view); + view + }) + } + + pub fn update(_: &[u32]) { + } + + pub fn get_keys() -> Option> { + return None; + } + + pub fn is_esc_pressed() -> bool { + false + } + + pub fn close() { } @@ -58,10 +116,10 @@ impl Minifb { } } } - - } + + struct IdRef(id); impl IdRef { @@ -82,4 +140,26 @@ impl IdRef { } } +impl Drop for IdRef { + fn drop(&mut self) { + if self.0 != nil { + let _: () = unsafe { msg_send![self.0, release] }; + } + } +} +impl Deref for IdRef { + type Target = id; + fn deref<'a>(&'a self) -> &'a id { + &self.0 + } +} + +impl Clone for IdRef { + fn clone(&self) -> IdRef { + if self.0 != nil { + let _: id = unsafe { msg_send![self.0, retain] }; + } + IdRef(self.0) + } +}