Merge branch 'Immediate-Mode-UI:master' into master

This commit is contained in:
Leonel Hernandez 2022-10-19 16:37:00 -05:00 committed by GitHub
commit b7418c79ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
136 changed files with 16262 additions and 4208 deletions

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# EditorConfig: https://EditorConfig.org
root = true
[*]
indent_style = space
charset = utf-8
end_of_line = lf
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
[clib.json]
indent_size = 2

16
.github/workflows/create-tag.yml vendored Normal file
View File

@ -0,0 +1,16 @@
name: Create Tag
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: butlerlogic/action-autotag@stable
with:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
root: clib.json

View File

@ -92,7 +92,7 @@ nk_end(&ctx);
![example](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png)
## Bindings
There are a number of nuklear bindings for different languges created by other authors.
There are a number of nuklear bindings for different languages created by other authors.
I cannot attest for their quality since I am not necessarily proficient in any of these
languages. Furthermore there are no guarantee that all bindings will always be kept up to date:
@ -185,8 +185,8 @@ Reviewing changes to `src/*` and `nuklear.h`:
* Variable/function name casing.
* Indentation.
* Curly bracket (`{}`) placement.
* Ensure that the contributer have bumped the appropriate version in
[package.json](https://github.com/Immediate-Mode-UI/Nuklear/blob/master/package.json)
* Ensure that the contributor has bumped the appropriate version in
[clib.json](https://github.com/Immediate-Mode-UI/Nuklear/blob/master/clib.json)
and added their changes to the
[CHANGELOG](https://github.com/Immediate-Mode-UI/Nuklear/blob/master/src/CHANGELOG).
* Have at least one other person review the changes before merging.

View File

@ -1,8 +1,9 @@
{
"name": "nuklear",
"version": "4.09.0",
"version": "4.10.1",
"repo": "Immediate-Mode-UI/Nuklear",
"description": "A small ANSI C gui toolkit",
"keywords": ["gl", "ui", "toolkit"],
"license": "MIT, Unlicense",
"src": ["nuklear.h"]
}

View File

@ -2,7 +2,7 @@
BIN = demo
# Flags
CFLAGS += -std=c99 -pedantic -O2
CFLAGS += -std=c89 -Wall -Wextra -pedantic -Wno-unused-function -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -29,32 +29,57 @@
#define MAX(a,b) ((a) < (b) ? (b) : (a))
#define LEN(a) (sizeof(a)/sizeof(a)[0])
/* ===============================================================
*
* 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. */
/*#include "../style.c"*/
/*#include "../calculator.c"*/
#include "../overview.c"
/*#include "../node_editor.c"*/
* done with this library. To try out an example uncomment the defines */
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
#define INCLUDE_OVERVIEW
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
*
* DEMO
*
* ===============================================================*/
static void error_callback(int e, const char *d)
{printf("Error %d: %s\n", e, d);}
int main(void)
{
/* Platform */
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
NkAllegro5Font *font;
struct nk_context *ctx;
if (!al_init()) {
fprintf(stdout, "failed to initialize allegro5!\n");
@ -85,25 +110,32 @@ int main(void)
al_register_event_source(event_queue, al_get_mouse_event_source());
al_register_event_source(event_queue, al_get_keyboard_event_source());
NkAllegro5Font *font;
font = nk_allegro5_font_create_from_file("../../../extra_font/Roboto-Regular.ttf", 12, 0);
struct nk_context *ctx;
ctx = nk_allegro5_init(font, display, WINDOW_WIDTH, WINDOW_HEIGHT);
/* style.c */
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
#ifdef INCLUDE_STYLE
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
while(1)
{
bool get_event;
ALLEGRO_EVENT ev;
ALLEGRO_TIMEOUT timeout;
al_init_timeout(&timeout, 0.06);
bool get_event = al_wait_for_event_until(event_queue, &ev, &timeout);
get_event = al_wait_for_event_until(event_queue, &ev, &timeout);
if (get_event && ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
@ -141,9 +173,18 @@ int main(void)
nk_end(ctx);
/* -------------- EXAMPLES ---------------- */
/*calculator(ctx);*/
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
/*node_editor(ctx);*/
#endif
#ifdef INCLUDE_NODE_EDITOR
node_editor(ctx);
#endif
/* ----------------------------------------- */
/* Draw */

View File

@ -70,18 +70,20 @@ static struct nk_allegro5 {
NK_API struct nk_image* nk_allegro5_create_image(const char* file_name)
{
ALLEGRO_BITMAP *bitmap;
struct nk_image *image;
if (!al_init_image_addon()) {
fprintf(stdout, "Unable to initialize required allegro5 image addon\n");
exit(1);
}
ALLEGRO_BITMAP* bitmap = al_load_bitmap(file_name);
bitmap = al_load_bitmap(file_name);
if (bitmap == NULL) {
fprintf(stdout, "Unable to load image file: %s\n", file_name);
return NULL;
}
struct nk_image *image = (struct nk_image*)calloc(1, sizeof(struct nk_image));
image = (struct nk_image*)calloc(1, sizeof(struct nk_image));
image->handle.ptr = bitmap;
image->w = al_get_bitmap_width(bitmap);
image->h = al_get_bitmap_height(bitmap);
@ -98,7 +100,10 @@ NK_API void nk_allegro5_del_image(struct nk_image* image)
static float
nk_allegro5_font_get_text_width(nk_handle handle, float height, const char *text, int len)
{
float width;
char *strcpy;
NkAllegro5Font *font = (NkAllegro5Font*)handle.ptr;
NK_UNUSED(height);
if (!font || !text) {
return 0;
}
@ -106,16 +111,19 @@ nk_allegro5_font_get_text_width(nk_handle handle, float height, const char *text
as nuklear uses variable size buffers and al_get_text_width doesn't
accept a length, it infers length from null-termination
(which is unsafe API design by allegro devs!) */
char strcpy[len+1];
strncpy((char*)&strcpy, text, len);
strcpy = malloc(len + 1);
strncpy(strcpy, text, len);
strcpy[len] = '\0';
return al_get_text_width(font->font, strcpy);
width = al_get_text_width(font->font, strcpy);
free(strcpy);
return width;
}
/* Flags are identical to al_load_font() flags argument */
NK_API NkAllegro5Font*
nk_allegro5_font_create_from_file(const char *file_name, int font_size, int flags)
{
NkAllegro5Font *font;
if (!al_init_image_addon()) {
fprintf(stdout, "Unable to initialize required allegro5 image addon\n");
exit(1);
@ -128,7 +136,7 @@ nk_allegro5_font_create_from_file(const char *file_name, int font_size, int flag
fprintf(stdout, "Unable to initialize required allegro5 TTF font addon\n");
exit(1);
}
NkAllegro5Font *font = (NkAllegro5Font*)calloc(1, sizeof(NkAllegro5Font));
font = (NkAllegro5Font*)calloc(1, sizeof(NkAllegro5Font));
font->font = al_load_font(file_name, font_size, flags);
if (font->font == NULL) {
@ -200,18 +208,18 @@ nk_allegro5_render()
(float)r->rounding, color);
} break;
case NK_COMMAND_CIRCLE: {
float xr, yr;
const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
color = nk_color_to_allegro_color(c->color);
float xr, yr;
xr = (float)c->w/2;
yr = (float)c->h/2;
al_draw_ellipse(((float)(c->x)) + xr, ((float)c->y) + yr,
xr, yr, color, (float)c->line_thickness);
} break;
case NK_COMMAND_CIRCLE_FILLED: {
float xr, yr;
const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
color = nk_color_to_allegro_color(c->color);
float xr, yr;
xr = (float)c->w/2;
yr = (float)c->h/2;
al_draw_filled_ellipse(((float)(c->x)) + xr, ((float)c->y) + yr,
@ -230,54 +238,61 @@ nk_allegro5_render()
(float)t->b.y, (float)t->c.x, (float)t->c.y, color);
} break;
case NK_COMMAND_POLYGON: {
const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd;
color = nk_color_to_allegro_color(p->color);
int i;
float vertices[p->point_count * 2];
float *vertices;
const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd;
vertices = calloc(p->point_count * 2, sizeof(float));
color = nk_color_to_allegro_color(p->color);
for (i = 0; i < p->point_count; i++) {
vertices[i*2] = p->points[i].x;
vertices[(i*2) + 1] = p->points[i].y;
}
al_draw_polyline((const float*)&vertices, (2 * sizeof(float)),
al_draw_polyline(vertices, (2 * sizeof(float)),
(int)p->point_count, ALLEGRO_LINE_JOIN_ROUND, ALLEGRO_LINE_CAP_CLOSED,
color, (float)p->line_thickness, 0.0);
free(vertices);
} break;
case NK_COMMAND_POLYGON_FILLED: {
int i, j = 0;
float *vertices;
const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
vertices = calloc(p->point_count * 2, sizeof(float));
color = nk_color_to_allegro_color(p->color);
int i;
float vertices[p->point_count * 2];
for (i = 0; i < p->point_count; i++) {
vertices[i*2] = p->points[i].x;
vertices[(i*2) + 1] = p->points[i].y;
for (i = p->point_count - 1; i >= 0; i--) {
vertices[j++] = p->points[i].x;
vertices[j++] = p->points[i].y;
}
al_draw_filled_polygon((const float*)&vertices, (int)p->point_count, color);
al_draw_filled_polygon(vertices, (int)p->point_count, color);
free(vertices);
} break;
case NK_COMMAND_POLYLINE: {
const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
color = nk_color_to_allegro_color(p->color);
int i;
float vertices[p->point_count * 2];
float *vertices;
const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
vertices = calloc(p->point_count * 2, sizeof(float));
color = nk_color_to_allegro_color(p->color);
for (i = 0; i < p->point_count; i++) {
vertices[i*2] = p->points[i].x;
vertices[(i*2) + 1] = p->points[i].y;
}
al_draw_polyline((const float*)&vertices, (2 * sizeof(float)),
al_draw_polyline(vertices, (2 * sizeof(float)),
(int)p->point_count, ALLEGRO_LINE_JOIN_ROUND, ALLEGRO_LINE_CAP_ROUND,
color, (float)p->line_thickness, 0.0);
free(vertices);
} break;
case NK_COMMAND_TEXT: {
NkAllegro5Font *font;
const struct nk_command_text *t = (const struct nk_command_text*)cmd;
color = nk_color_to_allegro_color(t->foreground);
NkAllegro5Font *font = (NkAllegro5Font*)t->font->userdata.ptr;
font = (NkAllegro5Font*)t->font->userdata.ptr;
al_draw_text(font->font,
color, (float)t->x, (float)t->y, 0,
(const char*)t->string);
} break;
case NK_COMMAND_CURVE: {
float points[8];
const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
color = nk_color_to_allegro_color(q->color);
float points[8];
points[0] = (float)q->begin.x;
points[1] = (float)q->begin.y;
points[2] = (float)q->ctrl[0].x;
@ -291,15 +306,20 @@ nk_allegro5_render()
case NK_COMMAND_ARC: {
const struct nk_command_arc *a = (const struct nk_command_arc *)cmd;
color = nk_color_to_allegro_color(a->color);
al_draw_arc((float)a->cx, (float)a->cy, (float)a->r, a->a[0],
al_draw_pieslice((float)a->cx, (float)a->cy, (float)a->r, a->a[0],
a->a[1], color, (float)a->line_thickness);
} break;
case NK_COMMAND_ARC_FILLED: {
const struct nk_command_arc_filled *a = (const struct nk_command_arc_filled *)cmd;
color = nk_color_to_allegro_color(a->color);
al_draw_filled_pieslice((float)a->cx, (float)a->cy, (float)a->r, a->a[0],
a->a[1], color);
} break;
case NK_COMMAND_IMAGE: {
const struct nk_command_image *i = (const struct nk_command_image *)cmd;
al_draw_bitmap_region(i->img.handle.ptr, 0, 0, i->w, i->h, i->x, i->y, 0);
} break;
case NK_COMMAND_RECT_MULTI_COLOR:
case NK_COMMAND_ARC_FILLED:
default: break;
}
}
@ -465,12 +485,13 @@ NK_API struct nk_context*
nk_allegro5_init(NkAllegro5Font *allegro5font, ALLEGRO_DISPLAY *dsp,
unsigned int width, unsigned int height)
{
struct nk_user_font *font;
if (!al_init_primitives_addon()) {
fprintf(stdout, "Unable to initialize required allegro5 primitives addon\n");
exit(1);
}
struct nk_user_font *font = &allegro5font->nk;
font = &allegro5font->nk;
allegro5.dsp = dsp;
allegro5.width = width;

105
demo/common/canvas.c Normal file
View File

@ -0,0 +1,105 @@
/* nuklear - v1.05 - public domain */
struct nk_canvas {
struct nk_command_buffer *painter;
struct nk_vec2 item_spacing;
struct nk_vec2 panel_padding;
struct nk_style_item window_background;
};
static nk_bool
canvas_begin(struct nk_context *ctx, struct nk_canvas *canvas, nk_flags flags,
int x, int y, int width, int height, struct nk_color background_color)
{
/* save style properties which will be overwritten */
canvas->panel_padding = ctx->style.window.padding;
canvas->item_spacing = ctx->style.window.spacing;
canvas->window_background = ctx->style.window.fixed_background;
/* use the complete window space and set background */
ctx->style.window.spacing = nk_vec2(0,0);
ctx->style.window.padding = nk_vec2(0,0);
ctx->style.window.fixed_background = nk_style_item_color(background_color);
/* create/update window and set position + size */
if (!nk_begin(ctx, "Canvas", nk_rect(x, y, width, height), NK_WINDOW_NO_SCROLLBAR|flags))
return nk_false;
/* allocate the complete window space for drawing */
{
struct nk_rect total_space;
total_space = nk_window_get_content_region(ctx);
nk_layout_row_dynamic(ctx, total_space.h, 1);
nk_widget(&total_space, ctx);
canvas->painter = nk_window_get_canvas(ctx);
}
return nk_true;
}
static void
canvas_end(struct nk_context *ctx, struct nk_canvas *canvas)
{
nk_end(ctx);
ctx->style.window.spacing = canvas->panel_padding;
ctx->style.window.padding = canvas->item_spacing;
ctx->style.window.fixed_background = canvas->window_background;
}
static void
canvas(struct nk_context *ctx)
{
struct nk_canvas canvas;
if (canvas_begin(ctx, &canvas, NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|
NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE, 10, 10, 500, 550, nk_rgb(250,250,250)))
{
float x = canvas.painter->clip.x, y = canvas.painter->clip.y;
nk_fill_rect(canvas.painter, nk_rect(x + 15, y + 15, 210, 210), 5, nk_rgb(247, 230, 154));
nk_fill_rect(canvas.painter, nk_rect(x + 20, y + 20, 200, 200), 5, nk_rgb(188, 174, 118));
/* nk_draw_text(canvas.painter, nk_rect(x + 30, y + 30, 150, 20), "Text to draw", 12, &font->handle, nk_rgb(188,174,118), nk_rgb(0,0,0)); */
nk_fill_rect(canvas.painter, nk_rect(x + 250, y + 20, 100, 100), 0, nk_rgb(0,0,255));
nk_fill_circle(canvas.painter, nk_rect(x + 20, y + 250, 100, 100), nk_rgb(255,0,0));
nk_fill_triangle(canvas.painter, x + 250, y + 250, x + 350, y + 250, x + 300, y + 350, nk_rgb(0,255,0));
nk_fill_arc(canvas.painter, x + 300, y + 420, 50, 0, 3.141592654f * 3.0f / 4.0f, nk_rgb(255,255,0));
{
float points[12];
points[0] = x + 200; points[1] = y + 250;
points[2] = x + 250; points[3] = y + 350;
points[4] = x + 225; points[5] = y + 350;
points[6] = x + 200; points[7] = y + 300;
points[8] = x + 175; points[9] = y + 350;
points[10] = x + 150; points[11] = y + 350;
nk_fill_polygon(canvas.painter, points, 6, nk_rgb(0,0,0));
}
{
float points[12];
points[0] = x + 200; points[1] = y + 370;
points[2] = x + 250; points[3] = y + 470;
points[4] = x + 225; points[5] = y + 470;
points[6] = x + 200; points[7] = y + 420;
points[8] = x + 175; points[9] = y + 470;
points[10] = x + 150; points[11] = y + 470;
nk_stroke_polygon(canvas.painter, points, 6, 4, nk_rgb(0,0,0));
}
{
float points[8];
points[0] = x + 250; points[1] = y + 200;
points[2] = x + 275; points[3] = y + 220;
points[4] = x + 325; points[5] = y + 170;
points[6] = x + 350; points[7] = y + 200;
nk_stroke_polyline(canvas.painter, points, 4, 2, nk_rgb(255,128,0));
}
nk_stroke_line(canvas.painter, x + 15, y + 10, x + 200, y + 10, 2.0f, nk_rgb(189,45,75));
nk_stroke_rect(canvas.painter, nk_rect(x + 370, y + 20, 100, 100), 10, 3, nk_rgb(0,0,255));
nk_stroke_curve(canvas.painter, x + 380, y + 200, x + 405, y + 270, x + 455, y + 120, x + 480, y + 200, 2, nk_rgb(0,150,220));
nk_stroke_circle(canvas.painter, nk_rect(x + 20, y + 370, 100, 100), 5, nk_rgb(0,255,120));
nk_stroke_triangle(canvas.painter, x + 370, y + 250, x + 470, y + 250, x + 420, y + 350, 6, nk_rgb(255,0,143));
nk_stroke_arc(canvas.painter, x + 420, y + 420, 50, 0, 3.141592654f * 3.0f / 4.0f, 5, nk_rgb(0,255,255));
}
canvas_end(ctx, &canvas);
}

511
demo/common/file_browser.c Normal file
View File

@ -0,0 +1,511 @@
#include <string.h> // strcpy, strlen
#ifdef __unix__
#include <dirent.h>
#include <unistd.h>
#endif
#ifndef _WIN32
# include <pwd.h>
#endif
struct icons {
struct nk_image desktop;
struct nk_image home;
struct nk_image computer;
struct nk_image directory;
struct nk_image default_file;
struct nk_image text_file;
struct nk_image music_file;
struct nk_image font_file;
struct nk_image img_file;
struct nk_image movie_file;
};
enum file_groups {
FILE_GROUP_DEFAULT,
FILE_GROUP_TEXT,
FILE_GROUP_MUSIC,
FILE_GROUP_FONT,
FILE_GROUP_IMAGE,
FILE_GROUP_MOVIE,
FILE_GROUP_MAX
};
enum file_types {
FILE_DEFAULT,
FILE_TEXT,
FILE_C_SOURCE,
FILE_CPP_SOURCE,
FILE_HEADER,
FILE_CPP_HEADER,
FILE_MP3,
FILE_WAV,
FILE_OGG,
FILE_TTF,
FILE_BMP,
FILE_PNG,
FILE_JPEG,
FILE_PCX,
FILE_TGA,
FILE_GIF,
FILE_MAX
};
struct file_group {
enum file_groups group;
const char *name;
struct nk_image *icon;
};
struct file {
enum file_types type;
const char *suffix;
enum file_groups group;
};
struct media {
int font;
int icon_sheet;
struct icons icons;
struct file_group group[FILE_GROUP_MAX];
struct file files[FILE_MAX];
};
#define MAX_PATH_LEN 512
struct file_browser {
/* path */
char file[MAX_PATH_LEN];
char home[MAX_PATH_LEN];
char desktop[MAX_PATH_LEN];
char directory[MAX_PATH_LEN];
/* directory content */
char **files;
char **directories;
size_t file_count;
size_t dir_count;
struct media *media;
};
static void
die(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fputs("\n", stderr);
exit(EXIT_FAILURE);
}
static struct nk_image
icon_load(const char *filename)
{
int x,y,n;
GLuint tex;
unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
if (!data) die("[SDL]: failed to load image: %s", filename);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
stbi_image_free(data);
return nk_image_id((int)tex);
}
#if 0
static char*
file_load(const char* path, size_t* siz)
{
char *buf;
FILE *fd = fopen(path, "rb");
if (!fd) die("Failed to open file: %s\n", path);
fseek(fd, 0, SEEK_END);
*siz = (size_t)ftell(fd);
fseek(fd, 0, SEEK_SET);
buf = (char*)calloc(*siz, 1);
fread(buf, *siz, 1, fd);
fclose(fd);
return buf;
}
#endif
static char*
str_duplicate(const char *src)
{
char *ret;
size_t len = strlen(src);
if (!len) return 0;
ret = (char*)malloc(len+1);
if (!ret) return 0;
memcpy(ret, src, len);
ret[len] = '\0';
return ret;
}
static void
dir_free_list(char **list, size_t size)
{
size_t i;
for (i = 0; i < size; ++i)
free(list[i]);
free(list);
}
static char**
dir_list(const char *dir, int return_subdirs, size_t *count)
{
size_t n = 0;
char buffer[MAX_PATH_LEN];
char **results = NULL;
const DIR *none = NULL;
size_t capacity = 32;
size_t size;
DIR *z;
assert(dir);
assert(count);
strncpy(buffer, dir, MAX_PATH_LEN);
buffer[MAX_PATH_LEN - 1] = 0;
n = strlen(buffer);
if (n > 0 && (buffer[n-1] != '/'))
buffer[n++] = '/';
size = 0;
z = opendir(dir);
if (z != none) {
int nonempty = 1;
struct dirent *data = readdir(z);
nonempty = (data != NULL);
if (!nonempty) return NULL;
do {
DIR *y;
char *p;
int is_subdir;
if (data->d_name[0] == '.')
continue;
strncpy(buffer + n, data->d_name, MAX_PATH_LEN-n);
y = opendir(buffer);
is_subdir = (y != NULL);
if (y != NULL) closedir(y);
if ((return_subdirs && is_subdir) || (!is_subdir && !return_subdirs)){
if (!size) {
results = (char**)calloc(sizeof(char*), capacity);
} else if (size >= capacity) {
void *old = results;
capacity = capacity * 2;
results = (char**)realloc(results, capacity * sizeof(char*));
assert(results);
if (!results) free(old);
}
p = str_duplicate(data->d_name);
results[size++] = p;
}
} while ((data = readdir(z)) != NULL);
}
if (z) closedir(z);
*count = size;
return results;
}
static struct file_group
FILE_GROUP(enum file_groups group, const char *name, struct nk_image *icon)
{
struct file_group fg;
fg.group = group;
fg.name = name;
fg.icon = icon;
return fg;
}
static struct file
FILE_DEF(enum file_types type, const char *suffix, enum file_groups group)
{
struct file fd;
fd.type = type;
fd.suffix = suffix;
fd.group = group;
return fd;
}
static struct nk_image*
media_icon_for_file(struct media *media, const char *file)
{
int i = 0;
const char *s = file;
char suffix[4];
int found = 0;
memset(suffix, 0, sizeof(suffix));
/* extract suffix .xxx from file */
while (*s++ != '\0') {
if (found && i < 3)
suffix[i++] = *s;
if (*s == '.') {
if (found){
found = 0;
break;
}
found = 1;
}
}
/* check for all file definition of all groups for fitting suffix*/
for (i = 0; i < FILE_MAX && found; ++i) {
struct file *d = &media->files[i];
{
const char *f = d->suffix;
s = suffix;
while (f && *f && *s && *s == *f) {
s++; f++;
}
/* found correct file definition so */
if (f && *s == '\0' && *f == '\0')
return media->group[d->group].icon;
}
}
return &media->icons.default_file;
}
static void
media_init(struct media *media)
{
/* file groups */
struct icons *icons = &media->icons;
media->group[FILE_GROUP_DEFAULT] = FILE_GROUP(FILE_GROUP_DEFAULT,"default",&icons->default_file);
media->group[FILE_GROUP_TEXT] = FILE_GROUP(FILE_GROUP_TEXT, "textual", &icons->text_file);
media->group[FILE_GROUP_MUSIC] = FILE_GROUP(FILE_GROUP_MUSIC, "music", &icons->music_file);
media->group[FILE_GROUP_FONT] = FILE_GROUP(FILE_GROUP_FONT, "font", &icons->font_file);
media->group[FILE_GROUP_IMAGE] = FILE_GROUP(FILE_GROUP_IMAGE, "image", &icons->img_file);
media->group[FILE_GROUP_MOVIE] = FILE_GROUP(FILE_GROUP_MOVIE, "movie", &icons->movie_file);
/* files */
media->files[FILE_DEFAULT] = FILE_DEF(FILE_DEFAULT, NULL, FILE_GROUP_DEFAULT);
media->files[FILE_TEXT] = FILE_DEF(FILE_TEXT, "txt", FILE_GROUP_TEXT);
media->files[FILE_C_SOURCE] = FILE_DEF(FILE_C_SOURCE, "c", FILE_GROUP_TEXT);
media->files[FILE_CPP_SOURCE] = FILE_DEF(FILE_CPP_SOURCE, "cpp", FILE_GROUP_TEXT);
media->files[FILE_HEADER] = FILE_DEF(FILE_HEADER, "h", FILE_GROUP_TEXT);
media->files[FILE_CPP_HEADER] = FILE_DEF(FILE_HEADER, "hpp", FILE_GROUP_TEXT);
media->files[FILE_MP3] = FILE_DEF(FILE_MP3, "mp3", FILE_GROUP_MUSIC);
media->files[FILE_WAV] = FILE_DEF(FILE_WAV, "wav", FILE_GROUP_MUSIC);
media->files[FILE_OGG] = FILE_DEF(FILE_OGG, "ogg", FILE_GROUP_MUSIC);
media->files[FILE_TTF] = FILE_DEF(FILE_TTF, "ttf", FILE_GROUP_FONT);
media->files[FILE_BMP] = FILE_DEF(FILE_BMP, "bmp", FILE_GROUP_IMAGE);
media->files[FILE_PNG] = FILE_DEF(FILE_PNG, "png", FILE_GROUP_IMAGE);
media->files[FILE_JPEG] = FILE_DEF(FILE_JPEG, "jpg", FILE_GROUP_IMAGE);
media->files[FILE_PCX] = FILE_DEF(FILE_PCX, "pcx", FILE_GROUP_IMAGE);
media->files[FILE_TGA] = FILE_DEF(FILE_TGA, "tga", FILE_GROUP_IMAGE);
media->files[FILE_GIF] = FILE_DEF(FILE_GIF, "gif", FILE_GROUP_IMAGE);
}
static void
file_browser_reload_directory_content(struct file_browser *browser, const char *path)
{
strncpy(browser->directory, path, MAX_PATH_LEN);
browser->directory[MAX_PATH_LEN - 1] = 0;
dir_free_list(browser->files, browser->file_count);
dir_free_list(browser->directories, browser->dir_count);
browser->files = dir_list(path, 0, &browser->file_count);
browser->directories = dir_list(path, 1, &browser->dir_count);
}
static void
file_browser_init(struct file_browser *browser, struct media *media)
{
memset(browser, 0, sizeof(*browser));
browser->media = media;
{
/* load files and sub-directory list */
const char *home = getenv("HOME");
#ifdef _WIN32
if (!home) home = getenv("USERPROFILE");
#else
if (!home) home = getpwuid(getuid())->pw_dir;
{
size_t l;
strncpy(browser->home, home, MAX_PATH_LEN);
browser->home[MAX_PATH_LEN - 1] = 0;
l = strlen(browser->home);
strcpy(browser->home + l, "/");
strcpy(browser->directory, browser->home);
}
#endif
{
size_t l;
strcpy(browser->desktop, browser->home);
l = strlen(browser->desktop);
strcpy(browser->desktop + l, "desktop/");
}
browser->files = dir_list(browser->directory, 0, &browser->file_count);
browser->directories = dir_list(browser->directory, 1, &browser->dir_count);
}
}
static void
file_browser_free(struct file_browser *browser)
{
if (browser->files)
dir_free_list(browser->files, browser->file_count);
if (browser->directories)
dir_free_list(browser->directories, browser->dir_count);
browser->files = NULL;
browser->directories = NULL;
memset(browser, 0, sizeof(*browser));
}
int cmp_fn(const void *str1, const void *str2)
{
const char *str1_ret = *(const char **)str1;
const char *str2_ret = *(const char **)str2;
return nk_stricmp(str1_ret, str2_ret);
}
static int
file_browser_run(struct file_browser *browser, struct nk_context *ctx)
{
int ret = 0;
struct media *media = browser->media;
struct nk_rect total_space;
static nk_bool file_browser_is_open = nk_true;
if (file_browser_is_open)
{
if (nk_begin(ctx, "File Browser", nk_rect(50, 50, 600, 400),
NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE|NK_WINDOW_NO_SCROLLBAR|
NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE))
{
static float ratio[] = {0.25f, NK_UNDEFINED};
float spacing_x = ctx->style.window.spacing.x;
/* output path directory selector in the menubar */
ctx->style.window.spacing.x = 0;
nk_menubar_begin(ctx);
{
char *d = browser->directory;
char *begin = d + 1;
nk_layout_row_dynamic(ctx, 25, 6);
while (*d++) {
if (*d == '/') {
*d = '\0';
if (nk_button_label(ctx, begin)) {
*d++ = '/'; *d = '\0';
file_browser_reload_directory_content(browser, browser->directory);
break;
}
*d = '/';
begin = d + 1;
}
}
}
nk_menubar_end(ctx);
ctx->style.window.spacing.x = spacing_x;
/* window layout */
total_space = nk_window_get_content_region(ctx);
nk_layout_row(ctx, NK_DYNAMIC, total_space.h - 40, 2, ratio);
nk_group_begin(ctx, "Special", NK_WINDOW_NO_SCROLLBAR);
{
struct nk_image home = media->icons.home;
struct nk_image desktop = media->icons.desktop;
struct nk_image computer = media->icons.computer;
nk_layout_row_dynamic(ctx, 40, 1);
if (nk_button_image_label(ctx, home, "home", NK_TEXT_CENTERED))
file_browser_reload_directory_content(browser, browser->home);
if (nk_button_image_label(ctx,desktop,"desktop",NK_TEXT_CENTERED))
file_browser_reload_directory_content(browser, browser->desktop);
if (nk_button_image_label(ctx,computer,"computer",NK_TEXT_CENTERED))
file_browser_reload_directory_content(browser, "/");
nk_group_end(ctx);
}
/* output directory content window */
nk_group_begin(ctx, "Content", NK_WINDOW_BORDER);
{
int index = -1;
size_t i = 0, j = 0;
size_t rows = 0, cols = 0;
size_t count = browser->dir_count + browser->file_count;
/* File icons layout */
cols = 2;
rows = count / cols;
static float ratio2[] = {0.08f, NK_UNDEFINED};
nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio2);
for (i = 0; i <= rows; i += 1) {
size_t n = j + cols;
for (; j < count && j < n; ++j) {
/* draw one column of icons */
if (j < browser->dir_count) {
/* draw and execute directory buttons */
if (nk_button_image(ctx,media->icons.directory))
index = (int)j;
qsort(browser->directories, browser->dir_count, sizeof(char *), cmp_fn);
nk_label(ctx, browser->directories[j], NK_TEXT_LEFT);
} else {
/* draw and execute files buttons */
struct nk_image *icon;
size_t fileIndex = ((size_t)j - browser->dir_count);
icon = media_icon_for_file(media,browser->files[fileIndex]);
if (nk_button_image(ctx, *icon)) {
strncpy(browser->file, browser->directory, MAX_PATH_LEN);
n = strlen(browser->file);
strncpy(browser->file + n, browser->files[fileIndex], MAX_PATH_LEN - n);
ret = 1;
}
}
/* draw one column of labels */
if (j >= browser->dir_count) {
size_t t = j - browser->dir_count;
qsort(browser->files, browser->file_count, sizeof(char *), cmp_fn);
nk_label(ctx,browser->files[t],NK_TEXT_LEFT);
}
}
}
if (index != -1) {
size_t n = strlen(browser->directory);
strncpy(browser->directory + n, browser->directories[index], MAX_PATH_LEN - n);
n = strlen(browser->directory);
if (n < MAX_PATH_LEN - 1) {
browser->directory[n] = '/';
browser->directory[n+1] = '\0';
}
file_browser_reload_directory_content(browser, browser->directory);
}
nk_group_end(ctx);
}
nk_layout_row_dynamic(ctx, 30, 5);
nk_label(ctx,"",NK_TEXT_LEFT);
nk_label(ctx,"",NK_TEXT_LEFT);
nk_label(ctx,"",NK_TEXT_LEFT);
if(nk_button_label(ctx, "Cancel"))
{
fprintf(stdout, "File dialog has been closed!\n");
file_browser_is_open = nk_false;
}
if(nk_button_label(ctx, "Open"))
fprintf(stdout, "Insert routine to open/save the file!\n");
}
nk_end(ctx);
}
return ret;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because it is too large Load Diff

View File

@ -199,7 +199,7 @@ overview(struct nk_context *ctx)
/* Basic widgets */
static int int_slider = 5;
static float float_slider = 2.5f;
static size_t prog_value = 40;
static nk_size prog_value = 40;
static float property_float = 2;
static int property_int = 10;
static int property_neg = 10;
@ -226,7 +226,7 @@ overview(struct nk_context *ctx)
nk_label(ctx, "Slider float", NK_TEXT_LEFT);
nk_slider_float(ctx, 0, &float_slider, 5.0, 0.5f);
nk_labelf(ctx, NK_TEXT_LEFT, "Progressbar: %zu" , prog_value);
nk_labelf(ctx, NK_TEXT_LEFT, "Progressbar: %u" , (int)prog_value);
nk_progress(ctx, &prog_value, 100, NK_MODIFIABLE);
nk_layout_row(ctx, NK_STATIC, 25, 2, ratio);
@ -623,13 +623,11 @@ overview(struct nk_context *ctx)
int i;
int index = -1;
struct nk_rect bounds;
/* line chart */
id = 0;
index = -1;
nk_layout_row_dynamic(ctx, 100, 1);
bounds = nk_widget_bounds(ctx);
if (nk_chart_begin(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f)) {
for (i = 0; i < 32; ++i) {
nk_flags res = nk_chart_push(ctx, (float)cos(id));
@ -651,7 +649,6 @@ overview(struct nk_context *ctx)
/* column chart */
nk_layout_row_dynamic(ctx, 100, 1);
bounds = nk_widget_bounds(ctx);
if (nk_chart_begin(ctx, NK_CHART_COLUMN, 32, 0.0f, 1.0f)) {
for (i = 0; i < 32; ++i) {
nk_flags res = nk_chart_push(ctx, (float)fabs(sin(id)));
@ -672,7 +669,6 @@ overview(struct nk_context *ctx)
/* mixed chart */
nk_layout_row_dynamic(ctx, 100, 1);
bounds = nk_widget_bounds(ctx);
if (nk_chart_begin(ctx, NK_CHART_COLUMN, 32, 0.0f, 1.0f)) {
nk_chart_add_slot(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f);
nk_chart_add_slot(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f);
@ -687,7 +683,6 @@ overview(struct nk_context *ctx)
/* mixed colored chart */
nk_layout_row_dynamic(ctx, 100, 1);
bounds = nk_widget_bounds(ctx);
if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) {
nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f);
nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,255,0), nk_rgb(0,150,0), 32, -1.0f, 1.0f);
@ -765,7 +760,7 @@ overview(struct nk_context *ctx)
if (nk_popup_begin(ctx, NK_POPUP_STATIC, "Error", 0, s))
{
nk_layout_row_dynamic(ctx, 25, 1);
nk_label(ctx, "A terrible error as occured", NK_TEXT_LEFT);
nk_label(ctx, "A terrible error as occurred", NK_TEXT_LEFT);
nk_layout_row_dynamic(ctx, 25, 2);
if (nk_button_label(ctx, "OK")) {
popup_active = 0;
@ -946,7 +941,6 @@ overview(struct nk_context *ctx)
if (nk_tree_push(ctx, NK_TREE_NODE, "Notebook", NK_MINIMIZED))
{
static int current_tab = 0;
struct nk_rect bounds;
float step = (2*3.141592654f) / 32;
enum chart_type {CHART_LINE, CHART_HISTO, CHART_MIXED};
const char *names[] = {"Lines", "Columns", "Mixed"};
@ -982,7 +976,6 @@ overview(struct nk_context *ctx)
default: break;
case CHART_LINE:
nk_layout_row_dynamic(ctx, 100, 1);
bounds = nk_widget_bounds(ctx);
if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) {
nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f);
for (i = 0, id = 0; i < 32; ++i) {
@ -995,7 +988,6 @@ overview(struct nk_context *ctx)
break;
case CHART_HISTO:
nk_layout_row_dynamic(ctx, 100, 1);
bounds = nk_widget_bounds(ctx);
if (nk_chart_begin_colored(ctx, NK_CHART_COLUMN, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) {
for (i = 0, id = 0; i < 32; ++i) {
nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0);
@ -1006,7 +998,6 @@ overview(struct nk_context *ctx)
break;
case CHART_MIXED:
nk_layout_row_dynamic(ctx, 100, 1);
bounds = nk_widget_bounds(ctx);
if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) {
nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f);
nk_chart_add_slot_colored(ctx, NK_CHART_COLUMN, nk_rgb(0,255,0), nk_rgb(0,150,0), 32, 0.0f, 1.0f);

View File

@ -36,27 +36,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -205,10 +210,16 @@ int main(void)
/* style.c */
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
@ -264,6 +275,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -61,7 +61,7 @@ static struct
struct nk_font_atlas atlas;
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
unsigned int max_vertex_buffer;
unsigned int max_index_buffer;
@ -137,7 +137,7 @@ nk_d3d11_render(ID3D11DeviceContext *context, enum nk_anti_aliasing AA)
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.null = d3d11.null;
config.tex_null = d3d11.tex_null;
{/* setup buffers to load vertices and elements */
struct nk_buffer vbuf, ibuf;
@ -179,11 +179,15 @@ nk_d3d11_get_projection_matrix(int width, int height, float *result)
const float B = (float)height;
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 },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 0.0f },
{ (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f },
{ 0.0f, 0.0f, 0.5f, 1.0f },
};
matrix[0][0] = 2.0f / (R - L);
matrix[1][1] = 2.0f / (T - B);
matrix[3][0] = (R + L) / (L - R);
matrix[3][1] = (T + B) / (B - T);
memcpy(result, matrix, sizeof(matrix));
}
@ -599,7 +603,7 @@ nk_d3d11_font_stash_end(void)
assert(SUCCEEDED(hr));}
ID3D11Texture2D_Release(font_texture);}
nk_font_atlas_end(&d3d11.atlas, nk_handle_ptr(d3d11.font_texture_view), &d3d11.null);
nk_font_atlas_end(&d3d11.atlas, nk_handle_ptr(d3d11.font_texture_view), &d3d11.tex_null);
if (d3d11.atlas.default_font)
nk_style_set_font(&d3d11.ctx, &d3d11.atlas.default_font->handle);
}

9
demo/d3d12/build.bat Normal file
View File

@ -0,0 +1,9 @@
@echo off
rem This will use VS2015 for compiler... if you have vs 2015 and it is installed at this / the default path
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86
fxc.exe /nologo /T vs_5_1 /E vs /O3 /Zpc /Ges /Fh nuklear_d3d12_vertex_shader.h /Vn nk_d3d12_vertex_shader /Qstrip_reflect /Qstrip_debug /Qstrip_priv nuklear_d3d12.hlsl
fxc.exe /nologo /T ps_5_1 /E ps /O3 /Zpc /Ges /Fh nuklear_d3d12_pixel_shader.h /Vn nk_d3d12_pixel_shader /Qstrip_reflect /Qstrip_debug /Qstrip_priv /enable_unbounded_descriptor_tables nuklear_d3d12.hlsl
cl /D_CRT_SECURE_NO_DEPRECATE /nologo /W3 /O2 /fp:fast /Gm- /Fedemo.exe main.c user32.lib dxguid.lib dxgi.lib d3d12.lib /link /incremental:no

445
demo/d3d12/main.c Normal file
View File

@ -0,0 +1,445 @@
/* nuklear - 1.32.0 - public domain */
#define COBJMACROS
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <combaseapi.h>
#include <dxgi1_6.h>
#include <d3d12.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define USER_TEXTURES 6
#define MAX_VERTEX_BUFFER 512 * 1024
#define MAX_INDEX_BUFFER 128 * 1024
#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_D3D12_IMPLEMENTATION
#include "../../nuklear.h"
#include "nuklear_d3d12.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 defines */
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
*
* DEMO
*
* ===============================================================*/
/* DXGI & Window related device objects */
static IDXGIFactory2 *dxgi_factory;
static IDXGISwapChain1 *swap_chain;
static ID3D12DescriptorHeap *rtv_descriptor_heap;
static D3D12_CPU_DESCRIPTOR_HANDLE rtv_handles[2];
static ID3D12Resource *rtv_buffers[2];
static UINT rtv_desc_increment;
static UINT rtv_index;
/* DirectX common device objects */
static ID3D12Device *device;
static ID3D12CommandQueue *command_queue;
static ID3D12Fence *queue_fence;
static UINT64 fence_value;
static ID3D12CommandAllocator *command_allocator;
static ID3D12GraphicsCommandList *command_list;
static void signal_and_wait()
{
HRESULT hr;
/* Signal fence when execution finishes */
hr = ID3D12CommandQueue_Signal(command_queue, queue_fence, ++fence_value);
assert(SUCCEEDED(hr));
/* Wait for queue to finish */
while(ID3D12Fence_GetCompletedValue(queue_fence) != fence_value)
{
SwitchToThread(); /* Allow windows to do other work */
}
}
static void execute_commands()
{
/* Prepare command list for execution */
ID3D12GraphicsCommandList_Close(command_list);
/* Execute on command queue */
ID3D12CommandList* cmd_lists[] = { (ID3D12CommandList*)command_list};
ID3D12CommandQueue_ExecuteCommandLists(command_queue, 1, cmd_lists);
/* Wait for execution */
signal_and_wait();
/* Reset command allocator and list */
ID3D12CommandAllocator_Reset(command_allocator);
ID3D12GraphicsCommandList_Reset(command_list, command_allocator, NULL);
}
static void get_swap_chain_buffers()
{
HRESULT hr;
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_handle;
/* Get resource objects from swap chain */
hr = IDXGISwapChain1_GetBuffer(swap_chain, 0, &IID_ID3D12Resource, &rtv_buffers[0]);
assert(SUCCEEDED(hr));
hr = IDXGISwapChain1_GetBuffer(swap_chain, 1, &IID_ID3D12Resource, &rtv_buffers[1]);
assert(SUCCEEDED(hr));
/* Recreate render target views */
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(rtv_descriptor_heap, &descriptor_handle);
ID3D12Device_CreateRenderTargetView(device, rtv_buffers[0], NULL, descriptor_handle);
rtv_handles[0] = descriptor_handle;
descriptor_handle.ptr += rtv_desc_increment;
ID3D12Device_CreateRenderTargetView(device, rtv_buffers[1], NULL, descriptor_handle);
rtv_handles[1] = descriptor_handle;
}
static void
set_swap_chain_size(int width, int height)
{
HRESULT hr;
/* Wait for pending work */
signal_and_wait();
signal_and_wait(); /* Two times because we have two buffers in flight */
/* Release all open refereces to the buffers */
ID3D12Resource_Release(rtv_buffers[0]);
ID3D12Resource_Release(rtv_buffers[1]);
/* DXGI can now perform resizing */
hr = IDXGISwapChain1_ResizeBuffers(swap_chain, 2, width, height, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
assert(SUCCEEDED(hr));
/* Get references for the new resized buffers */
get_swap_chain_buffers();
/* Reset RTV index */
rtv_index = 0;
}
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 (swap_chain)
{
int width = LOWORD(lparam);
int height = HIWORD(lparam);
set_swap_chain_size(width, height);
nk_d3d12_resize(width, height);
}
break;
}
if (nk_d3d12_handle_event(wnd, msg, wparam, lparam))
return 0;
return DefWindowProcW(wnd, msg, wparam, lparam);
}
int main(void)
{
struct nk_context *ctx;
struct nk_colorf bg;
WNDCLASSW wc;
RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT };
DWORD style = WS_OVERLAPPEDWINDOW;
DWORD exstyle = WS_EX_APPWINDOW;
HWND wnd;
int running = 1;
HRESULT hr;
D3D12_COMMAND_QUEUE_DESC command_queue_desc;
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc;
D3D12_DESCRIPTOR_HEAP_DESC rtv_desc_heap_desc;
/* 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);
/* D3D12 setup */
/* Create default Device */
hr = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, &IID_ID3D12Device, &device);
assert(SUCCEEDED(hr));
/* Create a command queue */
command_queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
command_queue_desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
command_queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
command_queue_desc.NodeMask = 0;
hr = ID3D12Device_CreateCommandQueue(device, &command_queue_desc, &IID_ID3D12CommandQueue, &command_queue);
assert(SUCCEEDED(hr));
/* Create a fence for command queue executions */
fence_value = 0;
hr = ID3D12Device_CreateFence(device, fence_value, D3D12_FENCE_FLAG_NONE, &IID_ID3D12Fence, &queue_fence);
assert(SUCCEEDED(hr));
/* Create a command allocator */
hr = ID3D12Device_CreateCommandAllocator(device, D3D12_COMMAND_LIST_TYPE_DIRECT, &IID_ID3D12CommandAllocator, &command_allocator);
assert(SUCCEEDED(hr));
/* Create a command list that will use our allocator */
hr = ID3D12Device_CreateCommandList(device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, command_allocator, NULL, &IID_ID3D12GraphicsCommandList1, &command_list);
assert(SUCCEEDED(hr));
/* DXGI Setup (Swap chain & resources) */
/* Create a descriptor heap for the back buffers */
rtv_desc_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
rtv_desc_heap_desc.NumDescriptors = 2;
rtv_desc_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
rtv_desc_heap_desc.NodeMask = 0;
hr = ID3D12Device_CreateDescriptorHeap(device, &rtv_desc_heap_desc, &IID_ID3D12DescriptorHeap, &rtv_descriptor_heap);
assert(SUCCEEDED(hr));
/* Get descriptor increment */
rtv_desc_increment = ID3D12Device_GetDescriptorHandleIncrementSize(device, D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
/* Get the DXGI factory */
hr = CreateDXGIFactory1(&IID_IDXGIFactory2, &dxgi_factory);
assert(SUCCEEDED(hr));
/* Create the swap chain */
swap_chain_desc.Width = WINDOW_WIDTH;
swap_chain_desc.Height = WINDOW_HEIGHT;
swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swap_chain_desc.Stereo = 0;
swap_chain_desc.SampleDesc.Count = 1;
swap_chain_desc.SampleDesc.Quality = 0;
swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swap_chain_desc.BufferCount = 2;
swap_chain_desc.Scaling = DXGI_SCALING_STRETCH;
swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ;
swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
swap_chain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgi_factory, (IUnknown*)command_queue, wnd, &swap_chain_desc, NULL, NULL, &swap_chain);
assert(SUCCEEDED(hr));
get_swap_chain_buffers();
/* GUI */
ctx = nk_d3d12_init(device, WINDOW_WIDTH, WINDOW_HEIGHT, MAX_VERTEX_BUFFER, MAX_INDEX_BUFFER, USER_TEXTURES);
/* 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_d3d12_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_d3d12_font_stash_end(command_list);
/*nk_style_load_all_cursors(ctx, atlas->cursors);*/
/*nk_style_set_font(ctx, &droid->handle)*/;
}
/* Execute the command list to make sure all texture (font) data has been uploaded */
execute_commands();
/* Now we can cleanup all resources consumed by font stashing that are no longer used */
nk_d3d12_font_stash_cleanup();
/* style.c */
#ifdef INCLUDE_STYLE
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
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, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) {
nk_layout_row_dynamic(ctx, 120, 1);
bg = nk_color_picker(ctx, bg, NK_RGBA);
nk_layout_row_dynamic(ctx, 25, 1);
bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f);
bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f);
bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f);
bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f);
nk_combo_end(ctx);
}
}
nk_end(ctx);
/* -------------- EXAMPLES ---------------- */
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif
#ifdef INCLUDE_NODE_EDITOR
node_editor(ctx);
#endif
/* ----------------------------------------- */
/* Set rtv resource state */
D3D12_RESOURCE_BARRIER resource_barrier;
resource_barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barrier.Transition.pResource = rtv_buffers[rtv_index];
resource_barrier.Transition.Subresource = 0;
resource_barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
resource_barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
resource_barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &resource_barrier);
/* Clear and set the rtv */
ID3D12GraphicsCommandList_ClearRenderTargetView(command_list, rtv_handles[rtv_index], &bg.r, 0, NULL);
ID3D12GraphicsCommandList_OMSetRenderTargets(command_list, 1, &rtv_handles[rtv_index], FALSE, NULL);
/* Draw */
nk_d3d12_render(command_list, NK_ANTI_ALIASING_ON);
/* Bring the rtv resource back to present state */
resource_barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barrier.Transition.pResource = rtv_buffers[rtv_index];
resource_barrier.Transition.Subresource = 0;
resource_barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
resource_barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
resource_barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &resource_barrier);
/* Execute command list and wait */
execute_commands();
/* Present frame */
hr = IDXGISwapChain2_Present(swap_chain, 1, 0);
rtv_index = (rtv_index + 1) % 2;
if (hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DEVICE_REMOVED) {
/* to recover from this, you'll need to recreate device and all the resources */
MessageBoxW(NULL, L"D3D12 device is lost or removed!", L"Error", 0);
break;
} else if (hr == DXGI_STATUS_OCCLUDED) {
/* window is not visible, so vsync won't work. Let's sleep a bit to reduce CPU usage */
Sleep(10);
}
assert(SUCCEEDED(hr));
}
/* Nuklear shutdown */
nk_d3d12_shutdown();
/* D3D12 and DXGI shutdown */
signal_and_wait();
signal_and_wait(); /* Two times because we have two buffers in flight */
ID3D12Resource_Release(rtv_buffers[0]);
ID3D12Resource_Release(rtv_buffers[1]);
ID3D12DescriptorHeap_Release(rtv_descriptor_heap);
IDXGISwapChain1_Release(swap_chain);
IDXGIFactory2_Release(dxgi_factory);
ID3D12GraphicsCommandList_Release(command_list);
ID3D12CommandAllocator_Release(command_allocator);
ID3D12CommandQueue_Release(command_queue);
ID3D12Fence_Release(queue_fence);
ID3D12Device_Release(device);
/* win32 shutdown */
UnregisterClassW(wc.lpszClassName, wc.hInstance);
return 0;
}

928
demo/d3d12/nuklear_d3d12.h Normal file
View File

@ -0,0 +1,928 @@
/*
* Nuklear - 1.32.0 - public domain
* no warrenty implied; use at your own risk.
* authored from 2015-2016 by Micha Mettke
*
* D3D12 backend created by Ludwig Fuechsl (2022)
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_D3D12_H_
#define NK_D3D12_H_
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
/*
* USAGE:
* - This function will initialize a new nuklear rendering context. The context will be bound to a GLOBAL DirectX 12 rendering state.
*/
NK_API struct nk_context *nk_d3d12_init(ID3D12Device *device, int width, int height, unsigned int max_vertex_buffer, unsigned int max_index_buffer, unsigned int max_user_textures);
/*
* USAGE:
* - A call to this function prepares the global nuklear d3d12 backend for receiving font informations. Use the obtained atlas pointer to load all required fonts and do all required font setup.
*/
NK_API void nk_d3d12_font_stash_begin(struct nk_font_atlas **atlas);
/*
* USAGE:
* - Call this function after a call to nk_d3d12_font_stash_begin(...) when all fonts have been loaded and configured.
* - This function will place commands on the supplied ID3D12GraphicsCommandList.
* - This function will allocate temporary data that is required until the command list has finish executing. The temporary data can be free by calling nk_d3d12_font_stash_cleanup(...)
*/
NK_API void nk_d3d12_font_stash_end(ID3D12GraphicsCommandList *command_list);
/*
* USAGE:
* - This function will free temporary data that was allocated by nk_d3d12_font_stash_begin(...)
* - Only call this function after the command list used in the nk_d3d12_font_stash_begin(...) function call has finished executing.
* - It is NOT required to call this function but highly recommended.
*/
NK_API void nk_d3d12_font_stash_cleanup();
/*
* USAGE:
* - This function will setup the supplied texture (ID3D12Resource) for rendering custom images using the supplied D3D12_SHADER_RESOURCE_VIEW_DESC.
* - This function may override any previous calls to nk_d3d12_set_user_texture(...) while using the same index.
* - The returned handle can be used as texture handle to render custom images.
* - The caller must keep track of the state of the texture when it comes to rendering with nk_d3d12_render(...).
*/
NK_API nk_bool nk_d3d12_set_user_texture(unsigned int index, ID3D12Resource* texture, const D3D12_SHADER_RESOURCE_VIEW_DESC* description, nk_handle* handle_out);
/*
* USAGE:
* - This function should be called within the user window proc to allow nuklear to listen to window events
*/
NK_API int nk_d3d12_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
/*
* USAGE:
* - A call to this function renders any previous placed nuklear draw calls and will flush all nuklear buffers for the next frame
* - This function will place commands on the supplied ID3D12GraphicsCommandList.
* - When using custom images for rendering make sure they are in the correct resource state (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) when calling this function.
* - This function will upload data to the gpu (64 + max_vertex_buffer + max_index_buffer BYTES).
*/
NK_API void nk_d3d12_render(ID3D12GraphicsCommandList *command_list, enum nk_anti_aliasing AA);
/*
* USAGE:
* - This function will notify nuklear that the framebuffer dimensions have changed.
*/
NK_API void nk_d3d12_resize(int width, int height);
/*
* USAGE:
* - This function will free the global d3d12 rendering state.
*/
NK_API void nk_d3d12_shutdown(void);
#endif
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_D3D12_IMPLEMENTATION
#define WIN32_LEAN_AND_MEAN
#define COBJMACROS
#include <d3d12.h>
#include <stddef.h>
#include <string.h>
#include <float.h>
#include <assert.h>
#include "nuklear_d3d12_vertex_shader.h"
#include "nuklear_d3d12_pixel_shader.h"
struct nk_d3d12_vertex
{
float position[2];
float uv[2];
nk_byte col[4];
};
static struct
{
struct nk_context ctx;
struct nk_font_atlas atlas;
struct nk_buffer cmds;
struct nk_draw_null_texture tex_null;
unsigned int max_vertex_buffer;
unsigned int max_index_buffer;
unsigned int max_user_textures;
D3D12_HEAP_PROPERTIES heap_prop_default;
D3D12_HEAP_PROPERTIES heap_prop_upload;
UINT cbv_srv_uav_desc_increment;
D3D12_VIEWPORT viewport;
ID3D12Device *device;
ID3D12RootSignature *root_signature;
ID3D12PipelineState *pipeline_state;
ID3D12DescriptorHeap *desc_heap;
ID3D12Resource *font_texture;
ID3D12Resource *font_upload_buffer;
ID3D12Resource *upload_buffer;
ID3D12Resource *const_buffer;
ID3D12Resource *index_buffer;
ID3D12Resource *vertex_buffer;
D3D12_CPU_DESCRIPTOR_HANDLE cpu_descriptor_handle;
D3D12_GPU_DESCRIPTOR_HANDLE gpu_descriptor_handle;
D3D12_GPU_VIRTUAL_ADDRESS gpu_vertex_buffer_address;
D3D12_GPU_VIRTUAL_ADDRESS gpu_index_buffer_address;
} d3d12;
NK_API void
nk_d3d12_render(ID3D12GraphicsCommandList *command_list, enum nk_anti_aliasing AA)
{
HRESULT hr;
#ifdef NK_UINT_DRAW_INDEX
DXGI_FORMAT index_buffer_format = DXGI_FORMAT_R32_UINT;
#else
DXGI_FORMAT index_buffer_format = DXGI_FORMAT_R16_UINT;
#endif
const UINT stride = sizeof(struct nk_d3d12_vertex);
const struct nk_draw_command *cmd;
UINT offset = 0;
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view;
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
unsigned char* ptr_data;
D3D12_RANGE map_range;
D3D12_RESOURCE_BARRIER resource_barriers[3];
/* Activate D3D12 pipeline state and config root signature */
ID3D12GraphicsCommandList_SetPipelineState(command_list, d3d12.pipeline_state);
ID3D12GraphicsCommandList_SetGraphicsRootSignature(command_list, d3d12.root_signature);
ID3D12GraphicsCommandList_SetDescriptorHeaps(command_list, 1, &d3d12.desc_heap);
ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable(command_list, 0, d3d12.gpu_descriptor_handle);
/* Configure rendering pipeline */
ID3D12GraphicsCommandList_IASetPrimitiveTopology(command_list, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
vertex_buffer_view.BufferLocation = d3d12.gpu_vertex_buffer_address;
vertex_buffer_view.SizeInBytes = d3d12.max_vertex_buffer;
vertex_buffer_view.StrideInBytes = stride;
ID3D12GraphicsCommandList_IASetVertexBuffers(command_list, 0, 1, &vertex_buffer_view);
index_buffer_view.BufferLocation = d3d12.gpu_index_buffer_address;
index_buffer_view.Format = index_buffer_format;
index_buffer_view.SizeInBytes = d3d12.max_index_buffer;
ID3D12GraphicsCommandList_IASetIndexBuffer(command_list, &index_buffer_view);
ID3D12GraphicsCommandList_RSSetViewports(command_list, 1, &d3d12.viewport);
/* Map upload buffer to cpu accessible pointer */
map_range.Begin = sizeof(float) * 4 * 4;
map_range.End = map_range.Begin + d3d12.max_vertex_buffer + d3d12.max_index_buffer;
hr = ID3D12Resource_Map(d3d12.upload_buffer, 0, &map_range, &ptr_data);
NK_ASSERT(SUCCEEDED(hr));
/* Nuklear convert and copy to upload buffer */
{
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_d3d12_vertex, position)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d12_vertex, uv)},
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_d3d12_vertex, col)},
{NK_VERTEX_LAYOUT_END}
};
memset(&config, 0, sizeof(config));
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_d3d12_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_d3d12_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.tex_null = d3d12.tex_null;
struct nk_buffer vbuf, ibuf;
nk_buffer_init_fixed(&vbuf, &ptr_data[sizeof(float) * 4 * 4], (size_t)d3d12.max_vertex_buffer);
nk_buffer_init_fixed(&ibuf, &ptr_data[sizeof(float) * 4 * 4 + d3d12.max_vertex_buffer], (size_t)d3d12.max_index_buffer);
nk_convert(&d3d12.ctx, &d3d12.cmds, &vbuf, &ibuf, &config);
}
/* Close mapping range */
ID3D12Resource_Unmap(d3d12.upload_buffer, 0, &map_range);
/* Issue GPU resource change for copying */
resource_barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barriers[0].Transition.pResource = d3d12.const_buffer;
resource_barriers[0].Transition.Subresource = 0;
resource_barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
resource_barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
resource_barriers[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
resource_barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barriers[1].Transition.pResource = d3d12.vertex_buffer;
resource_barriers[1].Transition.Subresource = 0;
resource_barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
resource_barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
resource_barriers[1].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
resource_barriers[2].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barriers[2].Transition.pResource = d3d12.index_buffer;
resource_barriers[2].Transition.Subresource = 0;
resource_barriers[2].Transition.StateBefore = D3D12_RESOURCE_STATE_INDEX_BUFFER;
resource_barriers[2].Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST;
resource_barriers[2].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 3, resource_barriers);
/* Copy from upload buffer to gpu buffers */
ID3D12GraphicsCommandList_CopyBufferRegion(command_list, d3d12.const_buffer, 0, d3d12.upload_buffer, 0, sizeof(float) * 4 * 4);
ID3D12GraphicsCommandList_CopyBufferRegion(command_list, d3d12.vertex_buffer, 0, d3d12.upload_buffer, sizeof(float) * 4 * 4, d3d12.max_vertex_buffer);
ID3D12GraphicsCommandList_CopyBufferRegion(command_list, d3d12.index_buffer, 0, d3d12.upload_buffer, sizeof(float) * 4 * 4 + d3d12.max_vertex_buffer, d3d12.max_index_buffer);
/* Issue GPU resource change for rendering */
resource_barriers[0].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barriers[0].Transition.pResource = d3d12.const_buffer;
resource_barriers[0].Transition.Subresource = 0;
resource_barriers[0].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
resource_barriers[0].Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
resource_barriers[0].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
resource_barriers[1].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barriers[1].Transition.pResource = d3d12.vertex_buffer;
resource_barriers[1].Transition.Subresource = 0;
resource_barriers[1].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
resource_barriers[1].Transition.StateAfter = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER;
resource_barriers[1].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
resource_barriers[2].Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barriers[2].Transition.pResource = d3d12.index_buffer;
resource_barriers[2].Transition.Subresource = 0;
resource_barriers[2].Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
resource_barriers[2].Transition.StateAfter = D3D12_RESOURCE_STATE_INDEX_BUFFER;
resource_barriers[2].Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 3, resource_barriers);
/* Issue draw commands */
nk_draw_foreach(cmd, &d3d12.ctx, &d3d12.cmds)
{
D3D12_RECT scissor;
UINT32 texture_id;
/* Only place a drawcall in case the command contains drawable data */
if(cmd->elem_count)
{
/* Setup scissor rect */
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);
ID3D12GraphicsCommandList_RSSetScissorRects(command_list, 1, &scissor);
/* Setup texture (index to descriptor heap table) to use for draw call */
texture_id = (UINT32)cmd->texture.id;
ID3D12GraphicsCommandList_SetGraphicsRoot32BitConstants(command_list, 1, 1, &texture_id, 0);
/* Dispatch draw call */
ID3D12GraphicsCommandList_DrawIndexedInstanced(command_list, (UINT)cmd->elem_count, 1, offset, 0, 0);
offset += cmd->elem_count;
}
}
/* Default nuklear context and command buffer clear */
nk_clear(&d3d12.ctx);
nk_buffer_clear(&d3d12.cmds);
}
static void
nk_d3d12_get_projection_matrix(int width, int height, float *result)
{
const float L = 0.0f;
const float R = (float)width;
const float T = 0.0f;
const float B = (float)height;
float matrix[4][4] =
{
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 0.0f },
{ 0.0f, 0.0f, 0.5f, 1.0f },
};
matrix[0][0] = 2.0f / (R - L);
matrix[1][1] = 2.0f / (T - B);
matrix[3][0] = (R + L) / (L - R);
matrix[3][1] = (T + B) / (B - T);
memcpy(result, matrix, sizeof(matrix));
}
NK_API void
nk_d3d12_resize(int width, int height)
{
D3D12_RANGE map_range;
void* ptr_data;
/* Describe area to be mapped (the upload buffer region where the constant buffer / projection matrix) lives */
map_range.Begin = 0;
map_range.End = sizeof(float) * 4 * 4;
/* Map area to cpu accassible pointer (from upload buffer) */
if (SUCCEEDED(ID3D12Resource_Map(d3d12.upload_buffer, 0, &map_range, &ptr_data)))
{
/* Compute projection matrix into upload buffer */
nk_d3d12_get_projection_matrix(width, height, (float*)ptr_data);
ID3D12Resource_Unmap(d3d12.upload_buffer, 0, &map_range);
/* Update internal viewport state to relect resize changes */
d3d12.viewport.Width = (float)width;
d3d12.viewport.Height = (float)height;
}
/*
NOTE:
When mapping and copying succeeds, the data will still be in CPU sided memory
copying to the GPU is done in the nk_d3d12_render function
*/
}
NK_API int
nk_d3d12_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(&d3d12.ctx, NK_KEY_SHIFT, down);
return 1;
case VK_DELETE:
nk_input_key(&d3d12.ctx, NK_KEY_DEL, down);
return 1;
case VK_RETURN:
nk_input_key(&d3d12.ctx, NK_KEY_ENTER, down);
return 1;
case VK_TAB:
nk_input_key(&d3d12.ctx, NK_KEY_TAB, down);
return 1;
case VK_LEFT:
if (ctrl)
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_WORD_LEFT, down);
else
nk_input_key(&d3d12.ctx, NK_KEY_LEFT, down);
return 1;
case VK_RIGHT:
if (ctrl)
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else
nk_input_key(&d3d12.ctx, NK_KEY_RIGHT, down);
return 1;
case VK_BACK:
nk_input_key(&d3d12.ctx, NK_KEY_BACKSPACE, down);
return 1;
case VK_HOME:
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_START, down);
nk_input_key(&d3d12.ctx, NK_KEY_SCROLL_START, down);
return 1;
case VK_END:
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_END, down);
nk_input_key(&d3d12.ctx, NK_KEY_SCROLL_END, down);
return 1;
case VK_NEXT:
nk_input_key(&d3d12.ctx, NK_KEY_SCROLL_DOWN, down);
return 1;
case VK_PRIOR:
nk_input_key(&d3d12.ctx, NK_KEY_SCROLL_UP, down);
return 1;
case 'C':
if (ctrl) {
nk_input_key(&d3d12.ctx, NK_KEY_COPY, down);
return 1;
}
break;
case 'V':
if (ctrl) {
nk_input_key(&d3d12.ctx, NK_KEY_PASTE, down);
return 1;
}
break;
case 'X':
if (ctrl) {
nk_input_key(&d3d12.ctx, NK_KEY_CUT, down);
return 1;
}
break;
case 'Z':
if (ctrl) {
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_UNDO, down);
return 1;
}
break;
case 'R':
if (ctrl) {
nk_input_key(&d3d12.ctx, NK_KEY_TEXT_REDO, down);
return 1;
}
break;
}
return 0;
}
case WM_CHAR:
if (wparam >= 32)
{
nk_input_unicode(&d3d12.ctx, (nk_rune)wparam);
return 1;
}
break;
case WM_LBUTTONDOWN:
nk_input_button(&d3d12.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_LBUTTONUP:
nk_input_button(&d3d12.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
nk_input_button(&d3d12.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_RBUTTONDOWN:
nk_input_button(&d3d12.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_RBUTTONUP:
nk_input_button(&d3d12.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_MBUTTONDOWN:
nk_input_button(&d3d12.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_MBUTTONUP:
nk_input_button(&d3d12.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_MOUSEWHEEL:
nk_input_scroll(&d3d12.ctx, nk_vec2(0,(float)(short)HIWORD(wparam) / WHEEL_DELTA));
return 1;
case WM_MOUSEMOVE:
nk_input_motion(&d3d12.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam));
return 1;
case WM_LBUTTONDBLCLK:
nk_input_button(&d3d12.ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
return 1;
}
return 0;
}
static void
nk_d3d12_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
(void)usr;
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
{
HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
if (mem)
{
SIZE_T size = GlobalSize(mem) - 1;
if (size)
{
LPCWSTR wstr = (LPCWSTR)GlobalLock(mem);
if (wstr)
{
int utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, size / sizeof(wchar_t), NULL, 0, NULL, NULL);
if (utf8size)
{
char* utf8 = (char*)malloc(utf8size);
if (utf8)
{
WideCharToMultiByte(CP_UTF8, 0, wstr, size / sizeof(wchar_t), utf8, utf8size, NULL, NULL);
nk_textedit_paste(edit, utf8, utf8size);
free(utf8);
}
}
GlobalUnlock(mem);
}
}
}
CloseClipboard();
}
}
static void
nk_d3d12_clipboard_copy(nk_handle usr, const char *text, int len)
{
(void)usr;
if (OpenClipboard(NULL))
{
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_d3d12_init(ID3D12Device *device, int width, int height, unsigned int max_vertex_buffer, unsigned int max_index_buffer, unsigned int max_user_textures)
{
HRESULT hr;
D3D12_CONSTANT_BUFFER_VIEW_DESC cbv;
D3D12_CPU_DESCRIPTOR_HANDLE cbv_handle;
/* Do plain object / ref copys */
d3d12.max_vertex_buffer = max_vertex_buffer;
d3d12.max_index_buffer = max_index_buffer;
d3d12.max_user_textures = max_user_textures;
d3d12.device = device;
ID3D12Device_AddRef(device);
d3d12.font_texture = NULL;
d3d12.font_upload_buffer = NULL;
/* Init nuklear context */
nk_init_default(&d3d12.ctx, 0);
d3d12.ctx.clip.copy = nk_d3d12_clipboard_copy;
d3d12.ctx.clip.paste = nk_d3d12_clipboard_paste;
d3d12.ctx.clip.userdata = nk_handle_ptr(0);
/* Init nuklear buffer */
nk_buffer_init_default(&d3d12.cmds);
/* Define Heap properties */
d3d12.heap_prop_default.Type = D3D12_HEAP_TYPE_DEFAULT;
d3d12.heap_prop_default.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
d3d12.heap_prop_default.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
d3d12.heap_prop_default.CreationNodeMask = 0;
d3d12.heap_prop_default.VisibleNodeMask = 0;
d3d12.heap_prop_upload.Type = D3D12_HEAP_TYPE_UPLOAD;
d3d12.heap_prop_upload.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
d3d12.heap_prop_upload.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
d3d12.heap_prop_upload.CreationNodeMask = 0;
d3d12.heap_prop_upload.VisibleNodeMask = 0;
/* Create data objects */
/* Create upload buffer */
{
D3D12_RESOURCE_DESC desc;
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
desc.Width = (sizeof(float) * 4 * 4) + max_vertex_buffer + max_index_buffer; /* Needs to hold matrix + vertices + indicies */
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_UNKNOWN;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
hr = ID3D12Device_CreateCommittedResource(device, &d3d12.heap_prop_upload, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_SOURCE, NULL, &IID_ID3D12Resource, &d3d12.upload_buffer);
NK_ASSERT(SUCCEEDED(hr));
}
/* Create constant buffer */
{
D3D12_RESOURCE_DESC desc;
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
desc.Width = 256; /* Should be sizeof(float) * 4 * 4 - but this does not match how d3d12 works (min CBV size of 256) */
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_UNKNOWN;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
hr = ID3D12Device_CreateCommittedResource(device, &d3d12.heap_prop_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, &d3d12.const_buffer);
NK_ASSERT(SUCCEEDED(hr));
}
/* Create vertex buffer */
{
D3D12_RESOURCE_DESC desc;
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
desc.Width = max_vertex_buffer;
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_UNKNOWN;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
hr = ID3D12Device_CreateCommittedResource(device, &d3d12.heap_prop_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, &d3d12.vertex_buffer);
NK_ASSERT(SUCCEEDED(hr));
}
/* Create index buffer */
{
D3D12_RESOURCE_DESC desc;
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
desc.Width = max_index_buffer;
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_UNKNOWN;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
hr = ID3D12Device_CreateCommittedResource(device, &d3d12.heap_prop_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, &d3d12.index_buffer);
NK_ASSERT(SUCCEEDED(hr));
}
/* Create descriptor heap for shader root signature */
{
D3D12_DESCRIPTOR_HEAP_DESC desc;
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
desc.NumDescriptors = 2 + max_user_textures;
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
desc.NodeMask = 0;
ID3D12Device_CreateDescriptorHeap(device, &desc, &IID_ID3D12DescriptorHeap, &d3d12.desc_heap);
}
/* Get address of first handle (CPU and GPU) */
ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart(d3d12.desc_heap, &d3d12.cpu_descriptor_handle);
ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart(d3d12.desc_heap, &d3d12.gpu_descriptor_handle);
/* Get addresses of vertex & index buffers */
d3d12.gpu_vertex_buffer_address = ID3D12Resource_GetGPUVirtualAddress(d3d12.vertex_buffer);
d3d12.gpu_index_buffer_address = ID3D12Resource_GetGPUVirtualAddress(d3d12.index_buffer);
/* Get handle increment */
d3d12.cbv_srv_uav_desc_increment = ID3D12Device_GetDescriptorHandleIncrementSize(device, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
/* Create view to constant buffer */
cbv.BufferLocation = ID3D12Resource_GetGPUVirtualAddress(d3d12.const_buffer);
cbv.SizeInBytes = 256;
cbv_handle = d3d12.cpu_descriptor_handle;
ID3D12Device_CreateConstantBufferView(device, &cbv, cbv_handle);
/* Create root signature */
hr = ID3D12Device_CreateRootSignature(device, 0, nk_d3d12_vertex_shader, sizeof(nk_d3d12_vertex_shader), &IID_ID3D12RootSignature, &d3d12.root_signature);
NK_ASSERT(SUCCEEDED(hr));
/* Create pipeline state */
{
/* Describe input layout */
const D3D12_INPUT_ELEMENT_DESC layout[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, NK_OFFSETOF(struct nk_d3d12_vertex, position), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, NK_OFFSETOF(struct nk_d3d12_vertex, uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, NK_OFFSETOF(struct nk_d3d12_vertex, col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
};
/* Describe pipeline state */
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.pRootSignature = d3d12.root_signature;
desc.VS.pShaderBytecode = nk_d3d12_vertex_shader;
desc.VS.BytecodeLength = sizeof(nk_d3d12_vertex_shader);
desc.PS.pShaderBytecode = nk_d3d12_pixel_shader;
desc.PS.BytecodeLength = sizeof(nk_d3d12_pixel_shader);
desc.BlendState.RenderTarget[0].BlendEnable = TRUE;
desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
desc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO;
desc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
desc.SampleMask = UINT_MAX;
desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
desc.RasterizerState.CullMode= D3D12_CULL_MODE_NONE;
desc.RasterizerState.DepthClipEnable = TRUE;
desc.InputLayout.NumElements = _countof(layout);
desc.InputLayout.pInputElementDescs = layout;
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
desc.NumRenderTargets = 1;
desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; /* NOTE: When using HDR rendering you might have a different framebuffer format */
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.NodeMask = 0;
/* Create PSO */
hr = ID3D12Device_CreateGraphicsPipelineState(device, &desc, &IID_ID3D12PipelineState, &d3d12.pipeline_state);
NK_ASSERT(SUCCEEDED(hr));
}
/* First time const buffer init */
nk_d3d12_resize(width, height);
/* viewport */
d3d12.viewport.TopLeftX = 0.0f;
d3d12.viewport.TopLeftY = 0.0f;
d3d12.viewport.Width = (float)width;
d3d12.viewport.Height = (float)height;
d3d12.viewport.MinDepth = 0.0f;
d3d12.viewport.MaxDepth = 1.0f;
return &d3d12.ctx;
}
NK_API void
nk_d3d12_font_stash_begin(struct nk_font_atlas **atlas)
{
/* Default nuklear font stash */
nk_font_atlas_init_default(&d3d12.atlas);
nk_font_atlas_begin(&d3d12.atlas);
*atlas = &d3d12.atlas;
}
NK_API void
nk_d3d12_font_stash_end(ID3D12GraphicsCommandList *command_list)
{
HRESULT hr;
D3D12_TEXTURE_COPY_LOCATION cpy_src, cpy_dest;
D3D12_BOX cpy_box;
D3D12_RESOURCE_BARRIER resource_barrier;
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc;
D3D12_CPU_DESCRIPTOR_HANDLE srv_handle;
const void *image;
void* ptr_data;
int w, h;
/* Bake nuklear font atlas */
image = nk_font_atlas_bake(&d3d12.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
NK_ASSERT(image);
/* Create font texture */
{
D3D12_RESOURCE_DESC desc;
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
desc.Width = w;
desc.Height = h;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
hr = ID3D12Device_CreateCommittedResource(d3d12.device, &d3d12.heap_prop_default, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_DEST, NULL, &IID_ID3D12Resource, &d3d12.font_texture);
NK_ASSERT(SUCCEEDED(hr));
}
/* Create font upload buffer */
{
D3D12_RESOURCE_DESC desc;
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT;
desc.Width = w * h * 4;
desc.Height = 1;
desc.DepthOrArraySize = 1;
desc.MipLevels = 1;
desc.Format = DXGI_FORMAT_UNKNOWN;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
hr = ID3D12Device_CreateCommittedResource(d3d12.device, &d3d12.heap_prop_upload, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_COPY_SOURCE, NULL, &IID_ID3D12Resource, &d3d12.font_upload_buffer);
NK_ASSERT(SUCCEEDED(hr));
}
/* Copy image data to upload buffer */
hr = ID3D12Resource_Map(d3d12.font_upload_buffer, 0, NULL, &ptr_data);
NK_ASSERT(SUCCEEDED(hr));
memcpy(ptr_data, image, w * h * 4);
ID3D12Resource_Unmap(d3d12.font_upload_buffer, 0, NULL);
/* Execute copy operation */
cpy_src.pResource = d3d12.font_upload_buffer;
cpy_src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
cpy_src.PlacedFootprint.Offset = 0;
cpy_src.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
cpy_src.PlacedFootprint.Footprint.Width = w;
cpy_src.PlacedFootprint.Footprint.Height = h;
cpy_src.PlacedFootprint.Footprint.Depth = 1;
cpy_src.PlacedFootprint.Footprint.RowPitch = w * 4;
cpy_dest.pResource = d3d12.font_texture;
cpy_dest.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
cpy_dest.SubresourceIndex = 0;
cpy_box.top = 0;
cpy_box.left = 0;
cpy_box.back = 1;
cpy_box.bottom = h;
cpy_box.right = w;
cpy_box.front = 0;
ID3D12GraphicsCommandList_CopyTextureRegion(command_list, &cpy_dest, 0, 0, 0, &cpy_src, &cpy_box);
/* Bring texture in the right state for rendering */
resource_barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
resource_barrier.Transition.pResource = d3d12.font_texture;
resource_barrier.Transition.Subresource = 0;
resource_barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
resource_barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
resource_barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
ID3D12GraphicsCommandList_ResourceBarrier(command_list, 1, &resource_barrier);
/* Create the SRV for the font texture */
srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srv_desc.Texture2D.MipLevels = 1;
srv_desc.Texture2D.MostDetailedMip = 0;
srv_desc.Texture2D.PlaneSlice = 0;
srv_desc.Texture2D.ResourceMinLODClamp = 0.0f;
srv_handle.ptr = d3d12.cpu_descriptor_handle.ptr + d3d12.cbv_srv_uav_desc_increment;
ID3D12Device_CreateShaderResourceView(d3d12.device, d3d12.font_texture, &srv_desc, srv_handle);
/* Done with nk atlas data. Atlas will be served with texture id 0 */
nk_font_atlas_end(&d3d12.atlas, nk_handle_id(0), &d3d12.tex_null);
/* Setup default font */
if (d3d12.atlas.default_font)
nk_style_set_font(&d3d12.ctx, &d3d12.atlas.default_font->handle);
}
NK_API
void nk_d3d12_font_stash_cleanup()
{
if(d3d12.font_upload_buffer)
{
ID3D12Resource_Release(d3d12.font_upload_buffer);
d3d12.font_upload_buffer = NULL;
}
}
NK_API
nk_bool nk_d3d12_set_user_texture(unsigned int index, ID3D12Resource* texture, const D3D12_SHADER_RESOURCE_VIEW_DESC* description, nk_handle* handle_out)
{
nk_bool result = nk_false;
if(index < d3d12.max_user_textures)
{
D3D12_CPU_DESCRIPTOR_HANDLE srv_handle;
/* Get handle to texture (0 - Const Buffer; 1 - Font Texture; 2 - First user texture) */
srv_handle.ptr = d3d12.cpu_descriptor_handle.ptr + ((2 + index) * d3d12.cbv_srv_uav_desc_increment);
/* Create SRV */
ID3D12Device_CreateShaderResourceView(d3d12.device, texture, description, srv_handle);
/* Set nk handle (0 - Font Texture; 1 - First user texture) */
*handle_out = nk_handle_id(1 + index);
result = nk_true;
}
return result;
}
NK_API
void nk_d3d12_shutdown(void)
{
/* Nuklear cleanup */
nk_font_atlas_clear(&d3d12.atlas);
nk_buffer_free(&d3d12.cmds);
nk_free(&d3d12.ctx);
/* DirectX 12 cleanup */
ID3D12Device_Release(d3d12.device);
ID3D12PipelineState_Release(d3d12.pipeline_state);
ID3D12RootSignature_Release(d3d12.root_signature);
ID3D12DescriptorHeap_Release(d3d12.desc_heap);
ID3D12Resource_Release(d3d12.upload_buffer);
ID3D12Resource_Release(d3d12.const_buffer);
ID3D12Resource_Release(d3d12.index_buffer);
ID3D12Resource_Release(d3d12.vertex_buffer);
if(d3d12.font_texture)
ID3D12Resource_Release(d3d12.font_texture);
if(d3d12.font_upload_buffer)
ID3D12Resource_Release(d3d12.font_upload_buffer);
}
#endif

View File

@ -0,0 +1,53 @@
#define NK_ROOTSIGNATURE ""\
"RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),"\
"DescriptorTable("\
"CBV(b0, numDescriptors = 1, flags = DATA_VOLATILE),"\
"SRV(t0, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)"\
"),"\
"RootConstants(num32BitConstants = 1, b1),"\
"StaticSampler(s0, "\
"filter = FILTER_MIN_MAG_MIP_LINEAR,"\
"addressU = TEXTURE_ADDRESS_CLAMP,"\
"addressV = TEXTURE_ADDRESS_CLAMP,"\
"addressW = TEXTURE_ADDRESS_CLAMP,"\
"comparisonFunc = COMPARISON_ALWAYS"\
")"
cbuffer buffer0 : register(b0)
{
float4x4 ProjectionMatrix;
};
static uint texture_index : register(b1);
sampler sampler0 : register(s0);
Texture2D<float4> textures[] : register(t0);
struct VS_INPUT
{
float2 pos : POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
struct PS_INPUT
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
[RootSignature(NK_ROOTSIGNATURE)]
PS_INPUT vs(VS_INPUT input)
{
PS_INPUT output;
output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));
output.col = input.col;
output.uv = input.uv;
return output;
}
[RootSignature(NK_ROOTSIGNATURE)]
float4 ps(PS_INPUT input) : SV_Target
{
return input.col * textures[texture_index].Sample(sampler0, input.uv);
}

View File

@ -0,0 +1,135 @@
#if 0
//
// Generated by Microsoft (R) D3D Shader Disassembler
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_POSITION 0 xyzw 0 POS float
// COLOR 0 xyzw 1 NONE float xyzw
// TEXCOORD 0 xy 2 NONE float xy
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_Target 0 xyzw 0 TARGET float xyzw
//
ps_5_1
dcl_globalFlags refactoringAllowed
dcl_sampler S0[0:0], mode_default, space=0
dcl_resource_texture2d (float,float,float,float) T0[0:*], space=0
dcl_input_ps linear v1.xyzw
dcl_input_ps linear v2.xy
dcl_output o0.xyzw
dcl_temps 1
sample r0.xyzw, v2.xyxx, T0[0].xyzw, S0[0]
mul o0.xyzw, r0.xyzw, v1.xyzw
ret
// Approximately 0 instruction slots used
#endif
const BYTE nk_d3d12_pixel_shader[] =
{
68, 88, 66, 67, 228, 128,
250, 93, 94, 248, 174, 160,
102, 133, 107, 228, 84, 49,
109, 253, 1, 0, 0, 0,
72, 2, 0, 0, 4, 0,
0, 0, 48, 0, 0, 0,
164, 0, 0, 0, 216, 0,
0, 0, 152, 1, 0, 0,
73, 83, 71, 78, 108, 0,
0, 0, 3, 0, 0, 0,
8, 0, 0, 0, 80, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
15, 0, 0, 0, 92, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 1, 0, 0, 0,
15, 15, 0, 0, 98, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 2, 0, 0, 0,
3, 3, 0, 0, 83, 86,
95, 80, 79, 83, 73, 84,
73, 79, 78, 0, 67, 79,
76, 79, 82, 0, 84, 69,
88, 67, 79, 79, 82, 68,
0, 171, 79, 83, 71, 78,
44, 0, 0, 0, 1, 0,
0, 0, 8, 0, 0, 0,
32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0,
0, 0, 15, 0, 0, 0,
83, 86, 95, 84, 97, 114,
103, 101, 116, 0, 171, 171,
83, 72, 69, 88, 184, 0,
0, 0, 81, 0, 0, 0,
46, 0, 0, 0, 106, 8,
0, 1, 90, 0, 0, 6,
70, 110, 48, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 88, 24, 0, 7,
70, 126, 48, 0, 0, 0,
0, 0, 0, 0, 0, 0,
255, 255, 255, 255, 85, 85,
0, 0, 0, 0, 0, 0,
98, 16, 0, 3, 242, 16,
16, 0, 1, 0, 0, 0,
98, 16, 0, 3, 50, 16,
16, 0, 2, 0, 0, 0,
101, 0, 0, 3, 242, 32,
16, 0, 0, 0, 0, 0,
104, 0, 0, 2, 1, 0,
0, 0, 69, 0, 0, 11,
242, 0, 16, 0, 0, 0,
0, 0, 70, 16, 16, 0,
2, 0, 0, 0, 70, 126,
32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 96,
32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 56, 0,
0, 7, 242, 32, 16, 0,
0, 0, 0, 0, 70, 14,
16, 0, 0, 0, 0, 0,
70, 30, 16, 0, 1, 0,
0, 0, 62, 0, 0, 1,
82, 84, 83, 48, 168, 0,
0, 0, 2, 0, 0, 0,
2, 0, 0, 0, 24, 0,
0, 0, 1, 0, 0, 0,
116, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 48, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 104, 0,
0, 0, 2, 0, 0, 0,
56, 0, 0, 0, 2, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 0,
255, 255, 255, 255, 0, 0,
0, 0, 255, 255, 255, 255,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
255, 255, 255, 255, 1, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 21, 0,
0, 0, 3, 0, 0, 0,
3, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
16, 0, 0, 0, 8, 0,
0, 0, 2, 0, 0, 0,
0, 0, 0, 0, 255, 255,
127, 127, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0
};

View File

@ -0,0 +1,168 @@
#if 0
//
// Generated by Microsoft (R) D3D Shader Disassembler
//
//
// Input signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// POSITION 0 xy 0 NONE float xy
// COLOR 0 xyzw 1 NONE float xyzw
// TEXCOORD 0 xy 2 NONE float xy
//
//
// Output signature:
//
// Name Index Mask Register SysValue Format Used
// -------------------- ----- ------ -------- -------- ------- ------
// SV_POSITION 0 xyzw 0 POS float xyzw
// COLOR 0 xyzw 1 NONE float xyzw
// TEXCOORD 0 xy 2 NONE float xy
//
vs_5_1
dcl_globalFlags refactoringAllowed
dcl_constantbuffer CB0[0:0][4], immediateIndexed, space=0
dcl_input v0.xy
dcl_input v1.xyzw
dcl_input v2.xy
dcl_output_siv o0.xyzw, position
dcl_output o1.xyzw
dcl_output o2.xy
dcl_temps 1
mul r0.xyzw, v0.yyyy, CB0[0][1].xyzw
mad r0.xyzw, CB0[0][0].xyzw, v0.xxxx, r0.xyzw
add o0.xyzw, r0.xyzw, CB0[0][3].xyzw
mov o1.xyzw, v1.xyzw
mov o2.xy, v2.xyxx
ret
// Approximately 0 instruction slots used
#endif
const BYTE nk_d3d12_vertex_shader[] =
{
68, 88, 66, 67, 187, 129,
163, 57, 169, 94, 219, 158,
174, 23, 30, 91, 108, 150,
135, 141, 1, 0, 0, 0,
232, 2, 0, 0, 4, 0,
0, 0, 48, 0, 0, 0,
160, 0, 0, 0, 20, 1,
0, 0, 56, 2, 0, 0,
73, 83, 71, 78, 104, 0,
0, 0, 3, 0, 0, 0,
8, 0, 0, 0, 80, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 0, 0, 0, 0,
3, 3, 0, 0, 89, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 1, 0, 0, 0,
15, 15, 0, 0, 95, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 2, 0, 0, 0,
3, 3, 0, 0, 80, 79,
83, 73, 84, 73, 79, 78,
0, 67, 79, 76, 79, 82,
0, 84, 69, 88, 67, 79,
79, 82, 68, 0, 79, 83,
71, 78, 108, 0, 0, 0,
3, 0, 0, 0, 8, 0,
0, 0, 80, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 3, 0, 0, 0,
0, 0, 0, 0, 15, 0,
0, 0, 92, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 3, 0, 0, 0,
1, 0, 0, 0, 15, 0,
0, 0, 98, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 3, 0, 0, 0,
2, 0, 0, 0, 3, 12,
0, 0, 83, 86, 95, 80,
79, 83, 73, 84, 73, 79,
78, 0, 67, 79, 76, 79,
82, 0, 84, 69, 88, 67,
79, 79, 82, 68, 0, 171,
83, 72, 69, 88, 28, 1,
0, 0, 81, 0, 1, 0,
71, 0, 0, 0, 106, 8,
0, 1, 89, 0, 0, 7,
70, 142, 48, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 4, 0,
0, 0, 0, 0, 0, 0,
95, 0, 0, 3, 50, 16,
16, 0, 0, 0, 0, 0,
95, 0, 0, 3, 242, 16,
16, 0, 1, 0, 0, 0,
95, 0, 0, 3, 50, 16,
16, 0, 2, 0, 0, 0,
103, 0, 0, 4, 242, 32,
16, 0, 0, 0, 0, 0,
1, 0, 0, 0, 101, 0,
0, 3, 242, 32, 16, 0,
1, 0, 0, 0, 101, 0,
0, 3, 50, 32, 16, 0,
2, 0, 0, 0, 104, 0,
0, 2, 1, 0, 0, 0,
56, 0, 0, 9, 242, 0,
16, 0, 0, 0, 0, 0,
86, 21, 16, 0, 0, 0,
0, 0, 70, 142, 48, 0,
0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0,
50, 0, 0, 11, 242, 0,
16, 0, 0, 0, 0, 0,
70, 142, 48, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 6, 16,
16, 0, 0, 0, 0, 0,
70, 14, 16, 0, 0, 0,
0, 0, 0, 0, 0, 9,
242, 32, 16, 0, 0, 0,
0, 0, 70, 14, 16, 0,
0, 0, 0, 0, 70, 142,
48, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0,
0, 0, 54, 0, 0, 5,
242, 32, 16, 0, 1, 0,
0, 0, 70, 30, 16, 0,
1, 0, 0, 0, 54, 0,
0, 5, 50, 32, 16, 0,
2, 0, 0, 0, 70, 16,
16, 0, 2, 0, 0, 0,
62, 0, 0, 1, 82, 84,
83, 48, 168, 0, 0, 0,
2, 0, 0, 0, 2, 0,
0, 0, 24, 0, 0, 0,
1, 0, 0, 0, 116, 0,
0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 48, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 0, 104, 0, 0, 0,
2, 0, 0, 0, 56, 0,
0, 0, 2, 0, 0, 0,
1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
2, 0, 0, 0, 255, 255,
255, 255, 0, 0, 0, 0,
255, 255, 255, 255, 0, 0,
0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 255, 255,
255, 255, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0,
0, 0, 21, 0, 0, 0,
3, 0, 0, 0, 3, 0,
0, 0, 3, 0, 0, 0,
0, 0, 0, 0, 16, 0,
0, 0, 8, 0, 0, 0,
2, 0, 0, 0, 0, 0,
0, 0, 255, 255, 127, 127,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0
};

View File

@ -33,27 +33,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -82,10 +87,11 @@ WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
if (width != 0 && height != 0 &&
(width != present.BackBufferWidth || height != present.BackBufferHeight))
{
HRESULT hr;
nk_d3d9_release();
present.BackBufferWidth = width;
present.BackBufferHeight = height;
HRESULT hr = IDirect3DDevice9_Reset(device, &present);
hr = IDirect3DDevice9_Reset(device, &present);
NK_ASSERT(SUCCEEDED(hr));
nk_d3d9_resize(width, height);
}
@ -210,10 +216,16 @@ int main(void)
/* style.c */
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
@ -268,6 +280,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -58,7 +58,7 @@ static struct {
struct nk_font_atlas atlas;
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
D3DVIEWPORT9 viewport;
D3DMATRIX projection;
@ -150,7 +150,7 @@ nk_d3d9_render(enum nk_anti_aliasing AA)
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.null = d3d9.null;
config.tex_null = d3d9.tex_null;
/* convert shapes into vertexes */
nk_buffer_init_default(&vbuf);
@ -204,11 +204,15 @@ nk_d3d9_get_projection_matrix(int width, int height, float *result)
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 },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f },
};
matrix[0][0] = 2.0f / (R - L);
matrix[1][1] = 2.0f / (T - B);
matrix[3][0] = (R + L) / (L - R);
matrix[3][1] = (T + B) / (B - T);
memcpy(result, matrix, sizeof(matrix));
}
@ -244,7 +248,7 @@ nk_d3d9_create_font_texture()
hr = IDirect3DTexture9_UnlockRect(d3d9.texture, 0);
NK_ASSERT(SUCCEEDED(hr));
nk_font_atlas_end(&d3d9.atlas, nk_handle_ptr(d3d9.texture), &d3d9.null);
nk_font_atlas_end(&d3d9.atlas, nk_handle_ptr(d3d9.texture), &d3d9.tex_null);
}
NK_API void
@ -426,30 +430,35 @@ nk_d3d9_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
static void
nk_d3d9_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
HGLOBAL mem;
SIZE_T size;
LPCWSTR wstr;
int utf8size;
(void)usr;
if (!IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) {
return;
}
HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
mem = GetClipboardData(CF_UNICODETEXT);
if (!mem) {
CloseClipboard();
return;
}
SIZE_T size = GlobalSize(mem) - 1;
size = GlobalSize(mem) - 1;
if (!size) {
CloseClipboard();
return;
}
LPCWSTR wstr = (LPCWSTR)GlobalLock(mem);
wstr = (LPCWSTR)GlobalLock(mem);
if (!wstr) {
CloseClipboard();
return;
}
int utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)size / sizeof(wchar_t), NULL, 0, NULL, NULL);
utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)size / sizeof(wchar_t), NULL, 0, NULL, NULL);
if (utf8size) {
char *utf8 = (char *)malloc(utf8size);
if (utf8) {
@ -466,12 +475,14 @@ nk_d3d9_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
static void
nk_d3d9_clipboard_copy(nk_handle usr, const char *text, int len)
{
int wsize;
(void)usr;
if (!OpenClipboard(NULL)) {
return;
}
int wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
if (wsize) {
HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t));
if (mem) {

View File

@ -28,27 +28,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -110,10 +115,16 @@ int main(void)
/* style.c */
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
while (running)
@ -164,6 +175,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -15,6 +15,7 @@
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wingdi.h>
typedef struct GdiFont GdiFont;
NK_API struct nk_context* nk_gdi_init(GdiFont *font, HDC window_dc, unsigned int width, unsigned int height);
@ -62,6 +63,13 @@ nk_create_image(struct nk_image * image, const char * frame_buffer, const int wi
{
if (image && frame_buffer && (width > 0) && (height > 0))
{
const unsigned char * src = (const unsigned char *)frame_buffer;
INT row = ((width * 3 + 3) & ~3);
LPBYTE lpBuf, pb = NULL;
BITMAPINFO bi = { 0 };
HBITMAP hbm;
int v, i;
image->w = width;
image->h = height;
image->region[0] = 0;
@ -69,8 +77,6 @@ nk_create_image(struct nk_image * image, const char * frame_buffer, const int wi
image->region[2] = width;
image->region[3] = height;
INT row = ((width * 3 + 3) & ~3);
BITMAPINFO bi = { 0 };
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = width;
bi.bmiHeader.biHeight = height;
@ -79,15 +85,13 @@ nk_create_image(struct nk_image * image, const char * frame_buffer, const int wi
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = row * height;
LPBYTE lpBuf, pb = NULL;
HBITMAP hbm = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&lpBuf, NULL, 0);
hbm = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&lpBuf, NULL, 0);
pb = lpBuf + row * height;
unsigned char * src = (unsigned char *)frame_buffer;
for (int v = 0; v<height; v++)
for (v = 0; v < height; v++)
{
pb -= row;
for (int i = 0; i < row; i += 3)
for (i = 0; i < row; i += 3)
{
pb[i + 0] = src[0];
pb[i + 1] = src[1];
@ -170,8 +174,9 @@ nk_gdi_stroke_rect(HDC dc, short x, short y, unsigned short w,
unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
HGDIOBJ br;
HPEN pen = NULL;
if (line_thickness == 1) {
SetDCPenColor(dc, color);
} else {
@ -179,7 +184,7 @@ nk_gdi_stroke_rect(HDC dc, short x, short y, unsigned short w,
SelectObject(dc, pen);
}
HGDIOBJ br = SelectObject(dc, GetStockObject(NULL_BRUSH));
br = SelectObject(dc, GetStockObject(NULL_BRUSH));
if (r == 0) {
Rectangle(dc, x, y, x + w, y + h);
} else {
@ -200,7 +205,8 @@ nk_gdi_fill_rect(HDC dc, short x, short y, unsigned short w,
COLORREF color = convert_color(col);
if (r == 0) {
RECT rect = { x, y, x + w, y + h };
RECT rect;
SetRect(&rect, x, y, x + w, y + h);
SetBkColor(dc, color);
ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
} else {
@ -262,16 +268,26 @@ nk_gdi_rect_multi_color(HDC dc, short x, short y, unsigned short w,
}
static BOOL
SetPoint(POINT *p, LONG x, LONG y)
{
if (!p)
return FALSE;
p->x = x;
p->y = y;
return TRUE;
}
static void
nk_gdi_fill_triangle(HDC dc, short x0, short y0, short x1,
short y1, short x2, short y2, struct nk_color col)
{
COLORREF color = convert_color(col);
POINT points[] = {
{ x0, y0 },
{ x1, y1 },
{ x2, y2 },
};
POINT points[3];
SetPoint(&points[0], x0, y0);
SetPoint(&points[1], x1, y1);
SetPoint(&points[2], x2, y2);
SetDCPenColor(dc, color);
SetDCBrushColor(dc, color);
@ -283,14 +299,14 @@ nk_gdi_stroke_triangle(HDC dc, short x0, short y0, short x1,
short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
POINT points[] = {
{ x0, y0 },
{ x1, y1 },
{ x2, y2 },
{ x0, y0 },
};
POINT points[4];
HPEN pen = NULL;
SetPoint(&points[0], x0, y0);
SetPoint(&points[1], x1, y1);
SetPoint(&points[2], x2, y2);
SetPoint(&points[3], x0, y0);
if (line_thickness == 1) {
SetDCPenColor(dc, color);
} else {
@ -376,6 +392,62 @@ nk_gdi_stroke_polyline(HDC dc, const struct nk_vec2i *pnts,
}
}
static void
nk_gdi_stroke_arc(HDC dc, short cx, short cy, unsigned short r, float amin, float adelta, unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
/* setup pen */
HPEN pen = NULL;
if (line_thickness == 1)
SetDCPenColor(dc, color);
else
{
/* the flat endcap makes thick arcs look better */
DWORD pen_style = PS_SOLID | PS_ENDCAP_FLAT | PS_GEOMETRIC;
LOGBRUSH brush;
brush.lbStyle = BS_SOLID;
brush.lbColor = color;
brush.lbHatch = 0;
pen = ExtCreatePen(pen_style, line_thickness, &brush, 0, NULL);
SelectObject(dc, pen);
}
/* calculate arc and draw */
int start_x = cx + (int) ((float)r*nk_cos(amin+adelta)),
start_y = cy + (int) ((float)r*nk_sin(amin+adelta)),
end_x = cx + (int) ((float)r*nk_cos(amin)),
end_y = cy + (int) ((float)r*nk_sin(amin));
HGDIOBJ br = SelectObject(dc, GetStockObject(NULL_BRUSH));
SetArcDirection(dc, AD_COUNTERCLOCKWISE);
Pie(dc, cx-r, cy-r, cx+r, cy+r, start_x, start_y, end_x, end_y);
SelectObject(dc, br);
if (pen)
{
SelectObject(dc, GetStockObject(DC_PEN));
DeleteObject(pen);
}
}
static void
nk_gdi_fill_arc(HDC dc, short cx, short cy, unsigned short r, float amin, float adelta, struct nk_color col)
{
COLORREF color = convert_color(col);
SetDCBrushColor(dc, color);
SetDCPenColor(dc, color);
int start_x = cx + (int) ((float)r*nk_cos(amin+adelta)),
start_y = cy + (int) ((float)r*nk_sin(amin+adelta)),
end_x = cx + (int) ((float)r*nk_cos(amin)),
end_y = cy + (int) ((float)r*nk_sin(amin));
Pie(dc, cx-r, cy-r, cx+r, cy+r, start_x, start_y, end_x, end_y);
}
static void
nk_gdi_fill_circle(HDC dc, short x, short y, unsigned short w,
unsigned short h, struct nk_color col)
@ -399,8 +471,10 @@ nk_gdi_stroke_circle(HDC dc, short x, short y, unsigned short w,
SelectObject(dc, pen);
}
HGDIOBJ br = SelectObject(dc, GetStockObject(NULL_BRUSH));
SetDCBrushColor(dc, OPAQUE);
Ellipse(dc, x, y, x + w, y + h);
SelectObject(dc, br);
if (pen) {
SelectObject(dc, GetStockObject(DC_PEN));
@ -414,14 +488,14 @@ nk_gdi_stroke_curve(HDC dc, struct nk_vec2i p1,
unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
POINT p[] = {
{ p1.x, p1.y },
{ p2.x, p2.y },
{ p3.x, p3.y },
{ p4.x, p4.y },
};
POINT p[4];
HPEN pen = NULL;
SetPoint(&p[0], p1.x, p1.y);
SetPoint(&p[1], p2.x, p2.y);
SetPoint(&p[2], p3.x, p3.y);
SetPoint(&p[3], p4.x, p4.y);
if (line_thickness == 1) {
SetDCPenColor(dc, color);
} else {
@ -462,7 +536,8 @@ static void
nk_gdi_clear(HDC dc, struct nk_color col)
{
COLORREF color = convert_color(col);
RECT rect = { 0, 0, gdi.width, gdi.height };
RECT rect;
SetRect(&rect, 0, 0, gdi.width, gdi.height);
SetBkColor(dc, color);
ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
@ -701,6 +776,13 @@ nk_gdi_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
nk_input_key(&gdi.ctx, NK_KEY_SCROLL_UP, down);
return 1;
case 'A':
if (ctrl) {
nk_input_key(&gdi.ctx, NK_KEY_TEXT_SELECT_ALL, down);
return 1;
}
break;
case 'C':
if (ctrl) {
nk_input_key(&gdi.ctx, NK_KEY_COPY, down);
@ -843,6 +925,14 @@ nk_gdi_render(struct nk_color clear)
const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
nk_gdi_fill_circle(memory_dc, c->x, c->y, c->w, c->h, c->color);
} break;
case NK_COMMAND_ARC: {
const struct nk_command_arc *q = (const struct nk_command_arc *)cmd;
nk_gdi_stroke_arc(memory_dc, q->cx, q->cy, q->r, q->a[0], q->a[1], q->line_thickness, q->color);
} break;
case NK_COMMAND_ARC_FILLED: {
const struct nk_command_arc_filled *q = (const struct nk_command_arc_filled *)cmd;
nk_gdi_fill_arc(memory_dc, q->cx, q->cy, q->r, q->a[0], q->a[1], q->color);
} break;
case NK_COMMAND_TRIANGLE: {
const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
nk_gdi_stroke_triangle(memory_dc, t->a.x, t->a.y, t->b.x, t->b.y,
@ -885,8 +975,7 @@ nk_gdi_render(struct nk_color clear)
const struct nk_command_image *i = (const struct nk_command_image *)cmd;
nk_gdi_draw_image(i->x, i->y, i->w, i->h, i->img, i->col);
} break;
case NK_COMMAND_ARC:
case NK_COMMAND_ARC_FILLED:
case NK_COMMAND_CUSTOM:
default: break;
}
}

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 /nologo /W3 /O2 /fp:fast /Gm- /D_CRT_SECURE_NO_DEPRECATE /Fedemo.exe main.c user32.lib gdi32.lib Msimg32.lib /link /incremental:no

View File

@ -0,0 +1,128 @@
#include <windows.h>
#pragma comment(linker,"\"/manifestdependency:type='win32' \
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
/* Includes the default nuklear implementation
* Includes the modified GDI backend (No more global state to allow multiple hwnd's)
*/
#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_IMPLEMENTATION
#define NK_GDI_IMPLEMENTATION
#include "../../nuklear.h"
#include "nuklear_gdi.h"
/* Include the window framework (the new fancy code of this demo) */
#define NKGDI_IMPLEMENT_WINDOW
#include "window.h"
/* This callback will be called when the window is draw
* You will NOT need to call nk_begin(...) and nk_end(...)
* begin and end are handled by the parent code calling this
* callback
*/
int drawCallback(struct nk_context* ctx)
{
/* Code is from ../calculator.c */
static int set = 0, prev = 0, op = 0;
static const char numbers[] = "789456123";
static const char ops[] = "+-*/";
static double a = 0, b = 0;
static double *current = &a;
size_t i = 0;
int solve = 0;
{int len; char buffer[256];
nk_layout_row_dynamic(ctx, 35, 1);
len = snprintf(buffer, 256, "%.2f", *current);
nk_edit_string(ctx, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_float);
buffer[len] = 0;
*current = atof(buffer);}
nk_layout_row_dynamic(ctx, 35, 4);
for (i = 0; i < 16; ++i) {
if (i >= 12 && i < 15) {
if (i > 12) continue;
if (nk_button_label(ctx, "C")) {
a = b = op = 0; current = &a; set = 0;
} if (nk_button_label(ctx, "0")) {
*current = *current*10.0f; set = 0;
} if (nk_button_label(ctx, "=")) {
solve = 1; prev = op; op = 0;
}
} else if (((i+1) % 4)) {
if (nk_button_text(ctx, &numbers[(i/4)*3+i%4], 1)) {
*current = *current * 10.0f + numbers[(i/4)*3+i%4] - '0';
set = 0;
}
} else if (nk_button_text(ctx, &ops[i/4], 1)) {
if (!set) {
if (current != &b) {
current = &b;
} else {
prev = op;
solve = 1;
}
}
op = ops[i/4];
set = 1;
}
}
if (solve) {
if (prev == '+') a = a + b;
if (prev == '-') a = a - b;
if (prev == '*') a = a * b;
if (prev == '/') a = a / b;
current = &a;
if (set) current = &b;
b = 0; set = 0;
}
return 1;
}
/* Main entry point - wWinMain used for UNICODE
* (You can also use _tWinMain(...) to automaticaly use the ASCII or WIDE char entry point base on your build)
*/
INT WINAPI wWinMain(HINSTANCE _In_ hInstance, HINSTANCE _In_opt_ hPrevInstance, PWSTR _In_ cmdArgs, INT _In_ cmdShow)
{
/* Call this first to setup all required prerequisites */
nkgdi_window_init();
/* Preparing two window contexts */
struct nkgdi_window w1, w2;
memset(&w1, 0x0, sizeof(struct nkgdi_window));
memset(&w2, 0x0, sizeof(struct nkgdi_window));
/* Configure and create window 1.
* Note: You can allways change the direct accesible parameters later as well!
*/
w1.allow_sizing = 0;
w1.allow_maximize = 0;
w1.allow_move = 0;
w1.has_titlebar = 0;
w1.cb_on_draw = &drawCallback;
nkgdi_window_create(&w1, 500, 500, "F1", 10, 10);
/* Configure and create window 2 */
w2.allow_sizing = 1;
w2.allow_maximize = 1;
w2.allow_move = 1;
w2.has_titlebar = 1;
w2.cb_on_draw = &drawCallback;
nkgdi_window_create(&w2, 500, 500, "F2", 520, 10);
/* As long as both windows are valid (nkgdi_window_update returning 1) */
while (nkgdi_window_update(&w1) && nkgdi_window_update(&w2)) Sleep(20);
/* Destroy both windows context */
nkgdi_window_destroy(&w1);
nkgdi_window_destroy(&w2);
/* Call nkgdi_window_shutdown to properly shutdown the gdi window framework */
nkgdi_window_shutdown();
return 0;
}

View File

@ -0,0 +1,937 @@
/*
* Nuklear - 1.32.0 - public domain
* no warrenty implied; use at your own risk.
* authored from 2015-2016 by Micha Mettke
*
* Modified GDI backend 2022
* Now based on a context that is required for each API function call.
* Removes the global state --> you can have multiple windows :-)
*
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_GDI_H_
#define NK_GDI_H_
#ifdef __cplusplus
extern "C"{
#endif
typedef struct GdiFont GdiFont;
struct _nk_gdi_ctx;
typedef struct _nk_gdi_ctx* nk_gdi_ctx;
NK_API struct nk_context* nk_gdi_init(nk_gdi_ctx* gdi, GdiFont* font, HDC window_dc, unsigned int width, unsigned int height);
NK_API int nk_gdi_handle_event(nk_gdi_ctx gdi, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
NK_API void nk_gdi_render(nk_gdi_ctx gdi, struct nk_color clear);
NK_API void nk_gdi_shutdown(nk_gdi_ctx gdi);
/* font */
NK_API GdiFont* nk_gdifont_create(const char* name, int size);
NK_API void nk_gdifont_del(GdiFont* font);
NK_API void nk_gdi_set_font(nk_gdi_ctx gdi, GdiFont* font);
#ifdef __cplusplus
}
#endif
#endif
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_GDI_IMPLEMENTATION
#include <stdlib.h>
#include <malloc.h>
struct GdiFont {
struct nk_user_font nk;
int height;
HFONT handle;
HDC dc;
};
struct _nk_gdi_ctx {
HBITMAP bitmap;
HDC window_dc;
HDC memory_dc;
unsigned int width;
unsigned int height;
struct nk_context ctx;
};
static void
nk_create_image(struct nk_image* image, const char* frame_buffer, const int width, const int height)
{
if (image && frame_buffer && (width > 0) && (height > 0))
{
const unsigned char* src = (const unsigned char*)frame_buffer;
INT row = ((width * 3 + 3) & ~3);
LPBYTE lpBuf, pb = NULL;
BITMAPINFO bi = { 0 };
HBITMAP hbm;
int v, i;
image->w = width;
image->h = height;
image->region[0] = 0;
image->region[1] = 0;
image->region[2] = width;
image->region[3] = height;
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = width;
bi.bmiHeader.biHeight = height;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = row * height;
hbm = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&lpBuf, NULL, 0);
pb = lpBuf + row * height;
for (v = 0; v < height; v++)
{
pb -= row;
for (i = 0; i < row; i += 3)
{
pb[i + 0] = src[0];
pb[i + 1] = src[1];
pb[i + 2] = src[2];
src += 3;
}
}
SetDIBits(NULL, hbm, 0, height, lpBuf, &bi, DIB_RGB_COLORS);
image->handle.ptr = hbm;
}
}
static void
nk_delete_image(struct nk_image* image)
{
if (image && image->handle.id != 0)
{
HBITMAP hbm = (HBITMAP)image->handle.ptr;
DeleteObject(hbm);
memset(image, 0, sizeof(struct nk_image));
}
}
static void
nk_gdi_draw_image(nk_gdi_ctx gdi, short x, short y, unsigned short w, unsigned short h,
struct nk_image img, struct nk_color col)
{
HBITMAP hbm = (HBITMAP)img.handle.ptr;
HDC hDCBits;
BITMAP bitmap;
if (!gdi->memory_dc || !hbm)
return;
hDCBits = CreateCompatibleDC(gdi->memory_dc);
GetObject(hbm, sizeof(BITMAP), (LPSTR)&bitmap);
SelectObject(hDCBits, hbm);
StretchBlt(gdi->memory_dc, x, y, w, h, hDCBits, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
DeleteDC(hDCBits);
}
static COLORREF
convert_color(struct nk_color c)
{
return c.r | (c.g << 8) | (c.b << 16);
}
static void
nk_gdi_scissor(HDC dc, float x, float y, float w, float h)
{
SelectClipRgn(dc, NULL);
IntersectClipRect(dc, (int)x, (int)y, (int)(x + w + 1), (int)(y + h + 1));
}
static void
nk_gdi_stroke_line(HDC dc, short x0, short y0, short x1,
short y1, unsigned int line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
HPEN pen = NULL;
if (line_thickness == 1) {
SetDCPenColor(dc, color);
}
else {
pen = CreatePen(PS_SOLID, line_thickness, color);
SelectObject(dc, pen);
}
MoveToEx(dc, x0, y0, NULL);
LineTo(dc, x1, y1);
if (pen) {
SelectObject(dc, GetStockObject(DC_PEN));
DeleteObject(pen);
}
}
static void
nk_gdi_stroke_rect(HDC dc, short x, short y, unsigned short w,
unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
HGDIOBJ br;
HPEN pen = NULL;
if (line_thickness == 1) {
SetDCPenColor(dc, color);
}
else {
pen = CreatePen(PS_SOLID, line_thickness, color);
SelectObject(dc, pen);
}
br = SelectObject(dc, GetStockObject(NULL_BRUSH));
if (r == 0) {
Rectangle(dc, x, y, x + w, y + h);
}
else {
RoundRect(dc, x, y, x + w, y + h, r, r);
}
SelectObject(dc, br);
if (pen) {
SelectObject(dc, GetStockObject(DC_PEN));
DeleteObject(pen);
}
}
static void
nk_gdi_fill_rect(HDC dc, short x, short y, unsigned short w,
unsigned short h, unsigned short r, struct nk_color col)
{
COLORREF color = convert_color(col);
if (r == 0) {
RECT rect;
SetRect(&rect, x, y, x + w, y + h);
SetBkColor(dc, color);
ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
}
else {
SetDCPenColor(dc, color);
SetDCBrushColor(dc, color);
RoundRect(dc, x, y, x + w, y + h, r, r);
}
}
static void
nk_gdi_set_vertexColor(PTRIVERTEX tri, struct nk_color col)
{
tri->Red = col.r << 8;
tri->Green = col.g << 8;
tri->Blue = col.b << 8;
tri->Alpha = 0xff << 8;
}
static void
nk_gdi_rect_multi_color(nk_gdi_ctx gdi, HDC dc, short x, short y, unsigned short w,
unsigned short h, struct nk_color left, struct nk_color top,
struct nk_color right, struct nk_color bottom)
{
BLENDFUNCTION alphaFunction;
// GRADIENT_RECT gRect;
GRADIENT_TRIANGLE gTri[2];
TRIVERTEX vt[4];
alphaFunction.BlendOp = AC_SRC_OVER;
alphaFunction.BlendFlags = 0;
alphaFunction.SourceConstantAlpha = 0;
alphaFunction.AlphaFormat = AC_SRC_ALPHA;
/* TODO: This Case Needs Repair.*/
/* Top Left Corner */
vt[0].x = x;
vt[0].y = y;
nk_gdi_set_vertexColor(&vt[0], left);
/* Top Right Corner */
vt[1].x = x + w;
vt[1].y = y;
nk_gdi_set_vertexColor(&vt[1], top);
/* Bottom Left Corner */
vt[2].x = x;
vt[2].y = y + h;
nk_gdi_set_vertexColor(&vt[2], right);
/* Bottom Right Corner */
vt[3].x = x + w;
vt[3].y = y + h;
nk_gdi_set_vertexColor(&vt[3], bottom);
gTri[0].Vertex1 = 0;
gTri[0].Vertex2 = 1;
gTri[0].Vertex3 = 2;
gTri[1].Vertex1 = 2;
gTri[1].Vertex2 = 1;
gTri[1].Vertex3 = 3;
GdiGradientFill(dc, vt, 4, gTri, 2, GRADIENT_FILL_TRIANGLE);
AlphaBlend(gdi->window_dc, x, y, x + w, y + h, gdi->memory_dc, x, y, x + w, y + h, alphaFunction);
}
static BOOL
SetPoint(POINT* p, LONG x, LONG y)
{
if (!p)
return FALSE;
p->x = x;
p->y = y;
return TRUE;
}
static void
nk_gdi_fill_triangle(HDC dc, short x0, short y0, short x1,
short y1, short x2, short y2, struct nk_color col)
{
COLORREF color = convert_color(col);
POINT points[3];
SetPoint(&points[0], x0, y0);
SetPoint(&points[1], x1, y1);
SetPoint(&points[2], x2, y2);
SetDCPenColor(dc, color);
SetDCBrushColor(dc, color);
Polygon(dc, points, 3);
}
static void
nk_gdi_stroke_triangle(HDC dc, short x0, short y0, short x1,
short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
POINT points[4];
HPEN pen = NULL;
SetPoint(&points[0], x0, y0);
SetPoint(&points[1], x1, y1);
SetPoint(&points[2], x2, y2);
SetPoint(&points[3], x0, y0);
if (line_thickness == 1) {
SetDCPenColor(dc, color);
}
else {
pen = CreatePen(PS_SOLID, line_thickness, color);
SelectObject(dc, pen);
}
Polyline(dc, points, 4);
if (pen) {
SelectObject(dc, GetStockObject(DC_PEN));
DeleteObject(pen);
}
}
static void
nk_gdi_fill_polygon(HDC dc, const struct nk_vec2i* pnts, int count, struct nk_color col)
{
int i = 0;
#define MAX_POINTS 64
POINT points[MAX_POINTS];
COLORREF color = convert_color(col);
SetDCBrushColor(dc, color);
SetDCPenColor(dc, color);
for (i = 0; i < count && i < MAX_POINTS; ++i) {
points[i].x = pnts[i].x;
points[i].y = pnts[i].y;
}
Polygon(dc, points, i);
#undef MAX_POINTS
}
static void
nk_gdi_stroke_polygon(HDC dc, const struct nk_vec2i* pnts, int count,
unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
HPEN pen = NULL;
if (line_thickness == 1) {
SetDCPenColor(dc, color);
}
else {
pen = CreatePen(PS_SOLID, line_thickness, color);
SelectObject(dc, pen);
}
if (count > 0) {
int i;
MoveToEx(dc, pnts[0].x, pnts[0].y, NULL);
for (i = 1; i < count; ++i)
LineTo(dc, pnts[i].x, pnts[i].y);
LineTo(dc, pnts[0].x, pnts[0].y);
}
if (pen) {
SelectObject(dc, GetStockObject(DC_PEN));
DeleteObject(pen);
}
}
static void
nk_gdi_stroke_polyline(HDC dc, const struct nk_vec2i* pnts,
int count, unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
HPEN pen = NULL;
if (line_thickness == 1) {
SetDCPenColor(dc, color);
}
else {
pen = CreatePen(PS_SOLID, line_thickness, color);
SelectObject(dc, pen);
}
if (count > 0) {
int i;
MoveToEx(dc, pnts[0].x, pnts[0].y, NULL);
for (i = 1; i < count; ++i)
LineTo(dc, pnts[i].x, pnts[i].y);
}
if (pen) {
SelectObject(dc, GetStockObject(DC_PEN));
DeleteObject(pen);
}
}
static void
nk_gdi_fill_circle(HDC dc, short x, short y, unsigned short w,
unsigned short h, struct nk_color col)
{
COLORREF color = convert_color(col);
SetDCBrushColor(dc, color);
SetDCPenColor(dc, color);
Ellipse(dc, x, y, x + w, y + h);
}
static void
nk_gdi_stroke_circle(HDC dc, short x, short y, unsigned short w,
unsigned short h, unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
HPEN pen = NULL;
if (line_thickness == 1) {
SetDCPenColor(dc, color);
}
else {
pen = CreatePen(PS_SOLID, line_thickness, color);
SelectObject(dc, pen);
}
SetDCBrushColor(dc, OPAQUE);
Ellipse(dc, x, y, x + w, y + h);
if (pen) {
SelectObject(dc, GetStockObject(DC_PEN));
DeleteObject(pen);
}
}
static void
nk_gdi_stroke_curve(HDC dc, struct nk_vec2i p1,
struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4,
unsigned short line_thickness, struct nk_color col)
{
COLORREF color = convert_color(col);
POINT p[4];
HPEN pen = NULL;
SetPoint(&p[0], p1.x, p1.y);
SetPoint(&p[1], p2.x, p2.y);
SetPoint(&p[2], p3.x, p3.y);
SetPoint(&p[3], p4.x, p4.y);
if (line_thickness == 1) {
SetDCPenColor(dc, color);
}
else {
pen = CreatePen(PS_SOLID, line_thickness, color);
SelectObject(dc, pen);
}
SetDCBrushColor(dc, OPAQUE);
PolyBezier(dc, p, 4);
if (pen) {
SelectObject(dc, GetStockObject(DC_PEN));
DeleteObject(pen);
}
}
static void
nk_gdi_draw_text(HDC dc, short x, short y, unsigned short w, unsigned short h,
const char* text, int len, GdiFont* font, struct nk_color cbg, struct nk_color cfg)
{
int wsize;
WCHAR* wstr;
if (!text || !font || !len) return;
wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
SetBkColor(dc, convert_color(cbg));
SetTextColor(dc, convert_color(cfg));
SelectObject(dc, font->handle);
ExtTextOutW(dc, x, y, ETO_OPAQUE, NULL, wstr, wsize, NULL);
}
static void
nk_gdi_clear(nk_gdi_ctx gdi, HDC dc, struct nk_color col)
{
COLORREF color = convert_color(col);
RECT rect;
SetRect(&rect, 0, 0, gdi->width, gdi->height);
SetBkColor(dc, color);
ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
}
static void
nk_gdi_blit(nk_gdi_ctx gdi, HDC dc)
{
BitBlt(dc, 0, 0, gdi->width, gdi->height, gdi->memory_dc, 0, 0, SRCCOPY);
}
GdiFont*
nk_gdifont_create(const char* name, int size)
{
TEXTMETRICW metric;
GdiFont* font = (GdiFont*)calloc(1, sizeof(GdiFont));
if (!font)
return NULL;
font->dc = CreateCompatibleDC(0);
font->handle = CreateFontA(size, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_DONTCARE, name);
SelectObject(font->dc, font->handle);
GetTextMetricsW(font->dc, &metric);
font->height = metric.tmHeight;
return font;
}
static float
nk_gdifont_get_text_width(nk_handle handle, float height, const char* text, int len)
{
GdiFont* font = (GdiFont*)handle.ptr;
SIZE size;
int wsize;
WCHAR* wstr;
if (!font || !text)
return 0;
wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize);
if (GetTextExtentPoint32W(font->dc, wstr, wsize, &size))
return (float)size.cx;
return -1.0f;
}
void
nk_gdifont_del(GdiFont* font)
{
if (!font) return;
DeleteObject(font->handle);
DeleteDC(font->dc);
free(font);
}
static void
nk_gdi_clipboard_paste(nk_handle usr, struct nk_text_edit* edit)
{
(void)usr;
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
{
HGLOBAL mem = GetClipboardData(CF_UNICODETEXT);
if (mem)
{
SIZE_T size = GlobalSize(mem) - 1;
if (size)
{
LPCWSTR wstr = (LPCWSTR)GlobalLock(mem);
if (wstr)
{
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_gdi_clipboard_copy(nk_handle usr, const char* text, int len)
{
if (OpenClipboard(NULL))
{
int wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0);
if (wsize)
{
HGLOBAL mem = (HGLOBAL)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_gdi_init(nk_gdi_ctx* gdi, GdiFont* gdifont, HDC window_dc, unsigned int width, unsigned int height)
{
*gdi = (nk_gdi_ctx)malloc(sizeof(struct _nk_gdi_ctx));
struct nk_user_font* font = &gdifont->nk;
font->userdata = nk_handle_ptr(gdifont);
font->height = (float)gdifont->height;
font->width = nk_gdifont_get_text_width;
(*gdi)->bitmap = CreateCompatibleBitmap(window_dc, width, height);
(*gdi)->window_dc = window_dc;
(*gdi)->memory_dc = CreateCompatibleDC(window_dc);
(*gdi)->width = width;
(*gdi)->height = height;
SelectObject((*gdi)->memory_dc, (*gdi)->bitmap);
nk_init_default(&(*gdi)->ctx, font);
(*gdi)->ctx.clip.copy = nk_gdi_clipboard_copy;
(*gdi)->ctx.clip.paste = nk_gdi_clipboard_paste;
return &(*gdi)->ctx;
}
NK_API void
nk_gdi_set_font(nk_gdi_ctx gdi, GdiFont* gdifont)
{
struct nk_user_font* font = &gdifont->nk;
font->userdata = nk_handle_ptr(gdifont);
font->height = (float)gdifont->height;
font->width = nk_gdifont_get_text_width;
nk_style_set_font(&gdi->ctx, font);
}
NK_API int
nk_gdi_handle_event(nk_gdi_ctx gdi, HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_SIZE:
{
unsigned width = LOWORD(lparam);
unsigned height = HIWORD(lparam);
if (width != gdi->width || height != gdi->height)
{
DeleteObject(gdi->bitmap);
gdi->bitmap = CreateCompatibleBitmap(gdi->window_dc, width, height);
gdi->width = width;
gdi->height = height;
SelectObject(gdi->memory_dc, gdi->bitmap);
}
break;
}
case WM_PAINT:
{
PAINTSTRUCT paint;
HDC dc = BeginPaint(wnd, &paint);
nk_gdi_blit(gdi, dc);
EndPaint(wnd, &paint);
return 1;
}
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(&gdi->ctx, NK_KEY_SHIFT, down);
return 1;
case VK_DELETE:
nk_input_key(&gdi->ctx, NK_KEY_DEL, down);
return 1;
case VK_RETURN:
nk_input_key(&gdi->ctx, NK_KEY_ENTER, down);
return 1;
case VK_TAB:
nk_input_key(&gdi->ctx, NK_KEY_TAB, down);
return 1;
case VK_LEFT:
if (ctrl)
nk_input_key(&gdi->ctx, NK_KEY_TEXT_WORD_LEFT, down);
else
nk_input_key(&gdi->ctx, NK_KEY_LEFT, down);
return 1;
case VK_RIGHT:
if (ctrl)
nk_input_key(&gdi->ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else
nk_input_key(&gdi->ctx, NK_KEY_RIGHT, down);
return 1;
case VK_BACK:
nk_input_key(&gdi->ctx, NK_KEY_BACKSPACE, down);
return 1;
case VK_HOME:
nk_input_key(&gdi->ctx, NK_KEY_TEXT_START, down);
nk_input_key(&gdi->ctx, NK_KEY_SCROLL_START, down);
return 1;
case VK_END:
nk_input_key(&gdi->ctx, NK_KEY_TEXT_END, down);
nk_input_key(&gdi->ctx, NK_KEY_SCROLL_END, down);
return 1;
case VK_NEXT:
nk_input_key(&gdi->ctx, NK_KEY_SCROLL_DOWN, down);
return 1;
case VK_PRIOR:
nk_input_key(&gdi->ctx, NK_KEY_SCROLL_UP, down);
return 1;
case 'C':
if (ctrl) {
nk_input_key(&gdi->ctx, NK_KEY_COPY, down);
return 1;
}
break;
case 'V':
if (ctrl) {
nk_input_key(&gdi->ctx, NK_KEY_PASTE, down);
return 1;
}
break;
case 'X':
if (ctrl) {
nk_input_key(&gdi->ctx, NK_KEY_CUT, down);
return 1;
}
break;
case 'Z':
if (ctrl) {
nk_input_key(&gdi->ctx, NK_KEY_TEXT_UNDO, down);
return 1;
}
break;
case 'R':
if (ctrl) {
nk_input_key(&gdi->ctx, NK_KEY_TEXT_REDO, down);
return 1;
}
break;
}
return 0;
}
case WM_CHAR:
if (wparam >= 32)
{
nk_input_unicode(&gdi->ctx, (nk_rune)wparam);
return 1;
}
break;
case WM_LBUTTONDOWN:
nk_input_button(&gdi->ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_LBUTTONUP:
nk_input_button(&gdi->ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
nk_input_button(&gdi->ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_RBUTTONDOWN:
nk_input_button(&gdi->ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_RBUTTONUP:
nk_input_button(&gdi->ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_MBUTTONDOWN:
nk_input_button(&gdi->ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
SetCapture(wnd);
return 1;
case WM_MBUTTONUP:
nk_input_button(&gdi->ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0);
ReleaseCapture();
return 1;
case WM_MOUSEWHEEL:
nk_input_scroll(&gdi->ctx, nk_vec2(0, (float)(short)HIWORD(wparam) / WHEEL_DELTA));
return 1;
case WM_MOUSEMOVE:
nk_input_motion(&gdi->ctx, (short)LOWORD(lparam), (short)HIWORD(lparam));
return 1;
case WM_LBUTTONDBLCLK:
nk_input_button(&gdi->ctx, NK_BUTTON_DOUBLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1);
return 1;
}
return 0;
}
NK_API void
nk_gdi_shutdown(nk_gdi_ctx gdi)
{
DeleteObject(gdi->memory_dc);
DeleteObject(gdi->bitmap);
nk_free(&gdi->ctx);
}
NK_API void
nk_gdi_render(nk_gdi_ctx gdi, struct nk_color clear)
{
const struct nk_command* cmd;
HDC memory_dc = gdi->memory_dc;
SelectObject(memory_dc, GetStockObject(DC_PEN));
SelectObject(memory_dc, GetStockObject(DC_BRUSH));
nk_gdi_clear(gdi, memory_dc, clear);
nk_foreach(cmd, &gdi->ctx)
{
switch (cmd->type) {
case NK_COMMAND_NOP: break;
case NK_COMMAND_SCISSOR: {
const struct nk_command_scissor* s = (const struct nk_command_scissor*)cmd;
nk_gdi_scissor(memory_dc, s->x, s->y, s->w, s->h);
} break;
case NK_COMMAND_LINE: {
const struct nk_command_line* l = (const struct nk_command_line*)cmd;
nk_gdi_stroke_line(memory_dc, l->begin.x, l->begin.y, l->end.x,
l->end.y, l->line_thickness, l->color);
} break;
case NK_COMMAND_RECT: {
const struct nk_command_rect* r = (const struct nk_command_rect*)cmd;
nk_gdi_stroke_rect(memory_dc, r->x, r->y, r->w, r->h,
(unsigned short)r->rounding, r->line_thickness, r->color);
} break;
case NK_COMMAND_RECT_FILLED: {
const struct nk_command_rect_filled* r = (const struct nk_command_rect_filled*)cmd;
nk_gdi_fill_rect(memory_dc, r->x, r->y, r->w, r->h,
(unsigned short)r->rounding, r->color);
} break;
case NK_COMMAND_CIRCLE: {
const struct nk_command_circle* c = (const struct nk_command_circle*)cmd;
nk_gdi_stroke_circle(memory_dc, c->x, c->y, c->w, c->h, c->line_thickness, c->color);
} break;
case NK_COMMAND_CIRCLE_FILLED: {
const struct nk_command_circle_filled* c = (const struct nk_command_circle_filled*)cmd;
nk_gdi_fill_circle(memory_dc, c->x, c->y, c->w, c->h, c->color);
} break;
case NK_COMMAND_TRIANGLE: {
const struct nk_command_triangle* t = (const struct nk_command_triangle*)cmd;
nk_gdi_stroke_triangle(memory_dc, t->a.x, t->a.y, t->b.x, t->b.y,
t->c.x, t->c.y, t->line_thickness, t->color);
} break;
case NK_COMMAND_TRIANGLE_FILLED: {
const struct nk_command_triangle_filled* t = (const struct nk_command_triangle_filled*)cmd;
nk_gdi_fill_triangle(memory_dc, t->a.x, t->a.y, t->b.x, t->b.y,
t->c.x, t->c.y, t->color);
} break;
case NK_COMMAND_POLYGON: {
const struct nk_command_polygon* p = (const struct nk_command_polygon*)cmd;
nk_gdi_stroke_polygon(memory_dc, p->points, p->point_count, p->line_thickness, p->color);
} break;
case NK_COMMAND_POLYGON_FILLED: {
const struct nk_command_polygon_filled* p = (const struct nk_command_polygon_filled*)cmd;
nk_gdi_fill_polygon(memory_dc, p->points, p->point_count, p->color);
} break;
case NK_COMMAND_POLYLINE: {
const struct nk_command_polyline* p = (const struct nk_command_polyline*)cmd;
nk_gdi_stroke_polyline(memory_dc, p->points, p->point_count, p->line_thickness, p->color);
} break;
case NK_COMMAND_TEXT: {
const struct nk_command_text* t = (const struct nk_command_text*)cmd;
nk_gdi_draw_text(memory_dc, t->x, t->y, t->w, t->h,
(const char*)t->string, t->length,
(GdiFont*)t->font->userdata.ptr,
t->background, t->foreground);
} break;
case NK_COMMAND_CURVE: {
const struct nk_command_curve* q = (const struct nk_command_curve*)cmd;
nk_gdi_stroke_curve(memory_dc, q->begin, q->ctrl[0], q->ctrl[1],
q->end, q->line_thickness, q->color);
} break;
case NK_COMMAND_RECT_MULTI_COLOR: {
const struct nk_command_rect_multi_color* r = (const struct nk_command_rect_multi_color*)cmd;
nk_gdi_rect_multi_color(gdi, memory_dc, r->x, r->y, r->w, r->h, r->left, r->top, r->right, r->bottom);
} break;
case NK_COMMAND_IMAGE: {
const struct nk_command_image* i = (const struct nk_command_image*)cmd;
nk_gdi_draw_image(gdi, i->x, i->y, i->w, i->h, i->img, i->col);
} break;
case NK_COMMAND_ARC:
case NK_COMMAND_ARC_FILLED:
default: break;
}
}
nk_gdi_blit(gdi, gdi->window_dc);
nk_clear(&gdi->ctx);
}
#endif

View File

@ -0,0 +1,387 @@
#ifndef NK_GDI_WINDOW
#define NK_GDI_WINDOW
#define NK_GDI_WINDOW_CLS L"WNDCLS_NkGdi"
#include <windows.h>
/* Functin pointer types for window callbacks */
typedef int(*nkgdi_window_func_close)(void);
typedef int(*nkgdi_window_func_draw)(struct nk_context*);
/* Window container / context */
struct nkgdi_window
{
/* The window can be sized */
int allow_sizing;
/* The window can be maximized by double clicking the titlebar */
int allow_maximize;
/* The window is allowed to be moved by the user */
int allow_move;
/* The window will render it's title bar */
int has_titlebar;
/* Callbacks */
/* Called when the user or os requests a window close (return 1 to accept the reqest)*/
nkgdi_window_func_close cb_on_close;
/* Called each time the window content should be drawn. Here you will do your nuklear drawing code
* but WITHOUT nk_begin and nk_end. Return 1 to keep the window open.
*/
nkgdi_window_func_draw cb_on_draw;
/* Internal Data */
struct
{
/* Window handle */
HWND window_handle;
/* Nuklear & GDI context */
nk_gdi_ctx nk_gdi_ctx;
struct nk_context* nk_ctx;
/* GDI required objects */
GdiFont* gdi_font;
HDC window_dc;
/* Internally used state variables */
int is_open;
int is_draggin;
int ws_override;
int is_maximized;
POINT drag_offset;
int width;
int height;
}_internal;
};
/* API */
/* This function will init all resources used by the implementation */
void nkgdi_window_init(void);
/* This function will free all globally used resources */
void nkgdi_window_shutdown(void);
/* Creates a new window (for the wnd context) */
void nkgdi_window_create(struct nkgdi_window* wnd, unsigned int width, unsigned int height, const char* name, int posX, int posY);
/* Updates the window (Windows message loop, nuklear loop and drawing). Returns one as long as the window is valid and open */
int nkgdi_window_update(struct nkgdi_window* wnd);
/* Destroys the window context wnd */
void nkgdi_window_destroy(struct nkgdi_window* wnd);
#ifdef NKGDI_IMPLEMENT_WINDOW
/* Predeclare the windows window message procs */
/* This proc will setup the pointer to the window context */
LRESULT nkgdi_window_proc_setup(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
/* This proc will take the window context pointer and performs operations on it*/
LRESULT nkgdi_window_proc_run(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam);
void nkgdi_window_init(void)
{
/* Describe the window class */
WNDCLASSEXW cls;
cls.cbSize = sizeof(WNDCLASSEXW);
cls.style = CS_OWNDC | CS_DBLCLKS;
cls.lpfnWndProc = &nkgdi_window_proc_setup;
cls.cbClsExtra = 0;
cls.cbWndExtra = 0;
cls.hInstance = GetModuleHandle(NULL);
cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
cls.hCursor = LoadCursor(NULL, IDC_ARROW);
cls.hbrBackground = NULL;
cls.lpszMenuName = NULL;
cls.lpszClassName = NK_GDI_WINDOW_CLS;
cls.hIconSm = NULL;
/* Register the window class */
RegisterClassExW(&cls);
}
void nkgdi_window_shutdown(void)
{
/* Windows class no longer required, unregister it */
UnregisterClassW(NK_GDI_WINDOW_CLS, GetModuleHandle(NULL));
}
void nkgdi_window_create(struct nkgdi_window* wnd, unsigned int width, unsigned int height, const char* name, int posX, int posY)
{
DWORD styleEx = WS_EX_WINDOWEDGE;
DWORD style = WS_POPUP;
/* Adjust window size to fit selected window styles */
RECT cr;
cr.left = 0;
cr.top = 0;
cr.right = width;
cr.bottom = height;
AdjustWindowRectEx(&cr, style, FALSE, styleEx);
/* Create the new window */
wnd->_internal.window_handle = CreateWindowExW(
styleEx,
NK_GDI_WINDOW_CLS,
L"NkGdi",
style | WS_VISIBLE,
posX, posY,
cr.right - cr.left, cr.bottom - cr.top,
NULL, NULL,
GetModuleHandleW(NULL),
wnd
);
/* Give the window the ascii char name */
SetWindowTextA(wnd->_internal.window_handle, name);
/* Extract the window dc for gdi drawing */
wnd->_internal.window_dc = GetWindowDC(wnd->_internal.window_handle);
/* Create the gdi font required to draw text */
wnd->_internal.gdi_font = nk_gdifont_create("Arial", 16);
/* Init the gdi backend */
wnd->_internal.nk_ctx = nk_gdi_init(&wnd->_internal.nk_gdi_ctx, wnd->_internal.gdi_font, wnd->_internal.window_dc, width, height);
/* Bring all internal variables to a defined and valid initial state */
wnd->_internal.is_open = 1;
wnd->_internal.is_draggin = 0;
wnd->_internal.ws_override = 0;
wnd->_internal.is_maximized = 0;
wnd->_internal.drag_offset.x = 0;
wnd->_internal.drag_offset.y = 0;
wnd->_internal.width = width;
wnd->_internal.height = height;
}
void nkgdi_window_destroy(struct nkgdi_window* wnd)
{
/* Destroy all objects in reverse order */
if (wnd->_internal.nk_gdi_ctx)
{
nk_gdi_shutdown(wnd->_internal.nk_gdi_ctx);
}
if (wnd->_internal.gdi_font)
{
nk_gdifont_del(wnd->_internal.gdi_font);
}
if (wnd->_internal.window_dc)
{
ReleaseDC(wnd->_internal.window_handle, wnd->_internal.window_dc);
}
if (wnd->_internal.window_handle)
{
CloseWindow(wnd->_internal.window_handle);
DestroyWindow(wnd->_internal.window_handle);
}
}
int nkgdi_window_update(struct nkgdi_window* wnd)
{
/* The window will only be updated when it is open / valid */
if (wnd->_internal.is_open)
{
/* First all pending window events will be processed */
MSG msg;
nk_input_begin(wnd->_internal.nk_ctx);
while (PeekMessage(&msg, wnd->_internal.window_handle, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
nk_input_end(wnd->_internal.nk_ctx);
/* To setup the nuklear window we need the windows title */
char title[1024];
GetWindowTextA(wnd->_internal.window_handle, title, 1024);
/* The nk window flags are beeing create based on the context setup */
nk_flags window_flags = NK_WINDOW_BORDER;
if(wnd->has_titlebar)
window_flags |= NK_WINDOW_CLOSABLE | NK_WINDOW_TITLE;
if(!wnd->_internal.is_maximized && wnd->allow_sizing)
window_flags |= NK_WINDOW_SCALABLE;
/* Override the nuklear windows size when required */
if (wnd->_internal.ws_override)
nk_window_set_bounds(wnd->_internal.nk_ctx, title, nk_rect(0, 0, wnd->_internal.width, wnd->_internal.height));
/* Start the nuklear window */
if (nk_begin(wnd->_internal.nk_ctx, title, nk_rect(0, 0, wnd->_internal.width, wnd->_internal.height), window_flags))
{
/* Call user drawing callback */
if(wnd->cb_on_draw && !wnd->cb_on_draw(wnd->_internal.nk_ctx))
wnd->_internal.is_open = 0;
/* Update the windows window to reflect the nuklear windows size */
struct nk_rect bounds = nk_window_get_bounds(wnd->_internal.nk_ctx);
if(bounds.w != wnd->_internal.width || bounds.h != wnd->_internal.height)
SetWindowPos(wnd->_internal.window_handle, NULL, 0, 0, bounds.w, bounds.h, SWP_NOMOVE | SWP_NOOWNERZORDER);
}
else
{
/* Nuklear window was closed. Handle close internally */
if(!wnd->cb_on_close || wnd->cb_on_close())
wnd->_internal.is_open = 0;
}
nk_end(wnd->_internal.nk_ctx);
/* We no longer need the window size override flag to be set */
wnd->_internal.ws_override = 0;
/* Pass context to the nuklear gdi renderer */
nk_gdi_render(wnd->_internal.nk_gdi_ctx, nk_rgb(0, 0, 0));
}
return wnd->_internal.is_open;
}
LRESULT nkgdi_window_proc_setup(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
/* Waiting to receive the NCCREATE message with the custom window data */
if (msg == WM_NCCREATE)
{
/* Extracting the window context from message parameters */
CREATESTRUCT* ptrCr = (CREATESTRUCT*)lParam;
struct nkgdi_window* nkgdi_wnd = (struct nkgdi_window*)ptrCr->lpCreateParams;
/* Store the context in the window and redirect any further message to the run window proc*/
SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)nkgdi_wnd);
SetWindowLongPtr(wnd, GWLP_WNDPROC, (LONG_PTR)&nkgdi_window_proc_run);
/* Already call the run proc so that it gets the chance to handle NCCREATE as well */
return nkgdi_window_proc_run(wnd, msg, wParam, lParam);
}
/* Until we get WM_NCCREATE windows is going to handle the messages */
return DefWindowProc(wnd, msg, wParam, lParam);
}
LRESULT nkgdi_window_proc_run(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
/* The window context is extracted from the window data */
struct nkgdi_window* nkwnd = (struct nkgdi_window*)GetWindowLongPtrW(wnd, GWLP_USERDATA);
/* Switch on the message code to handle all required messages */
switch (msg)
{
/* Window close event */
case WM_CLOSE:
/* Call custom close callback */
if(!nkwnd->cb_on_close || nkwnd->cb_on_close())
nkwnd->_internal.is_open = 0;
return 0; /* No default behaviour. We do it our own way */
/* Window sizing event (is currently beeing sized) */
case WM_SIZING:
{
/* Size of the client / active are is extracted and stored */
RECT cr;
GetClientRect(wnd, &cr);
nkwnd->_internal.width = cr.right - cr.left;
nkwnd->_internal.height = cr.bottom - cr.top;
}
break;
/* Window size event (done sizing, maximize, minimize, ...) */
case WM_SIZE:
{
/* Window was maximized */
if (wParam == SIZE_MAXIMIZED)
{
/* Get the nearest monitor and retrive its details */
HMONITOR monitor = MonitorFromWindow(wnd, MONITOR_DEFAULTTOPRIMARY);
MONITORINFO monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFO);
if (GetMonitorInfoW(monitor, &monitorInfo))
{
/* Adjust the window size and position by the monitor working area (without taskbar) */
nkwnd->_internal.height = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
nkwnd->_internal.width = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
nkwnd->_internal.ws_override = 1; /* Sizing was done without nuklear beeing aware. So we need to override it */
nkwnd->_internal.is_maximized = 1;
SetWindowPos(wnd, NULL, 0, 0, nkwnd->_internal.width, nkwnd->_internal.height, SWP_NOMOVE | SWP_NOZORDER);
}
}
/* Window was restored (no longer maximized) */
else if (wParam == SIZE_RESTORED)
{
nkwnd->_internal.is_maximized = 0;
}
/* Always get the new bounds of the window */
RECT cr;
GetClientRect(wnd, &cr);
nkwnd->_internal.width = cr.right - cr.left;
nkwnd->_internal.height = cr.bottom - cr.top;
}
break;
/* Mouse started left click */
case WM_LBUTTONDOWN:
{
/* Handle dragging when allowed, has titlebar and mouse is in titlebar (Y <= 30) */
if (HIWORD(lParam) <= 30 && nkwnd->allow_move && nkwnd->has_titlebar)
{
/* Mark dragging internally and store mouse click offset */
nkwnd->_internal.is_draggin = 1;
nkwnd->_internal.drag_offset.x = LOWORD(lParam);
nkwnd->_internal.drag_offset.y = HIWORD(lParam);
}
}
break;
/* Mouse stoped left click */
case WM_LBUTTONUP:
/* No longer dragging the window */
nkwnd->_internal.is_draggin = 0;
break;
/* Mouse is moving on the window */
case WM_MOUSEMOVE:
{
/* When we are dragging and are not maximized process dragging */
if (nkwnd->_internal.is_draggin && !nkwnd->_internal.is_maximized)
{
/* Get the current global position of the mouse */
POINT cursorPos;
GetCursorPos(&cursorPos);
/* Substract the internal offset */
cursorPos.x -= nkwnd->_internal.drag_offset.x;
cursorPos.y -= nkwnd->_internal.drag_offset.y;
/* Update position of out window and make sure window is in a movable state (= Restored) */
ShowWindow(wnd, SW_RESTORE);
SetWindowPos(wnd, NULL, cursorPos.x, cursorPos.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
}
}
break;
/* Mouse double clicked */
case WM_LBUTTONDBLCLK:
{
/* Will only affect window when on the titlebar */
if (HIWORD(lParam) <= 30 && nkwnd->allow_maximize && nkwnd->has_titlebar)
{
/* When the window is already maximized restore it */
if (nkwnd->_internal.is_maximized)
{
ShowWindow(wnd, SW_RESTORE);
}
/* Else we gonna do maximize it*/
else
{
ShowWindow(wnd, SW_MAXIMIZE);
}
/* We overrideed the window size, make sure to affect the nk window as well */
nkwnd->_internal.ws_override = 1;
}
}
break;
}
/* Allow nuklear to handle the message as well */
if (nkwnd->_internal.nk_gdi_ctx && nk_gdi_handle_event(nkwnd->_internal.nk_gdi_ctx, wnd, msg, wParam, lParam))
return 0;
/* In case we reach this line our code and nuklear did not respond to the message. Allow windows to handle it s*/
return DefWindowProc(wnd, msg, wParam, lParam);
}
#endif
#endif

View File

@ -28,27 +28,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -106,10 +111,16 @@ int main(void)
/* style.c */
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
while (running)
@ -159,6 +170,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -47,6 +47,8 @@ NK_API void nk_gdip_image_free(struct nk_image image);
#include <stdlib.h>
#include <malloc.h>
#define _USE_MATH_DEFINES
#include <math.h>
/* manually declare everything GDI+ needs, because
GDI+ headers are not usable from C */
@ -319,6 +321,10 @@ GpStatus WINGDIPAPI
GdipDrawArcI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
INT width, INT height, REAL startAngle, REAL sweepAngle);
GpStatus WINGDIPAPI
GdipDrawPieI(GpGraphics *graphics, GpPen *pen, INT x, INT y,
INT width, INT height, REAL startAngle, REAL sweepAngle);
GpStatus WINGDIPAPI
GdipFillPieI(GpGraphics *graphics, GpBrush *brush, INT x, INT y,
INT width, INT height, REAL startAngle, REAL sweepAngle);
@ -471,15 +477,25 @@ nk_gdip_fill_rect(short x, short y, unsigned short w,
}
}
static BOOL
SetPoint(POINT *p, LONG x, LONG y)
{
if (!p)
return FALSE;
p->x = x;
p->y = y;
return TRUE;
}
static void
nk_gdip_fill_triangle(short x0, short y0, short x1,
short y1, short x2, short y2, struct nk_color col)
{
POINT points[] = {
{ x0, y0 },
{ x1, y1 },
{ x2, y2 },
};
POINT points[3];
SetPoint(&points[0], x0, y0);
SetPoint(&points[1], x1, y1);
SetPoint(&points[2], x2, y2);
GdipSetSolidFillColor(gdip.brush, convert_color(col));
GdipFillPolygonI(gdip.memory, gdip.brush, points, 3, FillModeAlternate);
@ -489,12 +505,13 @@ static void
nk_gdip_stroke_triangle(short x0, short y0, short x1,
short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col)
{
POINT points[] = {
{ x0, y0 },
{ x1, y1 },
{ x2, y2 },
{ x0, y0 },
};
POINT points[4];
SetPoint(&points[0], x0, y0);
SetPoint(&points[1], x1, y1);
SetPoint(&points[2], x2, y2);
SetPoint(&points[3], x0, y0);
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
GdipDrawPolygonI(gdip.memory, gdip.pen, points, 4);
@ -569,13 +586,33 @@ nk_gdip_stroke_curve(struct nk_vec2i p1,
GdipDrawBezierI(gdip.memory, gdip.pen, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
}
static void
nk_gdip_fill_arc(short cx, short cy, unsigned short r, float amin, float adelta, struct nk_color col)
{
GdipSetSolidFillColor(gdip.brush, convert_color(col));
GdipFillPieI(gdip.memory, gdip.brush, cx - r, cy - r, r * 2, r * 2, amin * (180/M_PI), adelta * (180/M_PI));
}
static void
nk_gdip_stroke_arc(short cx, short cy, unsigned short r, float amin, float adelta, unsigned short line_thickness, struct nk_color col)
{
GdipSetPenWidth(gdip.pen, (REAL)line_thickness);
GdipSetPenColor(gdip.pen, convert_color(col));
GdipDrawPieI(gdip.memory, gdip.pen, cx - r, cy - r, r * 2, r * 2, amin * (180/M_PI), adelta * (180/M_PI));
}
static void
nk_gdip_draw_text(short x, short y, unsigned short w, unsigned short h,
const char *text, int len, GdipFont *font, struct nk_color cbg, struct nk_color cfg)
{
int wsize;
WCHAR* wstr;
RectF layout = { (FLOAT)x, (FLOAT)y, (FLOAT)w, (FLOAT)h };
RectF layout;
layout.X = x;
layout.Y = y;
layout.Width = w;
layout.Height = h;
if(!text || !font || !len) return;
@ -1149,9 +1186,15 @@ nk_gdip_prerender_gui(enum nk_anti_aliasing AA)
const struct nk_command_image *i = (const struct nk_command_image *)cmd;
nk_gdip_draw_image(i->x, i->y, i->w, i->h, i->img, i->col);
} break;
case NK_COMMAND_ARC: {
const struct nk_command_arc *i = (const struct nk_command_arc *)cmd;
nk_gdip_stroke_arc(i->cx, i->cy, i->r, i->a[0], i->a[1], i->line_thickness, i->color);
} break;
case NK_COMMAND_ARC_FILLED: {
const struct nk_command_arc_filled *i = (const struct nk_command_arc_filled *)cmd;
nk_gdip_fill_arc(i->cx, i->cy, i->r, i->a[0], i->a[1], i->color);
} break;
case NK_COMMAND_RECT_MULTI_COLOR:
case NK_COMMAND_ARC:
case NK_COMMAND_ARC_FILLED:
default: break;
}
}

View File

@ -2,7 +2,7 @@
BIN = demo
# Flags
CFLAGS += -std=c99 -pedantic -O2
CFLAGS += -std=c99 -Wall -Wextra -pedantic -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -24,6 +24,9 @@
#include "../../nuklear.h"
#include "nuklear_glfw_gl2.h"
#define STB_IMAGE_IMPLEMENTATION
#include "../../demo/common/filebrowser/stb_image.h"
#define WINDOW_WIDTH 1200
#define WINDOW_HEIGHT 800
@ -34,30 +37,39 @@
* ===============================================================*/
/* 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 defines */
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
#define INCLUDE_OVERVIEW
/*#define INCLUDE_NODE_EDITOR */
/* #define INCLUDE_ALL */
/* #define INCLUDE_STYLE */
/* #define INCLUDE_CALCULATOR */
#define INCLUDE_CANVAS
/* #define INCLUDE_FILE_BROWSER */
/* #define INCLUDE_OVERVIEW */
/* #define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_FILE_BROWSER
#include "../../demo/common/file_browser.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -73,8 +85,14 @@ int main(void)
/* Platform */
static GLFWwindow *win;
int width = 0, height = 0;
/* GUI */
struct nk_context *ctx;
struct nk_colorf bg;
#ifdef INCLUDE_FILE_BROWSER
struct file_browser browser;
struct media media;
#endif
/* GLFW */
glfwSetErrorCallback(error_callback);
@ -103,13 +121,38 @@ int main(void)
/*nk_style_set_font(ctx, &droid->handle);*/}
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
#ifdef INCLUDE_FILE_BROWSER
/* icons */
glEnable(GL_TEXTURE_2D);
media.icons.home = icon_load("../../demo/common/filebrowser/icon/home.png");
media.icons.directory = icon_load("../../demo/common/filebrowser/icon/directory.png");
media.icons.computer = icon_load("../../demo/common/filebrowser/icon/computer.png");
media.icons.desktop = icon_load("../../demo/common/filebrowser/icon/desktop.png");
media.icons.default_file = icon_load("../../demo/common/filebrowser/icon/default.png");
media.icons.text_file = icon_load("../../demo/common/filebrowser/icon/text.png");
media.icons.music_file = icon_load("../../demo/common/filebrowser/icon/music.png");
media.icons.font_file = icon_load("../../demo/common/filebrowser/icon/font.png");
media.icons.img_file = icon_load("../../demo/common/filebrowser/icon/img.png");
media.icons.movie_file = icon_load("../../demo/common/filebrowser/icon/movie.png");
media_init(&media);
file_browser_init(&browser, &media);
#endif
while (!glfwWindowShouldClose(win))
{
/* Input */
@ -155,6 +198,12 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_FILE_BROWSER
file_browser_run(&browser, ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif
@ -175,8 +224,23 @@ int main(void)
nk_glfw3_render(NK_ANTI_ALIASING_ON);
glfwSwapBuffers(win);
}
#ifdef INCLUDE_FILE_BROWSER
glDeleteTextures(1,(const GLuint*)&media.icons.home.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.directory.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.computer.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.desktop.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.default_file.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.text_file.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.music_file.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.font_file.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.img_file.handle.id);
glDeleteTextures(1,(const GLuint*)&media.icons.movie_file.handle.id);
file_browser_free(&browser);
#endif
nk_glfw3_shutdown();
glfwTerminate();
return 0;
}

View File

@ -53,7 +53,7 @@ NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xof
struct nk_glfw_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
GLuint font_tex;
};
@ -140,7 +140,7 @@ nk_glfw3_render(enum nk_anti_aliasing AA)
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_glfw_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
config.null = dev->null;
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
@ -218,6 +218,7 @@ NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
double x, y;
NK_UNUSED(mods);
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
glfwGetCursorPos(window, &x, &y);
if (action == GLFW_PRESS) {
@ -287,7 +288,7 @@ nk_glfw3_font_stash_end(void)
const void *image; int w, h;
image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_glfw3_device_upload_atlas(image, w, h);
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null);
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.tex_null);
if (glfw.atlas.default_font)
nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
}

View File

@ -2,7 +2,7 @@
BIN = demo
# Flags
CFLAGS += -std=c99 -pedantic -O2
CFLAGS += -std=c89 -Wall -Wextra -pedantic -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -41,27 +41,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
#define INCLUDE_OVERVIEW
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -121,10 +126,16 @@ int main(void)
/*nk_style_set_font(ctx, &droid->handle);*/}
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
@ -173,6 +184,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -26,7 +26,7 @@ enum nk_glfw_init_state{
struct nk_glfw_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
GLuint vbo, vao, ebo;
GLuint prog;
GLuint vert_shdr;
@ -266,7 +266,7 @@ nk_glfw3_render(struct nk_glfw* glfw, enum nk_anti_aliasing AA, int max_vertex_b
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_glfw_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
config.null = dev->null;
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
@ -328,9 +328,10 @@ nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff)
NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow* win, int button, int action, int mods)
{
double x, y;
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
struct nk_glfw* glfw = glfwGetWindowUserPointer(win);
double x, y;
NK_UNUSED(mods);
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
glfwGetCursorPos(win, &x, &y);
if (action == GLFW_PRESS) {
double dt = glfwGetTime() - glfw->last_button_click;
@ -345,7 +346,7 @@ nk_glfw3_mouse_button_callback(GLFWwindow* win, int button, int action, int mods
NK_INTERN void
nk_glfw3_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
struct nk_glfw* glfw = usr.ptr;
struct nk_glfw* glfw = (struct nk_glfw*)usr.ptr;
const char *text = glfwGetClipboardString(glfw->win);
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
(void)usr;
@ -354,13 +355,13 @@ nk_glfw3_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
NK_INTERN void
nk_glfw3_clipboard_copy(nk_handle usr, const char *text, int len)
{
struct nk_glfw* glfw = (struct nk_glfw*)usr.ptr;
char *str = 0;
if (!len) return;
str = (char*)malloc((size_t)len+1);
if (!str) return;
memcpy(str, text, (size_t)len);
str[len] = '\0';
struct nk_glfw* glfw = usr.ptr;
glfwSetClipboardString(glfw->win, str);
free(str);
}
@ -402,7 +403,7 @@ nk_glfw3_font_stash_end(struct nk_glfw* glfw)
const void *image; int w, h;
image = nk_font_atlas_bake(&glfw->atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_glfw3_device_upload_atlas(glfw, image, w, h);
nk_font_atlas_end(&glfw->atlas, nk_handle_id((int)glfw->ogl.font_tex), &glfw->ogl.null);
nk_font_atlas_end(&glfw->atlas, nk_handle_id((int)glfw->ogl.font_tex), &glfw->ogl.tex_null);
if (glfw->atlas.default_font)
nk_style_set_font(&glfw->ctx, &glfw->atlas.default_font->handle);
}

View File

@ -2,7 +2,7 @@
BIN = demo
# Flags
CFLAGS += -std=c99 -pedantic -O2
CFLAGS += -std=c89 -Wall -Wextra -pedantic -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -41,27 +41,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
#define INCLUDE_OVERVIEW
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -121,10 +126,16 @@ int main(void)
/*nk_style_set_font(ctx, &droid->handle);*/}
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
/* Create bindless texture.
@ -194,6 +205,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -72,7 +72,7 @@ struct nk_glfw_vertex {
struct nk_glfw_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
GLuint vbo, vao, ebo;
GLuint prog;
GLuint vert_shdr;
@ -116,6 +116,7 @@ NK_API void
nk_glfw3_device_create()
{
GLint status;
GLint len = 0;
static const GLchar *vertex_shader =
NK_SHADER_VERSION
NK_SHADER_BINDLESS
@ -156,7 +157,6 @@ nk_glfw3_device_create()
glCompileShader(dev->frag_shdr);
glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status);
GLint len = 0;
glGetShaderiv(dev->vert_shdr, GL_INFO_LOG_LENGTH, &len);
if (len > 1) {
char *log = (char*)calloc((size_t)len, sizeof(char));
@ -407,7 +407,7 @@ nk_glfw3_render(enum nk_anti_aliasing AA)
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_glfw_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex);
config.null = dev->null;
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
@ -477,6 +477,7 @@ NK_API void
nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
double x, y;
NK_UNUSED(mods);
if (button != GLFW_MOUSE_BUTTON_LEFT) return;
glfwGetCursorPos(window, &x, &y);
if (action == GLFW_PRESS) {
@ -552,7 +553,7 @@ nk_glfw3_font_stash_end(void)
const void *image; int w, h;
image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_glfw3_device_upload_atlas(image, w, h);
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex_index), &glfw.ogl.null);
nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex_index), &glfw.ogl.tex_null);
if (glfw.atlas.default_font)
nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle);
}

View File

@ -1,4 +1,4 @@
CFLAGS=`sdl2-config --cflags --libs` -std=c11 -Wall -O0 -g -fvisibility=hidden -Wno-unused `pkg-config SDL2_ttf --cflags --libs`
CFLAGS=`sdl2-config --cflags --libs` -std=c89 -Wall -Wextra -pedantic -Wno-unused-function -O0 -g -fvisibility=hidden `pkg-config SDL2_ttf --cflags --libs`
.PHONY: clean

View File

@ -2,7 +2,6 @@
#include <SDL_mouse.h>
#include <SDL_keyboard.h>
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
@ -23,9 +22,48 @@
#define NK_SDLSURFACE_IMPLEMENTATION
#include "sdl2surface_rawfb.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 defines */
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../../demo/common/node_editor.c"
#endif
static int translate_sdl_key(struct SDL_Keysym const *k)
{
/*keyboard handling left as an exercise for the reader */
NK_UNUSED(k);
return NK_KEY_NONE;
}
@ -36,7 +74,7 @@ static int sdl_button_to_nk(int button)
switch(button)
{
default:
//ft
/* ft */
case SDL_BUTTON_LEFT:
return NK_BUTTON_LEFT;
break;
@ -50,7 +88,7 @@ static int sdl_button_to_nk(int button)
}
}
#if 0
static void
grid_demo(struct nk_context *ctx)
{
@ -85,7 +123,7 @@ grid_demo(struct nk_context *ctx)
}
nk_end(ctx);
}
#endif
int main(int argc, char **argv)
@ -93,20 +131,28 @@ int main(int argc, char **argv)
struct nk_color clear = {0,100,0,255};
struct nk_vec2 vec;
struct nk_rect bounds = {40,40,0,0};
struct sdlsurface_context *context;
SDL_DisplayMode dm;
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *tex;
SDL_Surface *surface;
NK_UNUSED(argc);
NK_UNUSED(argv);
SDL_Init(SDL_INIT_VIDEO);
printf("sdl init called...\n");
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
SDL_DisplayMode dm;
SDL_GetDesktopDisplayMode(0, &dm);
printf("desktop display mode %d %d\n", dm.w, dm.h);
SDL_Window *window = SDL_CreateWindow("Puzzle", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w-200,dm.h-200, SDL_WINDOW_OPENGL);
window = SDL_CreateWindow("Puzzle", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w-200,dm.h-200, SDL_WINDOW_OPENGL);
if (!window)
{
printf("can't open window!\n");
@ -114,18 +160,18 @@ int main(int argc, char **argv)
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, dm.w-200, dm.h-200, 32, SDL_PIXELFORMAT_ARGB8888);
surface = SDL_CreateRGBSurfaceWithFormat(0, dm.w-200, dm.h-200, 32, SDL_PIXELFORMAT_ARGB8888);
struct sdlsurface_context *context = nk_sdlsurface_init(surface, 13.0f);
context = nk_sdlsurface_init(surface, 13.0f);
while(1)
{
nk_input_begin(&(context->ctx));
SDL_Event event;
nk_input_begin(&(context->ctx));
while (SDL_PollEvent(&event))
{
switch(event.type)
@ -177,14 +223,29 @@ int main(int argc, char **argv)
}
nk_end(&(context->ctx));
// grid_demo(&(context->ctx));
/* grid_demo(&(context->ctx)); */
/* -------------- EXAMPLES ---------------- */
#ifdef INCLUDE_CALCULATOR
calculator(&(context->ctx));
#endif
#ifdef INCLUDE_CANVAS
canvas(&(context->ctx));
#endif
#ifdef INCLUDE_OVERVIEW
overview(&(context->ctx));
#endif
#ifdef INCLUDE_NODE_EDITOR
node_editor(&(context->ctx));
#endif
/* ----------------------------------------- */
nk_sdlsurface_render(context, clear, 1);
SDL_Texture *tex = SDL_CreateTextureFromSurface(renderer, surface);
tex = SDL_CreateTextureFromSurface(renderer, surface);
SDL_RenderCopy(renderer, tex, NULL, NULL);
SDL_RenderPresent(renderer);
SDL_DestroyTexture(tex);

View File

@ -65,54 +65,18 @@ struct sdlsurface_context {
#endif
static unsigned int
nk_sdlsurface_color2int(const struct nk_color c, SDL_PixelFormatEnum pl)
nk_sdlsurface_color2int(const struct nk_color c, const SDL_PixelFormat *format)
{
unsigned int res = 0;
switch (pl) {
case SDL_PIXELFORMAT_RGBA8888:
res |= c.r << 24;
res |= c.g << 16;
res |= c.b << 8;
res |= c.a;
break;
case SDL_PIXELFORMAT_ARGB8888:
res |= c.a << 24;
res |= c.r << 16;
res |= c.g << 8;
res |= c.b;
break;
default:
perror("nk_sdlsurface_color2int(): Unsupported pixel layout.\n");
break;
}
return (res);
return SDL_MapRGBA(format, c.r, c.g, c.b, c.a);
}
static struct nk_color
nk_sdlsurface_int2color(const unsigned int i, SDL_PixelFormatEnum pl)
nk_sdlsurface_int2color(const unsigned int i, const SDL_PixelFormat *format)
{
struct nk_color col = {0,0,0,0};
switch (pl) {
case SDL_PIXELFORMAT_RGBA8888:
col.r = (i >> 24) & 0xff;
col.g = (i >> 16) & 0xff;
col.b = (i >> 8) & 0xff;
col.a = i & 0xff;
break;
case SDL_PIXELFORMAT_ARGB8888:
col.a = (i >> 24) & 0xff;
col.r = (i >> 16) & 0xff;
col.g = (i >> 8) & 0xff;
col.b = i & 0xff;
break;
SDL_GetRGBA(i, format, &col.r, &col.g, &col.b, &col.a);
default:
perror("nk_sdlsurface_int2color(): Unsupported pixel layout.\n");
break;
}
return col;
}
@ -120,16 +84,22 @@ static void
nk_sdlsurface_ctx_setpixel(const struct sdlsurface_context *sdlsurface,
const short x0, const short y0, const struct nk_color col)
{
unsigned int c = nk_sdlsurface_color2int(col, sdlsurface->fb->format->format);
unsigned int c = nk_sdlsurface_color2int(col, sdlsurface->fb->format);
unsigned char *pixels = sdlsurface->fb->pixels;
unsigned int *ptr;
pixels += y0 * sdlsurface->fb->pitch;
ptr = (unsigned int *)pixels + x0;
if (y0 < sdlsurface->scissors.h && y0 >= sdlsurface->scissors.y &&
x0 >= sdlsurface->scissors.x && x0 < sdlsurface->scissors.w)
*ptr = c;
x0 >= sdlsurface->scissors.x && x0 < sdlsurface->scissors.w) {
if (sdlsurface->fb->format->BytesPerPixel == 4) {
*((Uint32 *)pixels + x0) = c;
} else if (sdlsurface->fb->format->BytesPerPixel == 2) {
*((Uint16 *)pixels + x0) = c;
} else {
*((Uint8 *)pixels + x0) = c;
}
}
}
static void
@ -140,40 +110,49 @@ nk_sdlsurface_line_horizontal(const struct sdlsurface_context *sdlsurface,
* It does not check for scissors or image borders.
* The caller has to make sure it does no exceed bounds. */
unsigned int i, n;
unsigned int c[16];
unsigned char c[16 * 4];
unsigned char *pixels = sdlsurface->fb->pixels;
unsigned int *ptr;
unsigned int bpp = sdlsurface->fb->format->BytesPerPixel;
pixels += y * sdlsurface->fb->pitch;
ptr = (unsigned int *)pixels + x0;
pixels += (y * sdlsurface->fb->pitch) + (x0 * bpp);
n = x1 - x0;
for (i = 0; i < sizeof(c) / sizeof(c[0]); i++)
c[i] = nk_sdlsurface_color2int(col, sdlsurface->fb->format->format);
n = (x1 - x0) * bpp;
if (bpp == 4) {
for (i = 0; i < sizeof(c) / bpp; i++)
((Uint32 *)c)[i] = nk_sdlsurface_color2int(col, sdlsurface->fb->format);
} else if (bpp == 2) {
for (i = 0; i < sizeof(c) / bpp; i++)
((Uint16 *)c)[i] = nk_sdlsurface_color2int(col, sdlsurface->fb->format);
} else {
for (i = 0; i < sizeof(c) / bpp; i++)
((Uint8 *)c)[i] = nk_sdlsurface_color2int(col, sdlsurface->fb->format);
}
while (n > 16) {
memcpy((void *)ptr, c, sizeof(c));
n -= 16; ptr += 16;
while (n > sizeof(c)) {
memcpy((void*)pixels, c, sizeof(c));
n -= sizeof(c); pixels += sizeof(c);
} for (i = 0; i < n; i++)
ptr[i] = c[i];
pixels[i] = c[i];
}
static void
nk_sdlsurface_img_setpixel(const struct SDL_Surface *img,
const int x0, const int y0, const struct nk_color col)
{
unsigned int c = nk_sdlsurface_color2int(col, img->format->format);
unsigned int c = nk_sdlsurface_color2int(col, img->format);
unsigned char *ptr;
unsigned int *pixel;
NK_ASSERT(img);
if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) {
ptr = img->pixels + (img->pitch * y0);
pixel = (unsigned int *)ptr;
ptr = (unsigned char *)img->pixels + (img->pitch * y0);
if (img->format == NK_FONT_ATLAS_ALPHA8) {
ptr[x0] = col.a;
} else if (img->format->BytesPerPixel == 4) {
((Uint32 *)ptr)[x0] = c;
} else if (img->format->BytesPerPixel == 2) {
((Uint16 *)ptr)[x0] = c;
} else {
pixel[x0] = c;
((Uint8 *)ptr)[x0] = c;
}
}
}
@ -186,14 +165,20 @@ nk_sdlsurface_img_getpixel(const struct SDL_Surface *img, const int x0, const in
unsigned int pixel;
NK_ASSERT(img);
if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) {
ptr = img->pixels + (img->pitch * y0);
ptr = (unsigned char *)img->pixels + (img->pitch * y0);
if (img->format == NK_FONT_ATLAS_ALPHA8) {
col.a = ptr[x0];
col.b = col.g = col.r = 0xff;
} else if (img->format->BytesPerPixel == 4) {
pixel = ((Uint32 *)ptr)[x0];
col = nk_sdlsurface_int2color(pixel, img->format);
} else if (img->format->BytesPerPixel == 2) {
pixel = ((Uint16 *)ptr)[x0];
col = nk_sdlsurface_int2color(pixel, img->format);
} else {
pixel = ((unsigned int *)ptr)[x0];
col = nk_sdlsurface_int2color(pixel, img->format->format);
pixel = ((Uint8 *)ptr)[x0];
col = nk_sdlsurface_int2color(pixel, img->format);
}
} return col;
}
@ -235,6 +220,8 @@ nk_sdlsurface_stroke_line(const struct sdlsurface_context *sdlsurface,
short tmp;
int dy, dx, stepx, stepy;
NK_UNUSED(line_thickness);
dy = y1 - y0;
dx = x1 - x0;
@ -369,6 +356,8 @@ nk_sdlsurface_stroke_arc(const struct sdlsurface_context *sdlsurface,
const int fa2 = 4 * a2, fb2 = 4 * b2;
int x, y, sigma;
NK_UNUSED(line_thickness);
if (s != 0 && s != 90 && s != 180 && s != 270) return;
if (w < 1 || h < 1) return;
@ -735,6 +724,8 @@ nk_sdlsurface_stroke_circle(const struct sdlsurface_context *sdlsurface,
const int fa2 = 4 * a2, fb2 = 4 * b2;
int x, y, sigma;
NK_UNUSED(line_thickness);
/* Convert upper left to center */
h = (h + 1) / 2;
w = (w + 1) / 2;
@ -802,13 +793,13 @@ nk_sdlsurface_clear(const struct sdlsurface_context *sdlsurface, const struct nk
struct sdlsurface_context*
nk_sdlsurface_init(SDL_Surface *fb, float fontSize)
{
SDL_assert((fb->format->format == SDL_PIXELFORMAT_ARGB8888)
|| (fb->format->format == SDL_PIXELFORMAT_RGBA8888));
const void *tex;
int texh, texw;
struct sdlsurface_context *sdlsurface;
assert((fb->format->format == SDL_PIXELFORMAT_ARGB8888)
|| (fb->format->format == SDL_PIXELFORMAT_RGBA8888));
sdlsurface = malloc(sizeof(struct sdlsurface_context));
if (!sdlsurface)
return NULL;
@ -831,7 +822,7 @@ nk_sdlsurface_init(SDL_Surface *fb, float fontSize)
return NULL;
}
sdlsurface->font_tex = SDL_CreateRGBSurfaceWithFormat(0, texw, texh, 32, fb->format->format);
sdlsurface->font_tex = SDL_CreateRGBSurface(0, texw, texh, 32, 0xff, 0xff00, 0xff0000, 0xff000000);
memcpy(sdlsurface->font_tex->pixels, tex, texw * texh * 4);
@ -841,19 +832,6 @@ nk_sdlsurface_init(SDL_Surface *fb, float fontSize)
nk_style_load_all_cursors(&sdlsurface->ctx, sdlsurface->atlas.cursors);
nk_sdlsurface_scissor(sdlsurface, 0, 0, sdlsurface->fb->w, sdlsurface->fb->h);
if (fb->format->format == SDL_PIXELFORMAT_RGBA8888)
{
SDL_assert(sdlsurface->font_tex->pitch == sdlsurface->font_tex->w * 4);
uint32_t *fontPixels = (uint32_t *)sdlsurface->font_tex->pixels;
for (int i = 0; i < sdlsurface->font_tex->w * sdlsurface->font_tex->h; i++)
{
uint32_t col = fontPixels[i];
fontPixels[i] &= 0xFFFF00;
fontPixels[i] |= ((col & 0xFF000000) >> 24);
fontPixels[i] |= ((col & 0xFF) << 24);
}
}
return sdlsurface;
}
@ -961,8 +939,8 @@ nk_sdlsurface_draw_text(const struct sdlsurface_context *sdlsurface,
dst_rect.x = x + g.offset.x + rect.x;
dst_rect.y = g.offset.y + rect.y;
dst_rect.w = ceilf(g.width);
dst_rect.h = ceilf(g.height);
dst_rect.w = ceil(g.width);
dst_rect.h = ceil(g.height);
/* Use software rescaling to blit glyph from font_text to framebuffer */
nk_sdlsurface_stretch_image(sdlsurface->fb, sdlsurface->font_tex, &dst_rect, &src_rect, &sdlsurface->scissors, &fg);

View File

@ -2,7 +2,7 @@
BIN = demo
# Flags
CFLAGS += -std=c99 -pedantic -O2
CFLAGS += -std=c89 -Wall -Wextra -pedantic -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -37,27 +37,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -78,6 +83,9 @@ main(int argc, char *argv[])
struct nk_context *ctx;
struct nk_colorf bg;
NK_UNUSED(argc);
NK_UNUSED(argv);
/* SDL setup */
SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
SDL_Init(SDL_INIT_VIDEO);
@ -109,10 +117,16 @@ main(int argc, char *argv[])
/*nk_style_set_font(ctx, &roboto->handle)*/;}
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
@ -165,6 +179,9 @@ main(int argc, char *argv[])
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -33,7 +33,7 @@ NK_API void nk_sdl_shutdown(void);
struct nk_sdl_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
GLuint font_tex;
};
@ -120,7 +120,7 @@ nk_sdl_render(enum nk_anti_aliasing AA)
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_sdl_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_sdl_vertex);
config.null = dev->null;
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
@ -226,7 +226,7 @@ nk_sdl_font_stash_end(void)
const void *image; int w, h;
image = nk_font_atlas_bake(&sdl.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_sdl_device_upload_atlas(image, w, h);
nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.null);
nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.tex_null);
if (sdl.atlas.default_font)
nk_style_set_font(&sdl.ctx, &sdl.atlas.default_font->handle);
}
@ -246,87 +246,85 @@ nk_sdl_handle_event(SDL_Event *evt)
SDL_WarpMouseInWindow(sdl.win, x, y);
ctx->input.mouse.ungrab = 0;
}
if (evt->type == SDL_KEYUP || evt->type == SDL_KEYDOWN) {
/* key events */
switch(evt->type)
{
case SDL_KEYUP: /* KEYUP & KEYDOWN share same routine */
case SDL_KEYDOWN:
{
int down = evt->type == SDL_KEYDOWN;
const Uint8* state = SDL_GetKeyboardState(0);
SDL_Keycode sym = evt->key.keysym.sym;
if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT)
nk_input_key(ctx, NK_KEY_SHIFT, down);
else if (sym == SDLK_DELETE)
nk_input_key(ctx, NK_KEY_DEL, down);
else if (sym == SDLK_RETURN)
nk_input_key(ctx, NK_KEY_ENTER, down);
else if (sym == SDLK_TAB)
nk_input_key(ctx, NK_KEY_TAB, down);
else if (sym == SDLK_BACKSPACE)
nk_input_key(ctx, NK_KEY_BACKSPACE, down);
else if (sym == SDLK_HOME) {
nk_input_key(ctx, NK_KEY_TEXT_START, down);
nk_input_key(ctx, NK_KEY_SCROLL_START, down);
} else if (sym == SDLK_END) {
nk_input_key(ctx, NK_KEY_TEXT_END, down);
nk_input_key(ctx, NK_KEY_SCROLL_END, down);
} else if (sym == SDLK_PAGEDOWN) {
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down);
} else if (sym == SDLK_PAGEUP) {
nk_input_key(ctx, NK_KEY_SCROLL_UP, down);
} else if (sym == SDLK_z)
nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_r)
nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_c)
nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_v)
nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_x)
nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_b)
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_e)
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_UP)
nk_input_key(ctx, NK_KEY_UP, down);
else if (sym == SDLK_DOWN)
nk_input_key(ctx, NK_KEY_DOWN, down);
else if (sym == SDLK_LEFT) {
switch(evt->key.keysym.sym)
{
case SDLK_RSHIFT: /* RSHIFT & LSHIFT share same routine */
case SDLK_LSHIFT: nk_input_key(ctx, NK_KEY_SHIFT, down); break;
case SDLK_DELETE: nk_input_key(ctx, NK_KEY_DEL, down); break;
case SDLK_RETURN: nk_input_key(ctx, NK_KEY_ENTER, down); break;
case SDLK_TAB: nk_input_key(ctx, NK_KEY_TAB, down); break;
case SDLK_BACKSPACE: nk_input_key(ctx, NK_KEY_BACKSPACE, down); break;
case SDLK_HOME: nk_input_key(ctx, NK_KEY_TEXT_START, down);
nk_input_key(ctx, NK_KEY_SCROLL_START, down); break;
case SDLK_END: nk_input_key(ctx, NK_KEY_TEXT_END, down);
nk_input_key(ctx, NK_KEY_SCROLL_END, down); break;
case SDLK_PAGEDOWN: nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); break;
case SDLK_PAGEUP: nk_input_key(ctx, NK_KEY_SCROLL_UP, down); break;
case SDLK_z: nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_r: nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_c: nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_v: nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_x: nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_b: nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_e: nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_UP: nk_input_key(ctx, NK_KEY_UP, down); break;
case SDLK_DOWN: nk_input_key(ctx, NK_KEY_DOWN, down); break;
case SDLK_LEFT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
else nk_input_key(ctx, NK_KEY_LEFT, down);
} else if (sym == SDLK_RIGHT) {
break;
case SDLK_RIGHT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else nk_input_key(ctx, NK_KEY_RIGHT, down);
} else return 0;
break;
}
}
return 1;
} else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) {
/* mouse button */
case SDL_MOUSEBUTTONUP: /* MOUSEBUTTONUP & MOUSEBUTTONDOWN share same routine */
case SDL_MOUSEBUTTONDOWN:
{
int down = evt->type == SDL_MOUSEBUTTONDOWN;
const int x = evt->button.x, y = evt->button.y;
if (evt->button.button == SDL_BUTTON_LEFT) {
switch(evt->button.button)
{
case SDL_BUTTON_LEFT:
if (evt->button.clicks > 1)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
} else if (evt->button.button == SDL_BUTTON_MIDDLE)
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
else if (evt->button.button == SDL_BUTTON_RIGHT)
nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); break;
case SDL_BUTTON_MIDDLE: nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); break;
case SDL_BUTTON_RIGHT: nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); break;
}
}
return 1;
} else if (evt->type == SDL_MOUSEMOTION) {
/* mouse motion */
case SDL_MOUSEMOTION:
if (ctx->input.mouse.grabbed) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel);
} else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
}
else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
return 1;
} else if (evt->type == SDL_TEXTINPUT) {
/* text input */
case SDL_TEXTINPUT:
{
nk_glyph glyph;
memcpy(glyph, evt->text.text, NK_UTF_SIZE);
nk_input_glyph(ctx, glyph);
}
return 1;
} else if (evt->type == SDL_MOUSEWHEEL) {
/* mouse wheel */
case SDL_MOUSEWHEEL:
nk_input_scroll(ctx,nk_vec2((float)evt->wheel.x,(float)evt->wheel.y));
return 1;
}

View File

@ -2,7 +2,7 @@
BIN = demo
# Flags
CFLAGS += -std=c99 -pedantic -O2
CFLAGS += -std=c89 -Wall -Wextra -pedantic -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -41,27 +41,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -81,6 +86,9 @@ int main(int argc, char *argv[])
struct nk_context *ctx;
struct nk_colorf bg;
NK_UNUSED(argc);
NK_UNUSED(argv);
/* SDL setup */
SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS);
@ -120,10 +128,16 @@ int main(int argc, char *argv[])
/* style.c */
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
@ -175,6 +189,9 @@ int main(int argc, char *argv[])
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -40,7 +40,7 @@ NK_API void nk_sdl_device_create(void);
struct nk_sdl_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
GLuint vbo, vao, ebo;
GLuint prog;
GLuint vert_shdr;
@ -247,7 +247,7 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_sdl_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_sdl_vertex);
config.null = dev->null;
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
@ -334,7 +334,7 @@ nk_sdl_font_stash_end(void)
const void *image; int w, h;
image = nk_font_atlas_bake(&sdl.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_sdl_device_upload_atlas(image, w, h);
nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.null);
nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.tex_null);
if (sdl.atlas.default_font)
nk_style_set_font(&sdl.ctx, &sdl.atlas.default_font->handle);
@ -344,87 +344,96 @@ NK_API int
nk_sdl_handle_event(SDL_Event *evt)
{
struct nk_context *ctx = &sdl.ctx;
if (evt->type == SDL_KEYUP || evt->type == SDL_KEYDOWN) {
/* key events */
/* optional grabbing behavior */
if (ctx->input.mouse.grab) {
SDL_SetRelativeMouseMode(SDL_TRUE);
ctx->input.mouse.grab = 0;
} else if (ctx->input.mouse.ungrab) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_WarpMouseInWindow(sdl.win, x, y);
ctx->input.mouse.ungrab = 0;
}
switch(evt->type)
{
case SDL_KEYUP: /* KEYUP & KEYDOWN share same routine */
case SDL_KEYDOWN:
{
int down = evt->type == SDL_KEYDOWN;
const Uint8* state = SDL_GetKeyboardState(0);
SDL_Keycode sym = evt->key.keysym.sym;
if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT)
nk_input_key(ctx, NK_KEY_SHIFT, down);
else if (sym == SDLK_DELETE)
nk_input_key(ctx, NK_KEY_DEL, down);
else if (sym == SDLK_RETURN)
nk_input_key(ctx, NK_KEY_ENTER, down);
else if (sym == SDLK_TAB)
nk_input_key(ctx, NK_KEY_TAB, down);
else if (sym == SDLK_BACKSPACE)
nk_input_key(ctx, NK_KEY_BACKSPACE, down);
else if (sym == SDLK_HOME) {
nk_input_key(ctx, NK_KEY_TEXT_START, down);
nk_input_key(ctx, NK_KEY_SCROLL_START, down);
} else if (sym == SDLK_END) {
nk_input_key(ctx, NK_KEY_TEXT_END, down);
nk_input_key(ctx, NK_KEY_SCROLL_END, down);
} else if (sym == SDLK_PAGEDOWN) {
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down);
} else if (sym == SDLK_PAGEUP) {
nk_input_key(ctx, NK_KEY_SCROLL_UP, down);
} else if (sym == SDLK_z)
nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_r)
nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_c)
nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_v)
nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_x)
nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_b)
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_e)
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_UP)
nk_input_key(ctx, NK_KEY_UP, down);
else if (sym == SDLK_DOWN)
nk_input_key(ctx, NK_KEY_DOWN, down);
else if (sym == SDLK_LEFT) {
switch(evt->key.keysym.sym)
{
case SDLK_RSHIFT: /* RSHIFT & LSHIFT share same routine */
case SDLK_LSHIFT: nk_input_key(ctx, NK_KEY_SHIFT, down); break;
case SDLK_DELETE: nk_input_key(ctx, NK_KEY_DEL, down); break;
case SDLK_RETURN: nk_input_key(ctx, NK_KEY_ENTER, down); break;
case SDLK_TAB: nk_input_key(ctx, NK_KEY_TAB, down); break;
case SDLK_BACKSPACE: nk_input_key(ctx, NK_KEY_BACKSPACE, down); break;
case SDLK_HOME: nk_input_key(ctx, NK_KEY_TEXT_START, down);
nk_input_key(ctx, NK_KEY_SCROLL_START, down); break;
case SDLK_END: nk_input_key(ctx, NK_KEY_TEXT_END, down);
nk_input_key(ctx, NK_KEY_SCROLL_END, down); break;
case SDLK_PAGEDOWN: nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); break;
case SDLK_PAGEUP: nk_input_key(ctx, NK_KEY_SCROLL_UP, down); break;
case SDLK_z: nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_r: nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_c: nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_v: nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_x: nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_b: nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_e: nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_UP: nk_input_key(ctx, NK_KEY_UP, down); break;
case SDLK_DOWN: nk_input_key(ctx, NK_KEY_DOWN, down); break;
case SDLK_LEFT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
else nk_input_key(ctx, NK_KEY_LEFT, down);
} else if (sym == SDLK_RIGHT) {
break;
case SDLK_RIGHT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else nk_input_key(ctx, NK_KEY_RIGHT, down);
} else return 0;
break;
}
}
return 1;
} else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) {
/* mouse button */
case SDL_MOUSEBUTTONUP: /* MOUSEBUTTONUP & MOUSEBUTTONDOWN share same routine */
case SDL_MOUSEBUTTONDOWN:
{
int down = evt->type == SDL_MOUSEBUTTONDOWN;
const int x = evt->button.x, y = evt->button.y;
if (evt->button.button == SDL_BUTTON_LEFT) {
switch(evt->button.button)
{
case SDL_BUTTON_LEFT:
if (evt->button.clicks > 1)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
} else if (evt->button.button == SDL_BUTTON_MIDDLE)
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
else if (evt->button.button == SDL_BUTTON_RIGHT)
nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); break;
case SDL_BUTTON_MIDDLE: nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); break;
case SDL_BUTTON_RIGHT: nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); break;
}
}
return 1;
} else if (evt->type == SDL_MOUSEMOTION) {
/* mouse motion */
case SDL_MOUSEMOTION:
if (ctx->input.mouse.grabbed) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel);
} else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
}
else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
return 1;
} else if (evt->type == SDL_TEXTINPUT) {
/* text input */
case SDL_TEXTINPUT:
{
nk_glyph glyph;
memcpy(glyph, evt->text.text, NK_UTF_SIZE);
nk_input_glyph(ctx, glyph);
}
return 1;
} else if (evt->type == SDL_MOUSEWHEEL) {
/* mouse wheel */
case SDL_MOUSEWHEEL:
nk_input_scroll(ctx,nk_vec2((float)evt->wheel.x,(float)evt->wheel.y));
return 1;
}

