eco2d/code/game/source/editors/texed_widgets.c

687 lines
27 KiB
C
Raw Normal View History

2021-05-15 15:19:50 +00:00
static inline
void int_to_hex_color(uint32_t color, char *text);
2021-05-15 20:09:25 +00:00
static inline
int GuiDropdownBoxEco(Rectangle bounds, char const *text, char const *caption, int *active, bool editMode);
2021-05-17 05:53:10 +00:00
static inline
bool GuiValueBoxEco(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode);
2021-05-15 15:19:50 +00:00
2021-05-16 12:40:30 +00:00
static inline
bool IsCtrlAcceleratorPressed(char key);
2021-05-18 07:19:01 +00:00
static inline
char const *prettify_op_name(int idx);
2021-05-15 15:19:50 +00:00
void texed_draw_topbar(zpl_aabb2 r) {
zpl_aabb2 zoom_ctrl_r = zpl_aabb2_cut_left(&r, 150.0f);
zoom = GuiSlider(aabb2_ray(zoom_ctrl_r), "zoom: ", zpl_bprintf("%.02f x", zoom), zoom, 1.0f, 16.0f);
2021-05-16 11:36:01 +00:00
if (zoom != old_zoom) {
ctx.is_saved = false;
old_zoom = zoom;
}
2021-05-15 15:19:50 +00:00
zpl_aabb2_cut_left(&r, 100.0f);
2021-05-17 19:27:56 +00:00
zpl_aabb2 render_tiles_ctrl_r = zpl_aabb2_cut_left(&r, 150.0f);
render_tiles = (int)GuiSlider(aabb2_ray(render_tiles_ctrl_r), "tiles: ", zpl_bprintf("%d", render_tiles+1), render_tiles, 0.0f, 50.0f);
zpl_aabb2_cut_left(&r, 100.0f);
2021-05-15 15:19:50 +00:00
zpl_aabb2 new_prj_r = zpl_aabb2_cut_left(&r, 60.0f);
2021-05-16 12:07:28 +00:00
static bool new_pending = false;
2021-05-15 15:19:50 +00:00
2021-05-16 12:40:30 +00:00
if (GuiButton(aabb2_ray(new_prj_r), "NEW") || IsCtrlAcceleratorPressed('n')) {
2021-05-16 12:07:28 +00:00
if (ctx.is_saved) {
2021-05-17 05:53:10 +00:00
texed_clear();
2021-05-16 12:07:28 +00:00
texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT);
} else {
new_pending = true;
2021-05-16 12:40:30 +00:00
texed_msgbox_init("Discard unsaved work?", "You have an unsaved work! Do you want to proceed?", "OK;Cancel");
2021-05-16 12:07:28 +00:00
}
}
if (new_pending && ctx.msgbox.result != -1) {
new_pending = false;
2021-05-16 12:40:30 +00:00
if (ctx.msgbox.result == 1) {
2021-05-17 05:53:10 +00:00
texed_clear();
2021-05-16 12:07:28 +00:00
texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT);
}
2021-05-16 12:40:30 +00:00
ctx.msgbox.result = -1; // NOTE(zaklaus): ensure we don't re-trigger this branch next frame
2021-05-15 15:19:50 +00:00
}
zpl_aabb2 load_prj_r = zpl_aabb2_cut_left(&r, 60.0f);
static bool load_pending = false;
2021-05-16 12:40:30 +00:00
if (GuiButton(aabb2_ray(load_prj_r), "LOAD") || IsCtrlAcceleratorPressed('o')) {
2021-05-15 15:19:50 +00:00
load_pending = true;
2021-05-16 12:07:28 +00:00
if (ctx.is_saved) {
ctx.fileDialog.fileDialogActive = true;
} else {
2021-05-16 12:40:30 +00:00
texed_msgbox_init("Discard unsaved work?", "You have an unsaved work! Do you want to proceed?", "OK;Cancel");
2021-05-16 12:07:28 +00:00
}
2021-05-15 15:19:50 +00:00
}
if (ctx.fileDialog.SelectFilePressed && load_pending) {
ctx.fileDialog.SelectFilePressed = false;
if (IsFileExtension(ctx.fileDialog.fileNameText, ".ecotex")) {
2021-05-17 19:10:12 +00:00
strcpy(filename, GetFileNameWithoutExt(ctx.fileDialog.fileNameText));
2021-05-15 15:19:50 +00:00
ctx.filepath = filename;
load_pending = false;
texed_load();
} else {
ctx.fileDialog.fileDialogActive = true;
}
}
2021-05-16 12:07:28 +00:00
if (load_pending && ctx.msgbox.result != -1) {
2021-05-16 12:40:30 +00:00
if (ctx.msgbox.result == 1) {
2021-05-16 12:07:28 +00:00
ctx.fileDialog.fileDialogActive = true;
}
else load_pending = false;
2021-05-16 12:40:30 +00:00
ctx.msgbox.result = -1; // NOTE(zaklaus): ensure we don't re-trigger this branch next frame
2021-05-16 12:07:28 +00:00
}
2021-05-15 15:19:50 +00:00
zpl_aabb2 save_prj_r = zpl_aabb2_cut_left(&r, 60.0f);
static bool save_as_pending = false;
2021-05-16 12:40:30 +00:00
if (GuiButton(aabb2_ray(save_prj_r), "SAVE") || IsCtrlAcceleratorPressed('s')) {
2021-05-15 15:19:50 +00:00
if (ctx.filepath == NULL) {
save_as_pending = true;
ctx.fileDialog.fileDialogActive = true;
} else {
texed_save();
}
}
zpl_aabb2 save_as_prj_r = zpl_aabb2_cut_left(&r, 60.0f);
if (GuiButton(aabb2_ray(save_as_prj_r), "SAVE AS")) {
save_as_pending = true;
ctx.fileDialog.fileDialogActive = true;
}
if (ctx.fileDialog.SelectFilePressed && save_as_pending) {
ctx.fileDialog.SelectFilePressed = false;
2021-05-16 11:36:01 +00:00
if (TextLength(ctx.fileDialog.fileNameText)) {
2021-05-17 19:10:12 +00:00
strcpy(filename, GetFileNameWithoutExt(ctx.fileDialog.fileNameText));
2021-05-16 11:36:01 +00:00
ctx.filepath = filename;
save_as_pending = false;
texed_save();
} else {
ctx.fileDialog.fileDialogActive = true;
2021-05-15 15:19:50 +00:00
}
}
2021-05-16 13:15:44 +00:00
zpl_aabb2 split_r = zpl_aabb2_cut_left(&r, 5.0f);
split_r = zpl_aabb2_contract(&split_r, 2.0f);
DrawAABB(split_r, BLACK);
2021-05-15 15:19:50 +00:00
2021-05-16 13:15:44 +00:00
zpl_aabb2 exports_r = zpl_aabb2_cut_left(&r, 240.0f);
2021-05-15 15:19:50 +00:00
GuiSetState(ctx.filepath ? GUI_STATE_NORMAL : GUI_STATE_DISABLED);
2021-05-16 13:15:44 +00:00
zpl_aabb2 export_code_r = zpl_aabb2_cut_left(&exports_r, 120.0f);
2021-05-15 15:19:50 +00:00
if (GuiButton(aabb2_ray(export_code_r), "BUILD TEXTURE")) {
2021-05-16 09:10:33 +00:00
texed_export_cc(ctx.filepath);
2021-05-15 15:19:50 +00:00
}
2021-05-16 13:15:44 +00:00
zpl_aabb2 export_img_r = zpl_aabb2_cut_left(&exports_r, 120.0f);
2021-05-15 15:19:50 +00:00
if (GuiButton(aabb2_ray(export_img_r), "EXPORT AS IMAGE")) {
2021-05-16 09:10:33 +00:00
texed_export_png(ctx.filepath);
2021-05-15 15:19:50 +00:00
}
GuiSetState(GUI_STATE_NORMAL);
2021-05-16 13:15:44 +00:00
zpl_aabb2 prj_name_r = zpl_aabb2_cut_right(&r, 200.0f);
zpl_aabb2_cut_right(&prj_name_r, 15.0f);
GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_RIGHT);
2021-05-17 19:27:56 +00:00
GuiDrawText(zpl_bprintf("Project: %s%s", ctx.filepath ? ctx.filepath : "(unnamed)", ctx.is_saved ? "" : "*"), GetTextBounds(LABEL, aabb2_ray(prj_name_r)), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(GREEN, guiAlpha));
2021-05-16 13:15:44 +00:00
GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
}
void texed_draw_oplist_pane(zpl_aabb2 r) {
// NOTE(zaklaus): add operator
{
2021-05-18 07:19:01 +00:00
zpl_aabb2 add_op_r = zpl_aabb2_cut_right(&r, 200.0f);
2021-05-16 13:15:44 +00:00
DrawAABB(add_op_r, GetColor(0x122025));
add_op_r = zpl_aabb2_contract(&add_op_r, 3.0f);
2021-05-17 19:10:12 +00:00
Rectangle panel_rec = aabb2_ray(add_op_r);
static Vector2 panel_scroll = {99, -20};
float list_y = (DEF_OPS_LEN) * 22.5f;
if (list_y >= (add_op_r.max.y-add_op_r.min.y)) add_op_r.min.x += 12.0f;
else add_op_r.min.x += 2.0f;
add_op_r.max.y = add_op_r.min.y + list_y;
Rectangle view = GuiScrollPanel(panel_rec, aabb2_ray(add_op_r), &panel_scroll);
BeginScissorMode(view.x, view.y, view.width, view.height);
2021-05-18 07:19:01 +00:00
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
2021-05-16 13:15:44 +00:00
for (int i = 0; i < DEF_OPS_LEN; i += 1) {
if (default_ops[i].is_locked) continue;
2021-05-18 07:19:01 +00:00
tcat_desc cat_info = default_cats[default_ops[i].cat];
Color color = cat_info.color;
2021-05-16 13:15:44 +00:00
2021-05-16 13:18:27 +00:00
zpl_aabb2 add_op_btn_r = zpl_aabb2_cut_top(&add_op_r, 22.5f);
2021-05-17 19:10:12 +00:00
add_op_btn_r.min.y += panel_scroll.y;
add_op_btn_r.max.y += panel_scroll.y;
2021-05-18 07:19:01 +00:00
add_op_btn_r.max.x -= 2.0f;
2021-05-16 13:18:27 +00:00
zpl_aabb2_cut_bottom(&add_op_btn_r, 2.5f);
2021-05-18 07:19:01 +00:00
GuiSetStyle(BUTTON, BORDER, ColorToInt(Fade(color, 0.89f)));
GuiSetStyle(BUTTON, BORDER_WIDTH, 1);
if (GuiButton(aabb2_ray(add_op_btn_r), prettify_op_name(i))) {
2021-05-16 13:38:30 +00:00
texed_add_op(default_ops[i].kind);
2021-05-16 13:15:44 +00:00
}
2021-05-18 07:19:01 +00:00
GuiSetStyle(BUTTON, BORDER, 0x838383ff);
GuiSetStyle(BUTTON, BORDER_WIDTH, 2);
2021-05-16 13:15:44 +00:00
}
2021-05-18 07:19:01 +00:00
GuiSetStyle(BUTTON, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
2021-05-17 19:10:12 +00:00
EndScissorMode();
2021-05-16 13:15:44 +00:00
}
2021-05-17 19:10:12 +00:00
// NOTE(zaklaus): recalculate height based on ops count
Rectangle panel_rec = aabb2_ray(r);
static Vector2 panel_scroll = {99, -20};
float list_y = zpl_array_count(ctx.ops)*25.0f;
if (list_y >= (r.max.y-r.min.y)) r.min.x += 12.0f;
else r.min.x += 2.0f;
r.max.y = r.min.y + list_y;
Rectangle view = GuiScrollPanel(panel_rec, aabb2_ray(r), &panel_scroll);
BeginScissorMode(view.x, view.y, view.width, view.height);
2021-05-15 15:19:50 +00:00
// NOTE(zaklaus): operator list
for (int i = 0; i < zpl_array_count(ctx.ops); i += 1) {
2021-05-18 07:19:01 +00:00
td_op *op = &ctx.ops[i];
2021-05-16 12:45:30 +00:00
zpl_aabb2 op_item_r = zpl_aabb2_cut_top(&r, 25.0f);
2021-05-17 19:10:12 +00:00
op_item_r.min.y += panel_scroll.y;
op_item_r.max.y += panel_scroll.y;
2021-05-15 15:19:50 +00:00
zpl_aabb2_cut_top(&op_item_r, 2.5f);
zpl_aabb2_cut_bottom(&op_item_r, 2.5f);
Rectangle list_item = aabb2_ray(op_item_r);
2021-05-18 07:19:01 +00:00
tcat_desc cat_info = default_cats[default_ops[texed_find_op(op->kind)].cat];
Color bg_color = cat_info.color;
2021-05-15 15:19:50 +00:00
2021-05-18 07:19:01 +00:00
DrawRectangleRec(list_item, ColorAlpha(bg_color, ctx.selected_op == i ? 0.6f : 0.325f));
2021-05-15 15:19:50 +00:00
zpl_aabb2 swap_r = zpl_aabb2_cut_left(&op_item_r, 50.0f);
Rectangle list_text = aabb2_ray(op_item_r);
zpl_aabb2_cut_right(&swap_r, 5.0f);
2021-05-15 21:55:29 +00:00
zpl_aabb2 swap_top = zpl_aabb2_cut_left(&swap_r, aabb2_ray(swap_r).width/2.0f);
2021-05-15 15:19:50 +00:00
zpl_aabb2 swap_bottom = swap_r;
2021-05-18 07:19:01 +00:00
if (i == 0 || op->is_locked || (i > 0 && ctx.ops[i-1].is_locked)) GuiSetState(GUI_STATE_DISABLED);
2021-05-15 22:24:42 +00:00
if (GuiButton(aabb2_ray(swap_top), "#121#")) {
2021-05-15 15:19:50 +00:00
texed_swp_op(i, i-1);
}
2021-05-15 22:24:42 +00:00
GuiSetState(GUI_STATE_NORMAL);
2021-05-15 15:19:50 +00:00
2021-05-18 07:19:01 +00:00
if (op->is_locked || (i+1 < zpl_array_count(ctx.ops) && ctx.ops[i+1].is_locked) || i+1 >= zpl_array_count(ctx.ops)) GuiSetState(GUI_STATE_DISABLED);
2021-05-15 22:24:42 +00:00
if (GuiButton(aabb2_ray(swap_bottom), "#120#")) {
2021-05-15 15:19:50 +00:00
texed_swp_op(i, i+1);
}
2021-05-15 22:24:42 +00:00
GuiSetState(GUI_STATE_NORMAL);
2021-05-15 15:19:50 +00:00
2021-05-18 07:19:01 +00:00
zpl_aabb2 theme_stripe = zpl_aabb2_add_right(&swap_r, 3.0f);
if (op->is_locked && op->is_hidden) {
zpl_aabb2 stripe_bottom = zpl_aabb2_cut_bottom(&theme_stripe, (theme_stripe.max.y-theme_stripe.min.y)/2.0f);
DrawAABB(theme_stripe, SKYBLUE);
DrawAABB(stripe_bottom, RED);
} else if (op->is_locked) {
DrawAABB(theme_stripe, SKYBLUE);
} else if (op->is_hidden) {
DrawAABB(theme_stripe, RED);
}
2021-05-16 11:01:53 +00:00
zpl_aabb2 remove_r = zpl_aabb2_cut_right(&op_item_r, 20.0f);
2021-05-15 15:19:50 +00:00
2021-05-18 07:19:01 +00:00
if (op->is_locked) GuiSetState(GUI_STATE_DISABLED);
2021-05-16 11:01:53 +00:00
if (GuiButton(aabb2_ray(remove_r), "#143#")) {
2021-05-15 15:19:50 +00:00
texed_rem_op(i);
}
2021-05-16 11:01:53 +00:00
zpl_aabb2 hidden_r = zpl_aabb2_cut_right(&op_item_r, 20.0f);
2021-05-18 07:19:01 +00:00
if (!default_ops[texed_find_op(op->kind)].is_locked) GuiSetState(GUI_STATE_NORMAL);
2021-05-15 15:19:50 +00:00
2021-05-18 07:19:01 +00:00
if (op->is_hidden) {
GuiSetStyle(BUTTON, BASE, ColorToInt(RED));
}
if (GuiButton(aabb2_ray(hidden_r), op->is_hidden ? "#45#" : "#44#")) {
op->is_hidden = !op->is_hidden;
2021-05-15 15:19:50 +00:00
texed_repaint_preview();
}
2021-05-18 07:19:01 +00:00
GuiSetStyle(BUTTON, BASE, 0x202020ff);
2021-05-16 10:04:29 +00:00
GuiSetState(GUI_STATE_NORMAL);
2021-05-15 15:19:50 +00:00
2021-05-16 12:45:30 +00:00
zpl_aabb2 lock_r = zpl_aabb2_cut_right(&op_item_r, 20.0f);
2021-05-16 09:41:39 +00:00
2021-05-18 07:19:01 +00:00
if (default_ops[texed_find_op(op->kind)].is_locked) GuiSetState(GUI_STATE_DISABLED);
if (op->is_locked) {
GuiSetStyle(BUTTON, BASE, ColorToInt(BLUE));
}
if (GuiButton(aabb2_ray(lock_r), op->is_locked ? "#137#" : "#138#")) {
op->is_locked = !op->is_locked;
2021-05-16 11:36:01 +00:00
ctx.is_saved = false;
2021-05-15 15:19:50 +00:00
}
2021-05-18 07:19:01 +00:00
GuiSetStyle(BUTTON, BASE, 0x202020ff);
2021-05-16 09:41:39 +00:00
GuiSetState(GUI_STATE_NORMAL);
2021-05-16 12:45:30 +00:00
if (ctx.selected_op == i) GuiSetState(GUI_STATE_DISABLED);
zpl_aabb2 select_r = zpl_aabb2_cut_right(&op_item_r, 20.0f);
2021-05-16 10:56:36 +00:00
2021-05-16 12:45:30 +00:00
if (GuiButton(aabb2_ray(select_r), "#141#")) {
ctx.selected_op = i;
2021-05-16 11:36:01 +00:00
ctx.is_saved = false;
2021-05-16 10:56:36 +00:00
}
2021-05-16 12:48:18 +00:00
GuiSetState(GUI_STATE_NORMAL);
2021-05-16 10:56:36 +00:00
2021-05-18 07:19:01 +00:00
GuiDrawText(zpl_bprintf("%s %s", prettify_op_name(texed_find_op(op->kind)), op->is_locked ? "(locked)" : ""), GetTextBounds(LABEL, list_text), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(RAYWHITE, guiAlpha));
2021-05-15 15:19:50 +00:00
}
2021-05-17 19:10:12 +00:00
EndScissorMode();
2021-05-15 15:19:50 +00:00
}
void texed_draw_props_pane(zpl_aabb2 r) {
if (zpl_array_count(ctx.ops) == 0) {
GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_CENTER);
GuiDrawText("No operation is selected!", GetTextBounds(LABEL, aabb2_ray(r)), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(RAYWHITE, guiAlpha));
GuiSetStyle(LABEL, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
return;
}
td_op *op = &ctx.ops[ctx.selected_op];
Rectangle dims = aabb2_ray(r);
zpl_aabb2 column_1_r = zpl_aabb2_cut_left(&r, dims.width/2.0f);
zpl_aabb2 column_2_r = r;
float prop_height = 25.0f;
2021-05-15 15:19:50 +00:00
int prop_column_treshold = (int)zpl_floor(dims.height / prop_height);
for (int i = 0; i < op->num_params; i += 1) {
td_param *p = &op->params[i];
zpl_aabb2 *c = (i >= prop_column_treshold) ? &column_2_r : &column_1_r;
zpl_aabb2 item = zpl_aabb2_cut_top(c, prop_height);
zpl_aabb2_cut_bottom(&item, 5.0f);
2021-05-15 15:19:50 +00:00
zpl_aabb2 label_r = zpl_aabb2_cut_left(&item, dims.width/6.0f);
zpl_aabb2 tbox_r = item;
GuiDrawText(zpl_bprintf("%s: ", p->name ? p->name : "prop"), GetTextBounds(LABEL, aabb2_ray(label_r)), GuiGetStyle(LABEL, TEXT_ALIGNMENT), Fade(RAYWHITE, guiAlpha));
2021-05-15 20:09:25 +00:00
static bool is_color_editing = false;
if (is_color_editing) GuiLock();
2021-05-15 15:19:50 +00:00
switch (p->kind) {
case TPARAM_COLOR: {
2021-05-15 20:09:25 +00:00
if (is_color_editing) GuiUnlock();
if (GuiTextBoxEx(aabb2_ray(tbox_r), p->str, 1000, p->edit_mode)) {
2021-05-15 15:19:50 +00:00
p->edit_mode = true;
2021-05-15 20:09:25 +00:00
is_color_editing = true;
2021-05-15 15:19:50 +00:00
}
if (p->edit_mode) {
zpl_aabb2 extra_r = zpl_aabb2_cut_top(c, prop_height*4.0f + 50.0f);
zpl_aabb2_cut_bottom(&extra_r, 50.0f);
zpl_aabb2_cut_left(&extra_r, dims.width/6.0f);
2021-05-15 20:09:25 +00:00
DrawRectangleRec(aabb2_ray(extra_r), GRAY);
2021-05-15 15:48:15 +00:00
zpl_aabb2 ok_r = zpl_aabb2_cut_left(&extra_r, 50.0f);
p->color = GuiColorPicker(aabb2_ray(extra_r), p->color);
2021-05-15 15:19:50 +00:00
if (GuiButton(aabb2_ray(ok_r), "OK")) {
2021-05-15 20:09:25 +00:00
GuiUnlock();
2021-05-15 15:19:50 +00:00
p->edit_mode = false;
2021-05-15 20:09:25 +00:00
is_color_editing = false;
2021-05-15 15:19:50 +00:00
int_to_hex_color(ColorToInt(p->color), p->str);
texed_repaint_preview();
}
}
2021-05-15 20:09:25 +00:00
if (is_color_editing) GuiLock();
2021-05-15 15:19:50 +00:00
}break;
2021-05-16 14:11:29 +00:00
case TPARAM_SLIDER: {
p->flt = GuiSlider(aabb2_ray(tbox_r), NULL, zpl_bprintf("%.02f", p->flt), p->flt, 0.0f, 1.0f);
if (p->old_flt != p->flt) {
sprintf(p->str, "%f", p->flt);
p->old_flt = p->flt;
texed_repaint_preview();
}
}break;
2021-05-16 14:58:08 +00:00
case TPARAM_INT:
2021-05-15 16:41:30 +00:00
case TPARAM_COORD: {
2021-05-17 05:53:10 +00:00
if (GuiValueBoxEco(aabb2_ray(tbox_r), NULL, &p->i32, INT32_MIN, INT32_MAX, p->edit_mode)) {
2021-05-15 16:41:30 +00:00
p->edit_mode = !p->edit_mode;
if (!p->edit_mode) {
sprintf(p->str, "%d", p->i32);
texed_repaint_preview();
2021-05-17 05:53:10 +00:00
} else if (IsKeyDown(KEY_LEFT_SHIFT)) {
p->i32 = 0;
2021-05-15 16:41:30 +00:00
}
};
}break;
2021-05-15 15:19:50 +00:00
default: {
2021-05-15 20:09:25 +00:00
if (GuiTextBoxEx(aabb2_ray(tbox_r), p->str, 1000, p->edit_mode)) {
2021-05-15 15:19:50 +00:00
p->edit_mode = !p->edit_mode;
if (!p->edit_mode)
texed_repaint_preview();
}
}break;
};
2021-05-15 20:09:25 +00:00
if (is_color_editing) GuiUnlock();
2021-05-15 15:19:50 +00:00
}
}
zpl_global const char zpl__num_to_char_table[] = "0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"@$";
static inline
void int_to_hex_color(uint32_t value, char *string) {
char *buf = string;
if (value) {
while (value > 0) {
*buf++ = zpl__num_to_char_table[value % 16];
value /= 16;
}
} else {
*buf++ = '0';
}
*buf = '\0';
zpl_strrev(string);
}
2021-05-15 20:09:25 +00:00
// Dropdown Box control
// NOTE: Returns mouse click
static inline
int GuiDropdownBoxEco(Rectangle bounds, char const *text, char const *caption, int *active, bool editMode)
{
GuiControlState state = guiState;
int itemSelected = *active;
int itemFocused = -1;
// Get substrings items from text (items pointers, lengths and count)
int itemsCount = 0;
const char **items = GuiTextSplit(text, &itemsCount, NULL);
Rectangle boundsOpen = bounds;
boundsOpen.height = (itemsCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
Rectangle itemBounds = bounds;
bool pressed = false; // Check mouse button pressed
// Update control
//--------------------------------------------------------------------
if ((state != GUI_STATE_DISABLED) && !guiLocked && (itemsCount > 1))
{
Vector2 mousePoint = GetMousePosition();
if (editMode)
{
state = GUI_STATE_PRESSED;
// Check if already selected item has been pressed again
if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
// Check focused and selected item
for (int i = 0; i < itemsCount; i++)
{
// Update item rectangle y position for next item
itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
if (CheckCollisionPointRec(mousePoint, itemBounds))
{
itemFocused = i;
if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON))
{
itemSelected = i;
pressed = true; // Item selected, change to editMode = false
}
break;
}
}
itemBounds = bounds;
}
else
{
if (CheckCollisionPointRec(mousePoint, bounds))
{
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
{
pressed = true;
state = GUI_STATE_PRESSED;
}
else state = GUI_STATE_FOCUSED;
}
}
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
if (editMode) GuiPanel(boundsOpen);
GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3)), guiAlpha));
GuiDrawText(caption, GetTextBounds(DEFAULT, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3)), guiAlpha));
if (editMode)
{
// Draw visible items
for (int i = 0; i < itemsCount; i++)
{
// Update item rectangle y position for next item
itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_PADDING));
if (i == itemSelected)
{
GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED)), guiAlpha));
GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED)), guiAlpha));
}
else if (i == itemFocused)
{
GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), guiAlpha), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED)), guiAlpha));
GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED)), guiAlpha));
}
else GuiDrawText(items[i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL)), guiAlpha));
}
}
// TODO: Avoid this function, use icon instead or 'v'
DrawTriangle(RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2 },
RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING) + 5, bounds.y + bounds.height/2 - 2 + 5 },
RAYGUI_CLITERAL(Vector2){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING) + 10, bounds.y + bounds.height/2 - 2 },
Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
//GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 },
// GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3))), guiAlpha));
//--------------------------------------------------------------------
Vector2 mousePoint = GetMousePosition();
// Check if mouse has been pressed or released outside limits
if (!CheckCollisionPointRec(mousePoint, boundsOpen))
{
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) {
return 2;
}
}
*active = itemSelected;
return pressed;
}
2021-05-16 12:07:28 +00:00
#define TD_UI_MSGBOX_WIDTH 320
#define TD_UI_MSGBOX_HEIGHT 200
void texed_draw_msgbox(zpl_aabb2 r) {
if (!ctx.msgbox.visible) return;
DrawRectangle(r.min.x, r.min.y, r.max.x, r.max.y, Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), 0.85f));
Rectangle rec = {
r.max.x/2.0f - TD_UI_MSGBOX_WIDTH/2.0f,
r.max.y/2.0f - TD_UI_MSGBOX_HEIGHT/2.0f,
TD_UI_MSGBOX_WIDTH,
TD_UI_MSGBOX_HEIGHT,
};
ctx.msgbox.result = GuiMessageBox(rec, ctx.msgbox.title, ctx.msgbox.message, ctx.msgbox.buttons);
if (ctx.msgbox.result != -1) {
ctx.msgbox.visible = false;
}
2021-05-16 12:40:30 +00:00
}
static inline
bool IsCtrlAcceleratorPressed(char key) {
return (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)) && (char)GetKeyPressed() == key;
2021-05-17 05:53:10 +00:00
}
static inline
bool GuiValueBoxEco(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) {
#if !defined(VALUEBOX_MAX_CHARS)
#define VALUEBOX_MAX_CHARS 32
#endif
static int framesCounter = 0; // Required for blinking cursor
GuiControlState state = guiState;
bool pressed = false;
char textValue[VALUEBOX_MAX_CHARS + 1] = "\0";
sprintf(textValue, "%i", *value);
Rectangle textBounds = { 0 };
if (text != NULL)
{
textBounds.width = (float)GetTextWidth(text);
textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE);
textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING);
textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2;
if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING);
}
// Update control
//--------------------------------------------------------------------
if ((state != GUI_STATE_DISABLED) && !guiLocked)
{
Vector2 mousePoint = GetMousePosition();
bool valueHasChanged = false;
if (editMode)
{
state = GUI_STATE_PRESSED;
framesCounter++;
int keyCount = (int)strlen(textValue);
// Only allow keys in range [48..57]
if (keyCount < VALUEBOX_MAX_CHARS)
{
if (GetTextWidth(textValue) < bounds.width)
{
int key = GetCharPressed();
if ((key >= 48) && (key <= 57))
{
textValue[keyCount] = (char)key;
keyCount++;
valueHasChanged = true;
}
}
}
// Delete text
if (keyCount > 0)
{
if (IsKeyPressed(KEY_BACKSPACE))
{
keyCount--;
textValue[keyCount] = '\0';
framesCounter = 0;
if (keyCount < 0) keyCount = 0;
valueHasChanged = true;
}
else if (IsKeyDown(KEY_BACKSPACE))
{
if ((framesCounter > TEXTEDIT_CURSOR_BLINK_FRAMES) && (framesCounter%2) == 0) keyCount--;
textValue[keyCount] = '\0';
if (keyCount < 0) keyCount = 0;
valueHasChanged = true;
}
}
if (valueHasChanged) *value = TextToInteger(textValue);
if (IsKeyPressed(KEY_ENTER) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) pressed = true;
}
else
{
if (*value > maxValue) *value = maxValue;
else if (*value < minValue) *value = minValue;
if (CheckCollisionPointRec(mousePoint, bounds))
{
state = GUI_STATE_FOCUSED;
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) pressed = true;
}
}
if (pressed) framesCounter = 0;
}
//--------------------------------------------------------------------
// Draw control
//--------------------------------------------------------------------
Color baseColor = BLANK;
if (state == GUI_STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED));
else if (state == GUI_STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED));
// WARNING: BLANK color does not work properly with Fade()
GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), guiAlpha), baseColor);
GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), GUI_TEXT_ALIGN_CENTER, Fade(GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3))), guiAlpha));
// Draw blinking cursor
if ((state == GUI_STATE_PRESSED) && (editMode && ((framesCounter/20)%2 == 0)))
{
// NOTE: ValueBox internal text is always centered
Rectangle cursor = { bounds.x + GetTextWidth(textValue)/2 + bounds.width/2 + 2, bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 1, bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH) };
GuiDrawRectangle(cursor, 0, BLANK, Fade(GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED)), guiAlpha));
}
// Draw text label if provided
if (text != NULL) GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == GUI_TEXT_ALIGN_RIGHT)? GUI_TEXT_ALIGN_LEFT : GUI_TEXT_ALIGN_RIGHT, Fade(GetColor(GuiGetStyle(LABEL, TEXT + (state*3))), guiAlpha));
//--------------------------------------------------------------------
return pressed;
}
2021-05-18 07:19:01 +00:00
static inline
char const *prettify_op_name(int idx) {
static char name[200] = {0};
zpl_snprintf(name, 200, "%s %s", default_cats[default_ops[idx].cat].icon, default_ops[idx].name+4);
zpl_str_to_lower(name);
char *p = (char*)zpl_str_skip(name, ' ')+1;
do {
*p = zpl_char_to_upper(*p);
p = (char*)zpl_str_skip(p, '_');
if (*p) *p = ' ';
} while(*p++);
return name;
}