Demo using Direct3D 9 for rendering

This commit is contained in:
Martins Mozeiko 2017-06-05 21:09:16 -07:00
parent 6ac034c803
commit e14dd1cb1b
4 changed files with 843 additions and 0 deletions

6
demo/d3d9/build.bat Normal file
View File

@ -0,0 +1,6 @@
@echo off
rem This will use VS2015 for compiler
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
cl /D_CRT_SECURE_NO_DEPRECATE /nologo /W3 /O2 /fp:fast /Gm- /Fedemo.exe main.c user32.lib d3d9.lib /link /incremental:no

298
demo/d3d9/main.c Normal file
View File

@ -0,0 +1,298 @@
/* nuklear - 1.32.0 - public domain */
#define COBJMACROS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d9.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT
#define NK_IMPLEMENTATION
#define NK_D3D9_IMPLEMENTATION
#include "../../nuklear.h"
#include "nuklear_d3d9.h"
/* ===============================================================
*
* EXAMPLE
*
* ===============================================================*/
/* This are some code examples to provide a small overview of what can be
* done with this library. To try out an example uncomment the include
* and the corresponding function. */
#define UNUSED(a) (void)a
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a)/sizeof(a)[0])
/*#include "../style.c"*/
/*#include "../calculator.c"*/
/*#include "../overview.c"*/
/*#include "../node_editor.c"*/
/* ===============================================================
*
* DEMO
*
* ===============================================================*/
static IDirect3DDevice9 *device;
static IDirect3DDevice9Ex *deviceEx;
static D3DPRESENT_PARAMETERS present;
static LRESULT CALLBACK
WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_SIZE:
if (device)
{
UINT width = LOWORD(lparam);
UINT height = HIWORD(lparam);
if (width != 0 && height != 0 &&
(width != present.BackBufferWidth || height != present.BackBufferHeight))
{
nk_d3d9_release();
present.BackBufferWidth = width;
present.BackBufferHeight = height;
HRESULT hr = IDirect3DDevice9_Reset(device, &present);
NK_ASSERT(SUCCEEDED(hr));
nk_d3d9_resize(width, height);
}
}
break;
}
if (nk_d3d9_handle_event(wnd, msg, wparam, lparam))
return 0;
return DefWindowProcW(wnd, msg, wparam, lparam);
}
static void create_d3d9_device(HWND wnd)
{
HRESULT hr;
present.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
present.BackBufferWidth = WINDOW_WIDTH;
present.BackBufferHeight = WINDOW_HEIGHT;
present.BackBufferFormat = D3DFMT_X8R8G8B8;
present.BackBufferCount = 1;
present.MultiSampleType = D3DMULTISAMPLE_NONE;
present.SwapEffect = D3DSWAPEFFECT_DISCARD;
present.hDeviceWindow = wnd;
present.EnableAutoDepthStencil = TRUE;
present.AutoDepthStencilFormat = D3DFMT_D24S8;
present.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
present.Windowed = TRUE;
{/* first try to create Direct3D9Ex device if possible (on Windows 7+) */
typedef HRESULT WINAPI Direct3DCreate9ExPtr(UINT, IDirect3D9Ex**);
Direct3DCreate9ExPtr *Direct3DCreate9Ex = (void *)GetProcAddress(GetModuleHandleA("d3d9.dll"), "Direct3DCreate9Ex");
if (Direct3DCreate9Ex) {
IDirect3D9Ex *d3d9ex;
if (SUCCEEDED(Direct3DCreate9Ex(D3D_SDK_VERSION, &d3d9ex))) {
hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_FPU_PRESERVE,
&present, NULL, &deviceEx);
if (SUCCEEDED(hr)) {
device = (IDirect3DDevice9 *)deviceEx;
} else {
/* hardware vertex processing not supported, no big deal
retry with software vertex processing */
hr = IDirect3D9Ex_CreateDeviceEx(d3d9ex, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_FPU_PRESERVE,
&present, NULL, &deviceEx);
if (SUCCEEDED(hr)) {
device = (IDirect3DDevice9 *)deviceEx;
}
}
IDirect3D9Ex_Release(d3d9ex);
}
}
}
if (!device) {
/* otherwise do regular D3D9 setup */
IDirect3D9 *d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_FPU_PRESERVE,
&present, &device);
if (FAILED(hr)) {
/* hardware vertex processing not supported, no big deal
retry with software vertex processing */
hr = IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_FPU_PRESERVE,
&present, &device);
NK_ASSERT(SUCCEEDED(hr));
}
IDirect3D9_Release(d3d9);
}
}
int main(void)
{
struct nk_context *ctx;
struct nk_color background;
WNDCLASSW wc;
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
DWORD style = WS_OVERLAPPEDWINDOW;
DWORD exstyle = WS_EX_APPWINDOW;
HWND wnd;
int running = 1;
/* Win32 */
memset(&wc, 0, sizeof(wc));
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = WindowProc;
wc.hInstance = GetModuleHandleW(0);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"NuklearWindowClass";
RegisterClassW(&wc);
AdjustWindowRectEx(&rect, style, FALSE, exstyle);
wnd = CreateWindowExW(exstyle, wc.lpszClassName, L"Nuklear Demo",
style | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
rect.right - rect.left, rect.bottom - rect.top,
NULL, NULL, wc.hInstance, NULL);
create_d3d9_device(wnd);
/* GUI */
ctx = nk_d3d9_init(device, WINDOW_WIDTH, WINDOW_HEIGHT);
/* Load Fonts: if none of these are loaded a default font will be used */
/* Load Cursor: if you uncomment cursor loading please hide the cursor */
{struct nk_font_atlas *atlas;
nk_d3d9_font_stash_begin(&atlas);
/*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../extra_font/DroidSans.ttf", 14, 0);*/
/*struct nk_font *robot = nk_font_atlas_add_from_file(atlas, "../../extra_font/Roboto-Regular.ttf", 14, 0);*/
/*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../extra_font/kenvector_future_thin.ttf", 13, 0);*/
/*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../extra_font/ProggyClean.ttf", 12, 0);*/
/*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../extra_font/ProggyTiny.ttf", 10, 0);*/
/*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../extra_font/Cousine-Regular.ttf", 13, 0);*/
nk_d3d9_font_stash_end();
/*nk_style_load_all_cursors(ctx, atlas->cursors);*/
/*nk_style_set_font(ctx, &droid->handle)*/;}
/* style.c */
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
background = nk_rgb(28,48,62);
while (running)
{
/* Input */
MSG msg;
nk_input_begin(ctx);
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
running = 0;
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
nk_input_end(ctx);
/* GUI */
if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
enum {EASY, HARD};
static int op = EASY;
static int property = 20;
nk_layout_row_static(ctx, 30, 80, 1);
if (nk_button_label(ctx, "button"))
fprintf(stdout, "button pressed\n");
nk_layout_row_dynamic(ctx, 30, 2);
if (nk_option_label(ctx, "easy", op == EASY)) op = EASY;
if (nk_option_label(ctx, "hard", op == HARD)) op = HARD;
nk_layout_row_dynamic(ctx, 22, 1);
nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
nk_layout_row_dynamic(ctx, 20, 1);
nk_label(ctx, "background:", NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 25, 1);
if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) {
nk_layout_row_dynamic(ctx, 120, 1);
background = nk_color_picker(ctx, background, NK_RGBA);
nk_layout_row_dynamic(ctx, 25, 1);
background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1);
background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1);
background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1);
background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1);
nk_combo_end(ctx);
}
}
nk_end(ctx);
/* -------------- EXAMPLES ---------------- */
/*calculator(ctx);*/
/*overview(ctx);*/
/*node_editor(ctx);*/
/* ----------------------------------------- */
/* Draw */
{
HRESULT hr;
hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL,
D3DCOLOR_ARGB(background.a, background.r, background.g, background.b), 0.0f, 0);
NK_ASSERT(SUCCEEDED(hr));
hr = IDirect3DDevice9_BeginScene(device);
NK_ASSERT(SUCCEEDED(hr));
nk_d3d9_render(NK_ANTI_ALIASING_ON);
hr = IDirect3DDevice9_EndScene(device);
NK_ASSERT(SUCCEEDED(hr));
if (deviceEx) {
hr = IDirect3DDevice9Ex_PresentEx(deviceEx, NULL, NULL, NULL, NULL, 0);
} else {
hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
}
if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICEHUNG || hr == D3DERR_DEVICEREMOVED) {
/* to recover from this, you'll need to recreate device and all the resources */
MessageBoxW(NULL, L"D3D9 device is lost or removed!", L"Error", 0);
break;
} else if (hr == S_PRESENT_OCCLUDED) {
/* window is not visible, so vsync won't work. Let's sleep a bit to reduce CPU usage */
Sleep(10);
}
NK_ASSERT(SUCCEEDED(hr));
}
}
nk_d3d9_shutdown();
if (deviceEx) {
IDirect3DDevice9Ex_Release(deviceEx);
} else {
IDirect3DDevice9_Release(device);
}
UnregisterClassW(wc.lpszClassName, wc.hInstance);
return 0;
}

