Refresh the repo
This commit is contained in:
355
modules/win32_multimedia.core
Normal file
355
modules/win32_multimedia.core
Normal file
@@ -0,0 +1,355 @@
|
||||
#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)->int
|
||||
result.y = (window_rect.bottom - window_rect.top)->int
|
||||
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: int = 1280, y: int = 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*/
|
||||
Reference in New Issue
Block a user