View File

@ -2,7 +2,7 @@
BIN = demo
# Flags
CFLAGS += -std=c99 -pedantic -O2
CFLAGS += -std=c89 -Wall -Wextra -pedantic -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -38,12 +38,37 @@
*
* ===============================================================*/
/* 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. */
/*#include "../style.c"*/
/*#include "../calculator.c"*/
/*#include "../overview.c"*/
/*#include "../node_editor.c"*/
* done with this library. To try out an example uncomment the defines */
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
*
@ -95,6 +120,7 @@ MainLoop(void* loopArg){
nk_layout_row_end(ctx);
nk_menubar_end(ctx);
{
enum {EASY, HARD};
static int op = EASY;
static int property = 20;
@ -107,12 +133,22 @@ MainLoop(void* loopArg){
nk_layout_row_dynamic(ctx, 25, 1);
nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1);
}
}
nk_end(ctx);
/* -------------- EXAMPLES ---------------- */
/*calculator(ctx);*/
/*overview(ctx);*/
/*node_editor(ctx);*/
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif
#ifdef INCLUDE_NODE_EDITOR
node_editor(ctx);
#endif
/* ----------------------------------------- */
/* Draw */
@ -137,6 +173,10 @@ int main(int argc, char* argv[])
/* GUI */
struct nk_context *ctx;
SDL_GLContext glContext;
NK_UNUSED(argc);
NK_UNUSED(argv);
/* SDL setup */
SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
/*SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS); // - do NOT init SDL on GL ES 2 */
@ -169,10 +209,18 @@ int main(int argc, char* argv[])
/*nk_style_set_font(ctx, &roboto->handle)*/;}
/* style.c */
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
#ifdef INCLUDE_STYLE
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
#if defined(__EMSCRIPTEN__)
#include <emscripten.h>

View File

@ -43,7 +43,7 @@ NK_API void nk_sdl_device_create(void);
struct nk_sdl_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
GLuint vbo, ebo;
GLuint prog;
GLuint vert_shdr;
@ -245,7 +245,7 @@ nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_b
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_sdl_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_sdl_vertex);
config.null = dev->null;
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
@ -335,7 +335,7 @@ nk_sdl_font_stash_end(void)
const void *image; int w, h;
image = nk_font_atlas_bake(&sdl.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_sdl_device_upload_atlas(image, w, h);
nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.null);
nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.tex_null);
if (sdl.atlas.default_font)
nk_style_set_font(&sdl.ctx, &sdl.atlas.default_font->handle);
@ -345,87 +345,96 @@ NK_API int
nk_sdl_handle_event(SDL_Event *evt)
{
struct nk_context *ctx = &sdl.ctx;
if (evt->type == SDL_KEYUP || evt->type == SDL_KEYDOWN) {
/* key events */
/* optional grabbing behavior */
if (ctx->input.mouse.grab) {
SDL_SetRelativeMouseMode(SDL_TRUE);
ctx->input.mouse.grab = 0;
} else if (ctx->input.mouse.ungrab) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_WarpMouseInWindow(sdl.win, x, y);
ctx->input.mouse.ungrab = 0;
}
switch(evt->type)
{
case SDL_KEYUP: /* KEYUP & KEYDOWN share same routine */
case SDL_KEYDOWN:
{
int down = evt->type == SDL_KEYDOWN;
const Uint8* state = SDL_GetKeyboardState(0);
SDL_Keycode sym = evt->key.keysym.sym;
if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT)
nk_input_key(ctx, NK_KEY_SHIFT, down);
else if (sym == SDLK_DELETE)
nk_input_key(ctx, NK_KEY_DEL, down);
else if (sym == SDLK_RETURN)
nk_input_key(ctx, NK_KEY_ENTER, down);
else if (sym == SDLK_TAB)
nk_input_key(ctx, NK_KEY_TAB, down);
else if (sym == SDLK_BACKSPACE)
nk_input_key(ctx, NK_KEY_BACKSPACE, down);
else if (sym == SDLK_HOME) {
nk_input_key(ctx, NK_KEY_TEXT_START, down);
nk_input_key(ctx, NK_KEY_SCROLL_START, down);
} else if (sym == SDLK_END) {
nk_input_key(ctx, NK_KEY_TEXT_END, down);
nk_input_key(ctx, NK_KEY_SCROLL_END, down);
} else if (sym == SDLK_PAGEDOWN) {
nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down);
} else if (sym == SDLK_PAGEUP) {
nk_input_key(ctx, NK_KEY_SCROLL_UP, down);
} else if (sym == SDLK_z)
nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_r)
nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_c)
nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_v)
nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_x)
nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_b)
nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_e)
nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]);
else if (sym == SDLK_UP)
nk_input_key(ctx, NK_KEY_UP, down);
else if (sym == SDLK_DOWN)
nk_input_key(ctx, NK_KEY_DOWN, down);
else if (sym == SDLK_LEFT) {
switch(evt->key.keysym.sym)
{
case SDLK_RSHIFT: /* RSHIFT & LSHIFT share same routine */
case SDLK_LSHIFT: nk_input_key(ctx, NK_KEY_SHIFT, down); break;
case SDLK_DELETE: nk_input_key(ctx, NK_KEY_DEL, down); break;
case SDLK_RETURN: nk_input_key(ctx, NK_KEY_ENTER, down); break;
case SDLK_TAB: nk_input_key(ctx, NK_KEY_TAB, down); break;
case SDLK_BACKSPACE: nk_input_key(ctx, NK_KEY_BACKSPACE, down); break;
case SDLK_HOME: nk_input_key(ctx, NK_KEY_TEXT_START, down);
nk_input_key(ctx, NK_KEY_SCROLL_START, down); break;
case SDLK_END: nk_input_key(ctx, NK_KEY_TEXT_END, down);
nk_input_key(ctx, NK_KEY_SCROLL_END, down); break;
case SDLK_PAGEDOWN: nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); break;
case SDLK_PAGEUP: nk_input_key(ctx, NK_KEY_SCROLL_UP, down); break;
case SDLK_z: nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_r: nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_c: nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_v: nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_x: nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_b: nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_e: nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_UP: nk_input_key(ctx, NK_KEY_UP, down); break;
case SDLK_DOWN: nk_input_key(ctx, NK_KEY_DOWN, down); break;
case SDLK_LEFT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
else nk_input_key(ctx, NK_KEY_LEFT, down);
} else if (sym == SDLK_RIGHT) {
break;
case SDLK_RIGHT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else nk_input_key(ctx, NK_KEY_RIGHT, down);
} else return 0;
break;
}
}
return 1;
} else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) {
/* mouse button */
case SDL_MOUSEBUTTONUP: /* MOUSEBUTTONUP & MOUSEBUTTONDOWN share same routine */
case SDL_MOUSEBUTTONDOWN:
{
int down = evt->type == SDL_MOUSEBUTTONDOWN;
const int x = evt->button.x, y = evt->button.y;
if (evt->button.button == SDL_BUTTON_LEFT) {
switch(evt->button.button)
{
case SDL_BUTTON_LEFT:
if (evt->button.clicks > 1)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
} else if (evt->button.button == SDL_BUTTON_MIDDLE)
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
else if (evt->button.button == SDL_BUTTON_RIGHT)
nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); break;
case SDL_BUTTON_MIDDLE: nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); break;
case SDL_BUTTON_RIGHT: nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); break;
}
}
return 1;
} else if (evt->type == SDL_MOUSEMOTION) {
/* mouse motion */
case SDL_MOUSEMOTION:
if (ctx->input.mouse.grabbed) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel);
} else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
}
else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
return 1;
} else if (evt->type == SDL_TEXTINPUT) {
/* text input */
case SDL_TEXTINPUT:
{
nk_glyph glyph;
memcpy(glyph, evt->text.text, NK_UTF_SIZE);
nk_input_glyph(ctx, glyph);
}
return 1;
} else if (evt->type == SDL_MOUSEWHEEL) {
/* mouse wheel */
case SDL_MOUSEWHEEL:
nk_input_scroll(ctx,nk_vec2((float)evt->wheel.x,(float)evt->wheel.y));
return 1;
}

View File

@ -0,0 +1,27 @@
# Install
BIN = demo
# Flags
CFLAGS += -std=c89 -pedantic -O0
CFLAGS += `sdl2-config --cflags`
SRC = main.c
OBJ = $(SRC:.c=.o)
ifeq ($(OS),Windows_NT)
#TODO
#BIN := $(BIN).exe
#LIBS = -lmingw32 -lSDL2main -lSDL2 -lopengl32 -lm -lGLU32
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
#TODO LIBS = -lSDL2 -framework OpenGL -lm
else
LIBS += -lm -ldl `sdl2-config --libs`
endif
endif
$(BIN):
@mkdir -p bin
rm -f bin/$(BIN) $(OBJS)
$(CC) $(SRC) $(CFLAGS) -o bin/$(BIN) $(LIBS)

245
demo/sdl_renderer/main.c Normal file
View File

@ -0,0 +1,245 @@
/* nuklear - 1.32.0 - public domain */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <limits.h>
#include <time.h>
#include <SDL2/SDL.h>
#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_SDL_RENDERER_IMPLEMENTATION
#include "../../nuklear.h"
#include "nuklear_sdl_renderer.h"
#define WINDOW_WIDTH 1200
#define WINDOW_HEIGHT 800
/* ===============================================================
*
* 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 defines */
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
*
* DEMO
*
* ===============================================================*/
int
main(int argc, char *argv[])
{
/* Platform */
SDL_Window *win;
SDL_Renderer *renderer;
int running = 1;
int flags = 0;
float font_scale = 1;
/* GUI */
struct nk_context *ctx;
struct nk_colorf bg;
/* SDL setup */
SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0");
SDL_Init(SDL_INIT_VIDEO);
win = SDL_CreateWindow("Demo",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI);
if (win == NULL) {
SDL_Log("Error SDL_CreateWindow %s", SDL_GetError());
exit(-1);
}
flags |= SDL_RENDERER_ACCELERATED;
flags |= SDL_RENDERER_PRESENTVSYNC;
#if 0
SDL_SetHint(SDL_HINT_RENDER_BATCHING, "1");
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles2");
#endif
renderer = SDL_CreateRenderer(win, -1, flags);
if (renderer == NULL) {
SDL_Log("Error SDL_CreateRenderer %s", SDL_GetError());
exit(-1);
}
/* scale the renderer output for High-DPI displays */
{
int render_w, render_h;
int window_w, window_h;
float scale_x, scale_y;
SDL_GetRendererOutputSize(renderer, &render_w, &render_h);
SDL_GetWindowSize(win, &window_w, &window_h);
scale_x = (float)(render_w) / (float)(window_w);
scale_y = (float)(render_h) / (float)(window_h);
SDL_RenderSetScale(renderer, scale_x, scale_y);
font_scale = scale_y;
}
/* GUI */
ctx = nk_sdl_init(win, renderer);
/* 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;
struct nk_font_config config = nk_font_config(0);
struct nk_font *font;
/* set up the font atlas and add desired font; note that font sizes are
* multiplied by font_scale to produce better results at higher DPIs */
nk_sdl_font_stash_begin(&atlas);
font = nk_font_atlas_add_default(atlas, 13 * font_scale, &config);
/*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14 * font_scale, &config);*/
/*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 16 * font_scale, &config);*/
/*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13 * font_scale, &config);*/
/*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12 * font_scale, &config);*/
/*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10 * font_scale, &config);*/
/*font = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13 * font_scale, &config);*/
nk_sdl_font_stash_end();
/* this hack makes the font appear to be scaled down to the desired
* size and is only necessary when font_scale > 1 */
font->handle.height /= font_scale;
/*nk_style_load_all_cursors(ctx, atlas->cursors);*/
nk_style_set_font(ctx, &font->handle);
}
#ifdef INCLUDE_STYLE
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
while (running)
{
/* Input */
SDL_Event evt;
nk_input_begin(ctx);
while (SDL_PollEvent(&evt)) {
if (evt.type == SDL_QUIT) goto cleanup;
nk_sdl_handle_event(&evt);
}
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, 25, 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, nk_rgb_cf(bg), nk_vec2(nk_widget_width(ctx),400))) {
nk_layout_row_dynamic(ctx, 120, 1);
bg = nk_color_picker(ctx, bg, NK_RGBA);
nk_layout_row_dynamic(ctx, 25, 1);
bg.r = nk_propertyf(ctx, "#R:", 0, bg.r, 1.0f, 0.01f,0.005f);
bg.g = nk_propertyf(ctx, "#G:", 0, bg.g, 1.0f, 0.01f,0.005f);
bg.b = nk_propertyf(ctx, "#B:", 0, bg.b, 1.0f, 0.01f,0.005f);
bg.a = nk_propertyf(ctx, "#A:", 0, bg.a, 1.0f, 0.01f,0.005f);
nk_combo_end(ctx);
}
}
nk_end(ctx);
/* -------------- EXAMPLES ---------------- */
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif
#ifdef INCLUDE_NODE_EDITOR
node_editor(ctx);
#endif
/* ----------------------------------------- */
SDL_SetRenderDrawColor(renderer, bg.r * 255, bg.g * 255, bg.b * 255, bg.a * 255);
SDL_RenderClear(renderer);
nk_sdl_render(NK_ANTI_ALIASING_ON);
SDL_RenderPresent(renderer);
}
cleanup:
nk_sdl_shutdown();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(win);
SDL_Quit();
return 0;
}

