| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 |
- // stb_wingraph.h v0.01 - public domain windows graphics programming
- // wraps WinMain, ChoosePixelFormat, ChangeDisplayResolution, etc. for
- // doing OpenGL graphics
- //
- // in ONE source file, put '#define STB_DEFINE' before including this
- // OR put '#define STB_WINMAIN' to define a WinMain that calls stbwingraph_main(void)
- //
- // @TODO:
- // 2d rendering interface (that can be done easily in software)
- // STB_WINGRAPH_SOFTWARE -- 2d software rendering only
- // STB_WINGRAPH_OPENGL -- OpenGL only
- #ifndef INCLUDE_STB_WINGRAPH_H
- #define INCLUDE_STB_WINGRAPH_H
- #ifdef STB_WINMAIN
- #ifndef STB_DEFINE
- #define STB_DEFINE
- #define STB_WINGRAPH_DISABLE_DEFINE_AT_END
- #endif
- #endif
- #ifdef STB_DEFINE
- #pragma comment(lib, "opengl32.lib")
- #pragma comment(lib, "glu32.lib")
- #pragma comment(lib, "winmm.lib")
- #pragma comment(lib, "gdi32.lib")
- #pragma comment(lib, "user32.lib")
- #endif
- #ifdef __cplusplus
- #define STB_EXTERN extern "C"
- #else
- #define STB_EXTERN
- #endif
- #ifdef STB_DEFINE
- #ifndef _WINDOWS_
- #ifdef APIENTRY
- #undef APIENTRY
- #endif
- #ifdef WINGDIAPI
- #undef WINGDIAPI
- #endif
- #define _WIN32_WINNT 0x0400 // WM_MOUSEWHEEL
- #include <windows.h>
- #endif
- #include <stdio.h>
- #include <math.h>
- #include <time.h>
- #include <string.h>
- #include <assert.h>
- #endif
- typedef void * stbwingraph_hwnd;
- typedef void * stbwingraph_hinstance;
- enum
- {
- STBWINGRAPH_unprocessed = -(1 << 24),
- STBWINGRAPH_do_not_show,
- STBWINGRAPH_winproc_exit,
- STBWINGRAPH_winproc_update,
- STBWINGRAPH_update_exit,
- STBWINGRAPH_update_pause,
- };
- typedef enum
- {
- STBWGE__none=0,
- STBWGE_create,
- STBWGE_create_postshow,
- STBWGE_draw,
- STBWGE_destroy,
- STBWGE_char,
- STBWGE_keydown,
- STBWGE_syskeydown,
- STBWGE_keyup,
- STBWGE_syskeyup,
- STBWGE_deactivate,
- STBWGE_activate,
- STBWGE_size,
- STBWGE_mousemove ,
- STBWGE_leftdown , STBWGE_leftup ,
- STBWGE_middledown, STBWGE_middleup,
- STBWGE_rightdown , STBWGE_rightup ,
- STBWGE_mousewheel,
- } stbwingraph_event_type;
- typedef struct
- {
- stbwingraph_event_type type;
- // for input events (mouse, keyboard)
- int mx,my; // mouse x & y
- int dx,dy;
- int shift, ctrl, alt;
- // for keyboard events
- int key;
- // for STBWGE_size:
- int width, height;
- // for STBWGE_crate
- int did_share_lists; // if true, wglShareLists succeeded
- void *handle;
- } stbwingraph_event;
- typedef int (*stbwingraph_window_proc)(void *data, stbwingraph_event *event);
- extern stbwingraph_hinstance stbwingraph_app;
- extern stbwingraph_hwnd stbwingraph_primary_window;
- extern int stbwingraph_request_fullscreen;
- extern int stbwingraph_request_windowed;
- STB_EXTERN void stbwingraph_ods(char *str, ...);
- STB_EXTERN int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type,
- char *caption, char *text, ...);
- STB_EXTERN int stbwingraph_ChangeResolution(unsigned int w, unsigned int h,
- unsigned int bits, int use_message_box);
- STB_EXTERN int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits,
- int alpha_bits, int depth_bits, int stencil_bits, int accum_bits);
- STB_EXTERN int stbwingraph_DefineClass(void *hinstance, char *iconname);
- STB_EXTERN void stbwingraph_SwapBuffers(void *win);
- STB_EXTERN void stbwingraph_Priority(int n);
- STB_EXTERN void stbwingraph_MakeFonts(void *window, int font_base);
- STB_EXTERN void stbwingraph_ShowWindow(void *window);
- STB_EXTERN void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text, int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil);
- STB_EXTERN void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height);
- STB_EXTERN void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh);
- STB_EXTERN void stbwingraph_DestroyWindow(void *window);
- STB_EXTERN void stbwingraph_ShowCursor(void *window, int visible);
- STB_EXTERN float stbwingraph_GetTimestep(float minimum_time);
- STB_EXTERN void stbwingraph_SetGLWindow(void *win);
- typedef int (*stbwingraph_update)(float timestep, int real, int in_client);
- STB_EXTERN int stbwingraph_MainLoop(stbwingraph_update func, float mintime);
- #ifdef STB_DEFINE
- stbwingraph_hinstance stbwingraph_app;
- stbwingraph_hwnd stbwingraph_primary_window;
- int stbwingraph_request_fullscreen;
- int stbwingraph_request_windowed;
- void stbwingraph_ods(char *str, ...)
- {
- char buffer[1024];
- va_list v;
- va_start(v,str);
- vsprintf(buffer, str, v);
- va_end(v);
- OutputDebugString(buffer);
- }
- int stbwingraph_MessageBox(stbwingraph_hwnd win, unsigned int type, char *caption, char *text, ...)
- {
- va_list v;
- char buffer[1024];
- va_start(v, text);
- vsprintf(buffer, text, v);
- va_end(v);
- return MessageBox(win, buffer, caption, type);
- }
- void stbwingraph_Priority(int n)
- {
- int p;
- switch (n) {
- case -1: p = THREAD_PRIORITY_BELOW_NORMAL; break;
- case 0: p = THREAD_PRIORITY_NORMAL; break;
- case 1: p = THREAD_PRIORITY_ABOVE_NORMAL; break;
- default:
- if (n < 0) p = THREAD_PRIORITY_LOWEST;
- else p = THREAD_PRIORITY_HIGHEST;
- }
- SetThreadPriority(GetCurrentThread(), p);
- }
- static void stbwingraph_ResetResolution(void)
- {
- ChangeDisplaySettings(NULL, 0);
- }
- static void stbwingraph_RegisterResetResolution(void)
- {
- static int done=0;
- if (!done) {
- done = 1;
- atexit(stbwingraph_ResetResolution);
- }
- }
- int stbwingraph_ChangeResolution(unsigned int w, unsigned int h, unsigned int bits, int use_message_box)
- {
- DEVMODE mode;
- int res;
-
- int i, tries=0;
- for (i=0; ; ++i) {
- int success = EnumDisplaySettings(NULL, i, &mode);
- if (!success) break;
- if (mode.dmBitsPerPel == bits && mode.dmPelsWidth == w && mode.dmPelsHeight == h) {
- ++tries;
- success = ChangeDisplaySettings(&mode, CDS_FULLSCREEN);
- if (success == DISP_CHANGE_SUCCESSFUL) {
- stbwingraph_RegisterResetResolution();
- return TRUE;
- }
- break;
- }
- }
- if (!tries) {
- if (use_message_box)
- stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits);
- return FALSE;
- }
- // we tried but failed, so try explicitly doing it without specifying refresh rate
- // Win95 support logic
- mode.dmBitsPerPel = bits;
- mode.dmPelsWidth = w;
- mode.dmPelsHeight = h;
- mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
- res = ChangeDisplaySettings(&mode, CDS_FULLSCREEN);
- switch (res) {
- case DISP_CHANGE_SUCCESSFUL:
- stbwingraph_RegisterResetResolution();
- return TRUE;
- case DISP_CHANGE_RESTART:
- if (use_message_box)
- stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "Please set your desktop to %d-bit color and then try again.");
- return FALSE;
- case DISP_CHANGE_FAILED:
- if (use_message_box)
- stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The hardware failed to change modes.");
- return FALSE;
- case DISP_CHANGE_BADMODE:
- if (use_message_box)
- stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "The resolution %d x %d x %d-bits is not supported.", w, h, bits);
- return FALSE;
- default:
- if (use_message_box)
- stbwingraph_MessageBox(stbwingraph_primary_window, MB_ICONERROR, NULL, "An unknown error prevented a change to a %d x %d x %d-bit display.", w, h, bits);
- return FALSE;
- }
- }
- int stbwingraph_SetPixelFormat(stbwingraph_hwnd win, int color_bits, int alpha_bits, int depth_bits, int stencil_bits, int accum_bits)
- {
- HDC dc = GetDC(win);
- PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd) };
- int pixel_format;
- pfd.nVersion = 1;
- pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
- pfd.dwLayerMask = PFD_MAIN_PLANE;
- pfd.iPixelType = PFD_TYPE_RGBA;
- pfd.cColorBits = color_bits;
- pfd.cAlphaBits = alpha_bits;
- pfd.cDepthBits = depth_bits;
- pfd.cStencilBits = stencil_bits;
- pfd.cAccumBits = accum_bits;
- pixel_format = ChoosePixelFormat(dc, &pfd);
- if (!pixel_format) return FALSE;
- if (!DescribePixelFormat(dc, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
- return FALSE;
- SetPixelFormat(dc, pixel_format, &pfd);
- return TRUE;
- }
- typedef struct
- {
- // app data
- stbwingraph_window_proc func;
- void *data;
- // creation parameters
- int color, alpha, depth, stencil, accum;
- HWND share_window;
- HWND window;
- // internal data
- HGLRC rc;
- HDC dc;
- int hide_mouse;
- int in_client;
- int active;
- int did_share_lists;
- int mx,my; // last mouse positions
- } stbwingraph__window;
- static void stbwingraph__inclient(stbwingraph__window *win, int state)
- {
- if (state != win->in_client) {
- win->in_client = state;
- if (win->hide_mouse)
- ShowCursor(!state);
- }
- }
- static void stbwingraph__key(stbwingraph_event *e, int type, int key, stbwingraph__window *z)
- {
- e->type = type;
- e->key = key;
- e->shift = (GetKeyState(VK_SHIFT) < 0);
- e->ctrl = (GetKeyState(VK_CONTROL) < 0);
- e->alt = (GetKeyState(VK_MENU) < 0);
- if (z) {
- e->mx = z->mx;
- e->my = z->my;
- } else {
- e->mx = e->my = 0;
- }
- e->dx = e->dy = 0;
- }
- static void stbwingraph__mouse(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z)
- {
- static int captured = 0;
- e->type = type;
- e->mx = (short) LOWORD(lparam);
- e->my = (short) HIWORD(lparam);
- if (!z || z->mx == -(1 << 30)) {
- e->dx = e->dy = 0;
- } else {
- e->dx = e->mx - z->mx;
- e->dy = e->my - z->my;
- }
- e->shift = (wparam & MK_SHIFT) != 0;
- e->ctrl = (wparam & MK_CONTROL) != 0;
- e->alt = (wparam & MK_ALT) != 0;
- if (z) {
- z->mx = e->mx;
- z->my = e->my;
- }
- if (capture) {
- if (!captured && capture == 1)
- SetCapture(wnd);
- captured += capture;
- if (!captured && capture == -1)
- ReleaseCapture();
- if (captured < 0) captured = 0;
- }
- }
- static void stbwingraph__mousewheel(stbwingraph_event *e, int type, WPARAM wparam, LPARAM lparam, int capture, void *wnd, stbwingraph__window *z)
- {
- // lparam seems bogus!
- static int captured = 0;
- e->type = type;
- if (z) {
- e->mx = z->mx;
- e->my = z->my;
- }
- e->dx = e->dy = 0;
- e->shift = (wparam & MK_SHIFT) != 0;
- e->ctrl = (wparam & MK_CONTROL) != 0;
- e->alt = (GetKeyState(VK_MENU) < 0);
- e->key = ((int) wparam >> 16);
- }
- int stbwingraph_force_update;
- static int WINAPI stbwingraph_WinProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
- {
- int allow_default = TRUE;
- stbwingraph_event e = { STBWGE__none };
- // the following line is wrong for 64-bit windows, but VC6 doesn't have GetWindowLongPtr
- stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(wnd, GWL_USERDATA);
- switch (msg) {
- case WM_CREATE:
- {
- LPCREATESTRUCT lpcs = (LPCREATESTRUCT) lparam;
- assert(z == NULL);
- z = (stbwingraph__window *) lpcs->lpCreateParams;
- SetWindowLong(wnd, GWL_USERDATA, (LONG) z);
- z->dc = GetDC(wnd);
- if (stbwingraph_SetPixelFormat(wnd, z->color, z->alpha, z->depth, z->stencil, z->accum)) {
- z->rc = wglCreateContext(z->dc);
- if (z->rc) {
- e.type = STBWGE_create;
- z->did_share_lists = FALSE;
- if (z->share_window) {
- stbwingraph__window *y = (stbwingraph__window *) GetWindowLong(z->share_window, GWL_USERDATA);
- if (wglShareLists(z->rc, y->rc))
- z->did_share_lists = TRUE;
- }
- wglMakeCurrent(z->dc, z->rc);
- return 0;
- }
- }
- return -1;
- }
- case WM_PAINT: {
- PAINTSTRUCT ps;
- HDC hdc = BeginPaint(wnd, &ps);
- SelectObject(hdc, GetStockObject(NULL_BRUSH));
- e.type = STBWGE_draw;
- e.handle = wnd;
- z->func(z->data, &e);
- EndPaint(wnd, &ps);
- return 0;
- }
- case WM_DESTROY:
- e.type = STBWGE_destroy;
- e.handle = wnd;
- if (z && z->func)
- z->func(z->data, &e);
- wglMakeCurrent(NULL, NULL) ;
- if (z) {
- if (z->rc) wglDeleteContext(z->rc);
- z->dc = 0;
- z->rc = 0;
- }
- if (wnd == stbwingraph_primary_window)
- PostQuitMessage (0);
- return 0;
- case WM_CHAR: stbwingraph__key(&e, STBWGE_char , wparam, z); break;
- case WM_KEYDOWN: stbwingraph__key(&e, STBWGE_keydown, wparam, z); break;
- case WM_KEYUP: stbwingraph__key(&e, STBWGE_keyup , wparam, z); break;
- case WM_NCMOUSEMOVE: stbwingraph__inclient(z,0); break;
- case WM_MOUSEMOVE: stbwingraph__inclient(z,1); stbwingraph__mouse(&e, STBWGE_mousemove, wparam, lparam,0,wnd, z); break;
- case WM_LBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_leftdown, wparam, lparam,1,wnd, z); break;
- case WM_MBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_middledown, wparam, lparam,1,wnd, z); break;
- case WM_RBUTTONDOWN: stbwingraph__mouse(&e, STBWGE_rightdown, wparam, lparam,1,wnd, z); break;
- case WM_LBUTTONUP: stbwingraph__mouse(&e, STBWGE_leftup, wparam, lparam,-1,wnd, z); break;
- case WM_MBUTTONUP: stbwingraph__mouse(&e, STBWGE_middleup, wparam, lparam,-1,wnd, z); break;
- case WM_RBUTTONUP: stbwingraph__mouse(&e, STBWGE_rightup, wparam, lparam,-1,wnd, z); break;
- case WM_MOUSEWHEEL: stbwingraph__mousewheel(&e, STBWGE_mousewheel, wparam, lparam,0,wnd, z); break;
- case WM_ACTIVATE:
- allow_default = FALSE;
- if (LOWORD(wparam)==WA_INACTIVE ) {
- wglMakeCurrent(z->dc, NULL);
- e.type = STBWGE_deactivate;
- z->active = FALSE;
- } else {
- wglMakeCurrent(z->dc, z->rc);
- e.type = STBWGE_activate;
- z->active = TRUE;
- }
- e.handle = wnd;
- z->func(z->data, &e);
- return 0;
- case WM_SIZE: {
- RECT rect;
- allow_default = FALSE;
- GetClientRect(wnd, &rect);
- e.type = STBWGE_size;
- e.width = rect.right;
- e.height = rect.bottom;
- e.handle = wnd;
- z->func(z->data, &e);
- return 0;
- }
- default:
- return DefWindowProc (wnd, msg, wparam, lparam);
- }
- if (e.type != STBWGE__none) {
- int n;
- e.handle = wnd;
- n = z->func(z->data, &e);
- if (n == STBWINGRAPH_winproc_exit) {
- PostQuitMessage(0);
- n = 0;
- }
- if (n == STBWINGRAPH_winproc_update) {
- stbwingraph_force_update = TRUE;
- return 1;
- }
- if (n != STBWINGRAPH_unprocessed)
- return n;
- }
- return DefWindowProc (wnd, msg, wparam, lparam);
- }
- int stbwingraph_DefineClass(HINSTANCE hInstance, char *iconname)
- {
- WNDCLASSEX wndclass;
- stbwingraph_app = hInstance;
- wndclass.cbSize = sizeof(wndclass);
- wndclass.style = CS_OWNDC;
- wndclass.lpfnWndProc = (WNDPROC) stbwingraph_WinProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = 0;
- wndclass.hInstance = hInstance;
- wndclass.hIcon = LoadIcon(hInstance, iconname);
- wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
- wndclass.hbrBackground = GetStockObject(NULL_BRUSH);
- wndclass.lpszMenuName = "zwingraph";
- wndclass.lpszClassName = "zwingraph";
- wndclass.hIconSm = NULL;
- if (!RegisterClassEx(&wndclass))
- return FALSE;
- return TRUE;
- }
- void stbwingraph_ShowWindow(void *window)
- {
- stbwingraph_event e = { STBWGE_create_postshow };
- stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA);
- ShowWindow(window, SW_SHOWNORMAL);
- InvalidateRect(window, NULL, TRUE);
- UpdateWindow(window);
- e.handle = window;
- z->func(z->data, &e);
- }
- void *stbwingraph_CreateWindow(int primary, stbwingraph_window_proc func, void *data, char *text,
- int width, int height, int fullscreen, int resizeable, int dest_alpha, int stencil)
- {
- HWND win;
- DWORD dwstyle;
- stbwingraph__window *z = (stbwingraph__window *) malloc(sizeof(*z));
- if (z == NULL) return NULL;
- memset(z, 0, sizeof(*z));
- z->color = 24;
- z->depth = 24;
- z->alpha = dest_alpha;
- z->stencil = stencil;
- z->func = func;
- z->data = data;
- z->mx = -(1 << 30);
- z->my = 0;
- if (primary) {
- if (stbwingraph_request_windowed)
- fullscreen = FALSE;
- else if (stbwingraph_request_fullscreen)
- fullscreen = TRUE;
- }
- if (fullscreen) {
- #ifdef STB_SIMPLE
- stbwingraph_ChangeResolution(width, height, 32, 1);
- #else
- if (!stbwingraph_ChangeResolution(width, height, 32, 0))
- return NULL;
- #endif
- dwstyle = WS_POPUP | WS_CLIPSIBLINGS;
- } else {
- RECT rect;
- dwstyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
- if (resizeable)
- dwstyle |= WS_SIZEBOX | WS_MAXIMIZEBOX;
- rect.top = 0;
- rect.left = 0;
- rect.right = width;
- rect.bottom = height;
- AdjustWindowRect(&rect, dwstyle, FALSE);
- width = rect.right - rect.left;
- height = rect.bottom - rect.top;
- }
- win = CreateWindow("zwingraph", text ? text : "sample", dwstyle,
- CW_USEDEFAULT,0, width, height,
- NULL, NULL, stbwingraph_app, z);
- if (win == NULL) return win;
- if (primary) {
- if (stbwingraph_primary_window)
- stbwingraph_DestroyWindow(stbwingraph_primary_window);
- stbwingraph_primary_window = win;
- }
- {
- stbwingraph_event e = { STBWGE_create };
- stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA);
- z->window = win;
- e.did_share_lists = z->did_share_lists;
- e.handle = win;
- if (z->func(z->data, &e) != STBWINGRAPH_do_not_show)
- stbwingraph_ShowWindow(win);
- }
- return win;
- }
- void *stbwingraph_CreateWindowSimple(stbwingraph_window_proc func, int width, int height)
- {
- int fullscreen = 0;
- #ifndef _DEBUG
- if (width == 640 && height == 480) fullscreen = 1;
- if (width == 800 && height == 600) fullscreen = 1;
- if (width == 1024 && height == 768) fullscreen = 1;
- if (width == 1280 && height == 1024) fullscreen = 1;
- if (width == 1600 && height == 1200) fullscreen = 1;
- //@TODO: widescreen widths
- #endif
- return stbwingraph_CreateWindow(1, func, NULL, NULL, width, height, fullscreen, 1, 0, 0);
- }
- void *stbwingraph_CreateWindowSimpleFull(stbwingraph_window_proc func, int fullscreen, int ww, int wh, int fw, int fh)
- {
- if (fullscreen == -1) {
- #ifdef _DEBUG
- fullscreen = 0;
- #else
- fullscreen = 1;
- #endif
- }
- if (fullscreen) {
- if (fw) ww = fw;
- if (fh) wh = fh;
- }
- return stbwingraph_CreateWindow(1, func, NULL, NULL, ww, wh, fullscreen, 1, 0, 0);
- }
- void stbwingraph_DestroyWindow(void *window)
- {
- stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(window, GWL_USERDATA);
- DestroyWindow(window);
- free(z);
- if (stbwingraph_primary_window == window)
- stbwingraph_primary_window = NULL;
- }
- void stbwingraph_ShowCursor(void *window, int visible)
- {
- int hide;
- stbwingraph__window *win;
- if (!window)
- window = stbwingraph_primary_window;
- win = (stbwingraph__window *) GetWindowLong((HWND) window, GWL_USERDATA);
- hide = !visible;
- if (hide != win->hide_mouse) {
- win->hide_mouse = hide;
- if (!hide)
- ShowCursor(TRUE);
- else if (win->in_client)
- ShowCursor(FALSE);
- }
- }
- float stbwingraph_GetTimestep(float minimum_time)
- {
- float elapsedTime;
- double thisTime;
- static double lastTime = -1;
-
- if (lastTime == -1)
- lastTime = timeGetTime() / 1000.0 - minimum_time;
- for(;;) {
- thisTime = timeGetTime() / 1000.0;
- elapsedTime = (float) (thisTime - lastTime);
- if (elapsedTime >= minimum_time) {
- lastTime = thisTime;
- return elapsedTime;
- }
- #if 1
- Sleep(2);
- #endif
- }
- }
- void stbwingraph_SetGLWindow(void *win)
- {
- stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA);
- if (z)
- wglMakeCurrent(z->dc, z->rc);
- }
- void stbwingraph_MakeFonts(void *window, int font_base)
- {
- wglUseFontBitmaps(GetDC(window ? window : stbwingraph_primary_window), 0, 256, font_base);
- }
- // returns 1 if WM_QUIT, 0 if 'func' returned 0
- int stbwingraph_MainLoop(stbwingraph_update func, float mintime)
- {
- int needs_drawing = FALSE;
- MSG msg;
- int is_animating = TRUE;
- if (mintime <= 0) mintime = 0.01f;
- for(;;) {
- int n;
- is_animating = TRUE;
- // wait for a message if: (a) we're animating and there's already a message
- // or (b) we're not animating
- if (!is_animating || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
- stbwingraph_force_update = FALSE;
- if (GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- } else {
- return 1; // WM_QUIT
- }
- // only force a draw for certain messages...
- // if I don't do this, we peg at 50% for some reason... must
- // be a bug somewhere, because we peg at 100% when rendering...
- // very weird... looks like NVIDIA is pumping some messages
- // through our pipeline? well, ok, I guess if we can get
- // non-user-generated messages we have to do this
- if (!stbwingraph_force_update) {
- switch (msg.message) {
- case WM_MOUSEMOVE:
- case WM_NCMOUSEMOVE:
- break;
- case WM_CHAR:
- case WM_KEYDOWN:
- case WM_KEYUP:
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- case WM_RBUTTONUP:
- case WM_TIMER:
- case WM_SIZE:
- case WM_ACTIVATE:
- needs_drawing = TRUE;
- break;
- }
- } else
- needs_drawing = TRUE;
- }
- // if another message, process that first
- // @TODO: i don't think this is working, because I can't key ahead
- // in the SVT demo app
- if (PeekMessage(&msg, NULL, 0,0, PM_NOREMOVE))
- continue;
- // and now call update
- if (needs_drawing || is_animating) {
- int real=1, in_client=1;
- if (stbwingraph_primary_window) {
- stbwingraph__window *z = (stbwingraph__window *) GetWindowLong(stbwingraph_primary_window, GWL_USERDATA);
- if (z && !z->active) {
- real = 0;
- }
- if (z)
- in_client = z->in_client;
- }
- if (stbwingraph_primary_window)
- stbwingraph_SetGLWindow(stbwingraph_primary_window);
- n = func(stbwingraph_GetTimestep(mintime), real, in_client);
- if (n == STBWINGRAPH_update_exit)
- return 0; // update_quit
- is_animating = (n != STBWINGRAPH_update_pause);
- needs_drawing = FALSE;
- }
- }
- }
- void stbwingraph_SwapBuffers(void *win)
- {
- stbwingraph__window *z;
- if (win == NULL) win = stbwingraph_primary_window;
- z = (stbwingraph__window *) GetWindowLong(win, GWL_USERDATA);
- if (z && z->dc)
- SwapBuffers(z->dc);
- }
- #endif
- #ifdef STB_WINMAIN
- void stbwingraph_main(void);
- char *stb_wingraph_commandline;
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
- {
- {
- char buffer[1024];
- // add spaces to either side of the string
- buffer[0] = ' ';
- strcpy(buffer+1, lpCmdLine);
- strcat(buffer, " ");
- if (strstr(buffer, " -reset ")) {
- ChangeDisplaySettings(NULL, 0);
- exit(0);
- }
- if (strstr(buffer, " -window ") || strstr(buffer, " -windowed "))
- stbwingraph_request_windowed = TRUE;
- else if (strstr(buffer, " -full ") || strstr(buffer, " -fullscreen "))
- stbwingraph_request_fullscreen = TRUE;
- }
- stb_wingraph_commandline = lpCmdLine;
- stbwingraph_DefineClass(hInstance, "appicon");
- stbwingraph_main();
- return 0;
- }
- #endif
- #undef STB_EXTERN
- #ifdef STB_WINGRAPH_DISABLE_DEFINE_AT_END
- #undef STB_DEFINE
- #endif
- #endif // INCLUDE_STB_WINGRAPH_H
|