mirror of
https://github.com/bdnugget/zig-gamedev.git
synced 2026-11-07 09:07:31 +00:00
Merge branch 'main' into dds-textures
This commit is contained in:
commit
ef8bb66eb1
35 files changed
+4739
-1722
No files matched your search
@@ -21,6 +21,7 @@
|
||||
*.o filter=lfs diff=lfs merge=lfs -text
|
||||
*.so filter=lfs diff=lfs merge=lfs -text
|
||||
*.a filter=lfs diff=lfs merge=lfs -text
|
||||
*.dds filter=lfs diff=lfs merge=lfs -text
|
||||
libs/zwin32/bin/x64/dxc filter=lfs diff=lfs merge=lfs -text
|
||||
libs/zwin32/bin/x64/libdxcompiler.so.3.7 filter=lfs diff=lfs merge=lfs -text
|
||||
libs/zsdl/libs/macos/Frameworks/SDL2.framework/SDL2 filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
!*.flac
|
||||
!*.blend
|
||||
!*.hiplc
|
||||
!*.dds
|
||||
|
||||
!.ignore
|
||||
!.vimrc
|
||||
|
||||
@@ -26,7 +26,7 @@ Library | Latest version | Description
|
||||
**[zgui](libs/zgui)** | 0.9.5 | Easy to use [dear imgui](https://github.com/ocornut/imgui) bindings (includes [ImPlot](https://github.com/epezent/implot))
|
||||
**[zaudio](libs/zaudio)** | 0.9.3 | Fully-featured audio library built on top of [miniaudio](https://github.com/mackron/miniaudio)
|
||||
**[zmath](libs/zmath)** | 0.9.5 | SIMD math library for game developers
|
||||
**[zstbi](libs/zstbi)** | 0.9.2 | Image reading, writing and resizing with [stb](https://github.com/nothings/stb) libraries
|
||||
**[zstbi](libs/zstbi)** | 0.9.3 | Image reading, writing and resizing with [stb](https://github.com/nothings/stb) libraries
|
||||
**[zmesh](libs/zmesh)** | 0.9.0 | Loading, generating, processing and optimizing triangle meshes
|
||||
**[ztracy](libs/ztracy)** | 0.9.0 | Support for CPU profiling with [Tracy](https://github.com/wolfpld/tracy)
|
||||
**[zpool](libs/zpool)** | 0.9.0 | Generic pool & handle implementation
|
||||
|
||||
+2541
-835
File diff suppressed because it is too large.
Load diff
+839
-114
File diff suppressed because it is too large.
Load diff
+60
-11
@@ -31,18 +31,67 @@ test "zflecs.entities.basics" {
|
||||
ecs.add(world, alice, Walking);
|
||||
|
||||
const str = ecs.type_str(world, ecs.get_type(world, alice));
|
||||
defer ecs.os_free(str);
|
||||
defer ecs.os.free(str);
|
||||
std.debug.print("[{s}]\n", .{str});
|
||||
|
||||
ecs.remove(world, alice, Walking);
|
||||
|
||||
var it = ecs.term_iter(world, &.{ .id = ecs.id(Position) });
|
||||
while (ecs.term_next(&it)) {
|
||||
const positions = ecs.field(&it, Position, 1);
|
||||
for (positions.?, 0..) |p, i| {
|
||||
std.debug.print("{?s}: ({d}, {d})\n", .{ ecs.get_name(world, it.entities.?[i]), p.x, p.y });
|
||||
{
|
||||
var it = ecs.term_iter(world, &.{ .id = ecs.id(Position) });
|
||||
while (ecs.term_next(&it)) {
|
||||
if (ecs.field(&it, Position, 1)) |positions| {
|
||||
for (positions, 0..) |p, i| {
|
||||
std.debug.print(
|
||||
"Term loop: {?s}: ({d}, {d})\n",
|
||||
.{ ecs.get_name(world, it.entities.?[i]), p.x, p.y },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
var desc = ecs.filter_desc_t{};
|
||||
desc.terms[0].id = ecs.id(Position);
|
||||
const filter = try ecs.filter_init(world, &desc);
|
||||
defer ecs.filter_fini(filter);
|
||||
}
|
||||
|
||||
{
|
||||
const filter = try ecs.filter_init(world, &.{
|
||||
.terms = [_]ecs.term_t{
|
||||
.{ .id = ecs.id(Position) },
|
||||
.{ .id = ecs.id(Walking) },
|
||||
} ++ ecs.array(ecs.term_t, ecs.TERM_DESC_CACHE_SIZE - 2),
|
||||
});
|
||||
defer ecs.filter_fini(filter);
|
||||
|
||||
var it = ecs.filter_iter(world, filter);
|
||||
while (ecs.filter_next(&it)) {
|
||||
for (it.get_entities().?) |e| {
|
||||
std.debug.print("Filter loop: {?s}\n", .{ecs.get_name(world, e)});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const query = _: {
|
||||
var desc = ecs.query_desc_t{};
|
||||
desc.filter.terms[0].id = ecs.id(Position);
|
||||
break :_ try ecs.query_init(world, &desc);
|
||||
};
|
||||
defer ecs.query_fini(query);
|
||||
}
|
||||
|
||||
{
|
||||
const query = try ecs.query_init(world, &.{
|
||||
.filter = .{
|
||||
.terms = [_]ecs.term_t{.{ .id = ecs.id(Position) }} ++
|
||||
ecs.array(ecs.term_t, ecs.TERM_DESC_CACHE_SIZE - 1),
|
||||
},
|
||||
});
|
||||
defer ecs.query_fini(query);
|
||||
}
|
||||
}
|
||||
|
||||
fn registerComponents(world: *ecs.world_t) void {
|
||||
@@ -129,13 +178,13 @@ test "zflecs.basic" {
|
||||
}
|
||||
|
||||
const e0_type_str = ecs.type_str(world, ecs.get_type(world, e0));
|
||||
defer ecs.os_free(e0_type_str);
|
||||
defer ecs.os.free(e0_type_str);
|
||||
|
||||
const e0_table_str = ecs.table_str(world, ecs.get_table(world, e0));
|
||||
defer ecs.os_free(e0_table_str);
|
||||
defer ecs.os.free(e0_table_str);
|
||||
|
||||
const e0_str = ecs.entity_str(world, e0);
|
||||
defer ecs.os_free(e0_str);
|
||||
defer ecs.os.free(e0_str);
|
||||
|
||||
std.debug.print("type str: {s}\n", .{e0_type_str});
|
||||
std.debug.print("table str: {?s}\n", .{e0_table_str});
|
||||
@@ -143,12 +192,12 @@ test "zflecs.basic" {
|
||||
|
||||
{
|
||||
const str = ecs.type_str(world, ecs.get_type(world, ecs.id(Position)));
|
||||
defer ecs.os_free(str);
|
||||
defer ecs.os.free(str);
|
||||
std.debug.print("{s}\n", .{str});
|
||||
}
|
||||
{
|
||||
const str = ecs.id_str(world, ecs.id(Position));
|
||||
defer ecs.os_free(str);
|
||||
defer ecs.os.free(str);
|
||||
std.debug.print("{?s}\n", .{str});
|
||||
}
|
||||
}
|
||||
+165
-103
@@ -12,6 +12,11 @@ pub const vector_t = opaque {};
|
||||
pub const mixins_t = opaque {};
|
||||
|
||||
const filter_t_magic = 0x65637366;
|
||||
|
||||
pub const error_t = error{FlecsError};
|
||||
fn make_error() error{FlecsError} {
|
||||
return error.FlecsError;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Types for core API objects.
|
||||
@@ -42,9 +47,6 @@ pub const header_t = extern struct {
|
||||
type: i32 = 0,
|
||||
mixins: ?*mixins_t = null,
|
||||
};
|
||||
|
||||
const ID_CACHE_SIZE = 32;
|
||||
const TERM_DESC_CACHE_SIZE = 16;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Function types.
|
||||
@@ -205,6 +207,10 @@ pub const term_t = extern struct {
|
||||
move: bool = true,
|
||||
};
|
||||
|
||||
pub fn array(comptime T: type, comptime len: comptime_int) [len]T {
|
||||
return [_]T{.{}} ** len;
|
||||
}
|
||||
|
||||
pub const filter_t = extern struct {
|
||||
hdr: header_t = .{ .magic = filter_t_magic },
|
||||
|
||||
@@ -238,6 +244,7 @@ pub const observer_t = extern struct {
|
||||
binding_ctx_free: ctx_free_t,
|
||||
observable: [*c]observable_t,
|
||||
last_event_id: [*c]i32,
|
||||
last_event_id_storage: i32,
|
||||
register_id: id_t,
|
||||
term_index: i32,
|
||||
is_monitor: bool,
|
||||
@@ -466,6 +473,13 @@ pub const iter_t = extern struct {
|
||||
callback: iter_action_t,
|
||||
fini: iter_fini_action_t,
|
||||
chain_it: ?*iter_t,
|
||||
|
||||
pub fn get_entities(iter: iter_t) ?[]entity_t {
|
||||
if (iter.entities) |ptr| {
|
||||
return ptr[0..@intCast(usize, iter.count)];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
@@ -553,17 +567,17 @@ pub const map_params_t = extern struct {
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub const query_desc_t = extern struct {
|
||||
_canary: i32 = 0,
|
||||
filter: filter_desc_t,
|
||||
order_by_component: entity_t,
|
||||
order_by: ?order_by_action_t,
|
||||
sort_table: ?sort_table_action_t,
|
||||
group_by_id: id_t,
|
||||
group_by: ?group_by_action_t,
|
||||
on_group_create: ?group_create_action_t,
|
||||
on_group_delete: ?group_delete_action_t,
|
||||
group_by_ctx: ?*anyopaque,
|
||||
group_by_ctx_free: ?ctx_free_t,
|
||||
parent: ?*query_t,
|
||||
filter: filter_desc_t = .{},
|
||||
order_by_component: entity_t = 0,
|
||||
order_by: ?order_by_action_t = null,
|
||||
sort_table: ?sort_table_action_t = null,
|
||||
group_by_id: id_t = 0,
|
||||
group_by: ?group_by_action_t = null,
|
||||
on_group_create: ?group_create_action_t = null,
|
||||
on_group_delete: ?group_delete_action_t = null,
|
||||
group_by_ctx: ?*anyopaque = null,
|
||||
group_by_ctx_free: ?ctx_free_t = null,
|
||||
parent: ?*query_t = null,
|
||||
};
|
||||
|
||||
pub const component_desc_t = extern struct {
|
||||
@@ -572,6 +586,8 @@ pub const component_desc_t = extern struct {
|
||||
type: type_info_t,
|
||||
};
|
||||
|
||||
pub const ID_CACHE_SIZE = 32;
|
||||
|
||||
pub const entity_desc_t = extern struct {
|
||||
_canary: i32 = 0,
|
||||
id: entity_t = 0,
|
||||
@@ -584,6 +600,8 @@ pub const entity_desc_t = extern struct {
|
||||
add_expr: ?[*:0]const u8 = null,
|
||||
};
|
||||
|
||||
pub const TERM_DESC_CACHE_SIZE = 16;
|
||||
|
||||
pub const filter_desc_t = extern struct {
|
||||
_canary: i32 = 0,
|
||||
terms: [TERM_DESC_CACHE_SIZE]term_t = [_]term_t{.{}} ** TERM_DESC_CACHE_SIZE,
|
||||
@@ -596,6 +614,25 @@ pub const filter_desc_t = extern struct {
|
||||
entity: entity_t = 0,
|
||||
};
|
||||
|
||||
pub const OBSERVER_DESC_EVENT_COUNT_MAX = 8;
|
||||
|
||||
pub const observer_desc_t = extern struct {
|
||||
_canary: i32 = 0,
|
||||
entity: entity_t = 0,
|
||||
filter: filter_desc_t = .{},
|
||||
events: [OBSERVER_DESC_EVENT_COUNT_MAX]entity_t = [_]entity_t{0} ** OBSERVER_DESC_EVENT_COUNT_MAX,
|
||||
yield_existing: bool = false,
|
||||
callback: iter_action_t,
|
||||
run: ?run_action_t = null,
|
||||
ctx: ?*anyopaque = null,
|
||||
binding_ctx: ?*anyopaque = null,
|
||||
ctx_free: ?ctx_free_t = null,
|
||||
binding_ctx_free: ?ctx_free_t = null,
|
||||
observable: ?*poly_t = null,
|
||||
last_event_id: ?*i32 = null,
|
||||
term_index: i32 = 0,
|
||||
};
|
||||
|
||||
pub const world_info_t = extern struct {
|
||||
last_component_id: entity_t,
|
||||
last_id: entity_t,
|
||||
@@ -864,6 +901,10 @@ extern fn ecs_new_low_id(world: *world_t) entity_t;
|
||||
pub const new_w_id = ecs_new_w_id;
|
||||
extern fn ecs_new_w_id(world: *world_t, id: id_t) entity_t;
|
||||
|
||||
/// `pub fn new_w_table(world: *world_t, table: *table_t) entity_t`
|
||||
pub const new_w_table = ecs_new_w_table;
|
||||
extern fn ecs_new_w_table(world: *world_t, table: *table_t) entity_t;
|
||||
|
||||
/// `pub fn entity_init(world: *world_t, desc: *const entity_desc_t) entity_t`
|
||||
pub const entity_init = ecs_entity_init;
|
||||
extern fn ecs_entity_init(world: *world_t, desc: *const entity_desc_t) entity_t;
|
||||
@@ -1222,9 +1263,12 @@ extern fn ecs_get_hooks_id(world: *const world_t, id: entity_t) *const type_hook
|
||||
|
||||
/// `pub fn id_is_tag(world: *const world_t, id: id_t) bool;
|
||||
pub const id_is_tag = ecs_id_is_tag;
|
||||
// TODO: flecs upstream: missing const
|
||||
extern fn ecs_id_is_tag(world: *const world_t, id: id_t) bool;
|
||||
|
||||
/// `pub fn id_is_union(world: *const world_t, id: id_t) bool;
|
||||
pub const id_is_union = ecs_id_is_union;
|
||||
extern fn ecs_id_is_union(world: *const world_t, id: id_t) bool;
|
||||
|
||||
/// `pub fn id_in_use(world: *const world_t, id: id_t) bool`
|
||||
pub const id_in_use = ecs_id_in_use;
|
||||
// TODO: flecs upstream: missing const
|
||||
@@ -1322,8 +1366,9 @@ extern fn ecs_term_move(src: *term_t) term_t;
|
||||
pub const term_fini = ecs_term_fini;
|
||||
extern fn ecs_term_fini(term: *term_t) void;
|
||||
|
||||
/// `pub fn filter_init(world: *world_t, desc: *const filter_desc_t) ?*filter_t;`
|
||||
pub const filter_init = filter_init;
|
||||
pub fn filter_init(world: *world_t, desc: *const filter_desc_t) error_t!*filter_t {
|
||||
return ecs_filter_init(world, desc) orelse return make_error();
|
||||
}
|
||||
extern fn ecs_filter_init(world: *world_t, desc: *const filter_desc_t) ?*filter_t;
|
||||
|
||||
/// `pub fn filter_fini(filter: *filter_t) void`
|
||||
@@ -1378,7 +1423,14 @@ extern fn ecs_filter_copy(dst: *filter_t, src: *const filter_t) void;
|
||||
// Functions for working with `query_t`.
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// TODO:
|
||||
pub fn query_init(world: *world_t, desc: *const query_desc_t) error_t!*query_t {
|
||||
return ecs_query_init(world, desc) orelse return make_error();
|
||||
}
|
||||
extern fn ecs_query_init(world: *world_t, desc: *const query_desc_t) ?*query_t;
|
||||
|
||||
/// `pub fn query_fini(query: *query_t) void`
|
||||
pub const query_fini = ecs_query_fini;
|
||||
extern fn ecs_query_fini(query: *query_t) void;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Functions for working with events and observers.
|
||||
@@ -1491,11 +1543,18 @@ pub const iter_str = ecs_iter_str;
|
||||
extern fn ecs_iter_str(it: *const iter_t) ?[*:0]u8;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Functions for working with `table_t`.
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// TODO:
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Declarative functions (ECS_* macros in flecs)
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
// TODO: We support only one `world_t` at the time because type ids are stored in a global static memory.
|
||||
// We need to reset those ids to zero when the world is destroyed.
|
||||
// We need to reset those ids to zero when the world is destroyed
|
||||
// (we do this in `pub fn fini(world: *world_t) i32`).
|
||||
var num_worlds: u32 = 0;
|
||||
var component_ids_hm = std.AutoHashMap(*id_t, u0).init(std.heap.page_allocator);
|
||||
|
||||
@@ -1612,92 +1671,95 @@ pub const time_t = extern struct {
|
||||
sec: u32,
|
||||
nanosec: u32,
|
||||
};
|
||||
pub const os_thread_t = usize;
|
||||
pub const os_cond_t = usize;
|
||||
pub const os_mutex_t = usize;
|
||||
pub const os_dl_t = usize;
|
||||
pub const os_sock_t = usize;
|
||||
pub const os_thread_id_t = u64;
|
||||
pub const os_proc_t = *const fn () callconv(.C) void;
|
||||
pub const os_api_init_t = *const fn () callconv(.C) void;
|
||||
pub const os_api_fini_t = *const fn () callconv(.C) void;
|
||||
pub const os_api_malloc_t = *const fn (size_t) callconv(.C) ?*anyopaque;
|
||||
pub const os_api_free_t = *const fn (?*anyopaque) callconv(.C) void;
|
||||
pub const os_api_realloc_t = *const fn (?*anyopaque, size_t) callconv(.C) ?*anyopaque;
|
||||
pub const os_api_calloc_t = *const fn (size_t) callconv(.C) ?*anyopaque;
|
||||
pub const os_api_strdup_t = *const fn ([*:0]const u8) callconv(.C) [*c]u8;
|
||||
pub const os_thread_callback_t = *const fn (?*anyopaque) callconv(.C) ?*anyopaque;
|
||||
pub const os_api_thread_new_t = *const fn (os_thread_callback_t, ?*anyopaque) callconv(.C) os_thread_t;
|
||||
pub const os_api_thread_join_t = *const fn (os_thread_t) callconv(.C) ?*anyopaque;
|
||||
pub const os_api_thread_self_t = *const fn () callconv(.C) os_thread_id_t;
|
||||
pub const os_api_ainc_t = *const fn (*i32) callconv(.C) i32;
|
||||
pub const os_api_lainc_t = *const fn (*i64) callconv(.C) i64;
|
||||
pub const os_api_mutex_new_t = *const fn () callconv(.C) os_mutex_t;
|
||||
pub const os_api_mutex_lock_t = *const fn (os_mutex_t) callconv(.C) void;
|
||||
pub const os_api_mutex_unlock_t = *const fn (os_mutex_t) callconv(.C) void;
|
||||
pub const os_api_mutex_free_t = *const fn (os_mutex_t) callconv(.C) void;
|
||||
pub const os_api_cond_new_t = *const fn () callconv(.C) os_cond_t;
|
||||
pub const os_api_cond_free_t = *const fn (os_cond_t) callconv(.C) void;
|
||||
pub const os_api_cond_signal_t = *const fn (os_cond_t) callconv(.C) void;
|
||||
pub const os_api_cond_broadcast_t = *const fn (os_cond_t) callconv(.C) void;
|
||||
pub const os_api_cond_wait_t = *const fn (os_cond_t, os_mutex_t) callconv(.C) void;
|
||||
pub const os_api_sleep_t = *const fn (i32, i32) callconv(.C) void;
|
||||
pub const os_api_enable_high_timer_resolution_t = *const fn (bool) callconv(.C) void;
|
||||
pub const os_api_get_time_t = *const fn (*time_t) callconv(.C) void;
|
||||
pub const os_api_now_t = *const fn () callconv(.C) u64;
|
||||
pub const os_api_log_t = *const fn (i32, [*c]const u8, i32, [*:0]const u8) callconv(.C) void;
|
||||
pub const os_api_abort_t = *const fn () callconv(.C) void;
|
||||
pub const os_api_dlopen_t = *const fn ([*:0]const u8) callconv(.C) os_dl_t;
|
||||
pub const os_api_dlproc_t = *const fn (os_dl_t, [*:0]const u8) callconv(.C) os_proc_t;
|
||||
pub const os_api_dlclose_t = *const fn (os_dl_t) callconv(.C) void;
|
||||
pub const os_api_module_to_path_t = *const fn ([*:0]const u8) callconv(.C) [*:0]u8;
|
||||
|
||||
const os_api_t = extern struct {
|
||||
init_: os_api_init_t,
|
||||
fini_: os_api_fini_t,
|
||||
malloc_: os_api_malloc_t,
|
||||
realloc_: os_api_realloc_t,
|
||||
calloc_: os_api_calloc_t,
|
||||
free_: os_api_free_t,
|
||||
strdup_: os_api_strdup_t,
|
||||
thread_new_: os_api_thread_new_t,
|
||||
thread_join_: os_api_thread_join_t,
|
||||
thread_self_: os_api_thread_self_t,
|
||||
ainc_: os_api_ainc_t,
|
||||
adec_: os_api_ainc_t,
|
||||
lainc_: os_api_lainc_t,
|
||||
ladec_: os_api_lainc_t,
|
||||
mutex_new_: os_api_mutex_new_t,
|
||||
mutex_free_: os_api_mutex_free_t,
|
||||
mutex_lock_: os_api_mutex_lock_t,
|
||||
mutex_unlock_: os_api_mutex_lock_t,
|
||||
cond_new_: os_api_cond_new_t,
|
||||
cond_free_: os_api_cond_free_t,
|
||||
cond_signal_: os_api_cond_signal_t,
|
||||
cond_broadcast_: os_api_cond_broadcast_t,
|
||||
cond_wait_: os_api_cond_wait_t,
|
||||
sleep_: os_api_sleep_t,
|
||||
now_: os_api_now_t,
|
||||
get_time_: os_api_get_time_t,
|
||||
log_: os_api_log_t,
|
||||
abort_: os_api_abort_t,
|
||||
dlopen_: os_api_dlopen_t,
|
||||
dlproc_: os_api_dlproc_t,
|
||||
dlclose_: os_api_dlclose_t,
|
||||
module_to_dl_: os_api_module_to_path_t,
|
||||
module_to_etc_: os_api_module_to_path_t,
|
||||
log_level_: i32,
|
||||
log_indent_: i32,
|
||||
log_last_error_: i32,
|
||||
log_last_timestamp_: i64,
|
||||
flags_: flags32_t,
|
||||
pub const os = struct {
|
||||
pub const thread_t = usize;
|
||||
pub const cond_t = usize;
|
||||
pub const mutex_t = usize;
|
||||
pub const dl_t = usize;
|
||||
pub const sock_t = usize;
|
||||
pub const thread_id_t = u64;
|
||||
pub const proc_t = *const fn () callconv(.C) void;
|
||||
pub const api_init_t = *const fn () callconv(.C) void;
|
||||
pub const api_fini_t = *const fn () callconv(.C) void;
|
||||
pub const api_malloc_t = *const fn (size_t) callconv(.C) ?*anyopaque;
|
||||
pub const api_free_t = *const fn (?*anyopaque) callconv(.C) void;
|
||||
pub const api_realloc_t = *const fn (?*anyopaque, size_t) callconv(.C) ?*anyopaque;
|
||||
pub const api_calloc_t = *const fn (size_t) callconv(.C) ?*anyopaque;
|
||||
pub const api_strdup_t = *const fn ([*:0]const u8) callconv(.C) [*c]u8;
|
||||
pub const thread_callback_t = *const fn (?*anyopaque) callconv(.C) ?*anyopaque;
|
||||
pub const api_thread_new_t = *const fn (thread_callback_t, ?*anyopaque) callconv(.C) thread_t;
|
||||
pub const api_thread_join_t = *const fn (thread_t) callconv(.C) ?*anyopaque;
|
||||
pub const api_thread_self_t = *const fn () callconv(.C) thread_id_t;
|
||||
pub const api_ainc_t = *const fn (*i32) callconv(.C) i32;
|
||||
pub const api_lainc_t = *const fn (*i64) callconv(.C) i64;
|
||||
pub const api_mutex_new_t = *const fn () callconv(.C) mutex_t;
|
||||
pub const api_mutex_lock_t = *const fn (mutex_t) callconv(.C) void;
|
||||
pub const api_mutex_unlock_t = *const fn (mutex_t) callconv(.C) void;
|
||||
pub const api_mutex_free_t = *const fn (mutex_t) callconv(.C) void;
|
||||
pub const api_cond_new_t = *const fn () callconv(.C) cond_t;
|
||||
pub const api_cond_free_t = *const fn (cond_t) callconv(.C) void;
|
||||
pub const api_cond_signal_t = *const fn (cond_t) callconv(.C) void;
|
||||
pub const api_cond_broadcast_t = *const fn (cond_t) callconv(.C) void;
|
||||
pub const api_cond_wait_t = *const fn (cond_t, mutex_t) callconv(.C) void;
|
||||
pub const api_sleep_t = *const fn (i32, i32) callconv(.C) void;
|
||||
pub const api_enable_high_timer_resolution_t = *const fn (bool) callconv(.C) void;
|
||||
pub const api_get_time_t = *const fn (*time_t) callconv(.C) void;
|
||||
pub const api_now_t = *const fn () callconv(.C) u64;
|
||||
pub const api_log_t = *const fn (i32, [*:0]const u8, i32, [*:0]const u8) callconv(.C) void;
|
||||
pub const api_abort_t = *const fn () callconv(.C) void;
|
||||
pub const api_dlopen_t = *const fn ([*:0]const u8) callconv(.C) dl_t;
|
||||
pub const api_dlproc_t = *const fn (dl_t, [*:0]const u8) callconv(.C) proc_t;
|
||||
pub const api_dlclose_t = *const fn (dl_t) callconv(.C) void;
|
||||
pub const api_module_to_path_t = *const fn ([*:0]const u8) callconv(.C) [*:0]u8;
|
||||
|
||||
const api_t = extern struct {
|
||||
init_: api_init_t,
|
||||
fini_: api_fini_t,
|
||||
malloc_: api_malloc_t,
|
||||
realloc_: api_realloc_t,
|
||||
calloc_: api_calloc_t,
|
||||
free_: api_free_t,
|
||||
strdup_: api_strdup_t,
|
||||
thread_new_: api_thread_new_t,
|
||||
thread_join_: api_thread_join_t,
|
||||
thread_self_: api_thread_self_t,
|
||||
ainc_: api_ainc_t,
|
||||
adec_: api_ainc_t,
|
||||
lainc_: api_lainc_t,
|
||||
ladec_: api_lainc_t,
|
||||
mutex_new_: api_mutex_new_t,
|
||||
mutex_free_: api_mutex_free_t,
|
||||
mutex_lock_: api_mutex_lock_t,
|
||||
mutex_unlock_: api_mutex_lock_t,
|
||||
cond_new_: api_cond_new_t,
|
||||
cond_free_: api_cond_free_t,
|
||||
cond_signal_: api_cond_signal_t,
|
||||
cond_broadcast_: api_cond_broadcast_t,
|
||||
cond_wait_: api_cond_wait_t,
|
||||
sleep_: api_sleep_t,
|
||||
now_: api_now_t,
|
||||
get_time_: api_get_time_t,
|
||||
log_: api_log_t,
|
||||
abort_: api_abort_t,
|
||||
dlopen_: api_dlopen_t,
|
||||
dlproc_: api_dlproc_t,
|
||||
dlclose_: api_dlclose_t,
|
||||
module_to_dl_: api_module_to_path_t,
|
||||
module_to_etc_: api_module_to_path_t,
|
||||
log_level_: i32,
|
||||
log_indent_: i32,
|
||||
log_last_error_: i32,
|
||||
log_last_timestamp_: i64,
|
||||
flags_: flags32_t,
|
||||
};
|
||||
|
||||
extern var ecs_os_api: api_t;
|
||||
|
||||
pub fn free(ptr: ?*anyopaque) void {
|
||||
ecs_os_api.free_(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
extern var ecs_os_api: os_api_t;
|
||||
|
||||
pub fn os_free(ptr: ?*anyopaque) void {
|
||||
ecs_os_api.free_(ptr);
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
comptime {
|
||||
_ = @import("tests.zig");
|
||||
|
||||
@@ -93,6 +93,26 @@ while (...) {
|
||||
}
|
||||
```
|
||||
|
||||
### Building a shared library
|
||||
|
||||
If your project spans multiple zig modules that both use ImGui, such as an exe paired with a dll, you may want to build the `zgui` dependencies (`zgui_pkg.zgui_c_cpp`) as a shared library. This can be enabled with the `shared` build option. Then, in `build.zig`, use `zgui_pkg.link` to link `zgui` to all the modules that use ImGui.
|
||||
|
||||
When built this way, the ImGui context will be located in the shared library. However, the `zgui` zig code (which is compiled separately into each module) requires its own memory buffer which has to be initialized separately with `initNoContext`.
|
||||
|
||||
In your executable:
|
||||
```zig
|
||||
const zgui = @import("zgui");
|
||||
zgui.init(allocator);
|
||||
defer zgui.deinit();
|
||||
```
|
||||
|
||||
In your shared library:
|
||||
```zig
|
||||
const zgui = @import("zgui");
|
||||
zgui.initNoContext(allocator);
|
||||
defer zgui.deinitNoContxt();
|
||||
```
|
||||
|
||||
### DrawList API
|
||||
|
||||
```zig
|
||||
|
||||
+18
-1
@@ -8,6 +8,7 @@ pub const Package = struct {
|
||||
};
|
||||
pub const Options = struct {
|
||||
backend: Backend,
|
||||
shared: bool = false,
|
||||
};
|
||||
|
||||
options: Options,
|
||||
@@ -25,6 +26,7 @@ pub const Package = struct {
|
||||
) Package {
|
||||
const step = b.addOptions();
|
||||
step.addOption(Backend, "backend", args.options.backend);
|
||||
step.addOption(bool, "shared", args.options.shared);
|
||||
|
||||
const zgui_options = step.createModule();
|
||||
|
||||
@@ -35,7 +37,22 @@ pub const Package = struct {
|
||||
},
|
||||
});
|
||||
|
||||
const zgui_c_cpp = b.addStaticLibrary(.{
|
||||
const zgui_c_cpp = if (args.options.shared) blk: {
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "zgui",
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
lib.install();
|
||||
if (target.isWindows()) {
|
||||
lib.defineCMacro("IMGUI_API", "__declspec(dllexport)");
|
||||
lib.defineCMacro("IMPLOT_API", "__declspec(dllexport)");
|
||||
lib.defineCMacro("ZGUI_API", "__declspec(dllexport)");
|
||||
}
|
||||
|
||||
break :blk lib;
|
||||
} else b.addStaticLibrary(.{
|
||||
.name = "zgui",
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
|
||||
+32
-10
@@ -50,6 +50,17 @@ pub fn deinit() void {
|
||||
mem_allocator = null;
|
||||
}
|
||||
}
|
||||
pub fn initNoContext(allocator: std.mem.Allocator) void {
|
||||
if (temp_buffer == null) {
|
||||
temp_buffer = std.ArrayList(u8).init(allocator);
|
||||
temp_buffer.?.resize(3 * 1024 + 1) catch unreachable;
|
||||
}
|
||||
}
|
||||
pub fn deinitNoContext() void {
|
||||
if (temp_buffer) |buf| {
|
||||
buf.deinit();
|
||||
}
|
||||
}
|
||||
extern fn zguiCreateContext(shared_font_atlas: ?*const anyopaque) Context;
|
||||
extern fn zguiDestroyContext(ctx: ?Context) void;
|
||||
extern fn zguiGetCurrentContext() ?Context;
|
||||
@@ -92,16 +103,17 @@ extern fn zguiSetAllocatorFunctions(
|
||||
free_func: ?*const fn (?*anyopaque, ?*anyopaque) callconv(.C) void,
|
||||
) void;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub const ConfigFlags = enum(u32) {
|
||||
none = 0,
|
||||
nav_enable_keyboard = 1 << 0,
|
||||
nav_enable_gamepad = 1 << 1,
|
||||
nav_enable_set_mouse_pos = 1 << 2,
|
||||
nav_no_capture_keyboard = 1 << 3,
|
||||
no_mouse = 1 << 4,
|
||||
no_mouse_cursor_change = 1 << 5,
|
||||
is_srgb = 1 << 20,
|
||||
is_touch_screen = 1 << 21,
|
||||
pub const ConfigFlags = packed struct(u32) {
|
||||
nav_enable_keyboard: bool = false,
|
||||
nav_enable_gamepad: bool = false,
|
||||
nav_enable_set_mouse_pos: bool = false,
|
||||
nav_no_capture_keyboard: bool = false,
|
||||
no_mouse: bool = false,
|
||||
no_mouse_cursor_change: bool = false,
|
||||
user_storage: u14 = 0,
|
||||
is_srgb: bool = false,
|
||||
is_touch_screen: bool = false,
|
||||
_padding: u10 = 0,
|
||||
};
|
||||
|
||||
pub const FontConfig = extern struct {
|
||||
@@ -3061,6 +3073,15 @@ pub fn menuItem(label: [:0]const u8, args: MenuItem) bool {
|
||||
return zguiMenuItem(label, if (args.shortcut) |s| s.ptr else null, args.selected, args.enabled);
|
||||
}
|
||||
|
||||
const MenuItemPtr = struct {
|
||||
shortcut: ?[:0]const u8 = null,
|
||||
selected: *bool,
|
||||
enabled: bool = true,
|
||||
};
|
||||
pub fn menuItemPtr(label: [:0]const u8, args: MenuItemPtr) bool {
|
||||
return zguiMenuItemPtr(label, if (args.shortcut) |s| s.ptr else null, args.selected, args.enabled);
|
||||
}
|
||||
|
||||
extern fn zguiBeginMenuBar() bool;
|
||||
extern fn zguiEndMenuBar() void;
|
||||
extern fn zguiBeginMainMenuBar() bool;
|
||||
@@ -3068,6 +3089,7 @@ extern fn zguiEndMainMenuBar() void;
|
||||
extern fn zguiBeginMenu(label: [*:0]const u8, enabled: bool) bool;
|
||||
extern fn zguiEndMenu() void;
|
||||
extern fn zguiMenuItem(label: [*:0]const u8, shortcut: ?[*:0]const u8, selected: bool, enabled: bool) bool;
|
||||
extern fn zguiMenuItemPtr(label: [*:0]const u8, shortcut: ?[*:0]const u8, selected: *bool, enabled: bool) bool;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Popups
|
||||
|
||||
+10
-1
@@ -1,7 +1,11 @@
|
||||
#include "./imgui/imgui.h"
|
||||
#include "./imgui/implot.h"
|
||||
|
||||
#define ZGUI_API extern "C"
|
||||
#ifndef ZGUI_API
|
||||
#define ZGUI_API
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
||||
/*
|
||||
#include <stdio.h>
|
||||
@@ -1427,6 +1431,10 @@ ZGUI_API bool zguiMenuItem(const char* label, const char* shortcut, bool selecte
|
||||
return ImGui::MenuItem(label, shortcut, selected, enabled);
|
||||
}
|
||||
|
||||
ZGUI_API bool zguiMenuItemPtr(const char* label, const char* shortcut, bool* selected, bool enabled) {
|
||||
return ImGui::MenuItem(label, shortcut, selected, enabled);
|
||||
}
|
||||
|
||||
ZGUI_API void zguiBeginTooltip(void) {
|
||||
ImGui::BeginTooltip();
|
||||
}
|
||||
@@ -2300,3 +2308,4 @@ ZGUI_API void zguiPlot_EndPlot(void) {
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
} /* extern "C" */
|
||||
@@ -2544,7 +2544,7 @@ pub fn inverseDet(m: Mat, out_det: ?*F32x4) Mat {
|
||||
out_det.?.* = det;
|
||||
}
|
||||
|
||||
if (math.approxEqAbs(f32, det[0], 0.0, 0.0001)) {
|
||||
if (math.approxEqAbs(f32, det[0], 0.0, math.f32_epsilon)) {
|
||||
return .{
|
||||
f32x4(0.0, 0.0, 0.0, 0.0),
|
||||
f32x4(0.0, 0.0, 0.0, 0.0),
|
||||
|
||||
@@ -58,6 +58,7 @@ pub const Package = struct {
|
||||
zmesh_c_cpp.addCSourceFile(thisDir() ++ "/libs/meshoptimizer/vfetchanalyzer.cpp", &.{""});
|
||||
zmesh_c_cpp.addCSourceFile(thisDir() ++ "/libs/meshoptimizer/overdrawoptimizer.cpp", &.{""});
|
||||
zmesh_c_cpp.addCSourceFile(thisDir() ++ "/libs/meshoptimizer/overdrawanalyzer.cpp", &.{""});
|
||||
zmesh_c_cpp.addCSourceFile(thisDir() ++ "/libs/meshoptimizer/simplifier.cpp", &.{""});
|
||||
zmesh_c_cpp.addCSourceFile(thisDir() ++ "/libs/meshoptimizer/allocator.cpp", &.{""});
|
||||
|
||||
zmesh_c_cpp.addIncludePath(thisDir() ++ "/libs/cgltf");
|
||||
|
||||
@@ -187,7 +187,7 @@ size_t meshopt_generateVertexRemap(unsigned int* destination, const unsigned int
|
||||
using namespace meshopt;
|
||||
|
||||
assert(indices || index_count == vertex_count);
|
||||
assert(index_count % 3 == 0);
|
||||
assert(!indices || index_count % 3 == 0);
|
||||
assert(vertex_size > 0 && vertex_size <= 256);
|
||||
|
||||
meshopt_Allocator allocator;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* meshoptimizer - version 0.17
|
||||
* meshoptimizer - version 0.18
|
||||
*
|
||||
* Copyright (C) 2016-2021, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Copyright (C) 2016-2022, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
|
||||
* Report bugs and download new versions at https://github.com/zeux/meshoptimizer
|
||||
*
|
||||
* This library is distributed under the MIT License. See notice at the end of this file.
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <stddef.h>
|
||||
|
||||
/* Version macro; major * 1000 + minor * 10 + patch */
|
||||
#define MESHOPTIMIZER_VERSION 170 /* 0.17 */
|
||||
#define MESHOPTIMIZER_VERSION 180 /* 0.18 */
|
||||
|
||||
/* If no API is defined, assume default */
|
||||
#ifndef MESHOPTIMIZER_API
|
||||
@@ -313,7 +313,16 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterQuat(void* destination, size
|
||||
MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterExp(void* destination, size_t count, size_t stride, int bits, const float* data);
|
||||
|
||||
/**
|
||||
* Experimental: Mesh simplifier
|
||||
* Simplification options
|
||||
*/
|
||||
enum
|
||||
{
|
||||
/* Do not move vertices that are located on the topological border (vertices on triangle edges that don't have a paired triangle). Useful for simplifying portions of the larger mesh. */
|
||||
meshopt_SimplifyLockBorder = 1 << 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* Mesh simplifier
|
||||
* Reduces the number of triangles in the mesh, attempting to preserve mesh appearance as much as possible
|
||||
* The algorithm tries to preserve mesh topology and can stop short of the target goal based on topology constraints or target error.
|
||||
* If not all attributes from the input mesh are required, it's recommended to reindex the mesh using meshopt_generateShadowIndexBuffer prior to simplification.
|
||||
@@ -324,9 +333,10 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterExp(void* destination, size_
|
||||
* destination must contain enough space for the target index buffer, worst case is index_count elements (*not* target_index_count)!
|
||||
* vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
|
||||
* target_error represents the error relative to mesh extents that can be tolerated, e.g. 0.01 = 1% deformation
|
||||
* options must be a bitmask composed of meshopt_SimplifyX options; 0 is a safe default
|
||||
* result_error can be NULL; when it's not NULL, it will contain the resulting (relative) error after simplification
|
||||
*/
|
||||
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error);
|
||||
MESHOPTIMIZER_API size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* result_error);
|
||||
|
||||
/**
|
||||
* Experimental: Mesh simplifier (sloppy)
|
||||
@@ -356,12 +366,12 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifySloppy(unsigned int* destinati
|
||||
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyPoints(unsigned int* destination, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_vertex_count);
|
||||
|
||||
/**
|
||||
* Experimental: Returns the error scaling factor used by the simplifier to convert between absolute and relative extents
|
||||
* Returns the error scaling factor used by the simplifier to convert between absolute and relative extents
|
||||
*
|
||||
* Absolute error must be *divided* by the scaling factor before passing it to meshopt_simplify as target_error
|
||||
* Relative error returned by meshopt_simplify via result_error must be *multiplied* by the scaling factor to get absolute error.
|
||||
*/
|
||||
MESHOPTIMIZER_EXPERIMENTAL float meshopt_simplifyScale(const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
|
||||
MESHOPTIMIZER_API float meshopt_simplifyScale(const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
|
||||
|
||||
/**
|
||||
* Mesh stripifier
|
||||
@@ -605,7 +615,7 @@ inline size_t meshopt_encodeIndexSequence(unsigned char* buffer, size_t buffer_s
|
||||
template <typename T>
|
||||
inline int meshopt_decodeIndexSequence(T* destination, size_t index_count, const unsigned char* buffer, size_t buffer_size);
|
||||
template <typename T>
|
||||
inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error = 0);
|
||||
inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options = 0, float* result_error = 0);
|
||||
template <typename T>
|
||||
inline size_t meshopt_simplifySloppy(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error = 0);
|
||||
template <typename T>
|
||||
@@ -940,12 +950,12 @@ inline int meshopt_decodeIndexSequence(T* destination, size_t index_count, const
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error)
|
||||
inline size_t meshopt_simplify(T* destination, const T* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* result_error)
|
||||
{
|
||||
meshopt_IndexAdapter<T> in(0, indices, index_count);
|
||||
meshopt_IndexAdapter<T> out(destination, 0, index_count);
|
||||
|
||||
return meshopt_simplify(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error, result_error);
|
||||
return meshopt_simplify(out.data, in.data, index_count, vertex_positions, vertex_count, vertex_positions_stride, target_index_count, target_error, options, result_error);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -1034,7 +1044,7 @@ inline void meshopt_spatialSortTriangles(T* destination, const T* indices, size_
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Copyright (c) 2016-2021 Arseny Kapoulkine
|
||||
* Copyright (c) 2016-2022 Arseny Kapoulkine
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
|
||||
@@ -252,7 +252,7 @@ static bool hasEdge(const EdgeAdjacency& adjacency, unsigned int a, unsigned int
|
||||
return false;
|
||||
}
|
||||
|
||||
static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned int* loopback, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge)
|
||||
static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned int* loopback, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* wedge, unsigned int options)
|
||||
{
|
||||
memset(loop, -1, vertex_count * sizeof(unsigned int));
|
||||
memset(loopback, -1, vertex_count * sizeof(unsigned int));
|
||||
@@ -274,7 +274,15 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
|
||||
{
|
||||
unsigned int target = edges[j].next;
|
||||
|
||||
if (!hasEdge(adjacency, target, vertex))
|
||||
if (target == vertex)
|
||||
{
|
||||
// degenerate triangles have two distinct edges instead of three, and the self edge
|
||||
// is bi-directional by definition; this can break border/seam classification by "closing"
|
||||
// the open edge from another triangle and falsely marking the vertex as manifold
|
||||
// instead we mark the vertex as having >1 open edges which turns it into locked/complex
|
||||
openinc[vertex] = openout[vertex] = vertex;
|
||||
}
|
||||
else if (!hasEdge(adjacency, target, vertex))
|
||||
{
|
||||
openinc[target] = (openinc[target] == ~0u) ? vertex : target;
|
||||
openout[vertex] = (openout[vertex] == ~0u) ? target : vertex;
|
||||
@@ -354,6 +362,11 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
|
||||
}
|
||||
}
|
||||
|
||||
if (options & meshopt_SimplifyLockBorder)
|
||||
for (size_t i = 0; i < vertex_count; ++i)
|
||||
if (result[i] == Kind_Border)
|
||||
result[i] = Kind_Locked;
|
||||
|
||||
#if TRACE
|
||||
printf("locked: many open edges %d, disconnected seam %d, many seam edges %d, many wedges %d\n",
|
||||
int(stats[0]), int(stats[1]), int(stats[2]), int(stats[3]));
|
||||
@@ -1264,7 +1277,7 @@ MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoop = 0;
|
||||
MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = 0;
|
||||
#endif
|
||||
|
||||
size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error)
|
||||
size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, unsigned int options, float* out_result_error)
|
||||
{
|
||||
using namespace meshopt;
|
||||
|
||||
@@ -1272,6 +1285,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
||||
assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
|
||||
assert(vertex_positions_stride % sizeof(float) == 0);
|
||||
assert(target_index_count <= index_count);
|
||||
assert((options & ~(meshopt_SimplifyLockBorder)) == 0);
|
||||
|
||||
meshopt_Allocator allocator;
|
||||
|
||||
@@ -1291,7 +1305,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
|
||||
unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count);
|
||||
unsigned int* loop = allocator.allocate<unsigned int>(vertex_count);
|
||||
unsigned int* loopback = allocator.allocate<unsigned int>(vertex_count);
|
||||
classifyVertices(vertex_kind, loop, loopback, vertex_count, adjacency, remap, wedge);
|
||||
classifyVertices(vertex_kind, loop, loopback, vertex_count, adjacency, remap, wedge, options);
|
||||
|
||||
#if TRACE
|
||||
size_t unique_positions = 0;
|
||||
|
||||
@@ -152,6 +152,57 @@ pub inline fn analyzeVertexFetch(
|
||||
return meshopt_analyzeVertexFetch(indices.ptr, indices.len, vertex_count, vertex_size);
|
||||
}
|
||||
|
||||
// Simplifier
|
||||
pub inline fn simplify(
|
||||
comptime T: type,
|
||||
destination: []u32,
|
||||
indices: []const u32,
|
||||
index_count: usize,
|
||||
vertices: []const T,
|
||||
vertex_count: usize,
|
||||
target_index_count: usize,
|
||||
target_error: f32,
|
||||
options: u32,
|
||||
out_result_error: *f32,
|
||||
) usize {
|
||||
return meshopt_simplify(
|
||||
destination.ptr,
|
||||
indices.ptr,
|
||||
index_count,
|
||||
vertices.ptr,
|
||||
vertex_count,
|
||||
@sizeOf(T),
|
||||
target_index_count,
|
||||
target_error,
|
||||
options,
|
||||
out_result_error,
|
||||
);
|
||||
}
|
||||
|
||||
pub inline fn simplifySloppy(
|
||||
comptime T: type,
|
||||
destination: []u32,
|
||||
indices: []const u32,
|
||||
index_count: usize,
|
||||
vertices: []const T,
|
||||
vertex_count: usize,
|
||||
target_index_count: usize,
|
||||
target_error: f32,
|
||||
out_result_error: *f32,
|
||||
) usize {
|
||||
return meshopt_simplifySloppy(
|
||||
destination.ptr,
|
||||
indices.ptr,
|
||||
index_count,
|
||||
vertices.ptr,
|
||||
vertex_count,
|
||||
@sizeOf(T),
|
||||
target_index_count,
|
||||
target_error,
|
||||
out_result_error,
|
||||
);
|
||||
}
|
||||
|
||||
// Mesh shading
|
||||
pub inline fn buildMeshletsBound(index_count: usize, max_vertices: usize, max_triangles: usize) usize {
|
||||
return meshopt_buildMeshletsBound(index_count, max_vertices, max_triangles);
|
||||
@@ -255,6 +306,29 @@ extern fn meshopt_analyzeVertexFetch(
|
||||
vertex_count: usize,
|
||||
vertex_size: usize,
|
||||
) VertexFetchStatistics;
|
||||
extern fn meshopt_simplify(
|
||||
destination: [*]u32,
|
||||
indices: [*]const u32,
|
||||
index_count: usize,
|
||||
vertices: *const anyopaque,
|
||||
vertex_count: usize,
|
||||
vertex_stride: usize,
|
||||
target_index_count: usize,
|
||||
target_error: f32,
|
||||
options: u32,
|
||||
out_result_error: *f32,
|
||||
) usize;
|
||||
extern fn meshopt_simplifySloppy(
|
||||
destination: [*]u32,
|
||||
indices: [*]const u32,
|
||||
index_count: usize,
|
||||
vertices: *const anyopaque,
|
||||
vertex_count: usize,
|
||||
vertex_stride: usize,
|
||||
target_index_count: usize,
|
||||
target_error: f32,
|
||||
out_result_error: *f32,
|
||||
) usize;
|
||||
extern fn meshopt_buildMeshletsBound(
|
||||
index_count: usize,
|
||||
max_vertices: usize,
|
||||
|
||||
@@ -30,4 +30,9 @@ pub fn main() !void {
|
||||
|
||||
gl.clearBufferfv(gl.COLOR, 0, &[_]f32{ 0.2, 0.4, 0.8, 1.0 });
|
||||
}
|
||||
|
||||
fn getProcAddress(name: [:0]const u8) ?*anyopaque {
|
||||
// Load GL function pointer here
|
||||
// You could use `zsdl.gl.getProcAddress() or `zglfw.getProcAddress()`
|
||||
}
|
||||
```
|
||||
@@ -2414,7 +2414,7 @@ var loaderFunc: *const fn ([:0]const u8) ?*anyopaque = undefined;
|
||||
|
||||
fn getProcAddress(comptime T: type, name: [:0]const u8) !T {
|
||||
if (loaderFunc(name)) |addr| {
|
||||
return @ptrCast(T, @alignCast(@sizeOf(usize), addr));
|
||||
return @intToPtr(T, @ptrToInt(addr));
|
||||
}
|
||||
std.log.debug("zopengl: {s} not found", .{name});
|
||||
return error.OpenGL_FunctionNotFound;
|
||||
|
||||
@@ -67,7 +67,7 @@ pub fn Handle(
|
||||
const UInt = utils.UInt;
|
||||
const AddressableUInt = utils.AddressableUInt;
|
||||
|
||||
return struct {
|
||||
return extern struct {
|
||||
const Self = @This();
|
||||
|
||||
const HandleType = Self;
|
||||
|
||||
@@ -0,0 +1,500 @@
|
||||
pub const Scancode = enum(u32) {
|
||||
unknown = 0,
|
||||
a = 4,
|
||||
b = 5,
|
||||
c = 6,
|
||||
d = 7,
|
||||
e = 8,
|
||||
f = 9,
|
||||
g = 10,
|
||||
h = 11,
|
||||
i = 12,
|
||||
j = 13,
|
||||
k = 14,
|
||||
l = 15,
|
||||
m = 16,
|
||||
n = 17,
|
||||
o = 18,
|
||||
p = 19,
|
||||
q = 20,
|
||||
r = 21,
|
||||
s = 22,
|
||||
t = 23,
|
||||
u = 24,
|
||||
v = 25,
|
||||
w = 26,
|
||||
x = 27,
|
||||
y = 28,
|
||||
z = 29,
|
||||
@"1" = 30,
|
||||
@"2" = 31,
|
||||
@"3" = 32,
|
||||
@"4" = 33,
|
||||
@"5" = 34,
|
||||
@"6" = 35,
|
||||
@"7" = 36,
|
||||
@"8" = 37,
|
||||
@"9" = 38,
|
||||
@"0" = 39,
|
||||
@"return" = 40,
|
||||
escape = 41,
|
||||
backspace = 42,
|
||||
tab = 43,
|
||||
space = 44,
|
||||
minus = 45,
|
||||
equals = 46,
|
||||
leftbracket = 47,
|
||||
rightbracket = 48,
|
||||
backslash = 49,
|
||||
nonushash = 50,
|
||||
semicolon = 51,
|
||||
apostrophe = 52,
|
||||
grave = 53,
|
||||
comma = 54,
|
||||
period = 55,
|
||||
slash = 56,
|
||||
capslock = 57,
|
||||
f1 = 58,
|
||||
f2 = 59,
|
||||
f3 = 60,
|
||||
f4 = 61,
|
||||
f5 = 62,
|
||||
f6 = 63,
|
||||
f7 = 64,
|
||||
f8 = 65,
|
||||
f9 = 66,
|
||||
f10 = 67,
|
||||
f11 = 68,
|
||||
f12 = 69,
|
||||
printscreen = 70,
|
||||
scrolllock = 71,
|
||||
pause = 72,
|
||||
insert = 73,
|
||||
home = 74,
|
||||
pageup = 75,
|
||||
delete = 76,
|
||||
end = 77,
|
||||
pagedown = 78,
|
||||
right = 79,
|
||||
left = 80,
|
||||
down = 81,
|
||||
up = 82,
|
||||
numlockclear = 83,
|
||||
kp_divide = 84,
|
||||
kp_multiply = 85,
|
||||
kp_minus = 86,
|
||||
kp_plus = 87,
|
||||
kp_enter = 88,
|
||||
kp_1 = 89,
|
||||
kp_2 = 90,
|
||||
kp_3 = 91,
|
||||
kp_4 = 92,
|
||||
kp_5 = 93,
|
||||
kp_6 = 94,
|
||||
kp_7 = 95,
|
||||
kp_8 = 96,
|
||||
kp_9 = 97,
|
||||
kp_0 = 98,
|
||||
kp_period = 99,
|
||||
nonusbackslash = 100,
|
||||
application = 101,
|
||||
power = 102,
|
||||
kp_equals = 103,
|
||||
f13 = 104,
|
||||
f14 = 105,
|
||||
f15 = 106,
|
||||
f16 = 107,
|
||||
f17 = 108,
|
||||
f18 = 109,
|
||||
f19 = 110,
|
||||
f20 = 111,
|
||||
f21 = 112,
|
||||
f22 = 113,
|
||||
f23 = 114,
|
||||
f24 = 115,
|
||||
execute = 116,
|
||||
help = 117,
|
||||
menu = 118,
|
||||
select = 119,
|
||||
stop = 120,
|
||||
again = 121,
|
||||
undo = 122,
|
||||
cut = 123,
|
||||
copy = 124,
|
||||
paste = 125,
|
||||
find = 126,
|
||||
mute = 127,
|
||||
volumeup = 128,
|
||||
volumedown = 129,
|
||||
kp_comma = 133,
|
||||
kp_equalsas400 = 134,
|
||||
international1 = 135,
|
||||
international2 = 136,
|
||||
international3 = 137,
|
||||
international4 = 138,
|
||||
international5 = 139,
|
||||
international6 = 140,
|
||||
international7 = 141,
|
||||
international8 = 142,
|
||||
international9 = 143,
|
||||
lang1 = 144,
|
||||
lang2 = 145,
|
||||
lang3 = 146,
|
||||
lang4 = 147,
|
||||
lang5 = 148,
|
||||
lang6 = 149,
|
||||
lang7 = 150,
|
||||
lang8 = 151,
|
||||
lang9 = 152,
|
||||
alterase = 153,
|
||||
sysreq = 154,
|
||||
cancel = 155,
|
||||
clear = 156,
|
||||
prior = 157,
|
||||
return2 = 158,
|
||||
separator = 159,
|
||||
out = 160,
|
||||
oper = 161,
|
||||
clearagain = 162,
|
||||
crsel = 163,
|
||||
exsel = 164,
|
||||
kp_00 = 176,
|
||||
kp_000 = 177,
|
||||
thousandsseparator = 178,
|
||||
decimalseparator = 179,
|
||||
currencyunit = 180,
|
||||
currencysubunit = 181,
|
||||
kp_leftparen = 182,
|
||||
kp_rightparen = 183,
|
||||
kp_leftbrace = 184,
|
||||
kp_rightbrace = 185,
|
||||
kp_tab = 186,
|
||||
kp_backspace = 187,
|
||||
kp_a = 188,
|
||||
kp_b = 189,
|
||||
kp_c = 190,
|
||||
kp_d = 191,
|
||||
kp_e = 192,
|
||||
kp_f = 193,
|
||||
kp_xor = 194,
|
||||
kp_power = 195,
|
||||
kp_percent = 196,
|
||||
kp_less = 197,
|
||||
kp_greater = 198,
|
||||
kp_ampersand = 199,
|
||||
kp_dblampersand = 200,
|
||||
kp_verticalbar = 201,
|
||||
kp_dblverticalbar = 202,
|
||||
kp_colon = 203,
|
||||
kp_hash = 204,
|
||||
kp_space = 205,
|
||||
kp_at = 206,
|
||||
kp_exclam = 207,
|
||||
kp_memstore = 208,
|
||||
kp_memrecall = 209,
|
||||
kp_memclear = 210,
|
||||
kp_memadd = 211,
|
||||
kp_memsubtract = 212,
|
||||
kp_memmultiply = 213,
|
||||
kp_memdivide = 214,
|
||||
kp_plusminus = 215,
|
||||
kp_clear = 216,
|
||||
kp_clearentry = 217,
|
||||
kp_binary = 218,
|
||||
kp_octal = 219,
|
||||
kp_decimal = 220,
|
||||
kp_hexadecimal = 221,
|
||||
lctrl = 224,
|
||||
lshift = 225,
|
||||
lalt = 226,
|
||||
lgui = 227,
|
||||
rctrl = 228,
|
||||
rshift = 229,
|
||||
ralt = 230,
|
||||
rgui = 231,
|
||||
mode = 257,
|
||||
audionext = 258,
|
||||
audioprev = 259,
|
||||
audiostop = 260,
|
||||
audioplay = 261,
|
||||
audiomute = 262,
|
||||
mediaselect = 263,
|
||||
www = 264,
|
||||
mail = 265,
|
||||
calculator = 266,
|
||||
computer = 267,
|
||||
ac_search = 268,
|
||||
ac_home = 269,
|
||||
ac_back = 270,
|
||||
ac_forward = 271,
|
||||
ac_stop = 272,
|
||||
ac_refresh = 273,
|
||||
ac_bookmarks = 274,
|
||||
brightnessdown = 275,
|
||||
brightnessup = 276,
|
||||
displayswitch = 277,
|
||||
kbdillumtoggle = 278,
|
||||
kbdillumdown = 279,
|
||||
kbdillumup = 280,
|
||||
eject = 281,
|
||||
sleep = 282,
|
||||
app1 = 283,
|
||||
app2 = 284,
|
||||
audiorewind = 285,
|
||||
audiofastforward = 286,
|
||||
softleft = 287,
|
||||
softright = 288,
|
||||
call = 289,
|
||||
endcall = 290,
|
||||
_,
|
||||
};
|
||||
|
||||
pub const Keycode = enum(i32) {
|
||||
unknown = 0,
|
||||
@"return" = '\r',
|
||||
escape = '\x1b',
|
||||
backspace = '\x08',
|
||||
tab = '\t',
|
||||
space = ' ',
|
||||
exclaim = '!',
|
||||
quotedbl = '"',
|
||||
hash = '#',
|
||||
percent = '%',
|
||||
dollar = '$',
|
||||
ampersand = '&',
|
||||
quote = '\'',
|
||||
leftparen = '(',
|
||||
rightparen = ')',
|
||||
asterisk = '*',
|
||||
plus = '+',
|
||||
comma = ',',
|
||||
minus = '-',
|
||||
period = '.',
|
||||
slash = '/',
|
||||
@"0" = '0',
|
||||
@"1" = '1',
|
||||
@"2" = '2',
|
||||
@"3" = '3',
|
||||
@"4" = '4',
|
||||
@"5" = '5',
|
||||
@"6" = '6',
|
||||
@"7" = '7',
|
||||
@"8" = '8',
|
||||
@"9" = '9',
|
||||
colon = ':',
|
||||
semicolon = ';',
|
||||
less = '<',
|
||||
equals = '=',
|
||||
greater = '>',
|
||||
question = '?',
|
||||
at = '@',
|
||||
leftbracket = '[',
|
||||
backslash = '\\',
|
||||
rightbracket = ']',
|
||||
caret = '^',
|
||||
underscore = '_',
|
||||
backquote = '`',
|
||||
a = 'a',
|
||||
b = 'b',
|
||||
c = 'c',
|
||||
d = 'd',
|
||||
e = 'e',
|
||||
f = 'f',
|
||||
g = 'g',
|
||||
h = 'h',
|
||||
i = 'i',
|
||||
j = 'j',
|
||||
k = 'k',
|
||||
l = 'l',
|
||||
m = 'm',
|
||||
n = 'n',
|
||||
o = 'o',
|
||||
p = 'p',
|
||||
q = 'q',
|
||||
r = 'r',
|
||||
s = 's',
|
||||
t = 't',
|
||||
u = 'u',
|
||||
v = 'v',
|
||||
w = 'w',
|
||||
x = 'x',
|
||||
y = 'y',
|
||||
z = 'z',
|
||||
capslock = @enumToInt(Scancode.capslock) | mask,
|
||||
f1 = @enumToInt(Scancode.f1) | mask,
|
||||
f2 = @enumToInt(Scancode.f2) | mask,
|
||||
f3 = @enumToInt(Scancode.f3) | mask,
|
||||
f4 = @enumToInt(Scancode.f4) | mask,
|
||||
f5 = @enumToInt(Scancode.f5) | mask,
|
||||
f6 = @enumToInt(Scancode.f6) | mask,
|
||||
f7 = @enumToInt(Scancode.f7) | mask,
|
||||
f8 = @enumToInt(Scancode.f8) | mask,
|
||||
f9 = @enumToInt(Scancode.f9) | mask,
|
||||
f10 = @enumToInt(Scancode.f10) | mask,
|
||||
f11 = @enumToInt(Scancode.f11) | mask,
|
||||
f12 = @enumToInt(Scancode.f12) | mask,
|
||||
printscreen = @enumToInt(Scancode.printscreen) | mask,
|
||||
scrolllock = @enumToInt(Scancode.scrolllock) | mask,
|
||||
pause = @enumToInt(Scancode.pause) | mask,
|
||||
insert = @enumToInt(Scancode.insert) | mask,
|
||||
home = @enumToInt(Scancode.home) | mask,
|
||||
pageup = @enumToInt(Scancode.pageup) | mask,
|
||||
delete = '\x7f',
|
||||
end = @enumToInt(Scancode.end) | mask,
|
||||
pagedown = @enumToInt(Scancode.pagedown) | mask,
|
||||
right = @enumToInt(Scancode.right) | mask,
|
||||
left = @enumToInt(Scancode.left) | mask,
|
||||
down = @enumToInt(Scancode.down) | mask,
|
||||
up = @enumToInt(Scancode.up) | mask,
|
||||
numlockclear = @enumToInt(Scancode.numlockclear) | mask,
|
||||
kp_divide = @enumToInt(Scancode.kp_divide) | mask,
|
||||
kp_multiply = @enumToInt(Scancode.kp_multiply) | mask,
|
||||
kp_minus = @enumToInt(Scancode.kp_minus) | mask,
|
||||
kp_plus = @enumToInt(Scancode.kp_plus) | mask,
|
||||
kp_enter = @enumToInt(Scancode.kp_enter) | mask,
|
||||
kp_1 = @enumToInt(Scancode.kp_1) | mask,
|
||||
kp_2 = @enumToInt(Scancode.kp_2) | mask,
|
||||
kp_3 = @enumToInt(Scancode.kp_3) | mask,
|
||||
kp_4 = @enumToInt(Scancode.kp_4) | mask,
|
||||
kp_5 = @enumToInt(Scancode.kp_5) | mask,
|
||||
kp_6 = @enumToInt(Scancode.kp_6) | mask,
|
||||
kp_7 = @enumToInt(Scancode.kp_7) | mask,
|
||||
kp_8 = @enumToInt(Scancode.kp_8) | mask,
|
||||
kp_9 = @enumToInt(Scancode.kp_9) | mask,
|
||||
kp_0 = @enumToInt(Scancode.kp_0) | mask,
|
||||
kp_period = @enumToInt(Scancode.kp_period) | mask,
|
||||
application = @enumToInt(Scancode.application) | mask,
|
||||
power = @enumToInt(Scancode.power) | mask,
|
||||
kp_equals = @enumToInt(Scancode.kp_equals) | mask,
|
||||
f13 = @enumToInt(Scancode.f13) | mask,
|
||||
f14 = @enumToInt(Scancode.f14) | mask,
|
||||
f15 = @enumToInt(Scancode.f15) | mask,
|
||||
f16 = @enumToInt(Scancode.f16) | mask,
|
||||
f17 = @enumToInt(Scancode.f17) | mask,
|
||||
f18 = @enumToInt(Scancode.f18) | mask,
|
||||
f19 = @enumToInt(Scancode.f19) | mask,
|
||||
f20 = @enumToInt(Scancode.f20) | mask,
|
||||
f21 = @enumToInt(Scancode.f21) | mask,
|
||||
f22 = @enumToInt(Scancode.f22) | mask,
|
||||
f23 = @enumToInt(Scancode.f23) | mask,
|
||||
f24 = @enumToInt(Scancode.f24) | mask,
|
||||
execute = @enumToInt(Scancode.execute) | mask,
|
||||
help = @enumToInt(Scancode.help) | mask,
|
||||
menu = @enumToInt(Scancode.menu) | mask,
|
||||
select = @enumToInt(Scancode.select) | mask,
|
||||
stop = @enumToInt(Scancode.stop) | mask,
|
||||
again = @enumToInt(Scancode.again) | mask,
|
||||
undo = @enumToInt(Scancode.undo) | mask,
|
||||
cut = @enumToInt(Scancode.cut) | mask,
|
||||
copy = @enumToInt(Scancode.copy) | mask,
|
||||
paste = @enumToInt(Scancode.paste) | mask,
|
||||
find = @enumToInt(Scancode.find) | mask,
|
||||
mute = @enumToInt(Scancode.mute) | mask,
|
||||
volumeup = @enumToInt(Scancode.volumeup) | mask,
|
||||
volumedown = @enumToInt(Scancode.volumedown) | mask,
|
||||
kp_comma = @enumToInt(Scancode.kp_comma) | mask,
|
||||
kp_equalsas400 = @enumToInt(Scancode.kp_equalsas400) | mask,
|
||||
alterase = @enumToInt(Scancode.alterase) | mask,
|
||||
sysreq = @enumToInt(Scancode.sysreq) | mask,
|
||||
cancel = @enumToInt(Scancode.cancel) | mask,
|
||||
clear = @enumToInt(Scancode.clear) | mask,
|
||||
prior = @enumToInt(Scancode.prior) | mask,
|
||||
return2 = @enumToInt(Scancode.return2) | mask,
|
||||
separator = @enumToInt(Scancode.separator) | mask,
|
||||
out = @enumToInt(Scancode.out) | mask,
|
||||
oper = @enumToInt(Scancode.oper) | mask,
|
||||
clearagain = @enumToInt(Scancode.clearagain) | mask,
|
||||
crsel = @enumToInt(Scancode.crsel) | mask,
|
||||
exsel = @enumToInt(Scancode.exsel) | mask,
|
||||
kp_00 = @enumToInt(Scancode.kp_00) | mask,
|
||||
kp_000 = @enumToInt(Scancode.kp_000) | mask,
|
||||
thousandsseparator = @enumToInt(Scancode.thousandsseparator) | mask,
|
||||
decimalseparator = @enumToInt(Scancode.decimalseparator) | mask,
|
||||
currencyunit = @enumToInt(Scancode.currencyunit) | mask,
|
||||
currencysubunit = @enumToInt(Scancode.currencysubunit) | mask,
|
||||
kp_leftparen = @enumToInt(Scancode.kp_leftparen) | mask,
|
||||
kp_rightparen = @enumToInt(Scancode.kp_rightparen) | mask,
|
||||
kp_leftbrace = @enumToInt(Scancode.kp_leftbrace) | mask,
|
||||
kp_rightbrace = @enumToInt(Scancode.kp_rightbrace) | mask,
|
||||
kp_tab = @enumToInt(Scancode.kp_tab) | mask,
|
||||
kp_backspace = @enumToInt(Scancode.kp_backspace) | mask,
|
||||
kp_a = @enumToInt(Scancode.kp_a) | mask,
|
||||
kp_b = @enumToInt(Scancode.kp_b) | mask,
|
||||
kp_c = @enumToInt(Scancode.kp_c) | mask,
|
||||
kp_d = @enumToInt(Scancode.kp_d) | mask,
|
||||
kp_e = @enumToInt(Scancode.kp_e) | mask,
|
||||
kp_f = @enumToInt(Scancode.kp_f) | mask,
|
||||
kp_xor = @enumToInt(Scancode.kp_xor) | mask,
|
||||
kp_power = @enumToInt(Scancode.kp_power) | mask,
|
||||
kp_percent = @enumToInt(Scancode.kp_percent) | mask,
|
||||
kp_less = @enumToInt(Scancode.kp_less) | mask,
|
||||
kp_greater = @enumToInt(Scancode.kp_greater) | mask,
|
||||
kp_ampersand = @enumToInt(Scancode.kp_ampersand) | mask,
|
||||
kp_dblampersand = @enumToInt(Scancode.kp_dblampersand) | mask,
|
||||
kp_verticalbar = @enumToInt(Scancode.kp_verticalbar) | mask,
|
||||
kp_dblverticalbar = @enumToInt(Scancode.kp_dblverticalbar) | mask,
|
||||
kp_colon = @enumToInt(Scancode.kp_colon) | mask,
|
||||
kp_hash = @enumToInt(Scancode.kp_hash) | mask,
|
||||
kp_space = @enumToInt(Scancode.kp_space) | mask,
|
||||
kp_at = @enumToInt(Scancode.kp_at) | mask,
|
||||
kp_exclam = @enumToInt(Scancode.kp_exclam) | mask,
|
||||
kp_memstore = @enumToInt(Scancode.kp_memstore) | mask,
|
||||
kp_memrecall = @enumToInt(Scancode.kp_memrecall) | mask,
|
||||
kp_memclear = @enumToInt(Scancode.kp_memclear) | mask,
|
||||
kp_memadd = @enumToInt(Scancode.kp_memadd) | mask,
|
||||
kp_memsubtract = @enumToInt(Scancode.kp_memsubtract) | mask,
|
||||
kp_memmultiply = @enumToInt(Scancode.kp_memmultiply) | mask,
|
||||
kp_memdivide = @enumToInt(Scancode.kp_memdivide) | mask,
|
||||
kp_plusminus = @enumToInt(Scancode.kp_plusminus) | mask,
|
||||
kp_clear = @enumToInt(Scancode.kp_clear) | mask,
|
||||
kp_clearentry = @enumToInt(Scancode.kp_clearentry) | mask,
|
||||
kp_binary = @enumToInt(Scancode.kp_binary) | mask,
|
||||
kp_octal = @enumToInt(Scancode.kp_octal) | mask,
|
||||
kp_decimal = @enumToInt(Scancode.kp_decimal) | mask,
|
||||
kp_hexadecimal = @enumToInt(Scancode.kp_hexadecimal) | mask,
|
||||
lctrl = @enumToInt(Scancode.lctrl) | mask,
|
||||
lshift = @enumToInt(Scancode.lshift) | mask,
|
||||
lalt = @enumToInt(Scancode.lalt) | mask,
|
||||
lgui = @enumToInt(Scancode.lgui) | mask,
|
||||
rctrl = @enumToInt(Scancode.rctrl) | mask,
|
||||
rshift = @enumToInt(Scancode.rshift) | mask,
|
||||
ralt = @enumToInt(Scancode.ralt) | mask,
|
||||
rgui = @enumToInt(Scancode.rgui) | mask,
|
||||
mode = @enumToInt(Scancode.mode) | mask,
|
||||
audionext = @enumToInt(Scancode.audionext) | mask,
|
||||
audioprev = @enumToInt(Scancode.audioprev) | mask,
|
||||
audiostop = @enumToInt(Scancode.audiostop) | mask,
|
||||
audioplay = @enumToInt(Scancode.audioplay) | mask,
|
||||
audiomute = @enumToInt(Scancode.audiomute) | mask,
|
||||
mediaselect = @enumToInt(Scancode.mediaselect) | mask,
|
||||
www = @enumToInt(Scancode.www) | mask,
|
||||
mail = @enumToInt(Scancode.mail) | mask,
|
||||
calculator = @enumToInt(Scancode.calculator) | mask,
|
||||
computer = @enumToInt(Scancode.computer) | mask,
|
||||
ac_search = @enumToInt(Scancode.ac_search) | mask,
|
||||
ac_home = @enumToInt(Scancode.ac_home) | mask,
|
||||
ac_back = @enumToInt(Scancode.ac_back) | mask,
|
||||
ac_forward = @enumToInt(Scancode.ac_forward) | mask,
|
||||
ac_stop = @enumToInt(Scancode.ac_stop) | mask,
|
||||
ac_refresh = @enumToInt(Scancode.ac_refresh) | mask,
|
||||
ac_bookmarks = @enumToInt(Scancode.ac_bookmarks) | mask,
|
||||
brightnessdown = @enumToInt(Scancode.brightnessdown) | mask,
|
||||
brightnessup = @enumToInt(Scancode.brightnessup) | mask,
|
||||
displayswitch = @enumToInt(Scancode.displayswitch) | mask,
|
||||
kbdillumtoggle = @enumToInt(Scancode.kbdillumtoggle) | mask,
|
||||
kbdillumdown = @enumToInt(Scancode.kbdillumdown) | mask,
|
||||
kbdillumup = @enumToInt(Scancode.kbdillumup) | mask,
|
||||
eject = @enumToInt(Scancode.eject) | mask,
|
||||
sleep = @enumToInt(Scancode.sleep) | mask,
|
||||
app1 = @enumToInt(Scancode.app1) | mask,
|
||||
app2 = @enumToInt(Scancode.app2) | mask,
|
||||
audiorewind = @enumToInt(Scancode.audiorewind) | mask,
|
||||
audiofastforward = @enumToInt(Scancode.audiofastforward) | mask,
|
||||
softleft = @enumToInt(Scancode.softleft) | mask,
|
||||
softright = @enumToInt(Scancode.softright) | mask,
|
||||
call = @enumToInt(Scancode.call) | mask,
|
||||
endcall = @enumToInt(Scancode.endcall) | mask,
|
||||
_,
|
||||
|
||||
const mask = 1 << 30;
|
||||
};
|
||||
+112
-537
@@ -1,6 +1,10 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Init
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub const InitFlags = packed struct(u32) {
|
||||
timer: bool = false,
|
||||
__unused1: bool = false,
|
||||
@@ -45,13 +49,16 @@ extern fn SDL_Init(flags: InitFlags) i32;
|
||||
/// `pub fn quit() void`
|
||||
pub const quit = SDL_Quit;
|
||||
extern fn SDL_Quit() void;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Error
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub fn getError() ?[:0]const u8 {
|
||||
if (SDL_GetError()) |cstr| {
|
||||
return std.mem.sliceTo(cstr, 0);
|
||||
} else {
|
||||
return null;
|
||||
if (SDL_GetError()) |ptr| {
|
||||
return std.mem.sliceTo(ptr, 0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
extern fn SDL_GetError() ?[*:0]const u8;
|
||||
|
||||
@@ -63,7 +70,55 @@ pub fn makeError() error{SdlError} {
|
||||
}
|
||||
return error.SdlError;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Video driver
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// `pub fn getNumVideoDrivers() i32`
|
||||
pub const getNumVideoDrivers = SDL_GetNumVideoDrivers;
|
||||
extern fn SDL_GetNumVideoDrivers() i32;
|
||||
|
||||
pub fn getVideoDriver(index: i32) ?[:0]const u8 {
|
||||
if (SDL_GetVideoDriver(index)) |ptr| {
|
||||
return std.mem.sliceTo(ptr, 0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
extern fn SDL_GetVideoDriver(index: i32) ?[*:0]const u8;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Display
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub const DisplayId = u32;
|
||||
|
||||
pub const DisplayMode = DisplayMode_SDL2;
|
||||
|
||||
const DisplayMode_SDL2 = extern struct {
|
||||
format: u32,
|
||||
w: i32,
|
||||
h: i32,
|
||||
refresh_rate: i32,
|
||||
driverdata: ?*anyopaque,
|
||||
};
|
||||
|
||||
const DisplayMode_SDL3 = extern struct {
|
||||
display_id: DisplayId,
|
||||
format: u32,
|
||||
pixel_w: i32,
|
||||
pixel_h: i32,
|
||||
screen_w: i32,
|
||||
screen_h: i32,
|
||||
display_scale: f32,
|
||||
refresh_rate: f32,
|
||||
driverdata: ?*anyopaque,
|
||||
};
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Window
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub const Window = opaque {
|
||||
pub const Flags = packed struct(u32) {
|
||||
fullscreen: bool = false,
|
||||
@@ -124,14 +179,22 @@ pub const Window = opaque {
|
||||
pub const destroy = SDL_DestroyWindow;
|
||||
extern fn SDL_DestroyWindow(window: *Window) void;
|
||||
|
||||
pub fn getDisplayMode(window: *Window) DisplayMode {
|
||||
pub fn getDisplayMode(window: *Window) Error!DisplayMode {
|
||||
var mode: DisplayMode = undefined;
|
||||
SDL_GetWindowDisplayMode(window, &mode);
|
||||
if (SDL_GetWindowDisplayMode(window, &mode) < 0) return makeError();
|
||||
return mode;
|
||||
}
|
||||
extern fn SDL_GetWindowDisplayMode(*Window, *DisplayMode) void;
|
||||
};
|
||||
extern fn SDL_GetWindowDisplayMode(window: *Window, mode: *DisplayMode) void;
|
||||
|
||||
/// `pub fn getSize(window: *Window, w: ?*i32, h: ?*i32) void`
|
||||
pub const getSize = SDL_GetWindowSize;
|
||||
extern fn SDL_GetWindowSize(window: *Window, w: ?*i32, h: ?*i32) void;
|
||||
};
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Events
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub const EventType = enum(u32) {
|
||||
firstevent = 0,
|
||||
|
||||
@@ -253,506 +316,9 @@ pub const MouseWheelDirection = enum(u32) {
|
||||
flipped,
|
||||
};
|
||||
|
||||
pub const Scancode = enum(u32) {
|
||||
unknown = 0,
|
||||
a = 4,
|
||||
b = 5,
|
||||
c = 6,
|
||||
d = 7,
|
||||
e = 8,
|
||||
f = 9,
|
||||
g = 10,
|
||||
h = 11,
|
||||
i = 12,
|
||||
j = 13,
|
||||
k = 14,
|
||||
l = 15,
|
||||
m = 16,
|
||||
n = 17,
|
||||
o = 18,
|
||||
p = 19,
|
||||
q = 20,
|
||||
r = 21,
|
||||
s = 22,
|
||||
t = 23,
|
||||
u = 24,
|
||||
v = 25,
|
||||
w = 26,
|
||||
x = 27,
|
||||
y = 28,
|
||||
z = 29,
|
||||
@"1" = 30,
|
||||
@"2" = 31,
|
||||
@"3" = 32,
|
||||
@"4" = 33,
|
||||
@"5" = 34,
|
||||
@"6" = 35,
|
||||
@"7" = 36,
|
||||
@"8" = 37,
|
||||
@"9" = 38,
|
||||
@"0" = 39,
|
||||
@"return" = 40,
|
||||
escape = 41,
|
||||
backspace = 42,
|
||||
tab = 43,
|
||||
space = 44,
|
||||
minus = 45,
|
||||
equals = 46,
|
||||
leftbracket = 47,
|
||||
rightbracket = 48,
|
||||
backslash = 49,
|
||||
nonushash = 50,
|
||||
semicolon = 51,
|
||||
apostrophe = 52,
|
||||
grave = 53,
|
||||
comma = 54,
|
||||
period = 55,
|
||||
slash = 56,
|
||||
capslock = 57,
|
||||
f1 = 58,
|
||||
f2 = 59,
|
||||
f3 = 60,
|
||||
f4 = 61,
|
||||
f5 = 62,
|
||||
f6 = 63,
|
||||
f7 = 64,
|
||||
f8 = 65,
|
||||
f9 = 66,
|
||||
f10 = 67,
|
||||
f11 = 68,
|
||||
f12 = 69,
|
||||
printscreen = 70,
|
||||
scrolllock = 71,
|
||||
pause = 72,
|
||||
insert = 73,
|
||||
home = 74,
|
||||
pageup = 75,
|
||||
delete = 76,
|
||||
end = 77,
|
||||
pagedown = 78,
|
||||
right = 79,
|
||||
left = 80,
|
||||
down = 81,
|
||||
up = 82,
|
||||
numlockclear = 83,
|
||||
kp_divide = 84,
|
||||
kp_multiply = 85,
|
||||
kp_minus = 86,
|
||||
kp_plus = 87,
|
||||
kp_enter = 88,
|
||||
kp_1 = 89,
|
||||
kp_2 = 90,
|
||||
kp_3 = 91,
|
||||
kp_4 = 92,
|
||||
kp_5 = 93,
|
||||
kp_6 = 94,
|
||||
kp_7 = 95,
|
||||
kp_8 = 96,
|
||||
kp_9 = 97,
|
||||
kp_0 = 98,
|
||||
kp_period = 99,
|
||||
nonusbackslash = 100,
|
||||
application = 101,
|
||||
power = 102,
|
||||
kp_equals = 103,
|
||||
f13 = 104,
|
||||
f14 = 105,
|
||||
f15 = 106,
|
||||
f16 = 107,
|
||||
f17 = 108,
|
||||
f18 = 109,
|
||||
f19 = 110,
|
||||
f20 = 111,
|
||||
f21 = 112,
|
||||
f22 = 113,
|
||||
f23 = 114,
|
||||
f24 = 115,
|
||||
execute = 116,
|
||||
help = 117,
|
||||
menu = 118,
|
||||
select = 119,
|
||||
stop = 120,
|
||||
again = 121,
|
||||
undo = 122,
|
||||
cut = 123,
|
||||
copy = 124,
|
||||
paste = 125,
|
||||
find = 126,
|
||||
mute = 127,
|
||||
volumeup = 128,
|
||||
volumedown = 129,
|
||||
kp_comma = 133,
|
||||
kp_equalsas400 = 134,
|
||||
international1 = 135,
|
||||
international2 = 136,
|
||||
international3 = 137,
|
||||
international4 = 138,
|
||||
international5 = 139,
|
||||
international6 = 140,
|
||||
international7 = 141,
|
||||
international8 = 142,
|
||||
international9 = 143,
|
||||
lang1 = 144,
|
||||
lang2 = 145,
|
||||
lang3 = 146,
|
||||
lang4 = 147,
|
||||
lang5 = 148,
|
||||
lang6 = 149,
|
||||
lang7 = 150,
|
||||
lang8 = 151,
|
||||
lang9 = 152,
|
||||
alterase = 153,
|
||||
sysreq = 154,
|
||||
cancel = 155,
|
||||
clear = 156,
|
||||
prior = 157,
|
||||
return2 = 158,
|
||||
separator = 159,
|
||||
out = 160,
|
||||
oper = 161,
|
||||
clearagain = 162,
|
||||
crsel = 163,
|
||||
exsel = 164,
|
||||
kp_00 = 176,
|
||||
kp_000 = 177,
|
||||
thousandsseparator = 178,
|
||||
decimalseparator = 179,
|
||||
currencyunit = 180,
|
||||
currencysubunit = 181,
|
||||
kp_leftparen = 182,
|
||||
kp_rightparen = 183,
|
||||
kp_leftbrace = 184,
|
||||
kp_rightbrace = 185,
|
||||
kp_tab = 186,
|
||||
kp_backspace = 187,
|
||||
kp_a = 188,
|
||||
kp_b = 189,
|
||||
kp_c = 190,
|
||||
kp_d = 191,
|
||||
kp_e = 192,
|
||||
kp_f = 193,
|
||||
kp_xor = 194,
|
||||
kp_power = 195,
|
||||
kp_percent = 196,
|
||||
kp_less = 197,
|
||||
kp_greater = 198,
|
||||
kp_ampersand = 199,
|
||||
kp_dblampersand = 200,
|
||||
kp_verticalbar = 201,
|
||||
kp_dblverticalbar = 202,
|
||||
kp_colon = 203,
|
||||
kp_hash = 204,
|
||||
kp_space = 205,
|
||||
kp_at = 206,
|
||||
kp_exclam = 207,
|
||||
kp_memstore = 208,
|
||||
kp_memrecall = 209,
|
||||
kp_memclear = 210,
|
||||
kp_memadd = 211,
|
||||
kp_memsubtract = 212,
|
||||
kp_memmultiply = 213,
|
||||
kp_memdivide = 214,
|
||||
kp_plusminus = 215,
|
||||
kp_clear = 216,
|
||||
kp_clearentry = 217,
|
||||
kp_binary = 218,
|
||||
kp_octal = 219,
|
||||
kp_decimal = 220,
|
||||
kp_hexadecimal = 221,
|
||||
lctrl = 224,
|
||||
lshift = 225,
|
||||
lalt = 226,
|
||||
lgui = 227,
|
||||
rctrl = 228,
|
||||
rshift = 229,
|
||||
ralt = 230,
|
||||
rgui = 231,
|
||||
mode = 257,
|
||||
audionext = 258,
|
||||
audioprev = 259,
|
||||
audiostop = 260,
|
||||
audioplay = 261,
|
||||
audiomute = 262,
|
||||
mediaselect = 263,
|
||||
www = 264,
|
||||
mail = 265,
|
||||
calculator = 266,
|
||||
computer = 267,
|
||||
ac_search = 268,
|
||||
ac_home = 269,
|
||||
ac_back = 270,
|
||||
ac_forward = 271,
|
||||
ac_stop = 272,
|
||||
ac_refresh = 273,
|
||||
ac_bookmarks = 274,
|
||||
brightnessdown = 275,
|
||||
brightnessup = 276,
|
||||
displayswitch = 277,
|
||||
kbdillumtoggle = 278,
|
||||
kbdillumdown = 279,
|
||||
kbdillumup = 280,
|
||||
eject = 281,
|
||||
sleep = 282,
|
||||
app1 = 283,
|
||||
app2 = 284,
|
||||
audiorewind = 285,
|
||||
audiofastforward = 286,
|
||||
softleft = 287,
|
||||
softright = 288,
|
||||
call = 289,
|
||||
endcall = 290,
|
||||
_,
|
||||
};
|
||||
pub const Scancode = @import("keyboard.zig").Scancode;
|
||||
|
||||
pub const Keycode = enum(i32) {
|
||||
unknown = 0,
|
||||
@"return" = '\r',
|
||||
escape = '\x1b',
|
||||
backspace = '\x08',
|
||||
tab = '\t',
|
||||
space = ' ',
|
||||
exclaim = '!',
|
||||
quotedbl = '"',
|
||||
hash = '#',
|
||||
percent = '%',
|
||||
dollar = '$',
|
||||
ampersand = '&',
|
||||
quote = '\'',
|
||||
leftparen = '(',
|
||||
rightparen = ')',
|
||||
asterisk = '*',
|
||||
plus = '+',
|
||||
comma = ',',
|
||||
minus = '-',
|
||||
period = '.',
|
||||
slash = '/',
|
||||
@"0" = '0',
|
||||
@"1" = '1',
|
||||
@"2" = '2',
|
||||
@"3" = '3',
|
||||
@"4" = '4',
|
||||
@"5" = '5',
|
||||
@"6" = '6',
|
||||
@"7" = '7',
|
||||
@"8" = '8',
|
||||
@"9" = '9',
|
||||
colon = ':',
|
||||
semicolon = ';',
|
||||
less = '<',
|
||||
equals = '=',
|
||||
greater = '>',
|
||||
question = '?',
|
||||
at = '@',
|
||||
leftbracket = '[',
|
||||
backslash = '\\',
|
||||
rightbracket = ']',
|
||||
caret = '^',
|
||||
underscore = '_',
|
||||
backquote = '`',
|
||||
a = 'a',
|
||||
b = 'b',
|
||||
c = 'c',
|
||||
d = 'd',
|
||||
e = 'e',
|
||||
f = 'f',
|
||||
g = 'g',
|
||||
h = 'h',
|
||||
i = 'i',
|
||||
j = 'j',
|
||||
k = 'k',
|
||||
l = 'l',
|
||||
m = 'm',
|
||||
n = 'n',
|
||||
o = 'o',
|
||||
p = 'p',
|
||||
q = 'q',
|
||||
r = 'r',
|
||||
s = 's',
|
||||
t = 't',
|
||||
u = 'u',
|
||||
v = 'v',
|
||||
w = 'w',
|
||||
x = 'x',
|
||||
y = 'y',
|
||||
z = 'z',
|
||||
capslock = @enumToInt(Scancode.capslock) | mask,
|
||||
f1 = @enumToInt(Scancode.f1) | mask,
|
||||
f2 = @enumToInt(Scancode.f2) | mask,
|
||||
f3 = @enumToInt(Scancode.f3) | mask,
|
||||
f4 = @enumToInt(Scancode.f4) | mask,
|
||||
f5 = @enumToInt(Scancode.f5) | mask,
|
||||
f6 = @enumToInt(Scancode.f6) | mask,
|
||||
f7 = @enumToInt(Scancode.f7) | mask,
|
||||
f8 = @enumToInt(Scancode.f8) | mask,
|
||||
f9 = @enumToInt(Scancode.f9) | mask,
|
||||
f10 = @enumToInt(Scancode.f10) | mask,
|
||||
f11 = @enumToInt(Scancode.f11) | mask,
|
||||
f12 = @enumToInt(Scancode.f12) | mask,
|
||||
printscreen = @enumToInt(Scancode.printscreen) | mask,
|
||||
scrolllock = @enumToInt(Scancode.scrolllock) | mask,
|
||||
pause = @enumToInt(Scancode.pause) | mask,
|
||||
insert = @enumToInt(Scancode.insert) | mask,
|
||||
home = @enumToInt(Scancode.home) | mask,
|
||||
pageup = @enumToInt(Scancode.pageup) | mask,
|
||||
delete = '\x7f',
|
||||
end = @enumToInt(Scancode.end) | mask,
|
||||
pagedown = @enumToInt(Scancode.pagedown) | mask,
|
||||
right = @enumToInt(Scancode.right) | mask,
|
||||
left = @enumToInt(Scancode.left) | mask,
|
||||
down = @enumToInt(Scancode.down) | mask,
|
||||
up = @enumToInt(Scancode.up) | mask,
|
||||
numlockclear = @enumToInt(Scancode.numlockclear) | mask,
|
||||
kp_divide = @enumToInt(Scancode.kp_divide) | mask,
|
||||
kp_multiply = @enumToInt(Scancode.kp_multiply) | mask,
|
||||
kp_minus = @enumToInt(Scancode.kp_minus) | mask,
|
||||
kp_plus = @enumToInt(Scancode.kp_plus) | mask,
|
||||
kp_enter = @enumToInt(Scancode.kp_enter) | mask,
|
||||
kp_1 = @enumToInt(Scancode.kp_1) | mask,
|
||||
kp_2 = @enumToInt(Scancode.kp_2) | mask,
|
||||
kp_3 = @enumToInt(Scancode.kp_3) | mask,
|
||||
kp_4 = @enumToInt(Scancode.kp_4) | mask,
|
||||
kp_5 = @enumToInt(Scancode.kp_5) | mask,
|
||||
kp_6 = @enumToInt(Scancode.kp_6) | mask,
|
||||
kp_7 = @enumToInt(Scancode.kp_7) | mask,
|
||||
kp_8 = @enumToInt(Scancode.kp_8) | mask,
|
||||
kp_9 = @enumToInt(Scancode.kp_9) | mask,
|
||||
kp_0 = @enumToInt(Scancode.kp_0) | mask,
|
||||
kp_period = @enumToInt(Scancode.kp_period) | mask,
|
||||
application = @enumToInt(Scancode.application) | mask,
|
||||
power = @enumToInt(Scancode.power) | mask,
|
||||
kp_equals = @enumToInt(Scancode.kp_equals) | mask,
|
||||
f13 = @enumToInt(Scancode.f13) | mask,
|
||||
f14 = @enumToInt(Scancode.f14) | mask,
|
||||
f15 = @enumToInt(Scancode.f15) | mask,
|
||||
f16 = @enumToInt(Scancode.f16) | mask,
|
||||
f17 = @enumToInt(Scancode.f17) | mask,
|
||||
f18 = @enumToInt(Scancode.f18) | mask,
|
||||
f19 = @enumToInt(Scancode.f19) | mask,
|
||||
f20 = @enumToInt(Scancode.f20) | mask,
|
||||
f21 = @enumToInt(Scancode.f21) | mask,
|
||||
f22 = @enumToInt(Scancode.f22) | mask,
|
||||
f23 = @enumToInt(Scancode.f23) | mask,
|
||||
f24 = @enumToInt(Scancode.f24) | mask,
|
||||
execute = @enumToInt(Scancode.execute) | mask,
|
||||
help = @enumToInt(Scancode.help) | mask,
|
||||
menu = @enumToInt(Scancode.menu) | mask,
|
||||
select = @enumToInt(Scancode.select) | mask,
|
||||
stop = @enumToInt(Scancode.stop) | mask,
|
||||
again = @enumToInt(Scancode.again) | mask,
|
||||
undo = @enumToInt(Scancode.undo) | mask,
|
||||
cut = @enumToInt(Scancode.cut) | mask,
|
||||
copy = @enumToInt(Scancode.copy) | mask,
|
||||
paste = @enumToInt(Scancode.paste) | mask,
|
||||
find = @enumToInt(Scancode.find) | mask,
|
||||
mute = @enumToInt(Scancode.mute) | mask,
|
||||
volumeup = @enumToInt(Scancode.volumeup) | mask,
|
||||
volumedown = @enumToInt(Scancode.volumedown) | mask,
|
||||
kp_comma = @enumToInt(Scancode.kp_comma) | mask,
|
||||
kp_equalsas400 = @enumToInt(Scancode.kp_equalsas400) | mask,
|
||||
alterase = @enumToInt(Scancode.alterase) | mask,
|
||||
sysreq = @enumToInt(Scancode.sysreq) | mask,
|
||||
cancel = @enumToInt(Scancode.cancel) | mask,
|
||||
clear = @enumToInt(Scancode.clear) | mask,
|
||||
prior = @enumToInt(Scancode.prior) | mask,
|
||||
return2 = @enumToInt(Scancode.return2) | mask,
|
||||
separator = @enumToInt(Scancode.separator) | mask,
|
||||
out = @enumToInt(Scancode.out) | mask,
|
||||
oper = @enumToInt(Scancode.oper) | mask,
|
||||
clearagain = @enumToInt(Scancode.clearagain) | mask,
|
||||
crsel = @enumToInt(Scancode.crsel) | mask,
|
||||
exsel = @enumToInt(Scancode.exsel) | mask,
|
||||
kp_00 = @enumToInt(Scancode.kp_00) | mask,
|
||||
kp_000 = @enumToInt(Scancode.kp_000) | mask,
|
||||
thousandsseparator = @enumToInt(Scancode.thousandsseparator) | mask,
|
||||
decimalseparator = @enumToInt(Scancode.decimalseparator) | mask,
|
||||
currencyunit = @enumToInt(Scancode.currencyunit) | mask,
|
||||
currencysubunit = @enumToInt(Scancode.currencysubunit) | mask,
|
||||
kp_leftparen = @enumToInt(Scancode.kp_leftparen) | mask,
|
||||
kp_rightparen = @enumToInt(Scancode.kp_rightparen) | mask,
|
||||
kp_leftbrace = @enumToInt(Scancode.kp_leftbrace) | mask,
|
||||
kp_rightbrace = @enumToInt(Scancode.kp_rightbrace) | mask,
|
||||
kp_tab = @enumToInt(Scancode.kp_tab) | mask,
|
||||
kp_backspace = @enumToInt(Scancode.kp_backspace) | mask,
|
||||
kp_a = @enumToInt(Scancode.kp_a) | mask,
|
||||
kp_b = @enumToInt(Scancode.kp_b) | mask,
|
||||
kp_c = @enumToInt(Scancode.kp_c) | mask,
|
||||
kp_d = @enumToInt(Scancode.kp_d) | mask,
|
||||
kp_e = @enumToInt(Scancode.kp_e) | mask,
|
||||
kp_f = @enumToInt(Scancode.kp_f) | mask,
|
||||
kp_xor = @enumToInt(Scancode.kp_xor) | mask,
|
||||
kp_power = @enumToInt(Scancode.kp_power) | mask,
|
||||
kp_percent = @enumToInt(Scancode.kp_percent) | mask,
|
||||
kp_less = @enumToInt(Scancode.kp_less) | mask,
|
||||
kp_greater = @enumToInt(Scancode.kp_greater) | mask,
|
||||
kp_ampersand = @enumToInt(Scancode.kp_ampersand) | mask,
|
||||
kp_dblampersand = @enumToInt(Scancode.kp_dblampersand) | mask,
|
||||
kp_verticalbar = @enumToInt(Scancode.kp_verticalbar) | mask,
|
||||
kp_dblverticalbar = @enumToInt(Scancode.kp_dblverticalbar) | mask,
|
||||
kp_colon = @enumToInt(Scancode.kp_colon) | mask,
|
||||
kp_hash = @enumToInt(Scancode.kp_hash) | mask,
|
||||
kp_space = @enumToInt(Scancode.kp_space) | mask,
|
||||
kp_at = @enumToInt(Scancode.kp_at) | mask,
|
||||
kp_exclam = @enumToInt(Scancode.kp_exclam) | mask,
|
||||
kp_memstore = @enumToInt(Scancode.kp_memstore) | mask,
|
||||
kp_memrecall = @enumToInt(Scancode.kp_memrecall) | mask,
|
||||
kp_memclear = @enumToInt(Scancode.kp_memclear) | mask,
|
||||
kp_memadd = @enumToInt(Scancode.kp_memadd) | mask,
|
||||
kp_memsubtract = @enumToInt(Scancode.kp_memsubtract) | mask,
|
||||
kp_memmultiply = @enumToInt(Scancode.kp_memmultiply) | mask,
|
||||
kp_memdivide = @enumToInt(Scancode.kp_memdivide) | mask,
|
||||
kp_plusminus = @enumToInt(Scancode.kp_plusminus) | mask,
|
||||
kp_clear = @enumToInt(Scancode.kp_clear) | mask,
|
||||
kp_clearentry = @enumToInt(Scancode.kp_clearentry) | mask,
|
||||
kp_binary = @enumToInt(Scancode.kp_binary) | mask,
|
||||
kp_octal = @enumToInt(Scancode.kp_octal) | mask,
|
||||
kp_decimal = @enumToInt(Scancode.kp_decimal) | mask,
|
||||
kp_hexadecimal = @enumToInt(Scancode.kp_hexadecimal) | mask,
|
||||
lctrl = @enumToInt(Scancode.lctrl) | mask,
|
||||
lshift = @enumToInt(Scancode.lshift) | mask,
|
||||
lalt = @enumToInt(Scancode.lalt) | mask,
|
||||
lgui = @enumToInt(Scancode.lgui) | mask,
|
||||
rctrl = @enumToInt(Scancode.rctrl) | mask,
|
||||
rshift = @enumToInt(Scancode.rshift) | mask,
|
||||
ralt = @enumToInt(Scancode.ralt) | mask,
|
||||
rgui = @enumToInt(Scancode.rgui) | mask,
|
||||
mode = @enumToInt(Scancode.mode) | mask,
|
||||
audionext = @enumToInt(Scancode.audionext) | mask,
|
||||
audioprev = @enumToInt(Scancode.audioprev) | mask,
|
||||
audiostop = @enumToInt(Scancode.audiostop) | mask,
|
||||
audioplay = @enumToInt(Scancode.audioplay) | mask,
|
||||
audiomute = @enumToInt(Scancode.audiomute) | mask,
|
||||
mediaselect = @enumToInt(Scancode.mediaselect) | mask,
|
||||
www = @enumToInt(Scancode.www) | mask,
|
||||
mail = @enumToInt(Scancode.mail) | mask,
|
||||
calculator = @enumToInt(Scancode.calculator) | mask,
|
||||
computer = @enumToInt(Scancode.computer) | mask,
|
||||
ac_search = @enumToInt(Scancode.ac_search) | mask,
|
||||
ac_home = @enumToInt(Scancode.ac_home) | mask,
|
||||
ac_back = @enumToInt(Scancode.ac_back) | mask,
|
||||
ac_forward = @enumToInt(Scancode.ac_forward) | mask,
|
||||
ac_stop = @enumToInt(Scancode.ac_stop) | mask,
|
||||
ac_refresh = @enumToInt(Scancode.ac_refresh) | mask,
|
||||
ac_bookmarks = @enumToInt(Scancode.ac_bookmarks) | mask,
|
||||
brightnessdown = @enumToInt(Scancode.brightnessdown) | mask,
|
||||
brightnessup = @enumToInt(Scancode.brightnessup) | mask,
|
||||
displayswitch = @enumToInt(Scancode.displayswitch) | mask,
|
||||
kbdillumtoggle = @enumToInt(Scancode.kbdillumtoggle) | mask,
|
||||
kbdillumdown = @enumToInt(Scancode.kbdillumdown) | mask,
|
||||
kbdillumup = @enumToInt(Scancode.kbdillumup) | mask,
|
||||
eject = @enumToInt(Scancode.eject) | mask,
|
||||
sleep = @enumToInt(Scancode.sleep) | mask,
|
||||
app1 = @enumToInt(Scancode.app1) | mask,
|
||||
app2 = @enumToInt(Scancode.app2) | mask,
|
||||
audiorewind = @enumToInt(Scancode.audiorewind) | mask,
|
||||
audiofastforward = @enumToInt(Scancode.audiofastforward) | mask,
|
||||
softleft = @enumToInt(Scancode.softleft) | mask,
|
||||
softright = @enumToInt(Scancode.softright) | mask,
|
||||
call = @enumToInt(Scancode.call) | mask,
|
||||
endcall = @enumToInt(Scancode.endcall) | mask,
|
||||
_,
|
||||
|
||||
const mask = 1 << 30;
|
||||
};
|
||||
pub const Keycode = @import("keyboard.zig").Keycode;
|
||||
|
||||
pub const Keysym = extern struct {
|
||||
scancode: Scancode,
|
||||
@@ -832,7 +398,7 @@ pub const TextInputEvent = extern struct {
|
||||
pub const MouseMotionEvent = extern struct {
|
||||
type: EventType,
|
||||
timestamp: u32,
|
||||
windowID: u32,
|
||||
window_id: u32,
|
||||
which: u32,
|
||||
state: u32,
|
||||
x: i32,
|
||||
@@ -844,7 +410,7 @@ pub const MouseMotionEvent = extern struct {
|
||||
pub const MouseButtonEvent = extern struct {
|
||||
type: EventType,
|
||||
timestamp: u32,
|
||||
windowID: u32,
|
||||
window_id: u32,
|
||||
which: u32,
|
||||
button: u8,
|
||||
state: ReleasedOrPressed,
|
||||
@@ -871,6 +437,13 @@ pub const QuitEvent = extern struct {
|
||||
timestamp: u32,
|
||||
};
|
||||
|
||||
pub const DropEvent = extern struct {
|
||||
type: EventType,
|
||||
timestamp: u32,
|
||||
file: ?[*:0]u8,
|
||||
window_id: u32,
|
||||
};
|
||||
|
||||
pub const Event = extern union {
|
||||
type: EventType,
|
||||
common: CommonEvent,
|
||||
@@ -884,6 +457,7 @@ pub const Event = extern union {
|
||||
button: MouseButtonEvent,
|
||||
wheel: MouseWheelEvent,
|
||||
quit: QuitEvent,
|
||||
drop: DropEvent,
|
||||
|
||||
padding: [size]u8,
|
||||
|
||||
@@ -899,37 +473,29 @@ pub fn pollEvent(event: ?*Event) bool {
|
||||
}
|
||||
extern fn SDL_PollEvent(event: ?*Event) i32;
|
||||
|
||||
/// `pub fn getMouseFocus() ?*Window`
|
||||
pub const getMouseFocus = SDL_GetMouseFocus;
|
||||
extern fn SDL_GetMouseFocus() ?*Window;
|
||||
|
||||
/// `pub fn getMouseState(x: ?*i32, y: ?*i32) u32`
|
||||
pub const getMouseState = SDL_GetMouseState;
|
||||
extern fn SDL_GetMouseState(x: ?*i32, y: ?*i32) u32;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Hints
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub const hint_windows_dpi_awareness = "SDL_WINDOWS_DPI_AWARENESS";
|
||||
|
||||
pub fn setHint(name: [:0]const u8, value: [:0]const u8) bool {
|
||||
return SDL_SetHint(name, value) != 0;
|
||||
}
|
||||
extern fn SDL_SetHint(name: [*:0]const u8, value: [*:0]const u8) i32;
|
||||
|
||||
pub const DisplayId = u32;
|
||||
|
||||
pub const DisplayMode = DisplayMode_SDL2;
|
||||
|
||||
const DisplayMode_SDL2 = extern struct {
|
||||
format: u32,
|
||||
w: i32,
|
||||
h: i32,
|
||||
refresh_rate: i32,
|
||||
driverdata: *anyopaque,
|
||||
};
|
||||
|
||||
const DisplayMode_SDL3 = extern struct {
|
||||
display_id: DisplayId,
|
||||
format: u32,
|
||||
pixel_w: i32,
|
||||
pixel_h: i32,
|
||||
screen_w: i32,
|
||||
screen_h: i32,
|
||||
display_scale: f32,
|
||||
refresh_rate: f32,
|
||||
driverdata: *anyopaque,
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Timer
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/// `pub fn getPerformanceCounter() u64`
|
||||
pub const getPerformanceCounter = SDL_GetPerformanceCounter;
|
||||
extern fn SDL_GetPerformanceCounter() u64;
|
||||
@@ -941,7 +507,11 @@ extern fn SDL_GetPerformanceFrequency() u64;
|
||||
/// `pub fn delay(ms: u32) void`
|
||||
pub const delay = SDL_Delay;
|
||||
extern fn SDL_Delay(ms: u32) void;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// OpenGL
|
||||
//
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub const gl = struct {
|
||||
pub const Context = *anyopaque;
|
||||
|
||||
@@ -1048,4 +618,9 @@ pub const gl = struct {
|
||||
/// `pub fn deleteContext(context: Context) void`
|
||||
pub const deleteContext = SDL_GL_DeleteContext;
|
||||
extern fn SDL_GL_DeleteContext(context: Context) void;
|
||||
|
||||
/// `pub fn getDrawableSize(window: *Window, w: ?*i32, h: ?*i32) void`
|
||||
pub const getDrawableSize = SDL_GL_GetDrawableSize;
|
||||
extern fn SDL_GL_GetDrawableSize(window: *Window, w: ?*i32, h: ?*i32) void;
|
||||
};
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
+45
-20
@@ -1,4 +1,4 @@
|
||||
# zstbi v0.9.2 - stb image bindings
|
||||
# zstbi v0.9.3 - stb image bindings
|
||||
|
||||
## Features
|
||||
|
||||
@@ -35,30 +35,55 @@ const zstbi = @import("zstbi");
|
||||
zstbi.init(allocator);
|
||||
defer zstbi.deinit();
|
||||
```
|
||||
|
||||
Load image:
|
||||
```zig
|
||||
var image = try zstbi.Image.init("data/image.png", num_desired_channels);
|
||||
pub const Image = struct {
|
||||
data: []u8,
|
||||
width: u32,
|
||||
height: u32,
|
||||
num_components: u32,
|
||||
bytes_per_component: u32,
|
||||
bytes_per_row: u32,
|
||||
is_hdr: bool,
|
||||
...
|
||||
```
|
||||
```zig
|
||||
pub fn loadFromFile(pathname: [:0]const u8, forced_num_components: u32) !Image
|
||||
|
||||
pub fn loadFromMemory(data: []const u8, forced_num_components: u32) !Image
|
||||
|
||||
pub fn createEmpty(width: u32, height: u32, num_components: u32, args: struct {
|
||||
bytes_per_component: u32 = 0,
|
||||
bytes_per_row: u32 = 0,
|
||||
}) !Image
|
||||
|
||||
pub fn info(pathname: [:0]const u8) struct {
|
||||
is_supported: bool,
|
||||
width: u32,
|
||||
height: u32,
|
||||
num_components: u32,
|
||||
}
|
||||
|
||||
pub fn resize(image: *const Image, new_width: u32, new_height: u32) Image
|
||||
|
||||
pub fn writeToFile(
|
||||
image: *const Image,
|
||||
filename: [:0]const u8,
|
||||
image_format: ImageWriteFormat,
|
||||
) ImageWriteError!void
|
||||
|
||||
pub fn writeToFn(
|
||||
image: *const Image,
|
||||
write_fn: *const fn (ctx: ?*anyopaque, data: ?*anyopaque, size: c_int) callconv(.C) void,
|
||||
context: ?*anyopaque,
|
||||
image_format: ImageWriteFormat,
|
||||
) ImageWriteError!void
|
||||
```
|
||||
```zig
|
||||
var image = try zstbi.Image.loadFromFile("data/image.png", forced_num_components);
|
||||
defer image.deinit();
|
||||
_ = image.data; // stored as []u8
|
||||
_ = image.width;
|
||||
_ = image.height;
|
||||
_ = image.num_components;
|
||||
_ = image.bytes_per_component;
|
||||
_ = image.bytes_per_row;
|
||||
_ = image.is_hdr;
|
||||
|
||||
const new_resized_image = image.resize(1024, 1024);
|
||||
```
|
||||
|
||||
Get image info without loading:
|
||||
```zig
|
||||
const image_info = zstbi.Image.info("data/image.jpg");
|
||||
_ = image_info.is_supported; // Is image format supported?
|
||||
_ = image_info.width;
|
||||
_ = image_info.height;
|
||||
_ = image_info.num_components;
|
||||
```
|
||||
Misc functions:
|
||||
```zig
|
||||
pub fn isHdr(filename: [:0]const u8) bool
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* stb_image - v2.27 - public domain image loader - http://nothings.org/stb
|
||||
/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
Do this:
|
||||
@@ -48,6 +48,7 @@ LICENSE
|
||||
|
||||
RECENT REVISION HISTORY:
|
||||
|
||||
2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
|
||||
2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
|
||||
2.26 (2020-07-13) many minor fixes
|
||||
2.25 (2020-02-02) fix warnings
|
||||
@@ -108,7 +109,7 @@ RECENT REVISION HISTORY:
|
||||
Cass Everitt Ryamond Barbiero github:grim210
|
||||
Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
|
||||
Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
|
||||
Josh Tobin Matthew Gregan github:poppolopoppo
|
||||
Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo
|
||||
Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
|
||||
Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
|
||||
Brad Weinberger Matvey Cherevko github:mosra
|
||||
@@ -140,7 +141,7 @@ RECENT REVISION HISTORY:
|
||||
// // ... x = width, y = height, n = # 8-bit components per pixel ...
|
||||
// // ... replace '0' with '1'..'4' to force that many components per pixel
|
||||
// // ... but 'n' will always be the number that it would have been if you said 0
|
||||
// stbi_image_free(data)
|
||||
// stbi_image_free(data);
|
||||
//
|
||||
// Standard parameters:
|
||||
// int *x -- outputs image width in pixels
|
||||
@@ -635,7 +636,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) || defined(__SYMBIAN32__)
|
||||
typedef unsigned short stbi__uint16;
|
||||
typedef signed short stbi__int16;
|
||||
typedef unsigned int stbi__uint32;
|
||||
@@ -1063,6 +1064,23 @@ static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
|
||||
}
|
||||
#endif
|
||||
|
||||
// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow.
|
||||
static int stbi__addints_valid(int a, int b)
|
||||
{
|
||||
if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow
|
||||
if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0.
|
||||
return a <= INT_MAX - b;
|
||||
}
|
||||
|
||||
// returns 1 if the product of two signed shorts is valid, 0 on overflow.
|
||||
static int stbi__mul2shorts_valid(short a, short b)
|
||||
{
|
||||
if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
|
||||
if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
|
||||
if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN
|
||||
return a >= SHRT_MIN / b;
|
||||
}
|
||||
|
||||
// stbi__err - error
|
||||
// stbi__errpf - error returning pointer to float
|
||||
// stbi__errpuc - error returning pointer to unsigned char
|
||||
@@ -1985,9 +2003,12 @@ static int stbi__build_huffman(stbi__huffman *h, int *count)
|
||||
int i,j,k=0;
|
||||
unsigned int code;
|
||||
// build size list for each symbol (from JPEG spec)
|
||||
for (i=0; i < 16; ++i)
|
||||
for (j=0; j < count[i]; ++j)
|
||||
for (i=0; i < 16; ++i) {
|
||||
for (j=0; j < count[i]; ++j) {
|
||||
h->size[k++] = (stbi_uc) (i+1);
|
||||
if(k >= 257) return stbi__err("bad size list","Corrupt JPEG");
|
||||
}
|
||||
}
|
||||
h->size[k] = 0;
|
||||
|
||||
// compute actual symbols (from jpeg spec)
|
||||
@@ -2112,6 +2133,8 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
|
||||
|
||||
// convert the huffman code to the symbol id
|
||||
c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
|
||||
if(c < 0 || c >= 256) // symbol id out of bounds!
|
||||
return -1;
|
||||
STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
|
||||
|
||||
// convert the id to a symbol
|
||||
@@ -2130,6 +2153,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
|
||||
unsigned int k;
|
||||
int sgn;
|
||||
if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
|
||||
if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
|
||||
|
||||
sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)
|
||||
k = stbi_lrot(j->code_buffer, n);
|
||||
@@ -2144,6 +2168,7 @@ stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)
|
||||
{
|
||||
unsigned int k;
|
||||
if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
|
||||
if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
|
||||
k = stbi_lrot(j->code_buffer, n);
|
||||
j->code_buffer = k & ~stbi__bmask[n];
|
||||
k &= stbi__bmask[n];
|
||||
@@ -2155,6 +2180,7 @@ stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
|
||||
{
|
||||
unsigned int k;
|
||||
if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
|
||||
if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing
|
||||
k = j->code_buffer;
|
||||
j->code_buffer <<= 1;
|
||||
--j->code_bits;
|
||||
@@ -2192,8 +2218,10 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman
|
||||
memset(data,0,64*sizeof(data[0]));
|
||||
|
||||
diff = t ? stbi__extend_receive(j, t) : 0;
|
||||
if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG");
|
||||
dc = j->img_comp[b].dc_pred + diff;
|
||||
j->img_comp[b].dc_pred = dc;
|
||||
if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
data[0] = (short) (dc * dequant[0]);
|
||||
|
||||
// decode AC components, see JPEG spec
|
||||
@@ -2207,6 +2235,7 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman
|
||||
if (r) { // fast-AC path
|
||||
k += (r >> 4) & 15; // run
|
||||
s = r & 15; // combined length
|
||||
if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
|
||||
j->code_buffer <<= s;
|
||||
j->code_bits -= s;
|
||||
// decode into unzigzag'd location
|
||||
@@ -2246,8 +2275,10 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
|
||||
if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
diff = t ? stbi__extend_receive(j, t) : 0;
|
||||
|
||||
if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG");
|
||||
dc = j->img_comp[b].dc_pred + diff;
|
||||
j->img_comp[b].dc_pred = dc;
|
||||
if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
|
||||
data[0] = (short) (dc * (1 << j->succ_low));
|
||||
} else {
|
||||
// refinement scan for DC coefficient
|
||||
@@ -2282,6 +2313,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
|
||||
if (r) { // fast-AC path
|
||||
k += (r >> 4) & 15; // run
|
||||
s = r & 15; // combined length
|
||||
if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
|
||||
j->code_buffer <<= s;
|
||||
j->code_bits -= s;
|
||||
zig = stbi__jpeg_dezigzag[k++];
|
||||
@@ -3102,6 +3134,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m)
|
||||
sizes[i] = stbi__get8(z->s);
|
||||
n += sizes[i];
|
||||
}
|
||||
if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values!
|
||||
L -= 17;
|
||||
if (tc == 0) {
|
||||
if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
|
||||
@@ -3351,6 +3384,28 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
|
||||
{
|
||||
// some JPEGs have junk at end, skip over it but if we find what looks
|
||||
// like a valid marker, resume there
|
||||
while (!stbi__at_eof(j->s)) {
|
||||
int x = stbi__get8(j->s);
|
||||
while (x == 255) { // might be a marker
|
||||
if (stbi__at_eof(j->s)) return STBI__MARKER_none;
|
||||
x = stbi__get8(j->s);
|
||||
if (x != 0x00 && x != 0xff) {
|
||||
// not a stuffed zero or lead-in to another marker, looks
|
||||
// like an actual marker, return it
|
||||
return x;
|
||||
}
|
||||
// stuffed zero has x=0 now which ends the loop, meaning we go
|
||||
// back to regular scan loop.
|
||||
// repeated 0xff keeps trying to read the next byte of the marker.
|
||||
}
|
||||
}
|
||||
return STBI__MARKER_none;
|
||||
}
|
||||
|
||||
// decode image to YCbCr format
|
||||
static int stbi__decode_jpeg_image(stbi__jpeg *j)
|
||||
{
|
||||
@@ -3367,25 +3422,22 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j)
|
||||
if (!stbi__process_scan_header(j)) return 0;
|
||||
if (!stbi__parse_entropy_coded_data(j)) return 0;
|
||||
if (j->marker == STBI__MARKER_none ) {
|
||||
// handle 0s at the end of image data from IP Kamera 9060
|
||||
while (!stbi__at_eof(j->s)) {
|
||||
int x = stbi__get8(j->s);
|
||||
if (x == 255) {
|
||||
j->marker = stbi__get8(j->s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
j->marker = stbi__skip_jpeg_junk_at_end(j);
|
||||
// if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
|
||||
}
|
||||
m = stbi__get_marker(j);
|
||||
if (STBI__RESTART(m))
|
||||
m = stbi__get_marker(j);
|
||||
} else if (stbi__DNL(m)) {
|
||||
int Ld = stbi__get16be(j->s);
|
||||
stbi__uint32 NL = stbi__get16be(j->s);
|
||||
if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
|
||||
if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
|
||||
m = stbi__get_marker(j);
|
||||
} else {
|
||||
if (!stbi__process_marker(j, m)) return 0;
|
||||
if (!stbi__process_marker(j, m)) return 1;
|
||||
m = stbi__get_marker(j);
|
||||
}
|
||||
m = stbi__get_marker(j);
|
||||
}
|
||||
if (j->progressive)
|
||||
stbi__jpeg_finish(j);
|
||||
@@ -3976,6 +4028,7 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re
|
||||
unsigned char* result;
|
||||
stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
|
||||
if (!j) return stbi__errpuc("outofmem", "Out of memory");
|
||||
memset(j, 0, sizeof(stbi__jpeg));
|
||||
STBI_NOTUSED(ri);
|
||||
j->s = s;
|
||||
stbi__setup_jpeg(j);
|
||||
@@ -3989,6 +4042,7 @@ static int stbi__jpeg_test(stbi__context *s)
|
||||
int r;
|
||||
stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
|
||||
if (!j) return stbi__err("outofmem", "Out of memory");
|
||||
memset(j, 0, sizeof(stbi__jpeg));
|
||||
j->s = s;
|
||||
stbi__setup_jpeg(j);
|
||||
r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
|
||||
@@ -4014,6 +4068,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
|
||||
int result;
|
||||
stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
|
||||
if (!j) return stbi__err("outofmem", "Out of memory");
|
||||
memset(j, 0, sizeof(stbi__jpeg));
|
||||
j->s = s;
|
||||
result = stbi__jpeg_info_raw(j, x, y, comp);
|
||||
STBI_FREE(j);
|
||||
@@ -4256,11 +4311,12 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
|
||||
a->zout = zout;
|
||||
return 1;
|
||||
}
|
||||
if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
|
||||
z -= 257;
|
||||
len = stbi__zlength_base[z];
|
||||
if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
|
||||
z = stbi__zhuffman_decode(a, &a->z_distance);
|
||||
if (z < 0) return stbi__err("bad huffman code","Corrupt PNG");
|
||||
if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data
|
||||
dist = stbi__zdist_base[z];
|
||||
if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
|
||||
if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
|
||||
@@ -4955,7 +5011,7 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
|
||||
static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set;
|
||||
static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set;
|
||||
|
||||
STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
|
||||
STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
|
||||
{
|
||||
stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
|
||||
stbi__unpremultiply_on_load_set = 1;
|
||||
@@ -5064,14 +5120,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
||||
if (!pal_img_n) {
|
||||
s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
|
||||
if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
|
||||
if (scan == STBI__SCAN_header) return 1;
|
||||
} else {
|
||||
// if paletted, then pal_n is our final components, and
|
||||
// img_n is # components to decompress/filter.
|
||||
s->img_n = 1;
|
||||
if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
|
||||
// if SCAN_header, have to scan to see if we have a tRNS
|
||||
}
|
||||
// even with SCAN_header, have to scan to see if we have a tRNS
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -5103,6 +5158,8 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
||||
if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
|
||||
if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
|
||||
has_trans = 1;
|
||||
// non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
|
||||
if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
|
||||
if (z->depth == 16) {
|
||||
for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
|
||||
} else {
|
||||
@@ -5115,7 +5172,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
||||
case STBI__PNG_TYPE('I','D','A','T'): {
|
||||
if (first) return stbi__err("first not IHDR", "Corrupt PNG");
|
||||
if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
|
||||
if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
|
||||
if (scan == STBI__SCAN_header) {
|
||||
// header scan definitely stops at first IDAT
|
||||
if (pal_img_n)
|
||||
s->img_n = pal_img_n;
|
||||
return 1;
|
||||
}
|
||||
if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes");
|
||||
if ((int)(ioff + c.length) < (int)ioff) return 0;
|
||||
if (ioff + c.length > idata_limit) {
|
||||
stbi__uint32 idata_limit_old = idata_limit;
|
||||
@@ -5498,8 +5561,22 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
|
||||
psize = (info.offset - info.extra_read - info.hsz) >> 2;
|
||||
}
|
||||
if (psize == 0) {
|
||||
if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) {
|
||||
return stbi__errpuc("bad offset", "Corrupt BMP");
|
||||
// accept some number of extra bytes after the header, but if the offset points either to before
|
||||
// the header ends or implies a large amount of extra data, reject the file as malformed
|
||||
int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original);
|
||||
int header_limit = 1024; // max we actually read is below 256 bytes currently.
|
||||
int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size.
|
||||
if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) {
|
||||
return stbi__errpuc("bad header", "Corrupt BMP");
|
||||
}
|
||||
// we established that bytes_read_so_far is positive and sensible.
|
||||
// the first half of this test rejects offsets that are either too small positives, or
|
||||
// negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn
|
||||
// ensures the number computed in the second half of the test can't overflow.
|
||||
if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) {
|
||||
return stbi__errpuc("bad offset", "Corrupt BMP");
|
||||
} else {
|
||||
stbi__skip(s, info.offset - bytes_read_so_far);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7187,12 +7264,12 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
|
||||
// Run
|
||||
value = stbi__get8(s);
|
||||
count -= 128;
|
||||
if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
|
||||
if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
|
||||
for (z = 0; z < count; ++z)
|
||||
scanline[i++ * 4 + k] = value;
|
||||
} else {
|
||||
// Dump
|
||||
if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
|
||||
if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
|
||||
for (z = 0; z < count; ++z)
|
||||
scanline[i++ * 4 + k] = stbi__get8(s);
|
||||
}
|
||||
@@ -7446,10 +7523,17 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
|
||||
|
||||
out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);
|
||||
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
||||
stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8));
|
||||
if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) {
|
||||
STBI_FREE(out);
|
||||
return stbi__errpuc("bad PNM", "PNM file truncated");
|
||||
}
|
||||
|
||||
if (req_comp && req_comp != s->img_n) {
|
||||
out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
|
||||
if (ri->bits_per_channel == 16) {
|
||||
out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y);
|
||||
} else {
|
||||
out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
|
||||
}
|
||||
if (out == NULL) return out; // stbi__convert_format frees input on failure
|
||||
}
|
||||
return out;
|
||||
@@ -7486,6 +7570,8 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c)
|
||||
while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
|
||||
value = value*10 + (*c - '0');
|
||||
*c = (char) stbi__get8(s);
|
||||
if((value > 214748364) || (value == 214748364 && *c > '7'))
|
||||
return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int");
|
||||
}
|
||||
|
||||
return value;
|
||||
@@ -7516,9 +7602,13 @@ static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
|
||||
stbi__pnm_skip_whitespace(s, &c);
|
||||
|
||||
*x = stbi__pnm_getinteger(s, &c); // read width
|
||||
if(*x == 0)
|
||||
return stbi__err("invalid width", "PPM image header had zero or overflowing width");
|
||||
stbi__pnm_skip_whitespace(s, &c);
|
||||
|
||||
*y = stbi__pnm_getinteger(s, &c); // read height
|
||||
if (*y == 0)
|
||||
return stbi__err("invalid width", "PPM image header had zero or overflowing width");
|
||||
stbi__pnm_skip_whitespace(s, &c);
|
||||
|
||||
maxv = stbi__pnm_getinteger(s, &c); // read max value
|
||||
|
||||
+52
-23
@@ -1,4 +1,4 @@
|
||||
pub const version = @import("std").SemanticVersion{ .major = 0, .minor = 9, .patch = 2 };
|
||||
pub const version = @import("std").SemanticVersion{ .major = 0, .minor = 9, .patch = 3 };
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
|
||||
@@ -68,7 +68,7 @@ pub const Image = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init(pathname: [:0]const u8, forced_num_channels: u32) !Image {
|
||||
pub fn loadFromFile(pathname: [:0]const u8, forced_num_components: u32) !Image {
|
||||
var width: u32 = 0;
|
||||
var height: u32 = 0;
|
||||
var num_components: u32 = 0;
|
||||
@@ -85,11 +85,11 @@ pub const Image = struct {
|
||||
&x,
|
||||
&y,
|
||||
&ch,
|
||||
@intCast(c_int, forced_num_channels),
|
||||
@intCast(c_int, forced_num_components),
|
||||
);
|
||||
if (ptr == null) return error.ImageInitFailed;
|
||||
|
||||
num_components = if (forced_num_channels == 0) @intCast(u32, ch) else forced_num_channels;
|
||||
num_components = if (forced_num_components == 0) @intCast(u32, ch) else forced_num_components;
|
||||
width = @intCast(u32, x);
|
||||
height = @intCast(u32, y);
|
||||
bytes_per_component = 2;
|
||||
@@ -114,17 +114,17 @@ pub const Image = struct {
|
||||
&x,
|
||||
&y,
|
||||
&ch,
|
||||
@intCast(c_int, forced_num_channels),
|
||||
@intCast(c_int, forced_num_components),
|
||||
)) else stbi_load(
|
||||
pathname,
|
||||
&x,
|
||||
&y,
|
||||
&ch,
|
||||
@intCast(c_int, forced_num_channels),
|
||||
@intCast(c_int, forced_num_components),
|
||||
);
|
||||
if (ptr == null) return error.ImageInitFailed;
|
||||
|
||||
num_components = if (forced_num_channels == 0) @intCast(u32, ch) else forced_num_channels;
|
||||
num_components = if (forced_num_components == 0) @intCast(u32, ch) else forced_num_components;
|
||||
width = @intCast(u32, x);
|
||||
height = @intCast(u32, y);
|
||||
bytes_per_component = if (is_16bit) 2 else 1;
|
||||
@@ -145,7 +145,7 @@ pub const Image = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initFromData(data: []const u8, forced_num_channels: u32) !Image {
|
||||
pub fn loadFromMemory(data: []const u8, forced_num_components: u32) !Image {
|
||||
// TODO: Add support for HDR images (https://github.com/michal-z/zig-gamedev/issues/155).
|
||||
var width: u32 = 0;
|
||||
var height: u32 = 0;
|
||||
@@ -163,11 +163,11 @@ pub const Image = struct {
|
||||
&x,
|
||||
&y,
|
||||
&ch,
|
||||
@intCast(c_int, forced_num_channels),
|
||||
@intCast(c_int, forced_num_components),
|
||||
);
|
||||
if (ptr == null) return error.ImageInitFailed;
|
||||
|
||||
num_components = if (forced_num_channels == 0) @intCast(u32, ch) else forced_num_channels;
|
||||
num_components = if (forced_num_components == 0) @intCast(u32, ch) else forced_num_components;
|
||||
width = @intCast(u32, x);
|
||||
height = @intCast(u32, y);
|
||||
bytes_per_component = 1;
|
||||
@@ -187,6 +187,32 @@ pub const Image = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn createEmpty(width: u32, height: u32, num_components: u32, args: struct {
|
||||
bytes_per_component: u32 = 0,
|
||||
bytes_per_row: u32 = 0,
|
||||
}) !Image {
|
||||
const bytes_per_component = if (args.bytes_per_component == 0) 1 else args.bytes_per_component;
|
||||
const bytes_per_row = if (args.bytes_per_row == 0)
|
||||
width * num_components * bytes_per_component
|
||||
else
|
||||
args.bytes_per_row;
|
||||
|
||||
const size = height * bytes_per_row;
|
||||
|
||||
const data = @ptrCast([*]u8, zstbiMalloc(size));
|
||||
@memset(data, 0, size);
|
||||
|
||||
return Image{
|
||||
.data = data[0..size],
|
||||
.width = width,
|
||||
.height = height,
|
||||
.num_components = num_components,
|
||||
.bytes_per_component = bytes_per_component,
|
||||
.bytes_per_row = bytes_per_row,
|
||||
.is_hdr = false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn resize(image: *const Image, new_width: u32, new_height: u32) Image {
|
||||
// TODO: Add support for HDR images
|
||||
const new_bytes_per_row = new_width * image.num_components * image.bytes_per_component;
|
||||
@@ -215,21 +241,21 @@ pub const Image = struct {
|
||||
}
|
||||
|
||||
pub fn writeToFile(
|
||||
self: *const Image,
|
||||
image: *const Image,
|
||||
filename: [:0]const u8,
|
||||
image_format: ImageWriteFormat,
|
||||
) ImageWriteError!void {
|
||||
const w = @intCast(c_int, self.width);
|
||||
const h = @intCast(c_int, self.height);
|
||||
const comp = @intCast(c_int, self.num_components);
|
||||
const w = @intCast(c_int, image.width);
|
||||
const h = @intCast(c_int, image.height);
|
||||
const comp = @intCast(c_int, image.num_components);
|
||||
const result = switch (image_format) {
|
||||
.png => stbi_write_png(filename.ptr, w, h, comp, self.data.ptr, 0),
|
||||
.png => stbi_write_png(filename.ptr, w, h, comp, image.data.ptr, 0),
|
||||
.jpg => |settings| stbi_write_jpg(
|
||||
filename.ptr,
|
||||
w,
|
||||
h,
|
||||
comp,
|
||||
self.data.ptr,
|
||||
image.data.ptr,
|
||||
@intCast(c_int, settings.quality),
|
||||
),
|
||||
};
|
||||
@@ -240,23 +266,23 @@ pub const Image = struct {
|
||||
}
|
||||
|
||||
pub fn writeToFn(
|
||||
self: *const Image,
|
||||
write_fn: *const fn (?*anyopaque, ?*anyopaque, c_int) callconv(.C) void,
|
||||
image: *const Image,
|
||||
write_fn: *const fn (ctx: ?*anyopaque, data: ?*anyopaque, size: c_int) callconv(.C) void,
|
||||
context: ?*anyopaque,
|
||||
image_format: ImageWriteFormat,
|
||||
) ImageWriteError!void {
|
||||
const w = @intCast(c_int, self.width);
|
||||
const h = @intCast(c_int, self.height);
|
||||
const comp = @intCast(c_int, self.num_components);
|
||||
const w = @intCast(c_int, image.width);
|
||||
const h = @intCast(c_int, image.height);
|
||||
const comp = @intCast(c_int, image.num_components);
|
||||
const result = switch (image_format) {
|
||||
.png => stbi_write_png_to_func(write_fn, context, w, h, comp, self.data.ptr, 0),
|
||||
.png => stbi_write_png_to_func(write_fn, context, w, h, comp, image.data.ptr, 0),
|
||||
.jpg => |settings| stbi_write_jpg_to_func(
|
||||
write_fn,
|
||||
context,
|
||||
w,
|
||||
h,
|
||||
comp,
|
||||
self.data.ptr,
|
||||
image.data.ptr,
|
||||
@intCast(c_int, settings.quality),
|
||||
),
|
||||
};
|
||||
@@ -469,4 +495,7 @@ extern fn stbi_write_jpg_to_func(
|
||||
test "zstbi.basic" {
|
||||
init(std.testing.allocator);
|
||||
defer deinit();
|
||||
|
||||
var image = try Image.createEmpty(64, 64, 4, .{});
|
||||
defer image.deinit();
|
||||
}
|
||||
@@ -445,12 +445,12 @@ pub const RESOURCE_TRANSITION_BARRIER = extern struct {
|
||||
};
|
||||
|
||||
pub const RESOURCE_ALIASING_BARRIER = extern struct {
|
||||
pResourceBefore: *IResource,
|
||||
pResourceAfter: *IResource,
|
||||
pResourceBefore: ?*IResource,
|
||||
pResourceAfter: ?*IResource,
|
||||
};
|
||||
|
||||
pub const RESOURCE_UAV_BARRIER = extern struct {
|
||||
pResource: *IResource,
|
||||
pResource: ?*IResource,
|
||||
};
|
||||
|
||||
pub const RESOURCE_BARRIER_FLAGS = packed struct(UINT) {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e7adfbbafa5714a2a9ec3a651c63a4184b2ffff1a3d5c69f5bf402f50cc056ad
|
||||
size 2796344
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:590cd1fd50cf09e0577d4c1f3cf3d222d4379687e4bdd7d8719fd71e6c5bf708
|
||||
size 5592580
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ea9d1f7caecc8bd786bc7b5ce607ee31220439f7d36e7b182c34519386102966
|
||||
size 5592580
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:c54dab8e810b9e0e655351f9370cfda23114104c9671229059401c7887857f79
|
||||
size 5592560
|
||||
@@ -51,13 +51,21 @@ comptime {
|
||||
assert(@alignOf([2]Vertex) == 4);
|
||||
}
|
||||
|
||||
// In this demo program, Mesh is just a range of vertices/indices in a single global vertex/index buffer.
|
||||
const Mesh = struct {
|
||||
// In this demo program, MeshLod is a range of indices in a single global index buffer.
|
||||
// A Mesh is an vertex offset into a single global vertex buffer and has a list of lods.
|
||||
const MeshLod = struct {
|
||||
index_offset: u32,
|
||||
vertex_offset: u32,
|
||||
num_indices: u32,
|
||||
};
|
||||
|
||||
const max_num_lods: u32 = 4;
|
||||
|
||||
const Mesh = struct {
|
||||
vertex_offset: u32,
|
||||
num_lods: u32,
|
||||
lods: [max_num_lods]MeshLod,
|
||||
};
|
||||
|
||||
const Scene_Const = extern struct {
|
||||
world_to_clip: Mat4,
|
||||
camera_position: Vec3,
|
||||
@@ -110,6 +118,7 @@ const DemoState = struct {
|
||||
brdf_integration_texture: ResourceView,
|
||||
|
||||
draw_mode: i32,
|
||||
current_lod: i32,
|
||||
|
||||
camera: struct {
|
||||
position: Vec3,
|
||||
@@ -129,6 +138,7 @@ fn loadMesh(
|
||||
all_meshes: *std.ArrayList(Mesh),
|
||||
all_vertices: *std.ArrayList(Vertex),
|
||||
all_indices: *std.ArrayList(u32),
|
||||
generate_lods: u32,
|
||||
) !void {
|
||||
var indices = std.ArrayList(u32).init(arena);
|
||||
var positions = std.ArrayList([3]f32).init(arena);
|
||||
@@ -148,11 +158,57 @@ fn loadMesh(
|
||||
defer zmesh.io.freeData(data);
|
||||
try zmesh.io.appendMeshPrimitive(data, 0, 0, &indices, &positions, &normals, &texcoords0, &tangents);
|
||||
|
||||
all_meshes.append(.{
|
||||
.index_offset = @intCast(u32, pre_indices_len),
|
||||
var mesh = Mesh{
|
||||
.vertex_offset = @intCast(u32, pre_positions_len),
|
||||
.num_indices = @intCast(u32, indices.items.len - pre_indices_len),
|
||||
}) catch unreachable;
|
||||
.num_lods = 1,
|
||||
.lods = undefined,
|
||||
};
|
||||
|
||||
mesh.lods[0] = .{
|
||||
.index_offset = @intCast(u32, pre_indices_len),
|
||||
.num_indices = @intCast(u32, indices.items.len),
|
||||
};
|
||||
|
||||
if (generate_lods > 0) {
|
||||
assert(generate_lods <= max_num_lods);
|
||||
var all_lods_indices = std.ArrayList(u32).init(arena);
|
||||
|
||||
var lod_index: u32 = 1;
|
||||
while (lod_index < generate_lods) : (lod_index += 1) {
|
||||
mesh.num_lods += 1;
|
||||
|
||||
const threshold: f32 = 1.0 - @intToFloat(f32, lod_index) / @intToFloat(f32, max_num_lods);
|
||||
const target_index_count: usize = @floatToInt(usize, @intToFloat(f32, indices.items.len) * threshold);
|
||||
const target_error: f32 = 1e-2;
|
||||
|
||||
var lod_indices = std.ArrayList(u32).init(arena);
|
||||
lod_indices.resize(indices.items.len) catch unreachable;
|
||||
var lod_error: f32 = 0.0;
|
||||
var lod_indices_count = zmesh.opt.simplifySloppy(
|
||||
[3]f32,
|
||||
lod_indices.items,
|
||||
indices.items,
|
||||
indices.items.len,
|
||||
positions.items,
|
||||
positions.items.len,
|
||||
target_index_count,
|
||||
target_error,
|
||||
&lod_error,
|
||||
);
|
||||
lod_indices.resize(lod_indices_count) catch unreachable;
|
||||
|
||||
mesh.lods[lod_index] = .{
|
||||
.index_offset = mesh.lods[lod_index - 1].index_offset + mesh.lods[lod_index - 1].num_indices,
|
||||
.num_indices = @intCast(u32, lod_indices_count),
|
||||
};
|
||||
|
||||
all_lods_indices.appendSlice(lod_indices.items) catch unreachable;
|
||||
}
|
||||
|
||||
indices.appendSlice(all_lods_indices.items) catch unreachable;
|
||||
}
|
||||
|
||||
all_meshes.append(mesh) catch unreachable;
|
||||
|
||||
try all_indices.ensureTotalCapacity(indices.items.len);
|
||||
for (indices.items) |mesh_index| {
|
||||
@@ -370,13 +426,14 @@ fn init(allocator: std.mem.Allocator) !DemoState {
|
||||
var all_vertices = std.ArrayList(Vertex).init(arena_allocator);
|
||||
var all_indices = std.ArrayList(u32).init(arena_allocator);
|
||||
|
||||
try loadMesh(arena_allocator, content_dir ++ "cube.gltf", &all_meshes, &all_vertices, &all_indices);
|
||||
try loadMesh(arena_allocator, content_dir ++ "cube.gltf", &all_meshes, &all_vertices, &all_indices, 0);
|
||||
try loadMesh(
|
||||
arena_allocator,
|
||||
content_dir ++ "SciFiHelmet/SciFiHelmet.gltf",
|
||||
&all_meshes,
|
||||
&all_vertices,
|
||||
&all_indices,
|
||||
max_num_lods,
|
||||
);
|
||||
|
||||
const depth_texture = .{
|
||||
@@ -463,7 +520,7 @@ fn init(allocator: std.mem.Allocator) !DemoState {
|
||||
content_dir ++ "Newport_Loft.hdr",
|
||||
}) catch unreachable;
|
||||
|
||||
var image = zstbi.Image.init(pathname, 4) catch unreachable;
|
||||
var image = zstbi.Image.loadFromFile(pathname, 4) catch unreachable;
|
||||
defer {
|
||||
image.deinit();
|
||||
zstbi.setFlipVerticallyOnLoad(false);
|
||||
@@ -835,6 +892,7 @@ fn init(allocator: std.mem.Allocator) !DemoState {
|
||||
.vertex_buffer = vertex_buffer,
|
||||
.index_buffer = index_buffer,
|
||||
.draw_mode = 0,
|
||||
.current_lod = 0,
|
||||
.camera = .{
|
||||
.position = Vec3.init(2.2, 0.0, 2.2),
|
||||
.forward = Vec3.initZero(),
|
||||
@@ -879,6 +937,7 @@ fn update(demo: *DemoState) void {
|
||||
_ = c.igRadioButton_IntPtr("Draw Metallic texture", &demo.draw_mode, 3);
|
||||
_ = c.igRadioButton_IntPtr("Draw Roughness texture", &demo.draw_mode, 4);
|
||||
_ = c.igRadioButton_IntPtr("Draw Normal texture", &demo.draw_mode, 5);
|
||||
_ = c.igSliderInt("SciFi Helmet LOD", &demo.current_lod, 0, max_num_lods - 1, "%d", 0);
|
||||
c.igEnd();
|
||||
|
||||
// Handle camera rotation with mouse.
|
||||
@@ -1007,9 +1066,9 @@ fn draw(demo: *DemoState) void {
|
||||
});
|
||||
|
||||
gctx.cmdlist.DrawIndexedInstanced(
|
||||
demo.meshes.items[mesh_helmet].num_indices,
|
||||
demo.meshes.items[mesh_helmet].lods[@intCast(usize, demo.current_lod)].num_indices,
|
||||
1,
|
||||
demo.meshes.items[mesh_helmet].index_offset,
|
||||
demo.meshes.items[mesh_helmet].lods[@intCast(usize, demo.current_lod)].index_offset,
|
||||
@intCast(i32, demo.meshes.items[mesh_helmet].vertex_offset),
|
||||
0,
|
||||
);
|
||||
@@ -1027,9 +1086,9 @@ fn draw(demo: *DemoState) void {
|
||||
gctx.cmdlist.SetGraphicsRootDescriptorTable(1, gctx.copyDescriptorsToGpuHeap(1, demo.env_texture.view));
|
||||
|
||||
gctx.cmdlist.DrawIndexedInstanced(
|
||||
demo.meshes.items[mesh_cube].num_indices,
|
||||
demo.meshes.items[mesh_cube].lods[0].num_indices,
|
||||
1,
|
||||
demo.meshes.items[mesh_cube].index_offset,
|
||||
demo.meshes.items[mesh_cube].lods[0].index_offset,
|
||||
@intCast(i32, demo.meshes.items[mesh_cube].vertex_offset),
|
||||
0,
|
||||
);
|
||||
|
||||
@@ -30,7 +30,7 @@ fn create(allocator: std.mem.Allocator, window: *zglfw.Window) !*DemoState {
|
||||
zstbi.init(arena);
|
||||
defer zstbi.deinit();
|
||||
|
||||
var image = try zstbi.Image.init(content_dir ++ "genart_0025_5.png", 4);
|
||||
var image = try zstbi.Image.loadFromFile(content_dir ++ "genart_0025_5.png", 4);
|
||||
defer image.deinit();
|
||||
|
||||
// Create a texture.
|
||||
|
||||
@@ -33,6 +33,17 @@ pub fn main() !void {
|
||||
|
||||
try gl.loadCoreProfile(sdl.gl.getProcAddress, gl_major, gl_minor);
|
||||
|
||||
{
|
||||
var w: i32 = undefined;
|
||||
var h: i32 = undefined;
|
||||
|
||||
window.getSize(&w, &h);
|
||||
std.debug.print("Window size is {d}x{d}\n", .{ w, h });
|
||||
|
||||
sdl.gl.getDrawableSize(window, &w, &h);
|
||||
std.debug.print("Drawable size is {d}x{d}\n", .{ w, h });
|
||||
}
|
||||
|
||||
main_loop: while (true) {
|
||||
var event: sdl.Event = undefined;
|
||||
while (sdl.pollEvent(&event)) {
|
||||
|
||||
@@ -244,7 +244,7 @@ fn create(allocator: std.mem.Allocator, window: *zglfw.Window) !*DemoState {
|
||||
var mesh_texv: [num_mesh_textures]zgpu.TextureViewHandle = undefined;
|
||||
|
||||
for (mesh_texture_paths, 0..) |path, tex_index| {
|
||||
var image = try zstbi.Image.init(path, 4);
|
||||
var image = try zstbi.Image.loadFromFile(path, 4);
|
||||
defer image.deinit();
|
||||
|
||||
mesh_tex[tex_index] = gctx.createTexture(.{
|
||||
@@ -808,7 +808,7 @@ fn precomputeImageLighting(
|
||||
content_dir ++ "freight_station_4k.hdr",
|
||||
};
|
||||
zstbi.setFlipVerticallyOnLoad(true);
|
||||
var image = zstbi.Image.init(
|
||||
var image = zstbi.Image.loadFromFile(
|
||||
hdri_paths[@intCast(usize, demo.current_hdri_index)],
|
||||
4,
|
||||
) catch unreachable;
|
||||
|
||||
@@ -109,7 +109,7 @@ fn create(allocator: std.mem.Allocator, window: *zglfw.Window) !*DemoState {
|
||||
zstbi.init(arena);
|
||||
defer zstbi.deinit();
|
||||
|
||||
var image = try zstbi.Image.init(content_dir ++ "genart_0025_5.png", 4);
|
||||
var image = try zstbi.Image.loadFromFile(content_dir ++ "genart_0025_5.png", 4);
|
||||
defer image.deinit();
|
||||
|
||||
// Create a texture.
|
||||
|
||||
Reference in new issue
Block a user