View File

@ -0,0 +1,379 @@
/*
* Nuklear - 4.9.4 - public domain
*/
/*
* ==============================================================
*
* API
*
* ===============================================================
*/
#ifndef NK_SDL_RENDERER_H_
#define NK_SDL_RENDERER_H_
#include <SDL2/SDL.h>
NK_API struct nk_context* nk_sdl_init(SDL_Window *win, SDL_Renderer *renderer);
NK_API void nk_sdl_font_stash_begin(struct nk_font_atlas **atlas);
NK_API void nk_sdl_font_stash_end(void);
NK_API int nk_sdl_handle_event(SDL_Event *evt);
NK_API void nk_sdl_render(enum nk_anti_aliasing);
NK_API void nk_sdl_shutdown(void);
#if SDL_COMPILEDVERSION < SDL_VERSIONNUM(2, 0, 22)
/* Metal API does not support cliprects with negative coordinates or large
* dimensions. The issue is fixed in SDL2 with version 2.0.22 but until
* that version is released, the NK_SDL_CLAMP_CLIP_RECT flag can be used to
* ensure the cliprect is itself clipped to the viewport.
* See discussion at https://discourse.libsdl.org/t/rendergeometryraw-producing-different-results-in-metal-vs-opengl/34953
*/
#define NK_SDL_CLAMP_CLIP_RECT
#endif
#endif /* NK_SDL_RENDERER_H_ */
/*
* ==============================================================
*
* IMPLEMENTATION
*
* ===============================================================
*/
#ifdef NK_SDL_RENDERER_IMPLEMENTATION
#include <strings.h>
struct nk_sdl_device {
struct nk_buffer cmds;
struct nk_draw_null_texture tex_null;
SDL_Texture *font_tex;
};
struct nk_sdl_vertex {
float position[2];
float uv[2];
nk_byte col[4];
};
static struct nk_sdl {
SDL_Window *win;
SDL_Renderer *renderer;
struct nk_sdl_device ogl;
struct nk_context ctx;
struct nk_font_atlas atlas;
} sdl;
NK_INTERN void
nk_sdl_device_upload_atlas(const void *image, int width, int height)
{
struct nk_sdl_device *dev = &sdl.ogl;
SDL_Texture *g_SDLFontTexture = SDL_CreateTexture(sdl.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, width, height);
if (g_SDLFontTexture == NULL) {
SDL_Log("error creating texture");
return;
}
SDL_UpdateTexture(g_SDLFontTexture, NULL, image, 4 * width);
SDL_SetTextureBlendMode(g_SDLFontTexture, SDL_BLENDMODE_BLEND);
dev->font_tex = g_SDLFontTexture;
}
NK_API void
nk_sdl_render(enum nk_anti_aliasing AA)
{
/* setup global state */
struct nk_sdl_device *dev = &sdl.ogl;
{
SDL_Rect saved_clip;
#ifdef NK_SDL_CLAMP_CLIP_RECT
SDL_Rect viewport;
#endif
SDL_bool clipping_enabled;
int vs = sizeof(struct nk_sdl_vertex);
size_t vp = offsetof(struct nk_sdl_vertex, position);
size_t vt = offsetof(struct nk_sdl_vertex, uv);
size_t vc = offsetof(struct nk_sdl_vertex, col);
/* convert from command queue into draw list and draw to screen */
const struct nk_draw_command *cmd;
const nk_draw_index *offset = NULL;
struct nk_buffer vbuf, ebuf;
/* fill converting configuration */
struct nk_convert_config config;
static const struct nk_draw_vertex_layout_element vertex_layout[] = {
{NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, position)},
{NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, uv)},
{NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_sdl_vertex, col)},
{NK_VERTEX_LAYOUT_END}
};
NK_MEMSET(&config, 0, sizeof(config));
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_sdl_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_sdl_vertex);
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
config.global_alpha = 1.0f;
config.shape_AA = AA;
config.line_AA = AA;
/* convert shapes into vertexes */
nk_buffer_init_default(&vbuf);
nk_buffer_init_default(&ebuf);
nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config);
/* iterate over and execute each draw command */
offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
clipping_enabled = SDL_RenderIsClipEnabled(sdl.renderer);
SDL_RenderGetClipRect(sdl.renderer, &saved_clip);
#ifdef NK_SDL_CLAMP_CLIP_RECT
SDL_RenderGetViewport(sdl.renderer, &viewport);
#endif
nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds)
{
if (!cmd->elem_count) continue;
{
SDL_Rect r;
r.x = cmd->clip_rect.x;
r.y = cmd->clip_rect.y;
r.w = cmd->clip_rect.w;
r.h = cmd->clip_rect.h;
#ifdef NK_SDL_CLAMP_CLIP_RECT
if (r.x < 0) {
r.w += r.x;
r.x = 0;
}
if (r.y < 0) {
r.h += r.y;
r.y = 0;
}
if (r.h > viewport.h) {
r.h = viewport.h;
}
if (r.w > viewport.w) {
r.w = viewport.w;
}
#endif
SDL_RenderSetClipRect(sdl.renderer, &r);
}
{
const void *vertices = nk_buffer_memory_const(&vbuf);
SDL_RenderGeometryRaw(sdl.renderer,
(SDL_Texture *)cmd->texture.ptr,
(const float*)((const nk_byte*)vertices + vp), vs,
(const SDL_Color*)((const nk_byte*)vertices + vc), vs,
(const float*)((const nk_byte*)vertices + vt), vs,
(vbuf.needed / vs),
(void *) offset, cmd->elem_count, 2);
offset += cmd->elem_count;
}
}
SDL_RenderSetClipRect(sdl.renderer, &saved_clip);
if (!clipping_enabled) {
SDL_RenderSetClipRect(sdl.renderer, NULL);
}
nk_clear(&sdl.ctx);
nk_buffer_clear(&dev->cmds);
nk_buffer_free(&vbuf);
nk_buffer_free(&ebuf);
}
}
static void
nk_sdl_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
{
const char *text = SDL_GetClipboardText();
if (text) nk_textedit_paste(edit, text, nk_strlen(text));
(void)usr;
}
static void
nk_sdl_clipboard_copy(nk_handle usr, const char *text, int len)
{
char *str = 0;
(void)usr;
if (!len) return;
str = (char*)malloc((size_t)len+1);
if (!str) return;
memcpy(str, text, (size_t)len);
str[len] = '\0';
SDL_SetClipboardText(str);
free(str);
}
NK_API struct nk_context*
nk_sdl_init(SDL_Window *win, SDL_Renderer *renderer)
{
#ifndef NK_SDL_CLAMP_CLIP_RECT
SDL_RendererInfo info;
SDL_version runtimeVer;
/* warn for cases where NK_SDL_CLAMP_CLIP_RECT should have been set but isn't */
SDL_GetRendererInfo(renderer, &info);
SDL_GetVersion(&runtimeVer);
if (strncmp("metal", info.name, 5) == 0 &&
SDL_VERSIONNUM(runtimeVer.major, runtimeVer.minor, runtimeVer.patch) < SDL_VERSIONNUM(2, 0, 22))
{
SDL_LogWarn(
SDL_LOG_CATEGORY_APPLICATION,
"renderer is using Metal API but runtime SDL version %d.%d.%d is older than compiled version %d.%d.%d, "
"which may cause issues with rendering",
runtimeVer.major, runtimeVer.minor, runtimeVer.patch,
SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL
);
}
#endif
sdl.win = win;
sdl.renderer = renderer;
nk_init_default(&sdl.ctx, 0);
sdl.ctx.clip.copy = nk_sdl_clipboard_copy;
sdl.ctx.clip.paste = nk_sdl_clipboard_paste;
sdl.ctx.clip.userdata = nk_handle_ptr(0);
nk_buffer_init_default(&sdl.ogl.cmds);
return &sdl.ctx;
}
NK_API void
nk_sdl_font_stash_begin(struct nk_font_atlas **atlas)
{
nk_font_atlas_init_default(&sdl.atlas);
nk_font_atlas_begin(&sdl.atlas);
*atlas = &sdl.atlas;
}
NK_API void
nk_sdl_font_stash_end(void)
{
const void *image; int w, h;
image = nk_font_atlas_bake(&sdl.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_sdl_device_upload_atlas(image, w, h);
nk_font_atlas_end(&sdl.atlas, nk_handle_ptr(sdl.ogl.font_tex), &sdl.ogl.tex_null);
if (sdl.atlas.default_font)
nk_style_set_font(&sdl.ctx, &sdl.atlas.default_font->handle);
}
NK_API int
nk_sdl_handle_event(SDL_Event *evt)
{
struct nk_context *ctx = &sdl.ctx;
/* optional grabbing behavior */
if (ctx->input.mouse.grab) {
SDL_SetRelativeMouseMode(SDL_TRUE);
ctx->input.mouse.grab = 0;
} else if (ctx->input.mouse.ungrab) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_WarpMouseInWindow(sdl.win, x, y);
ctx->input.mouse.ungrab = 0;
}
switch(evt->type)
{
case SDL_KEYUP: /* KEYUP & KEYDOWN share same routine */
case SDL_KEYDOWN:
{
int down = evt->type == SDL_KEYDOWN;
const Uint8* state = SDL_GetKeyboardState(0);
switch(evt->key.keysym.sym)
{
case SDLK_RSHIFT: /* RSHIFT & LSHIFT share same routine */
case SDLK_LSHIFT: nk_input_key(ctx, NK_KEY_SHIFT, down); break;
case SDLK_DELETE: nk_input_key(ctx, NK_KEY_DEL, down); break;
case SDLK_RETURN: nk_input_key(ctx, NK_KEY_ENTER, down); break;
case SDLK_TAB: nk_input_key(ctx, NK_KEY_TAB, down); break;
case SDLK_BACKSPACE: nk_input_key(ctx, NK_KEY_BACKSPACE, down); break;
case SDLK_HOME: nk_input_key(ctx, NK_KEY_TEXT_START, down);
nk_input_key(ctx, NK_KEY_SCROLL_START, down); break;
case SDLK_END: nk_input_key(ctx, NK_KEY_TEXT_END, down);
nk_input_key(ctx, NK_KEY_SCROLL_END, down); break;
case SDLK_PAGEDOWN: nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); break;
case SDLK_PAGEUP: nk_input_key(ctx, NK_KEY_SCROLL_UP, down); break;
case SDLK_z: nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_r: nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_c: nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_v: nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_x: nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_b: nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_e: nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]); break;
case SDLK_UP: nk_input_key(ctx, NK_KEY_UP, down); break;
case SDLK_DOWN: nk_input_key(ctx, NK_KEY_DOWN, down); break;
case SDLK_LEFT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
else nk_input_key(ctx, NK_KEY_LEFT, down);
break;
case SDLK_RIGHT:
if (state[SDL_SCANCODE_LCTRL])
nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
else nk_input_key(ctx, NK_KEY_RIGHT, down);
break;
}
}
return 1;
case SDL_MOUSEBUTTONUP: /* MOUSEBUTTONUP & MOUSEBUTTONDOWN share same routine */
case SDL_MOUSEBUTTONDOWN:
{
int down = evt->type == SDL_MOUSEBUTTONDOWN;
const int x = evt->button.x, y = evt->button.y;
switch(evt->button.button)
{
case SDL_BUTTON_LEFT:
if (evt->button.clicks > 1)
nk_input_button(ctx, NK_BUTTON_DOUBLE, x, y, down);
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); break;
case SDL_BUTTON_MIDDLE: nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); break;
case SDL_BUTTON_RIGHT: nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); break;
}
}
return 1;
case SDL_MOUSEMOTION:
if (ctx->input.mouse.grabbed) {
int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y;
nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel);
}
else nk_input_motion(ctx, evt->motion.x, evt->motion.y);
return 1;
case SDL_TEXTINPUT:
{
nk_glyph glyph;
memcpy(glyph, evt->text.text, NK_UTF_SIZE);
nk_input_glyph(ctx, glyph);
}
return 1;
case SDL_MOUSEWHEEL:
nk_input_scroll(ctx,nk_vec2((float)evt->wheel.x,(float)evt->wheel.y));
return 1;
}
return 0;
}
NK_API
void nk_sdl_shutdown(void)
{
struct nk_sdl_device *dev = &sdl.ogl;
nk_font_atlas_clear(&sdl.atlas);
nk_free(&sdl.ctx);
SDL_DestroyTexture(dev->font_tex);
/* glDeleteTextures(1, &dev->font_tex); */
nk_buffer_free(&dev->cmds);
memset(&sdl, 0, sizeof(sdl));
}
#endif /* NK_SDL_RENDERER_IMPLEMENTATION */

