nuklear_allegro5.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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_ALLEGRO5_H_
  14. #define NK_ALLEGRO5_H_
  15. #include <string.h>
  16. #include <allegro5/allegro.h>
  17. #include <allegro5/allegro_image.h>
  18. #include <allegro5/allegro_primitives.h>
  19. #include <allegro5/allegro_font.h>
  20. #include <allegro5/allegro_ttf.h>
  21. typedef struct NkAllegro5Font NkAllegro5Font;
  22. NK_API struct nk_context* nk_allegro5_init(NkAllegro5Font *font, ALLEGRO_DISPLAY *dsp,
  23. unsigned int width, unsigned int height);
  24. NK_API int nk_allegro5_handle_event(ALLEGRO_EVENT *ev);
  25. NK_API void nk_allegro5_shutdown(void);
  26. NK_API void nk_allegro5_render(void);
  27. NK_API struct nk_image* nk_allegro5_create_image(const char* file_name);
  28. NK_API void nk_allegro5_del_image(struct nk_image* image);
  29. /* Fonts. We wrap normal allegro fonts in some nuklear book keeping */
  30. NK_API NkAllegro5Font* nk_allegro5_font_create_from_file(const char *file_name, int font_size, int flags);
  31. NK_API void nk_allegro5_font_del(NkAllegro5Font *font);
  32. /* NOTE : just use NkAllegro5Font instead of nk_user_font,
  33. since the former just extends the latter*/
  34. NK_API void nk_allegro5_font_set_font(NkAllegro5Font *font);
  35. #endif
  36. /*
  37. * ==============================================================
  38. *
  39. * IMPLEMENTATION
  40. *
  41. * ===============================================================
  42. */
  43. #ifdef NK_ALLEGRO5_IMPLEMENTATION
  44. #include <stdio.h>
  45. #ifndef NK_ALLEGRO5_TEXT_MAX
  46. #define NK_ALLEGRO5_TEXT_MAX 256
  47. #endif
  48. struct NkAllegro5Font {
  49. struct nk_user_font nk;
  50. ALLEGRO_FONT *font;
  51. };
  52. static struct nk_allegro5 {
  53. ALLEGRO_DISPLAY *dsp;
  54. unsigned int width;
  55. unsigned int height;
  56. int is_touch_down;
  57. int touch_down_id;
  58. struct nk_context ctx;
  59. struct nk_buffer cmds;
  60. float delta_time_seconds_last;
  61. } allegro5;
  62. NK_API struct nk_image* nk_allegro5_create_image(const char* file_name)
  63. {
  64. ALLEGRO_BITMAP *bitmap;
  65. struct nk_image *image;
  66. if (!al_init_image_addon()) {
  67. fprintf(stdout, "Unable to initialize required allegro5 image addon\n");
  68. exit(1);
  69. }
  70. bitmap = al_load_bitmap(file_name);
  71. if (bitmap == NULL) {
  72. fprintf(stdout, "Unable to load image file: %s\n", file_name);
  73. return NULL;
  74. }
  75. image = (struct nk_image*)calloc(1, sizeof(struct nk_image));
  76. image->handle.ptr = bitmap;
  77. image->w = al_get_bitmap_width(bitmap);
  78. image->h = al_get_bitmap_height(bitmap);
  79. return image;
  80. }
  81. NK_API void nk_allegro5_del_image(struct nk_image* image)
  82. {
  83. if(!image) return;
  84. al_destroy_bitmap(image->handle.ptr);
  85. free(image);
  86. }
  87. static float
  88. nk_allegro5_font_get_text_width(nk_handle handle, float height, const char *text, int len)
  89. {
  90. float width;
  91. char *str;
  92. NkAllegro5Font *font = (NkAllegro5Font*)handle.ptr;
  93. NK_UNUSED(height);
  94. if (!font || !text) {
  95. return 0;
  96. }
  97. /* We must copy into a new buffer with exact length null-terminated
  98. as nuklear uses variable size buffers and al_get_text_width doesn't
  99. accept a length, it infers length from null-termination
  100. (which is unsafe API design by allegro devs!) */
  101. str = calloc((size_t)len + 1, 1);
  102. if(!str) return 0;
  103. strncpy(str, text, len);
  104. width = al_get_text_width(font->font, str);
  105. free(str);
  106. return width;
  107. }
  108. /* Flags are identical to al_load_font() flags argument */
  109. NK_API NkAllegro5Font*
  110. nk_allegro5_font_create_from_file(const char *file_name, int font_size, int flags)
  111. {
  112. NkAllegro5Font *font;
  113. if (!al_init_image_addon()) {
  114. fprintf(stdout, "Unable to initialize required allegro5 image addon\n");
  115. exit(1);
  116. }
  117. if (!al_init_font_addon()) {
  118. fprintf(stdout, "Unable to initialize required allegro5 font addon\n");
  119. exit(1);
  120. }
  121. if (!al_init_ttf_addon()) {
  122. fprintf(stdout, "Unable to initialize required allegro5 TTF font addon\n");
  123. exit(1);
  124. }
  125. font = (NkAllegro5Font*)calloc(1, sizeof(NkAllegro5Font));
  126. font->font = al_load_font(file_name, font_size, flags);
  127. if (font->font == NULL) {
  128. fprintf(stdout, "Unable to load font file: %s\n", file_name);
  129. return NULL;
  130. }
  131. font->nk.userdata = nk_handle_ptr(font);
  132. font->nk.height = (float)al_get_font_line_height(font->font);
  133. font->nk.width = nk_allegro5_font_get_text_width;
  134. return font;
  135. }
  136. NK_API void
  137. nk_allegro5_font_set_font(NkAllegro5Font *allegro5font)
  138. {
  139. struct nk_user_font *font = &allegro5font->nk;
  140. nk_style_set_font(&allegro5.ctx, font);
  141. }
  142. NK_API void
  143. nk_allegro5_font_del(NkAllegro5Font *font)
  144. {
  145. if(!font) return;
  146. al_destroy_font(font->font);
  147. free(font);
  148. }
  149. static ALLEGRO_COLOR
  150. nk_color_to_allegro_color(struct nk_color color)
  151. {
  152. return al_map_rgba((unsigned char)color.r, (unsigned char)color.g,
  153. (unsigned char)color.b, (unsigned char)color.a);
  154. }
  155. NK_API void
  156. nk_allegro5_render()
  157. {
  158. const struct nk_command *cmd;
  159. /* Update the timer */
  160. float now = (float)al_get_time();
  161. allegro5.ctx.delta_time_seconds = now - allegro5.delta_time_seconds_last;
  162. allegro5.delta_time_seconds_last = now;
  163. al_set_target_backbuffer(allegro5.dsp);
  164. nk_foreach(cmd, &allegro5.ctx)
  165. {
  166. ALLEGRO_COLOR color;
  167. switch (cmd->type) {
  168. case NK_COMMAND_NOP: break;
  169. case NK_COMMAND_SCISSOR: {
  170. const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd;
  171. al_set_clipping_rectangle((int)s->x, (int)s->y, (int)s->w, (int)s->h);
  172. } break;
  173. case NK_COMMAND_LINE: {
  174. const struct nk_command_line *l = (const struct nk_command_line *)cmd;
  175. color = nk_color_to_allegro_color(l->color);
  176. al_draw_line((float)l->begin.x, (float)l->begin.y, (float)l->end.x,
  177. (float)l->end.y, color, (float)l->line_thickness);
  178. } break;
  179. case NK_COMMAND_RECT: {
  180. const struct nk_command_rect *r = (const struct nk_command_rect *)cmd;
  181. color = nk_color_to_allegro_color(r->color);
  182. al_draw_rounded_rectangle((float)r->x, (float)r->y, (float)(r->x + r->w),
  183. (float)(r->y + r->h), (float)r->rounding, (float)r->rounding, color,
  184. (float)r->line_thickness);
  185. } break;
  186. case NK_COMMAND_RECT_FILLED: {
  187. const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd;
  188. color = nk_color_to_allegro_color(r->color);
  189. al_draw_filled_rounded_rectangle((float)r->x, (float)r->y,
  190. (float)(r->x + r->w), (float)(r->y + r->h), (float)r->rounding,
  191. (float)r->rounding, color);
  192. } break;
  193. case NK_COMMAND_CIRCLE: {
  194. float xr, yr;
  195. const struct nk_command_circle *c = (const struct nk_command_circle *)cmd;
  196. color = nk_color_to_allegro_color(c->color);
  197. xr = (float)c->w/2;
  198. yr = (float)c->h/2;
  199. al_draw_ellipse(((float)(c->x)) + xr, ((float)c->y) + yr,
  200. xr, yr, color, (float)c->line_thickness);
  201. } break;
  202. case NK_COMMAND_CIRCLE_FILLED: {
  203. float xr, yr;
  204. const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
  205. color = nk_color_to_allegro_color(c->color);
  206. xr = (float)c->w/2;
  207. yr = (float)c->h/2;
  208. al_draw_filled_ellipse(((float)(c->x)) + xr, ((float)c->y) + yr,
  209. xr, yr, color);
  210. } break;
  211. case NK_COMMAND_TRIANGLE: {
  212. const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd;
  213. color = nk_color_to_allegro_color(t->color);
  214. al_draw_triangle((float)t->a.x, (float)t->a.y, (float)t->b.x, (float)t->b.y,
  215. (float)t->c.x, (float)t->c.y, color, (float)t->line_thickness);
  216. } break;
  217. case NK_COMMAND_TRIANGLE_FILLED: {
  218. const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd;
  219. color = nk_color_to_allegro_color(t->color);
  220. al_draw_filled_triangle((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. int i;
  225. float *vertices;
  226. const struct nk_command_polygon *p = (const struct nk_command_polygon*)cmd;
  227. vertices = calloc(p->point_count * 2, sizeof(float));
  228. color = nk_color_to_allegro_color(p->color);
  229. for (i = 0; i < p->point_count; i++) {
  230. vertices[i*2] = p->points[i].x;
  231. vertices[(i*2) + 1] = p->points[i].y;
  232. }
  233. al_draw_polyline(vertices, (2 * sizeof(float)),
  234. (int)p->point_count, ALLEGRO_LINE_JOIN_ROUND, ALLEGRO_LINE_CAP_CLOSED,
  235. color, (float)p->line_thickness, 0.0);
  236. free(vertices);
  237. } break;
  238. case NK_COMMAND_POLYGON_FILLED: {
  239. int i, j = 0;
  240. float *vertices;
  241. const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd;
  242. vertices = calloc(p->point_count * 2, sizeof(float));
  243. color = nk_color_to_allegro_color(p->color);
  244. for (i = p->point_count - 1; i >= 0; i--) {
  245. vertices[j++] = p->points[i].x;
  246. vertices[j++] = p->points[i].y;
  247. }
  248. al_draw_filled_polygon(vertices, (int)p->point_count, color);
  249. free(vertices);
  250. } break;
  251. case NK_COMMAND_POLYLINE: {
  252. int i;
  253. float *vertices;
  254. const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd;
  255. vertices = calloc(p->point_count * 2, sizeof(float));
  256. color = nk_color_to_allegro_color(p->color);
  257. for (i = 0; i < p->point_count; i++) {
  258. vertices[i*2] = p->points[i].x;
  259. vertices[(i*2) + 1] = p->points[i].y;
  260. }
  261. al_draw_polyline(vertices, (2 * sizeof(float)),
  262. (int)p->point_count, ALLEGRO_LINE_JOIN_ROUND, ALLEGRO_LINE_CAP_ROUND,
  263. color, (float)p->line_thickness, 0.0);
  264. free(vertices);
  265. } break;
  266. case NK_COMMAND_TEXT: {
  267. NkAllegro5Font *font;
  268. const struct nk_command_text *t = (const struct nk_command_text*)cmd;
  269. color = nk_color_to_allegro_color(t->foreground);
  270. font = (NkAllegro5Font*)t->font->userdata.ptr;
  271. al_draw_text(font->font,
  272. color, (float)t->x, (float)t->y, 0,
  273. (const char*)t->string);
  274. } break;
  275. case NK_COMMAND_CURVE: {
  276. float points[8];
  277. const struct nk_command_curve *q = (const struct nk_command_curve *)cmd;
  278. color = nk_color_to_allegro_color(q->color);
  279. points[0] = (float)q->begin.x;
  280. points[1] = (float)q->begin.y;
  281. points[2] = (float)q->ctrl[0].x;
  282. points[3] = (float)q->ctrl[0].y;
  283. points[4] = (float)q->ctrl[1].x;
  284. points[5] = (float)q->ctrl[1].y;
  285. points[6] = (float)q->end.x;
  286. points[7] = (float)q->end.y;
  287. al_draw_spline(points, color, (float)q->line_thickness);
  288. } break;
  289. case NK_COMMAND_ARC: {
  290. const struct nk_command_arc *a = (const struct nk_command_arc *)cmd;
  291. color = nk_color_to_allegro_color(a->color);
  292. al_draw_pieslice((float)a->cx, (float)a->cy, (float)a->r, a->a[0],
  293. a->a[1], color, (float)a->line_thickness);
  294. } break;
  295. case NK_COMMAND_ARC_FILLED: {
  296. const struct nk_command_arc_filled *a = (const struct nk_command_arc_filled *)cmd;
  297. color = nk_color_to_allegro_color(a->color);
  298. al_draw_filled_pieslice((float)a->cx, (float)a->cy, (float)a->r, a->a[0],
  299. a->a[1], color);
  300. } break;
  301. case NK_COMMAND_IMAGE: {
  302. const struct nk_command_image *i = (const struct nk_command_image *)cmd;
  303. nk_ushort
  304. x = i->img.region[0],
  305. y = i->img.region[1],
  306. w = i->img.region[2],
  307. h = i->img.region[3];
  308. if(w == 0 && h == 0)
  309. {
  310. x = i->x; y = i->y; w = i->w; h = i->h;
  311. }
  312. al_draw_scaled_bitmap(i->img.handle.ptr,
  313. x, y, w, h, i->x, i->y, i->w, i->h, 0);
  314. } break;
  315. case NK_COMMAND_RECT_MULTI_COLOR:
  316. default: break;
  317. }
  318. }
  319. nk_clear(&allegro5.ctx);
  320. }
  321. NK_API int
  322. nk_allegro5_handle_event(ALLEGRO_EVENT *ev)
  323. {
  324. struct nk_context *ctx = &allegro5.ctx;
  325. switch (ev->type) {
  326. case ALLEGRO_EVENT_DISPLAY_RESIZE: {
  327. allegro5.width = (unsigned int)ev->display.width;
  328. allegro5.height = (unsigned int)ev->display.height;
  329. al_acknowledge_resize(ev->display.source);
  330. return 1;
  331. } break;
  332. case ALLEGRO_EVENT_MOUSE_AXES: {
  333. nk_input_motion(ctx, ev->mouse.x, ev->mouse.y);
  334. if (ev->mouse.dz != 0) {
  335. nk_input_scroll(ctx, nk_vec2(0,(float)ev->mouse.dz / al_get_mouse_wheel_precision()));
  336. }
  337. return 1;
  338. } break;
  339. case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN:
  340. case ALLEGRO_EVENT_MOUSE_BUTTON_UP: {
  341. int button = NK_BUTTON_LEFT;
  342. if (ev->mouse.button == 2) {
  343. button = NK_BUTTON_RIGHT;
  344. }
  345. else if (ev->mouse.button == 3) {
  346. button = NK_BUTTON_MIDDLE;
  347. }
  348. nk_input_button(ctx, button, ev->mouse.x, ev->mouse.y, ev->type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN);
  349. return 1;
  350. } break;
  351. /* This essentially converts touch events to mouse events */
  352. case ALLEGRO_EVENT_TOUCH_BEGIN:
  353. case ALLEGRO_EVENT_TOUCH_END: {
  354. /* We only acknowledge one touch at a time. Otherwise, each touch
  355. would be manipulating multiple nuklear elements, as if there
  356. were multiple mouse cursors */
  357. if (allegro5.is_touch_down && allegro5.touch_down_id != ev->touch.id) {
  358. return 0;
  359. }
  360. if (ev->type == ALLEGRO_EVENT_TOUCH_BEGIN) {
  361. allegro5.is_touch_down = 1;
  362. allegro5.touch_down_id = ev->touch.id;
  363. /* FIXME: This is a hack to properly simulate
  364. touches as a mouse with nuklear. If you instantly jump
  365. from one place to another without an nk_input_end(), it
  366. confuses the nuklear state. nuklear expects smooth mouse
  367. movements, which is unlike a touch screen */
  368. nk_input_motion(ctx, (int)ev->touch.x, (int)ev->touch.y);
  369. nk_input_end(ctx);
  370. nk_input_begin(ctx);
  371. }
  372. else {
  373. allegro5.is_touch_down = 0;
  374. allegro5.touch_down_id = -1;
  375. }
  376. nk_input_button(ctx, NK_BUTTON_LEFT, (int)ev->touch.x, (int)ev->touch.y, ev->type == ALLEGRO_EVENT_TOUCH_BEGIN);
  377. return 1;
  378. } break;
  379. case ALLEGRO_EVENT_TOUCH_MOVE: {
  380. /* Only acknowledge movements of a single touch, we are
  381. simulating a mouse cursor */
  382. if (!allegro5.is_touch_down || allegro5.touch_down_id != ev->touch.id) {
  383. return 0;
  384. }
  385. nk_input_motion(ctx, (int)ev->touch.x, (int)ev->touch.y);
  386. return 1;
  387. } break;
  388. case ALLEGRO_EVENT_KEY_DOWN:
  389. case ALLEGRO_EVENT_KEY_UP: {
  390. int kc = ev->keyboard.keycode;
  391. int down = ev->type == ALLEGRO_EVENT_KEY_DOWN;
  392. if (kc == ALLEGRO_KEY_LSHIFT || kc == ALLEGRO_KEY_RSHIFT) nk_input_key(ctx, NK_KEY_SHIFT, down);
  393. else if (kc == ALLEGRO_KEY_DELETE) nk_input_key(ctx, NK_KEY_DEL, down);
  394. else if (kc == ALLEGRO_KEY_ENTER || kc == ALLEGRO_KEY_PAD_ENTER) nk_input_key(ctx, NK_KEY_ENTER, down);
  395. else if (kc == ALLEGRO_KEY_TAB) nk_input_key(ctx, NK_KEY_TAB, down);
  396. else if (kc == ALLEGRO_KEY_LEFT) nk_input_key(ctx, NK_KEY_LEFT, down);
  397. else if (kc == ALLEGRO_KEY_RIGHT) nk_input_key(ctx, NK_KEY_RIGHT, down);
  398. else if (kc == ALLEGRO_KEY_UP) nk_input_key(ctx, NK_KEY_UP, down);
  399. else if (kc == ALLEGRO_KEY_DOWN) nk_input_key(ctx, NK_KEY_DOWN, down);
  400. else if (kc == ALLEGRO_KEY_BACKSPACE) nk_input_key(ctx, NK_KEY_BACKSPACE, down);
  401. else if (kc == ALLEGRO_KEY_ESCAPE) nk_input_key(ctx, NK_KEY_TEXT_RESET_MODE, down);
  402. else if (kc == ALLEGRO_KEY_PGUP) nk_input_key(ctx, NK_KEY_SCROLL_UP, down);
  403. else if (kc == ALLEGRO_KEY_PGDN) nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down);
  404. else if (kc == ALLEGRO_KEY_HOME) {
  405. nk_input_key(ctx, NK_KEY_TEXT_START, down);
  406. nk_input_key(ctx, NK_KEY_SCROLL_START, down);
  407. } else if (kc == ALLEGRO_KEY_END) {
  408. nk_input_key(ctx, NK_KEY_TEXT_END, down);
  409. nk_input_key(ctx, NK_KEY_SCROLL_END, down);
  410. }
  411. return 1;
  412. } break;
  413. case ALLEGRO_EVENT_KEY_CHAR: {
  414. int kc = ev->keyboard.keycode;
  415. int control_mask = (ev->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL) ||
  416. (ev->keyboard.modifiers & ALLEGRO_KEYMOD_COMMAND);
  417. if (kc == ALLEGRO_KEY_C && control_mask) {
  418. nk_input_key(ctx, NK_KEY_COPY, 1);
  419. } else if (kc == ALLEGRO_KEY_V && control_mask) {
  420. nk_input_key(ctx, NK_KEY_PASTE, 1);
  421. } else if (kc == ALLEGRO_KEY_X && control_mask) {
  422. nk_input_key(ctx, NK_KEY_CUT, 1);
  423. } else if (kc == ALLEGRO_KEY_Z && control_mask) {
  424. nk_input_key(ctx, NK_KEY_TEXT_UNDO, 1);
  425. } else if (kc == ALLEGRO_KEY_R && control_mask) {
  426. nk_input_key(ctx, NK_KEY_TEXT_REDO, 1);
  427. } else if (kc == ALLEGRO_KEY_A && control_mask) {
  428. nk_input_key(ctx, NK_KEY_TEXT_SELECT_ALL, 1);
  429. } else {
  430. if (kc != ALLEGRO_KEY_BACKSPACE &&
  431. kc != ALLEGRO_KEY_LEFT &&
  432. kc != ALLEGRO_KEY_RIGHT &&
  433. kc != ALLEGRO_KEY_UP &&
  434. kc != ALLEGRO_KEY_DOWN &&
  435. kc != ALLEGRO_KEY_HOME &&
  436. kc != ALLEGRO_KEY_DELETE &&
  437. kc != ALLEGRO_KEY_ENTER &&
  438. kc != ALLEGRO_KEY_END &&
  439. kc != ALLEGRO_KEY_ESCAPE &&
  440. kc != ALLEGRO_KEY_PGDN &&
  441. kc != ALLEGRO_KEY_PGUP) {
  442. nk_input_unicode(ctx, ev->keyboard.unichar);
  443. }
  444. }
  445. return 1;
  446. } break;
  447. default: return 0; break;
  448. }
  449. }
  450. NK_INTERN void
  451. nk_allegro5_clipboard_paste(nk_handle usr, struct nk_text_edit *edit)
  452. {
  453. char *text = al_get_clipboard_text(allegro5.dsp);
  454. if (text) nk_textedit_paste(edit, text, nk_strlen(text));
  455. (void)usr;
  456. al_free(text);
  457. }
  458. NK_INTERN void
  459. nk_allegro5_clipboard_copy(nk_handle usr, const char *text, int len)
  460. {
  461. char *str = 0;
  462. (void)usr;
  463. if (!len) return;
  464. str = calloc((size_t)len + 1, 1);
  465. if (!str) return;
  466. strncpy(str, text, len);
  467. al_set_clipboard_text(allegro5.dsp, str);
  468. free(str);
  469. }
  470. NK_API struct nk_context*
  471. nk_allegro5_init(NkAllegro5Font *allegro5font, ALLEGRO_DISPLAY *dsp,
  472. unsigned int width, unsigned int height)
  473. {
  474. struct nk_user_font *font;
  475. if (!al_init_primitives_addon()) {
  476. fprintf(stdout, "Unable to initialize required allegro5 primitives addon\n");
  477. exit(1);
  478. }
  479. font = &allegro5font->nk;
  480. allegro5.dsp = dsp;
  481. allegro5.width = width;
  482. allegro5.height = height;
  483. allegro5.is_touch_down = 0;
  484. allegro5.touch_down_id = -1;
  485. allegro5.delta_time_seconds_last = (float)al_get_time();
  486. nk_init_default(&allegro5.ctx, font);
  487. allegro5.ctx.clip.copy = nk_allegro5_clipboard_copy;
  488. allegro5.ctx.clip.paste = nk_allegro5_clipboard_paste;
  489. allegro5.ctx.clip.userdata = nk_handle_ptr(0);
  490. return &allegro5.ctx;
  491. }
  492. NK_API
  493. void nk_allegro5_shutdown(void)
  494. {
  495. nk_free(&allegro5.ctx);
  496. memset(&allegro5, 0, sizeof(allegro5));
  497. }
  498. #endif /* NK_ALLEGRO5_IMPLEMENTATION */