355 lines
9.9 KiB
Core
355 lines
9.9 KiB
Core
#import "KERNEL32.core"
|
|
#import "GDI32.core"
|
|
#import "USER32.core"
|
|
#import "WINMM.core"
|
|
#import "OS$OS.core"
|
|
|
|
Platform :: struct
|
|
bitmap: WIN32_Bitmap
|
|
window_dc: HDC
|
|
window: HWND
|
|
good_scheduling: bool
|
|
|
|
WIN32_Bitmap :: struct
|
|
size: Vec2I
|
|
data: *U32
|
|
hdc: HDC
|
|
dib: HBITMAP
|
|
compatible_dc: HDC
|
|
|
|
IsValidBitmap :: (b: *WIN32_Bitmap): bool
|
|
result := b.data != 0
|
|
return result
|
|
|
|
CreateBitmap :: (for_dc: HDC, size: Vec2I, bottom_up: bool = true): WIN32_Bitmap
|
|
result: WIN32_Bitmap = {size = size}
|
|
if bottom_up == false
|
|
result.size.y = -result.size.y
|
|
|
|
header_size: U32 = sizeof(BITMAPINFOHEADER)
|
|
Assert(header_size == 40)
|
|
bminfo := BITMAPINFO{
|
|
BITMAPINFOHEADER{
|
|
biSize = header_size,
|
|
biWidth = size.x->LONG,
|
|
biHeight = size.y->LONG,
|
|
biPlanes = 1,
|
|
biBitCount = 32,
|
|
biCompression = BI_RGB,
|
|
biXPelsPerMeter = 1,
|
|
biYPelsPerMeter = 1,
|
|
}
|
|
}
|
|
|
|
result.dib = CreateDIBSection(for_dc, &bminfo, DIB_RGB_COLORS, (&result.data)->**void, 0, 0)
|
|
result.hdc = CreateCompatibleDC(for_dc)
|
|
result.compatible_dc = for_dc
|
|
return result
|
|
|
|
DestroyBitmap :: (b: *WIN32_Bitmap)
|
|
if IsValidBitmap(b)
|
|
DeleteDC(b.hdc)
|
|
DeleteObject(b.dib)
|
|
ZeroMemory(b, sizeof(WIN32_Bitmap))
|
|
|
|
DrawBitmapInCompatibleDC :: (b: *WIN32_Bitmap)
|
|
if IsValidBitmap(b)
|
|
SelectObject(b.hdc, b.dib)
|
|
BitBlt(b.compatible_dc, 0, 0, b.size.x->int, b.size.y->int, b.hdc, 0, 0, SRCCOPY)
|
|
|
|
GetWindowStyle :: (resizable: bool): DWORD
|
|
style: DWORD = WS_SYSMENU | WS_OVERLAPPED | WS_CAPTION
|
|
if resizable ;; style |= WS_MAXIMIZEBOX | WS_THICKFRAME | WS_MINIMIZEBOX
|
|
return style
|
|
|
|
GetWindowSize :: (window: HWND): Vec2I
|
|
result: Vec2I
|
|
window_rect: RECT
|
|
GetClientRect(window, &window_rect)
|
|
result.x = (window_rect.right - window_rect.left)->S64
|
|
result.y = (window_rect.bottom - window_rect.top)->S64
|
|
return result
|
|
|
|
GetWindowPos :: (window: HWND): Vec2I
|
|
pos: Point
|
|
ClientToScreen(window, &pos)
|
|
return {pos.x, pos.y}
|
|
|
|
AdjustWindowRect :: (window: HWND, style: DWORD, rect: *RECT): void
|
|
FALSE :: 0
|
|
// if window == 0
|
|
// dpi := GetDpiForWindow(window)
|
|
// AdjustWindowRectExForDpi(rect, style, FALSE, 0, dpi)
|
|
// else
|
|
AdjustWindowRectEx(rect, style, FALSE, 0)
|
|
|
|
SetWindowSize :: (window: HWND, style: DWORD, size: Vec2I): void
|
|
rect := RECT{ 0, 0, size.x->LONG, size.y->LONG }
|
|
AdjustWindowRect(window, style, &rect)
|
|
SetWindowPos(window, HWND_TOP, 0, 0, (rect.right - rect.left)->int, (rect.bottom - rect.top)->int, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER)
|
|
|
|
SetWindowPosition :: (window: HWND, style: DWORD, pos: Vec2I): void
|
|
rect := RECT{ pos.x->LONG, pos.y->LONG, pos.x->LONG, pos.y->LONG }
|
|
AdjustWindowRect(window, style, &rect)
|
|
SetWindowPos(window, 0, rect.left, rect.top, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE)
|
|
|
|
StartMultimedia :: (
|
|
x: S64 = 1280, y: S64 = 720,
|
|
title: String = "Hello people!",
|
|
window_resizable: bool = false,
|
|
target_ms: F64 = 0.0166666
|
|
)
|
|
Mu.time.delta = target_ms
|
|
if timeBeginPeriod(1) == TIMERR_NOERROR
|
|
Mu.os.good_scheduling = true
|
|
|
|
dpi_aware := SetProcessDPIAware()
|
|
Assert(dpi_aware != 0)
|
|
|
|
Mu.time.start = Time()
|
|
|
|
hInstance := GetModuleHandleA(0)
|
|
window_name := StringToString16(&Mu.frame_arena, title)
|
|
w := WNDCLASSW{
|
|
lpfnWndProc = WindowProc,
|
|
hInstance = hInstance,
|
|
lpszClassName = window_name.str,
|
|
// style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW,
|
|
}
|
|
Assert(RegisterClassW(&w) != 0)
|
|
|
|
style: DWORD = GetWindowStyle(window_resizable)
|
|
Mu.os.window = CreateWindowExW(
|
|
dwExStyle = 0, hWndParent = 0, hMenu = 0, lpParam = 0,
|
|
X = CW_USEDEFAULT, Y = CW_USEDEFAULT, nWidth = x->int, nHeight = y->int,
|
|
lpClassName = window_name.str,
|
|
lpWindowName = window_name.str,
|
|
dwStyle = style,
|
|
hInstance = hInstance
|
|
)
|
|
Assert(Mu.os.window != 0)
|
|
SetWindowSize(Mu.os.window, style, {x,y})
|
|
ShowWindow(Mu.os.window, SW_SHOW)
|
|
|
|
size := GetWindowSize(Mu.os.window)
|
|
Assert(size.x == x && size.y == y)
|
|
|
|
Mu.os.window_dc = GetDC(Mu.os.window)
|
|
Mu.os.bitmap = CreateBitmap(Mu.os.window_dc, size)
|
|
|
|
Mu.window.resizable = window_resizable
|
|
Mu.screen = Mu.os.bitmap.data
|
|
Mu.window.x = size.x
|
|
Mu.window.y = size.y
|
|
Mu.window.size = size
|
|
Mu.window.sizef.x = Mu.window.x->F32
|
|
Mu.window.sizef.y = Mu.window.y->F32
|
|
|
|
UpdateMultimedia :: (): bool
|
|
DrawBitmapInCompatibleDC(&Mu.os.bitmap)
|
|
|
|
msg: MSG
|
|
for PeekMessageW(&msg, Mu.os.window, 0, 0, PM_REMOVE) == 1
|
|
TranslateMessage(&msg)
|
|
DispatchMessageW(&msg)
|
|
|
|
size := GetWindowSize(Mu.os.window)
|
|
if size.x != Mu.window.x || size.y != Mu.window.y
|
|
DestroyBitmap(&Mu.os.bitmap)
|
|
Mu.os.bitmap = CreateBitmap(Mu.os.window_dc, size)
|
|
|
|
Mu.screen = Mu.os.bitmap.data
|
|
Mu.window.x = size.x
|
|
Mu.window.y = size.y
|
|
Mu.window.sizef.x = Mu.window.x->F32
|
|
Mu.window.sizef.y = Mu.window.y->F32
|
|
Mu.window.size = size
|
|
|
|
|
|
Mu.frame_count += 1
|
|
frame_time := Time() - Mu.time.frame_start
|
|
Mu.time.total += frame_time
|
|
if frame_time < Mu.time.delta
|
|
if Mu.os.good_scheduling
|
|
time_to_sleep := (Mu.time.delta - frame_time) * 1000
|
|
if time_to_sleep > 0
|
|
time_to_sleep_dword := time_to_sleep->DWORD
|
|
// @check if time_to_sleep_dword truncates down
|
|
Sleep(time_to_sleep_dword)
|
|
|
|
new_frame_time := Time()
|
|
for new_frame_time < Mu.time.delta
|
|
new_frame_time = Time() - Mu.time.frame_start
|
|
|
|
Mu.time.frame_start = Time()
|
|
return !Mu.quit
|
|
|
|
WindowProc :: (hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM): LRESULT
|
|
result: LRESULT
|
|
if msg == WM_DESTROY
|
|
// @todo: Add destroy window
|
|
PostQuitMessage(0)
|
|
return 0
|
|
elif msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN
|
|
key := MapVKToKey(wparam)
|
|
Mu.key[key].down = true
|
|
elif msg == WM_KEYUP || msg == WM_SYSKEYUP
|
|
key := MapVKToKey(wparam)
|
|
Mu.key[key].down = false
|
|
elif msg == WM_LBUTTONDOWN ;; Mu.mouse.left.down = true
|
|
elif msg == WM_LBUTTONUP ;; Mu.mouse.left.down = false
|
|
elif msg == WM_RBUTTONDOWN ;; Mu.mouse.right.down = true
|
|
elif msg == WM_RBUTTONUP ;; Mu.mouse.right.down = false
|
|
elif msg == WM_MBUTTONDOWN ;; Mu.mouse.middle.down = true
|
|
elif msg == WM_MBUTTONUP ;; Mu.mouse.middle.down = false
|
|
elif msg == WM_MOUSEWHEEL
|
|
if wparam->int > 0
|
|
Mu.mouse.wheel = 1
|
|
else
|
|
Mu.mouse.wheel = -1
|
|
// Case(WM_CHAR){
|
|
// Utf32Result utf32 = Utf16ToUtf32((u16 *)&wparam, 1);
|
|
// if(!utf32.error){
|
|
// int index = OS->input_count;
|
|
// OS->input_count = ClampTop(OS->input_count + 1, (int)(ArrayCount(OS->input) - 1));
|
|
// OS->input[index] = utf32.out_str;
|
|
// }
|
|
// }Break;
|
|
|
|
|
|
else;; result = DefWindowProcW(hwnd, msg, wparam, lparam)
|
|
|
|
return result
|
|
|
|
|
|
/*#
|
|
mapping = [
|
|
["Up", "VK_UP"],
|
|
["Down", "VK_DOWN"],
|
|
["Left", "VK_LEFT"],
|
|
["Right", "VK_RIGHT"],
|
|
["Escape", "VK_ESCAPE"],
|
|
["Control", "VK_CONTROL"],
|
|
["Backspace", "VK_BACK"],
|
|
["Alt", "VK_MENU"],
|
|
["Shift", "VK_SHIFT"],
|
|
["Tab", "VK_TAB"],
|
|
["F1", "VK_F1"],
|
|
["F2", "VK_F2"],
|
|
["F3", "VK_F3"],
|
|
["F4", "VK_F4"],
|
|
["F5", "VK_F5"],
|
|
["F6", "VK_F6"],
|
|
["F7", "VK_F7"],
|
|
["F8", "VK_F8"],
|
|
["F9", "VK_F9"],
|
|
["F10", "VK_F10"],
|
|
["F11", "VK_F11"],
|
|
["F12", "VK_F12"],
|
|
["A", "'A'"],
|
|
["B", "'B'"],
|
|
["C", "'C'"],
|
|
["D", "'D'"],
|
|
["E", "'E'"],
|
|
["F", "'F'"],
|
|
["G", "'G'"],
|
|
["H", "'H'"],
|
|
["I", "'I'"],
|
|
["J", "'J'"],
|
|
["K", "'K'"],
|
|
["L", "'L'"],
|
|
["M", "'M'"],
|
|
["N", "'N'"],
|
|
["O", "'O'"],
|
|
["P", "'P'"],
|
|
["Q", "'Q'"],
|
|
["R", "'R'"],
|
|
["S", "'S'"],
|
|
["T", "'T'"],
|
|
["U", "'U'"],
|
|
["V", "'V'"],
|
|
["W", "'W'"],
|
|
["X", "'X'"],
|
|
["Y", "'Y'"],
|
|
["Z", "'Z'"],
|
|
["K0", "'0'"],
|
|
["K1", "'1'"],
|
|
["K2", "'2'"],
|
|
["K3", "'3'"],
|
|
["K4", "'4'"],
|
|
["K5", "'5'"],
|
|
["K6", "'6'"],
|
|
["K7", "'7'"],
|
|
["K8", "'8'"],
|
|
["K9", "'9'"],
|
|
]
|
|
|
|
|
|
print("MapVKToKey :: (vk: WPARAM): Key")
|
|
el = ""
|
|
for val,map in mapping:
|
|
print(f" {el}if vk == {map} ;; return Key.{val}")
|
|
el = "el"
|
|
print(" return Key.None")
|
|
*/
|
|
MapVKToKey :: (vk: WPARAM): Key
|
|
if vk == VK_UP ;; return Key.Up
|
|
elif vk == VK_DOWN ;; return Key.Down
|
|
elif vk == VK_LEFT ;; return Key.Left
|
|
elif vk == VK_RIGHT ;; return Key.Right
|
|
elif vk == VK_ESCAPE ;; return Key.Escape
|
|
elif vk == VK_CONTROL ;; return Key.Control
|
|
elif vk == VK_BACK ;; return Key.Backspace
|
|
elif vk == VK_MENU ;; return Key.Alt
|
|
elif vk == VK_SHIFT ;; return Key.Shift
|
|
elif vk == VK_TAB ;; return Key.Tab
|
|
elif vk == VK_F1 ;; return Key.F1
|
|
elif vk == VK_F2 ;; return Key.F2
|
|
elif vk == VK_F3 ;; return Key.F3
|
|
elif vk == VK_F4 ;; return Key.F4
|
|
elif vk == VK_F5 ;; return Key.F5
|
|
elif vk == VK_F6 ;; return Key.F6
|
|
elif vk == VK_F7 ;; return Key.F7
|
|
elif vk == VK_F8 ;; return Key.F8
|
|
elif vk == VK_F9 ;; return Key.F9
|
|
elif vk == VK_F10 ;; return Key.F10
|
|
elif vk == VK_F11 ;; return Key.F11
|
|
elif vk == VK_F12 ;; return Key.F12
|
|
elif vk == 'A' ;; return Key.A
|
|
elif vk == 'B' ;; return Key.B
|
|
elif vk == 'C' ;; return Key.C
|
|
elif vk == 'D' ;; return Key.D
|
|
elif vk == 'E' ;; return Key.E
|
|
elif vk == 'F' ;; return Key.F
|
|
elif vk == 'G' ;; return Key.G
|
|
elif vk == 'H' ;; return Key.H
|
|
elif vk == 'I' ;; return Key.I
|
|
elif vk == 'J' ;; return Key.J
|
|
elif vk == 'K' ;; return Key.K
|
|
elif vk == 'L' ;; return Key.L
|
|
elif vk == 'M' ;; return Key.M
|
|
elif vk == 'N' ;; return Key.N
|
|
elif vk == 'O' ;; return Key.O
|
|
elif vk == 'P' ;; return Key.P
|
|
elif vk == 'Q' ;; return Key.Q
|
|
elif vk == 'R' ;; return Key.R
|
|
elif vk == 'S' ;; return Key.S
|
|
elif vk == 'T' ;; return Key.T
|
|
elif vk == 'U' ;; return Key.U
|
|
elif vk == 'V' ;; return Key.V
|
|
elif vk == 'W' ;; return Key.W
|
|
elif vk == 'X' ;; return Key.X
|
|
elif vk == 'Y' ;; return Key.Y
|
|
elif vk == 'Z' ;; return Key.Z
|
|
elif vk == '0' ;; return Key.K0
|
|
elif vk == '1' ;; return Key.K1
|
|
elif vk == '2' ;; return Key.K2
|
|
elif vk == '3' ;; return Key.K3
|
|
elif vk == '4' ;; return Key.K4
|
|
elif vk == '5' ;; return Key.K5
|
|
elif vk == '6' ;; return Key.K6
|
|
elif vk == '7' ;; return Key.K7
|
|
elif vk == '8' ;; return Key.K8
|
|
elif vk == '9' ;; return Key.K9
|
|
return Key.None
|
|
/*END*/ |