New version running with keyboard support

This commit is contained in:
Daniel Collin 2015-12-08 22:57:14 +01:00
parent 60e28c4a74
commit d4ca056adc
3 changed files with 180 additions and 166 deletions

View file

@ -6,27 +6,15 @@ const WIDTH: usize = 640;
const HEIGHT: usize = 360; const HEIGHT: usize = 360;
fn main() { fn main() {
//let mut noise; let mut noise;
//let mut carry; let mut carry;
//let mut seed = 0xbeefu32; let mut seed = 0xbeefu32;
let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT]; let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];
let window = match macos::Window::new("Noise Test - Press ESC to exit", let mut window = Window::new("Noise Test - Press ESC to exit", WIDTH, HEIGHT, Scale::X1, Vsync::No).unwrap();
WIDTH,
HEIGHT,
Scale::X1,
Vsync::No) {
Ok(window) => window,
Err(info) => {
println!("{}", info);
return;
}
};
loop { while window.update(&buffer) {
window.update(&buffer);
/*
for i in buffer.iter_mut() { for i in buffer.iter_mut() {
noise = seed; noise = seed;
noise >>= 3; noise >>= 3;
@ -38,6 +26,13 @@ fn main() {
noise &= 0xFF; noise &= 0xFF;
*i = (noise << 16) | (noise << 8) | noise; *i = (noise << 16) | (noise << 8) | noise;
} }
*/
for key in window.get_keys().iter() {
match *key {
Key::A => println!("Pressed A"),
Key::B => println!("Pressed B"),
_ => (),
}
}
} }
} }

View file