View File

@ -3,7 +3,7 @@ CC = g++
BIN = demo
# Flags
CFLAGS += -s -O2
CFLAGS += -s -Wall -Wextra -pedantic -O2
SRC = main.cpp
OBJ = $(SRC:.cpp=.o)

View File

@ -37,27 +37,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -93,10 +98,16 @@ int main(void)
/* style.c */
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
struct nk_colorf bg;
@ -154,6 +165,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -34,7 +34,7 @@ NK_API void nk_sfml_shutdown(void);
struct nk_sfml_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
GLuint font_tex;
};
@ -118,7 +118,7 @@ nk_sfml_render(enum nk_anti_aliasing AA)
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_sfml_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_sfml_vertex);
config.null = dev->null;
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
@ -189,6 +189,9 @@ nk_sfml_clipboard_paste(nk_handle usr, struct nk_text_edit* edit)
if(text)
nk_textedit_paste(edit, text, nk_strlen(text));
(void)usr;
#else
NK_UNUSED(usr);
NK_UNUSED(edit);
#endif
}
@ -208,6 +211,10 @@ nk_sfml_clipboard_copy(nk_handle usr, const char* text, int len)
sf::Clipboard clipboard(sfml.window);
clipboard.setText(str);
free(str);
#else
NK_UNUSED(usr);
NK_UNUSED(text);
NK_UNUSED(len);
#endif
}
@ -238,7 +245,7 @@ nk_sfml_font_stash_end()
const void* img;
img = nk_font_atlas_bake(&sfml.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_sfml_device_upload_atlas(img, w, h);
nk_font_atlas_end(&sfml.atlas, nk_handle_id((int)sfml.ogl.font_tex), &sfml.ogl.null);
nk_font_atlas_end(&sfml.atlas, nk_handle_id((int)sfml.ogl.font_tex), &sfml.ogl.tex_null);
if(sfml.atlas.default_font)
nk_style_set_font(&sfml.ctx, &sfml.atlas.default_font->handle);
}

View File

@ -3,7 +3,7 @@ CC = g++
BIN = demo
# Flags
CFLAGS += -s -O2
CFLAGS += -s -Wall -Wextra -pedantic -O2
SRC = main.cpp
OBJ = $(SRC:.cpp=.o)

View File

@ -39,27 +39,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -99,10 +104,16 @@ int main(void)
/* style.c */
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
struct nk_colorf bg;
@ -161,6 +172,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -43,7 +43,7 @@ NK_API void nk_sfml_device_destroy(void);
struct nk_sfml_device {
struct nk_buffer cmds;
struct nk_draw_null_texture null;
struct nk_draw_null_texture tex_null;
GLuint vbo, vao, ebo;
GLuint prog;
GLuint vert_shdr;
@ -248,7 +248,7 @@ nk_sfml_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_
config.vertex_layout = vertex_layout;
config.vertex_size = sizeof(struct nk_sfml_vertex);
config.vertex_alignment = NK_ALIGNOF(struct nk_sfml_vertex);
config.null = dev->null;
config.tex_null = dev->tex_null;
config.circle_segment_count = 22;
config.curve_segment_count = 22;
config.arc_segment_count = 22;
@ -298,6 +298,9 @@ nk_sfml_clipboard_paste(nk_handle usr, struct nk_text_edit* edit)
sf::Clipboard clipboard(sfml.window);
const char* text = clipboard.getText();
if(text) nk_textedit_paste(edit, text, nk_strlen(text));
#else
NK_UNUSED(usr);
NK_UNUSED(edit);
#endif
}
static void
@ -316,6 +319,10 @@ nk_sfml_clipboard_copy(nk_handle usr, const char* text, int len)
sf::Clipboard clipboard(sfml.window);
clipboard.setText(str);
free(str);
#else
NK_UNUSED(usr);
NK_UNUSED(text);
NK_UNUSED(len);
#endif
}
@ -346,7 +353,7 @@ nk_sfml_font_stash_end()
int w, h;
image = nk_font_atlas_bake(&sfml.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
nk_sfml_device_upload_atlas(image, w, h);
nk_font_atlas_end(&sfml.atlas, nk_handle_id((int)sfml.ogl.font_tex), &sfml.ogl.null);
nk_font_atlas_end(&sfml.atlas, nk_handle_id((int)sfml.ogl.font_tex), &sfml.ogl.tex_null);
if(sfml.atlas.default_font)
nk_style_set_font(&sfml.ctx, &sfml.atlas.default_font->handle);
}