533
demo/d3d9/nuklear_d3d9.h Normal file
View File

@ -0,0 +1,533 @@
/*
* Nuklear - 1.32.0 - public domain
* no warrenty implied; use at your own risk.
* authored from 2015-2016 by Micha Mettke
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_D3D9_H_
#define NK_D3D9_H_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef struct IDirect3DDevice9 IDirect3DDevice9;
NK_API struct nk_context *nk_d3d9_init(IDirect3DDevice9 *device, int width, int height);
NK_API void nk_d3d9_font_stash_begin(struct nk_font_atlas **atlas);
NK_API void nk_d3d9_font_stash_end(void);
NK_API int nk_d3d9_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
NK_API void nk_d3d9_render(enum nk_anti_aliasing);
NK_API void nk_d3d9_release(void);
NK_API void nk_d3d9_resize(int width, int height);
NK_API void nk_d3d9_shutdown(void);
#endif
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_D3D9_IMPLEMENTATION
#define WIN32_LEAN_AND_MEAN
#define COBJMACROS
#include <d3d9.h>
#include <stddef.h>
#include <string.h>
struct nk_d3d9_vertex {
/* D3d9 FFP requires three coordinate position, but nuklear writes only 2 elements
projection matrix doesn't use z coordinate => so it can be any value.
Member order here is important! Do not rearrange them! */
float position[3];
nk_uchar col[4];
float uv[2];
};
static struct {
struct nk_context ctx;
struct nk_font_atlas atlas;
struct nk_buffer cmds;
struct nk_draw_null_texture null;
D3DVIEWPORT9 viewport;
D3DMATRIX projection;
IDirect3DDevice9 *device;
IDirect3DTexture9 *texture;
IDirect3DStateBlock9 *state;
} d3d9;
NK_API void
nk_d3d9_render(enum nk_anti_aliasing AA)
{
HRESULT hr;
hr = IDirect3DStateBlock9_Apply(d3d9.state);
NK_ASSERT(SUCCEEDED(hr));
/* projection matrix */
IDirect3DDevice9_SetTransform(d3d9.device, D3DTS_PROJECTION, &d3d9.projection);
/* viewport */
IDirect3DDevice9_SetViewport(d3d9.device, &d3d9.viewport);
/* convert from command queue into draw list and draw to screen */
{
struct nk_buffer vbuf, ebuf;
const struct nk_draw_command *cmd;
const nk_draw_index *offset = NULL;
UINT vertex_count;
/* fill converting configuration */
struct nk_convert_config config;
NK_STORAGE const struct nk_draw_vertex_layout_element vertex_layout[] = {
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d9_vertex, position)},
{NK_VERTEX_COLOR, NK_FORMAT_B8G8R8A8, NK_OFFSETOF(struct nk_d3d9_vertex, col)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d9_vertex, uv)},
{NK_VERTEX_LAYOUT_END}
};
memset(&config, 0, sizeof(config));
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_d3d9_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_d3d9_vertex);
config.global_alpha = 1.0f;
config.shape_AA = AA;
config.line_AA = AA;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.null = d3d9.null;
/* convert shapes into vertexes */
nk_buffer_init_default(&vbuf);
nk_buffer_init_default(&ebuf);
nk_convert(&d3d9.ctx, &d3d9.cmds, &vbuf, &ebuf, &config);
/* iterate over and execute each draw command */
offset = (const nk_draw_index *)nk_buffer_memory_const(&ebuf);
vertex_count = (UINT)vbuf.needed / sizeof(struct nk_d3d9_vertex);
nk_draw_foreach(cmd, &d3d9.ctx, &d3d9.cmds)
{
RECT scissor;
if (!cmd->elem_count) continue;
hr = IDirect3DDevice9_SetTexture(d3d9.device, 0, (IDirect3DBaseTexture9 *)cmd->texture.ptr);
NK_ASSERT(SUCCEEDED(hr));
scissor.left = (LONG)cmd->clip_rect.x;
scissor.right = (LONG)(cmd->clip_rect.x + cmd->clip_rect.w);
scissor.top = (LONG)cmd->clip_rect.y;
scissor.bottom = (LONG)(cmd->clip_rect.y + cmd->clip_rect.h);
hr = IDirect3DDevice9_SetScissorRect(d3d9.device, &scissor);
NK_ASSERT(SUCCEEDED(hr));
NK_ASSERT(sizeof(nk_draw_index) == sizeof(NK_UINT16));
hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(d3d9.device, D3DPT_TRIANGLELIST,
0, vertex_count, cmd->elem_count/3, offset, D3DFMT_INDEX16,
nk_buffer_memory_const(&vbuf), sizeof(struct nk_d3d9_vertex));
NK_ASSERT(SUCCEEDED(hr));
offset += cmd->elem_count;
}
nk_buffer_free(&vbuf);
nk_buffer_free(&ebuf);
}
nk_clear(&d3d9.ctx);
}
static void
nk_d3d9_get_projection_matrix(int width, int height, float *result)
{
const float L = 0.5f;
const float R = (float)width + 0.5f;
const float T = 0.5f;
const float B = (float)height + 0.5f;
float matrix[4][4] = {
{ 2.0f / (R - L), 0.0f, 0.0f, 0.0f },
{ 0.0f, 2.0f / (T - B), 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ (R + L) / (L - R), (T + B) / (B - T), 0.0f, 1.0f },
};
memcpy(result, matrix, sizeof(matrix));
}
NK_API void
nk_d3d9_release(void)
{
IDirect3DTexture9_Release(d3d9.texture);
IDirect3DStateBlock9_Release(d3d9.state);
}
static void
nk_d3d9_create_font_texture()
{
int w, h, y;
const void *image;
HRESULT hr;
D3DLOCKED_RECT locked;
image = nk_font_atlas_bake(&d3d9.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
hr = IDirect3DDevice9_CreateTexture(d3d9.device, w, h, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &d3d9.texture, NULL);
NK_ASSERT(SUCCEEDED(hr));
hr = IDirect3DTexture9_LockRect(d3d9.texture, 0, &locked, NULL, 0);
NK_ASSERT(SUCCEEDED(hr));
for (y = 0; y < h; y++) {
void *src = (char *)image + y * w * 4;
void *dst = (char *)locked.pBits + y * locked.Pitch;
memcpy(dst, src, w * 4);
}
hr = IDirect3DTexture9_UnlockRect(d3d9.texture, 0);
NK_ASSERT(SUCCEEDED(hr));
nk_font_atlas_end(&d3d9.atlas, nk_handle_ptr(d3d9.texture), &d3d9.null);
}
NK_API void
nk_d3d9_resize(int width, int height)
{
HRESULT hr;
if (d3d9.texture) {
nk_d3d9_create_font_texture();
}
hr = IDirect3DDevice9_BeginStateBlock(d3d9.device);
NK_ASSERT(SUCCEEDED(hr));
/* vertex format */
IDirect3DDevice9_SetFVF(d3d9.device, D3DFVF_XYZ + D3DFVF_DIFFUSE + D3DFVF_TEX1);
/* blend state */
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_ALPHABLENDENABLE, TRUE);
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_BLENDOP, D3DBLENDOP_ADD);
/* render state */
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_LIGHTING, FALSE);
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_ZENABLE, FALSE);
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_ZWRITEENABLE, FALSE);
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_CULLMODE, D3DCULL_NONE);
IDirect3DDevice9_SetRenderState(d3d9.device, D3DRS_SCISSORTESTENABLE, TRUE);
/* sampler state */
IDirect3DDevice9_SetSamplerState(d3d9.device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
IDirect3DDevice9_SetSamplerState(d3d9.device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
IDirect3DDevice9_SetSamplerState(d3d9.device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
IDirect3DDevice9_SetSamplerState(d3d9.device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
/* texture stage state */
IDirect3DDevice9_SetTextureStageState(d3d9.device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
IDirect3DDevice9_SetTextureStageState(d3d9.device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(d3d9.device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
IDirect3DDevice9_SetTextureStageState(d3d9.device, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
IDirect3DDevice9_SetTextureStageState(d3d9.device, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(d3d9.device, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
hr = IDirect3DDevice9_EndStateBlock(d3d9.device, &d3d9.state);
NK_ASSERT(SUCCEEDED(hr));
nk_d3d9_get_projection_matrix(width, height, &d3d9.projection.m[0][0]);
d3d9.viewport.Width = width;
d3d9.viewport.Height = height;
}
NK_API int
nk_d3d9_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
{
int down = !((lparam >> 31) & 1);
int ctrl = GetKeyState(VK_CONTROL) & (1 << 15);
switch (wparam)
{
case VK_SHIFT:
case VK_LSHIFT:
case VK_RSHIFT:
nk_input_key(&d3d9.ctx, NK_KEY_SHIFT, down);
return 1;
case VK_DELETE:
nk_input_key(&d3d9.ctx, NK_KEY_DEL, down);
return 1;
case VK_RETURN:
nk_input_key(&d3d9.ctx, NK_KEY_ENTER, down);
return 1;
case VK_TAB:
nk_input_key(&d3d9.ctx, NK_KEY_TAB, down);
return 1;
case VK_LEFT:
if (ctrl)
nk_input_key(&d3d9.ctx, NK_KEY_TEXT_WORD_LEFT, down);
else
nk_input_key(&d3d9.ctx, NK_KEY_LEFT, down);
return 1;
case VK_RIGHT:
if (ctrl)
nk_input_key(&d3d9.ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else
nk_input_key(&d3d9.ctx, NK_KEY_RIGHT, down);
return 1;
case VK_BACK:
nk_input_key(&d3d9.ctx, NK_KEY_BACKSPACE, down);
return 1;
case VK_HOME:
nk_input_key(&d3d9.ctx, NK_KEY_TEXT_START, down);
nk_input_key(&d3d9.ctx, NK_KEY_SCROLL_START, down);
return 1;
case VK_END:
nk_input_key(&d3d9.ctx, NK_KEY_TEXT_END, down);
nk_input_key(&d3d9.ctx, NK_KEY_SCROLL_END, down);
return 1;
case VK_NEXT:
nk_input_key(&d3d9.ctx, NK_KEY_SCROLL_DOWN, down);
return 1;
case VK_PRIOR:
nk_input_key(&d3d9.ctx, NK_KEY_SCROLL_UP, down);
return 1;
case 'C':
if (ctrl) {
nk_input_key(&d3d9.ctx, NK_KEY_COPY, down);
return 1;
}
break;
case 'V':
if (ctrl) {
nk_input_key(&d3d9.ctx, NK_KEY_PASTE, down);
return 1;
}
break;
case 'X':
if (ctrl) {
nk_input_key(&d3d9.ctx, NK_KEY_CUT, down);
return 1;
}
break;
case 'Z':
if (ctrl) {
nk_input_key(&d3d9.ctx, NK_KEY_TEXT_UNDO, down);
return 1;
}
break;
case 'R':
if (ctrl) {
nk_input_key(&d3d9.ctx, NK_KEY_TEXT_REDO, down);
return 1;
}
break;
}
return 0;
}
case WM_CHAR:
if (wparam >= 32)
{
nk_input_unicode(&d3d9.ctx, (nk_rune)wparam);
return 1;
}
break;
case WM_LBUTTONDOWN:
nk_input_button(&d3d9.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_LBUTTONUP:
nk_input_button(&d3d9.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
nk_input_button(&d3d9.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_RBUTTONDOWN:
nk_input_button(&d3d9.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_RBUTTONUP:
nk_input_button(&d3d9.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_MBUTTONDOWN:
nk_input_button(&d3d9.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_MBUTTONUP:
nk_input_button(&d3d9.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_MOUSEWHEEL:
nk_input_scroll(&d3d9.ctx, nk_vec2(0,(float)(short)HIWORD(wparam) / WHEEL_DELTA));
return 1;
case WM_MOUSEMOVE:
nk_input_motion(&d3d9.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam));
return 1;
case WM_LBUTTONDBLCLK:
nk_input_button(&d3d9.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
return 1;
}
return 0;
}
static void
nk_d3d9_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
(void)usr;
if (!IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) {
return;
}
HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
if (!mem) {
CloseClipboard();
return;
}
SIZE_T size = GlobalSize(mem) - 1;
if (!size) {
CloseClipboard();
return;
}
LPCWSTR wstr = (LPCWSTR)GlobalLock(mem);
if (!wstr) {
CloseClipboard();
return;
}
int utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)size / sizeof(wchar_t), NULL, 0, NULL, NULL);
if (utf8size) {
char *utf8 = (char *)malloc(utf8size);
if (utf8) {
WideCharToMultiByte(CP_UTF8, 0, wstr, (int)size / sizeof(wchar_t), utf8, utf8size, NULL, NULL);
nk_textedit_paste(edit, utf8, utf8size);
free(utf8);
}
}
GlobalUnlock(mem);
CloseClipboard();
}
static void
nk_d3d9_clipboard_copy(nk_handle usr, const char *text, int len)
{
(void)usr;
if (!OpenClipboard(NULL)) {
return;
}
int wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
if (wsize) {
HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t));
if (mem) {
wchar_t *wstr = (wchar_t*)GlobalLock(mem);
if (wstr) {
MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
wstr[wsize] = 0;
GlobalUnlock(mem);
SetClipboardData(CF_UNICODETEXT, mem);
}
}
}
CloseClipboard();
}
NK_API struct nk_context*
nk_d3d9_init(IDirect3DDevice9 *device, int width, int height)
{
d3d9.device = device;
IDirect3DDevice9_AddRef(device);
nk_init_default(&d3d9.ctx, 0);
d3d9.state = NULL;
d3d9.texture = NULL;
d3d9.ctx.clip.copy = nk_d3d9_clipboard_copy;
d3d9.ctx.clip.paste = nk_d3d9_clipboard_paste;
d3d9.ctx.clip.userdata = nk_handle_ptr(0);
nk_buffer_init_default(&d3d9.cmds);
/* viewport */
d3d9.viewport.X = 0;
d3d9.viewport.Y = 0;
d3d9.viewport.MinZ = 0.0f;
d3d9.viewport.MaxZ = 1.0f;
nk_d3d9_resize(width, height);
return &d3d9.ctx;
}
NK_API void
nk_d3d9_font_stash_begin(struct nk_font_atlas **atlas)
{
nk_font_atlas_init_default(&d3d9.atlas);
nk_font_atlas_begin(&d3d9.atlas);
*atlas = &d3d9.atlas;
}
NK_API void
nk_d3d9_font_stash_end(void)
{
nk_d3d9_create_font_texture();
if (d3d9.atlas.default_font)
nk_style_set_font(&d3d9.ctx, &d3d9.atlas.default_font->handle);
}
NK_API
void nk_d3d9_shutdown(void)
{
nk_d3d9_release();
nk_font_atlas_clear(&d3d9.atlas);
nk_buffer_free(&d3d9.cmds);
nk_free(&d3d9.ctx);
}
#endif

View File

@ -3137,6 +3137,7 @@ NK_FORMAT_COLOR_BEGIN,
NK_FORMAT_R32G32B32,
NK_FORMAT_R8G8B8A8,
NK_FORMAT_B8G8R8A8,
NK_FORMAT_R16G15B16A16,
NK_FORMAT_R32G32B32A32,
NK_FORMAT_R32G32B32A32_FLOAT,
@ -7906,6 +7907,11 @@ nk_draw_vertex_color(void *attribute, const float *values,
struct nk_color col = nk_rgba_fv(values);
NK_MEMCPY(attribute, &col.r, sizeof(col));
} break;
case NK_FORMAT_B8G8R8A8: {
struct nk_color col = nk_rgba_fv(values);
struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
NK_MEMCPY(attribute, &bgra, sizeof(bgra));
} break;
case NK_FORMAT_R16G15B16: {
nk_ushort col[3];
col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);