From 2e7dd3dc0436e7af008141def78791fff95edf4b Mon Sep 17 00:00:00 2001 From: vurtun Date: Sun, 12 Jun 2016 15:28:38 +0200 Subject: [PATCH] Added GWEN style skinning example #155 This commit adds a GWEN UI style skinning example. It is certainly not perfect right now (especially windows suck) but it is probably useful for a general overview. One thing that is pretty clear for me now is that I need a way to read in a style from file or memory since manually setting up properties, colors and images is quite a pain. --- example/skinning.c | 805 +++++++++++++++++++++++++++++++++++++++++ example/skins/gwen.png | Bin 0 -> 24565 bytes 2 files changed, 805 insertions(+) create mode 100644 example/skinning.c create mode 100644 example/skins/gwen.png diff --git a/example/skinning.c b/example/skinning.c new file mode 100644 index 0000000..b3650c1 --- /dev/null +++ b/example/skinning.c @@ -0,0 +1,805 @@ +/* nuklear - v1.00 - public domain */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define NK_INCLUDE_FIXED_TYPES +#define NK_INCLUDE_STANDARD_IO +#define NK_INCLUDE_DEFAULT_ALLOCATOR +#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT +#define NK_INCLUDE_FONT_BAKING +#define NK_INCLUDE_DEFAULT_FONT +#define NK_IMPLEMENTATION +#include "../nuklear.h" + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" + +/* macros */ +#define WINDOW_WIDTH 1200 +#define WINDOW_HEIGHT 800 + +#define MAX_VERTEX_MEMORY 512 * 1024 +#define MAX_ELEMENT_MEMORY 128 * 1024 + +#define UNUSED(a) (void)a +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) < (b) ? (b) : (a)) +#define LEN(a) (sizeof(a)/sizeof(a)[0]) + +#ifdef __APPLE__ + #define NK_SHADER_VERSION "#version 150\n" +#else + #define NK_SHADER_VERSION "#version 300 es\n" +#endif + +struct media { + GLint skin; + struct nk_image menu; + struct nk_image check; + struct nk_image check_cursor; + struct nk_image option; + struct nk_image option_cursor; + struct nk_image header; + struct nk_image window; + struct nk_image scrollbar_inc_button; + struct nk_image scrollbar_inc_button_hover; + struct nk_image scrollbar_dec_button; + struct nk_image scrollbar_dec_button_hover; + struct nk_image button; + struct nk_image button_hover; + struct nk_image button_active; + struct nk_image tab_minimize; + struct nk_image tab_maximize; + struct nk_image slider; + struct nk_image slider_hover; + struct nk_image slider_active; +}; + + +/* =============================================================== + * + * DEVICE + * + * ===============================================================*/ +struct device { + struct nk_buffer cmds; + struct nk_draw_null_texture null; + GLuint vbo, vao, ebo; + GLuint prog; + GLuint vert_shdr; + GLuint frag_shdr; + GLint attrib_pos; + GLint attrib_uv; + GLint attrib_col; + GLint uniform_tex; + GLint uniform_proj; + GLuint font_tex; +}; + +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 GLuint +image_load(const char *filename) +{ + int x,y,n; + GLuint tex; + unsigned char *data = stbi_load(filename, &x, &y, &n, 0); + if (!data) die("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 tex; +} + +static void +device_init(struct device *dev) +{ + GLint status; + static const GLchar *vertex_shader = + NK_SHADER_VERSION + "uniform mat4 ProjMtx;\n" + "in vec2 Position;\n" + "in vec2 TexCoord;\n" + "in vec4 Color;\n" + "out vec2 Frag_UV;\n" + "out vec4 Frag_Color;\n" + "void main() {\n" + " Frag_UV = TexCoord;\n" + " Frag_Color = Color;\n" + " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" + "}\n"; + static const GLchar *fragment_shader = + NK_SHADER_VERSION + "precision mediump float;\n" + "uniform sampler2D Texture;\n" + "in vec2 Frag_UV;\n" + "in vec4 Frag_Color;\n" + "out vec4 Out_Color;\n" + "void main(){\n" + " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" + "}\n"; + + nk_buffer_init_default(&dev->cmds); + dev->prog = glCreateProgram(); + dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); + dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); + glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); + glCompileShader(dev->vert_shdr); + glCompileShader(dev->frag_shdr); + glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); + assert(status == GL_TRUE); + glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); + assert(status == GL_TRUE); + glAttachShader(dev->prog, dev->vert_shdr); + glAttachShader(dev->prog, dev->frag_shdr); + glLinkProgram(dev->prog); + glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); + assert(status == GL_TRUE); + + dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); + dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); + dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); + dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); + dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); + + { + /* buffer setup */ + GLsizei vs = sizeof(struct nk_draw_vertex); + size_t vp = offsetof(struct nk_draw_vertex, position); + size_t vt = offsetof(struct nk_draw_vertex, uv); + size_t vc = offsetof(struct nk_draw_vertex, col); + + glGenBuffers(1, &dev->vbo); + glGenBuffers(1, &dev->ebo); + glGenVertexArrays(1, &dev->vao); + + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + + glEnableVertexAttribArray((GLuint)dev->attrib_pos); + glEnableVertexAttribArray((GLuint)dev->attrib_uv); + glEnableVertexAttribArray((GLuint)dev->attrib_col); + + glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); + glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); + glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); + } + + glBindTexture(GL_TEXTURE_2D, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +static void +device_upload_atlas(struct device *dev, const void *image, int width, int height) +{ + glGenTextures(1, &dev->font_tex); + glBindTexture(GL_TEXTURE_2D, dev->font_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image); +} + +static void +device_shutdown(struct device *dev) +{ + glDetachShader(dev->prog, dev->vert_shdr); + glDetachShader(dev->prog, dev->frag_shdr); + glDeleteShader(dev->vert_shdr); + glDeleteShader(dev->frag_shdr); + glDeleteProgram(dev->prog); + glDeleteTextures(1, &dev->font_tex); + glDeleteBuffers(1, &dev->vbo); + glDeleteBuffers(1, &dev->ebo); + nk_buffer_free(&dev->cmds); +} + +static void +device_draw(struct device *dev, struct nk_context *ctx, int width, int height, + struct nk_vec2 scale, enum nk_anti_aliasing AA) +{ + GLfloat ortho[4][4] = { + {2.0f, 0.0f, 0.0f, 0.0f}, + {0.0f,-2.0f, 0.0f, 0.0f}, + {0.0f, 0.0f,-1.0f, 0.0f}, + {-1.0f,1.0f, 0.0f, 1.0f}, + }; + ortho[0][0] /= (GLfloat)width; + ortho[1][1] /= (GLfloat)height; + + /* setup global state */ + glEnable(GL_BLEND); + glBlendEquation(GL_FUNC_ADD); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glActiveTexture(GL_TEXTURE0); + + /* setup program */ + glUseProgram(dev->prog); + glUniform1i(dev->uniform_tex, 0); + glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); + { + /* convert from command queue into draw list and draw to screen */ + const struct nk_draw_command *cmd; + void *vertices, *elements; + const nk_draw_index *offset = NULL; + + /* allocate vertex and element buffer */ + glBindVertexArray(dev->vao); + glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); + + glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW); + + /* load draw vertices & elements directly into vertex + element buffer */ + vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); + elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); + { + /* fill converting configuration */ + struct nk_convert_config config; + memset(&config, 0, sizeof(config)); + config.global_alpha = 1.0f; + config.shape_AA = AA; + config.line_AA = AA; + config.circle_segment_count = 22; + config.curve_segment_count = 22; + config.arc_segment_count = 22; + config.null = dev->null; + + /* setup buffers to load vertices and elements */ + {struct nk_buffer vbuf, ebuf; + nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY); + nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY); + nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);} + } + glUnmapBuffer(GL_ARRAY_BUFFER); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + + /* iterate over and execute each draw command */ + nk_draw_foreach(cmd, ctx, &dev->cmds) + { + if (!cmd->elem_count) continue; + glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); + glScissor( + (GLint)(cmd->clip_rect.x * scale.x), + (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), + (GLint)(cmd->clip_rect.w * scale.x), + (GLint)(cmd->clip_rect.h * scale.y)); + glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); + offset += cmd->elem_count; + } + nk_clear(ctx); + } + + /* default OpenGL state */ + glUseProgram(0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindVertexArray(0); + glDisable(GL_BLEND); + glDisable(GL_SCISSOR_TEST); +} + +/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/ +static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);} +static void text_input(GLFWwindow *win, unsigned int codepoint) +{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);} +static void scroll_input(GLFWwindow *win, double _, double yoff) +{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);} + +int main(int argc, char *argv[]) +{ + /* Platform */ + static GLFWwindow *win; + int width = 0, height = 0; + int display_width=0, display_height=0; + + /* GUI */ + struct device device; + struct nk_font_atlas atlas; + struct media media; + struct nk_context ctx; + struct nk_font *font; + + /* GLFW */ + glfwSetErrorCallback(error_callback); + if (!glfwInit()) { + fprintf(stdout, "[GFLW] failed to init!\n"); + exit(1); + } + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +#ifdef __APPLE__ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); +#endif + win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL); + glfwMakeContextCurrent(win); + glfwSetWindowUserPointer(win, &ctx); + glfwSetCharCallback(win, text_input); + glfwSetScrollCallback(win, scroll_input); + glfwGetWindowSize(win, &width, &height); + glfwGetFramebufferSize(win, &display_width, &display_height); + + /* OpenGL */ + glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); + glewExperimental = 1; + if (glewInit() != GLEW_OK) { + fprintf(stderr, "Failed to setup GLEW\n"); + exit(1); + } + + /* GUI */ + {device_init(&device); + {const void *image; int w, h; + const char *font_path = (argc > 1) ? argv[1]: 0; + nk_font_atlas_init_default(&atlas); + nk_font_atlas_begin(&atlas); + if (font_path) font = nk_font_atlas_add_from_file(&atlas, font_path, 13.0f, NULL); + else font = nk_font_atlas_add_default(&atlas, 13.0f, NULL); + image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32); + device_upload_atlas(&device, image, w, h); + nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null);} + nk_init_default(&ctx, &font->handle);} + + { /* skin */ + glEnable(GL_TEXTURE_2D); + media.skin = image_load("../skins/gwen.png"); + media.check = nk_subimage_id(media.skin, 512,512, nk_rect(464,32,15,15)); + media.check_cursor = nk_subimage_id(media.skin, 512,512, nk_rect(450,34,11,11)); + media.option = nk_subimage_id(media.skin, 512,512, nk_rect(464,64,15,15)); + media.option_cursor = nk_subimage_id(media.skin, 512,512, nk_rect(451,67,9,9)); + media.header = nk_subimage_id(media.skin, 512,512, nk_rect(128,0,127,24)); + media.window = nk_subimage_id(media.skin, 512,512, nk_rect(128,23,127,104)); + media.scrollbar_inc_button = nk_subimage_id(media.skin, 512,512, nk_rect(464,256,15,15)); + media.scrollbar_inc_button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(464,320,15,15)); + media.scrollbar_dec_button = nk_subimage_id(media.skin, 512,512, nk_rect(464,224,15,15)); + media.scrollbar_dec_button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(464,288,15,15)); + media.button = nk_subimage_id(media.skin, 512,512, nk_rect(384,336,127,31)); + media.button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(384,368,127,31)); + media.button_active = nk_subimage_id(media.skin, 512,512, nk_rect(384,400,127,31)); + media.tab_minimize = nk_subimage_id(media.skin, 512,512, nk_rect(451, 99, 9, 9)); + media.tab_maximize = nk_subimage_id(media.skin, 512,512, nk_rect(467,99,9,9)); + media.slider = nk_subimage_id(media.skin, 512,512, nk_rect(418,33,11,14)); + media.slider_hover = nk_subimage_id(media.skin, 512,512, nk_rect(418,49,11,14)); + media.slider_active = nk_subimage_id(media.skin, 512,512, nk_rect(418,64,11,14)); + + /* window */ + ctx.style.window.background = nk_rgb(204,204,204); + ctx.style.window.fixed_background = nk_style_item_image(media.window); + ctx.style.window.border_color = nk_rgb(67,67,67); + ctx.style.window.combo_border_color = nk_rgb(67,67,67); + ctx.style.window.contextual_border_color = nk_rgb(67,67,67); + ctx.style.window.menu_border_color = nk_rgb(67,67,67); + ctx.style.window.group_border_color = nk_rgb(67,67,67); + ctx.style.window.tooltip_border_color = nk_rgb(67,67,67); + ctx.style.window.scrollbar_size = nk_vec2(16,16); + ctx.style.window.border_color = nk_rgba(0,0,0,0); + ctx.style.window.padding = nk_vec2(8,4); + ctx.style.window.border = 3; + + /* window header */ + ctx.style.window.header; + ctx.style.window.header.normal = nk_style_item_image(media.header); + ctx.style.window.header.hover = nk_style_item_image(media.header); + ctx.style.window.header.active = nk_style_item_image(media.header); + ctx.style.window.header.label_normal = nk_rgb(95,95,95); + ctx.style.window.header.label_hover = nk_rgb(95,95,95); + ctx.style.window.header.label_active = nk_rgb(95,95,95); + + /* scrollbar */ + ctx.style.scrollv.normal = nk_style_item_color(nk_rgb(184,184,184)); + ctx.style.scrollv.hover = nk_style_item_color(nk_rgb(184,184,184)); + ctx.style.scrollv.active = nk_style_item_color(nk_rgb(184,184,184)); + ctx.style.scrollv.cursor_normal = nk_style_item_color(nk_rgb(220,220,220)); + ctx.style.scrollv.cursor_hover = nk_style_item_color(nk_rgb(235,235,235)); + ctx.style.scrollv.cursor_active = nk_style_item_color(nk_rgb(99,202,255)); + ctx.style.scrollv.dec_symbol = NK_SYMBOL_NONE; + ctx.style.scrollv.inc_symbol = NK_SYMBOL_NONE; + ctx.style.scrollv.show_buttons = nk_true; + ctx.style.scrollv.border_color = nk_rgb(81,81,81); + ctx.style.scrollv.cursor_border_color = nk_rgb(81,81,81); + ctx.style.scrollv.border = 1; + ctx.style.scrollv.rounding = 0; + ctx.style.scrollv.border_cursor = 1; + ctx.style.scrollv.rounding_cursor = 2; + + /* scrollbar buttons */ + ctx.style.scrollv.inc_button.normal = nk_style_item_image(media.scrollbar_inc_button); + ctx.style.scrollv.inc_button.hover = nk_style_item_image(media.scrollbar_inc_button_hover); + ctx.style.scrollv.inc_button.active = nk_style_item_image(media.scrollbar_inc_button_hover); + ctx.style.scrollv.inc_button.border_color = nk_rgba(0,0,0,0); + ctx.style.scrollv.inc_button.text_background = nk_rgba(0,0,0,0); + ctx.style.scrollv.inc_button.text_normal = nk_rgba(0,0,0,0); + ctx.style.scrollv.inc_button.text_hover = nk_rgba(0,0,0,0); + ctx.style.scrollv.inc_button.text_active = nk_rgba(0,0,0,0); + ctx.style.scrollv.inc_button.border = 0.0f; + + ctx.style.scrollv.dec_button.normal = nk_style_item_image(media.scrollbar_dec_button); + ctx.style.scrollv.dec_button.hover = nk_style_item_image(media.scrollbar_dec_button_hover); + ctx.style.scrollv.dec_button.active = nk_style_item_image(media.scrollbar_dec_button_hover); + ctx.style.scrollv.dec_button.border_color = nk_rgba(0,0,0,0); + ctx.style.scrollv.dec_button.text_background = nk_rgba(0,0,0,0); + ctx.style.scrollv.dec_button.text_normal = nk_rgba(0,0,0,0); + ctx.style.scrollv.dec_button.text_hover = nk_rgba(0,0,0,0); + ctx.style.scrollv.dec_button.text_active = nk_rgba(0,0,0,0); + ctx.style.scrollv.dec_button.border = 0.0f; + + /* checkbox toggle */ + {struct nk_style_toggle *toggle; + toggle = &ctx.style.checkbox; + toggle->normal = nk_style_item_image(media.check); + toggle->hover = nk_style_item_image(media.check); + toggle->active = nk_style_item_image(media.check); + toggle->cursor_normal = nk_style_item_image(media.check_cursor); + toggle->cursor_hover = nk_style_item_image(media.check_cursor); + toggle->text_normal = nk_rgb(95,95,95); + toggle->text_hover = nk_rgb(95,95,95); + toggle->text_active = nk_rgb(95,95,95);} + + /* option toggle */ + {struct nk_style_toggle *toggle; + toggle = &ctx.style.option; + toggle->normal = nk_style_item_image(media.option); + toggle->hover = nk_style_item_image(media.option); + toggle->active = nk_style_item_image(media.option); + toggle->cursor_normal = nk_style_item_image(media.option_cursor); + toggle->cursor_hover = nk_style_item_image(media.option_cursor); + toggle->text_normal = nk_rgb(95,95,95); + toggle->text_hover = nk_rgb(95,95,95); + toggle->text_active = nk_rgb(95,95,95);} + + /* default button */ + ctx.style.button.normal = nk_style_item_image(media.button); + ctx.style.button.hover = nk_style_item_image(media.button_hover); + ctx.style.button.active = nk_style_item_image(media.button_active); + ctx.style.button.border_color = nk_rgba(0,0,0,0); + ctx.style.button.text_background = nk_rgba(0,0,0,0); + ctx.style.button.text_normal = nk_rgb(95,95,95); + ctx.style.button.text_hover = nk_rgb(95,95,95); + ctx.style.button.text_active = nk_rgb(95,95,95); + + /* contextual button */ + ctx.style.contextual_button.normal = nk_style_item_color(nk_rgb(206,206,206)); + ctx.style.contextual_button.hover = nk_style_item_color(nk_rgb(229,229,229)); + ctx.style.contextual_button.active = nk_style_item_color(nk_rgb(99,202,255)); + ctx.style.contextual_button.border_color = nk_rgba(0,0,0,0); + ctx.style.contextual_button.text_background = nk_rgba(0,0,0,0); + ctx.style.contextual_button.text_normal = nk_rgb(95,95,95); + ctx.style.contextual_button.text_hover = nk_rgb(95,95,95); + ctx.style.contextual_button.text_active = nk_rgb(95,95,95); + + /* menu button */ + ctx.style.menu_button.normal = nk_style_item_color(nk_rgb(206,206,206)); + ctx.style.menu_button.hover = nk_style_item_color(nk_rgb(229,229,229)); + ctx.style.menu_button.active = nk_style_item_color(nk_rgb(99,202,255)); + ctx.style.menu_button.border_color = nk_rgba(0,0,0,0); + ctx.style.menu_button.text_background = nk_rgba(0,0,0,0); + ctx.style.menu_button.text_normal = nk_rgb(95,95,95); + ctx.style.menu_button.text_hover = nk_rgb(95,95,95); + ctx.style.menu_button.text_active = nk_rgb(95,95,95); + + /* tree */ + ctx.style.tab.text = nk_rgb(95,95,95); + ctx.style.tab.tab_minimize_button.normal = nk_style_item_image(media.tab_minimize); + ctx.style.tab.tab_minimize_button.hover = nk_style_item_image(media.tab_minimize); + ctx.style.tab.tab_minimize_button.active = nk_style_item_image(media.tab_minimize); + ctx.style.tab.tab_minimize_button.text_background = nk_rgba(0,0,0,0); + ctx.style.tab.tab_minimize_button.text_normal = nk_rgba(0,0,0,0); + ctx.style.tab.tab_minimize_button.text_hover = nk_rgba(0,0,0,0); + ctx.style.tab.tab_minimize_button.text_active = nk_rgba(0,0,0,0); + + ctx.style.tab.tab_maximize_button.normal = nk_style_item_image(media.tab_maximize); + ctx.style.tab.tab_maximize_button.hover = nk_style_item_image(media.tab_maximize); + ctx.style.tab.tab_maximize_button.active = nk_style_item_image(media.tab_maximize); + ctx.style.tab.tab_maximize_button.text_background = nk_rgba(0,0,0,0); + ctx.style.tab.tab_maximize_button.text_normal = nk_rgba(0,0,0,0); + ctx.style.tab.tab_maximize_button.text_hover = nk_rgba(0,0,0,0); + ctx.style.tab.tab_maximize_button.text_active = nk_rgba(0,0,0,0); + + ctx.style.tab.node_minimize_button.normal = nk_style_item_image(media.tab_minimize); + ctx.style.tab.node_minimize_button.hover = nk_style_item_image(media.tab_minimize); + ctx.style.tab.node_minimize_button.active = nk_style_item_image(media.tab_minimize); + ctx.style.tab.node_minimize_button.text_background = nk_rgba(0,0,0,0); + ctx.style.tab.node_minimize_button.text_normal = nk_rgba(0,0,0,0); + ctx.style.tab.node_minimize_button.text_hover = nk_rgba(0,0,0,0); + ctx.style.tab.node_minimize_button.text_active = nk_rgba(0,0,0,0); + + ctx.style.tab.node_maximize_button.normal = nk_style_item_image(media.tab_maximize); + ctx.style.tab.node_maximize_button.hover = nk_style_item_image(media.tab_maximize); + ctx.style.tab.node_maximize_button.active = nk_style_item_image(media.tab_maximize); + ctx.style.tab.node_maximize_button.text_background = nk_rgba(0,0,0,0); + ctx.style.tab.node_maximize_button.text_normal = nk_rgba(0,0,0,0); + ctx.style.tab.node_maximize_button.text_hover = nk_rgba(0,0,0,0); + ctx.style.tab.node_maximize_button.text_active = nk_rgba(0,0,0,0); + + /* selectable */ + ctx.style.selectable.normal = nk_style_item_color(nk_rgb(206,206,206)); + ctx.style.selectable.hover = nk_style_item_color(nk_rgb(206,206,206)); + ctx.style.selectable.pressed = nk_style_item_color(nk_rgb(206,206,206)); + ctx.style.selectable.normal_active = nk_style_item_color(nk_rgb(185,205,248)); + ctx.style.selectable.hover_active = nk_style_item_color(nk_rgb(185,205,248)); + ctx.style.selectable.pressed_active = nk_style_item_color(nk_rgb(185,205,248)); + ctx.style.selectable.text_normal = nk_rgb(95,95,95); + ctx.style.selectable.text_hover = nk_rgb(95,95,95); + ctx.style.selectable.text_pressed = nk_rgb(95,95,95); + ctx.style.selectable.text_normal_active = nk_rgb(95,95,95); + ctx.style.selectable.text_hover_active = nk_rgb(95,95,95); + ctx.style.selectable.text_pressed_active = nk_rgb(95,95,95); + + /* slider */ + ctx.style.slider.normal = nk_style_item_hide(); + ctx.style.slider.hover = nk_style_item_hide(); + ctx.style.slider.active = nk_style_item_hide(); + ctx.style.slider.bar_normal = nk_rgb(156,156,156); + ctx.style.slider.bar_hover = nk_rgb(156,156,156); + ctx.style.slider.bar_active = nk_rgb(156,156,156); + ctx.style.slider.bar_filled = nk_rgb(156,156,156); + ctx.style.slider.cursor_normal = nk_style_item_image(media.slider); + ctx.style.slider.cursor_hover = nk_style_item_image(media.slider_hover); + ctx.style.slider.cursor_active = nk_style_item_image(media.slider_active); + ctx.style.slider.cursor_size = nk_vec2(16.5f,21); + ctx.style.slider.bar_height = 1; + + /* progressbar */ + ctx.style.progress.normal = nk_style_item_color(nk_rgb(231,231,231)); + ctx.style.progress.hover = nk_style_item_color(nk_rgb(231,231,231)); + ctx.style.progress.active = nk_style_item_color(nk_rgb(231,231,231)); + ctx.style.progress.cursor_normal = nk_style_item_color(nk_rgb(63,242,93)); + ctx.style.progress.cursor_hover = nk_style_item_color(nk_rgb(63,242,93)); + ctx.style.progress.cursor_active = nk_style_item_color(nk_rgb(63,242,93)); + ctx.style.progress.border_color = nk_rgb(114,116,115); + ctx.style.progress.padding = nk_vec2(0,0); + ctx.style.progress.border = 2; + ctx.style.progress.rounding = 1; + + /* combo */ + ctx.style.combo.normal = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.combo.hover = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.combo.active = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.combo.border_color = nk_rgb(95,95,95); + ctx.style.combo.label_normal = nk_rgb(95,95,95); + ctx.style.combo.label_hover = nk_rgb(95,95,95); + ctx.style.combo.label_active = nk_rgb(95,95,95); + ctx.style.combo.border = 1; + ctx.style.combo.rounding = 1; + + /* combo button */ + ctx.style.combo.button.normal = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.combo.button.hover = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.combo.button.active = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.combo.button.text_background = nk_rgb(216,216,216); + ctx.style.combo.button.text_normal = nk_rgb(95,95,95); + ctx.style.combo.button.text_hover = nk_rgb(95,95,95); + ctx.style.combo.button.text_active = nk_rgb(95,95,95); + + /* property */ + ctx.style.property.normal = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.hover = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.active = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.border_color = nk_rgb(81,81,81); + ctx.style.property.label_normal = nk_rgb(95,95,95); + ctx.style.property.label_hover = nk_rgb(95,95,95); + ctx.style.property.label_active = nk_rgb(95,95,95); + ctx.style.property.sym_left = NK_SYMBOL_TRIANGLE_LEFT; + ctx.style.property.sym_right = NK_SYMBOL_TRIANGLE_RIGHT; + ctx.style.property.rounding = 10; + ctx.style.property.border = 1; + + /* edit */ + ctx.style.edit.normal = nk_style_item_color(nk_rgb(240,240,240)); + ctx.style.edit.hover = nk_style_item_color(nk_rgb(240,240,240)); + ctx.style.edit.active = nk_style_item_color(nk_rgb(240,240,240)); + ctx.style.edit.border_color = nk_rgb(62,62,62); + ctx.style.edit.cursor_normal = nk_rgb(99,202,255); + ctx.style.edit.cursor_hover = nk_rgb(99,202,255); + ctx.style.edit.cursor_text_normal = nk_rgb(95,95,95); + ctx.style.edit.cursor_text_hover = nk_rgb(95,95,95); + ctx.style.edit.text_normal = nk_rgb(95,95,95); + ctx.style.edit.text_hover = nk_rgb(95,95,95); + ctx.style.edit.text_active = nk_rgb(95,95,95); + ctx.style.edit.selected_normal = nk_rgb(99,202,255); + ctx.style.edit.selected_hover = nk_rgb(99,202,255); + ctx.style.edit.selected_text_normal = nk_rgb(95,95,95); + ctx.style.edit.selected_text_hover = nk_rgb(95,95,95); + ctx.style.edit.border = 1; + ctx.style.edit.rounding = 2; + + /* property buttons */ + ctx.style.property.dec_button.normal = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.dec_button.hover = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.dec_button.active = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.dec_button.text_background = nk_rgba(0,0,0,0); + ctx.style.property.dec_button.text_normal = nk_rgb(95,95,95); + ctx.style.property.dec_button.text_hover = nk_rgb(95,95,95); + ctx.style.property.dec_button.text_active = nk_rgb(95,95,95); + ctx.style.property.inc_button = ctx.style.property.dec_button; + + /* property edit */ + ctx.style.property.edit.normal = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.edit.hover = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.edit.active = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.property.edit.border_color = nk_rgba(0,0,0,0); + ctx.style.property.edit.cursor_normal = nk_rgb(95,95,95); + ctx.style.property.edit.cursor_hover = nk_rgb(95,95,95); + ctx.style.property.edit.cursor_text_normal = nk_rgb(216,216,216); + ctx.style.property.edit.cursor_text_hover = nk_rgb(216,216,216); + ctx.style.property.edit.text_normal = nk_rgb(95,95,95); + ctx.style.property.edit.text_hover = nk_rgb(95,95,95); + ctx.style.property.edit.text_active = nk_rgb(95,95,95); + ctx.style.property.edit.selected_normal = nk_rgb(95,95,95); + ctx.style.property.edit.selected_hover = nk_rgb(95,95,95); + ctx.style.property.edit.selected_text_normal = nk_rgb(216,216,216); + ctx.style.property.edit.selected_text_hover = nk_rgb(216,216,216); + + /* chart */ + ctx.style.chart.background = nk_style_item_color(nk_rgb(216,216,216)); + ctx.style.chart.border_color = nk_rgb(81,81,81); + ctx.style.chart.color = nk_rgb(95,95,95); + ctx.style.chart.selected_color = nk_rgb(255,0,0); + ctx.style.chart.border = 1; + } + + while (!glfwWindowShouldClose(win)) + { + /* High DPI displays */ + struct nk_vec2 scale; + glfwGetWindowSize(win, &width, &height); + glfwGetFramebufferSize(win, &display_width, &display_height); + scale.x = (float)display_width/(float)width; + scale.y = (float)display_height/(float)height; + + /* Input */ + {double x, y; + nk_input_begin(&ctx); + glfwPollEvents(); + nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); + if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || + glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL)) { + nk_input_key(&ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); + nk_input_key(&ctx, NK_KEY_SHIFT, 1); + } else { + nk_input_key(&ctx, NK_KEY_COPY, 0); + nk_input_key(&ctx, NK_KEY_PASTE, 0); + nk_input_key(&ctx, NK_KEY_CUT, 0); + nk_input_key(&ctx, NK_KEY_SHIFT, 0); + } + glfwGetCursorPos(win, &x, &y); + nk_input_motion(&ctx, (int)x, (int)y); + nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); + nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); + nk_input_button(&ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); + nk_input_end(&ctx);} + + /* GUI */ + {struct nk_panel layout, tab; + if (nk_begin(&ctx, &layout, "Demo", nk_rect(50, 50, 300, 400), + NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_TITLE)) + { + int i; + float id; + static int slider = 10; + static int field_len; + static nk_size prog_value = 60; + static int current_weapon = 0; + static char field_buffer[64]; + static float pos; + static const char *weapons[] = {"Fist","Pistol","Shotgun","Plasma","BFG"}; + const float step = (2*3.141592654f) / 32; + + nk_layout_row_static(&ctx, 30, 120, 1); + if (nk_button_label(&ctx, "button", NK_BUTTON_DEFAULT)) + fprintf(stdout, "button pressed\n"); + + nk_layout_row_dynamic(&ctx, 30, 2); + nk_check_label(&ctx, "inactive", 0); + nk_check_label(&ctx, "active", 1); + nk_option_label(&ctx, "active", 1); + nk_option_label(&ctx, "inactive", 0); + + nk_layout_row_dynamic(&ctx, 30, 1); + nk_slider_int(&ctx, 0, &slider, 16, 1); + nk_layout_row_dynamic(&ctx, 20, 1); + nk_progress(&ctx, &prog_value, 100, NK_MODIFIABLE); + + nk_layout_row_dynamic(&ctx, 25, 1); + nk_edit_string(&ctx, NK_EDIT_FIELD, field_buffer, &field_len, 64, nk_filter_default); + nk_property_float(&ctx, "#X:", -1024.0f, &pos, 1024.0f, 1, 1); + current_weapon = nk_combo(&ctx, weapons, LEN(weapons), current_weapon, 25); + + nk_layout_row_dynamic(&ctx, 100, 1); + 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); + for (id = 0, i = 0; i < 32; ++i) { + nk_chart_push_slot(&ctx, (float)fabs(sin(id)), 0); + nk_chart_push_slot(&ctx, (float)cos(id), 1); + nk_chart_push_slot(&ctx, (float)sin(id), 2); + id += step; + } + } + nk_chart_end(&ctx); + + nk_layout_row_dynamic(&ctx, 250, 1); + if (nk_group_begin(&ctx, &tab, "Standard", NK_WINDOW_BORDER|NK_WINDOW_BORDER)) + { + if (nk_tree_push(&ctx, NK_TREE_NODE, "Window", NK_MAXIMIZED)) { + static int selected[8]; + if (nk_tree_push(&ctx, NK_TREE_NODE, "Next", NK_MAXIMIZED)) { + nk_layout_row_dynamic(&ctx, 20, 1); + for (i = 0; i < 4; ++i) + nk_selectable_label(&ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_LEFT, &selected[i]); + nk_tree_pop(&ctx); + } + if (nk_tree_push(&ctx, NK_TREE_NODE, "Previous", NK_MAXIMIZED)) { + nk_layout_row_dynamic(&ctx, 20, 1); + for (i = 4; i < 8; ++i) + nk_selectable_label(&ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_LEFT, &selected[i]); + nk_tree_pop(&ctx); + } + nk_tree_pop(&ctx); + } + nk_group_end(&ctx); + } + } + nk_end(&ctx);} + + /* Draw */ + glViewport(0, 0, display_width, display_height); + glClear(GL_COLOR_BUFFER_BIT); + glClearColor(0.5882, 0.6666, 0.6666, 1.0f); + device_draw(&device, &ctx, width, height, scale, NK_ANTI_ALIASING_ON); + glfwSwapBuffers(win); + } + glDeleteTextures(1,(const GLuint*)&media.skin); + nk_font_atlas_clear(&atlas); + nk_free(&ctx); + device_shutdown(&device); + glfwTerminate(); + return 0; +} + diff --git a/example/skins/gwen.png b/example/skins/gwen.png new file mode 100644 index 0000000000000000000000000000000000000000..40956c9411c4c59a9b5001589ae0fa2a6e2258c9 GIT binary patch literal 24565 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 G-~10fwS(yZ literal 0 HcmV?d00001