PumpkinBrush
nuklear_sfml_gl2.h
Go to the documentation of this file.
1 /*
2  * Nuklear - 1.32.0 - public domain
3  * no warrenty implied; use at your own risk.
4  * authored from 2015-2016 by Micha Mettke
5  */
6 /*
7  * ==============================================================
8  *
9  * API
10  *
11  * ===============================================================
12  */
13 #ifndef NK_SFML_GL2_H_
14 #define NK_SFML_GL2_H_
15 
16 #include <SFML/Window.hpp>
17 #include <cstring>
18 NK_API struct nk_context* nk_sfml_init(sf::Window* window);
19 NK_API void nk_sfml_font_stash_begin(struct nk_font_atlas** atlas);
21 NK_API int nk_sfml_handle_event(sf::Event* event);
23 NK_API void nk_sfml_shutdown(void);
24 
25 #endif
26 /*
27  * ==============================================================
28  *
29  * IMPLEMENTATION
30  *
31  * ===============================================================
32  */
33  #ifdef NK_SFML_GL2_IMPLEMENTATION
34 
35 struct nk_sfml_device {
36  struct nk_buffer cmds;
37  struct nk_draw_null_texture null;
38  GLuint font_tex;
39 };
40 
41 struct nk_sfml_vertex {
42  float position[2];
43  float uv[2];
44  nk_byte col[4];
45 };
46 
47 static struct nk_sfml {
48  sf::Window* window;
49  struct nk_sfml_device ogl;
50  struct nk_context ctx;
51  struct nk_font_atlas atlas;
52 } sfml;
53 
54 NK_INTERN void
55 nk_sfml_device_upload_atlas(const void* image, int width, int height)
56 {
57  struct nk_sfml_device* dev = &sfml.ogl;
58  glGenTextures(1, &dev->font_tex);
59  glBindTexture(GL_TEXTURE_2D, dev->font_tex);
60  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
61  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
62  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0,
63  GL_RGBA, GL_UNSIGNED_BYTE, image);
64 }
65 
66 NK_API void
68 {
69  /* setup global state */
70  struct nk_sfml_device* dev = &sfml.ogl;
71 
72  int window_width = sfml.window->getSize().x;
73  int window_height = sfml.window->getSize().y;
74 
75  glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
76  glDisable(GL_CULL_FACE);
77  glDisable(GL_DEPTH_TEST);
78  glEnable(GL_SCISSOR_TEST);
79  glEnable(GL_BLEND);
80  glEnable(GL_TEXTURE_2D);
81  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
82 
83  glViewport(0, 0, (GLsizei)window_width, (GLsizei)window_height);
84  glMatrixMode(GL_TEXTURE);
85  glPushMatrix();
86  glLoadIdentity();
87  glMatrixMode(GL_PROJECTION);
88  glPushMatrix();
89  glLoadIdentity();
90  glOrtho(0.0f, window_width, window_height, 0.0f, -1.0f, 1.0f);
91  glMatrixMode(GL_MODELVIEW);
92  glPushMatrix();
93  glLoadIdentity();
94 
95  glEnableClientState(GL_VERTEX_ARRAY);
96  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
97  glEnableClientState(GL_COLOR_ARRAY);
98  {
99  GLsizei vs = sizeof(struct nk_sfml_vertex);
100  size_t vp = NK_OFFSETOF(struct nk_sfml_vertex, position);
101  size_t vt = NK_OFFSETOF(struct nk_sfml_vertex, uv);
102  size_t vc = NK_OFFSETOF(struct nk_sfml_vertex, col);
103 
104  /* convert from command queue into draw list and draw to screen */
105  const struct nk_draw_command* cmd;
106  const nk_draw_index* offset = NULL;
107  struct nk_buffer vbuf, ebuf;
108 
109  /* fill converting configuration */
110  struct nk_convert_config config;
111  static const struct nk_draw_vertex_layout_element vertex_layout[] = {
112  {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sfml_vertex, position)},
113  {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sfml_vertex, uv)},
114  {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_sfml_vertex, col)},
115  {NK_VERTEX_LAYOUT_END}
116  };
117  NK_MEMSET(&config, 0, sizeof(config));
118  config.vertex_layout = vertex_layout;
119  config.vertex_size = sizeof(struct nk_sfml_vertex);
120  config.vertex_alignment = NK_ALIGNOF(struct nk_sfml_vertex);
121  config.null = dev->null;
122  config.circle_segment_count = 22;
123  config.curve_segment_count = 22;
124  config.arc_segment_count = 22;
125  config.global_alpha = 1.0f;
126  config.shape_AA = AA;
127  config.line_AA = AA;
128 
129  /* convert shapes into vertices */
130  nk_buffer_init_default(&vbuf);
131  nk_buffer_init_default(&ebuf);
132  nk_convert(&sfml.ctx, &dev->cmds, &vbuf, &ebuf, &config);
133 
134  /* setup vertex buffer pointer */
135  const void* vertices = nk_buffer_memory_const(&vbuf);
136  glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp));
137  glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt));
138  glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));
139 
140  /* iterate over and execute each draw command */
141  offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf);
142  nk_draw_foreach(cmd, &sfml.ctx, &dev->cmds)
143  {
144  if(!cmd->elem_count) continue;
145  glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id);
146  glScissor(
147  (GLint)(cmd->clip_rect.x),
148  (GLint)((window_height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h))),
149  (GLint)(cmd->clip_rect.w),
150  (GLint)(cmd->clip_rect.h));
151  glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset);
152  offset += cmd->elem_count;
153  }
154  nk_clear(&sfml.ctx);
155  nk_buffer_free(&vbuf);
156  nk_buffer_free(&ebuf);
157  }
158 
159  /* default OpenGL state */
160  glDisableClientState(GL_VERTEX_ARRAY);
161  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
162  glDisableClientState(GL_COLOR_ARRAY);
163 
164  glDisable(GL_CULL_FACE);
165  glDisable(GL_DEPTH_TEST);
166  glDisable(GL_SCISSOR_TEST);
167  glDisable(GL_BLEND);
168  glDisable(GL_TEXTURE_2D);
169 
170  glBindTexture(GL_TEXTURE_2D, 0);
171  glMatrixMode(GL_TEXTURE);
172  glPopMatrix();
173  glMatrixMode(GL_MODELVIEW);
174  glPopMatrix();
175  glMatrixMode(GL_PROJECTION);
176  glPopMatrix();
177  glPopAttrib();
178 }
179 
180 static void
181 nk_sfml_clipboard_paste(nk_handle usr, struct nk_text_edit* edit)
182 {
183 #if 0
184  /* Not Implemented in SFML */
185  sf::Clipboard clipboard(sfml.window);
186  const char* text = clipboard.getText();
187 
188  if(text)
189  nk_textedit_paste(edit, text, nk_strlen(text));
190  (void)usr;
191 #endif
192 }
193 
194 static void
195 nk_sfml_clipboard_copy(nk_handle usr, const char* text, int len)
196 {
197 #if 0
198  char* str = 0;
199  (void)usr;
200  if(!len) return;
201  str = (char*)malloc((size_t)len+1);
202  if(!str) return;
203  memcpy(str, text, (size_t)len);
204  str[len] = '\0';
205 
206  /* Not Implemented in SFML */
207  sf::Clipboard clipboard(sfml.window);
208  clipboard.setText(str);
209  free(str);
210 #endif
211 }
212 
213 NK_API struct nk_context*
214 nk_sfml_init(sf::Window* window)
215 {
216  sfml.window = window;
217  nk_init_default(&sfml.ctx, 0);
218  sfml.ctx.clip.copy = nk_sfml_clipboard_copy;
219  sfml.ctx.clip.paste = nk_sfml_clipboard_paste;
220  sfml.ctx.clip.userdata = nk_handle_ptr(0);
221  nk_buffer_init_default(&sfml.ogl.cmds);
222  return &sfml.ctx;
223 }
224 
225 NK_API void
226 nk_sfml_font_stash_begin(struct nk_font_atlas** atlas)
227 {
228  nk_font_atlas_init_default(&sfml.atlas);
229  nk_font_atlas_begin(&sfml.atlas);
230  *atlas = &sfml.atlas;
231 }
232 
233 NK_API void
235 {
236  int w, h;
237  const void* img;
238  img = nk_font_atlas_bake(&sfml.atlas, &w, &h, NK_FONT_ATLAS_RGBA32);
239  nk_sfml_device_upload_atlas(img, w, h);
240  nk_font_atlas_end(&sfml.atlas, nk_handle_id((int)sfml.ogl.font_tex), &sfml.ogl.null);
241  if(sfml.atlas.default_font)
242  nk_style_set_font(&sfml.ctx, &sfml.atlas.default_font->handle);
243 }
244 
245 NK_API int
246 nk_sfml_handle_event(sf::Event* evt)
247 {
248  struct nk_context* ctx = &sfml.ctx;
249  /* optional grabbing behavior */
250  if(ctx->input.mouse.grab)
251  ctx->input.mouse.grab = 0;
252  else if(ctx->input.mouse.ungrab) {
253  int x = (int)ctx->input.mouse.prev.x;
254  int y = (int)ctx->input.mouse.prev.y;
255  sf::Mouse::setPosition(sf::Vector2i(x, y), *sfml.window);
256  ctx->input.mouse.ungrab = 0;
257  }
258  if(evt->type == sf::Event::KeyReleased || evt->type == sf::Event::KeyPressed)
259  {
260  int down = evt->type == sf::Event::KeyPressed;
261  sf::Keyboard::Key key = evt->key.code;
262  if(key == sf::Keyboard::RShift || key == sf::Keyboard::LShift)
263  nk_input_key(ctx, NK_KEY_SHIFT, down);
264  else if(key == sf::Keyboard::Delete)
265  nk_input_key(ctx, NK_KEY_DEL, down);
266  else if(key == sf::Keyboard::Return)
267  nk_input_key(ctx, NK_KEY_ENTER, down);
268  else if(key == sf::Keyboard::Tab)
269  nk_input_key(ctx, NK_KEY_TAB, down);
270  else if(key == sf::Keyboard::BackSpace)
271  nk_input_key(ctx, NK_KEY_BACKSPACE, down);
272  else if(key == sf::Keyboard::Home) {
273  nk_input_key(ctx, NK_KEY_TEXT_START, down);
274  nk_input_key(ctx, NK_KEY_SCROLL_START, down);
275  } else if(key == sf::Keyboard::End) {
276  nk_input_key(ctx, NK_KEY_TEXT_END, down);
277  nk_input_key(ctx, NK_KEY_SCROLL_END, down);
278  } else if(key == sf::Keyboard::PageDown)
279  nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down);
280  else if(key == sf::Keyboard::PageUp)
281  nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down);
282  else if(key == sf::Keyboard::Z)
283  nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
284  else if(key == sf::Keyboard::R)
285  nk_input_key(ctx, NK_KEY_TEXT_REDO, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
286  else if(key == sf::Keyboard::C)
287  nk_input_key(ctx, NK_KEY_COPY, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
288  else if(key == sf::Keyboard::V)
289  nk_input_key(ctx, NK_KEY_PASTE, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
290  else if(key == sf::Keyboard::X)
291  nk_input_key(ctx, NK_KEY_CUT, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
292  else if(key == sf::Keyboard::B)
293  nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
294  else if(key == sf::Keyboard::E)
295  nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
296  else if(key == sf::Keyboard::Up)
297  nk_input_key(ctx, NK_KEY_UP, down);
298  else if(key == sf::Keyboard::Down)
299  nk_input_key(ctx, NK_KEY_DOWN, down);
300  else if(key == sf::Keyboard::Left) {
301  if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl))
303  else nk_input_key(ctx, NK_KEY_LEFT, down);
304  } else if(key == sf::Keyboard::Right) {
305  if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl))
307  else nk_input_key(ctx, NK_KEY_RIGHT, down);
308  } else return 0;
309  return 1;
310  } else if(evt->type == sf::Event::MouseButtonPressed || evt->type == sf::Event::MouseButtonReleased) {
311  int down = evt->type == sf::Event::MouseButtonPressed;
312  const int x = evt->mouseButton.x, y = evt->mouseButton.y;
313  if(evt->mouseButton.button == sf::Mouse::Left)
314  nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
315  if(evt->mouseButton.button == sf::Mouse::Middle)
316  nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
317  if(evt->mouseButton.button == sf::Mouse::Right)
318  nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
319  else return 0;
320  return 1;
321  } else if(evt->type == sf::Event::MouseMoved) {
322  nk_input_motion(ctx, evt->mouseMove.x, evt->mouseMove.y);
323  return 1;
324  } else if(evt->type == sf::Event::TouchBegan || evt->type == sf::Event::TouchEnded) {
325  int down = evt->type == sf::Event::TouchBegan;
326  const int x = evt->touch.x, y = evt->touch.y;
327  ctx->input.mouse.pos.x = x;
328  ctx->input.mouse.pos.y = y;
329  nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
330  return 1;
331  } else if(evt->type == sf::Event::TouchMoved) {
332  if(ctx->input.mouse.grabbed) {
333  int x = (int)ctx->input.mouse.prev.x;
334  int y = (int)ctx->input.mouse.prev.y;
335  nk_input_motion(ctx, x + evt->touch.x, y + evt->touch.y);
336  } else nk_input_motion(ctx, evt->touch.x, evt->touch.y);
337  return 1;
338  } else if(evt->type == sf::Event::TextEntered) {
339  nk_input_unicode(ctx, evt->text.unicode);
340  return 1;
341  } else if(evt->type == sf::Event::MouseWheelScrolled) {
342  nk_input_scroll(ctx, nk_vec2(0,evt->mouseWheelScroll.delta));
343  return 1;
344  }
345  return 0;
346 }
347 
348 NK_API
349 void nk_sfml_shutdown(void)
350 {
351  struct nk_sfml_device* dev = &sfml.ogl;
352  nk_font_atlas_clear(&sfml.atlas);
353  nk_free(&sfml.ctx);
354  glDeleteTextures(1, &dev->font_tex);
355  nk_buffer_free(&dev->cmds);
356  memset(&sfml, 0, sizeof(sfml));
357 }
358 
359 #endif
nk_buffer_memory_const
const NK_API void * nk_buffer_memory_const(const struct nk_buffer *)
NK_KEY_CUT
@ NK_KEY_CUT
Definition: nuklear.h:744
nk_sfml_font_stash_end
NK_API void nk_sfml_font_stash_end(void)
NK_BUTTON_MIDDLE
@ NK_BUTTON_MIDDLE
Definition: nuklear.h:772
nk_buffer
Definition: nuklear.h:4118
nk_byte
NK_UINT8 nk_byte
Definition: nuklear.h:400
NK_KEY_BACKSPACE
@ NK_KEY_BACKSPACE
Definition: nuklear.h:742
NK_OFFSETOF
#define NK_OFFSETOF(st, m)
Definition: nuklear.h:5661
NK_ALIGNOF
#define NK_ALIGNOF(t)
Definition: nuklear.h:5679
nk_mouse::prev
struct nk_vec2 prev
Definition: nuklear.h:4607
nk_sfml_render
NK_API void nk_sfml_render(enum nk_anti_aliasing)
nk_vec2
NK_API struct nk_vec2 nk_vec2(float x, float y)
NK_KEY_TEXT_REDO
@ NK_KEY_TEXT_REDO
Definition: nuklear.h:759
nk_context::input
struct nk_input input
Definition: nuklear.h:5571
NK_KEY_TEXT_WORD_LEFT
@ NK_KEY_TEXT_WORD_LEFT
Definition: nuklear.h:761
nk_input::mouse
struct nk_mouse mouse
Definition: nuklear.h:4627
nk_anti_aliasing
nk_anti_aliasing
Definition: nuklear.h:1142
nk_free
NK_API void nk_free(struct nk_context *)
NK_KEY_TEXT_LINE_START
@ NK_KEY_TEXT_LINE_START
Definition: nuklear.h:754
nk_text_edit
Definition: nuklear.h:4280
NK_KEY_LEFT
@ NK_KEY_LEFT
Definition: nuklear.h:748
NK_KEY_TEXT_END
@ NK_KEY_TEXT_END
Definition: nuklear.h:757
nk_input_scroll
NK_API void nk_input_scroll(struct nk_context *, struct nk_vec2 val)
nk_vec2::y
float y
Definition: nuklear.h:459
nk_strlen
NK_API int nk_strlen(const char *str)
NK_KEY_DEL
@ NK_KEY_DEL
Definition: nuklear.h:739
nk_sfml_font_stash_begin
NK_API void nk_sfml_font_stash_begin(struct nk_font_atlas **atlas)
nk_draw_null_texture
Definition: nuklear.h:1150
nk_mouse::grab
unsigned char grab
Definition: nuklear.h:4610
NK_KEY_TEXT_WORD_RIGHT
@ NK_KEY_TEXT_WORD_RIGHT
Definition: nuklear.h:762
NK_KEY_TEXT_START
@ NK_KEY_TEXT_START
Definition: nuklear.h:756
nk_convert_config
Definition: nuklear.h:1154
NK_KEY_COPY
@ NK_KEY_COPY
Definition: nuklear.h:743
NK_KEY_TEXT_UNDO
@ NK_KEY_TEXT_UNDO
Definition: nuklear.h:758
nk_sfml_handle_event
NK_API int nk_sfml_handle_event(sf::Event *event)
nk_textedit_paste
NK_API int nk_textedit_paste(struct nk_text_edit *, char const *, int len)
nk_context
Definition: nuklear.h:5569
nk_mouse::grabbed
unsigned char grabbed
Definition: nuklear.h:4611
NK_API
#define NK_API
Definition: nuklear.h:262
nk_buffer_free
NK_API void nk_buffer_free(struct nk_buffer *)
nk_input_motion
NK_API void nk_input_motion(struct nk_context *, int x, int y)
NK_KEY_UP
@ NK_KEY_UP
Definition: nuklear.h:746
nk_input_button
NK_API void nk_input_button(struct nk_context *, enum nk_buttons, int x, int y, int down)
nk_input_key
NK_API void nk_input_key(struct nk_context *, enum nk_keys, int down)
nk_mouse::pos
struct nk_vec2 pos
Definition: nuklear.h:4606
nk_sfml_init
NK_API struct nk_context * nk_sfml_init(sf::Window *window)
NK_INTERN
#define NK_INTERN
Definition: nuklear.h:273
NK_KEY_PASTE
@ NK_KEY_PASTE
Definition: nuklear.h:745
NK_KEY_TAB
@ NK_KEY_TAB
Definition: nuklear.h:741
nk_handle_ptr
NK_API nk_handle nk_handle_ptr(void *)
nk_clear
NK_API void nk_clear(struct nk_context *)
nk_handle_id
NK_API nk_handle nk_handle_id(int)
NK_KEY_DOWN
@ NK_KEY_DOWN
Definition: nuklear.h:747
nk_input_unicode
NK_API void nk_input_unicode(struct nk_context *, nk_rune)
nk_sfml_shutdown
NK_API void nk_sfml_shutdown(void)
NK_KEY_SCROLL_END
@ NK_KEY_SCROLL_END
Definition: nuklear.h:765
NK_KEY_SCROLL_START
@ NK_KEY_SCROLL_START
Definition: nuklear.h:764
NK_BUTTON_LEFT
@ NK_BUTTON_LEFT
Definition: nuklear.h:771
NK_KEY_SCROLL_DOWN
@ NK_KEY_SCROLL_DOWN
Definition: nuklear.h:766
NK_KEY_ENTER
@ NK_KEY_ENTER
Definition: nuklear.h:740
NK_KEY_TEXT_LINE_END
@ NK_KEY_TEXT_LINE_END
Definition: nuklear.h:755
nk_handle
Definition: nuklear.h:464
NK_KEY_SHIFT
@ NK_KEY_SHIFT
Definition: nuklear.h:737
NK_BUTTON_RIGHT
@ NK_BUTTON_RIGHT
Definition: nuklear.h:773
NK_KEY_RIGHT
@ NK_KEY_RIGHT
Definition: nuklear.h:749
nk_style_set_font
NK_API void nk_style_set_font(struct nk_context *, const struct nk_user_font *)
nk_vec2::x
float x
Definition: nuklear.h:459
nk_mouse::ungrab
unsigned char ungrab
Definition: nuklear.h:4612