@ -8,7 +8,6 @@ extern crate cgl;
extern crate cocoa; extern crate cocoa;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
extern crate core_foundation; extern crate core_foundation;
#[cfg(target_os = "macos")]
/// Scale will scale the frame buffer and the window that is being sent in when calling the update /// 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 /// function. This is useful if you for example want to display a 320 x 256 window on a screen with
@ -46,45 +45,44 @@ pub enum Vsync {
BestGuess, BestGuess,
} }
///
pub enum Key { pub enum Key {
Key1, Key0 = 0,
Key2, Key1 = 1,
Key3, Key2 = 2,
Key4, Key3 = 3,
Key5, Key4 = 4,
Key6, Key5 = 5,
Key7, Key6 = 6,
Key8, Key7 = 7,
Key9, Key8 = 8,
Key0, Key9 = 9,
A, A = 10,
B, B = 11,
C, C = 12,
D, D = 13,
E, E = 14,
F, F = 15,
G, G = 16,
H, H = 17,
I, I = 18,
J, J = 19,
K, K = 20,
L, L = 21,
M, M = 22,
N, N = 23,
O, O = 24,
P, P = 25,
Q, Q = 26,
R, R = 27,
S, S = 28,
T, T = 29,
U, U = 30,
V, V = 31,
W, W = 32,
X, X = 33,
Y, Y = 34,
Z, Z = 35,
F1, F1,
F2, F2,
@ -145,8 +143,8 @@ pub mod windows;
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub use windows::*; pub use windows::*;
#[cfg(target_os = "macos")] //#[cfg(target_os = "macos")]
pub mod macos; //pub mod macos;
#[cfg(target_os = "macos")] //#[cfg(target_os = "macos")]
pub use macos::*; //pub use macos::*;

View file

@ -9,6 +9,8 @@ use Scale;
use Vsync; use Vsync;
use Key; use Key;
//use Keys;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use std::os::windows::ffi::OsStrExt; use std::os::windows::ffi::OsStrExt;
@ -16,6 +18,7 @@ use std::ffi::OsStr;
use std::mem; use std::mem;
use self::winapi::windef::HWND; use self::winapi::windef::HWND;
use self::winapi::windef::HDC;
use self::winapi::winuser::WS_OVERLAPPEDWINDOW; use self::winapi::winuser::WS_OVERLAPPEDWINDOW;
use self::winapi::winuser::WNDCLASSW; use self::winapi::winuser::WNDCLASSW;
use self::winapi::wingdi::BITMAPINFOHEADER; use self::winapi::wingdi::BITMAPINFOHEADER;
@ -30,86 +33,85 @@ struct BitmapInfo {
pub bmi_colors: [RGBQUAD; 3], pub bmi_colors: [RGBQUAD; 3],
} }
fn update_key_state(window: &mut Window, wparam: u32, bool state) { fn update_key_state(window: &mut Window, wparam: u32, state: bool) {
match wparam & 0x1ff { match wparam & 0x1ff {
0x00B => window.keys[Key::Key0] = state, 0x00B => window.keys[Key::Key0 as usize] = state,
0x002 => window.keys[Key::Key1] = state, 0x002 => window.keys[Key::Key1 as usize] = state,
0x003 => window.keys[Key::Key2] = state, 0x003 => window.keys[Key::Key2 as usize] = state,
0x004 => window.keys[Key::Key3] = state, 0x004 => window.keys[Key::Key3 as usize] = state,
0x005 => window.keys[Key::Key4] = state, 0x005 => window.keys[Key::Key4 as usize] = state,
0x006 => window.keys[Key::Key5] = state, 0x006 => window.keys[Key::Key5 as usize] = state,
0x007 => window.keys[Key::Key6] = state, 0x007 => window.keys[Key::Key6 as usize] = state,
0x008 => window.keys[Key::Key7] = state, 0x008 => window.keys[Key::Key7 as usize] = state,
0x009 => window.keys[Key::Key8] = state, 0x009 => window.keys[Key::Key8 as usize] = state,
0x00A => window.keys[Key::Key9] = state, 0x00A => window.keys[Key::Key9 as usize] = state,
0x01E => window.keys[Key::A] = state, 0x01E => window.keys[Key::A as usize] = state,
0x030 => window.keys[Key::B] = state, 0x030 => window.keys[Key::B as usize] = state,
0x02E => window.keys[Key::C] = state, 0x02E => window.keys[Key::C as usize] = state,
0x020 => window.keys[Key::D] = state, 0x020 => window.keys[Key::D as usize] = state,
0x012 => window.keys[Key::E] = state, 0x012 => window.keys[Key::E as usize] = state,
0x021 => window.keys[Key::F] = state, 0x021 => window.keys[Key::F as usize] = state,
0x022 => window.keys[Key::G] = state, 0x022 => window.keys[Key::G as usize] = state,
0x023 => window.keys[Key::H] = state, 0x023 => window.keys[Key::H as usize] = state,
0x017 => window.keys[Key::I] = state, 0x017 => window.keys[Key::I as usize] = state,
0x024 => window.keys[Key::J] = state, 0x024 => window.keys[Key::J as usize] = state,
0x025 => window.keys[Key::K] = state, 0x025 => window.keys[Key::K as usize] = state,
0x026 => window.keys[Key::L] = state, 0x026 => window.keys[Key::L as usize] = state,
0x032 => window.keys[Key::M] = state, 0x032 => window.keys[Key::M as usize] = state,
0x031 => window.keys[Key::N] = state, 0x031 => window.keys[Key::N as usize] = state,
0x018 => window.keys[Key::O] = state, 0x018 => window.keys[Key::O as usize] = state,
0x019 => window.keys[Key::P] = state, 0x019 => window.keys[Key::P as usize] = state,
0x010 => window.keys[Key::Q] = state, 0x010 => window.keys[Key::Q as usize] = state,
0x013 => window.keys[Key::R] = state, 0x013 => window.keys[Key::R as usize] = state,
0x01F => window.keys[Key::S] = state, 0x01F => window.keys[Key::S as usize] = state,
0x014 => window.keys[Key::T] = state, 0x014 => window.keys[Key::T as usize] = state,
0x016 => window.keys[Key::U] = state, 0x016 => window.keys[Key::U as usize] = state,
0x02F => window.keys[Key::V] = state, 0x02F => window.keys[Key::V as usize] = state,
0x011 => window.keys[Key::W] = state, 0x011 => window.keys[Key::W as usize] = state,
0x02D => window.keys[Key::X] = state, 0x02D => window.keys[Key::X as usize] = state,
0x015 => window.keys[Key::Y] = state, 0x015 => window.keys[Key::Y as usize] = state,
0x02C => window.keys[Key::Z] = state, 0x02C => window.keys[Key::Z as usize] = state,
0x03B => window.keys[Key::F1] = state, 0x03B => window.keys[Key::F1 as usize] = state,
0x03C => window.keys[Key::F2] = state, 0x03C => window.keys[Key::F2 as usize] = state,
0x03D => window.keys[Key::F3] = state, 0x03D => window.keys[Key::F3 as usize] = state,
0x03E => window.keys[Key::F4] = state, 0x03E => window.keys[Key::F4 as usize] = state,
0x03F => window.keys[Key::F5] = state, 0x03F => window.keys[Key::F5 as usize] = state,
0x040 => window.keys[Key::F6] = state, 0x040 => window.keys[Key::F6 as usize] = state,
0x041 => window.keys[Key::F7] = state, 0x041 => window.keys[Key::F7 as usize] = state,
0x042 => window.keys[Key::F8] = state, 0x042 => window.keys[Key::F8 as usize] = state,
0x043 => window.keys[Key::F9] = state, 0x043 => window.keys[Key::F9 as usize] = state,
0x042 => window.keys[Key::F8] = state, 0x044 => window.keys[Key::F10 as usize] = state,
0x043 => window.keys[Key::F9] = state, 0x057 => window.keys[Key::F11 as usize] = state,
0x044 => window.keys[Key::F10] = state, 0x058 => window.keys[Key::F12 as usize] = state,
0x057 => window.keys[Key::F11] = state, 0x150 => window.keys[Key::Down as usize] = state,
0x058 => window.keys[Key::F12] = state, 0x14B => window.keys[Key::Left as usize] = state,
0x150 => window.keys[Key::Down] = state, 0x14D => window.keys[Key::Right as usize] = state,
0x14B => window.keys[Key::Left] = state, 0x148 => window.keys[Key::Up as usize] = state,
0x14D => window.keys[Key::Right] = state, 0x028 => window.keys[Key::Apostrophe as usize] = state,
0x148 => window.keys[Key::Up] = state, 0x02B => window.keys[Key::Backslash as usize] = state,
0x028 => window.keys[Key::Apostrophe] = state, 0x033 => window.keys[Key::Comma as usize] = state,
0x02B => window.keys[Key::Backslash] = state, 0x00D => window.keys[Key::Equal as usize] = state,
0x033 => window.keys[Key::Comma] = state, 0x01A => window.keys[Key::LeftBracket as usize] = state,
0x00D => window.keys[Key::Equal] = state, 0x00C => window.keys[Key::Minus as usize] = state,
0x01A => window.keys[Key::LeftBracket] = state, 0x034 => window.keys[Key::Period as usize] = state,
0x00C => window.keys[Key::Minus] = state, 0x01B => window.keys[Key::RightBracket as usize] = state,
0x034 => window.keys[Key::Period] = state, 0x027 => window.keys[Key::Semicolon as usize] = state,
0x01B => window.keys[Key::RightBracket] = state, 0x035 => window.keys[Key::Slash as usize] = state,
0x027 => window.keys[Key::Semicolon] = state, 0x00E => window.keys[Key::Backspace as usize] = state,
0x035 => window.keys[Key::Slash] = state, 0x153 => window.keys[Key::Delete as usize] = state,
0x00E => window.keys[Key::Backspace] = state, 0x14F => window.keys[Key::End as usize] = state,
0x153 => window.keys[Key::Delete] = state, 0x01C => window.keys[Key::Enter as usize] = state,
0x14F => window.keys[Key::End] = state, 0x001 => window.keys[Key::Escape as usize] = state,
0x01C => window.keys[Key::Enter] = state, 0x147 => window.keys[Key::Home as usize] = state,
0x001 => window.keys[Key::Escape] = state, 0x152 => window.keys[Key::Insert as usize] = state,
0x147 => window.keys[Key::Home] = state, 0x15D => window.keys[Key::Menu as usize] = state,
0x152 => window.keys[Key::Insert] = state, 0x151 => window.keys[Key::PageDown as usize] = state,
0x15D => window.keys[Key::Menu] = state, 0x149 => window.keys[Key::PageUp as usize] = state,
0x151 => window.keys[Key::PageDown] = state, 0x045 => window.keys[Key::Pause as usize] = state,
0x149 => window.keys[Key::PageUp] = state, 0x039 => window.keys[Key::Space as usize] = state,
0x045 => window.keys[Key::Pause] = state, 0x00F => window.keys[Key::Tab as usize] = state,
0x039 => window.keys[Key::Space] = state, 0x03A => window.keys[Key::CapsLock as usize] = state,
0x00F => window.keys[Key::Tab] = state, _ => (),
0x03A => window.keys[Key::CapsLock] = state,
} }
} }
@ -124,21 +126,22 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND,
let user_data = user32::GetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA); let user_data = user32::GetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA);
if user_data == 0 if user_data == 0 {
return user32::DefWindowProcW(window, msg, wparam, lparam); return user32::DefWindowProcW(window, msg, wparam, lparam);
}
let mut self = user_data as &mut Window; let mut wnd: &mut Window = mem::transmute(user_data);
match msg { match msg {
winapi::winuser::WM_KEYDOWN => { winapi::winuser::WM_KEYDOWN => {
update_key_state(self, wparam as u32, true); update_key_state(wnd, (lparam as u32) >> 16, true);
if (wparam & 0x1ff) == 27 { if (wparam & 0x1ff) == 27 {
CLOSE_APP = true; CLOSE_APP = true;
} }
} }
winapi::winuser::WM_KEYUP => { winapi::winuser::WM_KEYUP => {
update_key_state(self, wparam as u32, false); update_key_state(wnd, (lparam as u32) >> 16, false);
} }
winapi::winuser::WM_PAINT => { winapi::winuser::WM_PAINT => {
@ -160,7 +163,7 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND,
bitmap_info.bmi_colors[1].rgbGreen = 0xff; bitmap_info.bmi_colors[1].rgbGreen = 0xff;
bitmap_info.bmi_colors[2].rgbBlue = 0xff; bitmap_info.bmi_colors[2].rgbBlue = 0xff;
gdi32::StretchDIBits(self.dc, gdi32::StretchDIBits(wnd.dc.unwrap(),
0, 0,
0, 0,
width, width,
@ -169,7 +172,7 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND,
0, 0,
width, width,
height, height,
mem::transmute(self.buffer), mem::transmute(wnd.buffer.as_ptr()),
mem::transmute(&bitmap_info), mem::transmute(&bitmap_info),
winapi::wingdi::DIB_RGB_COLORS, winapi::wingdi::DIB_RGB_COLORS,
winapi::wingdi::SRCCOPY); winapi::wingdi::SRCCOPY);
@ -192,14 +195,14 @@ fn to_wstring(str: &str) -> *const u16 {
} }
pub struct Window { pub struct Window {
dc: DC, dc: Option<HDC>,
window: HWND, window: Option<HWND>,
bool keys_down: [bool; 512], keys: [bool; 512],
buffer: &[u32], buffer: Vec<u32>,
} }
impl Window { impl Window {
fn open_window(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result<Window, &str> { fn open_window(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> HWND {
unsafe { unsafe {
let class_name = to_wstring("minifb_window"); let class_name = to_wstring("minifb_window");
let s = CString::new(name).unwrap(); let s = CString::new(name).unwrap();
@ -252,26 +255,39 @@ impl Window {
user32::ShowWindow(handle, winapi::SW_NORMAL); user32::ShowWindow(handle, winapi::SW_NORMAL);
} }
return handle; return handle;
} }
} }
pub fn new(name: &str, width: usize, height: usize) -> Option<Minifb> { pub fn new(name: &str, width: usize, height: usize, scale: Scale, vsync: Vsync) -> Result<Window, &str> {
let handle = Minifb::open_window(name, width, height); unsafe {
let handle = Self::open_window(name, width, height, scale, vsync);
match handle.is_null() { if handle.is_null() {
true => None, return Err("Unable to create Window");
false => Some(Minifb { window: handle }), }
let window = Window {
dc: Some(user32::GetDC(handle)),
window: Some(handle),
keys: [false; 512],
buffer: Vec::new(),
};
Ok(window)
} }
} }
pub fn get_keys(&self -> Vec<Key> { pub fn get_keys(&self) -> Vec<Key> {
let index = 0; let mut index: u8 = 0;
let mut keys: Vec<Key> = Vec::new(); let mut keys: Vec<Key> = Vec::new();
for i in self.keys { for i in self.keys.iter() {
if *i { if *i {
keys.push(index as Key); unsafe {
keys.push(mem::transmute(index));
}
} }
index += 1; index += 1;
@ -283,11 +299,16 @@ impl Window {
pub fn update(&mut self, buffer: &[u32]) -> bool { pub fn update(&mut self, buffer: &[u32]) -> bool {
unsafe { unsafe {
let mut msg = mem::uninitialized(); let mut msg = mem::uninitialized();
let window = self.window.unwrap();
user32::SetWindowLongPtrW(self.window, winapi::winuser::GWLP_USERDATA, self as i64); // TODO: Optimize
user32::InvalidateRect(self.window, ptr::null_mut(), winapi::TRUE);
while user32::PeekMessageW(&mut msg, self.window, 0, 0, winapi::winuser::PM_REMOVE) != 0 { self.buffer = buffer.iter().cloned().collect();
user32::SetWindowLongPtrW(window, winapi::winuser::GWLP_USERDATA, mem::transmute(self));
user32::InvalidateRect(window, ptr::null_mut(), winapi::TRUE);
while user32::PeekMessageW(&mut msg, window, 0, 0, winapi::winuser::PM_REMOVE) != 0 {
user32::TranslateMessage(&mut msg); user32::TranslateMessage(&mut msg);
user32::DispatchMessageW(&mut msg); user32::DispatchMessageW(&mut msg);
} }
@ -302,12 +323,12 @@ impl Window {
impl Drop for Window { impl Drop for Window {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if self.dc.is_valid() { if self.dc.is_some() {
user32::ReleaseDC(self.window, self.dc); user32::ReleaseDC(self.window.unwrap(), self.dc.unwrap());
} }
if self.hwnd.is_valid() { if self.window.is_some() {
user32::CloseWindow(self.hwnd); user32::CloseWindow(self.window.unwrap());
} }
} }
} }