major render backend rewrite for greater portability
This commit is contained in:
parent
f69689b6ce
commit
581f8e9200
138
demo/example.c
138
demo/example.c
@ -1,138 +0,0 @@
|
||||
#define MAX_BUFFER 64
|
||||
|
||||
struct demo {
|
||||
gui_char in_buf[MAX_BUFFER];
|
||||
gui_size in_len;
|
||||
gui_bool in_act;
|
||||
gui_char cmd_buf[MAX_BUFFER];
|
||||
gui_size cmd_len;
|
||||
gui_bool cmd_act;
|
||||
gui_bool check;
|
||||
gui_int option;
|
||||
gui_float slider;
|
||||
gui_size prog;
|
||||
gui_int spinner;
|
||||
gui_bool spin_act;
|
||||
gui_size item_cur;
|
||||
gui_tab tab;
|
||||
gui_group group;
|
||||
gui_shelf shelf;
|
||||
gui_size current;
|
||||
};
|
||||
|
||||
struct color_picker {
|
||||
gui_bool active[4];
|
||||
struct gui_color color;
|
||||
};
|
||||
|
||||
static char*
|
||||
ldfile(const char* path, size_t* siz)
|
||||
{
|
||||
char *buf;
|
||||
FILE *fd = fopen(path, "rb");
|
||||
if (!fd) exit(EXIT_FAILURE);
|
||||
fseek(fd, 0, SEEK_END);
|
||||
*siz = (size_t)ftell(fd);
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
buf = calloc(*siz, 1);
|
||||
fread(buf, *siz, 1, fd);
|
||||
fclose(fd);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static gui_int
|
||||
message_panel(struct gui_context *ctx, struct gui_panel *panel)
|
||||
{
|
||||
gui_int ret = -1;
|
||||
gui_begin_panel(ctx, panel, "Error", GUI_PANEL_MOVEABLE|GUI_PANEL_BORDER);
|
||||
gui_panel_layout(panel, 30, 2);
|
||||
if (gui_panel_button_text(panel, "ok", GUI_BUTTON_DEFAULT)) ret = 1;
|
||||
if (gui_panel_button_text(panel, "cancel", GUI_BUTTON_DEFAULT)) ret = 0;
|
||||
if (ret != -1) gui_panel_hide(panel);
|
||||
gui_end_panel(ctx, panel, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gui_int
|
||||
color_picker_panel(struct gui_context *ctx, struct gui_panel *panel, struct color_picker *picker)
|
||||
{
|
||||
gui_size i;
|
||||
gui_int ret = -1;
|
||||
gui_byte *ptr = &picker->color.r;
|
||||
const char str[] = "R:G:B:A:";
|
||||
gui_begin_panel(ctx, panel, "Color Picker", GUI_PANEL_MOVEABLE|GUI_PANEL_BORDER);
|
||||
gui_panel_layout(panel, 30, 3);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
gui_int ivalue;
|
||||
gui_float fvalue = (gui_float)*ptr;
|
||||
gui_panel_text(panel, &str[i*2], 2, GUI_TEXT_CENTERED);
|
||||
fvalue = gui_panel_slider(panel, 0, fvalue, 255.0f, 10.0f, GUI_HORIZONTAL);
|
||||
ivalue = (gui_int)fvalue;
|
||||
picker->active[i] = gui_panel_spinner(panel, 0, &ivalue, 255, 1, picker->active[i]);
|
||||
*ptr = (gui_byte)ivalue;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
gui_panel_layout(panel, 30, 4);
|
||||
gui_panel_seperator(panel, 1);
|
||||
if (gui_panel_button_text(panel, "ok", GUI_BUTTON_DEFAULT)) ret = 1;
|
||||
if (gui_panel_button_text(panel, "cancel", GUI_BUTTON_DEFAULT)) ret = 0;
|
||||
if (ret != -1) gui_panel_hide(panel);
|
||||
gui_end_panel(ctx, panel, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gui_bool
|
||||
demo_panel(struct gui_context *ctx, struct gui_panel *panel, struct demo *demo)
|
||||
{
|
||||
enum {PLOT, HISTO};
|
||||
const char *shelfs[] = {"Histogram", "Lines"};
|
||||
const gui_float values[] = {8.0f, 15.0f, 20.0f, 12.0f, 30.0f};
|
||||
const char *items[] = {"Fist", "Pistol", "Shotgun", "Railgun", "BFG"};
|
||||
gui_bool running;
|
||||
|
||||
running = gui_begin_panel(ctx, panel, "Demo",
|
||||
GUI_PANEL_CLOSEABLE|GUI_PANEL_MINIMIZABLE|GUI_PANEL_SCALEABLE|
|
||||
GUI_PANEL_MOVEABLE|GUI_PANEL_BORDER);
|
||||
|
||||
/* Tabs */
|
||||
gui_panel_layout(panel, 100, 1);
|
||||
gui_panel_tab_begin(panel, &demo->tab, "Difficulty");
|
||||
gui_panel_layout(&demo->tab, 30, 2);
|
||||
if (gui_panel_option(&demo->tab, "easy", demo->option == 0)) demo->option = 0;
|
||||
if (gui_panel_option(&demo->tab, "hard", demo->option == 1)) demo->option = 1;
|
||||
if (gui_panel_option(&demo->tab, "normal", demo->option == 2)) demo->option = 2;
|
||||
if (gui_panel_option(&demo->tab, "godlike", demo->option == 3)) demo->option = 3;
|
||||
gui_panel_tab_end(panel, &demo->tab);
|
||||
|
||||
/* Shelf */
|
||||
gui_panel_layout(panel, 200, 2);
|
||||
demo->current = gui_panel_shelf_begin(panel, &demo->shelf, shelfs, LEN(shelfs), demo->current);
|
||||
gui_panel_layout(&demo->shelf, 100, 1);
|
||||
if (demo->current == PLOT) {
|
||||
gui_panel_histo(&demo->shelf, values, LEN(values));
|
||||
} else {
|
||||
gui_panel_plot(&demo->shelf, values, LEN(values));
|
||||
}
|
||||
gui_panel_shelf_end(panel, &demo->shelf);
|
||||
|
||||
/* Group */
|
||||
gui_panel_group_begin(panel, &demo->group, "Options");
|
||||
gui_panel_layout(&demo->group, 30, 1);
|
||||
if (gui_panel_button_text(&demo->group, "button", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
demo->check = gui_panel_check(&demo->group, "advanced", demo->check);
|
||||
demo->slider = gui_panel_slider(&demo->group, 0, demo->slider, 10, 1.0f, GUI_HORIZONTAL);
|
||||
demo->prog = gui_panel_progress(&demo->group, demo->prog, 100, gui_true, GUI_HORIZONTAL);
|
||||
if (gui_panel_shell(&demo->group, demo->cmd_buf, &demo->cmd_len, MAX_BUFFER, &demo->cmd_act))
|
||||
fprintf(stdout, "shell executed!\n");
|
||||
demo->spin_act = gui_panel_spinner(&demo->group, 0, &demo->spinner, 1024, 10, demo->spin_act);
|
||||
demo->in_act = gui_panel_input(&demo->group, demo->in_buf, &demo->in_len, MAX_BUFFER,
|
||||
GUI_INPUT_DEFAULT, demo->in_act);
|
||||
demo->item_cur = gui_panel_selector(&demo->group, items, LEN(items), demo->item_cur);
|
||||
gui_panel_group_end(panel, &demo->group);
|
||||
|
||||
gui_end_panel(ctx, panel, NULL);
|
||||
return running;
|
||||
}
|
||||
|
302
demo/opengl.c
302
demo/opengl.c
@ -1,302 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2015
|
||||
vurtun <polygone@gmx.net>
|
||||
MIT licence
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glu.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "../gui.h"
|
||||
|
||||
/* macros */
|
||||
#define LEN(a) (sizeof(a)/sizeof(a)[0])
|
||||
#define UNUSED(v) (void)v
|
||||
#define WIN_WIDTH 800
|
||||
#define WIN_HEIGHT 600
|
||||
#define MAX_MEMORY (256 * 1024)
|
||||
#define MAX_BUFFER 64
|
||||
#define DTIME 33
|
||||
|
||||
#include "example.c"
|
||||
|
||||
static void
|
||||
delfont(struct gui_font *font)
|
||||
{
|
||||
free(font->glyphes);
|
||||
free(font);
|
||||
}
|
||||
|
||||
static struct gui_font*
|
||||
mkfont(const char *path, gui_uint font_height, gui_uint bake_height,
|
||||
gui_size range, enum gui_font_atlas_dimension dim)
|
||||
{
|
||||
gui_byte *ttf_blob;
|
||||
gui_size ttf_blob_size;
|
||||
struct gui_font_atlas atlas;
|
||||
struct gui_font *font = calloc(sizeof(struct gui_font), 1);
|
||||
|
||||
atlas.dim = dim;
|
||||
atlas.range = range;
|
||||
atlas.size = gui_font_atlas_alloc_size(atlas.dim);
|
||||
atlas.memory = calloc((gui_size)atlas.size, 1);
|
||||
|
||||
memset(font, 0, sizeof(*font));
|
||||
font->glyph_count = (gui_uint)atlas.range;
|
||||
font->glyphes = calloc(atlas.range, sizeof(struct gui_font_glyph));
|
||||
font->fallback = &font->glyphes['?'];
|
||||
font->scale = (gui_float)font_height / (gui_float)bake_height;
|
||||
font->height = (gui_float)font_height;
|
||||
|
||||
ttf_blob = (gui_byte*)ldfile(path, &ttf_blob_size);
|
||||
if (!gui_font_load(font, &atlas, bake_height, ttf_blob, ttf_blob_size))
|
||||
goto failed;
|
||||
|
||||
glGenTextures(1, &font->texture.gl);
|
||||
glBindTexture(GL_TEXTURE_2D, font->texture.gl);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dim, dim, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, atlas.memory);
|
||||
|
||||
free(atlas.memory);
|
||||
free(ttf_blob);
|
||||
return font;
|
||||
|
||||
failed:
|
||||
free(atlas.memory);
|
||||
free(ttf_blob);
|
||||
delfont(font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
key(struct gui_input *in, SDL_Event* e, gui_bool down)
|
||||
{
|
||||
SDL_Keycode code = e->key.keysym.sym;
|
||||
if (code == SDLK_LCTRL || code == SDLK_RCTRL)
|
||||
gui_input_key(in, GUI_KEY_CTRL, down);
|
||||
else if (code == SDLK_LSHIFT || code == SDLK_RSHIFT)
|
||||
gui_input_key(in, GUI_KEY_SHIFT, down);
|
||||
else if (code == SDLK_DELETE)
|
||||
gui_input_key(in, GUI_KEY_DEL, down);
|
||||
else if (code == SDLK_RETURN)
|
||||
gui_input_key(in, GUI_KEY_ENTER, down);
|
||||
else if (code == SDLK_SPACE)
|
||||
gui_input_key(in, GUI_KEY_SPACE, down);
|
||||
else if (code == SDLK_BACKSPACE)
|
||||
gui_input_key(in, GUI_KEY_BACKSPACE, down);
|
||||
}
|
||||
|
||||
static void
|
||||
button(struct gui_input *in, SDL_Event *evt, gui_bool down)
|
||||
{
|
||||
const int x = evt->button.x;
|
||||
const int y = evt->button.y;
|
||||
if (evt->button.button == SDL_BUTTON_LEFT)
|
||||
gui_input_button(in, x, y, down);
|
||||
}
|
||||
|
||||
static void
|
||||
bmotion(struct gui_input *in, SDL_Event *evt)
|
||||
{
|
||||
const gui_int x = evt->motion.x;
|
||||
const gui_int y = evt->motion.y;
|
||||
gui_input_motion(in, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
text(struct gui_input *in, SDL_Event *evt)
|
||||
{
|
||||
gui_input_char(in, (const gui_char*)evt->text.text);
|
||||
}
|
||||
|
||||
static void
|
||||
resize(SDL_Event* evt)
|
||||
{
|
||||
if (evt->window.event == SDL_WINDOWEVENT_RESIZED)
|
||||
glViewport(0, 0, evt->window.data1, evt->window.data2);
|
||||
}
|
||||
|
||||
static void
|
||||
draw(int width, int height, struct gui_draw_call_list **list, gui_size count)
|
||||
{
|
||||
gui_size i = 0;
|
||||
gui_size n = 0;
|
||||
const gui_byte *vertexes;
|
||||
const struct gui_draw_command *cmd;
|
||||
static const size_t v = sizeof(struct gui_vertex);
|
||||
static const size_t p = offsetof(struct gui_vertex, pos);
|
||||
static const size_t t = offsetof(struct gui_vertex, uv);
|
||||
static const size_t c = offsetof(struct gui_vertex, color);
|
||||
|
||||
if (!list) return;
|
||||
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
glOrtho(0.0f, width, height, 0.0f, 0.0f, 1.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
glLoadIdentity();
|
||||
|
||||
for (n = 0; n < count; ++n) {
|
||||
GLint offset = 0;
|
||||
vertexes = (const gui_char*)list[n]->vertexes;
|
||||
glVertexPointer(2, GL_FLOAT, (GLsizei)v, (const void*)(vertexes + p));
|
||||
glTexCoordPointer(2, GL_FLOAT, (GLsizei)v, (const void*)(vertexes + t));
|
||||
glColorPointer(4, GL_UNSIGNED_BYTE, (GLsizei)v, (const void*)(vertexes + c));
|
||||
|
||||
for (i = 0; i < list[n]->command_size; ++i) {
|
||||
int x,y,w,h;
|
||||
cmd = &list[n]->commands[i];
|
||||
x = (int)cmd->clip_rect.x;
|
||||
w = (int)cmd->clip_rect.w;
|
||||
h = (int)cmd->clip_rect.h;
|
||||
y = height - (int)(cmd->clip_rect.y + cmd->clip_rect.h);
|
||||
glScissor(x, y, w, h);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.gl);
|
||||
glDrawArrays(GL_TRIANGLES, offset, (GLsizei)cmd->vertex_count);
|
||||
offset += (GLint)cmd->vertex_count;
|
||||
}
|
||||
}
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int width, height;
|
||||
uint32_t dt, started;
|
||||
gui_bool running;
|
||||
SDL_Window *win;
|
||||
SDL_GLContext glContext;
|
||||
struct color_picker picker;
|
||||
struct demo demo;
|
||||
|
||||
struct gui_memory memory;
|
||||
struct gui_config config;
|
||||
struct gui_font *font;
|
||||
struct gui_input input;
|
||||
struct gui_output output;
|
||||
struct gui_context *ctx;
|
||||
struct gui_panel *panel;
|
||||
struct gui_panel *message;
|
||||
struct gui_panel *color_panel;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stdout, "missing font file path!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Window */
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
win = SDL_CreateWindow("clone", 0, 0,
|
||||
WIN_WIDTH, WIN_HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN);
|
||||
glContext = SDL_GL_CreateContext(win);
|
||||
glViewport(0, 0, WIN_WIDTH, WIN_HEIGHT);
|
||||
|
||||
/* GUI */
|
||||
memset(&demo, 0, sizeof(demo));
|
||||
memset(&picker, 0, sizeof(picker));
|
||||
demo.tab.minimized = gui_true;
|
||||
demo.spinner = 250;
|
||||
demo.slider = 2.0f;
|
||||
demo.prog = 60;
|
||||
|
||||
/* Context */
|
||||
memset(&input, 0, sizeof(input));
|
||||
memory.max_panels = 8;
|
||||
memory.max_depth = 4;
|
||||
memory.memory = calloc(MAX_MEMORY , 1);
|
||||
memory.size = MAX_MEMORY;
|
||||
memory.vertex_percentage = 0.80f;
|
||||
memory.command_percentage = 0.20f;
|
||||
ctx = gui_new(&memory, &input);
|
||||
|
||||
/* Panel */
|
||||
gui_default_config(&config);
|
||||
font = mkfont(argv[1], 12, 16, 255, GUI_ATLAS_DIM_256);
|
||||
panel = gui_panel_new(ctx, 50, 50, 500, 320, &config, font);
|
||||
message = gui_panel_new(ctx, 150, 150, 200, 100, &config, font);
|
||||
color_panel = gui_panel_new(ctx, 250, 250, 400, 235, &config, font);
|
||||
|
||||
running = gui_true;
|
||||
while (running) {
|
||||
SDL_Event ev;
|
||||
started = SDL_GetTicks();
|
||||
|
||||
gui_input_begin(&input);
|
||||
while (SDL_PollEvent(&ev)) {
|
||||
if (ev.type == SDL_WINDOWEVENT) resize(&ev);
|
||||
else if (ev.type == SDL_MOUSEMOTION) bmotion(&input, &ev);
|
||||
else if (ev.type == SDL_MOUSEBUTTONDOWN) button(&input, &ev, gui_true);
|
||||
else if (ev.type == SDL_MOUSEBUTTONUP) button(&input, &ev, gui_false);
|
||||
else if (ev.type == SDL_KEYDOWN) key( &input, &ev, gui_true);
|
||||
else if (ev.type == SDL_KEYUP) key(&input, &ev, gui_false);
|
||||
else if (ev.type == SDL_TEXTINPUT) text(&input, &ev);
|
||||
else if (ev.type == SDL_QUIT) goto cleanup;
|
||||
}
|
||||
gui_input_end(&input);
|
||||
SDL_GetWindowSize(win, &width, &height);
|
||||
|
||||
/* ------------------------- GUI --------------------------*/
|
||||
gui_begin(ctx, (gui_float)width, (gui_float)height);
|
||||
running = demo_panel(ctx, panel, &demo);
|
||||
if (message_panel(ctx, message) >= 0)
|
||||
running = gui_false;
|
||||
if (color_picker_panel(ctx, color_panel, &picker) >= 0) {
|
||||
struct gui_color c = picker.color;
|
||||
fprintf(stdout, "color picked: {%u, %u, %u, %u}\n", c.r, c.g, c.b, c.a);
|
||||
}
|
||||
gui_end(ctx, &output, NULL);
|
||||
/* ---------------------------------------------------------*/
|
||||
|
||||
/* Draw */
|
||||
glClearColor(120.0f/255.0f, 120.0f/255.0f, 120.0f/255.0f, 120.0f/255.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
draw(width, height, output.list, output.list_size);
|
||||
SDL_GL_SwapWindow(win);
|
||||
|
||||
/* Timing */
|
||||
dt = SDL_GetTicks() - started;
|
||||
if (dt < DTIME)
|
||||
SDL_Delay(DTIME - dt);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
free(memory.memory);
|
||||
delfont(font);
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
SDL_DestroyWindow(win);
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
|
494
demo/xlib.c
Normal file
494
demo/xlib.c
Normal file
@ -0,0 +1,494 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include "../gui.h"
|
||||
|
||||
/* macros */
|
||||
#define MAX_MEMORY (8 * 1024)
|
||||
#define MAX_DEPTH 8
|
||||
#define MAX_PANEL 4
|
||||
#define WIN_WIDTH 800
|
||||
#define WIN_HEIGHT 600
|
||||
#define DTIME 16
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX(a,b) ((a) < (b) ? (b) : (a))
|
||||
#define CLAMP(i,v,x) (MAX(MIN(v,x), i))
|
||||
#define LEN(a) (sizeof(a)/sizeof(a)[0])
|
||||
#define UNUSED(a) ((void)(a))
|
||||
|
||||
typedef struct XFont XFont;
|
||||
typedef struct XSurface XSurface;
|
||||
typedef struct XWindow XWindow;
|
||||
|
||||
struct XFont {
|
||||
int ascent;
|
||||
int descent;
|
||||
int height;
|
||||
XFontSet set;
|
||||
XFontStruct *xfont;
|
||||
};
|
||||
|
||||
struct XSurface {
|
||||
GC gc;
|
||||
Display *dpy;
|
||||
int screen;
|
||||
Window root;
|
||||
Drawable drawable;
|
||||
unsigned int w, h;
|
||||
};
|
||||
|
||||
struct XWindow {
|
||||
Display *dpy;
|
||||
Window root;
|
||||
Visual *vis;
|
||||
Colormap cmap;
|
||||
XWindowAttributes attr;
|
||||
XSetWindowAttributes swa;
|
||||
Window win;
|
||||
GC gc;
|
||||
int screen;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
XSurface surface;
|
||||
};
|
||||
|
||||
static void
|
||||
die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static void*
|
||||
xcalloc(size_t siz, size_t n)
|
||||
{
|
||||
void *ptr = calloc(siz, n);
|
||||
if (!ptr) die("Out of memory\n");
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static long
|
||||
timestamp(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
if (gettimeofday(&tv, NULL) < 0)
|
||||
return 0;
|
||||
return (long)((long)tv.tv_sec * 1000 + (long)tv.tv_usec/1000);
|
||||
}
|
||||
|
||||
static void
|
||||
sleep_for(long t)
|
||||
{
|
||||
struct timespec req;
|
||||
const time_t sec = (int)(t/1000);
|
||||
const long ms = t - (sec * 1000);
|
||||
req.tv_sec = sec;
|
||||
req.tv_nsec = ms * 1000000L;
|
||||
while(-1 == nanosleep(&req, &req));
|
||||
}
|
||||
|
||||
static XSurface*
|
||||
surface_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
|
||||
{
|
||||
XSurface *surface = xcalloc(1, sizeof(XSurface));
|
||||
surface->w = w;
|
||||
surface->h = h;
|
||||
surface->dpy = dpy;
|
||||
surface->screen = screen;
|
||||
surface->root = root;
|
||||
surface->gc = XCreateGC(dpy, root, 0, NULL);
|
||||
XSetLineAttributes(dpy, surface->gc, 1, LineSolid, CapButt, JoinMiter);
|
||||
surface->drawable = XCreatePixmap(dpy, root, w, h, (unsigned int)DefaultDepth(dpy, screen));
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
surface_resize(XSurface *surf, unsigned int w, unsigned int h) {
|
||||
if(!surf) return;
|
||||
surf->w = w;
|
||||
surf->h = h;
|
||||
if(surf->drawable)
|
||||
XFreePixmap(surf->dpy, surf->drawable);
|
||||
surf->drawable = XCreatePixmap(surf->dpy, surf->root, w, h,
|
||||
(unsigned int)DefaultDepth(surf->dpy, surf->screen));
|
||||
}
|
||||
|
||||
static void
|
||||
surface_scissor(XSurface *surf, int x, int y, unsigned int w, unsigned int h)
|
||||
{
|
||||
XRectangle clip_rect;
|
||||
clip_rect.x = (short)x;
|
||||
clip_rect.y = (short)y;
|
||||
clip_rect.width = (unsigned short)w;
|
||||
clip_rect.height = (unsigned short)h;
|
||||
clip_rect.width = (unsigned short)MIN(surf->w, clip_rect.width);
|
||||
clip_rect.height = (unsigned short)MIN(surf->h, clip_rect.height);
|
||||
XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_line(XSurface *surf, int x0, int y0, int x1, int y1, unsigned long c)
|
||||
{
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, x0, y0, x1, y1);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_rect(XSurface *surf, int x, int y, unsigned int w, unsigned int h, unsigned long c)
|
||||
{
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_triangle(XSurface *surf, int x0, int y0, int x1, int y1, int x2, int y2,
|
||||
unsigned long c)
|
||||
{
|
||||
XPoint pnts[3];
|
||||
pnts[0].x = (short)x0;
|
||||
pnts[0].y = (short)y0;
|
||||
pnts[1].x = (short)x1;
|
||||
pnts[1].y = (short)y1;
|
||||
pnts[2].x = (short)x2;
|
||||
pnts[2].y = (short)y2;
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 3, Convex, CoordModeOrigin);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_circle(XSurface *surf, int x, int y, unsigned int radius, unsigned long c)
|
||||
{
|
||||
unsigned int d = radius * 2;
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillArc(surf->dpy, surf->drawable, surf->gc, x, y, d, d, 0, 360 * 64);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_text(XSurface *surf, XFont *font, int x, int y, unsigned int w, unsigned int h,
|
||||
const char *text, unsigned int len, unsigned long bg, unsigned long fg)
|
||||
{
|
||||
int i, tx, ty, th, olen;
|
||||
XSetForeground(surf->dpy, surf->gc, bg);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
|
||||
if(!text || !font) return;
|
||||
|
||||
th = font->ascent + font->descent;
|
||||
ty = y + ((int)h / 2) - (th / 2) + font->ascent;
|
||||
tx = x;/* + ((int)h / 2);*/
|
||||
XSetForeground(surf->dpy, surf->gc, fg);
|
||||
if(font->set)
|
||||
XmbDrawString(surf->dpy, surf->drawable, font->set, surf->gc, tx, ty, text, (int)len);
|
||||
else
|
||||
XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, text, (int)len);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_clear(XSurface *surf, unsigned long color)
|
||||
{
|
||||
XSetForeground(surf->dpy, surf->gc, color);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, 0, 0, surf->w, surf->h);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_blit(Drawable target, XSurface *surf, unsigned int width, unsigned int height)
|
||||
{
|
||||
XCopyArea(surf->dpy, surf->drawable, target, surf->gc, 0, 0, width, height, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_del(XSurface *surf)
|
||||
{
|
||||
XFreePixmap(surf->dpy, surf->drawable);
|
||||
XFreeGC(surf->dpy, surf->gc);
|
||||
free(surf);
|
||||
}
|
||||
|
||||
static XFont*
|
||||
font_create(Display *dpy, const char *name)
|
||||
{
|
||||
int n;
|
||||
char *def, **missing;
|
||||
XFont *font = xcalloc(1, sizeof(XFont));
|
||||
font->set = XCreateFontSet(dpy, name, &missing, &n, &def);
|
||||
if(missing) {
|
||||
while(n--)
|
||||
fprintf(stderr, "missing fontset: %s\n", missing[n]);
|
||||
XFreeStringList(missing);
|
||||
}
|
||||
|
||||
if(font->set) {
|
||||
XFontStruct **xfonts;
|
||||
char **font_names;
|
||||
XExtentsOfFontSet(font->set);
|
||||
n = XFontsOfFontSet(font->set, &xfonts, &font_names);
|
||||
while(n--) {
|
||||
font->ascent = MAX(font->ascent, (*xfonts)->ascent);
|
||||
font->descent = MAX(font->descent,(*xfonts)->descent);
|
||||
xfonts++;
|
||||
}
|
||||
} else {
|
||||
if(!(font->xfont = XLoadQueryFont(dpy, name))
|
||||
&& !(font->xfont = XLoadQueryFont(dpy, "fixed")))
|
||||
die("error, cannot load font: '%s'\n", name);
|
||||
font->ascent = font->xfont->ascent;
|
||||
font->descent = font->xfont->descent;
|
||||
}
|
||||
font->height = font->ascent + font->descent;
|
||||
return font;
|
||||
}
|
||||
|
||||
static gui_size
|
||||
font_get_text_width(void *handle, const gui_char *text, gui_size len)
|
||||
{
|
||||
XFont *font = handle;
|
||||
XRectangle r;
|
||||
gui_size width;
|
||||
if(!font || !text)
|
||||
return 0;
|
||||
|
||||
if(font->set) {
|
||||
XmbTextExtents(font->set, (const char*)text, (int)len, NULL, &r);
|
||||
return r.width;
|
||||
}
|
||||
else {
|
||||
return (gui_size)XTextWidth(font->xfont, (const char*)text, (int)len);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
static void
|
||||
font_del(Display *dpy, XFont *font)
|
||||
{
|
||||
if(!font) return;
|
||||
if(font->set)
|
||||
XFreeFontSet(dpy, font->set);
|
||||
else
|
||||
XFreeFont(dpy, font->xfont);
|
||||
free(font);
|
||||
}
|
||||
|
||||
static void
|
||||
key(struct XWindow *xw, struct gui_input *in, XEvent *evt, gui_bool down)
|
||||
{
|
||||
int ret;
|
||||
KeySym *code = XGetKeyboardMapping(xw->dpy, (KeyCode)evt->xkey.keycode, 1, &ret);
|
||||
if (*code == XK_Control_L || *code == XK_Control_R)
|
||||
gui_input_key(in, GUI_KEY_CTRL, down);
|
||||
else if (*code == XK_Shift_L || *code == XK_Shift_R)
|
||||
gui_input_key(in, GUI_KEY_SHIFT, down);
|
||||
else if (*code == XK_Delete)
|
||||
gui_input_key(in, GUI_KEY_DEL, down);
|
||||
else if (*code == XK_Return)
|
||||
gui_input_key(in, GUI_KEY_ENTER, down);
|
||||
else if (*code == XK_space)
|
||||
gui_input_key(in, GUI_KEY_SPACE, down);
|
||||
else if (*code == XK_BackSpace)
|
||||
gui_input_key(in, GUI_KEY_BACKSPACE, down);
|
||||
XFree(code);
|
||||
}
|
||||
|
||||
static void
|
||||
motion(struct gui_input *in, XEvent *evt)
|
||||
{
|
||||
const gui_int x = evt->xmotion.x;
|
||||
const gui_int y = evt->xmotion.y;
|
||||
gui_input_motion(in, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
button(struct gui_input *in, XEvent *evt, gui_bool down)
|
||||
{
|
||||
const gui_int x = evt->xbutton.x;
|
||||
const gui_int y = evt->xbutton.y;
|
||||
if (evt->xbutton.button == Button1)
|
||||
gui_input_button(in, x, y, down);
|
||||
}
|
||||
|
||||
static void
|
||||
resize(struct XWindow *xw, XSurface *surf)
|
||||
{
|
||||
XGetWindowAttributes(xw->dpy, xw->win, &xw->attr);
|
||||
xw->width = (unsigned int)xw->attr.width;
|
||||
xw->height = (unsigned int)xw->attr.height;
|
||||
surface_resize(surf, xw->width, xw->height);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
color_from_byte(struct gui_color col)
|
||||
{
|
||||
unsigned long res = 0;
|
||||
res |= (unsigned long)col.r << 16;
|
||||
res |= (unsigned long)col.g << 8;
|
||||
res |= (unsigned long)col.b << 0;
|
||||
return (res);
|
||||
}
|
||||
|
||||
static void
|
||||
execute(XSurface *surf, const struct gui_command_list *list)
|
||||
{
|
||||
const struct gui_command *iter = NULL;
|
||||
if (!list->count) return;
|
||||
iter = list->begin;
|
||||
while (iter != list->end) {
|
||||
if (iter->type == GUI_COMMAND_CLIP) {
|
||||
const struct gui_command_clip *clip = (const struct gui_command_clip*)iter;
|
||||
surface_scissor(surf, (int)clip->x, (int)clip->y,
|
||||
(unsigned int)clip->w, (unsigned int)clip->h);
|
||||
} else if (iter->type == GUI_COMMAND_LINE) {
|
||||
const struct gui_command_line *line = (const struct gui_command_line*)iter;
|
||||
const unsigned long color = color_from_byte(line->color);
|
||||
surface_draw_line(surf, (int)line->from.x, (int)line->from.y,
|
||||
(int)line->to.x, (int)line->to.y, color);
|
||||
} else if (iter->type == GUI_COMMAND_RECT) {
|
||||
const struct gui_command_rect *rect = (const struct gui_command_rect*)iter;
|
||||
const unsigned long color = color_from_byte(rect->color);
|
||||
surface_draw_rect(surf, (int)rect->x, (int)rect->y,
|
||||
(unsigned int)rect->w, (unsigned int)rect->h, color);
|
||||
} else if (iter->type == GUI_COMMAND_CIRCLE) {
|
||||
const struct gui_command_circle *circle = (const struct gui_command_circle*)iter;
|
||||
const unsigned long color = color_from_byte(circle->color);
|
||||
surface_draw_circle(surf, (int)circle->x, (int)circle->y,
|
||||
(unsigned int)circle->radius, color);
|
||||
} else if (iter->type == GUI_COMMAND_BITMAP) {
|
||||
const struct gui_command_bitmap *bitmap = (const struct gui_command_bitmap*)iter;
|
||||
} else if (iter->type == GUI_COMMAND_TRIANGLE) {
|
||||
const struct gui_command_triangle *triangle = (const struct gui_command_triangle*)iter;
|
||||
const unsigned long color = color_from_byte(triangle->color);
|
||||
surface_draw_triangle(surf, (int)triangle->pnt[0].x, (int)triangle->pnt[0].y,
|
||||
(int)triangle->pnt[1].x, (int)triangle->pnt[1].y, (int)triangle->pnt[2].x,
|
||||
(int)triangle->pnt[2].y, color);
|
||||
} else if (iter->type == GUI_COMMAND_TEXT) {
|
||||
const struct gui_command_text *text = (const struct gui_command_text*)iter;
|
||||
const unsigned long bg = color_from_byte(text->background);
|
||||
const unsigned long fg = color_from_byte(text->foreground);
|
||||
surface_draw_text(surf, text->font, (int)text->x, (int)text->y,
|
||||
(unsigned int)text->w, (unsigned int)text->h,
|
||||
(const char*)text->string, (unsigned int)text->length, bg, fg);
|
||||
}
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gui_draw(XSurface *surf, const struct gui_output *out)
|
||||
{
|
||||
gui_size i = 0;
|
||||
if (!out->list_size) return;
|
||||
for (i = 0; i < out->list_size; i++)
|
||||
execute(surf, out->list[i]);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
long dt;
|
||||
long started;
|
||||
gui_bool running = gui_true;
|
||||
|
||||
XWindow xw;
|
||||
XSurface *surf;
|
||||
XFont *xfont;
|
||||
|
||||
struct gui_input in;
|
||||
struct gui_config config;
|
||||
struct gui_memory memory;
|
||||
struct gui_font font;
|
||||
struct gui_panel *panel;
|
||||
struct gui_context *ctx;
|
||||
struct gui_output output;
|
||||
|
||||
/* Window */
|
||||
UNUSED(argc); UNUSED(argv);
|
||||
memset(&xw, 0, sizeof xw);
|
||||
xw.dpy = XOpenDisplay(NULL);
|
||||
xw.root = DefaultRootWindow(xw.dpy);
|
||||
xw.screen = XDefaultScreen(xw.dpy);
|
||||
xw.vis = XDefaultVisual(xw.dpy, xw.screen);
|
||||
xw.cmap = XCreateColormap(xw.dpy,xw.root,xw.vis,AllocNone);
|
||||
xw.swa.colormap = xw.cmap;
|
||||
xw.swa.event_mask =
|
||||
ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPress |
|
||||
ButtonReleaseMask | ButtonMotionMask | Button1MotionMask | PointerMotionMask;
|
||||
xw.win = XCreateWindow(xw.dpy, xw.root, 0, 0, WIN_WIDTH, WIN_HEIGHT, 0,
|
||||
XDefaultDepth(xw.dpy, xw.screen), InputOutput,
|
||||
xw.vis, CWEventMask | CWColormap, &xw.swa);
|
||||
XStoreName(xw.dpy, xw.win, "X11");
|
||||
XMapWindow(xw.dpy, xw.win);
|
||||
XGetWindowAttributes(xw.dpy, xw.win, &xw.attr);
|
||||
xw.width = (unsigned int)xw.attr.width;
|
||||
xw.height = (unsigned int)xw.attr.height;
|
||||
xfont = font_create(xw.dpy, "fixed");
|
||||
surf = surface_create(xw.dpy, xw.screen, xw.win, xw.width, xw.height);
|
||||
|
||||
/* GUI */
|
||||
memory.size = MAX_MEMORY;
|
||||
memory.memory = calloc(1, memory.size);
|
||||
memory.max_depth = MAX_DEPTH;
|
||||
memory.max_panels = MAX_PANEL;
|
||||
ctx = gui_new(&memory, &in);
|
||||
|
||||
font.user = xfont;
|
||||
font.height = (gui_float)xfont->height;
|
||||
font.width = font_get_text_width;
|
||||
gui_default_config(&config);
|
||||
panel = gui_new_panel(ctx, 50, 50, 200, 400, &config, &font);
|
||||
|
||||
while (running) {
|
||||
/* Input */
|
||||
XEvent evt;
|
||||
started = timestamp();
|
||||
gui_input_begin(&in);
|
||||
while (XCheckWindowEvent(xw.dpy, xw.win, xw.swa.event_mask, &evt)) {
|
||||
if (evt.type == KeyPress) key(&xw, &in, &evt, gui_true);
|
||||
else if (evt.type == KeyRelease) key(&xw, &in, &evt, gui_false);
|
||||
else if (evt.type == ButtonPress) button(&in, &evt, gui_true);
|
||||
else if (evt.type == ButtonRelease) button(&in, &evt, gui_false);
|
||||
else if (evt.type == MotionNotify) motion(&in, &evt);
|
||||
else if (evt.type == Expose || evt.type == ConfigureNotify)
|
||||
resize(&xw, surf);
|
||||
}
|
||||
gui_input_end(&in);
|
||||
|
||||
/* GUI */
|
||||
gui_begin(ctx, (gui_float)xw.width, (gui_float)xw.height);
|
||||
running = gui_begin_panel(ctx, panel, "Demo",
|
||||
GUI_PANEL_CLOSEABLE|GUI_PANEL_MINIMIZABLE|GUI_PANEL_SCALEABLE|
|
||||
GUI_PANEL_MOVEABLE|GUI_PANEL_BORDER);
|
||||
gui_panel_layout(panel, 30, 1);
|
||||
if (gui_panel_button_text(panel, "button", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "button pressed!\n");
|
||||
gui_end_panel(ctx, panel, NULL);
|
||||
gui_end(ctx, &output, NULL);
|
||||
|
||||
/* Draw */
|
||||
XClearWindow(xw.dpy, xw.win);
|
||||
surface_clear(surf, 0x00646464);
|
||||
gui_draw(surf, &output);
|
||||
surface_blit(xw.win, surf, xw.width, xw.height);
|
||||
XFlush(xw.dpy);
|
||||
|
||||
/* Timing */
|
||||
dt = timestamp() - started;
|
||||
if (dt < DTIME)
|
||||
sleep_for(DTIME - dt);
|
||||
}
|
||||
|
||||
free(memory.memory);
|
||||
font_del(xw.dpy, xfont);
|
||||
surface_del(surf);
|
||||
XDestroyWindow(xw.dpy, xw.win);
|
||||
XCloseDisplay(xw.dpy);
|
||||
return 0;
|
||||
}
|
||||
|
236
gui.h
236
gui.h
@ -12,7 +12,6 @@ extern "C" {
|
||||
|
||||
#define GUI_UTF_SIZE 4
|
||||
#define GUI_INPUT_MAX 16
|
||||
#define GUI_ATLAS_DEPTH 4
|
||||
|
||||
#ifdef GUI_USE_FIXED_TYPES
|
||||
#include <stdint.h>
|
||||
@ -43,15 +42,15 @@ typedef unsigned int gui_flag;
|
||||
typedef unsigned long gui_size;
|
||||
#endif
|
||||
|
||||
typedef gui_char gui_glyph[GUI_UTF_SIZE];
|
||||
typedef union {void* dx; gui_uint gl;} gui_texture;
|
||||
typedef struct gui_panel gui_tab;
|
||||
typedef struct gui_panel gui_group;
|
||||
typedef struct gui_panel gui_shelf;
|
||||
typedef gui_char gui_glyph[GUI_UTF_SIZE];
|
||||
typedef union {void* handle; gui_uint id;} gui_texture;
|
||||
typedef gui_size(*gui_text_width_f)(void*,const gui_char*, gui_size);
|
||||
|
||||
enum {gui_false, gui_true};
|
||||
enum gui_heading {GUI_UP, GUI_RIGHT, GUI_DOWN, GUI_LEFT};
|
||||
enum gui_direction {GUI_HORIZONTAL, GUI_VERTICAL};
|
||||
struct gui_color {gui_byte r,g,b,a;};
|
||||
struct gui_colorf {gui_float r,g,b,a;};
|
||||
struct gui_texCoord {gui_float u,v;};
|
||||
@ -59,60 +58,10 @@ struct gui_vec2 {gui_float x,y;};
|
||||
struct gui_rect {gui_float x,y,w,h;};
|
||||
struct gui_key {gui_bool down, clicked;};
|
||||
|
||||
#ifdef GUI_USE_FREETYPE_FONT
|
||||
enum gui_font_atlas_dimension {
|
||||
GUI_ATLAS_DIM_64 = 64,
|
||||
GUI_ATLAS_DIM_128 = 128,
|
||||
GUI_ATLAS_DIM_256 = 256,
|
||||
GUI_ATLAS_DIM_512 = 512,
|
||||
GUI_ATLAS_DIM_1024 = 1024,
|
||||
GUI_ATLAS_DIM_2048 = 2048,
|
||||
GUI_ATLAS_DIM_4096 = 4095
|
||||
};
|
||||
|
||||
struct gui_font_atlas {
|
||||
enum gui_font_atlas_dimension dim;
|
||||
gui_size range;
|
||||
gui_size size;
|
||||
gui_byte *memory;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct gui_font_glyph {
|
||||
gui_uint code;
|
||||
gui_float xadvance;
|
||||
gui_short width, height;
|
||||
gui_float xoff, yoff;
|
||||
struct gui_texCoord uv[2];
|
||||
};
|
||||
|
||||
struct gui_font {
|
||||
void *user;
|
||||
gui_float height;
|
||||
gui_float scale;
|
||||
gui_texture texture;
|
||||
struct gui_vec2 tex_size;
|
||||
gui_uint glyph_count;
|
||||
struct gui_font_glyph *glyphes;
|
||||
const struct gui_font_glyph *fallback;
|
||||
};
|
||||
|
||||
struct gui_memory {
|
||||
void *memory;
|
||||
gui_size size;
|
||||
gui_size max_panels;
|
||||
gui_size max_depth;
|
||||
gui_float vertex_percentage;
|
||||
gui_float command_percentage;
|
||||
};
|
||||
|
||||
struct gui_memory_status {
|
||||
gui_size vertexes_allocated;
|
||||
gui_size vertexes_needed;
|
||||
gui_size commands_allocated;
|
||||
gui_size commands_needed;
|
||||
gui_size clips_allocated;
|
||||
gui_size allocated;
|
||||
gui_size needed;
|
||||
gui_text_width_f width;
|
||||
};
|
||||
|
||||
enum gui_keys {
|
||||
@ -138,41 +87,104 @@ struct gui_input {
|
||||
struct gui_vec2 mouse_clicked_pos;
|
||||
};
|
||||
|
||||
struct gui_vertex {
|
||||
struct gui_vec2 pos;
|
||||
struct gui_texCoord uv;
|
||||
struct gui_memory {
|
||||
void *memory;
|
||||
gui_size size;
|
||||
gui_size max_panels;
|
||||
gui_size max_depth;
|
||||
};
|
||||
|
||||
struct gui_memory_status {
|
||||
gui_size allocated;
|
||||
gui_size needed;
|
||||
};
|
||||
|
||||
enum gui_command_type {
|
||||
GUI_COMMAND_NOP = 0,
|
||||
GUI_COMMAND_CLIP,
|
||||
GUI_COMMAND_LINE,
|
||||
GUI_COMMAND_RECT,
|
||||
GUI_COMMAND_CIRCLE,
|
||||
GUI_COMMAND_BITMAP,
|
||||
GUI_COMMAND_TRIANGLE,
|
||||
GUI_COMMAND_TEXT,
|
||||
GUI_COMMAND_MAX
|
||||
};
|
||||
|
||||
struct gui_command {
|
||||
enum gui_command_type type;
|
||||
struct gui_command *next;
|
||||
};
|
||||
|
||||
struct gui_command_clip {
|
||||
struct gui_command header;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
};
|
||||
|
||||
struct gui_command_line {
|
||||
struct gui_command header;
|
||||
struct gui_color color;
|
||||
struct gui_vec2 from;
|
||||
struct gui_vec2 to;
|
||||
};
|
||||
|
||||
struct gui_command_rect {
|
||||
struct gui_command header;
|
||||
struct gui_color color;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
};
|
||||
|
||||
struct gui_command_circle {
|
||||
struct gui_command header;
|
||||
struct gui_color color;
|
||||
gui_float radius;
|
||||
gui_float x, y;
|
||||
};
|
||||
|
||||
struct gui_command_bitmap {
|
||||
struct gui_command header;
|
||||
gui_texture texture;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
};
|
||||
|
||||
struct gui_command_triangle {
|
||||
struct gui_command header;
|
||||
struct gui_vec2 pnt[3];
|
||||
struct gui_color color;
|
||||
};
|
||||
|
||||
struct gui_draw_command {
|
||||
gui_size vertex_count;
|
||||
struct gui_rect clip_rect;
|
||||
gui_texture texture;
|
||||
struct gui_command_text {
|
||||
struct gui_command header;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
void *font;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_size length;
|
||||
gui_byte string[1];
|
||||
};
|
||||
|
||||
struct gui_draw_buffer {
|
||||
struct gui_vertex *vertexes;
|
||||
gui_size vertex_capacity;
|
||||
gui_size vertex_size;
|
||||
gui_size vertex_needed;
|
||||
struct gui_draw_command *commands;
|
||||
gui_size command_capacity;
|
||||
gui_size command_size;
|
||||
gui_size command_needed;
|
||||
struct gui_command_list{
|
||||
struct gui_command *begin;
|
||||
struct gui_command *end;
|
||||
gui_size count;
|
||||
gui_size capacity;
|
||||
gui_size needed;
|
||||
gui_size size;
|
||||
};
|
||||
|
||||
struct gui_command_buffer {
|
||||
struct gui_command_list cmds;
|
||||
struct gui_rect *clips;
|
||||
gui_size clip_capacity;
|
||||
gui_size clip_size;
|
||||
};
|
||||
|
||||
struct gui_draw_call_list {
|
||||
struct gui_vertex *vertexes;
|
||||
gui_size vertex_size;
|
||||
struct gui_draw_command *commands;
|
||||
gui_size command_size;
|
||||
};
|
||||
|
||||
struct gui_output {
|
||||
struct gui_draw_call_list **list;
|
||||
struct gui_command_list **list;
|
||||
gui_size list_size;
|
||||
};
|
||||
|
||||
@ -183,13 +195,14 @@ enum gui_text_align {
|
||||
};
|
||||
|
||||
struct gui_text {
|
||||
void *font;
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
const char *text;
|
||||
const char *string;
|
||||
gui_size length;
|
||||
enum gui_text_align align;
|
||||
struct gui_color font;
|
||||
struct gui_color foreground;
|
||||
struct gui_color background;
|
||||
};
|
||||
|
||||
@ -212,6 +225,7 @@ struct gui_button {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
gui_float border;
|
||||
enum gui_button_behavior behavior;
|
||||
struct gui_color background;
|
||||
struct gui_color foreground;
|
||||
@ -229,9 +243,8 @@ struct gui_toggle {
|
||||
gui_float x, y;
|
||||
gui_float w, h;
|
||||
gui_float pad_x, pad_y;
|
||||
gui_bool active;
|
||||
gui_size length;
|
||||
const gui_char *text;
|
||||
gui_size length;
|
||||
enum gui_toggle_type type;
|
||||
struct gui_color font;
|
||||
struct gui_color background;
|
||||
@ -390,19 +403,12 @@ struct gui_panel {
|
||||
gui_size row_columns;
|
||||
gui_float offset;
|
||||
gui_bool minimized;
|
||||
struct gui_draw_buffer *out;
|
||||
const struct gui_font *font;
|
||||
struct gui_command_buffer *out;
|
||||
struct gui_font font;
|
||||
const struct gui_input *in;
|
||||
const struct gui_config *config;
|
||||
};
|
||||
|
||||
/* font */
|
||||
#ifdef GUI_USE_FREETYPE_FONT
|
||||
#define gui_font_atlas_alloc_size(sz) ((sz) * (sz) * GUI_ATLAS_DEPTH)
|
||||
gui_bool gui_font_load(struct gui_font*, struct gui_font_atlas*, gui_uint height,
|
||||
const gui_byte*, gui_size);
|
||||
#endif
|
||||
|
||||
/* Input */
|
||||
void gui_input_begin(struct gui_input*);
|
||||
void gui_input_motion(struct gui_input*, gui_int x, gui_int y);
|
||||
@ -412,40 +418,36 @@ void gui_input_char(struct gui_input*, const gui_glyph);
|
||||
void gui_input_end(struct gui_input*);
|
||||
|
||||
/* Output */
|
||||
void gui_output_begin(struct gui_draw_buffer*, const struct gui_memory*);
|
||||
void gui_output_end(struct gui_draw_buffer*, struct gui_draw_call_list*,
|
||||
void gui_output_begin(struct gui_command_buffer*, const struct gui_memory*);
|
||||
void gui_output_end(struct gui_command_buffer*, struct gui_command_list*,
|
||||
struct gui_memory_status*);
|
||||
|
||||
/* Widgets */
|
||||
void gui_widget_text(struct gui_draw_buffer*, const struct gui_text*,
|
||||
void gui_widget_text(struct gui_command_buffer*, const struct gui_text*,
|
||||
const struct gui_font*);
|
||||
void gui_widget_image(struct gui_draw_buffer*, const struct gui_image*);
|
||||
gui_bool gui_widget_button_text(struct gui_draw_buffer*, const struct gui_button*,
|
||||
void gui_widget_image(struct gui_command_buffer*, const struct gui_image*);
|
||||
gui_bool gui_widget_button_text(struct gui_command_buffer*, const struct gui_button*,
|
||||
const char *text, gui_size len, const struct gui_font*,
|
||||
const struct gui_input*);
|
||||
gui_bool gui_widget_button_triangle(struct gui_draw_buffer*, struct gui_button*,
|
||||
gui_bool gui_widget_button_triangle(struct gui_command_buffer*, struct gui_button*,
|
||||
enum gui_heading, const struct gui_input*);
|
||||
gui_bool gui_widget_button_icon(struct gui_draw_buffer*, struct gui_button*,
|
||||
gui_bool gui_widget_button_icon(struct gui_command_buffer*, struct gui_button*,
|
||||
gui_texture, struct gui_texCoord from, struct gui_texCoord to,
|
||||
const struct gui_input*);
|
||||
gui_bool gui_widget_toggle(struct gui_draw_buffer*, const struct gui_toggle*,
|
||||
const struct gui_font*, const struct gui_input*);
|
||||
gui_float gui_widget_slider(struct gui_draw_buffer*, const struct gui_slider*,
|
||||
gui_bool gui_widget_toggle(struct gui_command_buffer*, const struct gui_toggle*,
|
||||
gui_bool active, const struct gui_font*, const struct gui_input*);
|
||||
gui_float gui_widget_slider(struct gui_command_buffer*, const struct gui_slider*,
|
||||
const struct gui_input*);
|
||||
gui_float gui_widget_slider_vertical(struct gui_draw_buffer*,
|
||||
const struct gui_slider*, const struct gui_input*);
|
||||
gui_size gui_widget_progress(struct gui_draw_buffer*, const struct gui_progress*,
|
||||
gui_size gui_widget_progress(struct gui_command_buffer*, const struct gui_progress*,
|
||||
const struct gui_input*);
|
||||
gui_size gui_widget_progress_vertical(struct gui_draw_buffer *buf,
|
||||
const struct gui_progress*, const struct gui_input*);
|
||||
gui_bool gui_widget_input(struct gui_draw_buffer*, gui_char*, gui_size*,
|
||||
gui_bool gui_widget_input(struct gui_command_buffer*, gui_char*, gui_size*,
|
||||
const struct gui_input_field*, const struct gui_font*,
|
||||
const struct gui_input*);
|
||||
gui_float gui_widget_scroll(struct gui_draw_buffer*, const struct gui_scroll*,
|
||||
gui_float gui_widget_scroll(struct gui_command_buffer*, const struct gui_scroll*,
|
||||
const struct gui_input*);
|
||||
gui_int gui_widget_histo(struct gui_draw_buffer*, const struct gui_histo*,
|
||||
gui_int gui_widget_histo(struct gui_command_buffer*, const struct gui_histo*,
|
||||
const struct gui_input*);
|
||||
gui_int gui_widget_plot(struct gui_draw_buffer*, const struct gui_plot*,
|
||||
gui_int gui_widget_plot(struct gui_command_buffer*, const struct gui_plot*,
|
||||
const struct gui_input*);
|
||||
|
||||
/* Panel */
|
||||
@ -454,7 +456,7 @@ void gui_panel_show(struct gui_panel*);
|
||||
void gui_panel_hide(struct gui_panel*);
|
||||
void gui_panel_init(struct gui_panel*, const struct gui_config*, const struct gui_font*);
|
||||
gui_bool gui_panel_is_hidden(const struct gui_panel*);
|
||||
gui_bool gui_panel_begin(struct gui_panel*, struct gui_draw_buffer*,
|
||||
gui_bool gui_panel_begin(struct gui_panel*, struct gui_command_buffer*,
|
||||
const struct gui_input*, const char*,
|
||||
gui_float x, gui_float y, gui_float w, gui_float h, gui_flags);
|
||||
void gui_panel_end(struct gui_panel*);
|
||||
@ -470,9 +472,9 @@ gui_bool gui_panel_button_toggle(struct gui_panel*, const char*, gui_bool value)
|
||||
gui_bool gui_panel_button_icon(struct gui_panel*, gui_texture, struct gui_texCoord from,
|
||||
struct gui_texCoord to, enum gui_button_behavior);
|
||||
gui_float gui_panel_slider(struct gui_panel*, gui_float min, gui_float val,
|
||||
gui_float max, gui_float step, enum gui_direction);
|
||||
gui_float max, gui_float step);
|
||||
gui_size gui_panel_progress(struct gui_panel*, gui_size cur, gui_size max,
|
||||
gui_bool modifyable, enum gui_direction);
|
||||
gui_bool modifyable);
|
||||
gui_bool gui_panel_input(struct gui_panel*, gui_char *buffer, gui_size *len,
|
||||
gui_size max, enum gui_input_filter, gui_bool active);
|
||||
gui_size gui_panel_shell(struct gui_panel*, gui_char *buffer, gui_size *length,
|
||||
@ -496,9 +498,9 @@ struct gui_context;
|
||||
struct gui_context *gui_new(const struct gui_memory*, const struct gui_input*);
|
||||
void gui_begin(struct gui_context*, gui_float width, gui_float height);
|
||||
void gui_end(struct gui_context*, struct gui_output*, struct gui_memory_status*);
|
||||
struct gui_panel *gui_panel_new(struct gui_context*, gui_float x, gui_float y, gui_float w,
|
||||
struct gui_panel *gui_new_panel(struct gui_context*, gui_float x, gui_float y, gui_float w,
|
||||
gui_float h, const struct gui_config* , const struct gui_font*);
|
||||
void gui_panel_del(struct gui_context*, struct gui_panel*);
|
||||
void gui_del_panel(struct gui_context*, struct gui_panel*);
|
||||
struct gui_vec2 gui_get_panel_position(const struct gui_context*, const struct gui_panel*);
|
||||
struct gui_vec2 gui_get_panel_size(const struct gui_context*, const struct gui_panel*);
|
||||
gui_bool gui_begin_panel(struct gui_context*, struct gui_panel*, const char *title, gui_flags flags);
|
||||
|
Loading…
Reference in New Issue
Block a user