Make UI look nicer #80
|
@ -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)
|
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 });
|
oc_runtime_window_set_size((oc_vec2){ .x = 400, .y = 400 });
|
||||||
|
|
||||||
surface = oc_surface_canvas();
|
surface = oc_surface_canvas();
|
||||||
|
|
|
@ -615,7 +615,7 @@ ORCA_EXPORT void oc_on_init()
|
||||||
{
|
{
|
||||||
oc_log_info("Hello, world (from C)");
|
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();
|
surface = oc_surface_gles();
|
||||||
oc_surface_select(surface);
|
oc_surface_select(surface);
|
||||||
|
|
|
@ -37,7 +37,7 @@ void compile_shader(GLuint shader, const char* source)
|
||||||
|
|
||||||
ORCA_EXPORT void oc_on_init(void)
|
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();
|
surface = oc_surface_gles();
|
||||||
oc_surface_select(surface);
|
oc_surface_select(surface);
|
||||||
|
|
|
@ -69,7 +69,7 @@ oc_str8 loadFile(oc_arena* arena, oc_str8 filename)
|
||||||
|
|
||||||
ORCA_EXPORT void oc_on_init(void)
|
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();
|
surface = oc_surface_canvas();
|
||||||
canvas = oc_canvas_create();
|
canvas = oc_canvas_create();
|
||||||
|
|
|
@ -16,7 +16,6 @@ STDLIB_DIR=../../src/libc-shim
|
||||||
|
|
||||||
wasmFlags="--target=wasm32 \
|
wasmFlags="--target=wasm32 \
|
||||||
--no-standard-libraries \
|
--no-standard-libraries \
|
||||||
-fno-builtin \
|
|
||||||
-Wl,--no-entry \
|
-Wl,--no-entry \
|
||||||
-Wl,--export-dynamic \
|
-Wl,--export-dynamic \
|
||||||
-g \
|
-g \
|
||||||
|
|
|
@ -10,7 +10,7 @@ oc_arena textArena = { 0 };
|
||||||
|
|
||||||
ORCA_EXPORT void oc_on_init(void)
|
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();
|
surface = oc_surface_canvas();
|
||||||
canvas = oc_canvas_create();
|
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;
|
frame.h = size.y;
|
||||||
oc_window_set_frame_rect(window, frame);
|
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 defaultPath,
|
||||||
oc_str8_list filters);
|
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,
|
ORCA_API int oc_alert_popup(oc_str8 title,
|
||||||
oc_str8 message,
|
oc_str8 message,
|
||||||
oc_str8_list options);
|
oc_str8_list options);
|
||||||
|
@ -403,12 +457,11 @@ ORCA_API int oc_directory_create(oc_str8 path);
|
||||||
|
|
||||||
#else
|
#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_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)
|
#endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
|
#include "platform/platform_io_internal.h"
|
||||||
#include "util/ringbuffer.h"
|
#include "util/ringbuffer.h"
|
||||||
|
|
||||||
#if OC_PLATFORM_WINDOWS
|
#if OC_PLATFORM_WINDOWS
|
||||||
|
|
|
@ -2,3 +2,8 @@
|
||||||
|
|
||||||
//This is used to pass raw events from the runtime
|
//This is used to pass raw events from the runtime
|
||||||
ORCA_EXPORT oc_event oc_rawEvent;
|
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_clock.h"
|
||||||
#include "platform_debug.h"
|
#include "platform_debug.h"
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
|
#include "platform/platform_path.h"
|
||||||
#include "app.c"
|
#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
|
// Events handling
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
@ -2133,18 +1926,27 @@ oc_str8 oc_open_dialog(oc_arena* arena,
|
||||||
oc_str8_list filters,
|
oc_str8_list filters,
|
||||||
bool directory)
|
bool directory)
|
||||||
{
|
{
|
||||||
|
__block oc_str8 path = { 0 };
|
||||||
|
|
||||||
|
dispatch_block_t block = ^{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
NSWindow* keyWindow = [NSApp keyWindow];
|
NSWindow* keyWindow = [NSApp keyWindow];
|
||||||
|
|
||||||
NSOpenPanel* dialog = [NSOpenPanel openPanel];
|
NSOpenPanel* dialog = [NSOpenPanel openPanel];
|
||||||
[dialog setLevel:CGShieldingWindowLevel()];
|
|
||||||
|
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)
|
if(filters.eltCount)
|
||||||
{
|
{
|
||||||
NSMutableArray* fileTypesArray = [NSMutableArray array];
|
NSMutableArray* fileTypesArray = [NSMutableArray array];
|
||||||
|
|
||||||
oc_list_for(&filters.list, elt, oc_str8_elt, listElt)
|
oc_list_for((oc_list*)&filters.list, elt, oc_str8_elt, listElt)
|
||||||
{
|
{
|
||||||
oc_str8 string = elt->string;
|
oc_str8 string = elt->string;
|
||||||
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
|
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
|
||||||
|
@ -2189,17 +1991,22 @@ oc_str8 oc_open_dialog(oc_arena* arena,
|
||||||
|
|
||||||
const char* result = [[[files objectAtIndex:0] path] UTF8String];
|
const char* result = [[[files objectAtIndex:0] path] UTF8String];
|
||||||
|
|
||||||
oc_str8 path = oc_str8_push_cstring(arena, result);
|
path = oc_str8_push_cstring(arena, result);
|
||||||
|
}
|
||||||
[keyWindow makeKeyWindow];
|
[keyWindow makeKeyWindow];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (path);
|
if([NSThread isMainThread])
|
||||||
|
{
|
||||||
|
block();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[keyWindow makeKeyWindow];
|
dispatch_sync(dispatch_get_main_queue(), block);
|
||||||
return ((oc_str8){ 0, 0 });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
oc_str8 oc_save_dialog(oc_arena* arena,
|
oc_str8 oc_save_dialog(oc_arena* arena,
|
||||||
|
@ -2207,6 +2014,9 @@ oc_str8 oc_save_dialog(oc_arena* arena,
|
||||||
oc_str8 defaultPath,
|
oc_str8 defaultPath,
|
||||||
oc_str8_list filters)
|
oc_str8_list filters)
|
||||||
{
|
{
|
||||||
|
__block oc_str8 path = { 0 };
|
||||||
|
|
||||||
|
dispatch_block_t block = ^{
|
||||||
@autoreleasepool
|
@autoreleasepool
|
||||||
{
|
{
|
||||||
NSWindow* keyWindow = [NSApp keyWindow];
|
NSWindow* keyWindow = [NSApp keyWindow];
|
||||||
|
@ -2218,7 +2028,7 @@ oc_str8 oc_save_dialog(oc_arena* arena,
|
||||||
{
|
{
|
||||||
NSMutableArray* fileTypesArray = [NSMutableArray array];
|
NSMutableArray* fileTypesArray = [NSMutableArray array];
|
||||||
|
|
||||||
oc_list_for(&filters.list, elt, oc_str8_elt, listElt)
|
oc_list_for((oc_list*)&filters.list, elt, oc_str8_elt, listElt)
|
||||||
{
|
{
|
||||||
oc_str8 string = elt->string;
|
oc_str8 string = elt->string;
|
||||||
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
|
NSString* filter = [[NSString alloc] initWithBytes:string.ptr length:string.len encoding:NSUTF8StringEncoding];
|
||||||
|
@ -2252,16 +2062,173 @@ oc_str8 oc_save_dialog(oc_arena* arena,
|
||||||
|
|
||||||
const char* result = [[files path] UTF8String];
|
const char* result = [[files path] UTF8String];
|
||||||
|
|
||||||
oc_str8 path = oc_str8_push_cstring(arena, result);
|
path = oc_str8_push_cstring(arena, result);
|
||||||
|
}
|
||||||
[keyWindow makeKeyWindow];
|
[keyWindow makeKeyWindow];
|
||||||
return (path);
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if([NSThread isMainThread])
|
||||||
|
{
|
||||||
|
block();
|
||||||
}
|
}
|
||||||
else
|
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];
|
[keyWindow makeKeyWindow];
|
||||||
return ((oc_str8){ 0, 0 });
|
|
||||||
|
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,
|
int oc_alert_popup(oc_str8 title,
|
||||||
|
|
|
@ -1206,31 +1206,6 @@ void* oc_win32_surface_native_layer(oc_surface_data* surface)
|
||||||
return ((void*)surface->layer.hWnd);
|
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)
|
void oc_surface_cleanup(oc_surface_data* surface)
|
||||||
{
|
{
|
||||||
oc_list_remove(&surface->layer.parent->win32.layers, &surface->layer.listElt);
|
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);
|
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
|
// native open/save/alert windows
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
@ -1565,6 +1478,207 @@ oc_str8 oc_save_dialog(oc_arena* arena,
|
||||||
return (res);
|
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>
|
#include <commctrl.h>
|
||||||
|
|
||||||
int oc_alert_popup(oc_str8 title,
|
int oc_alert_popup(oc_str8 title,
|
||||||
|
|
|
@ -150,22 +150,6 @@ void oc_egl_surface_init(oc_egl_surface* surface)
|
||||||
eglSwapInterval(surface->eglDisplay, 1);
|
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_surface_data* oc_egl_surface_create_for_window(oc_window window)
|
||||||
{
|
{
|
||||||
oc_egl_surface* surface = 0;
|
oc_egl_surface* surface = 0;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "util/typedefs.h"
|
#include "util/typedefs.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): backends selection
|
//SECTION: backends selection
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -85,49 +85,48 @@ typedef enum
|
||||||
#include "wgl_surface.h"
|
#include "wgl_surface.h"
|
||||||
#endif
|
#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);
|
ORCA_API bool oc_is_surface_api_available(oc_surface_api api);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): graphics surface
|
//SECTION: graphics surface
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
typedef struct oc_surface
|
typedef struct oc_surface
|
||||||
{
|
{
|
||||||
u64 h;
|
u64 h;
|
||||||
} oc_surface;
|
} oc_surface;
|
||||||
|
|
||||||
ORCA_API oc_surface oc_surface_nil(void);
|
ORCA_API oc_surface oc_surface_nil(void); //DOC: returns a nil surface
|
||||||
ORCA_API bool oc_surface_is_nil(oc_surface 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 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 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 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_set_hidden(oc_surface surface, bool hidden);
|
||||||
|
|
||||||
ORCA_API void oc_surface_bring_to_front(oc_surface surface);
|
#else
|
||||||
ORCA_API void oc_surface_send_to_back(oc_surface surface);
|
|
||||||
|
|
||||||
//NOTE(martin): surface sharing
|
ORCA_API oc_surface oc_surface_canvas(); //DOC: creates a surface for use with the canvas API
|
||||||
typedef u64 oc_surface_id;
|
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);
|
#endif
|
||||||
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_destroy(oc_surface surface); //DOC: destroys the surface
|
||||||
ORCA_API void oc_surface_host_connect(oc_surface surface, oc_surface_id remoteId);
|
|
||||||
|
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
|
typedef struct oc_canvas
|
||||||
{
|
{
|
||||||
|
@ -196,18 +195,18 @@ typedef struct oc_text_extents
|
||||||
} oc_text_extents;
|
} oc_text_extents;
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): graphics canvas
|
//SECTION: graphics canvas
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
ORCA_API oc_canvas oc_canvas_nil(void);
|
ORCA_API oc_canvas oc_canvas_nil(void); //DOC: returns a nil canvas
|
||||||
ORCA_API bool oc_canvas_is_nil(oc_canvas 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 oc_canvas oc_canvas_create(void); //DOC: create a new canvas
|
||||||
ORCA_API void oc_canvas_destroy(oc_canvas canvas);
|
ORCA_API void oc_canvas_destroy(oc_canvas canvas); //DOC: destroys canvas
|
||||||
ORCA_API oc_canvas oc_canvas_set_current(oc_canvas 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);
|
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_nil(void);
|
||||||
ORCA_API oc_font oc_font_create_from_memory(oc_str8 mem, u32 rangeCount, oc_unicode_range* ranges);
|
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);
|
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 oc_image oc_image_nil(void);
|
||||||
ORCA_API bool oc_image_is_nil(oc_image a);
|
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);
|
ORCA_API oc_vec2 oc_image_size(oc_image image);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
//NOTE(martin): atlasing
|
//SECTION: atlasing
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
//NOTE: rectangle allocator
|
//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);
|
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_push(oc_mat2x3 matrix);
|
||||||
ORCA_API void oc_matrix_pop(void);
|
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_push(f32 x, f32 y, f32 w, f32 h);
|
||||||
ORCA_API void oc_clip_pop(void);
|
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(oc_color color);
|
||||||
ORCA_API void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
|
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 oc_font oc_get_font(void);
|
||||||
ORCA_API f32 oc_get_font_size(void);
|
ORCA_API f32 oc_get_font_size(void);
|
||||||
ORCA_API bool oc_get_text_flip(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 oc_vec2 oc_get_position(void);
|
||||||
ORCA_API void oc_move_to(f32 x, f32 y);
|
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);
|
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_clear(void);
|
||||||
ORCA_API void oc_fill(void);
|
ORCA_API void oc_fill(void);
|
||||||
ORCA_API void oc_stroke(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_fill(f32 x, f32 y, f32 w, f32 h);
|
||||||
ORCA_API void oc_rectangle_stroke(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)
|
void oc_clip_push(f32 x, f32 y, f32 w, f32 h)
|
||||||
{
|
{
|
||||||
oc_canvas_data* canvas = __mgCurrentCanvas;
|
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 };
|
oc_rect clip = { -FLT_MAX / 2, -FLT_MAX / 2, FLT_MAX, FLT_MAX };
|
||||||
|
|
||||||
|
@ -1193,6 +1208,28 @@ bool oc_get_text_flip()
|
||||||
return (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
|
//NOTE(martin): path construction
|
||||||
//------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -153,55 +153,6 @@ oc_surface oc_surface_create_for_window(oc_window window, oc_surface_api api)
|
||||||
return (surfaceHandle);
|
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)
|
void oc_surface_destroy(oc_surface handle)
|
||||||
{
|
{
|
||||||
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
OC_DEBUG_ASSERT(oc_graphicsData.init);
|
||||||
|
@ -328,26 +279,6 @@ void* oc_surface_native_layer(oc_surface surface)
|
||||||
return (res);
|
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,
|
void oc_surface_render_commands(oc_surface surface,
|
||||||
oc_color clearColor,
|
oc_color clearColor,
|
||||||
u32 primitiveCount,
|
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 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_set_hidden_proc)(oc_surface_data* surface, bool hidden);
|
||||||
typedef void* (*oc_surface_native_layer_proc)(oc_surface_data* surface);
|
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_bring_to_front_proc)(oc_surface_data* surface);
|
||||||
typedef void (*oc_surface_send_to_back_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_get_hidden_proc getHidden;
|
||||||
oc_surface_set_hidden_proc setHidden;
|
oc_surface_set_hidden_proc setHidden;
|
||||||
oc_surface_native_layer_proc nativeLayer;
|
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_bring_to_front_proc bringToFront;
|
||||||
oc_surface_send_to_back_proc sendToBack;
|
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);
|
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_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_cleanup(oc_surface_data* surface);
|
||||||
void* oc_surface_native_layer(oc_surface surface);
|
void* oc_surface_native_layer(oc_surface surface);
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "platform/platform_io_common.c"
|
#include "platform/platform_io_common.c"
|
||||||
#include "platform/orca_io_stubs.c"
|
#include "platform/orca_io_stubs.c"
|
||||||
#include "platform/orca_platform.c"
|
#include "platform/orca_platform.c"
|
||||||
|
#include "platform/platform_path.c"
|
||||||
#else
|
#else
|
||||||
#error "Unsupported platform"
|
#error "Unsupported platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "platform/platform.h"
|
#include "platform/platform.h"
|
||||||
#include "platform/platform_clock.h"
|
#include "platform/platform_clock.h"
|
||||||
#include "platform/platform_io.h"
|
#include "platform/platform_io.h"
|
||||||
|
#include "platform/platform_io_dialog.h"
|
||||||
#include "platform/platform_path.h"
|
#include "platform/platform_path.h"
|
||||||
|
|
||||||
#if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
|
#if !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)
|
||||||
|
@ -39,9 +40,6 @@
|
||||||
//TODO: maybe make this conditional
|
//TODO: maybe make this conditional
|
||||||
#include "graphics/orca_gl31.h"
|
#include "graphics/orca_gl31.h"
|
||||||
|
|
||||||
oc_surface oc_surface_canvas();
|
|
||||||
oc_surface oc_surface_gles();
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#ifdef OC_INCLUDE_GL_API
|
#ifdef OC_INCLUDE_GL_API
|
||||||
#include "graphics/gl_api.h"
|
#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 };
|
static oc_log_output oc_logDefaultOutput = { .kind = ORCA_LOG_OUTPUT_CONSOLE };
|
||||||
oc_log_output* OC_LOG_DEFAULT_OUTPUT = &oc_logDefaultOutput;
|
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,
|
int fileLen,
|
||||||
const char* file,
|
const char* file,
|
||||||
int functionLen,
|
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_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);
|
oc_arena_scope_end(tmp);
|
||||||
}
|
}
|
||||||
|
@ -86,8 +86,8 @@ void platform_log_push(oc_log_output* output,
|
||||||
// Assert/Abort
|
// 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_bridge_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_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, ...)
|
_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_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);
|
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_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);
|
oc_scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,4 +222,10 @@ ORCA_API u64 oc_file_size(oc_file file);
|
||||||
|
|
||||||
//TODO: Complete as needed...
|
//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_
|
#endif //__PLATFORM_IO_H_
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
|
||||||
#include "platform_io.h"
|
#include "platform_io.h"
|
||||||
|
#include "platform_io_dialog.h"
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// File stream read/write API
|
// 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
|
* @date: 11/06/2023
|
||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
|
#include "app/app.h"
|
||||||
#include "platform_io_internal.h"
|
#include "platform/platform_io_internal.h"
|
||||||
#include "platform_path.h"
|
#include "platform/platform_path.h"
|
||||||
|
|
||||||
oc_file_table oc_globalFileTable = { 0 };
|
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* oc_file_slot_alloc(oc_file_table* table)
|
||||||
{
|
{
|
||||||
oc_file_slot* slot = oc_list_pop_entry(&table->freeList, oc_file_slot, freeListElt);
|
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)
|
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);
|
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.h"
|
||||||
#include "platform_io.h"
|
#include "platform_io.h"
|
||||||
|
#include "platform_io_dialog.h"
|
||||||
|
|
||||||
#if OC_PLATFORM_MACOS || PLATFORM_LINUX
|
#if OC_PLATFORM_MACOS || PLATFORM_LINUX
|
||||||
typedef int oc_file_desc;
|
typedef int oc_file_desc;
|
||||||
|
@ -46,12 +47,22 @@ typedef struct oc_file_table
|
||||||
oc_list freeList;
|
oc_list freeList;
|
||||||
} oc_file_table;
|
} oc_file_table;
|
||||||
|
|
||||||
|
ORCA_API oc_file_table* oc_file_table_get_global();
|
||||||
|
|
||||||
oc_file_slot* oc_file_slot_alloc(oc_file_table* table);
|
oc_file_slot* oc_file_slot_alloc(oc_file_table* table);
|
||||||
void oc_file_slot_recycle(oc_file_table* table, oc_file_slot* slot);
|
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 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);
|
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
|
// 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)
|
oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements)
|
||||||
{
|
{
|
||||||
//TODO: check if elements have ending/begining '/' ?
|
//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);
|
return (res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,8 @@ oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath)
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(OC_PLATFORM_ORCA) || !OC_PLATFORM_ORCA
|
||||||
|
|
||||||
oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath)
|
oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath)
|
||||||
{
|
{
|
||||||
oc_str8_list list = { 0 };
|
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);
|
oc_scratch_end(scratch);
|
||||||
return (path);
|
return (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#ifndef __PLATFORM_PATH_H_
|
#ifndef __PLATFORM_PATH_H_
|
||||||
#define __PLATFORM_PATH_H_
|
#define __PLATFORM_PATH_H_
|
||||||
|
|
||||||
|
#include"platform.h"
|
||||||
#include "util/strings.h"
|
#include "util/strings.h"
|
||||||
|
|
||||||
/*NOTE:
|
/*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 oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath);
|
||||||
|
|
||||||
ORCA_API bool oc_path_is_absolute(oc_str8 path);
|
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_executable(oc_arena* arena);
|
||||||
ORCA_API oc_str8 oc_path_canonical(oc_arena* arena, oc_str8 path);
|
ORCA_API oc_str8 oc_path_canonical(oc_arena* arena, oc_str8 path);
|
||||||
|
|
||||||
// helper: gets the path from oc_path_executable() and appends relPath
|
// 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);
|
ORCA_API oc_str8 oc_path_executable_relative(oc_arena* arena, oc_str8 relPath);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif //__PLATFORM_PATH_H_
|
#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);
|
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 };
|
oc_io_cmp cmp = { 0 };
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ oc_io_error oc_io_raw_last_error()
|
||||||
return (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 };
|
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_arena_scope scratch = oc_scratch_begin_next(arena);
|
||||||
|
|
||||||
oc_str16 dirPathW = win32_path_from_handle_null_terminated(scratch.arena, dirFd);
|
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)
|
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_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)
|
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);
|
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 };
|
oc_io_cmp cmp = { 0 };
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
bool oc_path_is_absolute(oc_str8 path)
|
bool oc_path_is_absolute(oc_str8 path)
|
||||||
{
|
{
|
||||||
oc_arena_scope scratch = oc_scratch_begin();
|
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);
|
bool result = !PathIsRelativeW(pathW.ptr);
|
||||||
|
|
||||||
oc_scratch_end(scratch);
|
oc_scratch_end(scratch);
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include "win32_string_helpers.h"
|
#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 };
|
oc_str16 res = { 0 };
|
||||||
res.len = 1 + MultiByteToWideChar(CP_UTF8, 0, s.ptr, s.len, NULL, 0);
|
res.len = 1 + MultiByteToWideChar(CP_UTF8, 0, s.ptr, s.len, NULL, 0);
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#include "util/strings.h"
|
#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);
|
oc_str8 oc_win32_wide_to_utf8(oc_arena* arena, oc_str16 s);
|
||||||
|
|
||||||
#endif // __WIN32_STRING_HELPERS_H_
|
#endif // __WIN32_STRING_HELPERS_H_
|
||||||
|
|
159
src/runtime.c
159
src/runtime.c
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
oc_font orca_font_create(const char* resourcePath)
|
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));
|
oc_str8 fontPath = oc_path_executable_relative(oc_scratch(), OC_STR8(resourcePath));
|
||||||
|
|
||||||
FILE* fontFile = fopen(fontPath.ptr, "r");
|
FILE* fontFile = fopen(fontPath.ptr, "r");
|
||||||
|
@ -49,11 +49,6 @@ oc_font orca_font_create(const char* resourcePath)
|
||||||
return (font);
|
return (font);
|
||||||
}
|
}
|
||||||
|
|
||||||
oc_font oc_font_create_default()
|
|
||||||
{
|
|
||||||
return (orca_font_create("../resources/OpenSansLatinSubset.ttf"));
|
|
||||||
}
|
|
||||||
|
|
||||||
oc_runtime __orcaApp = { 0 };
|
oc_runtime __orcaApp = { 0 };
|
||||||
|
|
||||||
oc_runtime* oc_runtime_get()
|
oc_runtime* oc_runtime_get()
|
||||||
|
@ -61,43 +56,49 @@ oc_runtime* oc_runtime_get()
|
||||||
return (&__orcaApp);
|
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
|
oc_str8 mem = { 0 };
|
||||||
// header at the beginning of the block we give it.
|
u32 size = 0;
|
||||||
u64 bufferIndex = (u64)wasmPtr & 0xffffffff;
|
mem.ptr = (char*)m3_GetMemory(__orcaApp.env.m3Runtime, &size, 0);
|
||||||
u32 memSize = 0;
|
mem.len = size;
|
||||||
char* memory = (char*)m3_GetMemory(orca->runtime.m3Runtime, &memSize, 0);
|
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;
|
oc_abort_ext(file, function, line, "%s: %s (%s)", msg, res, errInfo.message);
|
||||||
return nativePtr;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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);
|
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,
|
int fileLen,
|
||||||
char* file,
|
char* file,
|
||||||
int functionLen,
|
int functionLen,
|
||||||
|
@ -231,8 +232,8 @@ void orca_surface_render_commands(oc_surface surface,
|
||||||
{
|
{
|
||||||
oc_runtime* app = &__orcaApp;
|
oc_runtime* app = &__orcaApp;
|
||||||
|
|
||||||
char* memBase = app->runtime.wasmMemory.ptr;
|
char* memBase = app->env.wasmMemory.ptr;
|
||||||
u32 memSize = app->runtime.wasmMemory.committed;
|
u32 memSize = app->env.wasmMemory.committed;
|
||||||
if(((char*)primitives > memBase)
|
if(((char*)primitives > memBase)
|
||||||
&& ((char*)primitives + primitiveCount * sizeof(oc_primitive) - memBase <= memSize)
|
&& ((char*)primitives + primitiveCount * sizeof(oc_primitive) - memBase <= memSize)
|
||||||
&& ((char*)elements > memBase)
|
&& ((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();
|
oc_base_allocator* allocator = oc_base_allocator_default();
|
||||||
runtime->wasmMemory.committed = 0;
|
runtime->wasmMemory.committed = 0;
|
||||||
runtime->wasmMemory.reserved = 4ULL << 30;
|
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/io_api_bind_gen.c"
|
||||||
#include "wasmbind/surface_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)
|
i32 orca_runloop(void* user)
|
||||||
{
|
{
|
||||||
oc_runtime* app = &__orcaApp;
|
oc_runtime* app = &__orcaApp;
|
||||||
|
|
||||||
oc_runtime_env_init(&app->runtime);
|
oc_wasm_env_init(&app->env);
|
||||||
|
|
||||||
//NOTE: loads wasm module
|
//NOTE: loads wasm module
|
||||||
const char* bundleNameCString = "module";
|
const char* bundleNameCString = "module";
|
||||||
|
@ -386,42 +371,42 @@ i32 orca_runloop(void* user)
|
||||||
u64 wasmSize = ftell(file);
|
u64 wasmSize = ftell(file);
|
||||||
rewind(file);
|
rewind(file);
|
||||||
|
|
||||||
app->runtime.wasmBytecode.len = wasmSize;
|
app->env.wasmBytecode.len = wasmSize;
|
||||||
app->runtime.wasmBytecode.ptr = oc_malloc_array(char, wasmSize);
|
app->env.wasmBytecode.ptr = oc_malloc_array(char, wasmSize);
|
||||||
fread(app->runtime.wasmBytecode.ptr, 1, app->runtime.wasmBytecode.len, file);
|
fread(app->env.wasmBytecode.ptr, 1, app->env.wasmBytecode.len, file);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
u32 stackSize = 65536;
|
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.
|
//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)
|
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)
|
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());
|
oc_arena_clear(oc_scratch());
|
||||||
|
|
||||||
//NOTE: bind orca APIs
|
//NOTE: bind orca APIs
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
err |= bindgen_link_core_api(app->runtime.m3Module);
|
err |= bindgen_link_core_api(app->env.m3Module);
|
||||||
err |= bindgen_link_surface_api(app->runtime.m3Module);
|
err |= bindgen_link_surface_api(app->env.m3Module);
|
||||||
err |= bindgen_link_clock_api(app->runtime.m3Module);
|
err |= bindgen_link_clock_api(app->env.m3Module);
|
||||||
err |= bindgen_link_io_api(app->runtime.m3Module);
|
err |= bindgen_link_io_api(app->env.m3Module);
|
||||||
err |= bindgen_link_gles_api(app->runtime.m3Module);
|
err |= bindgen_link_gles_api(app->env.m3Module);
|
||||||
err |= manual_link_gles_api(app->runtime.m3Module);
|
err |= manual_link_gles_api(app->env.m3Module);
|
||||||
|
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
|
@ -429,10 +414,10 @@ i32 orca_runloop(void* user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//NOTE: compile
|
//NOTE: compile
|
||||||
res = m3_CompileModule(app->runtime.m3Module);
|
res = m3_CompileModule(app->env.m3Module);
|
||||||
if(res)
|
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.
|
//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];
|
const oc_export_desc* desc = &OC_EXPORT_DESC[i];
|
||||||
IM3Function handler = 0;
|
IM3Function handler = 0;
|
||||||
m3_FindFunction(&handler, app->runtime.m3Runtime, desc->name.ptr);
|
m3_FindFunction(&handler, app->env.m3Runtime, desc->name.ptr);
|
||||||
|
|
||||||
if(handler)
|
if(handler)
|
||||||
{
|
{
|
||||||
|
@ -481,7 +466,7 @@ i32 orca_runloop(void* user)
|
||||||
|
|
||||||
if(checked)
|
if(checked)
|
||||||
{
|
{
|
||||||
app->runtime.exports[i] = handler;
|
app->env.exports[i] = handler;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -491,8 +476,8 @@ i32 orca_runloop(void* user)
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: get location of the raw event slot
|
//NOTE: get location of the raw event slot
|
||||||
IM3Global rawEventGlobal = m3_FindGlobal(app->runtime.m3Module, "oc_rawEvent");
|
IM3Global rawEventGlobal = m3_FindGlobal(app->env.m3Module, "oc_rawEvent");
|
||||||
app->runtime.rawEventOffset = (u32)rawEventGlobal->intValue;
|
app->env.rawEventOffset = (u32)rawEventGlobal->intValue;
|
||||||
|
|
||||||
//NOTE: preopen the app local root dir
|
//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,
|
.open.rights = OC_FILE_ACCESS_READ | OC_FILE_ACCESS_WRITE,
|
||||||
.size = localRootPath.len,
|
.size = localRootPath.len,
|
||||||
.buffer = localRootPath.ptr };
|
.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;
|
app->rootDir = cmp.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
IM3Function* exports = app->runtime.exports;
|
IM3Function* exports = app->env.exports;
|
||||||
|
|
||||||
//NOTE: call init handler
|
//NOTE: call init handler
|
||||||
if(exports[OC_EXPORT_ON_INIT])
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_ON_INIT], 0, 0);
|
||||||
if(res)
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args);
|
||||||
if(res)
|
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])
|
if(exports[OC_EXPORT_RAW_EVENT])
|
||||||
{
|
{
|
||||||
#ifndef M3_BIG_ENDIAN
|
#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));
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_RAW_EVENT], 1, args);
|
||||||
if(res)
|
if(res)
|
||||||
{
|
{
|
||||||
ORCA_WASM3_ABORT(app->runtime.m3Runtime, res, "Runtime error");
|
ORCA_WASM3_ABORT(app->env.m3Runtime, res, "Runtime error");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
oc_log_error("oc_on_raw_event() is not supported on big endian platforms");
|
oc_log_error("oc_on_raw_event() is not supported on big endian platforms");
|
||||||
|
@ -581,7 +566,7 @@ i32 orca_runloop(void* user)
|
||||||
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args);
|
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_RESIZE], 2, args);
|
||||||
if(res)
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_DOWN], 1, args);
|
||||||
if(res)
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_UP], 1, args);
|
||||||
if(res)
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_MOUSE_MOVE], 4, args);
|
||||||
if(res)
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_KEY_DOWN], 1, args);
|
||||||
if(res)
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_KEY_UP], 1, args);
|
||||||
if(res)
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_FRAME_REFRESH], 0, 0);
|
||||||
if(res)
|
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);
|
M3Result res = m3_Call(exports[OC_EXPORT_TERMINATE], 0, 0);
|
||||||
if(res)
|
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_REFRESH, "oc_on_frame_refresh", "", "") \
|
||||||
X(OC_EXPORT_FRAME_RESIZE, "oc_on_resize", "", "ii") \
|
X(OC_EXPORT_FRAME_RESIZE, "oc_on_resize", "", "ii") \
|
||||||
X(OC_EXPORT_RAW_EVENT, "oc_on_raw_event", "", "i") \
|
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
|
typedef enum
|
||||||
{
|
{
|
||||||
|
@ -53,18 +54,18 @@ const oc_export_desc OC_EXPORT_DESC[] = {
|
||||||
#undef OC_STR8_LIT
|
#undef OC_STR8_LIT
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct wasm_memory
|
typedef struct oc_wasm_memory
|
||||||
{
|
{
|
||||||
char* ptr;
|
char* ptr;
|
||||||
u64 reserved;
|
u64 reserved;
|
||||||
u64 committed;
|
u64 committed;
|
||||||
|
|
||||||
} wasm_memory;
|
} oc_wasm_memory;
|
||||||
|
|
||||||
typedef struct oc_runtime_env
|
typedef struct oc_wasm_env
|
||||||
{
|
{
|
||||||
oc_str8 wasmBytecode;
|
oc_str8 wasmBytecode;
|
||||||
wasm_memory wasmMemory;
|
oc_wasm_memory wasmMemory;
|
||||||
|
|
||||||
// wasm3 data
|
// wasm3 data
|
||||||
IM3Environment m3Env;
|
IM3Environment m3Env;
|
||||||
|
@ -73,7 +74,7 @@ typedef struct oc_runtime_env
|
||||||
IM3Function exports[OC_EXPORT_COUNT];
|
IM3Function exports[OC_EXPORT_COUNT];
|
||||||
u32 rawEventOffset;
|
u32 rawEventOffset;
|
||||||
|
|
||||||
} oc_runtime_env;
|
} oc_wasm_env;
|
||||||
|
|
||||||
typedef struct log_entry
|
typedef struct log_entry
|
||||||
{
|
{
|
||||||
|
@ -113,19 +114,20 @@ typedef struct oc_runtime
|
||||||
{
|
{
|
||||||
bool quit;
|
bool quit;
|
||||||
oc_window window;
|
oc_window window;
|
||||||
|
oc_debug_overlay debugOverlay;
|
||||||
|
|
||||||
oc_file_table fileTable;
|
oc_file_table fileTable;
|
||||||
oc_file rootDir;
|
oc_file rootDir;
|
||||||
|
|
||||||
oc_runtime_env runtime;
|
oc_wasm_env env;
|
||||||
|
|
||||||
oc_debug_overlay debugOverlay;
|
|
||||||
|
|
||||||
} oc_runtime;
|
} oc_runtime;
|
||||||
|
|
||||||
oc_runtime* oc_runtime_get();
|
oc_runtime* oc_runtime_get(void);
|
||||||
oc_runtime_env* oc_runtime_env_get();
|
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_
|
#endif //__RUNTIME_H_
|
||||||
|
|
110
src/runtime_io.c
110
src/runtime_io.c
|
@ -7,15 +7,17 @@
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
#include "platform/platform_io_internal.h"
|
#include "platform/platform_io_internal.h"
|
||||||
#include "runtime.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_runtime* orca = oc_runtime_get();
|
||||||
|
|
||||||
oc_io_cmp cmp = { 0 };
|
oc_io_cmp cmp = { 0 };
|
||||||
oc_io_req req = *wasmReq;
|
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)
|
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;
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -39,3 +41,105 @@ oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq)
|
||||||
|
|
||||||
return (cmp);
|
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.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)
|
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_allocator* allocator = oc_base_allocator_default();
|
||||||
oc_base_release(allocator, memory->ptr, memory->reserved);
|
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)
|
extern u32 oc_mem_grow(u64 size)
|
||||||
{
|
{
|
||||||
oc_runtime_env* runtime = oc_runtime_env_get();
|
oc_wasm_env* env = oc_runtime_get_env();
|
||||||
wasm_memory* memory = &runtime->wasmMemory;
|
oc_wasm_memory* memory = &env->wasmMemory;
|
||||||
|
|
||||||
size = oc_align_up_pow2(size, d_m3MemPageSize);
|
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;
|
u32 addr = memory->committed;
|
||||||
|
|
||||||
//NOTE: call resize memory, which will call our custom resize callback... this is a bit involved because
|
//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
|
// 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);
|
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_str8 mem = oc_runtime_get_wasm_memory();
|
||||||
OC_DEBUG_ASSERT(offset < header->length, "Wasm offset exceeds memory length");
|
OC_ASSERT(addr + size < mem.len, "Object overflows wasm memory");
|
||||||
return memory->ptr + sizeof(M3MemoryHeader) + offset;
|
|
||||||
|
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;
|
bool draw = true;
|
||||||
|
|
||||||
{
|
{
|
||||||
oc_rect clip = oc_clip();
|
oc_rect clip = oc_clip_top();
|
||||||
oc_rect expRect = {
|
oc_rect expRect = {
|
||||||
box->rect.x - 0.5 * style->borderSize,
|
box->rect.x - 0.5 * style->borderSize,
|
||||||
box->rect.y - 0.5 * style->borderSize,
|
box->rect.y - 0.5 * style->borderSize,
|
||||||
|
|
374
src/ui/ui.h
374
src/ui/ui.h
|
@ -15,31 +15,30 @@
|
||||||
#include "util/typedefs.h"
|
#include "util/typedefs.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct oc_ui_key
|
typedef struct oc_ui_key
|
||||||
{
|
{
|
||||||
u64 hash;
|
u64 hash;
|
||||||
} oc_ui_key;
|
} oc_ui_key;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
OC_UI_AXIS_X,
|
OC_UI_AXIS_X,
|
||||||
OC_UI_AXIS_Y,
|
OC_UI_AXIS_Y,
|
||||||
OC_UI_AXIS_COUNT
|
OC_UI_AXIS_COUNT
|
||||||
} oc_ui_axis;
|
} oc_ui_axis;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
OC_UI_ALIGN_START,
|
OC_UI_ALIGN_START,
|
||||||
OC_UI_ALIGN_END,
|
OC_UI_ALIGN_END,
|
||||||
OC_UI_ALIGN_CENTER,
|
OC_UI_ALIGN_CENTER,
|
||||||
} oc_ui_align;
|
} oc_ui_align;
|
||||||
|
|
||||||
typedef union oc_ui_layout_align
|
typedef union oc_ui_layout_align
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
oc_ui_align x;
|
oc_ui_align x;
|
||||||
|
@ -47,10 +46,10 @@ extern "C"
|
||||||
};
|
};
|
||||||
|
|
||||||
oc_ui_align c[OC_UI_AXIS_COUNT];
|
oc_ui_align c[OC_UI_AXIS_COUNT];
|
||||||
} oc_ui_layout_align;
|
} oc_ui_layout_align;
|
||||||
|
|
||||||
typedef struct oc_ui_layout
|
typedef struct oc_ui_layout
|
||||||
{
|
{
|
||||||
oc_ui_axis axis;
|
oc_ui_axis axis;
|
||||||
f32 spacing;
|
f32 spacing;
|
||||||
|
|
||||||
|
@ -67,27 +66,27 @@ extern "C"
|
||||||
|
|
||||||
oc_ui_layout_align align;
|
oc_ui_layout_align align;
|
||||||
|
|
||||||
} oc_ui_layout;
|
} oc_ui_layout;
|
||||||
|
|
||||||
typedef enum oc_ui_size_kind
|
typedef enum oc_ui_size_kind
|
||||||
{
|
{
|
||||||
OC_UI_SIZE_TEXT,
|
OC_UI_SIZE_TEXT,
|
||||||
OC_UI_SIZE_PIXELS,
|
OC_UI_SIZE_PIXELS,
|
||||||
OC_UI_SIZE_CHILDREN,
|
OC_UI_SIZE_CHILDREN,
|
||||||
OC_UI_SIZE_PARENT,
|
OC_UI_SIZE_PARENT,
|
||||||
OC_UI_SIZE_PARENT_MINUS_PIXELS,
|
OC_UI_SIZE_PARENT_MINUS_PIXELS,
|
||||||
|
|
||||||
} oc_ui_size_kind;
|
} oc_ui_size_kind;
|
||||||
|
|
||||||
typedef struct oc_ui_size
|
typedef struct oc_ui_size
|
||||||
{
|
{
|
||||||
oc_ui_size_kind kind;
|
oc_ui_size_kind kind;
|
||||||
f32 value;
|
f32 value;
|
||||||
f32 relax;
|
f32 relax;
|
||||||
} oc_ui_size;
|
} oc_ui_size;
|
||||||
|
|
||||||
typedef union oc_ui_box_size
|
typedef union oc_ui_box_size
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
oc_ui_size width;
|
oc_ui_size width;
|
||||||
|
@ -95,10 +94,10 @@ extern "C"
|
||||||
};
|
};
|
||||||
|
|
||||||
oc_ui_size c[OC_UI_AXIS_COUNT];
|
oc_ui_size c[OC_UI_AXIS_COUNT];
|
||||||
} oc_ui_box_size;
|
} oc_ui_box_size;
|
||||||
|
|
||||||
typedef union oc_ui_box_floating
|
typedef union oc_ui_box_floating
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool x;
|
bool x;
|
||||||
|
@ -106,14 +105,14 @@ extern "C"
|
||||||
};
|
};
|
||||||
|
|
||||||
bool c[OC_UI_AXIS_COUNT];
|
bool c[OC_UI_AXIS_COUNT];
|
||||||
} oc_ui_box_floating;
|
} oc_ui_box_floating;
|
||||||
|
|
||||||
//NOTE: flags for axis-dependent properties (e.g. OC_UI_STYLE_FLOAT_X/Y) need to be consecutive bits
|
//NOTE: flags for axis-dependent properties (e.g. OC_UI_STYLE_FLOAT_X/Y) need to be consecutive bits
|
||||||
// in order to play well with axis agnostic functions
|
// in order to play well with axis agnostic functions
|
||||||
typedef u64 oc_ui_style_mask;
|
typedef u64 oc_ui_style_mask;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
OC_UI_STYLE_NONE = 0,
|
OC_UI_STYLE_NONE = 0,
|
||||||
OC_UI_STYLE_SIZE_WIDTH = 1 << 1,
|
OC_UI_STYLE_SIZE_WIDTH = 1 << 1,
|
||||||
OC_UI_STYLE_SIZE_HEIGHT = 1 << 2,
|
OC_UI_STYLE_SIZE_HEIGHT = 1 << 2,
|
||||||
|
@ -157,10 +156,10 @@ extern "C"
|
||||||
| OC_UI_STYLE_FONT_SIZE
|
| OC_UI_STYLE_FONT_SIZE
|
||||||
| OC_UI_STYLE_ANIMATION_TIME
|
| OC_UI_STYLE_ANIMATION_TIME
|
||||||
| OC_UI_STYLE_ANIMATION_MASK,
|
| OC_UI_STYLE_ANIMATION_MASK,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct oc_ui_style
|
typedef struct oc_ui_style
|
||||||
{
|
{
|
||||||
oc_ui_box_size size;
|
oc_ui_box_size size;
|
||||||
oc_ui_layout layout;
|
oc_ui_layout layout;
|
||||||
oc_ui_box_floating floating;
|
oc_ui_box_floating floating;
|
||||||
|
@ -174,10 +173,10 @@ extern "C"
|
||||||
f32 roundness;
|
f32 roundness;
|
||||||
f32 animationTime;
|
f32 animationTime;
|
||||||
oc_ui_style_mask animationMask;
|
oc_ui_style_mask animationMask;
|
||||||
} oc_ui_style;
|
} oc_ui_style;
|
||||||
|
|
||||||
typedef struct oc_ui_theme
|
typedef struct oc_ui_theme
|
||||||
{
|
{
|
||||||
oc_color white;
|
oc_color white;
|
||||||
oc_color primary;
|
oc_color primary;
|
||||||
oc_color primaryHover;
|
oc_color primaryHover;
|
||||||
|
@ -194,15 +193,15 @@ extern "C"
|
||||||
oc_color text1;
|
oc_color text1;
|
||||||
oc_color text2;
|
oc_color text2;
|
||||||
oc_color text3;
|
oc_color text3;
|
||||||
} oc_ui_theme;
|
} oc_ui_theme;
|
||||||
|
|
||||||
typedef struct oc_ui_tag
|
typedef struct oc_ui_tag
|
||||||
{
|
{
|
||||||
u64 hash;
|
u64 hash;
|
||||||
} oc_ui_tag;
|
} oc_ui_tag;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
OC_UI_SEL_ANY,
|
OC_UI_SEL_ANY,
|
||||||
OC_UI_SEL_OWNER,
|
OC_UI_SEL_OWNER,
|
||||||
OC_UI_SEL_TEXT,
|
OC_UI_SEL_TEXT,
|
||||||
|
@ -210,27 +209,27 @@ extern "C"
|
||||||
OC_UI_SEL_STATUS,
|
OC_UI_SEL_STATUS,
|
||||||
OC_UI_SEL_KEY,
|
OC_UI_SEL_KEY,
|
||||||
//...
|
//...
|
||||||
} oc_ui_selector_kind;
|
} oc_ui_selector_kind;
|
||||||
|
|
||||||
typedef u8 oc_ui_status;
|
typedef u8 oc_ui_status;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
OC_UI_NONE = 0,
|
OC_UI_NONE = 0,
|
||||||
OC_UI_HOVER = 1 << 1,
|
OC_UI_HOVER = 1 << 1,
|
||||||
OC_UI_ACTIVE = 1 << 2,
|
OC_UI_ACTIVE = 1 << 2,
|
||||||
OC_UI_DRAGGING = 1 << 3,
|
OC_UI_DRAGGING = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
OC_UI_SEL_DESCENDANT = 0,
|
OC_UI_SEL_DESCENDANT = 0,
|
||||||
OC_UI_SEL_AND = 1,
|
OC_UI_SEL_AND = 1,
|
||||||
//...
|
//...
|
||||||
} oc_ui_selector_op;
|
} oc_ui_selector_op;
|
||||||
|
|
||||||
typedef struct oc_ui_selector
|
typedef struct oc_ui_selector
|
||||||
{
|
{
|
||||||
oc_list_elt listElt;
|
oc_list_elt listElt;
|
||||||
oc_ui_selector_kind kind;
|
oc_ui_selector_kind kind;
|
||||||
oc_ui_selector_op op;
|
oc_ui_selector_op op;
|
||||||
|
@ -243,17 +242,17 @@ extern "C"
|
||||||
oc_ui_status status;
|
oc_ui_status status;
|
||||||
//...
|
//...
|
||||||
};
|
};
|
||||||
} oc_ui_selector;
|
} oc_ui_selector;
|
||||||
|
|
||||||
typedef struct oc_ui_pattern
|
typedef struct oc_ui_pattern
|
||||||
{
|
{
|
||||||
oc_list l;
|
oc_list l;
|
||||||
} oc_ui_pattern;
|
} oc_ui_pattern;
|
||||||
|
|
||||||
typedef struct oc_ui_box oc_ui_box;
|
typedef struct oc_ui_box oc_ui_box;
|
||||||
|
|
||||||
typedef struct oc_ui_style_rule
|
typedef struct oc_ui_style_rule
|
||||||
{
|
{
|
||||||
oc_list_elt boxElt;
|
oc_list_elt boxElt;
|
||||||
oc_list_elt buildElt;
|
oc_list_elt buildElt;
|
||||||
oc_list_elt tmpElt;
|
oc_list_elt tmpElt;
|
||||||
|
@ -262,10 +261,10 @@ extern "C"
|
||||||
oc_ui_pattern pattern;
|
oc_ui_pattern pattern;
|
||||||
oc_ui_style_mask mask;
|
oc_ui_style_mask mask;
|
||||||
oc_ui_style* style;
|
oc_ui_style* style;
|
||||||
} oc_ui_style_rule;
|
} oc_ui_style_rule;
|
||||||
|
|
||||||
typedef struct oc_ui_sig
|
typedef struct oc_ui_sig
|
||||||
{
|
{
|
||||||
oc_ui_box* box;
|
oc_ui_box* box;
|
||||||
|
|
||||||
oc_vec2 mouse;
|
oc_vec2 mouse;
|
||||||
|
@ -281,12 +280,12 @@ extern "C"
|
||||||
bool dragging;
|
bool dragging;
|
||||||
bool hovering;
|
bool hovering;
|
||||||
|
|
||||||
} oc_ui_sig;
|
} oc_ui_sig;
|
||||||
|
|
||||||
typedef void (*oc_ui_box_draw_proc)(oc_ui_box* box, void* data);
|
typedef void (*oc_ui_box_draw_proc)(oc_ui_box* box, void* data);
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
OC_UI_FLAG_CLICKABLE = (1 << 0),
|
OC_UI_FLAG_CLICKABLE = (1 << 0),
|
||||||
OC_UI_FLAG_SCROLL_WHEEL_X = (1 << 1),
|
OC_UI_FLAG_SCROLL_WHEEL_X = (1 << 1),
|
||||||
OC_UI_FLAG_SCROLL_WHEEL_Y = (1 << 2),
|
OC_UI_FLAG_SCROLL_WHEEL_Y = (1 << 2),
|
||||||
|
@ -305,10 +304,10 @@ extern "C"
|
||||||
OC_UI_FLAG_DRAW_PROC = (1 << 13),
|
OC_UI_FLAG_DRAW_PROC = (1 << 13),
|
||||||
|
|
||||||
OC_UI_FLAG_OVERLAY = (1 << 14),
|
OC_UI_FLAG_OVERLAY = (1 << 14),
|
||||||
} oc_ui_flags;
|
} oc_ui_flags;
|
||||||
|
|
||||||
struct oc_ui_box
|
struct oc_ui_box
|
||||||
{
|
{
|
||||||
// hierarchy
|
// hierarchy
|
||||||
oc_list_elt listElt;
|
oc_list_elt listElt;
|
||||||
oc_list children;
|
oc_list children;
|
||||||
|
@ -359,28 +358,28 @@ extern "C"
|
||||||
// animation data
|
// animation data
|
||||||
f32 hotTransition;
|
f32 hotTransition;
|
||||||
f32 activeTransition;
|
f32 activeTransition;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// context
|
// context
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
OC_UI_MAX_INPUT_CHAR_PER_FRAME = 64
|
OC_UI_MAX_INPUT_CHAR_PER_FRAME = 64
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct oc_ui_input_text
|
typedef struct oc_ui_input_text
|
||||||
{
|
{
|
||||||
u8 count;
|
u8 count;
|
||||||
oc_utf32 codePoints[OC_UI_MAX_INPUT_CHAR_PER_FRAME];
|
oc_utf32 codePoints[OC_UI_MAX_INPUT_CHAR_PER_FRAME];
|
||||||
|
|
||||||
} oc_ui_input_text;
|
} oc_ui_input_text;
|
||||||
|
|
||||||
typedef struct oc_ui_stack_elt oc_ui_stack_elt;
|
typedef struct oc_ui_stack_elt oc_ui_stack_elt;
|
||||||
|
|
||||||
struct oc_ui_stack_elt
|
struct oc_ui_stack_elt
|
||||||
{
|
{
|
||||||
oc_ui_stack_elt* parent;
|
oc_ui_stack_elt* parent;
|
||||||
|
|
||||||
union
|
union
|
||||||
|
@ -389,21 +388,21 @@ extern "C"
|
||||||
oc_ui_size size;
|
oc_ui_size size;
|
||||||
oc_rect clip;
|
oc_rect clip;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct oc_ui_tag_elt
|
typedef struct oc_ui_tag_elt
|
||||||
{
|
{
|
||||||
oc_list_elt listElt;
|
oc_list_elt listElt;
|
||||||
oc_ui_tag tag;
|
oc_ui_tag tag;
|
||||||
} oc_ui_tag_elt;
|
} oc_ui_tag_elt;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
OC_UI_BOX_MAP_BUCKET_COUNT = 1024
|
OC_UI_BOX_MAP_BUCKET_COUNT = 1024
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct oc_ui_context
|
typedef struct oc_ui_context
|
||||||
{
|
{
|
||||||
bool init;
|
bool init;
|
||||||
|
|
||||||
oc_input_state input;
|
oc_input_state input;
|
||||||
|
@ -435,104 +434,104 @@ extern "C"
|
||||||
i32 editFirstDisplayedChar;
|
i32 editFirstDisplayedChar;
|
||||||
f64 editCursorBlinkStart;
|
f64 editCursorBlinkStart;
|
||||||
|
|
||||||
} oc_ui_context;
|
} oc_ui_context;
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// UI context initialization and frame cycle
|
// UI context initialization and frame cycle
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
ORCA_API void oc_ui_init(oc_ui_context* context);
|
ORCA_API void oc_ui_init(oc_ui_context* context);
|
||||||
ORCA_API oc_ui_context* oc_ui_get_context(void);
|
ORCA_API oc_ui_context* oc_ui_get_context(void);
|
||||||
ORCA_API void oc_ui_set_context(oc_ui_context* context);
|
ORCA_API void oc_ui_set_context(oc_ui_context* context);
|
||||||
|
|
||||||
ORCA_API void oc_ui_process_event(oc_event* event);
|
ORCA_API void oc_ui_process_event(oc_event* event);
|
||||||
ORCA_API void oc_ui_begin_frame(oc_vec2 size, oc_ui_style* defaultStyle, oc_ui_style_mask mask);
|
ORCA_API void oc_ui_begin_frame(oc_vec2 size, oc_ui_style* defaultStyle, oc_ui_style_mask mask);
|
||||||
ORCA_API void oc_ui_end_frame(void);
|
ORCA_API void oc_ui_end_frame(void);
|
||||||
ORCA_API void oc_ui_draw(void);
|
ORCA_API void oc_ui_draw(void);
|
||||||
|
|
||||||
#define oc_ui_frame(size, style, mask) oc_defer_loop(oc_ui_begin_frame((size), (style), (mask)), oc_ui_end_frame())
|
#define oc_ui_frame(size, style, mask) oc_defer_loop(oc_ui_begin_frame((size), (style), (mask)), oc_ui_end_frame())
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Box keys
|
// Box keys
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
ORCA_API oc_ui_key oc_ui_key_make_str8(oc_str8 string);
|
ORCA_API oc_ui_key oc_ui_key_make_str8(oc_str8 string);
|
||||||
ORCA_API oc_ui_key oc_ui_key_make_path(oc_str8_list path);
|
ORCA_API oc_ui_key oc_ui_key_make_path(oc_str8_list path);
|
||||||
|
|
||||||
ORCA_API oc_ui_box* oc_ui_box_lookup_key(oc_ui_key key);
|
ORCA_API oc_ui_box* oc_ui_box_lookup_key(oc_ui_key key);
|
||||||
ORCA_API oc_ui_box* oc_ui_box_lookup_str8(oc_str8 string);
|
ORCA_API oc_ui_box* oc_ui_box_lookup_str8(oc_str8 string);
|
||||||
|
|
||||||
// C-string helper
|
// C-string helper
|
||||||
#define oc_ui_key_make(s) oc_ui_key_make_str8(OC_STR8(s))
|
#define oc_ui_key_make(s) oc_ui_key_make_str8(OC_STR8(s))
|
||||||
#define oc_ui_box_lookup(s) oc_ui_box_lookup_str8(OC_STR8(s))
|
#define oc_ui_box_lookup(s) oc_ui_box_lookup_str8(OC_STR8(s))
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Box hierarchy building
|
// Box hierarchy building
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
ORCA_API oc_ui_box* oc_ui_box_make_str8(oc_str8 string, oc_ui_flags flags);
|
ORCA_API oc_ui_box* oc_ui_box_make_str8(oc_str8 string, oc_ui_flags flags);
|
||||||
ORCA_API oc_ui_box* oc_ui_box_begin_str8(oc_str8 string, oc_ui_flags flags);
|
ORCA_API oc_ui_box* oc_ui_box_begin_str8(oc_str8 string, oc_ui_flags flags);
|
||||||
|
|
||||||
ORCA_API oc_ui_box* oc_ui_box_end(void);
|
ORCA_API oc_ui_box* oc_ui_box_end(void);
|
||||||
#define oc_ui_container(name, flags) oc_defer_loop(oc_ui_box_begin(name, flags), oc_ui_box_end())
|
#define oc_ui_container(name, flags) oc_defer_loop(oc_ui_box_begin(name, flags), oc_ui_box_end())
|
||||||
#define oc_ui_container_str8(name, flags) oc_defer_loop(oc_ui_box_begin_str8(name, flags), oc_ui_box_end())
|
#define oc_ui_container_str8(name, flags) oc_defer_loop(oc_ui_box_begin_str8(name, flags), oc_ui_box_end())
|
||||||
|
|
||||||
ORCA_API void oc_ui_box_push(oc_ui_box* box);
|
ORCA_API void oc_ui_box_push(oc_ui_box* box);
|
||||||
ORCA_API void oc_ui_box_pop(void);
|
ORCA_API void oc_ui_box_pop(void);
|
||||||
ORCA_API oc_ui_box* oc_ui_box_top(void);
|
ORCA_API oc_ui_box* oc_ui_box_top(void);
|
||||||
|
|
||||||
ORCA_API void oc_ui_box_set_draw_proc(oc_ui_box* box, oc_ui_box_draw_proc proc, void* data);
|
ORCA_API void oc_ui_box_set_draw_proc(oc_ui_box* box, oc_ui_box_draw_proc proc, void* data);
|
||||||
|
|
||||||
// C-string helpers
|
// C-string helpers
|
||||||
#define oc_ui_box_lookup(s) oc_ui_box_lookup_str8(OC_STR8(s))
|
#define oc_ui_box_lookup(s) oc_ui_box_lookup_str8(OC_STR8(s))
|
||||||
#define oc_ui_box_make(s, flags) oc_ui_box_make_str8(OC_STR8(s), flags)
|
#define oc_ui_box_make(s, flags) oc_ui_box_make_str8(OC_STR8(s), flags)
|
||||||
#define oc_ui_box_begin(s, flags) oc_ui_box_begin_str8(OC_STR8(s), flags)
|
#define oc_ui_box_begin(s, flags) oc_ui_box_begin_str8(OC_STR8(s), flags)
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Box status and signals
|
// Box status and signals
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
ORCA_API bool oc_ui_box_closed(oc_ui_box* box);
|
ORCA_API bool oc_ui_box_closed(oc_ui_box* box);
|
||||||
ORCA_API void oc_ui_box_set_closed(oc_ui_box* box, bool closed);
|
ORCA_API void oc_ui_box_set_closed(oc_ui_box* box, bool closed);
|
||||||
|
|
||||||
ORCA_API bool oc_ui_box_active(oc_ui_box* box);
|
ORCA_API bool oc_ui_box_active(oc_ui_box* box);
|
||||||
ORCA_API void oc_ui_box_activate(oc_ui_box* box);
|
ORCA_API void oc_ui_box_activate(oc_ui_box* box);
|
||||||
ORCA_API void oc_ui_box_deactivate(oc_ui_box* box);
|
ORCA_API void oc_ui_box_deactivate(oc_ui_box* box);
|
||||||
|
|
||||||
ORCA_API bool oc_ui_box_hot(oc_ui_box* box);
|
ORCA_API bool oc_ui_box_hot(oc_ui_box* box);
|
||||||
ORCA_API void oc_ui_box_set_hot(oc_ui_box* box, bool hot);
|
ORCA_API void oc_ui_box_set_hot(oc_ui_box* box, bool hot);
|
||||||
|
|
||||||
ORCA_API oc_ui_sig oc_ui_box_sig(oc_ui_box* box);
|
ORCA_API oc_ui_sig oc_ui_box_sig(oc_ui_box* box);
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Tagging
|
// Tagging
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
ORCA_API oc_ui_tag oc_ui_tag_make_str8(oc_str8 string);
|
ORCA_API oc_ui_tag oc_ui_tag_make_str8(oc_str8 string);
|
||||||
ORCA_API void oc_ui_tag_box_str8(oc_ui_box* box, oc_str8 string);
|
ORCA_API void oc_ui_tag_box_str8(oc_ui_box* box, oc_str8 string);
|
||||||
ORCA_API void oc_ui_tag_next_str8(oc_str8 string);
|
ORCA_API void oc_ui_tag_next_str8(oc_str8 string);
|
||||||
|
|
||||||
// C-string helpers
|
// C-string helpers
|
||||||
#define oc_ui_tag_make(s) oc_ui_tag_make_str8(OC_STR8(s))
|
#define oc_ui_tag_make(s) oc_ui_tag_make_str8(OC_STR8(s))
|
||||||
#define oc_ui_tag_box(b, s) oc_ui_tag_box_str8(b, OC_STR8(s))
|
#define oc_ui_tag_box(b, s) oc_ui_tag_box_str8(b, OC_STR8(s))
|
||||||
#define oc_ui_tag_next(s) oc_ui_tag_next_str8(OC_STR8(s))
|
#define oc_ui_tag_next(s) oc_ui_tag_next_str8(OC_STR8(s))
|
||||||
|
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
// Styling
|
// Styling
|
||||||
//-------------------------------------------------------------------------------------
|
//-------------------------------------------------------------------------------------
|
||||||
//NOTE: styling API
|
//NOTE: styling API
|
||||||
//WARN: You can use a pattern in multiple rules, but be aware that a pattern is references an underlying list of selectors,
|
//WARN: You can use a pattern in multiple rules, but be aware that a pattern is references an underlying list of selectors,
|
||||||
// hence pushing to a pattern also modifies rules in which the pattern was previously used!
|
// hence pushing to a pattern also modifies rules in which the pattern was previously used!
|
||||||
ORCA_API void oc_ui_apply_style_with_mask(oc_ui_style* dst, oc_ui_style* src, oc_ui_style_mask mask);
|
ORCA_API void oc_ui_apply_style_with_mask(oc_ui_style* dst, oc_ui_style* src, oc_ui_style_mask mask);
|
||||||
|
|
||||||
ORCA_API void oc_ui_pattern_push(oc_arena* arena, oc_ui_pattern* pattern, oc_ui_selector selector);
|
ORCA_API void oc_ui_pattern_push(oc_arena* arena, oc_ui_pattern* pattern, oc_ui_selector selector);
|
||||||
ORCA_API oc_ui_pattern oc_ui_pattern_all(void);
|
ORCA_API oc_ui_pattern oc_ui_pattern_all(void);
|
||||||
ORCA_API oc_ui_pattern oc_ui_pattern_owner(void);
|
ORCA_API oc_ui_pattern oc_ui_pattern_owner(void);
|
||||||
|
|
||||||
ORCA_API void oc_ui_style_next(oc_ui_style* style, oc_ui_style_mask mask);
|
ORCA_API void oc_ui_style_next(oc_ui_style* style, oc_ui_style_mask mask);
|
||||||
ORCA_API void oc_ui_style_match_before(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask);
|
ORCA_API void oc_ui_style_match_before(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask);
|
||||||
ORCA_API void oc_ui_style_match_after(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask);
|
ORCA_API void oc_ui_style_match_after(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask);
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Basic widget helpers
|
// Basic widget helpers
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
OC_UI_STYLE_TAG_USER_MAX = 1 << 16,
|
OC_UI_STYLE_TAG_USER_MAX = 1 << 16,
|
||||||
OC_UI_STYLE_TAG_LABEL,
|
OC_UI_STYLE_TAG_LABEL,
|
||||||
OC_UI_STYLE_TAG_BUTTON,
|
OC_UI_STYLE_TAG_BUTTON,
|
||||||
|
@ -540,51 +539,50 @@ extern "C"
|
||||||
OC_UI_STYLE_TAG_PANEL,
|
OC_UI_STYLE_TAG_PANEL,
|
||||||
OC_UI_STYLE_TAG_TOOLTIP,
|
OC_UI_STYLE_TAG_TOOLTIP,
|
||||||
OC_UI_STYLE_TAG_MENU
|
OC_UI_STYLE_TAG_MENU
|
||||||
};
|
};
|
||||||
|
|
||||||
ORCA_API oc_ui_sig oc_ui_label(const char* label);
|
ORCA_API oc_ui_sig oc_ui_label(const char* label);
|
||||||
ORCA_API oc_ui_sig oc_ui_label_str8(oc_str8 label);
|
ORCA_API oc_ui_sig oc_ui_label_str8(oc_str8 label);
|
||||||
|
|
||||||
ORCA_API oc_ui_sig oc_ui_button(const char* label);
|
ORCA_API oc_ui_sig oc_ui_button(const char* label);
|
||||||
ORCA_API oc_ui_sig oc_ui_checkbox(const char* name, bool* checked);
|
ORCA_API oc_ui_sig oc_ui_checkbox(const char* name, bool* checked);
|
||||||
ORCA_API oc_ui_box* oc_ui_slider(const char* label, f32* value);
|
ORCA_API oc_ui_box* oc_ui_slider(const char* label, f32* value);
|
||||||
ORCA_API oc_ui_box* oc_ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue);
|
ORCA_API oc_ui_box* oc_ui_scrollbar(const char* label, f32 thumbRatio, f32* scrollValue);
|
||||||
|
ORCA_API void oc_ui_tooltip(const char* label);
|
||||||
|
|
||||||
ORCA_API void oc_ui_panel_begin(const char* name, oc_ui_flags flags);
|
ORCA_API void oc_ui_panel_begin(const char* name, oc_ui_flags flags);
|
||||||
ORCA_API void oc_ui_panel_end(void);
|
ORCA_API void oc_ui_panel_end(void);
|
||||||
#define oc_ui_panel(s, f) oc_defer_loop(oc_ui_panel_begin(s, f), oc_ui_panel_end())
|
#define oc_ui_panel(s, f) oc_defer_loop(oc_ui_panel_begin(s, f), oc_ui_panel_end())
|
||||||
|
|
||||||
ORCA_API void oc_ui_tooltip(const char* label);
|
ORCA_API void oc_ui_menu_bar_begin(const char* label);
|
||||||
|
ORCA_API void oc_ui_menu_bar_end(void);
|
||||||
ORCA_API void oc_ui_menu_bar_begin(const char* label);
|
|
||||||
ORCA_API void oc_ui_menu_bar_end(void);
|
|
||||||
#define oc_ui_menu_bar(name) oc_defer_loop(oc_ui_menu_bar_begin(name), oc_ui_menu_bar_end())
|
#define oc_ui_menu_bar(name) oc_defer_loop(oc_ui_menu_bar_begin(name), oc_ui_menu_bar_end())
|
||||||
|
|
||||||
ORCA_API void oc_ui_menu_begin(const char* label);
|
ORCA_API void oc_ui_menu_begin(const char* label);
|
||||||
ORCA_API void oc_ui_menu_end(void);
|
ORCA_API void oc_ui_menu_end(void);
|
||||||
#define oc_ui_menu(name) oc_defer_loop(oc_ui_menu_begin(name), oc_ui_menu_end())
|
#define oc_ui_menu(name) oc_defer_loop(oc_ui_menu_begin(name), oc_ui_menu_end())
|
||||||
|
|
||||||
ORCA_API oc_ui_sig oc_ui_menu_button(const char* name);
|
ORCA_API oc_ui_sig oc_ui_menu_button(const char* name);
|
||||||
|
|
||||||
typedef struct oc_ui_select_popup_info
|
typedef struct oc_ui_text_box_result
|
||||||
{
|
{
|
||||||
bool changed;
|
|
||||||
int selectedIndex;
|
|
||||||
int optionCount;
|
|
||||||
oc_str8* options;
|
|
||||||
} oc_ui_select_popup_info;
|
|
||||||
|
|
||||||
ORCA_API oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_info* info);
|
|
||||||
|
|
||||||
typedef struct oc_ui_text_box_result
|
|
||||||
{
|
|
||||||
bool changed;
|
bool changed;
|
||||||
bool accepted;
|
bool accepted;
|
||||||
oc_str8 text;
|
oc_str8 text;
|
||||||
|
|
||||||
} oc_ui_text_box_result;
|
} oc_ui_text_box_result;
|
||||||
|
|
||||||
ORCA_API oc_ui_text_box_result oc_ui_text_box(const char* name, oc_arena* arena, oc_str8 text);
|
ORCA_API oc_ui_text_box_result oc_ui_text_box(const char* name, oc_arena* arena, oc_str8 text);
|
||||||
|
|
||||||
|
typedef struct oc_ui_select_popup_info
|
||||||
|
{
|
||||||
|
bool changed;
|
||||||
|
int selectedIndex;
|
||||||
|
int optionCount;
|
||||||
|
oc_str8* options;
|
||||||
|
} oc_ui_select_popup_info;
|
||||||
|
|
||||||
|
ORCA_API oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_info* info);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -14,13 +14,12 @@
|
||||||
#include "util/debug.h"
|
#include "util/debug.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// Intrusive linked lists
|
// Intrusive linked lists
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
#define oc_list_entry(ptr, type, member) \
|
#define oc_list_entry(ptr, type, member) \
|
||||||
oc_container_of(ptr, type, member)
|
oc_container_of(ptr, type, member)
|
||||||
|
@ -62,42 +61,42 @@ extern "C"
|
||||||
|
|
||||||
#define oc_list_pop_entry(list, type, member) (oc_list_empty(list) ? 0 : oc_list_entry(oc_list_pop(list), type, member))
|
#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
|
struct oc_list_elt
|
||||||
{
|
{
|
||||||
oc_list_elt* next;
|
|
||||||
oc_list_elt* prev;
|
oc_list_elt* prev;
|
||||||
};
|
oc_list_elt* next;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct oc_list
|
typedef struct oc_list
|
||||||
{
|
{
|
||||||
oc_list_elt* first;
|
oc_list_elt* first;
|
||||||
oc_list_elt* last;
|
oc_list_elt* last;
|
||||||
} oc_list;
|
} 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;
|
list->first = list->last = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline oc_list_elt* oc_list_begin(oc_list* list)
|
static inline oc_list_elt* oc_list_begin(oc_list* list)
|
||||||
{
|
{
|
||||||
return (list->first);
|
return (list->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline oc_list_elt* oc_list_end(oc_list* list)
|
static inline oc_list_elt* oc_list_end(oc_list* list)
|
||||||
{
|
{
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline oc_list_elt* oc_list_last(oc_list* list)
|
static inline oc_list_elt* oc_list_last(oc_list* list)
|
||||||
{
|
{
|
||||||
return (list->last);
|
return (list->last);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt)
|
static inline void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt)
|
||||||
{
|
{
|
||||||
elt->prev = afterElt;
|
elt->prev = afterElt;
|
||||||
elt->next = afterElt->next;
|
elt->next = afterElt->next;
|
||||||
if(afterElt->next)
|
if(afterElt->next)
|
||||||
|
@ -111,10 +110,10 @@ extern "C"
|
||||||
afterElt->next = elt;
|
afterElt->next = elt;
|
||||||
|
|
||||||
OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert(): can't insert an element into itself");
|
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)
|
static inline void oc_list_insert_before(oc_list* list, oc_list_elt* beforeElt, oc_list_elt* elt)
|
||||||
{
|
{
|
||||||
elt->next = beforeElt;
|
elt->next = beforeElt;
|
||||||
elt->prev = beforeElt->prev;
|
elt->prev = beforeElt->prev;
|
||||||
|
|
||||||
|
@ -129,10 +128,10 @@ extern "C"
|
||||||
beforeElt->prev = elt;
|
beforeElt->prev = elt;
|
||||||
|
|
||||||
OC_DEBUG_ASSERT(elt->next != elt, "oc_list_insert_before(): can't insert an element into itself");
|
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)
|
static inline void oc_list_remove(oc_list* list, oc_list_elt* elt)
|
||||||
{
|
{
|
||||||
if(elt->prev)
|
if(elt->prev)
|
||||||
{
|
{
|
||||||
elt->prev->next = elt->next;
|
elt->prev->next = elt->next;
|
||||||
|
@ -152,10 +151,10 @@ extern "C"
|
||||||
list->last = elt->prev;
|
list->last = elt->prev;
|
||||||
}
|
}
|
||||||
elt->prev = elt->next = 0;
|
elt->prev = elt->next = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void oc_list_push(oc_list* list, oc_list_elt* elt)
|
static inline void oc_list_push(oc_list* list, oc_list_elt* elt)
|
||||||
{
|
{
|
||||||
elt->next = list->first;
|
elt->next = list->first;
|
||||||
elt->prev = 0;
|
elt->prev = 0;
|
||||||
if(list->first)
|
if(list->first)
|
||||||
|
@ -167,10 +166,10 @@ extern "C"
|
||||||
list->last = elt;
|
list->last = elt;
|
||||||
}
|
}
|
||||||
list->first = elt;
|
list->first = elt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline oc_list_elt* oc_list_pop(oc_list* list)
|
static inline oc_list_elt* oc_list_pop(oc_list* list)
|
||||||
{
|
{
|
||||||
oc_list_elt* elt = oc_list_begin(list);
|
oc_list_elt* elt = oc_list_begin(list);
|
||||||
if(elt != oc_list_end(list))
|
if(elt != oc_list_end(list))
|
||||||
{
|
{
|
||||||
|
@ -181,10 +180,10 @@ extern "C"
|
||||||
{
|
{
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void oc_list_push_back(oc_list* list, oc_list_elt* elt)
|
static inline void oc_list_push_back(oc_list* list, oc_list_elt* elt)
|
||||||
{
|
{
|
||||||
elt->prev = list->last;
|
elt->prev = list->last;
|
||||||
elt->next = 0;
|
elt->next = 0;
|
||||||
if(list->last)
|
if(list->last)
|
||||||
|
@ -196,12 +195,12 @@ extern "C"
|
||||||
list->first = elt;
|
list->first = elt;
|
||||||
}
|
}
|
||||||
list->last = elt;
|
list->last = elt;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define oc_list_append(a, b) oc_list_push_back(a, b)
|
#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);
|
oc_list_elt* elt = oc_list_last(list);
|
||||||
if(elt != oc_list_end(list))
|
if(elt != oc_list_end(list))
|
||||||
{
|
{
|
||||||
|
@ -212,12 +211,12 @@ extern "C"
|
||||||
{
|
{
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool oc_list_empty(oc_list* list)
|
static inline bool oc_list_empty(oc_list* list)
|
||||||
{
|
{
|
||||||
return (list->first == 0 || list->last == 0);
|
return (list->first == 0 || list->last == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -241,7 +241,7 @@ ORCA_API oc_arena* oc_scratch_next(oc_arena* used)
|
||||||
return (res);
|
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* scratch = oc_scratch();
|
||||||
oc_arena_scope scope = oc_arena_scope_begin(scratch);
|
oc_arena_scope scope = oc_arena_scope_begin(scratch);
|
||||||
|
|
|
@ -14,94 +14,93 @@
|
||||||
#include "util/typedefs.h"
|
#include "util/typedefs.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
//NOTE(martin): memory arena
|
//NOTE(martin): memory arena
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
typedef struct oc_arena_chunk
|
typedef struct oc_arena_chunk
|
||||||
{
|
{
|
||||||
oc_list_elt listElt;
|
oc_list_elt listElt;
|
||||||
char* ptr;
|
char* ptr;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 committed;
|
u64 committed;
|
||||||
u64 cap;
|
u64 cap;
|
||||||
} oc_arena_chunk;
|
} oc_arena_chunk;
|
||||||
|
|
||||||
typedef struct oc_arena
|
typedef struct oc_arena
|
||||||
{
|
{
|
||||||
oc_base_allocator* base;
|
oc_base_allocator* base;
|
||||||
oc_list chunks;
|
oc_list chunks;
|
||||||
oc_arena_chunk* currentChunk;
|
oc_arena_chunk* currentChunk;
|
||||||
|
|
||||||
} oc_arena;
|
} oc_arena;
|
||||||
|
|
||||||
typedef struct oc_arena_scope
|
typedef struct oc_arena_scope
|
||||||
{
|
{
|
||||||
oc_arena* arena;
|
oc_arena* arena;
|
||||||
oc_arena_chunk* chunk;
|
oc_arena_chunk* chunk;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
} oc_arena_scope;
|
} oc_arena_scope;
|
||||||
|
|
||||||
typedef struct oc_arena_options
|
typedef struct oc_arena_options
|
||||||
{
|
{
|
||||||
oc_base_allocator* base;
|
oc_base_allocator* base;
|
||||||
u64 reserve;
|
u64 reserve;
|
||||||
} oc_arena_options;
|
} oc_arena_options;
|
||||||
|
|
||||||
ORCA_API void oc_arena_init(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_init_with_options(oc_arena* arena, oc_arena_options* options);
|
||||||
ORCA_API void oc_arena_cleanup(oc_arena* arena);
|
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_push(oc_arena* arena, u64 size);
|
||||||
ORCA_API void oc_arena_clear(oc_arena* arena);
|
ORCA_API void oc_arena_clear(oc_arena* arena);
|
||||||
|
|
||||||
ORCA_API oc_arena_scope oc_arena_scope_begin(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 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_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)))
|
#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
|
//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...
|
// arenas "manually" with different free lists per object types...
|
||||||
|
|
||||||
typedef struct oc_pool
|
typedef struct oc_pool
|
||||||
{
|
{
|
||||||
oc_arena arena;
|
oc_arena arena;
|
||||||
oc_list freeList;
|
oc_list freeList;
|
||||||
u64 blockSize;
|
u64 blockSize;
|
||||||
} oc_pool;
|
} oc_pool;
|
||||||
|
|
||||||
typedef struct oc_pool_options
|
typedef struct oc_pool_options
|
||||||
{
|
{
|
||||||
oc_base_allocator* base;
|
oc_base_allocator* base;
|
||||||
u64 reserve;
|
u64 reserve;
|
||||||
} oc_pool_options;
|
} oc_pool_options;
|
||||||
|
|
||||||
ORCA_API void oc_pool_init(oc_pool* pool, u64 blockSize);
|
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_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_cleanup(oc_pool* pool);
|
||||||
|
|
||||||
ORCA_API void* oc_pool_alloc(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_recycle(oc_pool* pool, void* ptr);
|
||||||
ORCA_API void oc_pool_clear(oc_pool* pool);
|
ORCA_API void oc_pool_clear(oc_pool* pool);
|
||||||
|
|
||||||
#define oc_pool_alloc_type(arena, type) ((type*)oc_pool_alloc(arena))
|
#define oc_pool_alloc_type(arena, type) ((type*)oc_pool_alloc(arena))
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
//NOTE(martin): per-thread implicit scratch arena
|
//NOTE(martin): per-thread implicit scratch arena
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
ORCA_API oc_arena* oc_scratch();
|
ORCA_API oc_arena* oc_scratch();
|
||||||
ORCA_API oc_arena* oc_scratch_next(oc_arena* used);
|
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(void);
|
||||||
ORCA_API oc_arena_scope oc_scratch_begin_next(oc_arena* used);
|
ORCA_API oc_arena_scope oc_scratch_begin_next(oc_arena* used);
|
||||||
|
|
||||||
#define oc_scratch_end(scope) oc_arena_scope_end(scope)
|
#define oc_scratch_end(scope) oc_arena_scope_end(scope)
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,10 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*NOTE:
|
/*NOTE:
|
||||||
By convention, functions that take an arena and return a string slice allocated on
|
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
|
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
|
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.
|
into the original string. Only the _list nodes_ are allocated on the arena.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// u8 strings
|
// u8 strings
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef struct oc_str8
|
typedef struct oc_str8
|
||||||
{
|
{
|
||||||
u64 len;
|
u64 len;
|
||||||
char* ptr;
|
char* ptr;
|
||||||
} oc_str8;
|
} oc_str8;
|
||||||
|
|
||||||
#define OC_STR8(s) ((oc_str8){ .len = (s) ? strlen(s) : 0, .ptr = (char*)s })
|
#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_lp(s) ((s).len), ((s).ptr)
|
||||||
#define oc_str8_ip(s) (int)oc_str8_lp(s)
|
#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_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_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_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_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_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_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_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_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
|
// string lists
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef struct oc_str8_elt
|
typedef struct oc_str8_elt
|
||||||
{
|
{
|
||||||
oc_list_elt listElt;
|
oc_list_elt listElt;
|
||||||
oc_str8 string;
|
oc_str8 string;
|
||||||
} oc_str8_elt;
|
} oc_str8_elt;
|
||||||
|
|
||||||
typedef struct oc_str8_list
|
typedef struct oc_str8_list
|
||||||
{
|
{
|
||||||
oc_list list;
|
oc_list list;
|
||||||
u64 eltCount;
|
u64 eltCount;
|
||||||
u64 len;
|
u64 len;
|
||||||
} oc_str8_list;
|
} 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_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_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_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 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_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// u16 strings
|
// u16 strings
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef struct oc_str16
|
typedef struct oc_str16
|
||||||
{
|
{
|
||||||
u64 len;
|
u64 len;
|
||||||
u16* ptr;
|
u16* ptr;
|
||||||
} oc_str16;
|
} oc_str16;
|
||||||
|
|
||||||
ORCA_API oc_str16 oc_str16_from_buffer(u64 len, u16* buffer);
|
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_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_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_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_slice(oc_arena* arena, oc_str16 s, u64 start, u64 end);
|
||||||
|
|
||||||
typedef struct oc_str16_elt
|
typedef struct oc_str16_elt
|
||||||
{
|
{
|
||||||
oc_list_elt listElt;
|
oc_list_elt listElt;
|
||||||
oc_str16 string;
|
oc_str16 string;
|
||||||
} oc_str16_elt;
|
} oc_str16_elt;
|
||||||
|
|
||||||
typedef struct oc_str16_list
|
typedef struct oc_str16_list
|
||||||
{
|
{
|
||||||
oc_list list;
|
oc_list list;
|
||||||
u64 eltCount;
|
u64 eltCount;
|
||||||
u64 len;
|
u64 len;
|
||||||
} oc_str16_list;
|
} oc_str16_list;
|
||||||
|
|
||||||
ORCA_API void oc_str16_list_push(oc_arena* arena, oc_str16_list* list, oc_str16 str);
|
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 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 oc_str16_list oc_str16_split(oc_arena* arena, oc_str16 str, oc_str16_list separators);
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// u32 strings
|
// u32 strings
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
typedef struct oc_str32
|
typedef struct oc_str32
|
||||||
{
|
{
|
||||||
u64 len;
|
u64 len;
|
||||||
u32* ptr;
|
u32* ptr;
|
||||||
} oc_str32;
|
} oc_str32;
|
||||||
|
|
||||||
ORCA_API oc_str32 oc_str32_from_buffer(u64 len, u32* buffer);
|
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_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_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_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_slice(oc_arena* arena, oc_str32 s, u64 start, u64 end);
|
||||||
|
|
||||||
typedef struct oc_str32_elt
|
typedef struct oc_str32_elt
|
||||||
{
|
{
|
||||||
oc_list_elt listElt;
|
oc_list_elt listElt;
|
||||||
oc_str32 string;
|
oc_str32 string;
|
||||||
} oc_str32_elt;
|
} oc_str32_elt;
|
||||||
|
|
||||||
typedef struct oc_str32_list
|
typedef struct oc_str32_list
|
||||||
{
|
{
|
||||||
oc_list list;
|
oc_list list;
|
||||||
u64 eltCount;
|
u64 eltCount;
|
||||||
u64 len;
|
u64 len;
|
||||||
} oc_str32_list;
|
} oc_str32_list;
|
||||||
|
|
||||||
ORCA_API void oc_str32_list_push(oc_arena* arena, oc_str32_list* list, oc_str32 str);
|
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 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 oc_str32_list oc_str32_split(oc_arena* arena, oc_str32 str, oc_str32_list separators);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "oc_runtime_log",
|
"name": "oc_bridge_log",
|
||||||
"cname": "oc_runtime_log",
|
"cname": "oc_bridge_log",
|
||||||
"ret": {"name": "void", "tag": "v"},
|
"ret": {"name": "void", "tag": "v"},
|
||||||
"args": [ {"name": "level",
|
"args": [ {"name": "level",
|
||||||
"type": {"name": "oc_log_level", "tag": "i"}},
|
"type": {"name": "oc_log_level", "tag": "i"}},
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
"type": {"name": "u64", "tag": "I"}}]
|
"type": {"name": "u64", "tag": "I"}}]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oc_runtime_assert_fail",
|
"name": "oc_bridge_assert_fail",
|
||||||
"cname": "oc_assert_fail",
|
"cname": "oc_assert_fail",
|
||||||
"ret": {"name": "void", "tag": "v"},
|
"ret": {"name": "void", "tag": "v"},
|
||||||
"args": [ {"name": "file",
|
"args": [ {"name": "file",
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oc_runtime_abort_ext",
|
"name": "oc_bridge_abort_ext",
|
||||||
"cname": "oc_abort_ext",
|
"cname": "oc_abort_ext",
|
||||||
"ret": {"name": "void", "tag": "v"},
|
"ret": {"name": "void", "tag": "v"},
|
||||||
"args": [ {"name": "file",
|
"args": [ {"name": "file",
|
||||||
|
@ -71,17 +71,17 @@
|
||||||
"args": []
|
"args": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oc_runtime_window_set_title",
|
"name": "oc_window_set_title",
|
||||||
"cname": "oc_runtime_window_set_title",
|
"cname": "oc_bridge_window_set_title",
|
||||||
"ret": {"name": "void", "tag": "v"},
|
"ret": {"name": "void", "tag": "v"},
|
||||||
"args": [
|
"args": [
|
||||||
{ "name": "title",
|
{ "name": "title",
|
||||||
"type": {"name": "oc_str8", "tag": "S"}}
|
"type": {"name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "oc_runtime_window_set_size",
|
"name": "oc_window_set_size",
|
||||||
"cname": "oc_runtime_window_set_size",
|
"cname": "oc_bridge_window_set_size",
|
||||||
"ret": {"name": "void", "tag": "v"},
|
"ret": {"name": "void", "tag": "v"},
|
||||||
"args": [
|
"args": [
|
||||||
{ "name": "size",
|
{ "name": "size",
|
||||||
|
|
|
@ -1,9 +1,37 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "oc_io_wait_single_req",
|
"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"},
|
"ret": {"name": "oc_io_cmp", "tag": "S"},
|
||||||
"args": [ {"name": "req",
|
"args": [ {"name": "req",
|
||||||
"type": {"name": "oc_io_req*", "tag": "p"}}]
|
"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",
|
{"name": "pixels",
|
||||||
"type": {"name": "u8*", "tag": "p"}}]
|
"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",
|
"name": "oc_surface_contents_scaling",
|
||||||
"cname": "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