From c6abea5bf041b9f917a1969759b8b29c09f65505 Mon Sep 17 00:00:00 2001 From: hgn Date: Sat, 22 Mar 2025 16:28:53 +0000 Subject: [PATCH] Some IO ops and modal changes --- .gitmodules | 3 +++ submodules/hashmap.c | 1 + vg_array_file.c | 0 vg_engine.c | 4 +-- vg_io.c | 27 ++++++++++++++++++- vg_io.h | 5 ++++ vg_mem.c | 6 +++++ vg_mem.h | 1 + vg_msg.h | 4 +-- vg_tex.h | 2 +- vg_ui/imgui.c | 64 +++++++++++++++++++++++++++++++------------- vg_ui/imgui.h | 8 +++--- 12 files changed, 95 insertions(+), 30 deletions(-) create mode 160000 submodules/hashmap.c create mode 100644 vg_array_file.c diff --git a/.gitmodules b/.gitmodules index 00137dc..af46047 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "submodules/rax"] path = submodules/rax url = https://github.com/antirez/rax.git +[submodule "submodules/hashmap.c"] + path = submodules/hashmap.c + url = https://github.com/tidwall/hashmap.c.git diff --git a/submodules/hashmap.c b/submodules/hashmap.c new file mode 160000 index 0000000..1c13992 --- /dev/null +++ b/submodules/hashmap.c @@ -0,0 +1 @@ +Subproject commit 1c139923fe08f36143ecc0ba37cd674684f87f9c diff --git a/vg_array_file.c b/vg_array_file.c new file mode 100644 index 0000000..e69de29 diff --git a/vg_engine.c b/vg_engine.c index 4a971f5..6f595aa 100644 --- a/vg_engine.c +++ b/vg_engine.c @@ -366,7 +366,7 @@ static void vg_changevsync(void) "Vsync not supported on this system.\n\n" "You may be overriding it in your" " graphics \ncontrol panel.\n", - UI_MODAL_BAD ); + NULL, UI_MODAL_BAD, NULL ); } else { @@ -374,7 +374,7 @@ static void vg_changevsync(void) "Adaptive Vsync is not supported by your system\n\n" "You may be overriding it in your" " graphics \ncontrol panel.\n", - UI_MODAL_BAD ); + NULL, UI_MODAL_BAD, NULL ); } vg.vsync_feature = k_vsync_feature_error; diff --git a/vg_io.c b/vg_io.c index 206b815..a061d0f 100644 --- a/vg_io.c +++ b/vg_io.c @@ -15,6 +15,27 @@ const char *dir_open_result_str[] = [k_dir_open_invalid_path] = "Invalid path" }; +bool vg_path_exists( const char *path ) +{ +#ifdef _WIN32 + DWORD attributes = GetFileAttributes( path ); + if( attributes == INVALID_FILE_ATTRIBUTES ) + return 0; + return 1; +#else + return access(path, F_OK) != -1; +#endif +} + +bool vg_make_directory( const char *path ) +{ +#ifdef _WIN32 + return CreateDirectory( path, NULL )? 1:0; +#else + return mkdir( path, S_IRWXU|S_IRWXG|S_IRWXO ) == 0; +#endif +} + enum dir_open_result vg_dir_open( vg_dir *dir, const char *name ) { #ifdef _WIN32 @@ -26,7 +47,11 @@ enum dir_open_result vg_dir_open( vg_dir *dir, const char *name ) if( !vg_strgood(&q) ) return k_dir_open_path_too_long; - if( !(GetFileAttributes( q.buffer ) & FILE_ATTRIBUTE_DIRECTORY) ) + DWORD attributes = GetFileAttributes( q.buffer ); + if( attributes == INVALID_FILE_ATTRIBUTES ) + return k_dir_open_invalid_path; + + if( !(attributes & FILE_ATTRIBUTE_DIRECTORY) ) return k_dir_open_is_file; vg_info( "FindFirstFile( '%s' )\n", q.buffer ); diff --git a/vg_io.h b/vg_io.h index 3c73de5..4f549b8 100644 --- a/vg_io.h +++ b/vg_io.h @@ -8,6 +8,8 @@ typedef struct vg_dir vg_dir; #ifndef _WIN32 #include + #include + #include struct vg_dir{ DIR *h; struct dirent *data; @@ -45,6 +47,9 @@ bool vg_dir_next_entry( vg_dir *dir ); enum vg_entry_type vg_dir_entry_type( vg_dir *dir ); void vg_dir_close( vg_dir *dir ); +bool vg_path_exists( const char *path ); +bool vg_make_directory( const char *path ); + /* * File I/O */ diff --git a/vg_mem.c b/vg_mem.c index 9451572..63c422b 100644 --- a/vg_mem.c +++ b/vg_mem.c @@ -9,6 +9,12 @@ struct vg_global_mem vg_mem; +u32 vg_align16( u32 s ) +{ + u32 m = (s + 15) >> 4; + return m << 4; +} + u32 vg_align8( u32 s ) { u32 m = (s + 7) >> 3; diff --git a/vg_mem.h b/vg_mem.h index 8d9441c..b5b0366 100644 --- a/vg_mem.h +++ b/vg_mem.h @@ -46,6 +46,7 @@ struct vg_linear_allocator }; #pragma pack(pop) +u32 vg_align16( u32 s ); u32 vg_align8( u32 s ); u32 vg_align4( u32 s ); diff --git a/vg_msg.h b/vg_msg.h index 0b13024..83d5105 100644 --- a/vg_msg.h +++ b/vg_msg.h @@ -130,7 +130,6 @@ struct vg_msg u32 max; u8 *buf; - /* reading */ struct vg_msg_cursor { u32 co, depth; @@ -168,8 +167,7 @@ void vg_msg_frame( vg_msg *msg, const char *name ); void vg_msg_end_frame( vg_msg *msg ); void vg_msg_wkvstr( vg_msg *msg, const char *key, const char *value ); void vg_msg_wkvbin( vg_msg *msg, const char *key, u8 *bin, u32 len ); -void vg_msg_wkvnum( vg_msg *msg, const char *key, - u8 type, u8 count, void *data ); +void vg_msg_wkvnum( vg_msg *msg, const char *key, u8 type, u8 count, void *data ); u32 vg_msg_cmd_array_count( u8 code ); u32 vg_msg_cmd_type_size( u8 code ); u32 vg_msg_cmd_bytecount( u8 code ); diff --git a/vg_tex.h b/vg_tex.h index ea197b2..b257808 100644 --- a/vg_tex.h +++ b/vg_tex.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021-2024 Harry Godden (hgn) - All Rights Reserved +/* Copyright (C) 2021-2025 Harry Godden (hgn) - All Rights Reserved * * A portion of this file is copied and altered from the QOI projects' source, * Originally written by Dominic Szablewski. It is slightly modified. diff --git a/vg_ui/imgui.c b/vg_ui/imgui.c index cd758f6..06a3eee 100644 --- a/vg_ui/imgui.c +++ b/vg_ui/imgui.c @@ -817,7 +817,7 @@ void ui_postrender( ui_context *ctx, f32 delta_time ) { ui_rect screen = { 0,0, ctx->area[0], ctx->area[1] }; ui_fill( ctx, screen, 0xa0000000 ); - ui_rect box = {0,0,400,200}; + ui_rect box = {0,0,416,216}; u32 colour = ui_colour(ctx,k_ui_fg), type = ctx->modal.options & UI_MODAL_TYPE_BITS; @@ -828,26 +828,48 @@ void ui_postrender( ui_context *ctx, f32 delta_time ) ui_rect_center( screen, box ); ui_fill( ctx, box, ui_colour(ctx,k_ui_bg) ); ui_outline( ctx, box, -1, colour, 0 ); + ui_rect_pad( box, (ui_px[]){8,8} ); ui_rect message; rect_copy( box, message ); - message[3] = 100; + message[3] = 150; ui_rect_center( box, message ); - ui_rect row0, row1, btn; - ui_split_ratio( message, k_ui_axis_h, 0.76f, 0, row0, row1 ); + ui_rect row0, row1; + ui_split( message, k_ui_axis_h, -28, 0, row0, row1 ); row0[0] += ctx->font->sx; - ui_ntext( ctx, row0, ctx->modal.message, (box[2]/ctx->font->sx)-2, 1, - k_ui_align_left, colour ); + ui_ntext( ctx, row0, ctx->modal.message, (box[2]/ctx->font->sx)-2, 1, k_ui_align_left, colour ); + + ui_rect btn_ok; + ui_split( row1, k_ui_axis_v, -120, 8, row1, btn_ok ); - rect_copy( row1, btn ); - btn[2] = 86; - btn[3] = 28; - ui_rect_center( row1, btn ); - ctx->focused_control_type = k_ui_control_none; /* HACK */ - if( ui_button_text( ctx, btn, "OK", 1 ) != 1 ) + + bool close_modal = 0; + if( ctx->modal.options & UI_MODAL_CANCEL ) + { + ui_rect btn_cancel; + ui_split( row1, k_ui_axis_v, -120, 8, row1, btn_cancel ); + if( ui_button_text( ctx, btn_cancel, "Cancel", 1 ) == k_ui_button_click ) + { + if( ctx->modal.callbacks.close ) + ctx->modal.callbacks.close( UI_MODAL_CANCEL ); + + close_modal = 1; + } + } + + if( ui_button_text( ctx, btn_ok, ctx->modal.ok_text, 1 ) == k_ui_button_click ) + { + if( ctx->modal.callbacks.close ) + ctx->modal.callbacks.close( 0 ); + + close_modal = 1; + } + + if( !close_modal ) ctx->focused_control_hit = 1; + ctx->focused_control_type = k_ui_control_modal; /* HACK */ ctx->wants_mouse = 1; } @@ -1251,7 +1273,6 @@ static void _ui_textbox_change_callback( ui_context *ctx ) } } -void ui_start_modal( ui_context *ctx, const char *message, u32 options ); void _ui_textbox_clipboard_paste( ui_context *ctx ) { if( !ctx->have_clipboard_text() ) @@ -1265,9 +1286,9 @@ void _ui_textbox_clipboard_paste( ui_context *ctx ) int datastart = _ui_textbox_delete_char( ctx, 0 ); int length = strlen( text ); - if( (ctx->textbox.len - strlen(ctx->textbuf)) < length ){ - ui_start_modal( ctx, - "Clipboard content exceeds buffer size.", UI_MODAL_BAD ); + if( (ctx->textbox.len - strlen(ctx->textbuf)) < length ) + { + ui_start_modal( ctx, "Clipboard content exceeds buffer size.", NULL, UI_MODAL_BAD, NULL ); return; } @@ -1921,13 +1942,18 @@ void ui_tabs( ui_context *ctx, ui_rect inout_panel, ui_rect out_content_panel, * Modal UI * ----------------------------------------------------------------------------- */ -void ui_start_modal( ui_context *ctx, const char *message, u32 options ) +void ui_start_modal( ui_context *ctx, const char *message, const char *ok_text, + u32 options, const struct ui_modal_callbacks *callbacks ) { ctx->focused_control_type = k_ui_control_modal; ctx->modal.message = message; - ctx->modal.callbacks.close = NULL; + ctx->modal.ok_text = ok_text? ok_text: "OK"; + if( callbacks ) + ctx->modal.callbacks = *callbacks; + else + ctx->modal.callbacks.close = NULL; + ctx->modal.options = options; - u32 type = options & UI_MODAL_TYPE_BITS; if( type == UI_MODAL_OK ) vg_info( message ); else if( type == UI_MODAL_WARN ) vg_warn( message ); diff --git a/vg_ui/imgui.h b/vg_ui/imgui.h index b64fd3d..8bea3b5 100644 --- a/vg_ui/imgui.h +++ b/vg_ui/imgui.h @@ -76,6 +76,7 @@ enum ui_scheme_colour #define UI_MODAL_BAD 0x2 #define UI_MODAL_WARN 0x3 #define UI_MODAL_TYPE_BITS 0x3 +#define UI_MODAL_CANCEL 0x8 #define UI_MOUSE_LEFT 1 #define UI_MOUSE_MIDDLE 2 @@ -169,7 +170,7 @@ struct ui_context struct ui_modal { - const char *message; + const char *message, *ok_text; u32 options; struct ui_modal_callbacks @@ -341,7 +342,8 @@ enum ui_colour_type bool ui_colourpicker( ui_context *ctx, ui_rect inout_panel, const char *str_label, v4f value, enum ui_colour_type type ); void _ui_textbox_move_cursor( ui_context *ctx, int *cursor0, int *cursor1, int dir, int snap_together ); int _ui_textbox_delete_char( ui_context *ctx, int direction ); -void ui_start_modal( ui_context *ctx, const char *message, u32 options ); +void ui_start_modal( ui_context *ctx, const char *message, const char *ok_text, + u32 options, const struct ui_modal_callbacks *callbacks ); void _ui_textbox_put_char( ui_context *ctx, char c ); void _ui_textbox_left_select( ui_context *ctx ); @@ -369,8 +371,6 @@ void ui_tabs( ui_context *ctx, ui_rect inout_panel, ui_rect out_content_panel, const char **titles, u32 count, i32 *page ); void ui_defocus_all( ui_context *ctx ); -void ui_start_modal( ui_context *ctx, const char *message, u32 options ); - void ui_proc_utf8( ui_context *ctx, const char *text ); void ui_dev_colourview( ui_context *ctx ); -- 2.25.1