jai port :D
This commit is contained in:
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct PlatformWindow;
|
||||
|
||||
struct PlatformWindowDesc {
|
||||
const char *title = "autosample";
|
||||
int32_t width = 1280;
|
||||
int32_t height = 720;
|
||||
};
|
||||
|
||||
struct PlatformMenuItem {
|
||||
const char *label; // nullptr = separator
|
||||
int32_t id; // command ID (ignored for separators)
|
||||
};
|
||||
|
||||
struct PlatformMenu {
|
||||
const char *label;
|
||||
PlatformMenuItem *items;
|
||||
int32_t item_count;
|
||||
};
|
||||
|
||||
PlatformWindow *platform_create_window(PlatformWindowDesc *desc);
|
||||
void platform_destroy_window(PlatformWindow *window);
|
||||
bool platform_poll_events(PlatformWindow *window);
|
||||
void platform_get_size(PlatformWindow *window, int32_t *w, int32_t *h);
|
||||
void *platform_get_native_handle(PlatformWindow *window);
|
||||
|
||||
void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count);
|
||||
int32_t platform_poll_menu_command(PlatformWindow *window);
|
||||
139
src/platform/platform.jai
Normal file
139
src/platform/platform.jai
Normal file
@@ -0,0 +1,139 @@
|
||||
// autosample — Win32 platform layer
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Missing Win32 declarations
|
||||
// -------------------------------------------------------------------
|
||||
CS_CLASSDC :: 0x0040;
|
||||
|
||||
user32 :: #library,system "user32";
|
||||
|
||||
CreateMenu :: () -> HMENU #foreign user32;
|
||||
CreatePopupMenu :: () -> HMENU #foreign user32;
|
||||
AppendMenuW :: (hMenu: HMENU, uFlags: u32, uIDNewItem: u64, lpNewItem: *u16) -> s32 #foreign user32;
|
||||
SetMenu :: (hWnd: HWND, hMenu: HMENU) -> s32 #foreign user32;
|
||||
|
||||
MF_STRING :: 0x0000;
|
||||
MF_SEPARATOR :: 0x0800;
|
||||
MF_POPUP :: 0x0010;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Platform state
|
||||
// -------------------------------------------------------------------
|
||||
hwnd: HWND;
|
||||
w_width: u32 = 1280;
|
||||
w_height: u32 = 800;
|
||||
|
||||
pending_menu_cmd: s32;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// WndProc
|
||||
// -------------------------------------------------------------------
|
||||
my_wndproc :: (window_hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #c_call {
|
||||
// Forward to ImGui
|
||||
result := ImGui.ImplWin32_WndProcHandler(window_hwnd, msg, wparam, lparam);
|
||||
if result return result;
|
||||
|
||||
if msg == {
|
||||
case WM_SIZE;
|
||||
if wparam != SIZE_MINIMIZED {
|
||||
w_width = cast(u32) (lparam & 0xFFFF);
|
||||
w_height = cast(u32) ((lparam >> 16) & 0xFFFF);
|
||||
}
|
||||
return 0;
|
||||
case WM_COMMAND;
|
||||
if (wparam >> 16) == 0 // HIWORD == 0 means menu
|
||||
pending_menu_cmd = cast(s32) (wparam & 0xFFFF);
|
||||
return 0;
|
||||
case WM_SYSCOMMAND;
|
||||
if (wparam & 0xfff0) == SC_KEYMENU return 0;
|
||||
case WM_DESTROY;
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProcW(window_hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Native Win32 Menus
|
||||
// -------------------------------------------------------------------
|
||||
menu_bar_handle: HMENU;
|
||||
|
||||
setup_menus :: () {
|
||||
menu_bar_handle = CreateMenu();
|
||||
|
||||
// File menu
|
||||
file_menu := CreatePopupMenu();
|
||||
AppendMenuW(file_menu, MF_STRING, xx MENU_FILE_NEW, utf8_to_wide("New"));
|
||||
AppendMenuW(file_menu, MF_STRING, xx MENU_FILE_OPEN, utf8_to_wide("Open..."));
|
||||
AppendMenuW(file_menu, MF_STRING, xx MENU_FILE_SAVE, utf8_to_wide("Save"));
|
||||
AppendMenuW(file_menu, MF_STRING, xx MENU_FILE_SAVE_AS, utf8_to_wide("Save As..."));
|
||||
AppendMenuW(file_menu, MF_SEPARATOR, 0, null);
|
||||
AppendMenuW(file_menu, MF_STRING, xx MENU_FILE_EXIT, utf8_to_wide("Exit"));
|
||||
AppendMenuW(menu_bar_handle, MF_POPUP, xx file_menu, utf8_to_wide("File"));
|
||||
|
||||
// Import menu
|
||||
import_menu := CreatePopupMenu();
|
||||
AppendMenuW(import_menu, MF_STRING, xx MENU_IMPORT_AUDIO, utf8_to_wide("Audio..."));
|
||||
AppendMenuW(import_menu, MF_STRING, xx MENU_IMPORT_MIDI, utf8_to_wide("MIDI..."));
|
||||
AppendMenuW(menu_bar_handle, MF_POPUP, xx import_menu, utf8_to_wide("Import"));
|
||||
|
||||
// View menu
|
||||
view_menu := CreatePopupMenu();
|
||||
AppendMenuW(view_menu, MF_STRING, xx MENU_VIEW_BROWSER, utf8_to_wide("Browser"));
|
||||
AppendMenuW(view_menu, MF_STRING, xx MENU_VIEW_PROPERTIES, utf8_to_wide("Properties"));
|
||||
AppendMenuW(view_menu, MF_STRING, xx MENU_VIEW_LOG, utf8_to_wide("Log"));
|
||||
AppendMenuW(view_menu, MF_SEPARATOR, 0, null);
|
||||
AppendMenuW(view_menu, MF_STRING, xx MENU_VIEW_DEMO, utf8_to_wide("Demo"));
|
||||
AppendMenuW(menu_bar_handle, MF_POPUP, xx view_menu, utf8_to_wide("View"));
|
||||
|
||||
SetMenu(hwnd, menu_bar_handle);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Platform Init / Shutdown
|
||||
// -------------------------------------------------------------------
|
||||
platform_init :: () -> bool {
|
||||
wc: WNDCLASSEXW;
|
||||
wc.cbSize = size_of(WNDCLASSEXW);
|
||||
wc.style = CS_CLASSDC;
|
||||
wc.lpfnWndProc = xx my_wndproc;
|
||||
wc.hInstance = GetModuleHandleW(null);
|
||||
wc.lpszClassName = utf8_to_wide("autosample_wc");
|
||||
RegisterClassExW(*wc);
|
||||
|
||||
screen_w := GetSystemMetrics(SM_CXSCREEN);
|
||||
screen_h := GetSystemMetrics(SM_CYSCREEN);
|
||||
x := (screen_w - cast(s32) w_width) / 2;
|
||||
y := (screen_h - cast(s32) w_height) / 2;
|
||||
|
||||
rect: RECT;
|
||||
rect.right = cast(s32) w_width;
|
||||
rect.bottom = cast(s32) w_height;
|
||||
AdjustWindowRect(*rect, WS_OVERLAPPEDWINDOW, 0);
|
||||
|
||||
hwnd = CreateWindowExW(
|
||||
0,
|
||||
wc.lpszClassName,
|
||||
utf8_to_wide("autosample"),
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
x, y,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
null, null, wc.hInstance, null
|
||||
);
|
||||
|
||||
if !hwnd {
|
||||
print("CreateWindowExW failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ShowWindow(hwnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hwnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
platform_shutdown :: () {
|
||||
DestroyWindow(hwnd);
|
||||
UnregisterClassW(utf8_to_wide("autosample_wc"), GetModuleHandleW(null));
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
#include "platform/platform.h"
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "imgui_impl_win32.h"
|
||||
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
struct PlatformWindow {
|
||||
HWND hwnd;
|
||||
bool should_close;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t pending_menu_cmd;
|
||||
};
|
||||
|
||||
static PlatformWindow *g_current_window = nullptr;
|
||||
|
||||
static LRESULT CALLBACK win32_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
if (ImGui_ImplWin32_WndProcHandler(hwnd, msg, wparam, lparam))
|
||||
return true;
|
||||
|
||||
switch (msg) {
|
||||
case WM_SIZE:
|
||||
if (g_current_window && wparam != SIZE_MINIMIZED) {
|
||||
g_current_window->width = (int32_t)LOWORD(lparam);
|
||||
g_current_window->height = (int32_t)HIWORD(lparam);
|
||||
}
|
||||
return 0;
|
||||
case WM_COMMAND:
|
||||
if (g_current_window && HIWORD(wparam) == 0)
|
||||
g_current_window->pending_menu_cmd = (int32_t)LOWORD(wparam);
|
||||
return 0;
|
||||
case WM_CLOSE:
|
||||
if (g_current_window)
|
||||
g_current_window->should_close = true;
|
||||
return 0;
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
case WM_SYSCOMMAND:
|
||||
if ((wparam & 0xfff0) == SC_KEYMENU)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
return DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
PlatformWindow *platform_create_window(PlatformWindowDesc *desc)
|
||||
{
|
||||
WNDCLASSEXW wc = {};
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.style = CS_CLASSDC;
|
||||
wc.lpfnWndProc = win32_wndproc;
|
||||
wc.hInstance = GetModuleHandleW(nullptr);
|
||||
wc.lpszClassName = L"autosample_wc";
|
||||
RegisterClassExW(&wc);
|
||||
|
||||
int screen_w = GetSystemMetrics(SM_CXSCREEN);
|
||||
int screen_h = GetSystemMetrics(SM_CYSCREEN);
|
||||
int x = (screen_w - desc->width) / 2;
|
||||
int y = (screen_h - desc->height) / 2;
|
||||
|
||||
RECT rect = { 0, 0, (LONG)desc->width, (LONG)desc->height };
|
||||
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
|
||||
|
||||
int wchar_count = MultiByteToWideChar(CP_UTF8, 0, desc->title, -1, nullptr, 0);
|
||||
wchar_t *wtitle = (wchar_t *)_malloca(wchar_count * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, desc->title, -1, wtitle, wchar_count);
|
||||
|
||||
HWND hwnd = CreateWindowExW(
|
||||
0, wc.lpszClassName, wtitle,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
x, y,
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
nullptr, nullptr, wc.hInstance, nullptr
|
||||
);
|
||||
|
||||
_freea(wtitle);
|
||||
|
||||
if (!hwnd)
|
||||
return nullptr;
|
||||
|
||||
ShowWindow(hwnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hwnd);
|
||||
|
||||
PlatformWindow *window = new PlatformWindow();
|
||||
window->hwnd = hwnd;
|
||||
window->should_close = false;
|
||||
window->width = desc->width;
|
||||
window->height = desc->height;
|
||||
|
||||
g_current_window = window;
|
||||
return window;
|
||||
}
|
||||
|
||||
void platform_destroy_window(PlatformWindow *window)
|
||||
{
|
||||
if (!window) return;
|
||||
|
||||
if (window->hwnd) {
|
||||
DestroyWindow(window->hwnd);
|
||||
UnregisterClassW(L"autosample_wc", GetModuleHandleW(nullptr));
|
||||
}
|
||||
|
||||
if (g_current_window == window)
|
||||
g_current_window = nullptr;
|
||||
|
||||
delete window;
|
||||
}
|
||||
|
||||
bool platform_poll_events(PlatformWindow *window)
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
if (msg.message == WM_QUIT) {
|
||||
window->should_close = true;
|
||||
}
|
||||
}
|
||||
return !window->should_close;
|
||||
}
|
||||
|
||||
void platform_get_size(PlatformWindow *window, int32_t *w, int32_t *h)
|
||||
{
|
||||
if (w) *w = window->width;
|
||||
if (h) *h = window->height;
|
||||
}
|
||||
|
||||
void *platform_get_native_handle(PlatformWindow *window)
|
||||
{
|
||||
return (void *)window->hwnd;
|
||||
}
|
||||
|
||||
void platform_set_menu(PlatformWindow *window, PlatformMenu *menus, int32_t menu_count)
|
||||
{
|
||||
HMENU menu_bar = CreateMenu();
|
||||
|
||||
for (int32_t i = 0; i < menu_count; i++) {
|
||||
HMENU submenu = CreatePopupMenu();
|
||||
|
||||
for (int32_t j = 0; j < menus[i].item_count; j++) {
|
||||
PlatformMenuItem *item = &menus[i].items[j];
|
||||
if (!item->label) {
|
||||
AppendMenuW(submenu, MF_SEPARATOR, 0, nullptr);
|
||||
} else {
|
||||
int wchar_count = MultiByteToWideChar(CP_UTF8, 0, item->label, -1, nullptr, 0);
|
||||
wchar_t *wlabel = (wchar_t *)_malloca(wchar_count * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, item->label, -1, wlabel, wchar_count);
|
||||
AppendMenuW(submenu, MF_STRING, (UINT_PTR)item->id, wlabel);
|
||||
_freea(wlabel);
|
||||
}
|
||||
}
|
||||
|
||||
int wchar_count = MultiByteToWideChar(CP_UTF8, 0, menus[i].label, -1, nullptr, 0);
|
||||
wchar_t *wlabel = (wchar_t *)_malloca(wchar_count * sizeof(wchar_t));
|
||||
MultiByteToWideChar(CP_UTF8, 0, menus[i].label, -1, wlabel, wchar_count);
|
||||
AppendMenuW(menu_bar, MF_POPUP, (UINT_PTR)submenu, wlabel);
|
||||
_freea(wlabel);
|
||||
}
|
||||
|
||||
SetMenu(window->hwnd, menu_bar);
|
||||
}
|
||||
|
||||
int32_t platform_poll_menu_command(PlatformWindow *window)
|
||||
{
|
||||
int32_t cmd = window->pending_menu_cmd;
|
||||
window->pending_menu_cmd = 0;
|
||||
return cmd;
|
||||
}
|
||||
Reference in New Issue
Block a user