Last active
December 20, 2016 17:46
-
-
Save cadaver/eaf784926ea394351731e319e8c6cef9 to your computer and use it in GitHub Desktop.
Urho3D NuklearUI work in progress
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 - v1.17 - 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 <SDL/SDL.h> | |
#include <SDL/SDL_opengl.h> | |
#include "../Graphics/Graphics.h" | |
#include "../Graphics/Texture2D.h" | |
#include "../Graphics/IndexBuffer.h" | |
#include "../Graphics/VertexBuffer.h" | |
#include "../Graphics/ShaderVariation.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 | |
#include <string.h> | |
struct nk_sdl_device { | |
struct nk_buffer cmds; | |
struct nk_draw_null_texture null; | |
Urho3D::VertexBuffer* vbuf; | |
Urho3D::IndexBuffer* ebuf; | |
//Urho3D::Vector<Urho3D::SharedPtr<Urho3D::Texture2D> > font_texs; | |
}; | |
struct nk_sdl_vertex { | |
float position[2]; | |
float uv[2]; | |
nk_byte col[4]; | |
}; | |
static struct nk_sdl { | |
SDL_Window *win; | |
Urho3D::Graphics* graphics; | |
struct nk_sdl_device ogl; | |
struct nk_context ctx; | |
struct nk_font_atlas atlas; | |
} sdl; | |
NK_API void | |
nk_sdl_device_create(void) | |
{ | |
struct nk_sdl_device *dev = &sdl.ogl; | |
nk_buffer_init_default(&dev->cmds); | |
sdl.ogl.ebuf = new Urho3D::IndexBuffer(sdl.graphics->GetContext()); | |
sdl.ogl.vbuf = new Urho3D::VertexBuffer(sdl.graphics->GetContext()); | |
Urho3D::Texture2D* nullTex = new Urho3D::Texture2D(sdl.graphics->GetContext()); | |
nullTex->SetNumLevels(1); | |
unsigned whiteOpaque = 0xffffffff; | |
nullTex->SetSize(1, 1, Urho3D::Graphics::GetRGBAFormat()); | |
nullTex->SetData(0, 0, 0, 1, 1, &whiteOpaque); | |
sdl.ogl.null.texture.ptr = nullTex; | |
} | |
NK_API void | |
nk_sdl_device_destroy(void) | |
{ | |
struct nk_sdl_device *dev = &sdl.ogl; | |
delete dev->vbuf; | |
dev->vbuf = 0; | |
delete dev->ebuf; | |
dev->ebuf = 0; | |
delete (Urho3D::Texture2D*)(dev->null.texture.ptr); | |
dev->null.texture.ptr = 0; | |
//dev->font_texs.Clear(); | |
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; | |
sdl.graphics->SetViewport(Urho3D::IntRect(0, 0, sdl.graphics->GetWidth(), sdl.graphics->GetHeight())); | |
sdl.graphics->SetBlendMode(Urho3D::BLEND_ALPHA); | |
sdl.graphics->SetCullMode(Urho3D::CULL_NONE); | |
sdl.graphics->SetDepthTest(Urho3D::CMP_ALWAYS); | |
sdl.graphics->SetFillMode(Urho3D::FILL_SOLID); | |
sdl.graphics->SetColorWrite(true); | |
sdl.graphics->SetDepthWrite(false); | |
// Max. vertex / index count is not assumed to change later | |
if (dev->vbuf->GetVertexCount() == 0) | |
{ | |
Urho3D::PODVector<Urho3D::VertexElement> elems; | |
elems.Push(Urho3D::VertexElement(Urho3D::TYPE_VECTOR2, Urho3D::SEM_POSITION)); | |
elems.Push(Urho3D::VertexElement(Urho3D::TYPE_VECTOR2, Urho3D::SEM_TEXCOORD)); | |
elems.Push(Urho3D::VertexElement(Urho3D::TYPE_UBYTE4_NORM, Urho3D::SEM_COLOR)); | |
dev->vbuf->SetSize(max_vertex_buffer / sizeof(nk_sdl_vertex), elems, true); | |
} | |
if (dev->ebuf->GetIndexCount() == 0) | |
dev->ebuf->SetSize(max_element_buffer / sizeof(unsigned short), false, true); | |
void* vertexData = dev->vbuf->Lock(0, dev->vbuf->GetVertexCount(), true); | |
void* indexData = dev->ebuf->Lock(0, dev->ebuf->GetIndexCount(), true); | |
if (vertexData && indexData) | |
{ | |
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; | |
{ | |
struct nk_buffer vbuf, ebuf; | |
nk_buffer_init_fixed(&vbuf, vertexData, (nk_size)max_vertex_buffer); | |
nk_buffer_init_fixed(&ebuf, indexData, (nk_size)max_element_buffer); | |
nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config); | |
} | |
Urho3D::IntVector2 viewSize = sdl.graphics->GetViewport().Size(); | |
Urho3D::Vector2 invScreenSize(1.0f / (float)viewSize.x_, 1.0f / (float)viewSize.y_); | |
Urho3D::Vector2 scale(2.0f * invScreenSize.x_, -2.0f * invScreenSize.y_); | |
Urho3D::Matrix4 projection(Urho3D::Matrix4::IDENTITY); | |
projection.m00_ = scale.x_; | |
projection.m03_ = -1.0f; | |
projection.m11_ = scale.y_; | |
projection.m13_ = 1.0f; | |
projection.m22_ = 1.0f; | |
projection.m23_ = 0.0f; | |
projection.m33_ = 1.0f; | |
Urho3D::ShaderVariation* diffTextureVS = sdl.graphics->GetShader(Urho3D::VS, "NuklearUI", ""); | |
Urho3D::ShaderVariation* diffTexturePS = sdl.graphics->GetShader(Urho3D::PS, "NuklearUI", ""); | |
sdl.graphics->SetShaders(diffTextureVS, diffTexturePS); | |
sdl.graphics->SetVertexBuffer(dev->vbuf); | |
sdl.graphics->SetIndexBuffer(dev->ebuf); | |
sdl.graphics->SetShaderParameter(Urho3D::VSP_VIEWPROJ, projection); | |
unsigned offset = 0; | |
const struct nk_draw_command *cmd; | |
nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) { | |
if (!cmd->elem_count) continue; | |
sdl.graphics->SetTexture(0, (Urho3D::Texture2D*)cmd->texture.ptr); | |
sdl.graphics->SetScissorTest(true, Urho3D::IntRect(cmd->clip_rect.x, cmd->clip_rect.y, | |
(cmd->clip_rect.x + cmd->clip_rect.w), (cmd->clip_rect.y + cmd->clip_rect.h))); | |
sdl.graphics->Draw(Urho3D::TRIANGLE_LIST, offset, cmd->elem_count, 0, 0, dev->vbuf->GetVertexCount()); | |
offset += cmd->elem_count; | |
} | |
nk_clear(&sdl.ctx); | |
} | |
dev->vbuf->Unlock(); | |
dev->ebuf->Unlock(); | |
sdl.graphics->SetScissorTest(false); | |
} | |
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(Urho3D::Graphics* graphics) | |
{ | |
sdl.graphics = graphics; | |
sdl.win = graphics->GetWindow(); | |
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); | |
struct nk_sdl_device *dev = &sdl.ogl; | |
Urho3D::Texture2D* fontTex(new Urho3D::Texture2D(sdl.graphics->GetContext())); | |
fontTex->SetNumLevels(1); | |
fontTex->SetSize(w, h, Urho3D::Graphics::GetRGBAFormat()); | |
fontTex->SetData(0, 0, 0, w, h, image); | |
// Remember the created texture for cleanup | |
//dev->font_texs.Push(fontTex); | |
nk_font_atlas_end(&sdl.atlas, nk_handle_ptr(fontTex), &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) | |
nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); | |
if (evt->button.button == SDL_BUTTON_MIDDLE) | |
nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); | |
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) { | |
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) { | |
nk_glyph glyph; | |
memcpy(glyph, evt->text.text, NK_UTF_SIZE); | |
nk_input_glyph(ctx, glyph); | |
return 1; | |
} | |
else if (evt->type == SDL_MOUSEWHEEL) { | |
nk_input_scroll(ctx, (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 |
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
#include "Uniforms.glsl" | |
#include "Samplers.glsl" | |
#ifdef COMPILEVS | |
// Silence GLSL 150 deprecation warnings | |
#ifdef GL3 | |
#define attribute in | |
#define varying out | |
#endif | |
attribute vec2 iPos; | |
attribute vec2 iTexCoord; | |
attribute vec4 iColor; | |
#else | |
// Silence GLSL 150 deprecation warnings | |
#ifdef GL3 | |
#define varying in | |
// \todo: should not hardcode the number of MRT outputs according to defines | |
#if defined(DEFERRED) | |
out vec4 fragData[4]; | |
#elif defined(PREPASS) | |
out vec4 fragData[2]; | |
#else | |
out vec4 fragData[1]; | |
#endif | |
#define gl_FragColor fragData[0] | |
#define gl_FragData fragData | |
#endif | |
#endif | |
varying vec2 vTexCoord; | |
varying vec4 vColor; | |
void VS() | |
{ | |
gl_Position = vec4(iPos, 0.0, 1.0) * cViewProj; | |
vTexCoord = iTexCoord; | |
vColor = iColor; | |
} | |
void PS() | |
{ | |
gl_FragColor = vColor * texture2D(sDiffMap, vTexCoord); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment