diff --git a/code/game/source/editors/texed.c b/code/game/source/editors/texed.c index 85484d0..cac8d5d 100644 --- a/code/game/source/editors/texed.c +++ b/code/game/source/editors/texed.c @@ -80,11 +80,20 @@ typedef struct { #define OP(n) .kind = n, .name = #n +typedef struct { + bool visible; + char const *title; + char const *message; + char const *buttons; + int result; +} td_msgbox; + typedef struct { char *filepath; Image img; Texture2D tex; GuiFileDialogState fileDialog; + td_msgbox msgbox; bool is_saved; td_op *ops; //< zpl_array @@ -105,6 +114,7 @@ void texed_export_cc(char const *path); void texed_export_png(char const *path); void texed_repaint_preview(void); void texed_compose_image(void); +void texed_msgbox_init(char const *title, char const *message, char const *buttons); void texed_process_ops(void); void texed_process_params(void); void texed_add_op(int idx); @@ -114,6 +124,7 @@ void texed_swp_op(int idx, int idx2); void texed_draw_oplist_pane(zpl_aabb2 r); void texed_draw_props_pane(zpl_aabb2 r); void texed_draw_topbar(zpl_aabb2 r); +void texed_draw_msgbox(zpl_aabb2 r); static inline void DrawAABB(zpl_aabb2 rect, Color color) { @@ -213,6 +224,7 @@ void texed_run(int argc, char **argv) { .min = (zpl_vec2) {.x = 0.0f, .y = 0.0f}, .max = (zpl_vec2) {.x = GetScreenWidth(), .y = GetScreenHeight()}, }; + zpl_aabb2 orig_screen = screen; zpl_aabb2 topbar = zpl_aabb2_cut_top(&screen, 25.0f); zpl_aabb2 oplist_pane = zpl_aabb2_cut_right(&screen, screenWidth / 2.0f); @@ -239,6 +251,8 @@ void texed_run(int argc, char **argv) { ClearBackground(GetColor(0x222034)); { if (ctx.fileDialog.fileDialogActive) GuiLock(); + if (ctx.msgbox.visible) GuiLock(); + DrawTextureEx(checker_tex, (Vector2){ preview_window.min.x, preview_window.min.y}, 0.0f, 1.0f, WHITE); DrawTextureEx(ctx.tex, (Vector2){ preview_window.min.x, preview_window.min.y}, 0.0f, zoom, WHITE); @@ -251,7 +265,10 @@ void texed_run(int argc, char **argv) { texed_draw_oplist_pane(oplist_pane); if (ctx.fileDialog.fileDialogActive) GuiUnlock(); + if (ctx.msgbox.visible) GuiUnlock(); + GuiFileDialog(&ctx.fileDialog); + texed_draw_msgbox(orig_screen); } EndDrawing(); } @@ -310,6 +327,14 @@ void texed_compose_image(void) { texed_process_ops(); } +void texed_msgbox_init(char const *title, char const *message, char const *buttons) { + ctx.msgbox.result = -1; + ctx.msgbox.visible = true; + ctx.msgbox.title = title; + ctx.msgbox.message = message; + ctx.msgbox.buttons = buttons; +} + void texed_add_op(int idx) { assert(idx >= 0 && idx < DEF_OPS_LEN); td_op *dop = &default_ops[idx]; diff --git a/code/game/source/editors/texed_widgets.c b/code/game/source/editors/texed_widgets.c index f91375f..9c4236f 100644 --- a/code/game/source/editors/texed_widgets.c +++ b/code/game/source/editors/texed_widgets.c @@ -15,10 +15,24 @@ void texed_draw_topbar(zpl_aabb2 r) { zpl_aabb2_cut_left(&r, 100.0f); zpl_aabb2 new_prj_r = zpl_aabb2_cut_left(&r, 60.0f); + static bool new_pending = false; if (GuiButton(aabb2_ray(new_prj_r), "NEW")) { - texed_destroy(); - texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT); + if (ctx.is_saved) { + texed_destroy(); + texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT); + } else { + new_pending = true; + texed_msgbox_init("Discard unsaved work?", "You have an unsaved work! Do you want to proceed?", "Cancel;OK"); + } + } + + if (new_pending && ctx.msgbox.result != -1) { + new_pending = false; + if (ctx.msgbox.result == 2) { + texed_destroy(); + texed_new(TD_DEFAULT_IMG_WIDTH, TD_DEFAULT_IMG_HEIGHT); + } } zpl_aabb2 load_prj_r = zpl_aabb2_cut_left(&r, 60.0f); @@ -26,7 +40,11 @@ void texed_draw_topbar(zpl_aabb2 r) { if (GuiButton(aabb2_ray(load_prj_r), "LOAD")) { load_pending = true; - ctx.fileDialog.fileDialogActive = true; + if (ctx.is_saved) { + ctx.fileDialog.fileDialogActive = true; + } else { + texed_msgbox_init("Discard unsaved work?", "You have an unsaved work! Do you want to proceed?", "Cancel;OK"); + } } if (ctx.fileDialog.SelectFilePressed && load_pending) { @@ -41,6 +59,14 @@ void texed_draw_topbar(zpl_aabb2 r) { } } + if (load_pending && ctx.msgbox.result != -1) { + if (ctx.msgbox.result == 2) { + ctx.msgbox.result = -1; // NOTE(zaklaus): ensure we don't re-trigger this branch next frame + ctx.fileDialog.fileDialogActive = true; + } + else load_pending = false; + } + zpl_aabb2 save_prj_r = zpl_aabb2_cut_left(&r, 60.0f); static bool save_as_pending = false; @@ -421,3 +447,23 @@ int GuiDropdownBoxEco(Rectangle bounds, char const *text, char const *caption, i *active = itemSelected; return pressed; } + +#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; + } +} \ No newline at end of file