Last active
June 11, 2018 14:20
-
-
Save sherjilozair/ee74b4e5267ac91e46fa856ac7555433 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Nuklear - 1.32.0 - public domain | |
* no warrenty implied; use at your own risk. | |
* authored from 2015-2016 by Micha Mettke | |
*/ | |
/* | |
* ============================================================== | |
* | |
* API | |
* | |
* =============================================================== | |
*/ | |
#ifndef NK_SDL_GL3_H_ | |
#define NK_SDL_GL3_H_ | |
#include <SDL2/SDL.h> | |
//#include <SDL2/SDL_opengl.h> | |
NK_API struct nk_context* nk_sdl_init(SDL_Window *win); | |
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 , int max_vertex_buffer, int max_element_buffer); | |
NK_API void nk_sdl_shutdown(void); | |
NK_API void nk_sdl_device_destroy(void); | |
NK_API void nk_sdl_device_create(void); | |
#endif | |
/* | |
* ============================================================== | |
* | |
* IMPLEMENTATION | |
* | |
* =============================================================== | |
*/ | |
#ifdef NK_SDL_GL3_IMPLEMENTATION | |
#define SOKOL_IMPL | |
#define SOKOL_GLCORE33 | |
#include "sokol_gfx.h" | |
#include <string.h> | |
struct nk_sdl_device { | |
struct nk_buffer cmds; | |
struct nk_draw_null_texture null; | |
sg_shader shader; | |
sg_pipeline pipeline; | |
sg_image font_tex; | |
}; | |
struct nk_sdl_vertex { | |
float position[2]; | |
float uv[2]; | |
nk_byte col[4]; | |
}; | |
static struct nk_sdl { | |
SDL_Window *win; | |
struct nk_sdl_device ogl; | |
struct nk_context ctx; | |
struct nk_font_atlas atlas; | |
} sdl; | |
#ifdef __APPLE__ | |
#define NK_SHADER_VERSION "#version 150\n" | |
#else | |
#define NK_SHADER_VERSION "#version 300 es\n" | |
#endif | |
NK_API void | |
nk_sdl_device_create(void) | |
{ | |
sg_setup(&(sg_desc) {0}); | |
struct nk_sdl_device *dev = &sdl.ogl; | |
nk_buffer_init_default(&dev->cmds); | |
dev->shader = sg_make_shader(&(sg_shader_desc){ | |
.fs.images[0] = {.name="tex", .type=SG_IMAGETYPE_2D}, | |
.vs.source = NK_SHADER_VERSION | |
"uniform mat4 ProjMtx;\n" | |
"layout(location = 0) in vec2 Position;\n" | |
"layout(location = 1) in vec2 TexCoord;\n" | |
"layout(location = 2) 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", | |
.fs.source = 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_INTERN void | |
nk_sdl_device_upload_atlas(const void *image, int width, int height) | |
{ | |
struct nk_sdl_device *dev = &sdl.ogl; | |
dev->font_tex = sg_make_image(&(sg_image_desc){ | |
.width=width, | |
.height=height, | |
.pixel_format = SG_PIXELFORMAT_RGBA8, | |
.min_filter = SG_FILTER_LINEAR, | |
.mag_filter = SG_FILTER_LINEAR, | |
.content.subimage[0][0] = { | |
.ptr = image, | |
.size = sizeof(image) | |
} | |
}); | |
} | |
NK_API void | |
nk_sdl_device_destroy(void) | |
{ | |
struct nk_sdl_device *dev = &sdl.ogl; | |
sg_destroy_shader(dev->shader); | |
sg_destroy_image(dev->font_tex); | |
sg_destroy_pipeline(dev->pipeline); | |
nk_buffer_free(&dev->cmds); | |
} | |
NK_API void | |
nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) | |
{ | |
struct nk_sdl_device *dev = &sdl.ogl; | |
int width, height; | |
int display_width, display_height; | |
struct nk_vec2 scale; | |
float 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}, | |
}; | |
SDL_GetWindowSize(sdl.win, &width, &height); | |
SDL_GL_GetDrawableSize(sdl.win, &display_width, &display_height); | |
ortho[0][0] /= (float)width; | |
ortho[1][1] /= (float)height; | |
scale.x = (float)display_width/(float)width; | |
scale.y = (float)display_height/(float)height; | |
const struct nk_draw_command *cmd; | |
struct nk_buffer vbuf, ebuf; | |
sg_buffer sg_vbuf = sg_make_buffer(&(sg_buffer_desc){ | |
.size = max_vertex_buffer | |
}); | |
sg_buffer sg_ibuf = sg_make_buffer(&(sg_buffer_desc){ | |
.size = max_element_buffer, | |
.type = SG_BUFFERTYPE_INDEXBUFFER, | |
}); | |
{ | |
/* fill convert 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.null = dev->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; | |
/* setup buffers to load vertices and elements */ | |
//TODO: need to figure out what to put in for vertices and elements | |
nk_buffer_init_fixed(&vbuf, vertices, (nk_size)max_vertex_buffer); | |
nk_buffer_init_fixed(&ebuf, elements, (nk_size)max_element_buffer); | |
nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config); | |
} | |
sg_pipeline pipeline = sg_make_pipeline(&(sg_pipeline_desc){ | |
.shader = dev->shader, | |
.blend = { | |
.enabled = true, | |
.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA, | |
.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, | |
.color_write_mask = SG_COLORMASK_RGB, | |
}, | |
.index_type = SG_INDEXTYPE_NONE, | |
.layout = { | |
.attrs = { | |
[0] = {.format=SG_VERTEXFORMAT_FLOAT2}, | |
[1] = {.format=SG_VERTEXFORMAT_FLOAT2}, | |
[2] = {.format=SG_VERTEXFORMAT_UBYTE4}, | |
} | |
} | |
}); | |
sg_draw_state draw_state = (sg_draw_state) { | |
.pipeline = pipeline, | |
.vertex_buffers[0] = sg_vbuf, | |
.index_buffer = sg_ibuf, | |
.fs_images[0] = 0 | |
}; | |
/* setup global state */ | |
sg_pass_action pass_action = {0}; | |
sg_begin_default_pass(&pass_action, display_width, display_height); | |
/* iterate over and execute each draw command */ | |
nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) { | |
if (!cmd->elem_count) continue; | |
draw_state.fs_images[0] = (sg_image) {cmd->texture.id}; | |
sg_apply_draw_state(&draw_state); | |
sg_apply_scissor_rect(cmd->clip_rect.x * scale.x, | |
((height - (cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), | |
cmd->clip_rect.w * scale.x, cmd->clip_rect.h * scale.y, true); | |
sg_draw(SG_PRIMITIVETYPE_TRIANGLES, cmd->elem_count, 1); | |
draw_state.index_buffer_offset += cmd->elem_count; | |
} | |
nk_clear(&sdl.ctx); | |
} | |
static void | |
nk_sdl_clipbard_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_clipbard_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.win = win; | |
nk_init_default(&sdl.ctx, 0); | |
sdl.ctx.clip.copy = nk_sdl_clipbard_copy; | |
sdl.ctx.clip.paste = nk_sdl_clipbard_paste; | |
sdl.ctx.clip.userdata = nk_handle_ptr(0); | |
nk_sdl_device_create(); | |
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_id((int)sdl.ogl.font_tex.id), &sdl.ogl.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; | |
if (evt->type == SDL_KEYUP || evt->type == SDL_KEYDOWN) { | |
/* key events */ | |
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) { | |
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) { | |
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; | |
return 1; | |
} else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) { | |
/* mouse button */ | |
int down = evt->type == SDL_MOUSEBUTTONDOWN; | |
const int x = evt->button.x, y = evt->button.y; | |
if (evt->button.button == 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); | |
return 1; | |
} else if (evt->type == SDL_MOUSEMOTION) { | |
/* mouse motion */ | |
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; | |
} else if (evt->type == SDL_TEXTINPUT) { | |
/* text input */ | |
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 */ | |
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) | |
{ | |
nk_font_atlas_clear(&sdl.atlas); | |
nk_free(&sdl.ctx); | |
nk_sdl_device_destroy(); | |
memset(&sdl, 0, sizeof(sdl)); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment