revert back to old demo version
This commit is contained in:
parent
11cb73ef97
commit
1e42945906
460
demo/demo.c
460
demo/demo.c
@ -1,61 +1,7 @@
|
||||
#define MAX_BUFFER 64
|
||||
#define MAX_MEMORY (64 * 1024)
|
||||
#define WINDOW_WIDTH 1200
|
||||
#define WINDOW_HEIGHT 800
|
||||
|
||||
struct menubar_window {
|
||||
struct gui_panel_hook hook;
|
||||
int current;
|
||||
gui_size selection;
|
||||
};
|
||||
|
||||
struct status_window {
|
||||
struct gui_panel_hook hook;
|
||||
gui_char mel_buffer[MAX_BUFFER];
|
||||
gui_size mel_length;
|
||||
gui_bool mel_active;
|
||||
gui_char py_buffer[MAX_BUFFER];
|
||||
gui_size py_length;
|
||||
gui_bool py_active;
|
||||
};
|
||||
|
||||
struct toolbar_window {struct gui_panel_hook hook;};
|
||||
struct settings_window {
|
||||
struct gui_panel_hook hook;
|
||||
|
||||
/* brush tab */
|
||||
gui_bool brush_tab;
|
||||
gui_bool radius_u_active;
|
||||
gui_bool radius_l_active;
|
||||
gui_float radiusu;
|
||||
gui_float radiusl;
|
||||
gui_bool rotate_to_stroke;
|
||||
|
||||
/* color tab */
|
||||
gui_bool color_tab;
|
||||
struct gui_color color;
|
||||
gui_float opacity;
|
||||
gui_bool opacity_active;
|
||||
|
||||
/* floot tab */
|
||||
gui_bool flood_tab;
|
||||
struct gui_color flood_color;
|
||||
gui_float flood_opacity;
|
||||
gui_size flood_type;
|
||||
|
||||
/* paint tabs */
|
||||
gui_bool paint_tab;
|
||||
gui_size artisan_type;
|
||||
gui_size effect_type;
|
||||
gui_size brush_mode;
|
||||
|
||||
/* texture tab */
|
||||
gui_bool texture_tab;
|
||||
gui_size attribute;
|
||||
gui_bool update_on_stroke;
|
||||
gui_bool save_on_stroke;
|
||||
gui_bool extend_seam_color;
|
||||
};
|
||||
#define WINDOW_WIDTH 800
|
||||
#define WINDOW_HEIGHT 600
|
||||
|
||||
struct show_window {
|
||||
struct gui_panel_hook hook;
|
||||
@ -104,34 +50,15 @@ struct control_window {
|
||||
struct gui_color color;
|
||||
};
|
||||
|
||||
struct demo_img {
|
||||
void *select;
|
||||
void *lasso;
|
||||
void *paint;
|
||||
void *move;
|
||||
void *rotate;
|
||||
void *scale;
|
||||
};
|
||||
|
||||
struct demo_gui {
|
||||
gui_bool running;
|
||||
struct show_window show;
|
||||
struct control_window control;
|
||||
struct settings_window settings;
|
||||
struct menubar_window menu;
|
||||
struct toolbar_window tool;
|
||||
struct status_window status;
|
||||
|
||||
struct gui_memory memory;
|
||||
struct gui_command_buffer buffer;
|
||||
|
||||
struct gui_layout_config conf;
|
||||
struct gui_panel_stack background;
|
||||
struct gui_layout layout;
|
||||
struct gui_panel_stack floating;
|
||||
struct gui_panel_stack stack;
|
||||
struct gui_panel_layout tab;
|
||||
|
||||
struct demo_img images;
|
||||
struct gui_config config;
|
||||
struct gui_font font;
|
||||
gui_size width, height;
|
||||
@ -228,7 +155,7 @@ static void
|
||||
init_show(struct show_window *win, struct gui_config *config, struct gui_font *font,
|
||||
struct gui_panel_stack *stack)
|
||||
{
|
||||
gui_panel_hook_init(&win->hook, 120, 160, 300, 545,
|
||||
gui_panel_hook_init(&win->hook, 20, 20, 300, 545,
|
||||
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|
|
||||
GUI_PANEL_CLOSEABLE|GUI_PANEL_SCALEABLE|
|
||||
GUI_PANEL_MINIMIZABLE|GUI_PANEL_HIDDEN, config, font);
|
||||
@ -401,7 +328,7 @@ static void
|
||||
init_control(struct control_window *win, struct gui_config *config, struct gui_font *font,
|
||||
struct gui_panel_stack *stack)
|
||||
{
|
||||
gui_panel_hook_init(&win->hook, 430, 180, 320, 500,
|
||||
gui_panel_hook_init(&win->hook, 380, 20, 320, 500,
|
||||
GUI_PANEL_BORDER|GUI_PANEL_MOVEABLE|GUI_PANEL_CLOSEABLE|GUI_PANEL_SCALEABLE, config, font);
|
||||
gui_stack_push(stack, &win->hook);
|
||||
win->show_flags = gui_hook_panel(&win->hook)->flags;
|
||||
@ -433,276 +360,6 @@ update_control(struct control_window *control, struct gui_panel_stack *stack,
|
||||
return running;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
brush_tab(struct gui_panel_layout *panel, struct settings_window *win)
|
||||
{
|
||||
gui_panel_row(panel, 20, 2);
|
||||
gui_panel_label(panel, "Radius (U):", GUI_TEXT_RIGHT);
|
||||
win->radiusu = gui_panel_slider(panel, 0, win->radiusu, 20, 1);
|
||||
gui_panel_label(panel, "Radius (L):", GUI_TEXT_RIGHT);
|
||||
win->radiusl = gui_panel_slider(panel, 0, win->radiusl, 20, 1);
|
||||
|
||||
gui_panel_row(panel, 25, 3);
|
||||
gui_panel_seperator(panel, 1);
|
||||
win->rotate_to_stroke = gui_panel_check(panel, "Rotate to stroke", win->rotate_to_stroke);
|
||||
}
|
||||
|
||||
static struct gui_color
|
||||
scolor_tab(struct gui_panel_layout *panel, struct settings_window *win)
|
||||
{
|
||||
char buffer[256];
|
||||
struct gui_color color = win->color;
|
||||
gui_float c = color.r;
|
||||
|
||||
gui_panel_row(panel, 25, 3);
|
||||
gui_panel_label(panel, "Color:", GUI_TEXT_RIGHT);
|
||||
c = gui_panel_slider(panel, 0, c, 250, 10);
|
||||
color.r = (gui_byte)c;
|
||||
color.g = (gui_byte)c;
|
||||
color.b = (gui_byte)c;
|
||||
color.a = 255;
|
||||
gui_panel_button_color(panel, color, GUI_BUTTON_DEFAULT);
|
||||
|
||||
gui_panel_label(panel, "Opacity:", GUI_TEXT_RIGHT);
|
||||
win->flood_opacity = gui_panel_slider(panel, 0, win->flood_opacity, 250, 10);
|
||||
sprintf(buffer, "%.2f", win->flood_opacity);
|
||||
gui_panel_label(panel, buffer, GUI_TEXT_LEFT);
|
||||
return color;
|
||||
}
|
||||
|
||||
static struct gui_color
|
||||
flood_tab(struct gui_panel_layout *panel, struct settings_window *win)
|
||||
{
|
||||
char buffer[256];
|
||||
const char *flood_types[] = {"All", "Selected"};
|
||||
struct gui_color color = win->flood_color;
|
||||
gui_float c = color.r;
|
||||
|
||||
gui_panel_row(panel, 25, 3);
|
||||
gui_panel_label(panel, "Color:", GUI_TEXT_RIGHT);
|
||||
c = gui_panel_slider(panel, 0, c, 250, 10);
|
||||
color.r = (gui_byte)c;
|
||||
color.g = (gui_byte)c;
|
||||
color.b = (gui_byte)c;
|
||||
color.a = 255;
|
||||
gui_panel_button_color(panel, color, GUI_BUTTON_DEFAULT);
|
||||
|
||||
gui_panel_label(panel, "Opacity:", GUI_TEXT_RIGHT);
|
||||
win->opacity = gui_panel_slider(panel, 0, win->opacity, 250, 10);
|
||||
sprintf(buffer, "%.2f", win->opacity);
|
||||
gui_panel_label(panel, buffer, GUI_TEXT_LEFT);
|
||||
|
||||
gui_panel_row(panel, 25, 2);
|
||||
if (gui_panel_button_text(panel, "Flood Paint", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "flood paint pressed!\n");
|
||||
if (gui_panel_button_text(panel, "Flood Erease", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "flood erase pressed!\n");
|
||||
|
||||
gui_panel_row(panel, 25, LEN(flood_types) + 1);
|
||||
gui_panel_label(panel, "Flood:", GUI_TEXT_RIGHT);
|
||||
win->flood_type = gui_panel_option_group(panel, flood_types, LEN(flood_types), win->flood_type);
|
||||
return color;
|
||||
}
|
||||
|
||||
static void
|
||||
paint_tab(struct gui_panel_layout *panel, struct settings_window *win)
|
||||
{
|
||||
const char *brush_mode[] = {"Dynamic", "Static"};
|
||||
const char *artisan_types[] = {"Paint", "Erase", "Clone"};
|
||||
const char *paint_effects[] = {"Paint", "Smear", "Blur"};
|
||||
gui_panel_row(panel, 25, LEN(artisan_types) + 1);
|
||||
gui_panel_label(panel, "Artisan:", GUI_TEXT_RIGHT);
|
||||
win->artisan_type = gui_panel_option_group(panel, artisan_types, LEN(artisan_types), win->artisan_type);
|
||||
gui_panel_row(panel, 25, LEN(paint_effects) + 1);
|
||||
gui_panel_label(panel, "Effects:", GUI_TEXT_RIGHT);
|
||||
win->effect_type = gui_panel_option_group(panel, paint_effects, LEN(paint_effects), win->effect_type);
|
||||
|
||||
gui_panel_row(panel, 25, 3);
|
||||
gui_panel_seperator(panel, 1);
|
||||
if (gui_panel_button_text(panel, "Erase", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "set erase image button pressed!\n");
|
||||
|
||||
gui_panel_row(panel, 25, 3);
|
||||
gui_panel_seperator(panel, 1);
|
||||
if (gui_panel_button_text(panel, "Reset", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "reset brushes button pressed!\n");
|
||||
|
||||
gui_panel_row(panel, 25, LEN(brush_mode) + 1);
|
||||
gui_panel_label(panel, "Brush mode:", GUI_TEXT_RIGHT);
|
||||
win->brush_mode = gui_panel_option_group(panel, brush_mode, LEN(brush_mode), win->brush_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
texture_tab(struct gui_panel_layout *panel, struct settings_window *win)
|
||||
{
|
||||
const char *attributes[] = {"Color", "Normals", "Depth"};
|
||||
gui_panel_row(panel, 25, 1);
|
||||
win->attribute = gui_panel_selector(panel, attributes, LEN(attributes), win->attribute);
|
||||
if (gui_panel_button_text(panel, "Assign", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "assign/edit textures button pressed!\n");
|
||||
if (gui_panel_button_text(panel, "Save", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "save textures button pressed!\n");
|
||||
if (gui_panel_button_text(panel, "Reload", GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "reload textures button pressed!\n");
|
||||
|
||||
win->update_on_stroke = gui_panel_check(panel, "Update on stroke", win->update_on_stroke);
|
||||
win->save_on_stroke = gui_panel_check(panel, "Save on stroke", win->save_on_stroke);
|
||||
win->extend_seam_color = gui_panel_check(panel, "Extend seam color", win->extend_seam_color);
|
||||
}
|
||||
|
||||
static void
|
||||
update_settings(struct settings_window *win, struct gui_layout *layout,
|
||||
struct gui_input *in, struct gui_canvas *canvas)
|
||||
{
|
||||
struct gui_panel_layout panel;
|
||||
struct gui_panel_layout tab;
|
||||
gui_panel_hook_begin_tiled(&panel, &win->hook, layout, GUI_SLOT_RIGHT, 0,
|
||||
"Tool Settings", canvas, in);
|
||||
|
||||
win->brush_tab = gui_panel_tab_begin(&panel, &tab, "Brush", win->brush_tab);
|
||||
brush_tab(&tab, win);
|
||||
gui_panel_tab_end(&panel, &tab);
|
||||
|
||||
win->color_tab = gui_panel_tab_begin(&panel, &tab, "Color", win->color_tab);
|
||||
win->color = scolor_tab(&tab, win);
|
||||
gui_panel_tab_end(&panel, &tab);
|
||||
|
||||
win->flood_tab = gui_panel_tab_begin(&panel, &tab, "Flood", win->flood_tab);
|
||||
win->flood_color = flood_tab(&tab, win);
|
||||
gui_panel_tab_end(&panel, &tab);
|
||||
|
||||
win->paint_tab = gui_panel_tab_begin(&panel, &tab, "Paint", win->paint_tab);
|
||||
paint_tab(&tab, win);
|
||||
gui_panel_tab_end(&panel, &tab);
|
||||
|
||||
win->texture_tab = gui_panel_tab_begin(&panel, &tab, "Textures", win->texture_tab);
|
||||
texture_tab(&tab, win);
|
||||
gui_panel_tab_end(&panel, &tab);
|
||||
|
||||
gui_panel_hook_end(&panel, &win->hook);
|
||||
}
|
||||
|
||||
static void
|
||||
update_menu(struct menubar_window *win, struct gui_layout *layout,
|
||||
struct gui_input *in, struct gui_canvas *canvas, struct demo_gui *demo)
|
||||
{
|
||||
/* TODO(vurtun): probably want this to be a little bit more expressive */
|
||||
struct level {const char *name; const int next;};
|
||||
static const struct level levels[][32] = {
|
||||
{{"File", 1}, {"Edit", 2}, {"Tools", 3}, {"Create", 4}, {"Window", 5}, {NULL, -1}},
|
||||
{{"Back", 0}, {"New", 0}, {"Open", 0}, {"Quit", 0}, {NULL, -1}},
|
||||
{{"Back", 0}, {"Undo", 0}, {"Redo", 0}, {"Copy", 0}, {"Paste", 0}, {NULL, -1}},
|
||||
{{"Back", 0}, {"Selection", 6}, {"Transform", 7}, {NULL, -1}},
|
||||
{{"Back", 0}, {"Sphere", 0}, {"Cube", 0}, {"Cylinder", 0}, {NULL, -1}},
|
||||
{{"Back", 0}, {"General Editor", 0}, {"Node Editor", 0}, {NULL, -1}},
|
||||
{{"Home", 0}, {"Back", 3}, {"Rectangle", 0}, {"Elipse", 0}, {NULL, -1}},
|
||||
{{"Home", 0}, {"Back", 3}, {"Align", 0}, {"Move", 0}, {NULL, -1}}
|
||||
};
|
||||
const char *tabs[] = {
|
||||
"General", "Curves", "Surfaces", "Polygons", "Deformation", "Animation", "Dynamics",
|
||||
"Rendering", "PaintEffects", "Toon", "Muscle", "Fluids", "Fur", "nHair", "nCloth"
|
||||
};
|
||||
|
||||
gui_size cols;
|
||||
const struct level *iter = levels[win->current];
|
||||
struct gui_panel_layout panel;
|
||||
struct gui_panel_layout tab;
|
||||
struct demo_img *images = &demo->images;
|
||||
|
||||
/* menus */
|
||||
gui_panel_hook_begin_tiled(&panel, &win->hook, layout, GUI_SLOT_TOP, 0, NULL, canvas, in);
|
||||
gui_panel_row(&panel, 20, 12);
|
||||
while (iter->name) {
|
||||
if (gui_panel_button_text(&panel, iter->name, GUI_BUTTON_DEFAULT)) {
|
||||
fprintf(stdout, "button: %s pressed!\n", iter->name);
|
||||
if (iter->next >= 0)
|
||||
win->current = iter->next;
|
||||
if (!strcmp(iter->name, "Quit"))
|
||||
demo->running = gui_false;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
/* toolbar */
|
||||
gui_panel_row(&panel, 85, 1);
|
||||
gui_config_push_property(&demo->config, GUI_PROPERTY_PADDING, 15, 5);
|
||||
gui_config_push_property(&demo->config, GUI_PROPERTY_ITEM_PADDING, 1, 1);
|
||||
win->selection = gui_panel_shelf_begin(&panel, &tab, tabs, LEN(tabs), win->selection, 0);
|
||||
|
||||
cols = gui_panel_row_columns(&tab, 40);
|
||||
gui_panel_row(&tab, 40, cols);
|
||||
if (win->selection % 2) {
|
||||
if (gui_panel_button_image(&tab, images->select, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "select button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->lasso, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "lasso button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->paint, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "paint button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->move, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "move button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->rotate, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "rotate button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->scale, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "scale button pressed!\n");
|
||||
} else {
|
||||
if (gui_panel_button_image(&tab, images->move, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "move button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->rotate, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "rotate button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->scale, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "scale button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->select, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "select button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->lasso, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "lasso button pressed!\n");
|
||||
if (gui_panel_button_image(&tab, images->paint, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "paint button pressed!\n");
|
||||
}
|
||||
gui_panel_shelf_end(&panel, &tab);
|
||||
gui_config_pop_property(&demo->config);
|
||||
gui_config_pop_property(&demo->config);
|
||||
gui_panel_hook_end(&panel, &win->hook);
|
||||
}
|
||||
|
||||
static void
|
||||
update_status(struct status_window *win, struct gui_layout *layout,
|
||||
struct gui_input *in, struct gui_canvas *canvas)
|
||||
{
|
||||
struct gui_panel_layout panel;
|
||||
gui_panel_hook_begin_tiled(&panel, &win->hook, layout, GUI_SLOT_BOTTOM, 0, NULL, canvas, in);
|
||||
gui_panel_row(&panel, 20, 2);
|
||||
if (gui_panel_shell(&panel, win->mel_buffer, &win->mel_length, MAX_BUFFER, &win->mel_active))
|
||||
win->mel_length = 0;
|
||||
if (gui_panel_shell(&panel, win->py_buffer, &win->py_length, MAX_BUFFER, &win->py_active))
|
||||
win->py_length = 0;
|
||||
gui_panel_hook_end(&panel, &win->hook);
|
||||
}
|
||||
|
||||
static void
|
||||
update_toolbar(struct toolbar_window *win, struct gui_layout *layout, struct demo_img *images,
|
||||
struct gui_input *in, struct gui_canvas *canvas, struct gui_config *config)
|
||||
{
|
||||
struct gui_panel_layout panel;
|
||||
gui_config_push_property(config, GUI_PROPERTY_PADDING, 5, 10);
|
||||
gui_panel_hook_begin_tiled(&panel, &win->hook, layout, GUI_SLOT_LEFT, 0, NULL, canvas, in);
|
||||
gui_panel_row(&panel, 45, 1);
|
||||
if (gui_panel_button_image(&panel, images->select, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "select button pressed!\n");
|
||||
if (gui_panel_button_image(&panel, images->lasso, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "lasso button pressed!\n");
|
||||
if (gui_panel_button_image(&panel, images->paint, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "paint button pressed!\n");
|
||||
if (gui_panel_button_image(&panel, images->move, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "move button pressed!\n");
|
||||
if (gui_panel_button_image(&panel, images->rotate, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "rotate button pressed!\n");
|
||||
if (gui_panel_button_image(&panel, images->scale, GUI_BUTTON_DEFAULT))
|
||||
fprintf(stdout, "scale button pressed!\n");
|
||||
gui_panel_hook_end(&panel, &win->hook);
|
||||
gui_config_pop_property(config);
|
||||
}
|
||||
|
||||
static void
|
||||
init_demo(struct demo_gui *gui, struct gui_font *font)
|
||||
{
|
||||
@ -717,101 +374,34 @@ init_demo(struct demo_gui *gui, struct gui_font *font)
|
||||
gui_buffer_init_fixed(buffer, memory, GUI_BUFFER_CLIPPING);
|
||||
gui_config_default(config);
|
||||
|
||||
/* background panels */
|
||||
gui_panel_hook_init(&gui->settings.hook, 0, 0, 0, 0, 0, config, font);
|
||||
gui_panel_hook_init(&gui->status.hook, 0, 0, 0, 0, GUI_PANEL_NO_HEADER, config, font);
|
||||
gui_panel_hook_init(&gui->tool.hook, 0, 0, 0, 0, GUI_PANEL_NO_HEADER, config, font);
|
||||
gui_panel_hook_init(&gui->menu.hook, 0, 0, 0, 0, GUI_PANEL_NO_HEADER, config, font);
|
||||
gui->settings.brush_tab = GUI_MINIMIZED;
|
||||
gui->settings.color_tab = GUI_MINIMIZED;
|
||||
gui->settings.texture_tab = GUI_MINIMIZED;
|
||||
|
||||
/* floating windows */
|
||||
gui_stack_clear(&gui->floating);
|
||||
init_show(&gui->show, config, font, &gui->floating);
|
||||
init_control(&gui->control, config, font, &gui->floating);
|
||||
}
|
||||
|
||||
static void
|
||||
background_demo(struct demo_gui *gui, struct gui_input *input, struct gui_command_buffer *buffer,
|
||||
gui_bool active)
|
||||
{
|
||||
struct gui_layout_config ratio;
|
||||
struct gui_command_buffer sub;
|
||||
struct gui_canvas canvas;
|
||||
struct menubar_window *menu = &gui->menu;
|
||||
struct toolbar_window *tool = &gui->tool;
|
||||
struct status_window *status = &gui->status;
|
||||
struct settings_window *settings = &gui->settings;
|
||||
|
||||
/* setup layout split to fit screen */
|
||||
ratio.right = 350.0f / gui->width;
|
||||
ratio.top = 140.0f / gui->height;
|
||||
ratio.left = 70.0f / gui->width;
|
||||
ratio.bottom = 48.0f / gui->height;
|
||||
ratio.centerv = 1.0f - (ratio.top + ratio.bottom);
|
||||
ratio.centerh = 1.0f - (ratio.right + ratio.left);
|
||||
gui_layout_init(&gui->layout, &ratio);
|
||||
|
||||
/* activate each used layout slot */
|
||||
gui_layout_begin(&gui->layout, gui->width, gui->height, active);
|
||||
gui_layout_slot(&gui->layout, GUI_SLOT_RIGHT, GUI_LAYOUT_VERTICAL, 1);
|
||||
gui_layout_slot(&gui->layout, GUI_SLOT_LEFT, GUI_LAYOUT_VERTICAL, 1);
|
||||
gui_layout_slot(&gui->layout, GUI_SLOT_TOP, GUI_LAYOUT_VERTICAL, 1);
|
||||
gui_layout_slot(&gui->layout, GUI_SLOT_BOTTOM, GUI_LAYOUT_VERTICAL, 1);
|
||||
|
||||
/* settings window */
|
||||
gui_buffer_lock(&canvas, buffer, &sub, 0, gui->width, gui->height);
|
||||
update_settings(settings, &gui->layout, input, &canvas);
|
||||
gui_buffer_unlock(gui_hook_output(&settings->hook), buffer, &sub, &canvas, NULL);
|
||||
|
||||
/* menubar window */
|
||||
gui_buffer_lock(&canvas, buffer, &sub, 0, gui->width, gui->height);
|
||||
update_menu(menu, &gui->layout, input, &canvas, gui);
|
||||
gui_buffer_unlock(gui_hook_output(&menu->hook), buffer, &sub, &canvas, NULL);
|
||||
|
||||
/* statusbar window */
|
||||
gui_buffer_lock(&canvas, buffer, &sub, 0, gui->width, gui->height);
|
||||
update_status(status, &gui->layout, input, &canvas);
|
||||
gui_buffer_unlock(gui_hook_output(&status->hook), buffer, &sub, &canvas, NULL);
|
||||
|
||||
/* toolbar window */
|
||||
gui_buffer_lock(&canvas, buffer, &sub, 0, gui->width, gui->height);
|
||||
update_toolbar(tool, &gui->layout, &gui->images, input, &canvas, &gui->config);
|
||||
gui_buffer_unlock(gui_hook_output(&tool->hook), buffer, &sub, &canvas, NULL);
|
||||
|
||||
gui_layout_end(&gui->background, &gui->layout);
|
||||
}
|
||||
|
||||
static void
|
||||
floating_demo(struct demo_gui *gui, struct gui_input *input, struct gui_command_buffer *buffer)
|
||||
{
|
||||
struct show_window *show = &gui->show;
|
||||
struct control_window *control = &gui->control;
|
||||
struct gui_command_buffer sub;
|
||||
struct gui_canvas canvas;
|
||||
|
||||
/* Show window */
|
||||
gui_buffer_lock(&canvas, buffer, &sub, 0, gui->width, gui->height);
|
||||
update_control(control, &gui->floating, input, &canvas, &gui->config);
|
||||
gui_buffer_unlock(gui_hook_output(&control->hook), buffer, &sub, &canvas, NULL);
|
||||
|
||||
/* control window */
|
||||
gui_hook_panel(&show->hook)->flags = control->show_flags;
|
||||
gui_buffer_lock(&canvas, buffer, &sub, 0, gui->width, gui->height);
|
||||
update_show(show, &gui->floating, input, &canvas);
|
||||
if (gui_hook_panel(&show->hook)->flags & GUI_PANEL_HIDDEN)
|
||||
control->show_flags |= GUI_PANEL_HIDDEN;
|
||||
gui_buffer_unlock(gui_hook_output(&show->hook), buffer, &sub, &canvas, NULL);
|
||||
gui_stack_clear(&gui->stack);
|
||||
init_show(&gui->show, config, font, &gui->stack);
|
||||
init_control(&gui->control, config, font, &gui->stack);
|
||||
}
|
||||
|
||||
static void
|
||||
run_demo(struct demo_gui *gui, struct gui_input *input)
|
||||
{
|
||||
struct gui_command_buffer *buffer = &gui->buffer;
|
||||
struct show_window *show = &gui->show;
|
||||
struct control_window *control = &gui->control;
|
||||
struct gui_command_buffer sub;
|
||||
struct gui_canvas canvas;
|
||||
|
||||
/* control window */
|
||||
gui_buffer_begin(NULL, buffer, gui->width, gui->height);
|
||||
background_demo(gui, input, buffer, gui->control.show_flags & GUI_PANEL_HIDDEN);
|
||||
floating_demo(gui, input, buffer);
|
||||
gui_buffer_lock(&canvas, buffer, &sub, 0, gui->width, gui->height);
|
||||
gui->running = update_control(control, &gui->stack, input, &canvas, &gui->config);
|
||||
gui_buffer_unlock(gui_hook_output(&control->hook), buffer, &sub, &canvas, NULL);
|
||||
|
||||
/* Show window */
|
||||
gui_hook_panel(&show->hook)->flags = control->show_flags;
|
||||
gui_buffer_lock(&canvas, buffer, &sub, 0, gui->width, gui->height);
|
||||
update_show(show, &gui->stack, input, &canvas);
|
||||
if (gui_hook_panel(&show->hook)->flags & GUI_PANEL_HIDDEN)
|
||||
control->show_flags |= GUI_PANEL_HIDDEN;
|
||||
gui_buffer_unlock(gui_hook_output(&show->hook), buffer, &sub, &canvas, NULL);
|
||||
gui_buffer_end(NULL, buffer, NULL, NULL);
|
||||
}
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
630
demo/opengl.c
Normal file
630
demo/opengl.c
Normal file
@ -0,0 +1,630 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
|
||||
#include "../gui.h"
|
||||
|
||||
/* macros */
|
||||
#define DTIME 16
|
||||
#define FONT_ATLAS_DEPTH 4
|
||||
#define CIRCLE_SEGMENTS 22
|
||||
|
||||
#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))
|
||||
|
||||
#include "demo.c"
|
||||
|
||||
struct texCoord {
|
||||
float u;
|
||||
float v;
|
||||
};
|
||||
|
||||
enum font_atlas_dimension {
|
||||
FONT_ATLAS_DIM_64 = 64,
|
||||
FONT_ATLAS_DIM_128 = 128,
|
||||
FONT_ATLAS_DIM_256 = 256,
|
||||
FONT_ATLAS_DIM_512 = 512,
|
||||
FONT_ATLAS_DIM_1024 = 1024,
|
||||
FONT_ATLAS_DIM_2048 = 2048
|
||||
};
|
||||
|
||||
struct font_atlas {
|
||||
enum font_atlas_dimension dim;
|
||||
gui_size range;
|
||||
gui_size size;
|
||||
gui_byte *memory;
|
||||
};
|
||||
|
||||
struct font_glyph {
|
||||
unsigned int code;
|
||||
float xadvance;
|
||||
short width, height;
|
||||
float xoff, yoff;
|
||||
struct texCoord uv[2];
|
||||
};
|
||||
|
||||
struct font {
|
||||
float height;
|
||||
float scale;
|
||||
GLuint texture;
|
||||
unsigned int glyph_count;
|
||||
struct font_glyph *glyphes;
|
||||
const struct font_glyph *fallback;
|
||||
};
|
||||
|
||||
struct demo {
|
||||
gui_char in_buf[MAX_BUFFER];
|
||||
gui_size in_len;
|
||||
gui_bool in_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_size cur;
|
||||
gui_bool tab_min;
|
||||
gui_float group_off;
|
||||
gui_float shelf_off;
|
||||
gui_bool toggle;
|
||||
};
|
||||
|
||||
static void
|
||||
die(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static char*
|
||||
file_load(const char* path, size_t* siz)
|
||||
{
|
||||
char *buf;
|
||||
FILE *fd = fopen(path, "rb");
|
||||
if (!fd) {
|
||||
fprintf(stderr, "Failed to open file: %s\n", path);
|
||||
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 void
|
||||
font_load_glyph(unsigned int code, struct font_glyph *glyph, FT_GlyphSlot slot)
|
||||
{
|
||||
glyph->code = code;
|
||||
glyph->width = (short)slot->bitmap.width;
|
||||
glyph->height = (short)slot->bitmap.rows;
|
||||
glyph->xoff = (float)slot->bitmap_left;
|
||||
glyph->yoff = (float)slot->bitmap_top;
|
||||
glyph->xadvance = (float)(slot->advance.x >> 6);
|
||||
}
|
||||
|
||||
static void
|
||||
font_load_glyphes(FT_Face face, struct font *font, size_t range)
|
||||
{
|
||||
size_t i;
|
||||
int ft_err;
|
||||
for (i = 0; i < range; ++i) {
|
||||
unsigned int index = FT_Get_Char_Index(face, i);
|
||||
if (!index) continue;
|
||||
ft_err = FT_Load_Glyph(face, index, 0);
|
||||
if (ft_err) continue;
|
||||
ft_err = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (ft_err) continue;
|
||||
font_load_glyph(index, &font->glyphes[i], face->glyph);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
font_pack_glyphes(struct font *font, float width, float height, size_t range)
|
||||
{
|
||||
size_t i;
|
||||
float xoff = 0, yoff = 0;
|
||||
float max_height = 0.0f;
|
||||
for (i = 0; i < range; ++i) {
|
||||
struct font_glyph *glyph = &font->glyphes[i];
|
||||
if ((xoff + glyph->width) > width) {
|
||||
yoff += max_height;
|
||||
max_height = 0.0f;
|
||||
xoff = 0.0f;
|
||||
}
|
||||
|
||||
glyph->uv[0].u = xoff / width;
|
||||
glyph->uv[0].v = yoff / height;
|
||||
glyph->uv[1].u = (xoff + glyph->width) / width;
|
||||
glyph->uv[1].v = (yoff + glyph->height) / height;
|
||||
if (glyph->height > max_height)
|
||||
max_height = glyph->height;
|
||||
xoff += glyph->width;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
font_atlas_blit(struct font_atlas *atlas, FT_GlyphSlot glyph,
|
||||
size_t off_x, size_t off_y)
|
||||
{
|
||||
size_t y, x;
|
||||
size_t width = glyph->bitmap.width;
|
||||
size_t height = glyph->bitmap.rows;
|
||||
const size_t pitch = atlas->dim * FONT_ATLAS_DEPTH;
|
||||
for (y = 0; y < height; y++) {
|
||||
size_t x_off = off_x * FONT_ATLAS_DEPTH;
|
||||
size_t y_off = (off_y + y) * pitch;
|
||||
unsigned char *dst = &atlas->memory[y_off + x_off];
|
||||
for (x = 0; x < width; ++x) {
|
||||
dst[0] = 255;
|
||||
dst[1] = 255;
|
||||
dst[2] = 255;
|
||||
dst[3] = glyph->bitmap.buffer[y * width + x];
|
||||
dst += FONT_ATLAS_DEPTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
font_bake_glyphes(FT_Face face, struct font_atlas *atlas,
|
||||
const struct font *font)
|
||||
{
|
||||
size_t i;
|
||||
int ft_err;
|
||||
for (i = 0; i < atlas->range; ++i) {
|
||||
size_t x, y;
|
||||
struct font_glyph *glyph = &font->glyphes[i];
|
||||
unsigned int index = FT_Get_Char_Index(face, i);
|
||||
|
||||
if (!index) continue;
|
||||
ft_err = FT_Load_Glyph(face, index, 0);
|
||||
if (ft_err) continue;
|
||||
ft_err = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
|
||||
if (ft_err) continue;
|
||||
|
||||
x = (gui_size)(glyph->uv[0].u * (gui_float)atlas->dim);
|
||||
y = (gui_size)(glyph->uv[0].v * (gui_float)atlas->dim);
|
||||
font_atlas_blit(atlas, face->glyph, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
font_load(struct font *font, struct font_atlas *atlas, unsigned int height,
|
||||
const unsigned char *data, size_t size)
|
||||
{
|
||||
int ret = 1;
|
||||
FT_Library ft_lib;
|
||||
FT_Face ft_face;
|
||||
|
||||
assert(font);
|
||||
assert(atlas);
|
||||
assert(font->glyphes);
|
||||
assert(atlas->memory);
|
||||
|
||||
if (!font || !atlas)
|
||||
return gui_false;
|
||||
if (!font->glyphes || !atlas->memory)
|
||||
return gui_false;
|
||||
if (FT_Init_FreeType(&ft_lib))
|
||||
return gui_false;
|
||||
if (FT_New_Memory_Face(ft_lib, data, (FT_Long)size, 0, &ft_face))
|
||||
goto cleanup;
|
||||
if (FT_Select_Charmap(ft_face, FT_ENCODING_UNICODE))
|
||||
goto failed;
|
||||
if (FT_Set_Char_Size(ft_face, height << 6, height << 6, 96, 96))
|
||||
goto failed;
|
||||
|
||||
font_load_glyphes(ft_face, font, atlas->range);
|
||||
font_pack_glyphes(font, atlas->dim, atlas->dim, atlas->range);
|
||||
font_bake_glyphes(ft_face, atlas, font);
|
||||
|
||||
failed:
|
||||
FT_Done_Face(ft_face);
|
||||
cleanup:
|
||||
FT_Done_FreeType(ft_lib);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gui_size
|
||||
font_get_text_width(void *handle, const gui_char *t, gui_size l)
|
||||
{
|
||||
long unicode;
|
||||
size_t text_width = 0;
|
||||
const struct font_glyph *glyph;
|
||||
size_t text_len = 0;
|
||||
size_t glyph_len;
|
||||
struct font *font = handle;
|
||||
assert(font);
|
||||
if (!t || !l) return 0;
|
||||
|
||||
glyph_len = gui_utf_decode(t, &unicode, l);
|
||||
while (text_len <= l && glyph_len) {
|
||||
if (unicode == GUI_UTF_INVALID) return 0;
|
||||
glyph = (unicode < font->glyph_count) ? &font->glyphes[unicode] : font->fallback;
|
||||
glyph = (glyph->code == 0) ? font->fallback : glyph;
|
||||
|
||||
text_width += (gui_size)((float)glyph->xadvance * font->scale);
|
||||
glyph_len = gui_utf_decode(t + text_len, &unicode, l - text_len);
|
||||
text_len += glyph_len;
|
||||
}
|
||||
return text_width;
|
||||
}
|
||||
|
||||
static void
|
||||
font_draw_text(const struct font *font, float x, float y, float h,
|
||||
struct gui_color color, const unsigned char *text, size_t len)
|
||||
{
|
||||
struct gui_rect clip;
|
||||
size_t text_len;
|
||||
long unicode;
|
||||
const struct font_glyph *g;
|
||||
|
||||
text_len = gui_utf_decode(text, &unicode, len);
|
||||
glBindTexture(GL_TEXTURE_2D, font->texture);
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glBegin(GL_QUADS);
|
||||
while (text_len <= len) {
|
||||
float gx, gy, gh, gw, char_width = 0;
|
||||
if (unicode == GUI_UTF_INVALID) break;
|
||||
g = (unicode < font->glyph_count) ?
|
||||
&font->glyphes[unicode] :
|
||||
font->fallback;
|
||||
g = (g->code == 0) ? font->fallback : g;
|
||||
|
||||
|
||||
gw = (float)g->width * font->scale;
|
||||
gh = (float)g->height * font->scale;
|
||||
gx = x + g->xoff * font->scale;
|
||||
gy = y + (h / 2) - (g->yoff * font->scale);
|
||||
char_width = g->xadvance * font->scale;
|
||||
|
||||
glTexCoord2f(g->uv[0].u, g->uv[0].v);
|
||||
glVertex2f(gx, gy);
|
||||
glTexCoord2f(g->uv[1].u, g->uv[0].v);
|
||||
glVertex2f(gx + gw, gy);
|
||||
glTexCoord2f(g->uv[1].u, g->uv[1].v);
|
||||
glVertex2f(gx + gw, gy + gh);
|
||||
glTexCoord2f(g->uv[0].u, g->uv[1].v);
|
||||
glVertex2f(gx, gy + gh);
|
||||
text_len += gui_utf_decode(text + text_len, &unicode, len - text_len);
|
||||
x += char_width;
|
||||
}
|
||||
glEnd();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
font_del(struct font *font)
|
||||
{
|
||||
glDeleteTextures(1, &font->texture);
|
||||
free(font->glyphes);
|
||||
free(font);
|
||||
}
|
||||
|
||||
static struct font*
|
||||
font_new(const char *path, unsigned int font_height, unsigned int bake_height,
|
||||
size_t range, enum font_atlas_dimension dim)
|
||||
{
|
||||
gui_byte *ttf_blob;
|
||||
gui_size ttf_blob_size;
|
||||
struct font_atlas atlas;
|
||||
struct font *font = calloc(sizeof(struct font), 1);
|
||||
|
||||
atlas.dim = dim;
|
||||
atlas.range = range;
|
||||
atlas.size = atlas.dim * atlas.dim * FONT_ATLAS_DEPTH;
|
||||
atlas.memory = calloc((gui_size)atlas.size, 1);
|
||||
|
||||
font->glyph_count = (unsigned int)atlas.range;
|
||||
font->glyphes = calloc(atlas.range, sizeof(struct font_glyph));
|
||||
font->fallback = &font->glyphes['?'];
|
||||
font->scale = (float)font_height / (gui_float)bake_height;
|
||||
font->height = (float)font_height;
|
||||
|
||||
ttf_blob = (unsigned char*)file_load(path, &ttf_blob_size);
|
||||
if (!font_load(font, &atlas, bake_height, ttf_blob, ttf_blob_size))
|
||||
goto failed;
|
||||
|
||||
glGenTextures(1, &font->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, font->texture);
|
||||
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);
|
||||
font_del(font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_line(float x0, float y0, float x1, float y1, struct gui_color color)
|
||||
{
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glBegin(GL_LINES);
|
||||
glVertex2f(x0, y0);
|
||||
glVertex2f(x1, y1);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void
|
||||
draw_rect(float x, float y, float w, float h, struct gui_color color)
|
||||
{
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(x, y);
|
||||
glVertex2f(x + w, y);
|
||||
glVertex2f(x + w, y + h);
|
||||
glVertex2f(x, y + h);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void
|
||||
draw_circle(float x, float y, float r, struct gui_color color)
|
||||
{
|
||||
int i;
|
||||
float a0 = 0.0f;
|
||||
const float a_step = (2 * 3.141592654f)/22.0f;
|
||||
x += r; y += r;
|
||||
glColor4ub(color.r, color.g, color.b, color.a);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (i = 0; i < CIRCLE_SEGMENTS; i++) {
|
||||
const float a1 = ((i + 1) == CIRCLE_SEGMENTS) ? 0.0f : a0 + a_step;
|
||||
const float p0x = x + (float)cos(a0) * r;
|
||||
const float p0y = y + (float)sin(a0) * r;
|
||||
const float p1x = x + (float)cos(a1) * r;
|
||||
const float p1y = y + (float)sin(a1) * r;
|
||||
|
||||
glVertex2f(p0x, p0y);
|
||||
glVertex2f(p1x, p1y);
|
||||
glVertex2f(x, y);
|
||||
a0 = a1;
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void
|
||||
execute(struct gui_command_list *list, int width, int height)
|
||||
{
|
||||
static const struct gui_color col = {255, 0, 0, 255};
|
||||
const struct gui_command *cmd;
|
||||
if (!list->count) 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);
|
||||
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();
|
||||
|
||||
gui_list_for_each(cmd, list) {
|
||||
switch (cmd->type) {
|
||||
case GUI_COMMAND_NOP: break;
|
||||
case GUI_COMMAND_SCISSOR: {
|
||||
const struct gui_command_scissor *s = GUI_FETCH(scissor, cmd);
|
||||
glScissor(s->x, height - (s->y + s->h), s->w, s->h);
|
||||
} break;
|
||||
case GUI_COMMAND_LINE: {
|
||||
const struct gui_command_line *l = GUI_FETCH(line, cmd);
|
||||
draw_line(l->begin[0], l->begin[1], l->end[0], l->end[1], l->color);
|
||||
} break;
|
||||
case GUI_COMMAND_RECT: {
|
||||
const struct gui_command_rect *r = GUI_FETCH(rect, cmd);
|
||||
draw_rect(r->x, r->y, r->w, r->h, r->color);
|
||||
} break;
|
||||
case GUI_COMMAND_CIRCLE: {
|
||||
const struct gui_command_circle *c = GUI_FETCH(circle, cmd);
|
||||
draw_circle(c->x, c->y, (float)c->w / 2.0f, c->color);
|
||||
} break;
|
||||
case GUI_COMMAND_TRIANGLE: {
|
||||
const struct gui_command_triangle *t = GUI_FETCH(triangle, cmd);
|
||||
glColor4ub(t->color.r, t->color.g, t->color.b, t->color.a);
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex2f(t->a[0], t->a[1]);
|
||||
glVertex2f(t->b[0], t->b[1]);
|
||||
glVertex2f(t->c[0], t->c[1]);
|
||||
glEnd();
|
||||
} break;
|
||||
case GUI_COMMAND_TEXT: {
|
||||
const struct gui_command_text *t = GUI_FETCH(text, cmd);
|
||||
font_draw_text(t->font, t->x, t->y, t->h, t->fg, t->string, t->length);
|
||||
} break;
|
||||
case GUI_COMMAND_IMAGE:
|
||||
case GUI_COMMAND_MAX:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
static void
|
||||
draw(struct gui_panel_stack *stack, int width, int height)
|
||||
{
|
||||
struct gui_panel_hook *iter;
|
||||
gui_stack_for_each(iter, stack)
|
||||
execute(gui_hook_output(iter), width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
key(struct gui_input *in, SDL_Event *evt, gui_bool down)
|
||||
{
|
||||
SDL_Keycode sym = evt->key.keysym.sym;
|
||||
if (sym == SDLK_LCTRL || sym == SDLK_RCTRL)
|
||||
gui_input_key(in, GUI_KEY_CTRL, down);
|
||||
else if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT)
|
||||
gui_input_key(in, GUI_KEY_SHIFT, down);
|
||||
else if (sym == SDLK_DELETE)
|
||||
gui_input_key(in, GUI_KEY_DEL, down);
|
||||
else if (sym == SDLK_RETURN)
|
||||
gui_input_key(in, GUI_KEY_ENTER, down);
|
||||
else if (sym == SDLK_SPACE)
|
||||
gui_input_key(in, GUI_KEY_SPACE, down);
|
||||
else if (sym == SDLK_BACKSPACE)
|
||||
gui_input_key(in, GUI_KEY_BACKSPACE, down);
|
||||
}
|
||||
|
||||
static void
|
||||
motion(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
|
||||
btn(struct gui_input *in, SDL_Event *evt, gui_bool down)
|
||||
{
|
||||
const gui_int x = evt->button.x;
|
||||
const gui_int y = evt->button.y;
|
||||
if (evt->button.button == SDL_BUTTON_LEFT)
|
||||
gui_input_button(in, x, y, down);
|
||||
}
|
||||
|
||||
static void
|
||||
text(struct gui_input *in, SDL_Event *evt)
|
||||
{
|
||||
gui_glyph glyph;
|
||||
memcpy(glyph, evt->text.text, GUI_UTF_SIZE);
|
||||
gui_input_char(in, glyph);
|
||||
}
|
||||
|
||||
static void
|
||||
resize(SDL_Event *evt)
|
||||
{
|
||||
if (evt->window.event != SDL_WINDOWEVENT_RESIZED) return;
|
||||
glViewport(0, 0, evt->window.data1, evt->window.data2);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
/* Platform */
|
||||
const char *font_path;
|
||||
SDL_Window *win;
|
||||
SDL_GLContext glContext;
|
||||
struct font *glfont;
|
||||
int win_width, win_height;
|
||||
unsigned int started;
|
||||
unsigned int dt;
|
||||
int width = 0, height = 0;
|
||||
|
||||
/* GUI */
|
||||
struct gui_input in;
|
||||
struct gui_font font;
|
||||
struct demo_gui gui;
|
||||
|
||||
font_path = argv[1];
|
||||
if (argc < 2) {
|
||||
fprintf(stdout, "Missing TTF Font file argument!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* SDL */
|
||||
SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
win = SDL_CreateWindow("Demo",
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN);
|
||||
glContext = SDL_GL_CreateContext(win);
|
||||
SDL_GetWindowSize(win, &win_width, &win_height);
|
||||
glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
glfont = font_new(font_path, 10, 12, 255, FONT_ATLAS_DIM_256);
|
||||
|
||||
/* GUI */
|
||||
memset(&in, 0, sizeof in);
|
||||
memset(&gui, 0, sizeof gui);
|
||||
font.userdata = glfont;
|
||||
font.height = glfont->height;
|
||||
font.width = font_get_text_width;
|
||||
init_demo(&gui, &font);
|
||||
|
||||
while (gui.running) {
|
||||
/* Input */
|
||||
SDL_Event evt;
|
||||
started = SDL_GetTicks();
|
||||
gui_input_begin(&in);
|
||||
while (SDL_PollEvent(&evt)) {
|
||||
if (evt.type == SDL_WINDOWEVENT) resize(&evt);
|
||||
else if (evt.type == SDL_QUIT) goto cleanup;
|
||||
else if (evt.type == SDL_KEYUP) key(&in, &evt, gui_false);
|
||||
else if (evt.type == SDL_KEYDOWN) key(&in, &evt, gui_true);
|
||||
else if (evt.type == SDL_MOUSEBUTTONDOWN) btn(&in, &evt, gui_true);
|
||||
else if (evt.type == SDL_MOUSEBUTTONUP) btn(&in, &evt, gui_false);
|
||||
else if (evt.type == SDL_MOUSEMOTION) motion(&in, &evt);
|
||||
else if (evt.type == SDL_TEXTINPUT) text(&in, &evt);
|
||||
}
|
||||
gui_input_end(&in);
|
||||
|
||||
/* GUI */
|
||||
SDL_GetWindowSize(win, &width, &height);
|
||||
gui.width = (gui_size)width;
|
||||
gui.height = (gui_size)height;
|
||||
run_demo(&gui, &in);
|
||||
|
||||
/* Draw */
|
||||
glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
draw(&gui.stack, width, height);
|
||||
SDL_GL_SwapWindow(win);
|
||||
|
||||
/* Timing */
|
||||
dt = SDL_GetTicks() - started;
|
||||
if (dt < DTIME)
|
||||
SDL_Delay(DTIME - dt);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* Cleanup */
|
||||
free(gui.memory.memory);
|
||||
font_del(glfont);
|
||||
SDL_GL_DeleteContext(glContext);
|
||||
SDL_DestroyWindow(win);
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
|
49
demo/win32.c
49
demo/win32.c
@ -247,21 +247,6 @@ surface_draw_text(XSurface *surf, XFont *font, short x, short y, unsigned short
|
||||
SelectObject(surf->hdc, old);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_image(XSurface *surf, HBITMAP img, short x, short y, unsigned short w, unsigned short h)
|
||||
{
|
||||
HDC mem;
|
||||
BITMAP bitmap;
|
||||
HGDIOBJ old;
|
||||
|
||||
mem = CreateCompatibleDC(surf->hdc);
|
||||
old = SelectObject(mem, img);
|
||||
GetObject(img, sizeof(bitmap), &bitmap);
|
||||
StretchBlt(surf->hdc, x, y, w, h, mem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
|
||||
SelectObject(mem, old);
|
||||
DeleteDC(mem);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_clear(XSurface *surf, unsigned char r, unsigned char g, unsigned char b)
|
||||
{surface_draw_rect(surf, 0, 0, (unsigned short)surf->width, (unsigned short)surf->height, r, g, b);}
|
||||
@ -317,11 +302,7 @@ execute(XSurface *surf, struct gui_command_list *list)
|
||||
surface_draw_text(surf, win->font, t->x, t->y, t->w, t->h, (const char*)t->string,
|
||||
t->length, t->bg.r, t->bg.g, t->bg.b, t->fg.r, t->fg.g, t->fg.b);
|
||||
} break;
|
||||
case GUI_COMMAND_IMAGE: {
|
||||
const struct gui_command_image *i = GUI_FETCH(image, cmd);
|
||||
HBITMAP bitmap = i->img;
|
||||
surface_draw_image(surf, bitmap, i->x, i->y, i->w, i->h);
|
||||
} break;
|
||||
case GUI_COMMAND_IMAGE:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -398,19 +379,6 @@ wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return 0;
|
||||
}
|
||||
|
||||
HBITMAP
|
||||
loadimg(const char *path)
|
||||
{
|
||||
HBITMAP bitmap;
|
||||
DWORD ret = 0;
|
||||
TCHAR buffer[4 *1024];
|
||||
TCHAR ** lppPart = {NULL};
|
||||
ret = GetFullPathName(path, 4 * 1024, buffer, lppPart);
|
||||
bitmap = (HBITMAP)LoadImage(NULL, buffer, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
|
||||
assert(bitmap);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
INT WINAPI
|
||||
WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR lpCmdLine, int shown)
|
||||
{
|
||||
@ -453,13 +421,6 @@ WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR lpCmdLine, int shown)
|
||||
gui.running = gui_true;
|
||||
init_demo(&gui, &font);
|
||||
|
||||
gui.images.select = loadimg("icon/select.bmp");
|
||||
gui.images.lasso = loadimg("icon/lasso.bmp");
|
||||
gui.images.paint = loadimg("icon/paint.bmp");
|
||||
gui.images.move = loadimg("icon/move.bmp");
|
||||
gui.images.rotate = loadimg("icon/rotate.bmp");
|
||||
gui.images.scale = loadimg("icon/scale.bmp");
|
||||
|
||||
while (gui.running && !quit) {
|
||||
/* Input */
|
||||
MSG msg;
|
||||
@ -485,8 +446,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR lpCmdLine, int shown)
|
||||
/* Draw */
|
||||
surface_begin(xw.backbuffer);
|
||||
surface_clear(xw.backbuffer, 100, 100, 100);
|
||||
draw(xw.backbuffer, &gui.background);
|
||||
draw(xw.backbuffer, &gui.floating);
|
||||
draw(xw.backbuffer, &gui.stack);
|
||||
surface_end(xw.backbuffer, xw.hdc);
|
||||
|
||||
/* Timing */
|
||||
@ -495,11 +455,6 @@ WinMain(HINSTANCE hInstance, HINSTANCE prev, LPSTR lpCmdLine, int shown)
|
||||
}
|
||||
|
||||
free(gui.memory.memory);
|
||||
DeleteObject(gui.images.select);
|
||||
DeleteObject(gui.images.paint);
|
||||
DeleteObject(gui.images.move);
|
||||
DeleteObject(gui.images.rotate);
|
||||
DeleteObject(gui.images.scale);
|
||||
font_del(xw.font);
|
||||
surface_del(xw.backbuffer);
|
||||
ReleaseDC(xw.hWnd, xw.hdc);
|
||||
|
484
demo/xlib.c
Normal file
484
demo/xlib.c
Normal file
@ -0,0 +1,484 @@
|
||||
#include <assert.h>
|
||||
#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 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))
|
||||
|
||||
#include "demo.c"
|
||||
|
||||
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;
|
||||
gui_size clip_depth;
|
||||
};
|
||||
|
||||
struct XWindow {
|
||||
Display *dpy;
|
||||
Window root;
|
||||
Visual *vis;
|
||||
XFont *font;
|
||||
XSurface *surf;
|
||||
Colormap cmap;
|
||||
XWindowAttributes attr;
|
||||
XSetWindowAttributes swa;
|
||||
Window win;
|
||||
int screen;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
};
|
||||
|
||||
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 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 unsigned long
|
||||
color_from_byte(struct gui_color col)
|
||||
{
|
||||
/* NOTE(vurtun): this only works for little-endian */
|
||||
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 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;
|
||||
if (surf->w == w && surf->h == h) 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, float x, float y, float w, float 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, gui_short x0, gui_short y0, gui_short x1,
|
||||
gui_short y1, struct gui_color col)
|
||||
{
|
||||
unsigned long c = color_from_byte(col);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XDrawLine(surf->dpy, surf->drawable, surf->gc, (int)x0, (int)y0, (int)x1, (int)y1);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_rect(XSurface* surf, gui_short x, gui_short y, gui_ushort w,
|
||||
gui_ushort h, struct gui_color col)
|
||||
{
|
||||
unsigned long c = color_from_byte(col);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_triangle(XSurface *surf, gui_short x0, gui_short y0, gui_short x1,
|
||||
gui_short y1, gui_short x2, gui_short y2, struct gui_color col)
|
||||
{
|
||||
XPoint pnts[3];
|
||||
unsigned long c = color_from_byte(col);
|
||||
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, gui_short x, gui_short y, gui_ushort w,
|
||||
gui_ushort h, struct gui_color col)
|
||||
{
|
||||
unsigned long c = color_from_byte(col);
|
||||
XSetForeground(surf->dpy, surf->gc, c);
|
||||
XFillArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y,
|
||||
(unsigned)w, (unsigned)h, 0, 360 * 64);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_draw_text(XSurface *surf, gui_short x, gui_short y, gui_ushort w, gui_ushort h,
|
||||
const char *text, size_t len, XFont *font, struct gui_color cbg, struct gui_color cfg)
|
||||
{
|
||||
int i, tx, ty, th, olen;
|
||||
unsigned long bg = color_from_byte(cbg);
|
||||
unsigned long fg = color_from_byte(cfg);
|
||||
|
||||
XSetForeground(surf->dpy, surf->gc, bg);
|
||||
XFillRectangle(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, (unsigned)w, (unsigned)h);
|
||||
if(!text || !font || !len) return;
|
||||
|
||||
tx = (int)x;
|
||||
th = font->ascent + font->descent;
|
||||
ty = (int)y + ((int)h / 2) - (th / 2) + font->ascent;
|
||||
XSetForeground(surf->dpy, surf->gc, fg);
|
||||
if(font->set)
|
||||
XmbDrawString(surf->dpy,surf->drawable,font->set,surf->gc,tx,ty,(const char*)text,(int)len);
|
||||
else
|
||||
XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)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 void
|
||||
execute(XSurface *surf, struct gui_command_list *list)
|
||||
{
|
||||
const struct gui_command *cmd;
|
||||
gui_list_for_each(cmd, list) {
|
||||
switch (cmd->type) {
|
||||
case GUI_COMMAND_NOP: break;
|
||||
case GUI_COMMAND_SCISSOR: {
|
||||
const struct gui_command_scissor *s = GUI_FETCH(scissor, cmd);
|
||||
surface_scissor(surf, s->x, s->y, s->w, s->h);
|
||||
} break;
|
||||
case GUI_COMMAND_LINE: {
|
||||
const struct gui_command_line *l = GUI_FETCH(line, cmd);
|
||||
surface_draw_line(surf, l->begin[0], l->begin[1], l->end[0],
|
||||
l->end[1], l->color);
|
||||
} break;
|
||||
case GUI_COMMAND_RECT: {
|
||||
const struct gui_command_rect *r = GUI_FETCH(rect, cmd);
|
||||
surface_draw_rect(surf, r->x, r->y, r->w, r->h, r->color);
|
||||
} break;
|
||||
case GUI_COMMAND_CIRCLE: {
|
||||
const struct gui_command_circle *c = GUI_FETCH(circle, cmd);
|
||||
surface_draw_circle(surf, c->x, c->y, c->w, c->h, c->color);
|
||||
} break;
|
||||
case GUI_COMMAND_TRIANGLE: {
|
||||
const struct gui_command_triangle *t = GUI_FETCH(triangle, cmd);
|
||||
surface_draw_triangle(surf, t->a[0], t->a[1], t->b[0], t->b[1],
|
||||
t->c[0], t->c[1], t->color);
|
||||
} break;
|
||||
case GUI_COMMAND_TEXT: {
|
||||
const struct gui_command_text *t = GUI_FETCH(text, cmd);
|
||||
surface_draw_text(surf, t->x, t->y, t->w, t->h, (const char*)t->string,
|
||||
t->length, t->font, t->bg, t->fg);
|
||||
} break;
|
||||
case GUI_COMMAND_IMAGE:
|
||||
case GUI_COMMAND_MAX:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
draw(XSurface *surf, struct gui_panel_stack *stack)
|
||||
{
|
||||
struct gui_panel_hook *iter;
|
||||
gui_stack_for_each(iter, stack)
|
||||
execute(surf, gui_hook_output(iter));
|
||||
}
|
||||
|
||||
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);
|
||||
else if (*code > 32 && *code < 128 && !down) {
|
||||
gui_glyph glyph;
|
||||
glyph[0] = (gui_char)*code;
|
||||
gui_input_char(in, glyph);
|
||||
}
|
||||
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
|
||||
btn(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);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
long dt;
|
||||
long started;
|
||||
XWindow xw;
|
||||
|
||||
struct gui_input in;
|
||||
struct gui_font font;
|
||||
struct demo_gui gui;
|
||||
|
||||
/* Platform */
|
||||
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, WINDOW_WIDTH, WINDOW_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;
|
||||
xw.surf = surface_create(xw.dpy, xw.screen, xw.win, xw.width, xw.height);
|
||||
xw.font = font_create(xw.dpy, "fixed");
|
||||
|
||||
/* GUI */
|
||||
memset(&in, 0, sizeof in);
|
||||
memset(&gui, 0, sizeof gui);
|
||||
font.userdata = xw.font;
|
||||
font.height = (gui_float)xw.font->height;
|
||||
font.width = font_get_text_width;
|
||||
init_demo(&gui, &font);
|
||||
|
||||
while (gui.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) btn(&in, &evt, gui_true);
|
||||
else if (evt.type == ButtonRelease) btn(&in, &evt, gui_false);
|
||||
else if (evt.type == MotionNotify) motion(&in, &evt);
|
||||
else if (evt.type == Expose || evt.type == ConfigureNotify)
|
||||
resize(&xw, xw.surf);
|
||||
}
|
||||
gui_input_end(&in);
|
||||
|
||||
/* GUI */
|
||||
gui.width = xw.width;
|
||||
gui.height = xw.height;
|
||||
run_demo(&gui, &in);
|
||||
|
||||
/* Draw */
|
||||
XClearWindow(xw.dpy, xw.win);
|
||||
surface_clear(xw.surf, 0x00646464);
|
||||
draw(xw.surf, &gui.stack);
|
||||
surface_blit(xw.win, xw.surf, xw.width, xw.height);
|
||||
XFlush(xw.dpy);
|
||||
|
||||
/* Timing */
|
||||
dt = timestamp() - started;
|
||||
if (dt < DTIME)
|
||||
sleep_for(DTIME - dt);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(gui.memory.memory);
|
||||
font_del(xw.dpy, xw.font);
|
||||
surface_del(xw.surf);
|
||||
XUnmapWindow(xw.dpy, xw.win);
|
||||
XFreeColormap(xw.dpy, xw.cmap);
|
||||
XDestroyWindow(xw.dpy, xw.win);
|
||||
XCloseDisplay(xw.dpy);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user