Files
corelang/modules/win32_multimedia.core
2022-10-14 17:20:46 +02:00

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*/