main.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #include <SDL2/SDL.h>
  2. #include <stdio.h>
  3. #include "renderer.h"
  4. #include "microui.h"
  5. static char logbuf[64000];
  6. static int logbuf_updated = 0;
  7. static float bg[3] = { 90, 95, 100 };
  8. static void write_log(const char *text) {
  9. if (logbuf[0]) { strcat(logbuf, "\n"); }
  10. strcat(logbuf, text);
  11. logbuf_updated = 1;
  12. }
  13. static void test_window(mu_Context *ctx) {
  14. /* do window */
  15. if (mu_begin_window(ctx, "Demo Window", mu_rect(40, 40, 300, 450))) {
  16. mu_Container *win = mu_get_current_container(ctx);
  17. win->rect.w = mu_max(win->rect.w, 240);
  18. win->rect.h = mu_max(win->rect.h, 300);
  19. /* window info */
  20. if (mu_header(ctx, "Window Info")) {
  21. mu_Container *win = mu_get_current_container(ctx);
  22. char buf[64];
  23. mu_layout_row(ctx, 2, (int[]) { 54, -1 }, 0);
  24. mu_label(ctx,"Position:");
  25. sprintf(buf, "%d, %d", win->rect.x, win->rect.y); mu_label(ctx, buf);
  26. mu_label(ctx, "Size:");
  27. sprintf(buf, "%d, %d", win->rect.w, win->rect.h); mu_label(ctx, buf);
  28. }
  29. /* labels + buttons */
  30. if (mu_header_ex(ctx, "Test Buttons", MU_OPT_EXPANDED)) {
  31. mu_layout_row(ctx, 3, (int[]) { 86, -110, -1 }, 0);
  32. mu_label(ctx, "Test buttons 1:");
  33. if (mu_button(ctx, "Button 1")) { write_log("Pressed button 1"); }
  34. if (mu_button(ctx, "Button 2")) { write_log("Pressed button 2"); }
  35. mu_label(ctx, "Test buttons 2:");
  36. if (mu_button(ctx, "Button 3")) { write_log("Pressed button 3"); }
  37. if (mu_button(ctx, "Popup")) { mu_open_popup(ctx, "Test Popup"); }
  38. if (mu_begin_popup(ctx, "Test Popup")) {
  39. mu_button(ctx, "Hello");
  40. mu_button(ctx, "World");
  41. mu_end_popup(ctx);
  42. }
  43. }
  44. /* tree */
  45. if (mu_header_ex(ctx, "Tree and Text", MU_OPT_EXPANDED)) {
  46. mu_layout_row(ctx, 2, (int[]) { 140, -1 }, 0);
  47. mu_layout_begin_column(ctx);
  48. if (mu_begin_treenode(ctx, "Test 1")) {
  49. if (mu_begin_treenode(ctx, "Test 1a")) {
  50. mu_label(ctx, "Hello");
  51. mu_label(ctx, "world");
  52. mu_end_treenode(ctx);
  53. }
  54. if (mu_begin_treenode(ctx, "Test 1b")) {
  55. if (mu_button(ctx, "Button 1")) { write_log("Pressed button 1"); }
  56. if (mu_button(ctx, "Button 2")) { write_log("Pressed button 2"); }
  57. mu_end_treenode(ctx);
  58. }
  59. mu_end_treenode(ctx);
  60. }
  61. if (mu_begin_treenode(ctx, "Test 2")) {
  62. mu_layout_row(ctx, 2, (int[]) { 54, 54 }, 0);
  63. if (mu_button(ctx, "Button 3")) { write_log("Pressed button 3"); }
  64. if (mu_button(ctx, "Button 4")) { write_log("Pressed button 4"); }
  65. if (mu_button(ctx, "Button 5")) { write_log("Pressed button 5"); }
  66. if (mu_button(ctx, "Button 6")) { write_log("Pressed button 6"); }
  67. mu_end_treenode(ctx);
  68. }
  69. if (mu_begin_treenode(ctx, "Test 3")) {
  70. static int checks[3] = { 1, 0, 1 };
  71. mu_checkbox(ctx, "Checkbox 1", &checks[0]);
  72. mu_checkbox(ctx, "Checkbox 2", &checks[1]);
  73. mu_checkbox(ctx, "Checkbox 3", &checks[2]);
  74. mu_end_treenode(ctx);
  75. }
  76. mu_layout_end_column(ctx);
  77. mu_layout_begin_column(ctx);
  78. mu_layout_row(ctx, 1, (int[]) { -1 }, 0);
  79. mu_text(ctx, "Lorem ipsum dolor sit amet, consectetur adipiscing "
  80. "elit. Maecenas lacinia, sem eu lacinia molestie, mi risus faucibus "
  81. "ipsum, eu varius magna felis a nulla.");
  82. mu_layout_end_column(ctx);
  83. }
  84. /* background color sliders */
  85. if (mu_header_ex(ctx, "Background Color", MU_OPT_EXPANDED)) {
  86. mu_layout_row(ctx, 2, (int[]) { -78, -1 }, 74);
  87. /* sliders */
  88. mu_layout_begin_column(ctx);
  89. mu_layout_row(ctx, 2, (int[]) { 46, -1 }, 0);
  90. mu_label(ctx, "Red:"); mu_slider(ctx, &bg[0], 0, 255);
  91. mu_label(ctx, "Green:"); mu_slider(ctx, &bg[1], 0, 255);
  92. mu_label(ctx, "Blue:"); mu_slider(ctx, &bg[2], 0, 255);
  93. mu_layout_end_column(ctx);
  94. /* color preview */
  95. mu_Rect r = mu_layout_next(ctx);
  96. mu_draw_rect(ctx, r, mu_color(bg[0], bg[1], bg[2], 255));
  97. char buf[32];
  98. sprintf(buf, "#%02X%02X%02X", (int) bg[0], (int) bg[1], (int) bg[2]);
  99. mu_draw_control_text(ctx, buf, r, MU_COLOR_TEXT, MU_OPT_ALIGNCENTER);
  100. }
  101. mu_end_window(ctx);
  102. }
  103. }
  104. static void log_window(mu_Context *ctx) {
  105. if (mu_begin_window(ctx, "Log Window", mu_rect(350, 40, 300, 200))) {
  106. /* output text panel */
  107. mu_layout_row(ctx, 1, (int[]) { -1 }, -25);
  108. mu_begin_panel(ctx, "Log Output");
  109. mu_Container *panel = mu_get_current_container(ctx);
  110. mu_layout_row(ctx, 1, (int[]) { -1 }, -1);
  111. mu_text(ctx, logbuf);
  112. mu_end_panel(ctx);
  113. if (logbuf_updated) {
  114. panel->scroll.y = panel->content_size.y;
  115. logbuf_updated = 0;
  116. }
  117. /* input textbox + submit button */
  118. static char buf[128];
  119. int submitted = 0;
  120. mu_layout_row(ctx, 2, (int[]) { -70, -1 }, 0);
  121. if (mu_textbox(ctx, buf, sizeof(buf)) & MU_RES_SUBMIT) {
  122. mu_set_focus(ctx, ctx->last_id);
  123. submitted = 1;
  124. }
  125. if (mu_button(ctx, "Submit")) { submitted = 1; }
  126. if (submitted) {
  127. write_log(buf);
  128. buf[0] = '\0';
  129. }
  130. mu_end_window(ctx);
  131. }
  132. }
  133. static int uint8_slider(mu_Context *ctx, unsigned char *value, int low, int high) {
  134. static float tmp;
  135. mu_push_id(ctx, &value, sizeof(value));
  136. tmp = *value;
  137. int res = mu_slider_ex(ctx, &tmp, low, high, 0, "%.0f", MU_OPT_ALIGNCENTER);
  138. *value = tmp;
  139. mu_pop_id(ctx);
  140. return res;
  141. }
  142. static void style_window(mu_Context *ctx) {
  143. static struct { const char *label; int idx; } colors[] = {
  144. { "text:", MU_COLOR_TEXT },
  145. { "border:", MU_COLOR_BORDER },
  146. { "windowbg:", MU_COLOR_WINDOWBG },
  147. { "titlebg:", MU_COLOR_TITLEBG },
  148. { "titletext:", MU_COLOR_TITLETEXT },
  149. { "panelbg:", MU_COLOR_PANELBG },
  150. { "button:", MU_COLOR_BUTTON },
  151. { "buttonhover:", MU_COLOR_BUTTONHOVER },
  152. { "buttonfocus:", MU_COLOR_BUTTONFOCUS },
  153. { "base:", MU_COLOR_BASE },
  154. { "basehover:", MU_COLOR_BASEHOVER },
  155. { "basefocus:", MU_COLOR_BASEFOCUS },
  156. { "scrollbase:", MU_COLOR_SCROLLBASE },
  157. { "scrollthumb:", MU_COLOR_SCROLLTHUMB },
  158. { NULL }
  159. };
  160. if (mu_begin_window(ctx, "Style Editor", mu_rect(350, 250, 300, 240))) {
  161. int sw = mu_get_current_container(ctx)->body.w * 0.14;
  162. mu_layout_row(ctx, 6, (int[]) { 80, sw, sw, sw, sw, -1 }, 0);
  163. for (int i = 0; colors[i].label; i++) {
  164. mu_label(ctx, colors[i].label);
  165. uint8_slider(ctx, &ctx->style->colors[i].r, 0, 255);
  166. uint8_slider(ctx, &ctx->style->colors[i].g, 0, 255);
  167. uint8_slider(ctx, &ctx->style->colors[i].b, 0, 255);
  168. uint8_slider(ctx, &ctx->style->colors[i].a, 0, 255);
  169. mu_draw_rect(ctx, mu_layout_next(ctx), ctx->style->colors[i]);
  170. }
  171. mu_end_window(ctx);
  172. }
  173. }
  174. static void process_frame(mu_Context *ctx) {
  175. mu_begin(ctx);
  176. style_window(ctx);
  177. log_window(ctx);
  178. test_window(ctx);
  179. mu_end(ctx);
  180. }
  181. static const char button_map[256] = {
  182. [ SDL_BUTTON_LEFT & 0xff ] = MU_MOUSE_LEFT,
  183. [ SDL_BUTTON_RIGHT & 0xff ] = MU_MOUSE_RIGHT,
  184. [ SDL_BUTTON_MIDDLE & 0xff ] = MU_MOUSE_MIDDLE,
  185. };
  186. static const char key_map[256] = {
  187. [ SDLK_LSHIFT & 0xff ] = MU_KEY_SHIFT,
  188. [ SDLK_RSHIFT & 0xff ] = MU_KEY_SHIFT,
  189. [ SDLK_LCTRL & 0xff ] = MU_KEY_CTRL,
  190. [ SDLK_RCTRL & 0xff ] = MU_KEY_CTRL,
  191. [ SDLK_LALT & 0xff ] = MU_KEY_ALT,
  192. [ SDLK_RALT & 0xff ] = MU_KEY_ALT,
  193. [ SDLK_RETURN & 0xff ] = MU_KEY_RETURN,
  194. [ SDLK_BACKSPACE & 0xff ] = MU_KEY_BACKSPACE,
  195. };
  196. static int text_width(mu_Font font, const char *text, int len) {
  197. if (len == -1) { len = strlen(text); }
  198. return r_get_text_width(text, len);
  199. }
  200. static int text_height(mu_Font font) {
  201. return r_get_text_height();
  202. }
  203. int main(int argc, char **argv) {
  204. /* init SDL and renderer */
  205. SDL_Init(SDL_INIT_EVERYTHING);
  206. r_init();
  207. /* init microui */
  208. mu_Context *ctx = malloc(sizeof(mu_Context));
  209. mu_init(ctx);
  210. ctx->text_width = text_width;
  211. ctx->text_height = text_height;
  212. /* main loop */
  213. for (;;) {
  214. /* handle SDL events */
  215. SDL_Event e;
  216. while (SDL_PollEvent(&e)) {
  217. switch (e.type) {
  218. case SDL_QUIT: exit(EXIT_SUCCESS); break;
  219. case SDL_MOUSEMOTION: mu_input_mousemove(ctx, e.motion.x, e.motion.y); break;
  220. case SDL_MOUSEWHEEL: mu_input_scroll(ctx, 0, e.wheel.y * -30); break;
  221. case SDL_TEXTINPUT: mu_input_text(ctx, e.text.text); break;
  222. case SDL_MOUSEBUTTONDOWN:
  223. case SDL_MOUSEBUTTONUP: {
  224. int b = button_map[e.button.button & 0xff];
  225. if (b && e.type == SDL_MOUSEBUTTONDOWN) { mu_input_mousedown(ctx, e.button.x, e.button.y, b); }
  226. if (b && e.type == SDL_MOUSEBUTTONUP) { mu_input_mouseup(ctx, e.button.x, e.button.y, b); }
  227. break;
  228. }
  229. case SDL_KEYDOWN:
  230. case SDL_KEYUP: {
  231. int c = key_map[e.key.keysym.sym & 0xff];
  232. if (c && e.type == SDL_KEYDOWN) { mu_input_keydown(ctx, c); }
  233. if (c && e.type == SDL_KEYUP) { mu_input_keyup(ctx, c); }
  234. break;
  235. }
  236. }
  237. }
  238. /* process frame */
  239. process_frame(ctx);
  240. /* render */
  241. r_clear(mu_color(bg[0], bg[1], bg[2], 255));
  242. mu_Command *cmd = NULL;
  243. while (mu_next_command(ctx, &cmd)) {
  244. switch (cmd->type) {
  245. case MU_COMMAND_TEXT: r_draw_text(cmd->text.str, cmd->text.pos, cmd->text.color); break;
  246. case MU_COMMAND_RECT: r_draw_rect(cmd->rect.rect, cmd->rect.color); break;
  247. case MU_COMMAND_ICON: r_draw_icon(cmd->icon.id, cmd->icon.rect, cmd->icon.color); break;
  248. case MU_COMMAND_CLIP: r_set_clip_rect(cmd->clip.rect); break;
  249. }
  250. }
  251. r_present();
  252. }
  253. return 0;
  254. }