Merge branch 'main' of git.handmade.network:hmn/orca into ui-redesign
This commit is contained in:
commit
15bc29d703
|
@ -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)
|
|
@ -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);
|
|
@ -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);
|
||||
|
||||
|
|
@ -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);
|
|
@ -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, ...)
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -16,7 +16,6 @@ STDLIB_DIR=../../src/libc-shim
|
|||
|
||||
wasmFlags="--target=wasm32 \
|
||||
--no-standard-libraries \
|
||||
-fno-builtin \
|
||||
-Wl,--no-entry \
|
||||
-Wl,--export-dynamic \
|
||||
-g \
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -1,289 +0,0 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define _USE_MATH_DEFINES //NOTE: necessary for MSVC
|
||||
#include <math.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define OC_INCLUDE_GL_API
|
||||
#include "orca.h"
|
||||
|
||||
#ifdef OC_PLATFORM_WINDOWS
|
||||
#include <process.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#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 <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#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);
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 <commctrl.h>
|
||||
|
||||
int oc_alert_popup(oc_str8 title,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*****************************************************************/
|
||||
|
||||
#include "platform_io.h"
|
||||
#include "platform_io_dialog.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// File stream read/write API
|
||||
|
|
|
@ -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_
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_
|
||||
|
|
161
src/runtime.c
161
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
110
src/runtime_io.c
110
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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_
|
|
@ -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,
|
||||
|
|
970
src/ui/ui.h
970
src/ui/ui.h
File diff suppressed because it is too large
Load Diff
275
src/util/lists.h
275
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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
#include <string.h>
|
||||
|
||||
#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"
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"}}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
bin
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
The quick brown fox jumps over the lazy dog
|
|
@ -0,0 +1 @@
|
|||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
@ -0,0 +1 @@
|
|||
bin
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
The quick brown fox jumps over the lazy dog
|
|
@ -0,0 +1 @@
|
|||
bin
|
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
The quick brown fox jumps over the lazy dog
|
Loading…
Reference in New Issue