nuklear_sfml.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  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_H_
  14. #define NK_SFML_H_
  15. #include <string>
  16. #include <SFML/Graphics.hpp>
  17. NK_API struct nk_context* nk_sfml_init(NkSFMLFont* sfmlfont, sf::RenderWindow* window, sf::View view);
  18. NK_API int nk_sfml_handle_event(sf::Event* event);
  19. NK_API void nk_sfml_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer);
  20. NK_API void nk_sfml_shutdown(void);
  21. typedef struct NkSFMLFont;
  22. NK_API NkSFMLFont* nk_sfml_font_create(const std::string& file_name, int font_size, int flags);
  23. NK_API void nk_sfml_font_delete(NkSFMLFont);
  24. NK_API void nk_sfml_font_set(NkSFMLFont);
  25. #endif
  26. /*
  27. * ==============================================================
  28. *
  29. * IMPLEMENTATION
  30. *
  31. * ===============================================================
  32. */
  33. #ifdef NK_SFML_IMPLEMENTATION
  34. sf::Shape& RoundedRectangle(float rectWidth, float rectHeight, float radius)
  35. {
  36. sf::Shape round_rect;
  37. rect->SetOutlineWidth(Outline);
  38. float a = 0.0f;
  39. float b = 0.0f;
  40. for(int i=0; i<POINTS; i++)
  41. {
  42. X+=radius/POINTS;
  43. Y=sqrt(radius*radius-X*X);
  44. rrect->AddPoint(X+x+rectWidth-radius,y-Y+radius,Col,OutlineCol);
  45. }
  46. Y=0;
  47. for(int i=0; i<POINTS; i++)
  48. {
  49. Y+=radius/POINTS;
  50. X=sqrt(radius*radius-Y*Y);
  51. rrect->AddPoint(x+rectWidth+X-radius,y+rectHeight-radius+Y,Col,OutlineCol);
  52. }
  53. X=0;
  54. for(int i=0; i<POINTS; i++)
  55. {
  56. X+=radius/POINTS;
  57. Y=sqrt(radius*radius-X*X);
  58. rrect->AddPoint(x+radius-X,y+rectHeight-radius+Y,Col,OutlineCol);
  59. }
  60. Y=0;
  61. for(int i=0; i<POINTS; i++)
  62. {
  63. Y+=radius/POINTS;
  64. X=sqrt(radius*radius-Y*Y);
  65. rrect->AddPoint(x-X+radius,y+radius-Y,Col,OutlineCol);
  66. }
  67. return *rrect;
  68. }
  69. struct NkSFMLFont
  70. {
  71. struct nk_user_font nk;
  72. int height;
  73. sf::Font font;
  74. };
  75. static struct nk_sfml
  76. {
  77. sf::RenderWindow* window;
  78. sf::View view;
  79. struct nk_context ctx;
  80. struct nk_buffer cmds;
  81. } sfml;
  82. NK_API NkSFMLFont*
  83. nk_sfml_font_create(const std::string& file_name)
  84. {
  85. NkSFMLFont* font = (NkSFMLFont*)calloc(1, sizeof(NkSFMLFont));
  86. if(!font->font.loadFromFile(file_name))
  87. {
  88. fprintf(stdout, "Unable to load font file: %s\n", file_name);
  89. return NULL;
  90. }
  91. // I really need to think of a better way of doing this
  92. sf::Text text("abjdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", font->font);
  93. font->height = text.getGlobalBounds().height;
  94. return font;
  95. }
  96. static float
  97. nk_sfml_font_get_text_width(nk_handle handle, float height, const char* string, int len)
  98. {
  99. NkSFMLFont* font = (NkSFMLFont*)handle.ptr;
  100. if(!font || !string)
  101. return 0;
  102. sf::Text sfmltext(font->font, string);
  103. //char strcpy[len + 1];
  104. //strncpy((char*)&strcpy, text, len);
  105. //strcpy[len] = '\0';
  106. return sfmltext.getGlobalBounds().width;
  107. }
  108. NK_API void
  109. nk_sfml_font_set(NkSFMLFont* sfmlfont)
  110. {
  111. struct nk_user_font* font = &sfmlfont->nk;
  112. font->userdata = nk_handle_ptr(sfmlfont);
  113. font->height = (float)sfmlfont->height;
  114. font->width = nk_sfml_font_get_text_width;
  115. nk_style_set_font(&sfml.ctx, font);
  116. }
  117. NK_API void
  118. nk_sfml_font_del(NkSFMLFont* font)
  119. {
  120. if(!font)
  121. return;
  122. free(font);
  123. }
  124. static sf::Color
  125. nk_color_to_sfml(struct nk_color color)
  126. {
  127. return sf::Color(color.r, color.g, color.b, color.a);
  128. }
  129. NK_API void
  130. nk_sfml_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer)
  131. {
  132. const struct nk_command *cmd;
  133. nk_foreach(cmd, &sfml.ctx)
  134. {
  135. sf::Color color;
  136. switch (cmd->type)
  137. {
  138. case NK_COMMAND_NOP: break;
  139. case NK_COMMAND_SCISSOR:
  140. {
  141. const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
  142. //sf::RenderTexture clip_tex((unsigned int)s->x, (unsigned int)s->y);
  143. //sf::Sprite clip;
  144. sf::View view;
  145. view.setCenter(s->x, s->y);
  146. view.setSize(s->w, s->h);
  147. sfml.window->setView(view);
  148. //al_set_clipping_rectangle((int)s->x, (int)s->y, (int)s->w, (int)s->h);
  149. } break;
  150. case NK_COMMAND_LINE:
  151. {
  152. const struct nk_command_line *l = (const struct nk_command_line *)cmd;
  153. color = nk_color_to_sfml(l->color);
  154. sf::Vertex line[] =
  155. {
  156. sf::Vertex(sf::Vector2f((float)l->begin.x - l->line_thickness, (float)l->begin.y + l->line_thickness), color),
  157. sf::Vertex(sf::Vector2f((float)l->begin.x + l->line_thickness, (float)l->begin.y - l->line_thickness), color),
  158. sf::Vertex(sf::Vector2f((float)l->end.x + l->line_thickness, (float)l->end.y - l->line_thickness), color),
  159. sf::Vertex(sf::Vector2f((float)l->end.x - l->line_thickness, (float)l->end.y + l->line_thickness), color)
  160. };
  161. sfml.window->draw(line, sf::Quads);
  162. } break;
  163. case NK_COMMAND_RECT:
  164. {
  165. const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
  166. color = nk_color_to_sfml(l->color);
  167. sf::RectangleShape rect;
  168. rect.setSize(sf::Vector2f(()))
  169. sfml.window->draw(line, sf::Quads);
  170. color = nk_color_to_sfml(r->color);
  171. al_draw_rounded_rectangle(
  172. (float)r->x, (float)r->y, (float)(r->x + r->w),
  173. (float)(r->y + r->h), (float)r->rounding, (float)r->rounding, color,
  174. (float)r->line_thickness);
  175. } break;
  176. case NK_COMMAND_RECT_FILLED:
  177. {
  178. const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
  179. color = nk_color_to_sfml(r->color);
  180. al_draw_filled_rounded_rectangle(
  181. (float)r->x, (float)r->y,
  182. (float)(r->x + r->w), (float)(r->y + r->h), (float)r->rounding,
  183. (float)r->rounding, color);
  184. } break;
  185. case NK_COMMAND_CIRCLE:
  186. {
  187. const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
  188. color = nk_color_to_sfml(c->color);
  189. float xr, yr;
  190. xr = (float)c->w/2;
  191. yr = (float)c->h/2;
  192. al_draw_ellipse(
  193. ((float)(c->x)) + xr, ((float)c->y) + yr,
  194. xr, yr, color, (float)c->line_thickness);
  195. } break;
  196. case NK_COMMAND_CIRCLE_FILLED:
  197. {
  198. const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
  199. color = nk_color_to_sfml(c->color);
  200. float xr, yr;
  201. xr = (float)c->w/2;
  202. yr = (float)c->h/2;
  203. al_draw_filled_ellipse(
  204. ((float)(c->x)) + xr, ((float)c->y) + yr,
  205. xr, yr, color);
  206. } break;
  207. case NK_COMMAND_TRIANGLE:
  208. {
  209. const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
  210. color = nk_color_to_sfml(t->color);
  211. al_draw_triangle(
  212. (float)t->a.x, (float)t->a.y, (float)t->b.x, (float)t->b.y,
  213. (float)t->c.x, (float)t->c.y, color, (float)t->line_thickness);
  214. } break;
  215. case NK_COMMAND_TRIANGLE_FILLED:
  216. {
  217. const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
  218. color = nk_color_to_sfml(t->color);
  219. al_draw_filled_triangle(
  220. (float)t->a.x, (float)t->a.y, (float)t->b.x,
  221. (float)t->b.y, (float)t->c.x, (float)t->c.y, color);
  222. } break;
  223. case NK_COMMAND_POLYGON:
  224. {
  225. const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd;
  226. color = nk_color_to_sfml(p->color);
  227. int i;
  228. float vertices[p->point_count * 2];
  229. for (i = 0; i < p->point_count; i++)
  230. {
  231. vertices[i*2] = p->points[i].x;
  232. vertices[(i*2) + 1] = p->points[i].y;
  233. }
  234. al_draw_polyline(
  235. (const float*)&vertices, (2 * sizeof(float)),
  236. (int)p->point_count, ALLEGRO_LINE_JOIN_ROUND, ALLEGRO_LINE_CAP_CLOSED,
  237. color, (float)p->line_thickness, 0.0);
  238. } break;
  239. case NK_COMMAND_POLYGON_FILLED:
  240. {
  241. const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
  242. color = nk_color_to_sfml(p->color);
  243. int i;
  244. float vertices[p->point_count * 2];
  245. for (i = 0; i < p->point_count; i++)
  246. {
  247. vertices[i*2] = p->points[i].x;
  248. vertices[(i*2) + 1] = p->points[i].y;
  249. }
  250. al_draw_filled_polygon((const float*)&vertices, (int)p->point_count, color);
  251. } break;
  252. case NK_COMMAND_POLYLINE:
  253. {
  254. const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
  255. color = nk_color_to_sfml(p->color);
  256. int i;
  257. float vertices[p->point_count * 2];
  258. for (i = 0; i < p->point_count; i++)
  259. {
  260. vertices[i*2] = p->points[i].x;
  261. vertices[(i*2) + 1] = p->points[i].y;
  262. }
  263. al_draw_polyline(
  264. (const float*)&vertices, (2 * sizeof(float)),
  265. (int)p->point_count, ALLEGRO_LINE_JOIN_ROUND, ALLEGRO_LINE_CAP_ROUND,
  266. color, (float)p->line_thickness, 0.0);
  267. } break;
  268. case NK_COMMAND_TEXT:
  269. {
  270. const struct nk_command_text *t = (const struct nk_command_text*)cmd;
  271. color = nk_color_to_sfml(t->foreground);
  272. NkAllegro5Font *font = (NkAllegro5Font*)t->font->userdata.ptr;
  273. al_draw_text(
  274. font->font,
  275. color, (float)t->x, (float)t->y, 0,
  276. (const char*)t->string);
  277. } break;
  278. case NK_COMMAND_CURVE:
  279. {
  280. const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
  281. color = nk_color_to_sfml(q->color);
  282. float points[8];
  283. points[0] = (float)q->begin.x;
  284. points[1] = (float)q->begin.y;
  285. points[2] = (float)q->ctrl[0].x;
  286. points[3] = (float)q->ctrl[0].y;
  287. points[4] = (float)q->ctrl[1].x;
  288. points[5] = (float)q->ctrl[1].y;
  289. points[6] = (float)q->end.x;
  290. points[7] = (float)q->end.y;
  291. al_draw_spline(points, color, (float)q->line_thickness);
  292. } break;
  293. case NK_COMMAND_ARC:
  294. {
  295. const struct nk_command_arc *a = (const struct nk_command_arc *)cmd;
  296. color = nk_color_to_sfml(a->color);
  297. al_draw_arc(
  298. (float)a->cx, (float)a->cy, (float)a->r, a->a[0],
  299. a->a[1], color, (float)a->line_thickness);
  300. } break;
  301. case NK_COMMAND_RECT_MULTI_COLOR:
  302. case NK_COMMAND_IMAGE:
  303. case NK_COMMAND_ARC_FILLED:
  304. default: break;
  305. }
  306. }
  307. nk_clear(&allegro5.ctx);
  308. }
  309. static void
  310. nk_sfml_clipboard_paste(nk_handle usr, struct nk_text_edit* edit)
  311. {
  312. /* Not Implemented in SFML
  313. sf::Clipboard clipboard(sfml.window);
  314. const char* text = clipboard.getText();
  315. if(text)
  316. nk_textedit_paste(edit, text, nk_strlen(text));
  317. (void)usr;
  318. */
  319. }
  320. static void
  321. nk_sfml_clipboard_copy(nk_handle usr, const char* text, int len)
  322. {
  323. char* str = 0;
  324. (void)usr;
  325. if(!len)
  326. return;
  327. str = (char*)malloc((size_t)len+1);
  328. if(!str)
  329. return;
  330. memcpy(str, text, (size_t)len);
  331. str[len] = '\0';
  332. /* Not Implemented in SFML
  333. sf::Clipboard clipboard(sfml.window);
  334. clipboard.setText(str);
  335. */
  336. free(str);
  337. }
  338. NK_API struct nk_context*
  339. nk_sfml_init(NkSFMLFont* sfmlfont, sf::RenderWindow* window, sf::View view)
  340. {
  341. struct nk_user_font* font = &sfmlfont->nk;
  342. font->userdata = nk_handle_ptr(sfmlfont);
  343. font->height = (float)sfmlfont->height;
  344. font->width = nk_sfml_get_text_width;
  345. sfml.window = window;
  346. sfml.view = view;
  347. nk_init_default(&sfml.ctx, font);
  348. sfml.ctx.clip.copy = nk_sfml_clipboard_copy;
  349. sfml.ctx.clip.paste = nk_sfml_clipboard_paste;
  350. sfml.ctx.clip.userdata = nk_handle_ptr(0);
  351. return &sfml.ctx;
  352. }
  353. NK_API int
  354. nk_sfml_handle_event(sf::Event* event)
  355. {
  356. struct nk_context* ctx = &sfml.ctx;
  357. /* optional grabbing behavior */
  358. if(ctx->input.mouse.grab)
  359. {
  360. sfml.window->setMouseCursorGrabbed(true);
  361. ctx->input.mouse.grab = 0;
  362. }
  363. else if(ctx->input.mouse.ungrab)
  364. {
  365. int x = (int)ctx->input.mouse.prev.x;
  366. int y = (int)ctx->input.mouse.prev.y;
  367. sfml.window->setMouseCursorGrabbed(false);
  368. sf::Mouse::setPosition(sf::Vector2i(x, y));
  369. ctx->input.mouse.ungrab = 0;
  370. }
  371. if(event->type == sf::Event::KeyReleased || event->type == sf::Event::KeyPressed)
  372. {
  373. int down = event->type == sf::Event::KeyPressed;
  374. sf::Keyboard::Key key = event->key.code;
  375. if(key == sf::Keyboard::RShift || key == sf::Keyboard::LShift)
  376. nk_input_key(ctx, NK_KEY_SHIFT, down);
  377. else if(key == sf::Keyboard::Delete)
  378. nk_input_key(ctx, NK_KEY_DEL, down);
  379. else if(key == sf::Keyboard::Return)
  380. nk_input_key(ctx, NK_KEY_ENTER, down);
  381. else if(key == sf::Keyboard::Tab)
  382. nk_input_key(ctx, NK_KEY_TAB, down);
  383. else if(key == sf::Keyboard::BackSpace)
  384. nk_input_key(ctx, NK_KEY_BACKSPACE, down);
  385. else if(key == sf::Keyboard::Home)
  386. {
  387. nk_input_key(ctx, NK_KEY_TEXT_START, down);
  388. nk_input_key(ctx, NK_KEY_SCROLL_START, down);
  389. }
  390. else if(key == sf::Keyboard::End)
  391. {
  392. nk_input_key(ctx, NK_KEY_TEXT_END, down);
  393. nk_input_key(ctx, NK_KEY_SCROLL_END, down);
  394. }
  395. else if(key == sf::Keyboard::PageDown)
  396. nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down);
  397. else if(key == sf::Keyboard::PageUp)
  398. nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down);
  399. else if(key == sf::Keyboard::Z)
  400. nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
  401. else if(key == sf::Keyboard::R)
  402. nk_input_key(ctx, NK_KEY_TEXT_REDO, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
  403. else if(key == sf::Keyboard::C)
  404. nk_input_key(ctx, NK_KEY_COPY, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
  405. else if(key == sf::Keyboard::V)
  406. nk_input_key(ctx, NK_KEY_PASTE, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
  407. else if(key == sf::Keyboard::X)
  408. nk_input_key(ctx, NK_KEY_CUT, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
  409. else if(key == sf::Keyboard::B)
  410. nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
  411. else if(key == sf::Keyboard::E)
  412. nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && sf::Keyboard::isKeyPressed(sf::Keyboard::LControl));
  413. else if(key == sf::Keyboard::Up)
  414. nk_input_key(ctx, NK_KEY_UP, down);
  415. else if(key == sf::Keyboard::Down)
  416. nk_input_key(ctx, NK_KEY_DOWN, down);
  417. else if(key == sf::Keyboard::Left)
  418. {
  419. if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl))
  420. nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down);
  421. else
  422. nk_input_key(ctx, NK_KEY_LEFT, down);
  423. }
  424. else if(key == sf::Keyboard::Right)
  425. {
  426. if(sf::Keyboard::isKeyPressed(sf::Keyboard::LControl))
  427. nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down);
  428. else
  429. nk_input_key(ctx, NK_KEY_RIGHT, down);
  430. }
  431. else return 0;
  432. return 1;
  433. }
  434. else if(event->type == sf::Event::MouseButtonPressed || event->type == sf::Event::MouseButtonReleased)
  435. {
  436. int down = event->type == sf::Event::MouseButtonPressed;
  437. const int x = event->mouseButton.x;
  438. const int y = event->mouseButton.y;
  439. if(event->mouseButton.button == sf::Mouse::Left)
  440. nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
  441. if(event->mouseButton.button == sf::Mouse::Middle)
  442. nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down);
  443. if(event->mouseButton.button == sf::Mouse::Right)
  444. nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down);
  445. else
  446. return 0;
  447. return 1;
  448. }
  449. else if(event->type == sf::Event::MouseMoved)
  450. {
  451. if(ctx->input.mouse.grabbed)
  452. {
  453. int x = (int)ctx->input.mouse.prev.x + event->mouseMove.x;
  454. int y = (int)ctx->input.mouse.prev.y + event->mouseMove.y;
  455. nk_input_motion(ctx, x, y);
  456. }
  457. else
  458. nk_input_motion(ctx, event->mouseMove.x, event->mouseMove.y);
  459. return 1;
  460. }
  461. /* For Android*/
  462. else if(event->type == sf::Event::TouchBegan || event->type == sf::Event::TouchEnded)
  463. {
  464. int down = event->type == sf::Event::TouchBegan;
  465. const int x = event->touch.x;
  466. const int y = event->touch.y;
  467. nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down);
  468. return 1;
  469. }
  470. else if(event->type == sf::Event::TouchMoved)
  471. {
  472. if(ctx->input.mouse.grabbed)
  473. {
  474. int x = (int)ctx->input.mouse.prev.x;
  475. int y = (int)ctx->input.mouse.prev.y;
  476. nk_input_motion(ctx, x + event->touch.x, y + event->touch.y);
  477. }
  478. else
  479. nk_input_motion(ctx, event->touch.x, event->touch.y);
  480. return 1;
  481. }
  482. else if(event->type == sf::Event::TextEntered)
  483. {
  484. nk_input_unicode(ctx, event->text.unicode);
  485. return 1;
  486. }
  487. else if(event->type == sf::Event::MouseWheelScrolled)
  488. {
  489. nk_input_scroll(ctx, event->mouseWheelScroll.delta);
  490. return 1;
  491. }
  492. return 0;
  493. }
  494. NK_API
  495. void nk_sfml_shutdown(void)
  496. {
  497. nk_free(&sfml.ctx);
  498. memset(&sfml, 0, sizeof(sfml));
  499. }
  500. #endif