View File

@ -2,12 +2,12 @@ WAYLAND=`pkg-config wayland-client --cflags --libs`
WAYLAND_SCANNER=wayland-scanner
WAYLAND_PROTOCOLS_DIR=/usr/share/wayland-protocols
CFLAGS?=-std=c11 -Wall -Werror -O3 -fvisibility=hidden
CFLAGS?=-std=c99 -Wall -Wextra -pedantic -Wno-unused-function -O3 -fvisibility=hidden
.PHONY: clean
demo: main.c xdg-shell.c xdg-shell.h
$(CC) -o demo *.c $(WAYLAND) -lrt -lm
$(CC) $(CFLAGS) -o demo *.c $(WAYLAND) -lrt -lm
xdg-shell.c:
$(WAYLAND_SCANNER) code $(WAYLAND_PROTOCOLS_DIR)/stable/xdg-shell/xdg-shell.xml xdg-shell.c

View File

@ -28,25 +28,79 @@
#define DTIME 20
/* ===============================================================
*
* 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 defines */
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../../demo/common/node_editor.c"
#endif
//WAYLAND OUTPUT INTERFACE
static void nk_wayland_output_cb_geometry(void *data, struct wl_output *wl_output, int x, int y, int w, int h, int subpixel, const char *make, const char *model, int transform)
{
NK_UNUSED(data);
NK_UNUSED(wl_output);
NK_UNUSED(subpixel);
NK_UNUSED(make);
NK_UNUSED(model);
NK_UNUSED(transform);
printf("wl_output geometry x=%d, y=%d, w=%d, h=%d make=%s, model=%s \n", x,y,w,h, make, model);
}
static void nk_wayland_output_cb_mode(void *data, struct wl_output *wl_output, unsigned int flags, int w, int h, int refresh)
{
NK_UNUSED(data);
NK_UNUSED(wl_output);
NK_UNUSED(flags);
NK_UNUSED(w);
NK_UNUSED(h);
NK_UNUSED(refresh);
}
static void nk_wayland_output_cb_done(void *data, struct wl_output *output)
{
NK_UNUSED(data);
NK_UNUSED(output);
}
static void nk_wayland_output_cb_scale(void *data, struct wl_output *output, int scale)
{
NK_UNUSED(data);
NK_UNUSED(output);
NK_UNUSED(scale);
}
static const struct wl_output_listener nk_wayland_output_listener =
@ -61,15 +115,29 @@ static const struct wl_output_listener nk_wayland_output_listener =
//WAYLAND POINTER INTERFACE (mouse/touchpad)
static void nk_wayland_pointer_enter (void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
NK_UNUSED(data);
NK_UNUSED(pointer);
NK_UNUSED(serial);
NK_UNUSED(surface);
NK_UNUSED(surface_x);
NK_UNUSED(surface_y);
}
static void nk_wayland_pointer_leave (void *data, struct wl_pointer *pointer, uint32_t serial, struct wl_surface *surface)
{
NK_UNUSED(data);
NK_UNUSED(pointer);
NK_UNUSED(serial);
NK_UNUSED(surface);
}
static void nk_wayland_pointer_motion (void *data, struct wl_pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y)
{
struct nk_wayland* win = (struct nk_wayland*)data;
NK_UNUSED(pointer);
NK_UNUSED(time);
win->mouse_pointer_x = wl_fixed_to_int(x);
win->mouse_pointer_y = wl_fixed_to_int(y);
@ -80,6 +148,10 @@ static void nk_wayland_pointer_button (void *data, struct wl_pointer *pointer, u
{
struct nk_wayland* win = (struct nk_wayland*)data;
NK_UNUSED(pointer);
NK_UNUSED(serial);
NK_UNUSED(time);
if (button == 272){ //left mouse button
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
// printf("nk_input_button x=%d, y=%d press: 1 \n", win->mouse_pointer_x, win->mouse_pointer_y);
@ -93,6 +165,11 @@ static void nk_wayland_pointer_button (void *data, struct wl_pointer *pointer, u
static void nk_wayland_pointer_axis (void *data, struct wl_pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
{
NK_UNUSED(data);
NK_UNUSED(pointer);
NK_UNUSED(time);
NK_UNUSED(axis);
NK_UNUSED(value);
}
static struct wl_pointer_listener nk_wayland_pointer_listener =
@ -101,30 +178,60 @@ static struct wl_pointer_listener nk_wayland_pointer_listener =
&nk_wayland_pointer_leave,
&nk_wayland_pointer_motion,
&nk_wayland_pointer_button,
&nk_wayland_pointer_axis
&nk_wayland_pointer_axis,
NULL,
NULL,
NULL,
NULL
};
//-------------------------------------------------------------------- endof WAYLAND POINTER INTERFACE
//WAYLAND KEYBOARD INTERFACE
static void nk_wayland_keyboard_keymap (void *data, struct wl_keyboard *keyboard, uint32_t format, int32_t fd, uint32_t size)
{
NK_UNUSED(data);
NK_UNUSED(keyboard);
NK_UNUSED(format);
NK_UNUSED(fd);
NK_UNUSED(size);
}
static void nk_wayland_keyboard_enter (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
{
NK_UNUSED(data);
NK_UNUSED(keyboard);
NK_UNUSED(serial);
NK_UNUSED(surface);
NK_UNUSED(keys);
}
static void nk_wayland_keyboard_leave (void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface)
{
NK_UNUSED(data);
NK_UNUSED(keyboard);
NK_UNUSED(serial);
NK_UNUSED(surface);
}
static void nk_wayland_keyboard_key (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
{
NK_UNUSED(data);
NK_UNUSED(keyboard);
NK_UNUSED(serial);
NK_UNUSED(time);
NK_UNUSED(state);
printf("key: %d \n", key);
}
static void nk_wayland_keyboard_modifiers (void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
{
NK_UNUSED(data);
NK_UNUSED(keyboard);
NK_UNUSED(serial);
NK_UNUSED(mods_depressed);
NK_UNUSED(mods_latched);
NK_UNUSED(mods_locked);
NK_UNUSED(group);
}
static struct wl_keyboard_listener nk_wayland_keyboard_listener =
@ -133,7 +240,8 @@ static struct wl_keyboard_listener nk_wayland_keyboard_listener =
&nk_wayland_keyboard_enter,
&nk_wayland_keyboard_leave,
&nk_wayland_keyboard_key,
&nk_wayland_keyboard_modifiers
&nk_wayland_keyboard_modifiers,
NULL
};
//-------------------------------------------------------------------- endof WAYLAND KEYBOARD INTERFACE
@ -154,13 +262,15 @@ static void seat_capabilities (void *data, struct wl_seat *seat, uint32_t capabi
static struct wl_seat_listener seat_listener =
{
&seat_capabilities
&seat_capabilities,
NULL
};
//-------------------------------------------------------------------- endof WAYLAND SEAT INTERFACE
// WAYLAND SHELL INTERFACE
static void nk_wayland_xdg_wm_base_ping (void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
{
NK_UNUSED(data);
xdg_wm_base_pong (xdg_wm_base, serial);
}
@ -171,6 +281,7 @@ static struct xdg_wm_base_listener nk_wayland_xdg_wm_base_listener =
static void nk_wayland_xdg_surface_configure (void *data, struct xdg_surface *xdg_surface, uint32_t serial)
{
NK_UNUSED(data);
xdg_surface_ack_configure(xdg_surface, serial);
}
@ -181,10 +292,17 @@ static struct xdg_surface_listener nk_wayland_xdg_surface_listener =
static void nk_wayland_xdg_toplevel_configure (void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states)
{
NK_UNUSED(data);
NK_UNUSED(xdg_toplevel);
NK_UNUSED(width);
NK_UNUSED(height);
NK_UNUSED(states);
}
static void nk_wayland_xdg_toplevel_close (void *data, struct xdg_toplevel *xdg_toplevel)
{
NK_UNUSED(data);
NK_UNUSED(xdg_toplevel);
}
static struct xdg_toplevel_listener nk_wayland_xdg_toplevel_listener =
@ -200,6 +318,8 @@ static void nk_wayland_registry_add_object (void *data, struct wl_registry *regi
{
struct nk_wayland* win = (struct nk_wayland*)data;
NK_UNUSED(version);
//printf("looking for %s interface \n", interface);
if (!strcmp(interface,"wl_compositor")) {
win->compositor = wl_registry_bind (registry, name, &wl_compositor_interface, 1);
@ -222,6 +342,9 @@ static void nk_wayland_registry_add_object (void *data, struct wl_registry *regi
static void nk_wayland_registry_remove_object (void *data, struct wl_registry *registry, uint32_t name)
{
NK_UNUSED(data);
NK_UNUSED(registry);
NK_UNUSED(name);
}
static struct wl_registry_listener nk_wayland_registry_listener =
@ -314,8 +437,10 @@ static void redraw(void *data, struct wl_callback *callback, uint32_t time)
{
// printf("redrawing.. 1\n");
struct nk_wayland* win = (struct nk_wayland*)data;
struct nk_color col_red = {0xFF,0x00,0x00,0xA0}; //r,g,b,a
struct nk_color col_green = {0x00,0xFF,0x00,0xA0}; //r,g,b,a
NK_UNUSED(callback);
NK_UNUSED(time);
wl_callback_destroy(win->frame_callback);
wl_surface_damage(win->surface, 0, 0, WIDTH, HEIGHT);
@ -338,7 +463,6 @@ int main ()
long dt;
long started;
struct nk_wayland nk_wayland_ctx;
struct wl_backend *backend;
struct wl_registry *registry;
int running = 1;
@ -418,17 +542,20 @@ int main ()
if (nk_window_is_closed(&(nk_wayland_ctx.ctx), "Demo")) break;
// -------------- EXAMPLES ----------------
//#ifdef INCLUDE_CALCULATOR
// calculator(&rawfb->ctx);
//#endif
// #ifdef INCLUDE_OVERVIEW
// overview(&rawfb->ctx);
// #endif
// #ifdef INCLUDE_NODE_EDITOR
// node_editor(&rawfb->ctx);
//#endif
// -----------------------------------------
/* -------------- EXAMPLES ---------------- */
#ifdef INCLUDE_CALCULATOR
calculator(&(nk_wayland_ctx.ctx));
#endif
#ifdef INCLUDE_CANVAS
canvas(&(nk_wayland_ctx.ctx));
#endif
#ifdef INCLUDE_OVERVIEW
overview(&(nk_wayland_ctx.ctx));
#endif
#ifdef INCLUDE_NODE_EDITOR
node_editor(&(nk_wayland_ctx.ctx));
#endif
/* ----------------------------------------- */
// Draw framebuffer
nk_wayland_render(&nk_wayland_ctx, nk_rgb(30,30,30), 1);

View File

@ -110,7 +110,7 @@ static void nk_wayland_ctx_setpixel(const struct nk_wayland* win,
const short x0, const short y0, const struct nk_color col)
{
uint32_t c = nk_color_to_xrgb8888(col);
uint32_t *pixels = win->data;
uint32_t *pixels = (uint32_t *)win->data;
unsigned int *ptr;
pixels += (y0 * win->width);
@ -252,7 +252,7 @@ static void nk_wayland_img_setpixel(const struct wayland_img *img, const int x0,
unsigned int *pixel;
NK_ASSERT(img);
if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) {
ptr = img->pixels + (img->pitch * y0);
ptr = (unsigned char *)img->pixels + (img->pitch * y0);
pixel = (unsigned int *)ptr;
if (img->format == NK_FONT_ATLAS_ALPHA8) {
@ -267,10 +267,9 @@ static struct nk_color nk_wayland_getpixel(const struct nk_wayland* win, const i
{
struct nk_color col = {0, 0, 0, 0};
uint32_t *ptr;
unsigned int pixel;
if (y0 < win->height && y0 >= 0 && x0 >= 0 && x0 < win->width) {
ptr = win->data + (y0 * win->width);
ptr = (uint32_t *)win->data + (y0 * win->width);
col = nk_wayland_int2color(*ptr, PIXEL_LAYOUT_XRGB_8888);
}
@ -285,7 +284,7 @@ static struct nk_color nk_wayland_img_getpixel(const struct wayland_img *img, co
unsigned int pixel;
NK_ASSERT(img);
if (y0 < img->h && y0 >= 0 && x0 >= 0 && x0 < img->w) {
ptr = img->pixels + (img->pitch * y0);
ptr = (unsigned char *)img->pixels + (img->pitch * y0);
if (img->format == NK_FONT_ATLAS_ALPHA8) {
col.a = ptr[x0];
@ -365,6 +364,8 @@ static void nk_wayland_stroke_line(const struct nk_wayland* win, short x0, short
short tmp;
int dy, dx, stepx, stepy;
NK_UNUSED(line_thickness);
dy = y1 - y0;
dx = x1 - x0;
@ -494,6 +495,8 @@ static void nk_wayland_stroke_arc(const struct nk_wayland* win,
const int fa2 = 4 * a2, fb2 = 4 * b2;
int x, y, sigma;
NK_UNUSED(line_thickness);
if (s != 0 && s != 90 && s != 180 && s != 270) return;
if (w < 1 || h < 1) return;

View File

@ -2,7 +2,7 @@
BIN = zahnrad
# Flags
CFLAGS += -std=c89 -pedantic -O2
CFLAGS += -std=c89 -Wall -Wextra -pedantic -Wno-unused-function -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -79,27 +79,32 @@ sleep_for(long t)
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -148,10 +153,16 @@ main(void)
ctx = nk_xlib_init(xw.font, xw.dpy, xw.screen, xw.win, xw.width, xw.height);
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
while (running)
@ -193,6 +204,9 @@ main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

View File

@ -357,6 +357,29 @@ nk_xsurf_stroke_circle(XSurface *surf, short x, short y, unsigned short w,
XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter);
}
NK_INTERN void
nk_xsurf_stroke_arc(XSurface *surf, short cx, short cy, unsigned short radius,
float a_min, float a_max, unsigned short line_thickness, struct nk_color col)
{
unsigned long c = nk_color_from_byte(&col.r);
XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter);
XSetForeground(surf->dpy, surf->gc, c);
XDrawArc(surf->dpy, surf->drawable, surf->gc, (int)(cx - radius), (int)(cy - radius),
(unsigned)(radius * 2), (unsigned)(radius * 2),
(int)(a_min * 180 * 64 / NK_PI), (int)(a_max * 180 * 64 / NK_PI));
}
NK_INTERN void
nk_xsurf_fill_arc(XSurface *surf, short cx, short cy, unsigned short radius,
float a_min, float a_max, struct nk_color col)
{
unsigned long c = nk_color_from_byte(&col.r);
XSetForeground(surf->dpy, surf->gc, c);
XFillArc(surf->dpy, surf->drawable, surf->gc, (int)(cx - radius), (int)(cy - radius),
(unsigned)(radius * 2), (unsigned)(radius * 2),
(int)(a_min * 180 * 64 / NK_PI), (int)(a_max * 180 * 64 / NK_PI));
}
NK_INTERN void
nk_xsurf_stroke_curve(XSurface *surf, struct nk_vec2i p1,
struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4,
@ -385,15 +408,12 @@ nk_xsurf_stroke_curve(XSurface *surf, struct nk_vec2i p1,
}
NK_INTERN void
nk_xsurf_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned short h,
const char *text, int len, XFont *font, struct nk_color cbg, struct nk_color cfg)
nk_xsurf_draw_text(XSurface *surf, short x, short y, const char *text, int len,
XFont *font, struct nk_color cfg)
{
int tx, ty;
unsigned long bg = nk_color_from_byte(&cbg.r);
unsigned long fg = nk_color_from_byte(&cfg.r);
XSetForeground(surf->dpy, surf->gc, bg);
XFillRectangle(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, (unsigned)w, (unsigned)h);
if(!text || !font || !len) return;
tx = (int)x;
@ -497,6 +517,9 @@ nk_xsurf_draw_image(XSurface *surf, short x, short y, unsigned short w, unsigned
struct nk_image img, struct nk_color col)
{
XImageWithAlpha *aimage = img.handle.ptr;
NK_UNUSED(col);
if (aimage){
if (aimage->clipMask){
XSetClipMask(surf->dpy, surf->gc, aimage->clipMask);
@ -581,6 +604,9 @@ nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int le
{
XFont *font = (XFont*)handle.ptr;
XRectangle r;
NK_UNUSED(height);
if(!font || !text)
return 0;
@ -687,6 +713,8 @@ nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt)
{
struct nk_context *ctx = &xlib.ctx;
NK_UNUSED(screen);
/* optional grabbing behavior */
if (ctx->input.mouse.grab) {
XDefineCursor(xlib.dpy, xlib.root, xlib.cursor);
@ -907,6 +935,14 @@ nk_xlib_render(Drawable screen, struct nk_color clear)
const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
nk_xsurf_fill_circle(surf, c->x, c->y, c->w, c->h, c->color);
} break;
case NK_COMMAND_ARC: {
const struct nk_command_arc *a = (const struct nk_command_arc *)cmd;
nk_xsurf_stroke_arc(surf, a->cx, a->cy, a->r, a->a[0], a->a[1], a->line_thickness, a->color);
} break;
case NK_COMMAND_ARC_FILLED: {
const struct nk_command_arc_filled *a = (const struct nk_command_arc_filled *)cmd;
nk_xsurf_fill_arc(surf, a->cx, a->cy, a->r, a->a[0], a->a[1], a->color);
} break;
case NK_COMMAND_TRIANGLE: {
const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
nk_xsurf_stroke_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y,
@ -931,10 +967,8 @@ nk_xlib_render(Drawable screen, struct nk_color clear)
} break;
case NK_COMMAND_TEXT: {
const struct nk_command_text *t = (const struct nk_command_text*)cmd;
nk_xsurf_draw_text(surf, t->x, t->y, t->w, t->h,
(const char*)t->string, t->length,
(XFont*)t->font->userdata.ptr,
t->background, t->foreground);
nk_xsurf_draw_text(surf, t->x, t->y, (const char*)t->string, t->length,
(XFont*)t->font->userdata.ptr, t->foreground);
} break;
case NK_COMMAND_CURVE: {
const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
@ -946,8 +980,6 @@ nk_xlib_render(Drawable screen, struct nk_color clear)
nk_xsurf_draw_image(surf, i->x, i->y, i->w, i->h, i->img, i->col);
} break;
case NK_COMMAND_RECT_MULTI_COLOR:
case NK_COMMAND_ARC:
case NK_COMMAND_ARC_FILLED:
case NK_COMMAND_CUSTOM:
default: break;
}

View File

@ -6,7 +6,7 @@ CC = clang
DCC = gcc
# Flags
CFLAGS += -std=c99 -pedantic -O2
CFLAGS += -std=c89 -Wall -Wextra -pedantic -O2
SRC = main.c
OBJ = $(SRC:.c=.o)

View File

@ -40,27 +40,32 @@
/*#define INCLUDE_ALL */
/*#define INCLUDE_STYLE */
/*#define INCLUDE_CALCULATOR */
/*#define INCLUDE_CANVAS */
/*#define INCLUDE_OVERVIEW */
/*#define INCLUDE_NODE_EDITOR */
#ifdef INCLUDE_ALL
#define INCLUDE_STYLE
#define INCLUDE_CALCULATOR
#define INCLUDE_CANVAS
#define INCLUDE_OVERVIEW
#define INCLUDE_NODE_EDITOR
#endif
#ifdef INCLUDE_STYLE
#include "../style.c"
#include "../../demo/common/style.c"
#endif
#ifdef INCLUDE_CALCULATOR
#include "../calculator.c"
#include "../../demo/common/calculator.c"
#endif
#ifdef INCLUDE_CANVAS
#include "../../demo/common/canvas.c"
#endif
#ifdef INCLUDE_OVERVIEW
#include "../overview.c"
#include "../../demo/common/overview.c"
#endif
#ifdef INCLUDE_NODE_EDITOR
#include "../node_editor.c"
#include "../../demo/common/node_editor.c"
#endif
/* ===============================================================
@ -167,6 +172,7 @@ int main(void)
glXGetFBConfigAttrib(win.dpy, fbc[i], GLX_SAMPLES, &samples);
if ((fb_best < 0) || (sample_buffer && samples > best_num_samples))
fb_best = i, best_num_samples = samples;
XFree(vi);
}
}
win.fbc = fbc[fb_best];
@ -251,10 +257,16 @@ int main(void)
/*nk_style_set_font(ctx, &droid->handle);*/}
#ifdef INCLUDE_STYLE
/*set_style(ctx, THEME_WHITE);*/
/*set_style(ctx, THEME_RED);*/
/*set_style(ctx, THEME_BLUE);*/
/*set_style(ctx, THEME_DARK);*/
/* ease regression testing during Nuklear release process; not needed for anything else */
#ifdef STYLE_WHITE
set_style(ctx, THEME_WHITE);
#elif defined(STYLE_RED)
set_style(ctx, THEME_RED);
#elif defined(STYLE_BLUE)
set_style(ctx, THEME_BLUE);
#elif defined(STYLE_DARK)
set_style(ctx, THEME_DARK);
#endif
#endif
bg.r = 0.10f, bg.g = 0.18f, bg.b = 0.24f, bg.a = 1.0f;
@ -309,6 +321,9 @@ int main(void)
#ifdef INCLUDE_CALCULATOR
calculator(ctx);
#endif
#ifdef INCLUDE_CANVAS
canvas(ctx);
#endif
#ifdef INCLUDE_OVERVIEW
overview(ctx);
#endif

Some files were not shown because too many files have changed in this diff Show More