diff --git a/doc/cheatsheet_app.h b/doc/cheatsheet_app.h new file mode 100644 index 0000000..de085c6 --- /dev/null +++ b/doc/cheatsheet_app.h @@ -0,0 +1,35 @@ +/************************************************************/ /** +* +* @file: cheatsheet_app.h +* @author: Martin Fouilleul +* @date: 05/09/2023 +* +*****************************************************************/ + +//---------------------------------------------------------------- +// Handlers (can be defined by your app to respond to events) +//---------------------------------------------------------------- +void oc_on_init(void); +void oc_on_mouse_down(oc_mouse_button button); +void oc_on_mouse_up(oc_mouse_button button); +void oc_on_mouse_enter(void); +void oc_on_mouse_leave(void); +void oc_on_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY); +void oc_on_mouse_wheel(f32 deltaX, f32 deltaY); +void oc_on_key_down(oc_key_code key); +void oc_on_key_up(oc_key_code key); +void oc_on_frame_refresh(void); +void oc_on_resize(f32 width, f32 height); +void oc_on_raw_event(oc_event* event); +void oc_on_terminate(void); + +//---------------------------------------------------------------- +// Window +//---------------------------------------------------------------- +void oc_window_set_title(oc_str8 title); +void oc_window_set_size(oc_vec2 size); + +//---------------------------------------------------------------- +// Quitting +//---------------------------------------------------------------- +void oc_request_quit(void) diff --git a/doc/cheatsheet_graphics.h b/doc/cheatsheet_graphics.h new file mode 100644 index 0000000..f683bac --- /dev/null +++ b/doc/cheatsheet_graphics.h @@ -0,0 +1,162 @@ +/************************************************************/ /** +* +* @file: cheatsheet_graphics.h +* @author: Martin Fouilleul +* @date: 05/09/2023 +* +*****************************************************************/ + +//------------------------------------------------------------------------------------------ +// graphics surface +//------------------------------------------------------------------------------------------ +oc_surface oc_surface_nil(void); +bool oc_surface_is_nil(oc_surface surface); +oc_surface oc_surface_canvas(); +oc_surface oc_surface_gles(); +void oc_surface_destroy(oc_surface surface); + +void oc_surface_select(oc_surface surface); +void oc_surface_present(oc_surface surface); +void oc_surface_deselect(void); + +oc_vec2 oc_surface_get_size(oc_surface surface); +oc_vec2 oc_surface_contents_scaling(oc_surface surface); +void oc_surface_bring_to_front(oc_surface surface); +void oc_surface_send_to_back(oc_surface surface); + +//------------------------------------------------------------------------------------------ +// 2D canvas command buffer +//------------------------------------------------------------------------------------------ +oc_canvas oc_canvas_nil(void); +bool oc_canvas_is_nil(oc_canvas canvas); +oc_canvas oc_canvas_create(void); +void oc_canvas_destroy(oc_canvas canvas); +oc_canvas oc_canvas_set_current(oc_canvas canvas); +void oc_render(oc_surface surface, oc_canvas canvas); + +//------------------------------------------------------------------------------------------ +// transform and clipping +//------------------------------------------------------------------------------------------ + +void oc_matrix_push(oc_mat2x3 matrix); +void oc_matrix_pop(void); +oc_mat2x3 oc_matrix_top(); + +void oc_clip_push(f32 x, f32 y, f32 w, f32 h); +void oc_clip_pop(void); +oc_rect oc_clip_top(); + +//------------------------------------------------------------------------------------------ +// graphics attributes setting/getting +//------------------------------------------------------------------------------------------ +void oc_set_color(oc_color color); +void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a); +void oc_set_width(f32 width); +void oc_set_tolerance(f32 tolerance); +void oc_set_joint(oc_joint_type joint); +void oc_set_max_joint_excursion(f32 maxJointExcursion); +void oc_set_cap(oc_cap_type cap); +void oc_set_font(oc_font font); +void oc_set_font_size(f32 size); +void oc_set_text_flip(bool flip); +void oc_set_image(oc_image image); +void oc_set_image_source_region(oc_rect region); + +oc_color oc_get_color(void); +f32 oc_get_width(void); +f32 oc_get_tolerance(void); +oc_joint_type oc_get_joint(void); +f32 oc_get_max_joint_excursion(void); +oc_cap_type oc_get_cap(void); +oc_font oc_get_font(void); +f32 oc_get_font_size(void); +bool oc_get_text_flip(void); +oc_image oc_get_image(); + +//------------------------------------------------------------------------------------------ +// path construction +//------------------------------------------------------------------------------------------ +oc_vec2 oc_get_position(void); +void oc_move_to(f32 x, f32 y); +void oc_line_to(f32 x, f32 y); +void oc_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2); +void oc_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3); +void oc_close_path(void); + +oc_rect oc_glyph_outlines(oc_str32 glyphIndices); +void oc_codepoints_outlines(oc_str32 string); +void oc_text_outlines(oc_str8 string); + +//------------------------------------------------------------------------------------------ +// clear/fill/stroke +//------------------------------------------------------------------------------------------ +void oc_clear(void); +void oc_fill(void); +void oc_stroke(void); + +//------------------------------------------------------------------------------------------ +// shapes helpers +//------------------------------------------------------------------------------------------ +void oc_rectangle_fill(f32 x, f32 y, f32 w, f32 h); +void oc_rectangle_stroke(f32 x, f32 y, f32 w, f32 h); +void oc_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r); +void oc_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r); +void oc_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry); +void oc_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry); +void oc_circle_fill(f32 x, f32 y, f32 r); +void oc_circle_stroke(f32 x, f32 y, f32 r); +void oc_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle); +void oc_image_draw(oc_image image, oc_rect rect); +void oc_image_draw_region(oc_image image, oc_rect srcRegion, oc_rect dstRegion); + +//------------------------------------------------------------------------------------------ +// fonts +//------------------------------------------------------------------------------------------ +oc_font oc_font_nil(void); +bool oc_font_is_nil(oc_font font); + +oc_font oc_font_create_from_memory(oc_str8 mem, u32 rangeCount, oc_unicode_range* ranges); +void oc_font_destroy(oc_font font); + +oc_font_extents oc_font_get_extents(oc_font font); +oc_font_extents oc_font_get_scaled_extents(oc_font font, f32 emSize); +f32 oc_font_get_scale_for_em_pixels(oc_font font, f32 emSize); + +u32 oc_font_get_glyph_index(oc_font font, oc_utf32 codePoint); +oc_str32 oc_font_get_glyph_indices(oc_font font, oc_str32 codePoints, oc_str32 backing); +oc_str32 oc_font_push_glyph_indices(oc_font font, oc_arena* arena, oc_str32 codePoints); + +int oc_font_get_codepoint_extents(oc_font font, oc_utf32 codePoint, oc_text_extents* outExtents); +int oc_font_get_glyph_extents(oc_font font, oc_str32 glyphIndices, oc_text_extents* outExtents); + +oc_rect oc_text_bounding_box_utf32(oc_font font, f32 fontSize, oc_str32 text); +oc_rect oc_text_bounding_box(oc_font font, f32 fontSize, oc_str8 text); + +//------------------------------------------------------------------------------------------ +// images +//------------------------------------------------------------------------------------------ +oc_image oc_image_nil(void); +bool oc_image_is_nil(oc_image a); + +oc_image oc_image_create(oc_surface surface, u32 width, u32 height); +oc_image oc_image_create_from_rgba8(oc_surface surface, u32 width, u32 height, u8* pixels); +oc_image oc_image_create_from_memory(oc_surface surface, oc_str8 mem, bool flip); +oc_image oc_image_create_from_file(oc_surface surface, oc_str8 path, bool flip); + +void oc_image_destroy(oc_image image); + +void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels); +oc_vec2 oc_image_size(oc_image image); + +//------------------------------------------------------------------------------------------ +// image atlas +//------------------------------------------------------------------------------------------ + +oc_rect_atlas* oc_rect_atlas_create(oc_arena* arena, i32 width, i32 height); +oc_rect oc_rect_atlas_alloc(oc_rect_atlas* atlas, i32 width, i32 height); +void oc_rect_atlas_recycle(oc_rect_atlas* atlas, oc_rect rect); + +oc_image_region oc_image_atlas_alloc_from_rgba8(oc_rect_atlas* atlas, oc_image backingImage, u32 width, u32 height, u8* pixels); +oc_image_region oc_image_atlas_alloc_from_data(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 data, bool flip); +oc_image_region oc_image_atlas_alloc_from_file(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 path, bool flip); +void oc_image_atlas_recycle(oc_rect_atlas* atlas, oc_image_region imageRgn); diff --git a/doc/cheatsheet_io.h b/doc/cheatsheet_io.h new file mode 100644 index 0000000..59d8a71 --- /dev/null +++ b/doc/cheatsheet_io.h @@ -0,0 +1,39 @@ +/************************************************************/ /** +* +* @file: cheatsheet_io.h +* @author: Martin Fouilleul +* @date: 05/09/2023 +* +*****************************************************************/ + +//---------------------------------------------------------------- +// Low-level File IO API +//---------------------------------------------------------------- +oc_io_cmp oc_io_wait_single_req(oc_io_req* req); + +//---------------------------------------------------------------- +// High-level File IO API +//---------------------------------------------------------------- +oc_file oc_file_nil(); +bool oc_file_is_nil(oc_file handle); + +oc_file oc_file_open(oc_str8 path, oc_file_access rights, oc_file_open_flags flags); +oc_file oc_file_open_at(oc_file dir, oc_str8 path, oc_file_access rights, oc_file_open_flags flags); +void oc_file_close(oc_file file); +oc_io_error oc_file_last_error(oc_file handle); + +i64 oc_file_pos(oc_file file); +i64 oc_file_seek(oc_file file, i64 offset, oc_file_whence whence); +u64 oc_file_write(oc_file file, u64 size, char* buffer); +u64 oc_file_read(oc_file file, u64 size, char* buffer); + +oc_file_status oc_file_get_status(oc_file file); +u64 oc_file_size(oc_file file); + +//---------------------------------------------------------------- +// Asking users for file capabilities +//---------------------------------------------------------------- +oc_file oc_file_open_with_request(oc_str8 path, oc_file_access rights, oc_file_open_flags flags); +oc_file_open_with_dialog_result oc_file_open_with_dialog(oc_arena* arena, oc_file_access rights, oc_file_open_flags flags, oc_file_dialog_desc* desc); + + diff --git a/doc/cheatsheet_ui.h b/doc/cheatsheet_ui.h new file mode 100644 index 0000000..3487195 --- /dev/null +++ b/doc/cheatsheet_ui.h @@ -0,0 +1,64 @@ +/************************************************************/ /** +* +* @file: cheatsheet_ui.h +* @author: Martin Fouilleul +* @date: 05/09/2023 +* +*****************************************************************/ + +//---------------------------------------------------------------- +// Context and frame lifecycle +//---------------------------------------------------------------- + +void oc_ui_init(oc_ui_context* context); +oc_ui_context* oc_ui_get_context(void); +void oc_ui_set_context(oc_ui_context* context); + +void oc_ui_process_event(oc_event* event); +void oc_ui_begin_frame(oc_vec2 size, oc_ui_style* defaultStyle, oc_ui_style_mask mask); +void oc_ui_end_frame(void); +void oc_ui_draw(void); + +#define oc_ui_frame(size, style, mask) + +//---------------------------------------------------------------- +// Common widget helpers +//---------------------------------------------------------------- + +oc_ui_sig oc_ui_label(const char* label); +oc_ui_sig oc_ui_label_str8(oc_str8 label); +oc_ui_sig oc_ui_button(const char* label); +oc_ui_sig oc_ui_checkbox(const char* name, bool* checked); +oc_ui_box* oc_ui_slider(const char* label, f32 thumbRatio, f32* scrollValue); +oc_ui_text_box_result oc_ui_text_box(const char* name, oc_arena* arena, oc_str8 text); +oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_info* info); + +void oc_ui_panel_begin(const char* name, oc_ui_flags flags); +void oc_ui_panel_end(void); +#define oc_ui_panel(s, f) + +void oc_ui_menu_bar_begin(const char* label); +void oc_ui_menu_bar_end(void); +#define oc_ui_menu_bar(name) + +void oc_ui_menu_begin(const char* label); +void oc_ui_menu_end(void); +#define oc_ui_menu(name) + +oc_ui_sig oc_ui_menu_button(const char* name); + +oc_ui_sig oc_ui_tooltip_begin(const char* name); +void oc_ui_tooltip_end(void); +#define oc_ui_tooltip(name) + +//------------------------------------------------------------------------------------- +// Styling +//------------------------------------------------------------------------------------- +void oc_ui_style_next(oc_ui_style* style, oc_ui_style_mask mask); + +void oc_ui_pattern_push(oc_arena* arena, oc_ui_pattern* pattern, oc_ui_selector selector); +oc_ui_pattern oc_ui_pattern_all(void); +oc_ui_pattern oc_ui_pattern_owner(void); + +void oc_ui_style_match_before(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask); +void oc_ui_style_match_after(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask); diff --git a/doc/cheatsheet_util.h b/doc/cheatsheet_util.h new file mode 100644 index 0000000..f6349bf --- /dev/null +++ b/doc/cheatsheet_util.h @@ -0,0 +1,101 @@ +/************************************************************/ /** +* +* @file: cheatsheet_util.h +* @author: Martin Fouilleul +* @date: 05/09/2023 +* +*****************************************************************/ + +//---------------------------------------------------------------- +// Arenas +//---------------------------------------------------------------- + +void oc_arena_init(oc_arena* arena); +void oc_arena_init_with_options(oc_arena* arena, oc_arena_options* options); +void oc_arena_cleanup(oc_arena* arena); + +void* oc_arena_push(oc_arena* arena, u64 size); +#define oc_arena_push_type(arena, type) +#define oc_arena_push_array(arena, type, count) +void oc_arena_clear(oc_arena* arena); + +oc_arena_scope oc_arena_scope_begin(oc_arena* arena); +void oc_arena_scope_end(oc_arena_scope scope); + +oc_arena_scope oc_scratch_begin(void); +oc_arena_scope oc_scratch_begin_next(oc_arena* used); +#define oc_scratch_end(scope) + +//---------------------------------------------------------------- +// Lists +//---------------------------------------------------------------- + +void oc_list_init(oc_list* list); +bool oc_list_empty(oc_list* list); + +oc_list_elt* oc_list_begin(oc_list* list); +oc_list_elt* oc_list_end(oc_list* list); +oc_list_elt* oc_list_last(oc_list* list); + +#define oc_list_next(elt) +#define oc_list_prev(elt) +#define oc_list_entry(ptr, type, member) +#define oc_list_next_entry(list, elt, type, member) +#define oc_list_prev_entry(list, elt, type, member) +#define oc_list_first_entry(list, type, member) +#define oc_list_last_entry(list, type, member) +#define oc_list_pop_entry(list, type, member) + +void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt); +void oc_list_insert_before(oc_list* list, oc_list_elt* beforeElt, oc_list_elt* elt); +void oc_list_remove(oc_list* list, oc_list_elt* elt); +void oc_list_push(oc_list* list, oc_list_elt* elt); +oc_list_elt* oc_list_pop(oc_list* list); +void oc_list_push_back(oc_list* list, oc_list_elt* elt); +oc_list_elt* oc_list_pop_back(oc_list* list); + +#define oc_list_for(list, elt, type, member) +#define oc_list_for_reverse(list, elt, type, member) +#define oc_list_for_safe(list, elt, type, member) + +//---------------------------------------------------------------- +// Strings / string lists / path strings +//---------------------------------------------------------------- + +oc_str8 oc_str8_from_buffer(u64 len, char* buffer); +oc_str8 oc_str8_slice(oc_str8 s, u64 start, u64 end); + +oc_str8 oc_str8_push_buffer(oc_arena* arena, u64 len, char* buffer); +oc_str8 oc_str8_push_cstring(oc_arena* arena, const char* str); +oc_str8 oc_str8_push_copy(oc_arena* arena, oc_str8 s); +oc_str8 oc_str8_push_slice(oc_arena* arena, oc_str8 s, u64 start, u64 end); +oc_str8 oc_str8_pushfv(oc_arena* arena, const char* format, va_list args); +oc_str8 oc_str8_pushf(oc_arena* arena, const char* format, ...); + +int oc_str8_cmp(oc_str8 s1, oc_str8 s2); + +char* oc_str8_to_cstring(oc_arena* arena, oc_str8 string); + +void oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str); +void oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...); + +oc_str8 oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix); +oc_str8 oc_str8_list_join(oc_arena* arena, oc_str8_list list); +oc_str8_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators); + +oc_str8 oc_path_slice_directory(oc_str8 path); +oc_str8 oc_path_slice_filename(oc_str8 path); +oc_str8_list oc_path_split(oc_arena* arena, oc_str8 path); +oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements); +oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath); +bool oc_path_is_absolute(oc_str8 path); + +//---------------------------------------------------------------- +// Debugging +//---------------------------------------------------------------- +#define oc_log_info(message, ...) +#define oc_log_warning(message, ...) +#define oc_log_error(message, ...) + +#define OC_ASSERT(test, message, ...) +#define OC_ABORT(message, ...) diff --git a/samples/clock/src/main.c b/samples/clock/src/main.c index e5b21ac..fefd5ee 100644 --- a/samples/clock/src/main.c +++ b/samples/clock/src/main.c @@ -19,7 +19,7 @@ f32 minf(f32 a, f32 b); ORCA_EXPORT void oc_on_init(void) { - oc_runtime_window_set_title(OC_STR8("clock")); + oc_window_set_title(OC_STR8("clock")); oc_runtime_window_set_size((oc_vec2){ .x = 400, .y = 400 }); surface = oc_surface_canvas(); diff --git a/samples/fluid/src/main.c b/samples/fluid/src/main.c index b86e9a6..019019a 100644 --- a/samples/fluid/src/main.c +++ b/samples/fluid/src/main.c @@ -615,7 +615,7 @@ ORCA_EXPORT void oc_on_init() { oc_log_info("Hello, world (from C)"); - oc_runtime_window_set_title(OC_STR8("fluid")); + oc_window_set_title(OC_STR8("fluid")); surface = oc_surface_gles(); oc_surface_select(surface); diff --git a/samples/glesTriangle/src/main.c b/samples/glesTriangle/src/main.c index 9ccb81a..b5a09cc 100644 --- a/samples/glesTriangle/src/main.c +++ b/samples/glesTriangle/src/main.c @@ -37,7 +37,7 @@ void compile_shader(GLuint shader, const char* source) ORCA_EXPORT void oc_on_init(void) { - oc_runtime_window_set_title(OC_STR8("triangle")); + oc_window_set_title(OC_STR8("triangle")); surface = oc_surface_gles(); oc_surface_select(surface); diff --git a/samples/pong/src/main.c b/samples/pong/src/main.c index 978eb94..0cfb47a 100644 --- a/samples/pong/src/main.c +++ b/samples/pong/src/main.c @@ -69,7 +69,7 @@ oc_str8 loadFile(oc_arena* arena, oc_str8 filename) ORCA_EXPORT void oc_on_init(void) { - oc_runtime_window_set_title(OC_STR8("pong")); + oc_window_set_title(OC_STR8("pong")); surface = oc_surface_canvas(); canvas = oc_canvas_create(); diff --git a/samples/ui/build.sh b/samples/ui/build.sh index 4d9bede..8aeea27 100755 --- a/samples/ui/build.sh +++ b/samples/ui/build.sh @@ -16,7 +16,6 @@ STDLIB_DIR=../../src/libc-shim wasmFlags="--target=wasm32 \ --no-standard-libraries \ - -fno-builtin \ -Wl,--no-entry \ -Wl,--export-dynamic \ -g \ diff --git a/samples/ui/src/main.c b/samples/ui/src/main.c index e4934ac..9990bfa 100644 --- a/samples/ui/src/main.c +++ b/samples/ui/src/main.c @@ -10,7 +10,7 @@ oc_arena textArena = { 0 }; ORCA_EXPORT void oc_on_init(void) { - oc_runtime_window_set_title(OC_STR8("ui")); + oc_window_set_title(OC_STR8("ui")); surface = oc_surface_canvas(); canvas = oc_canvas_create(); diff --git a/sketches/surface_sharing/build.bat b/sketches/surface_sharing/build.bat deleted file mode 100644 index e122dd2..0000000 --- a/sketches/surface_sharing/build.bat +++ /dev/null @@ -1,8 +0,0 @@ - -set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext /I ../../ext/angle/include - -if not exist "bin" mkdir bin -cl /we4013 /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% main.c /link /LIBPATH:../../build/bin orca.dll.lib /out:bin/example_surface_sharing.exe -copy ..\..\build\bin\orca.dll bin -copy ..\..\ext\angle\bin\libEGL.dll bin -copy ..\..\ext\angle\bin\libGLESv2.dll bin diff --git a/sketches/surface_sharing/build.sh b/sketches/surface_sharing/build.sh deleted file mode 100755 index 4518cfc..0000000 --- a/sketches/surface_sharing/build.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -BINDIR=bin -LIBDIR=../../build/bin -RESDIR=../resources -SRCDIR=../../src -EXTDIR=../../ext -ANGLEDIR=../../ext/angle/ - -INCLUDES="-I$SRCDIR -I$SRCDIR/util -I$SRCDIR/platform -I$SRCDIR/app -I$EXTDIR/ -I$ANGLEDIR/include" -LIBS="-L$LIBDIR -lorca" -FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG" - -mkdir -p $BINDIR -clang -g $FLAGS $LIBS $INCLUDES -o $BINDIR/example_surface_sharing main.c - -cp $LIBDIR/liborca.dylib $BINDIR/ -cp $LIBDIR/mtl_renderer.metallib $BINDIR/ -cp $ANGLEDIR/bin/libEGL.dylib $BINDIR/ -cp $ANGLEDIR/bin/libGLESv2.dylib $BINDIR/ - -install_name_tool -add_rpath "@executable_path" $BINDIR/example_surface_sharing diff --git a/sketches/surface_sharing/main.c b/sketches/surface_sharing/main.c deleted file mode 100644 index f22efce..0000000 --- a/sketches/surface_sharing/main.c +++ /dev/null @@ -1,289 +0,0 @@ - -#include -#include - -#define _USE_MATH_DEFINES //NOTE: necessary for MSVC -#include - -#include -#include - -#define OC_INCLUDE_GL_API -#include "orca.h" - -#ifdef OC_PLATFORM_WINDOWS - #include - #include - #include - - #define dup2 _dup2 - #define pipe(fds) _pipe(fds, 256, O_BINARY) - #define read _read - #define write _write - - #define process_id HANDLE - -process_id spawn_child(char* program, char** argv) -{ - return ((process_id)_spawnv(P_NOWAIT, program, argv)); -} - -void terminate_child(process_id child) -{ - TerminateProcess(child, 0); -} - -#elif OC_PLATFORM_MACOS - #include - #include - - #define process_id pid_t - -process_id spawn_child(char* program, char** argv) -{ - pid_t pid = fork(); - if(!pid) - { - char* envp[] = { 0 }; - execve(program, argv, envp); - OC_ASSERT(0); - } - return (pid); -} - -void terminate_child(process_id child) -{ - kill(child, SIGTERM); -} -#endif - -unsigned int program; - -const char* vshaderSource = - //"#version 320 es\n" - "attribute vec4 vPosition;\n" - "uniform mat4 transform;\n" - "void main()\n" - "{\n" - " gl_Position = transform*vPosition;\n" - "}\n"; - -const char* fshaderSource = - //"#version 320 es\n" - "precision mediump float;\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" - "}\n"; - -void compile_shader(GLuint shader, const char* source) -{ - glShaderSource(shader, 1, &source, 0); - glCompileShader(shader); - - int err = glGetError(); - if(err) - { - oc_log_error("gl error: %i\n", err); - } - - int status = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &status); - if(!status) - { - char buffer[256]; - int size = 0; - glGetShaderInfoLog(shader, 256, &size, buffer); - oc_log_error("shader error: %.*s\n", size, buffer); - } -} - -int child_main(int writeFd) -{ - oc_init(); - - oc_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 }; - oc_window window = oc_window_create(rect, OC_STR8("test"), 0); - - //NOTE: create surface - oc_surface surface = oc_surface_create_remote(800, 600, OC_GLES); - oc_surface_id connectionID = oc_surface_remote_id(surface); - - oc_surface_select(surface); - - //NOTE: init shader and gl state - oc_surface_select(surface); - - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - GLuint vertexBuffer; - glGenBuffers(1, &vertexBuffer); - - GLfloat vertices[] = { - -0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0 - }; - - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - unsigned int vshader = glCreateShader(GL_VERTEX_SHADER); - unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER); - program = glCreateProgram(); - - compile_shader(vshader, vshaderSource); - compile_shader(fshader, fshaderSource); - - glAttachShader(program, vshader); - glAttachShader(program, fshader); - glLinkProgram(program); - - int status = 0; - glGetProgramiv(program, GL_LINK_STATUS, &status); - if(!status) - { - char buffer[256]; - int size = 0; - glGetProgramInfoLog(program, 256, &size, buffer); - oc_log_error("link error: %.*s\n", size, buffer); - } - - glUseProgram(program); - - //NOTE: send context id to parent - write(writeFd, &connectionID, sizeof(connectionID)); - - //NOTE: render loop - while(!oc_should_quit()) - { - oc_pump_events(0); - oc_event* event = 0; - while((event = oc_next_event(oc_scratch())) != 0) - { - switch(event->type) - { - case OC_EVENT_WINDOW_CLOSE: - { - oc_request_quit(); - } - break; - - default: - break; - } - } - - oc_surface_select(surface); - - oc_vec2 size = oc_surface_get_size(surface); - oc_vec2 scaling = oc_surface_contents_scaling(surface); - - glViewport(0, 0, size.x * scaling.x, size.y * scaling.y); - glClearColor(0.3, 0.3, 1, 1); - glClear(GL_COLOR_BUFFER_BIT); - - static float alpha = 0; - //f32 aspect = frameSize.x/frameSize.y; - f32 aspect = 800 / (f32)600; - - GLfloat matrix[] = { cosf(alpha) / aspect, sinf(alpha), 0, 0, - -sinf(alpha) / aspect, cosf(alpha), 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 }; - - alpha += 2 * M_PI / 120; - - glUniformMatrix4fv(0, 1, false, matrix); - - glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); - glEnableVertexAttribArray(0); - - glDrawArrays(GL_TRIANGLES, 0, 3); - - oc_surface_present(surface); - } - - oc_terminate(); - - return (0); -} - -int main(int argc, char** argv) -{ - if(argc > 1) - { - if(!strcmp(argv[1], "--child")) - { - int writeFd = atoi(argv[2]); - oc_log_info("child process created with file desc %i\n", writeFd); - return (child_main(writeFd)); - } - else - { - return (-1); - } - } - // setvbuf( stdout, NULL, _IONBF, 0 ); - oc_init(); - - //NOTE: create main window - oc_rect rect = { .x = 100, .y = 100, .w = 800, .h = 600 }; - oc_window window = oc_window_create(rect, OC_STR8("test"), 0); - - //NOTE: create surface client - oc_surface surface = oc_surface_create_host(window); - - //NOTE setup descriptors - int fileDesc[2]; - pipe(fileDesc); - - oc_log_info("parent process created readFd %i and writeFd %i\n", fileDesc[0], fileDesc[1]); - - char writeDescStr[64]; - snprintf(writeDescStr, 64, "%i", fileDesc[1]); - char* args[] = { "bin/example_surface_sharing", "--child", writeDescStr, 0 }; - - process_id child = spawn_child(args[0], args); - - //NOTE: read the connection id - oc_surface_id connectionID = 0; - read(fileDesc[0], &connectionID, sizeof(connectionID)); - oc_log_info("received child connection id %llu\n", connectionID); - - //NOTE: connect the client - oc_surface_host_connect(surface, connectionID); - - //NOTE: show the window - oc_window_bring_to_front(window); - - while(!oc_should_quit()) - { - oc_pump_events(0); - oc_event* event = 0; - while((event = oc_next_event(oc_scratch())) != 0) - { - switch(event->type) - { - case OC_EVENT_WINDOW_CLOSE: - { - oc_request_quit(); - } - break; - - default: - break; - } - - oc_arena_clear(oc_scratch()); - } - oc_surface_select(surface); - oc_surface_present(surface); - } - - terminate_child(child); - - oc_terminate(); - return (0); -} diff --git a/src/app/app.c b/src/app/app.c index 57c7776..45e70ad 100644 --- a/src/app/app.c +++ b/src/app/app.c @@ -215,3 +215,12 @@ void oc_window_set_frame_size(oc_window window, oc_vec2 size) frame.h = size.y; oc_window_set_frame_rect(window, frame); } + +//--------------------------------------------------------------- +// dialogs +//--------------------------------------------------------------- + +oc_file_dialog_result oc_file_dialog(oc_arena* arena, oc_file_dialog_desc* desc) +{ + return (oc_file_dialog_for_table(arena, desc, oc_file_table_get_global())); +} diff --git a/src/app/app.h b/src/app/app.h index 657a162..a99a5a7 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -389,6 +389,60 @@ ORCA_API oc_str8 oc_save_dialog(oc_arena* arena, oc_str8 defaultPath, oc_str8_list filters); +#endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA) + +#include "platform/platform_io.h" + +typedef enum +{ + OC_FILE_DIALOG_SAVE, + OC_FILE_DIALOG_OPEN, +} oc_file_dialog_kind; + +typedef u32 oc_file_dialog_flags; + +enum _oc_file_dialog_flags +{ + OC_FILE_DIALOG_FILES = 1, + OC_FILE_DIALOG_DIRECTORIES = 1 << 1, + OC_FILE_DIALOG_MULTIPLE = 1 << 2, + OC_FILE_DIALOG_CREATE_DIRECTORIES = 1 << 3, +}; + +typedef struct oc_file_dialog_desc +{ + oc_file_dialog_kind kind; + oc_file_dialog_flags flags; + oc_str8 title; + oc_str8 okLabel; + oc_file startAt; + oc_str8 startPath; + oc_str8_list filters; + + //... later customization options with checkboxes / radiobuttons +} oc_file_dialog_desc; + +typedef enum +{ + OC_FILE_DIALOG_CANCEL = 0, + OC_FILE_DIALOG_OK, +} oc_file_dialog_button; + +typedef struct oc_file_dialog_result +{ + oc_file_dialog_button button; + oc_str8 path; + oc_str8_list selection; + +} oc_file_dialog_result; + +#if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA) + +ORCA_API oc_file_dialog_result oc_file_dialog(oc_arena* arena, oc_file_dialog_desc* desc); + +typedef struct oc_file_table oc_file_table; +ORCA_API oc_file_dialog_result oc_file_dialog_for_table(oc_arena* arena, oc_file_dialog_desc* desc, oc_file_table* table); + ORCA_API int oc_alert_popup(oc_str8 title, oc_str8 message, oc_str8_list options); @@ -403,12 +457,11 @@ ORCA_API int oc_directory_create(oc_str8 path); #else +void oc_window_set_title(oc_str8 title); +void oc_window_set_size(oc_vec2 size); + void ORCA_IMPORT(oc_request_quit)(void); -void ORCA_IMPORT(oc_runtime_window_set_title)(oc_str8 title); - -void ORCA_IMPORT(oc_runtime_window_set_size)(oc_vec2 size); - #endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA) #ifdef __cplusplus diff --git a/src/app/app_internal.h b/src/app/app_internal.h index 54b68d4..0899d1c 100644 --- a/src/app/app_internal.h +++ b/src/app/app_internal.h @@ -12,6 +12,7 @@ #include "app.h" #include "platform/platform.h" +#include "platform/platform_io_internal.h" #include "util/ringbuffer.h" #if OC_PLATFORM_WINDOWS diff --git a/src/app/orca_app.c b/src/app/orca_app.c index fd349f0..01180ba 100644 --- a/src/app/orca_app.c +++ b/src/app/orca_app.c @@ -2,3 +2,8 @@ //This is used to pass raw events from the runtime ORCA_EXPORT oc_event oc_rawEvent; + +ORCA_EXPORT void* oc_arena_push_stub(oc_arena* arena, u64 size) +{ + return (oc_arena_push(arena, size)); +} diff --git a/src/app/osx_app.m b/src/app/osx_app.m index e89bd70..b83e219 100644 --- a/src/app/osx_app.m +++ b/src/app/osx_app.m @@ -19,7 +19,7 @@ #include "platform_clock.h" #include "platform_debug.h" #include "ringbuffer.h" - +#include "platform/platform_path.h" #include "app.c" //-------------------------------------------------------------------- @@ -1843,213 +1843,6 @@ void oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window } } -//------------------------------------------------------------------------------------------------ -// Remote surfaces -//------------------------------------------------------------------------------------------------ -oc_surface_id oc_osx_surface_remote_id(oc_surface_data* surface) -{ - oc_surface_id remoteID = 0; - if(surface->layer.caContext) - { - @autoreleasepool - { - remoteID = (oc_surface_id)[surface->layer.caContext contextId]; - } - } - return (remoteID); -} - -void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height) -{ - @autoreleasepool - { - - surface->nativeLayer = oc_osx_surface_native_layer; - surface->contentsScaling = oc_osx_surface_contents_scaling; - surface->getSize = oc_osx_surface_get_size; - surface->getHidden = oc_osx_surface_get_hidden; - surface->setHidden = oc_osx_surface_set_hidden; - surface->remoteID = oc_osx_surface_remote_id; - - surface->layer.caLayer = [[CALayer alloc] init]; - [surface->layer.caLayer retain]; - [surface->layer.caLayer setFrame:(CGRect){ { 0, 0 }, { width, height } }]; - - NSDictionary* dict = [[NSDictionary alloc] init]; - CGSConnectionID connectionID = CGSMainConnectionID(); - surface->layer.caContext = [CAContext contextWithCGSConnection:connectionID options:dict]; - [surface->layer.caContext retain]; - [surface->layer.caContext setLayer:surface->layer.caLayer]; - } -} - -void oc_osx_surface_host_connect(oc_surface_data* surface, oc_surface_id remoteID) -{ - @autoreleasepool - { - [(CALayerHost*)surface->layer.caLayer setContextId:(CAContextID)remoteID]; - } -} - -void oc_surface_init_host(oc_surface_data* surface, oc_window_data* window) -{ - @autoreleasepool - { - - surface->api = OC_HOST; - surface->nativeLayer = oc_osx_surface_native_layer; - surface->contentsScaling = oc_osx_surface_contents_scaling; - surface->getSize = oc_osx_surface_get_size; - surface->getHidden = oc_osx_surface_get_hidden; - surface->setHidden = oc_osx_surface_set_hidden; - surface->hostConnect = oc_osx_surface_host_connect; - - surface->layer.caLayer = [[CALayerHost alloc] init]; - [surface->layer.caLayer retain]; - - NSRect frame = [[window->osx.nsWindow contentView] frame]; - CGSize size = frame.size; - [surface->layer.caLayer setFrame:(CGRect){ { 0, 0 }, size }]; - - [window->osx.nsView.layer addSublayer:surface->layer.caLayer]; - } -} - -oc_surface_data* oc_osx_surface_create_host(oc_window windowHandle) -{ - oc_surface_data* surface = 0; - oc_window_data* window = oc_window_ptr_from_handle(windowHandle); - if(window) - { - surface = oc_malloc_type(oc_surface_data); - if(surface) - { - oc_surface_init_host(surface, window); - } - } - return (surface); -} - -//-------------------------------------------------------------------- -// view management -//-------------------------------------------------------------------- -/* -oc_view oc_view_create(oc_window windowHandle, oc_rect frame) -{@autoreleasepool{ - oc_window_data* window = oc_window_ptr_from_handle(windowHandle); - if(!window) - { - oc_log_error("Can't create view for nil window\n"); - return(oc_view_nil()); - } - - oc_view_data* view = oc_view_alloc(); - if(!view) - { - oc_log_error("Could not allocate view data\n"); - return(oc_view_nil()); - } - - view->window = windowHandle; - - NSRect nsFrame = {{frame.x, frame.y}, {frame.w, frame.h}}; - view->nsView = [[NSView alloc] initWithFrame: nsFrame]; - [view->nsView setWantsLayer:YES]; - - [[window->osx.nsWindow contentView] addSubview: view->nsView]; - - return(oc_view_handle_from_ptr(view)); -}} - -void oc_view_destroy(oc_view viewHandle) -{@autoreleasepool{ - oc_view_data* view = oc_view_ptr_from_handle(viewHandle); - if(!view) - { - return; - } - - oc_window_data* window = oc_window_ptr_from_handle(view->window); - if(!window) - { - return; - } - - [view->nsView removeFromSuperview]; - - oc_view_recycle_ptr(view); -}} - -void oc_view_set_frame(oc_view viewHandle, oc_rect frame) -{ - oc_view_data* view = oc_view_ptr_from_handle(viewHandle); - if(!view) - { - return; - } - - NSRect nsFrame = {{frame.x, frame.y}, {frame.w, frame.h}}; - [view->nsView setFrame: nsFrame]; - - if(!oc_surface_is_nil(view->surface)) - { - oc_surface_resize(view->surface, frame.w, frame.h); - } -} -*/ -//-------------------------------------------------------------------- -// Main loop throttle -//-------------------------------------------------------------------- - -void oc_set_target_fps(u32 fps) -{ - oc_appData.frameStats.targetFramePeriod = 1. / (f64)fps; - oc_appData.frameStats.workTime = 0; - oc_appData.frameStats.remainingTime = 0; - - if(oc_appData.osx.frameTimer) - { - [oc_appData.osx.frameTimer invalidate]; - } - - oc_appData.osx.frameTimer = [NSTimer timerWithTimeInterval:oc_appData.frameStats.targetFramePeriod - target:[NSApp delegate] - selector:@selector(timerElapsed:) - userInfo:nil - repeats:YES]; - - [[NSRunLoop currentRunLoop] addTimer:oc_appData.osx.frameTimer forMode:NSRunLoopCommonModes]; -} - -/* -void oc_begin_frame() -{ - oc_appData.frameStats.start = oc_get_elapsed_seconds(); - - LOG_DEBUG("workTime = %.6f (%.6f fps), remaining = %.6f\n", - oc_appData.frameStats.workTime, - 1/oc_appData.frameStats.workTime, - oc_appData.frameStats.remainingTime); - -} - -void oc_end_frame() -{ - oc_appData.frameStats.workTime = oc_get_elapsed_seconds() - oc_appData.frameStats.start; - oc_appData.frameStats.remainingTime = oc_appData.frameStats.targetFramePeriod - oc_appData.frameStats.workTime; - - while(oc_appData.frameStats.remainingTime > 100e-9) - { - if(oc_appData.frameStats.remainingTime > 10e-6) - { - oc_sleep_nano(oc_appData.frameStats.remainingTime*0.8*1e9); - } - oc_appData.frameStats.workTime = oc_get_elapsed_seconds() - oc_appData.frameStats.start; - oc_appData.frameStats.remainingTime = oc_appData.frameStats.targetFramePeriod - oc_appData.frameStats.workTime; - } -} -*/ - //-------------------------------------------------------------------- // Events handling //-------------------------------------------------------------------- @@ -2133,73 +1926,87 @@ oc_str8 oc_open_dialog(oc_arena* arena, oc_str8_list filters, bool directory) { - @autoreleasepool + __block oc_str8 path = { 0 }; + + dispatch_block_t block = ^{ + @autoreleasepool + { + NSWindow* keyWindow = [NSApp keyWindow]; + + NSOpenPanel* dialog = [NSOpenPanel openPanel]; + + NSString* nsTitle = [[NSString alloc] initWithBytes:title.ptr length:title.len encoding:NSUTF8StringEncoding]; + //NOTE: title is not displayed since OS X 10.11, now use setMessage instead. + // see https://stackoverflow.com/questions/36879212/title-bar-missing-in-nsopenpanel + [dialog setMessage:nsTitle]; + + [dialog setLevel:NSModalPanelWindowLevel]; + + if(filters.eltCount) + { + NSMutableArray* fileTypesArray = [NSMutableArray array]; + + oc_list_for((oc_list*)&filters.list, elt, oc_str8_elt, listElt) + { + oc_str8 string = elt->string; + NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding]; + [fileTypesArray addObject:filter]; + } + [dialog setAllowedFileTypes:fileTypesArray]; + } + // Enable options in the dialog. + if(directory) + { + [dialog setCanChooseDirectories:YES]; + } + else + { + [dialog setCanChooseFiles:YES]; + } + + [dialog setAllowsMultipleSelection:FALSE]; + + NSString* nsPath = 0; + ; + if(defaultPath.len) + { + nsPath = [[NSString alloc] initWithBytes:defaultPath.ptr length:defaultPath.len encoding:NSUTF8StringEncoding]; + } + else + { + nsPath = [NSString stringWithUTF8String:"~"]; + } + nsPath = [nsPath stringByExpandingTildeInPath]; + + [dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]]; + + // Display the dialog box. If the OK pressed, + // process the files. + + if([dialog runModal] == NSModalResponseOK) + { + // Gets list of all files selected + NSArray* files = [dialog URLs]; + //TODO: Loop through the files and process them. + + const char* result = [[[files objectAtIndex:0] path] UTF8String]; + + path = oc_str8_push_cstring(arena, result); + } + [keyWindow makeKeyWindow]; + } + }; + + if([NSThread isMainThread]) { - NSWindow* keyWindow = [NSApp keyWindow]; - - NSOpenPanel* dialog = [NSOpenPanel openPanel]; - [dialog setLevel:CGShieldingWindowLevel()]; - - if(filters.eltCount) - { - NSMutableArray* fileTypesArray = [NSMutableArray array]; - - oc_list_for(&filters.list, elt, oc_str8_elt, listElt) - { - oc_str8 string = elt->string; - NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding]; - [fileTypesArray addObject:filter]; - } - [dialog setAllowedFileTypes:fileTypesArray]; - } - // Enable options in the dialog. - if(directory) - { - [dialog setCanChooseDirectories:YES]; - } - else - { - [dialog setCanChooseFiles:YES]; - } - - [dialog setAllowsMultipleSelection:FALSE]; - - NSString* nsPath = 0; - ; - if(defaultPath.len) - { - nsPath = [[NSString alloc] initWithBytes:defaultPath.ptr length:defaultPath.len encoding:NSUTF8StringEncoding]; - } - else - { - nsPath = [NSString stringWithUTF8String:"~"]; - } - nsPath = [nsPath stringByExpandingTildeInPath]; - - [dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]]; - - // Display the dialog box. If the OK pressed, - // process the files. - - if([dialog runModal] == NSModalResponseOK) - { - // Gets list of all files selected - NSArray* files = [dialog URLs]; - //TODO: Loop through the files and process them. - - const char* result = [[[files objectAtIndex:0] path] UTF8String]; - - oc_str8 path = oc_str8_push_cstring(arena, result); - [keyWindow makeKeyWindow]; - - return (path); - } - else - { - [keyWindow makeKeyWindow]; - return ((oc_str8){ 0, 0 }); - } + block(); } + else + { + dispatch_sync(dispatch_get_main_queue(), block); + } + + return (path); } oc_str8 oc_save_dialog(oc_arena* arena, @@ -2207,61 +2014,221 @@ oc_str8 oc_save_dialog(oc_arena* arena, oc_str8 defaultPath, oc_str8_list filters) { - @autoreleasepool + __block oc_str8 path = { 0 }; + + dispatch_block_t block = ^{ + @autoreleasepool + { + NSWindow* keyWindow = [NSApp keyWindow]; + + NSSavePanel* dialog = [NSSavePanel savePanel]; + [dialog setLevel:CGShieldingWindowLevel()]; + + if(filters.eltCount) + { + NSMutableArray* fileTypesArray = [NSMutableArray array]; + + oc_list_for((oc_list*)&filters.list, elt, oc_str8_elt, listElt) + { + oc_str8 string = elt->string; + NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding]; + [fileTypesArray addObject:filter]; + } + [dialog setAllowedFileTypes:fileTypesArray]; + } + + NSString* nsPath = 0; + ; + if(defaultPath.len) + { + nsPath = [[NSString alloc] initWithBytes:defaultPath.ptr length:defaultPath.len encoding:NSUTF8StringEncoding]; + } + else + { + nsPath = [NSString stringWithUTF8String:"~"]; + } + nsPath = [nsPath stringByExpandingTildeInPath]; + + [dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]]; + + // Display the dialog box. If the OK pressed, + // process the files. + + if([dialog runModal] == NSModalResponseOK) + { + // Gets list of all files selected + NSURL* files = [dialog URL]; + // Loop through the files and process them. + + const char* result = [[files path] UTF8String]; + + path = oc_str8_push_cstring(arena, result); + } + [keyWindow makeKeyWindow]; + } + }; + + if([NSThread isMainThread]) { - NSWindow* keyWindow = [NSApp keyWindow]; - - NSSavePanel* dialog = [NSSavePanel savePanel]; - [dialog setLevel:CGShieldingWindowLevel()]; - - if(filters.eltCount) - { - NSMutableArray* fileTypesArray = [NSMutableArray array]; - - oc_list_for(&filters.list, elt, oc_str8_elt, listElt) - { - oc_str8 string = elt->string; - NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding]; - [fileTypesArray addObject:filter]; - } - [dialog setAllowedFileTypes:fileTypesArray]; - } - - NSString* nsPath = 0; - ; - if(defaultPath.len) - { - nsPath = [[NSString alloc] initWithBytes:defaultPath.ptr length:defaultPath.len encoding:NSUTF8StringEncoding]; - } - else - { - nsPath = [NSString stringWithUTF8String:"~"]; - } - nsPath = [nsPath stringByExpandingTildeInPath]; - - [dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]]; - - // Display the dialog box. If the OK pressed, - // process the files. - - if([dialog runModal] == NSModalResponseOK) - { - // Gets list of all files selected - NSURL* files = [dialog URL]; - // Loop through the files and process them. - - const char* result = [[files path] UTF8String]; - - oc_str8 path = oc_str8_push_cstring(arena, result); - [keyWindow makeKeyWindow]; - return (path); - } - else - { - [keyWindow makeKeyWindow]; - return ((oc_str8){ 0, 0 }); - } + block(); } + else + { + dispatch_sync(dispatch_get_main_queue(), block); + } + + return (path); +} + +ORCA_API oc_file_dialog_result oc_file_dialog_for_table(oc_arena* arena, oc_file_dialog_desc* desc, oc_file_table* table) +{ + __block oc_file_dialog_result result = { 0 }; + + dispatch_block_t block = ^{ + @autoreleasepool + { + oc_arena_scope scratch = oc_scratch_begin_next(arena); + + NSWindow* keyWindow = [NSApp keyWindow]; + + NSSavePanel* dialog = 0; + if(desc->kind == OC_FILE_DIALOG_OPEN) + { + NSOpenPanel* openPanel = [NSOpenPanel openPanel]; + dialog = (NSSavePanel*)openPanel; + + openPanel.canChooseFiles = (desc->flags & OC_FILE_DIALOG_FILES) ? YES : NO; + openPanel.canChooseDirectories = (desc->flags & OC_FILE_DIALOG_DIRECTORIES) ? YES : NO; + openPanel.allowsMultipleSelection = (desc->flags & OC_FILE_DIALOG_MULTIPLE) ? YES : NO; + } + else + { + dialog = [NSSavePanel savePanel]; + + dialog.canCreateDirectories = (desc->flags & OC_FILE_DIALOG_CREATE_DIRECTORIES) ? YES : NO; + } + + //NOTE: set title. "title" property is not displayed since OS X 10.11, now use setMessage instead. + // see https://stackoverflow.com/questions/36879212/title-bar-missing-in-nsopenpanel + NSString* nsTitle = [[NSString alloc] initWithBytes:desc->title.ptr + length:desc->title.len + encoding:NSUTF8StringEncoding]; + [dialog setMessage:nsTitle]; + + //NOTE: set ok button + if(desc->okLabel.len) + { + NSString* label = [[NSString alloc] initWithBytes:desc->okLabel.ptr + length:desc->okLabel.len + encoding:NSUTF8StringEncoding]; + + [dialog setPrompt:label]; + } + + //NOTE: set starting path + oc_str8 startPath = { 0 }; + { + oc_str8_list list = { 0 }; + if(!oc_file_is_nil(desc->startAt)) + { + oc_file_slot* slot = oc_file_slot_from_handle(table, desc->startAt); + if(slot) + { + char path[PATH_MAX]; + if(fcntl(slot->fd, F_GETPATH, path) != -1) + { + oc_str8 string = oc_str8_push_cstring(scratch.arena, path); + oc_str8_list_push(scratch.arena, &list, string); + } + } + } + if(desc->startPath.len) + { + oc_str8_list_push(scratch.arena, &list, desc->startPath); + } + startPath = oc_path_join(scratch.arena, list); + } + + NSString* nsPath = 0; + if(startPath.len) + { + nsPath = [[NSString alloc] initWithBytes:startPath.ptr + length:startPath.len + encoding:NSUTF8StringEncoding]; + } + else + { + nsPath = [NSString stringWithUTF8String:"~"]; + } + nsPath = [nsPath stringByExpandingTildeInPath]; + [dialog setDirectoryURL:[NSURL fileURLWithPath:nsPath]]; + + //NOTE: set filters + if(desc->filters.eltCount) + { + NSMutableArray* fileTypesArray = [NSMutableArray array]; + + oc_list_for((oc_list*)&desc->filters.list, elt, oc_str8_elt, listElt) + { + oc_str8 string = elt->string; + NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding]; + [fileTypesArray addObject:filter]; + } + [dialog setAllowedFileTypes:fileTypesArray]; + } + + // Display the dialog box. If the OK pressed, + // process the files. + + [dialog validateVisibleColumns]; + [dialog setLevel:NSModalPanelWindowLevel]; + + if([dialog runModal] == NSModalResponseOK) + { + if(desc->kind == OC_FILE_DIALOG_OPEN && (desc->flags & OC_FILE_DIALOG_MULTIPLE)) + { + // Gets list of all files selected + NSArray* files = [((NSOpenPanel*)dialog) URLs]; + + const char* path = [[[files objectAtIndex:0] path] UTF8String]; + result.path = oc_str8_push_cstring(arena, path); + + for(int i = 0; i < [files count]; i++) + { + const char* path = [[[files objectAtIndex:i] path] UTF8String]; + oc_str8 string = oc_str8_push_cstring(arena, path); + oc_str8_list_push(arena, &result.selection, string); + } + } + else + { + const char* path = [[[dialog URL] path] UTF8String]; + result.path = oc_str8_push_cstring(arena, path); + + oc_str8_list_push(arena, &result.selection, result.path); + } + result.button = OC_FILE_DIALOG_OK; + } + else + { + result.button = OC_FILE_DIALOG_CANCEL; + } + [keyWindow makeKeyWindow]; + + oc_scratch_end(scratch); + } + }; + + if([NSThread isMainThread]) + { + block(); + } + else + { + dispatch_sync(dispatch_get_main_queue(), block); + } + + return (result); } int oc_alert_popup(oc_str8 title, diff --git a/src/app/win32_app.c b/src/app/win32_app.c index e131178..7312295 100644 --- a/src/app/win32_app.c +++ b/src/app/win32_app.c @@ -1189,16 +1189,16 @@ void oc_win32_surface_set_hidden(oc_surface_data* surface, bool hidden) void oc_win32_surface_bring_to_front(oc_surface_data* surface) { - oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt); - oc_list_push(&surface->layer.parent->win32.layers, &surface->layer.listElt); - oc_win32_update_child_layers_zorder(surface->layer.parent); + oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt); + oc_list_push(&surface->layer.parent->win32.layers, &surface->layer.listElt); + oc_win32_update_child_layers_zorder(surface->layer.parent); } void oc_win32_surface_send_to_back(oc_surface_data* surface) { - oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt); - oc_list_push_back(&surface->layer.parent->win32.layers, &surface->layer.listElt); - oc_win32_update_child_layers_zorder(surface->layer.parent); + oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt); + oc_list_push_back(&surface->layer.parent->win32.layers, &surface->layer.listElt); + oc_win32_update_child_layers_zorder(surface->layer.parent); } void* oc_win32_surface_native_layer(oc_surface_data* surface) @@ -1206,31 +1206,6 @@ void* oc_win32_surface_native_layer(oc_surface_data* surface) return ((void*)surface->layer.hWnd); } -oc_surface_id oc_win32_surface_remote_id(oc_surface_data* surface) -{ - return ((oc_surface_id)surface->layer.hWnd); -} - -void oc_win32_surface_host_connect(oc_surface_data* surface, oc_surface_id remoteID) -{ - HWND dstWnd = surface->layer.hWnd; - HWND srcWnd = (HWND)remoteID; - - RECT dstRect; - GetClientRect(dstWnd, &dstRect); - - SetParent(srcWnd, dstWnd); - ShowWindow(srcWnd, SW_NORMAL); - - SetWindowPos(srcWnd, - HWND_TOP, - 0, - 0, - dstRect.right - dstRect.left, - dstRect.bottom - dstRect.top, - SWP_NOACTIVATE | SWP_NOZORDER); -} - void oc_surface_cleanup(oc_surface_data* surface) { oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt); @@ -1307,68 +1282,6 @@ void oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window oc_list_append(&window->win32.layers, &surface->layer.listElt); } -void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height) -{ - surface->contentsScaling = oc_win32_surface_contents_scaling; - surface->getSize = oc_win32_surface_get_size; - surface->getHidden = oc_win32_surface_get_hidden; - surface->setHidden = oc_win32_surface_set_hidden; - surface->nativeLayer = oc_win32_surface_native_layer; - surface->remoteID = oc_win32_surface_remote_id; - - WNDCLASS layerWindowClass = { .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC, - .lpfnWndProc = DefWindowProc, - .hInstance = GetModuleHandleW(NULL), - .lpszClassName = "server_layer_window_class", - .hCursor = LoadCursor(0, IDC_ARROW) }; - - RegisterClass(&layerWindowClass); - - //NOTE(martin): create a temporary parent window. This seems like a necessary hack, because if layer window is created as - // a normal window first, and then parented to the client window, it breaks resizing the parent - // window for some reason... - HWND tmpParent = CreateWindow("server_layer_window_class", "layerParent", - WS_OVERLAPPED, - 0, 0, width, height, - 0, - 0, - layerWindowClass.hInstance, - 0); - - //NOTE: create the layer window - surface->layer.hWnd = CreateWindowEx(WS_EX_NOACTIVATE, - "server_layer_window_class", "layer", - WS_CHILD, - 0, 0, width, height, - tmpParent, - 0, - layerWindowClass.hInstance, - 0); - - //NOTE: unparent it and destroy tmp parent - SetParent(surface->layer.hWnd, 0); - DestroyWindow(tmpParent); -} - -oc_surface_data* oc_win32_surface_create_host(oc_window window) -{ - oc_surface_data* surface = 0; - oc_window_data* windowData = oc_window_ptr_from_handle(window); - if(windowData) - { - surface = oc_malloc_type(oc_surface_data); - if(surface) - { - memset(surface, 0, sizeof(oc_surface_data)); - oc_surface_init_for_window(surface, windowData); - - surface->api = OC_HOST; - surface->hostConnect = oc_win32_surface_host_connect; - } - } - return (surface); -} - //-------------------------------------------------------------------- // native open/save/alert windows //-------------------------------------------------------------------- @@ -1565,6 +1478,207 @@ oc_str8 oc_save_dialog(oc_arena* arena, return (res); } +#include "platform/platform_io_internal.h" + +oc_str16 win32_path_from_handle_null_terminated(oc_arena* arena, HANDLE handle); // defined in win32_io.c + +oc_file_dialog_result oc_file_dialog_for_table(oc_arena* arena, oc_file_dialog_desc* desc, oc_file_table* table) +{ + oc_arena_scope scratch = oc_scratch_begin_next(arena); + oc_file_dialog_result result = { 0 }; + + HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if(SUCCEEDED(hr)) + { + IFileDialog* dialog = 0; + + if(desc->kind == OC_FILE_DIALOG_OPEN) + { + hr = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL, &IID_IFileOpenDialog, (void**)&dialog); + if(SUCCEEDED(hr)) + { + FILEOPENDIALOGOPTIONS opt; + dialog->lpVtbl->GetOptions(dialog, &opt); + + //NOTE: OC_FILE_DIALOG_FILES is always implied, since IFileDialog offers no way to pick _only_ folders + if(desc->flags & OC_FILE_DIALOG_DIRECTORIES) + { + opt |= FOS_PICKFOLDERS; + } + else + { + opt &= ~FOS_PICKFOLDERS; + } + + if(desc->flags & OC_FILE_DIALOG_MULTIPLE) + { + opt |= FOS_ALLOWMULTISELECT; + } + else + { + opt &= ~FOS_ALLOWMULTISELECT; + } + + dialog->lpVtbl->SetOptions(dialog, opt); + } + } + else + { + hr = CoCreateInstance(&CLSID_FileSaveDialog, NULL, CLSCTX_ALL, &IID_IFileSaveDialog, (void**)&dialog); + + //NOTE: OC_FILE_DIALOG_CREATE_DIRECTORIES is implied, IFileSaveDialog offers no way of disabling it... + } + + if(SUCCEEDED(hr)) + { + //NOTE set title + if(desc->title.len) + { + oc_str16 titleWide = oc_win32_utf8_to_wide(scratch.arena, desc->title); + dialog->lpVtbl->SetTitle(dialog, (LPCWSTR)titleWide.ptr); + } + + //NOTE set ok button + if(desc->okLabel.len) + { + oc_str16 okLabelWide = oc_win32_utf8_to_wide(scratch.arena, desc->okLabel); + dialog->lpVtbl->SetOkButtonLabel(dialog, (LPCWSTR)okLabelWide.ptr); + } + + //NOTE: set starting path + oc_str8 startPath = { 0 }; + { + oc_str8_list list = { 0 }; + if(!oc_file_is_nil(desc->startAt)) + { + oc_file_slot* slot = oc_file_slot_from_handle(table, desc->startAt); + if(slot) + { + oc_str16 pathWide = win32_path_from_handle_null_terminated(scratch.arena, slot->fd); + oc_str8 path = oc_win32_wide_to_utf8(scratch.arena, pathWide); + //NOTE: remove potential \\?\ prefix which doesn't work with SHCreateItemFromParsingName() + if(!oc_str8_cmp(oc_str8_slice(path, 0, 4), OC_STR8("\\\\?\\"))) + { + path = oc_str8_slice(path, 4, path.len); + } + oc_str8_list_push(scratch.arena, &list, path); + } + } + if(desc->startPath.len) + { + oc_str8_list_push(scratch.arena, &list, desc->startPath); + } + startPath = oc_path_join(scratch.arena, list); + } + + if(startPath.len) + { + oc_str16 pathWide = oc_win32_utf8_to_wide(scratch.arena, startPath); + + IShellItem* item = 0; + hr = SHCreateItemFromParsingName((LPCWSTR)pathWide.ptr, NULL, &IID_IShellItem, (void**)&item); + if(SUCCEEDED(hr)) + { + hr = dialog->lpVtbl->SetFolder(dialog, item); + item->lpVtbl->Release(item); + } + } + + //NOTE: set filters + if(desc->filters.eltCount) + { + COMDLG_FILTERSPEC* filterSpecs = oc_arena_push_array(scratch.arena, COMDLG_FILTERSPEC, desc->filters.eltCount); + + int i = 0; + oc_list_for(&desc->filters.list, elt, oc_str8_elt, listElt) + { + oc_str8_list list = { 0 }; + oc_str8_list_push(scratch.arena, &list, OC_STR8("*.")); + oc_str8_list_push(scratch.arena, &list, elt->string); + oc_str8 filter = oc_str8_list_join(scratch.arena, list); + + int filterWideSize = 1 + MultiByteToWideChar(CP_UTF8, 0, filter.ptr, filter.len, NULL, 0); + filterSpecs[i].pszSpec = oc_arena_push_array(scratch.arena, wchar_t, filterWideSize); + MultiByteToWideChar(CP_UTF8, 0, filter.ptr, filter.len, (LPWSTR)filterSpecs[i].pszSpec, filterWideSize); + ((LPWSTR)(filterSpecs[i].pszSpec))[filterWideSize - 1] = 0; + + filterSpecs[i].pszName = filterSpecs[i].pszSpec; + i++; + } + + hr = dialog->lpVtbl->SetFileTypes(dialog, i, filterSpecs); + } + + hr = dialog->lpVtbl->Show(dialog, NULL); + + if(SUCCEEDED(hr)) + { + if(desc->kind == OC_FILE_DIALOG_OPEN && (desc->flags & OC_FILE_DIALOG_MULTIPLE)) + { + IShellItemArray* array = 0; + hr = ((IFileOpenDialog*)dialog)->lpVtbl->GetResults((IFileOpenDialog*)dialog, &array); + if(SUCCEEDED(hr)) + { + int count = 0; + array->lpVtbl->GetCount(array, &count); + for(int i = 0; i < count; i++) + { + IShellItem* item = 0; + hr = array->lpVtbl->GetItemAt(array, i, &item); + if(SUCCEEDED(hr)) + { + PWSTR pathWCStr = 0; + hr = item->lpVtbl->GetDisplayName(item, SIGDN_FILESYSPATH, &pathWCStr); + if(SUCCEEDED(hr)) + { + oc_str16 pathWide = oc_str16_from_buffer(lstrlenW(pathWCStr), pathWCStr); + oc_str8 path = oc_win32_wide_to_utf8(arena, pathWide); + oc_str8_list_push(arena, &result.selection, path); + + if(i == 0) + { + result.path = path; + } + + CoTaskMemFree(pathWCStr); + } + item->lpVtbl->Release(item); + } + } + result.button = OC_FILE_DIALOG_OK; + } + } + else + { + IShellItem* item; + hr = dialog->lpVtbl->GetResult(dialog, &item); + if(SUCCEEDED(hr)) + { + PWSTR pathWCStr; + hr = item->lpVtbl->GetDisplayName(item, SIGDN_FILESYSPATH, &pathWCStr); + + if(SUCCEEDED(hr)) + { + oc_str16 pathWide = oc_str16_from_buffer(lstrlenW(pathWCStr), pathWCStr); + result.path = oc_win32_wide_to_utf8(arena, pathWide); + oc_str8_list_push(arena, &result.selection, result.path); + + CoTaskMemFree(pathWCStr); + } + item->lpVtbl->Release(item); + result.button = OC_FILE_DIALOG_OK; + } + } + } + } + dialog->lpVtbl->Release(dialog); + } + CoUninitialize(); + + oc_scratch_end(scratch); + return (result); +} + #include int oc_alert_popup(oc_str8 title, diff --git a/src/graphics/egl_surface.c b/src/graphics/egl_surface.c index 1fdaf0f..e7d491f 100644 --- a/src/graphics/egl_surface.c +++ b/src/graphics/egl_surface.c @@ -150,22 +150,6 @@ void oc_egl_surface_init(oc_egl_surface* surface) eglSwapInterval(surface->eglDisplay, 1); } -oc_surface_data* oc_egl_surface_create_remote(u32 width, u32 height) -{ - oc_egl_surface* surface = 0; - - surface = oc_malloc_type(oc_egl_surface); - if(surface) - { - memset(surface, 0, sizeof(oc_egl_surface)); - - oc_surface_init_remote((oc_surface_data*)surface, width, height); - oc_egl_surface_init(surface); - } - - return ((oc_surface_data*)surface); -} - oc_surface_data* oc_egl_surface_create_for_window(oc_window window) { oc_egl_surface* surface = 0; diff --git a/src/graphics/graphics.h b/src/graphics/graphics.h index f8dd612..860a941 100644 --- a/src/graphics/graphics.h +++ b/src/graphics/graphics.h @@ -14,7 +14,7 @@ #include "util/typedefs.h" //------------------------------------------------------------------------------------------ -//NOTE(martin): backends selection +//SECTION: backends selection //------------------------------------------------------------------------------------------ typedef enum @@ -85,49 +85,48 @@ typedef enum #include "wgl_surface.h" #endif -//TODO: expose nsgl surface when supported, expose egl surface, etc... - -//TODO: add OC_INCLUDE_OPENGL/GLES/etc, once we know how we make different gl versions co-exist - ORCA_API bool oc_is_surface_api_available(oc_surface_api api); //------------------------------------------------------------------------------------------ -//NOTE(martin): graphics surface +//SECTION: graphics surface //------------------------------------------------------------------------------------------ typedef struct oc_surface { u64 h; } oc_surface; -ORCA_API oc_surface oc_surface_nil(void); -ORCA_API bool oc_surface_is_nil(oc_surface surface); +ORCA_API oc_surface oc_surface_nil(void); //DOC: returns a nil surface +ORCA_API bool oc_surface_is_nil(oc_surface surface); //DOC: true if surface is nil + +#if !defined(OC_PLATFORM_ORCA) || !OC_PLATFORM_ORCA ORCA_API oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api); -ORCA_API void oc_surface_destroy(oc_surface surface); - -ORCA_API void oc_surface_select(oc_surface surface); -ORCA_API void oc_surface_present(oc_surface surface); -ORCA_API void oc_surface_deselect(void); ORCA_API void oc_surface_swap_interval(oc_surface surface, int swap); -ORCA_API oc_vec2 oc_surface_get_size(oc_surface surface); -ORCA_API oc_vec2 oc_surface_contents_scaling(oc_surface surface); ORCA_API bool oc_surface_get_hidden(oc_surface surface); ORCA_API void oc_surface_set_hidden(oc_surface surface, bool hidden); -ORCA_API void oc_surface_bring_to_front(oc_surface surface); -ORCA_API void oc_surface_send_to_back(oc_surface surface); +#else -//NOTE(martin): surface sharing -typedef u64 oc_surface_id; +ORCA_API oc_surface oc_surface_canvas(); //DOC: creates a surface for use with the canvas API +ORCA_API oc_surface oc_surface_gles(); //DOC: create a surface for use with GLES API -ORCA_API oc_surface oc_surface_create_remote(u32 width, u32 height, oc_surface_api api); -ORCA_API oc_surface oc_surface_create_host(oc_window window); -ORCA_API oc_surface_id oc_surface_remote_id(oc_surface surface); -ORCA_API void oc_surface_host_connect(oc_surface surface, oc_surface_id remoteId); +#endif + +ORCA_API void oc_surface_destroy(oc_surface surface); //DOC: destroys the surface + +ORCA_API void oc_surface_select(oc_surface surface); //DOC: selects the surface in the current thread before drawing +ORCA_API void oc_surface_present(oc_surface surface); //DOC: presents the surface to its window +ORCA_API void oc_surface_deselect(void); //DOC: deselects the current thread's previously selected surface + +ORCA_API oc_vec2 oc_surface_get_size(oc_surface surface); +ORCA_API oc_vec2 oc_surface_contents_scaling(oc_surface surface); //DOC: returns the scaling of the surface (pixels = points * scale) + +ORCA_API void oc_surface_bring_to_front(oc_surface surface); //DOC: puts surface on top of the surface stack +ORCA_API void oc_surface_send_to_back(oc_surface surface); //DOC: puts surface at the bottom of the surface stack //------------------------------------------------------------------------------------------ -//NOTE(martin): graphics canvas structs +//SECTION: graphics canvas structs //------------------------------------------------------------------------------------------ typedef struct oc_canvas { @@ -196,18 +195,18 @@ typedef struct oc_text_extents } oc_text_extents; //------------------------------------------------------------------------------------------ -//NOTE(martin): graphics canvas +//SECTION: graphics canvas //------------------------------------------------------------------------------------------ -ORCA_API oc_canvas oc_canvas_nil(void); -ORCA_API bool oc_canvas_is_nil(oc_canvas canvas); +ORCA_API oc_canvas oc_canvas_nil(void); //DOC: returns a nil canvas +ORCA_API bool oc_canvas_is_nil(oc_canvas canvas); //DOC: true if canvas is nil -ORCA_API oc_canvas oc_canvas_create(void); -ORCA_API void oc_canvas_destroy(oc_canvas canvas); -ORCA_API oc_canvas oc_canvas_set_current(oc_canvas canvas); -ORCA_API void oc_render(oc_surface surface, oc_canvas canvas); +ORCA_API oc_canvas oc_canvas_create(void); //DOC: create a new canvas +ORCA_API void oc_canvas_destroy(oc_canvas canvas); //DOC: destroys canvas +ORCA_API oc_canvas oc_canvas_set_current(oc_canvas canvas); //DOC: selects canvas in the current thread +ORCA_API void oc_render(oc_surface surface, oc_canvas canvas); //DOC: renders all canvas commands onto surface //------------------------------------------------------------------------------------------ -//NOTE(martin): fonts +//SECTION: fonts //------------------------------------------------------------------------------------------ ORCA_API oc_font oc_font_nil(void); ORCA_API oc_font oc_font_create_from_memory(oc_str8 mem, u32 rangeCount, oc_unicode_range* ranges); @@ -235,7 +234,7 @@ ORCA_API oc_rect oc_text_bounding_box_utf32(oc_font font, f32 fontSize, oc_str32 ORCA_API oc_rect oc_text_bounding_box(oc_font font, f32 fontSize, oc_str8 text); //------------------------------------------------------------------------------------------ -//NOTE(martin): images +//SECTION: images //------------------------------------------------------------------------------------------ ORCA_API oc_image oc_image_nil(void); ORCA_API bool oc_image_is_nil(oc_image a); @@ -251,7 +250,7 @@ ORCA_API void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* p ORCA_API oc_vec2 oc_image_size(oc_image image); //------------------------------------------------------------------------------------------ -//NOTE(martin): atlasing +//SECTION: atlasing //------------------------------------------------------------------------------------------ //NOTE: rectangle allocator @@ -274,19 +273,18 @@ ORCA_API oc_image_region oc_image_atlas_alloc_from_file(oc_rect_atlas* atlas, oc ORCA_API void oc_image_atlas_recycle(oc_rect_atlas* atlas, oc_image_region imageRgn); //------------------------------------------------------------------------------------------ -//NOTE(martin): transform, viewport and clipping +//SECTION: transform, viewport and clipping //------------------------------------------------------------------------------------------ -ORCA_API void oc_viewport(oc_rect viewPort); - ORCA_API void oc_matrix_push(oc_mat2x3 matrix); ORCA_API void oc_matrix_pop(void); +ORCA_API oc_mat2x3 oc_matrix_top(); ORCA_API void oc_clip_push(f32 x, f32 y, f32 w, f32 h); ORCA_API void oc_clip_pop(void); -ORCA_API oc_rect oc_clip(); +ORCA_API oc_rect oc_clip_top(); //------------------------------------------------------------------------------------------ -//NOTE(martin): graphics attributes setting/getting +//SECTION: graphics attributes setting/getting //------------------------------------------------------------------------------------------ ORCA_API void oc_set_color(oc_color color); ORCA_API void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a); @@ -310,9 +308,11 @@ ORCA_API oc_cap_type oc_get_cap(void); ORCA_API oc_font oc_get_font(void); ORCA_API f32 oc_get_font_size(void); ORCA_API bool oc_get_text_flip(void); +ORCA_API oc_image oc_get_image(); +ORCA_API oc_rect oc_get_image_source_region(); //------------------------------------------------------------------------------------------ -//NOTE(martin): path construction +//SECTION: path construction //------------------------------------------------------------------------------------------ ORCA_API oc_vec2 oc_get_position(void); ORCA_API void oc_move_to(f32 x, f32 y); @@ -326,14 +326,14 @@ ORCA_API void oc_codepoints_outlines(oc_str32 string); ORCA_API void oc_text_outlines(oc_str8 string); //------------------------------------------------------------------------------------------ -//NOTE(martin): clear/fill/stroke +//SECTION: clear/fill/stroke //------------------------------------------------------------------------------------------ ORCA_API void oc_clear(void); ORCA_API void oc_fill(void); ORCA_API void oc_stroke(void); //------------------------------------------------------------------------------------------ -//NOTE(martin): 'fast' shapes primitives +//SECTION: shapes helpers //------------------------------------------------------------------------------------------ ORCA_API void oc_rectangle_fill(f32 x, f32 y, f32 w, f32 h); ORCA_API void oc_rectangle_stroke(f32 x, f32 y, f32 w, f32 h); diff --git a/src/graphics/graphics_common.c b/src/graphics/graphics_common.c index ccbefa4..9256856 100644 --- a/src/graphics/graphics_common.c +++ b/src/graphics/graphics_common.c @@ -928,6 +928,21 @@ void oc_matrix_pop() } } +oc_mat2x3 oc_matrix_top() +{ + oc_mat2x3 mat = { + 1, 0, 0, + 0, 1, 0 + }; + oc_canvas_data* canvas = __mgCurrentCanvas; + if(canvas) + { + mat = oc_matrix_stack_top(canvas); + } + + return (mat); +} + void oc_clip_push(f32 x, f32 y, f32 w, f32 h) { oc_canvas_data* canvas = __mgCurrentCanvas; @@ -972,7 +987,7 @@ void oc_clip_pop() } } -oc_rect oc_clip() +oc_rect oc_clip_top() { oc_rect clip = { -FLT_MAX / 2, -FLT_MAX / 2, FLT_MAX, FLT_MAX }; @@ -1193,6 +1208,28 @@ bool oc_get_text_flip() return (flip); } +oc_image oc_get_image() +{ + oc_image image = oc_image_nil(); + oc_canvas_data* canvas = __mgCurrentCanvas; + if(canvas) + { + image = canvas->attributes.image; + } + return (image); +} + +oc_rect oc_get_image_source_region() +{ + oc_rect rect = { 0 }; + oc_canvas_data* canvas = __mgCurrentCanvas; + if(canvas) + { + rect = canvas->attributes.srcRegion; + } + return (rect); +} + //------------------------------------------------------------------------------------------ //NOTE(martin): path construction //------------------------------------------------------------------------------------------ diff --git a/src/graphics/graphics_surface.c b/src/graphics/graphics_surface.c index 446f819..d55ba82 100644 --- a/src/graphics/graphics_surface.c +++ b/src/graphics/graphics_surface.c @@ -153,55 +153,6 @@ oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api) return (surfaceHandle); } -oc_surface oc_surface_create_remote(u32 width, u32 height, oc_surface_api api) -{ - if(!oc_graphicsData.init) - { - oc_graphics_init(); - } - oc_surface surfaceHandle = oc_surface_nil(); - oc_surface_data* surface = 0; - - switch(api) - { -#if OC_COMPILE_GLES - case OC_GLES: - surface = oc_egl_surface_create_remote(width, height); - break; -#endif - - default: - break; - } - if(surface) - { - surfaceHandle = oc_surface_handle_alloc(surface); - oc_surface_select(surfaceHandle); - } - return (surfaceHandle); -} - -oc_surface oc_surface_create_host(oc_window window) -{ - if(!oc_graphicsData.init) - { - oc_graphics_init(); - } - oc_surface handle = oc_surface_nil(); - oc_surface_data* surface = 0; -#if OC_PLATFORM_MACOS - surface = oc_osx_surface_create_host(window); -#elif OC_PLATFORM_WINDOWS - surface = oc_win32_surface_create_host(window); -#endif - - if(surface) - { - handle = oc_surface_handle_alloc(surface); - } - return (handle); -} - void oc_surface_destroy(oc_surface handle) { OC_DEBUG_ASSERT(oc_graphicsData.init); @@ -328,26 +279,6 @@ void* oc_surface_native_layer(oc_surface surface) return (res); } -oc_surface_id oc_surface_remote_id(oc_surface handle) -{ - oc_surface_id remoteId = 0; - oc_surface_data* surface = oc_surface_data_from_handle(handle); - if(surface && surface->remoteID) - { - remoteId = surface->remoteID(surface); - } - return (remoteId); -} - -void oc_surface_host_connect(oc_surface handle, oc_surface_id remoteID) -{ - oc_surface_data* surface = oc_surface_data_from_handle(handle); - if(surface && surface->hostConnect) - { - surface->hostConnect(surface, remoteID); - } -} - void oc_surface_render_commands(oc_surface surface, oc_color clearColor, u32 primitiveCount, diff --git a/src/graphics/graphics_surface.h b/src/graphics/graphics_surface.h index 7bce53b..f1a1ee5 100644 --- a/src/graphics/graphics_surface.h +++ b/src/graphics/graphics_surface.h @@ -31,8 +31,6 @@ typedef oc_vec2 (*oc_surface_contents_scaling_proc)(oc_surface_data* surface); typedef bool (*oc_surface_get_hidden_proc)(oc_surface_data* surface); typedef void (*oc_surface_set_hidden_proc)(oc_surface_data* surface, bool hidden); typedef void* (*oc_surface_native_layer_proc)(oc_surface_data* surface); -typedef oc_surface_id (*oc_surface_remote_id_proc)(oc_surface_data* surface); -typedef void (*oc_surface_host_connect_proc)(oc_surface_data* surface, oc_surface_id remoteId); typedef void (*oc_surface_bring_to_front_proc)(oc_surface_data* surface); typedef void (*oc_surface_send_to_back_proc)(oc_surface_data* surface); @@ -52,8 +50,6 @@ typedef struct oc_surface_data oc_surface_get_hidden_proc getHidden; oc_surface_set_hidden_proc setHidden; oc_surface_native_layer_proc nativeLayer; - oc_surface_remote_id_proc remoteID; - oc_surface_host_connect_proc hostConnect; oc_surface_bring_to_front_proc bringToFront; oc_surface_send_to_back_proc sendToBack; @@ -66,8 +62,6 @@ oc_surface oc_surface_handle_alloc(oc_surface_data* surface); oc_surface_data* oc_surface_data_from_handle(oc_surface handle); void oc_surface_init_for_window(oc_surface_data* surface, oc_window_data* window); -void oc_surface_init_remote(oc_surface_data* surface, u32 width, u32 height); -void oc_surface_init_host(oc_surface_data* surface, oc_window_data* window); void oc_surface_cleanup(oc_surface_data* surface); void* oc_surface_native_layer(oc_surface surface); diff --git a/src/orca.c b/src/orca.c index 078a89e..996f370 100644 --- a/src/orca.c +++ b/src/orca.c @@ -53,6 +53,7 @@ #include "platform/platform_io_common.c" #include "platform/orca_io_stubs.c" #include "platform/orca_platform.c" + #include "platform/platform_path.c" #else #error "Unsupported platform" #endif diff --git a/src/orca.h b/src/orca.h index 02d4e9c..c7bcb9c 100644 --- a/src/orca.h +++ b/src/orca.h @@ -22,6 +22,7 @@ #include "platform/platform.h" #include "platform/platform_clock.h" #include "platform/platform_io.h" +#include "platform/platform_io_dialog.h" #include "platform/platform_path.h" #if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA) @@ -39,9 +40,6 @@ //TODO: maybe make this conditional #include "graphics/orca_gl31.h" -oc_surface oc_surface_canvas(); -oc_surface oc_surface_gles(); - #else #ifdef OC_INCLUDE_GL_API #include "graphics/gl_api.h" diff --git a/src/platform/orca_debug.c b/src/platform/orca_debug.c index 2ccdc5a..a71742e 100644 --- a/src/platform/orca_debug.c +++ b/src/platform/orca_debug.c @@ -49,7 +49,7 @@ typedef struct oc_log_output static oc_log_output oc_logDefaultOutput = { .kind = ORCA_LOG_OUTPUT_CONSOLE }; oc_log_output* OC_LOG_DEFAULT_OUTPUT = &oc_logDefaultOutput; -void ORCA_IMPORT(oc_runtime_log)(oc_log_level level, +void ORCA_IMPORT(oc_bridge_log)(oc_log_level level, int fileLen, const char* file, int functionLen, @@ -77,7 +77,7 @@ void platform_log_push(oc_log_output* output, oc_str8 string = oc_str8_list_join(scratch, ctx.list); - oc_runtime_log(level, strlen(file), file, strlen(function), function, line, oc_str8_ip(string)); + oc_bridge_log(level, strlen(file), file, strlen(function), function, line, oc_str8_ip(string)); oc_arena_scope_end(tmp); } @@ -86,8 +86,8 @@ void platform_log_push(oc_log_output* output, // Assert/Abort //---------------------------------------------------------------- -_Noreturn void ORCA_IMPORT(oc_runtime_abort_ext)(const char* file, const char* function, int line, const char* msg); -_Noreturn void ORCA_IMPORT(oc_runtime_assert_fail)(const char* file, const char* function, int line, const char* src, const char* msg); +_Noreturn void ORCA_IMPORT(oc_bridge_abort_ext)(const char* file, const char* function, int line, const char* msg); +_Noreturn void ORCA_IMPORT(oc_bridge_assert_fail)(const char* file, const char* function, int line, const char* src, const char* msg); _Noreturn void oc_abort_ext(const char* file, const char* function, int line, const char* fmt, ...) { @@ -108,7 +108,7 @@ _Noreturn void oc_abort_ext(const char* file, const char* function, int line, co oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list); - oc_runtime_abort_ext(file, function, line, msg.ptr); + oc_bridge_abort_ext(file, function, line, msg.ptr); oc_scratch_end(scratch); } @@ -132,7 +132,7 @@ _Noreturn void oc_assert_fail(const char* file, const char* function, int line, oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list); - oc_runtime_assert_fail(file, function, line, src, msg.ptr); + oc_bridge_assert_fail(file, function, line, src, msg.ptr); oc_scratch_end(scratch); } diff --git a/src/platform/platform_io.h b/src/platform/platform_io.h index b5403a5..8c85cdb 100644 --- a/src/platform/platform_io.h +++ b/src/platform/platform_io.h @@ -222,4 +222,10 @@ ORCA_API u64 oc_file_size(oc_file file); //TODO: Complete as needed... +//---------------------------------------------------------------- +// Acquiring new file capabilities through user interaction +//---------------------------------------------------------------- + +ORCA_API oc_file oc_file_open_with_request(oc_str8 path, oc_file_access rights, oc_file_open_flags flags); + #endif //__PLATFORM_IO_H_ diff --git a/src/platform/platform_io_common.c b/src/platform/platform_io_common.c index 4d1141b..eb7314d 100644 --- a/src/platform/platform_io_common.c +++ b/src/platform/platform_io_common.c @@ -7,6 +7,7 @@ *****************************************************************/ #include "platform_io.h" +#include "platform_io_dialog.h" //------------------------------------------------------------------------------ // File stream read/write API diff --git a/src/platform/platform_io_dialog.h b/src/platform/platform_io_dialog.h new file mode 100644 index 0000000..1fb1ecc --- /dev/null +++ b/src/platform/platform_io_dialog.h @@ -0,0 +1,29 @@ +/************************************************************/ /** +* +* @file: platform_io_dialog.h +* @author: Martin Fouilleul +* @date: 01/09/2023 +* +*****************************************************************/ +#ifndef __PLATFORM_IO_DIALOG_H_ +#define __PLATFORM_IO_DIALOG_H_ + +#include "platform_io.h" +#include "app/app.h" + +typedef struct oc_file_open_with_dialog_elt +{ + oc_list_elt listElt; + oc_file file; +} oc_file_open_with_dialog_elt; + +typedef struct oc_file_open_with_dialog_result +{ + oc_file_dialog_button button; + oc_file file; + oc_list selection; +} oc_file_open_with_dialog_result; + +ORCA_API oc_file_open_with_dialog_result oc_file_open_with_dialog(oc_arena* arena, oc_file_access rights, oc_file_open_flags flags, oc_file_dialog_desc* desc); + +#endif //__PLATFORM_IO_DIALOG_H_ diff --git a/src/platform/platform_io_internal.c b/src/platform/platform_io_internal.c index 9f922c0..4a99d6b 100644 --- a/src/platform/platform_io_internal.c +++ b/src/platform/platform_io_internal.c @@ -5,12 +5,17 @@ * @date: 11/06/2023 * *****************************************************************/ - -#include "platform_io_internal.h" -#include "platform_path.h" +#include "app/app.h" +#include "platform/platform_io_internal.h" +#include "platform/platform_path.h" oc_file_table oc_globalFileTable = { 0 }; +oc_file_table* oc_file_table_get_global() +{ + return (&oc_globalFileTable); +} + oc_file_slot* oc_file_slot_alloc(oc_file_table* table) { oc_file_slot* slot = oc_list_pop_entry(&table->freeList, oc_file_slot, freeListElt); @@ -62,7 +67,7 @@ oc_file_slot* oc_file_slot_from_handle(oc_file_table* table, oc_file handle) oc_io_cmp oc_io_wait_single_req(oc_io_req* req) { - return (oc_io_wait_single_req_with_table(req, &oc_globalFileTable)); + return (oc_io_wait_single_req_for_table(req, &oc_globalFileTable)); } //----------------------------------------------------------------------- @@ -341,3 +346,100 @@ oc_io_cmp oc_io_open_at(oc_file_slot* atSlot, oc_io_req* req, oc_file_table* tab } return (cmp); } + +oc_file oc_file_open_with_request_for_table(oc_str8 path, oc_file_access rights, oc_file_open_flags flags, oc_file_table* table) +{ + oc_arena_scope scratch = oc_scratch_begin(); + oc_str8 msg = oc_str8_pushf(scratch.arena, "Application wants to access file '%.*s'.", (int)path.len, path.ptr); + + oc_str8_list options = { 0 }; + oc_str8_list_push(scratch.arena, &options, OC_STR8("Deny")); + oc_str8_list_push(scratch.arena, &options, OC_STR8("Accept")); + + int res = oc_alert_popup(OC_STR8("File Access"), msg, options); + + oc_file file = oc_file_nil(); + if(res == 1) + { + oc_io_cmp cmp = { 0 }; + + oc_io_req req = { + .op = OC_IO_OPEN_AT, + .size = path.len, + .buffer = path.ptr, + .open.rights = rights, + .open.flags = flags + }; + cmp = oc_io_open_at(0, &req, table); + if(cmp.error == OC_IO_OK) + { + file = cmp.handle; + } + } + + oc_scratch_end(scratch); + + return (file); +} + +oc_file oc_file_open_with_request(oc_str8 path, oc_file_access rights, oc_file_open_flags flags) +{ + return (oc_file_open_with_request_for_table(path, rights, flags, &oc_globalFileTable)); +} + +oc_file_open_with_dialog_result oc_file_open_with_dialog_for_table(oc_arena* arena, + oc_file_access rights, + oc_file_open_flags flags, + oc_file_dialog_desc* desc, + oc_file_table* table) +{ + oc_arena_scope scratch = oc_scratch_begin_next(arena); + + oc_file_dialog_result dialogResult = oc_file_dialog_for_table(scratch.arena, desc, table); + + oc_file_open_with_dialog_result result = { + .button = dialogResult.button + }; + + if(dialogResult.button == OC_FILE_DIALOG_OK) + { + int i = 0; + oc_list_for(&dialogResult.selection.list, elt, oc_str8_elt, listElt) + { + oc_file file = oc_file_nil(); + if(elt->string.len) + { + oc_io_req req = { + .op = OC_IO_OPEN_AT, + .size = elt->string.len, + .buffer = elt->string.ptr, + .open.rights = rights, + .open.flags = flags + }; + + oc_io_cmp cmp = oc_io_wait_single_req_for_table(&req, table); + file = cmp.handle; + } + + oc_file_open_with_dialog_elt* resElt = oc_arena_push_type(arena, oc_file_open_with_dialog_elt); + memset(resElt, 0, sizeof(*resElt)); + resElt->file = file; + oc_list_push_back(&result.selection, &resElt->listElt); + + if(i == 0) + { + result.file = file; + i++; + } + } + } + + oc_scratch_end(scratch); + + return (result); +} + +oc_file_open_with_dialog_result oc_file_open_with_dialog(oc_arena* arena, oc_file_access rights, oc_file_open_flags flags, oc_file_dialog_desc* desc) +{ + return (oc_file_open_with_dialog_for_table(arena, rights, flags, desc, &oc_globalFileTable)); +} diff --git a/src/platform/platform_io_internal.h b/src/platform/platform_io_internal.h index de20b52..085204e 100644 --- a/src/platform/platform_io_internal.h +++ b/src/platform/platform_io_internal.h @@ -10,6 +10,7 @@ #include "platform.h" #include "platform_io.h" +#include "platform_io_dialog.h" #if OC_PLATFORM_MACOS || PLATFORM_LINUX typedef int oc_file_desc; @@ -46,12 +47,22 @@ typedef struct oc_file_table oc_list freeList; } oc_file_table; +ORCA_API oc_file_table* oc_file_table_get_global(); + oc_file_slot* oc_file_slot_alloc(oc_file_table* table); void oc_file_slot_recycle(oc_file_table* table, oc_file_slot* slot); oc_file oc_file_from_slot(oc_file_table* table, oc_file_slot* slot); oc_file_slot* oc_file_slot_from_handle(oc_file_table* table, oc_file handle); -ORCA_API oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table); +ORCA_API oc_io_cmp oc_io_wait_single_req_for_table(oc_io_req* req, oc_file_table* table); + +ORCA_API oc_file oc_file_open_with_request_for_table(oc_str8 path, oc_file_access rights, oc_file_open_flags flags, oc_file_table* table); + +ORCA_API oc_file_open_with_dialog_result oc_file_open_with_dialog_for_table(oc_arena* arena, + oc_file_access rights, + oc_file_open_flags flags, + oc_file_dialog_desc* desc, + oc_file_table* table); //----------------------------------------------------------------------- // raw io primitives diff --git a/src/platform/platform_path.c b/src/platform/platform_path.c index ca5643e..9ce8eb8 100644 --- a/src/platform/platform_path.c +++ b/src/platform/platform_path.c @@ -54,7 +54,7 @@ oc_str8_list oc_path_split(oc_arena* arena, oc_str8 path) oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements) { //TODO: check if elements have ending/begining '/' ? - oc_str8 res = oc_str8_list_collate(arena, elements, OC_STR8("/"), OC_STR8("/"), (oc_str8){ 0 }); + oc_str8 res = oc_str8_list_collate(arena, elements, OC_STR8(""), OC_STR8("/"), (oc_str8){ 0 }); return (res); } @@ -90,6 +90,8 @@ oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath) return (result); } +#if !defined(OC_PLATFORM_ORCA) || !OC_PLATFORM_ORCA + oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath) { oc_str8_list list = { 0 }; @@ -103,3 +105,5 @@ oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath) oc_scratch_end(scratch); return (path); } + +#endif diff --git a/src/platform/platform_path.h b/src/platform/platform_path.h index 892a775..a74b1e1 100644 --- a/src/platform/platform_path.h +++ b/src/platform/platform_path.h @@ -8,6 +8,7 @@ #ifndef __PLATFORM_PATH_H_ #define __PLATFORM_PATH_H_ +#include"platform.h" #include "util/strings.h" /*NOTE: @@ -24,10 +25,14 @@ ORCA_API oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements); ORCA_API oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath); ORCA_API bool oc_path_is_absolute(oc_str8 path); + +#if !defined(OC_PLATFORM_ORCA) || !OC_PLATFORM_ORCA + ORCA_API oc_str8 oc_path_executable(oc_arena* arena); ORCA_API oc_str8 oc_path_canonical(oc_arena* arena, oc_str8 path); // helper: gets the path from oc_path_executable() and appends relPath ORCA_API oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath); +#endif #endif //__PLATFORM_PATH_H_ diff --git a/src/platform/posix_io.c b/src/platform/posix_io.c index 0360bc1..e765464 100644 --- a/src/platform/posix_io.c +++ b/src/platform/posix_io.c @@ -518,7 +518,7 @@ oc_io_cmp oc_io_get_error(oc_file_slot* slot, oc_io_req* req) return (cmp); } -oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table) +oc_io_cmp oc_io_wait_single_req_for_table(oc_io_req* req, oc_file_table* table) { oc_io_cmp cmp = { 0 }; diff --git a/src/platform/win32_io.c b/src/platform/win32_io.c index 0c49050..3e705d2 100644 --- a/src/platform/win32_io.c +++ b/src/platform/win32_io.c @@ -73,7 +73,7 @@ oc_io_error oc_io_raw_last_error() return (error); } -static oc_str16 win32_path_from_handle_null_terminated(oc_arena* arena, HANDLE handle) +oc_str16 win32_path_from_handle_null_terminated(oc_arena* arena, HANDLE handle) { oc_str16 res = { 0 }; @@ -108,7 +108,7 @@ static oc_str16 win32_get_path_at_null_terminated(oc_arena* arena, oc_file_desc oc_arena_scope scratch = oc_scratch_begin_next(arena); oc_str16 dirPathW = win32_path_from_handle_null_terminated(scratch.arena, dirFd); - oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path); + oc_str16 pathW = oc_win32_utf8_to_wide(scratch.arena, path); if(dirPathW.len && pathW.len) { @@ -194,7 +194,7 @@ oc_file_desc oc_io_raw_open_at(oc_file_desc dirFd, oc_str8 path, oc_file_access } oc_arena_scope scratch = oc_scratch_begin(); - oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path); + oc_str16 pathW = oc_win32_utf8_to_wide(scratch.arena, path); if(dirFd == NULL || dirFd == INVALID_HANDLE_VALUE) { @@ -505,7 +505,7 @@ static oc_io_cmp oc_io_get_error(oc_file_slot* slot, oc_io_req* req) return (cmp); } -oc_io_cmp oc_io_wait_single_req_with_table(oc_io_req* req, oc_file_table* table) +oc_io_cmp oc_io_wait_single_req_for_table(oc_io_req* req, oc_file_table* table) { oc_io_cmp cmp = { 0 }; diff --git a/src/platform/win32_path.c b/src/platform/win32_path.c index de04e19..a9b8edd 100644 --- a/src/platform/win32_path.c +++ b/src/platform/win32_path.c @@ -13,7 +13,7 @@ bool oc_path_is_absolute(oc_str8 path) { oc_arena_scope scratch = oc_scratch_begin(); - oc_str16 pathW = oc_win32_utf8_to_wide_null_terminated(scratch.arena, path); + oc_str16 pathW = oc_win32_utf8_to_wide(scratch.arena, path); bool result = !PathIsRelativeW(pathW.ptr); oc_scratch_end(scratch); diff --git a/src/platform/win32_string_helpers.c b/src/platform/win32_string_helpers.c index 35a5a8a..cbd509d 100644 --- a/src/platform/win32_string_helpers.c +++ b/src/platform/win32_string_helpers.c @@ -11,7 +11,7 @@ #include "win32_string_helpers.h" -oc_str16 oc_win32_utf8_to_wide_null_terminated(oc_arena* arena, oc_str8 s) +oc_str16 oc_win32_utf8_to_wide(oc_arena* arena, oc_str8 s) { oc_str16 res = { 0 }; res.len = 1 + MultiByteToWideChar(CP_UTF8, 0, s.ptr, s.len, NULL, 0); diff --git a/src/platform/win32_string_helpers.h b/src/platform/win32_string_helpers.h index 7e00490..4aae181 100644 --- a/src/platform/win32_string_helpers.h +++ b/src/platform/win32_string_helpers.h @@ -10,7 +10,7 @@ #include "util/strings.h" -oc_str16 oc_win32_utf8_to_wide_null_terminated(oc_arena* arena, oc_str8 s); +oc_str16 oc_win32_utf8_to_wide(oc_arena* arena, oc_str8 s); oc_str8 oc_win32_wide_to_utf8(oc_arena* arena, oc_str16 s); #endif // __WIN32_STRING_HELPERS_H_ diff --git a/src/runtime.c b/src/runtime.c index 9935976..ac38895 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -19,7 +19,7 @@ oc_font orca_font_create(const char* resourcePath) { - //NOTE(martin): create default font + //NOTE(martin): create default fonts oc_str8 fontPath = oc_path_executable_relative(oc_scratch(), OC_STR8(resourcePath)); FILE* fontFile = fopen(fontPath.ptr, "r"); @@ -49,11 +49,6 @@ oc_font orca_font_create(const char* resourcePath) return (font); } -oc_font oc_font_create_default() -{ - return (orca_font_create("../resources/OpenSansLatinSubset.ttf")); -} - oc_runtime __orcaApp = { 0 }; oc_runtime* oc_runtime_get() @@ -61,43 +56,49 @@ oc_runtime* oc_runtime_get() return (&__orcaApp); } -oc_runtime_env* oc_runtime_env_get() +oc_wasm_env* oc_runtime_get_env() { - return (&__orcaApp.runtime); + return (&__orcaApp.env); } -void* oc_runtime_ptr_to_native(oc_runtime* orca, void* wasmPtr, u32 length) +oc_str8 oc_runtime_get_wasm_memory() { - // We can't use the runtime's memory pointer directly because wasm3 embeds a - // header at the beginning of the block we give it. - u64 bufferIndex = (u64)wasmPtr & 0xffffffff; - u32 memSize = 0; - char* memory = (char*)m3_GetMemory(orca->runtime.m3Runtime, &memSize, 0); + oc_str8 mem = { 0 }; + u32 size = 0; + mem.ptr = (char*)m3_GetMemory(__orcaApp.env.m3Runtime, &size, 0); + mem.len = size; + return (mem); +} - if(bufferIndex + length < memSize) +void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg) +{ + M3ErrorInfo errInfo = { 0 }; + m3_GetErrorInfo(runtime, &errInfo); + if(errInfo.message && res == errInfo.result) { - char* nativePtr = memory + bufferIndex; - return nativePtr; + oc_abort_ext(file, function, line, "%s: %s (%s)", msg, res, errInfo.message); } - - return NULL; -} - -void oc_runtime_window_set_title(oc_str8 title) -{ - title.ptr = oc_runtime_ptr_to_native(oc_runtime_get(), title.ptr, title.len); - if(title.ptr) + else { - oc_window_set_title(__orcaApp.window, title); + oc_abort_ext(file, function, line, "%s: %s", msg, res); } } -void oc_runtime_window_set_size(oc_vec2 size) +void oc_bridge_window_set_title(oc_wasm_str8 title) +{ + oc_str8 nativeTitle = oc_wasm_str8_to_native(title); + if(nativeTitle.ptr) + { + oc_window_set_title(__orcaApp.window, nativeTitle); + } +} + +void oc_bridge_window_set_size(oc_vec2 size) { oc_window_set_content_size(__orcaApp.window, size); } -void oc_runtime_log(oc_log_level level, +void oc_bridge_log(oc_log_level level, int fileLen, char* file, int functionLen, @@ -231,8 +232,8 @@ void orca_surface_render_commands(oc_surface surface, { oc_runtime* app = &__orcaApp; - char* memBase = app->runtime.wasmMemory.ptr; - u32 memSize = app->runtime.wasmMemory.committed; + char* memBase = app->env.wasmMemory.ptr; + u32 memSize = app->env.wasmMemory.committed; if(((char*)primitives > memBase) && ((char*)primitives + primitiveCount * sizeof(oc_primitive) - memBase <= memSize) && ((char*)elements > memBase) @@ -334,9 +335,9 @@ char m3_type_to_tag(M3ValueType type) } } -void oc_runtime_env_init(oc_runtime_env* runtime) +void oc_wasm_env_init(oc_wasm_env* runtime) { - memset(runtime, 0, sizeof(oc_runtime_env)); + memset(runtime, 0, sizeof(oc_wasm_env)); oc_base_allocator* allocator = oc_base_allocator_default(); runtime->wasmMemory.committed = 0; runtime->wasmMemory.reserved = 4ULL << 30; @@ -350,27 +351,11 @@ void oc_runtime_env_init(oc_runtime_env* runtime) #include "wasmbind/io_api_bind_gen.c" #include "wasmbind/surface_api_bind_gen.c" -void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg) -{ - M3ErrorInfo errInfo = { 0 }; - m3_GetErrorInfo(runtime, &errInfo); - if(errInfo.message && res == errInfo.result) - { - oc_abort_ext(file, function, line, "%s: %s (%s)", msg, res, errInfo.message); - } - else - { - oc_abort_ext(file, function, line, "%s: %s", msg, res); - } -} - -#define ORCA_WASM3_ABORT(runtime, err, msg) orca_wasm3_abort(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg) - i32 orca_runloop(void* user) { oc_runtime* app = &__orcaApp; - oc_runtime_env_init(&app->runtime); + oc_wasm_env_init(&app->env); //NOTE: loads wasm module const char* bundleNameCString = "module"; @@ -386,42 +371,42 @@ i32 orca_runloop(void* user) u64 wasmSize = ftell(file); rewind(file); - app->runtime.wasmBytecode.len = wasmSize; - app->runtime.wasmBytecode.ptr = oc_malloc_array(char, wasmSize); - fread(app->runtime.wasmBytecode.ptr, 1, app->runtime.wasmBytecode.len, file); + app->env.wasmBytecode.len = wasmSize; + app->env.wasmBytecode.ptr = oc_malloc_array(char, wasmSize); + fread(app->env.wasmBytecode.ptr, 1, app->env.wasmBytecode.len, file); fclose(file); u32 stackSize = 65536; - app->runtime.m3Env = m3_NewEnvironment(); + app->env.m3Env = m3_NewEnvironment(); - app->runtime.m3Runtime = m3_NewRuntime(app->runtime.m3Env, stackSize, NULL); + app->env.m3Runtime = m3_NewRuntime(app->env.m3Env, stackSize, NULL); //NOTE: host memory will be freed when runtime is freed. - m3_RuntimeSetMemoryCallbacks(app->runtime.m3Runtime, wasm_memory_resize_callback, wasm_memory_free_callback, &app->runtime.wasmMemory); + m3_RuntimeSetMemoryCallbacks(app->env.m3Runtime, oc_wasm_memory_resize_callback, oc_wasm_memory_free_callback, &app->env.wasmMemory); - M3Result res = m3_ParseModule(app->runtime.m3Env, &app->runtime.m3Module, (u8*)app->runtime.wasmBytecode.ptr, app->runtime.wasmBytecode.len); + M3Result res = m3_ParseModule(app->env.m3Env, &app->env.m3Module, (u8*)app->env.wasmBytecode.ptr, app->env.wasmBytecode.len); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't parse its web assembly module"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't parse its web assembly module"); } - res = m3_LoadModule(app->runtime.m3Runtime, app->runtime.m3Module); + res = m3_LoadModule(app->env.m3Runtime, app->env.m3Module); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't load its web assembly module into the runtime"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't load its web assembly module into the runtime"); } - m3_SetModuleName(app->runtime.m3Module, bundleNameCString); + m3_SetModuleName(app->env.m3Module, bundleNameCString); oc_arena_clear(oc_scratch()); //NOTE: bind orca APIs { int err = 0; - err |= bindgen_link_core_api(app->runtime.m3Module); - err |= bindgen_link_surface_api(app->runtime.m3Module); - err |= bindgen_link_clock_api(app->runtime.m3Module); - err |= bindgen_link_io_api(app->runtime.m3Module); - err |= bindgen_link_gles_api(app->runtime.m3Module); - err |= manual_link_gles_api(app->runtime.m3Module); + err |= bindgen_link_core_api(app->env.m3Module); + err |= bindgen_link_surface_api(app->env.m3Module); + err |= bindgen_link_clock_api(app->env.m3Module); + err |= bindgen_link_io_api(app->env.m3Module); + err |= bindgen_link_gles_api(app->env.m3Module); + err |= manual_link_gles_api(app->env.m3Module); if(err) { @@ -429,10 +414,10 @@ i32 orca_runloop(void* user) } } //NOTE: compile - res = m3_CompileModule(app->runtime.m3Module); + res = m3_CompileModule(app->env.m3Module); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "The application couldn't compile its web assembly module"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "The application couldn't compile its web assembly module"); } //NOTE: Find and type check event handlers. @@ -440,7 +425,7 @@ i32 orca_runloop(void* user) { const oc_export_desc* desc = &OC_EXPORT_DESC[i]; IM3Function handler = 0; - m3_FindFunction(&handler, app->runtime.m3Runtime, desc->name.ptr); + m3_FindFunction(&handler, app->env.m3Runtime, desc->name.ptr); if(handler) { @@ -481,7 +466,7 @@ i32 orca_runloop(void* user) if(checked) { - app->runtime.exports[i] = handler; + app->env.exports[i] = handler; } else { @@ -491,8 +476,8 @@ i32 orca_runloop(void* user) } //NOTE: get location of the raw event slot - IM3Global rawEventGlobal = m3_FindGlobal(app->runtime.m3Module, "oc_rawEvent"); - app->runtime.rawEventOffset = (u32)rawEventGlobal->intValue; + IM3Global rawEventGlobal = m3_FindGlobal(app->env.m3Module, "oc_rawEvent"); + app->env.rawEventOffset = (u32)rawEventGlobal->intValue; //NOTE: preopen the app local root dir { @@ -502,11 +487,11 @@ i32 orca_runloop(void* user) .open.rights = OC_FILE_ACCESS_READ | OC_FILE_ACCESS_WRITE, .size = localRootPath.len, .buffer = localRootPath.ptr }; - oc_io_cmp cmp = oc_io_wait_single_req_with_table(&req, &app->fileTable); + oc_io_cmp cmp = oc_io_wait_single_req_for_table(&req, &app->fileTable); app->rootDir = cmp.handle; } - IM3Function* exports = app->runtime.exports; + IM3Function* exports = app->env.exports; //NOTE: call init handler if(exports[OC_EXPORT_ON_INIT]) @@ -514,7 +499,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_ON_INIT], 0, 0); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } @@ -527,7 +512,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } @@ -547,14 +532,14 @@ i32 orca_runloop(void* user) if(exports[OC_EXPORT_RAW_EVENT]) { #ifndef M3_BIG_ENDIAN - oc_event* eventPtr = (oc_event*)wasm_memory_offset_to_ptr(&app->runtime.wasmMemory, app->runtime.rawEventOffset); + oc_event* eventPtr = (oc_event*)oc_wasm_address_to_ptr(app->env.rawEventOffset, sizeof(oc_event)); memcpy(eventPtr, event, sizeof(*event)); - const void* args[1] = { &app->runtime.rawEventOffset }; + const void* args[1] = { &app->env.rawEventOffset }; M3Result res = m3_Call(exports[OC_EXPORT_RAW_EVENT], 1, args); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } #else oc_log_error("oc_on_raw_event() is not supported on big endian platforms"); @@ -565,7 +550,7 @@ i32 orca_runloop(void* user) { case OC_EVENT_WINDOW_CLOSE: { - oc_request_quit(); + oc_request_quit(); } break; @@ -581,7 +566,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } } @@ -598,7 +583,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_DOWN], 1, args); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } } @@ -611,7 +596,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_UP], 1, args); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } } @@ -626,7 +611,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_MOVE], 4, args); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } } @@ -649,7 +634,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 1, args); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } } @@ -661,7 +646,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 1, args); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } } @@ -680,7 +665,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_FRAME_REFRESH], 0, 0); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } @@ -837,7 +822,7 @@ i32 orca_runloop(void* user) M3Result res = m3_Call(exports[OC_EXPORT_TERMINATE], 0, 0); if(res) { - ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error"); + ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error"); } } diff --git a/src/runtime.h b/src/runtime.h index 271df68..133670e 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -27,7 +27,8 @@ X(OC_EXPORT_FRAME_REFRESH, "oc_on_frame_refresh", "", "") \ X(OC_EXPORT_FRAME_RESIZE, "oc_on_resize", "", "ii") \ X(OC_EXPORT_RAW_EVENT, "oc_on_raw_event", "", "i") \ - X(OC_EXPORT_TERMINATE, "oc_on_terminate", "", "") + X(OC_EXPORT_TERMINATE, "oc_on_terminate", "", "") \ + X(OC_EXPORT_ARENA_PUSH, "oc_arena_push_stub", "i", "iI") typedef enum { @@ -53,18 +54,18 @@ const oc_export_desc OC_EXPORT_DESC[] = { #undef OC_STR8_LIT }; -typedef struct wasm_memory +typedef struct oc_wasm_memory { char* ptr; u64 reserved; u64 committed; -} wasm_memory; +} oc_wasm_memory; -typedef struct oc_runtime_env +typedef struct oc_wasm_env { oc_str8 wasmBytecode; - wasm_memory wasmMemory; + oc_wasm_memory wasmMemory; // wasm3 data IM3Environment m3Env; @@ -73,7 +74,7 @@ typedef struct oc_runtime_env IM3Function exports[OC_EXPORT_COUNT]; u32 rawEventOffset; -} oc_runtime_env; +} oc_wasm_env; typedef struct log_entry { @@ -111,21 +112,22 @@ typedef struct oc_debug_overlay typedef struct oc_runtime { - bool quit; + bool quit; oc_window window; + oc_debug_overlay debugOverlay; oc_file_table fileTable; oc_file rootDir; - oc_runtime_env runtime; - - oc_debug_overlay debugOverlay; + oc_wasm_env env; } oc_runtime; -oc_runtime* oc_runtime_get(); -oc_runtime_env* oc_runtime_env_get(); +oc_runtime* oc_runtime_get(void); +oc_wasm_env* oc_runtime_get_env(void); +oc_str8 oc_runtime_get_wasm_memory(void); -void* oc_runtime_ptr_to_native(oc_runtime* runtime, void* wasmPtr, u32 length); +void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg); +#define ORCA_WASM3_ABORT(runtime, err, msg) orca_wasm3_abort(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg) #endif //__RUNTIME_H_ diff --git a/src/runtime_io.c b/src/runtime_io.c index aa80007..2fcb245 100644 --- a/src/runtime_io.c +++ b/src/runtime_io.c @@ -7,15 +7,17 @@ *****************************************************************/ #include "platform/platform_io_internal.h" #include "runtime.h" +#include "runtime_memory.h" -oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq) +oc_io_cmp oc_bridge_io_single_rect(oc_io_req* wasmReq) { oc_runtime* orca = oc_runtime_get(); oc_io_cmp cmp = { 0 }; oc_io_req req = *wasmReq; - void* buffer = oc_runtime_ptr_to_native(orca, req.buffer, req.size); + //TODO have a separate oc_wasm_io_req struct + void* buffer = oc_wasm_address_to_ptr((oc_wasm_addr)(uintptr_t)req.buffer, req.size); if(buffer) { @@ -30,7 +32,7 @@ oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq) req.open.flags |= OC_FILE_OPEN_RESTRICT; } } - cmp = oc_io_wait_single_req_with_table(&req, &orca->fileTable); + cmp = oc_io_wait_single_req_for_table(&req, &orca->fileTable); } else { @@ -39,3 +41,105 @@ oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq) return (cmp); } + +oc_file oc_file_open_with_request_bridge(oc_wasm_str8 path, oc_file_access rights, oc_file_open_flags flags) +{ + oc_file file = oc_file_nil(); + oc_runtime* orca = oc_runtime_get(); + + oc_str8 nativePath = oc_wasm_str8_to_native(path); + + if(nativePath.ptr) + { + file = oc_file_open_with_request_for_table(nativePath, rights, flags, &orca->fileTable); + } + return (file); +} + +typedef struct oc_wasm_file_dialog_desc +{ + oc_file_dialog_kind kind; + oc_file_dialog_flags flags; + oc_wasm_str8 title; + oc_wasm_str8 okLabel; + oc_file startAt; + oc_wasm_str8 startPath; + oc_wasm_str8_list filters; + +} oc_wasm_file_dialog_desc; + +typedef struct oc_wasm_file_open_with_dialog_elt +{ + oc_wasm_list_elt listElt; + oc_file file; +} oc_wasm_file_open_with_dialog_elt; + +typedef struct oc_wasm_file_open_with_dialog_result +{ + oc_file_dialog_button button; + oc_file file; + oc_wasm_list selection; + +} oc_wasm_file_open_with_dialog_result; + +oc_wasm_file_open_with_dialog_result oc_file_open_with_dialog_bridge(oc_wasm_addr wasmArena, + oc_file_access rights, + oc_file_open_flags flags, + oc_wasm_file_dialog_desc* desc) +{ + oc_runtime* orca = oc_runtime_get(); + oc_arena_scope scratch = oc_scratch_begin(); + + oc_file_dialog_desc nativeDesc = { + .kind = desc->kind, + .flags = desc->flags + }; + + nativeDesc.title.ptr = oc_wasm_address_to_ptr(desc->title.ptr, desc->title.len); + nativeDesc.title.len = desc->title.len; + + nativeDesc.okLabel.ptr = oc_wasm_address_to_ptr(desc->okLabel.ptr, desc->okLabel.len); + nativeDesc.okLabel.len = desc->okLabel.len; + + if(oc_file_is_nil(desc->startAt) && desc->startPath.len) + { + nativeDesc.startAt = orca->rootDir; + } + else + { + nativeDesc.startAt = desc->startAt; + } + nativeDesc.startPath.ptr = oc_wasm_address_to_ptr(desc->startPath.ptr, desc->startPath.len); + nativeDesc.startPath.len = desc->startPath.len; + + u32 eltIndex = desc->filters.list.first; + while(eltIndex) + { + oc_wasm_str8_elt* elt = oc_wasm_address_to_ptr(eltIndex, sizeof(oc_wasm_str8_elt)); + oc_str8 filter = oc_wasm_str8_to_native(elt->string); + + oc_str8_list_push(scratch.arena, &nativeDesc.filters, filter); + + oc_log_info("filter: %.*s\n", (int)filter.len, filter.ptr); + + eltIndex = elt->listElt.next; + } + + oc_file_open_with_dialog_result nativeResult = oc_file_open_with_dialog_for_table(scratch.arena, rights, flags, &nativeDesc, &orca->fileTable); + + oc_wasm_file_open_with_dialog_result result = { + .button = nativeResult.button, + .file = nativeResult.file + }; + + oc_list_for(&nativeResult.selection, elt, oc_file_open_with_dialog_elt, listElt) + { + oc_wasm_file_open_with_dialog_elt* wasmElt = oc_wasm_arena_push(wasmArena, sizeof(oc_wasm_file_open_with_dialog_elt)); + wasmElt->file = elt->file; + + oc_wasm_list_push_back(&result.selection, &wasmElt->listElt); + } + + oc_scratch_end(scratch); + return (result); +} diff --git a/src/runtime_memory.c b/src/runtime_memory.c index 1c0158c..8e5ee43 100644 --- a/src/runtime_memory.c +++ b/src/runtime_memory.c @@ -7,10 +7,11 @@ *****************************************************************/ #include "runtime.h" +#include "runtime_memory.h" -void* wasm_memory_resize_callback(void* p, unsigned long size, void* userData) +void* oc_wasm_memory_resize_callback(void* p, unsigned long size, void* userData) { - wasm_memory* memory = (wasm_memory*)userData; + oc_wasm_memory* memory = (oc_wasm_memory*)userData; if(memory->committed >= size) { @@ -32,35 +33,119 @@ void* wasm_memory_resize_callback(void* p, unsigned long size, void* userData) } } -void wasm_memory_free_callback(void* p, void* userData) +void oc_wasm_memory_free_callback(void* p, void* userData) { - wasm_memory* memory = (wasm_memory*)userData; + oc_wasm_memory* memory = (oc_wasm_memory*)userData; oc_base_allocator* allocator = oc_base_allocator_default(); oc_base_release(allocator, memory->ptr, memory->reserved); - memset(memory, 0, sizeof(wasm_memory)); + memset(memory, 0, sizeof(oc_wasm_memory)); } extern u32 oc_mem_grow(u64 size) { - oc_runtime_env* runtime = oc_runtime_env_get(); - wasm_memory* memory = &runtime->wasmMemory; + oc_wasm_env* env = oc_runtime_get_env(); + oc_wasm_memory* memory = &env->wasmMemory; size = oc_align_up_pow2(size, d_m3MemPageSize); - u64 totalSize = size + m3_GetMemorySize(runtime->m3Runtime); + u64 totalSize = size + m3_GetMemorySize(env->m3Runtime); u32 addr = memory->committed; //NOTE: call resize memory, which will call our custom resize callback... this is a bit involved because // wasm3 doesn't allow resizing the memory directly - M3Result res = ResizeMemory(runtime->m3Runtime, totalSize / d_m3MemPageSize); + M3Result res = ResizeMemory(env->m3Runtime, totalSize / d_m3MemPageSize); return (addr); } -void* wasm_memory_offset_to_ptr(wasm_memory* memory, u32 offset) +void* oc_wasm_address_to_ptr(oc_wasm_addr addr, oc_wasm_size size) { - M3MemoryHeader* header = (M3MemoryHeader*)(memory->ptr); - OC_DEBUG_ASSERT(offset < header->length, "Wasm offset exceeds memory length"); - return memory->ptr + sizeof(M3MemoryHeader) + offset; + oc_str8 mem = oc_runtime_get_wasm_memory(); + OC_ASSERT(addr + size < mem.len, "Object overflows wasm memory"); + + void* ptr = (addr == 0) ? 0 : mem.ptr + addr; + return (ptr); +} + +oc_wasm_addr oc_wasm_address_from_ptr(void* ptr, oc_wasm_size size) +{ + oc_wasm_addr addr = 0; + if(ptr != 0) + { + oc_str8 mem = oc_runtime_get_wasm_memory(); + OC_ASSERT((char*)ptr > mem.ptr && (((char*)ptr - mem.ptr) + size < mem.len), "Object overflows wasm memory"); + + addr = (char*)ptr - mem.ptr; + } + return (addr); +} + +//------------------------------------------------------------------------------------ +// oc_wasm_list helpers +//------------------------------------------------------------------------------------ + +void oc_wasm_list_push(oc_wasm_list* list, oc_wasm_list_elt* elt) +{ + elt->next = list->first; + elt->prev = 0; + + oc_wasm_addr eltAddr = oc_wasm_address_from_ptr(elt, sizeof(oc_wasm_list_elt)); + + if(list->first) + { + oc_wasm_list_elt* first = oc_wasm_address_to_ptr(list->first, sizeof(oc_wasm_list_elt)); + first->prev = eltAddr; + } + else + { + list->last = eltAddr; + } + list->first = eltAddr; +} + +void oc_wasm_list_push_back(oc_wasm_list* list, oc_wasm_list_elt* elt) +{ + elt->prev = list->last; + elt->next = 0; + + oc_wasm_addr eltAddr = oc_wasm_address_from_ptr(elt, sizeof(oc_wasm_list_elt)); + + if(list->last) + { + oc_wasm_list_elt* last = oc_wasm_address_to_ptr(list->last, sizeof(oc_wasm_list_elt)); + last->next = eltAddr; + } + else + { + list->first = eltAddr; + } + list->last = eltAddr; +} + +//------------------------------------------------------------------------------------ +// Wasm arenas helpers +//------------------------------------------------------------------------------------ + +void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size) +{ + oc_wasm_env* env = oc_runtime_get_env(); + + oc_wasm_addr retValues[1] = { 0 }; + const void* retPointers[1] = { (void*)&retValues[0] }; + const void* args[2] = { &arena, &size }; + + M3Result res = m3_Call(env->exports[OC_EXPORT_ARENA_PUSH], 2, args); + if(res) + { + ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error"); + } + + res = m3_GetResults(env->exports[OC_EXPORT_ARENA_PUSH], 1, retPointers); + if(res) + { + ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error"); + } + void* ptr = oc_wasm_address_to_ptr(retValues[0], size); + return (ptr); } diff --git a/src/runtime_memory.h b/src/runtime_memory.h new file mode 100644 index 0000000..75fbe41 --- /dev/null +++ b/src/runtime_memory.h @@ -0,0 +1,101 @@ +/************************************************************/ /** +* +* @file: runtime_memory.h +* @author: Martin Fouilleul +* @date: 02/09/2023 +* +*****************************************************************/ +#ifndef __RUNTIME_MEMORY_H_ +#define __RUNTIME_MEMORY_H_ + +#include "runtime.h" + +typedef u32 oc_wasm_addr; +typedef u32 oc_wasm_size; + +void* oc_wasm_address_to_ptr(oc_wasm_addr addr, oc_wasm_size size); +oc_wasm_addr oc_wasm_address_from_ptr(void* ptr, oc_wasm_size size); + +//------------------------------------------------------------------------------------ +// oc_wasm_list helpers +//------------------------------------------------------------------------------------ + +typedef struct oc_wasm_list +{ + u32 first; + u32 last; +} oc_wasm_list; + +typedef struct oc_wasm_list_elt +{ + u32 prev; + u32 next; +} oc_wasm_list_elt; + +bool oc_wasm_list_empty(oc_wasm_list* list); + +#define oc_wasm_list_begin(list) oc_wasm_address_to_ptr(list->first, sizeof(oc_wasm_list_elt)) +#define oc_wasm_list_end(list) oc_wasm_address_to_ptr(list->last, sizeof(oc_wasm_list_elt)) + +#define oc_wasm_list_next(elt) oc_wasm_address_to_ptr((elt)->next, sizeof(oc_wasm_list_elt)) +#define oc_wasm_list_prev(elt) oc_wasm_address_to_ptr((elt)->prev, sizeof(oc_wasm_list_elt)) + +#define oc_wasm_list_entry(ptr, type, member) \ + oc_container_of(ptr, type, member) + +#define oc_wasm_list_next_entry(list, elt, type, member) \ + (((elt)->member.next != 0) ? oc_wasm_list_entry(oc_wasm_list_next((elt)->member), type, member) : 0) + +#define oc_wasm_list_prev_entry(list, elt, type, member) \ + (((elt)->member.prev != 0) ? oc_wasm_list_entry(oc_wasm_list_prev((elt)->member), type, member) : 0) + +#define oc_wasm_list_checked_entry(elt, type, member) \ + (((elt) != 0) ? oc_wasm_list_entry(elt, type, member) : 0) + +#define oc_wasm_list_first_entry(list, type, member) \ + (oc_wasm_list_checked_entry(oc_wasm_list_begin(list), type, member)) + +#define oc_wasm_list_last_entry(list, type, member) \ + (oc_wasm_list_checked_entry(oc_wasm_list_last(list), type, member)) + +#define oc_wasm_list_for(list, elt, type, member) \ + for(type* elt = oc_wasm_list_checked_entry(oc_wasm_list_begin(list), type, member); \ + elt != 0; \ + elt = oc_wasm_list_checked_entry(oc_wasm_list_next((elt)->member), type, member)) + +void oc_wasm_list_push(oc_wasm_list* list, oc_wasm_list_elt* elt); +void oc_wasm_list_push_back(oc_wasm_list* list, oc_wasm_list_elt* elt); + +//------------------------------------------------------------------------------------ +// oc_wasm_str8 helpers +//------------------------------------------------------------------------------------ + +typedef struct oc_wasm_str8 +{ + u64 len; + u32 ptr; +} oc_wasm_str8; + +typedef struct oc_wasm_str8_elt +{ + oc_wasm_list_elt listElt; + oc_wasm_str8 string; + +} oc_wasm_str8_elt; + +typedef struct oc_wasm_str8_list +{ + oc_wasm_list list; + u64 eltCount; + u64 len; +} oc_wasm_str8_list; + +#define oc_wasm_str8_to_native(wasmString) ((oc_str8){ .ptr = oc_wasm_address_to_ptr(wasmString.ptr, wasmString.len), .len = wasmString.len }) + +//------------------------------------------------------------------------------------ +// Wasm arenas helpers +//------------------------------------------------------------------------------------ + +void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size); + +#endif //__RUNTIME_MEMORY_H_ diff --git a/src/ui/ui.c b/src/ui/ui.c index 67e33e5..e0a7540 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -1338,7 +1338,7 @@ void oc_ui_draw_box(oc_ui_box* box) bool draw = true; { - oc_rect clip = oc_clip(); + oc_rect clip = oc_clip_top(); oc_rect expRect = { box->rect.x - 0.5 * style->borderSize, box->rect.y - 0.5 * style->borderSize, diff --git a/src/ui/ui.h b/src/ui/ui.h index 112ff99..41746ff 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -15,576 +15,574 @@ #include "util/typedefs.h" #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - typedef struct oc_ui_key +typedef struct oc_ui_key +{ + u64 hash; +} oc_ui_key; + +typedef enum +{ + OC_UI_AXIS_X, + OC_UI_AXIS_Y, + OC_UI_AXIS_COUNT +} oc_ui_axis; + +typedef enum +{ + OC_UI_ALIGN_START, + OC_UI_ALIGN_END, + OC_UI_ALIGN_CENTER, +} oc_ui_align; + +typedef union oc_ui_layout_align +{ + struct { - u64 hash; - } oc_ui_key; - - typedef enum - { - OC_UI_AXIS_X, - OC_UI_AXIS_Y, - OC_UI_AXIS_COUNT - } oc_ui_axis; - - typedef enum - { - OC_UI_ALIGN_START, - OC_UI_ALIGN_END, - OC_UI_ALIGN_CENTER, - } oc_ui_align; - - typedef union oc_ui_layout_align - { - struct - { - oc_ui_align x; - oc_ui_align y; - }; - - oc_ui_align c[OC_UI_AXIS_COUNT]; - } oc_ui_layout_align; - - typedef struct oc_ui_layout - { - oc_ui_axis axis; - f32 spacing; - - union - { - struct - { - f32 x; - f32 y; - }; - - f32 c[OC_UI_AXIS_COUNT]; - } margin; - - oc_ui_layout_align align; - - } oc_ui_layout; - - typedef enum oc_ui_size_kind - { - OC_UI_SIZE_TEXT, - OC_UI_SIZE_PIXELS, - OC_UI_SIZE_CHILDREN, - OC_UI_SIZE_PARENT, - OC_UI_SIZE_PARENT_MINUS_PIXELS, - - } oc_ui_size_kind; - - typedef struct oc_ui_size - { - oc_ui_size_kind kind; - f32 value; - f32 relax; - } oc_ui_size; - - typedef union oc_ui_box_size - { - struct - { - oc_ui_size width; - oc_ui_size height; - }; - - oc_ui_size c[OC_UI_AXIS_COUNT]; - } oc_ui_box_size; - - typedef union oc_ui_box_floating - { - struct - { - bool x; - bool y; - }; - - bool c[OC_UI_AXIS_COUNT]; - } oc_ui_box_floating; - - //NOTE: flags for axis-dependent properties (e.g. OC_UI_STYLE_FLOAT_X/Y) need to be consecutive bits - // in order to play well with axis agnostic functions - typedef u64 oc_ui_style_mask; - - enum - { - OC_UI_STYLE_NONE = 0, - OC_UI_STYLE_SIZE_WIDTH = 1 << 1, - OC_UI_STYLE_SIZE_HEIGHT = 1 << 2, - OC_UI_STYLE_LAYOUT_AXIS = 1 << 3, - OC_UI_STYLE_LAYOUT_ALIGN_X = 1 << 4, - OC_UI_STYLE_LAYOUT_ALIGN_Y = 1 << 5, - OC_UI_STYLE_LAYOUT_SPACING = 1 << 6, - OC_UI_STYLE_LAYOUT_MARGIN_X = 1 << 7, - OC_UI_STYLE_LAYOUT_MARGIN_Y = 1 << 8, - OC_UI_STYLE_FLOAT_X = 1 << 9, - OC_UI_STYLE_FLOAT_Y = 1 << 10, - OC_UI_STYLE_COLOR = 1 << 11, - OC_UI_STYLE_BG_COLOR = 1 << 12, - OC_UI_STYLE_BORDER_COLOR = 1 << 13, - OC_UI_STYLE_BORDER_SIZE = 1 << 14, - OC_UI_STYLE_ROUNDNESS = 1 << 15, - OC_UI_STYLE_FONT = 1 << 16, - OC_UI_STYLE_FONT_SIZE = 1 << 17, - OC_UI_STYLE_ANIMATION_TIME = 1 << 18, - OC_UI_STYLE_ANIMATION_MASK = 1 << 19, - - //masks - OC_UI_STYLE_SIZE = OC_UI_STYLE_SIZE_WIDTH - | OC_UI_STYLE_SIZE_HEIGHT, - - OC_UI_STYLE_LAYOUT_MARGINS = OC_UI_STYLE_LAYOUT_MARGIN_X - | OC_UI_STYLE_LAYOUT_MARGIN_Y, - - OC_UI_STYLE_LAYOUT = OC_UI_STYLE_LAYOUT_AXIS - | OC_UI_STYLE_LAYOUT_ALIGN_X - | OC_UI_STYLE_LAYOUT_ALIGN_Y - | OC_UI_STYLE_LAYOUT_SPACING - | OC_UI_STYLE_LAYOUT_MARGIN_X - | OC_UI_STYLE_LAYOUT_MARGIN_Y, - - OC_UI_STYLE_FLOAT = OC_UI_STYLE_FLOAT_X - | OC_UI_STYLE_FLOAT_Y, - - OC_UI_STYLE_MASK_INHERITED = OC_UI_STYLE_COLOR - | OC_UI_STYLE_FONT - | OC_UI_STYLE_FONT_SIZE - | OC_UI_STYLE_ANIMATION_TIME - | OC_UI_STYLE_ANIMATION_MASK, + oc_ui_align x; + oc_ui_align y; }; - typedef struct oc_ui_style - { - oc_ui_box_size size; - oc_ui_layout layout; - oc_ui_box_floating floating; - oc_vec2 floatTarget; - oc_color color; - oc_color bgColor; - oc_color borderColor; - oc_font font; - f32 fontSize; - f32 borderSize; - f32 roundness; - f32 animationTime; - oc_ui_style_mask animationMask; - } oc_ui_style; + oc_ui_align c[OC_UI_AXIS_COUNT]; +} oc_ui_layout_align; - typedef struct oc_ui_theme - { - oc_color white; - oc_color primary; - oc_color primaryHover; - oc_color primaryActive; - oc_color fill0; - oc_color fill1; - oc_color fill2; - oc_color bg0; - oc_color bg1; - oc_color bg2; - oc_color bg3; - oc_color bg4; - oc_color text0; - oc_color text1; - oc_color text2; - oc_color text3; - } oc_ui_theme; +typedef struct oc_ui_layout +{ + oc_ui_axis axis; + f32 spacing; - typedef struct oc_ui_tag + union { - u64 hash; - } oc_ui_tag; + struct + { + f32 x; + f32 y; + }; - typedef enum + f32 c[OC_UI_AXIS_COUNT]; + } margin; + + oc_ui_layout_align align; + +} oc_ui_layout; + +typedef enum oc_ui_size_kind +{ + OC_UI_SIZE_TEXT, + OC_UI_SIZE_PIXELS, + OC_UI_SIZE_CHILDREN, + OC_UI_SIZE_PARENT, + OC_UI_SIZE_PARENT_MINUS_PIXELS, + +} oc_ui_size_kind; + +typedef struct oc_ui_size +{ + oc_ui_size_kind kind; + f32 value; + f32 relax; +} oc_ui_size; + +typedef union oc_ui_box_size +{ + struct { - OC_UI_SEL_ANY, - OC_UI_SEL_OWNER, - OC_UI_SEL_TEXT, - OC_UI_SEL_TAG, - OC_UI_SEL_STATUS, - OC_UI_SEL_KEY, - //... - } oc_ui_selector_kind; - - typedef u8 oc_ui_status; - - enum - { - OC_UI_NONE = 0, - OC_UI_HOVER = 1 << 1, - OC_UI_ACTIVE = 1 << 2, - OC_UI_DRAGGING = 1 << 3, + oc_ui_size width; + oc_ui_size height; }; - typedef enum + oc_ui_size c[OC_UI_AXIS_COUNT]; +} oc_ui_box_size; + +typedef union oc_ui_box_floating +{ + struct { - OC_UI_SEL_DESCENDANT = 0, - OC_UI_SEL_AND = 1, + bool x; + bool y; + }; + + bool c[OC_UI_AXIS_COUNT]; +} oc_ui_box_floating; + +//NOTE: flags for axis-dependent properties (e.g. OC_UI_STYLE_FLOAT_X/Y) need to be consecutive bits +// in order to play well with axis agnostic functions +typedef u64 oc_ui_style_mask; + +enum +{ + OC_UI_STYLE_NONE = 0, + OC_UI_STYLE_SIZE_WIDTH = 1 << 1, + OC_UI_STYLE_SIZE_HEIGHT = 1 << 2, + OC_UI_STYLE_LAYOUT_AXIS = 1 << 3, + OC_UI_STYLE_LAYOUT_ALIGN_X = 1 << 4, + OC_UI_STYLE_LAYOUT_ALIGN_Y = 1 << 5, + OC_UI_STYLE_LAYOUT_SPACING = 1 << 6, + OC_UI_STYLE_LAYOUT_MARGIN_X = 1 << 7, + OC_UI_STYLE_LAYOUT_MARGIN_Y = 1 << 8, + OC_UI_STYLE_FLOAT_X = 1 << 9, + OC_UI_STYLE_FLOAT_Y = 1 << 10, + OC_UI_STYLE_COLOR = 1 << 11, + OC_UI_STYLE_BG_COLOR = 1 << 12, + OC_UI_STYLE_BORDER_COLOR = 1 << 13, + OC_UI_STYLE_BORDER_SIZE = 1 << 14, + OC_UI_STYLE_ROUNDNESS = 1 << 15, + OC_UI_STYLE_FONT = 1 << 16, + OC_UI_STYLE_FONT_SIZE = 1 << 17, + OC_UI_STYLE_ANIMATION_TIME = 1 << 18, + OC_UI_STYLE_ANIMATION_MASK = 1 << 19, + + //masks + OC_UI_STYLE_SIZE = OC_UI_STYLE_SIZE_WIDTH + | OC_UI_STYLE_SIZE_HEIGHT, + + OC_UI_STYLE_LAYOUT_MARGINS = OC_UI_STYLE_LAYOUT_MARGIN_X + | OC_UI_STYLE_LAYOUT_MARGIN_Y, + + OC_UI_STYLE_LAYOUT = OC_UI_STYLE_LAYOUT_AXIS + | OC_UI_STYLE_LAYOUT_ALIGN_X + | OC_UI_STYLE_LAYOUT_ALIGN_Y + | OC_UI_STYLE_LAYOUT_SPACING + | OC_UI_STYLE_LAYOUT_MARGIN_X + | OC_UI_STYLE_LAYOUT_MARGIN_Y, + + OC_UI_STYLE_FLOAT = OC_UI_STYLE_FLOAT_X + | OC_UI_STYLE_FLOAT_Y, + + OC_UI_STYLE_MASK_INHERITED = OC_UI_STYLE_COLOR + | OC_UI_STYLE_FONT + | OC_UI_STYLE_FONT_SIZE + | OC_UI_STYLE_ANIMATION_TIME + | OC_UI_STYLE_ANIMATION_MASK, +}; + +typedef struct oc_ui_style +{ + oc_ui_box_size size; + oc_ui_layout layout; + oc_ui_box_floating floating; + oc_vec2 floatTarget; + oc_color color; + oc_color bgColor; + oc_color borderColor; + oc_font font; + f32 fontSize; + f32 borderSize; + f32 roundness; + f32 animationTime; + oc_ui_style_mask animationMask; +} oc_ui_style; + +typedef struct oc_ui_theme +{ + oc_color white; + oc_color primary; + oc_color primaryHover; + oc_color primaryActive; + oc_color fill0; + oc_color fill1; + oc_color fill2; + oc_color bg0; + oc_color bg1; + oc_color bg2; + oc_color bg3; + oc_color bg4; + oc_color text0; + oc_color text1; + oc_color text2; + oc_color text3; +} oc_ui_theme; + +typedef struct oc_ui_tag +{ + u64 hash; +} oc_ui_tag; + +typedef enum +{ + OC_UI_SEL_ANY, + OC_UI_SEL_OWNER, + OC_UI_SEL_TEXT, + OC_UI_SEL_TAG, + OC_UI_SEL_STATUS, + OC_UI_SEL_KEY, + //... +} oc_ui_selector_kind; + +typedef u8 oc_ui_status; + +enum +{ + OC_UI_NONE = 0, + OC_UI_HOVER = 1 << 1, + OC_UI_ACTIVE = 1 << 2, + OC_UI_DRAGGING = 1 << 3, +}; + +typedef enum +{ + OC_UI_SEL_DESCENDANT = 0, + OC_UI_SEL_AND = 1, + //... +} oc_ui_selector_op; + +typedef struct oc_ui_selector +{ + oc_list_elt listElt; + oc_ui_selector_kind kind; + oc_ui_selector_op op; + + union + { + oc_str8 text; + oc_ui_key key; + oc_ui_tag tag; + oc_ui_status status; //... - } oc_ui_selector_op; + }; +} oc_ui_selector; - typedef struct oc_ui_selector - { - oc_list_elt listElt; - oc_ui_selector_kind kind; - oc_ui_selector_op op; +typedef struct oc_ui_pattern +{ + oc_list l; +} oc_ui_pattern; - union - { - oc_str8 text; - oc_ui_key key; - oc_ui_tag tag; - oc_ui_status status; - //... - }; - } oc_ui_selector; +typedef struct oc_ui_box oc_ui_box; - typedef struct oc_ui_pattern - { - oc_list l; - } oc_ui_pattern; +typedef struct oc_ui_style_rule +{ + oc_list_elt boxElt; + oc_list_elt buildElt; + oc_list_elt tmpElt; - typedef struct oc_ui_box oc_ui_box; + oc_ui_box* owner; + oc_ui_pattern pattern; + oc_ui_style_mask mask; + oc_ui_style* style; +} oc_ui_style_rule; - typedef struct oc_ui_style_rule - { - oc_list_elt boxElt; - oc_list_elt buildElt; - oc_list_elt tmpElt; +typedef struct oc_ui_sig +{ + oc_ui_box* box; - oc_ui_box* owner; - oc_ui_pattern pattern; - oc_ui_style_mask mask; - oc_ui_style* style; - } oc_ui_style_rule; + oc_vec2 mouse; + oc_vec2 delta; + oc_vec2 wheel; - typedef struct oc_ui_sig + bool pressed; + bool released; + bool clicked; + bool doubleClicked; + bool rightPressed; + + bool dragging; + bool hovering; + +} oc_ui_sig; + +typedef void (*oc_ui_box_draw_proc)(oc_ui_box* box, void* data); + +typedef enum +{ + OC_UI_FLAG_CLICKABLE = (1 << 0), + OC_UI_FLAG_SCROLL_WHEEL_X = (1 << 1), + OC_UI_FLAG_SCROLL_WHEEL_Y = (1 << 2), + OC_UI_FLAG_BLOCK_MOUSE = (1 << 3), + OC_UI_FLAG_HOT_ANIMATION = (1 << 4), + OC_UI_FLAG_ACTIVE_ANIMATION = (1 << 5), + //WARN: these two following flags need to be kept as consecutive bits to + // play well with axis-agnostic functions + OC_UI_FLAG_ALLOW_OVERFLOW_X = (1 << 6), + OC_UI_FLAG_ALLOW_OVERFLOW_Y = (1 << 7), + OC_UI_FLAG_CLIP = (1 << 8), + OC_UI_FLAG_DRAW_BACKGROUND = (1 << 9), + OC_UI_FLAG_DRAW_FOREGROUND = (1 << 10), + OC_UI_FLAG_DRAW_BORDER = (1 << 11), + OC_UI_FLAG_DRAW_TEXT = (1 << 12), + OC_UI_FLAG_DRAW_PROC = (1 << 13), + + OC_UI_FLAG_OVERLAY = (1 << 14), +} oc_ui_flags; + +struct oc_ui_box +{ + // hierarchy + oc_list_elt listElt; + oc_list children; + oc_ui_box* parent; + + oc_list_elt overlayElt; + + // keying and caching + oc_list_elt bucketElt; + oc_ui_key key; + u64 frameCounter; + + // builder-provided info + oc_ui_flags flags; + oc_str8 string; + oc_list tags; + + oc_ui_box_draw_proc drawProc; + void* drawData; + + // styling + oc_list beforeRules; + oc_list afterRules; + + //oc_ui_style_tag tag; + oc_ui_style* targetStyle; + oc_ui_style style; + u32 z; + + oc_vec2 floatPos; + f32 childrenSum[2]; + f32 spacing[2]; + oc_rect rect; + + // signals + oc_ui_sig* sig; + + // stateful behaviour + bool fresh; + bool closed; + bool parentClosed; + bool dragging; + bool hot; + bool active; + oc_vec2 scroll; + oc_vec2 pressedMouse; + + // animation data + f32 hotTransition; + f32 activeTransition; +}; + +//----------------------------------------------------------------------------- +// context +//----------------------------------------------------------------------------- + +enum +{ + OC_UI_MAX_INPUT_CHAR_PER_FRAME = 64 +}; + +typedef struct oc_ui_input_text +{ + u8 count; + oc_utf32 codePoints[OC_UI_MAX_INPUT_CHAR_PER_FRAME]; + +} oc_ui_input_text; + +typedef struct oc_ui_stack_elt oc_ui_stack_elt; + +struct oc_ui_stack_elt +{ + oc_ui_stack_elt* parent; + + union { oc_ui_box* box; - - oc_vec2 mouse; - oc_vec2 delta; - oc_vec2 wheel; - - bool pressed; - bool released; - bool clicked; - bool doubleClicked; - bool rightPressed; - - bool dragging; - bool hovering; - - } oc_ui_sig; - - typedef void (*oc_ui_box_draw_proc)(oc_ui_box* box, void* data); - - typedef enum - { - OC_UI_FLAG_CLICKABLE = (1 << 0), - OC_UI_FLAG_SCROLL_WHEEL_X = (1 << 1), - OC_UI_FLAG_SCROLL_WHEEL_Y = (1 << 2), - OC_UI_FLAG_BLOCK_MOUSE = (1 << 3), - OC_UI_FLAG_HOT_ANIMATION = (1 << 4), - OC_UI_FLAG_ACTIVE_ANIMATION = (1 << 5), - //WARN: these two following flags need to be kept as consecutive bits to - // play well with axis-agnostic functions - OC_UI_FLAG_ALLOW_OVERFLOW_X = (1 << 6), - OC_UI_FLAG_ALLOW_OVERFLOW_Y = (1 << 7), - OC_UI_FLAG_CLIP = (1 << 8), - OC_UI_FLAG_DRAW_BACKGROUND = (1 << 9), - OC_UI_FLAG_DRAW_FOREGROUND = (1 << 10), - OC_UI_FLAG_DRAW_BORDER = (1 << 11), - OC_UI_FLAG_DRAW_TEXT = (1 << 12), - OC_UI_FLAG_DRAW_PROC = (1 << 13), - - OC_UI_FLAG_OVERLAY = (1 << 14), - } oc_ui_flags; - - struct oc_ui_box - { - // hierarchy - oc_list_elt listElt; - oc_list children; - oc_ui_box* parent; - - oc_list_elt overlayElt; - - // keying and caching - oc_list_elt bucketElt; - oc_ui_key key; - u64 frameCounter; - - // builder-provided info - oc_ui_flags flags; - oc_str8 string; - oc_list tags; - - oc_ui_box_draw_proc drawProc; - void* drawData; - - // styling - oc_list beforeRules; - oc_list afterRules; - - //oc_ui_style_tag tag; - oc_ui_style* targetStyle; - oc_ui_style style; - u32 z; - - oc_vec2 floatPos; - f32 childrenSum[2]; - f32 spacing[2]; - oc_rect rect; - - // signals - oc_ui_sig* sig; - - // stateful behaviour - bool fresh; - bool closed; - bool parentClosed; - bool dragging; - bool hot; - bool active; - oc_vec2 scroll; - oc_vec2 pressedMouse; - - // animation data - f32 hotTransition; - f32 activeTransition; + oc_ui_size size; + oc_rect clip; }; +}; - //----------------------------------------------------------------------------- - // context - //----------------------------------------------------------------------------- +typedef struct oc_ui_tag_elt +{ + oc_list_elt listElt; + oc_ui_tag tag; +} oc_ui_tag_elt; - enum - { - OC_UI_MAX_INPUT_CHAR_PER_FRAME = 64 - }; +enum +{ + OC_UI_BOX_MAP_BUCKET_COUNT = 1024 +}; - typedef struct oc_ui_input_text - { - u8 count; - oc_utf32 codePoints[OC_UI_MAX_INPUT_CHAR_PER_FRAME]; +typedef struct oc_ui_context +{ + bool init; - } oc_ui_input_text; + oc_input_state input; - typedef struct oc_ui_stack_elt oc_ui_stack_elt; + u64 frameCounter; + f64 frameTime; + f64 lastFrameDuration; - struct oc_ui_stack_elt - { - oc_ui_stack_elt* parent; + oc_arena frameArena; + oc_pool boxPool; + oc_list boxMap[OC_UI_BOX_MAP_BUCKET_COUNT]; - union - { - oc_ui_box* box; - oc_ui_size size; - oc_rect clip; - }; - }; + oc_ui_box* root; + oc_ui_box* overlay; + oc_list overlayList; + oc_ui_stack_elt* boxStack; + oc_ui_stack_elt* clipStack; - typedef struct oc_ui_tag_elt - { - oc_list_elt listElt; - oc_ui_tag tag; - } oc_ui_tag_elt; + oc_list nextBoxBeforeRules; + oc_list nextBoxAfterRules; + oc_list nextBoxTags; - enum - { - OC_UI_BOX_MAP_BUCKET_COUNT = 1024 - }; + u32 z; + oc_ui_box* hovered; - typedef struct oc_ui_context - { - bool init; + oc_ui_box* focus; + i32 editCursor; + i32 editMark; + i32 editFirstDisplayedChar; + f64 editCursorBlinkStart; - oc_input_state input; +} oc_ui_context; - u64 frameCounter; - f64 frameTime; - f64 lastFrameDuration; +//------------------------------------------------------------------------------------- +// UI context initialization and frame cycle +//------------------------------------------------------------------------------------- +ORCA_API void oc_ui_init(oc_ui_context* context); +ORCA_API oc_ui_context* oc_ui_get_context(void); +ORCA_API void oc_ui_set_context(oc_ui_context* context); - oc_arena frameArena; - oc_pool boxPool; - oc_list boxMap[OC_UI_BOX_MAP_BUCKET_COUNT]; - - oc_ui_box* root; - oc_ui_box* overlay; - oc_list overlayList; - oc_ui_stack_elt* boxStack; - oc_ui_stack_elt* clipStack; - - oc_list nextBoxBeforeRules; - oc_list nextBoxAfterRules; - oc_list nextBoxTags; - - u32 z; - oc_ui_box* hovered; - - oc_ui_box* focus; - i32 editCursor; - i32 editMark; - i32 editFirstDisplayedChar; - f64 editCursorBlinkStart; - - } oc_ui_context; - - //------------------------------------------------------------------------------------- - // UI context initialization and frame cycle - //------------------------------------------------------------------------------------- - ORCA_API void oc_ui_init(oc_ui_context* context); - ORCA_API oc_ui_context* oc_ui_get_context(void); - ORCA_API void oc_ui_set_context(oc_ui_context* context); - - ORCA_API void oc_ui_process_event(oc_event* event); - ORCA_API void oc_ui_begin_frame(oc_vec2 size, oc_ui_style* defaultStyle, oc_ui_style_mask mask); - ORCA_API void oc_ui_end_frame(void); - ORCA_API void oc_ui_draw(void); +ORCA_API void oc_ui_process_event(oc_event* event); +ORCA_API void oc_ui_begin_frame(oc_vec2 size, oc_ui_style* defaultStyle, oc_ui_style_mask mask); +ORCA_API void oc_ui_end_frame(void); +ORCA_API void oc_ui_draw(void); #define oc_ui_frame(size, style, mask) oc_defer_loop(oc_ui_begin_frame((size), (style), (mask)), oc_ui_end_frame()) - //------------------------------------------------------------------------------------- - // Box keys - //------------------------------------------------------------------------------------- - ORCA_API oc_ui_key oc_ui_key_make_str8(oc_str8 string); - ORCA_API oc_ui_key oc_ui_key_make_path(oc_str8_list path); +//------------------------------------------------------------------------------------- +// Box keys +//------------------------------------------------------------------------------------- +ORCA_API oc_ui_key oc_ui_key_make_str8(oc_str8 string); +ORCA_API oc_ui_key oc_ui_key_make_path(oc_str8_list path); - ORCA_API oc_ui_box* oc_ui_box_lookup_key(oc_ui_key key); - ORCA_API oc_ui_box* oc_ui_box_lookup_str8(oc_str8 string); +ORCA_API oc_ui_box* oc_ui_box_lookup_key(oc_ui_key key); +ORCA_API oc_ui_box* oc_ui_box_lookup_str8(oc_str8 string); // C-string helper #define oc_ui_key_make(s) oc_ui_key_make_str8(OC_STR8(s)) #define oc_ui_box_lookup(s) oc_ui_box_lookup_str8(OC_STR8(s)) - //------------------------------------------------------------------------------------- - // Box hierarchy building - //------------------------------------------------------------------------------------- - ORCA_API oc_ui_box* oc_ui_box_make_str8(oc_str8 string, oc_ui_flags flags); - ORCA_API oc_ui_box* oc_ui_box_begin_str8(oc_str8 string, oc_ui_flags flags); +//------------------------------------------------------------------------------------- +// Box hierarchy building +//------------------------------------------------------------------------------------- +ORCA_API oc_ui_box* oc_ui_box_make_str8(oc_str8 string, oc_ui_flags flags); +ORCA_API oc_ui_box* oc_ui_box_begin_str8(oc_str8 string, oc_ui_flags flags); - ORCA_API oc_ui_box* oc_ui_box_end(void); +ORCA_API oc_ui_box* oc_ui_box_end(void); #define oc_ui_container(name, flags) oc_defer_loop(oc_ui_box_begin(name, flags), oc_ui_box_end()) #define oc_ui_container_str8(name, flags) oc_defer_loop(oc_ui_box_begin_str8(name, flags), oc_ui_box_end()) - ORCA_API void oc_ui_box_push(oc_ui_box* box); - ORCA_API void oc_ui_box_pop(void); - ORCA_API oc_ui_box* oc_ui_box_top(void); +ORCA_API void oc_ui_box_push(oc_ui_box* box); +ORCA_API void oc_ui_box_pop(void); +ORCA_API oc_ui_box* oc_ui_box_top(void); - ORCA_API void oc_ui_box_set_draw_proc(oc_ui_box* box, oc_ui_box_draw_proc proc, void* data); +ORCA_API void oc_ui_box_set_draw_proc(oc_ui_box* box, oc_ui_box_draw_proc proc, void* data); // C-string helpers #define oc_ui_box_lookup(s) oc_ui_box_lookup_str8(OC_STR8(s)) #define oc_ui_box_make(s, flags) oc_ui_box_make_str8(OC_STR8(s), flags) #define oc_ui_box_begin(s, flags) oc_ui_box_begin_str8(OC_STR8(s), flags) - //------------------------------------------------------------------------------------- - // Box status and signals - //------------------------------------------------------------------------------------- - ORCA_API bool oc_ui_box_closed(oc_ui_box* box); - ORCA_API void oc_ui_box_set_closed(oc_ui_box* box, bool closed); +//------------------------------------------------------------------------------------- +// Box status and signals +//------------------------------------------------------------------------------------- +ORCA_API bool oc_ui_box_closed(oc_ui_box* box); +ORCA_API void oc_ui_box_set_closed(oc_ui_box* box, bool closed); - ORCA_API bool oc_ui_box_active(oc_ui_box* box); - ORCA_API void oc_ui_box_activate(oc_ui_box* box); - ORCA_API void oc_ui_box_deactivate(oc_ui_box* box); +ORCA_API bool oc_ui_box_active(oc_ui_box* box); +ORCA_API void oc_ui_box_activate(oc_ui_box* box); +ORCA_API void oc_ui_box_deactivate(oc_ui_box* box); - ORCA_API bool oc_ui_box_hot(oc_ui_box* box); - ORCA_API void oc_ui_box_set_hot(oc_ui_box* box, bool hot); +ORCA_API bool oc_ui_box_hot(oc_ui_box* box); +ORCA_API void oc_ui_box_set_hot(oc_ui_box* box, bool hot); - ORCA_API oc_ui_sig oc_ui_box_sig(oc_ui_box* box); +ORCA_API oc_ui_sig oc_ui_box_sig(oc_ui_box* box); - //------------------------------------------------------------------------------------- - // Tagging - //------------------------------------------------------------------------------------- - ORCA_API oc_ui_tag oc_ui_tag_make_str8(oc_str8 string); - ORCA_API void oc_ui_tag_box_str8(oc_ui_box* box, oc_str8 string); - ORCA_API void oc_ui_tag_next_str8(oc_str8 string); +//------------------------------------------------------------------------------------- +// Tagging +//------------------------------------------------------------------------------------- +ORCA_API oc_ui_tag oc_ui_tag_make_str8(oc_str8 string); +ORCA_API void oc_ui_tag_box_str8(oc_ui_box* box, oc_str8 string); +ORCA_API void oc_ui_tag_next_str8(oc_str8 string); // C-string helpers #define oc_ui_tag_make(s) oc_ui_tag_make_str8(OC_STR8(s)) #define oc_ui_tag_box(b, s) oc_ui_tag_box_str8(b, OC_STR8(s)) #define oc_ui_tag_next(s) oc_ui_tag_next_str8(OC_STR8(s)) - //------------------------------------------------------------------------------------- - // Styling - //------------------------------------------------------------------------------------- - //NOTE: styling API - //WARN: You can use a pattern in multiple rules, but be aware that a pattern is references an underlying list of selectors, - // hence pushing to a pattern also modifies rules in which the pattern was previously used! - ORCA_API void oc_ui_apply_style_with_mask(oc_ui_style* dst, oc_ui_style* src, oc_ui_style_mask mask); +//------------------------------------------------------------------------------------- +// Styling +//------------------------------------------------------------------------------------- +//NOTE: styling API +//WARN: You can use a pattern in multiple rules, but be aware that a pattern is references an underlying list of selectors, +// hence pushing to a pattern also modifies rules in which the pattern was previously used! +ORCA_API void oc_ui_apply_style_with_mask(oc_ui_style* dst, oc_ui_style* src, oc_ui_style_mask mask); - ORCA_API void oc_ui_pattern_push(oc_arena* arena, oc_ui_pattern* pattern, oc_ui_selector selector); - ORCA_API oc_ui_pattern oc_ui_pattern_all(void); - ORCA_API oc_ui_pattern oc_ui_pattern_owner(void); +ORCA_API void oc_ui_pattern_push(oc_arena* arena, oc_ui_pattern* pattern, oc_ui_selector selector); +ORCA_API oc_ui_pattern oc_ui_pattern_all(void); +ORCA_API oc_ui_pattern oc_ui_pattern_owner(void); - ORCA_API void oc_ui_style_next(oc_ui_style* style, oc_ui_style_mask mask); - ORCA_API void oc_ui_style_match_before(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask); - ORCA_API void oc_ui_style_match_after(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask); +ORCA_API void oc_ui_style_next(oc_ui_style* style, oc_ui_style_mask mask); +ORCA_API void oc_ui_style_match_before(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask); +ORCA_API void oc_ui_style_match_after(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask); - //------------------------------------------------------------------------- - // Basic widget helpers - //------------------------------------------------------------------------- - enum - { - OC_UI_STYLE_TAG_USER_MAX = 1 << 16, - OC_UI_STYLE_TAG_LABEL, - OC_UI_STYLE_TAG_BUTTON, - OC_UI_STYLE_TAG_SCROLLBAR, - OC_UI_STYLE_TAG_PANEL, - OC_UI_STYLE_TAG_TOOLTIP, - OC_UI_STYLE_TAG_MENU - }; +//------------------------------------------------------------------------- +// Basic widget helpers +//------------------------------------------------------------------------- +enum +{ + OC_UI_STYLE_TAG_USER_MAX = 1 << 16, + OC_UI_STYLE_TAG_LABEL, + OC_UI_STYLE_TAG_BUTTON, + OC_UI_STYLE_TAG_SCROLLBAR, + OC_UI_STYLE_TAG_PANEL, + OC_UI_STYLE_TAG_TOOLTIP, + OC_UI_STYLE_TAG_MENU +}; - ORCA_API oc_ui_sig oc_ui_label(const char* label); - ORCA_API oc_ui_sig oc_ui_label_str8(oc_str8 label); +ORCA_API oc_ui_sig oc_ui_label(const char* label); +ORCA_API oc_ui_sig oc_ui_label_str8(oc_str8 label); - ORCA_API oc_ui_sig oc_ui_button(const char* label); - ORCA_API oc_ui_sig oc_ui_checkbox(const char* name, bool* checked); - ORCA_API oc_ui_box* oc_ui_slider(const char* label, f32* value); - ORCA_API oc_ui_box* oc_ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue); +ORCA_API oc_ui_sig oc_ui_button(const char* label); +ORCA_API oc_ui_sig oc_ui_checkbox(const char* name, bool* checked); +ORCA_API oc_ui_box* oc_ui_slider(const char* label, f32* value); +ORCA_API oc_ui_box* oc_ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue); +ORCA_API void oc_ui_tooltip(const char* label); - ORCA_API void oc_ui_panel_begin(const char* name, oc_ui_flags flags); - ORCA_API void oc_ui_panel_end(void); +ORCA_API void oc_ui_panel_begin(const char* name, oc_ui_flags flags); +ORCA_API void oc_ui_panel_end(void); #define oc_ui_panel(s, f) oc_defer_loop(oc_ui_panel_begin(s, f), oc_ui_panel_end()) - ORCA_API void oc_ui_tooltip(const char* label); - - ORCA_API void oc_ui_menu_bar_begin(const char* label); - ORCA_API void oc_ui_menu_bar_end(void); +ORCA_API void oc_ui_menu_bar_begin(const char* label); +ORCA_API void oc_ui_menu_bar_end(void); #define oc_ui_menu_bar(name) oc_defer_loop(oc_ui_menu_bar_begin(name), oc_ui_menu_bar_end()) - ORCA_API void oc_ui_menu_begin(const char* label); - ORCA_API void oc_ui_menu_end(void); +ORCA_API void oc_ui_menu_begin(const char* label); +ORCA_API void oc_ui_menu_end(void); #define oc_ui_menu(name) oc_defer_loop(oc_ui_menu_begin(name), oc_ui_menu_end()) - ORCA_API oc_ui_sig oc_ui_menu_button(const char* name); +ORCA_API oc_ui_sig oc_ui_menu_button(const char* name); - typedef struct oc_ui_select_popup_info - { - bool changed; - int selectedIndex; - int optionCount; - oc_str8* options; - } oc_ui_select_popup_info; +typedef struct oc_ui_text_box_result +{ + bool changed; + bool accepted; + oc_str8 text; - ORCA_API oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_info* info); +} oc_ui_text_box_result; - typedef struct oc_ui_text_box_result - { - bool changed; - bool accepted; - oc_str8 text; +ORCA_API oc_ui_text_box_result oc_ui_text_box(const char* name, oc_arena* arena, oc_str8 text); - } oc_ui_text_box_result; +typedef struct oc_ui_select_popup_info +{ + bool changed; + int selectedIndex; + int optionCount; + oc_str8* options; +} oc_ui_select_popup_info; - ORCA_API oc_ui_text_box_result oc_ui_text_box(const char* name, oc_arena* arena, oc_str8 text); +ORCA_API oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_info* info); #ifdef __cplusplus } // extern "C" diff --git a/src/util/lists.h b/src/util/lists.h index c09757b..81dc398 100644 --- a/src/util/lists.h +++ b/src/util/lists.h @@ -14,13 +14,12 @@ #include "util/debug.h" #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - //------------------------------------------------------------------------- - // Intrusive linked lists - //------------------------------------------------------------------------- +//------------------------------------------------------------------------- +// Intrusive linked lists +//------------------------------------------------------------------------- #define oc_list_entry(ptr, type, member) \ oc_container_of(ptr, type, member) @@ -62,162 +61,162 @@ extern "C" #define oc_list_pop_entry(list, type, member) (oc_list_empty(list) ? 0 : oc_list_entry(oc_list_pop(list), type, member)) - typedef struct oc_list_elt oc_list_elt; +typedef struct oc_list_elt oc_list_elt; - struct oc_list_elt - { - oc_list_elt* next; - oc_list_elt* prev; - }; +struct oc_list_elt +{ + oc_list_elt* prev; + oc_list_elt* next; +}; - typedef struct oc_list - { - oc_list_elt* first; - oc_list_elt* last; - } oc_list; +typedef struct oc_list +{ + oc_list_elt* first; + oc_list_elt* last; +} oc_list; - static inline void oc_list_init(oc_list* list) +static inline void oc_list_init(oc_list* list) +{ + list->first = list->last = 0; +} + +static inline oc_list_elt* oc_list_begin(oc_list* list) +{ + return (list->first); +} + +static inline oc_list_elt* oc_list_end(oc_list* list) +{ + return (0); +} + +static inline oc_list_elt* oc_list_last(oc_list* list) +{ + return (list->last); +} + +static inline void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt) +{ + elt->prev = afterElt; + elt->next = afterElt->next; + if(afterElt->next) { - list->first = list->last = 0; + afterElt->next->prev = elt; } - - static inline oc_list_elt* oc_list_begin(oc_list* list) + else { - return (list->first); + list->last = elt; } + afterElt->next = elt; - static inline oc_list_elt* oc_list_end(oc_list* list) + OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert(): can't insert an element into itself"); +} + +static inline void oc_list_insert_before(oc_list* list, oc_list_elt* beforeElt, oc_list_elt* elt) +{ + elt->next = beforeElt; + elt->prev = beforeElt->prev; + + if(beforeElt->prev) + { + beforeElt->prev->next = elt; + } + else + { + list->first = elt; + } + beforeElt->prev = elt; + + OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert_before(): can't insert an element into itself"); +} + +static inline void oc_list_remove(oc_list* list, oc_list_elt* elt) +{ + if(elt->prev) + { + elt->prev->next = elt->next; + } + else + { + OC_DEBUG_ASSERT(list->first == elt); + list->first = elt->next; + } + if(elt->next) + { + elt->next->prev = elt->prev; + } + else + { + OC_DEBUG_ASSERT(list->last == elt); + list->last = elt->prev; + } + elt->prev = elt->next = 0; +} + +static inline void oc_list_push(oc_list* list, oc_list_elt* elt) +{ + elt->next = list->first; + elt->prev = 0; + if(list->first) + { + list->first->prev = elt; + } + else + { + list->last = elt; + } + list->first = elt; +} + +static inline oc_list_elt* oc_list_pop(oc_list* list) +{ + oc_list_elt* elt = oc_list_begin(list); + if(elt != oc_list_end(list)) + { + oc_list_remove(list, elt); + return (elt); + } + else { return (0); } +} - static inline oc_list_elt* oc_list_last(oc_list* list) +static inline void oc_list_push_back(oc_list* list, oc_list_elt* elt) +{ + elt->prev = list->last; + elt->next = 0; + if(list->last) { - return (list->last); + list->last->next = elt; } - - static inline void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt) + else { - elt->prev = afterElt; - elt->next = afterElt->next; - if(afterElt->next) - { - afterElt->next->prev = elt; - } - else - { - list->last = elt; - } - afterElt->next = elt; - - OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert(): can't insert an element into itself"); - } - - static inline void oc_list_insert_before(oc_list* list, oc_list_elt* beforeElt, oc_list_elt* elt) - { - elt->next = beforeElt; - elt->prev = beforeElt->prev; - - if(beforeElt->prev) - { - beforeElt->prev->next = elt; - } - else - { - list->first = elt; - } - beforeElt->prev = elt; - - OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert_before(): can't insert an element into itself"); - } - - static inline void oc_list_remove(oc_list* list, oc_list_elt* elt) - { - if(elt->prev) - { - elt->prev->next = elt->next; - } - else - { - OC_DEBUG_ASSERT(list->first == elt); - list->first = elt->next; - } - if(elt->next) - { - elt->next->prev = elt->prev; - } - else - { - OC_DEBUG_ASSERT(list->last == elt); - list->last = elt->prev; - } - elt->prev = elt->next = 0; - } - - static inline void oc_list_push(oc_list* list, oc_list_elt* elt) - { - elt->next = list->first; - elt->prev = 0; - if(list->first) - { - list->first->prev = elt; - } - else - { - list->last = elt; - } list->first = elt; } - - static inline oc_list_elt* oc_list_pop(oc_list* list) - { - oc_list_elt* elt = oc_list_begin(list); - if(elt != oc_list_end(list)) - { - oc_list_remove(list, elt); - return (elt); - } - else - { - return (0); - } - } - - static inline void oc_list_push_back(oc_list* list, oc_list_elt* elt) - { - elt->prev = list->last; - elt->next = 0; - if(list->last) - { - list->last->next = elt; - } - else - { - list->first = elt; - } - list->last = elt; - } + list->last = elt; +} #define oc_list_append(a, b) oc_list_push_back(a, b) - static inline oc_list_elt* oc_list_pop_back(oc_list* list) +static inline oc_list_elt* oc_list_pop_back(oc_list* list) +{ + oc_list_elt* elt = oc_list_last(list); + if(elt != oc_list_end(list)) { - oc_list_elt* elt = oc_list_last(list); - if(elt != oc_list_end(list)) - { - oc_list_remove(list, elt); - return (elt); - } - else - { - return (0); - } + oc_list_remove(list, elt); + return (elt); } + else + { + return (0); + } +} - static inline bool oc_list_empty(oc_list* list) - { - return (list->first == 0 || list->last == 0); - } +static inline bool oc_list_empty(oc_list* list) +{ + return (list->first == 0 || list->last == 0); +} #ifdef __cplusplus } // extern "C" diff --git a/src/util/memory.c b/src/util/memory.c index 445d70b..da9fa3d 100644 --- a/src/util/memory.c +++ b/src/util/memory.c @@ -241,7 +241,7 @@ ORCA_API oc_arena* oc_scratch_next(oc_arena* used) return (res); } -ORCA_API oc_arena_scope oc_scratch_begin() +ORCA_API oc_arena_scope oc_scratch_begin(void) { oc_arena* scratch = oc_scratch(); oc_arena_scope scope = oc_arena_scope_begin(scratch); diff --git a/src/util/memory.h b/src/util/memory.h index a042203..fd2c81a 100644 --- a/src/util/memory.h +++ b/src/util/memory.h @@ -14,94 +14,93 @@ #include "util/typedefs.h" #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - //-------------------------------------------------------------------------------- - //NOTE(martin): memory arena - //-------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------- +//NOTE(martin): memory arena +//-------------------------------------------------------------------------------- - typedef struct oc_arena_chunk - { - oc_list_elt listElt; - char* ptr; - u64 offset; - u64 committed; - u64 cap; - } oc_arena_chunk; +typedef struct oc_arena_chunk +{ + oc_list_elt listElt; + char* ptr; + u64 offset; + u64 committed; + u64 cap; +} oc_arena_chunk; - typedef struct oc_arena - { - oc_base_allocator* base; - oc_list chunks; - oc_arena_chunk* currentChunk; +typedef struct oc_arena +{ + oc_base_allocator* base; + oc_list chunks; + oc_arena_chunk* currentChunk; - } oc_arena; +} oc_arena; - typedef struct oc_arena_scope - { - oc_arena* arena; - oc_arena_chunk* chunk; - u64 offset; - } oc_arena_scope; +typedef struct oc_arena_scope +{ + oc_arena* arena; + oc_arena_chunk* chunk; + u64 offset; +} oc_arena_scope; - typedef struct oc_arena_options - { - oc_base_allocator* base; - u64 reserve; - } oc_arena_options; +typedef struct oc_arena_options +{ + oc_base_allocator* base; + u64 reserve; +} oc_arena_options; - ORCA_API void oc_arena_init(oc_arena* arena); - ORCA_API void oc_arena_init_with_options(oc_arena* arena, oc_arena_options* options); - ORCA_API void oc_arena_cleanup(oc_arena* arena); +ORCA_API void oc_arena_init(oc_arena* arena); +ORCA_API void oc_arena_init_with_options(oc_arena* arena, oc_arena_options* options); +ORCA_API void oc_arena_cleanup(oc_arena* arena); - ORCA_API void* oc_arena_push(oc_arena* arena, u64 size); - ORCA_API void oc_arena_clear(oc_arena* arena); +ORCA_API void* oc_arena_push(oc_arena* arena, u64 size); +ORCA_API void oc_arena_clear(oc_arena* arena); - ORCA_API oc_arena_scope oc_arena_scope_begin(oc_arena* arena); - ORCA_API void oc_arena_scope_end(oc_arena_scope scope); +ORCA_API oc_arena_scope oc_arena_scope_begin(oc_arena* arena); +ORCA_API void oc_arena_scope_end(oc_arena_scope scope); #define oc_arena_push_type(arena, type) ((type*)oc_arena_push(arena, sizeof(type))) #define oc_arena_push_array(arena, type, count) ((type*)oc_arena_push(arena, sizeof(type) * (count))) - //-------------------------------------------------------------------------------- - //NOTE(martin): memory pool - //-------------------------------------------------------------------------------- +//-------------------------------------------------------------------------------- +//NOTE(martin): memory pool +//-------------------------------------------------------------------------------- - //TODO: we could probably remove pool. Most of the time we construct pool on top of - // arenas "manually" with different free lists per object types... +//TODO: we could probably remove pool. Most of the time we construct pool on top of +// arenas "manually" with different free lists per object types... - typedef struct oc_pool - { - oc_arena arena; - oc_list freeList; - u64 blockSize; - } oc_pool; +typedef struct oc_pool +{ + oc_arena arena; + oc_list freeList; + u64 blockSize; +} oc_pool; - typedef struct oc_pool_options - { - oc_base_allocator* base; - u64 reserve; - } oc_pool_options; +typedef struct oc_pool_options +{ + oc_base_allocator* base; + u64 reserve; +} oc_pool_options; - ORCA_API void oc_pool_init(oc_pool* pool, u64 blockSize); - ORCA_API void oc_pool_init_with_options(oc_pool* pool, u64 blockSize, oc_pool_options* options); - ORCA_API void oc_pool_cleanup(oc_pool* pool); +ORCA_API void oc_pool_init(oc_pool* pool, u64 blockSize); +ORCA_API void oc_pool_init_with_options(oc_pool* pool, u64 blockSize, oc_pool_options* options); +ORCA_API void oc_pool_cleanup(oc_pool* pool); - ORCA_API void* oc_pool_alloc(oc_pool* pool); - ORCA_API void oc_pool_recycle(oc_pool* pool, void* ptr); - ORCA_API void oc_pool_clear(oc_pool* pool); +ORCA_API void* oc_pool_alloc(oc_pool* pool); +ORCA_API void oc_pool_recycle(oc_pool* pool, void* ptr); +ORCA_API void oc_pool_clear(oc_pool* pool); #define oc_pool_alloc_type(arena, type) ((type*)oc_pool_alloc(arena)) - //-------------------------------------------------------------------------------- - //NOTE(martin): per-thread implicit scratch arena - //-------------------------------------------------------------------------------- - ORCA_API oc_arena* oc_scratch(); - ORCA_API oc_arena* oc_scratch_next(oc_arena* used); - ORCA_API oc_arena_scope oc_scratch_begin(); - ORCA_API oc_arena_scope oc_scratch_begin_next(oc_arena* used); +//-------------------------------------------------------------------------------- +//NOTE(martin): per-thread implicit scratch arena +//-------------------------------------------------------------------------------- +ORCA_API oc_arena* oc_scratch(); +ORCA_API oc_arena* oc_scratch_next(oc_arena* used); +ORCA_API oc_arena_scope oc_scratch_begin(void); +ORCA_API oc_arena_scope oc_scratch_begin_next(oc_arena* used); #define oc_scratch_end(scope) oc_arena_scope_end(scope) diff --git a/src/util/strings.h b/src/util/strings.h index 4f574be..8ebc37e 100644 --- a/src/util/strings.h +++ b/src/util/strings.h @@ -17,11 +17,10 @@ #include #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - /*NOTE: +/*NOTE: By convention, functions that take an arena and return a string slice allocated on this arena, always allocate one more element and null-terminate the string. This is done so we can pass those strings directly to C APIs that requires C strings without @@ -31,14 +30,14 @@ extern "C" into the original string. Only the _list nodes_ are allocated on the arena. */ - //---------------------------------------------------------------------------------- - // u8 strings - //---------------------------------------------------------------------------------- - typedef struct oc_str8 - { - u64 len; - char* ptr; - } oc_str8; +//---------------------------------------------------------------------------------- +// u8 strings +//---------------------------------------------------------------------------------- +typedef struct oc_str8 +{ + u64 len; + char* ptr; +} oc_str8; #define OC_STR8(s) ((oc_str8){ .len = (s) ? strlen(s) : 0, .ptr = (char*)s }) @@ -51,109 +50,109 @@ extern "C" #define oc_str8_lp(s) ((s).len), ((s).ptr) #define oc_str8_ip(s) (int)oc_str8_lp(s) - ORCA_API oc_str8 oc_str8_from_buffer(u64 len, char* buffer); - ORCA_API oc_str8 oc_str8_slice(oc_str8 s, u64 start, u64 end); +ORCA_API oc_str8 oc_str8_from_buffer(u64 len, char* buffer); +ORCA_API oc_str8 oc_str8_slice(oc_str8 s, u64 start, u64 end); - ORCA_API oc_str8 oc_str8_push_buffer(oc_arena* arena, u64 len, char* buffer); - ORCA_API oc_str8 oc_str8_push_cstring(oc_arena* arena, const char* str); - ORCA_API oc_str8 oc_str8_push_copy(oc_arena* arena, oc_str8 s); - ORCA_API oc_str8 oc_str8_push_slice(oc_arena* arena, oc_str8 s, u64 start, u64 end); +ORCA_API oc_str8 oc_str8_push_buffer(oc_arena* arena, u64 len, char* buffer); +ORCA_API oc_str8 oc_str8_push_cstring(oc_arena* arena, const char* str); +ORCA_API oc_str8 oc_str8_push_copy(oc_arena* arena, oc_str8 s); +ORCA_API oc_str8 oc_str8_push_slice(oc_arena* arena, oc_str8 s, u64 start, u64 end); - ORCA_API oc_str8 oc_str8_pushfv(oc_arena* arena, const char* format, va_list args); - ORCA_API oc_str8 oc_str8_pushf(oc_arena* arena, const char* format, ...); +ORCA_API oc_str8 oc_str8_pushfv(oc_arena* arena, const char* format, va_list args); +ORCA_API oc_str8 oc_str8_pushf(oc_arena* arena, const char* format, ...); - ORCA_API int oc_str8_cmp(oc_str8 s1, oc_str8 s2); +ORCA_API int oc_str8_cmp(oc_str8 s1, oc_str8 s2); - ORCA_API char* oc_str8_to_cstring(oc_arena* arena, oc_str8 string); +ORCA_API char* oc_str8_to_cstring(oc_arena* arena, oc_str8 string); - //---------------------------------------------------------------------------------- - // string lists - //---------------------------------------------------------------------------------- - typedef struct oc_str8_elt - { - oc_list_elt listElt; - oc_str8 string; - } oc_str8_elt; +//---------------------------------------------------------------------------------- +// string lists +//---------------------------------------------------------------------------------- +typedef struct oc_str8_elt +{ + oc_list_elt listElt; + oc_str8 string; +} oc_str8_elt; - typedef struct oc_str8_list - { - oc_list list; - u64 eltCount; - u64 len; - } oc_str8_list; +typedef struct oc_str8_list +{ + oc_list list; + u64 eltCount; + u64 len; +} oc_str8_list; - ORCA_API void oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str); - ORCA_API void oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...); +ORCA_API void oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str); +ORCA_API void oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...); - ORCA_API oc_str8 oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix); - ORCA_API oc_str8 oc_str8_list_join(oc_arena* arena, oc_str8_list list); - ORCA_API oc_str8_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators); +ORCA_API oc_str8 oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix); +ORCA_API oc_str8 oc_str8_list_join(oc_arena* arena, oc_str8_list list); +ORCA_API oc_str8_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators); - //---------------------------------------------------------------------------------- - // u16 strings - //---------------------------------------------------------------------------------- - typedef struct oc_str16 - { - u64 len; - u16* ptr; - } oc_str16; +//---------------------------------------------------------------------------------- +// u16 strings +//---------------------------------------------------------------------------------- +typedef struct oc_str16 +{ + u64 len; + u16* ptr; +} oc_str16; - ORCA_API oc_str16 oc_str16_from_buffer(u64 len, u16* buffer); - ORCA_API oc_str16 oc_str16_slice(oc_str16 s, u64 start, u64 end); +ORCA_API oc_str16 oc_str16_from_buffer(u64 len, u16* buffer); +ORCA_API oc_str16 oc_str16_slice(oc_str16 s, u64 start, u64 end); - ORCA_API oc_str16 oc_str16_push_buffer(oc_arena* arena, u64 len, u16* buffer); - ORCA_API oc_str16 oc_str16_push_copy(oc_arena* arena, oc_str16 s); - ORCA_API oc_str16 oc_str16_push_slice(oc_arena* arena, oc_str16 s, u64 start, u64 end); +ORCA_API oc_str16 oc_str16_push_buffer(oc_arena* arena, u64 len, u16* buffer); +ORCA_API oc_str16 oc_str16_push_copy(oc_arena* arena, oc_str16 s); +ORCA_API oc_str16 oc_str16_push_slice(oc_arena* arena, oc_str16 s, u64 start, u64 end); - typedef struct oc_str16_elt - { - oc_list_elt listElt; - oc_str16 string; - } oc_str16_elt; +typedef struct oc_str16_elt +{ + oc_list_elt listElt; + oc_str16 string; +} oc_str16_elt; - typedef struct oc_str16_list - { - oc_list list; - u64 eltCount; - u64 len; - } oc_str16_list; +typedef struct oc_str16_list +{ + oc_list list; + u64 eltCount; + u64 len; +} oc_str16_list; - ORCA_API void oc_str16_list_push(oc_arena* arena, oc_str16_list* list, oc_str16 str); - ORCA_API oc_str16 oc_str16_list_join(oc_arena* arena, oc_str16_list list); - ORCA_API oc_str16_list oc_str16_split(oc_arena* arena, oc_str16 str, oc_str16_list separators); +ORCA_API void oc_str16_list_push(oc_arena* arena, oc_str16_list* list, oc_str16 str); +ORCA_API oc_str16 oc_str16_list_join(oc_arena* arena, oc_str16_list list); +ORCA_API oc_str16_list oc_str16_split(oc_arena* arena, oc_str16 str, oc_str16_list separators); - //---------------------------------------------------------------------------------- - // u32 strings - //---------------------------------------------------------------------------------- - typedef struct oc_str32 - { - u64 len; - u32* ptr; - } oc_str32; +//---------------------------------------------------------------------------------- +// u32 strings +//---------------------------------------------------------------------------------- +typedef struct oc_str32 +{ + u64 len; + u32* ptr; +} oc_str32; - ORCA_API oc_str32 oc_str32_from_buffer(u64 len, u32* buffer); - ORCA_API oc_str32 oc_str32_slice(oc_str32 s, u64 start, u64 end); +ORCA_API oc_str32 oc_str32_from_buffer(u64 len, u32* buffer); +ORCA_API oc_str32 oc_str32_slice(oc_str32 s, u64 start, u64 end); - ORCA_API oc_str32 oc_str32_push_buffer(oc_arena* arena, u64 len, u32* buffer); - ORCA_API oc_str32 oc_str32_push_copy(oc_arena* arena, oc_str32 s); - ORCA_API oc_str32 oc_str32_push_slice(oc_arena* arena, oc_str32 s, u64 start, u64 end); +ORCA_API oc_str32 oc_str32_push_buffer(oc_arena* arena, u64 len, u32* buffer); +ORCA_API oc_str32 oc_str32_push_copy(oc_arena* arena, oc_str32 s); +ORCA_API oc_str32 oc_str32_push_slice(oc_arena* arena, oc_str32 s, u64 start, u64 end); - typedef struct oc_str32_elt - { - oc_list_elt listElt; - oc_str32 string; - } oc_str32_elt; +typedef struct oc_str32_elt +{ + oc_list_elt listElt; + oc_str32 string; +} oc_str32_elt; - typedef struct oc_str32_list - { - oc_list list; - u64 eltCount; - u64 len; - } oc_str32_list; +typedef struct oc_str32_list +{ + oc_list list; + u64 eltCount; + u64 len; +} oc_str32_list; - ORCA_API void oc_str32_list_push(oc_arena* arena, oc_str32_list* list, oc_str32 str); - ORCA_API oc_str32 oc_str32_list_join(oc_arena* arena, oc_str32_list list); - ORCA_API oc_str32_list oc_str32_split(oc_arena* arena, oc_str32 str, oc_str32_list separators); +ORCA_API void oc_str32_list_push(oc_arena* arena, oc_str32_list* list, oc_str32 str); +ORCA_API oc_str32 oc_str32_list_join(oc_arena* arena, oc_str32_list list); +ORCA_API oc_str32_list oc_str32_split(oc_arena* arena, oc_str32 str, oc_str32_list separators); #ifdef __cplusplus } // extern "C" diff --git a/src/wasmbind/core_api.json b/src/wasmbind/core_api.json index 7cc1a5f..8d43000 100644 --- a/src/wasmbind/core_api.json +++ b/src/wasmbind/core_api.json @@ -1,7 +1,7 @@ [ { - "name": "oc_runtime_log", - "cname": "oc_runtime_log", + "name": "oc_bridge_log", + "cname": "oc_bridge_log", "ret": {"name": "void", "tag": "v"}, "args": [ {"name": "level", "type": {"name": "oc_log_level", "tag": "i"}}, @@ -29,7 +29,7 @@ "type": {"name": "u64", "tag": "I"}}] }, { - "name": "oc_runtime_assert_fail", + "name": "oc_bridge_assert_fail", "cname": "oc_assert_fail", "ret": {"name": "void", "tag": "v"}, "args": [ {"name": "file", @@ -45,7 +45,7 @@ ] }, { - "name": "oc_runtime_abort_ext", + "name": "oc_bridge_abort_ext", "cname": "oc_abort_ext", "ret": {"name": "void", "tag": "v"}, "args": [ {"name": "file", @@ -71,17 +71,17 @@ "args": [] }, { - "name": "oc_runtime_window_set_title", - "cname": "oc_runtime_window_set_title", + "name": "oc_window_set_title", + "cname": "oc_bridge_window_set_title", "ret": {"name": "void", "tag": "v"}, "args": [ { "name": "title", - "type": {"name": "oc_str8", "tag": "S"}} + "type": {"name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"}} ] }, { - "name": "oc_runtime_window_set_size", - "cname": "oc_runtime_window_set_size", + "name": "oc_window_set_size", + "cname": "oc_bridge_window_set_size", "ret": {"name": "void", "tag": "v"}, "args": [ { "name": "size", diff --git a/src/wasmbind/io_api.json b/src/wasmbind/io_api.json index ecb5c14..5f720f3 100644 --- a/src/wasmbind/io_api.json +++ b/src/wasmbind/io_api.json @@ -1,9 +1,37 @@ [ { "name": "oc_io_wait_single_req", - "cname": "oc_runtime_io_wait_single_req", + "cname": "oc_bridge_io_single_rect", "ret": {"name": "oc_io_cmp", "tag": "S"}, "args": [ {"name": "req", "type": {"name": "oc_io_req*", "tag": "p"}}] +}, +{ + "name": "oc_file_open_with_request", + "cname": "oc_file_open_with_request_bridge", + "ret": {"name": "oc_file", "tag": "S"}, + "args": [ + {"name": "path", + "type": {"name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"}}, + {"name": "rights", + "type": {"name": "oc_file_access", "tag": "i"}}, + {"name": "flags", + "type": {"name": "oc_file_open_flags", "tag": "i"}} + ] +}, +{ + "name": "oc_file_open_with_dialog", + "cname": "oc_file_open_with_dialog_bridge", + "ret": {"name": "oc_file_open_with_dialog_result", "cname": "oc_wasm_file_open_with_dialog_result", "tag": "S"}, + "args": [ + {"name": "arena", + "type": {"name": "oc_arena*", "cname": "i32", "tag": "i"}}, + {"name": "rights", + "type": {"name": "oc_file_access", "tag": "i"}}, + {"name": "flags", + "type": {"name": "oc_file_open_flags", "tag": "i"}}, + {"name": "desc", + "type": {"name": "oc_file_dialog_desc*", "cname": "oc_wasm_file_dialog_desc*", "tag": "p"}} + ] } ] diff --git a/src/wasmbind/surface_api.json b/src/wasmbind/surface_api.json index 714c63e..633d7db 100644 --- a/src/wasmbind/surface_api.json +++ b/src/wasmbind/surface_api.json @@ -36,6 +36,14 @@ {"name": "pixels", "type": {"name": "u8*", "tag": "p"}}] }, +{ + "name": "oc_surface_get_size", + "cname": "oc_surface_get_size", + "ret": {"name": "oc_vec2", "tag": "S"}, + "args": [ + {"name": "surface", + "type": {"name": "oc_surface", "tag": "S"}}] +}, { "name": "oc_surface_contents_scaling", "cname": "oc_surface_contents_scaling", diff --git a/tests/file_dialog/.gitignore b/tests/file_dialog/.gitignore new file mode 100644 index 0000000..c5e82d7 --- /dev/null +++ b/tests/file_dialog/.gitignore @@ -0,0 +1 @@ +bin \ No newline at end of file diff --git a/tests/file_dialog/build.bat b/tests/file_dialog/build.bat new file mode 100644 index 0000000..4ea5871 --- /dev/null +++ b/tests/file_dialog/build.bat @@ -0,0 +1,7 @@ + +set INCLUDES=/I ..\..\src /I ..\..\ext + +mkdir bin + +cl /we4013 /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% main.c /link /LIBPATH:../../build/bin orca.dll.lib /out:bin/test_file_dialog.exe +copy ..\..\build\bin\orca.dll bin diff --git a/tests/file_dialog/build.sh b/tests/file_dialog/build.sh new file mode 100755 index 0000000..8123429 --- /dev/null +++ b/tests/file_dialog/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +LIBDIR=../../build/bin +SRCDIR=../../src + +INCLUDES="-I$SRCDIR" +LIBS="-L$LIBDIR -lorca" +FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG" + +if [ ! \( -e bin \) ] ; then + mkdir ./bin +fi + +clang -g $FLAGS $LIBS $INCLUDES -o ./bin/test_file_dialog main.c + +cp $LIBDIR/liborca.dylib ./bin/ + +install_name_tool -add_rpath "@executable_path" ./bin/test_file_dialog diff --git a/tests/file_dialog/main.c b/tests/file_dialog/main.c new file mode 100644 index 0000000..e5d3378 --- /dev/null +++ b/tests/file_dialog/main.c @@ -0,0 +1,45 @@ +/************************************************************/ /** +* +* @file: main.c +* @author: Martin Fouilleul +* @date: 26/05/2023 +* +*****************************************************************/ + +#include "orca.h" + +int main(int argc, char** argv) +{ + oc_init(); + + oc_str8 path = oc_path_executable_relative(oc_scratch(), OC_STR8("../")); + oc_file dir = oc_file_open(path, OC_FILE_ACCESS_READ, 0); + + oc_file_dialog_desc desc = { + .kind = OC_FILE_DIALOG_OPEN, + .flags = OC_FILE_DIALOG_FILES | OC_FILE_DIALOG_MULTIPLE, + .title = OC_STR8("Select Files"), + .okLabel = OC_STR8("Select"), + .startAt = dir, + .startPath = OC_STR8(".."), + }; + + oc_str8_list_push(oc_scratch(), &desc.filters, OC_STR8("txt")); + + oc_file_dialog_result res = oc_file_dialog(oc_scratch(), &desc); + + if(res.button == OC_FILE_DIALOG_CANCEL) + { + oc_log_error("Cancel\n"); + } + else + { + oc_log_info("Selected files:\n"); + oc_list_for(&res.selection.list, elt, oc_str8_elt, listElt) + { + oc_log_info("\t%.*s\n", (int)elt->string.len, elt->string.ptr); + } + } + + return (0); +} diff --git a/tests/file_dialog/test.txt b/tests/file_dialog/test.txt new file mode 100644 index 0000000..ff3bb63 --- /dev/null +++ b/tests/file_dialog/test.txt @@ -0,0 +1 @@ +The quick brown fox jumps over the lazy dog \ No newline at end of file diff --git a/tests/file_dialog/test2.txt b/tests/file_dialog/test2.txt new file mode 100644 index 0000000..4f006a8 --- /dev/null +++ b/tests/file_dialog/test2.txt @@ -0,0 +1 @@ +Lorem ipsum dolor sit amet, consectetur adipiscing elit. diff --git a/tests/file_open_dialog/.gitignore b/tests/file_open_dialog/.gitignore new file mode 100644 index 0000000..c5e82d7 --- /dev/null +++ b/tests/file_open_dialog/.gitignore @@ -0,0 +1 @@ +bin \ No newline at end of file diff --git a/tests/file_open_dialog/build.bat b/tests/file_open_dialog/build.bat new file mode 100644 index 0000000..72b70b5 --- /dev/null +++ b/tests/file_open_dialog/build.bat @@ -0,0 +1,5 @@ + +set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext + +cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/test_open_dialog.exe +copy ..\..\build\bin\orca.dll bin diff --git a/tests/file_open_dialog/build.sh b/tests/file_open_dialog/build.sh new file mode 100755 index 0000000..8f5e240 --- /dev/null +++ b/tests/file_open_dialog/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +LIBDIR=../../build/bin +SRCDIR=../../src + +INCLUDES="-I$SRCDIR" +LIBS="-L$LIBDIR -lorca" +FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG" + +if [ ! \( -e bin \) ] ; then + mkdir ./bin +fi + +clang -g $FLAGS $LIBS $INCLUDES -o ./bin/test_open_dialog main.c + +cp $LIBDIR/liborca.dylib ./bin/ + +install_name_tool -add_rpath "@executable_path" ./bin/test_open_dialog diff --git a/tests/file_open_dialog/main.c b/tests/file_open_dialog/main.c new file mode 100644 index 0000000..7d2b32c --- /dev/null +++ b/tests/file_open_dialog/main.c @@ -0,0 +1,37 @@ +/************************************************************/ /** +* +* @file: main.c +* @author: Martin Fouilleul +* @date: 26/05/2023 +* +*****************************************************************/ + +#include "orca.h" + +int main(int argc, char** argv) +{ + oc_init(); + + oc_file_dialog_desc desc = { + .kind = OC_FILE_DIALOG_OPEN, + .flags = OC_FILE_DIALOG_FILES, + .title = OC_STR8("Select Files"), + .okLabel = OC_STR8("Select") + }; + + oc_str8_list_push(oc_scratch(), &desc.filters, OC_STR8("txt")); + + oc_file file = oc_file_open_with_dialog(OC_FILE_ACCESS_READ, 0, &desc); + if(oc_file_is_nil(file)) + { + oc_log_error("Couldn't open file\n"); + } + else + { + char buffer[1024]; + u64 len = oc_file_read(file, 1024, buffer); + oc_log_info("file contents: %.*s\n", (int)len, buffer); + } + + return (0); +} diff --git a/tests/file_open_dialog/test.txt b/tests/file_open_dialog/test.txt new file mode 100644 index 0000000..ff3bb63 --- /dev/null +++ b/tests/file_open_dialog/test.txt @@ -0,0 +1 @@ +The quick brown fox jumps over the lazy dog \ No newline at end of file diff --git a/tests/file_open_request/.gitignore b/tests/file_open_request/.gitignore new file mode 100644 index 0000000..c5e82d7 --- /dev/null +++ b/tests/file_open_request/.gitignore @@ -0,0 +1 @@ +bin \ No newline at end of file diff --git a/tests/file_open_request/build.bat b/tests/file_open_request/build.bat new file mode 100644 index 0000000..e771f65 --- /dev/null +++ b/tests/file_open_request/build.bat @@ -0,0 +1,5 @@ + +set INCLUDES=/I ..\..\src /I ..\..\src\util /I ..\..\src\platform /I ../../ext + +cl /we4013 /Zi /Zc:preprocessor /std:c11 %INCLUDES% main.c /link /LIBPATH:../../bin milepost.dll.lib /out:../../bin/test_open_request.exe +copy ..\..\build\bin\orca.dll bin diff --git a/tests/file_open_request/build.sh b/tests/file_open_request/build.sh new file mode 100755 index 0000000..b63795d --- /dev/null +++ b/tests/file_open_request/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +LIBDIR=../../build/bin +SRCDIR=../../src + +INCLUDES="-I$SRCDIR" +LIBS="-L$LIBDIR -lorca" +FLAGS="-mmacos-version-min=10.15.4 -DOC_DEBUG -DLOG_COMPILE_DEBUG" + +if [ ! \( -e bin \) ] ; then + mkdir ./bin +fi + +clang -g $FLAGS $LIBS $INCLUDES -o ./bin/test_open_request main.c + +cp $LIBDIR/liborca.dylib ./bin/ + +install_name_tool -add_rpath "@executable_path" ./bin/test_open_request diff --git a/tests/file_open_request/main.c b/tests/file_open_request/main.c new file mode 100644 index 0000000..02bcd25 --- /dev/null +++ b/tests/file_open_request/main.c @@ -0,0 +1,28 @@ +/************************************************************/ /** +* +* @file: main.c +* @author: Martin Fouilleul +* @date: 26/05/2023 +* +*****************************************************************/ + +#include "orca.h" + +int main(int argc, char** argv) +{ + oc_init(); + + oc_file file = oc_file_open_with_request(OC_STR8("./test.txt"), OC_FILE_ACCESS_READ, 0); + if(oc_file_is_nil(file)) + { + oc_log_error("Couldn't open file\n"); + } + else + { + char buffer[1024]; + u64 len = oc_file_read(file, 1024, buffer); + oc_log_info("file contents: %.*s\n", (int)len, buffer); + } + + return (0); +} diff --git a/tests/file_open_request/test.txt b/tests/file_open_request/test.txt new file mode 100644 index 0000000..ff3bb63 --- /dev/null +++ b/tests/file_open_request/test.txt @@ -0,0 +1 @@ +The quick brown fox jumps over the lazy dog \ No newline at end of file