Zig bindings for orca (still WIP) #140

Open
rdunnington wants to merge 24 commits from zig_ffi into main
3 changed files with 211 additions and 196 deletions
Showing only changes of commit db2828141f - Show all commits

View File

@ -1,19 +1,6 @@
@echo off
:: compile wasm module
rem set wasmFlags=--target=wasm32^
rem --no-standard-libraries ^
rem -fno-builtin ^
rem -Wl,--no-entry ^
rem -Wl,--export-dynamic ^
rem -Wl,--relocatable ^
rem -g ^
rem -O2 ^
rem -mbulk-memory ^
rem -D__ORCA__ ^
rem -isystem ..\..\src\libc-shim\include ^
rem -I..\..\ext -I ..\..\src
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim

View File

@ -54,6 +54,10 @@ export fn oc_on_mouse_up(button: oc.MouseButton) void {
oc.log.info("mouse up! {}", .{button}, @src());
}
export fn oc_on_mouse_wheel(dx: f32, dy: f32) void {
oc.log.info("mouse wheel! dx: {d:.2}, dy: {d:.2}", .{ dx, dy }, @src());
}
export fn oc_on_key_down(scan: oc.ScanCode, key: oc.KeyCode) void {
oc.log.info("key down: {} {}", .{ scan, key }, @src());
}
@ -132,10 +136,6 @@ export fn oc_on_frame_refresh() void {
const center_x = frame_size.x / 2;
const text_begin_x = center_x - text_rect.Flat.w / 2;
oc.log.info("text rect width: {d}", .{text_rect.Flat.w}, @src());
oc.log.info("center_x: {d}", .{center_x}, @src());
oc.log.info("text_begin_x: {d}", .{text_begin_x}, @src());
Mat2x3.push(Mat2x3.translate(text_begin_x, 150));
defer Mat2x3.pop();

View File

@ -90,6 +90,109 @@ pub const ListElt = extern struct {
pub const List = extern struct {
first: ?*ListElt,
last: ?*ListElt,
pub fn init() List {
return .{
.first = null,
.last = null,
};
}
pub fn begin(self: *List) ?*ListElt {
return self.first;
}
pub fn end() ?*ListElt {
return null;
}
pub fn last(self: *List) ?*ListElt {
return self.last;
}
pub fn insert(self: *List, after_elt: *ListElt, elt: *ListElt) void {
elt.prev = after_elt;
elt.next = after_elt.next;
if (after_elt.next != null) {
after_elt.next.prev = elt;
} else {
self.last = elt;
}
after_elt.next = elt;
}
pub fn insertBefore(self: *List, before_elt: *ListElt, elt: *ListElt) void {
elt.next = before_elt;
elt.prev = before_elt.prev;
if (before_elt.prev != null) {
before_elt.prev.next = elt;
} else {
self.first = elt;
}
before_elt.prev = elt;
}
pub fn remove(self: *List, elt: *ListElt) void {
if (elt.prev != null) {
elt.prev.next = elt.next;
} else {
self.first = elt.next;
}
if (elt.next != null) {
elt.next.prev = elt.prev;
} else {
self.last = elt.prev;
}
elt.prev = blk: {
const tmp = null;
elt.next = tmp;
break :blk tmp;
};
}
pub fn push(self: *List, elt: *ListElt) void {
elt.next = self.first;
elt.prev = null;
if (self.first != null) {
self.first.prev = elt;
} else {
self.last = elt;
}
self.first = elt;
}
pub fn pop(self: *List) ListElt {
var elt: *ListElt = begin(self);
if (elt != end(self)) {
remove(self, elt);
return elt;
}
return null;
}
pub fn pushBack(self: *List, elt: *ListElt) void {
elt.prev = self.last;
elt.next = null;
if (self.last != null) {
self.last.next = elt;
} else {
self.first = elt;
}
self.last = elt;
}
pub fn popBack(self: *List) ListElt {
var elt: *ListElt = last(self);
if (elt != end(self)) {
remove(self, elt);
return elt;
}
return null;
}
pub fn empty(self: *const List) bool {
return (self.first == null) or (self.last == null);
}
};
//------------------------------------------------------------------------------------------
@ -198,87 +301,129 @@ pub const ArenaOptions = extern struct {
fn stringType(comptime CharType: type) type {
return extern struct {
const Self = @This();
pub const StrListElt = extern struct {
list_elt: ListElt,
string: Str,
};
pub const StrList = extern struct {
list: List,
elt_count: u64,
len: u64,
pub fn init() StrList {
return .{
.list = List.init(),
.elt_count = 0,
.len = 0,
};
}
pub fn push(list: *StrList, str: *Str, arena: *Arena) void {
var elt: *StrListElt = arena.pushType(ListElt);
elt.string = str;
list.append(elt.list_elt);
list.elt_count += 1;
list.len += str.len;
}
pub fn pushf(list: *StrList, arena: *Arena, comptime format: []const u8, args: anytype) Str {
var str = Str.pushf(arena, format, args);
list.push(str, arena);
}
// TODO
// pub fn join(list: *const StrList, arena: *Arena) Str;
// const empty = Str{ .ptr = null, .len = 0 };
// return list.collate(arena, empty, empty, empty));
// }
// pub fn collate(list: *StrList, arena: *Arena, prefix: Str, separator: Str, postfix: Str) Str;
};
const Str = @This();
ptr: ?[*]CharType,
len: usize,
extern fn strncmp(a: ?[*]u8, b: ?[*]u8, len: usize) c_int;
// extern fn oc_str8_push_buffer(arena: *Arena, len: u64, buffer: [*]u8) oc_str8;
// extern fn oc_str8_push_cstring(arena: *Arena, str: [*]const u8) oc_str8;
// extern fn oc_str8_push_copy(arena: *Arena, s: oc_str8) oc_str8;
// extern fn oc_str8_push_slice(arena: *Arena, s: oc_str8, start: u64, end: u64) oc_str8;
// // extern fn oc_str8_pushfv(arena: oc_arena*, char: const* format, args: va_list) oc_str8;
// // extern fn oc_str8_pushf(arena: oc_arena*, char: const* format, ...) oc_str8;
// extern fn oc_str8_cmp(s1: oc_str8, s2: oc_str8) c_int;
// extern fn oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str) void;
// extern fn oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...) void;
// extern fn oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix) oc_str8;
// extern fn oc_str8_list_join(oc_arena* arena, oc_str8_list list) oc_str8;
// extern fn oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators) oc_str8_list;
// extern fn oc_str16_from_buffer(u64 len, u16* buffer) oc_str16;
// extern fn oc_str16_slice(oc_str16 s, u64 start, u64 end) oc_str16;
// extern fn oc_str16_push_buffer(oc_arena* arena, u64 len, u16* buffer) oc_str16;
// extern fn oc_str16_push_copy(oc_arena* arena, oc_str16 s) oc_str16;
// extern fn oc_str16_push_slice(oc_arena* arena, oc_str16 s, u64 start, u64 end) oc_str16;
// extern fn oc_str16_list_push(oc_arena* arena, oc_str16_list* list, oc_str16 str) void;
// extern fn oc_str16_list_join(oc_arena* arena, oc_str16_list list) oc_str16;
// extern fn oc_str16_split(oc_arena* arena, oc_str16 str, oc_str16_list separators) oc_str16_list;
// extern fn oc_str32_from_buffer(u64 len, u32* buffer) oc_str32;
// extern fn oc_str32_slice(oc_str32 s, u64 start, u64 end) oc_str32;
// extern fn oc_str32_push_buffer(oc_arena* arena, u64 len, u32* buffer) oc_str32;
// extern fn oc_str32_push_copy(oc_arena* arena, oc_str32 s) oc_str32;
// extern fn oc_str32_push_slice(oc_arena* arena, oc_str32 s, u64 start, u64 end) oc_str32;
// extern fn oc_str32_list_push(oc_arena* arena, oc_str32_list* list, oc_str32 str) void;
// extern fn oc_str32_list_join(oc_arena* arena, oc_str32_list list) oc_str32;
// extern fn oc_str32_split(oc_arena* arena, oc_str32 str, oc_str32_list separators) oc_str32_list;
pub fn fromSlice(str: []const CharType) Self {
pub fn fromSlice(str: []const CharType) Str {
return .{
.ptr = @constCast(str.ptr),
.len = str.len,
};
}
pub fn slice(self: *const Self) []CharType {
if (self.ptr) |p| {
return p[0..self.len];
pub fn slice(str: *const Str) []CharType {
if (str.ptr) |p| {
return p[0..str.len];
}
return &[_]CharType{};
}
pub fn sliceInner(self: *const Self, start: u64, end: u64) []CharType {
if (self.ptr) |p| {
pub fn sliceInner(str: *const Str, start: u64, end: u64) []CharType {
if (str.ptr) |p| {
assert(start <= end, "{}.sliceLen: start <= end", .{typename()}, @src());
assert(end <= self.len, "{}.sliceLen: end <= self.len", .{typename()}, @src());
assert(end <= str.len, "{}.sliceLen: end <= str.len", .{typename()}, @src());
return p[start..end];
}
return &[_]CharType{};
}
pub fn fromBuffer(len: u64, buffer: ?[]CharType) Self {
pub fn fromBuffer(len: u64, buffer: ?[]CharType) Str {
return .{
.ptr = buffer,
.len = @intCast(len),
};
}
// pub fn cmp(a: *const Self, b: *const Self) std.math.Order {
// if (CharType != u8) {
// @compileError("cmp() is only supported for Str8");
// }
// const value = strncmp(a.ptr, b.ptr, std.math.min(a.len, b.len));
pub fn pushBuffer(arena: *Arena, buffer: []u8) Str {
var str: Str = undefined;
str.len = buffer.len;
str.ptr = arena.pushArray(CharType, buffer.len + 1);
@memcpy(str.ptr[0..buffer.len], buffer);
str.ptr[buffer.len] = 0;
return str;
}
pub fn pushCopy(str: *const Str, arena: *Arena) Str {
return pushBuffer(arena, str.ptr[0..str.len]);
}
pub fn pushSlice(str: *const Str, arena: *Arena, start: usize, end: usize) Str {
return pushBuffer(arena, str.ptr[start..end]);
}
pub fn pushf(arena: *Arena, format: []const u8, args: anytype) Str {
if (CharType != u8) {
@compileError("pushf() is only supported for Str8");
}
var str: Str = undefined;
str.len = @intCast(std.fmt.count(format, args));
str.ptr = arena.pushArray(CharType, str.len + 1);
_ = std.fmt.bufPrintZ(str.ptr[0 .. str.len + 1], format, args) catch unreachable;
return str;
}
// }
// TODO
// pub fn split() void;
pub fn cmp(a: *const Str, b: *const Str) std.math.Order {
if (CharType != u8) {
@compileError("cmp() is only supported for Str8");
}
const value = strncmp(a.ptr, b.ptr, std.math.min(a.len, b.len));
if (value < 0) {
return .lt;
} else if (value == 0) {
return .eq;
} else {
return .gt;
}
}
fn typename() []const u8 {
return switch (CharType) {
@ -318,136 +463,6 @@ pub const Str8List = stringListType(Str8);
pub const Str16List = stringListType(Str8);
pub const Str32List = stringListType(Str8);
// pub const Str8 = extern struct {
// ptr: ?[*:0]u8,
// len: usize,
// pub fn fromSlice(slice: [:0]const u8) Str8 {
// return .{
// ptr: @constCast(slice.ptr),
// len: slice.len,
// };
// }
// };
// typedef struct oc_str8
// {
// char* ptr;
// size_t len;
// } oc_str8;
// #define OC_STR8(s) ((oc_str8){ .ptr = (char*)s, .len = (s) ? strlen(s) : 0 })
//NOTE: this only works with string literals, but is sometimes necessary to generate compile-time constants
// #define OC_STR8_LIT(s) \
// { \
// (char*)(s), sizeof(s) - 1 \
// }
// #define oc_str8_lp(s) ((s).len), ((s).ptr)
// #define oc_str8_ip(s) (int)oc_str8_lp(s)
// ORCA_API oc_str8 oc_str8_from_buffer(u64 len, char* buffer);
// ORCA_API oc_str8 oc_str8_slice(oc_str8 s, u64 start, u64 end);
// ORCA_API oc_str8 oc_str8_push_buffer(oc_arena* arena, u64 len, char* buffer);
// ORCA_API oc_str8 oc_str8_push_cstring(oc_arena* arena, const char* str);
// ORCA_API oc_str8 oc_str8_push_copy(oc_arena* arena, oc_str8 s);
// ORCA_API oc_str8 oc_str8_push_slice(oc_arena* arena, oc_str8 s, u64 start, u64 end);
// ORCA_API oc_str8 oc_str8_pushfv(oc_arena* arena, const char* format, va_list args);
// ORCA_API oc_str8 oc_str8_pushf(oc_arena* arena, const char* format, ...);
// ORCA_API int oc_str8_cmp(oc_str8 s1, oc_str8 s2);
// ORCA_API char* oc_str8_to_cstring(oc_arena* arena, oc_str8 string);
// typedef struct oc_str8_elt
// {
// oc_list_elt listElt;
// oc_str8 string;
// } oc_str8_elt;
// typedef struct oc_str8_list
// {
// oc_list list;
// u64 eltCount;
// u64 len;
// } oc_str8_list;
// ORCA_API void oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str);
// ORCA_API void oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...);
// ORCA_API oc_str8 oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix);
// ORCA_API oc_str8 oc_str8_list_join(oc_arena* arena, oc_str8_list list);
// ORCA_API oc_str8_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators);
// //----------------------------------------------------------------------------------
// // [STRINGS] u16 strings
// //----------------------------------------------------------------------------------
// typedef struct oc_str16
// {
// u16* ptr;
// size_t len;
// } oc_str16;
// ORCA_API oc_str16 oc_str16_from_buffer(u64 len, u16* buffer);
// ORCA_API oc_str16 oc_str16_slice(oc_str16 s, u64 start, u64 end);
// ORCA_API oc_str16 oc_str16_push_buffer(oc_arena* arena, u64 len, u16* buffer);
// ORCA_API oc_str16 oc_str16_push_copy(oc_arena* arena, oc_str16 s);
// ORCA_API oc_str16 oc_str16_push_slice(oc_arena* arena, oc_str16 s, u64 start, u64 end);
// typedef struct oc_str16_elt
// {
// oc_list_elt listElt;
// oc_str16 string;
// } oc_str16_elt;
// typedef struct oc_str16_list
// {
// oc_list list;
// u64 eltCount;
// u64 len;
// } oc_str16_list;
// ORCA_API void oc_str16_list_push(oc_arena* arena, oc_str16_list* list, oc_str16 str);
// ORCA_API oc_str16 oc_str16_list_join(oc_arena* arena, oc_str16_list list);
// ORCA_API oc_str16_list oc_str16_split(oc_arena* arena, oc_str16 str, oc_str16_list separators);
// //----------------------------------------------------------------------------------
// // [STRINGS] u32 strings
// //----------------------------------------------------------------------------------
// typedef struct oc_str32
// {
// u32* ptr;
// size_t len;
// } oc_str32;
// ORCA_API oc_str32 oc_str32_from_buffer(u64 len, u32* buffer);
// ORCA_API oc_str32 oc_str32_slice(oc_str32 s, u64 start, u64 end);
// ORCA_API oc_str32 oc_str32_push_buffer(oc_arena* arena, u64 len, u32* buffer);
// ORCA_API oc_str32 oc_str32_push_copy(oc_arena* arena, oc_str32 s);
// ORCA_API oc_str32 oc_str32_push_slice(oc_arena* arena, oc_str32 s, u64 start, u64 end);
// typedef struct oc_str32_elt
// {
// oc_list_elt listElt;
// oc_str32 string;
// } oc_str32_elt;
// typedef struct oc_str32_list
// {
// oc_list list;
// u64 eltCount;
// u64 len;
// } oc_str32_list;
// ORCA_API void oc_str32_list_push(oc_arena* arena, oc_str32_list* list, oc_str32 str);
// ORCA_API oc_str32 oc_str32_list_join(oc_arena* arena, oc_str32_list list);
// ORCA_API oc_str32_list oc_str32_split(oc_arena* arena, oc_str32 str, oc_str32_list separators);
//------------------------------------------------------------------------------------------
// [UTF8]
//------------------------------------------------------------------------------------------
@ -1402,6 +1417,7 @@ pub const Surface = extern struct {
extern fn oc_surface_contents_scaling(surface: Surface) Vec2;
extern fn oc_surface_bring_to_front(surface: Surface) void;
extern fn oc_surface_send_to_back(surface: Surface) void;
// TODO
// extern fn oc_surface_render_commands(
// surface: Surface,
// color: Color,
@ -1616,6 +1632,18 @@ pub const circleFill = oc_circle_fill;
pub const circleStroke = oc_circle_stroke;
pub const arc = oc_arc;
//------------------------------------------------------------------------------------------
// [GRAPHICS]: GLES
//------------------------------------------------------------------------------------------
// TODO
//------------------------------------------------------------------------------------------
// [UI]: GLES
//------------------------------------------------------------------------------------------
// TODO
//------------------------------------------------------------------------------------------
// [FILE IO] basic API
//------------------------------------------------------------------------------------------