ref: 9bcef8453a0197d571290b6ea8b5c593c3d6e9d2
parent: 6f5f943b97fd091996911d67ff0c862ee4c33fd7
author: Sigrid Haflínudóttir <[email protected]>
date: Wed Jan 1 11:30:36 EST 2020
take platform-specific parts of the demo out to separate files
--- a/demo/build.sh
+++ b/demo/build.sh
@@ -1,3 +1,3 @@
-#!/bin/bash
-gcc main.c renderer.c ../src/microui.c -I../src\
- -Wall -std=c11 -pedantic -lSDL2 -lGL -lm -O3 -g
+#!/usr/bin/env bash
+gcc common.c sdl2.c renderer_gl.c ../src/microui.c -I../src\
+ -Wall -Wextra -std=c11 -pedantic -lSDL2 -lGL -lm -O3 -g
--- /dev/null
+++ b/demo/common.c
@@ -1,0 +1,229 @@
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+
+
+static char logbuf[64000];
+static int logbuf_updated = 0;
+
+float bg[3] = { 90, 95, 100 };
+
+
+static void write_log(const char *text) {
+ if (logbuf[0]) { strcat(logbuf, "\n"); }
+ strcat(logbuf, text);
+ logbuf_updated = 1;
+}
+
+
+static void test_window(mu_Context *ctx) {
+ static mu_Container window;
+
+ /* init window manually so we can set its position and size */
+ if (!window.inited) {
+ mu_init_window(ctx, &window, 0);
+ window.rect = mu_rect(40, 40, 300, 450);
+ }
+
+ /* limit window to minimum size */
+ window.rect.w = mu_max(window.rect.w, 240);
+ window.rect.h = mu_max(window.rect.h, 300);
+
+
+ /* do window */
+ if (mu_begin_window(ctx, &window, "Demo Window")) {
+
+ /* window info */
+ static int show_info = 0;
+ if (mu_header(ctx, &show_info, "Window Info")) {
+ char buf[64];
+ mu_layout_row(ctx, 2, (int[]) { 54, -1 }, 0);
+ mu_label(ctx,"Position:");
+ sprintf(buf, "%d, %d", window.rect.x, window.rect.y); mu_label(ctx, buf);
+ mu_label(ctx, "Size:");
+ sprintf(buf, "%d, %d", window.rect.w, window.rect.h); mu_label(ctx, buf);
+ }
+
+ /* labels + buttons */
+ static int show_buttons = 1;
+ if (mu_header(ctx, &show_buttons, "Test Buttons")) {
+ mu_layout_row(ctx, 3, (int[]) { 86, -110, -1 }, 0);
+ mu_label(ctx, "Test buttons 1:");
+ if (mu_button(ctx, "Button 1")) { write_log("Pressed button 1"); }
+ if (mu_button(ctx, "Button 2")) { write_log("Pressed button 2"); }
+ mu_label(ctx, "Test buttons 2:");
+ if (mu_button(ctx, "Button 3")) { write_log("Pressed button 3"); }
+ if (mu_button(ctx, "Button 4")) { write_log("Pressed button 4"); }
+ }
+
+ /* tree */
+ static int show_tree = 1;
+ if (mu_header(ctx, &show_tree, "Tree and Text")) {
+ mu_layout_row(ctx, 2, (int[]) { 140, -1 }, 0);
+ mu_layout_begin_column(ctx);
+ static int states[8];
+ if (mu_begin_treenode(ctx, &states[0], "Test 1")) {
+ if (mu_begin_treenode(ctx, &states[1], "Test 1a")) {
+ mu_label(ctx, "Hello");
+ mu_label(ctx, "world");
+ mu_end_treenode(ctx);
+ }
+ if (mu_begin_treenode(ctx, &states[2], "Test 1b")) {
+ if (mu_button(ctx, "Button 1")) { write_log("Pressed button 1"); }
+ if (mu_button(ctx, "Button 2")) { write_log("Pressed button 2"); }
+ mu_end_treenode(ctx);
+ }
+ mu_end_treenode(ctx);
+ }
+ if (mu_begin_treenode(ctx, &states[3], "Test 2")) {
+ mu_layout_row(ctx, 2, (int[]) { 54, 54 }, 0);
+ if (mu_button(ctx, "Button 3")) { write_log("Pressed button 3"); }
+ if (mu_button(ctx, "Button 4")) { write_log("Pressed button 4"); }
+ if (mu_button(ctx, "Button 5")) { write_log("Pressed button 5"); }
+ if (mu_button(ctx, "Button 6")) { write_log("Pressed button 6"); }
+ mu_end_treenode(ctx);
+ }
+ if (mu_begin_treenode(ctx, &states[4], "Test 3")) {
+ static int checks[3] = { 1, 0, 1 };
+ mu_checkbox(ctx, &checks[0], "Checkbox 1");
+ mu_checkbox(ctx, &checks[1], "Checkbox 2");
+ mu_checkbox(ctx, &checks[2], "Checkbox 3");
+ mu_end_treenode(ctx);
+ }
+ mu_layout_end_column(ctx);
+
+ mu_layout_begin_column(ctx);
+ mu_layout_row(ctx, 1, (int[]) { -1 }, 0);
+ mu_text(ctx, "Lorem ipsum dolor sit amet, consectetur adipiscing "
+ "elit. Maecenas lacinia, sem eu lacinia molestie, mi risus faucibus "
+ "ipsum, eu varius magna felis a nulla.");
+ mu_layout_end_column(ctx);
+ }
+
+ /* background color sliders */
+ static int show_sliders = 1;
+ if (mu_header(ctx, &show_sliders, "Background Color")) {
+ mu_layout_row(ctx, 2, (int[]) { -78, -1 }, 74);
+ /* sliders */
+ mu_layout_begin_column(ctx);
+ mu_layout_row(ctx, 2, (int[]) { 46, -1 }, 0);
+ mu_label(ctx, "Red:"); mu_slider(ctx, &bg[0], 0, 255);
+ mu_label(ctx, "Green:"); mu_slider(ctx, &bg[1], 0, 255);
+ mu_label(ctx, "Blue:"); mu_slider(ctx, &bg[2], 0, 255);
+ mu_layout_end_column(ctx);
+ /* color preview */
+ mu_Rect r = mu_layout_next(ctx);
+ mu_draw_rect(ctx, r, mu_color(bg[0], bg[1], bg[2], 255));
+ char buf[32];
+ sprintf(buf, "#%02X%02X%02X", (int) bg[0], (int) bg[1], (int) bg[2]);
+ mu_draw_control_text(ctx, buf, r, MU_COLOR_TEXT, MU_OPT_ALIGNCENTER);
+ }
+
+ mu_end_window(ctx);
+ }
+}
+
+
+static void log_window(mu_Context *ctx) {
+ static mu_Container window;
+
+ /* init window manually so we can set its position and size */
+ if (!window.inited) {
+ mu_init_window(ctx, &window, 0);
+ window.rect = mu_rect(350, 40, 300, 200);
+ }
+
+ if (mu_begin_window(ctx, &window, "Log Window")) {
+
+ /* output text panel */
+ static mu_Container panel;
+ mu_layout_row(ctx, 1, (int[]) { -1 }, -28);
+ mu_begin_panel(ctx, &panel);
+ mu_layout_row(ctx, 1, (int[]) { -1 }, -1);
+ mu_text(ctx, logbuf);
+ mu_end_panel(ctx);
+ if (logbuf_updated) {
+ panel.scroll.y = panel.content_size.y;
+ logbuf_updated = 0;
+ }
+
+ /* input textbox + submit button */
+ static char buf[128];
+ int submitted = 0;
+ mu_layout_row(ctx, 2, (int[]) { -70, -1 }, 0);
+ if (mu_textbox(ctx, buf, sizeof(buf)) & MU_RES_SUBMIT) {
+ mu_set_focus(ctx, ctx->last_id);
+ submitted = 1;
+ }
+ if (mu_button(ctx, "Submit")) { submitted = 1; }
+ if (submitted) {
+ write_log(buf);
+ buf[0] = '\0';
+ }
+
+ mu_end_window(ctx);
+ }
+}
+
+
+static int uint8_slider(mu_Context *ctx, unsigned char *value, int low, int high) {
+ static float tmp;
+ mu_push_id(ctx, &value, sizeof(value));
+ tmp = *value;
+ int res = mu_slider_ex(ctx, &tmp, low, high, 0, "%.0f", MU_OPT_ALIGNCENTER);
+ *value = tmp;
+ mu_pop_id(ctx);
+ return res;
+}
+
+
+static void style_window(mu_Context *ctx) {
+ static mu_Container window;
+
+ /* init window manually so we can set its position and size */
+ if (!window.inited) {
+ mu_init_window(ctx, &window, 0);
+ window.rect = mu_rect(350, 250, 300, 240);
+ }
+
+ static struct { const char *label; int idx; } colors[] = {
+ { "text:", MU_COLOR_TEXT },
+ { "border:", MU_COLOR_BORDER },
+ { "windowbg:", MU_COLOR_WINDOWBG },
+ { "titlebg:", MU_COLOR_TITLEBG },
+ { "titletext:", MU_COLOR_TITLETEXT },
+ { "panelbg:", MU_COLOR_PANELBG },
+ { "button:", MU_COLOR_BUTTON },
+ { "buttonhover:", MU_COLOR_BUTTONHOVER },
+ { "buttonfocus:", MU_COLOR_BUTTONFOCUS },
+ { "base:", MU_COLOR_BASE },
+ { "basehover:", MU_COLOR_BASEHOVER },
+ { "basefocus:", MU_COLOR_BASEFOCUS },
+ { "scrollbase:", MU_COLOR_SCROLLBASE },
+ { "scrollthumb:", MU_COLOR_SCROLLTHUMB },
+ { NULL }
+ };
+
+ if (mu_begin_window(ctx, &window, "Style Editor")) {
+ int sw = mu_get_container(ctx)->body.w * 0.14;
+ mu_layout_row(ctx, 6, (int[]) { 80, sw, sw, sw, sw, -1 }, 0);
+ for (int i = 0; colors[i].label; i++) {
+ mu_label(ctx, colors[i].label);
+ uint8_slider(ctx, &ctx->style->colors[i].r, 0, 255);
+ uint8_slider(ctx, &ctx->style->colors[i].g, 0, 255);
+ uint8_slider(ctx, &ctx->style->colors[i].b, 0, 255);
+ uint8_slider(ctx, &ctx->style->colors[i].a, 0, 255);
+ mu_draw_rect(ctx, mu_layout_next(ctx), ctx->style->colors[i]);
+ }
+ mu_end_window(ctx);
+ }
+}
+
+
+void process_frame(mu_Context *ctx) {
+ mu_begin(ctx);
+ test_window(ctx);
+ log_window(ctx);
+ style_window(ctx);
+ mu_end(ctx);
+}
--- /dev/null
+++ b/demo/common.h
@@ -1,0 +1,11 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+#include "microui.h"
+#include "renderer.h"
+
+extern float bg[3];
+
+void process_frame(mu_Context *ctx);
+
+#endif
--- a/demo/main.c
+++ /dev/null
@@ -1,320 +1,0 @@
-#include <SDL2/SDL.h>
-#include <stdio.h>
-#include "renderer.h"
-#include "microui.h"
-
-
-static char logbuf[64000];
-static int logbuf_updated = 0;
-static float bg[3] = { 90, 95, 100 };
-
-
-static void write_log(const char *text) {
- if (logbuf[0]) { strcat(logbuf, "\n"); }
- strcat(logbuf, text);
- logbuf_updated = 1;
-}
-
-
-static void test_window(mu_Context *ctx) {
- static mu_Container window;
-
- /* init window manually so we can set its position and size */
- if (!window.inited) {
- mu_init_window(ctx, &window, 0);
- window.rect = mu_rect(40, 40, 300, 450);
- }
-
- /* limit window to minimum size */
- window.rect.w = mu_max(window.rect.w, 240);
- window.rect.h = mu_max(window.rect.h, 300);
-
-
- /* do window */
- if (mu_begin_window(ctx, &window, "Demo Window")) {
-
- /* window info */
- static int show_info = 0;
- if (mu_header(ctx, &show_info, "Window Info")) {
- char buf[64];
- mu_layout_row(ctx, 2, (int[]) { 54, -1 }, 0);
- mu_label(ctx,"Position:");
- sprintf(buf, "%d, %d", window.rect.x, window.rect.y); mu_label(ctx, buf);
- mu_label(ctx, "Size:");
- sprintf(buf, "%d, %d", window.rect.w, window.rect.h); mu_label(ctx, buf);
- }
-
- /* labels + buttons */
- static int show_buttons = 1;
- if (mu_header(ctx, &show_buttons, "Test Buttons")) {
- mu_layout_row(ctx, 3, (int[]) { 86, -110, -1 }, 0);
- mu_label(ctx, "Test buttons 1:");
- if (mu_button(ctx, "Button 1")) { write_log("Pressed button 1"); }
- if (mu_button(ctx, "Button 2")) { write_log("Pressed button 2"); }
- mu_label(ctx, "Test buttons 2:");
- if (mu_button(ctx, "Button 3")) { write_log("Pressed button 3"); }
- if (mu_button(ctx, "Button 4")) { write_log("Pressed button 4"); }
- }
-
- /* tree */
- static int show_tree = 1;
- if (mu_header(ctx, &show_tree, "Tree and Text")) {
- mu_layout_row(ctx, 2, (int[]) { 140, -1 }, 0);
- mu_layout_begin_column(ctx);
- static int states[8];
- if (mu_begin_treenode(ctx, &states[0], "Test 1")) {
- if (mu_begin_treenode(ctx, &states[1], "Test 1a")) {
- mu_label(ctx, "Hello");
- mu_label(ctx, "world");
- mu_end_treenode(ctx);
- }
- if (mu_begin_treenode(ctx, &states[2], "Test 1b")) {
- if (mu_button(ctx, "Button 1")) { write_log("Pressed button 1"); }
- if (mu_button(ctx, "Button 2")) { write_log("Pressed button 2"); }
- mu_end_treenode(ctx);
- }
- mu_end_treenode(ctx);
- }
- if (mu_begin_treenode(ctx, &states[3], "Test 2")) {
- mu_layout_row(ctx, 2, (int[]) { 54, 54 }, 0);
- if (mu_button(ctx, "Button 3")) { write_log("Pressed button 3"); }
- if (mu_button(ctx, "Button 4")) { write_log("Pressed button 4"); }
- if (mu_button(ctx, "Button 5")) { write_log("Pressed button 5"); }
- if (mu_button(ctx, "Button 6")) { write_log("Pressed button 6"); }
- mu_end_treenode(ctx);
- }
- if (mu_begin_treenode(ctx, &states[4], "Test 3")) {
- static int checks[3] = { 1, 0, 1 };
- mu_checkbox(ctx, &checks[0], "Checkbox 1");
- mu_checkbox(ctx, &checks[1], "Checkbox 2");
- mu_checkbox(ctx, &checks[2], "Checkbox 3");
- mu_end_treenode(ctx);
- }
- mu_layout_end_column(ctx);
-
- mu_layout_begin_column(ctx);
- mu_layout_row(ctx, 1, (int[]) { -1 }, 0);
- mu_text(ctx, "Lorem ipsum dolor sit amet, consectetur adipiscing "
- "elit. Maecenas lacinia, sem eu lacinia molestie, mi risus faucibus "
- "ipsum, eu varius magna felis a nulla.");
- mu_layout_end_column(ctx);
- }
-
- /* background color sliders */
- static int show_sliders = 1;
- if (mu_header(ctx, &show_sliders, "Background Color")) {
- mu_layout_row(ctx, 2, (int[]) { -78, -1 }, 74);
- /* sliders */
- mu_layout_begin_column(ctx);
- mu_layout_row(ctx, 2, (int[]) { 46, -1 }, 0);
- mu_label(ctx, "Red:"); mu_slider(ctx, &bg[0], 0, 255);
- mu_label(ctx, "Green:"); mu_slider(ctx, &bg[1], 0, 255);
- mu_label(ctx, "Blue:"); mu_slider(ctx, &bg[2], 0, 255);
- mu_layout_end_column(ctx);
- /* color preview */
- mu_Rect r = mu_layout_next(ctx);
- mu_draw_rect(ctx, r, mu_color(bg[0], bg[1], bg[2], 255));
- char buf[32];
- sprintf(buf, "#%02X%02X%02X", (int) bg[0], (int) bg[1], (int) bg[2]);
- mu_draw_control_text(ctx, buf, r, MU_COLOR_TEXT, MU_OPT_ALIGNCENTER);
- }
-
- mu_end_window(ctx);
- }
-}
-
-
-static void log_window(mu_Context *ctx) {
- static mu_Container window;
-
- /* init window manually so we can set its position and size */
- if (!window.inited) {
- mu_init_window(ctx, &window, 0);
- window.rect = mu_rect(350, 40, 300, 200);
- }
-
- if (mu_begin_window(ctx, &window, "Log Window")) {
-
- /* output text panel */
- static mu_Container panel;
- mu_layout_row(ctx, 1, (int[]) { -1 }, -28);
- mu_begin_panel(ctx, &panel);
- mu_layout_row(ctx, 1, (int[]) { -1 }, -1);
- mu_text(ctx, logbuf);
- mu_end_panel(ctx);
- if (logbuf_updated) {
- panel.scroll.y = panel.content_size.y;
- logbuf_updated = 0;
- }
-
- /* input textbox + submit button */
- static char buf[128];
- int submitted = 0;
- mu_layout_row(ctx, 2, (int[]) { -70, -1 }, 0);
- if (mu_textbox(ctx, buf, sizeof(buf)) & MU_RES_SUBMIT) {
- mu_set_focus(ctx, ctx->last_id);
- submitted = 1;
- }
- if (mu_button(ctx, "Submit")) { submitted = 1; }
- if (submitted) {
- write_log(buf);
- buf[0] = '\0';
- }
-
- mu_end_window(ctx);
- }
-}
-
-
-static int uint8_slider(mu_Context *ctx, unsigned char *value, int low, int high) {
- static float tmp;
- mu_push_id(ctx, &value, sizeof(value));
- tmp = *value;
- int res = mu_slider_ex(ctx, &tmp, low, high, 0, "%.0f", MU_OPT_ALIGNCENTER);
- *value = tmp;
- mu_pop_id(ctx);
- return res;
-}
-
-
-static void style_window(mu_Context *ctx) {
- static mu_Container window;
-
- /* init window manually so we can set its position and size */
- if (!window.inited) {
- mu_init_window(ctx, &window, 0);
- window.rect = mu_rect(350, 250, 300, 240);
- }
-
- static struct { const char *label; int idx; } colors[] = {
- { "text:", MU_COLOR_TEXT },
- { "border:", MU_COLOR_BORDER },
- { "windowbg:", MU_COLOR_WINDOWBG },
- { "titlebg:", MU_COLOR_TITLEBG },
- { "titletext:", MU_COLOR_TITLETEXT },
- { "panelbg:", MU_COLOR_PANELBG },
- { "button:", MU_COLOR_BUTTON },
- { "buttonhover:", MU_COLOR_BUTTONHOVER },
- { "buttonfocus:", MU_COLOR_BUTTONFOCUS },
- { "base:", MU_COLOR_BASE },
- { "basehover:", MU_COLOR_BASEHOVER },
- { "basefocus:", MU_COLOR_BASEFOCUS },
- { "scrollbase:", MU_COLOR_SCROLLBASE },
- { "scrollthumb:", MU_COLOR_SCROLLTHUMB },
- { NULL }
- };
-
- if (mu_begin_window(ctx, &window, "Style Editor")) {
- int sw = mu_get_container(ctx)->body.w * 0.14;
- mu_layout_row(ctx, 6, (int[]) { 80, sw, sw, sw, sw, -1 }, 0);
- for (int i = 0; colors[i].label; i++) {
- mu_label(ctx, colors[i].label);
- uint8_slider(ctx, &ctx->style->colors[i].r, 0, 255);
- uint8_slider(ctx, &ctx->style->colors[i].g, 0, 255);
- uint8_slider(ctx, &ctx->style->colors[i].b, 0, 255);
- uint8_slider(ctx, &ctx->style->colors[i].a, 0, 255);
- mu_draw_rect(ctx, mu_layout_next(ctx), ctx->style->colors[i]);
- }
- mu_end_window(ctx);
- }
-}
-
-
-static void process_frame(mu_Context *ctx) {
- mu_begin(ctx);
- test_window(ctx);
- log_window(ctx);
- style_window(ctx);
- mu_end(ctx);
-}
-
-
-
-static const char button_map[256] = {
- [ SDL_BUTTON_LEFT & 0xff ] = MU_MOUSE_LEFT,
- [ SDL_BUTTON_RIGHT & 0xff ] = MU_MOUSE_RIGHT,
- [ SDL_BUTTON_MIDDLE & 0xff ] = MU_MOUSE_MIDDLE,
-};
-
-static const char key_map[256] = {
- [ SDLK_LSHIFT & 0xff ] = MU_KEY_SHIFT,
- [ SDLK_RSHIFT & 0xff ] = MU_KEY_SHIFT,
- [ SDLK_LCTRL & 0xff ] = MU_KEY_CTRL,
- [ SDLK_RCTRL & 0xff ] = MU_KEY_CTRL,
- [ SDLK_LALT & 0xff ] = MU_KEY_ALT,
- [ SDLK_RALT & 0xff ] = MU_KEY_ALT,
- [ SDLK_RETURN & 0xff ] = MU_KEY_RETURN,
- [ SDLK_BACKSPACE & 0xff ] = MU_KEY_BACKSPACE,
-};
-
-
-static int text_width(mu_Font font, const char *text, int len) {
- if (len == -1) { len = strlen(text); }
- return r_get_text_width(text, len);
-}
-
-static int text_height(mu_Font font) {
- return r_get_text_height();
-}
-
-
-int main(int argc, char **argv) {
- /* init SDL and renderer */
- SDL_Init(SDL_INIT_EVERYTHING);
- r_init();
-
- /* init microui */
- mu_Context *ctx = malloc(sizeof(mu_Context));
- mu_init(ctx);
- ctx->text_width = text_width;
- ctx->text_height = text_height;
-
- /* main loop */
- for (;;) {
- /* handle SDL events */
- SDL_Event e;
- while (SDL_PollEvent(&e)) {
- switch (e.type) {
- case SDL_QUIT: exit(EXIT_SUCCESS); break;
- case SDL_MOUSEMOTION: mu_input_mousemove(ctx, e.motion.x, e.motion.y); break;
- case SDL_MOUSEWHEEL: mu_input_scroll(ctx, 0, e.wheel.y * -30); break;
- case SDL_TEXTINPUT: mu_input_text(ctx, e.text.text); break;
-
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP: {
- int b = button_map[e.button.button & 0xff];
- if (b && e.type == SDL_MOUSEBUTTONDOWN) { mu_input_mousedown(ctx, e.button.x, e.button.y, b); }
- if (b && e.type == SDL_MOUSEBUTTONUP) { mu_input_mouseup(ctx, e.button.x, e.button.y, b); }
- }
-
- case SDL_KEYDOWN:
- case SDL_KEYUP: {
- int c = key_map[e.key.keysym.sym & 0xff];
- if (c && e.type == SDL_KEYDOWN) { mu_input_keydown(ctx, c); }
- if (c && e.type == SDL_KEYUP) { mu_input_keyup(ctx, c); }
- break;
- }
- }
- }
-
- /* process frame */
- process_frame(ctx);
-
- /* render */
- r_clear(mu_color(bg[0], bg[1], bg[2], 255));
- mu_Command *cmd = NULL;
- while (mu_next_command(ctx, &cmd)) {
- switch (cmd->type) {
- case MU_COMMAND_TEXT: r_draw_text(cmd->text.str, cmd->text.pos, cmd->text.color); break;
- case MU_COMMAND_RECT: r_draw_rect(cmd->rect.rect, cmd->rect.color); break;
- case MU_COMMAND_ICON: r_draw_icon(cmd->icon.id, cmd->icon.rect, cmd->icon.color); break;
- case MU_COMMAND_CLIP: r_set_clip_rect(cmd->clip.rect); break;
- }
- }
- r_present();
- }
-
- return 0;
-}
-
-
--- a/demo/renderer.c
+++ /dev/null
@@ -1,185 +1,0 @@
-#include <SDL2/SDL.h>
-#include <SDL2/SDL_opengl.h>
-#include <assert.h>
-#include "renderer.h"
-#include "atlas.inl"
-
-#define BUFFER_SIZE 16384
-
-static GLfloat tex_buf[BUFFER_SIZE * 8];
-static GLfloat vert_buf[BUFFER_SIZE * 8];
-static GLubyte color_buf[BUFFER_SIZE * 16];
-static GLuint index_buf[BUFFER_SIZE * 6];
-
-static int width = 800;
-static int height = 600;
-static int buf_idx;
-
-static SDL_Window *window;
-
-
-void r_init(void) {
- /* init SDL window */
- window = SDL_CreateWindow(
- NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
- width, height, SDL_WINDOW_OPENGL);
- SDL_GL_CreateContext(window);
-
- /* init gl */
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glDisable(GL_CULL_FACE);
- glDisable(GL_DEPTH_TEST);
- glEnable(GL_SCISSOR_TEST);
- glEnable(GL_TEXTURE_2D);
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
-
- /* init texture */
- GLuint id;
- glGenTextures(1, &id);
- glBindTexture(GL_TEXTURE_2D, id);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ATLAS_WIDTH, ATLAS_HEIGHT, 0,
- GL_ALPHA, GL_UNSIGNED_BYTE, atlas_texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- assert(glGetError() == 0);
-}
-
-
-static void flush(void) {
- if (buf_idx == 0) { return; }
-
- glViewport(0, 0, width, height);
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- glTexCoordPointer(2, GL_FLOAT, 0, tex_buf);
- glVertexPointer(2, GL_FLOAT, 0, vert_buf);
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, color_buf);
- glDrawElements(GL_TRIANGLES, buf_idx * 6, GL_UNSIGNED_INT, index_buf);
-
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
-
- buf_idx = 0;
-}
-
-
-static void push_quad(mu_Rect dst, mu_Rect src, mu_Color color) {
- if (buf_idx == BUFFER_SIZE) { flush(); }
-
- int texvert_idx = buf_idx * 8;
- int color_idx = buf_idx * 16;
- int element_idx = buf_idx * 4;
- int index_idx = buf_idx * 6;
- buf_idx++;
-
- /* update texture buffer */
- float x = src.x / (float) ATLAS_WIDTH;
- float y = src.y / (float) ATLAS_HEIGHT;
- float w = src.w / (float) ATLAS_WIDTH;
- float h = src.h / (float) ATLAS_HEIGHT;
- tex_buf[texvert_idx + 0] = x;
- tex_buf[texvert_idx + 1] = y;
- tex_buf[texvert_idx + 2] = x + w;
- tex_buf[texvert_idx + 3] = y;
- tex_buf[texvert_idx + 4] = x;
- tex_buf[texvert_idx + 5] = y + h;
- tex_buf[texvert_idx + 6] = x + w;
- tex_buf[texvert_idx + 7] = y + h;
-
- /* update vertex buffer */
- vert_buf[texvert_idx + 0] = dst.x;
- vert_buf[texvert_idx + 1] = dst.y;
- vert_buf[texvert_idx + 2] = dst.x + dst.w;
- vert_buf[texvert_idx + 3] = dst.y;
- vert_buf[texvert_idx + 4] = dst.x;
- vert_buf[texvert_idx + 5] = dst.y + dst.h;
- vert_buf[texvert_idx + 6] = dst.x + dst.w;
- vert_buf[texvert_idx + 7] = dst.y + dst.h;
-
- /* update color buffer */
- memcpy(color_buf + color_idx + 0, &color, 4);
- memcpy(color_buf + color_idx + 4, &color, 4);
- memcpy(color_buf + color_idx + 8, &color, 4);
- memcpy(color_buf + color_idx + 12, &color, 4);
-
- /* update index buffer */
- index_buf[index_idx + 0] = element_idx + 0;
- index_buf[index_idx + 1] = element_idx + 1;
- index_buf[index_idx + 2] = element_idx + 2;
- index_buf[index_idx + 3] = element_idx + 2;
- index_buf[index_idx + 4] = element_idx + 3;
- index_buf[index_idx + 5] = element_idx + 1;
-}
-
-
-void r_draw_rect(mu_Rect rect, mu_Color color) {
- push_quad(rect, atlas[ATLAS_WHITE], color);
-}
-
-
-void r_draw_text(const char *text, mu_Vec2 pos, mu_Color color) {
- mu_Rect dst = { pos.x, pos.y, 0, 0 };
- for (const char *p = text; *p; p++) {
- if ((*p & 0xc0) == 0x80) { continue; }
- int chr = mu_min((unsigned char) *p, 127);
- mu_Rect src = atlas[ATLAS_FONT + chr];
- dst.w = src.w;
- dst.h = src.h;
- push_quad(dst, src, color);
- dst.x += dst.w;
- }
-}
-
-
-void r_draw_icon(int id, mu_Rect rect, mu_Color color) {
- mu_Rect src = atlas[id];
- int x = rect.x + (rect.w - src.w) / 2;
- int y = rect.y + (rect.h - src.h) / 2;
- push_quad(mu_rect(x, y, src.w, src.h), src, color);
-}
-
-
-int r_get_text_width(const char *text, int len) {
- int res = 0;
- for (const char *p = text; *p && len--; p++) {
- if ((*p & 0xc0) == 0x80) { continue; }
- int chr = mu_min((unsigned char) *p, 127);
- res += atlas[ATLAS_FONT + chr].w;
- }
- return res;
-}
-
-
-int r_get_text_height(void) {
- return 18;
-}
-
-
-void r_set_clip_rect(mu_Rect rect) {
- flush();
- glScissor(rect.x, height - (rect.y + rect.h), rect.w, rect.h);
-}
-
-
-void r_clear(mu_Color clr) {
- flush();
- glClearColor(clr.r / 255., clr.g / 255., clr.b / 255., clr.a / 255.);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-
-void r_present(void) {
- flush();
- SDL_GL_SwapWindow(window);
-}
--- a/demo/renderer.h
+++ b/demo/renderer.h
@@ -1,14 +1,12 @@
#ifndef RENDERER_H
#define RENDERER_H
-#include "microui.h"
-
void r_init(void);
void r_draw_rect(mu_Rect rect, mu_Color color);
-void r_draw_text(const char *text, mu_Vec2 pos, mu_Color color);
+void r_draw_text(mu_Font font, const char *text, mu_Vec2 pos, mu_Color color);
void r_draw_icon(int id, mu_Rect rect, mu_Color color);
- int r_get_text_width(const char *text, int len);
- int r_get_text_height(void);
+ int r_get_text_width(mu_Font font, const char *text, int len);
+ int r_get_text_height(mu_Font font);
void r_set_clip_rect(mu_Rect rect);
void r_clear(mu_Color color);
void r_present(void);
--- /dev/null
+++ b/demo/renderer_gl.c
@@ -1,0 +1,190 @@
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_opengl.h>
+#include <assert.h>
+#include "common.h"
+#include "atlas.inl"
+
+#define BUFFER_SIZE 16384
+#define unused(x) ((void) (x))
+
+static GLfloat tex_buf[BUFFER_SIZE * 8];
+static GLfloat vert_buf[BUFFER_SIZE * 8];
+static GLubyte color_buf[BUFFER_SIZE * 16];
+static GLuint index_buf[BUFFER_SIZE * 6];
+
+static int width = 800;
+static int height = 600;
+static int buf_idx;
+
+static SDL_Window *window;
+
+
+void r_init(void) {
+ /* init SDL window */
+ window = SDL_CreateWindow(
+ NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ width, height, SDL_WINDOW_OPENGL);
+ SDL_GL_CreateContext(window);
+
+ /* init gl */
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_SCISSOR_TEST);
+ glEnable(GL_TEXTURE_2D);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ /* init texture */
+ GLuint id;
+ glGenTextures(1, &id);
+ glBindTexture(GL_TEXTURE_2D, id);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ATLAS_WIDTH, ATLAS_HEIGHT, 0,
+ GL_ALPHA, GL_UNSIGNED_BYTE, atlas_texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ assert(glGetError() == 0);
+}
+
+
+static void flush(void) {
+ if (buf_idx == 0) { return; }
+
+ glViewport(0, 0, width, height);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(0.0f, width, height, 0.0f, -1.0f, +1.0f);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ glTexCoordPointer(2, GL_FLOAT, 0, tex_buf);
+ glVertexPointer(2, GL_FLOAT, 0, vert_buf);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, color_buf);
+ glDrawElements(GL_TRIANGLES, buf_idx * 6, GL_UNSIGNED_INT, index_buf);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ buf_idx = 0;
+}
+
+
+static void push_quad(mu_Rect dst, mu_Rect src, mu_Color color) {
+ if (buf_idx == BUFFER_SIZE) { flush(); }
+
+ int texvert_idx = buf_idx * 8;
+ int color_idx = buf_idx * 16;
+ int element_idx = buf_idx * 4;
+ int index_idx = buf_idx * 6;
+ buf_idx++;
+
+ /* update texture buffer */
+ float x = src.x / (float) ATLAS_WIDTH;
+ float y = src.y / (float) ATLAS_HEIGHT;
+ float w = src.w / (float) ATLAS_WIDTH;
+ float h = src.h / (float) ATLAS_HEIGHT;
+ tex_buf[texvert_idx + 0] = x;
+ tex_buf[texvert_idx + 1] = y;
+ tex_buf[texvert_idx + 2] = x + w;
+ tex_buf[texvert_idx + 3] = y;
+ tex_buf[texvert_idx + 4] = x;
+ tex_buf[texvert_idx + 5] = y + h;
+ tex_buf[texvert_idx + 6] = x + w;
+ tex_buf[texvert_idx + 7] = y + h;
+
+ /* update vertex buffer */
+ vert_buf[texvert_idx + 0] = dst.x;
+ vert_buf[texvert_idx + 1] = dst.y;
+ vert_buf[texvert_idx + 2] = dst.x + dst.w;
+ vert_buf[texvert_idx + 3] = dst.y;
+ vert_buf[texvert_idx + 4] = dst.x;
+ vert_buf[texvert_idx + 5] = dst.y + dst.h;
+ vert_buf[texvert_idx + 6] = dst.x + dst.w;
+ vert_buf[texvert_idx + 7] = dst.y + dst.h;
+
+ /* update color buffer */
+ memcpy(color_buf + color_idx + 0, &color, 4);
+ memcpy(color_buf + color_idx + 4, &color, 4);
+ memcpy(color_buf + color_idx + 8, &color, 4);
+ memcpy(color_buf + color_idx + 12, &color, 4);
+
+ /* update index buffer */
+ index_buf[index_idx + 0] = element_idx + 0;
+ index_buf[index_idx + 1] = element_idx + 1;
+ index_buf[index_idx + 2] = element_idx + 2;
+ index_buf[index_idx + 3] = element_idx + 2;
+ index_buf[index_idx + 4] = element_idx + 3;
+ index_buf[index_idx + 5] = element_idx + 1;
+}
+
+
+void r_draw_rect(mu_Rect rect, mu_Color color) {
+ push_quad(rect, atlas[ATLAS_WHITE], color);
+}
+
+
+void r_draw_text(mu_Font font, const char *text, mu_Vec2 pos, mu_Color color) {
+ mu_Rect dst = { pos.x, pos.y, 0, 0 };
+ unused(font);
+ for (const char *p = text; *p; p++) {
+ if ((*p & 0xc0) == 0x80) { continue; }
+ int chr = mu_min((unsigned char) *p, 127);
+ mu_Rect src = atlas[ATLAS_FONT + chr];
+ dst.w = src.w;
+ dst.h = src.h;
+ push_quad(dst, src, color);
+ dst.x += dst.w;
+ }
+}
+
+
+void r_draw_icon(int id, mu_Rect rect, mu_Color color) {
+ mu_Rect src = atlas[id];
+ int x = rect.x + (rect.w - src.w) / 2;
+ int y = rect.y + (rect.h - src.h) / 2;
+ push_quad(mu_rect(x, y, src.w, src.h), src, color);
+}
+
+
+int r_get_text_width(mu_Font font, const char *text, int len) {
+ int res = 0;
+ unused(font);
+ if (len == -1) { len = strlen(text); }
+ for (const char *p = text; *p && len--; p++) {
+ if ((*p & 0xc0) == 0x80) { continue; }
+ int chr = mu_min((unsigned char) *p, 127);
+ res += atlas[ATLAS_FONT + chr].w;
+ }
+ return res;
+}
+
+
+int r_get_text_height(mu_Font font) {
+ unused(font);
+ return 18;
+}
+
+
+void r_set_clip_rect(mu_Rect rect) {
+ flush();
+ glScissor(rect.x, height - (rect.y + rect.h), rect.w, rect.h);
+}
+
+
+void r_clear(mu_Color clr) {
+ flush();
+ glClearColor(clr.r / 255., clr.g / 255., clr.b / 255., clr.a / 255.);
+ glClear(GL_COLOR_BUFFER_BIT);
+}
+
+
+void r_present(void) {
+ flush();
+ SDL_GL_SwapWindow(window);
+}
--- /dev/null
+++ b/demo/sdl2.c
@@ -1,0 +1,86 @@
+#include <SDL2/SDL.h>
+#include "common.h"
+
+#define unused(x) ((void) (x))
+
+static const char button_map[256] = {
+ [ SDL_BUTTON_LEFT & 0xff ] = MU_MOUSE_LEFT,
+ [ SDL_BUTTON_RIGHT & 0xff ] = MU_MOUSE_RIGHT,
+ [ SDL_BUTTON_MIDDLE & 0xff ] = MU_MOUSE_MIDDLE,
+};
+
+static const char key_map[256] = {
+ [ SDLK_LSHIFT & 0xff ] = MU_KEY_SHIFT,
+ [ SDLK_RSHIFT & 0xff ] = MU_KEY_SHIFT,
+ [ SDLK_LCTRL & 0xff ] = MU_KEY_CTRL,
+ [ SDLK_RCTRL & 0xff ] = MU_KEY_CTRL,
+ [ SDLK_LALT & 0xff ] = MU_KEY_ALT,
+ [ SDLK_RALT & 0xff ] = MU_KEY_ALT,
+ [ SDLK_RETURN & 0xff ] = MU_KEY_RETURN,
+ [ SDLK_BACKSPACE & 0xff ] = MU_KEY_BACKSPACE,
+};
+
+
+int main(int argc, char **argv) {
+ mu_Font dummy = {0};
+
+ unused(argc); unused(argv);
+
+ /* init SDL and renderer */
+ SDL_Init(SDL_INIT_EVERYTHING);
+ r_init();
+
+ /* init microui */
+ mu_Context *ctx = malloc(sizeof(mu_Context));
+ mu_init(ctx);
+ ctx->text_width = r_get_text_width;
+ ctx->text_height = r_get_text_height;
+
+ /* main loop */
+ for (;;) {
+ /* handle SDL events */
+ SDL_Event e;
+ while (SDL_PollEvent(&e)) {
+ switch (e.type) {
+ case SDL_QUIT: exit(EXIT_SUCCESS); break;
+ case SDL_MOUSEMOTION: mu_input_mousemove(ctx, e.motion.x, e.motion.y); break;
+ case SDL_MOUSEWHEEL: mu_input_scroll(ctx, 0, e.wheel.y * -30); break;
+ case SDL_TEXTINPUT: mu_input_text(ctx, e.text.text); break;
+
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP: {
+ int b = button_map[e.button.button & 0xff];
+ if (b && e.type == SDL_MOUSEBUTTONDOWN) { mu_input_mousedown(ctx, e.button.x, e.button.y, b); }
+ if (b && e.type == SDL_MOUSEBUTTONUP) { mu_input_mouseup(ctx, e.button.x, e.button.y, b); }
+ break;
+ }
+
+ case SDL_KEYDOWN:
+ case SDL_KEYUP: {
+ int c = key_map[e.key.keysym.sym & 0xff];
+ if (c && e.type == SDL_KEYDOWN) { mu_input_keydown(ctx, c); }
+ if (c && e.type == SDL_KEYUP) { mu_input_keyup(ctx, c); }
+ break;
+ }
+ }
+ }
+
+ /* process frame */
+ process_frame(ctx);
+
+ /* render */
+ r_clear(mu_color(bg[0], bg[1], bg[2], 255));
+ mu_Command *cmd = NULL;
+ while (mu_next_command(ctx, &cmd)) {
+ switch (cmd->type) {
+ case MU_COMMAND_TEXT: r_draw_text(dummy, cmd->text.str, cmd->text.pos, cmd->text.color); break;
+ case MU_COMMAND_RECT: r_draw_rect(cmd->rect.rect, cmd->rect.color); break;
+ case MU_COMMAND_ICON: r_draw_icon(cmd->icon.id, cmd->icon.rect, cmd->icon.color); break;
+ case MU_COMMAND_CLIP: r_set_clip_rect(cmd->clip.rect); break;
+ }
+ }
+ r_present();
+ }
+
+ return 0;
+}