mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2025-01-26 02:36:32 +11:00
Merge branch 'windows-rs' into wip
# Conflicts: # Cargo.toml # README.md # examples/noise.rs # src/lib.rs # src/windows.rs
This commit is contained in:
commit
6c6d611599
5 changed files with 271 additions and 90 deletions
25
Cargo.toml
25
Cargo.toml
|
@ -8,30 +8,9 @@ build = "build.rs"
|
||||||
gcc = "0.3.19"
|
gcc = "0.3.19"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.1.10"
|
libc = "0.2"
|
||||||
user32-sys = "0.1.2"
|
user32-sys = "0.1.2"
|
||||||
winapi = "0.2.4"
|
winapi = "0.2.4"
|
||||||
kernel32-sys = "0.1.4"
|
kernel32-sys = "0.1.4"
|
||||||
gdi32-sys = "0.1.1"
|
gdi32-sys = "0.1.1"
|
||||||
|
time = "0.1.34"
|
||||||
[target.x86_64-apple-darwin.dependencies]
|
|
||||||
objc = "0.1.8"
|
|
||||||
cgl = "0.1"
|
|
||||||
cocoa = "0.1.4"
|
|
||||||
core-foundation = "0"
|
|
||||||
core-graphics = "0"
|
|
||||||
|
|
||||||
[target.i686-pc-windows-gnu.dependencies]
|
|
||||||
winapi = "0.2.4"
|
|
||||||
user32-sys = "0.1.2"
|
|
||||||
kernel32-sys = "0.1.4"
|
|
||||||
gdi32-sys = "0.1.1"
|
|
||||||
|
|
||||||
[target.i686-pc-windows-msvc.dependencies]
|
|
||||||
winapi = "0.2.4"
|
|
||||||
user32-sys = "0.1.2"
|
|
||||||
kernel32-sys = "0.1.4"
|
|
||||||
gdi32-sys = "0.1.1"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
29
README.md
29
README.md
|
@ -7,32 +7,37 @@ rust_minifb (Mini FrameBuffer) is a small cross platform library written in [Rus
|
||||||
```rust
|
```rust
|
||||||
extern crate minifb;
|
extern crate minifb;
|
||||||
|
|
||||||
const WIDTH: usize = 1280;
|
use minifb::*;
|
||||||
const HEIGHT: usize = 720;
|
|
||||||
|
const WIDTH: usize = 640;
|
||||||
|
const HEIGHT: usize = 360;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];
|
let mut buffer: [u32; WIDTH * HEIGHT] = [0; WIDTH * HEIGHT];
|
||||||
|
|
||||||
if !(minifb::open("TestWindow", WIDTH, HEIGHT)) {
|
let mut window = Window::new("Noise Test - Press ESC to exit",
|
||||||
return;
|
WIDTH,
|
||||||
}
|
HEIGHT,
|
||||||
|
Scale::X1,
|
||||||
|
Vsync::No)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
while minifb::update(&buffer) {
|
while window.is_open() && !window.is_key_down(Key::Escape) {
|
||||||
for i in buffer.iter_mut() {
|
for i in buffer.iter_mut() {
|
||||||
*i = ... // write something here
|
*i = 0; // write something more funny here!
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
minifb::close();
|
window.update(&buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Status
|
Status
|
||||||
------
|
------
|
||||||
Currently Mac, Windows and Linux has been tested which are the supported platforms for now.
|
Currently Windows is the supported platform.
|
||||||
|
|
||||||
|
|
||||||
Build instructions
|
Build instruction
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -40,6 +45,6 @@ cargo build
|
||||||
cargo run --example noise
|
cargo run --example noise
|
||||||
```
|
```
|
||||||
|
|
||||||
This will run the [noise example](https://github.com/emoon/rust_minifb/blob/master/examples/noise.rs) which should look something like this (Mac screenshot)
|
This will run the [noise example](https://github.com/emoon/rust_minifb/blob/windows-rs/examples/noise.rs) which should look something like this (Mac screenshot)
|
||||||
|
|
||||||
![mac_screenshot](https://dl.dropboxusercontent.com/u/5205843/rust_minifb/noise_screen.png)
|
![mac_screenshot](https://dl.dropboxusercontent.com/u/5205843/rust_minifb/noise_screen.png)
|
||||||
|
|
|
@ -19,7 +19,7 @@ fn main() {
|
||||||
Vsync::No)
|
Vsync::No)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
while window.update(&buffer) {
|
while window.is_open() && !window.is_key_down(Key::Escape) {
|
||||||
for i in buffer.iter_mut() {
|
for i in buffer.iter_mut() {
|
||||||
noise = seed;
|
noise = seed;
|
||||||
noise >>= 3;
|
noise >>= 3;
|
||||||
|
@ -32,12 +32,17 @@ fn main() {
|
||||||
*i = (noise << 16) | (noise << 8) | noise;
|
*i = (noise << 16) | (noise << 8) | noise;
|
||||||
}
|
}
|
||||||
|
|
||||||
for key in window.get_keys().iter() {
|
window.get_keys_pressed(KeyRepeat::No).map(|keys| {
|
||||||
match *key {
|
for t in keys.iter() {
|
||||||
Key::A => println!("Pressed A"),
|
match *t {
|
||||||
Key::B => println!("Pressed B"),
|
Key::W => println!("holding w!"),
|
||||||
_ => (),
|
Key::T => println!("holding t!"),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
|
||||||
|
window.update(&buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
36
src/lib.rs
36
src/lib.rs
|
@ -12,6 +12,7 @@ extern crate core_foundation;
|
||||||
/// 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
|
||||||
/// much higher resolution which would result in that the window is very small.
|
/// much higher resolution which would result in that the window is very small.
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
pub enum Scale {
|
pub enum Scale {
|
||||||
/// This mode checks your current screen resolution and will caluclate the largest window size
|
/// 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
|
/// that can be used within that limit and resize it. Useful if you have a small buffer to
|
||||||
|
@ -45,6 +46,15 @@ pub enum Vsync {
|
||||||
BestGuess,
|
BestGuess,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used for is_key_pressed and get_keys_pressed() to indicated if repeat of presses is wanted
|
||||||
|
#[derive(PartialEq, Clone, Copy)]
|
||||||
|
pub enum KeyRepeat {
|
||||||
|
/// Use repeat
|
||||||
|
Yes,
|
||||||
|
/// Don't use repeat
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Key {
|
pub enum Key {
|
||||||
Key0 = 0,
|
Key0 = 0,
|
||||||
Key1 = 1,
|
Key1 = 1,
|
||||||
|
@ -105,6 +115,7 @@ pub enum Key {
|
||||||
Right,
|
Right,
|
||||||
Up,
|
Up,
|
||||||
Apostrophe,
|
Apostrophe,
|
||||||
|
Backquote,
|
||||||
|
|
||||||
Backslash,
|
Backslash,
|
||||||
Comma,
|
Comma,
|
||||||
|
@ -133,9 +144,32 @@ pub enum Key {
|
||||||
Pause,
|
Pause,
|
||||||
Space,
|
Space,
|
||||||
Tab,
|
Tab,
|
||||||
|
NumLock,
|
||||||
CapsLock,
|
CapsLock,
|
||||||
|
ScrollLock,
|
||||||
|
LeftShift,
|
||||||
|
RightShift,
|
||||||
|
LeftCtrl,
|
||||||
|
RightCtrl,
|
||||||
|
|
||||||
Count = 80,
|
NumPad0,
|
||||||
|
NumPad1,
|
||||||
|
NumPad2,
|
||||||
|
NumPad3,
|
||||||
|
NumPad4,
|
||||||
|
NumPad5,
|
||||||
|
NumPad6,
|
||||||
|
NumPad7,
|
||||||
|
NumPad8,
|
||||||
|
NumPad9,
|
||||||
|
NumPadDot,
|
||||||
|
NumPadSlash,
|
||||||
|
NumPadAsterisk,
|
||||||
|
NumPadMinus,
|
||||||
|
NumPadPlus,
|
||||||
|
NumPadEnter,
|
||||||
|
|
||||||
|
Count = 103,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
|
252
src/windows.rs
252
src/windows.rs
|
@ -4,12 +4,13 @@ extern crate user32;
|
||||||
extern crate kernel32;
|
extern crate kernel32;
|
||||||
extern crate winapi;
|
extern crate winapi;
|
||||||
extern crate gdi32;
|
extern crate gdi32;
|
||||||
|
extern crate time;
|
||||||
|
|
||||||
use Scale;
|
use Scale;
|
||||||
use Vsync;
|
use Vsync;
|
||||||
use Key;
|
use Key;
|
||||||
|
use KeyRepeat;
|
||||||
|
|
||||||
use std::ffi::CString;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::os::windows::ffi::OsStrExt;
|
use std::os::windows::ffi::OsStrExt;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
@ -22,8 +23,6 @@ use self::winapi::winuser::WNDCLASSW;
|
||||||
use self::winapi::wingdi::BITMAPINFOHEADER;
|
use self::winapi::wingdi::BITMAPINFOHEADER;
|
||||||
use self::winapi::wingdi::RGBQUAD;
|
use self::winapi::wingdi::RGBQUAD;
|
||||||
|
|
||||||
static mut CLOSE_APP: bool = false;
|
|
||||||
|
|
||||||
// Wrap this so we can have a proper numbef of bmiColors to write in
|
// Wrap this so we can have a proper numbef of bmiColors to write in
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct BitmapInfo {
|
struct BitmapInfo {
|
||||||
|
@ -86,6 +85,7 @@ fn update_key_state(window: &mut Window, wparam: u32, state: bool) {
|
||||||
0x14D => window.keys[Key::Right as usize] = state,
|
0x14D => window.keys[Key::Right as usize] = state,
|
||||||
0x148 => window.keys[Key::Up as usize] = state,
|
0x148 => window.keys[Key::Up as usize] = state,
|
||||||
0x028 => window.keys[Key::Apostrophe as usize] = state,
|
0x028 => window.keys[Key::Apostrophe as usize] = state,
|
||||||
|
0x029 => window.keys[Key::Backquote as usize] = state,
|
||||||
0x02B => window.keys[Key::Backslash as usize] = state,
|
0x02B => window.keys[Key::Backslash as usize] = state,
|
||||||
0x033 => window.keys[Key::Comma as usize] = state,
|
0x033 => window.keys[Key::Comma as usize] = state,
|
||||||
0x00D => window.keys[Key::Equal as usize] = state,
|
0x00D => window.keys[Key::Equal as usize] = state,
|
||||||
|
@ -108,7 +108,29 @@ fn update_key_state(window: &mut Window, wparam: u32, state: bool) {
|
||||||
0x045 => window.keys[Key::Pause as usize] = state,
|
0x045 => window.keys[Key::Pause as usize] = state,
|
||||||
0x039 => window.keys[Key::Space as usize] = state,
|
0x039 => window.keys[Key::Space as usize] = state,
|
||||||
0x00F => window.keys[Key::Tab as usize] = state,
|
0x00F => window.keys[Key::Tab as usize] = state,
|
||||||
|
0x145 => window.keys[Key::NumLock as usize] = state,
|
||||||
0x03A => window.keys[Key::CapsLock as usize] = state,
|
0x03A => window.keys[Key::CapsLock as usize] = state,
|
||||||
|
0x046 => window.keys[Key::ScrollLock as usize] = state,
|
||||||
|
0x02A => window.keys[Key::LeftShift as usize] = state,
|
||||||
|
0x036 => window.keys[Key::RightShift as usize] = state,
|
||||||
|
0x01D => window.keys[Key::LeftCtrl as usize] = state,
|
||||||
|
0x11D => window.keys[Key::RightCtrl as usize] = state,
|
||||||
|
0x052 => window.keys[Key::NumPad0 as usize] = state,
|
||||||
|
0x04F => window.keys[Key::NumPad1 as usize] = state,
|
||||||
|
0x050 => window.keys[Key::NumPad2 as usize] = state,
|
||||||
|
0x051 => window.keys[Key::NumPad3 as usize] = state,
|
||||||
|
0x04B => window.keys[Key::NumPad4 as usize] = state,
|
||||||
|
0x04C => window.keys[Key::NumPad5 as usize] = state,
|
||||||
|
0x04D => window.keys[Key::NumPad6 as usize] = state,
|
||||||
|
0x047 => window.keys[Key::NumPad7 as usize] = state,
|
||||||
|
0x048 => window.keys[Key::NumPad8 as usize] = state,
|
||||||
|
0x049 => window.keys[Key::NumPad9 as usize] = state,
|
||||||
|
0x053 => window.keys[Key::NumPadDot as usize] = state,
|
||||||
|
0x135 => window.keys[Key::NumPadSlash as usize] = state,
|
||||||
|
0x037 => window.keys[Key::NumPadAsterisk as usize] = state,
|
||||||
|
0x04A => window.keys[Key::NumPadMinus as usize] = state,
|
||||||
|
0x04E => window.keys[Key::NumPadPlus as usize] = state,
|
||||||
|
0x11C => window.keys[Key::NumPadEnter as usize] = state,
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,30 +155,27 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND,
|
||||||
match msg {
|
match msg {
|
||||||
winapi::winuser::WM_KEYDOWN => {
|
winapi::winuser::WM_KEYDOWN => {
|
||||||
update_key_state(wnd, (lparam as u32) >> 16, true);
|
update_key_state(wnd, (lparam as u32) >> 16, true);
|
||||||
if (wparam & 0x1ff) == 27 {
|
return 0;
|
||||||
CLOSE_APP = true;
|
}
|
||||||
}
|
|
||||||
|
winapi::winuser::WM_CLOSE => {
|
||||||
|
wnd.is_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
winapi::winuser::WM_KEYUP => {
|
winapi::winuser::WM_KEYUP => {
|
||||||
update_key_state(wnd, (lparam as u32) >> 16, false);
|
update_key_state(wnd, (lparam as u32) >> 16, false);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
winapi::winuser::WM_PAINT => {
|
winapi::winuser::WM_PAINT => {
|
||||||
let mut rect: winapi::RECT = mem::uninitialized();
|
|
||||||
|
|
||||||
user32::GetClientRect(window, &mut rect);
|
|
||||||
|
|
||||||
let mut bitmap_info: BitmapInfo = mem::zeroed();
|
let mut bitmap_info: BitmapInfo = mem::zeroed();
|
||||||
let width = rect.right - rect.left;
|
|
||||||
let height = rect.bottom - rect.top;
|
|
||||||
|
|
||||||
bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
|
bitmap_info.bmi_header.biSize = mem::size_of::<BITMAPINFOHEADER>() as u32;
|
||||||
bitmap_info.bmi_header.biPlanes = 1;
|
bitmap_info.bmi_header.biPlanes = 1;
|
||||||
bitmap_info.bmi_header.biBitCount = 32;
|
bitmap_info.bmi_header.biBitCount = 32;
|
||||||
bitmap_info.bmi_header.biCompression = winapi::wingdi::BI_BITFIELDS;
|
bitmap_info.bmi_header.biCompression = winapi::wingdi::BI_BITFIELDS;
|
||||||
bitmap_info.bmi_header.biWidth = width;
|
bitmap_info.bmi_header.biWidth = wnd.width;
|
||||||
bitmap_info.bmi_header.biHeight = -height;
|
bitmap_info.bmi_header.biHeight = -wnd.height;
|
||||||
bitmap_info.bmi_colors[0].rgbRed = 0xff;
|
bitmap_info.bmi_colors[0].rgbRed = 0xff;
|
||||||
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;
|
||||||
|
@ -164,19 +183,22 @@ unsafe extern "system" fn wnd_proc(window: winapi::HWND,
|
||||||
gdi32::StretchDIBits(wnd.dc.unwrap(),
|
gdi32::StretchDIBits(wnd.dc.unwrap(),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
width,
|
wnd.width * wnd.scale_factor,
|
||||||
height,
|
wnd.height * wnd.scale_factor,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
width,
|
wnd.width,
|
||||||
height,
|
wnd.height,
|
||||||
mem::transmute(wnd.buffer.as_ptr()),
|
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);
|
||||||
|
|
||||||
user32::ValidateRect(window, ptr::null_mut());
|
user32::ValidateRect(window, ptr::null_mut());
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,24 +209,32 @@ pub enum MinifbError {
|
||||||
UnableToCreateWindow,
|
UnableToCreateWindow,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_wstring(str: &str) -> *const u16 {
|
fn to_wstring(str: &str) -> Vec<u16> {
|
||||||
let v: Vec<u16> = OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect();
|
let mut v: Vec<u16> = OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect();
|
||||||
v.as_ptr()
|
v.push(0u16);
|
||||||
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
dc: Option<HDC>,
|
dc: Option<HDC>,
|
||||||
window: Option<HWND>,
|
window: Option<HWND>,
|
||||||
keys: [bool; 512],
|
keys: [bool; 512],
|
||||||
|
keys_down_duration: [f32; 512],
|
||||||
buffer: Vec<u32>,
|
buffer: Vec<u32>,
|
||||||
|
is_open : bool,
|
||||||
|
scale_factor: i32,
|
||||||
|
width: i32,
|
||||||
|
height: i32,
|
||||||
|
prev_time: f64,
|
||||||
|
delta_time: f32,
|
||||||
|
key_repeat_delay: f32,
|
||||||
|
key_repeat_rate: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
fn open_window(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> HWND {
|
fn open_window(name: &str, width: usize, height: usize, scale_factor: i32, _: Vsync) -> Option<HWND> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let class_name = to_wstring("minifb_window");
|
let class_name = to_wstring("minifb_window");
|
||||||
let s = CString::new(name).unwrap();
|
|
||||||
|
|
||||||
let class = WNDCLASSW {
|
let class = WNDCLASSW {
|
||||||
style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
|
style: winapi::CS_HREDRAW | winapi::CS_VREDRAW | winapi::CS_OWNDC,
|
||||||
lpfnWndProc: Some(wnd_proc),
|
lpfnWndProc: Some(wnd_proc),
|
||||||
|
@ -215,16 +245,25 @@ impl Window {
|
||||||
hCursor: ptr::null_mut(),
|
hCursor: ptr::null_mut(),
|
||||||
hbrBackground: ptr::null_mut(),
|
hbrBackground: ptr::null_mut(),
|
||||||
lpszMenuName: ptr::null(),
|
lpszMenuName: ptr::null(),
|
||||||
lpszClassName: class_name,
|
lpszClassName: class_name.as_ptr(),
|
||||||
};
|
};
|
||||||
|
|
||||||
user32::RegisterClassW(&class);
|
if user32::RegisterClassW(&class) == 0 {
|
||||||
|
// ignore the "Class already exists" error for multiple windows
|
||||||
|
if kernel32::GetLastError() as u32 != 1410 {
|
||||||
|
println!("Unable to register class, error {}", kernel32::GetLastError() as u32);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_width = width * scale_factor as usize;
|
||||||
|
let new_height = height * scale_factor as usize;
|
||||||
|
|
||||||
let mut rect = winapi::RECT {
|
let mut rect = winapi::RECT {
|
||||||
left: 0,
|
left: 0,
|
||||||
right: width as winapi::LONG,
|
right: new_width as winapi::LONG,
|
||||||
top: 0,
|
top: 0,
|
||||||
bottom: height as winapi::LONG,
|
bottom: new_height as winapi::LONG,
|
||||||
};
|
};
|
||||||
|
|
||||||
user32::AdjustWindowRect(&mut rect,
|
user32::AdjustWindowRect(&mut rect,
|
||||||
|
@ -234,9 +273,11 @@ impl Window {
|
||||||
rect.right -= rect.left;
|
rect.right -= rect.left;
|
||||||
rect.bottom -= rect.top;
|
rect.bottom -= rect.top;
|
||||||
|
|
||||||
let handle = user32::CreateWindowExA(0,
|
let window_name = to_wstring(name);
|
||||||
"minifb_window".as_ptr() as *mut _,
|
|
||||||
s.as_ptr(),
|
let handle = user32::CreateWindowExW(0,
|
||||||
|
class_name.as_ptr(),
|
||||||
|
window_name.as_ptr(),
|
||||||
winapi::WS_OVERLAPPEDWINDOW &
|
winapi::WS_OVERLAPPEDWINDOW &
|
||||||
!winapi::WS_MAXIMIZEBOX &
|
!winapi::WS_MAXIMIZEBOX &
|
||||||
!winapi::WS_THICKFRAME,
|
!winapi::WS_THICKFRAME,
|
||||||
|
@ -248,13 +289,14 @@ impl Window {
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
ptr::null_mut());
|
ptr::null_mut());
|
||||||
|
if handle.is_null() {
|
||||||
if !handle.is_null() {
|
println!("Unable to create window, error {}", kernel32::GetLastError() as u32);
|
||||||
user32::ShowWindow(handle, winapi::SW_NORMAL);
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
user32::ShowWindow(handle, winapi::SW_NORMAL);
|
||||||
|
|
||||||
return handle;
|
return Some(handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,45 +307,133 @@ impl Window {
|
||||||
vsync: Vsync)
|
vsync: Vsync)
|
||||||
-> Result<Window, &str> {
|
-> Result<Window, &str> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let handle = Self::open_window(name, width, height, scale, vsync);
|
let scale_factor = Self::get_scale_factor(width, height, scale);
|
||||||
|
|
||||||
if handle.is_null() {
|
let handle = Self::open_window(name, width, height, scale_factor, vsync);
|
||||||
|
|
||||||
|
if handle.is_none() {
|
||||||
return Err("Unable to create Window");
|
return Err("Unable to create Window");
|
||||||
}
|
}
|
||||||
|
|
||||||
let window = Window {
|
let window = Window {
|
||||||
dc: Some(user32::GetDC(handle)),
|
dc: Some(user32::GetDC(handle.unwrap())),
|
||||||
window: Some(handle),
|
window: Some(handle.unwrap()),
|
||||||
keys: [false; 512],
|
keys: [false; 512],
|
||||||
|
keys_down_duration: [-1.0; 512],
|
||||||
|
prev_time: time::precise_time_s(),
|
||||||
|
delta_time: 0.0,
|
||||||
|
key_repeat_delay: 0.250,
|
||||||
|
key_repeat_rate: 0.050,
|
||||||
buffer: Vec::new(),
|
buffer: Vec::new(),
|
||||||
|
is_open: true,
|
||||||
|
scale_factor: scale_factor,
|
||||||
|
width: width as i32,
|
||||||
|
height: height as i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(window)
|
Ok(window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_keys(&self) -> Vec<Key> {
|
pub fn get_keys(&self) -> Option<Vec<Key>> {
|
||||||
let mut index: u8 = 0;
|
let mut index: u16 = 0;
|
||||||
let mut keys: Vec<Key> = Vec::new();
|
let mut keys: Vec<Key> = Vec::new();
|
||||||
|
|
||||||
for i in self.keys.iter() {
|
for i in self.keys.iter() {
|
||||||
if *i {
|
if *i {
|
||||||
unsafe {
|
unsafe {
|
||||||
keys.push(mem::transmute(index));
|
keys.push(mem::transmute(index as u8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
keys
|
Some(keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, buffer: &[u32]) -> bool {
|
pub fn get_keys_pressed(&self, repeat: KeyRepeat) -> Option<Vec<Key>> {
|
||||||
|
let mut index: u16 = 0;
|
||||||
|
let mut keys: Vec<Key> = Vec::new();
|
||||||
|
|
||||||
|
for i in self.keys.iter() {
|
||||||
|
if *i {
|
||||||
|
unsafe {
|
||||||
|
if Self::key_pressed(self, index as usize, repeat) {
|
||||||
|
keys.push(mem::transmute(index as u8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_key_down(&self, key: Key) -> bool {
|
||||||
|
return self.keys[key as usize];
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_key_repeat_delay(&mut self, delay: f32) {
|
||||||
|
self.key_repeat_delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn set_key_repeat_rate(&mut self, rate: f32) {
|
||||||
|
self.key_repeat_rate = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn key_pressed(&self, index: usize, repeat: KeyRepeat) -> bool {
|
||||||
|
let t = self.keys_down_duration[index];
|
||||||
|
|
||||||
|
if t == 0.0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if repeat == KeyRepeat::Yes && t > self.key_repeat_delay {
|
||||||
|
let delay = self.key_repeat_delay;
|
||||||
|
let rate = self.key_repeat_rate;
|
||||||
|
if ((((t - delay) % rate) > rate * 0.5)) != (((t - delay - self.delta_time) % rate) > rate * 0.5) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_key_pressed(&self, key: Key, repeat: KeyRepeat) -> bool {
|
||||||
|
return Self::key_pressed(self, key as usize, repeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_open(&self) -> bool {
|
||||||
|
return self.is_open
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, buffer: &[u32]) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut msg = mem::uninitialized();
|
let mut msg = mem::uninitialized();
|
||||||
let window = self.window.unwrap();
|
let window = self.window.unwrap();
|
||||||
|
|
||||||
|
let current_time = time::precise_time_s();
|
||||||
|
let delta_time = (current_time - self.prev_time) as f32;
|
||||||
|
self.prev_time = current_time;
|
||||||
|
self.delta_time = delta_time;
|
||||||
|
|
||||||
|
for i in 0..self.keys.len() {
|
||||||
|
if self.keys[i] {
|
||||||
|
if self.keys_down_duration[i] < 0.0 {
|
||||||
|
self.keys_down_duration[i] = 0.0;
|
||||||
|
} else {
|
||||||
|
self.keys_down_duration[i] += delta_time;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.keys_down_duration[i] = -1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Optimize
|
// TODO: Optimize
|
||||||
|
|
||||||
self.buffer = buffer.iter().cloned().collect();
|
self.buffer = buffer.iter().cloned().collect();
|
||||||
|
@ -316,10 +446,38 @@ impl Window {
|
||||||
user32::DispatchMessageW(&mut msg);
|
user32::DispatchMessageW(&mut msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe fn get_scale_factor(width: usize, height: usize, scale: Scale) -> i32 {
|
||||||
return !CLOSE_APP;
|
let factor: i32 = match scale {
|
||||||
}
|
Scale::X1 => 1,
|
||||||
|
Scale::X2 => 2,
|
||||||
|
Scale::X4 => 4,
|
||||||
|
Scale::X8 => 8,
|
||||||
|
Scale::X16 => 16,
|
||||||
|
Scale::X32 => 32,
|
||||||
|
Scale::FitScreen => {
|
||||||
|
let screen_x = user32::GetSystemMetrics(winapi::winuser::SM_CXSCREEN) as i32;
|
||||||
|
let screen_y = user32::GetSystemMetrics(winapi::winuser::SM_CYSCREEN) as i32;
|
||||||
|
|
||||||
|
let mut scale = 1i32;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let w = width as i32 * (scale + 1);
|
||||||
|
let h = height as i32 * (scale + 1);
|
||||||
|
|
||||||
|
if w > screen_x || h > screen_y {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
scale
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return factor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue