struct typedef progress
This commit is contained in:
parent
06e69945c9
commit
8f96d89f35
2
build.c
2
build.c
@ -867,7 +867,7 @@ void OnBuild(StringList cli_args)
|
|||||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/sound/sound.c"), D_TagKind_File));
|
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/sound/sound.c"), D_TagKind_File));
|
||||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/draw/draw.c"), D_TagKind_File));
|
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/draw/draw.c"), D_TagKind_File));
|
||||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/inc/inc.c"), D_TagKind_File));
|
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/inc/inc.c"), D_TagKind_File));
|
||||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/host/host.c"), D_TagKind_File));
|
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/net/net.c"), D_TagKind_File));
|
||||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/asset_cache/asset_cache.c"), D_TagKind_File));
|
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/asset_cache/asset_cache.c"), D_TagKind_File));
|
||||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/mixer/mixer.c"), D_TagKind_File));
|
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/mixer/mixer.c"), D_TagKind_File));
|
||||||
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/settings/settings.c"), D_TagKind_File));
|
D_TagListAppend(&perm, &src_files, D_TagFromPath(&perm, Lit("src/settings/settings.c"), D_TagKind_File));
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
#include "../asset_cache/asset_cache.h"
|
#include "../asset_cache/asset_cache.h"
|
||||||
#include "../mixer/mixer.h"
|
#include "../mixer/mixer.h"
|
||||||
#include "../settings/settings.h"
|
#include "../settings/settings.h"
|
||||||
#include "../host/host.h"
|
#include "../net/net.h"
|
||||||
#include "../resource/resource.h"
|
#include "../resource/resource.h"
|
||||||
#include "../playback/playback.h"
|
#include "../playback/playback.h"
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct string write_path;
|
String write_path;
|
||||||
} G = ZI, DEBUG_ALIAS(G, G_app);
|
} G = ZI, DEBUG_ALIAS(G, G_app);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Write directory
|
* Write directory
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct string initialize_write_directory(struct arena *arena, struct string write_dir)
|
INTERNAL String initialize_write_directory(Arena *arena, String write_dir)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
/* Create write path */
|
/* Create write path */
|
||||||
struct string base_write_dir = sys_get_write_path(scratch.arena);
|
String base_write_dir = sys_get_write_path(scratch.arena);
|
||||||
struct string write_path_fmt = base_write_dir.len > 0 ? LIT("%F/%F/") : LIT("%F%F/");
|
String write_path_fmt = base_write_dir.len > 0 ? LIT("%F/%F/") : LIT("%F%F/");
|
||||||
struct string write_path = string_format(
|
String write_path = string_format(
|
||||||
arena,
|
arena,
|
||||||
write_path_fmt,
|
write_path_fmt,
|
||||||
FMT_STR(base_write_dir),
|
FMT_STR(base_write_dir),
|
||||||
@ -32,7 +32,7 @@ INTERNAL struct string initialize_write_directory(struct arena *arena, struct st
|
|||||||
return write_path;
|
return write_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string app_write_path_cat(struct arena *arena, struct string filename)
|
String app_write_path_cat(Arena *arena, String filename)
|
||||||
{
|
{
|
||||||
return string_cat(arena, G.write_path, filename);
|
return string_cat(arena, G.write_path, filename);
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ INTERNAL struct sys_window_settings default_window_settings(struct sys_window *w
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct v2 monitor_size = sys_window_get_monitor_size(window);
|
V2 monitor_size = sys_window_get_monitor_size(window);
|
||||||
|
|
||||||
i32 width = 1280;
|
i32 width = 1280;
|
||||||
i32 height = math_round_to_int(width / (f32)(DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT));
|
i32 height = math_round_to_int(width / (f32)(DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT));
|
||||||
@ -66,8 +66,8 @@ INTERNAL struct sys_window_settings default_window_settings(struct sys_window *w
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct app_arg {
|
struct app_arg {
|
||||||
struct string key;
|
String key;
|
||||||
struct string value;
|
String value;
|
||||||
struct app_arg *next;
|
struct app_arg *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ struct app_arg_list {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* TODO: Remove this and do real argument parsing */
|
/* TODO: Remove this and do real argument parsing */
|
||||||
INTERNAL struct app_arg_list parse_args(struct arena *arena, struct string args_str)
|
INTERNAL struct app_arg_list parse_args(Arena *arena, String args_str)
|
||||||
{
|
{
|
||||||
struct app_arg_list res = ZI;
|
struct app_arg_list res = ZI;
|
||||||
i64 mode = 0;
|
i64 mode = 0;
|
||||||
@ -118,8 +118,8 @@ INTERNAL struct app_arg_list parse_args(struct arena *arena, struct string args_
|
|||||||
value_end = i + 1;
|
value_end = i + 1;
|
||||||
}
|
}
|
||||||
if (key_start >= 0 && key_end > key_start && key_end <= (i64)args_str.len && value_start >= 0 && value_end > value_start && value_end <= (i64)args_str.len) {
|
if (key_start >= 0 && key_end > key_start && key_end <= (i64)args_str.len && value_start >= 0 && value_end > value_start && value_end <= (i64)args_str.len) {
|
||||||
struct string key = string_copy(arena, STRING(key_end - key_start, args_str.text + key_start));
|
String key = string_copy(arena, STRING(key_end - key_start, args_str.text + key_start));
|
||||||
struct string value = string_copy(arena, STRING(value_end - value_start, args_str.text + value_start));
|
String value = string_copy(arena, STRING(value_end - value_start, args_str.text + value_start));
|
||||||
struct app_arg *arg = arena_push(arena, struct app_arg);
|
struct app_arg *arg = arena_push(arena, struct app_arg);
|
||||||
arg->key = key;
|
arg->key = key;
|
||||||
arg->value = value;
|
arg->value = value;
|
||||||
@ -146,18 +146,18 @@ INTERNAL struct app_arg_list parse_args(struct arena *arena, struct string args_
|
|||||||
* Entry point
|
* Entry point
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sys_app_startup(struct string args_str)
|
void sys_app_startup(String args_str)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct app_arg_list args = parse_args(scratch.arena, args_str);
|
struct app_arg_list args = parse_args(scratch.arena, args_str);
|
||||||
struct string logfile_name = LIT("log.log");
|
String logfile_name = LIT("log.log");
|
||||||
struct string settings_file_name = LIT("settings.txt");
|
String settings_file_name = LIT("settings.txt");
|
||||||
struct string connect_address = ZI;
|
String connect_address = ZI;
|
||||||
for (struct app_arg *arg = args.first; arg; arg = arg->next) {
|
for (struct app_arg *arg = args.first; arg; arg = arg->next) {
|
||||||
struct string key = arg->key;
|
String key = arg->key;
|
||||||
struct string value = arg->value;
|
String value = arg->value;
|
||||||
if (string_eq(key, LIT("log"))) {
|
if (string_eq(key, LIT("log"))) {
|
||||||
logfile_name = value;
|
logfile_name = value;
|
||||||
} else if (string_eq(key, LIT("settings"))) {
|
} else if (string_eq(key, LIT("settings"))) {
|
||||||
@ -194,10 +194,10 @@ void sys_app_startup(struct string args_str)
|
|||||||
|
|
||||||
/* Startup logging */
|
/* Startup logging */
|
||||||
{
|
{
|
||||||
struct arena_temp temp = arena_temp_begin(scratch.arena);
|
TempArena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
struct string logfile_dir = string_cat(temp.arena, G.write_path, LIT("logs/"));
|
String logfile_dir = string_cat(temp.arena, G.write_path, LIT("logs/"));
|
||||||
struct string logfile_path = string_cat(temp.arena, logfile_dir, logfile_name);
|
String logfile_path = string_cat(temp.arena, logfile_dir, logfile_name);
|
||||||
sys_mkdir(logfile_dir);
|
sys_mkdir(logfile_dir);
|
||||||
|
|
||||||
log_startup(logfile_path);
|
log_startup(logfile_path);
|
||||||
@ -212,22 +212,22 @@ void sys_app_startup(struct string args_str)
|
|||||||
#if 0
|
#if 0
|
||||||
/* Read window settings from file */
|
/* Read window settings from file */
|
||||||
{
|
{
|
||||||
struct arena_temp temp = arena_temp_begin(scratch.arena);
|
TempArena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
struct sys_window_settings window_settings = ZI;
|
struct sys_window_settings window_settings = ZI;
|
||||||
struct string settings_path = app_write_path_cat(temp.arena, settings_file_name);
|
String settings_path = app_write_path_cat(temp.arena, settings_file_name);
|
||||||
logf_info("Looking for settings file \"%F\"", FMT_STR(settings_path));
|
logf_info("Looking for settings file \"%F\"", FMT_STR(settings_path));
|
||||||
if (sys_is_file(settings_path)) {
|
if (sys_is_file(settings_path)) {
|
||||||
logf_info("Settings file found");
|
logf_info("Settings file found");
|
||||||
struct sys_file settings_file = sys_file_open_read(settings_path);
|
struct sys_file settings_file = sys_file_open_read(settings_path);
|
||||||
struct string file_data = sys_file_read_all(temp.arena, settings_file);
|
String file_data = sys_file_read_all(temp.arena, settings_file);
|
||||||
sys_file_close(settings_file);
|
sys_file_close(settings_file);
|
||||||
logf_info("Deserializing settings file data: %F", FMT_STR(file_data));
|
logf_info("Deserializing settings file data: %F", FMT_STR(file_data));
|
||||||
struct string error = ZI;
|
String error = ZI;
|
||||||
struct sys_window_settings *res = settings_deserialize(temp.arena, file_data, &error);
|
struct sys_window_settings *res = settings_deserialize(temp.arena, file_data, &error);
|
||||||
if (error.len > 0) {
|
if (error.len > 0) {
|
||||||
logf_info("Failed to load settings file with error - %F", FMT_STR(error));
|
logf_info("Failed to load settings file with error - %F", FMT_STR(error));
|
||||||
struct string msg = string_format(temp.arena,
|
String msg = string_format(temp.arena,
|
||||||
LIT(
|
LIT(
|
||||||
"Failed to loading settings file \"%F\":\n"
|
"Failed to loading settings file \"%F\":\n"
|
||||||
"------------\n"
|
"------------\n"
|
||||||
@ -258,18 +258,18 @@ void sys_app_startup(struct string args_str)
|
|||||||
gp_startup();
|
gp_startup();
|
||||||
|
|
||||||
/* Subsystems */
|
/* Subsystems */
|
||||||
struct host_startup_receipt host_sr = host_startup();
|
N_StartupReceipt host_sr = host_startup();
|
||||||
struct asset_cache_startup_receipt asset_cache_sr = asset_cache_startup();
|
AC_StartupReceipt asset_cache_sr = asset_cache_startup();
|
||||||
struct ttf_startup_receipt ttf_sr = ttf_startup();
|
TTF_StartupReceipt ttf_sr = ttf_startup();
|
||||||
struct font_startup_receipt font_sr = font_startup(&asset_cache_sr, &ttf_sr);
|
F_StartupReceipt font_sr = font_startup(&asset_cache_sr, &ttf_sr);
|
||||||
struct sprite_startup_receipt sprite_sr = sprite_startup();
|
struct sprite_startup_receipt sprite_sr = sprite_startup();
|
||||||
struct mixer_startup_receipt mixer_sr = mixer_startup();
|
M_StartupReceipt mixer_sr = mixer_startup();
|
||||||
struct sound_startup_receipt sound_sr = sound_startup(&asset_cache_sr);
|
struct sound_startup_receipt sound_sr = sound_startup(&asset_cache_sr);
|
||||||
struct draw_startup_receipt draw_sr = draw_startup(&font_sr);
|
D_StartupReceipt draw_sr = draw_startup(&font_sr);
|
||||||
struct sim_startup_receipt sim_sr = sim_startup();
|
struct sim_startup_receipt sim_sr = sim_startup();
|
||||||
|
|
||||||
/* Interface systems */
|
/* Interface systems */
|
||||||
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);
|
PB_StartupReceipt playback_sr = playback_startup(&mixer_sr);
|
||||||
struct user_startup_receipt user_sr = user_startup(&font_sr, &sprite_sr, &draw_sr, &asset_cache_sr, &sound_sr, &mixer_sr, &host_sr, &sim_sr, connect_address);
|
struct user_startup_receipt user_sr = user_startup(&font_sr, &sprite_sr, &draw_sr, &asset_cache_sr, &sound_sr, &mixer_sr, &host_sr, &sim_sr, connect_address);
|
||||||
|
|
||||||
(UNUSED)user_sr;
|
(UNUSED)user_sr;
|
||||||
@ -279,12 +279,12 @@ void sys_app_startup(struct string args_str)
|
|||||||
/* Write window settings to file */
|
/* Write window settings to file */
|
||||||
{
|
{
|
||||||
__profn("Write settings file");
|
__profn("Write settings file");
|
||||||
struct arena_temp temp = arena_temp_begin(scratch.arena);
|
TempArena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
struct string window_settings_path = app_write_path_cat(temp.arena, settings_file_name);
|
String window_settings_path = app_write_path_cat(temp.arena, settings_file_name);
|
||||||
|
|
||||||
struct sys_window_settings settings = sys_window_get_settings(window);
|
struct sys_window_settings settings = sys_window_get_settings(window);
|
||||||
struct string str = settings_serialize(temp.arena, &settings);
|
String str = settings_serialize(temp.arena, &settings);
|
||||||
logf_info("Serialized window settings: %F", FMT_STR(str));
|
logf_info("Serialized window settings: %F", FMT_STR(str));
|
||||||
|
|
||||||
logf_info("Writing settings file to path \"%F\"", FMT_STR(window_settings_path));
|
logf_info("Writing settings file to path \"%F\"", FMT_STR(window_settings_path));
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
struct string app_write_path_cat(struct arena *arena, struct string filename);
|
String app_write_path_cat(Arena *arena, String filename);
|
||||||
|
|||||||
@ -172,7 +172,7 @@ INTERNAL u32 reverse_bits(u32 v, u32 bit_count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct huffman huffman_init(struct arena *arena, u32 max_code_bits, u32 *bl_counts, u32 bl_counts_count)
|
INTERNAL struct huffman huffman_init(Arena *arena, u32 max_code_bits, u32 *bl_counts, u32 bl_counts_count)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ INTERNAL u16 huffman_decode(struct huffman *huffman, struct huff_bb *bb)
|
|||||||
|
|
||||||
INTERNAL void inflate(u8 *dst, u8 *encoded)
|
INTERNAL void inflate(u8 *dst, u8 *encoded)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
__prof;
|
__prof;
|
||||||
struct huff_bb bb = { .data = encoded };
|
struct huff_bb bb = { .data = encoded };
|
||||||
@ -271,7 +271,7 @@ INTERNAL void inflate(u8 *dst, u8 *encoded)
|
|||||||
|
|
||||||
case BLOCK_TYPE_COMPRESSED_FIXED:
|
case BLOCK_TYPE_COMPRESSED_FIXED:
|
||||||
case BLOCK_TYPE_COMPRESSED_DYNAMIC: {
|
case BLOCK_TYPE_COMPRESSED_DYNAMIC: {
|
||||||
struct arena_temp temp = arena_temp_begin(scratch.arena);
|
TempArena temp = arena_temp_begin(scratch.arena);
|
||||||
u32 lit_len_dist_table[512] = ZI;
|
u32 lit_len_dist_table[512] = ZI;
|
||||||
u32 hlit;
|
u32 hlit;
|
||||||
u32 hdist;
|
u32 hdist;
|
||||||
@ -440,9 +440,9 @@ PACK(struct frame_header {
|
|||||||
u32 chunks_new;
|
u32 chunks_new;
|
||||||
});
|
});
|
||||||
|
|
||||||
INTERNAL void push_error_copy_msg(struct arena *arena, struct ase_error_list *list, struct string msg_src)
|
INTERNAL void push_error_copy_msg(Arena *arena, Ase_ErrorList *list, String msg_src)
|
||||||
{
|
{
|
||||||
struct ase_error *e = arena_push(arena, struct ase_error);
|
Ase_Error *e = arena_push(arena, Ase_Error);
|
||||||
e->msg = string_copy(arena, msg_src);
|
e->msg = string_copy(arena, msg_src);
|
||||||
if (!list->first) {
|
if (!list->first) {
|
||||||
list->first = e;
|
list->first = e;
|
||||||
@ -463,7 +463,7 @@ struct layer {
|
|||||||
u16 child_level;
|
u16 child_level;
|
||||||
u16 blend_mode;
|
u16 blend_mode;
|
||||||
u8 opacity;
|
u8 opacity;
|
||||||
struct string name;
|
String name;
|
||||||
u32 tileset_index;
|
u32 tileset_index;
|
||||||
|
|
||||||
u32 index;
|
u32 index;
|
||||||
@ -544,15 +544,15 @@ INTERNAL void make_image_dimensions_squareish(struct ase_header *header, u32 *fr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ase_decode_image_result ase_decode_image(struct arena *arena, struct string encoded)
|
Ase_DecodedImage ase_decode_image(Arena *arena, String encoded)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
struct ase_decode_image_result res = ZI;
|
Ase_DecodedImage res = ZI;
|
||||||
|
|
||||||
struct bitbuff bb = bitbuff_from_string(encoded);
|
Bitbuff bb = bitbuff_from_string(encoded);
|
||||||
struct bitbuff_reader br = br_from_bitbuff_no_debug(&bb);
|
BitbuffReader br = br_from_bitbuff_no_debug(&bb);
|
||||||
struct ase_header ase_header;
|
struct ase_header ase_header;
|
||||||
br_read_bytes(&br, STRING_FROM_STRUCT(&ase_header));
|
br_read_bytes(&br, STRING_FROM_STRUCT(&ase_header));
|
||||||
|
|
||||||
@ -562,7 +562,7 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ase_header.color_depth != 32) {
|
if (ase_header.color_depth != 32) {
|
||||||
struct string msg = string_format(scratch.arena,
|
String msg = string_format(scratch.arena,
|
||||||
LIT("Only 32 bit rgba color mode is supported (got %F)"),
|
LIT("Only 32 bit rgba color mode is supported (got %F)"),
|
||||||
FMT_UINT(ase_header.color_depth));
|
FMT_UINT(ase_header.color_depth));
|
||||||
push_error_copy_msg(arena, &res.errors, msg);
|
push_error_copy_msg(arena, &res.errors, msg);
|
||||||
@ -641,7 +641,7 @@ struct ase_decode_image_result ase_decode_image(struct arena *arena, struct stri
|
|||||||
br_seek_bytes(&br, sizeof(u8) * 3);
|
br_seek_bytes(&br, sizeof(u8) * 3);
|
||||||
|
|
||||||
u16 str_len = br_read_ubits(&br, 16);
|
u16 str_len = br_read_ubits(&br, 16);
|
||||||
layer->name = (struct string) { str_len, arena_push_array_no_zero(scratch.arena, u8, str_len) };
|
layer->name = (String) { str_len, arena_push_array_no_zero(scratch.arena, u8, str_len) };
|
||||||
br_read_bytes(&br, layer->name);
|
br_read_bytes(&br, layer->name);
|
||||||
|
|
||||||
if (layer->type == 2) {
|
if (layer->type == 2) {
|
||||||
@ -806,14 +806,14 @@ abort:
|
|||||||
* Decode sheet
|
* Decode sheet
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct string encoded)
|
Ase_DecodedSheet ase_decode_sheet(Arena *arena, String encoded)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct ase_decode_sheet_result res = ZI;
|
Ase_DecodedSheet res = ZI;
|
||||||
|
|
||||||
struct bitbuff bb = bitbuff_from_string(encoded);
|
Bitbuff bb = bitbuff_from_string(encoded);
|
||||||
struct bitbuff_reader br = br_from_bitbuff_no_debug(&bb);
|
BitbuffReader br = br_from_bitbuff_no_debug(&bb);
|
||||||
struct ase_header ase_header;
|
struct ase_header ase_header;
|
||||||
br_read_bytes(&br, STRING_FROM_STRUCT(&ase_header));
|
br_read_bytes(&br, STRING_FROM_STRUCT(&ase_header));
|
||||||
|
|
||||||
@ -827,13 +827,13 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct stri
|
|||||||
make_image_dimensions_squareish(&ase_header, &frames_x, &frames_y, &image_width, &image_height);
|
make_image_dimensions_squareish(&ase_header, &frames_x, &frames_y, &image_width, &image_height);
|
||||||
|
|
||||||
u32 num_frames = 0;
|
u32 num_frames = 0;
|
||||||
struct ase_frame *frame_head = 0;
|
Ase_Frame *frame_head = 0;
|
||||||
|
|
||||||
u32 num_spans = 0;
|
u32 num_spans = 0;
|
||||||
struct ase_span *span_head = 0;
|
Ase_Span *span_head = 0;
|
||||||
|
|
||||||
u32 num_slice_keys = 0;
|
u32 num_slice_keys = 0;
|
||||||
struct ase_slice_key *slice_key_head = 0;
|
Ase_SliceKey *slice_key_head = 0;
|
||||||
|
|
||||||
/* Iterate frames */
|
/* Iterate frames */
|
||||||
for (u16 i = 0; i < ase_header.frames; ++i) {
|
for (u16 i = 0; i < ase_header.frames; ++i) {
|
||||||
@ -846,7 +846,7 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct stri
|
|||||||
num_chunks = frame_header.chunks_old;
|
num_chunks = frame_header.chunks_old;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ase_frame *frame = arena_push(arena, struct ase_frame);
|
Ase_Frame *frame = arena_push(arena, Ase_Frame);
|
||||||
frame->next = frame_head;
|
frame->next = frame_head;
|
||||||
frame_head = frame;
|
frame_head = frame;
|
||||||
|
|
||||||
@ -885,7 +885,7 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct stri
|
|||||||
br_seek_bytes(&br, 8);
|
br_seek_bytes(&br, 8);
|
||||||
|
|
||||||
for (u16 k = 0; k < frame_span_count; ++k) {
|
for (u16 k = 0; k < frame_span_count; ++k) {
|
||||||
struct ase_span *span = arena_push(arena, struct ase_span);
|
Ase_Span *span = arena_push(arena, Ase_Span);
|
||||||
span->next = span_head;
|
span->next = span_head;
|
||||||
span_head = span;
|
span_head = span;
|
||||||
|
|
||||||
@ -894,7 +894,7 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct stri
|
|||||||
br_seek_bytes(&br, 13);
|
br_seek_bytes(&br, 13);
|
||||||
|
|
||||||
u16 str_len = br_read_ubits(&br, 16);
|
u16 str_len = br_read_ubits(&br, 16);
|
||||||
span->name = (struct string) { str_len, arena_push_array_no_zero(arena, u8, str_len) };
|
span->name = (String) { str_len, arena_push_array_no_zero(arena, u8, str_len) };
|
||||||
br_read_bytes(&br, span->name);
|
br_read_bytes(&br, span->name);
|
||||||
|
|
||||||
++num_spans;
|
++num_spans;
|
||||||
@ -903,7 +903,7 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct stri
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case CHUNK_TYPE_SLICE: {
|
case CHUNK_TYPE_SLICE: {
|
||||||
struct ase_slice_key *slice_key = arena_push(arena, struct ase_slice_key);
|
Ase_SliceKey *slice_key = arena_push(arena, Ase_SliceKey);
|
||||||
slice_key->next = slice_key_head;
|
slice_key->next = slice_key_head;
|
||||||
slice_key_head = slice_key;
|
slice_key_head = slice_key;
|
||||||
|
|
||||||
@ -914,11 +914,11 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct stri
|
|||||||
br_seek_bytes(&br, 4);
|
br_seek_bytes(&br, 4);
|
||||||
|
|
||||||
u16 str_len = br_read_ubits(&br, 16);
|
u16 str_len = br_read_ubits(&br, 16);
|
||||||
slice_key->name = (struct string) { str_len, arena_push_array_no_zero(arena, u8, str_len) };
|
slice_key->name = (String) { str_len, arena_push_array_no_zero(arena, u8, str_len) };
|
||||||
br_read_bytes(&br, slice_key->name);
|
br_read_bytes(&br, slice_key->name);
|
||||||
|
|
||||||
for (u32 k = 0; k < num_slices; ++k) {
|
for (u32 k = 0; k < num_slices; ++k) {
|
||||||
struct ase_slice *slice = arena_push(arena, struct ase_slice);
|
Ase_Slice *slice = arena_push(arena, Ase_Slice);
|
||||||
slice->next = slice_key->slice_head;
|
slice->next = slice_key->slice_head;
|
||||||
slice_key->slice_head = slice;
|
slice_key->slice_head = slice;
|
||||||
|
|
||||||
@ -960,8 +960,8 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct stri
|
|||||||
/* ASSERT all data was read */
|
/* ASSERT all data was read */
|
||||||
ASSERT(br_num_bytes_left(&br) == 0);
|
ASSERT(br_num_bytes_left(&br) == 0);
|
||||||
|
|
||||||
res.image_size = V2(image_width, image_height);
|
res.image_size = V2FromXY(image_width, image_height);
|
||||||
res.frame_size = V2(frame_width, frame_height);
|
res.frame_size = V2FromXY(frame_width, frame_height);
|
||||||
res.num_frames = num_frames;
|
res.num_frames = num_frames;
|
||||||
res.num_spans = num_spans;
|
res.num_spans = num_spans;
|
||||||
res.num_slice_keys = num_slice_keys;
|
res.num_slice_keys = num_slice_keys;
|
||||||
|
|||||||
@ -1,65 +1,73 @@
|
|||||||
struct ase_error {
|
typedef struct Ase_Error Ase_Error;
|
||||||
struct string msg;
|
struct Ase_Error {
|
||||||
struct ase_error *next;
|
String msg;
|
||||||
|
Ase_Error *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ase_error_list {
|
typedef struct Ase_ErrorList Ase_ErrorList;
|
||||||
|
struct Ase_ErrorList {
|
||||||
u64 count;
|
u64 count;
|
||||||
struct ase_error *first;
|
Ase_Error *first;
|
||||||
struct ase_error *last;
|
Ase_Error *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ase_slice {
|
typedef struct Ase_Slice Ase_Slice;
|
||||||
|
struct Ase_Slice {
|
||||||
u32 start;
|
u32 start;
|
||||||
i32 x1;
|
i32 x1;
|
||||||
i32 y1;
|
i32 y1;
|
||||||
i32 x2;
|
i32 x2;
|
||||||
i32 y2;
|
i32 y2;
|
||||||
struct ase_slice *next;
|
Ase_Slice *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ase_slice_key {
|
typedef struct Ase_SliceKey Ase_SliceKey;
|
||||||
struct string name;
|
struct Ase_SliceKey {
|
||||||
|
String name;
|
||||||
u32 num_slices;
|
u32 num_slices;
|
||||||
struct ase_slice *slice_head;
|
Ase_Slice *slice_head;
|
||||||
struct ase_slice_key *next;
|
Ase_SliceKey *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ase_span {
|
typedef struct Ase_Span Ase_Span;
|
||||||
struct string name;
|
struct Ase_Span {
|
||||||
|
String name;
|
||||||
u32 start;
|
u32 start;
|
||||||
u32 end;
|
u32 end;
|
||||||
struct ase_span *next;
|
Ase_Span *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ase_frame {
|
typedef struct Ase_Frame Ase_Frame;
|
||||||
|
struct Ase_Frame {
|
||||||
u32 index;
|
u32 index;
|
||||||
u32 x1;
|
u32 x1;
|
||||||
u32 y1;
|
u32 y1;
|
||||||
u32 x2;
|
u32 x2;
|
||||||
u32 y2;
|
u32 y2;
|
||||||
f64 duration;
|
f64 duration;
|
||||||
struct ase_frame *next;
|
Ase_Frame *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ase_decode_image_result {
|
typedef struct Ase_DecodedImage Ase_DecodedImage;
|
||||||
struct image_rgba image;
|
struct Ase_DecodedImage {
|
||||||
struct ase_error_list errors;
|
ImageDataRgba image;
|
||||||
|
Ase_ErrorList errors;
|
||||||
b32 success;
|
b32 success;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ase_decode_sheet_result {
|
typedef struct Ase_DecodedSheet Ase_DecodedSheet;
|
||||||
struct v2 image_size;
|
struct Ase_DecodedSheet {
|
||||||
struct v2 frame_size;
|
V2 image_size;
|
||||||
|
V2 frame_size;
|
||||||
u32 num_frames;
|
u32 num_frames;
|
||||||
u32 num_spans;
|
u32 num_spans;
|
||||||
u32 num_slice_keys;
|
u32 num_slice_keys;
|
||||||
struct ase_frame *frame_head;
|
Ase_Frame *frame_head;
|
||||||
struct ase_span *span_head;
|
Ase_Span *span_head;
|
||||||
struct ase_slice_key *slice_key_head;
|
Ase_SliceKey *slice_key_head;
|
||||||
struct ase_error_list errors;
|
Ase_ErrorList errors;
|
||||||
b32 success;
|
b32 success;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ase_decode_image_result ase_decode_image(struct arena *arena, struct string encoded);
|
Ase_DecodedImage ase_decode_image(Arena *arena, String encoded);
|
||||||
struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct string encoded);
|
Ase_DecodedSheet ase_decode_sheet(Arena *arena, String encoded);
|
||||||
|
|||||||
@ -7,15 +7,15 @@
|
|||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct snc_mutex lookup_mutex;
|
struct snc_mutex lookup_mutex;
|
||||||
struct asset lookup[ASSET_LOOKUP_TABLE_CAPACITY];
|
AC_Asset lookup[ASSET_LOOKUP_TABLE_CAPACITY];
|
||||||
u64 num_assets;
|
u64 num_assets;
|
||||||
|
|
||||||
struct snc_mutex store_mutex;
|
struct snc_mutex store_mutex;
|
||||||
struct arena *store_arena;
|
Arena *store_arena;
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
/* Array of len `num_assets` pointing into populated entries of `lookup`. */
|
/* Array of len `num_assets` pointing into populated entries of `lookup`. */
|
||||||
struct asset *dbg_table[ASSET_LOOKUP_TABLE_CAPACITY];
|
AC_Asset *dbg_table[ASSET_LOOKUP_TABLE_CAPACITY];
|
||||||
u64 dbg_table_count;
|
u64 dbg_table_count;
|
||||||
struct snc_mutex dbg_table_mutex;
|
struct snc_mutex dbg_table_mutex;
|
||||||
#endif
|
#endif
|
||||||
@ -25,12 +25,12 @@ GLOBAL struct {
|
|||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct asset_cache_startup_receipt asset_cache_startup(void)
|
AC_StartupReceipt asset_cache_startup(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
/* Init store */
|
/* Init store */
|
||||||
G.store_arena = arena_alloc(GIBI(64));
|
G.store_arena = arena_alloc(GIBI(64));
|
||||||
return (struct asset_cache_startup_receipt) { 0 };
|
return (AC_StartupReceipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -44,7 +44,7 @@ INTERNAL void refresh_dbg_table(void)
|
|||||||
MEMZERO_ARRAY(G.dbg_table);
|
MEMZERO_ARRAY(G.dbg_table);
|
||||||
G.dbg_table_count = 0;
|
G.dbg_table_count = 0;
|
||||||
for (u64 i = 0; i < countof(G.lookup); ++i) {
|
for (u64 i = 0; i < countof(G.lookup); ++i) {
|
||||||
struct asset *asset = &G.lookup[i];
|
AC_Asset *asset = &G.lookup[i];
|
||||||
if (asset->hash != 0) {
|
if (asset->hash != 0) {
|
||||||
G.dbg_table[G.dbg_table_count++] = asset;
|
G.dbg_table[G.dbg_table_count++] = asset;
|
||||||
}
|
}
|
||||||
@ -55,14 +55,14 @@ INTERNAL void refresh_dbg_table(void)
|
|||||||
|
|
||||||
/* Returns first matching slot or first empty slot if not found.
|
/* Returns first matching slot or first empty slot if not found.
|
||||||
* Check returned slot->hash != 0 for presence. */
|
* Check returned slot->hash != 0 for presence. */
|
||||||
INTERNAL struct asset *asset_cache_get_slot_locked(struct snc_lock *lock, struct string key, u64 hash)
|
INTERNAL AC_Asset *asset_cache_get_slot_locked(struct snc_lock *lock, String key, u64 hash)
|
||||||
{
|
{
|
||||||
snc_assert_locked_e_or_s(lock, &G.lookup_mutex);
|
snc_assert_locked_e_or_s(lock, &G.lookup_mutex);
|
||||||
(UNUSED)lock;
|
(UNUSED)lock;
|
||||||
|
|
||||||
u64 index = hash % countof(G.lookup);
|
u64 index = hash % countof(G.lookup);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct asset *slot = &G.lookup[index];
|
AC_Asset *slot = &G.lookup[index];
|
||||||
if (slot->hash) {
|
if (slot->hash) {
|
||||||
/* Occupied */
|
/* Occupied */
|
||||||
if (hash == slot->hash && string_eq(key, slot->key)) {
|
if (hash == slot->hash && string_eq(key, slot->key)) {
|
||||||
@ -81,7 +81,7 @@ INTERNAL struct asset *asset_cache_get_slot_locked(struct snc_lock *lock, struct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 asset_cache_hash(struct string key)
|
u64 asset_cache_hash(String key)
|
||||||
{
|
{
|
||||||
/* TODO: Better hash */
|
/* TODO: Better hash */
|
||||||
return hash_fnv64(HASH_FNV64_BASIS, key);
|
return hash_fnv64(HASH_FNV64_BASIS, key);
|
||||||
@ -95,9 +95,9 @@ u64 asset_cache_hash(struct string key)
|
|||||||
* inserted the asset into the cache.
|
* inserted the asset into the cache.
|
||||||
*
|
*
|
||||||
* */
|
* */
|
||||||
struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch)
|
AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch)
|
||||||
{
|
{
|
||||||
struct asset *asset = 0;
|
AC_Asset *asset = 0;
|
||||||
|
|
||||||
/* Lookup */
|
/* Lookup */
|
||||||
{
|
{
|
||||||
@ -121,16 +121,16 @@ struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch
|
|||||||
if (G.num_assets >= MAX_ASSETS) {
|
if (G.num_assets >= MAX_ASSETS) {
|
||||||
sys_panic(LIT("Max assets reached"));
|
sys_panic(LIT("Max assets reached"));
|
||||||
}
|
}
|
||||||
struct string key_stored = ZI;
|
String key_stored = ZI;
|
||||||
{
|
{
|
||||||
/* Copy key to store */
|
/* Copy key to store */
|
||||||
struct asset_cache_store store = asset_cache_store_open();
|
AC_Store store = asset_cache_store_open();
|
||||||
key_stored = string_copy(store.arena, key);
|
key_stored = string_copy(store.arena, key);
|
||||||
asset_cache_store_close(&store);
|
asset_cache_store_close(&store);
|
||||||
}
|
}
|
||||||
/* Initialize asset data */
|
/* Initialize asset data */
|
||||||
logf_info("Inserting asset cache entry for \"%F\"", FMT_STR(key));
|
logf_info("Inserting asset cache entry for \"%F\"", FMT_STR(key));
|
||||||
*asset = (struct asset) {
|
*asset = (AC_Asset) {
|
||||||
.status = ASSET_STATUS_UNINITIALIZED,
|
.status = ASSET_STATUS_UNINITIALIZED,
|
||||||
.hash = hash,
|
.hash = hash,
|
||||||
.key = key_stored
|
.key = key_stored
|
||||||
@ -155,13 +155,13 @@ struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Call this once asset job has been created */
|
/* Call this once asset job has been created */
|
||||||
void asset_cache_mark_loading(struct asset *asset)
|
void asset_cache_mark_loading(AC_Asset *asset)
|
||||||
{
|
{
|
||||||
asset->status = ASSET_STATUS_LOADING;
|
asset->status = ASSET_STATUS_LOADING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Call this once asset job has finished */
|
/* Call this once asset job has finished */
|
||||||
void asset_cache_mark_ready(struct asset *asset, void *store_data)
|
void asset_cache_mark_ready(AC_Asset *asset, void *store_data)
|
||||||
{
|
{
|
||||||
asset->store_data = store_data;
|
asset->store_data = store_data;
|
||||||
asset->status = ASSET_STATUS_READY;
|
asset->status = ASSET_STATUS_READY;
|
||||||
@ -172,7 +172,7 @@ void asset_cache_mark_ready(struct asset *asset, void *store_data)
|
|||||||
* Job
|
* Job
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void asset_cache_wait(struct asset *asset)
|
void asset_cache_wait(AC_Asset *asset)
|
||||||
{
|
{
|
||||||
snc_counter_wait(&asset->counter);
|
snc_counter_wait(&asset->counter);
|
||||||
}
|
}
|
||||||
@ -184,7 +184,7 @@ void asset_cache_wait(struct asset *asset)
|
|||||||
/* NOTE: At the moment only one global asset store exists, however in the
|
/* NOTE: At the moment only one global asset store exists, however in the
|
||||||
* future there could be more based on asset lifetime. */
|
* future there could be more based on asset lifetime. */
|
||||||
|
|
||||||
void *asset_cache_get_store_data(struct asset *asset)
|
void *asset_cache_get_store_data(AC_Asset *asset)
|
||||||
{
|
{
|
||||||
if (asset->status == ASSET_STATUS_READY) {
|
if (asset->status == ASSET_STATUS_READY) {
|
||||||
return asset->store_data;
|
return asset->store_data;
|
||||||
@ -194,17 +194,17 @@ void *asset_cache_get_store_data(struct asset *asset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Asset store should be opened to allocate memory to the store arena */
|
/* Asset store should be opened to allocate memory to the store arena */
|
||||||
struct asset_cache_store asset_cache_store_open(void)
|
AC_Store asset_cache_store_open(void)
|
||||||
{
|
{
|
||||||
struct snc_lock lock = snc_lock_e(&G.store_mutex);
|
struct snc_lock lock = snc_lock_e(&G.store_mutex);
|
||||||
struct asset_cache_store store = {
|
AC_Store store = {
|
||||||
.lock = lock,
|
.lock = lock,
|
||||||
.arena = G.store_arena
|
.arena = G.store_arena
|
||||||
};
|
};
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
void asset_cache_store_close(struct asset_cache_store *store)
|
void asset_cache_store_close(AC_Store *store)
|
||||||
{
|
{
|
||||||
snc_unlock(&store->lock);
|
snc_unlock(&store->lock);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,45 +1,48 @@
|
|||||||
enum asset_status {
|
typedef enum AC_Status {
|
||||||
ASSET_STATUS_NONE,
|
ASSET_STATUS_NONE,
|
||||||
|
|
||||||
ASSET_STATUS_UNINITIALIZED,
|
ASSET_STATUS_UNINITIALIZED,
|
||||||
/* TODO: ASSET_STATUS_QUEUED? */
|
/* TODO: ASSET_STATUS_QUEUED? */
|
||||||
ASSET_STATUS_LOADING,
|
ASSET_STATUS_LOADING,
|
||||||
ASSET_STATUS_READY
|
ASSET_STATUS_READY
|
||||||
};
|
} AC_Status;
|
||||||
|
|
||||||
struct asset {
|
typedef struct AC_Asset AC_Asset;
|
||||||
|
struct AC_Asset {
|
||||||
/* Managed via asset_cache_touch */
|
/* Managed via asset_cache_touch */
|
||||||
u64 hash;
|
u64 hash;
|
||||||
struct string key;
|
String key;
|
||||||
|
|
||||||
struct snc_counter counter;
|
struct snc_counter counter;
|
||||||
|
|
||||||
/* Managed via asset_cache_mark_x functions */
|
/* Managed via asset_cache_mark_x functions */
|
||||||
enum asset_status status;
|
AC_Status status;
|
||||||
|
|
||||||
/* Accessed via asset_cache_get_data */
|
/* Accessed via asset_cache_get_data */
|
||||||
void *store_data;
|
void *store_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct asset_cache_store {
|
typedef struct AC_Store AC_Store;
|
||||||
struct arena *arena;
|
struct AC_Store {
|
||||||
|
Arena *arena;
|
||||||
|
|
||||||
/* Internal */
|
/* Internal */
|
||||||
struct snc_lock lock;
|
struct snc_lock lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct asset_cache_startup_receipt { i32 _; };
|
typedef struct AC_StartupReceipt AC_StartupReceipt;
|
||||||
struct asset_cache_startup_receipt asset_cache_startup(void);
|
struct AC_StartupReceipt { i32 _; };
|
||||||
|
AC_StartupReceipt asset_cache_startup(void);
|
||||||
|
|
||||||
struct asset *asset_cache_touch(struct string key, u64 hash, b32 *is_first_touch);
|
AC_Asset *asset_cache_touch(String key, u64 hash, b32 *is_first_touch);
|
||||||
|
|
||||||
void asset_cache_mark_loading(struct asset *asset);
|
void asset_cache_mark_loading(AC_Asset *asset);
|
||||||
void asset_cache_mark_ready(struct asset *asset, void *store_data);
|
void asset_cache_mark_ready(AC_Asset *asset, void *store_data);
|
||||||
|
|
||||||
void asset_cache_wait(struct asset *asset);
|
void asset_cache_wait(AC_Asset *asset);
|
||||||
|
|
||||||
void *asset_cache_get_store_data(struct asset *asset);
|
void *asset_cache_get_store_data(AC_Asset *asset);
|
||||||
struct asset_cache_store asset_cache_store_open(void);
|
AC_Store asset_cache_store_open(void);
|
||||||
void asset_cache_store_close(struct asset_cache_store *store);
|
void asset_cache_store_close(AC_Store *store);
|
||||||
|
|
||||||
u64 asset_cache_hash(struct string key);
|
u64 asset_cache_hash(String key);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
struct scratch_shared g_scratch_shared = ZI;
|
SharedScratchCtx g_scratch_shared = ZI;
|
||||||
|
|
||||||
/* NOTE: Application will exit if arena fails to reserve or commit initial memory. */
|
/* NOTE: Application will exit if arena fails to reserve or commit initial memory. */
|
||||||
struct arena *arena_alloc(u64 reserve)
|
Arena *arena_alloc(u64 reserve)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
reserve += ARENA_HEADER_SIZE;
|
reserve += ARENA_HEADER_SIZE;
|
||||||
@ -33,22 +33,22 @@ struct arena *arena_alloc(u64 reserve)
|
|||||||
|
|
||||||
ASSERT(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */
|
ASSERT(((u64)base & 0xFFF) == 0); /* Base should be 4k aligned */
|
||||||
STATIC_ASSERT(ARENA_HEADER_SIZE <= ARENA_BLOCK_SIZE); /* Header must fit in first block */
|
STATIC_ASSERT(ARENA_HEADER_SIZE <= ARENA_BLOCK_SIZE); /* Header must fit in first block */
|
||||||
STATIC_ASSERT(sizeof(struct arena) <= ARENA_HEADER_SIZE); /* Arena struct must fit in header */
|
STATIC_ASSERT(sizeof(Arena) <= ARENA_HEADER_SIZE); /* Arena struct must fit in header */
|
||||||
|
|
||||||
__profalloc(base, ARENA_BLOCK_SIZE);
|
__profalloc(base, ARENA_BLOCK_SIZE);
|
||||||
ASAN_POISON(base + sizeof(struct arena), ARENA_BLOCK_SIZE - sizeof(struct arena));
|
ASAN_POISON(base + sizeof(Arena), ARENA_BLOCK_SIZE - sizeof(Arena));
|
||||||
gstat_add(GSTAT_MEMORY_COMMITTED, ARENA_BLOCK_SIZE);
|
gstat_add(GSTAT_MEMORY_COMMITTED, ARENA_BLOCK_SIZE);
|
||||||
gstat_add(GSTAT_NUM_ARENAS, 1);
|
gstat_add(GSTAT_NUM_ARENAS, 1);
|
||||||
|
|
||||||
/* Create & return arena header at beginning of block */
|
/* Create & return arena header at beginning of block */
|
||||||
struct arena *arena = (struct arena *)base;
|
Arena *arena = (Arena *)base;
|
||||||
MEMZERO_STRUCT(arena);
|
MEMZERO_STRUCT(arena);
|
||||||
arena->committed = ARENA_BLOCK_SIZE - ARENA_HEADER_SIZE;
|
arena->committed = ARENA_BLOCK_SIZE - ARENA_HEADER_SIZE;
|
||||||
arena->reserved = reserved;
|
arena->reserved = reserved;
|
||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arena_release(struct arena *arena)
|
void arena_release(Arena *arena)
|
||||||
{
|
{
|
||||||
ASAN_UNPOISON(arena, arena->committed + ARENA_HEADER_SIZE);
|
ASAN_UNPOISON(arena, arena->committed + ARENA_HEADER_SIZE);
|
||||||
__prof;
|
__prof;
|
||||||
@ -60,7 +60,7 @@ void arena_release(struct arena *arena)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: Application will exit if arena fails to commit memory */
|
/* NOTE: Application will exit if arena fails to commit memory */
|
||||||
void *arena_push_bytes_no_zero(struct arena *arena, u64 size, u64 align)
|
void *arena_push_bytes_no_zero(Arena *arena, u64 size, u64 align)
|
||||||
{
|
{
|
||||||
ASSERT(align > 0);
|
ASSERT(align > 0);
|
||||||
ASSERT(!arena->readonly);
|
ASSERT(!arena->readonly);
|
||||||
@ -112,7 +112,7 @@ void *arena_push_bytes_no_zero(struct arena *arena, u64 size, u64 align)
|
|||||||
|
|
||||||
/* Copies the memory from the source arena into the destination arena,
|
/* Copies the memory from the source arena into the destination arena,
|
||||||
* replacing old contents. Destination arena will be expanded if necessary. */
|
* replacing old contents. Destination arena will be expanded if necessary. */
|
||||||
void arena_copy_replace(struct arena *dst, struct arena *src)
|
void arena_copy_replace(Arena *dst, Arena *src)
|
||||||
{
|
{
|
||||||
arena_reset(dst);
|
arena_reset(dst);
|
||||||
u64 data_size = src->pos;
|
u64 data_size = src->pos;
|
||||||
@ -121,14 +121,14 @@ void arena_copy_replace(struct arena *dst, struct arena *src)
|
|||||||
MEMCPY(data_dst, data_src, data_size);
|
MEMCPY(data_dst, data_src, data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arena_decommit_unused_blocks(struct arena *arena)
|
void arena_decommit_unused_blocks(Arena *arena)
|
||||||
{
|
{
|
||||||
/* Not implemented */
|
/* Not implemented */
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
(UNUSED)arena;
|
(UNUSED)arena;
|
||||||
}
|
}
|
||||||
|
|
||||||
void arena_set_readonly(struct arena *arena)
|
void arena_set_readonly(Arena *arena)
|
||||||
{
|
{
|
||||||
#if RTC
|
#if RTC
|
||||||
arena->readonly = 1;
|
arena->readonly = 1;
|
||||||
@ -136,7 +136,7 @@ void arena_set_readonly(struct arena *arena)
|
|||||||
memory_set_committed_readonly(arena, arena->committed + ARENA_HEADER_SIZE);
|
memory_set_committed_readonly(arena, arena->committed + ARENA_HEADER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void arena_set_readwrite(struct arena *arena)
|
void arena_set_readwrite(Arena *arena)
|
||||||
{
|
{
|
||||||
memory_set_committed_readwrite(arena, arena->committed + ARENA_HEADER_SIZE);
|
memory_set_committed_readwrite(arena, arena->committed + ARENA_HEADER_SIZE);
|
||||||
#if RTC
|
#if RTC
|
||||||
|
|||||||
@ -18,7 +18,8 @@
|
|||||||
* Equivalent to arena_push but without actually allocating anything or modifying the arena. */
|
* Equivalent to arena_push but without actually allocating anything or modifying the arena. */
|
||||||
#define arena_push_dry(a, type) (type *)(_arena_push_dry((a), alignof(type)))
|
#define arena_push_dry(a, type) (type *)(_arena_push_dry((a), alignof(type)))
|
||||||
|
|
||||||
struct arena {
|
typedef struct Arena Arena;
|
||||||
|
struct Arena {
|
||||||
u64 pos;
|
u64 pos;
|
||||||
u64 committed;
|
u64 committed;
|
||||||
u64 reserved;
|
u64 reserved;
|
||||||
@ -27,8 +28,9 @@ struct arena {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arena_temp {
|
typedef struct TempArena TempArena;
|
||||||
struct arena *arena;
|
struct TempArena {
|
||||||
|
Arena *arena;
|
||||||
u64 start_pos;
|
u64 start_pos;
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
@ -36,27 +38,27 @@ struct arena_temp {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arena *arena_alloc(u64 reserve);
|
Arena *arena_alloc(u64 reserve);
|
||||||
void arena_release(struct arena *arena);
|
void arena_release(Arena *arena);
|
||||||
void *arena_push_bytes_no_zero(struct arena *arena, u64 size, u64 align);
|
void *arena_push_bytes_no_zero(Arena *arena, u64 size, u64 align);
|
||||||
void arena_copy_replace(struct arena *dst, struct arena *src);
|
void arena_copy_replace(Arena *dst, Arena *src);
|
||||||
void arena_decommit_unused_blocks(struct arena *arena);
|
void arena_decommit_unused_blocks(Arena *arena);
|
||||||
void arena_set_readonly(struct arena *arena);
|
void arena_set_readonly(Arena *arena);
|
||||||
void arena_set_readwrite(struct arena *arena);
|
void arena_set_readwrite(Arena *arena);
|
||||||
|
|
||||||
INLINE u8 *arena_base(struct arena *arena)
|
INLINE u8 *arena_base(Arena *arena)
|
||||||
{
|
{
|
||||||
return (u8 *)arena + ARENA_HEADER_SIZE;
|
return (u8 *)arena + ARENA_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void *arena_push_bytes(struct arena *arena, u64 size, u64 align)
|
INLINE void *arena_push_bytes(Arena *arena, u64 size, u64 align)
|
||||||
{
|
{
|
||||||
void *p = arena_push_bytes_no_zero(arena, size, align);
|
void *p = arena_push_bytes_no_zero(arena, size, align);
|
||||||
MEMZERO(p, size);
|
MEMZERO(p, size);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void arena_pop_to(struct arena *arena, u64 pos)
|
INLINE void arena_pop_to(Arena *arena, u64 pos)
|
||||||
{
|
{
|
||||||
ASSERT(arena->pos >= pos);
|
ASSERT(arena->pos >= pos);
|
||||||
ASSERT(!arena->readonly);
|
ASSERT(!arena->readonly);
|
||||||
@ -65,7 +67,7 @@ INLINE void arena_pop_to(struct arena *arena, u64 pos)
|
|||||||
arena->pos = pos;
|
arena->pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void arena_pop_struct(struct arena *arena, u64 size, void *copy_dst)
|
INLINE void arena_pop_struct(Arena *arena, u64 size, void *copy_dst)
|
||||||
{
|
{
|
||||||
ASSERT(arena->pos >= size);
|
ASSERT(arena->pos >= size);
|
||||||
ASSERT(!arena->readonly);
|
ASSERT(!arena->readonly);
|
||||||
@ -78,7 +80,7 @@ INLINE void arena_pop_struct(struct arena *arena, u64 size, void *copy_dst)
|
|||||||
arena->pos = new_pos;
|
arena->pos = new_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void *arena_align(struct arena *arena, u64 align)
|
INLINE void *arena_align(Arena *arena, u64 align)
|
||||||
{
|
{
|
||||||
ASSERT(!arena->readonly);
|
ASSERT(!arena->readonly);
|
||||||
if (align > 0) {
|
if (align > 0) {
|
||||||
@ -97,25 +99,25 @@ INLINE void *arena_align(struct arena *arena, u64 align)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct arena_temp arena_temp_begin(struct arena *arena)
|
INLINE TempArena arena_temp_begin(Arena *arena)
|
||||||
{
|
{
|
||||||
struct arena_temp t = ZI;
|
TempArena t = ZI;
|
||||||
t.arena = arena;
|
t.arena = arena;
|
||||||
t.start_pos = arena->pos;
|
t.start_pos = arena->pos;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void arena_temp_end(struct arena_temp temp)
|
INLINE void arena_temp_end(TempArena temp)
|
||||||
{
|
{
|
||||||
arena_pop_to(temp.arena, temp.start_pos);
|
arena_pop_to(temp.arena, temp.start_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void arena_reset(struct arena *arena)
|
INLINE void arena_reset(Arena *arena)
|
||||||
{
|
{
|
||||||
arena_pop_to(arena, 0);
|
arena_pop_to(arena, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void *_arena_push_dry(struct arena *arena, u64 align)
|
INLINE void *_arena_push_dry(Arena *arena, u64 align)
|
||||||
{
|
{
|
||||||
u64 aligned_start_pos = (arena->pos + (align - 1));
|
u64 aligned_start_pos = (arena->pos + (align - 1));
|
||||||
aligned_start_pos -= aligned_start_pos % align;
|
aligned_start_pos -= aligned_start_pos % align;
|
||||||
@ -129,20 +131,22 @@ INLINE void *_arena_push_dry(struct arena *arena, u64 align)
|
|||||||
|
|
||||||
#define SCRATCH_ARENAS_PER_CTX 2
|
#define SCRATCH_ARENAS_PER_CTX 2
|
||||||
|
|
||||||
struct scratch_ctx {
|
typedef struct ScratchCtx ScratchCtx;
|
||||||
struct arena *arenas[SCRATCH_ARENAS_PER_CTX];
|
struct ScratchCtx {
|
||||||
|
Arena *arenas[SCRATCH_ARENAS_PER_CTX];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scratch_shared {
|
typedef struct SharedScratchCtx SharedScratchCtx;
|
||||||
struct scratch_ctx scratch_contexts[MAX_FIBERS];
|
struct SharedScratchCtx {
|
||||||
|
ScratchCtx scratch_contexts[MAX_FIBERS];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct scratch_shared g_scratch_shared;
|
extern SharedScratchCtx g_scratch_shared;
|
||||||
|
|
||||||
INLINE struct scratch_ctx *scratch_ctx_from_fiber_id(i16 fiber_id)
|
INLINE ScratchCtx *scratch_ctx_from_fiber_id(i16 fiber_id)
|
||||||
{
|
{
|
||||||
struct scratch_shared *shared = &g_scratch_shared;
|
SharedScratchCtx *shared = &g_scratch_shared;
|
||||||
struct scratch_ctx *ctx = &shared->scratch_contexts[fiber_id];
|
ScratchCtx *ctx = &shared->scratch_contexts[fiber_id];
|
||||||
if (!ctx->arenas[0]) {
|
if (!ctx->arenas[0]) {
|
||||||
for (i32 i = 0; i < (i32)countof(ctx->arenas); ++i) {
|
for (i32 i = 0; i < (i32)countof(ctx->arenas); ++i) {
|
||||||
ctx->arenas[i] = arena_alloc(GIBI(64));
|
ctx->arenas[i] = arena_alloc(GIBI(64));
|
||||||
@ -161,7 +165,7 @@ INLINE struct scratch_ctx *scratch_ctx_from_fiber_id(i16 fiber_id)
|
|||||||
* scope that could potentially be a scratch arena from another scope. */
|
* scope that could potentially be a scratch arena from another scope. */
|
||||||
#define scratch_begin(potential_conflict) _scratch_begin(potential_conflict)
|
#define scratch_begin(potential_conflict) _scratch_begin(potential_conflict)
|
||||||
|
|
||||||
INLINE struct arena_temp _scratch_begin(struct arena *potential_conflict)
|
INLINE TempArena _scratch_begin(Arena *potential_conflict)
|
||||||
{
|
{
|
||||||
/* This function is currently hard-coded to support 2 scratch arenas */
|
/* This function is currently hard-coded to support 2 scratch arenas */
|
||||||
STATIC_ASSERT(SCRATCH_ARENAS_PER_CTX == 2);
|
STATIC_ASSERT(SCRATCH_ARENAS_PER_CTX == 2);
|
||||||
@ -169,12 +173,12 @@ INLINE struct arena_temp _scratch_begin(struct arena *potential_conflict)
|
|||||||
/* Use `scratch_begin_no_conflict` if no conflicts are present */
|
/* Use `scratch_begin_no_conflict` if no conflicts are present */
|
||||||
ASSERT(potential_conflict != 0);
|
ASSERT(potential_conflict != 0);
|
||||||
|
|
||||||
struct scratch_ctx *ctx = scratch_ctx_from_fiber_id(FiberId());
|
ScratchCtx *ctx = scratch_ctx_from_fiber_id(FiberId());
|
||||||
struct arena *scratch_arena = ctx->arenas[0];
|
Arena *scratch_arena = ctx->arenas[0];
|
||||||
if (potential_conflict && scratch_arena == potential_conflict) {
|
if (potential_conflict && scratch_arena == potential_conflict) {
|
||||||
scratch_arena = ctx->arenas[1];
|
scratch_arena = ctx->arenas[1];
|
||||||
}
|
}
|
||||||
struct arena_temp temp = arena_temp_begin(scratch_arena);
|
TempArena temp = arena_temp_begin(scratch_arena);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,15 +194,15 @@ INLINE struct arena_temp _scratch_begin(struct arena *potential_conflict)
|
|||||||
(UNUSED)arena; \
|
(UNUSED)arena; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
INLINE struct arena_temp _scratch_begin_no_conflict(void)
|
INLINE TempArena _scratch_begin_no_conflict(void)
|
||||||
{
|
{
|
||||||
struct scratch_ctx *ctx = scratch_ctx_from_fiber_id(FiberId());
|
ScratchCtx *ctx = scratch_ctx_from_fiber_id(FiberId());
|
||||||
struct arena *scratch_arena = ctx->arenas[0];
|
Arena *scratch_arena = ctx->arenas[0];
|
||||||
struct arena_temp temp = arena_temp_begin(scratch_arena);
|
TempArena temp = arena_temp_begin(scratch_arena);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void scratch_end(struct arena_temp scratch_temp)
|
INLINE void scratch_end(TempArena scratch_temp)
|
||||||
{
|
{
|
||||||
arena_temp_end(scratch_temp);
|
arena_temp_end(scratch_temp);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,20 +3,24 @@
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* NOTE: Must be aligned to 32 bit boundary by user */
|
/* NOTE: Must be aligned to 32 bit boundary by user */
|
||||||
struct atomic8 {
|
typedef struct Atomic8 Atomic8;
|
||||||
|
struct Atomic8 {
|
||||||
volatile i8 _v;
|
volatile i8 _v;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* NOTE: Must be aligned to 32 bit boundary by user */
|
/* NOTE: Must be aligned to 32 bit boundary by user */
|
||||||
struct atomic16 {
|
typedef struct Atomic16 Atomic16;
|
||||||
|
struct Atomic16 {
|
||||||
volatile i16 _v;
|
volatile i16 _v;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct atomic32 {
|
typedef struct Atomic32 Atomic32;
|
||||||
|
struct Atomic32 {
|
||||||
volatile i32 _v;
|
volatile i32 _v;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct atomic64 {
|
typedef struct Atomic64 Atomic64;
|
||||||
|
struct Atomic64 {
|
||||||
volatile i64 _v;
|
volatile i64 _v;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,29 +28,33 @@ struct atomic64 {
|
|||||||
* Cache-line isolated atomic types
|
* Cache-line isolated atomic types
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct alignas(64) atomic8_padded {
|
typedef struct Atomic8Padded Atomic8Padded;
|
||||||
struct atomic8 v;
|
struct alignas(64) Atomic8Padded {
|
||||||
|
Atomic8 v;
|
||||||
u8 _pad[60];
|
u8 _pad[60];
|
||||||
};
|
};
|
||||||
STATIC_ASSERT(sizeof(struct atomic8_padded) == 64 && alignof(struct atomic8_padded) == 64);
|
STATIC_ASSERT(sizeof(Atomic8Padded) == 64 && alignof(Atomic8Padded) == 64);
|
||||||
|
|
||||||
struct alignas(64) atomic16_padded {
|
typedef struct Atomic16Padded Atomic16Padded;
|
||||||
struct atomic16 v;
|
struct alignas(64) Atomic16Padded {
|
||||||
|
Atomic16 v;
|
||||||
u8 _pad[60];
|
u8 _pad[60];
|
||||||
};
|
};
|
||||||
STATIC_ASSERT(sizeof(struct atomic16_padded) == 64 && alignof(struct atomic16_padded) == 64);
|
STATIC_ASSERT(sizeof(Atomic16Padded) == 64 && alignof(Atomic16Padded) == 64);
|
||||||
|
|
||||||
struct alignas(64) atomic32_padded {
|
typedef struct Atomic32Padded Atomic32Padded;
|
||||||
struct atomic32 v;
|
struct alignas(64) Atomic32Padded {
|
||||||
|
Atomic32 v;
|
||||||
u8 _pad[60];
|
u8 _pad[60];
|
||||||
};
|
};
|
||||||
STATIC_ASSERT(sizeof(struct atomic32_padded) == 64 && alignof(struct atomic32_padded) == 64);
|
STATIC_ASSERT(sizeof(Atomic32Padded) == 64 && alignof(Atomic32Padded) == 64);
|
||||||
|
|
||||||
struct alignas(64) atomic64_padded {
|
typedef struct Atomic64Padded Atomic64Padded;
|
||||||
struct atomic64 v;
|
struct alignas(64) Atomic64Padded {
|
||||||
|
Atomic64 v;
|
||||||
u8 _pad[56];
|
u8 _pad[56];
|
||||||
};
|
};
|
||||||
STATIC_ASSERT(sizeof(struct atomic64_padded) == 64 && alignof(struct atomic64_padded) == 64);
|
STATIC_ASSERT(sizeof(Atomic64Padded) == 64 && alignof(Atomic64Padded) == 64);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Atomics impl
|
* Atomics impl
|
||||||
@ -54,29 +62,29 @@ STATIC_ASSERT(sizeof(struct atomic64_padded) == 64 && alignof(struct atomic64_pa
|
|||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
|
|
||||||
FORCE_INLINE i8 atomic8_fetch(struct atomic8 *x) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, 0, 0); }
|
FORCE_INLINE i8 atomic8_fetch(Atomic8 *x) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, 0, 0); }
|
||||||
FORCE_INLINE i8 atomic8_fetch_set(struct atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((char *)&x->_v, e); }
|
FORCE_INLINE i8 atomic8_fetch_set(Atomic8 *x, i8 e) { return (i8)_InterlockedExchange8((char *)&x->_v, e); }
|
||||||
FORCE_INLINE i8 atomic8_fetch_test_set(struct atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, e, c); }
|
FORCE_INLINE i8 atomic8_fetch_test_set(Atomic8 *x, i8 c, i8 e) { return (i8)_InterlockedCompareExchange8((char *)&x->_v, e, c); }
|
||||||
FORCE_INLINE i8 atomic8_fetch_xor(struct atomic8 *x, i8 c) { return (i8)_InterlockedXor8((char *)&x->_v, c); }
|
FORCE_INLINE i8 atomic8_fetch_xor(Atomic8 *x, i8 c) { return (i8)_InterlockedXor8((char *)&x->_v, c); }
|
||||||
FORCE_INLINE i8 atomic8_fetch_add(struct atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((char *)&x->_v, a); }
|
FORCE_INLINE i8 atomic8_fetch_add(Atomic8 *x, i8 a) { return (i8)_InterlockedExchangeAdd8((char *)&x->_v, a); }
|
||||||
|
|
||||||
FORCE_INLINE i16 atomic16_fetch(struct atomic16 *x) { return (i16)_InterlockedCompareExchange16(&x->_v, 0, 0); }
|
FORCE_INLINE i16 atomic16_fetch(Atomic16 *x) { return (i16)_InterlockedCompareExchange16(&x->_v, 0, 0); }
|
||||||
FORCE_INLINE i16 atomic16_fetch_set(struct atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&x->_v, e); }
|
FORCE_INLINE i16 atomic16_fetch_set(Atomic16 *x, i16 e) { return (i16)_InterlockedExchange16(&x->_v, e); }
|
||||||
FORCE_INLINE i16 atomic16_fetch_test_set(struct atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&x->_v, e, c); }
|
FORCE_INLINE i16 atomic16_fetch_test_set(Atomic16 *x, i16 c, i16 e) { return (i16)_InterlockedCompareExchange16(&x->_v, e, c); }
|
||||||
FORCE_INLINE i16 atomic16_fetch_xor(struct atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&x->_v, c); }
|
FORCE_INLINE i16 atomic16_fetch_xor(Atomic16 *x, i16 c) { return (i16)_InterlockedXor16(&x->_v, c); }
|
||||||
FORCE_INLINE i16 atomic16_fetch_add(struct atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&x->_v, a); }
|
FORCE_INLINE i16 atomic16_fetch_add(Atomic16 *x, i16 a) { return (i16)_InterlockedExchangeAdd16(&x->_v, a); }
|
||||||
|
|
||||||
FORCE_INLINE i32 atomic32_fetch(struct atomic32 *x) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, 0, 0); }
|
FORCE_INLINE i32 atomic32_fetch(Atomic32 *x) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, 0, 0); }
|
||||||
FORCE_INLINE i32 atomic32_fetch_set(struct atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&x->_v, e); }
|
FORCE_INLINE i32 atomic32_fetch_set(Atomic32 *x, i32 e) { return (i32)_InterlockedExchange((volatile long *)&x->_v, e); }
|
||||||
FORCE_INLINE i32 atomic32_fetch_test_set(struct atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, e, c); }
|
FORCE_INLINE i32 atomic32_fetch_test_set(Atomic32 *x, i32 c, i32 e) { return (i32)_InterlockedCompareExchange((volatile long *)&x->_v, e, c); }
|
||||||
FORCE_INLINE i32 atomic32_fetch_xor(struct atomic32 *x, i32 c) { return (i32)_InterlockedXor((volatile long *)&x->_v,c); }
|
FORCE_INLINE i32 atomic32_fetch_xor(Atomic32 *x, i32 c) { return (i32)_InterlockedXor((volatile long *)&x->_v,c); }
|
||||||
FORCE_INLINE i32 atomic32_fetch_add(struct atomic32 *x, i32 a) { return (i32)_InterlockedExchangeAdd((volatile long *)&x->_v, a); }
|
FORCE_INLINE i32 atomic32_fetch_add(Atomic32 *x, i32 a) { return (i32)_InterlockedExchangeAdd((volatile long *)&x->_v, a); }
|
||||||
|
|
||||||
FORCE_INLINE i64 atomic64_fetch(struct atomic64 *x) { return (i64)_InterlockedCompareExchange64(&x->_v, 0, 0); }
|
FORCE_INLINE i64 atomic64_fetch(Atomic64 *x) { return (i64)_InterlockedCompareExchange64(&x->_v, 0, 0); }
|
||||||
FORCE_INLINE i64 atomic64_fetch_set(struct atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&x->_v, e); }
|
FORCE_INLINE i64 atomic64_fetch_set(Atomic64 *x, i64 e) { return (i64)_InterlockedExchange64(&x->_v, e); }
|
||||||
FORCE_INLINE i64 atomic64_fetch_test_set(struct atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&x->_v, e, c); }
|
FORCE_INLINE i64 atomic64_fetch_test_set(Atomic64 *x, i64 c, i64 e) { return (i64)_InterlockedCompareExchange64(&x->_v, e, c); }
|
||||||
FORCE_INLINE i64 atomic64_fetch_xor(struct atomic64 *x, i64 c) { return (i64)_InterlockedXor64(&x->_v, c); }
|
FORCE_INLINE i64 atomic64_fetch_xor(Atomic64 *x, i64 c) { return (i64)_InterlockedXor64(&x->_v, c); }
|
||||||
FORCE_INLINE i64 atomic64_fetch_add(struct atomic64 *x, i64 a) { return (i64)_InterlockedExchangeAdd64(&x->_v, a); }
|
FORCE_INLINE i64 atomic64_fetch_add(Atomic64 *x, i64 a) { return (i64)_InterlockedExchangeAdd64(&x->_v, a); }
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# error Atomics not implemented
|
# error Atomics not implemented
|
||||||
|
|||||||
@ -20,8 +20,8 @@ enum dbg_magic {
|
|||||||
DBG_MAGIC_STRING = 0x7866,
|
DBG_MAGIC_STRING = 0x7866,
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL void bw_write_ubits_nomagic(struct bitbuff_writer *bw, u64 value, u8 num_bits);
|
INTERNAL void bw_write_ubits_nomagic(BitbuffWriter *bw, u64 value, u8 num_bits);
|
||||||
INTERNAL void _dbg_write_magic(struct bitbuff_writer *bw, enum dbg_magic magic, u8 num_bits)
|
INTERNAL void _dbg_write_magic(BitbuffWriter *bw, enum dbg_magic magic, u8 num_bits)
|
||||||
{
|
{
|
||||||
if (bw->debug_enabled) {
|
if (bw->debug_enabled) {
|
||||||
if (bw_check_overflow_bits(bw, 24)) {
|
if (bw_check_overflow_bits(bw, 24)) {
|
||||||
@ -32,8 +32,8 @@ INTERNAL void _dbg_write_magic(struct bitbuff_writer *bw, enum dbg_magic magic,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL u64 br_read_ubits_nomagic(struct bitbuff_reader *br, u8 num_bits);
|
INTERNAL u64 br_read_ubits_nomagic(BitbuffReader *br, u8 num_bits);
|
||||||
INTERNAL void _dbg_read_magic(struct bitbuff_reader *br, enum dbg_magic expected_magic, u8 expected_num_bits)
|
INTERNAL void _dbg_read_magic(BitbuffReader *br, enum dbg_magic expected_magic, u8 expected_num_bits)
|
||||||
{
|
{
|
||||||
if (br->debug_enabled) {
|
if (br->debug_enabled) {
|
||||||
if (br_check_overflow_bits(br, 24)) {
|
if (br_check_overflow_bits(br, 24)) {
|
||||||
@ -83,15 +83,15 @@ INTERNAL i64 sint_from_twos_compliment(u64 tc, u8 num_bits)
|
|||||||
* Bitbuff
|
* Bitbuff
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct bitbuff bitbuff_alloc(u64 arena_reserve)
|
Bitbuff bitbuff_alloc(u64 arena_reserve)
|
||||||
{
|
{
|
||||||
struct bitbuff res = ZI;
|
Bitbuff res = ZI;
|
||||||
res.arena = arena_alloc(arena_reserve);
|
res.arena = arena_alloc(arena_reserve);
|
||||||
res.is_backed_by_arena = 1;
|
res.is_backed_by_arena = 1;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bitbuff_release(struct bitbuff *bb)
|
void bitbuff_release(Bitbuff *bb)
|
||||||
{
|
{
|
||||||
/* Only arena bitbuffs need to be released */
|
/* Only arena bitbuffs need to be released */
|
||||||
if (bb->is_backed_by_arena) {
|
if (bb->is_backed_by_arena) {
|
||||||
@ -99,9 +99,9 @@ void bitbuff_release(struct bitbuff *bb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bitbuff bitbuff_from_string(struct string s)
|
Bitbuff bitbuff_from_string(String s)
|
||||||
{
|
{
|
||||||
struct bitbuff res = ZI;
|
Bitbuff res = ZI;
|
||||||
res.fixed_buffer = s;
|
res.fixed_buffer = s;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -110,9 +110,9 @@ struct bitbuff bitbuff_from_string(struct string s)
|
|||||||
* Writer
|
* Writer
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct bitbuff_writer bw_from_bitbuff(struct bitbuff *bb)
|
BitbuffWriter bw_from_bitbuff(Bitbuff *bb)
|
||||||
{
|
{
|
||||||
struct bitbuff_writer res = ZI;
|
BitbuffWriter res = ZI;
|
||||||
res.bb = bb;
|
res.bb = bb;
|
||||||
if (bb->is_backed_by_arena) {
|
if (bb->is_backed_by_arena) {
|
||||||
res.base = arena_base(bb->arena);
|
res.base = arena_base(bb->arena);
|
||||||
@ -127,9 +127,9 @@ struct bitbuff_writer bw_from_bitbuff(struct bitbuff *bb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Use this when writing external formats that will not verify bitbuff debug symbols / magic numbers */
|
/* Use this when writing external formats that will not verify bitbuff debug symbols / magic numbers */
|
||||||
struct bitbuff_writer bw_from_bitbuff_no_debug(struct bitbuff *bb)
|
BitbuffWriter bw_from_bitbuff_no_debug(Bitbuff *bb)
|
||||||
{
|
{
|
||||||
struct bitbuff_writer res = bw_from_bitbuff(bb);
|
BitbuffWriter res = bw_from_bitbuff(bb);
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
res.debug_enabled = 0;
|
res.debug_enabled = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -137,21 +137,21 @@ struct bitbuff_writer bw_from_bitbuff_no_debug(struct bitbuff *bb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Handle overflowed bw */
|
/* FIXME: Handle overflowed bw */
|
||||||
u64 bw_num_bits_written(struct bitbuff_writer *bw)
|
u64 bw_num_bits_written(BitbuffWriter *bw)
|
||||||
{
|
{
|
||||||
return bw->cur_bit;
|
return bw->cur_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Handle overflowed bw */
|
/* FIXME: Handle overflowed bw */
|
||||||
u64 bw_num_bytes_written(struct bitbuff_writer *bw)
|
u64 bw_num_bytes_written(BitbuffWriter *bw)
|
||||||
{
|
{
|
||||||
return (bw->cur_bit + 7) >> 3;
|
return (bw->cur_bit + 7) >> 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Handle overflowed bw */
|
/* FIXME: Handle overflowed bw */
|
||||||
struct string bw_get_written(struct arena *arena, struct bitbuff_writer *bw)
|
String bw_get_written(Arena *arena, BitbuffWriter *bw)
|
||||||
{
|
{
|
||||||
struct string res = ZI;
|
String res = ZI;
|
||||||
res.len = (bw->cur_bit + 7) >> 3;
|
res.len = (bw->cur_bit + 7) >> 3;
|
||||||
res.text = arena_push_array_no_zero(arena, u8, res.len);
|
res.text = arena_push_array_no_zero(arena, u8, res.len);
|
||||||
MEMCPY(res.text, bw->base, res.len);
|
MEMCPY(res.text, bw->base, res.len);
|
||||||
@ -159,22 +159,22 @@ struct string bw_get_written(struct arena *arena, struct bitbuff_writer *bw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Handle overflowed bw */
|
/* FIXME: Handle overflowed bw */
|
||||||
u8 *bw_get_written_raw(struct bitbuff_writer *bw)
|
u8 *bw_get_written_raw(BitbuffWriter *bw)
|
||||||
{
|
{
|
||||||
return bw->base;
|
return bw->base;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 if num_bits would cause the writer to overflow its fixed buffer size (if writer is not backed by a dynamic arena bitbuff) */
|
/* Returns 1 if num_bits would cause the writer to overflow its fixed buffer size (if writer is not backed by a dynamic arena bitbuff) */
|
||||||
b32 bw_check_overflow_bits(struct bitbuff_writer *bw, u64 num_bits)
|
b32 bw_check_overflow_bits(BitbuffWriter *bw, u64 num_bits)
|
||||||
{
|
{
|
||||||
b32 res = 0;
|
b32 res = 0;
|
||||||
struct bitbuff *bb = bw->bb;
|
Bitbuff *bb = bw->bb;
|
||||||
if (bw->overflowed) {
|
if (bw->overflowed) {
|
||||||
res = 1;
|
res = 1;
|
||||||
} else {
|
} else {
|
||||||
u64 bytes_needed = (bw->cur_bit + num_bits + 7) >> 3;
|
u64 bytes_needed = (bw->cur_bit + num_bits + 7) >> 3;
|
||||||
if (bb->is_backed_by_arena) {
|
if (bb->is_backed_by_arena) {
|
||||||
struct arena *arena = bb->arena;
|
Arena *arena = bb->arena;
|
||||||
if (bytes_needed >= arena->pos) {
|
if (bytes_needed >= arena->pos) {
|
||||||
/* Grow arena */
|
/* Grow arena */
|
||||||
u64 push_size = (((bytes_needed - arena->pos) / WRITE_OVERFLOW_ARENA_PUSH_SIZE) + 1) * WRITE_OVERFLOW_ARENA_PUSH_SIZE;
|
u64 push_size = (((bytes_needed - arena->pos) / WRITE_OVERFLOW_ARENA_PUSH_SIZE) + 1) * WRITE_OVERFLOW_ARENA_PUSH_SIZE;
|
||||||
@ -195,7 +195,7 @@ b32 bw_check_overflow_bits(struct bitbuff_writer *bw, u64 num_bits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Align the pos to the next byte */
|
/* Align the pos to the next byte */
|
||||||
void bw_align(struct bitbuff_writer *bw)
|
void bw_align(BitbuffWriter *bw)
|
||||||
{
|
{
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
if ((bw->cur_bit & 7) != 0) {
|
if ((bw->cur_bit & 7) != 0) {
|
||||||
@ -206,9 +206,9 @@ void bw_align(struct bitbuff_writer *bw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
INTERNAL void bw_write_ubits_nomagic(struct bitbuff_writer *bw, u64 value, u8 num_bits)
|
INTERNAL void bw_write_ubits_nomagic(BitbuffWriter *bw, u64 value, u8 num_bits)
|
||||||
#else
|
#else
|
||||||
void bw_write_ubits(struct bitbuff_writer *bw, u64 value, u8 num_bits)
|
void bw_write_ubits(BitbuffWriter *bw, u64 value, u8 num_bits)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
ASSERT(num_bits > 0 && (num_bits == 64 || value <= ~(U64_MAX << num_bits))); /* Bit count must be able to hold value */
|
ASSERT(num_bits > 0 && (num_bits == 64 || value <= ~(U64_MAX << num_bits))); /* Bit count must be able to hold value */
|
||||||
@ -236,14 +236,14 @@ void bw_write_ubits(struct bitbuff_writer *bw, u64 value, u8 num_bits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
void bw_write_ubits(struct bitbuff_writer *bw, u64 value, u8 num_bits)
|
void bw_write_ubits(BitbuffWriter *bw, u64 value, u8 num_bits)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_UBITS, num_bits);
|
_dbg_write_magic(bw, DBG_MAGIC_UBITS, num_bits);
|
||||||
bw_write_ubits_nomagic(bw, value, num_bits);
|
bw_write_ubits_nomagic(bw, value, num_bits);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void bw_write_ibits(struct bitbuff_writer *bw, i64 value, u8 num_bits)
|
void bw_write_ibits(BitbuffWriter *bw, i64 value, u8 num_bits)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_IBITS, num_bits);
|
_dbg_write_magic(bw, DBG_MAGIC_IBITS, num_bits);
|
||||||
u64 ubits;
|
u64 ubits;
|
||||||
@ -256,7 +256,7 @@ void bw_write_ibits(struct bitbuff_writer *bw, i64 value, u8 num_bits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns written bit to make writing delta encoding logic cleaner */
|
/* Returns written bit to make writing delta encoding logic cleaner */
|
||||||
b32 bw_write_bit(struct bitbuff_writer *bw, u8 value)
|
b32 bw_write_bit(BitbuffWriter *bw, u8 value)
|
||||||
{
|
{
|
||||||
bw_write_ubits(bw, value, 1);
|
bw_write_ubits(bw, value, 1);
|
||||||
return value;
|
return value;
|
||||||
@ -264,7 +264,7 @@ b32 bw_write_bit(struct bitbuff_writer *bw, u8 value)
|
|||||||
|
|
||||||
/* Writes a variable length unsigned integer.
|
/* Writes a variable length unsigned integer.
|
||||||
* Value is written in chunks of 7 bits w/ 8th bit signaling continuation. */
|
* Value is written in chunks of 7 bits w/ 8th bit signaling continuation. */
|
||||||
void bw_write_uv(struct bitbuff_writer *bw, u64 value)
|
void bw_write_uv(BitbuffWriter *bw, u64 value)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_UV, 0);
|
_dbg_write_magic(bw, DBG_MAGIC_UV, 0);
|
||||||
while (value > 0x7F) {
|
while (value > 0x7F) {
|
||||||
@ -278,7 +278,7 @@ void bw_write_uv(struct bitbuff_writer *bw, u64 value)
|
|||||||
/* Writes a variable length signed integer.
|
/* Writes a variable length signed integer.
|
||||||
* Similar to bw_write_uv, except the 7th bit of the first byte is a sign bit
|
* Similar to bw_write_uv, except the 7th bit of the first byte is a sign bit
|
||||||
* indicating that the value is stored in twos compliment. */
|
* indicating that the value is stored in twos compliment. */
|
||||||
void bw_write_iv(struct bitbuff_writer *bw, i64 value)
|
void bw_write_iv(BitbuffWriter *bw, i64 value)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_IV, 0);
|
_dbg_write_magic(bw, DBG_MAGIC_IV, 0);
|
||||||
u8 sign_bit;
|
u8 sign_bit;
|
||||||
@ -316,33 +316,33 @@ void bw_write_iv(struct bitbuff_writer *bw, i64 value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_write_f32(struct bitbuff_writer *bw, f32 value)
|
void bw_write_f32(BitbuffWriter *bw, f32 value)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_F32, 0);
|
_dbg_write_magic(bw, DBG_MAGIC_F32, 0);
|
||||||
bw_write_ubits(bw, *(u32 *)&value, 32);
|
bw_write_ubits(bw, *(u32 *)&value, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_write_f64(struct bitbuff_writer *bw, f64 value)
|
void bw_write_f64(BitbuffWriter *bw, f64 value)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_F64, 0);
|
_dbg_write_magic(bw, DBG_MAGIC_F64, 0);
|
||||||
bw_write_ubits(bw, *(u64 *)&value, 64);
|
bw_write_ubits(bw, *(u64 *)&value, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_write_uid(struct bitbuff_writer *bw, struct uid value)
|
void bw_write_uid(BitbuffWriter *bw, UID value)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_UID, 128);
|
_dbg_write_magic(bw, DBG_MAGIC_UID, 128);
|
||||||
bw_write_ubits(bw, value.hi, 64);
|
bw_write_ubits(bw, value.hi, 64);
|
||||||
bw_write_ubits(bw, value.lo, 64);
|
bw_write_ubits(bw, value.lo, 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_write_string(struct bitbuff_writer *bw, struct string s)
|
void bw_write_string(BitbuffWriter *bw, String s)
|
||||||
{
|
{
|
||||||
_dbg_write_magic(bw, DBG_MAGIC_STRING, 0);
|
_dbg_write_magic(bw, DBG_MAGIC_STRING, 0);
|
||||||
bw_write_uv(bw, s.len);
|
bw_write_uv(bw, s.len);
|
||||||
bw_write_bytes(bw, s);
|
bw_write_bytes(bw, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bw_write_bytes(struct bitbuff_writer *bw, struct string bytes)
|
void bw_write_bytes(BitbuffWriter *bw, String bytes)
|
||||||
{
|
{
|
||||||
/* Align start of bytes */
|
/* Align start of bytes */
|
||||||
bw_align(bw);
|
bw_align(bw);
|
||||||
@ -358,7 +358,7 @@ void bw_write_bytes(struct bitbuff_writer *bw, struct string bytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
void bw_write_dbg_marker(struct bitbuff_writer *bw, struct string name)
|
void bw_write_dbg_marker(BitbuffWriter *bw, String name)
|
||||||
{
|
{
|
||||||
bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7;
|
bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7;
|
||||||
for (u64 i = 0; i < name.len; ++i) {
|
for (u64 i = 0; i < name.len; ++i) {
|
||||||
@ -371,14 +371,14 @@ void bw_write_dbg_marker(struct bitbuff_writer *bw, struct string name)
|
|||||||
* Reader
|
* Reader
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct bitbuff_reader br_from_bitbuff(struct bitbuff *bb)
|
BitbuffReader br_from_bitbuff(Bitbuff *bb)
|
||||||
{
|
{
|
||||||
struct bitbuff_reader res = ZI;
|
BitbuffReader res = ZI;
|
||||||
if (!bb->is_backed_by_arena) {
|
if (!bb->is_backed_by_arena) {
|
||||||
res.base = bb->fixed_buffer.text;
|
res.base = bb->fixed_buffer.text;
|
||||||
res.base_len = bb->fixed_buffer.len;
|
res.base_len = bb->fixed_buffer.len;
|
||||||
} else {
|
} else {
|
||||||
struct arena *arena = bb->arena;
|
Arena *arena = bb->arena;
|
||||||
res.base = arena_base(arena);
|
res.base = arena_base(arena);
|
||||||
res.base_len = arena->pos;
|
res.base_len = arena->pos;
|
||||||
}
|
}
|
||||||
@ -390,9 +390,9 @@ struct bitbuff_reader br_from_bitbuff(struct bitbuff *bb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Use this when reading from external formats that will not contain bitbuff debug symbols / magic numbers */
|
/* Use this when reading from external formats that will not contain bitbuff debug symbols / magic numbers */
|
||||||
struct bitbuff_reader br_from_bitbuff_no_debug(struct bitbuff *bb)
|
BitbuffReader br_from_bitbuff_no_debug(Bitbuff *bb)
|
||||||
{
|
{
|
||||||
struct bitbuff_reader res = br_from_bitbuff(bb);
|
BitbuffReader res = br_from_bitbuff(bb);
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
res.debug_enabled = 0;
|
res.debug_enabled = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -401,33 +401,33 @@ struct bitbuff_reader br_from_bitbuff_no_debug(struct bitbuff *bb)
|
|||||||
|
|
||||||
/* Returns the number of bits read from the bitbuff */
|
/* Returns the number of bits read from the bitbuff */
|
||||||
/* FIXME: Handle overflowed br */
|
/* FIXME: Handle overflowed br */
|
||||||
u64 br_cur_bit(struct bitbuff_reader *br)
|
u64 br_cur_bit(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
return br->cur_bit;
|
return br->cur_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the number of *full* bytes read from the bitbuff */
|
/* Returns the number of *full* bytes read from the bitbuff */
|
||||||
/* FIXME: Handle overflowed br */
|
/* FIXME: Handle overflowed br */
|
||||||
u64 br_cur_byte(struct bitbuff_reader *br)
|
u64 br_cur_byte(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
return br->cur_bit >> 3;
|
return br->cur_bit >> 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the number of bits left until the bitbuff overflows */
|
/* Returns the number of bits left until the bitbuff overflows */
|
||||||
/* FIXME: Handle overflowed br */
|
/* FIXME: Handle overflowed br */
|
||||||
u64 br_num_bits_left(struct bitbuff_reader *br)
|
u64 br_num_bits_left(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
return (br->base_len << 3) - br->cur_bit;
|
return (br->base_len << 3) - br->cur_bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the number of *full* bytes left until the bitbuff overflows */
|
/* Returns the number of *full* bytes left until the bitbuff overflows */
|
||||||
/* FIXME: Handle overflowed br */
|
/* FIXME: Handle overflowed br */
|
||||||
u64 br_num_bytes_left(struct bitbuff_reader *br)
|
u64 br_num_bytes_left(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
return br->base_len - (br->cur_bit >> 3);
|
return br->base_len - (br->cur_bit >> 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 br_check_overflow_bits(struct bitbuff_reader *br, u64 num_bits)
|
b32 br_check_overflow_bits(BitbuffReader *br, u64 num_bits)
|
||||||
{
|
{
|
||||||
b32 res = 0;
|
b32 res = 0;
|
||||||
if (br->overflowed) {
|
if (br->overflowed) {
|
||||||
@ -447,7 +447,7 @@ b32 br_check_overflow_bits(struct bitbuff_reader *br, u64 num_bits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Align the pos to the next byte */
|
/* Align the pos to the next byte */
|
||||||
void br_align(struct bitbuff_reader *br)
|
void br_align(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
if ((br->cur_bit & 7) != 0) {
|
if ((br->cur_bit & 7) != 0) {
|
||||||
@ -458,9 +458,9 @@ void br_align(struct bitbuff_reader *br)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
INTERNAL u64 br_read_ubits_nomagic(struct bitbuff_reader *br, u8 num_bits)
|
INTERNAL u64 br_read_ubits_nomagic(BitbuffReader *br, u8 num_bits)
|
||||||
#else
|
#else
|
||||||
u64 br_read_ubits(struct bitbuff_reader *br, u8 num_bits)
|
u64 br_read_ubits(BitbuffReader *br, u8 num_bits)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (br_check_overflow_bits(br, num_bits)) {
|
if (br_check_overflow_bits(br, num_bits)) {
|
||||||
@ -498,14 +498,14 @@ u64 br_read_ubits(struct bitbuff_reader *br, u8 num_bits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
u64 br_read_ubits(struct bitbuff_reader *br, u8 num_bits)
|
u64 br_read_ubits(BitbuffReader *br, u8 num_bits)
|
||||||
{
|
{
|
||||||
_dbg_read_magic(br, DBG_MAGIC_UBITS, num_bits);
|
_dbg_read_magic(br, DBG_MAGIC_UBITS, num_bits);
|
||||||
return br_read_ubits_nomagic(br, num_bits);
|
return br_read_ubits_nomagic(br, num_bits);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
i64 br_read_ibits(struct bitbuff_reader *br, u8 num_bits)
|
i64 br_read_ibits(BitbuffReader *br, u8 num_bits)
|
||||||
{
|
{
|
||||||
ASSERT(num_bits > 1);
|
ASSERT(num_bits > 1);
|
||||||
_dbg_read_magic(br, DBG_MAGIC_IBITS, num_bits);
|
_dbg_read_magic(br, DBG_MAGIC_IBITS, num_bits);
|
||||||
@ -513,14 +513,14 @@ i64 br_read_ibits(struct bitbuff_reader *br, u8 num_bits)
|
|||||||
return sint_from_twos_compliment(tc, num_bits);
|
return sint_from_twos_compliment(tc, num_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 br_read_bit(struct bitbuff_reader *br)
|
u8 br_read_bit(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
return br_read_ubits(br, 1);
|
return br_read_ubits(br, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read a variable length unsigned integer.
|
/* Read a variable length unsigned integer.
|
||||||
* See bw_write_uv for details. */
|
* See bw_write_uv for details. */
|
||||||
u64 br_read_uv(struct bitbuff_reader *br)
|
u64 br_read_uv(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
_dbg_read_magic(br, DBG_MAGIC_UV, 0);
|
_dbg_read_magic(br, DBG_MAGIC_UV, 0);
|
||||||
|
|
||||||
@ -538,7 +538,7 @@ u64 br_read_uv(struct bitbuff_reader *br)
|
|||||||
|
|
||||||
/* Read a variable length signed integer.
|
/* Read a variable length signed integer.
|
||||||
* See bw_write_iv for details. */
|
* See bw_write_iv for details. */
|
||||||
i64 br_read_iv(struct bitbuff_reader *br)
|
i64 br_read_iv(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
_dbg_read_magic(br, DBG_MAGIC_IV, 0);
|
_dbg_read_magic(br, DBG_MAGIC_IV, 0);
|
||||||
u8 first_byte = br_read_ubits(br, 8);
|
u8 first_byte = br_read_ubits(br, 8);
|
||||||
@ -571,32 +571,32 @@ i64 br_read_iv(struct bitbuff_reader *br)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 br_read_f32(struct bitbuff_reader *br)
|
f32 br_read_f32(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
_dbg_read_magic(br, DBG_MAGIC_F32, 0);
|
_dbg_read_magic(br, DBG_MAGIC_F32, 0);
|
||||||
u32 ubits = br_read_ubits(br, 32);
|
u32 ubits = br_read_ubits(br, 32);
|
||||||
return *(f32 *)&ubits;
|
return *(f32 *)&ubits;
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 br_read_f64(struct bitbuff_reader *br)
|
f64 br_read_f64(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
_dbg_read_magic(br, DBG_MAGIC_F64, 0);
|
_dbg_read_magic(br, DBG_MAGIC_F64, 0);
|
||||||
u64 ubits = br_read_ubits(br, 64);
|
u64 ubits = br_read_ubits(br, 64);
|
||||||
return *(f64 *)&ubits;
|
return *(f64 *)&ubits;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct uid br_read_uid(struct bitbuff_reader *br)
|
UID br_read_uid(BitbuffReader *br)
|
||||||
{
|
{
|
||||||
_dbg_read_magic(br, DBG_MAGIC_UID, 128);
|
_dbg_read_magic(br, DBG_MAGIC_UID, 128);
|
||||||
u64 hi = br_read_ubits(br, 64);
|
u64 hi = br_read_ubits(br, 64);
|
||||||
u64 lo = br_read_ubits(br, 64);
|
u64 lo = br_read_ubits(br, 64);
|
||||||
return UID(hi, lo);
|
return MakeUID(hi, lo);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string br_read_string(struct arena *arena, struct bitbuff_reader *br)
|
String br_read_string(Arena *arena, BitbuffReader *br)
|
||||||
{
|
{
|
||||||
_dbg_read_magic(br, DBG_MAGIC_STRING, 0);
|
_dbg_read_magic(br, DBG_MAGIC_STRING, 0);
|
||||||
struct string res = ZI;
|
String res = ZI;
|
||||||
u64 len = br_read_uv(br);
|
u64 len = br_read_uv(br);
|
||||||
u8 *src = br_read_bytes_raw(br, len);
|
u8 *src = br_read_bytes_raw(br, len);
|
||||||
if (src != 0) {
|
if (src != 0) {
|
||||||
@ -608,7 +608,7 @@ struct string br_read_string(struct arena *arena, struct bitbuff_reader *br)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Will fill dst with zeroes if bitbuff overflows */
|
/* Will fill dst with zeroes if bitbuff overflows */
|
||||||
void br_read_bytes(struct bitbuff_reader *br, struct string out)
|
void br_read_bytes(BitbuffReader *br, String out)
|
||||||
{
|
{
|
||||||
u8 *src = br_read_bytes_raw(br, out.len);
|
u8 *src = br_read_bytes_raw(br, out.len);
|
||||||
if (src) {
|
if (src) {
|
||||||
@ -619,7 +619,7 @@ void br_read_bytes(struct bitbuff_reader *br, struct string out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Will return 0 on bitbuff overflow. Result should be checked. */
|
/* Will return 0 on bitbuff overflow. Result should be checked. */
|
||||||
u8 *br_read_bytes_raw(struct bitbuff_reader *br, u64 num_bytes)
|
u8 *br_read_bytes_raw(BitbuffReader *br, u64 num_bytes)
|
||||||
{
|
{
|
||||||
br_align(br);
|
br_align(br);
|
||||||
|
|
||||||
@ -634,7 +634,7 @@ u8 *br_read_bytes_raw(struct bitbuff_reader *br, u64 num_bytes)
|
|||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void br_seek_bytes(struct bitbuff_reader *br, u64 num_bytes)
|
void br_seek_bytes(BitbuffReader *br, u64 num_bytes)
|
||||||
{
|
{
|
||||||
br_align(br);
|
br_align(br);
|
||||||
|
|
||||||
@ -646,7 +646,7 @@ void br_seek_bytes(struct bitbuff_reader *br, u64 num_bytes)
|
|||||||
br->cur_bit += num_bits;
|
br->cur_bit += num_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
void br_seek_to_byte(struct bitbuff_reader *br, u64 pos)
|
void br_seek_to_byte(BitbuffReader *br, u64 pos)
|
||||||
{
|
{
|
||||||
u64 cur_byte_pos = br->cur_bit >> 3;
|
u64 cur_byte_pos = br->cur_bit >> 3;
|
||||||
if (pos >= cur_byte_pos) {
|
if (pos >= cur_byte_pos) {
|
||||||
@ -661,7 +661,7 @@ void br_seek_to_byte(struct bitbuff_reader *br, u64 pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
void br_read_dbg_marker(struct bitbuff_reader *br, struct string name)
|
void br_read_dbg_marker(BitbuffReader *br, String name)
|
||||||
{
|
{
|
||||||
br->cur_bit += (8 - (br->cur_bit & 7)) & 7;
|
br->cur_bit += (8 - (br->cur_bit & 7)) & 7;
|
||||||
for (u64 i = 0; i < name.len; ++i) {
|
for (u64 i = 0; i < name.len; ++i) {
|
||||||
@ -680,7 +680,7 @@ void br_read_dbg_marker(struct bitbuff_reader *br, struct string name)
|
|||||||
|
|
||||||
void bitbuff_test(void)
|
void bitbuff_test(void)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
u8 kind_ubits = 0;
|
u8 kind_ubits = 0;
|
||||||
u8 kind_ibits = 1;
|
u8 kind_ibits = 1;
|
||||||
@ -692,7 +692,7 @@ void bitbuff_test(void)
|
|||||||
struct test_case_ibits { i64 v; u64 num_bits; };
|
struct test_case_ibits { i64 v; u64 num_bits; };
|
||||||
struct test_case_uv { u64 v; };
|
struct test_case_uv { u64 v; };
|
||||||
struct test_case_iv { i64 v; };
|
struct test_case_iv { i64 v; };
|
||||||
struct test_case_string { struct string v; };
|
struct test_case_string { String v; };
|
||||||
struct test_case {
|
struct test_case {
|
||||||
u8 kind;
|
u8 kind;
|
||||||
union {
|
union {
|
||||||
@ -744,10 +744,10 @@ void bitbuff_test(void)
|
|||||||
{ kind_string, .s = { LIT("Alriiiiiiiiiiiiiiiiiiighty then") } },
|
{ kind_string, .s = { LIT("Alriiiiiiiiiiiiiiiiiiighty then") } },
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string encoded = ZI;
|
String encoded = ZI;
|
||||||
{
|
{
|
||||||
struct bitbuff bb = bitbuff_alloc(GIBI(64));
|
Bitbuff bb = bitbuff_alloc(GIBI(64));
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(&bb);
|
BitbuffWriter bw = bw_from_bitbuff(&bb);
|
||||||
for (u64 i = 0; i < countof(cases); ++i) {
|
for (u64 i = 0; i < countof(cases); ++i) {
|
||||||
struct test_case c = cases[i];
|
struct test_case c = cases[i];
|
||||||
if (c.kind == kind_ubits) {
|
if (c.kind == kind_ubits) {
|
||||||
@ -768,8 +768,8 @@ void bitbuff_test(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
struct bitbuff bb = bitbuff_from_string(encoded);
|
Bitbuff bb = bitbuff_from_string(encoded);
|
||||||
struct bitbuff_reader br = br_from_bitbuff(&bb);
|
BitbuffReader br = br_from_bitbuff(&bb);
|
||||||
for (u64 i = 0; i < countof(cases); ++i) {
|
for (u64 i = 0; i < countof(cases); ++i) {
|
||||||
struct test_case c = cases[i];
|
struct test_case c = cases[i];
|
||||||
if (c.kind == kind_ubits) {
|
if (c.kind == kind_ubits) {
|
||||||
@ -789,8 +789,8 @@ void bitbuff_test(void)
|
|||||||
i64 r = br_read_iv(&br);
|
i64 r = br_read_iv(&br);
|
||||||
ASSERT(r == w);
|
ASSERT(r == w);
|
||||||
} else if (c.kind == kind_string) {
|
} else if (c.kind == kind_string) {
|
||||||
struct string w = c.s.v;
|
String w = c.s.v;
|
||||||
struct string r = br_read_string(scratch.arena, &br);
|
String r = br_read_string(scratch.arena, &br);
|
||||||
ASSERT(string_eq(r, w));
|
ASSERT(string_eq(r, w));
|
||||||
} else {
|
} else {
|
||||||
ASSERT(0);
|
ASSERT(0);
|
||||||
|
|||||||
@ -2,29 +2,31 @@
|
|||||||
* Bitbuff
|
* Bitbuff
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct bitbuff {
|
typedef struct Bitbuff Bitbuff;
|
||||||
|
struct Bitbuff {
|
||||||
b32 is_backed_by_arena;
|
b32 is_backed_by_arena;
|
||||||
|
|
||||||
/* If `is_arena_bitbuff` is 1, this dynamically-sized arena will be used for reading & writing (meaning writing cannot overflow) */
|
/* If `is_arena_bitbuff` is 1, this dynamically-sized arena will be used for reading & writing (meaning writing cannot overflow) */
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
/* If `is_arena_bitbuff` is 0, this fixed-sized buffer willl be used for reading & writing */
|
/* If `is_arena_bitbuff` is 0, this fixed-sized buffer willl be used for reading & writing */
|
||||||
struct string fixed_buffer;
|
String fixed_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bitbuff bitbuff_alloc(u64 arena_reserve);
|
Bitbuff bitbuff_alloc(u64 arena_reserve);
|
||||||
void bitbuff_release(struct bitbuff *bitbuff);
|
void bitbuff_release(Bitbuff *bitbuff);
|
||||||
|
|
||||||
struct bitbuff bitbuff_from_string(struct string s);
|
Bitbuff bitbuff_from_string(String s);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Writer
|
* Writer
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* NOTE: base_len is not stored in writer (as it is in the reader) since a dynamic arena-backed bitbuff could grow meaning len needs to be re-checked */
|
/* NOTE: base_len is not stored in writer (as it is in the reader) since a dynamic arena-backed bitbuff could grow meaning len needs to be re-checked */
|
||||||
struct bitbuff_writer {
|
typedef struct BitbuffWriter BitbuffWriter;
|
||||||
|
struct BitbuffWriter {
|
||||||
b32 overflowed;
|
b32 overflowed;
|
||||||
struct bitbuff *bb;
|
Bitbuff *bb;
|
||||||
u8 *base;
|
u8 *base;
|
||||||
u64 cur_bit;
|
u64 cur_bit;
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
@ -32,36 +34,36 @@ struct bitbuff_writer {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bitbuff_writer bw_from_bitbuff(struct bitbuff *bb);
|
BitbuffWriter bw_from_bitbuff(Bitbuff *bb);
|
||||||
struct bitbuff_writer bw_from_bitbuff_no_debug(struct bitbuff *bb);
|
BitbuffWriter bw_from_bitbuff_no_debug(Bitbuff *bb);
|
||||||
|
|
||||||
u64 bw_num_bits_written(struct bitbuff_writer *bw);
|
u64 bw_num_bits_written(BitbuffWriter *bw);
|
||||||
u64 bw_num_bytes_written(struct bitbuff_writer *bw);
|
u64 bw_num_bytes_written(BitbuffWriter *bw);
|
||||||
|
|
||||||
struct string bw_get_written(struct arena *arena, struct bitbuff_writer *bw);
|
String bw_get_written(Arena *arena, BitbuffWriter *bw);
|
||||||
u8 *bw_get_written_raw(struct bitbuff_writer *bw);
|
u8 *bw_get_written_raw(BitbuffWriter *bw);
|
||||||
|
|
||||||
b32 bw_check_overflow_bits(struct bitbuff_writer *bw, u64 num_bits);
|
b32 bw_check_overflow_bits(BitbuffWriter *bw, u64 num_bits);
|
||||||
|
|
||||||
void bw_align(struct bitbuff_writer *bw);
|
void bw_align(BitbuffWriter *bw);
|
||||||
|
|
||||||
void bw_write_ubits(struct bitbuff_writer *bw, u64 value, u8 num_bits);
|
void bw_write_ubits(BitbuffWriter *bw, u64 value, u8 num_bits);
|
||||||
void bw_write_ibits(struct bitbuff_writer *bw, i64 value, u8 num_bits);
|
void bw_write_ibits(BitbuffWriter *bw, i64 value, u8 num_bits);
|
||||||
b32 bw_write_bit(struct bitbuff_writer *bw, u8 value);
|
b32 bw_write_bit(BitbuffWriter *bw, u8 value);
|
||||||
|
|
||||||
void bw_write_uv(struct bitbuff_writer *bw, u64 value);
|
void bw_write_uv(BitbuffWriter *bw, u64 value);
|
||||||
void bw_write_iv(struct bitbuff_writer *bw, i64 value);
|
void bw_write_iv(BitbuffWriter *bw, i64 value);
|
||||||
|
|
||||||
void bw_write_f32(struct bitbuff_writer *bw, f32 value);
|
void bw_write_f32(BitbuffWriter *bw, f32 value);
|
||||||
void bw_write_f64(struct bitbuff_writer *bw, f64 value);
|
void bw_write_f64(BitbuffWriter *bw, f64 value);
|
||||||
void bw_write_uid(struct bitbuff_writer *bw, struct uid value);
|
void bw_write_uid(BitbuffWriter *bw, UID value);
|
||||||
|
|
||||||
void bw_write_string(struct bitbuff_writer *bw, struct string s);
|
void bw_write_string(BitbuffWriter *bw, String s);
|
||||||
|
|
||||||
void bw_write_bytes(struct bitbuff_writer *bw, struct string bytes);
|
void bw_write_bytes(BitbuffWriter *bw, String bytes);
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
void bw_write_dbg_marker(struct bitbuff_writer *bw, struct string name);
|
void bw_write_dbg_marker(BitbuffWriter *bw, String name);
|
||||||
#else
|
#else
|
||||||
#define bw_write_dbg_marker(bw, name)
|
#define bw_write_dbg_marker(bw, name)
|
||||||
#endif
|
#endif
|
||||||
@ -70,7 +72,8 @@ void bw_write_dbg_marker(struct bitbuff_writer *bw, struct string name);
|
|||||||
* Reader
|
* Reader
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct bitbuff_reader {
|
typedef struct BitbuffReader BitbuffReader;
|
||||||
|
struct BitbuffReader {
|
||||||
b32 overflowed;
|
b32 overflowed;
|
||||||
u64 base_len;
|
u64 base_len;
|
||||||
u8 *base;
|
u8 *base;
|
||||||
@ -80,39 +83,39 @@ struct bitbuff_reader {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bitbuff_reader br_from_bitbuff(struct bitbuff *bb);
|
BitbuffReader br_from_bitbuff(Bitbuff *bb);
|
||||||
struct bitbuff_reader br_from_bitbuff_no_debug(struct bitbuff *bb);
|
BitbuffReader br_from_bitbuff_no_debug(Bitbuff *bb);
|
||||||
|
|
||||||
u64 br_cur_bit(struct bitbuff_reader *br);
|
u64 br_cur_bit(BitbuffReader *br);
|
||||||
u64 br_cur_byte(struct bitbuff_reader *br);
|
u64 br_cur_byte(BitbuffReader *br);
|
||||||
|
|
||||||
u64 br_num_bits_left(struct bitbuff_reader *br);
|
u64 br_num_bits_left(BitbuffReader *br);
|
||||||
u64 br_num_bytes_left(struct bitbuff_reader *br);
|
u64 br_num_bytes_left(BitbuffReader *br);
|
||||||
|
|
||||||
b32 br_check_overflow_bits(struct bitbuff_reader *br, u64 num_bits);
|
b32 br_check_overflow_bits(BitbuffReader *br, u64 num_bits);
|
||||||
|
|
||||||
void br_align(struct bitbuff_reader *br);
|
void br_align(BitbuffReader *br);
|
||||||
|
|
||||||
u64 br_read_ubits(struct bitbuff_reader *br, u8 num_bits);
|
u64 br_read_ubits(BitbuffReader *br, u8 num_bits);
|
||||||
i64 br_read_ibits(struct bitbuff_reader *br, u8 num_bits);
|
i64 br_read_ibits(BitbuffReader *br, u8 num_bits);
|
||||||
u8 br_read_bit(struct bitbuff_reader *br);
|
u8 br_read_bit(BitbuffReader *br);
|
||||||
|
|
||||||
u64 br_read_uv(struct bitbuff_reader *br);
|
u64 br_read_uv(BitbuffReader *br);
|
||||||
i64 br_read_iv(struct bitbuff_reader *br);
|
i64 br_read_iv(BitbuffReader *br);
|
||||||
|
|
||||||
f32 br_read_f32(struct bitbuff_reader *br);
|
f32 br_read_f32(BitbuffReader *br);
|
||||||
f64 br_read_f64(struct bitbuff_reader *br);
|
f64 br_read_f64(BitbuffReader *br);
|
||||||
struct uid br_read_uid(struct bitbuff_reader *br);
|
UID br_read_uid(BitbuffReader *br);
|
||||||
|
|
||||||
struct string br_read_string(struct arena *arena, struct bitbuff_reader *br);
|
String br_read_string(Arena *arena, BitbuffReader *br);
|
||||||
|
|
||||||
void br_read_bytes(struct bitbuff_reader *br, struct string dst);
|
void br_read_bytes(BitbuffReader *br, String dst);
|
||||||
u8 *br_read_bytes_raw(struct bitbuff_reader *br, u64 num_bytes);
|
u8 *br_read_bytes_raw(BitbuffReader *br, u64 num_bytes);
|
||||||
void br_seek_bytes(struct bitbuff_reader *br, u64 num_bytes);
|
void br_seek_bytes(BitbuffReader *br, u64 num_bytes);
|
||||||
void br_seek_to_byte(struct bitbuff_reader *br, u64 pos);
|
void br_seek_to_byte(BitbuffReader *br, u64 pos);
|
||||||
|
|
||||||
#if BITBUFF_DEBUG
|
#if BITBUFF_DEBUG
|
||||||
void br_read_dbg_marker(struct bitbuff_reader *br, struct string name);
|
void br_read_dbg_marker(BitbuffReader *br, String name);
|
||||||
#else
|
#else
|
||||||
#define br_read_dbg_marker(br, name)
|
#define br_read_dbg_marker(br, name)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -4,18 +4,18 @@
|
|||||||
* Ctx
|
* Ctx
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct buddy_ctx *buddy_ctx_alloc(u64 reserve)
|
BuddyCtx *buddy_ctx_alloc(u64 reserve)
|
||||||
{
|
{
|
||||||
/* TODO: Determine meta reserve dynamically */
|
/* TODO: Determine meta reserve dynamically */
|
||||||
struct arena *meta_arena = arena_alloc(GIBI(64));
|
Arena *meta_arena = arena_alloc(GIBI(64));
|
||||||
struct buddy_ctx *ctx = arena_push(meta_arena, struct buddy_ctx);
|
BuddyCtx *ctx = arena_push(meta_arena, BuddyCtx);
|
||||||
ctx->meta_arena = meta_arena;
|
ctx->meta_arena = meta_arena;
|
||||||
ctx->data_arena = arena_alloc(reserve);
|
ctx->data_arena = arena_alloc(reserve);
|
||||||
|
|
||||||
/* TODO: Minimum block size */
|
/* TODO: Minimum block size */
|
||||||
ctx->levels = arena_push_array(ctx->meta_arena, struct buddy_level, 64);
|
ctx->levels = arena_push_array(ctx->meta_arena, BuddyLevel, 64);
|
||||||
for (u64 i = 0; i < 64; ++i) {
|
for (u64 i = 0; i < 64; ++i) {
|
||||||
struct buddy_level *level = &ctx->levels[i];
|
BuddyLevel *level = &ctx->levels[i];
|
||||||
level->ctx = ctx;
|
level->ctx = ctx;
|
||||||
level->tier = i;
|
level->tier = i;
|
||||||
level->size = (u64)1 << i;
|
level->size = (u64)1 << i;
|
||||||
@ -24,7 +24,7 @@ struct buddy_ctx *buddy_ctx_alloc(u64 reserve)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buddy_ctx_release(struct buddy_ctx *ctx)
|
void buddy_ctx_release(BuddyCtx *ctx)
|
||||||
{
|
{
|
||||||
arena_release(ctx->data_arena);
|
arena_release(ctx->data_arena);
|
||||||
arena_release(ctx->meta_arena);
|
arena_release(ctx->meta_arena);
|
||||||
@ -34,25 +34,25 @@ void buddy_ctx_release(struct buddy_ctx *ctx)
|
|||||||
* Block
|
* Block
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct buddy_block *buddy_block_alloc_internal(struct buddy_ctx *ctx)
|
INTERNAL BuddyBlock *buddy_block_alloc_internal(BuddyCtx *ctx)
|
||||||
{
|
{
|
||||||
struct buddy_block *block;
|
BuddyBlock *block;
|
||||||
if (ctx->first_free_block) {
|
if (ctx->first_free_block) {
|
||||||
block = ctx->first_free_block;
|
block = ctx->first_free_block;
|
||||||
ctx->first_free_block = block->next;
|
ctx->first_free_block = block->next;
|
||||||
} else {
|
} else {
|
||||||
block = arena_push_no_zero(ctx->meta_arena, struct buddy_block);
|
block = arena_push_no_zero(ctx->meta_arena, BuddyBlock);
|
||||||
}
|
}
|
||||||
MEMZERO_STRUCT(block);
|
MEMZERO_STRUCT(block);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void buddy_block_release_internal(struct buddy_ctx *ctx, struct buddy_level *level, struct buddy_block *block)
|
INTERNAL void buddy_block_release_internal(BuddyCtx *ctx, BuddyLevel *level, BuddyBlock *block)
|
||||||
{
|
{
|
||||||
/* Remove from unused list */
|
/* Remove from unused list */
|
||||||
{
|
{
|
||||||
struct buddy_block *prev = block->prev;
|
BuddyBlock *prev = block->prev;
|
||||||
struct buddy_block *next = block->next;
|
BuddyBlock *next = block->next;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
} else {
|
} else {
|
||||||
@ -67,9 +67,9 @@ INTERNAL void buddy_block_release_internal(struct buddy_ctx *ctx, struct buddy_l
|
|||||||
ctx->first_free_block = block;
|
ctx->first_free_block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct buddy_block *buddy_block_get_unused(struct buddy_ctx *ctx, struct buddy_level *level)
|
INTERNAL BuddyBlock *buddy_block_get_unused(BuddyCtx *ctx, BuddyLevel *level)
|
||||||
{
|
{
|
||||||
struct buddy_block *block = 0;
|
BuddyBlock *block = 0;
|
||||||
|
|
||||||
/* TODO: Tier oob check */
|
/* TODO: Tier oob check */
|
||||||
if (level->first_unused_block) {
|
if (level->first_unused_block) {
|
||||||
@ -82,18 +82,18 @@ INTERNAL struct buddy_block *buddy_block_get_unused(struct buddy_ctx *ctx, struc
|
|||||||
block->next = 0;
|
block->next = 0;
|
||||||
} else {
|
} else {
|
||||||
if (level->backed) {
|
if (level->backed) {
|
||||||
struct buddy_level *parent_level = &ctx->levels[level->tier + 1];
|
BuddyLevel *parent_level = &ctx->levels[level->tier + 1];
|
||||||
struct buddy_block *parent_block = buddy_block_get_unused(ctx, parent_level);
|
BuddyBlock *parent_block = buddy_block_get_unused(ctx, parent_level);
|
||||||
|
|
||||||
/* Create left (used) block from parent block */
|
/* Create left (used) block from parent block */
|
||||||
struct buddy_block *left = buddy_block_alloc_internal(ctx);
|
BuddyBlock *left = buddy_block_alloc_internal(ctx);
|
||||||
left->is_used = 1;
|
left->is_used = 1;
|
||||||
left->level = level;
|
left->level = level;
|
||||||
left->parent = parent_block;
|
left->parent = parent_block;
|
||||||
left->memory = parent_block->memory;
|
left->memory = parent_block->memory;
|
||||||
|
|
||||||
/* Create right (unused) block from parent block */
|
/* Create right (unused) block from parent block */
|
||||||
struct buddy_block *right = buddy_block_alloc_internal(ctx);
|
BuddyBlock *right = buddy_block_alloc_internal(ctx);
|
||||||
right->is_used = 0;
|
right->is_used = 0;
|
||||||
right->level = level;
|
right->level = level;
|
||||||
right->parent = parent_block;
|
right->parent = parent_block;
|
||||||
@ -108,7 +108,7 @@ INTERNAL struct buddy_block *buddy_block_get_unused(struct buddy_ctx *ctx, struc
|
|||||||
right->sibling = left;
|
right->sibling = left;
|
||||||
block = left;
|
block = left;
|
||||||
} else {
|
} else {
|
||||||
struct arena *arena = ctx->data_arena;
|
Arena *arena = ctx->data_arena;
|
||||||
|
|
||||||
/* Grow arena */
|
/* Grow arena */
|
||||||
i64 level_commit_diff = (level->size * 2) - arena->pos;
|
i64 level_commit_diff = (level->size * 2) - arena->pos;
|
||||||
@ -118,13 +118,13 @@ INTERNAL struct buddy_block *buddy_block_get_unused(struct buddy_ctx *ctx, struc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create left (used) block from existing child block memory */
|
/* Create left (used) block from existing child block memory */
|
||||||
struct buddy_block *left = buddy_block_alloc_internal(ctx);
|
BuddyBlock *left = buddy_block_alloc_internal(ctx);
|
||||||
left->is_used = 1;
|
left->is_used = 1;
|
||||||
left->level = level;
|
left->level = level;
|
||||||
left->memory = arena_base(arena);
|
left->memory = arena_base(arena);
|
||||||
|
|
||||||
/* Create right (unused) block from new arena memory */
|
/* Create right (unused) block from new arena memory */
|
||||||
struct buddy_block *right = buddy_block_alloc_internal(ctx);
|
BuddyBlock *right = buddy_block_alloc_internal(ctx);
|
||||||
right->is_used = 0;
|
right->is_used = 0;
|
||||||
right->level = level;
|
right->level = level;
|
||||||
right->memory = left->memory + level->size;
|
right->memory = left->memory + level->size;
|
||||||
@ -140,15 +140,15 @@ INTERNAL struct buddy_block *buddy_block_get_unused(struct buddy_ctx *ctx, struc
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void buddy_block_mark_unused(struct buddy_block *block)
|
INTERNAL void buddy_block_mark_unused(BuddyBlock *block)
|
||||||
{
|
{
|
||||||
block->is_used = 0;
|
block->is_used = 0;
|
||||||
struct buddy_level *level = block->level;
|
BuddyLevel *level = block->level;
|
||||||
struct buddy_block *parent = block->parent;
|
BuddyBlock *parent = block->parent;
|
||||||
struct buddy_block *sibling = block->sibling;
|
BuddyBlock *sibling = block->sibling;
|
||||||
if (!sibling->is_used && parent != 0) {
|
if (!sibling->is_used && parent != 0) {
|
||||||
/* Merge siblings */
|
/* Merge siblings */
|
||||||
struct buddy_ctx *ctx = level->ctx;
|
BuddyCtx *ctx = level->ctx;
|
||||||
buddy_block_release_internal(ctx, level, block);
|
buddy_block_release_internal(ctx, level, block);
|
||||||
buddy_block_release_internal(ctx, level, sibling);
|
buddy_block_release_internal(ctx, level, sibling);
|
||||||
buddy_block_mark_unused(parent);
|
buddy_block_mark_unused(parent);
|
||||||
@ -161,7 +161,7 @@ INTERNAL void buddy_block_mark_unused(struct buddy_block *block)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buddy_block *buddy_alloc(struct buddy_ctx *ctx, u64 size)
|
BuddyBlock *buddy_alloc(BuddyCtx *ctx, u64 size)
|
||||||
{
|
{
|
||||||
if (size > 0x00FFFFFFFFFFFFFFULL) {
|
if (size > 0x00FFFFFFFFFFFFFFULL) {
|
||||||
/* TODO: Error */
|
/* TODO: Error */
|
||||||
@ -179,12 +179,12 @@ struct buddy_block *buddy_alloc(struct buddy_ctx *ctx, u64 size)
|
|||||||
++desired_level_tier;
|
++desired_level_tier;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct buddy_block *block = buddy_block_get_unused(ctx, &ctx->levels[desired_level_tier]);
|
BuddyBlock *block = buddy_block_get_unused(ctx, &ctx->levels[desired_level_tier]);
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void buddy_release(struct buddy_block *block)
|
void buddy_release(BuddyBlock *block)
|
||||||
{
|
{
|
||||||
buddy_block_mark_unused(block);
|
buddy_block_mark_unused(block);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,33 +1,38 @@
|
|||||||
struct buddy_block {
|
typedef struct BuddyLevel BuddyLevel;
|
||||||
|
typedef struct BuddyBlock BuddyBlock;
|
||||||
|
struct BuddyBlock {
|
||||||
b32 is_used;
|
b32 is_used;
|
||||||
struct buddy_level *level;
|
BuddyLevel *level;
|
||||||
struct buddy_block *parent;
|
BuddyBlock *parent;
|
||||||
struct buddy_block *sibling;
|
BuddyBlock *sibling;
|
||||||
|
|
||||||
/* Links to block in level's unused list or in ctx's free list */
|
/* Links to block in level's unused list or in ctx's free list */
|
||||||
struct buddy_block *prev;
|
BuddyBlock *prev;
|
||||||
struct buddy_block *next;
|
BuddyBlock *next;
|
||||||
|
|
||||||
u8 *memory;
|
u8 *memory;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buddy_level {
|
typedef struct BuddyCtx BuddyCtx;
|
||||||
struct buddy_ctx *ctx;
|
typedef struct BuddyLevel BuddyLevel;
|
||||||
|
struct BuddyLevel {
|
||||||
|
BuddyCtx *ctx;
|
||||||
b32 backed; /* Signals whether this level is backed by memory in the ctx arena */
|
b32 backed; /* Signals whether this level is backed by memory in the ctx arena */
|
||||||
u32 tier;
|
u32 tier;
|
||||||
u64 size;
|
u64 size;
|
||||||
struct buddy_block *first_unused_block;
|
BuddyBlock *first_unused_block;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buddy_ctx {
|
typedef struct BuddyCtx BuddyCtx;
|
||||||
struct arena *meta_arena;
|
struct BuddyCtx {
|
||||||
struct arena *data_arena;
|
Arena *meta_arena;
|
||||||
struct buddy_level *levels;
|
Arena *data_arena;
|
||||||
struct buddy_block *first_free_block;
|
BuddyLevel *levels;
|
||||||
|
BuddyBlock *first_free_block;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct buddy_ctx *buddy_ctx_alloc(u64 reserve);
|
BuddyCtx *buddy_ctx_alloc(u64 reserve);
|
||||||
void buddy_ctx_release(struct buddy_ctx *ctx);
|
void buddy_ctx_release(BuddyCtx *ctx);
|
||||||
|
|
||||||
struct buddy_block *buddy_alloc(struct buddy_ctx *ctx, u64 size);
|
BuddyBlock *buddy_alloc(BuddyCtx *ctx, u64 size);
|
||||||
void buddy_release(struct buddy_block *block);
|
void buddy_release(BuddyBlock *block);
|
||||||
|
|||||||
@ -369,13 +369,15 @@ GLOBAL const f64 *_f64_nan = (f64 *)&_f64_nan_u64;
|
|||||||
* Common structs
|
* Common structs
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct image_rgba {
|
typedef struct ImageDataRgba ImageDataRgba;
|
||||||
|
struct ImageDataRgba {
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
u32 *pixels; /* Array of [width * height] pixels */
|
u32 *pixels; /* Array of [width * height] pixels */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pcm {
|
typedef struct PcmData PcmData;
|
||||||
|
struct PcmData {
|
||||||
u64 count;
|
u64 count;
|
||||||
i16 *samples;
|
i16 *samples;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -3,12 +3,12 @@
|
|||||||
#if GSTAT_ENABLED
|
#if GSTAT_ENABLED
|
||||||
|
|
||||||
struct _gstats {
|
struct _gstats {
|
||||||
struct atomic64_padded GSTAT_SOCK_BYTES_SENT;
|
Atomic64Padded GSTAT_SOCK_BYTES_SENT;
|
||||||
struct atomic64_padded GSTAT_SOCK_BYTES_RECEIVED;
|
Atomic64Padded GSTAT_SOCK_BYTES_RECEIVED;
|
||||||
struct atomic64_padded GSTAT_MEMORY_COMMITTED;
|
Atomic64Padded GSTAT_MEMORY_COMMITTED;
|
||||||
struct atomic64_padded GSTAT_MEMORY_RESERVED;
|
Atomic64Padded GSTAT_MEMORY_RESERVED;
|
||||||
struct atomic64_padded GSTAT_NUM_ARENAS;
|
Atomic64Padded GSTAT_NUM_ARENAS;
|
||||||
struct atomic64_padded GSTAT_DEBUG_STEPS;
|
Atomic64Padded GSTAT_DEBUG_STEPS;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct _gstats _g_gstats;
|
extern struct _gstats _g_gstats;
|
||||||
|
|||||||
@ -10,18 +10,18 @@
|
|||||||
|
|
||||||
struct rc_search_params {
|
struct rc_search_params {
|
||||||
/* In */
|
/* In */
|
||||||
struct string name_lower;
|
String name_lower;
|
||||||
/* Out */
|
/* Out */
|
||||||
b32 found;
|
b32 found;
|
||||||
struct string data;
|
String data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Find first resource with `type` and return the data in `udata`. */
|
/* Find first resource with `type` and return the data in `udata`. */
|
||||||
INTERNAL BOOL CALLBACK enum_func(HMODULE module, LPCWSTR type, LPCWSTR wstr_entry_name, LONG_PTR udata)
|
INTERNAL BOOL CALLBACK enum_func(HMODULE module, LPCWSTR type, LPCWSTR wstr_entry_name, LONG_PTR udata)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct rc_search_params *params = (struct rc_search_params *)udata;
|
struct rc_search_params *params = (struct rc_search_params *)udata;
|
||||||
struct string entry_name_lower = string_lower(scratch.arena, string_from_wstr_no_limit(scratch.arena, (LPWSTR)wstr_entry_name));
|
String entry_name_lower = string_lower(scratch.arena, string_from_wstr_no_limit(scratch.arena, (LPWSTR)wstr_entry_name));
|
||||||
params->found = 0;
|
params->found = 0;
|
||||||
params->data = STRING(0, 0);
|
params->data = STRING(0, 0);
|
||||||
if (string_eq(entry_name_lower, params->name_lower)) {
|
if (string_eq(entry_name_lower, params->name_lower)) {
|
||||||
@ -39,17 +39,17 @@ INTERNAL BOOL CALLBACK enum_func(HMODULE module, LPCWSTR type, LPCWSTR wstr_entr
|
|||||||
return !params->found;
|
return !params->found;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string _incbin_get(struct _incbin_rc_resource *inc)
|
String _incbin_get(_IncbinRcResource *inc)
|
||||||
{
|
{
|
||||||
enum _incbin_state state = atomic32_fetch(&inc->state);
|
enum _incbin_state state = atomic32_fetch(&inc->state);
|
||||||
if (state != INCBIN_STATE_SEARCHED) {
|
if (state != INCBIN_STATE_SEARCHED) {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
if (state == INCBIN_STATE_UNSEARCHED) {
|
if (state == INCBIN_STATE_UNSEARCHED) {
|
||||||
enum _incbin_state v = atomic32_fetch_test_set(&inc->state, state, INCBIN_STATE_SEARCHING);
|
enum _incbin_state v = atomic32_fetch_test_set(&inc->state, state, INCBIN_STATE_SEARCHING);
|
||||||
if (v == state) {
|
if (v == state) {
|
||||||
/* Search RC file for the resource name */
|
/* Search RC file for the resource name */
|
||||||
struct string name_lower = string_lower(scratch.arena, inc->rc_name);
|
String name_lower = string_lower(scratch.arena, inc->rc_name);
|
||||||
struct rc_search_params params = { .name_lower = name_lower };
|
struct rc_search_params params = { .name_lower = name_lower };
|
||||||
EnumResourceNamesW(0, RT_RCDATA, &enum_func, (LONG_PTR)¶ms);
|
EnumResourceNamesW(0, RT_RCDATA, &enum_func, (LONG_PTR)¶ms);
|
||||||
if (!params.found) {
|
if (!params.found) {
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
* file).
|
* file).
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#define INCBIN_INCLUDE(var, _rc_name) static struct _incbin_rc_resource _incbin_ ## var = { .rc_name = LIT_NOCAST((_rc_name)) }
|
#define INCBIN_INCLUDE(var, _rc_name) static _IncbinRcResource _incbin_ ## var = { .rc_name = LIT_NOCAST((_rc_name)) }
|
||||||
#define INCBIN_GET(var) _incbin_get(&_incbin_ ## var)
|
#define INCBIN_GET(var) _incbin_get(&_incbin_ ## var)
|
||||||
|
|
||||||
enum _incbin_state {
|
enum _incbin_state {
|
||||||
@ -18,13 +18,14 @@ enum _incbin_state {
|
|||||||
INCBIN_STATE_SEARCHED
|
INCBIN_STATE_SEARCHED
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _incbin_rc_resource {
|
typedef struct _IncbinRcResource _IncbinRcResource;
|
||||||
struct atomic32 state;
|
struct _IncbinRcResource {
|
||||||
struct string rc_name;
|
Atomic32 state;
|
||||||
struct string data;
|
String rc_name;
|
||||||
|
String data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string _incbin_get(struct _incbin_rc_resource *inc);
|
String _incbin_get(struct _IncbinRcResource *inc);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
|||||||
@ -7,95 +7,110 @@
|
|||||||
* Math types
|
* Math types
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#define V2(x, y) CPPCOMPAT_INITLIST_TYPE(struct v2) { (x), (y) }
|
#define V2FromXY(x, y) CPPCOMPAT_INITLIST_TYPE(V2) { (x), (y) }
|
||||||
#define V2_FROM_V2I32(v) V2((v).x, (v).y)
|
#define V2FromV2i32(v) V2FromXY((v).x, (v).y)
|
||||||
struct v2 {
|
typedef struct V2 V2;
|
||||||
|
struct V2 {
|
||||||
f32 x, y;
|
f32 x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct v2_array {
|
typedef struct V2Array V2Array;
|
||||||
struct v2 *points;
|
struct V2Array {
|
||||||
|
V2 *points;
|
||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define V3(x, y, z) ((struct v3) { (x), (y), (z) })
|
#define V3FromXYZ(x, y, z) ((V3) { (x), (y), (z) })
|
||||||
struct v3 {
|
typedef struct V3 V3;
|
||||||
|
struct V3 {
|
||||||
f32 x, y, z;
|
f32 x, y, z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct v3_array {
|
typedef struct V3Array V3Array;
|
||||||
struct v3 *points;
|
struct V3Array {
|
||||||
|
V3 *points;
|
||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define V4(x, y, z, w) ((struct v4) { (x), (y), (z), (w) })
|
#define V4FromXYZW(x, y, z, w) ((V4) { (x), (y), (z), (w) })
|
||||||
struct v4 {
|
typedef struct V4 V4;
|
||||||
|
struct V4 {
|
||||||
f32 x, y, z, w;
|
f32 x, y, z, w;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct v4_array {
|
typedef struct V4Array V4Array;
|
||||||
struct v4 *points;
|
struct V4Array {
|
||||||
|
V4 *points;
|
||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define V2I32(x, y) CPPCOMPAT_INITLIST_TYPE(struct v2i32) { (x), (y) }
|
#define V2i32FromXY(x, y) CPPCOMPAT_INITLIST_TYPE(V2i32) { (x), (y) }
|
||||||
struct v2i32 {
|
typedef struct V2i32 V2i32;
|
||||||
|
struct V2i32 {
|
||||||
i32 x, y;
|
i32 x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define V3I32(x, y, z) CPPCOMPAT_INITLIST_TYPE(struct v3i32) { (x), (y), (z) }
|
#define V3i32FromXYZ(x, y, z) CPPCOMPAT_INITLIST_TYPE(V3i32) { (x), (y), (z) }
|
||||||
struct v3i32 {
|
typedef struct V3i32 V3i32;
|
||||||
|
struct V3i32 {
|
||||||
i32 x, y, z;
|
i32 x, y, z;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xform {
|
typedef struct Xform Xform;
|
||||||
struct v2 bx; /* X basis vector (x axis) */
|
struct Xform {
|
||||||
struct v2 by; /* Y basis vector (y axis)*/
|
V2 bx; /* X basis vector (x axis) */
|
||||||
struct v2 og; /* Translation vector (origin) */
|
V2 by; /* Y basis vector (y axis)*/
|
||||||
|
V2 og; /* Translation vector (origin) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mat4x4 {
|
typedef struct Mat4x4 Mat4x4;
|
||||||
|
struct Mat4x4 {
|
||||||
union {
|
union {
|
||||||
struct { struct v4 bx, by, bz, bw; };
|
struct { V4 bx, by, bz, bw; };
|
||||||
f32 e[4][4];
|
f32 e[4][4];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RECT(_x, _y, _width, _height) (struct rect) { .x = (_x), .y = (_y), .width = (_width), .height = (_height) }
|
#define RECT(_x, _y, _width, _height) (Rect) { .x = (_x), .y = (_y), .width = (_width), .height = (_height) }
|
||||||
#define RECT_FROM_V2(_pos, _size) (struct rect) { .pos = (_pos), .size = (_size) }
|
#define RECT_FROM_V2(_pos, _size) (Rect) { .pos = (_pos), .size = (_size) }
|
||||||
struct rect {
|
typedef struct Rect Rect;
|
||||||
|
struct Rect {
|
||||||
union {
|
union {
|
||||||
struct { f32 x, y, width, height; };
|
struct { f32 x, y, width, height; };
|
||||||
struct { struct v2 pos, size; };
|
struct { V2 pos, size; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE b32 rect_eq(struct rect r1, struct rect r2) { return r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height == r2.height; }
|
INLINE b32 rect_eq(Rect r1, Rect r2) { return r1.x == r2.x && r1.y == r2.y && r1.width == r2.width && r1.height == r2.height; }
|
||||||
|
|
||||||
struct aabb {
|
typedef struct Aabb Aabb;
|
||||||
struct v2 p0, p1;
|
struct Aabb {
|
||||||
|
V2 p0, p1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Values expected to be normalized 0.0 -> 1.0 */
|
/* Values expected to be normalized 0.0 -> 1.0 */
|
||||||
#define CLIP_ALL ((struct clip_rect) { { 0.0f, 0.0f }, { 1.0f, 1.0f } })
|
#define CLIP_ALL ((ClipRect) { { 0.0f, 0.0f }, { 1.0f, 1.0f } })
|
||||||
struct clip_rect {
|
typedef struct ClipRect ClipRect;
|
||||||
struct v2 p0, p1;
|
struct ClipRect {
|
||||||
|
V2 p0, p1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QUAD_UNIT_SQUARE (struct quad) { .p0 = V2(0, 0), .p1 = V2(0, 1), .p2 = V2(1, 1), .p3 = V2(1, 0) }
|
#define QUAD_UNIT_SQUARE (Quad) { .p0 = V2FromXY(0, 0), .p1 = V2FromXY(0, 1), .p2 = V2FromXY(1, 1), .p3 = V2FromXY(1, 0) }
|
||||||
#define QUAD_UNIT_SQUARE_CENTERED (struct quad) { .p0 = V2(-0.5f, -0.5f), .p1 = V2(0.5f, -0.5f), .p2 = V2(0.5f, 0.5f), .p3 = V2(-0.5f, 0.5f) }
|
#define QUAD_UNIT_SQUARE_CENTERED (Quad) { .p0 = V2FromXY(-0.5f, -0.5f), .p1 = V2FromXY(0.5f, -0.5f), .p2 = V2FromXY(0.5f, 0.5f), .p3 = V2FromXY(-0.5f, 0.5f) }
|
||||||
struct quad {
|
typedef struct Quad Quad;
|
||||||
|
struct Quad {
|
||||||
union {
|
union {
|
||||||
struct { struct v2 p0, p1, p2, p3; };
|
struct { V2 p0, p1, p2, p3; };
|
||||||
struct { struct v2 e[4]; };
|
struct { V2 e[4]; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* (T)ranslation, (R)otation, (S)cale */
|
/* (T)ranslation, (R)otation, (S)cale */
|
||||||
#define TRS(...) ((struct trs) { .t = V2(0,0), .s = V2(1, 1), .r = 0, __VA_ARGS__ })
|
#define MakeTrs(...) ((Trs) { .t = V2FromXY(0,0), .s = V2FromXY(1, 1), .r = 0, __VA_ARGS__ })
|
||||||
struct trs {
|
typedef struct Trs Trs;
|
||||||
struct v2 t;
|
struct Trs {
|
||||||
struct v2 s;
|
V2 t;
|
||||||
|
V2 s;
|
||||||
f32 r;
|
f32 r;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -751,53 +766,53 @@ INLINE f32 math_lerp_angle(f32 a, f32 b, f32 t) {
|
|||||||
* V2
|
* V2
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE struct v2 v2_mul(struct v2 a, f32 s)
|
INLINE V2 v2_mul(V2 a, f32 s)
|
||||||
{
|
{
|
||||||
return V2(a.x * s, a.y * s);
|
return V2FromXY(a.x * s, a.y * s);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_mul_v2(struct v2 a, struct v2 b)
|
INLINE V2 v2_mul_v2(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
return V2(a.x * b.x, a.y * b.y);
|
return V2FromXY(a.x * b.x, a.y * b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_div(struct v2 a, f32 s)
|
INLINE V2 v2_div(V2 a, f32 s)
|
||||||
{
|
{
|
||||||
f32 d = 1 / s;
|
f32 d = 1 / s;
|
||||||
return V2(a.x * d, a.y * d);
|
return V2FromXY(a.x * d, a.y * d);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_div_v2(struct v2 a, struct v2 b)
|
INLINE V2 v2_div_v2(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
return V2(a.x * (1 / b.x), a.y * (1 / b.y));
|
return V2FromXY(a.x * (1 / b.x), a.y * (1 / b.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_neg(struct v2 a)
|
INLINE V2 v2_neg(V2 a)
|
||||||
{
|
{
|
||||||
return V2(-a.x, -a.y);
|
return V2FromXY(-a.x, -a.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_add(struct v2 a, struct v2 b)
|
INLINE V2 v2_add(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
return V2(a.x + b.x, a.y + b.y);
|
return V2FromXY(a.x + b.x, a.y + b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_sub(struct v2 a, struct v2 b)
|
INLINE V2 v2_sub(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
return V2(a.x - b.x, a.y - b.y);
|
return V2FromXY(a.x - b.x, a.y - b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 v2_len(struct v2 a)
|
INLINE f32 v2_len(V2 a)
|
||||||
{
|
{
|
||||||
return math_sqrt(a.x * a.x + a.y * a.y);
|
return math_sqrt(a.x * a.x + a.y * a.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 v2_len_sq(struct v2 a)
|
INLINE f32 v2_len_sq(V2 a)
|
||||||
{
|
{
|
||||||
return a.x * a.x + a.y * a.y;
|
return a.x * a.x + a.y * a.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 v2_dot(struct v2 a, struct v2 b)
|
INLINE f32 v2_dot(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
return a.x * b.x + a.y * b.y;
|
return a.x * b.x + a.y * b.y;
|
||||||
}
|
}
|
||||||
@ -805,37 +820,37 @@ INLINE f32 v2_dot(struct v2 a, struct v2 b)
|
|||||||
/* Returns signed area between vectors (positive in clockwise direction)
|
/* Returns signed area between vectors (positive in clockwise direction)
|
||||||
* AKA perpendicular dot product
|
* AKA perpendicular dot product
|
||||||
* AKA 2d cross-product */
|
* AKA 2d cross-product */
|
||||||
INLINE f32 v2_wedge(struct v2 a, struct v2 b)
|
INLINE f32 v2_wedge(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
return a.x * b.y - a.y * b.x;
|
return a.x * b.y - a.y * b.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clockwise (right) perpendicular vector */
|
/* Clockwise (right) perpendicular vector */
|
||||||
INLINE struct v2 v2_perp(struct v2 a)
|
INLINE V2 v2_perp(V2 a)
|
||||||
{
|
{
|
||||||
return V2(-a.y, a.x);
|
return V2FromXY(-a.y, a.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clockwise (right) perpendicular vector scaled by s */
|
/* Clockwise (right) perpendicular vector scaled by s */
|
||||||
INLINE struct v2 v2_perp_mul(struct v2 a, f32 s)
|
INLINE V2 v2_perp_mul(V2 a, f32 s)
|
||||||
{
|
{
|
||||||
return V2(s * -a.y, s * a.x);
|
return V2FromXY(s * -a.y, s * a.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_perp_towards_dir(struct v2 v, struct v2 dir)
|
INLINE V2 v2_perp_towards_dir(V2 v, V2 dir)
|
||||||
{
|
{
|
||||||
f32 wedge = v2_wedge(v, dir);
|
f32 wedge = v2_wedge(v, dir);
|
||||||
return v2_perp_mul(v, (wedge >= 0) - (wedge < 0));
|
return v2_perp_mul(v, (wedge >= 0) - (wedge < 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns 1 if winding between vectors a & b is clockwise or straight, -1 if counter-clockwise */
|
/* Returns 1 if winding between vectors a & b is clockwise or straight, -1 if counter-clockwise */
|
||||||
INLINE i32 v2_winding(struct v2 a, struct v2 b)
|
INLINE i32 v2_winding(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
f32 w = v2_wedge(a, b);
|
f32 w = v2_wedge(a, b);
|
||||||
return (w >= 0) - (w < 0);
|
return (w >= 0) - (w < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_with_len(struct v2 a, f32 len)
|
INLINE V2 v2_with_len(V2 a, f32 len)
|
||||||
{
|
{
|
||||||
f32 l_sq = a.x * a.x + a.y * a.y;
|
f32 l_sq = a.x * a.x + a.y * a.y;
|
||||||
if (l_sq != 0) {
|
if (l_sq != 0) {
|
||||||
@ -846,7 +861,7 @@ INLINE struct v2 v2_with_len(struct v2 a, f32 len)
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_clamp_len(struct v2 a, f32 max)
|
INLINE V2 v2_clamp_len(V2 a, f32 max)
|
||||||
{
|
{
|
||||||
f32 l_sq = a.x * a.x + a.y * a.y;
|
f32 l_sq = a.x * a.x + a.y * a.y;
|
||||||
if (l_sq > max * max) {
|
if (l_sq > max * max) {
|
||||||
@ -857,91 +872,91 @@ INLINE struct v2 v2_clamp_len(struct v2 a, f32 max)
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_norm(struct v2 a)
|
INLINE V2 v2_norm(V2 a)
|
||||||
{
|
{
|
||||||
return v2_with_len(a, 1.f);
|
return v2_with_len(a, 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_round(struct v2 a)
|
INLINE V2 v2_round(V2 a)
|
||||||
{
|
{
|
||||||
return V2(math_round(a.x), math_round(a.y));
|
return V2FromXY(math_round(a.x), math_round(a.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2i32 v2_round_to_int(struct v2 a)
|
INLINE V2i32 v2_round_to_int(V2 a)
|
||||||
{
|
{
|
||||||
return V2I32(math_round_to_int(a.x), math_round_to_int(a.y));
|
return V2i32FromXY(math_round_to_int(a.x), math_round_to_int(a.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_floor(struct v2 a)
|
INLINE V2 v2_floor(V2 a)
|
||||||
{
|
{
|
||||||
return V2(math_floor(a.x), math_floor(a.y));
|
return V2FromXY(math_floor(a.x), math_floor(a.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_ceil(struct v2 a)
|
INLINE V2 v2_ceil(V2 a)
|
||||||
{
|
{
|
||||||
return V2(math_ceil(a.x), math_ceil(a.y));
|
return V2FromXY(math_ceil(a.x), math_ceil(a.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 v2_distance(struct v2 a, struct v2 b)
|
INLINE f32 v2_distance(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
f32 dx = b.x - a.x;
|
f32 dx = b.x - a.x;
|
||||||
f32 dy = b.y - a.y;
|
f32 dy = b.y - a.y;
|
||||||
return math_sqrt(dx * dx + dy * dy);
|
return math_sqrt(dx * dx + dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE b32 v2_eq(struct v2 a, struct v2 b)
|
INLINE b32 v2_eq(V2 a, V2 b)
|
||||||
{
|
{
|
||||||
return a.x == b.x && a.y == b.y;
|
return a.x == b.x && a.y == b.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE b32 v2_is_zero(struct v2 a)
|
INLINE b32 v2_is_zero(V2 a)
|
||||||
{
|
{
|
||||||
return a.x == 0 && a.y == 0;
|
return a.x == 0 && a.y == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_rotated(struct v2 v, f32 a)
|
INLINE V2 v2_rotated(V2 v, f32 a)
|
||||||
{
|
{
|
||||||
f32 c = math_cos(a);
|
f32 c = math_cos(a);
|
||||||
f32 s = math_sin(a);
|
f32 s = math_sin(a);
|
||||||
return V2(v.x * c - v.y * s, v.x * s + v.y * c);
|
return V2FromXY(v.x * c - v.y * s, v.x * s + v.y * c);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_from_angle(f32 a)
|
INLINE V2 v2_from_angle(f32 a)
|
||||||
{
|
{
|
||||||
return V2(math_cos(a), math_sin(a));
|
return V2FromXY(math_cos(a), math_sin(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 v2_angle(struct v2 v)
|
INLINE f32 v2_angle(V2 v)
|
||||||
{
|
{
|
||||||
return math_atan2(v.y, v.x);
|
return math_atan2(v.y, v.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 v2_angle_from_dirs(struct v2 dir1, struct v2 dir2)
|
INLINE f32 v2_angle_from_dirs(V2 dir1, V2 dir2)
|
||||||
{
|
{
|
||||||
return math_atan2(v2_wedge(dir1, dir2), v2_dot(dir1, dir2));
|
return math_atan2(v2_wedge(dir1, dir2), v2_dot(dir1, dir2));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 v2_angle_from_points(struct v2 pt1, struct v2 pt2)
|
INLINE f32 v2_angle_from_points(V2 pt1, V2 pt2)
|
||||||
{
|
{
|
||||||
return v2_angle(v2_sub(pt2, pt1));
|
return v2_angle(v2_sub(pt2, pt1));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 v2_closest_point_ray(struct v2 ray_pos, struct v2 ray_dir_norm, struct v2 p)
|
INLINE V2 v2_closest_point_ray(V2 ray_pos, V2 ray_dir_norm, V2 p)
|
||||||
{
|
{
|
||||||
struct v2 ray_p_dir = v2_sub(p, ray_pos);
|
V2 ray_p_dir = v2_sub(p, ray_pos);
|
||||||
f32 dot = v2_dot(ray_dir_norm, ray_p_dir);
|
f32 dot = v2_dot(ray_dir_norm, ray_p_dir);
|
||||||
struct v2 ray_dir_closest = v2_mul(ray_dir_norm, dot);
|
V2 ray_dir_closest = v2_mul(ray_dir_norm, dot);
|
||||||
return v2_add(ray_pos, ray_dir_closest);
|
return v2_add(ray_pos, ray_dir_closest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interpolate position vectors */
|
/* Interpolate position vectors */
|
||||||
INLINE struct v2 v2_lerp(struct v2 val0, struct v2 val1, f32 t)
|
INLINE V2 v2_lerp(V2 val0, V2 val1, f32 t)
|
||||||
{
|
{
|
||||||
return V2(math_lerp_f32(val0.x, val1.x, t), math_lerp_f32(val0.y, val1.y, t));
|
return V2FromXY(math_lerp_f32(val0.x, val1.x, t), math_lerp_f32(val0.y, val1.y, t));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Interpolate direction vectors (spherical lerp) */
|
/* Interpolate direction vectors (spherical lerp) */
|
||||||
INLINE struct v2 v2_slerp(struct v2 val0, struct v2 val1, f32 t)
|
INLINE V2 v2_slerp(V2 val0, V2 val1, f32 t)
|
||||||
{
|
{
|
||||||
f32 rot = math_lerp_angle(v2_angle(val0), v2_angle(val1), t);
|
f32 rot = math_lerp_angle(v2_angle(val0), v2_angle(val1), t);
|
||||||
f32 len = math_lerp_f32(v2_len(val0), v2_len(val1), t);
|
f32 len = math_lerp_f32(v2_len(val0), v2_len(val1), t);
|
||||||
@ -949,36 +964,36 @@ INLINE struct v2 v2_slerp(struct v2 val0, struct v2 val1, f32 t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* V2I32
|
* V2i32
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE b32 v2i32_eq(struct v2i32 a, struct v2i32 b)
|
INLINE b32 v2i32_eq(V2i32 a, V2i32 b)
|
||||||
{
|
{
|
||||||
return a.x == b.x && a.y == b.y;
|
return a.x == b.x && a.y == b.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2i32 v2i32_neg(struct v2i32 a)
|
INLINE V2i32 v2i32_neg(V2i32 a)
|
||||||
{
|
{
|
||||||
return V2I32(-a.x, -a.y);
|
return V2i32FromXY(-a.x, -a.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2i32 v2i32_add(struct v2i32 a, struct v2i32 b)
|
INLINE V2i32 v2i32_add(V2i32 a, V2i32 b)
|
||||||
{
|
{
|
||||||
return V2I32(a.x + b.x, a.y + b.y);
|
return V2i32FromXY(a.x + b.x, a.y + b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2i32 v2i32_sub(struct v2i32 a, struct v2i32 b)
|
INLINE V2i32 v2i32_sub(V2i32 a, V2i32 b)
|
||||||
{
|
{
|
||||||
return V2I32(a.x - b.x, a.y - b.y);
|
return V2i32FromXY(a.x - b.x, a.y - b.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Mat4x4
|
* Mat4x4
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE struct mat4x4 mat4x4_from_xform(struct xform xf)
|
INLINE Mat4x4 mat4x4_from_xform(Xform xf)
|
||||||
{
|
{
|
||||||
return CPPCOMPAT_INITLIST_TYPE(struct mat4x4) {
|
return CPPCOMPAT_INITLIST_TYPE(Mat4x4) {
|
||||||
.e = {
|
.e = {
|
||||||
{xf.bx.x, xf.bx.y, 0, 0},
|
{xf.bx.x, xf.bx.y, 0, 0},
|
||||||
{xf.by.x, xf.by.y, 0, 0},
|
{xf.by.x, xf.by.y, 0, 0},
|
||||||
@ -988,9 +1003,9 @@ INLINE struct mat4x4 mat4x4_from_xform(struct xform xf)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct mat4x4 mat4x4_from_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near_z, f32 far_z)
|
INLINE Mat4x4 mat4x4_from_ortho(f32 left, f32 right, f32 bottom, f32 top, f32 near_z, f32 far_z)
|
||||||
{
|
{
|
||||||
struct mat4x4 m = ZI;
|
Mat4x4 m = ZI;
|
||||||
|
|
||||||
f32 rl = 1.0f / (right - left);
|
f32 rl = 1.0f / (right - left);
|
||||||
f32 tb = 1.0f / (top - bottom);
|
f32 tb = 1.0f / (top - bottom);
|
||||||
@ -1007,7 +1022,7 @@ INLINE struct mat4x4 mat4x4_from_ortho(f32 left, f32 right, f32 bottom, f32 top,
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct mat4x4 mat4x4_mul(struct mat4x4 m1, struct mat4x4 m2)
|
INLINE Mat4x4 mat4x4_mul(Mat4x4 m1, Mat4x4 m2)
|
||||||
{
|
{
|
||||||
f32 a00 = m1.e[0][0], a01 = m1.e[0][1], a02 = m1.e[0][2], a03 = m1.e[0][3],
|
f32 a00 = m1.e[0][0], a01 = m1.e[0][1], a02 = m1.e[0][2], a03 = m1.e[0][3],
|
||||||
a10 = m1.e[1][0], a11 = m1.e[1][1], a12 = m1.e[1][2], a13 = m1.e[1][3],
|
a10 = m1.e[1][0], a11 = m1.e[1][1], a12 = m1.e[1][2], a13 = m1.e[1][3],
|
||||||
@ -1019,7 +1034,7 @@ INLINE struct mat4x4 mat4x4_mul(struct mat4x4 m1, struct mat4x4 m2)
|
|||||||
b20 = m2.e[2][0], b21 = m2.e[2][1], b22 = m2.e[2][2], b23 = m2.e[2][3],
|
b20 = m2.e[2][0], b21 = m2.e[2][1], b22 = m2.e[2][2], b23 = m2.e[2][3],
|
||||||
b30 = m2.e[3][0], b31 = m2.e[3][1], b32 = m2.e[3][2], b33 = m2.e[3][3];
|
b30 = m2.e[3][0], b31 = m2.e[3][1], b32 = m2.e[3][2], b33 = m2.e[3][3];
|
||||||
|
|
||||||
struct mat4x4 res;
|
Mat4x4 res;
|
||||||
res.e[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03;
|
res.e[0][0] = a00 * b00 + a10 * b01 + a20 * b02 + a30 * b03;
|
||||||
res.e[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03;
|
res.e[0][1] = a01 * b00 + a11 * b01 + a21 * b02 + a31 * b03;
|
||||||
res.e[0][2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03;
|
res.e[0][2] = a02 * b00 + a12 * b01 + a22 * b02 + a32 * b03;
|
||||||
@ -1045,138 +1060,138 @@ INLINE struct mat4x4 mat4x4_mul(struct mat4x4 m1, struct mat4x4 m2)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Construct identity xform */
|
/* Construct identity xform */
|
||||||
#define XFORM_IDENT CPPCOMPAT_INITLIST_TYPE(struct xform) { .bx = V2(1, 0), .by = V2(0, 1) }
|
#define XFORM_IDENT CPPCOMPAT_INITLIST_TYPE(Xform) { .bx = V2FromXY(1, 0), .by = V2FromXY(0, 1) }
|
||||||
#define XFORM_IDENT_NOCAST { .bx = V2(1, 0), .by = V2(0, 1) }
|
#define XFORM_IDENT_NOCAST { .bx = V2FromXY(1, 0), .by = V2FromXY(0, 1) }
|
||||||
|
|
||||||
#define XFORM_POS(p) CPPCOMPAT_INITLIST_TYPE(struct xform) { .bx = V2(1, 0), .by = V2(0, 1), .og = (p) }
|
#define XFORM_POS(p) CPPCOMPAT_INITLIST_TYPE(Xform) { .bx = V2FromXY(1, 0), .by = V2FromXY(0, 1), .og = (p) }
|
||||||
|
|
||||||
/* Takes a translation, rotation, and scale as optional parameters for constructing an xform */
|
/* Takes a translation, rotation, and scale as optional parameters for constructing an xform */
|
||||||
#define XFORM_TRS(...) xform_from_trs((struct trs) { .t = V2(0,0), .s = V2(1, 1), .r = 0, __VA_ARGS__ })
|
#define XFORM_TRS(...) xform_from_trs((Trs) { .t = V2FromXY(0,0), .s = V2FromXY(1, 1), .r = 0, __VA_ARGS__ })
|
||||||
|
|
||||||
INLINE struct xform xform_mul(struct xform a, struct xform b);
|
INLINE Xform xform_mul(Xform a, Xform b);
|
||||||
INLINE struct xform xform_rotated(struct xform xf, f32 angle);
|
INLINE Xform xform_rotated(Xform xf, f32 angle);
|
||||||
INLINE struct xform xform_scaled(struct xform xf, struct v2 v);
|
INLINE Xform xform_scaled(Xform xf, V2 v);
|
||||||
INLINE struct v2 xform_basis_mul_v2(struct xform xf, struct v2 v);
|
INLINE V2 xform_basis_mul_v2(Xform xf, V2 v);
|
||||||
INLINE struct v2 xform_mul_v2(struct xform xf, struct v2 v);
|
INLINE V2 xform_mul_v2(Xform xf, V2 v);
|
||||||
INLINE f32 xform_get_determinant(struct xform xf);
|
INLINE f32 xform_get_determinant(Xform xf);
|
||||||
INLINE struct v2 xform_get_scale(struct xform xf);
|
INLINE V2 xform_get_scale(Xform xf);
|
||||||
INLINE f32 xform_get_rotation(struct xform xf);
|
INLINE f32 xform_get_rotation(Xform xf);
|
||||||
|
|
||||||
INLINE b32 xform_eq(struct xform xf1, struct xform xf2)
|
INLINE b32 xform_eq(Xform xf1, Xform xf2)
|
||||||
{
|
{
|
||||||
return v2_eq(xf1.og, xf2.og) && v2_eq(xf1.bx, xf2.bx) && v2_eq(xf1.by, xf2.by);
|
return v2_eq(xf1.og, xf2.og) && v2_eq(xf1.bx, xf2.bx) && v2_eq(xf1.by, xf2.by);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_from_pos(struct v2 v)
|
INLINE Xform xform_from_pos(V2 v)
|
||||||
{
|
{
|
||||||
struct xform xf;
|
Xform xf;
|
||||||
xf.bx = V2(1, 0);
|
xf.bx = V2FromXY(1, 0);
|
||||||
xf.by = V2(0, 1);
|
xf.by = V2FromXY(0, 1);
|
||||||
xf.og = v;
|
xf.og = v;
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_from_rotation(f32 r)
|
INLINE Xform xform_from_rotation(f32 r)
|
||||||
{
|
{
|
||||||
struct xform res;
|
Xform res;
|
||||||
f32 c = math_cos(r);
|
f32 c = math_cos(r);
|
||||||
f32 s = math_sin(r);
|
f32 s = math_sin(r);
|
||||||
res.bx = V2(c, s);
|
res.bx = V2FromXY(c, s);
|
||||||
res.by = V2(-s, c);
|
res.by = V2FromXY(-s, c);
|
||||||
res.og = V2(0, 0);
|
res.og = V2FromXY(0, 0);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_from_scale(struct v2 scale)
|
INLINE Xform xform_from_scale(V2 scale)
|
||||||
{
|
{
|
||||||
struct xform res;
|
Xform res;
|
||||||
res.bx = V2(scale.x, 0);
|
res.bx = V2FromXY(scale.x, 0);
|
||||||
res.by = V2(0, scale.y);
|
res.by = V2FromXY(0, scale.y);
|
||||||
res.og = V2(0, 0);
|
res.og = V2FromXY(0, 0);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_from_trs(struct trs trs)
|
INLINE Xform xform_from_trs(Trs trs)
|
||||||
{
|
{
|
||||||
struct xform xf = XFORM_POS(trs.t);
|
Xform xf = XFORM_POS(trs.t);
|
||||||
xf = xform_rotated(xf, trs.r);
|
xf = xform_rotated(xf, trs.r);
|
||||||
xf = xform_scaled(xf, trs.s);
|
xf = xform_scaled(xf, trs.s);
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_from_rect(struct rect rect)
|
INLINE Xform xform_from_rect(Rect rect)
|
||||||
{
|
{
|
||||||
struct v2 half_size = v2_mul(rect.size, 0.5);
|
V2 half_size = v2_mul(rect.size, 0.5);
|
||||||
struct xform xf = ZI;
|
Xform xf = ZI;
|
||||||
xf.bx = V2(rect.size.x, 0);
|
xf.bx = V2FromXY(rect.size.x, 0);
|
||||||
xf.by = V2(0, rect.size.y);
|
xf.by = V2FromXY(0, rect.size.y);
|
||||||
xf.og = v2_add(rect.pos, half_size);
|
xf.og = v2_add(rect.pos, half_size);
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_translated(struct xform xf, struct v2 v)
|
INLINE Xform xform_translated(Xform xf, V2 v)
|
||||||
{
|
{
|
||||||
xf.og = V2(xf.bx.x * v.x + xf.by.x * v.y + xf.og.x, xf.bx.y * v.x + xf.by.y * v.y + xf.og.y);
|
xf.og = V2FromXY(xf.bx.x * v.x + xf.by.x * v.y + xf.og.x, xf.bx.y * v.x + xf.by.y * v.y + xf.og.y);
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_translated_world(struct xform xf, struct v2 v)
|
INLINE Xform xform_translated_world(Xform xf, V2 v)
|
||||||
{
|
{
|
||||||
xf.og = v2_add(xf.og, v);
|
xf.og = v2_add(xf.og, v);
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_rotated(struct xform xf, f32 r)
|
INLINE Xform xform_rotated(Xform xf, f32 r)
|
||||||
{
|
{
|
||||||
return xform_mul(xf, xform_from_rotation(r));
|
return xform_mul(xf, xform_from_rotation(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_rotated_world(struct xform xf, f32 r)
|
INLINE Xform xform_rotated_world(Xform xf, f32 r)
|
||||||
{
|
{
|
||||||
return xform_mul(xform_from_rotation(r), xf);
|
return xform_mul(xform_from_rotation(r), xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_basis_rotated_world(struct xform xf, f32 r)
|
INLINE Xform xform_basis_rotated_world(Xform xf, f32 r)
|
||||||
{
|
{
|
||||||
f32 diff = r;
|
f32 diff = r;
|
||||||
f32 c = math_cos(diff);
|
f32 c = math_cos(diff);
|
||||||
f32 s = math_sin(diff);
|
f32 s = math_sin(diff);
|
||||||
xf.bx = V2(xf.bx.x * c - xf.bx.y * s, xf.bx.x * s + xf.bx.y * c);
|
xf.bx = V2FromXY(xf.bx.x * c - xf.bx.y * s, xf.bx.x * s + xf.bx.y * c);
|
||||||
xf.by = V2(xf.by.x * c - xf.by.y * s, xf.by.x * s + xf.by.y * c);
|
xf.by = V2FromXY(xf.by.x * c - xf.by.y * s, xf.by.x * s + xf.by.y * c);
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_basis_with_rotation_world(struct xform xf, f32 r)
|
INLINE Xform xform_basis_with_rotation_world(Xform xf, f32 r)
|
||||||
{
|
{
|
||||||
return xform_basis_rotated_world(xf, r - xform_get_rotation(xf));
|
return xform_basis_rotated_world(xf, r - xform_get_rotation(xf));
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_scaled(struct xform xf, struct v2 scale)
|
INLINE Xform xform_scaled(Xform xf, V2 scale)
|
||||||
{
|
{
|
||||||
xf.bx = v2_mul(xf.bx, scale.x);
|
xf.bx = v2_mul(xf.bx, scale.x);
|
||||||
xf.by = v2_mul(xf.by, scale.y);
|
xf.by = v2_mul(xf.by, scale.y);
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_scaled_world(struct xform xf, struct v2 scale)
|
INLINE Xform xform_scaled_world(Xform xf, V2 scale)
|
||||||
{
|
{
|
||||||
struct xform res;
|
Xform res;
|
||||||
res.bx = v2_mul_v2(xf.bx, scale);
|
res.bx = v2_mul_v2(xf.bx, scale);
|
||||||
res.by = v2_mul_v2(xf.by, scale);
|
res.by = v2_mul_v2(xf.by, scale);
|
||||||
res.og = v2_mul_v2(xf.og, scale);
|
res.og = v2_mul_v2(xf.og, scale);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_lerp(struct xform a, struct xform b, f32 t)
|
INLINE Xform xform_lerp(Xform a, Xform b, f32 t)
|
||||||
{
|
{
|
||||||
struct xform res;
|
Xform res;
|
||||||
res.bx = v2_slerp(a.bx, b.bx, t);
|
res.bx = v2_slerp(a.bx, b.bx, t);
|
||||||
res.by = v2_slerp(a.by, b.by, t);
|
res.by = v2_slerp(a.by, b.by, t);
|
||||||
res.og = v2_lerp(a.og, b.og, t);
|
res.og = v2_lerp(a.og, b.og, t);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_invert(struct xform xf)
|
INLINE Xform xform_invert(Xform xf)
|
||||||
{
|
{
|
||||||
f32 det = xform_get_determinant(xf);
|
f32 det = xform_get_determinant(xf);
|
||||||
f32 inv_det = 1.0f / det;
|
f32 inv_det = 1.0f / det;
|
||||||
@ -1185,17 +1200,17 @@ INLINE struct xform xform_invert(struct xform xf)
|
|||||||
xf.bx.x = xf.by.y;
|
xf.bx.x = xf.by.y;
|
||||||
xf.by.y = old_bx_x;
|
xf.by.y = old_bx_x;
|
||||||
|
|
||||||
xf.bx = v2_mul_v2(xf.bx, V2(inv_det, -inv_det));
|
xf.bx = v2_mul_v2(xf.bx, V2FromXY(inv_det, -inv_det));
|
||||||
xf.by = v2_mul_v2(xf.by, V2(-inv_det, inv_det));
|
xf.by = v2_mul_v2(xf.by, V2FromXY(-inv_det, inv_det));
|
||||||
|
|
||||||
xf.og = xform_basis_mul_v2(xf, v2_neg(xf.og));
|
xf.og = xform_basis_mul_v2(xf, v2_neg(xf.og));
|
||||||
|
|
||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_mul(struct xform a, struct xform b)
|
INLINE Xform xform_mul(Xform a, Xform b)
|
||||||
{
|
{
|
||||||
struct xform res;
|
Xform res;
|
||||||
res.bx.x = a.bx.x * b.bx.x + a.by.x * b.bx.y;
|
res.bx.x = a.bx.x * b.bx.x + a.by.x * b.bx.y;
|
||||||
res.bx.y = a.bx.y * b.bx.x + a.by.y * b.bx.y;
|
res.bx.y = a.bx.y * b.bx.x + a.by.y * b.bx.y;
|
||||||
res.by.x = a.bx.x * b.by.x + a.by.x * b.by.y;
|
res.by.x = a.bx.x * b.by.x + a.by.x * b.by.y;
|
||||||
@ -1204,46 +1219,46 @@ INLINE struct xform xform_mul(struct xform a, struct xform b)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 xform_basis_mul_v2(struct xform xf, struct v2 v)
|
INLINE V2 xform_basis_mul_v2(Xform xf, V2 v)
|
||||||
{
|
{
|
||||||
return V2(
|
return V2FromXY(
|
||||||
xf.bx.x * v.x + xf.by.x * v.y,
|
xf.bx.x * v.x + xf.by.x * v.y,
|
||||||
xf.bx.y * v.x + xf.by.y * v.y
|
xf.bx.y * v.x + xf.by.y * v.y
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 xform_mul_v2(struct xform xf, struct v2 v)
|
INLINE V2 xform_mul_v2(Xform xf, V2 v)
|
||||||
{
|
{
|
||||||
struct v2 res = xform_basis_mul_v2(xf, v);
|
V2 res = xform_basis_mul_v2(xf, v);
|
||||||
res = v2_add(res, xf.og);
|
res = v2_add(res, xf.og);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct xform xform_basis(struct xform xf)
|
INLINE Xform xform_basis(Xform xf)
|
||||||
{
|
{
|
||||||
struct xform res = ZI;
|
Xform res = ZI;
|
||||||
res.bx = xf.bx;
|
res.bx = xf.bx;
|
||||||
res.by = xf.by;
|
res.by = xf.by;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 xform_basis_invert_mul_v2(struct xform xf, struct v2 v)
|
INLINE V2 xform_basis_invert_mul_v2(Xform xf, V2 v)
|
||||||
{
|
{
|
||||||
struct xform inv = xform_invert(xf);
|
Xform inv = xform_invert(xf);
|
||||||
struct v2 res = xform_basis_mul_v2(inv, v);
|
V2 res = xform_basis_mul_v2(inv, v);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Get rid of this? Just force caller to use invert manually since it's expensive. */
|
/* TODO: Get rid of this? Just force caller to use invert manually since it's expensive. */
|
||||||
INLINE struct v2 xform_invert_mul_v2(struct xform xf, struct v2 v)
|
INLINE V2 xform_invert_mul_v2(Xform xf, V2 v)
|
||||||
{
|
{
|
||||||
struct xform inv = xform_invert(xf);
|
Xform inv = xform_invert(xf);
|
||||||
return xform_mul_v2(inv, v);
|
return xform_mul_v2(inv, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct quad xform_mul_quad(struct xform xf, struct quad quad)
|
INLINE Quad xform_mul_quad(Xform xf, Quad quad)
|
||||||
{
|
{
|
||||||
struct quad res;
|
Quad res;
|
||||||
res.p0 = xform_mul_v2(xf, quad.p0);
|
res.p0 = xform_mul_v2(xf, quad.p0);
|
||||||
res.p1 = xform_mul_v2(xf, quad.p1);
|
res.p1 = xform_mul_v2(xf, quad.p1);
|
||||||
res.p2 = xform_mul_v2(xf, quad.p2);
|
res.p2 = xform_mul_v2(xf, quad.p2);
|
||||||
@ -1251,77 +1266,77 @@ INLINE struct quad xform_mul_quad(struct xform xf, struct quad quad)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 xform_get_determinant(struct xform xf)
|
INLINE f32 xform_get_determinant(Xform xf)
|
||||||
{
|
{
|
||||||
return v2_wedge(xf.bx, xf.by);
|
return v2_wedge(xf.bx, xf.by);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 xform_get_right(struct xform xf)
|
INLINE V2 xform_get_right(Xform xf)
|
||||||
{
|
{
|
||||||
return xf.bx;
|
return xf.bx;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 xform_get_left(struct xform xf)
|
INLINE V2 xform_get_left(Xform xf)
|
||||||
{
|
{
|
||||||
return v2_neg(xf.bx);
|
return v2_neg(xf.bx);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 xform_get_up(struct xform xf)
|
INLINE V2 xform_get_up(Xform xf)
|
||||||
{
|
{
|
||||||
return v2_neg(xf.by);
|
return v2_neg(xf.by);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 xform_get_down(struct xform xf)
|
INLINE V2 xform_get_down(Xform xf)
|
||||||
{
|
{
|
||||||
return xf.by;
|
return xf.by;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE f32 xform_get_rotation(struct xform xf)
|
INLINE f32 xform_get_rotation(Xform xf)
|
||||||
{
|
{
|
||||||
return v2_angle(xf.bx);
|
return v2_angle(xf.bx);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct v2 xform_get_scale(struct xform xf)
|
INLINE V2 xform_get_scale(Xform xf)
|
||||||
{
|
{
|
||||||
f32 det_sign = math_fsign(xform_get_determinant(xf));
|
f32 det_sign = math_fsign(xform_get_determinant(xf));
|
||||||
return V2(v2_len(xf.bx), det_sign * v2_len(xf.by));
|
return V2FromXY(v2_len(xf.bx), det_sign * v2_len(xf.by));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Quad
|
* Quad
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE struct quad quad_from_rect(struct rect rect)
|
INLINE Quad quad_from_rect(Rect rect)
|
||||||
{
|
{
|
||||||
struct quad res;
|
Quad res;
|
||||||
res.p0 = V2(rect.x, rect.y); /* Top left */
|
res.p0 = V2FromXY(rect.x, rect.y); /* Top left */
|
||||||
res.p1 = V2(rect.x + rect.width, rect.y); /* Top right */
|
res.p1 = V2FromXY(rect.x + rect.width, rect.y); /* Top right */
|
||||||
res.p2 = V2(rect.x + rect.width, rect.y + rect.height); /* Bottom right */
|
res.p2 = V2FromXY(rect.x + rect.width, rect.y + rect.height); /* Bottom right */
|
||||||
res.p3 = V2(rect.x, rect.y + rect.height); /* Bottom left */
|
res.p3 = V2FromXY(rect.x, rect.y + rect.height); /* Bottom left */
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct quad quad_from_aabb(struct aabb aabb)
|
INLINE Quad quad_from_aabb(Aabb aabb)
|
||||||
{
|
{
|
||||||
struct quad res;
|
Quad res;
|
||||||
res.p0 = V2(aabb.p0.x, aabb.p0.y); /* Top left */
|
res.p0 = V2FromXY(aabb.p0.x, aabb.p0.y); /* Top left */
|
||||||
res.p1 = V2(aabb.p1.x, aabb.p0.y); /* Top right */
|
res.p1 = V2FromXY(aabb.p1.x, aabb.p0.y); /* Top right */
|
||||||
res.p2 = V2(aabb.p1.x, aabb.p1.y); /* Bottom right */
|
res.p2 = V2FromXY(aabb.p1.x, aabb.p1.y); /* Bottom right */
|
||||||
res.p3 = V2(aabb.p0.x, aabb.p1.y); /* Bottom left */
|
res.p3 = V2FromXY(aabb.p0.x, aabb.p1.y); /* Bottom left */
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct quad quad_from_line(struct v2 start, struct v2 end, f32 thickness)
|
INLINE Quad quad_from_line(V2 start, V2 end, f32 thickness)
|
||||||
{
|
{
|
||||||
f32 width = thickness / 2.f;
|
f32 width = thickness / 2.f;
|
||||||
|
|
||||||
struct v2 dir = v2_norm(v2_sub(end, start));
|
V2 dir = v2_norm(v2_sub(end, start));
|
||||||
struct v2 dir_perp = v2_perp(dir);
|
V2 dir_perp = v2_perp(dir);
|
||||||
|
|
||||||
struct v2 left = v2_mul(dir_perp, -width);
|
V2 left = v2_mul(dir_perp, -width);
|
||||||
struct v2 right = v2_mul(dir_perp, width);
|
V2 right = v2_mul(dir_perp, width);
|
||||||
|
|
||||||
struct quad res;
|
Quad res;
|
||||||
res.p0 = v2_add(start, left);
|
res.p0 = v2_add(start, left);
|
||||||
res.p1 = v2_add(start, right);
|
res.p1 = v2_add(start, right);
|
||||||
res.p2 = v2_add(end, right);
|
res.p2 = v2_add(end, right);
|
||||||
@ -1329,13 +1344,13 @@ INLINE struct quad quad_from_line(struct v2 start, struct v2 end, f32 thickness)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct quad quad_from_ray(struct v2 pos, struct v2 rel, f32 thickness)
|
INLINE Quad quad_from_ray(V2 pos, V2 rel, f32 thickness)
|
||||||
{
|
{
|
||||||
struct v2 end = v2_add(pos, rel);
|
V2 end = v2_add(pos, rel);
|
||||||
return quad_from_line(pos, end, thickness);
|
return quad_from_line(pos, end, thickness);
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct quad quad_scale(struct quad q, f32 s)
|
INLINE Quad quad_scale(Quad q, f32 s)
|
||||||
{
|
{
|
||||||
q.p0 = v2_mul(q.p0, s);
|
q.p0 = v2_mul(q.p0, s);
|
||||||
q.p1 = v2_mul(q.p1, s);
|
q.p1 = v2_mul(q.p1, s);
|
||||||
@ -1344,9 +1359,9 @@ INLINE struct quad quad_scale(struct quad q, f32 s)
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct quad quad_round(struct quad quad)
|
INLINE Quad quad_round(Quad quad)
|
||||||
{
|
{
|
||||||
struct quad res;
|
Quad res;
|
||||||
res.p0 = v2_round(quad.p0);
|
res.p0 = v2_round(quad.p0);
|
||||||
res.p1 = v2_round(quad.p1);
|
res.p1 = v2_round(quad.p1);
|
||||||
res.p2 = v2_round(quad.p2);
|
res.p2 = v2_round(quad.p2);
|
||||||
@ -1354,9 +1369,9 @@ INLINE struct quad quad_round(struct quad quad)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct quad quad_floor(struct quad quad)
|
INLINE Quad quad_floor(Quad quad)
|
||||||
{
|
{
|
||||||
struct quad res;
|
Quad res;
|
||||||
res.p0 = v2_floor(quad.p0);
|
res.p0 = v2_floor(quad.p0);
|
||||||
res.p1 = v2_floor(quad.p1);
|
res.p1 = v2_floor(quad.p1);
|
||||||
res.p2 = v2_floor(quad.p2);
|
res.p2 = v2_floor(quad.p2);
|
||||||
@ -1368,9 +1383,9 @@ INLINE struct quad quad_floor(struct quad quad)
|
|||||||
* Convex polygon
|
* Convex polygon
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INLINE struct v2 math_poly_center(struct v2_array a)
|
INLINE V2 math_poly_center(V2Array a)
|
||||||
{
|
{
|
||||||
struct v2 sum = V2(0, 0);
|
V2 sum = V2FromXY(0, 0);
|
||||||
for (u64 i = 0; i < a.count; ++i) {
|
for (u64 i = 0; i < a.count; ++i) {
|
||||||
sum = v2_add(sum, a.points[i]);
|
sum = v2_add(sum, a.points[i]);
|
||||||
}
|
}
|
||||||
@ -1378,14 +1393,20 @@ INLINE struct v2 math_poly_center(struct v2_array a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Other
|
* Spring
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* https://box2d.org/files/ErinCatto_SoftConstraints_GDC2011.pdf */
|
/* https://box2d.org/files/ErinCatto_SoftConstraints_GDC2011.pdf */
|
||||||
struct math_spring { f32 bias_rate; f32 mass_scale; f32 impulse_scale; };
|
typedef struct SoftSpring SoftSpring;
|
||||||
INLINE struct math_spring math_spring_init(f32 hertz, f32 damping_ratio, f32 dt)
|
struct SoftSpring {
|
||||||
|
f32 bias_rate;
|
||||||
|
f32 mass_scale;
|
||||||
|
f32 impulse_scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
INLINE SoftSpring math_spring_init(f32 hertz, f32 damping_ratio, f32 dt)
|
||||||
{
|
{
|
||||||
struct math_spring res;
|
SoftSpring res;
|
||||||
if (hertz == 0.0f) {
|
if (hertz == 0.0f) {
|
||||||
res.bias_rate = 0;
|
res.bias_rate = 0;
|
||||||
res.mass_scale = 1;
|
res.mass_scale = 1;
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
# define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081)
|
# define BCRYPT_RNG_ALG_HANDLE ((void *)0x00000081)
|
||||||
u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
u32 BCryptGenRandom(void *algorithm, u8 *buffer, u32 buffer_size, u32 flags);
|
||||||
void rand_true(struct string buffer)
|
void rand_true(String buffer)
|
||||||
{
|
{
|
||||||
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, (u8 *)buffer.text, buffer.len, 0);
|
||||||
}
|
}
|
||||||
@ -16,7 +16,7 @@ void rand_true(struct string buffer)
|
|||||||
* Stateful prng
|
* Stateful prng
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
u64 rand_u64_from_state(struct rand_state *state)
|
u64 rand_u64_from_state(RandState *state)
|
||||||
{
|
{
|
||||||
u64 seed = state->seed;
|
u64 seed = state->seed;
|
||||||
if (seed == 0) {
|
if (seed == 0) {
|
||||||
@ -26,7 +26,7 @@ u64 rand_u64_from_state(struct rand_state *state)
|
|||||||
return seed ^ rand_u64_from_seed(++state->counter);
|
return seed ^ rand_u64_from_seed(++state->counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end)
|
f64 rand_f64_from_state(RandState *state, f64 range_start, f64 range_end)
|
||||||
{
|
{
|
||||||
return range_start + (range_end - range_start) * ((f64)(rand_u64_from_state(state) % F64_RAND_MAX) / (f64)F64_RAND_MAX);
|
return range_start + (range_end - range_start) * ((f64)(rand_u64_from_state(state) % F64_RAND_MAX) / (f64)F64_RAND_MAX);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
struct rand_state {
|
typedef struct RandState RandState;
|
||||||
|
struct RandState {
|
||||||
/* If a state's seed == 0 upon a call to a related function, it will be initialized using platform's true rng source */
|
/* If a state's seed == 0 upon a call to a related function, it will be initialized using platform's true rng source */
|
||||||
u64 seed;
|
u64 seed;
|
||||||
u64 counter;
|
u64 counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
void rand_true(struct string buffer);
|
void rand_true(String buffer);
|
||||||
|
|
||||||
u64 rand_u64_from_state(struct rand_state *state);
|
u64 rand_u64_from_state(RandState *state);
|
||||||
f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end);
|
f64 rand_f64_from_state(RandState *state, f64 range_start, f64 range_end);
|
||||||
|
|
||||||
u64 rand_u64_from_seed(u64 seed);
|
u64 rand_u64_from_seed(u64 seed);
|
||||||
u64 rand_u64_from_seeds(u64 seed_a, u64 seed_b);
|
u64 rand_u64_from_seeds(u64 seed_a, u64 seed_b);
|
||||||
|
|||||||
@ -16,22 +16,22 @@
|
|||||||
|
|
||||||
#define INT_CHARS ("0123456789abcdef")
|
#define INT_CHARS ("0123456789abcdef")
|
||||||
|
|
||||||
struct string string_from_char(struct arena *arena, char c)
|
String string_from_char(Arena *arena, char c)
|
||||||
{
|
{
|
||||||
u8 *dst = arena_push_no_zero(arena, u8);
|
u8 *dst = arena_push_no_zero(arena, u8);
|
||||||
*dst = c;
|
*dst = c;
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.len = 1,
|
.len = 1,
|
||||||
.text = dst
|
.text = dst
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_uint(struct arena *arena, u64 n, u64 base, u64 zfill)
|
String string_from_uint(Arena *arena, u64 n, u64 base, u64 zfill)
|
||||||
{
|
{
|
||||||
/* Base too large */
|
/* Base too large */
|
||||||
ASSERT(base <= (countof(INT_CHARS) - 1));
|
ASSERT(base <= (countof(INT_CHARS) - 1));
|
||||||
|
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
/* Build backwards text starting from least significant digit */
|
/* Build backwards text starting from least significant digit */
|
||||||
u64 len = 0;
|
u64 len = 0;
|
||||||
@ -55,13 +55,13 @@ struct string string_from_uint(struct arena *arena, u64 n, u64 base, u64 zfill)
|
|||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.len = len,
|
.len = len,
|
||||||
.text = final_text
|
.text = final_text
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_int(struct arena *arena, i64 n, u64 base, u64 zfill)
|
String string_from_int(Arena *arena, i64 n, u64 base, u64 zfill)
|
||||||
{
|
{
|
||||||
u8 *final_text = arena_push_dry(arena, u8);
|
u8 *final_text = arena_push_dry(arena, u8);
|
||||||
u8 len = 0;
|
u8 len = 0;
|
||||||
@ -72,26 +72,26 @@ struct string string_from_int(struct arena *arena, i64 n, u64 base, u64 zfill)
|
|||||||
n = -n;
|
n = -n;
|
||||||
}
|
}
|
||||||
/* Push unsigned number */
|
/* Push unsigned number */
|
||||||
struct string uint_str = string_from_uint(arena, n, base, zfill);
|
String uint_str = string_from_uint(arena, n, base, zfill);
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.len = len + uint_str.len,
|
.len = len + uint_str.len,
|
||||||
.text = final_text
|
.text = final_text
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_ptr(struct arena *arena, void *ptr)
|
String string_from_ptr(Arena *arena, void *ptr)
|
||||||
{
|
{
|
||||||
struct string prepend = string_copy(arena, LIT("0x"));
|
String prepend = string_copy(arena, LIT("0x"));
|
||||||
struct string uint_str = string_from_uint(arena, (u64)ptr, 16, sizeof(ptr));
|
String uint_str = string_from_uint(arena, (u64)ptr, 16, sizeof(ptr));
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.len = prepend.len + uint_str.len,
|
.len = prepend.len + uint_str.len,
|
||||||
.text = prepend.text
|
.text = prepend.text
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_float(struct arena *arena, f64 f, u32 precision)
|
String string_from_float(Arena *arena, f64 f, u32 precision)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
u8 *final_text = arena_push_dry(arena, u8);
|
u8 *final_text = arena_push_dry(arena, u8);
|
||||||
u64 final_len = 0;
|
u64 final_len = 0;
|
||||||
|
|
||||||
@ -148,15 +148,15 @@ struct string string_from_float(struct arena *arena, f64 f, u32 precision)
|
|||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.len = final_len,
|
.len = final_len,
|
||||||
.text = final_text
|
.text = final_text
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_handle(struct arena *arena, u64 v0, u64 v1)
|
String string_from_handle(Arena *arena, u64 v0, u64 v1)
|
||||||
{
|
{
|
||||||
struct string res = ZI;
|
String res = ZI;
|
||||||
res.text = arena_push_dry(arena, u8);
|
res.text = arena_push_dry(arena, u8);
|
||||||
res.len += string_copy(arena, LIT("h")).len;
|
res.len += string_copy(arena, LIT("h")).len;
|
||||||
res.len += string_from_uint(arena, v0, 16, 0).len;
|
res.len += string_from_uint(arena, v0, 16, 0).len;
|
||||||
@ -165,9 +165,9 @@ struct string string_from_handle(struct arena *arena, u64 v0, u64 v1)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_uid(struct arena *arena, struct uid uid)
|
String string_from_uid(Arena *arena, UID uid)
|
||||||
{
|
{
|
||||||
struct string res = ZI;
|
String res = ZI;
|
||||||
res.text = arena_push_dry(arena, u8);
|
res.text = arena_push_dry(arena, u8);
|
||||||
res.len += string_from_uint(arena, (uid.hi >> 32), 16, 8).len;
|
res.len += string_from_uint(arena, (uid.hi >> 32), 16, 8).len;
|
||||||
return res;
|
return res;
|
||||||
@ -177,9 +177,9 @@ struct string string_from_uid(struct arena *arena, struct uid uid)
|
|||||||
* String operations
|
* String operations
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string string_copy(struct arena *arena, struct string src)
|
String string_copy(Arena *arena, String src)
|
||||||
{
|
{
|
||||||
struct string str = {
|
String str = {
|
||||||
.len = src.len,
|
.len = src.len,
|
||||||
.text = arena_push_array_no_zero(arena, u8, src.len)
|
.text = arena_push_array_no_zero(arena, u8, src.len)
|
||||||
};
|
};
|
||||||
@ -187,31 +187,31 @@ struct string string_copy(struct arena *arena, struct string src)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_copy_to_string(struct string dst, struct string src)
|
String string_copy_to_string(String dst, String src)
|
||||||
{
|
{
|
||||||
struct string res = ZI;
|
String res = ZI;
|
||||||
res.len = min_u64(dst.len, src.len);
|
res.len = min_u64(dst.len, src.len);
|
||||||
res.text = dst.text;
|
res.text = dst.text;
|
||||||
MEMCPY(res.text, src.text, res.len);
|
MEMCPY(res.text, src.text, res.len);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_repeat(struct arena *arena, struct string src, u64 count)
|
String string_repeat(Arena *arena, String src, u64 count)
|
||||||
{
|
{
|
||||||
u64 final_len = src.len * count;
|
u64 final_len = src.len * count;
|
||||||
u8 *final_text = arena_push_array_no_zero(arena, u8, final_len);
|
u8 *final_text = arena_push_array_no_zero(arena, u8, final_len);
|
||||||
for (u64 i = 0; i < count; ++i) {
|
for (u64 i = 0; i < count; ++i) {
|
||||||
MEMCPY(final_text + (src.len * i), src.text, src.len);
|
MEMCPY(final_text + (src.len * i), src.text, src.len);
|
||||||
}
|
}
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.text = final_text,
|
.text = final_text,
|
||||||
.len = final_len
|
.len = final_len
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_cat(struct arena *arena, struct string str1, struct string str2)
|
String string_cat(Arena *arena, String str1, String str2)
|
||||||
{
|
{
|
||||||
struct string new_str = ZI;
|
String new_str = ZI;
|
||||||
new_str.len = str1.len + str2.len;
|
new_str.len = str1.len + str2.len;
|
||||||
new_str.text = arena_push_array_no_zero(arena, u8, new_str.len);
|
new_str.text = arena_push_array_no_zero(arena, u8, new_str.len);
|
||||||
MEMCPY(new_str.text, str1.text, str1.len);
|
MEMCPY(new_str.text, str1.text, str1.len);
|
||||||
@ -221,50 +221,50 @@ struct string string_cat(struct arena *arena, struct string str1, struct string
|
|||||||
|
|
||||||
/* `arena` is where pieces will be allocated. These strings point
|
/* `arena` is where pieces will be allocated. These strings point
|
||||||
* into the existing string and do not allocate any new text. */
|
* into the existing string and do not allocate any new text. */
|
||||||
struct string_array string_split(struct arena *arena, struct string str, struct string delim)
|
StringArray string_split(Arena *arena, String str, String delim)
|
||||||
{
|
{
|
||||||
struct string_array pieces = ZI;
|
StringArray pieces = ZI;
|
||||||
pieces.strings = arena_push_dry(arena, struct string);
|
pieces.strings = arena_push_dry(arena, String);
|
||||||
i64 piece_start = 0;
|
i64 piece_start = 0;
|
||||||
for (i64 i = 0; i < (i64)str.len - (i64)delim.len; ++i) {
|
for (i64 i = 0; i < (i64)str.len - (i64)delim.len; ++i) {
|
||||||
struct string cmp = ZI;
|
String cmp = ZI;
|
||||||
cmp.text = &str.text[i];
|
cmp.text = &str.text[i];
|
||||||
cmp.len = min_i64(str.len - i, delim.len);
|
cmp.len = min_i64(str.len - i, delim.len);
|
||||||
|
|
||||||
b32 is_delimiter = string_eq(cmp, delim);
|
b32 is_delimiter = string_eq(cmp, delim);
|
||||||
if (is_delimiter) {
|
if (is_delimiter) {
|
||||||
struct string piece = ZI;
|
String piece = ZI;
|
||||||
piece.text = &str.text[piece_start];
|
piece.text = &str.text[piece_start];
|
||||||
piece.len = i - piece_start;
|
piece.len = i - piece_start;
|
||||||
i += delim.len;
|
i += delim.len;
|
||||||
piece_start = i;
|
piece_start = i;
|
||||||
if (piece.len > 0) {
|
if (piece.len > 0) {
|
||||||
*arena_push_no_zero(arena, struct string) = piece;
|
*arena_push_no_zero(arena, String) = piece;
|
||||||
++pieces.count;
|
++pieces.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (piece_start < (i64)str.len) {
|
if (piece_start < (i64)str.len) {
|
||||||
struct string piece = ZI;
|
String piece = ZI;
|
||||||
piece.text = &str.text[piece_start];
|
piece.text = &str.text[piece_start];
|
||||||
piece.len = str.len - piece_start;
|
piece.len = str.len - piece_start;
|
||||||
*arena_push_no_zero(arena, struct string) = piece;
|
*arena_push_no_zero(arena, String) = piece;
|
||||||
++pieces.count;
|
++pieces.count;
|
||||||
}
|
}
|
||||||
return pieces;
|
return pieces;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: Really slow */
|
/* NOTE: Really slow */
|
||||||
struct string string_indent(struct arena *arena, struct string str, u32 indent)
|
String string_indent(Arena *arena, String str, u32 indent)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
u64 final_len = 0;
|
u64 final_len = 0;
|
||||||
u8 *final_text = arena_push_dry(arena, u8);
|
u8 *final_text = arena_push_dry(arena, u8);
|
||||||
|
|
||||||
struct string_array split = string_split(scratch.arena, str, LIT("\n"));
|
StringArray split = string_split(scratch.arena, str, LIT("\n"));
|
||||||
for (u64 i = 0; i < split.count; ++i) {
|
for (u64 i = 0; i < split.count; ++i) {
|
||||||
struct string piece = split.strings[i];
|
String piece = split.strings[i];
|
||||||
for (u32 j = 0; j < indent; ++j) {
|
for (u32 j = 0; j < indent; ++j) {
|
||||||
string_from_char(arena, ' ');
|
string_from_char(arena, ' ');
|
||||||
++final_len;
|
++final_len;
|
||||||
@ -279,15 +279,15 @@ struct string string_indent(struct arena *arena, struct string str, u32 indent)
|
|||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.len = final_len,
|
.len = final_len,
|
||||||
.text = final_text
|
.text = final_text
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_lower(struct arena *arena, struct string str)
|
String string_lower(Arena *arena, String str)
|
||||||
{
|
{
|
||||||
struct string res = ZI;
|
String res = ZI;
|
||||||
res.text = arena_push_array_no_zero(arena, u8, str.len);
|
res.text = arena_push_array_no_zero(arena, u8, str.len);
|
||||||
res.len = str.len;
|
res.len = str.len;
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ struct string string_lower(struct arena *arena, struct string str)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 string_eq(struct string str1, struct string str2)
|
b32 string_eq(String str1, String str2)
|
||||||
{
|
{
|
||||||
b32 eq = 1;
|
b32 eq = 1;
|
||||||
if (str1.len == str2.len) {
|
if (str1.len == str2.len) {
|
||||||
@ -318,7 +318,7 @@ b32 string_eq(struct string str1, struct string str2)
|
|||||||
return eq;
|
return eq;
|
||||||
}
|
}
|
||||||
|
|
||||||
i32 string_cmp(struct string str1, struct string str2)
|
i32 string_cmp(String str1, String str2)
|
||||||
{
|
{
|
||||||
i32 res = 0;
|
i32 res = 0;
|
||||||
for (u64 i = 0; i < min_u64(str1.len, str2.len); ++i) {
|
for (u64 i = 0; i < min_u64(str1.len, str2.len); ++i) {
|
||||||
@ -337,7 +337,7 @@ i32 string_cmp(struct string str1, struct string str2)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 string_contains(struct string str, struct string substring)
|
b32 string_contains(String str, String substring)
|
||||||
{
|
{
|
||||||
if (substring.len > str.len) {
|
if (substring.len > str.len) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -359,7 +359,7 @@ b32 string_contains(struct string str, struct string substring)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 string_starts_with(struct string str, struct string substring)
|
b32 string_starts_with(String str, String substring)
|
||||||
{
|
{
|
||||||
if (str.len >= substring.len) {
|
if (str.len >= substring.len) {
|
||||||
for (u64 i = 0; i < substring.len; ++i) {
|
for (u64 i = 0; i < substring.len; ++i) {
|
||||||
@ -372,7 +372,7 @@ b32 string_starts_with(struct string str, struct string substring)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 string_ends_with(struct string str, struct string substring)
|
b32 string_ends_with(String str, String substring)
|
||||||
{
|
{
|
||||||
if (str.len >= substring.len) {
|
if (str.len >= substring.len) {
|
||||||
u64 start = str.len - substring.len;
|
u64 start = str.len - substring.len;
|
||||||
@ -421,7 +421,7 @@ b32 string_ends_with(struct string str, struct string substring)
|
|||||||
* %e/%E equivalent? (scientific notation of floats)
|
* %e/%E equivalent? (scientific notation of floats)
|
||||||
* %o equivalent? (octal representation)
|
* %o equivalent? (octal representation)
|
||||||
*/
|
*/
|
||||||
struct string string_formatv(struct arena *arena, struct string fmt, va_list args)
|
String string_formatv(Arena *arena, String fmt, va_list args)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -441,7 +441,7 @@ struct string string_formatv(struct arena *arena, struct string fmt, va_list arg
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!no_more_args && !escape && *c == '%' && *next == 'F') {
|
if (!no_more_args && !escape && *c == '%' && *next == 'F') {
|
||||||
struct string parsed_str = ZI;
|
String parsed_str = ZI;
|
||||||
/* Detect arg type and parse to string */
|
/* Detect arg type and parse to string */
|
||||||
struct fmt_arg arg = va_arg(args, struct fmt_arg);
|
struct fmt_arg arg = va_arg(args, struct fmt_arg);
|
||||||
switch (arg.type) {
|
switch (arg.type) {
|
||||||
@ -514,17 +514,17 @@ struct string string_formatv(struct arena *arena, struct string fmt, va_list arg
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.len = final_len,
|
.len = final_len,
|
||||||
.text = final_text
|
.text = final_text
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string _string_format(struct arena *arena, struct string fmt, ...)
|
String _string_format(Arena *arena, String fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
struct string new_str = string_formatv(arena, fmt, args);
|
String new_str = string_formatv(arena, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return new_str;
|
return new_str;
|
||||||
}
|
}
|
||||||
@ -535,7 +535,7 @@ struct string _string_format(struct arena *arena, struct string fmt, ...)
|
|||||||
|
|
||||||
/* Codepoint iteration */
|
/* Codepoint iteration */
|
||||||
|
|
||||||
struct string_codepoint_iter string_codepoint_iter_begin(struct string str)
|
struct string_codepoint_iter string_codepoint_iter_begin(String str)
|
||||||
{
|
{
|
||||||
return (struct string_codepoint_iter) {
|
return (struct string_codepoint_iter) {
|
||||||
.src = str
|
.src = str
|
||||||
@ -546,8 +546,8 @@ struct string_codepoint_iter string_codepoint_iter_begin(struct string str)
|
|||||||
b32 string_codepoint_iter_next(struct string_codepoint_iter *iter)
|
b32 string_codepoint_iter_next(struct string_codepoint_iter *iter)
|
||||||
{
|
{
|
||||||
if (iter->pos < iter->src.len) {
|
if (iter->pos < iter->src.len) {
|
||||||
struct string str_remaining = { .len = (iter->src.len - iter->pos), .text = iter->src.text + iter->pos };
|
String str_remaining = { .len = (iter->src.len - iter->pos), .text = iter->src.text + iter->pos };
|
||||||
struct uni_decode_utf8_result decoded = uni_decode_utf8(str_remaining);
|
Utf8DecodeResult decoded = uni_decode_utf8(str_remaining);
|
||||||
iter->pos += decoded.advance8;
|
iter->pos += decoded.advance8;
|
||||||
iter->codepoint = decoded.codepoint;
|
iter->codepoint = decoded.codepoint;
|
||||||
return 1;
|
return 1;
|
||||||
@ -563,18 +563,18 @@ void string_codepoint_iter_end(struct string_codepoint_iter *iter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* utf8 <- utf16 */
|
/* utf8 <- utf16 */
|
||||||
struct string string_from_string16(struct arena *arena, struct string16 str16)
|
String string_from_string16(Arena *arena, String16 str16)
|
||||||
{
|
{
|
||||||
struct string res = {
|
String res = {
|
||||||
.len = 0,
|
.len = 0,
|
||||||
.text = arena_push_dry(arena, u8)
|
.text = arena_push_dry(arena, u8)
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 pos16 = 0;
|
u64 pos16 = 0;
|
||||||
while (pos16 < str16.len) {
|
while (pos16 < str16.len) {
|
||||||
struct string16 str16_remaining = { .len = (str16.len - pos16), .text = str16.text + pos16 };
|
String16 str16_remaining = { .len = (str16.len - pos16), .text = str16.text + pos16 };
|
||||||
struct uni_decode_utf16_result decoded = uni_decode_utf16(str16_remaining);
|
Utf16DecodeResult decoded = uni_decode_utf16(str16_remaining);
|
||||||
struct uni_encode_utf8_result encoded = uni_encode_utf8(decoded.codepoint);
|
Utf8EncodeResult encoded = uni_encode_utf8(decoded.codepoint);
|
||||||
|
|
||||||
u8 *dst = arena_push_array_no_zero(arena, u8, encoded.count8);
|
u8 *dst = arena_push_array_no_zero(arena, u8, encoded.count8);
|
||||||
MEMCPY(dst, encoded.chars8, encoded.count8);
|
MEMCPY(dst, encoded.chars8, encoded.count8);
|
||||||
@ -587,18 +587,18 @@ struct string string_from_string16(struct arena *arena, struct string16 str16)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* utf8 <- utf32 */
|
/* utf8 <- utf32 */
|
||||||
struct string string_from_string32(struct arena *arena, struct string32 str32)
|
String string_from_string32(Arena *arena, String32 str32)
|
||||||
{
|
{
|
||||||
struct string res = {
|
String res = {
|
||||||
.len = 0,
|
.len = 0,
|
||||||
.text = arena_push_dry(arena, u8)
|
.text = arena_push_dry(arena, u8)
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 pos32 = 0;
|
u64 pos32 = 0;
|
||||||
while (pos32 < str32.len) {
|
while (pos32 < str32.len) {
|
||||||
struct string32 str32_remaining = { .len = (str32.len - pos32), .text = str32.text + pos32 };
|
String32 str32_remaining = { .len = (str32.len - pos32), .text = str32.text + pos32 };
|
||||||
struct uni_decode_utf32_result decoded = uni_decode_utf32(str32_remaining);
|
Utf32DecodeResult decoded = uni_decode_utf32(str32_remaining);
|
||||||
struct uni_encode_utf8_result encoded = uni_encode_utf8(decoded.codepoint);
|
Utf8EncodeResult encoded = uni_encode_utf8(decoded.codepoint);
|
||||||
|
|
||||||
u8 *dst = arena_push_array_no_zero(arena, u8, encoded.count8);
|
u8 *dst = arena_push_array_no_zero(arena, u8, encoded.count8);
|
||||||
MEMCPY(dst, &encoded.chars8, encoded.count8);
|
MEMCPY(dst, &encoded.chars8, encoded.count8);
|
||||||
@ -611,18 +611,18 @@ struct string string_from_string32(struct arena *arena, struct string32 str32)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* utf16 <- utf8 */
|
/* utf16 <- utf8 */
|
||||||
struct string16 string16_from_string(struct arena *arena, struct string str8)
|
String16 string16_from_string(Arena *arena, String str8)
|
||||||
{
|
{
|
||||||
struct string16 res = {
|
String16 res = {
|
||||||
.len = 0,
|
.len = 0,
|
||||||
.text = arena_push_dry(arena, u16)
|
.text = arena_push_dry(arena, u16)
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 pos8 = 0;
|
u64 pos8 = 0;
|
||||||
while (pos8 < str8.len) {
|
while (pos8 < str8.len) {
|
||||||
struct string str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 };
|
String str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 };
|
||||||
struct uni_decode_utf8_result decoded = uni_decode_utf8(str8_remaining);
|
Utf8DecodeResult decoded = uni_decode_utf8(str8_remaining);
|
||||||
struct uni_encode_utf16_result encoded = uni_encode_utf16(decoded.codepoint);
|
Utf16EncodeResult encoded = uni_encode_utf16(decoded.codepoint);
|
||||||
|
|
||||||
u16 *dst = arena_push_array_no_zero(arena, u16, encoded.count16);
|
u16 *dst = arena_push_array_no_zero(arena, u16, encoded.count16);
|
||||||
MEMCPY(dst, encoded.chars16, (encoded.count16 << 1));
|
MEMCPY(dst, encoded.chars16, (encoded.count16 << 1));
|
||||||
@ -635,18 +635,18 @@ struct string16 string16_from_string(struct arena *arena, struct string str8)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* utf32 <- utf8 */
|
/* utf32 <- utf8 */
|
||||||
struct string32 string32_from_string(struct arena *arena, struct string str8)
|
String32 string32_from_string(Arena *arena, String str8)
|
||||||
{
|
{
|
||||||
struct string32 res = {
|
String32 res = {
|
||||||
.len = 0,
|
.len = 0,
|
||||||
.text = arena_push_dry(arena, u32)
|
.text = arena_push_dry(arena, u32)
|
||||||
};
|
};
|
||||||
|
|
||||||
u64 pos8 = 0;
|
u64 pos8 = 0;
|
||||||
while (pos8 < str8.len) {
|
while (pos8 < str8.len) {
|
||||||
struct string str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 };
|
String str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 };
|
||||||
struct uni_decode_utf8_result decoded = uni_decode_utf8(str8_remaining);
|
Utf8DecodeResult decoded = uni_decode_utf8(str8_remaining);
|
||||||
struct uni_encode_utf32_result encoded = uni_encode_utf32(decoded.codepoint);
|
Utf32EncodeResult encoded = uni_encode_utf32(decoded.codepoint);
|
||||||
|
|
||||||
u32 *dst = arena_push_no_zero(arena, u32);
|
u32 *dst = arena_push_no_zero(arena, u32);
|
||||||
*dst = encoded.chars32;
|
*dst = encoded.chars32;
|
||||||
@ -688,7 +688,7 @@ u64 cstr_len(char *cstr, u64 limit)
|
|||||||
return end - cstr;
|
return end - cstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *cstr_from_string(struct arena *arena, struct string src)
|
char *cstr_from_string(Arena *arena, String src)
|
||||||
{
|
{
|
||||||
u8 *text = arena_push_array_no_zero(arena, u8, src.len + 1);
|
u8 *text = arena_push_array_no_zero(arena, u8, src.len + 1);
|
||||||
MEMCPY(text, src.text, src.len);
|
MEMCPY(text, src.text, src.len);
|
||||||
@ -696,7 +696,7 @@ char *cstr_from_string(struct arena *arena, struct string src)
|
|||||||
return (char *)text;
|
return (char *)text;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *cstr_buff_from_string(struct string dst_buff, struct string src)
|
char *cstr_buff_from_string(String dst_buff, String src)
|
||||||
{
|
{
|
||||||
if (dst_buff.len > 0) {
|
if (dst_buff.len > 0) {
|
||||||
u64 len = min_u64(src.len, dst_buff.len - 1);
|
u64 len = min_u64(src.len, dst_buff.len - 1);
|
||||||
@ -706,19 +706,19 @@ char *cstr_buff_from_string(struct string dst_buff, struct string src)
|
|||||||
return (char *)dst_buff.text;
|
return (char *)dst_buff.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_cstr_no_limit(char *cstr)
|
String string_from_cstr_no_limit(char *cstr)
|
||||||
{
|
{
|
||||||
u64 len = cstr_len_no_limit(cstr);
|
u64 len = cstr_len_no_limit(cstr);
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.len = len,
|
.len = len,
|
||||||
.text = (u8 *)cstr
|
.text = (u8 *)cstr
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_cstr(char *cstr, u64 limit)
|
String string_from_cstr(char *cstr, u64 limit)
|
||||||
{
|
{
|
||||||
u64 len = cstr_len(cstr, limit);
|
u64 len = cstr_len(cstr, limit);
|
||||||
return (struct string) {
|
return (String) {
|
||||||
.text = (u8 *)cstr,
|
.text = (u8 *)cstr,
|
||||||
.len = len
|
.len = len
|
||||||
};
|
};
|
||||||
@ -754,45 +754,45 @@ u64 wstr_len(wchar_t *wstr, u64 limit)
|
|||||||
return end - wstr;
|
return end - wstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *wstr_from_string(struct arena *arena, struct string src)
|
wchar_t *wstr_from_string(Arena *arena, String src)
|
||||||
{
|
{
|
||||||
struct string16 str16 = string16_from_string(arena, src);
|
String16 str16 = string16_from_string(arena, src);
|
||||||
*arena_push_no_zero(arena, u16) = 0;
|
*arena_push_no_zero(arena, u16) = 0;
|
||||||
return (wchar_t *)str16.text;
|
return (wchar_t *)str16.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *wstr_from_string16(struct arena *arena, struct string16 src)
|
wchar_t *wstr_from_string16(Arena *arena, String16 src)
|
||||||
{
|
{
|
||||||
u16 *text = arena_push_array_no_zero(arena, u16, src.len + 1);
|
u16 *text = arena_push_array_no_zero(arena, u16, src.len + 1);
|
||||||
text[src.len] = 0;
|
text[src.len] = 0;
|
||||||
return (wchar_t *)text;
|
return (wchar_t *)text;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_wstr_no_limit(struct arena *arena, wchar_t *wstr)
|
String string_from_wstr_no_limit(Arena *arena, wchar_t *wstr)
|
||||||
{
|
{
|
||||||
struct string16 str16 = string16_from_wstr_no_limit(wstr);
|
String16 str16 = string16_from_wstr_no_limit(wstr);
|
||||||
return string_from_string16(arena, str16);
|
return string_from_string16(arena, str16);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string string_from_wstr(struct arena *arena, wchar_t *wstr, u64 limit)
|
String string_from_wstr(Arena *arena, wchar_t *wstr, u64 limit)
|
||||||
{
|
{
|
||||||
struct string16 str16 = string16_from_wstr(wstr, limit);
|
String16 str16 = string16_from_wstr(wstr, limit);
|
||||||
return string_from_string16(arena, str16);
|
return string_from_string16(arena, str16);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string16 string16_from_wstr_no_limit(wchar_t *wstr)
|
String16 string16_from_wstr_no_limit(wchar_t *wstr)
|
||||||
{
|
{
|
||||||
u64 len = wstr_len_no_limit(wstr);
|
u64 len = wstr_len_no_limit(wstr);
|
||||||
return (struct string16) {
|
return (String16) {
|
||||||
.len = len,
|
.len = len,
|
||||||
.text = (u16 *)wstr
|
.text = (u16 *)wstr
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string16 string16_from_wstr(wchar_t *wstr, u64 limit)
|
String16 string16_from_wstr(wchar_t *wstr, u64 limit)
|
||||||
{
|
{
|
||||||
u64 len = wstr_len(wstr, limit);
|
u64 len = wstr_len(wstr, limit);
|
||||||
return (struct string16)
|
return (String16)
|
||||||
{
|
{
|
||||||
.len = len,
|
.len = len,
|
||||||
.text = (u16 *)wstr
|
.text = (u16 *)wstr
|
||||||
|
|||||||
@ -1,21 +1,25 @@
|
|||||||
struct string {
|
typedef struct String String;
|
||||||
|
struct String {
|
||||||
u64 len;
|
u64 len;
|
||||||
u8 *text;
|
u8 *text;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string16 {
|
typedef struct String16 String16;
|
||||||
|
struct String16 {
|
||||||
u64 len;
|
u64 len;
|
||||||
u16 *text;
|
u16 *text;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string32 {
|
typedef struct String32 String32;
|
||||||
|
struct String32 {
|
||||||
u64 len;
|
u64 len;
|
||||||
u32 *text;
|
u32 *text;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string_array {
|
typedef struct StringArray StringArray;
|
||||||
|
struct StringArray {
|
||||||
u64 count;
|
u64 count;
|
||||||
struct string *strings;
|
String *strings;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -23,16 +27,16 @@ struct string_array {
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Expand C string literal with size for string initialization */
|
/* Expand C string literal with size for string initialization */
|
||||||
#define LIT(cstr_lit) CPPCOMPAT_INITLIST_TYPE(struct string) { (sizeof((cstr_lit)) - 1), (u8 *)(cstr_lit) }
|
#define LIT(cstr_lit) CPPCOMPAT_INITLIST_TYPE(String) { (sizeof((cstr_lit)) - 1), (u8 *)(cstr_lit) }
|
||||||
|
|
||||||
/* Same as `STR`, but works with static variable initialization */
|
/* Same as `STR`, but works with static variable initialization */
|
||||||
#define LIT_NOCAST(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) }
|
#define LIT_NOCAST(cstr_lit) { .len = (sizeof((cstr_lit)) - 1), .text = (u8 *)(cstr_lit) }
|
||||||
|
|
||||||
#define STRING(size, data) (CPPCOMPAT_INITLIST_TYPE(struct string) { (size), (data) })
|
#define STRING(size, data) (CPPCOMPAT_INITLIST_TYPE(String) { (size), (data) })
|
||||||
|
|
||||||
#define STRING_FROM_POINTERS(p0, p1) (CPPCOMPAT_INITLIST_TYPE(struct string) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 })
|
#define STRING_FROM_POINTERS(p0, p1) (CPPCOMPAT_INITLIST_TYPE(String) { (u8 *)(p1) - (u8 *)(p0), (u8 *)p0 })
|
||||||
|
|
||||||
#define STRING_FROM_STRUCT(ptr) (CPPCOMPAT_INITLIST_TYPE(struct string) { sizeof(*(ptr)), (u8 *)(ptr) })
|
#define STRING_FROM_STRUCT(ptr) (CPPCOMPAT_INITLIST_TYPE(String) { sizeof(*(ptr)), (u8 *)(ptr) })
|
||||||
|
|
||||||
#define STRING_FROM_ARENA(arena) (STRING((arena)->pos, arena_base(arena)))
|
#define STRING_FROM_ARENA(arena) (STRING((arena)->pos, arena_base(arena)))
|
||||||
|
|
||||||
@ -41,7 +45,7 @@ struct string_array {
|
|||||||
( \
|
( \
|
||||||
/* Must be array */ \
|
/* Must be array */ \
|
||||||
ASSERT(IS_ARRAY(a)), \
|
ASSERT(IS_ARRAY(a)), \
|
||||||
((struct string) { .len = sizeof(a), .text = (u8 *)(a) }) \
|
((String) { .len = sizeof(a), .text = (u8 *)(a) }) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -49,30 +53,30 @@ struct string_array {
|
|||||||
* Conversion
|
* Conversion
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string string_from_char(struct arena *arena, char c);
|
String string_from_char(Arena *arena, char c);
|
||||||
struct string string_from_uint(struct arena *arena, u64 n, u64 base, u64 zfill);
|
String string_from_uint(Arena *arena, u64 n, u64 base, u64 zfill);
|
||||||
struct string string_from_int(struct arena *arena, i64 n, u64 base, u64 zfill);
|
String string_from_int(Arena *arena, i64 n, u64 base, u64 zfill);
|
||||||
struct string string_from_ptr(struct arena *arena, void *ptr);
|
String string_from_ptr(Arena *arena, void *ptr);
|
||||||
struct string string_from_float(struct arena *arena, f64 f, u32 precision);
|
String string_from_float(Arena *arena, f64 f, u32 precision);
|
||||||
struct string string_from_handle(struct arena *arena, u64 v0, u64 v1);
|
String string_from_handle(Arena *arena, u64 v0, u64 v1);
|
||||||
struct string string_from_uid(struct arena *arena, struct uid uid);
|
String string_from_uid(Arena *arena, UID uid);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* String operations
|
* String operations
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string string_copy(struct arena *arena, struct string src);
|
String string_copy(Arena *arena, String src);
|
||||||
struct string string_copy_to_string(struct string dst, struct string src);
|
String string_copy_to_string(String dst, String src);
|
||||||
struct string string_repeat(struct arena *arena, struct string src, u64 count);
|
String string_repeat(Arena *arena, String src, u64 count);
|
||||||
struct string string_cat(struct arena *arena, struct string str1, struct string str2);
|
String string_cat(Arena *arena, String str1, String str2);
|
||||||
struct string_array string_split(struct arena *arena, struct string str, struct string delim);
|
StringArray string_split(Arena *arena, String str, String delim);
|
||||||
struct string string_indent(struct arena *arena, struct string str, u32 indent);
|
String string_indent(Arena *arena, String str, u32 indent);
|
||||||
struct string string_lower(struct arena *arena, struct string str);
|
String string_lower(Arena *arena, String str);
|
||||||
b32 string_eq(struct string str1, struct string str2);
|
b32 string_eq(String str1, String str2);
|
||||||
i32 string_cmp(struct string str1, struct string str2);
|
i32 string_cmp(String str1, String str2);
|
||||||
b32 string_contains(struct string str, struct string substring);
|
b32 string_contains(String str, String substring);
|
||||||
b32 string_starts_with(struct string str, struct string substring);
|
b32 string_starts_with(String str, String substring);
|
||||||
b32 string_ends_with(struct string str, struct string substring);
|
b32 string_ends_with(String str, String substring);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Format
|
* Format
|
||||||
@ -103,7 +107,7 @@ struct fmt_arg {
|
|||||||
u32 zfill;
|
u32 zfill;
|
||||||
union {
|
union {
|
||||||
u8 c;
|
u8 c;
|
||||||
struct string string;
|
String string;
|
||||||
u64 uint;
|
u64 uint;
|
||||||
i64 sint;
|
i64 sint;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
@ -111,7 +115,7 @@ struct fmt_arg {
|
|||||||
struct {
|
struct {
|
||||||
u64 h64[2];
|
u64 h64[2];
|
||||||
} handle;
|
} handle;
|
||||||
struct uid uid;
|
UID uid;
|
||||||
} value;
|
} value;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -130,8 +134,8 @@ struct fmt_arg {
|
|||||||
#define FMT_UID(v) (struct fmt_arg) {.type = FMT_TYPE_UID, .value.uid = (v) }
|
#define FMT_UID(v) (struct fmt_arg) {.type = FMT_TYPE_UID, .value.uid = (v) }
|
||||||
|
|
||||||
#define string_format(arena, fmt, ...) _string_format((arena), (fmt), __VA_ARGS__, FMT_END)
|
#define string_format(arena, fmt, ...) _string_format((arena), (fmt), __VA_ARGS__, FMT_END)
|
||||||
struct string _string_format(struct arena *arena, struct string fmt, ...);
|
String _string_format(Arena *arena, String fmt, ...);
|
||||||
struct string string_formatv(struct arena *arena, struct string fmt, va_list args);
|
String string_formatv(Arena *arena, String fmt, va_list args);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Unicode
|
* Unicode
|
||||||
@ -141,19 +145,19 @@ struct string_codepoint_iter {
|
|||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
|
|
||||||
/* Internal */
|
/* Internal */
|
||||||
struct string src;
|
String src;
|
||||||
u64 pos;
|
u64 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string_codepoint_iter string_codepoint_iter_begin(struct string str);
|
struct string_codepoint_iter string_codepoint_iter_begin(String str);
|
||||||
b32 string_codepoint_iter_next(struct string_codepoint_iter *iter);
|
b32 string_codepoint_iter_next(struct string_codepoint_iter *iter);
|
||||||
void string_codepoint_iter_end(struct string_codepoint_iter *iter);
|
void string_codepoint_iter_end(struct string_codepoint_iter *iter);
|
||||||
|
|
||||||
struct string string_from_string16(struct arena *arena, struct string16 str16);
|
String string_from_string16(Arena *arena, String16 str16);
|
||||||
struct string string_from_string32(struct arena *arena, struct string32 str32);
|
String string_from_string32(Arena *arena, String32 str32);
|
||||||
|
|
||||||
struct string16 string16_from_string(struct arena *arena, struct string str8);
|
String16 string16_from_string(Arena *arena, String str8);
|
||||||
struct string32 string32_from_string(struct arena *arena, struct string str8);
|
String32 string32_from_string(Arena *arena, String str8);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Legacy strings
|
* Legacy strings
|
||||||
@ -161,16 +165,16 @@ struct string32 string32_from_string(struct arena *arena, struct string str8);
|
|||||||
|
|
||||||
u64 cstr_len_no_limit(char *cstr);
|
u64 cstr_len_no_limit(char *cstr);
|
||||||
u64 cstr_len(char *cstr, u64 limit);
|
u64 cstr_len(char *cstr, u64 limit);
|
||||||
char *cstr_from_string(struct arena *arena, struct string src);
|
char *cstr_from_string(Arena *arena, String src);
|
||||||
char *cstr_buff_from_string(struct string dest_buff, struct string src);
|
char *cstr_buff_from_string(String dest_buff, String src);
|
||||||
struct string string_from_cstr_no_limit(char *cstr);
|
String string_from_cstr_no_limit(char *cstr);
|
||||||
struct string string_from_cstr(char *cstr, u64 limit);
|
String string_from_cstr(char *cstr, u64 limit);
|
||||||
|
|
||||||
u64 wstr_len_no_limit(wchar_t *wstr);
|
u64 wstr_len_no_limit(wchar_t *wstr);
|
||||||
u64 wstr_len(wchar_t *wstr, u64 limit);
|
u64 wstr_len(wchar_t *wstr, u64 limit);
|
||||||
wchar_t *wstr_from_string(struct arena *arena, struct string src);
|
wchar_t *wstr_from_string(Arena *arena, String src);
|
||||||
wchar_t *wstr_from_string16(struct arena *arena, struct string16 src);
|
wchar_t *wstr_from_string16(Arena *arena, String16 src);
|
||||||
struct string string_from_wstr_no_limit(struct arena *arena, wchar_t *wstr);
|
String string_from_wstr_no_limit(Arena *arena, wchar_t *wstr);
|
||||||
struct string string_from_wstr(struct arena *arena, wchar_t *wstr, u64 limit);
|
String string_from_wstr(Arena *arena, wchar_t *wstr, u64 limit);
|
||||||
struct string16 string16_from_wstr_no_limit(wchar_t *wstr);
|
String16 string16_from_wstr_no_limit(wchar_t *wstr);
|
||||||
struct string16 string16_from_wstr(wchar_t *wstr, u64 limit);
|
String16 string16_from_wstr(wchar_t *wstr, u64 limit);
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
/* Returns a uid generated from the system's random number generator */
|
/* Returns a uid generated from the system's random number generator */
|
||||||
struct uid uid_true_rand(void)
|
UID uid_true_rand(void)
|
||||||
{
|
{
|
||||||
struct uid res = ZI;
|
UID res = ZI;
|
||||||
rand_true(STRING_FROM_STRUCT(&res));
|
rand_true(STRING_FROM_STRUCT(&res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combines 2 uids into a new uid */
|
/* Combines 2 uids into a new uid */
|
||||||
struct uid uid_combine(struct uid a, struct uid b)
|
UID uid_combine(UID a, UID b)
|
||||||
{
|
{
|
||||||
struct uid res;
|
UID res;
|
||||||
res.hi = (a.hi * 3) + b.hi;
|
res.hi = (a.hi * 3) + b.hi;
|
||||||
res.lo = (a.lo * 3) + b.lo;
|
res.lo = (a.lo * 3) + b.lo;
|
||||||
res.hi += res.lo;
|
res.hi += res.lo;
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
#define UID(hi64, lo64) ((struct uid) { .hi = (hi64), .lo = (lo64) })
|
#define MakeUID(hi64, lo64) ((UID) { .hi = (hi64), .lo = (lo64) })
|
||||||
struct uid {
|
typedef struct UID UID;
|
||||||
|
struct UID {
|
||||||
u64 hi;
|
u64 hi;
|
||||||
u64 lo;
|
u64 lo;
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE b32 uid_eq(struct uid a, struct uid b) { return a.hi == b.hi && a.lo == b.lo; }
|
INLINE b32 uid_eq(UID a, UID b) { return a.hi == b.hi && a.lo == b.lo; }
|
||||||
|
|
||||||
INLINE b32 uid_is_zero(struct uid v) { return v.hi == 0 && v.lo == 0; }
|
INLINE b32 uid_is_zero(UID v) { return v.hi == 0 && v.lo == 0; }
|
||||||
|
|
||||||
struct uid uid_true_rand(void);
|
UID uid_true_rand(void);
|
||||||
|
|
||||||
struct uid uid_combine(struct uid a, struct uid b);
|
UID uid_combine(UID a, UID b);
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
* utf8
|
* utf8
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct uni_decode_utf8_result uni_decode_utf8(struct string str)
|
Utf8DecodeResult uni_decode_utf8(String str)
|
||||||
{
|
{
|
||||||
LOCAL_PERSIST const u8 lengths[32] = {
|
LOCAL_PERSIST const u8 lengths[32] = {
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2,3,3,4,5
|
||||||
@ -66,15 +66,15 @@ struct uni_decode_utf8_result uni_decode_utf8(struct string str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct uni_decode_utf8_result) {
|
return (Utf8DecodeResult) {
|
||||||
.advance8 = advance,
|
.advance8 = advance,
|
||||||
.codepoint = codepoint
|
.codepoint = codepoint
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct uni_encode_utf8_result uni_encode_utf8(u32 codepoint)
|
Utf8EncodeResult uni_encode_utf8(u32 codepoint)
|
||||||
{
|
{
|
||||||
struct uni_encode_utf8_result res = ZI;
|
Utf8EncodeResult res = ZI;
|
||||||
|
|
||||||
if (codepoint <= 0x7F) {
|
if (codepoint <= 0x7F) {
|
||||||
res.count8 = 1;
|
res.count8 = 1;
|
||||||
@ -107,7 +107,7 @@ struct uni_encode_utf8_result uni_encode_utf8(u32 codepoint)
|
|||||||
* utf16
|
* utf16
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct uni_decode_utf16_result uni_decode_utf16(struct string16 str)
|
Utf16DecodeResult uni_decode_utf16(String16 str)
|
||||||
{
|
{
|
||||||
u32 codepoint = U32_MAX;
|
u32 codepoint = U32_MAX;
|
||||||
u32 advance = 0;
|
u32 advance = 0;
|
||||||
@ -126,15 +126,15 @@ struct uni_decode_utf16_result uni_decode_utf16(struct string16 str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct uni_decode_utf16_result) {
|
return (Utf16DecodeResult) {
|
||||||
.advance16 = advance,
|
.advance16 = advance,
|
||||||
.codepoint = codepoint
|
.codepoint = codepoint
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct uni_encode_utf16_result uni_encode_utf16(u32 codepoint)
|
Utf16EncodeResult uni_encode_utf16(u32 codepoint)
|
||||||
{
|
{
|
||||||
struct uni_encode_utf16_result res = ZI;
|
Utf16EncodeResult res = ZI;
|
||||||
|
|
||||||
if (codepoint <= 0xFFFF) {
|
if (codepoint <= 0xFFFF) {
|
||||||
res.count16 = 1;
|
res.count16 = 1;
|
||||||
@ -166,7 +166,7 @@ b32 uni_is_utf16_low_surrogate(u16 c)
|
|||||||
* utf32
|
* utf32
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct uni_decode_utf32_result uni_decode_utf32(struct string32 str)
|
Utf32DecodeResult uni_decode_utf32(String32 str)
|
||||||
{
|
{
|
||||||
u32 codepoint = U32_MAX;
|
u32 codepoint = U32_MAX;
|
||||||
u32 advance = 0;
|
u32 advance = 0;
|
||||||
@ -179,15 +179,15 @@ struct uni_decode_utf32_result uni_decode_utf32(struct string32 str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct uni_decode_utf32_result) {
|
return (Utf32DecodeResult) {
|
||||||
.advance32 = advance,
|
.advance32 = advance,
|
||||||
.codepoint = codepoint
|
.codepoint = codepoint
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct uni_encode_utf32_result uni_encode_utf32(u32 codepoint)
|
Utf32EncodeResult uni_encode_utf32(u32 codepoint)
|
||||||
{
|
{
|
||||||
struct uni_encode_utf32_result res = ZI;
|
Utf32EncodeResult res = ZI;
|
||||||
|
|
||||||
if (codepoint <= 0x10FFFF) {
|
if (codepoint <= 0x10FFFF) {
|
||||||
res.chars32 = codepoint;
|
res.chars32 = codepoint;
|
||||||
|
|||||||
@ -2,35 +2,39 @@
|
|||||||
* utf8
|
* utf8
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct uni_decode_utf8_result {
|
typedef struct Utf8DecodeResult Utf8DecodeResult;
|
||||||
|
struct Utf8DecodeResult {
|
||||||
u32 advance8;
|
u32 advance8;
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uni_encode_utf8_result {
|
typedef struct Utf8EncodeResult Utf8EncodeResult;
|
||||||
|
struct Utf8EncodeResult {
|
||||||
u32 count8;
|
u32 count8;
|
||||||
u8 chars8[4];
|
u8 chars8[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uni_decode_utf8_result uni_decode_utf8(struct string str);
|
Utf8DecodeResult uni_decode_utf8(String str);
|
||||||
struct uni_encode_utf8_result uni_encode_utf8(u32 codepoint);
|
Utf8EncodeResult uni_encode_utf8(u32 codepoint);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* utf16
|
* utf16
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct uni_decode_utf16_result {
|
typedef struct Utf16DecodeResult Utf16DecodeResult;
|
||||||
|
struct Utf16DecodeResult {
|
||||||
u32 advance16;
|
u32 advance16;
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uni_encode_utf16_result {
|
typedef struct Utf16EncodeResult Utf16EncodeResult;
|
||||||
|
struct Utf16EncodeResult {
|
||||||
u32 count16;
|
u32 count16;
|
||||||
u16 chars16[2];
|
u16 chars16[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uni_decode_utf16_result uni_decode_utf16(struct string16 str);
|
Utf16DecodeResult uni_decode_utf16(String16 str);
|
||||||
struct uni_encode_utf16_result uni_encode_utf16(u32 codepoint);
|
Utf16EncodeResult uni_encode_utf16(u32 codepoint);
|
||||||
b32 uni_is_utf16_high_surrogate(u16 c);
|
b32 uni_is_utf16_high_surrogate(u16 c);
|
||||||
b32 uni_is_utf16_low_surrogate(u16 c);
|
b32 uni_is_utf16_low_surrogate(u16 c);
|
||||||
|
|
||||||
@ -38,14 +42,16 @@ b32 uni_is_utf16_low_surrogate(u16 c);
|
|||||||
* utf32
|
* utf32
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct uni_decode_utf32_result {
|
typedef struct Utf32DecodeResult Utf32DecodeResult;
|
||||||
|
struct Utf32DecodeResult {
|
||||||
u32 advance32;
|
u32 advance32;
|
||||||
u32 codepoint;
|
u32 codepoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uni_encode_utf32_result {
|
typedef struct Utf32EncodeResult Utf32EncodeResult;
|
||||||
|
struct Utf32EncodeResult {
|
||||||
u32 chars32;
|
u32 chars32;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uni_decode_utf32_result uni_decode_utf32(struct string32 str);
|
Utf32DecodeResult uni_decode_utf32(String32 str);
|
||||||
struct uni_encode_utf32_result uni_encode_utf32(u32 codepoint);
|
Utf32EncodeResult uni_encode_utf32(u32 codepoint);
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define HASH_FNV64_BASIS 0xCBF29CE484222325
|
#define HASH_FNV64_BASIS 0xCBF29CE484222325
|
||||||
INLINE u64 hash_fnv64(u64 seed, struct string s)
|
INLINE u64 hash_fnv64(u64 seed, String s)
|
||||||
{
|
{
|
||||||
u64 hash = seed;
|
u64 hash = seed;
|
||||||
for (u64 i = 0; i < s.len; ++i) {
|
for (u64 i = 0; i < s.len; ++i) {
|
||||||
@ -69,7 +69,7 @@ INLINE void merge_sort_internal(u8 *left, u8 *right, u8 *items, u64 left_count,
|
|||||||
INLINE void merge_sort(void *items, u64 item_count, u64 item_size, sort_compare_func *callback, void *udata)
|
INLINE void merge_sort(void *items, u64 item_count, u64 item_size, sort_compare_func *callback, void *udata)
|
||||||
{
|
{
|
||||||
if (item_count > 1) {
|
if (item_count > 1) {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
u64 left_count = item_count / 2;
|
u64 left_count = item_count / 2;
|
||||||
u64 right_count = item_count - left_count;
|
u64 right_count = item_count - left_count;
|
||||||
|
|
||||||
@ -94,38 +94,41 @@ INLINE void merge_sort(void *items, u64 item_count, u64 item_size, sort_compare_
|
|||||||
* Simple chaining hash -> 64 bit value table for generic use
|
* Simple chaining hash -> 64 bit value table for generic use
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct dict_entry {
|
typedef struct DictEntry DictEntry;
|
||||||
|
struct DictEntry {
|
||||||
u64 hash;
|
u64 hash;
|
||||||
u64 value;
|
u64 value;
|
||||||
struct dict_entry *prev_in_bin;
|
DictEntry *prev_in_bin;
|
||||||
struct dict_entry *next_in_bin;
|
DictEntry *next_in_bin;
|
||||||
struct dict_entry *prev;
|
DictEntry *prev;
|
||||||
struct dict_entry *next;
|
DictEntry *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dict_bin {
|
typedef struct DictBin DictBin;
|
||||||
struct dict_entry *first;
|
struct DictBin {
|
||||||
struct dict_entry *last;
|
DictEntry *first;
|
||||||
|
DictEntry *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dict {
|
typedef struct Dict Dict;
|
||||||
|
struct Dict {
|
||||||
u64 bins_count;
|
u64 bins_count;
|
||||||
struct dict_bin *bins;
|
DictBin *bins;
|
||||||
struct dict_entry *first_free;
|
DictEntry *first_free;
|
||||||
struct dict_entry *first;
|
DictEntry *first;
|
||||||
struct dict_entry *last;
|
DictEntry *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE struct dict *dict_init(struct arena *arena, u64 bins_count)
|
INLINE Dict *dict_init(Arena *arena, u64 bins_count)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct dict *dict = arena_push(arena, struct dict);
|
Dict *dict = arena_push(arena, Dict);
|
||||||
dict->bins_count = max_u64(bins_count, 1); /* Ensure at least 1 bin */
|
dict->bins_count = max_u64(bins_count, 1); /* Ensure at least 1 bin */
|
||||||
dict->bins = arena_push_array(arena, struct dict_bin, dict->bins_count);
|
dict->bins = arena_push_array(arena, DictBin, dict->bins_count);
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void dict_reset(struct dict *dict)
|
INLINE void dict_reset(Dict *dict)
|
||||||
{
|
{
|
||||||
MEMZERO(dict->bins, sizeof(*dict->bins) * dict->bins_count);
|
MEMZERO(dict->bins, sizeof(*dict->bins) * dict->bins_count);
|
||||||
if (dict->first) {
|
if (dict->first) {
|
||||||
@ -134,12 +137,12 @@ INLINE void dict_reset(struct dict *dict)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct dict_entry *dict_ensure_entry(struct arena *arena, struct dict *dict, u64 hash)
|
INLINE DictEntry *dict_ensure_entry(Arena *arena, Dict *dict, u64 hash)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct dict_bin *bin = &dict->bins[hash % dict->bins_count];
|
DictBin *bin = &dict->bins[hash % dict->bins_count];
|
||||||
|
|
||||||
struct dict_entry *entry = bin->first;
|
DictEntry *entry = bin->first;
|
||||||
while (entry) {
|
while (entry) {
|
||||||
if (hash == entry->hash) {
|
if (hash == entry->hash) {
|
||||||
/* Existing match found */
|
/* Existing match found */
|
||||||
@ -154,7 +157,7 @@ INLINE struct dict_entry *dict_ensure_entry(struct arena *arena, struct dict *di
|
|||||||
entry = dict->first_free;
|
entry = dict->first_free;
|
||||||
dict->first_free = entry->next;
|
dict->first_free = entry->next;
|
||||||
} else {
|
} else {
|
||||||
entry = arena_push_no_zero(arena, struct dict_entry);
|
entry = arena_push_no_zero(arena, DictEntry);
|
||||||
}
|
}
|
||||||
MEMZERO_STRUCT(entry);
|
MEMZERO_STRUCT(entry);
|
||||||
entry->hash = hash;
|
entry->hash = hash;
|
||||||
@ -177,19 +180,19 @@ INLINE struct dict_entry *dict_ensure_entry(struct arena *arena, struct dict *di
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void dict_set(struct arena *arena, struct dict *dict, u64 hash, u64 value)
|
INLINE void dict_set(Arena *arena, Dict *dict, u64 hash, u64 value)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct dict_entry *entry = dict_ensure_entry(arena, dict, hash);
|
DictEntry *entry = dict_ensure_entry(arena, dict, hash);
|
||||||
entry->value = value;
|
entry->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE struct dict_entry *dict_get_entry(struct dict *dict, u64 hash)
|
INLINE DictEntry *dict_get_entry(Dict *dict, u64 hash)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct dict_entry *result = 0;
|
DictEntry *result = 0;
|
||||||
struct dict_bin *bin = &dict->bins[hash % dict->bins_count];
|
DictBin *bin = &dict->bins[hash % dict->bins_count];
|
||||||
for (struct dict_entry *entry = bin->first; entry; entry = entry->next_in_bin) {
|
for (DictEntry *entry = bin->first; entry; entry = entry->next_in_bin) {
|
||||||
if (hash == entry->hash) {
|
if (hash == entry->hash) {
|
||||||
/* Match found */
|
/* Match found */
|
||||||
result = entry;
|
result = entry;
|
||||||
@ -199,20 +202,20 @@ INLINE struct dict_entry *dict_get_entry(struct dict *dict, u64 hash)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE u64 dict_get(struct dict *dict, u64 hash)
|
INLINE u64 dict_get(Dict *dict, u64 hash)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct dict_entry *entry = dict_get_entry(dict, hash);
|
DictEntry *entry = dict_get_entry(dict, hash);
|
||||||
return entry ? entry->value : 0;
|
return entry ? entry->value : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INLINE void dict_remove_entry(struct dict *dict, struct dict_entry *entry)
|
INLINE void dict_remove_entry(Dict *dict, DictEntry *entry)
|
||||||
{
|
{
|
||||||
/* Remove from bin */
|
/* Remove from bin */
|
||||||
{
|
{
|
||||||
struct dict_bin *bin = &dict->bins[entry->hash % dict->bins_count];
|
DictBin *bin = &dict->bins[entry->hash % dict->bins_count];
|
||||||
struct dict_entry *prev_in_bin = entry->prev_in_bin;
|
DictEntry *prev_in_bin = entry->prev_in_bin;
|
||||||
struct dict_entry *next_in_bin = entry->next_in_bin;
|
DictEntry *next_in_bin = entry->next_in_bin;
|
||||||
if (prev_in_bin) {
|
if (prev_in_bin) {
|
||||||
prev_in_bin->next_in_bin = next_in_bin;
|
prev_in_bin->next_in_bin = next_in_bin;
|
||||||
} else {
|
} else {
|
||||||
@ -226,8 +229,8 @@ INLINE void dict_remove_entry(struct dict *dict, struct dict_entry *entry)
|
|||||||
}
|
}
|
||||||
/* Remove from list */
|
/* Remove from list */
|
||||||
{
|
{
|
||||||
struct dict_entry *prev = entry->prev;
|
DictEntry *prev = entry->prev;
|
||||||
struct dict_entry *next = entry->next;
|
DictEntry *next = entry->next;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
prev->next = next;
|
prev->next = next;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -26,9 +26,9 @@ INTERNAL void _dbgbreakable(void)
|
|||||||
#define DBGSTEP
|
#define DBGSTEP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
INTERNAL struct collider_support_point collider_get_support_point_internal(struct collider_shape *shape, struct xform xf, struct v2 dir, i32 ignore)
|
INTERNAL CLD_SupportPoint collider_get_support_point_internal(CLD_Shape *shape, Xform xf, V2 dir, i32 ignore)
|
||||||
{
|
{
|
||||||
struct v2 *points = shape->points;
|
V2 *points = shape->points;
|
||||||
u32 count = shape->count;
|
u32 count = shape->count;
|
||||||
f32 radius = shape->radius;
|
f32 radius = shape->radius;
|
||||||
|
|
||||||
@ -40,14 +40,14 @@ INTERNAL struct collider_support_point collider_get_support_point_internal(struc
|
|||||||
ignore = -1;
|
ignore = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 furthest = ZI;
|
V2 furthest = ZI;
|
||||||
u32 furthest_index = 0;
|
u32 furthest_index = 0;
|
||||||
f32 furthest_dot = -F32_INFINITY;
|
f32 furthest_dot = -F32_INFINITY;
|
||||||
for (u32 i = 0; i < count; ++i) {
|
for (u32 i = 0; i < count; ++i) {
|
||||||
if ((i32)i == ignore) {
|
if ((i32)i == ignore) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
struct v2 p = points[i];
|
V2 p = points[i];
|
||||||
f32 dot = v2_dot(dir, p);
|
f32 dot = v2_dot(dir, p);
|
||||||
if (dot > furthest_dot) {
|
if (dot > furthest_dot) {
|
||||||
furthest = p;
|
furthest = p;
|
||||||
@ -63,15 +63,15 @@ INTERNAL struct collider_support_point collider_get_support_point_internal(struc
|
|||||||
|
|
||||||
furthest = xform_mul_v2(xf, furthest);
|
furthest = xform_mul_v2(xf, furthest);
|
||||||
|
|
||||||
struct collider_support_point res;
|
CLD_SupportPoint res;
|
||||||
res.p = furthest;
|
res.p = furthest;
|
||||||
res.i = furthest_index;
|
res.i = furthest_index;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct collider_shape collider_from_quad(struct quad quad)
|
CLD_Shape collider_from_quad(Quad quad)
|
||||||
{
|
{
|
||||||
struct collider_shape res;
|
CLD_Shape res;
|
||||||
res.points[0] = quad.p0;
|
res.points[0] = quad.p0;
|
||||||
res.points[1] = quad.p1;
|
res.points[1] = quad.p1;
|
||||||
res.points[2] = quad.p2;
|
res.points[2] = quad.p2;
|
||||||
@ -81,14 +81,14 @@ struct collider_shape collider_from_quad(struct quad quad)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct collider_support_point collider_get_support_point(struct collider_shape *shape, struct xform xf, struct v2 dir)
|
CLD_SupportPoint collider_get_support_point(CLD_Shape *shape, Xform xf, V2 dir)
|
||||||
{
|
{
|
||||||
return collider_get_support_point_internal(shape, xf, dir, -1);
|
return collider_get_support_point_internal(shape, xf, dir, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct collider_menkowski_point get_menkowski_point(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1, struct v2 dir)
|
INTERNAL CLD_MenkowskiPoint get_menkowski_point(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, V2 dir)
|
||||||
{
|
{
|
||||||
struct collider_menkowski_point res;
|
CLD_MenkowskiPoint res;
|
||||||
res.s0 = collider_get_support_point(shape0, xf0, dir);
|
res.s0 = collider_get_support_point(shape0, xf0, dir);
|
||||||
res.s1 = collider_get_support_point(shape1, xf1, v2_neg(dir));
|
res.s1 = collider_get_support_point(shape1, xf1, v2_neg(dir));
|
||||||
res.p = v2_sub(res.s0.p, res.s1.p);
|
res.p = v2_sub(res.s0.p, res.s1.p);
|
||||||
@ -99,19 +99,19 @@ INTERNAL struct collider_menkowski_point get_menkowski_point(struct collider_sha
|
|||||||
* AABB
|
* AABB
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct aabb collider_aabb_from_collider(struct collider_shape *shape, struct xform xf)
|
Aabb collider_aabb_from_collider(CLD_Shape *shape, Xform xf)
|
||||||
{
|
{
|
||||||
struct aabb res;
|
Aabb res;
|
||||||
res.p0.x = collider_get_support_point(shape, xf, V2(-1, 0)).p.x - COLLISION_TOLERANCE;
|
res.p0.x = collider_get_support_point(shape, xf, V2FromXY(-1, 0)).p.x - COLLISION_TOLERANCE;
|
||||||
res.p0.y = collider_get_support_point(shape, xf, V2(0, -1)).p.y - COLLISION_TOLERANCE;
|
res.p0.y = collider_get_support_point(shape, xf, V2FromXY(0, -1)).p.y - COLLISION_TOLERANCE;
|
||||||
res.p1.x = collider_get_support_point(shape, xf, V2(1, 0)).p.x + COLLISION_TOLERANCE;
|
res.p1.x = collider_get_support_point(shape, xf, V2FromXY(1, 0)).p.x + COLLISION_TOLERANCE;
|
||||||
res.p1.y = collider_get_support_point(shape, xf, V2(0, 1)).p.y + COLLISION_TOLERANCE;
|
res.p1.y = collider_get_support_point(shape, xf, V2FromXY(0, 1)).p.y + COLLISION_TOLERANCE;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct aabb collider_aabb_from_combined_aabb(struct aabb b0, struct aabb b1)
|
Aabb collider_aabb_from_combined_aabb(Aabb b0, Aabb b1)
|
||||||
{
|
{
|
||||||
struct aabb res;
|
Aabb res;
|
||||||
res.p0.x = min_f32(min_f32(b0.p0.x, b0.p1.x), min_f32(b1.p0.x, b1.p1.x));
|
res.p0.x = min_f32(min_f32(b0.p0.x, b0.p1.x), min_f32(b1.p0.x, b1.p1.x));
|
||||||
res.p0.y = min_f32(min_f32(b0.p0.y, b0.p1.y), min_f32(b1.p0.y, b1.p1.y));
|
res.p0.y = min_f32(min_f32(b0.p0.y, b0.p1.y), min_f32(b1.p0.y, b1.p1.y));
|
||||||
res.p1.x = max_f32(max_f32(b0.p0.x, b0.p1.x), max_f32(b1.p0.x, b1.p1.x));
|
res.p1.x = max_f32(max_f32(b0.p0.x, b0.p1.x), max_f32(b1.p0.x, b1.p1.x));
|
||||||
@ -119,7 +119,7 @@ struct aabb collider_aabb_from_combined_aabb(struct aabb b0, struct aabb b1)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 collider_test_aabb(struct aabb box0, struct aabb box1)
|
b32 collider_test_aabb(Aabb box0, Aabb box1)
|
||||||
{
|
{
|
||||||
f32 b0_x0 = box0.p0.x;
|
f32 b0_x0 = box0.p0.x;
|
||||||
f32 b0_x1 = box0.p1.x;
|
f32 b0_x1 = box0.p1.x;
|
||||||
@ -142,8 +142,8 @@ b32 collider_test_aabb(struct aabb box0, struct aabb box1)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gjk_result {
|
struct gjk_result {
|
||||||
struct collider_menkowski_simplex simplex;
|
CLD_MenkowskiSimplex simplex;
|
||||||
struct v2 final_dir;
|
V2 final_dir;
|
||||||
|
|
||||||
/* If 1, simplex represents triangle inside of menkowski difference
|
/* If 1, simplex represents triangle inside of menkowski difference
|
||||||
* encapsulating the origin. If 0, simplex represents the closest
|
* encapsulating the origin. If 0, simplex represents the closest
|
||||||
@ -156,24 +156,24 @@ struct gjk_result {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
INTERNAL struct gjk_result gjk_get_simplex(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1, f32 min_unique_pt_dist_sq, u32 dbg_step)
|
INTERNAL struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, f32 min_unique_pt_dist_sq, u32 dbg_step)
|
||||||
#else
|
#else
|
||||||
INTERNAL struct gjk_result gjk_get_simplex(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1, f32 min_unique_pt_dist_sq)
|
INTERNAL struct gjk_result gjk_get_simplex(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, f32 min_unique_pt_dist_sq)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
b32 overlapping = 0;
|
b32 overlapping = 0;
|
||||||
struct collider_menkowski_simplex s = ZI;
|
CLD_MenkowskiSimplex s = ZI;
|
||||||
struct v2 dir = ZI;
|
V2 dir = ZI;
|
||||||
struct collider_menkowski_point m = ZI;
|
CLD_MenkowskiPoint m = ZI;
|
||||||
|
|
||||||
/* First point is support point in shape's general directions to eachother */
|
/* First point is support point in shape's general directions to eachother */
|
||||||
dir = v2_sub(xf1.og, xf0.og);
|
dir = v2_sub(xf1.og, xf0.og);
|
||||||
if (v2_is_zero(dir)) dir = V2(1, 0);
|
if (v2_is_zero(dir)) dir = V2FromXY(1, 0);
|
||||||
s.a = get_menkowski_point(shape0, shape1, xf0, xf1, dir);
|
s.a = get_menkowski_point(shape0, shape1, xf0, xf1, dir);
|
||||||
s.len = 1;
|
s.len = 1;
|
||||||
|
|
||||||
struct v2 removed_a = ZI;
|
V2 removed_a = ZI;
|
||||||
struct v2 removed_b = ZI;
|
V2 removed_b = ZI;
|
||||||
u32 num_removed = 0;
|
u32 num_removed = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (s.len == 1) {
|
if (s.len == 1) {
|
||||||
@ -226,13 +226,13 @@ INTERNAL struct gjk_result gjk_get_simplex(struct collider_shape *shape0, struct
|
|||||||
|
|
||||||
/* Determine region of the simplex in which the origin lies */
|
/* Determine region of the simplex in which the origin lies */
|
||||||
DBGSTEP;
|
DBGSTEP;
|
||||||
struct v2 vab = v2_sub(s.b.p, s.a.p);
|
V2 vab = v2_sub(s.b.p, s.a.p);
|
||||||
struct v2 vac = v2_sub(s.c.p, s.a.p);
|
V2 vac = v2_sub(s.c.p, s.a.p);
|
||||||
struct v2 vbc = v2_sub(s.c.p, s.b.p);
|
V2 vbc = v2_sub(s.c.p, s.b.p);
|
||||||
|
|
||||||
struct v2 rab_dir = v2_perp_towards_dir(vab, v2_neg(vac));
|
V2 rab_dir = v2_perp_towards_dir(vab, v2_neg(vac));
|
||||||
struct v2 rac_dir = v2_perp_towards_dir(vac, v2_neg(vab));
|
V2 rac_dir = v2_perp_towards_dir(vac, v2_neg(vab));
|
||||||
struct v2 rbc_dir = v2_perp_towards_dir(vbc, vab);
|
V2 rbc_dir = v2_perp_towards_dir(vbc, vab);
|
||||||
|
|
||||||
f32 rab_dot = v2_dot(rab_dir, v2_neg(s.a.p));
|
f32 rab_dot = v2_dot(rab_dir, v2_neg(s.a.p));
|
||||||
f32 rac_dot = v2_dot(rac_dir, v2_neg(s.a.p));
|
f32 rac_dot = v2_dot(rac_dir, v2_neg(s.a.p));
|
||||||
@ -313,34 +313,34 @@ INTERNAL struct gjk_result gjk_get_simplex(struct collider_shape *shape0, struct
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct epa_result {
|
struct epa_result {
|
||||||
struct v2 normal;
|
V2 normal;
|
||||||
struct collider_menkowski_feature closest_feature; /* Represents closest feature (edge or point) to origin on menkowski difference */
|
CLD_MenkowskiFeature closest_feature; /* Represents closest feature (edge or point) to origin on menkowski difference */
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
struct collider_prototype prototype;
|
CLD_Prototype prototype;
|
||||||
u32 dbg_step;
|
u32 dbg_step;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
INTERNAL struct epa_result epa_get_normal_from_gjk(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1, struct gjk_result gjk_res, f32 min_unique_pt_dist_sq, u32 max_iterations, u32 dbg_step)
|
INTERNAL struct epa_result epa_get_normal_from_gjk(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, struct gjk_result gjk_res, f32 min_unique_pt_dist_sq, u32 max_iterations, u32 dbg_step)
|
||||||
#else
|
#else
|
||||||
INTERNAL struct epa_result epa_get_normal_from_gjk(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1, struct gjk_result gjk_res, f32 min_unique_pt_dist_sq, u32 max_iterations)
|
INTERNAL struct epa_result epa_get_normal_from_gjk(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, struct gjk_result gjk_res, f32 min_unique_pt_dist_sq, u32 max_iterations)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct collider_menkowski_feature closest_feature = ZI;
|
CLD_MenkowskiFeature closest_feature = ZI;
|
||||||
struct v2 normal = ZI;
|
V2 normal = ZI;
|
||||||
|
|
||||||
struct collider_menkowski_point *proto = 0;
|
CLD_MenkowskiPoint *proto = 0;
|
||||||
u32 proto_count = 0;
|
u32 proto_count = 0;
|
||||||
if (gjk_res.overlapping) {
|
if (gjk_res.overlapping) {
|
||||||
struct collider_menkowski_simplex s = gjk_res.simplex;
|
CLD_MenkowskiSimplex s = gjk_res.simplex;
|
||||||
proto = arena_push_dry(scratch.arena, struct collider_menkowski_point);
|
proto = arena_push_dry(scratch.arena, CLD_MenkowskiPoint);
|
||||||
{
|
{
|
||||||
ASSERT(s.len == 3);
|
ASSERT(s.len == 3);
|
||||||
struct collider_menkowski_point *tmp = arena_push_array_no_zero(scratch.arena, struct collider_menkowski_point, 3);
|
CLD_MenkowskiPoint *tmp = arena_push_array_no_zero(scratch.arena, CLD_MenkowskiPoint, 3);
|
||||||
tmp[0] = s.a;
|
tmp[0] = s.a;
|
||||||
tmp[1] = s.b;
|
tmp[1] = s.b;
|
||||||
tmp[2] = s.c;
|
tmp[2] = s.c;
|
||||||
@ -356,20 +356,20 @@ INTERNAL struct epa_result epa_get_normal_from_gjk(struct collider_shape *shape0
|
|||||||
/* Find dir from origin to closest edge */
|
/* Find dir from origin to closest edge */
|
||||||
/* FIXME: Winding order of ps & pe index */
|
/* FIXME: Winding order of ps & pe index */
|
||||||
f32 closest_len_sq = F32_INFINITY;
|
f32 closest_len_sq = F32_INFINITY;
|
||||||
struct collider_menkowski_point closest_a = ZI;
|
CLD_MenkowskiPoint closest_a = ZI;
|
||||||
struct collider_menkowski_point closest_b = ZI;
|
CLD_MenkowskiPoint closest_b = ZI;
|
||||||
u32 closest_b_index = 0;
|
u32 closest_b_index = 0;
|
||||||
for (u32 i = 0; i < proto_count; ++i) {
|
for (u32 i = 0; i < proto_count; ++i) {
|
||||||
u32 a_index = i;
|
u32 a_index = i;
|
||||||
u32 b_index = (i < proto_count - 1) ? (i + 1) : 0;
|
u32 b_index = (i < proto_count - 1) ? (i + 1) : 0;
|
||||||
struct collider_menkowski_point a = proto[a_index];
|
CLD_MenkowskiPoint a = proto[a_index];
|
||||||
struct collider_menkowski_point b = proto[b_index];
|
CLD_MenkowskiPoint b = proto[b_index];
|
||||||
|
|
||||||
struct v2 vab = v2_sub(b.p, a.p);
|
V2 vab = v2_sub(b.p, a.p);
|
||||||
struct v2 vao = v2_neg(a.p);
|
V2 vao = v2_neg(a.p);
|
||||||
|
|
||||||
f32 proj_ratio = clamp_f32(v2_dot(vao, vab) / v2_len_sq(vab), 0, 1);
|
f32 proj_ratio = clamp_f32(v2_dot(vao, vab) / v2_len_sq(vab), 0, 1);
|
||||||
struct v2 proj = v2_add(a.p, v2_mul(vab, proj_ratio));
|
V2 proj = v2_add(a.p, v2_mul(vab, proj_ratio));
|
||||||
|
|
||||||
f32 proj_len_sq = v2_len_sq(proj);
|
f32 proj_len_sq = v2_len_sq(proj);
|
||||||
if (proj_len_sq < closest_len_sq - min_unique_pt_dist_sq) {
|
if (proj_len_sq < closest_len_sq - min_unique_pt_dist_sq) {
|
||||||
@ -379,11 +379,11 @@ INTERNAL struct epa_result epa_get_normal_from_gjk(struct collider_shape *shape0
|
|||||||
closest_len_sq = proj_len_sq;
|
closest_len_sq = proj_len_sq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct v2 vab = v2_sub(closest_b.p, closest_a.p);
|
V2 vab = v2_sub(closest_b.p, closest_a.p);
|
||||||
|
|
||||||
/* Find new point in dir */
|
/* Find new point in dir */
|
||||||
struct v2 dir = v2_mul(v2_perp(vab), winding);
|
V2 dir = v2_mul(v2_perp(vab), winding);
|
||||||
struct collider_menkowski_point m = get_menkowski_point(shape0, shape1, xf0, xf1, dir);
|
CLD_MenkowskiPoint m = get_menkowski_point(shape0, shape1, xf0, xf1, dir);
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
{
|
{
|
||||||
@ -406,8 +406,8 @@ INTERNAL struct epa_result epa_get_normal_from_gjk(struct collider_shape *shape0
|
|||||||
//const f32 validity_epsilon = 0.00000000001f; /* Arbitrary */
|
//const f32 validity_epsilon = 0.00000000001f; /* Arbitrary */
|
||||||
const f32 validity_epsilon = min_unique_pt_dist_sq; /* Arbitrary */
|
const f32 validity_epsilon = min_unique_pt_dist_sq; /* Arbitrary */
|
||||||
|
|
||||||
struct v2 vam = v2_sub(m.p, closest_a.p);
|
V2 vam = v2_sub(m.p, closest_a.p);
|
||||||
struct v2 vbm = v2_sub(closest_b.p, closest_a.p);
|
V2 vbm = v2_sub(closest_b.p, closest_a.p);
|
||||||
|
|
||||||
f32 dot = v2_dot(vab, vam) / v2_len_sq(vab);
|
f32 dot = v2_dot(vab, vam) / v2_len_sq(vab);
|
||||||
|
|
||||||
@ -430,7 +430,7 @@ INTERNAL struct epa_result epa_get_normal_from_gjk(struct collider_shape *shape0
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Expand prototype */
|
/* Expand prototype */
|
||||||
arena_push_no_zero(scratch.arena, struct collider_menkowski_point);
|
arena_push_no_zero(scratch.arena, CLD_MenkowskiPoint);
|
||||||
++proto_count;
|
++proto_count;
|
||||||
|
|
||||||
/* Shift points in prototype to make room */
|
/* Shift points in prototype to make room */
|
||||||
@ -477,16 +477,16 @@ INTERNAL struct epa_result epa_get_normal_from_gjk(struct collider_shape *shape0
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct clip_line_to_line_result {
|
struct clip_line_to_line_result {
|
||||||
struct v2 a0_clipped, b0_clipped;
|
V2 a0_clipped, b0_clipped;
|
||||||
struct v2 a1_clipped, b1_clipped;
|
V2 a1_clipped, b1_clipped;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL struct clip_line_to_line_result clip_line_to_line(struct v2 a0, struct v2 b0, struct v2 a1, struct v2 b1, struct v2 normal)
|
INTERNAL struct clip_line_to_line_result clip_line_to_line(V2 a0, V2 b0, V2 a1, V2 b1, V2 normal)
|
||||||
{
|
{
|
||||||
struct v2 vab0 = v2_sub(b0, a0);
|
V2 vab0 = v2_sub(b0, a0);
|
||||||
struct v2 vab1 = v2_sub(b1, a1);
|
V2 vab1 = v2_sub(b1, a1);
|
||||||
struct v2 va0a1 = v2_sub(a1, a0);
|
V2 va0a1 = v2_sub(a1, a0);
|
||||||
struct v2 vb0b1 = v2_sub(b1, b0);
|
V2 vb0b1 = v2_sub(b1, b0);
|
||||||
f32 vab0_w = v2_wedge(vab0, normal);
|
f32 vab0_w = v2_wedge(vab0, normal);
|
||||||
f32 vab1_w = v2_wedge(vab1, normal);
|
f32 vab1_w = v2_wedge(vab1, normal);
|
||||||
f32 va0a1_w = v2_wedge(va0a1, normal);
|
f32 va0a1_w = v2_wedge(va0a1, normal);
|
||||||
@ -516,10 +516,10 @@ INTERNAL struct clip_line_to_line_result clip_line_to_line(struct v2 a0, struct
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct v2 clip_point_to_line(struct v2 a, struct v2 b, struct v2 p, struct v2 normal)
|
INTERNAL V2 clip_point_to_line(V2 a, V2 b, V2 p, V2 normal)
|
||||||
{
|
{
|
||||||
struct v2 vab = v2_sub(b, a);
|
V2 vab = v2_sub(b, a);
|
||||||
struct v2 vap = v2_sub(p, a);
|
V2 vap = v2_sub(p, a);
|
||||||
|
|
||||||
f32 vab_w = v2_wedge(vab, normal);
|
f32 vab_w = v2_wedge(vab, normal);
|
||||||
f32 vap_w = v2_wedge(vap, normal);
|
f32 vap_w = v2_wedge(vap, normal);
|
||||||
@ -530,7 +530,7 @@ INTERNAL struct v2 clip_point_to_line(struct v2 a, struct v2 b, struct v2 p, str
|
|||||||
t = clamp_f32(vap_w * w, 0, 1);
|
t = clamp_f32(vap_w * w, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 res = v2_add(a, v2_mul(vab, t));
|
V2 res = v2_add(a, v2_mul(vab, t));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,18 +538,18 @@ INTERNAL struct v2 clip_point_to_line(struct v2 a, struct v2 b, struct v2 p, str
|
|||||||
* Collision points
|
* Collision points
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct collider_collision_points_result collider_collision_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1)
|
CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1)
|
||||||
{
|
{
|
||||||
struct collider_collision_points_result res = ZI;
|
CLD_CollisionResult res = ZI;
|
||||||
|
|
||||||
const f32 tolerance = COLLISION_TOLERANCE;
|
const f32 tolerance = COLLISION_TOLERANCE;
|
||||||
const f32 min_unique_pt_dist_sq = MIN_UNIQUE_PT_DIST_SQ;
|
const f32 min_unique_pt_dist_sq = MIN_UNIQUE_PT_DIST_SQ;
|
||||||
const u32 max_epa_iterations = MAX_EPA_ITERATIONS;
|
const u32 max_epa_iterations = MAX_EPA_ITERATIONS;
|
||||||
|
|
||||||
struct collider_collision_point points[2] = ZI;
|
CLD_CollisionPoint points[2] = ZI;
|
||||||
u32 num_points = 0;
|
u32 num_points = 0;
|
||||||
b32 colliding = 0;
|
b32 colliding = 0;
|
||||||
struct v2 normal = ZI;
|
V2 normal = ZI;
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
u32 dbg_step = 0;
|
u32 dbg_step = 0;
|
||||||
@ -581,20 +581,20 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
if (gjk_res.overlapping) {
|
if (gjk_res.overlapping) {
|
||||||
colliding = 1;
|
colliding = 1;
|
||||||
} else {
|
} else {
|
||||||
struct collider_menkowski_feature f = epa_res.closest_feature;
|
CLD_MenkowskiFeature f = epa_res.closest_feature;
|
||||||
/* Shapes not overlapping, determine if distance between shapes within tolerance */
|
/* Shapes not overlapping, determine if distance between shapes within tolerance */
|
||||||
if (f.len == 1) {
|
if (f.len == 1) {
|
||||||
struct v2 p = v2_neg(f.a.p);
|
V2 p = v2_neg(f.a.p);
|
||||||
if (v2_len_sq(p) <= (tolerance * tolerance)) {
|
if (v2_len_sq(p) <= (tolerance * tolerance)) {
|
||||||
colliding = 1;
|
colliding = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Project origin to determine if distance is within tolerance. */
|
/* Project origin to determine if distance is within tolerance. */
|
||||||
ASSERT(f.len == 2);
|
ASSERT(f.len == 2);
|
||||||
struct v2 vab = v2_sub(f.b.p, f.a.p);
|
V2 vab = v2_sub(f.b.p, f.a.p);
|
||||||
struct v2 vao = v2_neg(f.a.p);
|
V2 vao = v2_neg(f.a.p);
|
||||||
f32 ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
|
f32 ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
|
||||||
struct v2 p = v2_add(f.a.p, v2_mul(vab, ratio));
|
V2 p = v2_add(f.a.p, v2_mul(vab, ratio));
|
||||||
if (v2_len_sq(p) <= (tolerance * tolerance)) {
|
if (v2_len_sq(p) <= (tolerance * tolerance)) {
|
||||||
colliding = 1;
|
colliding = 1;
|
||||||
}
|
}
|
||||||
@ -606,16 +606,16 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
/* Max vertices must be < 16 to fit in 4 bit ids */
|
/* Max vertices must be < 16 to fit in 4 bit ids */
|
||||||
STATIC_ASSERT(countof(shape0->points) <= 16);
|
STATIC_ASSERT(countof(shape0->points) <= 16);
|
||||||
|
|
||||||
struct collider_menkowski_feature f = epa_res.closest_feature;
|
CLD_MenkowskiFeature f = epa_res.closest_feature;
|
||||||
|
|
||||||
{
|
{
|
||||||
b32 collapse0 = 0;
|
b32 collapse0 = 0;
|
||||||
b32 collapse1 = 0;
|
b32 collapse1 = 0;
|
||||||
|
|
||||||
struct collider_support_point a0 = f.a.s0;
|
CLD_SupportPoint a0 = f.a.s0;
|
||||||
struct collider_support_point a1 = f.a.s1;
|
CLD_SupportPoint a1 = f.a.s1;
|
||||||
struct collider_support_point b0 = f.b.s0;
|
CLD_SupportPoint b0 = f.b.s0;
|
||||||
struct collider_support_point b1 = f.b.s1;
|
CLD_SupportPoint b1 = f.b.s1;
|
||||||
/* FIXME: Manually account for shapes w/ 1 & 2 points */
|
/* FIXME: Manually account for shapes w/ 1 & 2 points */
|
||||||
if (f.len == 2) {
|
if (f.len == 2) {
|
||||||
if (a0.i == b0.i) {
|
if (a0.i == b0.i) {
|
||||||
@ -641,20 +641,20 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
b1 = a1;
|
b1 = a1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 vab0 = v2_sub(b0.p, a0.p);
|
V2 vab0 = v2_sub(b0.p, a0.p);
|
||||||
struct v2 vab1 = v2_sub(b1.p, a1.p);
|
V2 vab1 = v2_sub(b1.p, a1.p);
|
||||||
struct v2 vab0_norm = v2_norm(vab0);
|
V2 vab0_norm = v2_norm(vab0);
|
||||||
struct v2 vab1_norm = v2_norm(vab1);
|
V2 vab1_norm = v2_norm(vab1);
|
||||||
|
|
||||||
/* Swap points based on normal direction for consistent clipping */
|
/* Swap points based on normal direction for consistent clipping */
|
||||||
if (v2_wedge(normal, vab0) < 0) {
|
if (v2_wedge(normal, vab0) < 0) {
|
||||||
struct collider_support_point tmp = a0;
|
CLD_SupportPoint tmp = a0;
|
||||||
a0 = b0;
|
a0 = b0;
|
||||||
b0 = tmp;
|
b0 = tmp;
|
||||||
vab0 = v2_neg(vab0);
|
vab0 = v2_neg(vab0);
|
||||||
}
|
}
|
||||||
if (v2_wedge(normal, vab1) < 0) {
|
if (v2_wedge(normal, vab1) < 0) {
|
||||||
struct collider_support_point tmp = a1;
|
CLD_SupportPoint tmp = a1;
|
||||||
a1 = b1;
|
a1 = b1;
|
||||||
b1 = tmp;
|
b1 = tmp;
|
||||||
vab1 = v2_neg(vab1);
|
vab1 = v2_neg(vab1);
|
||||||
@ -685,27 +685,27 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
|
|
||||||
f32 a_sep = F32_INFINITY;
|
f32 a_sep = F32_INFINITY;
|
||||||
f32 b_sep = F32_INFINITY;
|
f32 b_sep = F32_INFINITY;
|
||||||
struct v2 a_midpoint = ZI;
|
V2 a_midpoint = ZI;
|
||||||
struct v2 b_midpoint = ZI;
|
V2 b_midpoint = ZI;
|
||||||
b32 ignore_a = 1;
|
b32 ignore_a = 1;
|
||||||
b32 ignore_b = 1;
|
b32 ignore_b = 1;
|
||||||
if (!collapse0 && !collapse1) {
|
if (!collapse0 && !collapse1) {
|
||||||
/* Clip line to line */
|
/* Clip line to line */
|
||||||
struct clip_line_to_line_result clip_res = clip_line_to_line(a0.p, b0.p, a1.p, b1.p, normal);
|
struct clip_line_to_line_result clip_res = clip_line_to_line(a0.p, b0.p, a1.p, b1.p, normal);
|
||||||
struct v2 a0_clipped = clip_res.a0_clipped;
|
V2 a0_clipped = clip_res.a0_clipped;
|
||||||
struct v2 a1_clipped = clip_res.a1_clipped;
|
V2 a1_clipped = clip_res.a1_clipped;
|
||||||
struct v2 b0_clipped = clip_res.b0_clipped;
|
V2 b0_clipped = clip_res.b0_clipped;
|
||||||
struct v2 b1_clipped = clip_res.b1_clipped;
|
V2 b1_clipped = clip_res.b1_clipped;
|
||||||
/* Calc midpoint between clipped a & b */
|
/* Calc midpoint between clipped a & b */
|
||||||
struct v2 va0a1_clipped = v2_sub(a1_clipped, a0_clipped);
|
V2 va0a1_clipped = v2_sub(a1_clipped, a0_clipped);
|
||||||
struct v2 vb0b1_clipped = v2_sub(b1_clipped, b0_clipped);
|
V2 vb0b1_clipped = v2_sub(b1_clipped, b0_clipped);
|
||||||
a_sep = v2_dot(va0a1_clipped, normal);
|
a_sep = v2_dot(va0a1_clipped, normal);
|
||||||
b_sep = v2_dot(vb0b1_clipped, normal);
|
b_sep = v2_dot(vb0b1_clipped, normal);
|
||||||
a_midpoint = v2_add(a0_clipped, v2_mul(va0a1_clipped, 0.5f));
|
a_midpoint = v2_add(a0_clipped, v2_mul(va0a1_clipped, 0.5f));
|
||||||
b_midpoint = v2_add(b0_clipped, v2_mul(vb0b1_clipped, 0.5f));
|
b_midpoint = v2_add(b0_clipped, v2_mul(vb0b1_clipped, 0.5f));
|
||||||
ignore_a = 0;
|
ignore_a = 0;
|
||||||
ignore_b = 0;
|
ignore_b = 0;
|
||||||
struct v2 vfin = v2_sub(b_midpoint, a_midpoint);
|
V2 vfin = v2_sub(b_midpoint, a_midpoint);
|
||||||
if (v2_len_sq(vfin) < (0.005 * 0.005)) {
|
if (v2_len_sq(vfin) < (0.005 * 0.005)) {
|
||||||
if (a_sep > b_sep) {
|
if (a_sep > b_sep) {
|
||||||
ignore_a = 1;
|
ignore_a = 1;
|
||||||
@ -718,8 +718,8 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
res.b0_clipped = b0_clipped;
|
res.b0_clipped = b0_clipped;
|
||||||
res.b1_clipped = b1_clipped;
|
res.b1_clipped = b1_clipped;
|
||||||
} else {
|
} else {
|
||||||
struct v2 p0 = a0.p;
|
V2 p0 = a0.p;
|
||||||
struct v2 p1 = a1.p;
|
V2 p1 = a1.p;
|
||||||
/* TODO: Choose ID based on closest clipped point */
|
/* TODO: Choose ID based on closest clipped point */
|
||||||
if (collapse1 && !collapse0) {
|
if (collapse1 && !collapse0) {
|
||||||
/* Project a1 onto vab0 */
|
/* Project a1 onto vab0 */
|
||||||
@ -730,7 +730,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
p1 = clip_point_to_line(a1.p, b1.p, a0.p, normal);
|
p1 = clip_point_to_line(a1.p, b1.p, a0.p, normal);
|
||||||
}
|
}
|
||||||
/* Calc midpoint */
|
/* Calc midpoint */
|
||||||
struct v2 vsep = v2_sub(p1, p0);
|
V2 vsep = v2_sub(p1, p0);
|
||||||
a_midpoint = v2_add(p0, v2_mul(vsep, 0.5f));
|
a_midpoint = v2_add(p0, v2_mul(vsep, 0.5f));
|
||||||
a_sep = v2_dot(normal, p1) - v2_dot(normal, p0);
|
a_sep = v2_dot(normal, p1) - v2_dot(normal, p0);
|
||||||
ignore_a = 0;
|
ignore_a = 0;
|
||||||
@ -742,13 +742,13 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
|
|
||||||
/* Insert points */
|
/* Insert points */
|
||||||
if (!ignore_a && a_sep < tolerance) {
|
if (!ignore_a && a_sep < tolerance) {
|
||||||
struct collider_collision_point *point = &points[num_points++];
|
CLD_CollisionPoint *point = &points[num_points++];
|
||||||
point->id = a0.i | (a1.i << 4);
|
point->id = a0.i | (a1.i << 4);
|
||||||
point->separation = a_sep;
|
point->separation = a_sep;
|
||||||
point->point = a_midpoint;
|
point->point = a_midpoint;
|
||||||
}
|
}
|
||||||
if (!ignore_b && b_sep < tolerance) {
|
if (!ignore_b && b_sep < tolerance) {
|
||||||
struct collider_collision_point *point = &points[num_points++];
|
CLD_CollisionPoint *point = &points[num_points++];
|
||||||
point->id = b0.i | (b1.i << 4);
|
point->id = b0.i | (b1.i << 4);
|
||||||
point->separation = b_sep;
|
point->separation = b_sep;
|
||||||
point->point = b_midpoint;
|
point->point = b_midpoint;
|
||||||
@ -781,16 +781,16 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
|
|
||||||
/* TODO: De-duplicate code between collider_closest_points & collider_collision_points */
|
/* TODO: De-duplicate code between collider_closest_points & collider_collision_points */
|
||||||
|
|
||||||
struct collider_closest_points_result collider_closest_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1)
|
CLD_ClosestResult collider_closest_points(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1)
|
||||||
{
|
{
|
||||||
struct collider_closest_points_result res = ZI;
|
CLD_ClosestResult res = ZI;
|
||||||
|
|
||||||
const f32 tolerance = COLLISION_TOLERANCE;
|
const f32 tolerance = COLLISION_TOLERANCE;
|
||||||
const f32 min_unique_pt_dist_sq = MIN_UNIQUE_PT_DIST_SQ;
|
const f32 min_unique_pt_dist_sq = MIN_UNIQUE_PT_DIST_SQ;
|
||||||
const u32 max_epa_iterations = MAX_EPA_ITERATIONS;
|
const u32 max_epa_iterations = MAX_EPA_ITERATIONS;
|
||||||
|
|
||||||
struct v2 p0 = ZI;
|
V2 p0 = ZI;
|
||||||
struct v2 p1 = ZI;
|
V2 p1 = ZI;
|
||||||
b32 colliding = 0;
|
b32 colliding = 0;
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
@ -823,7 +823,7 @@ struct collider_closest_points_result collider_closest_points(struct collider_sh
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
colliding = gjk_res.overlapping;
|
colliding = gjk_res.overlapping;
|
||||||
struct collider_menkowski_feature f = epa_res.closest_feature;
|
CLD_MenkowskiFeature f = epa_res.closest_feature;
|
||||||
if (f.len == 1) {
|
if (f.len == 1) {
|
||||||
p0 = f.a.s0.p;
|
p0 = f.a.s0.p;
|
||||||
p1 = f.a.s1.p;
|
p1 = f.a.s1.p;
|
||||||
@ -834,8 +834,8 @@ struct collider_closest_points_result collider_closest_points(struct collider_sh
|
|||||||
f32 ratio;
|
f32 ratio;
|
||||||
{
|
{
|
||||||
/* Determine ratio between edge a & b that projected origin lies */
|
/* Determine ratio between edge a & b that projected origin lies */
|
||||||
struct v2 vab = v2_sub(f.b.p, f.a.p);
|
V2 vab = v2_sub(f.b.p, f.a.p);
|
||||||
struct v2 vao = v2_neg(f.a.p);
|
V2 vao = v2_neg(f.a.p);
|
||||||
ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
|
ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
|
||||||
}
|
}
|
||||||
/* Shape 0 */
|
/* Shape 0 */
|
||||||
@ -869,9 +869,9 @@ struct collider_closest_points_result collider_closest_points(struct collider_sh
|
|||||||
|
|
||||||
/* Takes 2 shapes and their xforms at t=0 and t=1.
|
/* Takes 2 shapes and their xforms at t=0 and t=1.
|
||||||
* Returns time of impact in range [0, 1]. */
|
* Returns time of impact in range [0, 1]. */
|
||||||
f32 collider_time_of_impact(struct collider_shape *c0, struct collider_shape *c1,
|
f32 collider_time_of_impact(CLD_Shape *c0, CLD_Shape *c1,
|
||||||
struct xform xf0_t0, struct xform xf1_t0,
|
Xform xf0_t0, Xform xf1_t0,
|
||||||
struct xform xf0_t1, struct xform xf1_t1,
|
Xform xf0_t1, Xform xf1_t1,
|
||||||
f32 tolerance, u32 max_iterations)
|
f32 tolerance, u32 max_iterations)
|
||||||
{
|
{
|
||||||
f32 t0 = 0;
|
f32 t0 = 0;
|
||||||
@ -882,10 +882,10 @@ f32 collider_time_of_impact(struct collider_shape *c0, struct collider_shape *c1
|
|||||||
f32 t_sep = F32_INFINITY;
|
f32 t_sep = F32_INFINITY;
|
||||||
|
|
||||||
/* Find direction p0 -> p1 at t=0 */
|
/* Find direction p0 -> p1 at t=0 */
|
||||||
struct v2 dir;
|
V2 dir;
|
||||||
struct v2 dir_neg;
|
V2 dir_neg;
|
||||||
{
|
{
|
||||||
struct collider_closest_points_result closest_points_res = collider_closest_points(c0, c1, xf0_t0, xf1_t0);
|
CLD_ClosestResult closest_points_res = collider_closest_points(c0, c1, xf0_t0, xf1_t0);
|
||||||
if (closest_points_res.colliding) {
|
if (closest_points_res.colliding) {
|
||||||
/* Shapes are penetrating at t=0 */
|
/* Shapes are penetrating at t=0 */
|
||||||
return 0;
|
return 0;
|
||||||
@ -897,8 +897,8 @@ f32 collider_time_of_impact(struct collider_shape *c0, struct collider_shape *c1
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
struct v2 p0 = collider_get_support_point(c0, xf0_t1, dir).p;
|
V2 p0 = collider_get_support_point(c0, xf0_t1, dir).p;
|
||||||
struct v2 p1 = collider_get_support_point(c1, xf1_t1, dir_neg).p;
|
V2 p1 = collider_get_support_point(c1, xf1_t1, dir_neg).p;
|
||||||
t1_sep = v2_dot(dir, v2_sub(p1, p0));
|
t1_sep = v2_dot(dir, v2_sub(p1, p0));
|
||||||
if (t1_sep > 0) {
|
if (t1_sep > 0) {
|
||||||
/* Shapes are not penetrating at t=1 */
|
/* Shapes are not penetrating at t=1 */
|
||||||
@ -919,11 +919,11 @@ f32 collider_time_of_impact(struct collider_shape *c0, struct collider_shape *c1
|
|||||||
t = (-t1_sep / m) + t1;
|
t = (-t1_sep / m) + t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xform xf0 = xform_lerp(xf0_t0, xf0_t1, t);
|
Xform xf0 = xform_lerp(xf0_t0, xf0_t1, t);
|
||||||
struct xform xf1 = xform_lerp(xf1_t0, xf1_t1, t);
|
Xform xf1 = xform_lerp(xf1_t0, xf1_t1, t);
|
||||||
|
|
||||||
struct v2 p0 = collider_get_support_point(c0, xf0, dir).p;
|
V2 p0 = collider_get_support_point(c0, xf0, dir).p;
|
||||||
struct v2 p1 = collider_get_support_point(c1, xf1, dir_neg).p;
|
V2 p1 = collider_get_support_point(c1, xf1, dir_neg).p;
|
||||||
t_sep = v2_dot(dir, v2_sub(p1, p0));
|
t_sep = v2_dot(dir, v2_sub(p1, p0));
|
||||||
|
|
||||||
/* Update bracket */
|
/* Update bracket */
|
||||||
@ -947,15 +947,15 @@ f32 collider_time_of_impact(struct collider_shape *c0, struct collider_shape *c1
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* TODO: Remove this (debugging) */
|
/* TODO: Remove this (debugging) */
|
||||||
struct v2_array menkowski(struct arena *arena, struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1, u32 detail)
|
V2Array menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail)
|
||||||
{
|
{
|
||||||
struct v2_array res = { .points = arena_push_dry(arena, struct v2) };
|
V2Array res = { .points = arena_push_dry(arena, V2) };
|
||||||
for (u64 i = 0; i < detail; ++i) {
|
for (u64 i = 0; i < detail; ++i) {
|
||||||
f32 angle = ((f32)i / detail) * (2 * PI);
|
f32 angle = ((f32)i / detail) * (2 * PI);
|
||||||
struct v2 dir = v2_from_angle(angle);
|
V2 dir = v2_from_angle(angle);
|
||||||
struct collider_menkowski_point m = get_menkowski_point(shape0, shape1, xf0, xf1, dir);
|
CLD_MenkowskiPoint m = get_menkowski_point(shape0, shape1, xf0, xf1, dir);
|
||||||
if (res.count == 0 || !v2_eq(m.p, res.points[res.count - 1])) {
|
if (res.count == 0 || !v2_eq(m.p, res.points[res.count - 1])) {
|
||||||
*arena_push_no_zero(arena, struct v2) = m.p;
|
*arena_push_no_zero(arena, V2) = m.p;
|
||||||
++res.count;
|
++res.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -963,19 +963,19 @@ struct v2_array menkowski(struct arena *arena, struct collider_shape *shape0, st
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Remove this (debugging) */
|
/* TODO: Remove this (debugging) */
|
||||||
struct v2_array cloud(struct arena *arena, struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1)
|
V2Array cloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1)
|
||||||
{
|
{
|
||||||
/* FIXME: Account for radius */
|
/* FIXME: Account for radius */
|
||||||
struct v2_array res = { .points = arena_push_dry(arena, struct v2) };
|
V2Array res = { .points = arena_push_dry(arena, V2) };
|
||||||
struct v2 *points0 = shape0->points;
|
V2 *points0 = shape0->points;
|
||||||
struct v2 *points1 = shape1->points;
|
V2 *points1 = shape1->points;
|
||||||
u32 count0 = shape0->count;
|
u32 count0 = shape0->count;
|
||||||
u32 count1 = shape1->count;
|
u32 count1 = shape1->count;
|
||||||
for (u64 i = 0; i < count0; ++i) {
|
for (u64 i = 0; i < count0; ++i) {
|
||||||
struct v2 p0 = xform_mul_v2(xf0, points0[i]);
|
V2 p0 = xform_mul_v2(xf0, points0[i]);
|
||||||
for (u64 j = 0; j < count1; ++j) {
|
for (u64 j = 0; j < count1; ++j) {
|
||||||
struct v2 p1 = xform_mul_v2(xf1, points1[j]);
|
V2 p1 = xform_mul_v2(xf1, points1[j]);
|
||||||
*arena_push_no_zero(arena, struct v2) = v2_sub(p0, p1);
|
*arena_push_no_zero(arena, V2) = v2_sub(p0, p1);
|
||||||
++res.count;
|
++res.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -987,16 +987,16 @@ struct v2_array cloud(struct arena *arena, struct collider_shape *shape0, struct
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
b32 collider_collision_boolean(struct collider_shape *shape0, struct collider_shape *shape1)
|
b32 collider_collision_boolean(CLD_Shape *shape0, CLD_Shape *shape1)
|
||||||
{
|
{
|
||||||
struct { struct v2 a, b, c; } s = ZI;
|
struct { V2 a, b, c; } s = ZI;
|
||||||
|
|
||||||
/* FIXME: Infinite loop when shapes exactly overlap same space? */
|
/* FIXME: Infinite loop when shapes exactly overlap same space? */
|
||||||
struct v2 dir, p;
|
V2 dir, p;
|
||||||
|
|
||||||
/* First point is support point in shape's general directions to eachother */
|
/* First point is support point in shape's general directions to eachother */
|
||||||
dir = v2_sub(starting_point(shape1), starting_point(shape0));
|
dir = v2_sub(starting_point(shape1), starting_point(shape0));
|
||||||
if (v2_is_zero(dir)) dir = V2(1, 0);
|
if (v2_is_zero(dir)) dir = V2FromXY(1, 0);
|
||||||
s.a = get_menkowski_point(shape0, shape1, dir);
|
s.a = get_menkowski_point(shape0, shape1, dir);
|
||||||
|
|
||||||
/* Second point is support point towards origin */
|
/* Second point is support point towards origin */
|
||||||
@ -1018,9 +1018,9 @@ b32 collider_collision_boolean(struct collider_shape *shape0, struct collider_sh
|
|||||||
s.b = s.a;
|
s.b = s.a;
|
||||||
s.a = p;
|
s.a = p;
|
||||||
|
|
||||||
struct v2 vab = v2_sub(s.b, s.a);
|
V2 vab = v2_sub(s.b, s.a);
|
||||||
struct v2 vac = v2_sub(s.c, s.a);
|
V2 vac = v2_sub(s.c, s.a);
|
||||||
struct v2 a_to_origin = v2_neg(s.a);
|
V2 a_to_origin = v2_neg(s.a);
|
||||||
|
|
||||||
dir = v2_perp_towards_dir(vab, v2_neg(vac)); /* Normal of ab pointing away from c */
|
dir = v2_perp_towards_dir(vab, v2_neg(vac)); /* Normal of ab pointing away from c */
|
||||||
if (v2_dot(dir, a_to_origin) >= 0) {
|
if (v2_dot(dir, a_to_origin) >= 0) {
|
||||||
|
|||||||
@ -1,77 +1,90 @@
|
|||||||
struct collider_shape {
|
typedef struct CLD_Shape CLD_Shape;
|
||||||
struct v2 points[8];
|
struct CLD_Shape {
|
||||||
|
V2 points[8];
|
||||||
u32 count;
|
u32 count;
|
||||||
f32 radius;
|
f32 radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collider_support_point {
|
typedef struct CLD_SupportPoint CLD_SupportPoint;
|
||||||
struct v2 p;
|
struct CLD_SupportPoint {
|
||||||
|
V2 p;
|
||||||
u32 i; /* Index of original point in shape */
|
u32 i; /* Index of original point in shape */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collider_menkowski_point {
|
typedef struct CLD_MenkowskiPoint CLD_MenkowskiPoint;
|
||||||
struct v2 p; /* Menkowski difference point */
|
struct CLD_MenkowskiPoint {
|
||||||
struct collider_support_point s0; /* Support point of first shape in dir */
|
V2 p; /* Menkowski difference point */
|
||||||
struct collider_support_point s1; /* Support point of second shape in -dir */
|
CLD_SupportPoint s0; /* Support point of first shape in dir */
|
||||||
|
CLD_SupportPoint s1; /* Support point of second shape in -dir */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collider_menkowski_simplex {
|
typedef struct CLD_MenkowskiSimplex CLD_MenkowskiSimplex;
|
||||||
|
struct CLD_MenkowskiSimplex {
|
||||||
u32 len;
|
u32 len;
|
||||||
struct collider_menkowski_point a, b, c;
|
CLD_MenkowskiPoint a, b, c;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collider_menkowski_feature {
|
typedef struct CLD_MenkowskiFeature CLD_MenkowskiFeature;
|
||||||
|
struct CLD_MenkowskiFeature {
|
||||||
u32 len;
|
u32 len;
|
||||||
struct collider_menkowski_point a, b;
|
CLD_MenkowskiPoint a, b;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collider_collision_point {
|
typedef struct CLD_CollisionPoint CLD_CollisionPoint;
|
||||||
struct v2 point;
|
struct CLD_CollisionPoint {
|
||||||
|
V2 point;
|
||||||
f32 separation;
|
f32 separation;
|
||||||
u32 id; /* Based on polygon edge-to-edge */
|
u32 id; /* Based on polygon edge-to-edge */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collider_prototype { struct v2 points[64]; u32 len; };
|
typedef struct CLD_Prototype CLD_Prototype;
|
||||||
struct collider_collision_points_result {
|
struct CLD_Prototype {
|
||||||
struct v2 normal;
|
V2 points[64];
|
||||||
struct collider_collision_point points[2];
|
u32 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct CLD_CollisionResult CLD_CollisionResult;
|
||||||
|
struct CLD_CollisionResult {
|
||||||
|
V2 normal;
|
||||||
|
CLD_CollisionPoint points[2];
|
||||||
u32 num_points;
|
u32 num_points;
|
||||||
|
|
||||||
/* For debugging */
|
/* For debugging */
|
||||||
b32 solved;
|
b32 solved;
|
||||||
struct collider_menkowski_simplex simplex;
|
CLD_MenkowskiSimplex simplex;
|
||||||
struct collider_prototype prototype;
|
CLD_Prototype prototype;
|
||||||
|
|
||||||
/* For debugging */
|
/* For debugging */
|
||||||
struct v2 a0, b0, a1, b1;
|
V2 a0, b0, a1, b1;
|
||||||
struct v2 a0_clipped, b0_clipped, a1_clipped, b1_clipped;
|
V2 a0_clipped, b0_clipped, a1_clipped, b1_clipped;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collider_closest_points_result {
|
typedef struct CLD_ClosestResult CLD_ClosestResult;
|
||||||
struct v2 p0, p1;
|
struct CLD_ClosestResult {
|
||||||
|
V2 p0, p1;
|
||||||
b32 colliding;
|
b32 colliding;
|
||||||
|
|
||||||
/* For debugging */
|
/* For debugging */
|
||||||
b32 solved;
|
b32 solved;
|
||||||
struct collider_menkowski_simplex simplex;
|
CLD_MenkowskiSimplex simplex;
|
||||||
struct collider_prototype prototype;
|
CLD_Prototype prototype;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collider_shape collider_from_quad(struct quad quad);
|
CLD_Shape collider_from_quad(Quad quad);
|
||||||
|
|
||||||
struct collider_support_point collider_get_support_point(struct collider_shape *shape, struct xform xf, struct v2 dir);
|
CLD_SupportPoint collider_get_support_point(CLD_Shape *shape, Xform xf, V2 dir);
|
||||||
|
|
||||||
struct aabb collider_aabb_from_collider(struct collider_shape *shape, struct xform xf);
|
Aabb collider_aabb_from_collider(CLD_Shape *shape, Xform xf);
|
||||||
|
|
||||||
struct aabb collider_aabb_from_combined_aabb(struct aabb b0, struct aabb b1);
|
Aabb collider_aabb_from_combined_aabb(Aabb b0, Aabb b1);
|
||||||
|
|
||||||
b32 collider_test_aabb(struct aabb box0, struct aabb box1);
|
b32 collider_test_aabb(Aabb box0, Aabb box1);
|
||||||
|
|
||||||
struct collider_collision_points_result collider_collision_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1);
|
CLD_CollisionResult collider_collision_points(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1);
|
||||||
|
|
||||||
struct collider_closest_points_result collider_closest_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1);
|
CLD_ClosestResult collider_closest_points(CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1);
|
||||||
|
|
||||||
f32 collider_time_of_impact(struct collider_shape *c0, struct collider_shape *c1, struct xform xf0_t0, struct xform xf1_t0, struct xform xf0_t1, struct xform xf1_t1, f32 tolerance, u32 max_iterations);
|
f32 collider_time_of_impact(CLD_Shape *c0, CLD_Shape *c1, Xform xf0_t0, Xform xf1_t0, Xform xf0_t1, Xform xf1_t1, f32 tolerance, u32 max_iterations);
|
||||||
|
|
||||||
struct v2_array menkowski(struct arena *arena, struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1, u32 detail);
|
V2Array menkowski(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1, u32 detail);
|
||||||
struct v2_array cloud(struct arena *arena, struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1);
|
V2Array cloud(Arena *arena, CLD_Shape *shape0, CLD_Shape *shape1, Xform xf0, Xform xf1);
|
||||||
|
|||||||
@ -1,27 +1,27 @@
|
|||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct gp_resource *solid_white_texture;
|
G_Resource *solid_white_texture;
|
||||||
} G = ZI, DEBUG_ALIAS(G, G_draw);
|
} G = ZI, DEBUG_ALIAS(G, G_draw);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct draw_startup_receipt draw_startup(struct font_startup_receipt *font_sr)
|
D_StartupReceipt draw_startup(F_StartupReceipt *font_sr)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
(UNUSED)font_sr;
|
(UNUSED)font_sr;
|
||||||
u32 pixel_white = 0xFFFFFFFF;
|
u32 pixel_white = 0xFFFFFFFF;
|
||||||
G.solid_white_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32(1, 1), &pixel_white);
|
G.solid_white_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2i32FromXY(1, 1), &pixel_white);
|
||||||
return (struct draw_startup_receipt) { 0 };
|
return (D_StartupReceipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Material
|
* Material
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_material(struct gp_render_sig *sig, struct draw_material_params params)
|
void draw_material(G_RenderSig *sig, D_MaterialParams params)
|
||||||
{
|
{
|
||||||
struct gp_render_cmd_desc cmd = ZI;
|
G_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
|
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
|
||||||
cmd.material.xf = params.xf;
|
cmd.material.xf = params.xf;
|
||||||
cmd.material.texture = params.texture;
|
cmd.material.texture = params.texture;
|
||||||
@ -36,9 +36,9 @@ void draw_material(struct gp_render_sig *sig, struct draw_material_params params
|
|||||||
* Fill shapes
|
* Fill shapes
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_poly_ex(struct gp_render_sig *sig, struct v2_array vertices, struct gp_indices indices, u32 color)
|
void draw_poly_ex(G_RenderSig *sig, V2Array vertices, G_Indices indices, u32 color)
|
||||||
{
|
{
|
||||||
struct gp_render_cmd_desc cmd = ZI;
|
G_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_SHAPE;
|
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_SHAPE;
|
||||||
cmd.ui_shape.vertices = vertices;
|
cmd.ui_shape.vertices = vertices;
|
||||||
cmd.ui_shape.indices = indices;
|
cmd.ui_shape.indices = indices;
|
||||||
@ -47,16 +47,16 @@ void draw_poly_ex(struct gp_render_sig *sig, struct v2_array vertices, struct gp
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Draws a filled polygon using triangles in a fan pattern */
|
/* Draws a filled polygon using triangles in a fan pattern */
|
||||||
void draw_poly(struct gp_render_sig *sig, struct v2_array vertices, u32 color)
|
void draw_poly(G_RenderSig *sig, V2Array vertices, u32 color)
|
||||||
{
|
{
|
||||||
if (vertices.count >= 3) {
|
if (vertices.count >= 3) {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
u32 num_tris = vertices.count - 2;
|
u32 num_tris = vertices.count - 2;
|
||||||
u32 num_indices = num_tris * 3;
|
u32 num_indices = num_tris * 3;
|
||||||
|
|
||||||
/* Generate indices in a fan pattern */
|
/* Generate indices in a fan pattern */
|
||||||
struct gp_indices indices = {
|
G_Indices indices = {
|
||||||
.count = num_indices,
|
.count = num_indices,
|
||||||
.indices = arena_push_array_no_zero(scratch.arena, u32, num_indices)
|
.indices = arena_push_array_no_zero(scratch.arena, u32, num_indices)
|
||||||
};
|
};
|
||||||
@ -73,21 +73,21 @@ void draw_poly(struct gp_render_sig *sig, struct v2_array vertices, u32 color)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_circle(struct gp_render_sig *sig, struct v2 pos, f32 radius, u32 color, u32 detail)
|
void draw_circle(G_RenderSig *sig, V2 pos, f32 radius, u32 color, u32 detail)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct v2 *points = arena_push_array_no_zero(scratch.arena, struct v2, detail);
|
V2 *points = arena_push_array_no_zero(scratch.arena, V2, detail);
|
||||||
for (u32 i = 0; i < detail; ++i) {
|
for (u32 i = 0; i < detail; ++i) {
|
||||||
f32 angle = ((f32)i / (f32)detail) * TAU;
|
f32 angle = ((f32)i / (f32)detail) * TAU;
|
||||||
struct v2 p = V2(
|
V2 p = V2FromXY(
|
||||||
radius * math_cos(angle),
|
radius * math_cos(angle),
|
||||||
radius * math_sin(angle)
|
radius * math_sin(angle)
|
||||||
);
|
);
|
||||||
points[i] = v2_add(pos, p);
|
points[i] = v2_add(pos, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2_array vertices = {
|
V2Array vertices = {
|
||||||
.points = points,
|
.points = points,
|
||||||
.count = detail
|
.count = detail
|
||||||
};
|
};
|
||||||
@ -96,14 +96,14 @@ void draw_circle(struct gp_render_sig *sig, struct v2 pos, f32 radius, u32 color
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_quad(struct gp_render_sig *sig, struct quad quad, u32 color)
|
void draw_quad(G_RenderSig *sig, Quad quad, u32 color)
|
||||||
{
|
{
|
||||||
LOCAL_PERSIST u32 indices_array[6] = {
|
LOCAL_PERSIST u32 indices_array[6] = {
|
||||||
0, 1, 2,
|
0, 1, 2,
|
||||||
0, 2, 3
|
0, 2, 3
|
||||||
};
|
};
|
||||||
struct v2_array vertices = { .count = 4, .points = quad.e };
|
V2Array vertices = { .count = 4, .points = quad.e };
|
||||||
struct gp_indices indices = { .count = 6, .indices = indices_array };
|
G_Indices indices = { .count = 6, .indices = indices_array };
|
||||||
draw_poly_ex(sig, vertices, indices, color);
|
draw_poly_ex(sig, vertices, indices, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,64 +111,64 @@ void draw_quad(struct gp_render_sig *sig, struct quad quad, u32 color)
|
|||||||
* Line shapes
|
* Line shapes
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_gradient_line(struct gp_render_sig *sig, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color)
|
void draw_gradient_line(G_RenderSig *sig, V2 start, V2 end, f32 thickness, u32 start_color, u32 end_color)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
struct quad quad = quad_from_line(start, end, thickness);
|
Quad quad = quad_from_line(start, end, thickness);
|
||||||
draw_material(sig, DRAW_MATERIAL_PARAMS(.texture = G.solid_white_texture, .tint0 = start_color, .tint1 = end_color, .quad = quad));
|
draw_material(sig, DRAW_MATERIAL_PARAMS(.texture = G.solid_white_texture, .tint0 = start_color, .tint1 = end_color, .quad = quad));
|
||||||
#else
|
#else
|
||||||
/* Placeholder */
|
/* Placeholder */
|
||||||
(UNUSED)end_color;
|
(UNUSED)end_color;
|
||||||
struct quad quad = quad_from_line(start, end, thickness);
|
Quad quad = quad_from_line(start, end, thickness);
|
||||||
draw_quad(sig, quad, start_color);
|
draw_quad(sig, quad, start_color);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_line(struct gp_render_sig *sig, struct v2 start, struct v2 end, f32 thickness, u32 color)
|
void draw_line(G_RenderSig *sig, V2 start, V2 end, f32 thickness, u32 color)
|
||||||
{
|
{
|
||||||
struct quad quad = quad_from_line(start, end, thickness);
|
Quad quad = quad_from_line(start, end, thickness);
|
||||||
draw_quad(sig, quad, color);
|
draw_quad(sig, quad, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_ray(struct gp_render_sig *sig, struct v2 pos, struct v2 rel, f32 thickness, u32 color)
|
void draw_ray(G_RenderSig *sig, V2 pos, V2 rel, f32 thickness, u32 color)
|
||||||
{
|
{
|
||||||
struct quad quad = quad_from_ray(pos, rel, thickness);
|
Quad quad = quad_from_ray(pos, rel, thickness);
|
||||||
draw_quad(sig, quad, color);
|
draw_quad(sig, quad, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_poly_line(struct gp_render_sig *sig, struct v2_array points, b32 loop, f32 thickness, u32 color)
|
void draw_poly_line(G_RenderSig *sig, V2Array points, b32 loop, f32 thickness, u32 color)
|
||||||
{
|
{
|
||||||
if (points.count >= 2) {
|
if (points.count >= 2) {
|
||||||
for (u64 i = 1; i < points.count; ++i) {
|
for (u64 i = 1; i < points.count; ++i) {
|
||||||
struct v2 p1 = points.points[i - 1];
|
V2 p1 = points.points[i - 1];
|
||||||
struct v2 p2 = points.points[i];
|
V2 p2 = points.points[i];
|
||||||
struct quad q = quad_from_line(p1, p2, thickness);
|
Quad q = quad_from_line(p1, p2, thickness);
|
||||||
draw_quad(sig, q, color);
|
draw_quad(sig, q, color);
|
||||||
}
|
}
|
||||||
if (loop && points.count > 2) {
|
if (loop && points.count > 2) {
|
||||||
struct v2 p1 = points.points[points.count - 1];
|
V2 p1 = points.points[points.count - 1];
|
||||||
struct v2 p2 = points.points[0];
|
V2 p2 = points.points[0];
|
||||||
struct quad q = quad_from_line(p1, p2, thickness);
|
Quad q = quad_from_line(p1, p2, thickness);
|
||||||
draw_quad(sig, q, color);
|
draw_quad(sig, q, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_circle_line(struct gp_render_sig *sig, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail)
|
void draw_circle_line(G_RenderSig *sig, V2 pos, f32 radius, f32 thickness, u32 color, u32 detail)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct v2 *points = arena_push_array_no_zero(scratch.arena, struct v2, detail);
|
V2 *points = arena_push_array_no_zero(scratch.arena, V2, detail);
|
||||||
for (u32 i = 0; i < detail; ++i) {
|
for (u32 i = 0; i < detail; ++i) {
|
||||||
f32 angle = ((f32)i / (f32)detail) * TAU;
|
f32 angle = ((f32)i / (f32)detail) * TAU;
|
||||||
struct v2 p = V2(
|
V2 p = V2FromXY(
|
||||||
radius * math_cos(angle),
|
radius * math_cos(angle),
|
||||||
radius * math_sin(angle)
|
radius * math_sin(angle)
|
||||||
);
|
);
|
||||||
points[i] = v2_add(pos, p);
|
points[i] = v2_add(pos, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2_array a = {
|
V2Array a = {
|
||||||
.points = points,
|
.points = points,
|
||||||
.count = detail
|
.count = detail
|
||||||
};
|
};
|
||||||
@ -177,67 +177,67 @@ void draw_circle_line(struct gp_render_sig *sig, struct v2 pos, f32 radius, f32
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_quad_line(struct gp_render_sig *sig, struct quad quad, f32 thickness, u32 color)
|
void draw_quad_line(G_RenderSig *sig, Quad quad, f32 thickness, u32 color)
|
||||||
{
|
{
|
||||||
struct v2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 };
|
V2 points[] = { quad.p0, quad.p1, quad.p2, quad.p3 };
|
||||||
struct v2_array a = { .points = points, .count = countof(points) };
|
V2Array a = { .points = points, .count = countof(points) };
|
||||||
draw_poly_line(sig, a, 1, thickness, color);
|
draw_poly_line(sig, a, 1, thickness, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_arrow_line(struct gp_render_sig *sig, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color)
|
void draw_arrow_line(G_RenderSig *sig, V2 start, V2 end, f32 thickness, f32 arrowhead_height, u32 color)
|
||||||
{
|
{
|
||||||
const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */
|
const f32 head_width_ratio = 0.5f; /* Width of arrowhead relative to its length */
|
||||||
|
|
||||||
const f32 max_height_to_line_ratio = 0.9f; /* Maximum length of arrowhead relative to total line length */
|
const f32 max_height_to_line_ratio = 0.9f; /* Maximum length of arrowhead relative to total line length */
|
||||||
arrowhead_height = min_f32(arrowhead_height, v2_len(v2_sub(end, start)) * max_height_to_line_ratio);
|
arrowhead_height = min_f32(arrowhead_height, v2_len(v2_sub(end, start)) * max_height_to_line_ratio);
|
||||||
|
|
||||||
struct v2 head_start_dir = v2_sub(start, end);
|
V2 head_start_dir = v2_sub(start, end);
|
||||||
head_start_dir = v2_norm(head_start_dir);
|
head_start_dir = v2_norm(head_start_dir);
|
||||||
head_start_dir = v2_mul(head_start_dir, arrowhead_height);
|
head_start_dir = v2_mul(head_start_dir, arrowhead_height);
|
||||||
|
|
||||||
struct v2 head_start = v2_add(end, head_start_dir);
|
V2 head_start = v2_add(end, head_start_dir);
|
||||||
|
|
||||||
struct v2 head_p1_dir = v2_perp_mul(head_start_dir, head_width_ratio);
|
V2 head_p1_dir = v2_perp_mul(head_start_dir, head_width_ratio);
|
||||||
struct v2 head_p2_dir = v2_neg(head_p1_dir);
|
V2 head_p2_dir = v2_neg(head_p1_dir);
|
||||||
|
|
||||||
struct v2 head_p1 = v2_add(head_start, head_p1_dir);
|
V2 head_p1 = v2_add(head_start, head_p1_dir);
|
||||||
struct v2 head_p2 = v2_add(head_start, head_p2_dir);
|
V2 head_p2 = v2_add(head_start, head_p2_dir);
|
||||||
|
|
||||||
struct v2 head_points[] = { end, head_p1, head_p2 };
|
V2 head_points[] = { end, head_p1, head_p2 };
|
||||||
struct v2_array head_points_v2_array = {
|
V2Array head_points_v2_array = {
|
||||||
.points = head_points,
|
.points = head_points,
|
||||||
.count = countof(head_points)
|
.count = countof(head_points)
|
||||||
};
|
};
|
||||||
draw_poly(sig, head_points_v2_array, color);
|
draw_poly(sig, head_points_v2_array, color);
|
||||||
|
|
||||||
struct quad line_quad = quad_from_line(start, head_start, thickness);
|
Quad line_quad = quad_from_line(start, head_start, thickness);
|
||||||
draw_quad(sig, line_quad, color);
|
draw_quad(sig, line_quad, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_arrow_ray(struct gp_render_sig *sig, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color)
|
void draw_arrow_ray(G_RenderSig *sig, V2 pos, V2 rel, f32 thickness, f32 arrowhead_height, u32 color)
|
||||||
{
|
{
|
||||||
struct v2 end = v2_add(pos, rel);
|
V2 end = v2_add(pos, rel);
|
||||||
draw_arrow_line(sig, pos, end, thickness, arrowhead_height, color);
|
draw_arrow_line(sig, pos, end, thickness, arrowhead_height, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_collider_line(struct gp_render_sig *sig, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail)
|
void draw_collider_line(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct v2_array poly = ZI;
|
V2Array poly = ZI;
|
||||||
if (shape.radius == 0) {
|
if (shape.radius == 0) {
|
||||||
poly.count = shape.count;
|
poly.count = shape.count;
|
||||||
poly.points = arena_push_array_no_zero(scratch.arena, struct v2, shape.count);
|
poly.points = arena_push_array_no_zero(scratch.arena, V2, shape.count);
|
||||||
for (u32 i = 0; i < shape.count; ++i) {
|
for (u32 i = 0; i < shape.count; ++i) {
|
||||||
struct v2 p = xform_mul_v2(shape_xf, shape.points[i]);
|
V2 p = xform_mul_v2(shape_xf, shape.points[i]);
|
||||||
poly.points[i] = p;
|
poly.points[i] = p;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
poly.count = detail;
|
poly.count = detail;
|
||||||
poly.points = arena_push_array_no_zero(scratch.arena, struct v2, detail);
|
poly.points = arena_push_array_no_zero(scratch.arena, V2, detail);
|
||||||
for (u32 i = 0; i < detail; ++i) {
|
for (u32 i = 0; i < detail; ++i) {
|
||||||
f32 angle = ((f32)i / (f32)detail) * TAU;
|
f32 angle = ((f32)i / (f32)detail) * TAU;
|
||||||
struct v2 dir = V2(math_cos(angle), math_sin(angle));
|
V2 dir = V2FromXY(math_cos(angle), math_sin(angle));
|
||||||
struct v2 p = collider_get_support_point(&shape, shape_xf, dir).p;
|
V2 p = collider_get_support_point(&shape, shape_xf, dir).p;
|
||||||
poly.points[i] = p;
|
poly.points[i] = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,11 +249,11 @@ void draw_collider_line(struct gp_render_sig *sig, struct collider_shape shape,
|
|||||||
* Grid
|
* Grid
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_grid(struct gp_render_sig *sig, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset)
|
void draw_grid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, V2 offset)
|
||||||
{
|
{
|
||||||
i32 grid_id = 0;
|
i32 grid_id = 0;
|
||||||
{
|
{
|
||||||
struct gp_render_cmd_desc cmd = ZI;
|
G_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_PUSH_GRID;
|
cmd.kind = GP_RENDER_CMD_KIND_PUSH_GRID;
|
||||||
cmd.grid.bg0_color = bg0_color;
|
cmd.grid.bg0_color = bg0_color;
|
||||||
cmd.grid.bg1_color = bg1_color;
|
cmd.grid.bg1_color = bg1_color;
|
||||||
@ -266,7 +266,7 @@ void draw_grid(struct gp_render_sig *sig, struct xform xf, u32 bg0_color, u32 bg
|
|||||||
grid_id = gp_push_render_cmd(sig, &cmd);
|
grid_id = gp_push_render_cmd(sig, &cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gp_render_cmd_desc cmd = ZI;
|
G_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
|
cmd.kind = GP_RENDER_CMD_KIND_DRAW_MATERIAL;
|
||||||
cmd.material.xf = xf;
|
cmd.material.xf = xf;
|
||||||
cmd.material.tint = COLOR_WHITE;
|
cmd.material.tint = COLOR_WHITE;
|
||||||
@ -278,9 +278,9 @@ void draw_grid(struct gp_render_sig *sig, struct xform xf, u32 bg0_color, u32 bg
|
|||||||
* UI
|
* UI
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_ui_rect(struct gp_render_sig *sig, struct draw_ui_rect_params params)
|
void draw_ui_rect(G_RenderSig *sig, D_UiRectParams params)
|
||||||
{
|
{
|
||||||
struct gp_render_cmd_desc cmd = ZI;
|
G_RenderCmdDesc cmd = ZI;
|
||||||
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_RECT;
|
cmd.kind = GP_RENDER_CMD_KIND_DRAW_UI_RECT;
|
||||||
cmd.ui_rect.xf = params.xf;
|
cmd.ui_rect.xf = params.xf;
|
||||||
cmd.ui_rect.texture = params.texture;
|
cmd.ui_rect.texture = params.texture;
|
||||||
@ -294,9 +294,9 @@ void draw_ui_rect(struct gp_render_sig *sig, struct draw_ui_rect_params params)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Returns the rect of the text area */
|
/* Returns the rect of the text area */
|
||||||
struct rect draw_text(struct gp_render_sig *sig, struct draw_text_params params)
|
Rect draw_text(G_RenderSig *sig, D_TextParams params)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
f32 inv_font_image_width = 1.0 / (f32)params.font->image_width;
|
f32 inv_font_image_width = 1.0 / (f32)params.font->image_width;
|
||||||
f32 inv_font_image_height = 1.0 / (f32)params.font->image_height;
|
f32 inv_font_image_height = 1.0 / (f32)params.font->image_height;
|
||||||
@ -312,7 +312,7 @@ struct rect draw_text(struct gp_render_sig *sig, struct draw_text_params params)
|
|||||||
f32 width;
|
f32 width;
|
||||||
f32 height;
|
f32 height;
|
||||||
f32 advance;
|
f32 advance;
|
||||||
struct clip_rect clip;
|
ClipRect clip;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drawable_line {
|
struct drawable_line {
|
||||||
@ -352,14 +352,14 @@ struct rect draw_text(struct gp_render_sig *sig, struct draw_text_params params)
|
|||||||
} else {
|
} else {
|
||||||
struct drawable_glyph *tg = arena_push(scratch.arena, struct drawable_glyph);
|
struct drawable_glyph *tg = arena_push(scratch.arena, struct drawable_glyph);
|
||||||
++num_line_glyphs;
|
++num_line_glyphs;
|
||||||
struct font_glyph *glyph = font_get_glyph(params.font, codepoint);
|
F_Glyph *glyph = font_get_glyph(params.font, codepoint);
|
||||||
tg->off_x = glyph->off_x * params.scale;
|
tg->off_x = glyph->off_x * params.scale;
|
||||||
tg->off_y = glyph->off_y * params.scale;
|
tg->off_y = glyph->off_y * params.scale;
|
||||||
tg->width = glyph->width * params.scale;
|
tg->width = glyph->width * params.scale;
|
||||||
tg->height = glyph->height * params.scale;
|
tg->height = glyph->height * params.scale;
|
||||||
tg->advance = glyph->advance * params.scale;
|
tg->advance = glyph->advance * params.scale;
|
||||||
struct rect glyph_atlas_rect = glyph->atlas_rect;
|
Rect glyph_atlas_rect = glyph->atlas_rect;
|
||||||
tg->clip = (struct clip_rect) {
|
tg->clip = (ClipRect) {
|
||||||
{
|
{
|
||||||
glyph_atlas_rect.x * inv_font_image_width,
|
glyph_atlas_rect.x * inv_font_image_width,
|
||||||
glyph_atlas_rect.y * inv_font_image_height
|
glyph_atlas_rect.y * inv_font_image_height
|
||||||
@ -400,7 +400,7 @@ struct rect draw_text(struct gp_render_sig *sig, struct draw_text_params params)
|
|||||||
* Determine text bounds
|
* Determine text bounds
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct rect bounds = ZI;
|
Rect bounds = ZI;
|
||||||
bounds.x = params.pos.x;
|
bounds.x = params.pos.x;
|
||||||
bounds.y = params.pos.y;
|
bounds.y = params.pos.y;
|
||||||
bounds.width = widest_line;
|
bounds.width = widest_line;
|
||||||
@ -440,7 +440,7 @@ struct rect draw_text(struct gp_render_sig *sig, struct draw_text_params params)
|
|||||||
|
|
||||||
u64 line_number = 0;
|
u64 line_number = 0;
|
||||||
for (struct drawable_line *line = first_line; line; line = line->next) {
|
for (struct drawable_line *line = first_line; line; line = line->next) {
|
||||||
struct v2 draw_pos = bounds.pos;
|
V2 draw_pos = bounds.pos;
|
||||||
draw_pos.y += line_number * line_spacing - first_line_top_offset;
|
draw_pos.y += line_number * line_spacing - first_line_top_offset;
|
||||||
|
|
||||||
/* Alignment */
|
/* Alignment */
|
||||||
@ -459,9 +459,9 @@ struct rect draw_text(struct gp_render_sig *sig, struct draw_text_params params)
|
|||||||
/* Draw glyphs */
|
/* Draw glyphs */
|
||||||
for (u64 i = 0; i < line->num_glyphs; ++i) {
|
for (u64 i = 0; i < line->num_glyphs; ++i) {
|
||||||
struct drawable_glyph *tg = &line->glyphs[i];
|
struct drawable_glyph *tg = &line->glyphs[i];
|
||||||
struct v2 pos = V2(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y);
|
V2 pos = V2FromXY(draw_pos.x + tg->off_x, draw_pos.y + tg->off_y);
|
||||||
struct v2 size = V2(tg->width, tg->height);
|
V2 size = V2FromXY(tg->width, tg->height);
|
||||||
struct xform xf = xform_from_rect(RECT_FROM_V2(pos, size));
|
Xform xf = xform_from_rect(RECT_FROM_V2(pos, size));
|
||||||
draw_ui_rect(sig, DRAW_UI_RECT_PARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip));
|
draw_ui_rect(sig, DRAW_UI_RECT_PARAMS(.xf = xf, .texture = params.font->texture, .tint = params.color, .clip = tg->clip));
|
||||||
draw_pos.x += tg->advance;
|
draw_pos.x += tg->advance;
|
||||||
|
|
||||||
|
|||||||
@ -1,94 +1,94 @@
|
|||||||
struct font;
|
typedef struct D_StartupReceipt D_StartupReceipt;
|
||||||
struct font_startup_receipt;
|
struct D_StartupReceipt { i32 _; };
|
||||||
|
D_StartupReceipt draw_startup(F_StartupReceipt *font_sr);
|
||||||
struct draw_startup_receipt { i32 _; };
|
|
||||||
struct draw_startup_receipt draw_startup(struct font_startup_receipt *font_sr);
|
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Material
|
* Material
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#define DRAW_MATERIAL_PARAMS(...) ((struct draw_material_params) { \
|
#define DRAW_MATERIAL_PARAMS(...) ((D_MaterialParams) { \
|
||||||
.tint = COLOR_WHITE, \
|
.tint = COLOR_WHITE, \
|
||||||
.clip = CLIP_ALL, \
|
.clip = CLIP_ALL, \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
})
|
})
|
||||||
|
|
||||||
struct draw_material_params {
|
typedef struct D_MaterialParams D_MaterialParams;
|
||||||
struct xform xf;
|
struct D_MaterialParams {
|
||||||
struct gp_resource *texture;
|
Xform xf;
|
||||||
struct clip_rect clip;
|
G_Resource *texture;
|
||||||
|
ClipRect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
b32 is_light;
|
b32 is_light;
|
||||||
struct v3 light_emittance;
|
V3 light_emittance;
|
||||||
};
|
};
|
||||||
|
|
||||||
void draw_material(struct gp_render_sig *sig, struct draw_material_params params);
|
void draw_material(G_RenderSig *sig, D_MaterialParams params);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Fill shapes
|
* Fill shapes
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_poly_ex(struct gp_render_sig *sig, struct v2_array vertices, struct gp_indices indices, u32 color);
|
void draw_poly_ex(G_RenderSig *sig, V2Array vertices, G_Indices indices, u32 color);
|
||||||
|
|
||||||
void draw_poly(struct gp_render_sig *sig, struct v2_array points, u32 color);
|
void draw_poly(G_RenderSig *sig, V2Array points, u32 color);
|
||||||
|
|
||||||
void draw_circle(struct gp_render_sig *sig, struct v2 pos, f32 radius, u32 color, u32 detail);
|
void draw_circle(G_RenderSig *sig, V2 pos, f32 radius, u32 color, u32 detail);
|
||||||
|
|
||||||
void draw_quad(struct gp_render_sig *sig, struct quad quad, u32 color);
|
void draw_quad(G_RenderSig *sig, Quad quad, u32 color);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Line shapes
|
* Line shapes
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_gradient_line(struct gp_render_sig *sig, struct v2 start, struct v2 end, f32 thickness, u32 start_color, u32 end_color);
|
void draw_gradient_line(G_RenderSig *sig, V2 start, V2 end, f32 thickness, u32 start_color, u32 end_color);
|
||||||
|
|
||||||
void draw_line(struct gp_render_sig *sig, struct v2 start, struct v2 end, f32 thickness, u32 color);
|
void draw_line(G_RenderSig *sig, V2 start, V2 end, f32 thickness, u32 color);
|
||||||
|
|
||||||
void draw_ray(struct gp_render_sig *sig, struct v2 pos, struct v2 rel, f32 thickness, u32 color);
|
void draw_ray(G_RenderSig *sig, V2 pos, V2 rel, f32 thickness, u32 color);
|
||||||
|
|
||||||
void draw_poly_line(struct gp_render_sig *sig, struct v2_array points, b32 loop, f32 thickness, u32 color);
|
void draw_poly_line(G_RenderSig *sig, V2Array points, b32 loop, f32 thickness, u32 color);
|
||||||
|
|
||||||
void draw_circle_line(struct gp_render_sig *sig, struct v2 pos, f32 radius, f32 thickness, u32 color, u32 detail);
|
void draw_circle_line(G_RenderSig *sig, V2 pos, f32 radius, f32 thickness, u32 color, u32 detail);
|
||||||
|
|
||||||
void draw_quad_line(struct gp_render_sig *sig, struct quad quad, f32 thickness, u32 color);
|
void draw_quad_line(G_RenderSig *sig, Quad quad, f32 thickness, u32 color);
|
||||||
|
|
||||||
void draw_arrow_line(struct gp_render_sig *sig, struct v2 start, struct v2 end, f32 thickness, f32 arrowhead_height, u32 color);
|
void draw_arrow_line(G_RenderSig *sig, V2 start, V2 end, f32 thickness, f32 arrowhead_height, u32 color);
|
||||||
|
|
||||||
void draw_arrow_ray(struct gp_render_sig *sig, struct v2 pos, struct v2 rel, f32 thickness, f32 arrowhead_height, u32 color);
|
void draw_arrow_ray(G_RenderSig *sig, V2 pos, V2 rel, f32 thickness, f32 arrowhead_height, u32 color);
|
||||||
|
|
||||||
void draw_collider_line(struct gp_render_sig *sig, struct collider_shape shape, struct xform shape_xf, f32 thickness, u32 color, u32 detail);
|
void draw_collider_line(G_RenderSig *sig, CLD_Shape shape, Xform shape_xf, f32 thickness, u32 color, u32 detail);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Grid
|
* Grid
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void draw_grid(struct gp_render_sig *sig, struct xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, struct v2 offset);
|
void draw_grid(G_RenderSig *sig, Xform xf, u32 bg0_color, u32 bg1_color, u32 line_color, u32 x_color, u32 y_color, f32 thickness, f32 spacing, V2 offset);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* UI
|
* UI
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#define DRAW_UI_RECT_PARAMS(...) ((struct draw_ui_rect_params) { \
|
#define DRAW_UI_RECT_PARAMS(...) ((D_UiRectParams) { \
|
||||||
.tint = COLOR_WHITE, \
|
.tint = COLOR_WHITE, \
|
||||||
.clip = CLIP_ALL, \
|
.clip = CLIP_ALL, \
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
})
|
})
|
||||||
|
|
||||||
struct draw_ui_rect_params {
|
typedef struct D_UiRectParams D_UiRectParams;
|
||||||
struct xform xf;
|
struct D_UiRectParams {
|
||||||
struct gp_resource *texture;
|
Xform xf;
|
||||||
struct clip_rect clip;
|
G_Resource *texture;
|
||||||
|
ClipRect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
};
|
};
|
||||||
|
|
||||||
void draw_ui_rect(struct gp_render_sig *sig, struct draw_ui_rect_params params);
|
void draw_ui_rect(G_RenderSig *sig, D_UiRectParams params);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Text
|
* Text
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#define DRAW_TEXT_PARAMS(...) ((struct draw_text_params) { \
|
#define DRAW_TEXT_PARAMS(...) ((D_TextParams) { \
|
||||||
.scale = 1.0, \
|
.scale = 1.0, \
|
||||||
.alignment = DRAW_TEXT_ALIGNMENT_LEFT, \
|
.alignment = DRAW_TEXT_ALIGNMENT_LEFT, \
|
||||||
.offset_x = DRAW_TEXT_OFFSET_X_LEFT, \
|
.offset_x = DRAW_TEXT_OFFSET_X_LEFT, \
|
||||||
@ -98,36 +98,37 @@ void draw_ui_rect(struct gp_render_sig *sig, struct draw_ui_rect_params params);
|
|||||||
})
|
})
|
||||||
|
|
||||||
/* How is text aligned within its area */
|
/* How is text aligned within its area */
|
||||||
enum draw_text_alignment {
|
typedef enum D_TextAlignment {
|
||||||
DRAW_TEXT_ALIGNMENT_LEFT, /* Default */
|
DRAW_TEXT_ALIGNMENT_LEFT, /* Default */
|
||||||
DRAW_TEXT_ALIGNMENT_CENTER,
|
DRAW_TEXT_ALIGNMENT_CENTER,
|
||||||
DRAW_TEXT_ALIGNMENT_RIGHT
|
DRAW_TEXT_ALIGNMENT_RIGHT
|
||||||
};
|
} D_TextAlignment;
|
||||||
|
|
||||||
/* How does the specified text position relate to the text area.
|
/* How does the specified text position relate to the text area.
|
||||||
* E.g. BOTTOM & RIGHT means the bottom-right of the text area will snap to
|
* E.g. BOTTOM & RIGHT means the bottom-right of the text area will snap to
|
||||||
* the specified position. */
|
* the specified position. */
|
||||||
enum draw_text_offset_x {
|
typedef enum D_TextOffsetX {
|
||||||
DRAW_TEXT_OFFSET_X_LEFT, /* Default */
|
DRAW_TEXT_OFFSET_X_LEFT, /* Default */
|
||||||
DRAW_TEXT_OFFSET_X_CENTER,
|
DRAW_TEXT_OFFSET_X_CENTER,
|
||||||
DRAW_TEXT_OFFSET_X_RIGHT
|
DRAW_TEXT_OFFSET_X_RIGHT
|
||||||
};
|
} D_TextOffsetX;
|
||||||
|
|
||||||
enum draw_text_offset_y {
|
typedef enum D_TextOffsetY {
|
||||||
DRAW_TEXT_OFFSET_Y_TOP, /* Default */
|
DRAW_TEXT_OFFSET_Y_TOP, /* Default */
|
||||||
DRAW_TEXT_OFFSET_Y_CENTER,
|
DRAW_TEXT_OFFSET_Y_CENTER,
|
||||||
DRAW_TEXT_OFFSET_Y_BOTTOM
|
DRAW_TEXT_OFFSET_Y_BOTTOM
|
||||||
};
|
} D_TextOffsetY;
|
||||||
|
|
||||||
struct draw_text_params {
|
typedef struct D_TextParams D_TextParams;
|
||||||
struct font *font;
|
struct D_TextParams {
|
||||||
struct v2 pos;
|
F_Font *font;
|
||||||
|
V2 pos;
|
||||||
f32 scale;
|
f32 scale;
|
||||||
u32 color;
|
u32 color;
|
||||||
enum draw_text_alignment alignment;
|
D_TextAlignment alignment;
|
||||||
enum draw_text_offset_x offset_x;
|
D_TextOffsetX offset_x;
|
||||||
enum draw_text_offset_y offset_y;
|
D_TextOffsetY offset_y;
|
||||||
struct string str;
|
String str;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rect draw_text(struct gp_render_sig *sig, struct draw_text_params params);
|
Rect draw_text(G_RenderSig *sig, D_TextParams params);
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
struct dxc_compile_result {
|
typedef struct DXC_Result DXC_Result;
|
||||||
struct string dxc;
|
struct DXC_Result {
|
||||||
struct string errors;
|
String dxc;
|
||||||
|
String errors;
|
||||||
b32 success;
|
b32 success;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dxc_compile_result dxc_compile(struct arena *arena, struct string shader_source, i32 num_args, struct string *args);
|
DXC_Result dxc_compile(Arena *arena, String shader_source, i32 num_args, String *args);
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
#if !RESOURCE_RELOADING
|
#if !RESOURCE_RELOADING
|
||||||
|
|
||||||
struct dxc_compile_result dxc_compile(struct arena *arena, struct string shader_source, i32 num_args, struct string *args)
|
DXC_Result dxc_compile(Arena *arena, String shader_source, i32 num_args, String *args)
|
||||||
{
|
{
|
||||||
(UNUSED)arena;
|
(UNUSED)arena;
|
||||||
(UNUSED)shader_source;
|
(UNUSED)shader_source;
|
||||||
(UNUSED)num_args;
|
(UNUSED)num_args;
|
||||||
(UNUSED)args;
|
(UNUSED)args;
|
||||||
struct dxc_compile_result res = ZI;
|
DXC_Result res = ZI;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,11 +33,11 @@ struct dxc_compile_result dxc_compile(struct arena *arena, struct string shader_
|
|||||||
#pragma comment(lib, "dxcompiler")
|
#pragma comment(lib, "dxcompiler")
|
||||||
|
|
||||||
/* https://github.com/microsoft/DirectXShaderCompiler/wiki/Using-dxc.exe-and-dxcompiler.dll */
|
/* https://github.com/microsoft/DirectXShaderCompiler/wiki/Using-dxc.exe-and-dxcompiler.dll */
|
||||||
struct dxc_compile_result dxc_compile(struct arena *arena, struct string shader_source, i32 num_args, struct string *args)
|
DXC_Result dxc_compile(Arena *arena, String shader_source, i32 num_args, String *args)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
struct dxc_compile_result res = ZI;
|
DXC_Result res = ZI;
|
||||||
|
|
||||||
wchar_t **wstr_args = arena_push_array(scratch.arena, wchar_t *, num_args);
|
wchar_t **wstr_args = arena_push_array(scratch.arena, wchar_t *, num_args);
|
||||||
for (i32 i = 0; i < num_args; ++i) {
|
for (i32 i = 0; i < num_args; ++i) {
|
||||||
@ -65,7 +65,7 @@ struct dxc_compile_result dxc_compile(struct arena *arena, struct string shader_
|
|||||||
CComPtr<IDxcBlobUtf8> dxc_errors = 0;
|
CComPtr<IDxcBlobUtf8> dxc_errors = 0;
|
||||||
compile_results->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&dxc_errors), 0);
|
compile_results->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&dxc_errors), 0);
|
||||||
if (dxc_errors != 0) {
|
if (dxc_errors != 0) {
|
||||||
struct string blob_str = ZI;
|
String blob_str = ZI;
|
||||||
blob_str.len = dxc_errors->GetBufferSize();
|
blob_str.len = dxc_errors->GetBufferSize();
|
||||||
blob_str.text = (u8 *)dxc_errors->GetBufferPointer();
|
blob_str.text = (u8 *)dxc_errors->GetBufferPointer();
|
||||||
res.errors = string_copy(arena, blob_str);
|
res.errors = string_copy(arena, blob_str);
|
||||||
@ -81,7 +81,7 @@ struct dxc_compile_result dxc_compile(struct arena *arena, struct string shader_
|
|||||||
CComPtr<IDxcBlob> dxc_shader = 0;
|
CComPtr<IDxcBlob> dxc_shader = 0;
|
||||||
compile_results->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&dxc_shader), 0);
|
compile_results->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&dxc_shader), 0);
|
||||||
if (dxc_shader != 0) {
|
if (dxc_shader != 0) {
|
||||||
struct string blob_str = ZI;
|
String blob_str = ZI;
|
||||||
blob_str.len = dxc_shader->GetBufferSize();
|
blob_str.len = dxc_shader->GetBufferSize();
|
||||||
blob_str.text = (u8 *)dxc_shader->GetBufferPointer();
|
blob_str.text = (u8 *)dxc_shader->GetBufferPointer();
|
||||||
res.dxc = string_copy(arena, blob_str);
|
res.dxc = string_copy(arena, blob_str);
|
||||||
|
|||||||
@ -6,7 +6,7 @@ GLOBAL u32 g_font_codes[] = {
|
|||||||
struct font_task_params {
|
struct font_task_params {
|
||||||
struct font_task_params *next_free;
|
struct font_task_params *next_free;
|
||||||
|
|
||||||
struct asset *asset;
|
AC_Asset *asset;
|
||||||
f32 point_size;
|
f32 point_size;
|
||||||
u64 path_len;
|
u64 path_len;
|
||||||
char path_cstr[1024];
|
char path_cstr[1024];
|
||||||
@ -14,7 +14,7 @@ struct font_task_params {
|
|||||||
|
|
||||||
struct font_task_params_store {
|
struct font_task_params_store {
|
||||||
struct font_task_params *head_free;
|
struct font_task_params *head_free;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct snc_mutex mutex;
|
struct snc_mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,20 +24,20 @@ struct font_task_params_store {
|
|||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct font_task_params_store params;
|
struct font_task_params_store params;
|
||||||
} G = ZI, DEBUG_ALIAS(G, L_font);
|
} G = ZI, DEBUG_ALIAS(G, G_font);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct font_startup_receipt font_startup(struct asset_cache_startup_receipt *asset_cache_sr,
|
F_StartupReceipt font_startup(AC_StartupReceipt *asset_cache_sr,
|
||||||
struct ttf_startup_receipt *ttf_sr)
|
TTF_StartupReceipt *ttf_sr)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
(UNUSED)asset_cache_sr;
|
(UNUSED)asset_cache_sr;
|
||||||
(UNUSED)ttf_sr;
|
(UNUSED)ttf_sr;
|
||||||
G.params.arena = arena_alloc(GIBI(64));
|
G.params.arena = arena_alloc(GIBI(64));
|
||||||
return (struct font_startup_receipt) { 0 };
|
return (F_StartupReceipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -75,12 +75,12 @@ INTERNAL void font_task_params_release(struct font_task_params *p)
|
|||||||
INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct font_task_params *params = job.sig;
|
struct font_task_params *params = job.sig;
|
||||||
struct string path = STRING(params->path_len, (u8 *)params->path_cstr);
|
String path = STRING(params->path_len, (u8 *)params->path_cstr);
|
||||||
f32 point_size = params->point_size;
|
f32 point_size = params->point_size;
|
||||||
struct asset *asset = params->asset;
|
AC_Asset *asset = params->asset;
|
||||||
|
|
||||||
logf_info("Loading font \"%F\" (point size %F)", FMT_STR(path), FMT_FLOAT((f64)point_size));
|
logf_info("Loading font \"%F\" (point size %F)", FMT_STR(path), FMT_FLOAT((f64)point_size));
|
||||||
i64 start_ns = sys_time_ns();
|
i64 start_ns = sys_time_ns();
|
||||||
@ -89,25 +89,25 @@ INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
|||||||
ASSERT(countof(g_font_codes) < LOOKUP_TABLE_SIZE);
|
ASSERT(countof(g_font_codes) < LOOKUP_TABLE_SIZE);
|
||||||
|
|
||||||
/* Decode */
|
/* Decode */
|
||||||
struct resource res = resource_open(path);
|
R_Resource res = resource_open(path);
|
||||||
if (!resource_exists(&res)) {
|
if (!resource_exists(&res)) {
|
||||||
/* FIME: Load baked font instead of panicking */
|
/* FIME: Load baked font instead of panicking */
|
||||||
sys_panic(string_format(scratch.arena,
|
sys_panic(string_format(scratch.arena,
|
||||||
LIT("Font \"%F\" not found"),
|
LIT("Font \"%F\" not found"),
|
||||||
FMT_STR(path)));
|
FMT_STR(path)));
|
||||||
}
|
}
|
||||||
struct ttf_decode_result result = ttf_decode(scratch.arena, resource_get_data(&res), point_size, g_font_codes, countof(g_font_codes));
|
TTF_Result result = ttf_decode(scratch.arena, resource_get_data(&res), point_size, g_font_codes, countof(g_font_codes));
|
||||||
resource_close(&res);
|
resource_close(&res);
|
||||||
|
|
||||||
/* Send texture to GPU */
|
/* Send texture to GPU */
|
||||||
struct gp_resource *texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32(result.image_data.width, result.image_data.height), result.image_data.pixels);
|
G_Resource *texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2i32FromXY(result.image_data.width, result.image_data.height), result.image_data.pixels);
|
||||||
|
|
||||||
/* Allocate store memory */
|
/* Allocate store memory */
|
||||||
struct font *font = 0;
|
F_Font *font = 0;
|
||||||
{
|
{
|
||||||
struct asset_cache_store store = asset_cache_store_open();
|
AC_Store store = asset_cache_store_open();
|
||||||
font = arena_push(store.arena, struct font);
|
font = arena_push(store.arena, F_Font);
|
||||||
font->glyphs = arena_push_array_no_zero(store.arena, struct font_glyph, result.glyphs_count);
|
font->glyphs = arena_push_array_no_zero(store.arena, F_Glyph, result.glyphs_count);
|
||||||
font->lookup = arena_push_array(store.arena, u16, LOOKUP_TABLE_SIZE);
|
font->lookup = arena_push_array(store.arena, u16, LOOKUP_TABLE_SIZE);
|
||||||
asset_cache_store_close(&store);
|
asset_cache_store_close(&store);
|
||||||
}
|
}
|
||||||
@ -127,6 +127,7 @@ INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Copy glyphs from decode result */
|
/* Copy glyphs from decode result */
|
||||||
|
STATIC_ASSERT(sizeof(*font->glyphs) == sizeof(*result.glyphs)); /* Font glyph size must match TTF glyph size for memcpy */
|
||||||
MEMCPY(font->glyphs, result.glyphs, sizeof(*font->glyphs) * result.glyphs_count);
|
MEMCPY(font->glyphs, result.glyphs, sizeof(*font->glyphs) * result.glyphs_count);
|
||||||
|
|
||||||
/* Build lookup table */
|
/* Build lookup table */
|
||||||
@ -144,19 +145,19 @@ INTERNAL SYS_JOB_DEF(font_load_asset_job, job)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the asset from the asset cache */
|
/* Returns the asset from the asset cache */
|
||||||
struct asset *font_load_asset(struct string path, f32 point_size, b32 wait)
|
AC_Asset *font_load_asset(String path, f32 point_size, b32 wait)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
/* Concatenate point_size to path for key */
|
/* Concatenate point_size to path for key */
|
||||||
struct string key = string_format(scratch.arena,
|
String key = string_format(scratch.arena,
|
||||||
LIT("%F%F_font"),
|
LIT("%F%F_font"),
|
||||||
FMT_STR(path),
|
FMT_STR(path),
|
||||||
FMT_FLOAT_P((f64)point_size, 1));
|
FMT_FLOAT_P((f64)point_size, 1));
|
||||||
u64 hash = asset_cache_hash(key);
|
u64 hash = asset_cache_hash(key);
|
||||||
b32 is_first_touch;
|
b32 is_first_touch;
|
||||||
struct asset *asset = asset_cache_touch(key, hash, &is_first_touch);
|
AC_Asset *asset = asset_cache_touch(key, hash, &is_first_touch);
|
||||||
|
|
||||||
if (is_first_touch) {
|
if (is_first_touch) {
|
||||||
/* Assemble task params */
|
/* Assemble task params */
|
||||||
@ -183,20 +184,20 @@ struct asset *font_load_asset(struct string path, f32 point_size, b32 wait)
|
|||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct font *font_load_async(struct string path, f32 point_size)
|
F_Font *font_load_async(String path, f32 point_size)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct asset *asset = font_load_asset(path, point_size, 0);
|
AC_Asset *asset = font_load_asset(path, point_size, 0);
|
||||||
struct font *f = (struct font *)asset_cache_get_store_data(asset);
|
F_Font *f = (F_Font *)asset_cache_get_store_data(asset);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct font *font_load(struct string path, f32 point_size)
|
F_Font *font_load(String path, f32 point_size)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct asset *asset = font_load_asset(path, point_size, 1);
|
AC_Asset *asset = font_load_asset(path, point_size, 1);
|
||||||
asset_cache_wait(asset);
|
asset_cache_wait(asset);
|
||||||
struct font *f = (struct font *)asset_cache_get_store_data(asset);
|
F_Font *f = (F_Font *)asset_cache_get_store_data(asset);
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +205,7 @@ struct font *font_load(struct string path, f32 point_size)
|
|||||||
* Other
|
* Other
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct font_glyph *font_get_glyph(struct font *font, u32 codepoint)
|
F_Glyph *font_get_glyph(F_Font *font, u32 codepoint)
|
||||||
{
|
{
|
||||||
if (codepoint < LOOKUP_TABLE_SIZE) {
|
if (codepoint < LOOKUP_TABLE_SIZE) {
|
||||||
u16 index = font->lookup[codepoint];
|
u16 index = font->lookup[codepoint];
|
||||||
|
|||||||
@ -1,32 +1,30 @@
|
|||||||
struct asset;
|
typedef struct F_Glyph F_Glyph;
|
||||||
struct asset_cache_startup_receipt;
|
struct F_Glyph {
|
||||||
struct ttf_startup_receipt;
|
|
||||||
|
|
||||||
struct font_glyph {
|
|
||||||
f32 off_x;
|
f32 off_x;
|
||||||
f32 off_y;
|
f32 off_y;
|
||||||
i32 advance;
|
i32 advance;
|
||||||
f32 width;
|
f32 width;
|
||||||
f32 height;
|
f32 height;
|
||||||
struct rect atlas_rect;
|
Rect atlas_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct font {
|
typedef struct F_Font F_Font;
|
||||||
struct gp_resource *texture;
|
struct F_Font {
|
||||||
|
G_Resource *texture;
|
||||||
u32 image_width;
|
u32 image_width;
|
||||||
u32 image_height;
|
u32 image_height;
|
||||||
f32 point_size;
|
f32 point_size;
|
||||||
u16 glyphs_count;
|
u16 glyphs_count;
|
||||||
struct font_glyph *glyphs;
|
F_Glyph *glyphs;
|
||||||
u16 *lookup;
|
u16 *lookup;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct font_startup_receipt { i32 _; };
|
typedef struct F_StartupReceipt F_StartupReceipt;
|
||||||
struct font_startup_receipt font_startup(struct asset_cache_startup_receipt *asset_cache_sr,
|
struct F_StartupReceipt { i32 _; };
|
||||||
struct ttf_startup_receipt *ttf_sr);
|
F_StartupReceipt font_startup(AC_StartupReceipt *asset_cache_sr, TTF_StartupReceipt *ttf_sr);
|
||||||
|
|
||||||
struct asset *font_load_asset(struct string path, f32 point_size, b32 wait);
|
AC_Asset *font_load_asset(String path, f32 point_size, b32 wait);
|
||||||
struct font *font_load_async(struct string path, f32 point_size);
|
F_Font *font_load_async(String path, f32 point_size);
|
||||||
struct font *font_load(struct string path, f32 point_size);
|
F_Font *font_load(String path, f32 point_size);
|
||||||
|
|
||||||
struct font_glyph *font_get_glyph(struct font *font, u32 codepoint);
|
F_Glyph *font_get_glyph(F_Font *font, u32 codepoint);
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
struct sys_window;
|
struct sys_window;
|
||||||
struct snc_counter;
|
struct snc_counter;
|
||||||
|
|
||||||
struct gp_indices {
|
typedef struct G_Indices G_Indices;
|
||||||
|
struct G_Indices {
|
||||||
u32 count;
|
u32 count;
|
||||||
u32 *indices;
|
u32 *indices;
|
||||||
};
|
};
|
||||||
@ -16,20 +17,20 @@ void gp_startup(void);
|
|||||||
* Resource
|
* Resource
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gp_resource;
|
typedef struct G_Resource G_Resource;
|
||||||
|
|
||||||
/* NOTE: Internally, the layer will make sure to not release any resources
|
/* NOTE: Internally, the layer will make sure to not release any resources
|
||||||
* until after any in-flight GPU runs finish using them. However, it is up to
|
* until after any in-flight GPU runs finish using them. However, it is up to
|
||||||
* the caller to make sure the released resources aren't then referenced in
|
* the caller to make sure the released resources aren't then referenced in
|
||||||
* any runs
|
* any runs
|
||||||
*/
|
*/
|
||||||
void gp_resource_release(struct gp_resource *resource);
|
void gp_resource_release(G_Resource *resource);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Texture
|
* Texture
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
enum gp_texture_format {
|
typedef enum G_TextureFormat {
|
||||||
GP_TEXTURE_FORMAT_NONE,
|
GP_TEXTURE_FORMAT_NONE,
|
||||||
GP_TEXTURE_FORMAT_R8_UNORM,
|
GP_TEXTURE_FORMAT_R8_UNORM,
|
||||||
GP_TEXTURE_FORMAT_R8G8B8A8_UNORM,
|
GP_TEXTURE_FORMAT_R8G8B8A8_UNORM,
|
||||||
@ -37,22 +38,22 @@ enum gp_texture_format {
|
|||||||
GP_TEXTURE_FORMAT_R16G16B16A16_FLOAT,
|
GP_TEXTURE_FORMAT_R16G16B16A16_FLOAT,
|
||||||
|
|
||||||
NUM_GP_TEXTURE_FORMATS
|
NUM_GP_TEXTURE_FORMATS
|
||||||
};
|
} G_TextureFormat;
|
||||||
|
|
||||||
enum gp_texture_flag {
|
typedef enum G_TextureFlag {
|
||||||
GP_TEXTURE_FLAG_NONE = (0),
|
GP_TEXTURE_FLAG_NONE = (0),
|
||||||
GP_TEXTURE_FLAG_TARGETABLE = (1 << 0)
|
GP_TEXTURE_FLAG_TARGETABLE = (1 << 0)
|
||||||
};
|
} G_TextureFlag;
|
||||||
|
|
||||||
struct gp_resource *gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data);
|
G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void *initial_data);
|
||||||
|
|
||||||
struct v2i32 gp_texture_get_size(struct gp_resource *texture);
|
V2i32 gp_texture_get_size(G_Resource *texture);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Render
|
* Render
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
enum gp_render_cmd_kind {
|
typedef enum G_RenderCmdKind {
|
||||||
GP_RENDER_CMD_KIND_NONE,
|
GP_RENDER_CMD_KIND_NONE,
|
||||||
GP_RENDER_CMD_KIND_DRAW_MATERIAL,
|
GP_RENDER_CMD_KIND_DRAW_MATERIAL,
|
||||||
GP_RENDER_CMD_KIND_DRAW_UI_RECT,
|
GP_RENDER_CMD_KIND_DRAW_UI_RECT,
|
||||||
@ -60,35 +61,36 @@ enum gp_render_cmd_kind {
|
|||||||
GP_RENDER_CMD_KIND_PUSH_GRID,
|
GP_RENDER_CMD_KIND_PUSH_GRID,
|
||||||
|
|
||||||
NUM_GP_RENDER_CMD_KINDS
|
NUM_GP_RENDER_CMD_KINDS
|
||||||
};
|
} G_RenderCmdKind;
|
||||||
|
|
||||||
struct gp_render_cmd_desc {
|
typedef struct G_RenderCmdDesc G_RenderCmdDesc;
|
||||||
enum gp_render_cmd_kind kind;
|
struct G_RenderCmdDesc {
|
||||||
|
G_RenderCmdKind kind;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
struct xform xf;
|
Xform xf;
|
||||||
struct gp_resource *texture;
|
G_Resource *texture;
|
||||||
struct clip_rect clip;
|
ClipRect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
b32 is_light;
|
b32 is_light;
|
||||||
struct v3 light_emittance;
|
V3 light_emittance;
|
||||||
u32 grid_cmd_id;
|
u32 grid_cmd_id;
|
||||||
} material;
|
} material;
|
||||||
struct {
|
struct {
|
||||||
struct xform xf;
|
Xform xf;
|
||||||
struct gp_resource *texture;
|
G_Resource *texture;
|
||||||
struct clip_rect clip;
|
ClipRect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
} ui_rect;
|
} ui_rect;
|
||||||
struct {
|
struct {
|
||||||
struct v2_array vertices;
|
V2Array vertices;
|
||||||
struct gp_indices indices;
|
G_Indices indices;
|
||||||
u32 color;
|
u32 color;
|
||||||
} ui_shape;
|
} ui_shape;
|
||||||
struct {
|
struct {
|
||||||
f32 line_thickness;
|
f32 line_thickness;
|
||||||
f32 line_spacing;
|
f32 line_spacing;
|
||||||
struct v2 offset;
|
V2 offset;
|
||||||
u32 bg0_color;
|
u32 bg0_color;
|
||||||
u32 bg1_color;
|
u32 bg1_color;
|
||||||
u32 line_color;
|
u32 line_color;
|
||||||
@ -98,45 +100,51 @@ struct gp_render_cmd_desc {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gp_render_params {
|
typedef struct G_RenderParams G_RenderParams;
|
||||||
struct v2i32 ui_size;
|
struct G_RenderParams {
|
||||||
struct v2i32 render_size;
|
V2i32 ui_size;
|
||||||
struct xform world_to_render_xf;
|
V2i32 render_size;
|
||||||
struct xform render_to_ui_xf;
|
Xform world_to_render_xf;
|
||||||
|
Xform render_to_ui_xf;
|
||||||
b32 effects_disabled;
|
b32 effects_disabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gp_render_sig *gp_render_sig_alloc(void);
|
typedef struct G_RenderSig G_RenderSig;
|
||||||
|
|
||||||
|
G_RenderSig *gp_render_sig_alloc(void);
|
||||||
|
|
||||||
/* Returns a cmd id internal to the sig */
|
/* Returns a cmd id internal to the sig */
|
||||||
u32 gp_push_render_cmd(struct gp_render_sig *render_sig, struct gp_render_cmd_desc *desc);
|
u32 gp_push_render_cmd(G_RenderSig *render_sig, G_RenderCmdDesc *desc);
|
||||||
|
|
||||||
struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp_render_params render_params);
|
G_Resource *gp_run_render(G_RenderSig *gp_render_sig, G_RenderParams render_params);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Memory info
|
* Memory info
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gp_memory_info {
|
typedef struct G_MemoryInfo G_MemoryInfo;
|
||||||
|
struct G_MemoryInfo {
|
||||||
u64 local_used;
|
u64 local_used;
|
||||||
u64 local_budget;
|
u64 local_budget;
|
||||||
u64 non_local_used;
|
u64 non_local_used;
|
||||||
u64 non_local_budget;
|
u64 non_local_budget;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct gp_memory_info gp_query_memory_info(void);
|
G_MemoryInfo gp_query_memory_info(void);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Swapchain
|
* Swapchain
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gp_swapchain *gp_swapchain_alloc(struct sys_window *window, struct v2i32 resolution);
|
typedef struct G_Swapchain G_Swapchain;
|
||||||
|
|
||||||
void gp_swapchain_release(struct gp_swapchain *gp_swapchain);
|
G_Swapchain *gp_swapchain_alloc(struct sys_window *window, V2i32 resolution);
|
||||||
|
|
||||||
|
void gp_swapchain_release(G_Swapchain *gp_swapchain);
|
||||||
|
|
||||||
/* Waits until a new backbuffer is ready to be written to.
|
/* Waits until a new backbuffer is ready to be written to.
|
||||||
* This should be called before rendering for minimum latency. */
|
* This should be called before rendering for minimum latency. */
|
||||||
void gp_swapchain_wait(struct gp_swapchain *gp_swapchain);
|
void gp_swapchain_wait(G_Swapchain *gp_swapchain);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Present
|
* Present
|
||||||
@ -145,4 +153,4 @@ void gp_swapchain_wait(struct gp_swapchain *gp_swapchain);
|
|||||||
/* 1. Clears the backbuffer and ensures it's at size `backbuffer_resolution`
|
/* 1. Clears the backbuffer and ensures it's at size `backbuffer_resolution`
|
||||||
* 2. Blits `texture` to the backbuffer using `texture_xf`
|
* 2. Blits `texture` to the backbuffer using `texture_xf`
|
||||||
* 3. Presents the backbuffer */
|
* 3. Presents the backbuffer */
|
||||||
void gp_present(struct gp_swapchain *gp_swapchain, struct v2i32 backbuffer_resolution, struct gp_resource *texture, struct xform texture_xf, i32 vsync);
|
void gp_present(G_Swapchain *gp_swapchain, V2i32 backbuffer_resolution, G_Resource *texture, Xform texture_xf, i32 vsync);
|
||||||
|
|||||||
@ -58,8 +58,8 @@
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct shader_desc {
|
struct shader_desc {
|
||||||
struct string file;
|
String file;
|
||||||
struct string func;
|
String func;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pipeline_rtv_desc {
|
struct pipeline_rtv_desc {
|
||||||
@ -68,22 +68,22 @@ struct pipeline_rtv_desc {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pipeline_desc {
|
struct pipeline_desc {
|
||||||
struct string name;
|
String name;
|
||||||
|
|
||||||
/* If a dxc string is set, then it will be used directly instead of looking up dxc from archive using pipeline name */
|
/* If a dxc string is set, then it will be used directly instead of looking up dxc from archive using pipeline name */
|
||||||
struct string vs_dxc;
|
String vs_dxc;
|
||||||
struct string ps_dxc;
|
String ps_dxc;
|
||||||
struct string cs_dxc;
|
String cs_dxc;
|
||||||
|
|
||||||
struct pipeline_rtv_desc rtvs[8];
|
struct pipeline_rtv_desc rtvs[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pipeline {
|
struct pipeline {
|
||||||
struct string name;
|
String name;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
b32 success;
|
b32 success;
|
||||||
b32 is_gfx;
|
b32 is_gfx;
|
||||||
struct string error;
|
String error;
|
||||||
i64 compilation_time_ns;
|
i64 compilation_time_ns;
|
||||||
|
|
||||||
/* Lock global pipelines mutex when accessing */
|
/* Lock global pipelines mutex when accessing */
|
||||||
@ -97,32 +97,32 @@ struct pipeline {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct pipeline_error {
|
struct pipeline_error {
|
||||||
struct string msg;
|
String msg;
|
||||||
struct pipeline_error *next;
|
struct pipeline_error *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pipeline_include {
|
struct pipeline_include {
|
||||||
struct string name;
|
String name;
|
||||||
u64 name_hash;
|
u64 name_hash;
|
||||||
struct pipeline_include *next;
|
struct pipeline_include *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pipeline_scope {
|
struct pipeline_scope {
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct dict *refs;
|
Dict *refs;
|
||||||
struct pipeline_scope *next_free;
|
struct pipeline_scope *next_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct command_queue_desc {
|
struct command_queue_desc {
|
||||||
enum D3D12_COMMAND_LIST_TYPE type;
|
enum D3D12_COMMAND_LIST_TYPE type;
|
||||||
enum D3D12_COMMAND_QUEUE_PRIORITY priority;
|
enum D3D12_COMMAND_QUEUE_PRIORITY priority;
|
||||||
struct string dbg_name;
|
String dbg_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct command_queue {
|
struct command_queue {
|
||||||
struct command_queue_desc desc;
|
struct command_queue_desc desc;
|
||||||
ID3D12CommandQueue *cq;
|
ID3D12CommandQueue *cq;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
struct snc_mutex submit_fence_mutex;
|
struct snc_mutex submit_fence_mutex;
|
||||||
u64 submit_fence_target;
|
u64 submit_fence_target;
|
||||||
@ -137,7 +137,7 @@ struct command_queue {
|
|||||||
|
|
||||||
struct command_list_pool {
|
struct command_list_pool {
|
||||||
struct command_queue *cq;
|
struct command_queue *cq;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct snc_mutex mutex;
|
struct snc_mutex mutex;
|
||||||
struct command_list *first_submitted_command_list;
|
struct command_list *first_submitted_command_list;
|
||||||
struct command_list *last_submitted_command_list;
|
struct command_list *last_submitted_command_list;
|
||||||
@ -214,7 +214,7 @@ struct dx12_resource {
|
|||||||
|
|
||||||
D3D12_GPU_VIRTUAL_ADDRESS gpu_address; /* NOTE: 0 for textures */
|
D3D12_GPU_VIRTUAL_ADDRESS gpu_address; /* NOTE: 0 for textures */
|
||||||
|
|
||||||
struct v2i32 texture_size;
|
V2i32 texture_size;
|
||||||
struct dx12_resource *next_free;
|
struct dx12_resource *next_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ struct swapchain {
|
|||||||
IDXGISwapChain3 *swapchain;
|
IDXGISwapChain3 *swapchain;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
HANDLE waitable;
|
HANDLE waitable;
|
||||||
struct v2i32 resolution;
|
V2i32 resolution;
|
||||||
struct swapchain_buffer buffers[DX12_SWAPCHAIN_BUFFER_COUNT];
|
struct swapchain_buffer buffers[DX12_SWAPCHAIN_BUFFER_COUNT];
|
||||||
|
|
||||||
struct swapchain *next_free;
|
struct swapchain *next_free;
|
||||||
@ -237,7 +237,7 @@ struct swapchain {
|
|||||||
|
|
||||||
struct cpu_descriptor_heap {
|
struct cpu_descriptor_heap {
|
||||||
enum D3D12_DESCRIPTOR_HEAP_TYPE type;
|
enum D3D12_DESCRIPTOR_HEAP_TYPE type;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct snc_mutex mutex;
|
struct snc_mutex mutex;
|
||||||
|
|
||||||
u32 descriptor_size;
|
u32 descriptor_size;
|
||||||
@ -305,27 +305,27 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name);
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct atomic32 initialized;
|
Atomic32 initialized;
|
||||||
|
|
||||||
/* Descriptor heaps pool */
|
/* Descriptor heaps pool */
|
||||||
struct snc_mutex command_descriptor_heaps_mutex;
|
struct snc_mutex command_descriptor_heaps_mutex;
|
||||||
struct arena *command_descriptor_heaps_arena;
|
Arena *command_descriptor_heaps_arena;
|
||||||
struct command_descriptor_heap *first_submitted_command_descriptor_heap;
|
struct command_descriptor_heap *first_submitted_command_descriptor_heap;
|
||||||
struct command_descriptor_heap *last_submitted_command_descriptor_heap;
|
struct command_descriptor_heap *last_submitted_command_descriptor_heap;
|
||||||
|
|
||||||
/* Command buffers pool */
|
/* Command buffers pool */
|
||||||
struct snc_mutex command_buffers_mutex;
|
struct snc_mutex command_buffers_mutex;
|
||||||
struct arena *command_buffers_arena;
|
Arena *command_buffers_arena;
|
||||||
struct dict *command_buffers_dict;
|
Dict *command_buffers_dict;
|
||||||
|
|
||||||
/* Resources pool */
|
/* Resources pool */
|
||||||
struct snc_mutex resources_mutex;
|
struct snc_mutex resources_mutex;
|
||||||
struct arena *resources_arena;
|
Arena *resources_arena;
|
||||||
struct dx12_resource *first_free_resource;
|
struct dx12_resource *first_free_resource;
|
||||||
|
|
||||||
/* Swapchains pool */
|
/* Swapchains pool */
|
||||||
struct snc_mutex swapchains_mutex;
|
struct snc_mutex swapchains_mutex;
|
||||||
struct arena *swapchains_arena;
|
Arena *swapchains_arena;
|
||||||
struct swapchain *first_free_swapchain;
|
struct swapchain *first_free_swapchain;
|
||||||
|
|
||||||
/* Shader bytecode archive */
|
/* Shader bytecode archive */
|
||||||
@ -333,16 +333,16 @@ GLOBAL struct {
|
|||||||
|
|
||||||
/* Pipeline cache */
|
/* Pipeline cache */
|
||||||
struct snc_mutex pipelines_mutex;
|
struct snc_mutex pipelines_mutex;
|
||||||
struct arena *pipelines_arena;
|
Arena *pipelines_arena;
|
||||||
struct pipeline *first_free_pipeline;
|
struct pipeline *first_free_pipeline;
|
||||||
struct dict *pipeline_descs;
|
Dict *pipeline_descs;
|
||||||
struct dict *top_pipelines; /* Latest pipelines */
|
Dict *top_pipelines; /* Latest pipelines */
|
||||||
struct dict *top_successful_pipelines; /* Latest pipelines that successfully compiled */
|
Dict *top_successful_pipelines; /* Latest pipelines that successfully compiled */
|
||||||
struct pipeline_scope *first_free_pipeline_scope;
|
struct pipeline_scope *first_free_pipeline_scope;
|
||||||
|
|
||||||
/* Fenced release queue */
|
/* Fenced release queue */
|
||||||
struct snc_mutex fenced_releases_mutex;
|
struct snc_mutex fenced_releases_mutex;
|
||||||
struct arena *fenced_releases_arena;
|
Arena *fenced_releases_arena;
|
||||||
u64 fenced_release_targets[DX12_NUM_QUEUES];
|
u64 fenced_release_targets[DX12_NUM_QUEUES];
|
||||||
|
|
||||||
/* Factory */
|
/* Factory */
|
||||||
@ -409,7 +409,7 @@ void gp_startup(void)
|
|||||||
G.fenced_releases_arena = arena_alloc(GIBI(64));
|
G.fenced_releases_arena = arena_alloc(GIBI(64));
|
||||||
|
|
||||||
/* Initialize embedded shader archive */
|
/* Initialize embedded shader archive */
|
||||||
struct string embedded_data = inc_dxc_tar();
|
String embedded_data = inc_dxc_tar();
|
||||||
if (embedded_data.len <= 0) {
|
if (embedded_data.len <= 0) {
|
||||||
sys_panic(LIT("No embedded shaders found"));
|
sys_panic(LIT("No embedded shaders found"));
|
||||||
}
|
}
|
||||||
@ -460,10 +460,10 @@ INTERNAL SYS_EXIT_FUNC(gp_shutdown)
|
|||||||
* Dx12 device initialization
|
* Dx12 device initialization
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL void dx12_init_error(struct string error)
|
INTERNAL void dx12_init_error(String error)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct string msg = string_format(scratch.arena, LIT("Failed to initialize DirectX 12.\n\n%F"), FMT_STR(error));
|
String msg = string_format(scratch.arena, LIT("Failed to initialize DirectX 12.\n\n%F"), FMT_STR(error));
|
||||||
sys_panic(msg);
|
sys_panic(msg);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
@ -471,7 +471,7 @@ INTERNAL void dx12_init_error(struct string error)
|
|||||||
INTERNAL void dx12_init_device(void)
|
INTERNAL void dx12_init_device(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
|
|
||||||
/* Enable debug layer */
|
/* Enable debug layer */
|
||||||
@ -516,8 +516,8 @@ INTERNAL void dx12_init_device(void)
|
|||||||
__profn("Create device");
|
__profn("Create device");
|
||||||
IDXGIAdapter1 *adapter = 0;
|
IDXGIAdapter1 *adapter = 0;
|
||||||
ID3D12Device *device = 0;
|
ID3D12Device *device = 0;
|
||||||
struct string error = LIT("Could not initialize GPU device.");
|
String error = LIT("Could not initialize GPU device.");
|
||||||
struct string first_gpu_name = ZI;
|
String first_gpu_name = ZI;
|
||||||
u32 adapter_index = 0;
|
u32 adapter_index = 0;
|
||||||
b32 skip = 0; /* For debugging iGPU */
|
b32 skip = 0; /* For debugging iGPU */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -548,7 +548,7 @@ INTERNAL void dx12_init_device(void)
|
|||||||
}
|
}
|
||||||
if (!device) {
|
if (!device) {
|
||||||
if (first_gpu_name.len > 0) {
|
if (first_gpu_name.len > 0) {
|
||||||
struct string fmt = LIT("Could not initialize device '%F' with D3D_FEATURE_LEVEL_12_0. Ensure that the device is capable and drivers are up to date.");
|
String fmt = LIT("Could not initialize device '%F' with D3D_FEATURE_LEVEL_12_0. Ensure that the device is capable and drivers are up to date.");
|
||||||
error = string_format(scratch.arena, fmt, FMT_STR(first_gpu_name));
|
error = string_format(scratch.arena, fmt, FMT_STR(first_gpu_name));
|
||||||
}
|
}
|
||||||
dx12_init_error(error);
|
dx12_init_error(error);
|
||||||
@ -668,7 +668,7 @@ INTERNAL void dx12_init_objects(void)
|
|||||||
__profn("Initialize command queue profiling contexts");
|
__profn("Initialize command queue profiling contexts");
|
||||||
for (i32 i = 0; i < DX12_NUM_QUEUES; ++i) {
|
for (i32 i = 0; i < DX12_NUM_QUEUES; ++i) {
|
||||||
struct command_queue *cq = G.command_queues[i];
|
struct command_queue *cq = G.command_queues[i];
|
||||||
struct string dbg_name = params[i].dbg_name;
|
String dbg_name = params[i].dbg_name;
|
||||||
__prof_dx12_ctx_alloc(cq->prof, G.device, cq->cq, dbg_name.text, dbg_name.len);
|
__prof_dx12_ctx_alloc(cq->prof, G.device, cq->cq, dbg_name.text, dbg_name.len);
|
||||||
(UNUSED)dbg_name;
|
(UNUSED)dbg_name;
|
||||||
}
|
}
|
||||||
@ -686,7 +686,7 @@ INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines);
|
|||||||
INTERNAL void dx12_init_pipelines(void)
|
INTERNAL void dx12_init_pipelines(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
/* Register pipeline descs */
|
/* Register pipeline descs */
|
||||||
{
|
{
|
||||||
@ -741,7 +741,7 @@ INTERNAL void dx12_init_pipelines(void)
|
|||||||
/* Compile pipelines */
|
/* Compile pipelines */
|
||||||
u32 num_pipelines = 0;
|
u32 num_pipelines = 0;
|
||||||
struct pipeline_desc *descs = arena_push_dry(scratch.arena, struct pipeline_desc);
|
struct pipeline_desc *descs = arena_push_dry(scratch.arena, struct pipeline_desc);
|
||||||
for (struct dict_entry *entry = G.pipeline_descs->first; entry; entry = entry->next) {
|
for (DictEntry *entry = G.pipeline_descs->first; entry; entry = entry->next) {
|
||||||
struct pipeline_desc *desc = (struct pipeline_desc *)entry->value;
|
struct pipeline_desc *desc = (struct pipeline_desc *)entry->value;
|
||||||
*arena_push(scratch.arena, struct pipeline_desc) = *desc;
|
*arena_push(scratch.arena, struct pipeline_desc) = *desc;
|
||||||
++num_pipelines;
|
++num_pipelines;
|
||||||
@ -761,12 +761,12 @@ INTERNAL void dx12_init_pipelines(void)
|
|||||||
if (pipeline->success) {
|
if (pipeline->success) {
|
||||||
logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
|
logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
|
||||||
if (pipeline->error.len) {
|
if (pipeline->error.len) {
|
||||||
struct string msg = string_format(scratch.arena, LIT("Warning while compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(pipeline->error));
|
String msg = string_format(scratch.arena, LIT("Warning while compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(pipeline->error));
|
||||||
log_warning(msg);
|
log_warning(msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct string error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
String error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
||||||
struct string msg = string_format(scratch.arena, LIT("Error initializing pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
String msg = string_format(scratch.arena, LIT("Error initializing pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
||||||
log_error(msg);
|
log_error(msg);
|
||||||
sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg);
|
sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg);
|
||||||
}
|
}
|
||||||
@ -782,16 +782,16 @@ INTERNAL void dx12_init_pipelines(void)
|
|||||||
|
|
||||||
INTERNAL void dx12_init_noise(void)
|
INTERNAL void dx12_init_noise(void)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
{
|
{
|
||||||
struct string noise_res_name = LIT("noise_128x128x64_16.dat");
|
String noise_res_name = LIT("noise_128x128x64_16.dat");
|
||||||
struct resource noise_res = resource_open(noise_res_name);
|
R_Resource noise_res = resource_open(noise_res_name);
|
||||||
DXGI_FORMAT format = DXGI_FORMAT_R16_UINT;
|
DXGI_FORMAT format = DXGI_FORMAT_R16_UINT;
|
||||||
//u32 expected_size = K_BLUE_NOISE_TEX_WIDTH * K_BLUE_NOISE_TEX_HEIGHT * K_BLUE_NOISE_TEX_DEPTH * 2;
|
//u32 expected_size = K_BLUE_NOISE_TEX_WIDTH * K_BLUE_NOISE_TEX_HEIGHT * K_BLUE_NOISE_TEX_DEPTH * 2;
|
||||||
u32 expected_size = K_BLUE_NOISE_TEX_WIDTH * K_BLUE_NOISE_TEX_HEIGHT * K_BLUE_NOISE_TEX_DEPTH * 2;
|
u32 expected_size = K_BLUE_NOISE_TEX_WIDTH * K_BLUE_NOISE_TEX_HEIGHT * K_BLUE_NOISE_TEX_DEPTH * 2;
|
||||||
if (resource_exists(&noise_res)) {
|
if (resource_exists(&noise_res)) {
|
||||||
struct string data = resource_get_data(&noise_res);
|
String data = resource_get_data(&noise_res);
|
||||||
if (data.len != expected_size) {
|
if (data.len != expected_size) {
|
||||||
sys_panic(string_format(scratch.arena,
|
sys_panic(string_format(scratch.arena,
|
||||||
LIT("Noise texture has unexpected size for a %Fx%Fx%F texture (expected %F, got %F)"),
|
LIT("Noise texture has unexpected size for a %Fx%Fx%F texture (expected %F, got %F)"),
|
||||||
@ -848,21 +848,21 @@ INTERNAL void dx12_init_noise(void)
|
|||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
|
|
||||||
struct shader_compile_desc {
|
struct shader_compile_desc {
|
||||||
struct string src;
|
String src;
|
||||||
struct string friendly_name;
|
String friendly_name;
|
||||||
struct string entry;
|
String entry;
|
||||||
struct string target;
|
String target;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct shader_compile_result {
|
struct shader_compile_result {
|
||||||
i64 elapsed_ns;
|
i64 elapsed_ns;
|
||||||
struct string dxc;
|
String dxc;
|
||||||
struct string errors;
|
String errors;
|
||||||
b32 success;
|
b32 success;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct shader_compile_job_sig {
|
struct shader_compile_job_sig {
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct shader_compile_desc *descs;
|
struct shader_compile_desc *descs;
|
||||||
struct shader_compile_result *results;
|
struct shader_compile_result *results;
|
||||||
};
|
};
|
||||||
@ -871,28 +871,28 @@ INTERNAL SYS_JOB_DEF(shader_compile_job, job)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct shader_compile_job_sig *sig = job.sig;
|
struct shader_compile_job_sig *sig = job.sig;
|
||||||
struct arena *arena = sig->arena;
|
Arena *arena = sig->arena;
|
||||||
struct shader_compile_desc *desc = &sig->descs[job.id];
|
struct shader_compile_desc *desc = &sig->descs[job.id];
|
||||||
struct shader_compile_result *result = &sig->results[job.id];
|
struct shader_compile_result *result = &sig->results[job.id];
|
||||||
|
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
{
|
{
|
||||||
i64 start_ns = sys_time_ns();
|
i64 start_ns = sys_time_ns();
|
||||||
struct dxc_compile_result dxc_result = ZI;
|
DXC_Result dxc_result = ZI;
|
||||||
{
|
{
|
||||||
__profn("Compile shader");
|
__profn("Compile shader");
|
||||||
logf_info("Compiling shader \"%F:%F\"", FMT_STR(desc->friendly_name), FMT_STR(desc->entry));
|
logf_info("Compiling shader \"%F:%F\"", FMT_STR(desc->friendly_name), FMT_STR(desc->entry));
|
||||||
/* NOTE: `DXC_ARGS` is supplied by build system at compile time */
|
/* NOTE: `DXC_ARGS` is supplied by build system at compile time */
|
||||||
char *dxc_args_cstr = STRINGIZE(DXC_ARGS);
|
char *dxc_args_cstr = STRINGIZE(DXC_ARGS);
|
||||||
struct string dxc_args_str = string_from_cstr_no_limit(dxc_args_cstr);
|
String dxc_args_str = string_from_cstr_no_limit(dxc_args_cstr);
|
||||||
struct string_array dxc_args_array = string_split(scratch.arena, dxc_args_str, LIT(" "));
|
StringArray dxc_args_array = string_split(scratch.arena, dxc_args_str, LIT(" "));
|
||||||
struct string shader_args[] = {
|
String shader_args[] = {
|
||||||
desc->friendly_name,
|
desc->friendly_name,
|
||||||
LIT("-E"), desc->entry,
|
LIT("-E"), desc->entry,
|
||||||
LIT("-T"), desc->target,
|
LIT("-T"), desc->target,
|
||||||
};
|
};
|
||||||
u32 num_args = countof(shader_args) + dxc_args_array.count;
|
u32 num_args = countof(shader_args) + dxc_args_array.count;
|
||||||
struct string *args = arena_push_array(scratch.arena, struct string, num_args);
|
String *args = arena_push_array(scratch.arena, String, num_args);
|
||||||
for (u32 i = 0; i < countof(shader_args); ++i) {
|
for (u32 i = 0; i < countof(shader_args); ++i) {
|
||||||
args[i] = shader_args[i];
|
args[i] = shader_args[i];
|
||||||
}
|
}
|
||||||
@ -940,19 +940,19 @@ INTERNAL SYS_JOB_DEF(pipeline_alloc_job, job)
|
|||||||
pipeline->name = desc->name;
|
pipeline->name = desc->name;
|
||||||
pipeline->hash = hash_fnv64(HASH_FNV64_BASIS, pipeline->name);
|
pipeline->hash = hash_fnv64(HASH_FNV64_BASIS, pipeline->name);
|
||||||
|
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
{
|
{
|
||||||
i64 start_ns = sys_time_ns();
|
i64 start_ns = sys_time_ns();
|
||||||
struct string pipeline_name = pipeline->name;
|
String pipeline_name = pipeline->name;
|
||||||
logf_info("Loading pipeline \"%F\"", FMT_STR(pipeline_name));
|
logf_info("Loading pipeline \"%F\"", FMT_STR(pipeline_name));
|
||||||
b32 success = 1;
|
b32 success = 1;
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
|
|
||||||
struct string error_str = ZI;
|
String error_str = ZI;
|
||||||
|
|
||||||
struct string vs_dxc = desc->vs_dxc.len > 0 ? desc->vs_dxc : tar_get(&G.dxc_archive, string_cat(scratch.arena, pipeline_name, LIT(".vs")))->data;
|
String vs_dxc = desc->vs_dxc.len > 0 ? desc->vs_dxc : tar_get(&G.dxc_archive, string_cat(scratch.arena, pipeline_name, LIT(".vs")))->data;
|
||||||
struct string ps_dxc = desc->ps_dxc.len > 0 ? desc->ps_dxc : tar_get(&G.dxc_archive, string_cat(scratch.arena, pipeline_name, LIT(".ps")))->data;
|
String ps_dxc = desc->ps_dxc.len > 0 ? desc->ps_dxc : tar_get(&G.dxc_archive, string_cat(scratch.arena, pipeline_name, LIT(".ps")))->data;
|
||||||
struct string cs_dxc = desc->cs_dxc.len > 0 ? desc->cs_dxc : tar_get(&G.dxc_archive, string_cat(scratch.arena, pipeline_name, LIT(".cs")))->data;
|
String cs_dxc = desc->cs_dxc.len > 0 ? desc->cs_dxc : tar_get(&G.dxc_archive, string_cat(scratch.arena, pipeline_name, LIT(".cs")))->data;
|
||||||
if (success && vs_dxc.len > 0 && ps_dxc.len <= 0) {
|
if (success && vs_dxc.len > 0 && ps_dxc.len <= 0) {
|
||||||
error_str = LIT("Pipeline has vertex shader without pixel shader");
|
error_str = LIT("Pipeline has vertex shader without pixel shader");
|
||||||
success = 0;
|
success = 0;
|
||||||
@ -1216,7 +1216,7 @@ INTERNAL struct pipeline_scope *pipeline_scope_begin(void)
|
|||||||
}
|
}
|
||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
struct arena *arena = 0;
|
Arena *arena = 0;
|
||||||
if (scope) {
|
if (scope) {
|
||||||
arena = scope->arena;
|
arena = scope->arena;
|
||||||
} else {
|
} else {
|
||||||
@ -1234,7 +1234,7 @@ INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
|
|||||||
__prof;
|
__prof;
|
||||||
struct snc_lock lock = snc_lock_e(&G.pipelines_mutex);
|
struct snc_lock lock = snc_lock_e(&G.pipelines_mutex);
|
||||||
{
|
{
|
||||||
for (struct dict_entry *entry = scope->refs->first; entry; entry = entry->next) {
|
for (DictEntry *entry = scope->refs->first; entry; entry = entry->next) {
|
||||||
struct pipeline *pipeline = (struct pipeline *)entry->value;
|
struct pipeline *pipeline = (struct pipeline *)entry->value;
|
||||||
if (--pipeline->refcount <= 0) {
|
if (--pipeline->refcount <= 0) {
|
||||||
fenced_release(pipeline, FENCED_RELEASE_KIND_PIPELINE);
|
fenced_release(pipeline, FENCED_RELEASE_KIND_PIPELINE);
|
||||||
@ -1247,7 +1247,7 @@ INTERNAL void pipeline_scope_end(struct pipeline_scope *scope)
|
|||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL READONLY struct pipeline g_nil_pipeline = ZI;
|
INTERNAL READONLY struct pipeline g_nil_pipeline = ZI;
|
||||||
INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, struct string name)
|
INTERNAL struct pipeline *pipeline_from_name(struct pipeline_scope *scope, String name)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct pipeline *res = &g_nil_pipeline;
|
struct pipeline *res = &g_nil_pipeline;
|
||||||
@ -1309,10 +1309,10 @@ INTERNAL void pipeline_register(u64 num_pipelines, struct pipeline **pipelines)
|
|||||||
INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct string rst_extension = LIT(".rst");
|
String rst_extension = LIT(".rst");
|
||||||
struct string knl_extension = LIT(".knl");
|
String knl_extension = LIT(".knl");
|
||||||
|
|
||||||
b32 is_src = string_starts_with(name, LIT("src/"));
|
b32 is_src = string_starts_with(name, LIT("src/"));
|
||||||
b32 is_rs = is_src && string_ends_with(name, rst_extension);
|
b32 is_rs = is_src && string_ends_with(name, rst_extension);
|
||||||
@ -1320,8 +1320,8 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
|||||||
b32 success = 0;
|
b32 success = 0;
|
||||||
|
|
||||||
/* Recompile shaders */
|
/* Recompile shaders */
|
||||||
struct string pipeline_name = ZI;
|
String pipeline_name = ZI;
|
||||||
struct string friendly_name = ZI;
|
String friendly_name = ZI;
|
||||||
i32 num_shaders = 0;
|
i32 num_shaders = 0;
|
||||||
struct shader_compile_desc *shader_descs = 0;
|
struct shader_compile_desc *shader_descs = 0;
|
||||||
struct shader_compile_result *shader_results = 0;
|
struct shader_compile_result *shader_results = 0;
|
||||||
@ -1329,15 +1329,15 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
|||||||
logf_debug("Change detected in shader source file \"%F\", recompiling...", FMT_STR(name));
|
logf_debug("Change detected in shader source file \"%F\", recompiling...", FMT_STR(name));
|
||||||
success = 1;
|
success = 1;
|
||||||
struct sys_file file = sys_file_open_read_wait(name);
|
struct sys_file file = sys_file_open_read_wait(name);
|
||||||
struct string data = sys_file_read_all(scratch.arena, file);
|
String data = sys_file_read_all(scratch.arena, file);
|
||||||
{
|
{
|
||||||
friendly_name = name;
|
friendly_name = name;
|
||||||
struct string_array split = string_split(scratch.arena, friendly_name, LIT("src/"));
|
StringArray split = string_split(scratch.arena, friendly_name, LIT("src/"));
|
||||||
friendly_name = split.count > 0 ? string_cat(scratch.arena, LIT("src/"), split.strings[split.count - 1]) : friendly_name;
|
friendly_name = split.count > 0 ? string_cat(scratch.arena, LIT("src/"), split.strings[split.count - 1]) : friendly_name;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
pipeline_name = name;
|
pipeline_name = name;
|
||||||
struct string_array split = string_split(scratch.arena, pipeline_name, LIT("/"));
|
StringArray split = string_split(scratch.arena, pipeline_name, LIT("/"));
|
||||||
pipeline_name = split.count > 0 ? split.strings[split.count - 1] : pipeline_name;
|
pipeline_name = split.count > 0 ? split.strings[split.count - 1] : pipeline_name;
|
||||||
split = string_split(scratch.arena, pipeline_name, LIT("."));
|
split = string_split(scratch.arena, pipeline_name, LIT("."));
|
||||||
pipeline_name = split.count > 1 ? split.strings[split.count - 2] : pipeline_name;
|
pipeline_name = split.count > 1 ? split.strings[split.count - 2] : pipeline_name;
|
||||||
@ -1386,11 +1386,11 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
|||||||
if (result->success) {
|
if (result->success) {
|
||||||
logf_success("Finished compiling shader \"%F:%F\" in %F seconds", FMT_STR(desc->friendly_name), FMT_STR(desc->entry), FMT_FLOAT(SECONDS_FROM_NS(result->elapsed_ns)));
|
logf_success("Finished compiling shader \"%F:%F\" in %F seconds", FMT_STR(desc->friendly_name), FMT_STR(desc->entry), FMT_FLOAT(SECONDS_FROM_NS(result->elapsed_ns)));
|
||||||
if (result->errors.len > 0) {
|
if (result->errors.len > 0) {
|
||||||
struct string msg = result->errors;
|
String msg = result->errors;
|
||||||
log_warning(msg);
|
log_warning(msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
struct string msg = result->errors;
|
String msg = result->errors;
|
||||||
log_error(msg);
|
log_error(msg);
|
||||||
success = 0;
|
success = 0;
|
||||||
}
|
}
|
||||||
@ -1400,7 +1400,7 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
|||||||
/* Create pipeline descs */
|
/* Create pipeline descs */
|
||||||
u32 num_pipelines = 0;
|
u32 num_pipelines = 0;
|
||||||
struct pipeline_desc *pipeline_descs = arena_push_dry(scratch.arena, struct pipeline_desc);
|
struct pipeline_desc *pipeline_descs = arena_push_dry(scratch.arena, struct pipeline_desc);
|
||||||
for (struct dict_entry *entry = G.pipeline_descs->first; entry; entry = entry->next) {
|
for (DictEntry *entry = G.pipeline_descs->first; entry; entry = entry->next) {
|
||||||
struct pipeline_desc *pipeline_desc = (struct pipeline_desc *)entry->value;
|
struct pipeline_desc *pipeline_desc = (struct pipeline_desc *)entry->value;
|
||||||
struct pipeline_desc new_pipeline_desc = *pipeline_desc;
|
struct pipeline_desc new_pipeline_desc = *pipeline_desc;
|
||||||
if (string_eq(pipeline_desc->name, pipeline_name)) {
|
if (string_eq(pipeline_desc->name, pipeline_name)) {
|
||||||
@ -1434,20 +1434,20 @@ INTERNAL WATCH_CALLBACK_FUNC_DEF(pipeline_watch_callback, name)
|
|||||||
if (pipeline->success) {
|
if (pipeline->success) {
|
||||||
logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
|
logf_success("Successfully compiled pipeline \"%F\" in %F seconds", FMT_STR(pipeline->name), FMT_FLOAT(SECONDS_FROM_NS(pipeline->compilation_time_ns)));
|
||||||
if (pipeline->error.len > 0) {
|
if (pipeline->error.len > 0) {
|
||||||
struct string msg = string_format(scratch.arena, LIT("Warning while compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(pipeline->error));
|
String msg = string_format(scratch.arena, LIT("Warning while compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(pipeline->error));
|
||||||
log_warning(msg);
|
log_warning(msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
{
|
{
|
||||||
struct string error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
String error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
||||||
struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
String msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
||||||
log_error(msg);
|
log_error(msg);
|
||||||
}
|
}
|
||||||
struct pipeline *old_pipeline = (struct pipeline *)dict_get(G.top_successful_pipelines, pipeline->hash);
|
struct pipeline *old_pipeline = (struct pipeline *)dict_get(G.top_successful_pipelines, pipeline->hash);
|
||||||
if (!old_pipeline) {
|
if (!old_pipeline) {
|
||||||
/* If no previously successful pipeline exists, then show a message box rather than logging since logs may not be visible to user */
|
/* If no previously successful pipeline exists, then show a message box rather than logging since logs may not be visible to user */
|
||||||
struct string error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
String error = pipeline->error.len > 0 ? pipeline->error : LIT("Unknown error");
|
||||||
struct string msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
String msg = string_format(scratch.arena, LIT("Error compiling pipeline \"%F\":\n\n%F"), FMT_STR(pipeline->name), FMT_STR(error));
|
||||||
sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg);
|
sys_message_box(SYS_MESSAGE_BOX_KIND_WARNING, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1517,7 +1517,7 @@ INTERNAL struct cpu_descriptor_heap *cpu_descriptor_heap_alloc(enum D3D12_DESCRI
|
|||||||
__prof;
|
__prof;
|
||||||
struct cpu_descriptor_heap *dh = 0;
|
struct cpu_descriptor_heap *dh = 0;
|
||||||
{
|
{
|
||||||
struct arena *arena = arena_alloc(MEBI(64));
|
Arena *arena = arena_alloc(MEBI(64));
|
||||||
dh = arena_push(arena, struct cpu_descriptor_heap);
|
dh = arena_push(arena, struct cpu_descriptor_heap);
|
||||||
dh->arena = arena;
|
dh->arena = arena;
|
||||||
}
|
}
|
||||||
@ -1663,7 +1663,7 @@ INTERNAL void dx12_resource_release_now(struct dx12_resource *t)
|
|||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gp_resource_release(struct gp_resource *resource)
|
void gp_resource_release(G_Resource *resource)
|
||||||
{
|
{
|
||||||
struct dx12_resource *r = (struct dx12_resource *)resource;
|
struct dx12_resource *r = (struct dx12_resource *)resource;
|
||||||
fenced_release(r, FENCED_RELEASE_KIND_RESOURCE);
|
fenced_release(r, FENCED_RELEASE_KIND_RESOURCE);
|
||||||
@ -1682,7 +1682,7 @@ struct dx12_resource_barrier_desc {
|
|||||||
INTERNAL void dx12_resource_barriers(ID3D12GraphicsCommandList *cl, i32 num_descs, struct dx12_resource_barrier_desc *descs)
|
INTERNAL void dx12_resource_barriers(ID3D12GraphicsCommandList *cl, i32 num_descs, struct dx12_resource_barrier_desc *descs)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
i32 num_rbs = 0;
|
i32 num_rbs = 0;
|
||||||
struct D3D12_RESOURCE_BARRIER *rbs = arena_push_array_no_zero(scratch.arena, struct D3D12_RESOURCE_BARRIER, num_descs);
|
struct D3D12_RESOURCE_BARRIER *rbs = arena_push_array_no_zero(scratch.arena, struct D3D12_RESOURCE_BARRIER, num_descs);
|
||||||
@ -1737,7 +1737,7 @@ INTERNAL SYS_JOB_DEF(command_queue_alloc_job, job)
|
|||||||
{
|
{
|
||||||
struct command_queue *cq = 0;
|
struct command_queue *cq = 0;
|
||||||
{
|
{
|
||||||
struct arena *arena = arena_alloc(GIBI(64));
|
Arena *arena = arena_alloc(GIBI(64));
|
||||||
cq = arena_push(arena, struct command_queue);
|
cq = arena_push(arena, struct command_queue);
|
||||||
cq->arena = arena;
|
cq->arena = arena;
|
||||||
}
|
}
|
||||||
@ -1779,7 +1779,7 @@ INTERNAL struct command_list_pool *command_list_pool_alloc(struct command_queue
|
|||||||
{
|
{
|
||||||
struct command_list_pool *pool = 0;
|
struct command_list_pool *pool = 0;
|
||||||
{
|
{
|
||||||
struct arena *arena = arena_alloc(GIBI(64));
|
Arena *arena = arena_alloc(GIBI(64));
|
||||||
pool = arena_push(arena, struct command_list_pool);
|
pool = arena_push(arena, struct command_list_pool);
|
||||||
pool->arena = arena;
|
pool->arena = arena;
|
||||||
}
|
}
|
||||||
@ -2075,7 +2075,7 @@ INTERNAL struct command_buffer *_command_list_push_buffer(struct command_list *c
|
|||||||
|
|
||||||
{
|
{
|
||||||
u64 group_hash = command_buffer_hash_from_size(size);
|
u64 group_hash = command_buffer_hash_from_size(size);
|
||||||
struct dict_entry *cb_group_entry = dict_ensure_entry(G.command_buffers_arena, G.command_buffers_dict, group_hash);
|
DictEntry *cb_group_entry = dict_ensure_entry(G.command_buffers_arena, G.command_buffers_dict, group_hash);
|
||||||
cb_group = (struct command_buffer_group *)cb_group_entry->value;
|
cb_group = (struct command_buffer_group *)cb_group_entry->value;
|
||||||
if (!cb_group) {
|
if (!cb_group) {
|
||||||
/* Create group */
|
/* Create group */
|
||||||
@ -2204,7 +2204,7 @@ INTERNAL SYS_JOB_DEF(dx12_wait_fence_job, job)
|
|||||||
* Texture
|
* Texture
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gp_resource *gp_texture_alloc(enum gp_texture_format format, u32 flags, struct v2i32 size, void *initial_data)
|
G_Resource *gp_texture_alloc(G_TextureFormat format, u32 flags, V2i32 size, void *initial_data)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
if (size.x <= 0 || size.y <= 0) {
|
if (size.x <= 0 || size.y <= 0) {
|
||||||
@ -2268,10 +2268,10 @@ struct gp_resource *gp_texture_alloc(enum gp_texture_format format, u32 flags, s
|
|||||||
snc_counter_wait(&counter);
|
snc_counter_wait(&counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct gp_resource *)r;
|
return (G_Resource *)r;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2i32 gp_texture_get_size(struct gp_resource *resource)
|
V2i32 gp_texture_get_size(G_Resource *resource)
|
||||||
{
|
{
|
||||||
struct dx12_resource *r = (struct dx12_resource *)resource;
|
struct dx12_resource *r = (struct dx12_resource *)resource;
|
||||||
return r->texture_size;
|
return r->texture_size;
|
||||||
@ -2418,7 +2418,7 @@ INTERNAL void command_list_set_sig(struct command_list *cl, void *src, u32 size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct D3D12_VIEWPORT viewport_from_rect(struct rect r)
|
INTERNAL struct D3D12_VIEWPORT viewport_from_rect(Rect r)
|
||||||
{
|
{
|
||||||
struct D3D12_VIEWPORT viewport = ZI;
|
struct D3D12_VIEWPORT viewport = ZI;
|
||||||
viewport.TopLeftX = r.x;
|
viewport.TopLeftX = r.x;
|
||||||
@ -2430,7 +2430,7 @@ INTERNAL struct D3D12_VIEWPORT viewport_from_rect(struct rect r)
|
|||||||
return viewport;
|
return viewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL D3D12_RECT scissor_from_rect(struct rect r)
|
INTERNAL D3D12_RECT scissor_from_rect(Rect r)
|
||||||
{
|
{
|
||||||
D3D12_RECT scissor = ZI;
|
D3D12_RECT scissor = ZI;
|
||||||
scissor.left = r.x;
|
scissor.left = r.x;
|
||||||
@ -2458,7 +2458,7 @@ INTERNAL D3D12_INDEX_BUFFER_VIEW ibv_from_command_buffer(struct command_buffer *
|
|||||||
return ibv;
|
return ibv;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct dx12_resource *gbuff_alloc(DXGI_FORMAT format, struct v2i32 size, D3D12_RESOURCE_STATES initial_state)
|
INTERNAL struct dx12_resource *gbuff_alloc(DXGI_FORMAT format, V2i32 size, D3D12_RESOURCE_STATES initial_state)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
|
D3D12_HEAP_PROPERTIES heap_props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
|
||||||
@ -2493,10 +2493,10 @@ INTERNAL struct dx12_resource *gbuff_alloc(DXGI_FORMAT format, struct v2i32 size
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the view projection matrix */
|
/* Calculate the view projection matrix */
|
||||||
INLINE struct mat4x4 calculate_vp(struct xform view, f32 viewport_width, f32 viewport_height)
|
INLINE Mat4x4 calculate_vp(Xform view, f32 viewport_width, f32 viewport_height)
|
||||||
{
|
{
|
||||||
struct mat4x4 projection = mat4x4_from_ortho(0.0, viewport_width, viewport_height, 0.0, -1.0, 1.0);
|
Mat4x4 projection = mat4x4_from_ortho(0.0, viewport_width, viewport_height, 0.0, -1.0, 1.0);
|
||||||
struct mat4x4 view4x4 = mat4x4_from_xform(view);
|
Mat4x4 view4x4 = mat4x4_from_xform(view);
|
||||||
return mat4x4_mul(projection, view4x4);
|
return mat4x4_mul(projection, view4x4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2512,25 +2512,25 @@ INTERNAL D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle_from_descriptor(struct descripto
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct render_sig {
|
struct render_sig {
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct rand_state rand;
|
RandState rand;
|
||||||
u32 frame_index;
|
u32 frame_index;
|
||||||
|
|
||||||
/* Material instances */
|
/* Material instances */
|
||||||
u32 num_material_instance_descs;
|
u32 num_material_instance_descs;
|
||||||
struct arena *material_instance_descs_arena;
|
Arena *material_instance_descs_arena;
|
||||||
|
|
||||||
/* Ui instances */
|
/* Ui instances */
|
||||||
u32 num_ui_rect_instance_descs;
|
u32 num_ui_rect_instance_descs;
|
||||||
struct arena *ui_rect_instance_descs_arena;
|
Arena *ui_rect_instance_descs_arena;
|
||||||
|
|
||||||
/* UI shapes */
|
/* UI shapes */
|
||||||
struct arena *ui_shape_verts_arena;
|
Arena *ui_shape_verts_arena;
|
||||||
struct arena *ui_shape_indices_arena;
|
Arena *ui_shape_indices_arena;
|
||||||
|
|
||||||
/* Grids */
|
/* Grids */
|
||||||
u32 num_material_grid_descs;
|
u32 num_material_grid_descs;
|
||||||
struct arena *material_grid_descs_arena;
|
Arena *material_grid_descs_arena;
|
||||||
|
|
||||||
/* Resources */
|
/* Resources */
|
||||||
struct dx12_resource *albedo;
|
struct dx12_resource *albedo;
|
||||||
@ -2543,26 +2543,26 @@ struct render_sig {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct material_instance_desc {
|
struct material_instance_desc {
|
||||||
struct xform xf;
|
Xform xf;
|
||||||
u32 texture_id;
|
u32 texture_id;
|
||||||
struct clip_rect clip;
|
ClipRect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
b32 is_light;
|
b32 is_light;
|
||||||
struct v3 light_emittance;
|
V3 light_emittance;
|
||||||
u32 grid_id;
|
u32 grid_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ui_rect_instance_desc {
|
struct ui_rect_instance_desc {
|
||||||
struct xform xf;
|
Xform xf;
|
||||||
u32 texture_id;
|
u32 texture_id;
|
||||||
struct clip_rect clip;
|
ClipRect clip;
|
||||||
u32 tint;
|
u32 tint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct material_grid_desc {
|
struct material_grid_desc {
|
||||||
f32 line_thickness;
|
f32 line_thickness;
|
||||||
f32 line_spacing;
|
f32 line_spacing;
|
||||||
struct v2 offset;
|
V2 offset;
|
||||||
u32 bg0_color;
|
u32 bg0_color;
|
||||||
u32 bg1_color;
|
u32 bg1_color;
|
||||||
u32 line_color;
|
u32 line_color;
|
||||||
@ -2575,7 +2575,7 @@ INTERNAL struct render_sig *render_sig_alloc(void)
|
|||||||
__prof;
|
__prof;
|
||||||
struct render_sig *sig = 0;
|
struct render_sig *sig = 0;
|
||||||
{
|
{
|
||||||
struct arena *arena = arena_alloc(MEBI(64));
|
Arena *arena = arena_alloc(MEBI(64));
|
||||||
sig = arena_push(arena, struct render_sig);
|
sig = arena_push(arena, struct render_sig);
|
||||||
sig->arena = arena;
|
sig->arena = arena;
|
||||||
}
|
}
|
||||||
@ -2610,14 +2610,14 @@ INTERNAL void render_sig_reset(struct render_sig *sig)
|
|||||||
arena_reset(sig->material_grid_descs_arena);
|
arena_reset(sig->material_grid_descs_arena);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gp_render_sig *gp_render_sig_alloc(void)
|
G_RenderSig *gp_render_sig_alloc(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct render_sig *sig = render_sig_alloc();
|
struct render_sig *sig = render_sig_alloc();
|
||||||
return (struct gp_render_sig *)sig;
|
return (G_RenderSig *)sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 gp_push_render_cmd(struct gp_render_sig *render_sig, struct gp_render_cmd_desc *cmd_desc)
|
u32 gp_push_render_cmd(G_RenderSig *render_sig, G_RenderCmdDesc *cmd_desc)
|
||||||
{
|
{
|
||||||
u32 ret = 0;
|
u32 ret = 0;
|
||||||
struct render_sig *sig = (struct render_sig *)render_sig;
|
struct render_sig *sig = (struct render_sig *)render_sig;
|
||||||
@ -2657,8 +2657,8 @@ u32 gp_push_render_cmd(struct gp_render_sig *render_sig, struct gp_render_cmd_de
|
|||||||
u32 *indices = arena_push_array_no_zero(sig->ui_shape_indices_arena, u32, cmd_desc->ui_shape.indices.count);
|
u32 *indices = arena_push_array_no_zero(sig->ui_shape_indices_arena, u32, cmd_desc->ui_shape.indices.count);
|
||||||
for (u32 i = 0; i < cmd_desc->ui_shape.vertices.count; ++i) {
|
for (u32 i = 0; i < cmd_desc->ui_shape.vertices.count; ++i) {
|
||||||
struct k_shape_vert *v = &verts[i];
|
struct k_shape_vert *v = &verts[i];
|
||||||
v->pos = k_float2_from_v2(cmd_desc->ui_shape.vertices.points[i]);
|
v->pos = K_Float2FromV2(cmd_desc->ui_shape.vertices.points[i]);
|
||||||
v->color_srgb = k_uint_from_u32(color);
|
v->color_srgb = K_UintFromU32(color);
|
||||||
}
|
}
|
||||||
u32 vert_offset = verts - (struct k_shape_vert *)arena_base(sig->ui_shape_verts_arena);
|
u32 vert_offset = verts - (struct k_shape_vert *)arena_base(sig->ui_shape_verts_arena);
|
||||||
for (u32 i = 0; i < cmd_desc->ui_shape.indices.count; ++i) {
|
for (u32 i = 0; i < cmd_desc->ui_shape.indices.count; ++i) {
|
||||||
@ -2688,20 +2688,20 @@ u32 gp_push_render_cmd(struct gp_render_sig *render_sig, struct gp_render_cmd_de
|
|||||||
* Render
|
* Render
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp_render_params params)
|
G_Resource *gp_run_render(G_RenderSig *gp_render_sig, G_RenderParams params)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct render_sig *rsig = (struct render_sig *)gp_render_sig;
|
struct render_sig *rsig = (struct render_sig *)gp_render_sig;
|
||||||
++rsig->frame_index;
|
++rsig->frame_index;
|
||||||
|
|
||||||
struct v2i32 ui_size = V2I32(max_i32(params.ui_size.x, 1), max_i32(params.ui_size.y, 1));
|
V2i32 ui_size = V2i32FromXY(max_i32(params.ui_size.x, 1), max_i32(params.ui_size.y, 1));
|
||||||
struct v2i32 render_size = V2I32(max_i32(params.render_size.x, 1), max_i32(params.render_size.y, 1));
|
V2i32 render_size = V2i32FromXY(max_i32(params.render_size.x, 1), max_i32(params.render_size.y, 1));
|
||||||
struct xform world_to_render_xf = params.world_to_render_xf;
|
Xform world_to_render_xf = params.world_to_render_xf;
|
||||||
struct xform render_to_ui_xf = params.render_to_ui_xf;
|
Xform render_to_ui_xf = params.render_to_ui_xf;
|
||||||
|
|
||||||
struct rect ui_viewport = RECT_FROM_V2(V2(0, 0), V2(ui_size.x, ui_size.y));
|
Rect ui_viewport = RECT_FROM_V2(V2FromXY(0, 0), V2FromXY(ui_size.x, ui_size.y));
|
||||||
struct rect render_viewport = RECT_FROM_V2(V2(0, 0), V2(render_size.x, render_size.y));
|
Rect render_viewport = RECT_FROM_V2(V2FromXY(0, 0), V2FromXY(render_size.x, render_size.y));
|
||||||
|
|
||||||
|
|
||||||
/* Allocate render buffers */
|
/* Allocate render buffers */
|
||||||
@ -2746,13 +2746,13 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
{
|
{
|
||||||
__profn("Run render");
|
__profn("Run render");
|
||||||
__profnc_dx12(cl->cq->prof, cl->cl, "Run render", RGB32_F(0.5, 0.2, 0.2));
|
__profnc_dx12(cl->cq->prof, cl->cl, "Run render", RGB32_F(0.5, 0.2, 0.2));
|
||||||
struct mat4x4 world_to_render_vp_matrix = calculate_vp(world_to_render_xf, render_viewport.width, render_viewport.height);
|
Mat4x4 world_to_render_vp_matrix = calculate_vp(world_to_render_xf, render_viewport.width, render_viewport.height);
|
||||||
struct mat4x4 ui_vp_matrix = calculate_vp(XFORM_IDENT, ui_viewport.width, ui_viewport.height);
|
Mat4x4 ui_vp_matrix = calculate_vp(XFORM_IDENT, ui_viewport.width, ui_viewport.height);
|
||||||
struct mat4x4 blit_vp_matrix = ZI;
|
Mat4x4 blit_vp_matrix = ZI;
|
||||||
{
|
{
|
||||||
struct xform xf = render_to_ui_xf;
|
Xform xf = render_to_ui_xf;
|
||||||
xf = xform_scaled(xf, V2(render_size.x, render_size.y));
|
xf = xform_scaled(xf, V2FromXY(render_size.x, render_size.y));
|
||||||
xf = xform_translated(xf, V2(0.5, 0.5));
|
xf = xform_translated(xf, V2FromXY(0.5, 0.5));
|
||||||
blit_vp_matrix = calculate_vp(xf, ui_viewport.width, ui_viewport.height);
|
blit_vp_matrix = calculate_vp(xf, ui_viewport.width, ui_viewport.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2776,14 +2776,14 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
for (u32 i = 0; i < rsig->num_material_instance_descs; ++i) {
|
for (u32 i = 0; i < rsig->num_material_instance_descs; ++i) {
|
||||||
struct material_instance_desc *desc = &((struct material_instance_desc *)arena_base(rsig->material_instance_descs_arena))[i];
|
struct material_instance_desc *desc = &((struct material_instance_desc *)arena_base(rsig->material_instance_descs_arena))[i];
|
||||||
struct k_material_instance *instance = &material_instances[i];
|
struct k_material_instance *instance = &material_instances[i];
|
||||||
instance->tex_nurid = k_uint_from_u32(desc->texture_id);
|
instance->tex_nurid = K_UintFromU32(desc->texture_id);
|
||||||
instance->grid_id = k_uint_from_u32(desc->grid_id);
|
instance->grid_id = K_UintFromU32(desc->grid_id);
|
||||||
instance->xf = k_float2x3_from_xform(desc->xf);
|
instance->xf = K_Float2x3FromXform(desc->xf);
|
||||||
instance->uv0 = k_float2_from_v2(desc->clip.p0);
|
instance->uv0 = K_Float2FromV2(desc->clip.p0);
|
||||||
instance->uv1 = k_float2_from_v2(desc->clip.p1);
|
instance->uv1 = K_Float2FromV2(desc->clip.p1);
|
||||||
instance->tint_srgb = k_uint_from_u32(desc->tint);
|
instance->tint_srgb = K_UintFromU32(desc->tint);
|
||||||
instance->is_light = k_uint_from_u32(desc->is_light);
|
instance->is_light = K_UintFromU32(desc->is_light);
|
||||||
instance->light_emittance_srgb = k_float3_from_v3(desc->light_emittance);
|
instance->light_emittance_srgb = K_Float3FromV3(desc->light_emittance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2793,11 +2793,11 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
for (u32 i = 0; i < rsig->num_ui_rect_instance_descs; ++i) {
|
for (u32 i = 0; i < rsig->num_ui_rect_instance_descs; ++i) {
|
||||||
struct ui_rect_instance_desc *desc = &((struct ui_rect_instance_desc *)arena_base(rsig->ui_rect_instance_descs_arena))[i];
|
struct ui_rect_instance_desc *desc = &((struct ui_rect_instance_desc *)arena_base(rsig->ui_rect_instance_descs_arena))[i];
|
||||||
struct k_ui_instance *instance = &ui_rect_instances[i];
|
struct k_ui_instance *instance = &ui_rect_instances[i];
|
||||||
instance->tex_nurid = k_uint_from_u32(desc->texture_id);
|
instance->tex_nurid = K_UintFromU32(desc->texture_id);
|
||||||
instance->xf = k_float2x3_from_xform(desc->xf);
|
instance->xf = K_Float2x3FromXform(desc->xf);
|
||||||
instance->uv0 = k_float2_from_v2(desc->clip.p0);
|
instance->uv0 = K_Float2FromV2(desc->clip.p0);
|
||||||
instance->uv1 = k_float2_from_v2(desc->clip.p1);
|
instance->uv1 = K_Float2FromV2(desc->clip.p1);
|
||||||
instance->tint_srgb = k_uint_from_u32(desc->tint);
|
instance->tint_srgb = K_UintFromU32(desc->tint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2807,14 +2807,14 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
for (u32 i = 0; i < rsig->num_material_grid_descs; ++i) {
|
for (u32 i = 0; i < rsig->num_material_grid_descs; ++i) {
|
||||||
struct material_grid_desc *desc = &((struct material_grid_desc *)arena_base(rsig->material_grid_descs_arena))[i];
|
struct material_grid_desc *desc = &((struct material_grid_desc *)arena_base(rsig->material_grid_descs_arena))[i];
|
||||||
struct k_material_grid *grid = &grids[i];
|
struct k_material_grid *grid = &grids[i];
|
||||||
grid->line_thickness = k_float_from_f32(desc->line_thickness);
|
grid->line_thickness = K_FloatFromF32(desc->line_thickness);
|
||||||
grid->line_spacing = k_float_from_f32(desc->line_spacing);
|
grid->line_spacing = K_FloatFromF32(desc->line_spacing);
|
||||||
grid->offset = k_float2_from_v2(desc->offset);
|
grid->offset = K_Float2FromV2(desc->offset);
|
||||||
grid->bg0_srgb = k_uint_from_u32(desc->bg0_color);
|
grid->bg0_srgb = K_UintFromU32(desc->bg0_color);
|
||||||
grid->bg1_srgb = k_uint_from_u32(desc->bg1_color);
|
grid->bg1_srgb = K_UintFromU32(desc->bg1_color);
|
||||||
grid->line_srgb = k_uint_from_u32(desc->line_color);
|
grid->line_srgb = K_UintFromU32(desc->line_color);
|
||||||
grid->x_srgb = k_uint_from_u32(desc->x_color);
|
grid->x_srgb = K_UintFromU32(desc->x_color);
|
||||||
grid->y_srgb = k_uint_from_u32(desc->y_color);
|
grid->y_srgb = K_UintFromU32(desc->y_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2874,9 +2874,9 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
|
|
||||||
/* Set sig */
|
/* Set sig */
|
||||||
struct k_material_sig sig = ZI;
|
struct k_material_sig sig = ZI;
|
||||||
sig.projection = k_float4x4_from_mat4x4(world_to_render_vp_matrix);
|
sig.projection = K_Float4x4FromMat4x4(world_to_render_vp_matrix);
|
||||||
sig.instances_urid = k_uint_from_u32(material_instance_buffer->resource->srv_descriptor->index);
|
sig.instances_urid = K_UintFromU32(material_instance_buffer->resource->srv_descriptor->index);
|
||||||
sig.grids_urid = k_uint_from_u32(grid_buffer->resource->srv_descriptor->index);
|
sig.grids_urid = K_UintFromU32(grid_buffer->resource->srv_descriptor->index);
|
||||||
command_list_set_sig(cl, &sig, sizeof(sig));
|
command_list_set_sig(cl, &sig, sizeof(sig));
|
||||||
|
|
||||||
/* Draw */
|
/* Draw */
|
||||||
@ -2932,12 +2932,12 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
|
|
||||||
/* Set sig */
|
/* Set sig */
|
||||||
struct k_flood_sig sig = ZI;
|
struct k_flood_sig sig = ZI;
|
||||||
sig.step_len = k_int_from_i32(step_length);
|
sig.step_len = K_IntFromI32(step_length);
|
||||||
sig.emittance_tex_urid = k_uint_from_u32(rsig->emittance->srv_descriptor->index);
|
sig.emittance_tex_urid = K_UintFromU32(rsig->emittance->srv_descriptor->index);
|
||||||
sig.read_flood_tex_urid = k_uint_from_u32(rsig->emittance_flood_read->uav_descriptor->index);
|
sig.read_flood_tex_urid = K_UintFromU32(rsig->emittance_flood_read->uav_descriptor->index);
|
||||||
sig.target_flood_tex_urid = k_uint_from_u32(rsig->emittance_flood_target->uav_descriptor->index);
|
sig.target_flood_tex_urid = K_UintFromU32(rsig->emittance_flood_target->uav_descriptor->index);
|
||||||
sig.tex_width = k_uint_from_u32(render_size.x);
|
sig.tex_width = K_UintFromU32(render_size.x);
|
||||||
sig.tex_height = k_uint_from_u32(render_size.y);
|
sig.tex_height = K_UintFromU32(render_size.y);
|
||||||
command_list_set_sig(cl, &sig, sizeof(sig));
|
command_list_set_sig(cl, &sig, sizeof(sig));
|
||||||
|
|
||||||
/* Dispatch */
|
/* Dispatch */
|
||||||
@ -3000,20 +3000,20 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
|
|
||||||
/* Set sig */
|
/* Set sig */
|
||||||
struct k_shade_sig sig = ZI;
|
struct k_shade_sig sig = ZI;
|
||||||
sig.flags = k_uint_from_u32(shade_flags);
|
sig.flags = K_UintFromU32(shade_flags);
|
||||||
sig.tex_width = k_uint_from_u32(render_size.x);
|
sig.tex_width = K_UintFromU32(render_size.x);
|
||||||
sig.tex_height = k_uint_from_u32(render_size.y);
|
sig.tex_height = K_UintFromU32(render_size.y);
|
||||||
sig.frame_seed = k_uint4_from_u32((u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
sig.frame_seed = K_Uint4FromU32((u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
||||||
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
||||||
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF),
|
||||||
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF));
|
(u32)(rand_u64_from_state(&rsig->rand) & 0xFFFFFFFF));
|
||||||
sig.frame_index = k_uint_from_u32(rsig->frame_index);
|
sig.frame_index = K_UintFromU32(rsig->frame_index);
|
||||||
sig.camera_offset = k_float2_from_v2(world_to_render_xf.og);
|
sig.camera_offset = K_Float2FromV2(world_to_render_xf.og);
|
||||||
sig.albedo_tex_urid = k_uint_from_u32(rsig->albedo->srv_descriptor->index);
|
sig.albedo_tex_urid = K_UintFromU32(rsig->albedo->srv_descriptor->index);
|
||||||
sig.emittance_tex_urid = k_uint_from_u32(rsig->emittance->srv_descriptor->index);
|
sig.emittance_tex_urid = K_UintFromU32(rsig->emittance->srv_descriptor->index);
|
||||||
sig.emittance_flood_tex_urid = k_uint_from_u32(rsig->emittance_flood_read->srv_descriptor->index);
|
sig.emittance_flood_tex_urid = K_UintFromU32(rsig->emittance_flood_read->srv_descriptor->index);
|
||||||
sig.read_tex_urid = k_uint_from_u32(rsig->shade_read->uav_descriptor->index);
|
sig.read_tex_urid = K_UintFromU32(rsig->shade_read->uav_descriptor->index);
|
||||||
sig.target_tex_urid = k_uint_from_u32(rsig->shade_target->uav_descriptor->index);
|
sig.target_tex_urid = K_UintFromU32(rsig->shade_target->uav_descriptor->index);
|
||||||
command_list_set_sig(cl, &sig, sizeof(sig));
|
command_list_set_sig(cl, &sig, sizeof(sig));
|
||||||
|
|
||||||
/* Dispatch */
|
/* Dispatch */
|
||||||
@ -3062,11 +3062,11 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
|
|
||||||
/* Set sig */
|
/* Set sig */
|
||||||
struct k_blit_sig sig = ZI;
|
struct k_blit_sig sig = ZI;
|
||||||
sig.projection = k_float4x4_from_mat4x4(blit_vp_matrix);
|
sig.projection = K_Float4x4FromMat4x4(blit_vp_matrix);
|
||||||
sig.flags = k_uint_from_u32(K_BLIT_FLAG_TONE_MAP | K_BLIT_FLAG_GAMMA_CORRECT);
|
sig.flags = K_UintFromU32(K_BLIT_FLAG_TONE_MAP | K_BLIT_FLAG_GAMMA_CORRECT);
|
||||||
sig.exposure = k_float_from_f32(2.0);
|
sig.exposure = K_FloatFromF32(2.0);
|
||||||
sig.gamma = k_float_from_f32((f32)2.2);
|
sig.gamma = K_FloatFromF32((f32)2.2);
|
||||||
sig.tex_urid = k_uint_from_u32(rsig->shade_read->uav_descriptor->index);
|
sig.tex_urid = K_UintFromU32(rsig->shade_read->uav_descriptor->index);
|
||||||
command_list_set_sig(cl, &sig, sizeof(sig));
|
command_list_set_sig(cl, &sig, sizeof(sig));
|
||||||
|
|
||||||
/* Draw */
|
/* Draw */
|
||||||
@ -3094,8 +3094,8 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
|
|
||||||
/* Set sig */
|
/* Set sig */
|
||||||
struct k_ui_sig sig = ZI;
|
struct k_ui_sig sig = ZI;
|
||||||
sig.projection = k_float4x4_from_mat4x4(ui_vp_matrix);
|
sig.projection = K_Float4x4FromMat4x4(ui_vp_matrix);
|
||||||
sig.instances_urid = k_uint_from_u32(ui_rect_instance_buffer->resource->srv_descriptor->index);
|
sig.instances_urid = K_UintFromU32(ui_rect_instance_buffer->resource->srv_descriptor->index);
|
||||||
command_list_set_sig(cl, &sig, sizeof(sig));
|
command_list_set_sig(cl, &sig, sizeof(sig));
|
||||||
|
|
||||||
/* Draw */
|
/* Draw */
|
||||||
@ -3124,8 +3124,8 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
|
|
||||||
/* Set sig */
|
/* Set sig */
|
||||||
struct k_shape_sig sig = ZI;
|
struct k_shape_sig sig = ZI;
|
||||||
sig.projection = k_float4x4_from_mat4x4(ui_vp_matrix);
|
sig.projection = K_Float4x4FromMat4x4(ui_vp_matrix);
|
||||||
sig.verts_urid = k_uint_from_u32(ui_shape_verts_buffer->resource->srv_descriptor->index);
|
sig.verts_urid = K_UintFromU32(ui_shape_verts_buffer->resource->srv_descriptor->index);
|
||||||
command_list_set_sig(cl, &sig, sizeof(sig));
|
command_list_set_sig(cl, &sig, sizeof(sig));
|
||||||
|
|
||||||
/* Draw */
|
/* Draw */
|
||||||
@ -3144,16 +3144,16 @@ struct gp_resource *gp_run_render(struct gp_render_sig *gp_render_sig, struct gp
|
|||||||
render_sig_reset(rsig);
|
render_sig_reset(rsig);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|
||||||
return (struct gp_resource *)rsig->ui_target;
|
return (G_Resource *)rsig->ui_target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Memory info
|
* Memory info
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct gp_memory_info gp_query_memory_info(void)
|
G_MemoryInfo gp_query_memory_info(void)
|
||||||
{
|
{
|
||||||
struct gp_memory_info res = ZI;
|
G_MemoryInfo res = ZI;
|
||||||
|
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
IDXGIAdapter3 *dxgiAdapter3 = 0;
|
IDXGIAdapter3 *dxgiAdapter3 = 0;
|
||||||
@ -3201,7 +3201,7 @@ INTERNAL void swapchain_init_resources(struct swapchain *swapchain)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct gp_swapchain *gp_swapchain_alloc(struct sys_window *window, struct v2i32 resolution)
|
G_Swapchain *gp_swapchain_alloc(struct sys_window *window, V2i32 resolution)
|
||||||
{
|
{
|
||||||
HRESULT hr = 0;
|
HRESULT hr = 0;
|
||||||
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
|
HWND hwnd = (HWND)sys_window_get_internal_handle(window);
|
||||||
@ -3261,16 +3261,16 @@ struct gp_swapchain *gp_swapchain_alloc(struct sys_window *window, struct v2i32
|
|||||||
|
|
||||||
swapchain_init_resources(swapchain);
|
swapchain_init_resources(swapchain);
|
||||||
|
|
||||||
return (struct gp_swapchain *)swapchain;
|
return (G_Swapchain *)swapchain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gp_swapchain_release(struct gp_swapchain *gp_swapchain)
|
void gp_swapchain_release(G_Swapchain *gp_swapchain)
|
||||||
{
|
{
|
||||||
/* TODO */
|
/* TODO */
|
||||||
(UNUSED)gp_swapchain;
|
(UNUSED)gp_swapchain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gp_swapchain_wait(struct gp_swapchain *gp_swapchain)
|
void gp_swapchain_wait(G_Swapchain *gp_swapchain)
|
||||||
{
|
{
|
||||||
#if DX12_WAIT_FRAME_LATENCY > 0
|
#if DX12_WAIT_FRAME_LATENCY > 0
|
||||||
struct swapchain *swapchain = (struct swapchain *)gp_swapchain;
|
struct swapchain *swapchain = (struct swapchain *)gp_swapchain;
|
||||||
@ -3282,7 +3282,7 @@ void gp_swapchain_wait(struct gp_swapchain *gp_swapchain)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct swapchain_buffer *update_swapchain(struct swapchain *swapchain, struct v2i32 resolution)
|
INTERNAL struct swapchain_buffer *update_swapchain(struct swapchain *swapchain, V2i32 resolution)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
resolution.x = max_i32(resolution.x, 1);
|
resolution.x = max_i32(resolution.x, 1);
|
||||||
@ -3335,7 +3335,7 @@ INTERNAL struct swapchain_buffer *update_swapchain(struct swapchain *swapchain,
|
|||||||
* Present
|
* Present
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL void present_blit(struct swapchain_buffer *dst, struct dx12_resource *src, struct xform src_xf)
|
INTERNAL void present_blit(struct swapchain_buffer *dst, struct dx12_resource *src, Xform src_xf)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct pipeline_scope *pipeline_scope = pipeline_scope_begin();
|
struct pipeline_scope *pipeline_scope = pipeline_scope_begin();
|
||||||
@ -3360,15 +3360,15 @@ INTERNAL void present_blit(struct swapchain_buffer *dst, struct dx12_resource *s
|
|||||||
ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap };
|
ID3D12DescriptorHeap *heaps[] = { descriptor_heap->heap };
|
||||||
ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, countof(heaps), heaps);
|
ID3D12GraphicsCommandList_SetDescriptorHeaps(cl->cl, countof(heaps), heaps);
|
||||||
|
|
||||||
struct rect viewport_rect = RECT_FROM_V2(V2(0, 0), V2(swapchain->resolution.x, swapchain->resolution.y));
|
Rect viewport_rect = RECT_FROM_V2(V2FromXY(0, 0), V2FromXY(swapchain->resolution.x, swapchain->resolution.y));
|
||||||
D3D12_VIEWPORT viewport = viewport_from_rect(viewport_rect);
|
D3D12_VIEWPORT viewport = viewport_from_rect(viewport_rect);
|
||||||
D3D12_RECT scissor = scissor_from_rect(viewport_rect);
|
D3D12_RECT scissor = scissor_from_rect(viewport_rect);
|
||||||
|
|
||||||
struct mat4x4 vp_matrix = ZI;
|
Mat4x4 vp_matrix = ZI;
|
||||||
{
|
{
|
||||||
struct xform xf = src_xf;
|
Xform xf = src_xf;
|
||||||
xf = xform_scaled(xf, V2(src->texture_size.x, src->texture_size.y));
|
xf = xform_scaled(xf, V2FromXY(src->texture_size.x, src->texture_size.y));
|
||||||
xf = xform_translated(xf, V2(0.5, 0.5));
|
xf = xform_translated(xf, V2FromXY(0.5, 0.5));
|
||||||
vp_matrix = calculate_vp(xf, viewport.Width, viewport.Height);
|
vp_matrix = calculate_vp(xf, viewport.Width, viewport.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3401,9 +3401,9 @@ INTERNAL void present_blit(struct swapchain_buffer *dst, struct dx12_resource *s
|
|||||||
|
|
||||||
/* Set sig */
|
/* Set sig */
|
||||||
struct k_blit_sig sig = ZI;
|
struct k_blit_sig sig = ZI;
|
||||||
sig.projection = k_float4x4_from_mat4x4(vp_matrix);
|
sig.projection = K_Float4x4FromMat4x4(vp_matrix);
|
||||||
sig.flags = k_uint_from_u32(K_BLIT_FLAG_NONE);
|
sig.flags = K_UintFromU32(K_BLIT_FLAG_NONE);
|
||||||
sig.tex_urid = k_uint_from_u32(src->srv_descriptor->index);
|
sig.tex_urid = K_UintFromU32(src->srv_descriptor->index);
|
||||||
command_list_set_sig(cl, &sig, sizeof(sig));
|
command_list_set_sig(cl, &sig, sizeof(sig));
|
||||||
|
|
||||||
/* Draw */
|
/* Draw */
|
||||||
@ -3434,7 +3434,7 @@ INTERNAL void present_blit(struct swapchain_buffer *dst, struct dx12_resource *s
|
|||||||
pipeline_scope_end(pipeline_scope);
|
pipeline_scope_end(pipeline_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gp_present(struct gp_swapchain *gp_swapchain, struct v2i32 backbuffer_resolution, struct gp_resource *texture, struct xform texture_xf, i32 vsync)
|
void gp_present(G_Swapchain *gp_swapchain, V2i32 backbuffer_resolution, G_Resource *texture, Xform texture_xf, i32 vsync)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct swapchain *swapchain = (struct swapchain *)gp_swapchain;
|
struct swapchain *swapchain = (struct swapchain *)gp_swapchain;
|
||||||
@ -3497,7 +3497,7 @@ INTERNAL SYS_JOB_DEF(dx12_evictor_job, _)
|
|||||||
while (!shutdown) {
|
while (!shutdown) {
|
||||||
{
|
{
|
||||||
__profn("Dx12 evictor run");
|
__profn("Dx12 evictor run");
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
u64 targets[countof(completed_targets)] = ZI;
|
u64 targets[countof(completed_targets)] = ZI;
|
||||||
|
|
||||||
/* Copy queued data */
|
/* Copy queued data */
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
#include "host.h"
|
|
||||||
|
|
||||||
#include "host_core.c"
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
#define HOST_CHANNEL_ID_NIL (struct host_channel_id) { .gen = 0, .idx = 0 }
|
|
||||||
#define HOST_CHANNEL_ID_ALL (struct host_channel_id) { .gen = U32_MAX, .idx = U32_MAX }
|
|
||||||
|
|
||||||
struct buddy_ctx;
|
|
||||||
struct host_snd_packet;
|
|
||||||
struct host_channel_lookup_bin;
|
|
||||||
struct host_rcv_buffer;
|
|
||||||
|
|
||||||
enum host_cmd_kind {
|
|
||||||
HOST_CMD_KIND_NONE,
|
|
||||||
|
|
||||||
HOST_CMD_KIND_TRY_CONNECT,
|
|
||||||
HOST_CMD_KIND_CONNECT_SUCCESS,
|
|
||||||
HOST_CMD_KIND_DISCONNECT,
|
|
||||||
HOST_CMD_KIND_HEARTBEAT,
|
|
||||||
HOST_CMD_KIND_WRITE
|
|
||||||
};
|
|
||||||
|
|
||||||
enum host_event_kind {
|
|
||||||
HOST_EVENT_KIND_NONE,
|
|
||||||
|
|
||||||
HOST_EVENT_KIND_CHANNEL_OPENED,
|
|
||||||
HOST_EVENT_KIND_CHANNEL_CLOSED,
|
|
||||||
HOST_EVENT_KIND_MSG
|
|
||||||
};
|
|
||||||
|
|
||||||
enum host_write_flag {
|
|
||||||
HOST_WRITE_FLAG_NONE = 0,
|
|
||||||
|
|
||||||
HOST_WRITE_FLAG_RELIABLE = (1 << 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host_channel_id {
|
|
||||||
u32 gen;
|
|
||||||
u32 idx;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host_cmd {
|
|
||||||
enum host_cmd_kind kind;
|
|
||||||
struct host_channel_id channel_id;
|
|
||||||
|
|
||||||
u16 heartbeat_id;
|
|
||||||
u16 heartbeat_ack_id;
|
|
||||||
|
|
||||||
b32 write_reliable;
|
|
||||||
struct string write_msg;
|
|
||||||
|
|
||||||
|
|
||||||
struct host_cmd *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host_event {
|
|
||||||
enum host_event_kind kind;
|
|
||||||
struct host_channel_id channel_id;
|
|
||||||
struct string msg;
|
|
||||||
|
|
||||||
struct host_event *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host_event_list {
|
|
||||||
struct host_event *first;
|
|
||||||
struct host_event *last;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host {
|
|
||||||
struct arena *arena;
|
|
||||||
|
|
||||||
struct sys_sock *sock;
|
|
||||||
|
|
||||||
struct buddy_ctx *buddy; /* For storing msg assembler data */
|
|
||||||
|
|
||||||
struct arena *cmd_arena;
|
|
||||||
struct host_cmd *first_cmd;
|
|
||||||
struct host_cmd *last_cmd;
|
|
||||||
struct host_cmd *first_free_cmd;
|
|
||||||
|
|
||||||
struct arena *channel_arena;
|
|
||||||
struct host_channel *channels;
|
|
||||||
struct host_channel *first_free_channel;
|
|
||||||
u64 num_channels_reserved;
|
|
||||||
|
|
||||||
struct host_snd_packet *first_free_packet; /* Allocated in `arena` */
|
|
||||||
struct host_msg_assembler *first_free_msg_assembler; /* Allocated in `arena` */
|
|
||||||
|
|
||||||
struct host_channel_lookup_bin *channel_lookup_bins; /* Allocated in `arena` */
|
|
||||||
u64 num_channel_lookup_bins;
|
|
||||||
|
|
||||||
struct host_msg_assembler_lookup_bin *msg_assembler_lookup_bins; /* Allocated in `arena` */
|
|
||||||
u64 num_msg_assembler_lookup_bins;
|
|
||||||
|
|
||||||
/* Double buffer for incoming data */
|
|
||||||
struct snc_mutex rcv_buffer_write_mutex;
|
|
||||||
struct host_rcv_buffer *rcv_buffer_read;
|
|
||||||
struct host_rcv_buffer *rcv_buffer_write;
|
|
||||||
|
|
||||||
u64 bytes_received;
|
|
||||||
u64 bytes_sent;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Startup
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
struct host_startup_receipt { i32 _; };
|
|
||||||
struct host_startup_receipt host_startup(void);
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Host
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
struct host *host_alloc(u16 listen_port);
|
|
||||||
|
|
||||||
void host_release(struct host *host);
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Queue
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
void host_queue_connect_to_address(struct host *host, struct sys_address connect_address);
|
|
||||||
|
|
||||||
void host_queue_disconnect(struct host *host, struct host_channel_id channel_id);
|
|
||||||
|
|
||||||
void host_queue_write(struct host *host, struct host_channel_id channel_id, struct string msg, u32 flags);
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Info
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
i64 host_get_channel_last_rtt_ns(struct host *host, struct host_channel_id channel_id);
|
|
||||||
INLINE b32 host_channel_id_eq(struct host_channel_id a, struct host_channel_id b) { return a.idx == b.idx && a.gen == b.gen; }
|
|
||||||
INLINE b32 host_channel_id_is_nil(struct host_channel_id id) { return id.gen == 0 && id.idx == 0; }
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Update
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
struct host_event_list host_update_begin(struct arena *arena, struct host *host);
|
|
||||||
void host_update_end(struct host *host);
|
|
||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
INCBIN_INCLUDE(res_tar, INCBIN_DIR "res.tar");
|
INCBIN_INCLUDE(res_tar, INCBIN_DIR "res.tar");
|
||||||
struct string inc_res_tar(void)
|
String inc_res_tar(void)
|
||||||
{
|
{
|
||||||
return INCBIN_GET(res_tar);
|
return INCBIN_GET(res_tar);
|
||||||
}
|
}
|
||||||
@ -13,7 +13,7 @@ struct string inc_res_tar(void)
|
|||||||
|
|
||||||
|
|
||||||
INCBIN_INCLUDE(dxc_tar, INCBIN_DIR "dxc.tar");
|
INCBIN_INCLUDE(dxc_tar, INCBIN_DIR "dxc.tar");
|
||||||
struct string inc_dxc_tar(void)
|
String inc_dxc_tar(void)
|
||||||
{
|
{
|
||||||
return INCBIN_GET(dxc_tar);
|
return INCBIN_GET(dxc_tar);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
struct string inc_res_tar(void);
|
String inc_res_tar(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct string inc_dxc_tar(void);
|
String inc_dxc_tar(void);
|
||||||
|
|||||||
@ -63,7 +63,7 @@ enum lex_number_state {
|
|||||||
LEX_NUMBER_STATE_EXPONENT
|
LEX_NUMBER_STATE_EXPONENT
|
||||||
};
|
};
|
||||||
|
|
||||||
GLOBAL READONLY struct string g_keyword_strings[] = {
|
GLOBAL READONLY String g_keyword_strings[] = {
|
||||||
['t'] = LIT_NOCAST("true"),
|
['t'] = LIT_NOCAST("true"),
|
||||||
['f'] = LIT_NOCAST("false"),
|
['f'] = LIT_NOCAST("false"),
|
||||||
['n'] = LIT_NOCAST("null")
|
['n'] = LIT_NOCAST("null")
|
||||||
@ -75,7 +75,7 @@ GLOBAL READONLY enum token_type g_keyword_types[] = {
|
|||||||
['n'] = TOKEN_TYPE_KEYWORD_NULL
|
['n'] = TOKEN_TYPE_KEYWORD_NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL struct token *push_token(struct arena *arena, struct token_list *list)
|
INTERNAL struct token *push_token(Arena *arena, struct token_list *list)
|
||||||
{
|
{
|
||||||
struct token *t = arena_push(arena, struct token);
|
struct token *t = arena_push(arena, struct token);
|
||||||
if (!list->token_first) {
|
if (!list->token_first) {
|
||||||
@ -87,7 +87,7 @@ INTERNAL struct token *push_token(struct arena *arena, struct token_list *list)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct token_list lex(struct arena *arena, struct string src)
|
INTERNAL struct token_list lex(Arena *arena, String src)
|
||||||
{
|
{
|
||||||
struct token_list res = ZI;
|
struct token_list res = ZI;
|
||||||
|
|
||||||
@ -286,7 +286,7 @@ INTERNAL struct token_list lex(struct arena *arena, struct string src)
|
|||||||
case 't':
|
case 't':
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'n': {
|
case 'n': {
|
||||||
struct string keyword = g_keyword_strings[src.text[pos]];
|
String keyword = g_keyword_strings[src.text[pos]];
|
||||||
|
|
||||||
b32 match = 1;
|
b32 match = 1;
|
||||||
if ((pos + keyword.len - 1) < src.len) {
|
if ((pos + keyword.len - 1) < src.len) {
|
||||||
@ -304,7 +304,7 @@ INTERNAL struct token_list lex(struct arena *arena, struct string src)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (match) {
|
if (match) {
|
||||||
struct string cmp_str = {
|
String cmp_str = {
|
||||||
.len = keyword.len,
|
.len = keyword.len,
|
||||||
.text = &src.text[pos]
|
.text = &src.text[pos]
|
||||||
};
|
};
|
||||||
@ -354,13 +354,13 @@ INTERNAL struct token_list lex(struct arena *arena, struct string src)
|
|||||||
* Interpret
|
* Interpret
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL void append_char(struct arena *arena, struct string *str, u8 c)
|
INTERNAL void append_char(Arena *arena, String *str, u8 c)
|
||||||
{
|
{
|
||||||
*arena_push_no_zero(arena, u8) = c;
|
*arena_push_no_zero(arena, u8) = c;
|
||||||
++str->len;
|
++str->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL f64 interpret_number(struct string src)
|
INTERNAL f64 interpret_number(String src)
|
||||||
{
|
{
|
||||||
b32 whole_present = 0;
|
b32 whole_present = 0;
|
||||||
u64 whole_left = 0;
|
u64 whole_left = 0;
|
||||||
@ -522,9 +522,9 @@ INTERNAL f64 interpret_number(struct string src)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct string interpret_string(struct arena *arena, struct string src, struct string *error)
|
INTERNAL String interpret_string(Arena *arena, String src, String *error)
|
||||||
{
|
{
|
||||||
struct string res = {
|
String res = {
|
||||||
.len = 0,
|
.len = 0,
|
||||||
.text = arena_push_dry(arena, u8)
|
.text = arena_push_dry(arena, u8)
|
||||||
};
|
};
|
||||||
@ -634,22 +634,22 @@ INTERNAL struct string interpret_string(struct arena *arena, struct string src,
|
|||||||
|
|
||||||
struct parser {
|
struct parser {
|
||||||
/* Input */
|
/* Input */
|
||||||
struct string src;
|
String src;
|
||||||
struct token *at;
|
struct token *at;
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
struct json *root;
|
JSON_Blob *root;
|
||||||
struct json_error_list errors;
|
JSON_ErrorList errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL void push_error(struct arena *arena, struct parser *p, struct token *t, struct string msg)
|
INTERNAL void push_error(Arena *arena, struct parser *p, struct token *t, String msg)
|
||||||
{
|
{
|
||||||
struct json_error *error = arena_push(arena, struct json_error);
|
JSON_Error *error = arena_push(arena, JSON_Error);
|
||||||
error->msg = msg;
|
error->msg = msg;
|
||||||
error->start = t->start;
|
error->start = t->start;
|
||||||
error->end = t->end;
|
error->end = t->end;
|
||||||
|
|
||||||
struct json_error_list *list = &p->errors;
|
JSON_ErrorList *list = &p->errors;
|
||||||
if (!list->first) {
|
if (!list->first) {
|
||||||
list->first = error;
|
list->first = error;
|
||||||
} else {
|
} else {
|
||||||
@ -659,28 +659,28 @@ INTERNAL void push_error(struct arena *arena, struct parser *p, struct token *t,
|
|||||||
++list->count;
|
++list->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void parse(struct arena *arena, struct parser *p)
|
INTERNAL void parse(Arena *arena, struct parser *p)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
struct json *root = arena_push(arena, struct json);
|
JSON_Blob *root = arena_push(arena, JSON_Blob);
|
||||||
struct token *at = p->at;
|
struct token *at = p->at;
|
||||||
struct string src = p->src;
|
String src = p->src;
|
||||||
|
|
||||||
if (at->type == TOKEN_TYPE_BOF) {
|
if (at->type == TOKEN_TYPE_BOF) {
|
||||||
at = at->next;
|
at = at->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Depth first stack */
|
/* Depth first stack */
|
||||||
*arena_push_no_zero(scratch.arena, struct json *) = root;
|
*arena_push_no_zero(scratch.arena, JSON_Blob *) = root;
|
||||||
u64 stack_count = 1;
|
u64 stack_count = 1;
|
||||||
|
|
||||||
while (stack_count > 0) {
|
while (stack_count > 0) {
|
||||||
struct json *json = 0;
|
JSON_Blob *json = 0;
|
||||||
arena_pop(scratch.arena, struct json *, &json);
|
arena_pop(scratch.arena, JSON_Blob *, &json);
|
||||||
--stack_count;
|
--stack_count;
|
||||||
|
|
||||||
struct json *parent_json = json->parent;
|
JSON_Blob *parent_json = json->parent;
|
||||||
b32 is_new_parent = 0;
|
b32 is_new_parent = 0;
|
||||||
if (json->type == JSON_TYPE_OBJECT || json->type == JSON_TYPE_ARRAY) {
|
if (json->type == JSON_TYPE_OBJECT || json->type == JSON_TYPE_ARRAY) {
|
||||||
/* No more children to parse for object/array, check for closing brace. */
|
/* No more children to parse for object/array, check for closing brace. */
|
||||||
@ -697,9 +697,9 @@ INTERNAL void parse(struct arena *arena, struct parser *p)
|
|||||||
if (parent_json->type == JSON_TYPE_OBJECT) {
|
if (parent_json->type == JSON_TYPE_OBJECT) {
|
||||||
/* Parse key */
|
/* Parse key */
|
||||||
if (at->type == TOKEN_TYPE_STRING) {
|
if (at->type == TOKEN_TYPE_STRING) {
|
||||||
struct string t_text = (struct string) { .len = at->end - at->start, .text = &src.text[at->start] };
|
String t_text = (String) { .len = at->end - at->start, .text = &src.text[at->start] };
|
||||||
struct string error = ZI;
|
String error = ZI;
|
||||||
struct string key = interpret_string(arena, t_text, &error);
|
String key = interpret_string(arena, t_text, &error);
|
||||||
if (error.len > 0) {
|
if (error.len > 0) {
|
||||||
push_error(arena, p, at, error);
|
push_error(arena, p, at, error);
|
||||||
goto abort;
|
goto abort;
|
||||||
@ -732,7 +732,7 @@ INTERNAL void parse(struct arena *arena, struct parser *p)
|
|||||||
/* Parse value */
|
/* Parse value */
|
||||||
switch (at->type) {
|
switch (at->type) {
|
||||||
case TOKEN_TYPE_NUMBER: {
|
case TOKEN_TYPE_NUMBER: {
|
||||||
struct string t_text = (struct string) { .len = at->end - at->start, .text = &src.text[at->start] };
|
String t_text = (String) { .len = at->end - at->start, .text = &src.text[at->start] };
|
||||||
f64 value = interpret_number(t_text);
|
f64 value = interpret_number(t_text);
|
||||||
json->type = JSON_TYPE_NUMBER;
|
json->type = JSON_TYPE_NUMBER;
|
||||||
json->value.number = value;
|
json->value.number = value;
|
||||||
@ -740,9 +740,9 @@ INTERNAL void parse(struct arena *arena, struct parser *p)
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case TOKEN_TYPE_STRING: {
|
case TOKEN_TYPE_STRING: {
|
||||||
struct string t_text = (struct string) { .len = at->end - at->start, .text = &src.text[at->start] };
|
String t_text = (String) { .len = at->end - at->start, .text = &src.text[at->start] };
|
||||||
struct string error = ZI;
|
String error = ZI;
|
||||||
struct string value = interpret_string(arena, t_text, &error);
|
String value = interpret_string(arena, t_text, &error);
|
||||||
if (error.len > 0) {
|
if (error.len > 0) {
|
||||||
push_error(arena, p, at, error);
|
push_error(arena, p, at, error);
|
||||||
goto abort;
|
goto abort;
|
||||||
@ -792,21 +792,21 @@ INTERNAL void parse(struct arena *arena, struct parser *p)
|
|||||||
|
|
||||||
if (is_new_parent) {
|
if (is_new_parent) {
|
||||||
/* Push self back to stack to re-check for closing brace later */
|
/* Push self back to stack to re-check for closing brace later */
|
||||||
*arena_push_no_zero(scratch.arena, struct json *) = json;
|
*arena_push_no_zero(scratch.arena, JSON_Blob *) = json;
|
||||||
++stack_count;
|
++stack_count;
|
||||||
|
|
||||||
/* Create child & push to stack */
|
/* Create child & push to stack */
|
||||||
struct json *child = arena_push(arena, struct json);
|
JSON_Blob *child = arena_push(arena, JSON_Blob);
|
||||||
child->parent = json;
|
child->parent = json;
|
||||||
*arena_push_no_zero(scratch.arena, struct json *) = child;
|
*arena_push_no_zero(scratch.arena, JSON_Blob *) = child;
|
||||||
++stack_count;
|
++stack_count;
|
||||||
} else if (parent_json) {
|
} else if (parent_json) {
|
||||||
/* Check for comma */
|
/* Check for comma */
|
||||||
if (at->type == TOKEN_TYPE_COMMA) {
|
if (at->type == TOKEN_TYPE_COMMA) {
|
||||||
/* Create sibling & push to stack */
|
/* Create sibling & push to stack */
|
||||||
struct json *sibling = arena_push(arena, struct json);
|
JSON_Blob *sibling = arena_push(arena, JSON_Blob);
|
||||||
sibling->parent = parent_json;
|
sibling->parent = parent_json;
|
||||||
*arena_push_no_zero(scratch.arena, struct json *) = sibling;
|
*arena_push_no_zero(scratch.arena, JSON_Blob *) = sibling;
|
||||||
++stack_count;
|
++stack_count;
|
||||||
at = at->next;
|
at = at->next;
|
||||||
}
|
}
|
||||||
@ -825,9 +825,9 @@ INTERNAL void parse(struct arena *arena, struct parser *p)
|
|||||||
* Interface
|
* Interface
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct json_parse_result json_from_string(struct arena *arena, struct string src)
|
JSON_Result json_from_string(Arena *arena, String src)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
struct token_list tl = lex(scratch.arena, src);
|
struct token_list tl = lex(scratch.arena, src);
|
||||||
|
|
||||||
@ -845,7 +845,7 @@ struct json_parse_result json_from_string(struct arena *arena, struct string src
|
|||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|
||||||
return (struct json_parse_result) {
|
return (JSON_Result) {
|
||||||
.root = p.root,
|
.root = p.root,
|
||||||
.errors = p.errors
|
.errors = p.errors
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,44 +1,49 @@
|
|||||||
enum json_type {
|
|
||||||
|
typedef enum JSON_Type {
|
||||||
JSON_TYPE_NULL,
|
JSON_TYPE_NULL,
|
||||||
JSON_TYPE_BOOL,
|
JSON_TYPE_BOOL,
|
||||||
JSON_TYPE_NUMBER,
|
JSON_TYPE_NUMBER,
|
||||||
JSON_TYPE_STRING,
|
JSON_TYPE_STRING,
|
||||||
JSON_TYPE_ARRAY,
|
JSON_TYPE_ARRAY,
|
||||||
JSON_TYPE_OBJECT
|
JSON_TYPE_OBJECT
|
||||||
};
|
} JSON_Type;
|
||||||
|
|
||||||
struct json {
|
typedef struct JSON_Blob JSON_Blob;
|
||||||
enum json_type type;
|
struct JSON_Blob {
|
||||||
struct string key;
|
JSON_Type type;
|
||||||
|
String key;
|
||||||
|
|
||||||
struct json *parent;
|
JSON_Blob *parent;
|
||||||
struct json *next;
|
JSON_Blob *next;
|
||||||
struct json *child_first;
|
JSON_Blob *child_first;
|
||||||
struct json *child_last;
|
JSON_Blob *child_last;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct string string;
|
String string;
|
||||||
f64 number;
|
f64 number;
|
||||||
b32 boolean;
|
b32 boolean;
|
||||||
} value;
|
} value;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct json_error {
|
typedef struct JSON_Error JSON_Error;
|
||||||
struct string msg;
|
struct JSON_Error {
|
||||||
|
String msg;
|
||||||
u64 start;
|
u64 start;
|
||||||
u64 end;
|
u64 end;
|
||||||
struct json_error *next;
|
JSON_Error *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct json_error_list {
|
typedef struct JSON_ErrorList JSON_ErrorList;
|
||||||
|
struct JSON_ErrorList {
|
||||||
u64 count;
|
u64 count;
|
||||||
struct json_error *first;
|
JSON_Error *first;
|
||||||
struct json_error *last;
|
JSON_Error *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct json_parse_result {
|
typedef struct JSON_Result JSON_Result;
|
||||||
struct json *root;
|
struct JSON_Result {
|
||||||
struct json_error_list errors;
|
JSON_Blob *root;
|
||||||
|
JSON_ErrorList errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct json_parse_result json_from_string(struct arena *arena, struct string src);
|
JSON_Result json_from_string(Arena *arena, String src);
|
||||||
|
|||||||
@ -8,71 +8,80 @@
|
|||||||
#if K_IS_CPU
|
#if K_IS_CPU
|
||||||
|
|
||||||
#define K_STRUCT(s) PACK(struct s)
|
#define K_STRUCT(s) PACK(struct s)
|
||||||
#define K_DECL(t, n) struct CAT(k_, t) n
|
#define K_DECL(t, n) struct CAT(K_, t) n
|
||||||
#define K_DECLS(t, n) K_DECL(t, n)
|
#define K_DECLS(t, n) K_DECL(t, n)
|
||||||
#define K_STATIC_ASSERT(c) STATIC_ASSERT(c)
|
#define K_STATIC_ASSERT(c) STATIC_ASSERT(c)
|
||||||
|
|
||||||
struct k_uint { u32 v; };
|
typedef struct K_uint K_uint;
|
||||||
INLINE struct k_uint k_uint_from_u32(u32 v)
|
struct K_uint { u32 v; };
|
||||||
|
INLINE struct K_uint K_UintFromU32(u32 v)
|
||||||
{
|
{
|
||||||
return (struct k_uint) { .v = v };
|
return (struct K_uint) { .v = v };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_int { i32 v; };
|
typedef struct K_int K_int;
|
||||||
INLINE struct k_int k_int_from_i32(i32 v)
|
struct K_int { i32 v; };
|
||||||
|
INLINE struct K_int K_IntFromI32(i32 v)
|
||||||
{
|
{
|
||||||
return (struct k_int) { .v = v };
|
return (struct K_int) { .v = v };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_uint2 { u32 v[2]; };
|
typedef struct K_uint2 K_uint2;
|
||||||
INLINE struct k_uint2 k_uint2_from_u32(u32 x, u32 y)
|
struct K_uint2 { u32 v[2]; };
|
||||||
|
INLINE struct K_uint2 K_Uint2FromU32(u32 x, u32 y)
|
||||||
{
|
{
|
||||||
return (struct k_uint2) { .v[0] = x, .v[1] = y };
|
return (struct K_uint2) { .v[0] = x, .v[1] = y };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_uint3 { u32 v[3]; };
|
typedef struct K_uint3 K_uint3;
|
||||||
INLINE struct k_uint3 k_uint3_from_u32(u32 x, u32 y, u32 z)
|
struct K_uint3 { u32 v[3]; };
|
||||||
|
INLINE struct K_uint3 K_Uint3FromU32(u32 x, u32 y, u32 z)
|
||||||
{
|
{
|
||||||
return (struct k_uint3) { .v[0] = x, .v[1] = y, .v[2] = z };
|
return (struct K_uint3) { .v[0] = x, .v[1] = y, .v[2] = z };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_uint4 { u32 v[4]; };
|
typedef struct K_uint4 K_uint4;
|
||||||
INLINE struct k_uint4 k_uint4_from_u32(u32 x, u32 y, u32 z, u32 w)
|
struct K_uint4 { u32 v[4]; };
|
||||||
|
INLINE struct K_uint4 K_Uint4FromU32(u32 x, u32 y, u32 z, u32 w)
|
||||||
{
|
{
|
||||||
return (struct k_uint4) { .v[0] = x, .v[1] = y, .v[2] = z, .v[3] = w };
|
return (struct K_uint4) { .v[0] = x, .v[1] = y, .v[2] = z, .v[3] = w };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_float { f32 v; };
|
typedef struct K_float K_float;
|
||||||
INLINE struct k_float k_float_from_f32(f32 v)
|
struct K_float { f32 v; };
|
||||||
|
INLINE struct K_float K_FloatFromF32(f32 v)
|
||||||
{
|
{
|
||||||
return (struct k_float) { .v = v };
|
return (struct K_float) { .v = v };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_float2 { f32 v[2]; };
|
typedef struct K_float2 K_float2;
|
||||||
INLINE struct k_float2 k_float2_from_v2(struct v2 v)
|
struct K_float2 { f32 v[2]; };
|
||||||
|
INLINE struct K_float2 K_Float2FromV2(V2 v)
|
||||||
{
|
{
|
||||||
return (struct k_float2) { .v[0] = v.x, .v[1] = v.y };
|
return (struct K_float2) { .v[0] = v.x, .v[1] = v.y };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_float3 { f32 v[3]; };
|
typedef struct K_float3 K_float3;
|
||||||
INLINE struct k_float3 k_float3_from_v3(struct v3 v)
|
struct K_float3 { f32 v[3]; };
|
||||||
|
INLINE struct K_float3 K_Float3FromV3(V3 v)
|
||||||
{
|
{
|
||||||
return (struct k_float3) { .v[0] = v.x, .v[1] = v.y, .v[2] = v.z };
|
return (struct K_float3) { .v[0] = v.x, .v[1] = v.y, .v[2] = v.z };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_float4x4 { f32 v[4][4]; };
|
typedef struct K_float4x4 K_float4x4;
|
||||||
INLINE struct k_float4x4 k_float4x4_from_mat4x4(struct mat4x4 v)
|
struct K_float4x4 { f32 v[4][4]; };
|
||||||
|
INLINE struct K_float4x4 K_Float4x4FromMat4x4(Mat4x4 v)
|
||||||
{
|
{
|
||||||
struct k_float4x4 res;
|
struct K_float4x4 res;
|
||||||
STATIC_ASSERT(sizeof(res) == sizeof(v));
|
STATIC_ASSERT(sizeof(res) == sizeof(v));
|
||||||
MEMCPY(&res, v.e, sizeof(res));
|
MEMCPY(&res, v.e, sizeof(res));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct k_float2x3 { f32 v[2][3]; };
|
struct K_float2x3 { f32 v[2][3]; };
|
||||||
INLINE struct k_float2x3 k_float2x3_from_xform(struct xform v)
|
INLINE struct K_float2x3 K_Float2x3FromXform(Xform v)
|
||||||
{
|
{
|
||||||
struct k_float2x3 res;
|
struct K_float2x3 res;
|
||||||
STATIC_ASSERT(sizeof(res) == sizeof(v));
|
STATIC_ASSERT(sizeof(res) == sizeof(v));
|
||||||
MEMCPY(&res, &v, sizeof(res));
|
MEMCPY(&res, &v, sizeof(res));
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@ -21,10 +21,10 @@ struct effect_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct mix {
|
struct mix {
|
||||||
struct mixer_track_handle track_handle;
|
M_Handle track_handle;
|
||||||
b32 track_finished;
|
b32 track_finished;
|
||||||
|
|
||||||
struct mixer_desc desc;
|
M_TrackDesc desc;
|
||||||
struct effect_data effect_data;
|
struct effect_data effect_data;
|
||||||
struct sound *source;
|
struct sound *source;
|
||||||
u64 source_pos;
|
u64 source_pos;
|
||||||
@ -35,7 +35,7 @@ struct track {
|
|||||||
|
|
||||||
/* Controlled via interface */
|
/* Controlled via interface */
|
||||||
struct sound *sound;
|
struct sound *sound;
|
||||||
struct mixer_desc desc;
|
M_TrackDesc desc;
|
||||||
|
|
||||||
/* Internal */
|
/* Internal */
|
||||||
struct mix mix;
|
struct mix mix;
|
||||||
@ -48,11 +48,11 @@ GLOBAL struct {
|
|||||||
struct snc_mutex mutex;
|
struct snc_mutex mutex;
|
||||||
|
|
||||||
/* Listener */
|
/* Listener */
|
||||||
struct v2 listener_pos;
|
V2 listener_pos;
|
||||||
struct v2 listener_dir;
|
V2 listener_dir;
|
||||||
|
|
||||||
/* Track list */
|
/* Track list */
|
||||||
struct arena *track_arena;
|
Arena *track_arena;
|
||||||
struct track *track_first_playing;
|
struct track *track_first_playing;
|
||||||
struct track *track_last_playing;
|
struct track *track_last_playing;
|
||||||
u64 track_playing_count;
|
u64 track_playing_count;
|
||||||
@ -63,28 +63,28 @@ GLOBAL struct {
|
|||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct mixer_startup_receipt mixer_startup(void)
|
M_StartupReceipt mixer_startup(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
G.track_arena = arena_alloc(GIBI(64));
|
G.track_arena = arena_alloc(GIBI(64));
|
||||||
G.listener_pos = V2(0, 0);
|
G.listener_pos = V2FromXY(0, 0);
|
||||||
G.listener_dir = V2(0, -1);
|
G.listener_dir = V2FromXY(0, -1);
|
||||||
return (struct mixer_startup_receipt) { 0 };
|
return (M_StartupReceipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Track
|
* Track
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct mixer_track_handle track_to_handle(struct track *track)
|
INTERNAL M_Handle track_to_handle(struct track *track)
|
||||||
{
|
{
|
||||||
return (struct mixer_track_handle) {
|
return (M_Handle) {
|
||||||
.gen = track->gen,
|
.gen = track->gen,
|
||||||
.data = track
|
.data = track
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct track *track_from_handle(struct mixer_track_handle handle)
|
INTERNAL struct track *track_from_handle(M_Handle handle)
|
||||||
{
|
{
|
||||||
struct track *track = (struct track *)handle.data;
|
struct track *track = (struct track *)handle.data;
|
||||||
if (track && track->gen == handle.gen) {
|
if (track && track->gen == handle.gen) {
|
||||||
@ -172,12 +172,12 @@ INTERNAL void track_release_locked(struct snc_lock *lock, struct track *track)
|
|||||||
/* TODO: Rework interface to take "mixer_cmd"s instead of
|
/* TODO: Rework interface to take "mixer_cmd"s instead of
|
||||||
* directly modifying tracks. */
|
* directly modifying tracks. */
|
||||||
|
|
||||||
struct mixer_track_handle mixer_play(struct sound *sound)
|
M_Handle mixer_play(struct sound *sound)
|
||||||
{
|
{
|
||||||
return mixer_play_ex(sound, MIXER_DESC());
|
return mixer_play_ex(sound, MIXER_DESC());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mixer_track_handle mixer_play_ex(struct sound *sound, struct mixer_desc desc)
|
M_Handle mixer_play_ex(struct sound *sound, M_TrackDesc desc)
|
||||||
{
|
{
|
||||||
struct track *track;
|
struct track *track;
|
||||||
{
|
{
|
||||||
@ -192,9 +192,9 @@ struct mixer_track_handle mixer_play_ex(struct sound *sound, struct mixer_desc d
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: This is quite inefficient. */
|
/* NOTE: This is quite inefficient. */
|
||||||
struct mixer_desc mixer_track_get(struct mixer_track_handle handle)
|
M_TrackDesc mixer_track_get(M_Handle handle)
|
||||||
{
|
{
|
||||||
struct mixer_desc res = ZI;
|
M_TrackDesc res = ZI;
|
||||||
|
|
||||||
struct track *track = track_from_handle(handle);
|
struct track *track = track_from_handle(handle);
|
||||||
if (track) {
|
if (track) {
|
||||||
@ -214,7 +214,7 @@ struct mixer_desc mixer_track_get(struct mixer_track_handle handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: This is quite inefficient. */
|
/* NOTE: This is quite inefficient. */
|
||||||
void mixer_track_set(struct mixer_track_handle handle, struct mixer_desc desc)
|
void mixer_track_set(M_Handle handle, M_TrackDesc desc)
|
||||||
{
|
{
|
||||||
struct track *track = track_from_handle(handle);
|
struct track *track = track_from_handle(handle);
|
||||||
if (track) {
|
if (track) {
|
||||||
@ -231,7 +231,7 @@ void mixer_track_set(struct mixer_track_handle handle, struct mixer_desc desc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mixer_set_listener(struct v2 pos, struct v2 dir)
|
void mixer_set_listener(V2 pos, V2 dir)
|
||||||
{
|
{
|
||||||
struct snc_lock lock = snc_lock_e(&G.mutex);
|
struct snc_lock lock = snc_lock_e(&G.mutex);
|
||||||
{
|
{
|
||||||
@ -257,18 +257,18 @@ INTERNAL i16 sample_sound(struct sound *sound, u64 sample_pos, b32 wrap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* To be called once per audio playback interval */
|
/* To be called once per audio playback interval */
|
||||||
struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
M_PcmF32 mixer_update(Arena *arena, u64 frame_count)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
struct mixed_pcm_f32 res = ZI;
|
M_PcmF32 res = ZI;
|
||||||
res.count = frame_count * 2;
|
res.count = frame_count * 2;
|
||||||
res.samples = arena_push_array(arena, f32, res.count);
|
res.samples = arena_push_array(arena, f32, res.count);
|
||||||
|
|
||||||
struct v2 listener_pos = V2(0, 0);
|
V2 listener_pos = V2FromXY(0, 0);
|
||||||
struct v2 listener_dir = V2(0, 0);
|
V2 listener_dir = V2FromXY(0, 0);
|
||||||
|
|
||||||
/* Create temp array of mixes */
|
/* Create temp array of mixes */
|
||||||
struct mix **mixes = 0;
|
struct mix **mixes = 0;
|
||||||
@ -302,7 +302,7 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct sound *source = mix->source;
|
struct sound *source = mix->source;
|
||||||
struct mixer_desc desc = mix->desc;
|
M_TrackDesc desc = mix->desc;
|
||||||
struct effect_data *effect_data = &mix->effect_data;
|
struct effect_data *effect_data = &mix->effect_data;
|
||||||
b32 source_is_stereo = source->flags & SOUND_FLAG_STEREO;
|
b32 source_is_stereo = source->flags & SOUND_FLAG_STEREO;
|
||||||
f32 speed = max_f32(0, desc.speed);
|
f32 speed = max_f32(0, desc.speed);
|
||||||
@ -335,7 +335,7 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
|
|
||||||
mix->source_pos = source_sample_pos_end;
|
mix->source_pos = source_sample_pos_end;
|
||||||
|
|
||||||
struct mixed_pcm_f32 mix_pcm = {
|
M_PcmF32 mix_pcm = {
|
||||||
.count = res.count,
|
.count = res.count,
|
||||||
.samples = arena_push_array(scratch.arena, f32, res.count)
|
.samples = arena_push_array(scratch.arena, f32, res.count)
|
||||||
};
|
};
|
||||||
@ -407,14 +407,14 @@ struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_count)
|
|||||||
const f32 rolloff_scale = 6.0f;
|
const f32 rolloff_scale = 6.0f;
|
||||||
const f32 pan_scale = 0.75;
|
const f32 pan_scale = 0.75;
|
||||||
|
|
||||||
struct v2 pos = desc.pos;
|
V2 pos = desc.pos;
|
||||||
|
|
||||||
/* If sound pos = listener pos, pretend sound is close in front of listener. */
|
/* If sound pos = listener pos, pretend sound is close in front of listener. */
|
||||||
if (v2_eq(listener_pos, pos)) {
|
if (v2_eq(listener_pos, pos)) {
|
||||||
pos = v2_add(listener_pos, v2_mul(listener_dir, 0.001f));
|
pos = v2_add(listener_pos, v2_mul(listener_dir, 0.001f));
|
||||||
}
|
}
|
||||||
struct v2 sound_rel = v2_sub(pos, listener_pos);
|
V2 sound_rel = v2_sub(pos, listener_pos);
|
||||||
struct v2 sound_rel_dir = v2_norm(sound_rel);
|
V2 sound_rel_dir = v2_norm(sound_rel);
|
||||||
|
|
||||||
/* Calculate volume */
|
/* Calculate volume */
|
||||||
f32 volume_start = effect_data->spatial_volume;
|
f32 volume_start = effect_data->spatial_volume;
|
||||||
|
|||||||
@ -3,47 +3,52 @@ struct sound;
|
|||||||
#define MIXER_FLAG_NONE 0x0
|
#define MIXER_FLAG_NONE 0x0
|
||||||
#define MIXER_FLAG_SPATIALIZE 0x1
|
#define MIXER_FLAG_SPATIALIZE 0x1
|
||||||
|
|
||||||
#define MIXER_DESC(...) ((struct mixer_desc) { \
|
#define MIXER_DESC(...) ((M_TrackDesc) { \
|
||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
\
|
\
|
||||||
.volume = 1.0, \
|
.volume = 1.0, \
|
||||||
.speed = 1.0, \
|
.speed = 1.0, \
|
||||||
.looping = 0, \
|
.looping = 0, \
|
||||||
\
|
\
|
||||||
.pos = V2(0, 0), \
|
.pos = V2FromXY(0, 0), \
|
||||||
\
|
\
|
||||||
__VA_ARGS__ \
|
__VA_ARGS__ \
|
||||||
})
|
})
|
||||||
struct mixer_desc {
|
|
||||||
|
typedef struct M_TrackDesc M_TrackDesc;
|
||||||
|
struct M_TrackDesc {
|
||||||
u32 flags;
|
u32 flags;
|
||||||
f32 volume; /* 0 -> 1.0+ */
|
f32 volume; /* 0 -> 1.0+ */
|
||||||
f32 speed; /* 0 -> 1.0+ */
|
f32 speed; /* 0 -> 1.0+ */
|
||||||
b32 looping;
|
b32 looping;
|
||||||
|
|
||||||
/* MIXER_FLAG_SPATIALIZE */
|
/* MIXER_FLAG_SPATIALIZE */
|
||||||
struct v2 pos;
|
V2 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mixer_track_handle {
|
typedef struct M_Handle M_Handle;
|
||||||
|
struct M_Handle {
|
||||||
u64 gen;
|
u64 gen;
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Stereo mix of 32 bit float samples */
|
/* Stereo mix of 32 bit float samples */
|
||||||
struct mixed_pcm_f32 {
|
typedef struct M_PcmF32 M_PcmF32;
|
||||||
|
struct M_PcmF32 {
|
||||||
u64 count;
|
u64 count;
|
||||||
f32 *samples;
|
f32 *samples;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mixer_startup_receipt { i32 _; };
|
typedef struct M_StartupReceipt M_StartupReceipt;
|
||||||
struct mixer_startup_receipt mixer_startup(void);
|
struct M_StartupReceipt { i32 _; };
|
||||||
|
M_StartupReceipt mixer_startup(void);
|
||||||
|
|
||||||
/* Interface */
|
/* Interface */
|
||||||
struct mixer_track_handle mixer_play(struct sound *sound);
|
M_Handle mixer_play(struct sound *sound);
|
||||||
struct mixer_track_handle mixer_play_ex(struct sound *sound, struct mixer_desc desc);
|
M_Handle mixer_play_ex(struct sound *sound, M_TrackDesc desc);
|
||||||
struct mixer_desc mixer_track_get(struct mixer_track_handle handle);
|
M_TrackDesc mixer_track_get(M_Handle handle);
|
||||||
void mixer_track_set(struct mixer_track_handle handle, struct mixer_desc desc);
|
void mixer_track_set(M_Handle handle, M_TrackDesc desc);
|
||||||
void mixer_set_listener(struct v2 pos, struct v2 dir);
|
void mixer_set_listener(V2 pos, V2 dir);
|
||||||
|
|
||||||
/* Mixing */
|
/* Mixing */
|
||||||
struct mixed_pcm_f32 mixer_update(struct arena *arena, u64 frame_request_count);
|
M_PcmF32 mixer_update(Arena *arena, u64 frame_request_count);
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
#define MP3_DECODE_FLAG_NONE 0x00
|
#define MP3_DECODE_FLAG_NONE 0x00
|
||||||
#define MP3_DECODE_FLAG_STEREO 0x01
|
#define MP3_DECODE_FLAG_STEREO 0x01
|
||||||
|
|
||||||
struct mp3_decode_result {
|
typedef struct MP3_Result MP3_Result;
|
||||||
struct pcm pcm;
|
struct MP3_Result {
|
||||||
|
PcmData pcm;
|
||||||
b32 success;
|
b32 success;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mp3_decode_result mp3_decode(struct arena *arena, struct string encoded, u32 sample_rate, u32 flags);
|
MP3_Result mp3_decode(Arena *arena, String encoded, u32 sample_rate, u32 flags);
|
||||||
|
|||||||
@ -18,9 +18,9 @@
|
|||||||
#pragma comment(lib, "mfreadwrite")
|
#pragma comment(lib, "mfreadwrite")
|
||||||
#pragma comment(lib, "shlwapi")
|
#pragma comment(lib, "shlwapi")
|
||||||
|
|
||||||
struct mp3_decode_result mp3_decode(struct arena *arena, struct string encoded, u32 sample_rate, u32 flags)
|
MP3_Result mp3_decode(Arena *arena, String encoded, u32 sample_rate, u32 flags)
|
||||||
{
|
{
|
||||||
struct mp3_decode_result res = ZI;
|
MP3_Result res = ZI;
|
||||||
u64 bytes_per_sample = 2;
|
u64 bytes_per_sample = 2;
|
||||||
|
|
||||||
u64 channel_count;
|
u64 channel_count;
|
||||||
|
|||||||
3
src/net/net.c
Normal file
3
src/net/net.c
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "net.h"
|
||||||
|
|
||||||
|
#include "net_core.c"
|
||||||
@ -1,9 +1,9 @@
|
|||||||
#ifndef HOST_H
|
#ifndef NET_H
|
||||||
#define HOST_H
|
#define NET_H
|
||||||
|
|
||||||
#include "../base/base.h"
|
#include "../base/base.h"
|
||||||
#include "../sys/sys.h"
|
#include "../sys/sys.h"
|
||||||
|
|
||||||
#include "host_core.h"
|
#include "net_core.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -12,13 +12,6 @@
|
|||||||
* Challenges to verify receiving address.
|
* Challenges to verify receiving address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PACKET_MAGIC 0xd9e3b8b6
|
|
||||||
#define PACKET_MSG_CHUNK_MAX_LEN 1024
|
|
||||||
#define PACKET_DATA_MAX_LEN 1280 /* Give enough space for msg chunk + header */
|
|
||||||
|
|
||||||
#define NUM_CHANNEL_LOOKUP_BINS 512
|
|
||||||
#define NUM_MSG_ASSEMBLER_LOOKUP_BINS 16384
|
|
||||||
|
|
||||||
enum host_packet_kind {
|
enum host_packet_kind {
|
||||||
HOST_PACKET_KIND_NONE,
|
HOST_PACKET_KIND_NONE,
|
||||||
HOST_PACKET_KIND_TRY_CONNECT,
|
HOST_PACKET_KIND_TRY_CONNECT,
|
||||||
@ -33,19 +26,11 @@ enum host_packet_flag {
|
|||||||
HOST_PACKET_FLAG_RELIABLE = (1 << 0)
|
HOST_PACKET_FLAG_RELIABLE = (1 << 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
struct host_snd_packet {
|
|
||||||
struct host_snd_packet *next;
|
|
||||||
u64 seq;
|
|
||||||
|
|
||||||
u64 data_len;
|
|
||||||
u8 data[PACKET_DATA_MAX_LEN];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host_channel {
|
struct host_channel {
|
||||||
struct host_channel_id id;
|
N_ChannelId id;
|
||||||
b32 valid;
|
b32 valid;
|
||||||
b32 connected;
|
b32 connected;
|
||||||
struct host *host;
|
N_Host *host;
|
||||||
|
|
||||||
struct host_channel *next_free;
|
struct host_channel *next_free;
|
||||||
|
|
||||||
@ -55,10 +40,10 @@ struct host_channel {
|
|||||||
struct host_channel *prev_address_hash;
|
struct host_channel *prev_address_hash;
|
||||||
|
|
||||||
/* NOTE: Packets are allocated in host's `arena` */
|
/* NOTE: Packets are allocated in host's `arena` */
|
||||||
struct host_snd_packet *first_reliable_packet;
|
N_SndPacket *first_reliable_packet;
|
||||||
struct host_snd_packet *last_reliable_packet;
|
N_SndPacket *last_reliable_packet;
|
||||||
struct host_snd_packet *first_unreliable_packet;
|
N_SndPacket *first_unreliable_packet;
|
||||||
struct host_snd_packet *last_unreliable_packet;
|
N_SndPacket *last_unreliable_packet;
|
||||||
u64 num_reliable_packets;
|
u64 num_reliable_packets;
|
||||||
u64 num_unreliable_packets;
|
u64 num_unreliable_packets;
|
||||||
|
|
||||||
@ -89,24 +74,13 @@ struct host_channel_list {
|
|||||||
struct host_channel_node *last;
|
struct host_channel_node *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct host_channel_lookup_bin {
|
|
||||||
struct host_channel *first;
|
|
||||||
struct host_channel *last;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host_rcv_packet {
|
struct host_rcv_packet {
|
||||||
struct sock *sock;
|
struct sock *sock;
|
||||||
struct sys_address address;
|
struct sys_address address;
|
||||||
struct string data;
|
String data;
|
||||||
struct host_rcv_packet *next;
|
struct host_rcv_packet *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct host_rcv_buffer {
|
|
||||||
struct arena *arena;
|
|
||||||
struct host_rcv_packet *first_packet;
|
|
||||||
struct host_rcv_packet *last_packet;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host_msg_assembler {
|
struct host_msg_assembler {
|
||||||
struct host_channel *channel;
|
struct host_channel *channel;
|
||||||
b32 is_reliable;
|
b32 is_reliable;
|
||||||
@ -131,7 +105,7 @@ struct host_msg_assembler {
|
|||||||
|
|
||||||
i64 touched_ns;
|
i64 touched_ns;
|
||||||
|
|
||||||
struct buddy_block *buddy_block;
|
BuddyBlock *buddy_block;
|
||||||
u8 *chunk_bitmap;
|
u8 *chunk_bitmap;
|
||||||
u8 *chunk_data;
|
u8 *chunk_data;
|
||||||
};
|
};
|
||||||
@ -153,36 +127,36 @@ INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma);
|
|||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct host_startup_receipt host_startup(void)
|
N_StartupReceipt host_startup(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
return (struct host_startup_receipt) { 0 };
|
return (N_StartupReceipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Host
|
* Host
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct host *host_alloc(u16 listen_port)
|
N_Host *host_alloc(u16 listen_port)
|
||||||
{
|
{
|
||||||
struct arena *arena = arena_alloc(GIBI(64));
|
Arena *arena = arena_alloc(GIBI(64));
|
||||||
struct host *host = arena_push(arena, struct host);
|
N_Host *host = arena_push(arena, N_Host);
|
||||||
|
|
||||||
host->arena = arena;
|
host->arena = arena;
|
||||||
host->cmd_arena = arena_alloc(GIBI(64));
|
host->cmd_arena = arena_alloc(GIBI(64));
|
||||||
host->channel_arena = arena_alloc(GIBI(64));
|
host->channel_arena = arena_alloc(GIBI(64));
|
||||||
host->rcv_buffer_read = arena_push(host->arena, struct host_rcv_buffer);
|
host->rcv_buffer_read = arena_push(host->arena, N_RcvBuffer);
|
||||||
host->rcv_buffer_write = arena_push(host->arena, struct host_rcv_buffer);
|
host->rcv_buffer_write = arena_push(host->arena, N_RcvBuffer);
|
||||||
host->rcv_buffer_read->arena = arena_alloc(GIBI(64));
|
host->rcv_buffer_read->arena = arena_alloc(GIBI(64));
|
||||||
host->rcv_buffer_write->arena = arena_alloc(GIBI(64));
|
host->rcv_buffer_write->arena = arena_alloc(GIBI(64));
|
||||||
host->buddy = buddy_ctx_alloc(GIBI(64));
|
host->buddy = buddy_ctx_alloc(GIBI(64));
|
||||||
|
|
||||||
host->channels = arena_push_dry(host->channel_arena, struct host_channel);
|
host->channels = arena_push_dry(host->channel_arena, struct host_channel);
|
||||||
|
|
||||||
host->num_channel_lookup_bins = NUM_CHANNEL_LOOKUP_BINS;
|
host->num_channel_lookup_bins = N_NumChannelLookupBins;
|
||||||
host->channel_lookup_bins = arena_push_array(host->arena, struct host_channel_lookup_bin, host->num_channel_lookup_bins);
|
host->channel_lookup_bins = arena_push_array(host->arena, N_ChannelLookupBin, host->num_channel_lookup_bins);
|
||||||
|
|
||||||
host->num_msg_assembler_lookup_bins = NUM_MSG_ASSEMBLER_LOOKUP_BINS;
|
host->num_msg_assembler_lookup_bins = N_NumMsgAssemblerLookupBins;
|
||||||
host->msg_assembler_lookup_bins = arena_push_array(host->arena, struct host_msg_assembler_lookup_bin, host->num_msg_assembler_lookup_bins);
|
host->msg_assembler_lookup_bins = arena_push_array(host->arena, struct host_msg_assembler_lookup_bin, host->num_msg_assembler_lookup_bins);
|
||||||
|
|
||||||
host->sock = sys_sock_alloc(listen_port, MEBI(2), MEBI(2));
|
host->sock = sys_sock_alloc(listen_port, MEBI(2), MEBI(2));
|
||||||
@ -190,7 +164,7 @@ struct host *host_alloc(u16 listen_port)
|
|||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
void host_release(struct host *host)
|
void host_release(N_Host *host)
|
||||||
{
|
{
|
||||||
sys_sock_release(host->sock);
|
sys_sock_release(host->sock);
|
||||||
|
|
||||||
@ -211,10 +185,10 @@ INTERNAL u64 hash_from_address(struct sys_address address)
|
|||||||
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&address));
|
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&address));
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct host_channel *host_channel_from_address(struct host *host, struct sys_address address)
|
INTERNAL struct host_channel *host_channel_from_address(N_Host *host, struct sys_address address)
|
||||||
{
|
{
|
||||||
u64 hash = hash_from_address(address);
|
u64 hash = hash_from_address(address);
|
||||||
struct host_channel_lookup_bin *bin = &host->channel_lookup_bins[hash % host->num_channel_lookup_bins];
|
N_ChannelLookupBin *bin = &host->channel_lookup_bins[hash % host->num_channel_lookup_bins];
|
||||||
for (struct host_channel *channel = bin->first; channel; channel = channel->next_address_hash) {
|
for (struct host_channel *channel = bin->first; channel; channel = channel->next_address_hash) {
|
||||||
if (channel->address_hash == hash && sys_address_eq(channel->address, address)) {
|
if (channel->address_hash == hash && sys_address_eq(channel->address, address)) {
|
||||||
return channel;
|
return channel;
|
||||||
@ -224,7 +198,7 @@ INTERNAL struct host_channel *host_channel_from_address(struct host *host, struc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns nil channel if id = HOST_CHANNEL_ID_ALL */
|
/* Returns nil channel if id = HOST_CHANNEL_ID_ALL */
|
||||||
INTERNAL struct host_channel *host_single_channel_from_id(struct host *host, struct host_channel_id channel_id)
|
INTERNAL struct host_channel *host_single_channel_from_id(N_Host *host, N_ChannelId channel_id)
|
||||||
{
|
{
|
||||||
if (channel_id.gen > 0 && channel_id.idx < host->num_channels_reserved) {
|
if (channel_id.gen > 0 && channel_id.idx < host->num_channels_reserved) {
|
||||||
struct host_channel *channel = &host->channels[channel_id.idx];
|
struct host_channel *channel = &host->channels[channel_id.idx];
|
||||||
@ -235,7 +209,7 @@ INTERNAL struct host_channel *host_single_channel_from_id(struct host *host, str
|
|||||||
return &_g_host_channel_nil;
|
return &_g_host_channel_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct host_channel_list host_channels_from_id(struct arena *arena, struct host *host, struct host_channel_id channel_id)
|
INTERNAL struct host_channel_list host_channels_from_id(Arena *arena, N_Host *host, N_ChannelId channel_id)
|
||||||
{
|
{
|
||||||
struct host_channel_list res = ZI;
|
struct host_channel_list res = ZI;
|
||||||
if (host_channel_id_eq(channel_id, HOST_CHANNEL_ID_ALL)) {
|
if (host_channel_id_eq(channel_id, HOST_CHANNEL_ID_ALL)) {
|
||||||
@ -264,9 +238,9 @@ INTERNAL struct host_channel_list host_channels_from_id(struct arena *arena, str
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct host_channel *host_channel_alloc(struct host *host, struct sys_address address)
|
INTERNAL struct host_channel *host_channel_alloc(N_Host *host, struct sys_address address)
|
||||||
{
|
{
|
||||||
struct host_channel_id id = ZI;
|
N_ChannelId id = ZI;
|
||||||
struct host_channel *channel;
|
struct host_channel *channel;
|
||||||
if (host->first_free_channel) {
|
if (host->first_free_channel) {
|
||||||
channel = host->first_free_channel;
|
channel = host->first_free_channel;
|
||||||
@ -288,7 +262,7 @@ INTERNAL struct host_channel *host_channel_alloc(struct host *host, struct sys_a
|
|||||||
channel->address_hash = address_hash;
|
channel->address_hash = address_hash;
|
||||||
|
|
||||||
u64 bin_index = address_hash % host->num_channel_lookup_bins;
|
u64 bin_index = address_hash % host->num_channel_lookup_bins;
|
||||||
struct host_channel_lookup_bin *bin = &host->channel_lookup_bins[bin_index];
|
N_ChannelLookupBin *bin = &host->channel_lookup_bins[bin_index];
|
||||||
if (bin->last) {
|
if (bin->last) {
|
||||||
channel->prev_address_hash = bin->last;
|
channel->prev_address_hash = bin->last;
|
||||||
bin->last->next_address_hash = channel;
|
bin->last->next_address_hash = channel;
|
||||||
@ -302,11 +276,11 @@ INTERNAL struct host_channel *host_channel_alloc(struct host *host, struct sys_a
|
|||||||
|
|
||||||
INTERNAL void host_channel_release(struct host_channel *channel)
|
INTERNAL void host_channel_release(struct host_channel *channel)
|
||||||
{
|
{
|
||||||
struct host *host = channel->host;
|
N_Host *host = channel->host;
|
||||||
|
|
||||||
/* Release from lookup table */
|
/* Release from lookup table */
|
||||||
{
|
{
|
||||||
struct host_channel_lookup_bin *bin = &host->channel_lookup_bins[channel->address_hash % host->num_channel_lookup_bins];
|
N_ChannelLookupBin *bin = &host->channel_lookup_bins[channel->address_hash % host->num_channel_lookup_bins];
|
||||||
struct host_channel *prev = channel->prev_address_hash;
|
struct host_channel *prev = channel->prev_address_hash;
|
||||||
struct host_channel *next = channel->next_address_hash;
|
struct host_channel *next = channel->next_address_hash;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
@ -348,7 +322,7 @@ INTERNAL void host_channel_release(struct host_channel *channel)
|
|||||||
* Msg assembler
|
* Msg assembler
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL u64 hash_from_channel_msg(struct host_channel_id channel_id, u64 msg_id)
|
INTERNAL u64 hash_from_channel_msg(N_ChannelId channel_id, u64 msg_id)
|
||||||
{
|
{
|
||||||
u64 res = HASH_FNV64_BASIS;
|
u64 res = HASH_FNV64_BASIS;
|
||||||
res = hash_fnv64(res, STRING_FROM_STRUCT(&channel_id));
|
res = hash_fnv64(res, STRING_FROM_STRUCT(&channel_id));
|
||||||
@ -356,7 +330,7 @@ INTERNAL u64 hash_from_channel_msg(struct host_channel_id channel_id, u64 msg_id
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct host_msg_assembler *host_get_msg_assembler(struct host *host, struct host_channel_id channel_id, u64 msg_id)
|
INTERNAL struct host_msg_assembler *host_get_msg_assembler(N_Host *host, N_ChannelId channel_id, u64 msg_id)
|
||||||
{
|
{
|
||||||
u64 hash = hash_from_channel_msg(channel_id, msg_id);
|
u64 hash = hash_from_channel_msg(channel_id, msg_id);
|
||||||
struct host_msg_assembler_lookup_bin *bin = &host->msg_assembler_lookup_bins[hash % host->num_msg_assembler_lookup_bins];
|
struct host_msg_assembler_lookup_bin *bin = &host->msg_assembler_lookup_bins[hash % host->num_msg_assembler_lookup_bins];
|
||||||
@ -370,7 +344,7 @@ INTERNAL struct host_msg_assembler *host_get_msg_assembler(struct host *host, st
|
|||||||
|
|
||||||
INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel *channel, u64 msg_id, u64 chunk_count, u64 now_ns, b32 is_reliable)
|
INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel *channel, u64 msg_id, u64 chunk_count, u64 now_ns, b32 is_reliable)
|
||||||
{
|
{
|
||||||
struct host *host = channel->host;
|
N_Host *host = channel->host;
|
||||||
struct host_msg_assembler *ma;
|
struct host_msg_assembler *ma;
|
||||||
if (host->first_free_msg_assembler) {
|
if (host->first_free_msg_assembler) {
|
||||||
ma = host->first_free_msg_assembler;
|
ma = host->first_free_msg_assembler;
|
||||||
@ -389,7 +363,7 @@ INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel
|
|||||||
/* Align chunk bitmap to 16 so msg data is aligned */
|
/* Align chunk bitmap to 16 so msg data is aligned */
|
||||||
chunk_bitmap_size += 16 - (chunk_bitmap_size % 16);
|
chunk_bitmap_size += 16 - (chunk_bitmap_size % 16);
|
||||||
}
|
}
|
||||||
u64 chunk_data_size = chunk_count * PACKET_MSG_CHUNK_MAX_LEN;
|
u64 chunk_data_size = chunk_count * N_MaxPacketChunkLen;
|
||||||
|
|
||||||
/* Allocate msg data using buddy allocator since the assembler has
|
/* Allocate msg data using buddy allocator since the assembler has
|
||||||
* arbitrary lifetime and data needs to stay contiguous for random
|
* arbitrary lifetime and data needs to stay contiguous for random
|
||||||
@ -430,7 +404,7 @@ INTERNAL struct host_msg_assembler *host_msg_assembler_alloc(struct host_channel
|
|||||||
INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma)
|
INTERNAL void host_msg_assembler_release(struct host_msg_assembler *ma)
|
||||||
{
|
{
|
||||||
struct host_channel *channel = ma->channel;
|
struct host_channel *channel = ma->channel;
|
||||||
struct host *host = channel->host;
|
N_Host *host = channel->host;
|
||||||
buddy_release(ma->buddy_block);
|
buddy_release(ma->buddy_block);
|
||||||
|
|
||||||
/* Release from channel list */
|
/* Release from channel list */
|
||||||
@ -523,15 +497,15 @@ INTERNAL void host_msg_assembler_set_chunk_received(struct host_msg_assembler *m
|
|||||||
* Packet
|
* Packet
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct host_snd_packet *host_channel_snd_packet_alloc(struct host_channel *channel, b32 is_reliable)
|
INTERNAL N_SndPacket *host_channel_snd_packet_alloc(struct host_channel *channel, b32 is_reliable)
|
||||||
{
|
{
|
||||||
struct host *host = channel->host;
|
N_Host *host = channel->host;
|
||||||
struct host_snd_packet *packet = 0;
|
N_SndPacket *packet = 0;
|
||||||
if (host->first_free_packet) {
|
if (host->first_free_packet) {
|
||||||
packet = host->first_free_packet;
|
packet = host->first_free_packet;
|
||||||
host->first_free_packet = packet->next;
|
host->first_free_packet = packet->next;
|
||||||
} else {
|
} else {
|
||||||
packet = arena_push_no_zero(host->arena, struct host_snd_packet);
|
packet = arena_push_no_zero(host->arena, N_SndPacket);
|
||||||
}
|
}
|
||||||
MEMZERO_STRUCT(packet);
|
MEMZERO_STRUCT(packet);
|
||||||
|
|
||||||
@ -560,9 +534,9 @@ INTERNAL struct host_snd_packet *host_channel_snd_packet_alloc(struct host_chann
|
|||||||
* Cmd interface
|
* Cmd interface
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct host_cmd *host_cmd_alloc_and_append(struct host *host)
|
INTERNAL N_Cmd *host_cmd_alloc_and_append(N_Host *host)
|
||||||
{
|
{
|
||||||
struct host_cmd *cmd = arena_push(host->cmd_arena, struct host_cmd);
|
N_Cmd *cmd = arena_push(host->cmd_arena, N_Cmd);
|
||||||
if (host->last_cmd) {
|
if (host->last_cmd) {
|
||||||
host->last_cmd->next = cmd;
|
host->last_cmd->next = cmd;
|
||||||
} else {
|
} else {
|
||||||
@ -572,7 +546,7 @@ INTERNAL struct host_cmd *host_cmd_alloc_and_append(struct host *host)
|
|||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void host_queue_connect_to_address(struct host *host, struct sys_address connect_address)
|
void host_queue_connect_to_address(N_Host *host, struct sys_address connect_address)
|
||||||
{
|
{
|
||||||
struct host_channel *channel = host_channel_from_address(host, connect_address);
|
struct host_channel *channel = host_channel_from_address(host, connect_address);
|
||||||
if (!channel->valid) {
|
if (!channel->valid) {
|
||||||
@ -580,16 +554,16 @@ void host_queue_connect_to_address(struct host *host, struct sys_address connect
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void host_queue_disconnect(struct host *host, struct host_channel_id channel_id)
|
void host_queue_disconnect(N_Host *host, N_ChannelId channel_id)
|
||||||
{
|
{
|
||||||
struct host_cmd *cmd = host_cmd_alloc_and_append(host);
|
N_Cmd *cmd = host_cmd_alloc_and_append(host);
|
||||||
cmd->kind = HOST_CMD_KIND_DISCONNECT;
|
cmd->kind = HOST_CMD_KIND_DISCONNECT;
|
||||||
cmd->channel_id = channel_id;
|
cmd->channel_id = channel_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void host_queue_write(struct host *host, struct host_channel_id channel_id, struct string msg, u32 flags)
|
void host_queue_write(N_Host *host, N_ChannelId channel_id, String msg, u32 flags)
|
||||||
{
|
{
|
||||||
struct host_cmd *cmd = host_cmd_alloc_and_append(host);
|
N_Cmd *cmd = host_cmd_alloc_and_append(host);
|
||||||
cmd->kind = HOST_CMD_KIND_WRITE;
|
cmd->kind = HOST_CMD_KIND_WRITE;
|
||||||
cmd->channel_id = channel_id;
|
cmd->channel_id = channel_id;
|
||||||
cmd->write_msg = string_copy(host->cmd_arena, msg);
|
cmd->write_msg = string_copy(host->cmd_arena, msg);
|
||||||
@ -600,7 +574,7 @@ void host_queue_write(struct host *host, struct host_channel_id channel_id, stru
|
|||||||
* Info
|
* Info
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
i64 host_get_channel_last_rtt_ns(struct host *host, struct host_channel_id channel_id)
|
i64 host_get_channel_last_rtt_ns(N_Host *host, N_ChannelId channel_id)
|
||||||
{
|
{
|
||||||
struct host_channel *channel = host_single_channel_from_id(host, channel_id);
|
struct host_channel *channel = host_single_channel_from_id(host, channel_id);
|
||||||
return channel->last_heartbeat_rtt_ns;
|
return channel->last_heartbeat_rtt_ns;
|
||||||
@ -610,9 +584,9 @@ i64 host_get_channel_last_rtt_ns(struct host *host, struct host_channel_id chann
|
|||||||
* Update
|
* Update
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct host_event *push_event(struct arena *arena, struct host_event_list *list)
|
INTERNAL N_Event *push_event(Arena *arena, N_EventList *list)
|
||||||
{
|
{
|
||||||
struct host_event *event = arena_push(arena, struct host_event);
|
N_Event *event = arena_push(arena, N_Event);
|
||||||
if (list->last) {
|
if (list->last) {
|
||||||
list->last->next = event;
|
list->last->next = event;
|
||||||
} else {
|
} else {
|
||||||
@ -623,11 +597,11 @@ INTERNAL struct host_event *push_event(struct arena *arena, struct host_event_li
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read incoming packets, update channels, and return events */
|
/* Read incoming packets, update channels, and return events */
|
||||||
struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
N_EventList host_update_begin(Arena *arena, N_Host *host)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
struct host_event_list events = ZI;
|
N_EventList events = ZI;
|
||||||
i64 now_ns = sys_time_ns();
|
i64 now_ns = sys_time_ns();
|
||||||
{
|
{
|
||||||
__profn("Read packets");
|
__profn("Read packets");
|
||||||
@ -641,7 +615,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
struct sys_sock_read_result res = ZI;
|
struct sys_sock_read_result res = ZI;
|
||||||
while ((res = sys_sock_read(scratch.arena, sock)).valid) {
|
while ((res = sys_sock_read(scratch.arena, sock)).valid) {
|
||||||
struct sys_address address = res.address;
|
struct sys_address address = res.address;
|
||||||
struct string data = res.data;
|
String data = res.data;
|
||||||
if (data.len > 0) {
|
if (data.len > 0) {
|
||||||
struct host_rcv_packet *packet = arena_push(scratch.arena, struct host_rcv_packet);
|
struct host_rcv_packet *packet = arena_push(scratch.arena, struct host_rcv_packet);
|
||||||
packet->address = address;
|
packet->address = address;
|
||||||
@ -662,10 +636,10 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
for (struct host_rcv_packet *packet = first_packet; packet; packet = packet->next) {
|
for (struct host_rcv_packet *packet = first_packet; packet; packet = packet->next) {
|
||||||
//struct sock *sock = packet->sock;
|
//struct sock *sock = packet->sock;
|
||||||
struct sys_address address = packet->address;
|
struct sys_address address = packet->address;
|
||||||
struct bitbuff bb = bitbuff_from_string(packet->data);
|
Bitbuff bb = bitbuff_from_string(packet->data);
|
||||||
struct bitbuff_reader br = br_from_bitbuff(&bb);
|
BitbuffReader br = br_from_bitbuff(&bb);
|
||||||
u32 magic = br_read_ubits(&br, 32); /* TODO: implicitly encode magic into crc32 */
|
u32 magic = br_read_ubits(&br, 32); /* TODO: implicitly encode magic into crc32 */
|
||||||
if (magic == PACKET_MAGIC) {
|
if (magic == N_PacketMagic) {
|
||||||
/* TODO: Combine kind byte with flags byte */
|
/* TODO: Combine kind byte with flags byte */
|
||||||
struct host_channel *channel = host_channel_from_address(host, address);
|
struct host_channel *channel = host_channel_from_address(host, address);
|
||||||
enum host_packet_kind host_packet_kind = br_read_ibits(&br, 8);
|
enum host_packet_kind host_packet_kind = br_read_ibits(&br, 8);
|
||||||
@ -702,7 +676,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
/* TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? */
|
/* TODO: Verify that some per-host uuid isn't present in a rolling window to prevent reconnects right after a disconnect? */
|
||||||
channel = host_channel_alloc(host, address);
|
channel = host_channel_alloc(host, address);
|
||||||
}
|
}
|
||||||
struct host_cmd *cmd = host_cmd_alloc_and_append(host);
|
N_Cmd *cmd = host_cmd_alloc_and_append(host);
|
||||||
cmd->kind = HOST_CMD_KIND_CONNECT_SUCCESS;
|
cmd->kind = HOST_CMD_KIND_CONNECT_SUCCESS;
|
||||||
cmd->channel_id = channel->id;
|
cmd->channel_id = channel->id;
|
||||||
} break;
|
} break;
|
||||||
@ -712,7 +686,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
/* We successfully connected to a foreign host and they are ready to receive messages */
|
/* We successfully connected to a foreign host and they are ready to receive messages */
|
||||||
if (channel->valid && !channel->connected) {
|
if (channel->valid && !channel->connected) {
|
||||||
logf_info("Host received connection from %F", FMT_STR(sys_string_from_address(scratch.arena, address)));
|
logf_info("Host received connection from %F", FMT_STR(sys_string_from_address(scratch.arena, address)));
|
||||||
struct host_event *event = push_event(arena, &events);
|
N_Event *event = push_event(arena, &events);
|
||||||
event->kind = HOST_EVENT_KIND_CHANNEL_OPENED;
|
event->kind = HOST_EVENT_KIND_CHANNEL_OPENED;
|
||||||
event->channel_id = channel->id;
|
event->channel_id = channel->id;
|
||||||
channel->connected = 1;
|
channel->connected = 1;
|
||||||
@ -724,7 +698,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
/* A foreign host disconnected from us */
|
/* A foreign host disconnected from us */
|
||||||
if (channel->valid) {
|
if (channel->valid) {
|
||||||
logf_info("Host received disconnection from %F", FMT_STR(sys_string_from_address(scratch.arena, address)));
|
logf_info("Host received disconnection from %F", FMT_STR(sys_string_from_address(scratch.arena, address)));
|
||||||
struct host_event *event = push_event(arena, &events);
|
N_Event *event = push_event(arena, &events);
|
||||||
event->kind = HOST_EVENT_KIND_CHANNEL_CLOSED;
|
event->kind = HOST_EVENT_KIND_CHANNEL_CLOSED;
|
||||||
event->channel_id = channel->id;
|
event->channel_id = channel->id;
|
||||||
host_channel_release(channel);
|
host_channel_release(channel);
|
||||||
@ -758,7 +732,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
u64 chunk_id = br_read_uv(&br);
|
u64 chunk_id = br_read_uv(&br);
|
||||||
u64 chunk_count = br_read_uv(&br);
|
u64 chunk_count = br_read_uv(&br);
|
||||||
b32 is_last_chunk = (chunk_id + 1) == chunk_count;
|
b32 is_last_chunk = (chunk_id + 1) == chunk_count;
|
||||||
u64 chunk_len = is_last_chunk ? br_read_uv(&br) : PACKET_MSG_CHUNK_MAX_LEN;
|
u64 chunk_len = is_last_chunk ? br_read_uv(&br) : N_MaxPacketChunkLen;
|
||||||
|
|
||||||
struct host_msg_assembler *ma = host_get_msg_assembler(host, channel->id, msg_id);
|
struct host_msg_assembler *ma = host_get_msg_assembler(host, channel->id, msg_id);
|
||||||
if (!ma) {
|
if (!ma) {
|
||||||
@ -769,7 +743,7 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
if (!host_msg_assembler_is_chunk_filled(ma, chunk_id)) {
|
if (!host_msg_assembler_is_chunk_filled(ma, chunk_id)) {
|
||||||
u8 *src = br_read_bytes_raw(&br, chunk_len);
|
u8 *src = br_read_bytes_raw(&br, chunk_len);
|
||||||
if (src) {
|
if (src) {
|
||||||
u8 *dst = &ma->chunk_data[chunk_id * PACKET_MSG_CHUNK_MAX_LEN];
|
u8 *dst = &ma->chunk_data[chunk_id * N_MaxPacketChunkLen];
|
||||||
MEMCPY(dst, src, chunk_len);
|
MEMCPY(dst, src, chunk_len);
|
||||||
if (is_last_chunk) {
|
if (is_last_chunk) {
|
||||||
ma->last_chunk_len = chunk_len;
|
ma->last_chunk_len = chunk_len;
|
||||||
@ -780,9 +754,9 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
if (ma->num_chunks_received == chunk_count) {
|
if (ma->num_chunks_received == chunk_count) {
|
||||||
/* All chunks filled, message has finished assembling */
|
/* All chunks filled, message has finished assembling */
|
||||||
/* TODO: Message ordering */
|
/* TODO: Message ordering */
|
||||||
struct host_event *event = push_event(arena, &events);
|
N_Event *event = push_event(arena, &events);
|
||||||
struct string data = ZI;
|
String data = ZI;
|
||||||
data.len = ((chunk_count - 1) * PACKET_MSG_CHUNK_MAX_LEN) + ma->last_chunk_len;
|
data.len = ((chunk_count - 1) * N_MaxPacketChunkLen) + ma->last_chunk_len;
|
||||||
data.text = arena_push_array_no_zero(arena, u8, data.len);
|
data.text = arena_push_array_no_zero(arena, u8, data.len);
|
||||||
MEMCPY(data.text, ma->chunk_data, data.len);
|
MEMCPY(data.text, ma->chunk_data, data.len);
|
||||||
event->kind = HOST_EVENT_KIND_MSG;
|
event->kind = HOST_EVENT_KIND_MSG;
|
||||||
@ -822,14 +796,14 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
if (channel->valid) {
|
if (channel->valid) {
|
||||||
/* Send / resend handshake if not connected */
|
/* Send / resend handshake if not connected */
|
||||||
if (!channel->connected) {
|
if (!channel->connected) {
|
||||||
struct host_cmd *cmd = host_cmd_alloc_and_append(host);
|
N_Cmd *cmd = host_cmd_alloc_and_append(host);
|
||||||
cmd->kind = HOST_CMD_KIND_TRY_CONNECT;
|
cmd->kind = HOST_CMD_KIND_TRY_CONNECT;
|
||||||
cmd->channel_id = channel->id;
|
cmd->channel_id = channel->id;
|
||||||
}
|
}
|
||||||
/* Send heartbeat */
|
/* Send heartbeat */
|
||||||
/* TODO: Send this less frequently (once per second or half of timeout or something) */
|
/* TODO: Send this less frequently (once per second or half of timeout or something) */
|
||||||
{
|
{
|
||||||
struct host_cmd *cmd = host_cmd_alloc_and_append(host);
|
N_Cmd *cmd = host_cmd_alloc_and_append(host);
|
||||||
cmd->kind = HOST_CMD_KIND_HEARTBEAT;
|
cmd->kind = HOST_CMD_KIND_HEARTBEAT;
|
||||||
cmd->heartbeat_id = channel->last_heartbeat_acked_id + 1;
|
cmd->heartbeat_id = channel->last_heartbeat_acked_id + 1;
|
||||||
cmd->heartbeat_ack_id = channel->last_heartbeat_received_id;
|
cmd->heartbeat_ack_id = channel->last_heartbeat_received_id;
|
||||||
@ -838,9 +812,9 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
/* Release acked reliable packets */
|
/* Release acked reliable packets */
|
||||||
{
|
{
|
||||||
u64 acked_seq = channel->their_acked_seq;
|
u64 acked_seq = channel->their_acked_seq;
|
||||||
struct host_snd_packet *packet = channel->first_reliable_packet;
|
N_SndPacket *packet = channel->first_reliable_packet;
|
||||||
while (packet) {
|
while (packet) {
|
||||||
struct host_snd_packet *next = packet->next;
|
N_SndPacket *next = packet->next;
|
||||||
u64 seq = packet->seq;
|
u64 seq = packet->seq;
|
||||||
if (seq < acked_seq) {
|
if (seq < acked_seq) {
|
||||||
packet->next = host->first_free_packet;
|
packet->next = host->first_free_packet;
|
||||||
@ -882,18 +856,18 @@ struct host_event_list host_update_begin(struct arena *arena, struct host *host)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Process host cmds & send outgoing packets */
|
/* Process host cmds & send outgoing packets */
|
||||||
void host_update_end(struct host *host)
|
void host_update_end(N_Host *host)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
/* Process cmds into sendable packets */
|
/* Process cmds into sendable packets */
|
||||||
/* TODO: Unreliable packets don't need to be allocated into unreliable packet queue, should just send them and forget */
|
/* TODO: Unreliable packets don't need to be allocated into unreliable packet queue, should just send them and forget */
|
||||||
{
|
{
|
||||||
__profn("Process host cmds");
|
__profn("Process host cmds");
|
||||||
for (struct host_cmd *cmd = host->first_cmd; cmd; cmd = cmd->next) {
|
for (N_Cmd *cmd = host->first_cmd; cmd; cmd = cmd->next) {
|
||||||
enum host_cmd_kind kind = cmd->kind;
|
N_CmdKind kind = cmd->kind;
|
||||||
struct host_channel_id channel_id = cmd->channel_id;
|
N_ChannelId channel_id = cmd->channel_id;
|
||||||
struct host_channel_list channels = host_channels_from_id(scratch.arena, host, channel_id);
|
struct host_channel_list channels = host_channels_from_id(scratch.arena, host, channel_id);
|
||||||
for (struct host_channel_node *node = channels.first; node; node = node->next) {
|
for (struct host_channel_node *node = channels.first; node; node = node->next) {
|
||||||
struct host_channel *channel = node->channel;
|
struct host_channel *channel = node->channel;
|
||||||
@ -901,10 +875,10 @@ void host_update_end(struct host *host)
|
|||||||
case HOST_CMD_KIND_TRY_CONNECT:
|
case HOST_CMD_KIND_TRY_CONNECT:
|
||||||
{
|
{
|
||||||
u8 packet_flags = 0;
|
u8 packet_flags = 0;
|
||||||
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, 0);
|
N_SndPacket *packet = host_channel_snd_packet_alloc(channel, 0);
|
||||||
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
Bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(&bb);
|
BitbuffWriter bw = bw_from_bitbuff(&bb);
|
||||||
bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
|
bw_write_ubits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||||
bw_write_ibits(&bw, HOST_PACKET_KIND_TRY_CONNECT, 8);
|
bw_write_ibits(&bw, HOST_PACKET_KIND_TRY_CONNECT, 8);
|
||||||
bw_write_ubits(&bw, packet_flags, 8);
|
bw_write_ubits(&bw, packet_flags, 8);
|
||||||
bw_write_uv(&bw, channel->our_acked_seq);
|
bw_write_uv(&bw, channel->our_acked_seq);
|
||||||
@ -914,10 +888,10 @@ void host_update_end(struct host *host)
|
|||||||
case HOST_CMD_KIND_CONNECT_SUCCESS:
|
case HOST_CMD_KIND_CONNECT_SUCCESS:
|
||||||
{
|
{
|
||||||
u8 packet_flags = 0;
|
u8 packet_flags = 0;
|
||||||
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, 0);
|
N_SndPacket *packet = host_channel_snd_packet_alloc(channel, 0);
|
||||||
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
Bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(&bb);
|
BitbuffWriter bw = bw_from_bitbuff(&bb);
|
||||||
bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
|
bw_write_ubits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||||
bw_write_ibits(&bw, HOST_PACKET_KIND_CONNECT_SUCCESS, 8);
|
bw_write_ibits(&bw, HOST_PACKET_KIND_CONNECT_SUCCESS, 8);
|
||||||
bw_write_ubits(&bw, packet_flags, 8);
|
bw_write_ubits(&bw, packet_flags, 8);
|
||||||
bw_write_uv(&bw, channel->our_acked_seq);
|
bw_write_uv(&bw, channel->our_acked_seq);
|
||||||
@ -927,10 +901,10 @@ void host_update_end(struct host *host)
|
|||||||
case HOST_CMD_KIND_DISCONNECT:
|
case HOST_CMD_KIND_DISCONNECT:
|
||||||
{
|
{
|
||||||
u8 packet_flags = 0;
|
u8 packet_flags = 0;
|
||||||
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, 0);
|
N_SndPacket *packet = host_channel_snd_packet_alloc(channel, 0);
|
||||||
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
Bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(&bb);
|
BitbuffWriter bw = bw_from_bitbuff(&bb);
|
||||||
bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
|
bw_write_ubits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||||
bw_write_ibits(&bw, HOST_PACKET_KIND_DISCONNECT, 8);
|
bw_write_ibits(&bw, HOST_PACKET_KIND_DISCONNECT, 8);
|
||||||
bw_write_ubits(&bw, packet_flags, 8);
|
bw_write_ubits(&bw, packet_flags, 8);
|
||||||
bw_write_uv(&bw, channel->our_acked_seq);
|
bw_write_uv(&bw, channel->our_acked_seq);
|
||||||
@ -940,10 +914,10 @@ void host_update_end(struct host *host)
|
|||||||
case HOST_CMD_KIND_HEARTBEAT:
|
case HOST_CMD_KIND_HEARTBEAT:
|
||||||
{
|
{
|
||||||
u8 packet_flags = 0;
|
u8 packet_flags = 0;
|
||||||
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, 0);
|
N_SndPacket *packet = host_channel_snd_packet_alloc(channel, 0);
|
||||||
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
Bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(&bb);
|
BitbuffWriter bw = bw_from_bitbuff(&bb);
|
||||||
bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
|
bw_write_ubits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||||
bw_write_ibits(&bw, HOST_PACKET_KIND_HEARTBEAT, 8);
|
bw_write_ibits(&bw, HOST_PACKET_KIND_HEARTBEAT, 8);
|
||||||
bw_write_ubits(&bw, packet_flags, 8);
|
bw_write_ubits(&bw, packet_flags, 8);
|
||||||
bw_write_uv(&bw, channel->our_acked_seq);
|
bw_write_uv(&bw, channel->our_acked_seq);
|
||||||
@ -956,28 +930,28 @@ void host_update_end(struct host *host)
|
|||||||
{
|
{
|
||||||
b32 is_reliable = cmd->write_reliable;
|
b32 is_reliable = cmd->write_reliable;
|
||||||
u8 packet_flags = (is_reliable * HOST_PACKET_FLAG_RELIABLE);
|
u8 packet_flags = (is_reliable * HOST_PACKET_FLAG_RELIABLE);
|
||||||
struct string msg = cmd->write_msg;
|
String msg = cmd->write_msg;
|
||||||
|
|
||||||
u64 chunk_count = 0;
|
u64 chunk_count = 0;
|
||||||
if (msg.len > 0) {
|
if (msg.len > 0) {
|
||||||
chunk_count = (msg.len - 1) / PACKET_MSG_CHUNK_MAX_LEN;
|
chunk_count = (msg.len - 1) / N_MaxPacketChunkLen;
|
||||||
}
|
}
|
||||||
chunk_count += 1;
|
chunk_count += 1;
|
||||||
|
|
||||||
u64 msg_id = ++channel->last_sent_msg_id;
|
u64 msg_id = ++channel->last_sent_msg_id;
|
||||||
for (u64 i = 0; i < chunk_count; ++i) {
|
for (u64 i = 0; i < chunk_count; ++i) {
|
||||||
u64 chunk_len = PACKET_MSG_CHUNK_MAX_LEN;
|
u64 chunk_len = N_MaxPacketChunkLen;
|
||||||
b32 is_last_chunk = i + 1 == chunk_count;
|
b32 is_last_chunk = i + 1 == chunk_count;
|
||||||
if (is_last_chunk) {
|
if (is_last_chunk) {
|
||||||
chunk_len = msg.len % PACKET_MSG_CHUNK_MAX_LEN;
|
chunk_len = msg.len % N_MaxPacketChunkLen;
|
||||||
if (chunk_len == 0) {
|
if (chunk_len == 0) {
|
||||||
chunk_len = PACKET_MSG_CHUNK_MAX_LEN;
|
chunk_len = N_MaxPacketChunkLen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, is_reliable);
|
N_SndPacket *packet = host_channel_snd_packet_alloc(channel, is_reliable);
|
||||||
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
Bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
|
||||||
struct bitbuff_writer bw = bw_from_bitbuff(&bb);
|
BitbuffWriter bw = bw_from_bitbuff(&bb);
|
||||||
bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
|
bw_write_ubits(&bw, N_PacketMagic, 32); /* TODO: implicitly encode magic into crc32 */
|
||||||
bw_write_ibits(&bw, HOST_PACKET_KIND_MSG_CHUNK, 8);
|
bw_write_ibits(&bw, HOST_PACKET_KIND_MSG_CHUNK, 8);
|
||||||
bw_write_ubits(&bw, packet_flags, 8);
|
bw_write_ubits(&bw, packet_flags, 8);
|
||||||
bw_write_uv(&bw, channel->our_acked_seq);
|
bw_write_uv(&bw, channel->our_acked_seq);
|
||||||
@ -990,7 +964,7 @@ void host_update_end(struct host *host)
|
|||||||
if (is_last_chunk) {
|
if (is_last_chunk) {
|
||||||
bw_write_uv(&bw, chunk_len);
|
bw_write_uv(&bw, chunk_len);
|
||||||
}
|
}
|
||||||
u8 *chunk_data = msg.text + (i * PACKET_MSG_CHUNK_MAX_LEN);
|
u8 *chunk_data = msg.text + (i * N_MaxPacketChunkLen);
|
||||||
bw_write_bytes(&bw, STRING(chunk_len, chunk_data));
|
bw_write_bytes(&bw, STRING(chunk_len, chunk_data));
|
||||||
packet->data_len = bw_num_bytes_written(&bw);
|
packet->data_len = bw_num_bytes_written(&bw);
|
||||||
}
|
}
|
||||||
@ -1013,12 +987,12 @@ void host_update_end(struct host *host)
|
|||||||
if (channel->valid) {
|
if (channel->valid) {
|
||||||
struct sys_address address = channel->address;
|
struct sys_address address = channel->address;
|
||||||
/* Send reliable packets to channel */
|
/* Send reliable packets to channel */
|
||||||
for (struct host_snd_packet *packet = channel->first_reliable_packet; packet; packet = packet->next) {
|
for (N_SndPacket *packet = channel->first_reliable_packet; packet; packet = packet->next) {
|
||||||
sys_sock_write(sock, address, STRING(packet->data_len, packet->data));
|
sys_sock_write(sock, address, STRING(packet->data_len, packet->data));
|
||||||
total_sent += packet->data_len;
|
total_sent += packet->data_len;
|
||||||
}
|
}
|
||||||
/* Send unreliable packets to channel */
|
/* Send unreliable packets to channel */
|
||||||
for (struct host_snd_packet *packet = channel->first_unreliable_packet; packet; packet = packet->next) {
|
for (N_SndPacket *packet = channel->first_unreliable_packet; packet; packet = packet->next) {
|
||||||
sys_sock_write(sock, address, STRING(packet->data_len, packet->data));
|
sys_sock_write(sock, address, STRING(packet->data_len, packet->data));
|
||||||
total_sent += packet->data_len;
|
total_sent += packet->data_len;
|
||||||
}
|
}
|
||||||
168
src/net/net_core.h
Normal file
168
src/net/net_core.h
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#define HOST_CHANNEL_ID_NIL (N_ChannelId) { .gen = 0, .idx = 0 }
|
||||||
|
#define HOST_CHANNEL_ID_ALL (N_ChannelId) { .gen = U32_MAX, .idx = U32_MAX }
|
||||||
|
|
||||||
|
#define N_PacketMagic 0xd9e3b8b6
|
||||||
|
#define N_MaxPacketChunkLen 1024
|
||||||
|
#define N_MaxPacketLen 1280 /* Give enough space for msg chunk + header */
|
||||||
|
|
||||||
|
#define N_NumChannelLookupBins 512
|
||||||
|
#define N_NumMsgAssemblerLookupBins 16384
|
||||||
|
|
||||||
|
typedef enum N_CmdKind {
|
||||||
|
HOST_CMD_KIND_NONE,
|
||||||
|
|
||||||
|
HOST_CMD_KIND_TRY_CONNECT,
|
||||||
|
HOST_CMD_KIND_CONNECT_SUCCESS,
|
||||||
|
HOST_CMD_KIND_DISCONNECT,
|
||||||
|
HOST_CMD_KIND_HEARTBEAT,
|
||||||
|
HOST_CMD_KIND_WRITE
|
||||||
|
} N_CmdKind;
|
||||||
|
|
||||||
|
typedef enum N_EventKind {
|
||||||
|
HOST_EVENT_KIND_NONE,
|
||||||
|
|
||||||
|
HOST_EVENT_KIND_CHANNEL_OPENED,
|
||||||
|
HOST_EVENT_KIND_CHANNEL_CLOSED,
|
||||||
|
HOST_EVENT_KIND_MSG
|
||||||
|
} N_EventKind;
|
||||||
|
|
||||||
|
typedef enum N_WriteFlag {
|
||||||
|
HOST_WRITE_FLAG_NONE = 0,
|
||||||
|
|
||||||
|
HOST_WRITE_FLAG_RELIABLE = (1 << 0)
|
||||||
|
} N_WriteFlag;
|
||||||
|
|
||||||
|
typedef struct N_ChannelId N_ChannelId;
|
||||||
|
struct N_ChannelId {
|
||||||
|
u32 gen;
|
||||||
|
u32 idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N_Cmd N_Cmd;
|
||||||
|
struct N_Cmd {
|
||||||
|
N_CmdKind kind;
|
||||||
|
N_ChannelId channel_id;
|
||||||
|
|
||||||
|
u16 heartbeat_id;
|
||||||
|
u16 heartbeat_ack_id;
|
||||||
|
|
||||||
|
b32 write_reliable;
|
||||||
|
String write_msg;
|
||||||
|
|
||||||
|
|
||||||
|
N_Cmd *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N_Event N_Event;
|
||||||
|
struct N_Event {
|
||||||
|
N_EventKind kind;
|
||||||
|
N_ChannelId channel_id;
|
||||||
|
String msg;
|
||||||
|
|
||||||
|
N_Event *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N_EventList N_EventList;
|
||||||
|
struct N_EventList {
|
||||||
|
N_Event *first;
|
||||||
|
N_Event *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N_ChannelLookupBin N_ChannelLookupBin;
|
||||||
|
struct N_ChannelLookupBin {
|
||||||
|
struct host_channel *first;
|
||||||
|
struct host_channel *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N_RcvBuffer N_RcvBuffer;
|
||||||
|
struct N_RcvBuffer {
|
||||||
|
Arena *arena;
|
||||||
|
struct host_rcv_packet *first_packet;
|
||||||
|
struct host_rcv_packet *last_packet;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N_SndPacket N_SndPacket;
|
||||||
|
struct N_SndPacket {
|
||||||
|
N_SndPacket *next;
|
||||||
|
u64 seq;
|
||||||
|
|
||||||
|
u64 data_len;
|
||||||
|
u8 data[N_MaxPacketLen];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct N_Host N_Host;
|
||||||
|
struct N_Host {
|
||||||
|
Arena *arena;
|
||||||
|
|
||||||
|
struct sys_sock *sock;
|
||||||
|
|
||||||
|
BuddyCtx *buddy; /* For storing msg assembler data */
|
||||||
|
|
||||||
|
Arena *cmd_arena;
|
||||||
|
N_Cmd *first_cmd;
|
||||||
|
N_Cmd *last_cmd;
|
||||||
|
N_Cmd *first_free_cmd;
|
||||||
|
|
||||||
|
Arena *channel_arena;
|
||||||
|
struct host_channel *channels;
|
||||||
|
struct host_channel *first_free_channel;
|
||||||
|
u64 num_channels_reserved;
|
||||||
|
|
||||||
|
N_SndPacket *first_free_packet; /* Allocated in `arena` */
|
||||||
|
struct host_msg_assembler *first_free_msg_assembler; /* Allocated in `arena` */
|
||||||
|
|
||||||
|
N_ChannelLookupBin *channel_lookup_bins; /* Allocated in `arena` */
|
||||||
|
u64 num_channel_lookup_bins;
|
||||||
|
|
||||||
|
struct host_msg_assembler_lookup_bin *msg_assembler_lookup_bins; /* Allocated in `arena` */
|
||||||
|
u64 num_msg_assembler_lookup_bins;
|
||||||
|
|
||||||
|
/* Double buffer for incoming data */
|
||||||
|
struct snc_mutex rcv_buffer_write_mutex;
|
||||||
|
N_RcvBuffer *rcv_buffer_read;
|
||||||
|
N_RcvBuffer *rcv_buffer_write;
|
||||||
|
|
||||||
|
u64 bytes_received;
|
||||||
|
u64 bytes_sent;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Startup
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
typedef struct N_StartupReceipt N_StartupReceipt;
|
||||||
|
struct N_StartupReceipt { i32 _; };
|
||||||
|
N_StartupReceipt host_startup(void);
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Host
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
N_Host *host_alloc(u16 listen_port);
|
||||||
|
|
||||||
|
void host_release(N_Host *host);
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Queue
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
void host_queue_connect_to_address(N_Host *host, struct sys_address connect_address);
|
||||||
|
|
||||||
|
void host_queue_disconnect(N_Host *host, N_ChannelId channel_id);
|
||||||
|
|
||||||
|
void host_queue_write(N_Host *host, N_ChannelId channel_id, String msg, u32 flags);
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Info
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
i64 host_get_channel_last_rtt_ns(N_Host *host, N_ChannelId channel_id);
|
||||||
|
INLINE b32 host_channel_id_eq(N_ChannelId a, N_ChannelId b) { return a.idx == b.idx && a.gen == b.gen; }
|
||||||
|
INLINE b32 host_channel_id_is_nil(N_ChannelId id) { return id.gen == 0 && id.idx == 0; }
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Update
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
N_EventList host_update_begin(Arena *arena, N_Host *host);
|
||||||
|
void host_update_end(N_Host *host);
|
||||||
@ -1,4 +1,3 @@
|
|||||||
struct mixer_startup_receipt;
|
typedef struct PB_StartupReceipt PB_StartupReceipt;
|
||||||
|
struct PB_StartupReceipt { i32 _; };
|
||||||
struct playback_startup_receipt { i32 _; };
|
PB_StartupReceipt playback_startup(M_StartupReceipt *mixer_sr);
|
||||||
struct playback_startup_receipt playback_startup(struct mixer_startup_receipt *mixer_sr);
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ struct wasapi_buffer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
IAudioClient *client;
|
IAudioClient *client;
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
IAudioRenderClient *playback;
|
IAudioRenderClient *playback;
|
||||||
@ -50,7 +50,7 @@ INTERNAL void wasapi_initialize(void);
|
|||||||
INTERNAL SYS_EXIT_FUNC(playback_shutdown);
|
INTERNAL SYS_EXIT_FUNC(playback_shutdown);
|
||||||
INTERNAL SYS_JOB_DEF(playback_job, _);
|
INTERNAL SYS_JOB_DEF(playback_job, _);
|
||||||
|
|
||||||
struct playback_startup_receipt playback_startup(struct mixer_startup_receipt *mixer_sr)
|
PB_StartupReceipt playback_startup(M_StartupReceipt *mixer_sr)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
(UNUSED)mixer_sr;
|
(UNUSED)mixer_sr;
|
||||||
@ -59,7 +59,7 @@ struct playback_startup_receipt playback_startup(struct mixer_startup_receipt *m
|
|||||||
sys_run(1, playback_job, 0, SYS_POOL_AUDIO, SYS_PRIORITY_HIGH, &G.playback_job_counter);
|
sys_run(1, playback_job, 0, SYS_POOL_AUDIO, SYS_PRIORITY_HIGH, &G.playback_job_counter);
|
||||||
sys_on_exit(&playback_shutdown);
|
sys_on_exit(&playback_shutdown);
|
||||||
|
|
||||||
return (struct playback_startup_receipt) { 0 };
|
return (PB_StartupReceipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL SYS_EXIT_FUNC(playback_shutdown)
|
INTERNAL SYS_EXIT_FUNC(playback_shutdown)
|
||||||
@ -185,7 +185,7 @@ INTERNAL struct wasapi_buffer wasapi_update_begin(void)
|
|||||||
return wspbuf;
|
return wspbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void wasapi_update_end(struct wasapi_buffer *wspbuf, struct mixed_pcm_f32 src)
|
INTERNAL void wasapi_update_end(struct wasapi_buffer *wspbuf, M_PcmF32 src)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
u32 frames_in_source = src.count / 2;
|
u32 frames_in_source = src.count / 2;
|
||||||
@ -228,7 +228,7 @@ INTERNAL SYS_JOB_DEF(playback_job, _)
|
|||||||
* need to halt mixer to prevent memory leak when sounds are played. */
|
* need to halt mixer to prevent memory leak when sounds are played. */
|
||||||
/* TODO: Signal counter that running job wiats on, rather than scheduling job manually */
|
/* TODO: Signal counter that running job wiats on, rather than scheduling job manually */
|
||||||
while (!atomic32_fetch(&G.shutdown)) {
|
while (!atomic32_fetch(&G.shutdown)) {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
{
|
{
|
||||||
__profn("Wasapi wait");
|
__profn("Wasapi wait");
|
||||||
WaitForSingleObject(G.event, INFINITE);
|
WaitForSingleObject(G.event, INFINITE);
|
||||||
@ -236,7 +236,7 @@ INTERNAL SYS_JOB_DEF(playback_job, _)
|
|||||||
{
|
{
|
||||||
__profn("Fill sample buffer");
|
__profn("Fill sample buffer");
|
||||||
struct wasapi_buffer wspbuf = wasapi_update_begin();
|
struct wasapi_buffer wspbuf = wasapi_update_begin();
|
||||||
struct mixed_pcm_f32 pcm = mixer_update(scratch.arena, wspbuf.frames_count);
|
M_PcmF32 pcm = mixer_update(scratch.arena, wspbuf.frames_count);
|
||||||
wasapi_update_end(&wspbuf, pcm);
|
wasapi_update_end(&wspbuf, pcm);
|
||||||
}
|
}
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
/* Add resource data to binary */
|
/* Add resource data to binary */
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
struct tar_archive archive;
|
struct tar_archive archive;
|
||||||
@ -16,13 +16,13 @@ GLOBAL struct {
|
|||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct resource_startup_receipt resource_startup(void)
|
R_StartupReceipt resource_startup(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
G.arena = arena_alloc(GIBI(64));
|
G.arena = arena_alloc(GIBI(64));
|
||||||
|
|
||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
struct string embedded_data = inc_res_tar();
|
String embedded_data = inc_res_tar();
|
||||||
if (embedded_data.len <= 0) {
|
if (embedded_data.len <= 0) {
|
||||||
sys_panic(LIT("No embedded resources found"));
|
sys_panic(LIT("No embedded resources found"));
|
||||||
}
|
}
|
||||||
@ -34,28 +34,28 @@ struct resource_startup_receipt resource_startup(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (struct resource_startup_receipt) { 0 };
|
return (R_StartupReceipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Open / close
|
* Open / close
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct resource resource_open(struct string name)
|
R_Resource resource_open(String name)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
struct resource res = ZI;
|
R_Resource res = ZI;
|
||||||
struct tar_entry *entry = tar_get(&G.archive, name);
|
struct tar_entry *entry = tar_get(&G.archive, name);
|
||||||
res._data = entry->data;
|
res._data = entry->data;
|
||||||
res._name = entry->file_name;
|
res._name = entry->file_name;
|
||||||
res._exists = entry->valid;
|
res._exists = entry->valid;
|
||||||
return res;
|
return res;
|
||||||
#else
|
#else
|
||||||
struct resource res = ZI;
|
R_Resource res = ZI;
|
||||||
if (name.len < countof(res._name_text)) {
|
if (name.len < countof(res._name_text)) {
|
||||||
u8 path_text[RESOURCE_NAME_LEN_MAX + (sizeof("res/") - 1)];
|
u8 path_text[RESOURCE_NAME_LEN_MAX + (sizeof("res/") - 1)];
|
||||||
struct string path = ZI;
|
String path = ZI;
|
||||||
{
|
{
|
||||||
path_text[0] = 'r';
|
path_text[0] = 'r';
|
||||||
path_text[1] = 'e';
|
path_text[1] = 'e';
|
||||||
@ -69,7 +69,7 @@ struct resource resource_open(struct string name)
|
|||||||
|
|
||||||
struct sys_file file = sys_file_open_read_wait(path);
|
struct sys_file file = sys_file_open_read_wait(path);
|
||||||
struct sys_file_map file_map = ZI;
|
struct sys_file_map file_map = ZI;
|
||||||
struct string data = ZI;
|
String data = ZI;
|
||||||
if (file.valid) {
|
if (file.valid) {
|
||||||
file_map = sys_file_map_open_read(file);
|
file_map = sys_file_map_open_read(file);
|
||||||
if (file_map.valid) {
|
if (file_map.valid) {
|
||||||
@ -95,7 +95,7 @@ struct resource resource_open(struct string name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !RESOURCES_EMBEDDED
|
#if !RESOURCES_EMBEDDED
|
||||||
void resource_close(struct resource *res_ptr)
|
void resource_close(R_Resource *res_ptr)
|
||||||
{
|
{
|
||||||
sys_file_map_close(res_ptr->_file_map);
|
sys_file_map_close(res_ptr->_file_map);
|
||||||
sys_file_close(res_ptr->_file);
|
sys_file_close(res_ptr->_file);
|
||||||
|
|||||||
@ -3,11 +3,12 @@
|
|||||||
/* A resource contains data that can be retrieved globally by name.
|
/* A resource contains data that can be retrieved globally by name.
|
||||||
* If enabled during compilation, resource data is embedded in the
|
* If enabled during compilation, resource data is embedded in the
|
||||||
* executable. Otherwise each resource represents a file on disk. */
|
* executable. Otherwise each resource represents a file on disk. */
|
||||||
struct resource {
|
typedef struct R_Resource R_Resource;
|
||||||
struct string _data;
|
struct R_Resource {
|
||||||
|
String _data;
|
||||||
b32 _exists;
|
b32 _exists;
|
||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
struct string _name;
|
String _name;
|
||||||
#else
|
#else
|
||||||
struct sys_file _file;
|
struct sys_file _file;
|
||||||
struct sys_file_map _file_map;
|
struct sys_file_map _file_map;
|
||||||
@ -20,19 +21,20 @@ struct resource {
|
|||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct resource_startup_receipt { i32 _; };
|
typedef struct R_StartupReceipt R_StartupReceipt;
|
||||||
struct resource_startup_receipt resource_startup(void);
|
struct R_StartupReceipt { i32 _; };
|
||||||
|
R_StartupReceipt resource_startup(void);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Open / close
|
* Open / close
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct resource resource_open(struct string name);
|
R_Resource resource_open(String name);
|
||||||
|
|
||||||
#if RESOURCES_EMBEDDED
|
#if RESOURCES_EMBEDDED
|
||||||
#define resource_close(res_ptr) (UNUSED)res_ptr
|
#define resource_close(res_ptr) (UNUSED)res_ptr
|
||||||
#else
|
#else
|
||||||
void resource_close(struct resource *res_ptr);
|
void resource_close(R_Resource *res_ptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
struct string settings_serialize(struct arena *arena, const struct sys_window_settings *settings)
|
String settings_serialize(Arena *arena, const struct sys_window_settings *settings)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct string minimized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MINIMIZED ? LIT("true") : LIT("false");
|
String minimized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MINIMIZED ? LIT("true") : LIT("false");
|
||||||
struct string maximized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED ? LIT("true") : LIT("false");
|
String maximized = settings->flags & SYS_WINDOW_SETTINGS_FLAG_MAXIMIZED ? LIT("true") : LIT("false");
|
||||||
struct string fullscreen = settings->flags & SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN ? LIT("true") : LIT("false");
|
String fullscreen = settings->flags & SYS_WINDOW_SETTINGS_FLAG_FULLSCREEN ? LIT("true") : LIT("false");
|
||||||
i32 x = settings->floating_x;
|
i32 x = settings->floating_x;
|
||||||
i32 y = settings->floating_y;
|
i32 y = settings->floating_y;
|
||||||
i32 width = settings->floating_width;
|
i32 width = settings->floating_width;
|
||||||
i32 height = settings->floating_height;
|
i32 height = settings->floating_height;
|
||||||
|
|
||||||
struct string fmt = LIT(
|
String fmt = LIT(
|
||||||
"{\n"
|
"{\n"
|
||||||
" \"window\": {\n"
|
" \"window\": {\n"
|
||||||
" \"minimized\": %F,\n"
|
" \"minimized\": %F,\n"
|
||||||
@ -24,7 +24,7 @@ struct string settings_serialize(struct arena *arena, const struct sys_window_se
|
|||||||
"}\n"
|
"}\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
struct string formatted = string_format(arena,
|
String formatted = string_format(arena,
|
||||||
fmt,
|
fmt,
|
||||||
FMT_STR(minimized),
|
FMT_STR(minimized),
|
||||||
FMT_STR(maximized),
|
FMT_STR(maximized),
|
||||||
@ -37,29 +37,29 @@ struct string settings_serialize(struct arena *arena, const struct sys_window_se
|
|||||||
return formatted;
|
return formatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_window_settings *settings_deserialize(struct arena *arena, struct string src, struct string *error_out)
|
struct sys_window_settings *settings_deserialize(Arena *arena, String src, String *error_out)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
struct string error = ZI;
|
String error = ZI;
|
||||||
struct json_error json_error = ZI;
|
JSON_Error json_error = ZI;
|
||||||
|
|
||||||
struct sys_window_settings *settings = arena_push(arena, struct sys_window_settings);
|
struct sys_window_settings *settings = arena_push(arena, struct sys_window_settings);
|
||||||
struct json_parse_result parse_res = json_from_string(scratch.arena, src);
|
JSON_Result parse_res = json_from_string(scratch.arena, src);
|
||||||
|
|
||||||
if (parse_res.errors.count > 0) {
|
if (parse_res.errors.count > 0) {
|
||||||
json_error = *parse_res.errors.first;
|
json_error = *parse_res.errors.first;
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct json *root = parse_res.root;
|
JSON_Blob *root = parse_res.root;
|
||||||
if (!root) {
|
if (!root) {
|
||||||
error = LIT("Root object not found.");
|
error = LIT("Root object not found.");
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct json *window = root->child_first;
|
JSON_Blob *window = root->child_first;
|
||||||
if (!window || window->type != JSON_TYPE_OBJECT || !string_eq(window->key, LIT("window"))) {
|
if (!window || window->type != JSON_TYPE_OBJECT || !string_eq(window->key, LIT("window"))) {
|
||||||
error = LIT("\"window\" object not found");
|
error = LIT("\"window\" object not found");
|
||||||
goto abort;
|
goto abort;
|
||||||
@ -71,8 +71,8 @@ struct sys_window_settings *settings_deserialize(struct arena *arena, struct str
|
|||||||
b32 found_y = 0;
|
b32 found_y = 0;
|
||||||
b32 found_width = 0;
|
b32 found_width = 0;
|
||||||
b32 found_height = 0;
|
b32 found_height = 0;
|
||||||
for (struct json *child = window->child_first; child; child = child->next) {
|
for (JSON_Blob *child = window->child_first; child; child = child->next) {
|
||||||
struct string key = child->key;
|
String key = child->key;
|
||||||
|
|
||||||
if (string_eq(key, LIT("maximized"))) {
|
if (string_eq(key, LIT("maximized"))) {
|
||||||
if (child->type != JSON_TYPE_BOOL) {
|
if (child->type != JSON_TYPE_BOOL) {
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
struct sys_window_settings;
|
String settings_serialize(Arena *arena, const struct sys_window_settings *settings);
|
||||||
|
|
||||||
struct string settings_serialize(struct arena *arena, const struct sys_window_settings *settings);
|
struct sys_window_settings *settings_deserialize(Arena *arena, String src, String *error_out);
|
||||||
|
|
||||||
struct sys_window_settings *settings_deserialize(struct arena *arena, struct string src, struct string *error_out);
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
#include "../base/base.h"
|
#include "../base/base.h"
|
||||||
#include "../sprite/sprite.h"
|
#include "../sprite/sprite.h"
|
||||||
#include "../collider/collider.h"
|
#include "../collider/collider.h"
|
||||||
#include "../host/host.h"
|
#include "../net/net.h"
|
||||||
#include "../mixer/mixer.h"
|
#include "../mixer/mixer.h"
|
||||||
|
|
||||||
#include "sim_core.h"
|
#include "sim_core.h"
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct arena *nil_arena;
|
Arena *nil_arena;
|
||||||
struct sim_client_store *nil_client_store;
|
struct sim_client_store *nil_client_store;
|
||||||
struct sim_client *nil_client;
|
struct sim_client *nil_client;
|
||||||
struct sim_snapshot *nil_snapshot;
|
struct sim_snapshot *nil_snapshot;
|
||||||
@ -99,7 +99,7 @@ struct sim_client_store *sim_client_store_alloc(void)
|
|||||||
__prof;
|
__prof;
|
||||||
struct sim_client_store *store;
|
struct sim_client_store *store;
|
||||||
{
|
{
|
||||||
struct arena *arena = arena_alloc(GIBI(64));
|
Arena *arena = arena_alloc(GIBI(64));
|
||||||
store = arena_push(arena, struct sim_client_store);
|
store = arena_push(arena, struct sim_client_store);
|
||||||
store->arena = arena;
|
store->arena = arena;
|
||||||
}
|
}
|
||||||
@ -187,15 +187,15 @@ void sim_client_release(struct sim_client *client)
|
|||||||
* Client lookup
|
* Client lookup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL u64 hash_from_channel_id(struct host_channel_id channel_id)
|
INTERNAL u64 hash_from_channel_id(N_ChannelId channel_id)
|
||||||
{
|
{
|
||||||
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&channel_id));
|
return hash_fnv64(HASH_FNV64_BASIS, STRING_FROM_STRUCT(&channel_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_client_set_channel_id(struct sim_client *client, struct host_channel_id channel_id)
|
void sim_client_set_channel_id(struct sim_client *client, N_ChannelId channel_id)
|
||||||
{
|
{
|
||||||
struct sim_client_store *store = client->store;
|
struct sim_client_store *store = client->store;
|
||||||
struct host_channel_id old_channel_id = client->channel_id;
|
N_ChannelId old_channel_id = client->channel_id;
|
||||||
|
|
||||||
/* Remove old channel id from channel lookup */
|
/* Remove old channel id from channel lookup */
|
||||||
if (!host_channel_id_is_nil(old_channel_id)) {
|
if (!host_channel_id_is_nil(old_channel_id)) {
|
||||||
@ -236,7 +236,7 @@ void sim_client_set_channel_id(struct sim_client *client, struct host_channel_id
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, struct host_channel_id channel_id)
|
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, N_ChannelId channel_id)
|
||||||
{
|
{
|
||||||
struct sim_client *res = sim_client_nil();
|
struct sim_client *res = sim_client_nil();
|
||||||
u64 channel_hash = hash_from_channel_id(channel_id);
|
u64 channel_hash = hash_from_channel_id(channel_id);
|
||||||
@ -275,8 +275,8 @@ struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_sn
|
|||||||
|
|
||||||
struct sim_snapshot *ss;
|
struct sim_snapshot *ss;
|
||||||
{
|
{
|
||||||
struct arena *arena = ZI;
|
Arena *arena = ZI;
|
||||||
struct arena *ents_arena = 0;
|
Arena *ents_arena = 0;
|
||||||
{
|
{
|
||||||
ss = client->first_free_snapshot;
|
ss = client->first_free_snapshot;
|
||||||
if (ss) {
|
if (ss) {
|
||||||
@ -540,26 +540,26 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *clien
|
|||||||
* Tile
|
* Tile
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct v2i32 sim_world_tile_index_from_pos(struct v2 pos)
|
V2i32 sim_world_tile_index_from_pos(V2 pos)
|
||||||
{
|
{
|
||||||
struct v2i32 res = V2I32(pos.x * SIM_TILES_PER_UNIT_SQRT, pos.y * SIM_TILES_PER_UNIT_SQRT);
|
V2i32 res = V2i32FromXY(pos.x * SIM_TILES_PER_UNIT_SQRT, pos.y * SIM_TILES_PER_UNIT_SQRT);
|
||||||
res.x -= pos.x < 0;
|
res.x -= pos.x < 0;
|
||||||
res.y -= pos.y < 0;
|
res.y -= pos.y < 0;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 sim_pos_from_world_tile_index(struct v2i32 world_tile_index)
|
V2 sim_pos_from_world_tile_index(V2i32 world_tile_index)
|
||||||
{
|
{
|
||||||
struct v2 res = ZI;
|
V2 res = ZI;
|
||||||
f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT;
|
f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT;
|
||||||
res.x = (f32)world_tile_index.x * tile_size;
|
res.x = (f32)world_tile_index.x * tile_size;
|
||||||
res.y = (f32)world_tile_index.y * tile_size;
|
res.y = (f32)world_tile_index.y * tile_size;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2i32 sim_local_tile_index_from_world_tile_index(struct v2i32 world_tile_index)
|
V2i32 sim_local_tile_index_from_world_tile_index(V2i32 world_tile_index)
|
||||||
{
|
{
|
||||||
struct v2i32 res = world_tile_index;
|
V2i32 res = world_tile_index;
|
||||||
res.x += res.x < 0;
|
res.x += res.x < 0;
|
||||||
res.y += res.y < 0;
|
res.y += res.y < 0;
|
||||||
res.x = res.x % SIM_TILES_PER_CHUNK_SQRT;
|
res.x = res.x % SIM_TILES_PER_CHUNK_SQRT;
|
||||||
@ -569,17 +569,17 @@ struct v2i32 sim_local_tile_index_from_world_tile_index(struct v2i32 world_tile_
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2i32 sim_world_tile_index_from_local_tile_index(struct v2i32 tile_chunk_index, struct v2i32 local_tile_index)
|
V2i32 sim_world_tile_index_from_local_tile_index(V2i32 tile_chunk_index, V2i32 local_tile_index)
|
||||||
{
|
{
|
||||||
struct v2i32 res = ZI;
|
V2i32 res = ZI;
|
||||||
res.x = (tile_chunk_index.x * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.x;
|
res.x = (tile_chunk_index.x * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.x;
|
||||||
res.y = (tile_chunk_index.y * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.y;
|
res.y = (tile_chunk_index.y * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.y;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2i32 sim_tile_chunk_index_from_world_tile_index(struct v2i32 world_tile_index)
|
V2i32 sim_tile_chunk_index_from_world_tile_index(V2i32 world_tile_index)
|
||||||
{
|
{
|
||||||
struct v2i32 res = world_tile_index;
|
V2i32 res = world_tile_index;
|
||||||
res.x += res.x < 0;
|
res.x += res.x < 0;
|
||||||
res.y += res.y < 0;
|
res.y += res.y < 0;
|
||||||
res.x = res.x / SIM_TILES_PER_CHUNK_SQRT;
|
res.x = res.x / SIM_TILES_PER_CHUNK_SQRT;
|
||||||
@ -589,9 +589,9 @@ struct v2i32 sim_tile_chunk_index_from_world_tile_index(struct v2i32 world_tile_
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_snapshot_set_tile(struct sim_snapshot *ss, struct v2i32 world_tile_index, enum sim_tile_kind tile_kind)
|
void sim_snapshot_set_tile(struct sim_snapshot *ss, V2i32 world_tile_index, enum sim_tile_kind tile_kind)
|
||||||
{
|
{
|
||||||
struct v2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
V2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
||||||
|
|
||||||
struct sim_ent_id chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
struct sim_ent_id chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
||||||
struct sim_ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
struct sim_ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||||
@ -602,7 +602,7 @@ void sim_snapshot_set_tile(struct sim_snapshot *ss, struct v2i32 world_tile_inde
|
|||||||
chunk_ent->tile_chunk_index = chunk_index;
|
chunk_ent->tile_chunk_index = chunk_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2i32 local_index = sim_local_tile_index_from_world_tile_index(world_tile_index);
|
V2i32 local_index = sim_local_tile_index_from_world_tile_index(world_tile_index);
|
||||||
chunk_ent->tile_chunk_tiles[local_index.x + (local_index.y * SIM_TILES_PER_CHUNK_SQRT)] = tile_kind;
|
chunk_ent->tile_chunk_tiles[local_index.x + (local_index.y * SIM_TILES_PER_CHUNK_SQRT)] = tile_kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,7 +720,7 @@ void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *
|
|||||||
* Snapshot encode
|
* Snapshot encode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
|
void sim_snapshot_encode(BitbuffWriter *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -789,7 +789,7 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
|
|||||||
* Snapshot decode
|
* Snapshot decode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
|
void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -869,7 +869,7 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
|
|||||||
* Snapshot encode
|
* Snapshot encode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
|
void sim_snapshot_encode(BitbuffWriter *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -928,7 +928,7 @@ void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver,
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sim_ent_decode_node {
|
struct sim_ent_decode_node {
|
||||||
struct string tmp_encoded;
|
String tmp_encoded;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sim_ent_decode_queue {
|
struct sim_ent_decode_queue {
|
||||||
@ -936,10 +936,10 @@ struct sim_ent_decode_queue {
|
|||||||
struct sim_ent_decode_node *last;
|
struct sim_ent_decode_node *last;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
|
void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
ss->sim_dt_ns = br_read_iv(br);
|
ss->sim_dt_ns = br_read_iv(br);
|
||||||
ss->sim_time_ns = br_read_iv(br);
|
ss->sim_time_ns = br_read_iv(br);
|
||||||
@ -995,7 +995,7 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
|
|||||||
|
|
||||||
if (!released) {
|
if (!released) {
|
||||||
u64 num_ent_bits = br_read_uv(br);
|
u64 num_ent_bits = br_read_uv(br);
|
||||||
struct bitbuff_reader ent_br = br_from_seek_bits(br, num_ent_bits);
|
BitbuffReader ent_br = br_from_seek_bits(br, num_ent_bits);
|
||||||
if (br_num_bits_left(&ent_br) > 0) {
|
if (br_num_bits_left(&ent_br) > 0) {
|
||||||
struct sim_ent_decode_node *n = arena_push(scratch.arena, struct sim_ent_decode_node);
|
struct sim_ent_decode_node *n = arena_push(scratch.arena, struct sim_ent_decode_node);
|
||||||
n->is_new = allocation_changed && !released;
|
n->is_new = allocation_changed && !released;
|
||||||
@ -1036,7 +1036,7 @@ void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss)
|
|||||||
|
|
||||||
/* Decode ent data from decode queue */
|
/* Decode ent data from decode queue */
|
||||||
for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) {
|
for (struct sim_ent_decode_node *n = queue.first; n; n = n->next) {
|
||||||
struct bitbuff_reader ent_br = n->br;
|
BitbuffReader ent_br = n->br;
|
||||||
u32 index = n->index;
|
u32 index = n->index;
|
||||||
struct sim_ent *e = sim_ent_from_index(ss, index);
|
struct sim_ent *e = sim_ent_from_index(ss, index);
|
||||||
if (e->valid) {
|
if (e->valid) {
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
#define SIM_LAYER_RELATIVE_WEAPON (1)
|
#define SIM_LAYER_RELATIVE_WEAPON (1)
|
||||||
|
|
||||||
struct sim_ent_id {
|
struct sim_ent_id {
|
||||||
struct uid uid;
|
UID uid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sim_client_handle {
|
struct sim_client_handle {
|
||||||
@ -38,14 +38,14 @@ struct sim_client_lookup_bin {
|
|||||||
|
|
||||||
struct sim_client_store {
|
struct sim_client_store {
|
||||||
b32 valid;
|
b32 valid;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
/* Client lookup */
|
/* Client lookup */
|
||||||
struct sim_client_lookup_bin *client_lookup_bins;
|
struct sim_client_lookup_bin *client_lookup_bins;
|
||||||
u64 num_client_lookup_bins;
|
u64 num_client_lookup_bins;
|
||||||
|
|
||||||
/* Clients */
|
/* Clients */
|
||||||
struct arena *clients_arena;
|
Arena *clients_arena;
|
||||||
struct sim_client *clients;
|
struct sim_client *clients;
|
||||||
struct sim_client_handle first_free_client;
|
struct sim_client_handle first_free_client;
|
||||||
u64 num_clients_allocated;
|
u64 num_clients_allocated;
|
||||||
@ -77,12 +77,12 @@ struct sim_client {
|
|||||||
struct sim_client_handle handle;
|
struct sim_client_handle handle;
|
||||||
struct sim_client_store *store;
|
struct sim_client_store *store;
|
||||||
|
|
||||||
struct arena *snapshots_arena;
|
Arena *snapshots_arena;
|
||||||
|
|
||||||
/* Round trip time of the client (if networked) */
|
/* Round trip time of the client (if networked) */
|
||||||
i64 last_rtt_ns;
|
i64 last_rtt_ns;
|
||||||
|
|
||||||
struct host_channel_id channel_id;
|
N_ChannelId channel_id;
|
||||||
u64 channel_hash;
|
u64 channel_hash;
|
||||||
|
|
||||||
struct sim_client_handle next_free;
|
struct sim_client_handle next_free;
|
||||||
@ -128,8 +128,8 @@ INLINE b32 sim_client_handle_eq(struct sim_client_handle a, struct sim_client_ha
|
|||||||
struct sim_client *sim_client_alloc(struct sim_client_store *store);
|
struct sim_client *sim_client_alloc(struct sim_client_store *store);
|
||||||
void sim_client_release(struct sim_client *client);
|
void sim_client_release(struct sim_client *client);
|
||||||
|
|
||||||
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, struct host_channel_id channel_id);
|
struct sim_client *sim_client_from_channel_id(struct sim_client_store *store, N_ChannelId channel_id);
|
||||||
void sim_client_set_channel_id(struct sim_client *client, struct host_channel_id channel_id);
|
void sim_client_set_channel_id(struct sim_client *client, N_ChannelId channel_id);
|
||||||
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct sim_client_handle handle);
|
struct sim_client *sim_client_from_handle(struct sim_client_store *store, struct sim_client_handle handle);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -159,9 +159,9 @@ enum sim_control_flag {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct sim_control {
|
struct sim_control {
|
||||||
struct v2 move; /* Movement direction vector (speed of 0 -> 1) */
|
V2 move; /* Movement direction vector (speed of 0 -> 1) */
|
||||||
struct v2 focus; /* Focus direction vector (where does the controller want to look) */
|
V2 focus; /* Focus direction vector (where does the controller want to look) */
|
||||||
struct v2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */
|
V2 dbg_cursor; /* Where is the user's cursor in the world (used for things like editing the world) */
|
||||||
u32 flags;
|
u32 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -192,7 +192,7 @@ struct sim_snapshot {
|
|||||||
u64 prev_tick;
|
u64 prev_tick;
|
||||||
u64 next_tick;
|
u64 next_tick;
|
||||||
|
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
/* Sim time (guaranteed to increase by sim_dt_ns each step) */
|
/* Sim time (guaranteed to increase by sim_dt_ns each step) */
|
||||||
i64 sim_dt_ns;
|
i64 sim_dt_ns;
|
||||||
@ -212,7 +212,7 @@ struct sim_snapshot {
|
|||||||
u64 num_id_bins;
|
u64 num_id_bins;
|
||||||
|
|
||||||
/* Entities */
|
/* Entities */
|
||||||
struct arena *ents_arena;
|
Arena *ents_arena;
|
||||||
struct sim_ent *ents;
|
struct sim_ent *ents;
|
||||||
u32 first_free_ent;
|
u32 first_free_ent;
|
||||||
u32 num_ents_allocated;
|
u32 num_ents_allocated;
|
||||||
@ -225,9 +225,6 @@ INLINE struct sim_snapshot *sim_snapshot_nil(void)
|
|||||||
return *_g_sim_snapshot_nil;
|
return *_g_sim_snapshot_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bitbuff_writer;
|
|
||||||
struct bitbuff_reader;
|
|
||||||
|
|
||||||
/* Alloc */
|
/* Alloc */
|
||||||
struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_snapshot *src, u64 tick);
|
struct sim_snapshot *sim_snapshot_alloc(struct sim_client *client, struct sim_snapshot *src, u64 tick);
|
||||||
void sim_snapshot_release(struct sim_snapshot *sim_snapshot);
|
void sim_snapshot_release(struct sim_snapshot *sim_snapshot);
|
||||||
@ -239,12 +236,12 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *clien
|
|||||||
struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick);
|
struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick);
|
||||||
|
|
||||||
/* Tile */
|
/* Tile */
|
||||||
struct v2i32 sim_world_tile_index_from_pos(struct v2 pos);
|
V2i32 sim_world_tile_index_from_pos(V2 pos);
|
||||||
struct v2 sim_pos_from_world_tile_index(struct v2i32 world_tile_index);
|
V2 sim_pos_from_world_tile_index(V2i32 world_tile_index);
|
||||||
struct v2i32 sim_local_tile_index_from_world_tile_index(struct v2i32 world_tile_index);
|
V2i32 sim_local_tile_index_from_world_tile_index(V2i32 world_tile_index);
|
||||||
struct v2i32 sim_world_tile_index_from_local_tile_index(struct v2i32 tile_chunk_index, struct v2i32 local_tile_index);
|
V2i32 sim_world_tile_index_from_local_tile_index(V2i32 tile_chunk_index, V2i32 local_tile_index);
|
||||||
struct v2i32 sim_tile_chunk_index_from_world_tile_index(struct v2i32 world_tile_index);
|
V2i32 sim_tile_chunk_index_from_world_tile_index(V2i32 world_tile_index);
|
||||||
void sim_snapshot_set_tile(struct sim_snapshot *ss, struct v2i32 world_tile_index, enum sim_tile_kind tile_kind);
|
void sim_snapshot_set_tile(struct sim_snapshot *ss, V2i32 world_tile_index, enum sim_tile_kind tile_kind);
|
||||||
|
|
||||||
/* Lerp */
|
/* Lerp */
|
||||||
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
|
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
|
||||||
@ -253,5 +250,5 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str
|
|||||||
void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss, struct sim_ent_id remote_player, u32 sync_flags);
|
void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss, struct sim_ent_id remote_player, u32 sync_flags);
|
||||||
|
|
||||||
/* Encode / decode */
|
/* Encode / decode */
|
||||||
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1);
|
void sim_snapshot_encode(BitbuffWriter *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1);
|
||||||
void sim_snapshot_decode(struct bitbuff_reader *br, struct sim_snapshot *ss);
|
void sim_snapshot_decode(BitbuffReader *br, struct sim_snapshot *ss);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/* Id magic number constants (to be used in conjunction with ent ids in deterministic id combinations) */
|
/* Id magic number constants (to be used in conjunction with ent ids in deterministic id combinations) */
|
||||||
#define SIM_ENT_CONTACT_BASIS_UID (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
|
#define SIM_ENT_CONTACT_BASIS_UID (MakeUID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
|
||||||
#define SIM_ENT_COLLISION_DEBUG_BASIS_UID (UID(0x302c01182013bb02, 0x570bd270399d11a5))
|
#define SIM_ENT_COLLISION_DEBUG_BASIS_UID (MakeUID(0x302c01182013bb02, 0x570bd270399d11a5))
|
||||||
#define SIM_ENT_TILE_CHUNK_BASIS_UID (UID(0x3ce42de071dd226b, 0x9b566f7df30c813a))
|
#define SIM_ENT_TILE_CHUNK_BASIS_UID (MakeUID(0x3ce42de071dd226b, 0x9b566f7df30c813a))
|
||||||
|
|
||||||
INTERNAL u32 index_from_ent(struct sim_snapshot *ss, struct sim_ent *ent)
|
INTERNAL u32 index_from_ent(struct sim_snapshot *ss, struct sim_ent *ent)
|
||||||
{
|
{
|
||||||
@ -128,7 +128,7 @@ void sim_ent_release(struct sim_ent *ent)
|
|||||||
|
|
||||||
void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop prop)
|
void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop prop)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct sim_ent **ents_to_release = arena_push_dry(scratch.arena, struct sim_ent *);
|
struct sim_ent **ents_to_release = arena_push_dry(scratch.arena, struct sim_ent *);
|
||||||
u64 ents_to_release_count = 0;
|
u64 ents_to_release_count = 0;
|
||||||
@ -289,11 +289,11 @@ struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_i
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the deterministic id of the tile chunk that should be produced at chunk pos */
|
/* Returns the deterministic id of the tile chunk that should be produced at chunk pos */
|
||||||
struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(struct v2i32 chunk_index)
|
struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_index)
|
||||||
{
|
{
|
||||||
struct sim_ent_id res = ZI;
|
struct sim_ent_id res = ZI;
|
||||||
res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID;
|
res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID;
|
||||||
res.uid = uid_combine(res.uid, UID(rand_u64_from_seed(chunk_index.x), rand_u64_from_seed(chunk_index.y)));
|
res.uid = uid_combine(res.uid, MakeUID(rand_u64_from_seed(chunk_index.x), rand_u64_from_seed(chunk_index.y)));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,9 +412,9 @@ INTERNAL void sim_ent_mark_child_xforms_dirty(struct sim_snapshot *ss, struct si
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct xform sim_ent_get_xform_internal(struct sim_snapshot *ss, struct sim_ent *ent)
|
INTERNAL Xform sim_ent_get_xform_internal(struct sim_snapshot *ss, struct sim_ent *ent)
|
||||||
{
|
{
|
||||||
struct xform xf;
|
Xform xf;
|
||||||
if (ent->_is_xform_dirty) {
|
if (ent->_is_xform_dirty) {
|
||||||
if (ent->is_top) {
|
if (ent->is_top) {
|
||||||
xf = ent->_local_xform;
|
xf = ent->_local_xform;
|
||||||
@ -433,9 +433,9 @@ INTERNAL struct xform sim_ent_get_xform_internal(struct sim_snapshot *ss, struct
|
|||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xform sim_ent_get_xform(struct sim_ent *ent)
|
Xform sim_ent_get_xform(struct sim_ent *ent)
|
||||||
{
|
{
|
||||||
struct xform xf;
|
Xform xf;
|
||||||
if (ent->_is_xform_dirty) {
|
if (ent->_is_xform_dirty) {
|
||||||
if (ent->is_top) {
|
if (ent->is_top) {
|
||||||
xf = ent->_local_xform;
|
xf = ent->_local_xform;
|
||||||
@ -455,12 +455,12 @@ struct xform sim_ent_get_xform(struct sim_ent *ent)
|
|||||||
return xf;
|
return xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xform sim_ent_get_local_xform(struct sim_ent *ent)
|
Xform sim_ent_get_local_xform(struct sim_ent *ent)
|
||||||
{
|
{
|
||||||
return ent->_local_xform;
|
return ent->_local_xform;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_ent_set_xform(struct sim_ent *ent, struct xform xf)
|
void sim_ent_set_xform(struct sim_ent *ent, Xform xf)
|
||||||
{
|
{
|
||||||
if (!xform_eq(xf, ent->_xform)) {
|
if (!xform_eq(xf, ent->_xform)) {
|
||||||
struct sim_snapshot *ss = ent->ss;
|
struct sim_snapshot *ss = ent->ss;
|
||||||
@ -469,7 +469,7 @@ void sim_ent_set_xform(struct sim_ent *ent, struct xform xf)
|
|||||||
ent->_local_xform = xf;
|
ent->_local_xform = xf;
|
||||||
} else {
|
} else {
|
||||||
struct sim_ent *parent = sim_ent_from_id(ss, ent->parent);
|
struct sim_ent *parent = sim_ent_from_id(ss, ent->parent);
|
||||||
struct xform parent_global = sim_ent_get_xform_internal(ss, parent);
|
Xform parent_global = sim_ent_get_xform_internal(ss, parent);
|
||||||
ent->_local_xform = xform_mul(xform_invert(parent_global), xf);
|
ent->_local_xform = xform_mul(xform_invert(parent_global), xf);
|
||||||
}
|
}
|
||||||
ent->_xform = xf;
|
ent->_xform = xf;
|
||||||
@ -478,7 +478,7 @@ void sim_ent_set_xform(struct sim_ent *ent, struct xform xf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_ent_set_local_xform(struct sim_ent *ent, struct xform xf)
|
void sim_ent_set_local_xform(struct sim_ent *ent, Xform xf)
|
||||||
{
|
{
|
||||||
if (!xform_eq(xf, ent->_local_xform)) {
|
if (!xform_eq(xf, ent->_local_xform)) {
|
||||||
ent->_local_xform = xf;
|
ent->_local_xform = xf;
|
||||||
@ -491,7 +491,7 @@ void sim_ent_set_local_xform(struct sim_ent *ent, struct xform xf)
|
|||||||
* Ent movement
|
* Ent movement
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_ent_set_linear_velocity(struct sim_ent *ent, struct v2 velocity)
|
void sim_ent_set_linear_velocity(struct sim_ent *ent, V2 velocity)
|
||||||
{
|
{
|
||||||
if (sim_ent_has_prop(ent, SEPROP_KINEMATIC) || sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
if (sim_ent_has_prop(ent, SEPROP_KINEMATIC) || sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||||
ent->linear_velocity = v2_clamp_len(velocity, SIM_MAX_LINEAR_VELOCITY);
|
ent->linear_velocity = v2_clamp_len(velocity, SIM_MAX_LINEAR_VELOCITY);
|
||||||
@ -505,25 +505,25 @@ void sim_ent_set_angular_velocity(struct sim_ent *ent, f32 velocity)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_ent_apply_linear_impulse(struct sim_ent *ent, struct v2 impulse, struct v2 point)
|
void sim_ent_apply_linear_impulse(struct sim_ent *ent, V2 impulse, V2 point)
|
||||||
{
|
{
|
||||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
struct v2 center = xf.og;
|
V2 center = xf.og;
|
||||||
f32 scale = math_fabs(xform_get_determinant(xf));
|
f32 scale = math_fabs(xform_get_determinant(xf));
|
||||||
f32 inv_mass = 1.f / (ent->mass_unscaled * scale);
|
f32 inv_mass = 1.f / (ent->mass_unscaled * scale);
|
||||||
f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale);
|
f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale);
|
||||||
|
|
||||||
struct v2 vcp = v2_sub(point, center);
|
V2 vcp = v2_sub(point, center);
|
||||||
sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(impulse, inv_mass)));
|
sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(impulse, inv_mass)));
|
||||||
sim_ent_set_angular_velocity(ent, v2_wedge(vcp, impulse) * inv_inertia);
|
sim_ent_set_angular_velocity(ent, v2_wedge(vcp, impulse) * inv_inertia);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, struct v2 impulse)
|
void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, V2 impulse)
|
||||||
{
|
{
|
||||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
f32 scale = math_fabs(xform_get_determinant(xf));
|
f32 scale = math_fabs(xform_get_determinant(xf));
|
||||||
f32 inv_mass = 1.f / (ent->mass_unscaled * scale);
|
f32 inv_mass = 1.f / (ent->mass_unscaled * scale);
|
||||||
|
|
||||||
@ -531,7 +531,7 @@ void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, struct v2 impul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sim_ent_apply_force_to_center(struct sim_ent *ent, struct v2 force)
|
void sim_ent_apply_force_to_center(struct sim_ent *ent, V2 force)
|
||||||
{
|
{
|
||||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||||
ent->force = v2_add(ent->force, force);
|
ent->force = v2_add(ent->force, force);
|
||||||
@ -541,7 +541,7 @@ void sim_ent_apply_force_to_center(struct sim_ent *ent, struct v2 force)
|
|||||||
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse)
|
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse)
|
||||||
{
|
{
|
||||||
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
if (sim_ent_has_prop(ent, SEPROP_DYNAMIC)) {
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
f32 scale = math_fabs(xform_get_determinant(xf));
|
f32 scale = math_fabs(xform_get_determinant(xf));
|
||||||
f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale);
|
f32 inv_inertia = 1.f / (ent->inertia_unscaled * scale);
|
||||||
sim_ent_set_angular_velocity(ent, ent->angular_velocity + impulse * inv_inertia);
|
sim_ent_set_angular_velocity(ent, ent->angular_velocity + impulse * inv_inertia);
|
||||||
@ -559,21 +559,21 @@ void sim_ent_apply_torque(struct sim_ent *ent, f32 torque)
|
|||||||
* Tile
|
* Tile
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sim_ent *sim_tile_chunk_from_chunk_index(struct sim_snapshot *ss, struct v2i32 chunk_index)
|
struct sim_ent *sim_tile_chunk_from_chunk_index(struct sim_snapshot *ss, V2i32 chunk_index)
|
||||||
{
|
{
|
||||||
struct sim_ent_id chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
struct sim_ent_id chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
|
||||||
struct sim_ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
struct sim_ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
|
||||||
return chunk_ent;
|
return chunk_ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, struct v2i32 world_tile_index)
|
struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, V2i32 world_tile_index)
|
||||||
{
|
{
|
||||||
struct v2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
V2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
|
||||||
struct sim_ent *chunk_ent = sim_tile_chunk_from_chunk_index(ss, chunk_index);
|
struct sim_ent *chunk_ent = sim_tile_chunk_from_chunk_index(ss, chunk_index);
|
||||||
return chunk_ent;
|
return chunk_ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, struct v2i32 local_tile_index)
|
enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, V2i32 local_tile_index)
|
||||||
{
|
{
|
||||||
enum sim_tile_kind res = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
enum sim_tile_kind res = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
|
||||||
return res;
|
return res;
|
||||||
@ -592,8 +592,8 @@ void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64
|
|||||||
|
|
||||||
if (e->is_top) {
|
if (e->is_top) {
|
||||||
/* TODO: Cache parent & child xforms in sim */
|
/* TODO: Cache parent & child xforms in sim */
|
||||||
struct xform e0_xf = sim_ent_get_xform(e0);
|
Xform e0_xf = sim_ent_get_xform(e0);
|
||||||
struct xform e1_xf = sim_ent_get_xform(e1);
|
Xform e1_xf = sim_ent_get_xform(e1);
|
||||||
sim_ent_set_xform(e, xform_lerp(e0_xf, e1_xf, blend));
|
sim_ent_set_xform(e, xform_lerp(e0_xf, e1_xf, blend));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,7 +687,7 @@ void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote)
|
|||||||
* Ent encode
|
* Ent encode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_ent *e1)
|
void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||||
{
|
{
|
||||||
struct sim_snapshot *ss = e1->ss;
|
struct sim_snapshot *ss = e1->ss;
|
||||||
/* FIXME: Things like xforms need to be retreived manually rather than memcopied. */
|
/* FIXME: Things like xforms need to be retreived manually rather than memcopied. */
|
||||||
@ -714,7 +714,7 @@ void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_en
|
|||||||
* Ent decode
|
* Ent decode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
|
void sim_ent_decode(BitbuffReader *br, struct sim_ent *e)
|
||||||
{
|
{
|
||||||
struct sim_snapshot *old_ss = e->ss;
|
struct sim_snapshot *old_ss = e->ss;
|
||||||
{
|
{
|
||||||
@ -739,7 +739,7 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
|
|||||||
* Ent encode
|
* Ent encode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_ent *e1)
|
void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1)
|
||||||
{
|
{
|
||||||
struct sim_snapshot *ss = e1->ss;
|
struct sim_snapshot *ss = e1->ss;
|
||||||
|
|
||||||
@ -772,7 +772,7 @@ void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_en
|
|||||||
* Ent decode
|
* Ent decode
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
|
void sim_ent_decode(BitbuffReader *br, struct sim_ent *e)
|
||||||
{
|
{
|
||||||
struct sim_ent decoded = *e;
|
struct sim_ent decoded = *e;
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
#define SIM_ENT_NIL_ID ((struct sim_ent_id) { UID(0, 0) })
|
#define SIM_ENT_NIL_ID ((struct sim_ent_id) { MakeUID(0, 0) })
|
||||||
#define SIM_ENT_ROOT_ID ((struct sim_ent_id) { UID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
#define SIM_ENT_ROOT_ID ((struct sim_ent_id) { MakeUID(0xaaaaaaaaaaaaaaaa, 0xaaaaaaaaaaaaaaaa) })
|
||||||
|
|
||||||
struct bitbuff_writer;
|
|
||||||
struct bitbuff_reader;
|
|
||||||
|
|
||||||
enum sim_ent_prop {
|
enum sim_ent_prop {
|
||||||
SEPROP_ACTIVE,
|
SEPROP_ACTIVE,
|
||||||
@ -111,8 +108,8 @@ struct sim_ent {
|
|||||||
/* Position */
|
/* Position */
|
||||||
|
|
||||||
/* Use xform getters & setters to access. */
|
/* Use xform getters & setters to access. */
|
||||||
struct xform _local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */
|
Xform _local_xform; /* Transform in relation to parent ent (or the world if ent has no parent) */
|
||||||
struct xform _xform; /* Calculated from ent tree */
|
Xform _xform; /* Calculated from ent tree */
|
||||||
b32 _is_xform_dirty;
|
b32 _is_xform_dirty;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
@ -142,7 +139,7 @@ struct sim_ent {
|
|||||||
struct sim_ent_id cmd_control_hovered_ent;
|
struct sim_ent_id cmd_control_hovered_ent;
|
||||||
|
|
||||||
/* Chat cmd */
|
/* Chat cmd */
|
||||||
//struct string cmd_chat_msg;
|
//String cmd_chat_msg;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Chat */
|
/* Chat */
|
||||||
@ -150,7 +147,7 @@ struct sim_ent {
|
|||||||
/* SEPROP_CHAT */
|
/* SEPROP_CHAT */
|
||||||
|
|
||||||
struct sim_ent_id chat_player;
|
struct sim_ent_id chat_player;
|
||||||
//struct string chat_msg;
|
//String chat_msg;
|
||||||
|
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
@ -160,7 +157,7 @@ struct sim_ent {
|
|||||||
|
|
||||||
/* FIXME: Move out of here */
|
/* FIXME: Move out of here */
|
||||||
u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT];
|
u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT];
|
||||||
struct v2i32 tile_chunk_index;
|
V2i32 tile_chunk_index;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Client */
|
/* Client */
|
||||||
@ -172,7 +169,7 @@ struct sim_ent {
|
|||||||
struct sim_client_handle player_client_handle; /* The client handle on the master sim's machine */
|
struct sim_client_handle player_client_handle; /* The client handle on the master sim's machine */
|
||||||
|
|
||||||
struct sim_control player_control;
|
struct sim_control player_control;
|
||||||
struct v2 player_cursor_pos;
|
V2 player_cursor_pos;
|
||||||
|
|
||||||
struct sim_ent_id player_hovered_ent;
|
struct sim_ent_id player_hovered_ent;
|
||||||
struct sim_ent_id player_control_ent;
|
struct sim_ent_id player_control_ent;
|
||||||
@ -189,8 +186,8 @@ struct sim_ent {
|
|||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Collider */
|
/* Collider */
|
||||||
|
|
||||||
struct v2 collision_dir; /* If set, then only collisions coming from this direction will generate contacts (used for walls to prevent ghost collisions) */
|
V2 collision_dir; /* If set, then only collisions coming from this direction will generate contacts (used for walls to prevent ghost collisions) */
|
||||||
struct collider_shape local_collider;
|
CLD_Shape local_collider;
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
struct phys_collision_debug collision_debug_data;
|
struct phys_collision_debug collision_debug_data;
|
||||||
@ -247,10 +244,10 @@ struct sim_ent {
|
|||||||
f32 angular_ground_friction;
|
f32 angular_ground_friction;
|
||||||
|
|
||||||
/* Use sim_ent_set_linear_velocity & sim_ent_set_angular_velocity to set */
|
/* Use sim_ent_set_linear_velocity & sim_ent_set_angular_velocity to set */
|
||||||
struct v2 linear_velocity; /* m/s */
|
V2 linear_velocity; /* m/s */
|
||||||
f32 angular_velocity; /* rad/s */
|
f32 angular_velocity; /* rad/s */
|
||||||
|
|
||||||
struct v2 force;
|
V2 force;
|
||||||
f32 torque;
|
f32 torque;
|
||||||
|
|
||||||
f32 linear_damping;
|
f32 linear_damping;
|
||||||
@ -260,13 +257,13 @@ struct sim_ent {
|
|||||||
/* Sprite */
|
/* Sprite */
|
||||||
|
|
||||||
struct sprite_tag sprite;
|
struct sprite_tag sprite;
|
||||||
struct string sprite_span_name;
|
String sprite_span_name;
|
||||||
u32 sprite_tint;
|
u32 sprite_tint;
|
||||||
struct v3 sprite_emittance;
|
V3 sprite_emittance;
|
||||||
|
|
||||||
struct string sprite_collider_slice; /* Collider will sync to bounds of this slice if set */
|
String sprite_collider_slice; /* Collider will sync to bounds of this slice if set */
|
||||||
|
|
||||||
struct xform sprite_local_xform; /* Sprite transform in relation to ent */
|
Xform sprite_local_xform; /* Sprite transform in relation to ent */
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Animation */
|
/* Animation */
|
||||||
@ -280,7 +277,7 @@ struct sim_ent {
|
|||||||
|
|
||||||
/* SEPROP_ATTACHED */
|
/* SEPROP_ATTACHED */
|
||||||
/* Slice name on the parent ent's sprite to attach to */
|
/* Slice name on the parent ent's sprite to attach to */
|
||||||
struct string attach_slice;
|
String attach_slice;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Equip */
|
/* Equip */
|
||||||
@ -330,8 +327,8 @@ struct sim_ent {
|
|||||||
|
|
||||||
struct sim_ent_id bullet_src;
|
struct sim_ent_id bullet_src;
|
||||||
struct sim_ent_id bullet_tracer;
|
struct sim_ent_id bullet_tracer;
|
||||||
struct v2 bullet_src_pos;
|
V2 bullet_src_pos;
|
||||||
struct v2 bullet_src_dir;
|
V2 bullet_src_dir;
|
||||||
f32 bullet_launch_velocity;
|
f32 bullet_launch_velocity;
|
||||||
f32 bullet_knockback;
|
f32 bullet_knockback;
|
||||||
f32 bullet_explosion_strength;
|
f32 bullet_explosion_strength;
|
||||||
@ -349,13 +346,13 @@ struct sim_ent {
|
|||||||
|
|
||||||
/* SEPROP_TRACER */
|
/* SEPROP_TRACER */
|
||||||
|
|
||||||
struct v2 tracer_start;
|
V2 tracer_start;
|
||||||
struct v2 tracer_start_velocity;
|
V2 tracer_start_velocity;
|
||||||
f32 tracer_fade_duration; /* Time for tracer to fade from opacity of 1 to 0 */
|
f32 tracer_fade_duration; /* Time for tracer to fade from opacity of 1 to 0 */
|
||||||
|
|
||||||
/* calculated each frame */
|
/* calculated each frame */
|
||||||
struct v2 tracer_gradient_start;
|
V2 tracer_gradient_start;
|
||||||
struct v2 tracer_gradient_end;
|
V2 tracer_gradient_end;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Quake */
|
/* Quake */
|
||||||
@ -371,24 +368,24 @@ struct sim_ent {
|
|||||||
|
|
||||||
/* SEPROP_TEST */
|
/* SEPROP_TEST */
|
||||||
b32 test_initialized;
|
b32 test_initialized;
|
||||||
struct xform test_start_local_xform;
|
Xform test_start_local_xform;
|
||||||
struct xform test_start_sprite_xform;
|
Xform test_start_sprite_xform;
|
||||||
|
|
||||||
/* SEPROP_TEST_SOUND_EMITTER */
|
/* SEPROP_TEST_SOUND_EMITTER */
|
||||||
struct string sound_name;
|
String sound_name;
|
||||||
struct mixer_desc sound_desc;
|
M_TrackDesc sound_desc;
|
||||||
struct mixer_track_handle sound_handle;
|
M_Handle sound_handle;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Camera */
|
/* Camera */
|
||||||
|
|
||||||
/* SEPROP_CAMERA */
|
/* SEPROP_CAMERA */
|
||||||
struct sim_ent_id camera_follow;
|
struct sim_ent_id camera_follow;
|
||||||
struct xform camera_quad_xform;
|
Xform camera_quad_xform;
|
||||||
f32 camera_lerp; /* Rate at which camera xform approaches target xform */
|
f32 camera_lerp; /* Rate at which camera xform approaches target xform */
|
||||||
|
|
||||||
u32 camera_lerp_continuity_gen;
|
u32 camera_lerp_continuity_gen;
|
||||||
struct xform camera_xform_target; /* Calculated from camera_follow */
|
Xform camera_xform_target; /* Calculated from camera_follow */
|
||||||
u32 camera_applied_lerp_continuity_gen_plus_one; /* Calculated */
|
u32 camera_applied_lerp_continuity_gen_plus_one; /* Calculated */
|
||||||
|
|
||||||
f32 shake;
|
f32 shake;
|
||||||
@ -511,7 +508,7 @@ struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id);
|
|||||||
struct sim_ent_id sim_ent_random_id(void);
|
struct sim_ent_id sim_ent_random_id(void);
|
||||||
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
|
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
|
||||||
struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
|
struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
|
||||||
struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(struct v2i32 chunk_start);
|
struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(V2i32 chunk_start);
|
||||||
|
|
||||||
/* Query */
|
/* Query */
|
||||||
struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop);
|
struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop);
|
||||||
@ -522,24 +519,24 @@ void sim_ent_link_parent(struct sim_ent *parent, struct sim_ent *child);
|
|||||||
void sim_ent_unlink_from_parent(struct sim_ent *ent);
|
void sim_ent_unlink_from_parent(struct sim_ent *ent);
|
||||||
|
|
||||||
/* Xform */
|
/* Xform */
|
||||||
struct xform sim_ent_get_xform(struct sim_ent *ent);
|
Xform sim_ent_get_xform(struct sim_ent *ent);
|
||||||
struct xform sim_ent_get_local_xform(struct sim_ent *ent);
|
Xform sim_ent_get_local_xform(struct sim_ent *ent);
|
||||||
void sim_ent_set_xform(struct sim_ent *ent, struct xform xf);
|
void sim_ent_set_xform(struct sim_ent *ent, Xform xf);
|
||||||
void sim_ent_set_local_xform(struct sim_ent *ent, struct xform xf);
|
void sim_ent_set_local_xform(struct sim_ent *ent, Xform xf);
|
||||||
|
|
||||||
/* Movement */
|
/* Movement */
|
||||||
void sim_ent_set_linear_velocity(struct sim_ent *ent, struct v2 velocity);
|
void sim_ent_set_linear_velocity(struct sim_ent *ent, V2 velocity);
|
||||||
void sim_ent_set_angular_velocity(struct sim_ent *ent, f32 velocity);
|
void sim_ent_set_angular_velocity(struct sim_ent *ent, f32 velocity);
|
||||||
void sim_ent_apply_linear_impulse(struct sim_ent *ent, struct v2 impulse, struct v2 world_point);
|
void sim_ent_apply_linear_impulse(struct sim_ent *ent, V2 impulse, V2 world_point);
|
||||||
void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, struct v2 impulse);
|
void sim_ent_apply_linear_impulse_to_center(struct sim_ent *ent, V2 impulse);
|
||||||
void sim_ent_apply_force_to_center(struct sim_ent *ent, struct v2 force);
|
void sim_ent_apply_force_to_center(struct sim_ent *ent, V2 force);
|
||||||
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse);
|
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse);
|
||||||
void sim_ent_apply_torque(struct sim_ent *ent, f32 torque);
|
void sim_ent_apply_torque(struct sim_ent *ent, f32 torque);
|
||||||
|
|
||||||
/* Tile */
|
/* Tile */
|
||||||
struct sim_ent *sim_tile_chunk_from_chunk_index(struct sim_snapshot *ss, struct v2i32 chunk_index);
|
struct sim_ent *sim_tile_chunk_from_chunk_index(struct sim_snapshot *ss, V2i32 chunk_index);
|
||||||
struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, struct v2i32 world_tile_index);
|
struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, V2i32 world_tile_index);
|
||||||
enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, struct v2i32 local_tile_index);
|
enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, V2i32 local_tile_index);
|
||||||
|
|
||||||
/* Lerp */
|
/* Lerp */
|
||||||
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend);
|
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend);
|
||||||
@ -549,5 +546,5 @@ void sim_ent_sync_alloc_tree(struct sim_ent *local_parent, struct sim_ent *remot
|
|||||||
void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote);
|
void sim_ent_sync(struct sim_ent *local, struct sim_ent *remote);
|
||||||
|
|
||||||
/* Encode / decode */
|
/* Encode / decode */
|
||||||
void sim_ent_encode(struct bitbuff_writer *bw, struct sim_ent *e0, struct sim_ent *e1);
|
void sim_ent_encode(BitbuffWriter *bw, struct sim_ent *e0, struct sim_ent *e1);
|
||||||
void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e);
|
void sim_ent_decode(BitbuffReader *br, struct sim_ent *e);
|
||||||
|
|||||||
@ -32,9 +32,9 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
if (!(sim_ent_has_prop(check0, SEPROP_SOLID) || sim_ent_has_prop(check0, SEPROP_SENSOR))) continue;
|
if (!(sim_ent_has_prop(check0, SEPROP_SOLID) || sim_ent_has_prop(check0, SEPROP_SENSOR))) continue;
|
||||||
if (check0->local_collider.count <= 0) continue;
|
if (check0->local_collider.count <= 0) continue;
|
||||||
|
|
||||||
struct xform check0_xf = sim_ent_get_xform(check0);
|
Xform check0_xf = sim_ent_get_xform(check0);
|
||||||
struct collider_shape check0_collider = check0->local_collider;
|
CLD_Shape check0_collider = check0->local_collider;
|
||||||
struct aabb aabb = collider_aabb_from_collider(&check0_collider, check0_xf);
|
Aabb aabb = collider_aabb_from_collider(&check0_collider, check0_xf);
|
||||||
|
|
||||||
struct space_iter iter = space_iter_begin_aabb(space, aabb);
|
struct space_iter iter = space_iter_begin_aabb(space, aabb);
|
||||||
struct space_entry *space_entry;
|
struct space_entry *space_entry;
|
||||||
@ -48,10 +48,10 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
/* Deterministic order based on entity id */
|
/* Deterministic order based on entity id */
|
||||||
struct sim_ent *e0;
|
struct sim_ent *e0;
|
||||||
struct sim_ent *e1;
|
struct sim_ent *e1;
|
||||||
struct xform e0_xf;
|
Xform e0_xf;
|
||||||
struct xform e1_xf;
|
Xform e1_xf;
|
||||||
struct collider_shape e0_collider;
|
CLD_Shape e0_collider;
|
||||||
struct collider_shape e1_collider;
|
CLD_Shape e1_collider;
|
||||||
if (check0->id.uid.hi < check1->id.uid.hi) {
|
if (check0->id.uid.hi < check1->id.uid.hi) {
|
||||||
e0 = check0;
|
e0 = check0;
|
||||||
e1 = check1;
|
e1 = check1;
|
||||||
@ -81,7 +81,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate collision */
|
/* Calculate collision */
|
||||||
struct collider_collision_points_result collider_res = collider_collision_points(&e0_collider, &e1_collider, e0_xf, e1_xf);
|
CLD_CollisionResult collider_res = collider_collision_points(&e0_collider, &e1_collider, e0_xf, e1_xf);
|
||||||
|
|
||||||
/* Parts of algorithm are hard-coded to support 2 contact points */
|
/* Parts of algorithm are hard-coded to support 2 contact points */
|
||||||
STATIC_ASSERT(countof(constraint_ent->contact_constraint_data.points) == 2);
|
STATIC_ASSERT(countof(constraint_ent->contact_constraint_data.points) == 2);
|
||||||
@ -129,8 +129,8 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
|
|
||||||
/* Update / insert returned contacts */
|
/* Update / insert returned contacts */
|
||||||
for (u32 i = 0; i < collider_res.num_points; ++i) {
|
for (u32 i = 0; i < collider_res.num_points; ++i) {
|
||||||
struct collider_collision_point *res_point = &collider_res.points[i];
|
CLD_CollisionPoint *res_point = &collider_res.points[i];
|
||||||
struct v2 point = res_point->point;
|
V2 point = res_point->point;
|
||||||
f32 sep = res_point->separation;
|
f32 sep = res_point->separation;
|
||||||
u32 id = res_point->id;
|
u32 id = res_point->id;
|
||||||
struct phys_contact_point *contact = 0;
|
struct phys_contact_point *contact = 0;
|
||||||
@ -162,9 +162,9 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
|
|
||||||
/* Skip solve based on collision direction */
|
/* Skip solve based on collision direction */
|
||||||
{
|
{
|
||||||
struct v2 normal = collider_res.normal;
|
V2 normal = collider_res.normal;
|
||||||
struct v2 dir0 = e0->collision_dir;
|
V2 dir0 = e0->collision_dir;
|
||||||
struct v2 dir1 = e1->collision_dir;
|
V2 dir1 = e1->collision_dir;
|
||||||
f32 threshold = 0.5;
|
f32 threshold = 0.5;
|
||||||
b32 is_wrong_dir = 0;
|
b32 is_wrong_dir = 0;
|
||||||
if (!v2_is_zero(dir0)) {
|
if (!v2_is_zero(dir0)) {
|
||||||
@ -186,23 +186,23 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
data.dt = elapsed_dt;
|
data.dt = elapsed_dt;
|
||||||
|
|
||||||
/* Calculate point */
|
/* Calculate point */
|
||||||
struct v2 midpoint = collider_res.points[0].point;
|
V2 midpoint = collider_res.points[0].point;
|
||||||
if (collider_res.num_points > 1) {
|
if (collider_res.num_points > 1) {
|
||||||
midpoint = v2_add(midpoint, v2_mul(v2_sub(collider_res.points[1].point, midpoint), 0.5f));
|
midpoint = v2_add(midpoint, v2_mul(v2_sub(collider_res.points[1].point, midpoint), 0.5f));
|
||||||
}
|
}
|
||||||
data.point = midpoint;
|
data.point = midpoint;
|
||||||
|
|
||||||
/* Calculate relative velocity */
|
/* Calculate relative velocity */
|
||||||
struct v2 vrel;
|
V2 vrel;
|
||||||
{
|
{
|
||||||
struct v2 v0 = e0->linear_velocity;
|
V2 v0 = e0->linear_velocity;
|
||||||
struct v2 v1 = e1->linear_velocity;
|
V2 v1 = e1->linear_velocity;
|
||||||
f32 w0 = e0->angular_velocity;
|
f32 w0 = e0->angular_velocity;
|
||||||
f32 w1 = e1->angular_velocity;
|
f32 w1 = e1->angular_velocity;
|
||||||
struct v2 vcp1 = v2_sub(midpoint, e1_xf.og);
|
V2 vcp1 = v2_sub(midpoint, e1_xf.og);
|
||||||
struct v2 vcp0 = v2_sub(midpoint, e0_xf.og);
|
V2 vcp0 = v2_sub(midpoint, e0_xf.og);
|
||||||
struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
|
V2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
|
||||||
struct v2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1));
|
V2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1));
|
||||||
vrel = v2_sub(vel0, vel1);
|
vrel = v2_sub(vel0, vel1);
|
||||||
}
|
}
|
||||||
data.vrel = vrel;
|
data.vrel = vrel;
|
||||||
@ -254,7 +254,7 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
|
|
||||||
/* Update closest points */
|
/* Update closest points */
|
||||||
{
|
{
|
||||||
struct collider_closest_points_result closest_points_res = collider_closest_points(&e0_collider, &e1_collider, e0_xf, e1_xf);
|
CLD_ClosestResult closest_points_res = collider_closest_points(&e0_collider, &e1_collider, e0_xf, e1_xf);
|
||||||
dbg->closest0 = closest_points_res.p0;
|
dbg->closest0 = closest_points_res.p0;
|
||||||
dbg->closest1 = closest_points_res.p1;
|
dbg->closest1 = closest_points_res.p1;
|
||||||
}
|
}
|
||||||
@ -281,11 +281,11 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
|
|||||||
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||||
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||||
if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) {
|
if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) {
|
||||||
struct v2 normal = constraint->normal;
|
V2 normal = constraint->normal;
|
||||||
struct v2 tangent = v2_perp(normal);
|
V2 tangent = v2_perp(normal);
|
||||||
|
|
||||||
struct xform e0_xf = sim_ent_get_xform(e0);
|
Xform e0_xf = sim_ent_get_xform(e0);
|
||||||
struct xform e1_xf = sim_ent_get_xform(e1);
|
Xform e1_xf = sim_ent_get_xform(e1);
|
||||||
|
|
||||||
/* TODO: Cache this */
|
/* TODO: Cache this */
|
||||||
/* Calculate masses */
|
/* Calculate masses */
|
||||||
@ -319,8 +319,8 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
|
|||||||
/* Update / insert returned contacts */
|
/* Update / insert returned contacts */
|
||||||
for (u32 i = 0; i < num_points; ++i) {
|
for (u32 i = 0; i < num_points; ++i) {
|
||||||
struct phys_contact_point *contact = &constraint->points[i];
|
struct phys_contact_point *contact = &constraint->points[i];
|
||||||
struct v2 vcp0 = contact->vcp0;
|
V2 vcp0 = contact->vcp0;
|
||||||
struct v2 vcp1 = contact->vcp1;
|
V2 vcp1 = contact->vcp1;
|
||||||
|
|
||||||
/* Normal mass */
|
/* Normal mass */
|
||||||
{
|
{
|
||||||
@ -396,21 +396,21 @@ void phys_warm_start_contacts(struct phys_step_ctx *ctx)
|
|||||||
f32 inv_i0 = constraint->inv_i0;
|
f32 inv_i0 = constraint->inv_i0;
|
||||||
f32 inv_i1 = constraint->inv_i1;
|
f32 inv_i1 = constraint->inv_i1;
|
||||||
|
|
||||||
struct v2 v0 = e0->linear_velocity;
|
V2 v0 = e0->linear_velocity;
|
||||||
struct v2 v1 = e1->linear_velocity;
|
V2 v1 = e1->linear_velocity;
|
||||||
f32 w0 = e0->angular_velocity;
|
f32 w0 = e0->angular_velocity;
|
||||||
f32 w1 = e1->angular_velocity;
|
f32 w1 = e1->angular_velocity;
|
||||||
|
|
||||||
/* Warm start */
|
/* Warm start */
|
||||||
struct v2 normal = constraint->normal;
|
V2 normal = constraint->normal;
|
||||||
struct v2 tangent = v2_perp(normal);
|
V2 tangent = v2_perp(normal);
|
||||||
f32 inv_num_points = 1.f / num_points;
|
f32 inv_num_points = 1.f / num_points;
|
||||||
for (u32 i = 0; i < num_points; ++i) {
|
for (u32 i = 0; i < num_points; ++i) {
|
||||||
struct phys_contact_point *point = &constraint->points[i];
|
struct phys_contact_point *point = &constraint->points[i];
|
||||||
struct v2 vcp0 = point->vcp0;
|
V2 vcp0 = point->vcp0;
|
||||||
struct v2 vcp1 = point->vcp1;
|
V2 vcp1 = point->vcp1;
|
||||||
|
|
||||||
struct v2 impulse = v2_add(v2_mul(normal, point->normal_impulse), v2_mul(tangent, point->tangent_impulse));
|
V2 impulse = v2_add(v2_mul(normal, point->normal_impulse), v2_mul(tangent, point->tangent_impulse));
|
||||||
impulse = v2_mul(impulse, inv_num_points);
|
impulse = v2_mul(impulse, inv_num_points);
|
||||||
|
|
||||||
v0 = v2_sub(v0, v2_mul(impulse, inv_m0));
|
v0 = v2_sub(v0, v2_mul(impulse, inv_m0));
|
||||||
@ -441,15 +441,15 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
|||||||
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
|
||||||
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
|
||||||
|
|
||||||
struct v2 v0 = e0->linear_velocity;
|
V2 v0 = e0->linear_velocity;
|
||||||
struct v2 v1 = e1->linear_velocity;
|
V2 v1 = e1->linear_velocity;
|
||||||
f32 w0 = e0->angular_velocity;
|
f32 w0 = e0->angular_velocity;
|
||||||
f32 w1 = e1->angular_velocity;
|
f32 w1 = e1->angular_velocity;
|
||||||
|
|
||||||
u32 num_points = constraint->num_points;
|
u32 num_points = constraint->num_points;
|
||||||
if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve && !constraint->wrong_dir) {
|
if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve && !constraint->wrong_dir) {
|
||||||
struct xform e0_xf = sim_ent_get_xform(e0);
|
Xform e0_xf = sim_ent_get_xform(e0);
|
||||||
struct xform e1_xf = sim_ent_get_xform(e1);
|
Xform e1_xf = sim_ent_get_xform(e1);
|
||||||
|
|
||||||
f32 inv_m0 = constraint->inv_m0;
|
f32 inv_m0 = constraint->inv_m0;
|
||||||
f32 inv_m1 = constraint->inv_m1;
|
f32 inv_m1 = constraint->inv_m1;
|
||||||
@ -457,13 +457,13 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
|||||||
f32 inv_i1 = constraint->inv_i1;
|
f32 inv_i1 = constraint->inv_i1;
|
||||||
|
|
||||||
/* Normal impulse */
|
/* Normal impulse */
|
||||||
struct v2 normal = constraint->normal;
|
V2 normal = constraint->normal;
|
||||||
for (u32 point_index = 0; point_index < num_points; ++point_index) {
|
for (u32 point_index = 0; point_index < num_points; ++point_index) {
|
||||||
struct phys_contact_point *point = &constraint->points[point_index];
|
struct phys_contact_point *point = &constraint->points[point_index];
|
||||||
struct v2 vcp0 = point->vcp0;
|
V2 vcp0 = point->vcp0;
|
||||||
struct v2 vcp1 = point->vcp1;
|
V2 vcp1 = point->vcp1;
|
||||||
struct v2 p0 = v2_add(e0_xf.og, vcp0);
|
V2 p0 = v2_add(e0_xf.og, vcp0);
|
||||||
struct v2 p1 = v2_add(e1_xf.og, vcp1);
|
V2 p1 = v2_add(e1_xf.og, vcp1);
|
||||||
|
|
||||||
/* FIXME: Should separation use the rotated contact points? */
|
/* FIXME: Should separation use the rotated contact points? */
|
||||||
f32 separation = v2_dot(v2_sub(p1, p0), normal) + point->starting_separation;
|
f32 separation = v2_dot(v2_sub(p1, p0), normal) + point->starting_separation;
|
||||||
@ -477,16 +477,16 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
|||||||
velocity_bias = separation / dt;
|
velocity_bias = separation / dt;
|
||||||
} else if (apply_bias) {
|
} else if (apply_bias) {
|
||||||
/* Soft constraint */
|
/* Soft constraint */
|
||||||
struct math_spring softness = math_spring_init(CONTACT_SPRING_HZ, CONTACT_SPRING_DAMP, dt);
|
SoftSpring softness = math_spring_init(CONTACT_SPRING_HZ, CONTACT_SPRING_DAMP, dt);
|
||||||
f32 pushout_velocity = constraint->pushout_velocity;
|
f32 pushout_velocity = constraint->pushout_velocity;
|
||||||
mass_scale = softness.mass_scale;
|
mass_scale = softness.mass_scale;
|
||||||
impulse_scale = softness.impulse_scale;
|
impulse_scale = softness.impulse_scale;
|
||||||
velocity_bias = max_f32(softness.bias_rate * separation, -pushout_velocity);
|
velocity_bias = max_f32(softness.bias_rate * separation, -pushout_velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
|
V2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
|
||||||
struct v2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1));
|
V2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1));
|
||||||
struct v2 vrel = v2_sub(vel0, vel1);
|
V2 vrel = v2_sub(vel0, vel1);
|
||||||
|
|
||||||
f32 k = point->inv_normal_mass;
|
f32 k = point->inv_normal_mass;
|
||||||
|
|
||||||
@ -499,7 +499,7 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
|||||||
f32 delta = new_impulse - old_impulse;
|
f32 delta = new_impulse - old_impulse;
|
||||||
point->normal_impulse = new_impulse;
|
point->normal_impulse = new_impulse;
|
||||||
|
|
||||||
struct v2 impulse = v2_mul(normal, delta);
|
V2 impulse = v2_mul(normal, delta);
|
||||||
v0 = v2_sub(v0, v2_mul(impulse, inv_m0));
|
v0 = v2_sub(v0, v2_mul(impulse, inv_m0));
|
||||||
v1 = v2_add(v1, v2_mul(impulse, inv_m1));
|
v1 = v2_add(v1, v2_mul(impulse, inv_m1));
|
||||||
w0 -= v2_wedge(vcp0, impulse) * inv_i0;
|
w0 -= v2_wedge(vcp0, impulse) * inv_i0;
|
||||||
@ -507,15 +507,15 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Tangent impulse */
|
/* Tangent impulse */
|
||||||
struct v2 tangent = v2_perp(normal);
|
V2 tangent = v2_perp(normal);
|
||||||
for (u32 point_index = 0; point_index < num_points; ++point_index) {
|
for (u32 point_index = 0; point_index < num_points; ++point_index) {
|
||||||
struct phys_contact_point *point = &constraint->points[point_index];
|
struct phys_contact_point *point = &constraint->points[point_index];
|
||||||
struct v2 vcp0 = point->vcp0;
|
V2 vcp0 = point->vcp0;
|
||||||
struct v2 vcp1 = point->vcp1;
|
V2 vcp1 = point->vcp1;
|
||||||
|
|
||||||
struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
|
V2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
|
||||||
struct v2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1));
|
V2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1));
|
||||||
struct v2 vrel = v2_sub(vel0, vel1);
|
V2 vrel = v2_sub(vel0, vel1);
|
||||||
|
|
||||||
f32 k = point->inv_tangent_mass;
|
f32 k = point->inv_tangent_mass;
|
||||||
|
|
||||||
@ -529,7 +529,7 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
|
|||||||
f32 delta = new_impulse - old_impulse;
|
f32 delta = new_impulse - old_impulse;
|
||||||
point->tangent_impulse = new_impulse;
|
point->tangent_impulse = new_impulse;
|
||||||
|
|
||||||
struct v2 impulse = v2_mul(tangent, delta);
|
V2 impulse = v2_mul(tangent, delta);
|
||||||
v0 = v2_sub(v0, v2_mul(impulse, inv_m0));
|
v0 = v2_sub(v0, v2_mul(impulse, inv_m0));
|
||||||
v1 = v2_add(v1, v2_mul(impulse, inv_m1));
|
v1 = v2_add(v1, v2_mul(impulse, inv_m1));
|
||||||
w0 -= v2_wedge(vcp0, impulse) * inv_i0;
|
w0 -= v2_wedge(vcp0, impulse) * inv_i0;
|
||||||
@ -580,8 +580,8 @@ void phys_prepare_motor_joints(struct phys_step_ctx *ctx)
|
|||||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||||
|
|
||||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||||
struct xform e0_xf = sim_ent_get_xform(e0);
|
Xform e0_xf = sim_ent_get_xform(e0);
|
||||||
struct xform e1_xf = sim_ent_get_xform(e1);
|
Xform e1_xf = sim_ent_get_xform(e1);
|
||||||
|
|
||||||
/* TODO: Cache this */
|
/* TODO: Cache this */
|
||||||
/* Calculate masses */
|
/* Calculate masses */
|
||||||
@ -602,13 +602,13 @@ void phys_prepare_motor_joints(struct phys_step_ctx *ctx)
|
|||||||
joint->inv_i0 = inv_i0;
|
joint->inv_i0 = inv_i0;
|
||||||
joint->inv_i1 = inv_i1;
|
joint->inv_i1 = inv_i1;
|
||||||
|
|
||||||
joint->point_local_e0 = V2(0, 0);
|
joint->point_local_e0 = V2FromXY(0, 0);
|
||||||
joint->point_local_e1 = V2(0, 0);
|
joint->point_local_e1 = V2FromXY(0, 0);
|
||||||
|
|
||||||
struct v2 vcp0 = v2_sub(xform_mul_v2(e0_xf, joint->point_local_e0), e0_xf.og);
|
V2 vcp0 = v2_sub(xform_mul_v2(e0_xf, joint->point_local_e0), e0_xf.og);
|
||||||
struct v2 vcp1 = v2_sub(xform_mul_v2(e1_xf, joint->point_local_e1), e1_xf.og);
|
V2 vcp1 = v2_sub(xform_mul_v2(e1_xf, joint->point_local_e1), e1_xf.og);
|
||||||
|
|
||||||
struct xform linear_mass_xf = ZI;
|
Xform linear_mass_xf = ZI;
|
||||||
linear_mass_xf.bx.x = inv_m0 + inv_m1 + vcp0.y * vcp0.y * inv_i0 + vcp1.y * vcp1.y * inv_i1;
|
linear_mass_xf.bx.x = inv_m0 + inv_m1 + vcp0.y * vcp0.y * inv_i0 + vcp1.y * vcp1.y * inv_i1;
|
||||||
linear_mass_xf.bx.y = -vcp0.y * vcp0.x * inv_i0 - vcp1.y * vcp1.x * inv_i1;
|
linear_mass_xf.bx.y = -vcp0.y * vcp0.x * inv_i0 - vcp1.y * vcp1.x * inv_i1;
|
||||||
linear_mass_xf.by.x = linear_mass_xf.bx.y;
|
linear_mass_xf.by.x = linear_mass_xf.bx.y;
|
||||||
@ -618,7 +618,7 @@ void phys_prepare_motor_joints(struct phys_step_ctx *ctx)
|
|||||||
joint->angular_mass = 1.f / (inv_i0 + inv_i1);
|
joint->angular_mass = 1.f / (inv_i0 + inv_i1);
|
||||||
|
|
||||||
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
||||||
joint->linear_impulse = V2(0, 0);
|
joint->linear_impulse = V2FromXY(0, 0);
|
||||||
joint->angular_impulse = 0;
|
joint->angular_impulse = 0;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@ -643,16 +643,16 @@ void phys_warm_start_motor_joints(struct phys_step_ctx *ctx)
|
|||||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||||
|
|
||||||
struct xform e0_xf = sim_ent_get_xform(e0);
|
Xform e0_xf = sim_ent_get_xform(e0);
|
||||||
struct xform e1_xf = sim_ent_get_xform(e1);
|
Xform e1_xf = sim_ent_get_xform(e1);
|
||||||
|
|
||||||
f32 inv_m0 = joint->inv_m0;
|
f32 inv_m0 = joint->inv_m0;
|
||||||
f32 inv_m1 = joint->inv_m1;
|
f32 inv_m1 = joint->inv_m1;
|
||||||
f32 inv_i0 = joint->inv_i0;
|
f32 inv_i0 = joint->inv_i0;
|
||||||
f32 inv_i1 = joint->inv_i1;
|
f32 inv_i1 = joint->inv_i1;
|
||||||
|
|
||||||
struct v2 vcp0 = v2_sub(xform_mul_v2(e0_xf, joint->point_local_e0), e0_xf.og);
|
V2 vcp0 = v2_sub(xform_mul_v2(e0_xf, joint->point_local_e0), e0_xf.og);
|
||||||
struct v2 vcp1 = v2_sub(xform_mul_v2(e1_xf, joint->point_local_e1), e1_xf.og);
|
V2 vcp1 = v2_sub(xform_mul_v2(e1_xf, joint->point_local_e1), e1_xf.og);
|
||||||
|
|
||||||
sim_ent_set_linear_velocity(e0, v2_sub(e0->linear_velocity, v2_mul(joint->linear_impulse, inv_m0)));
|
sim_ent_set_linear_velocity(e0, v2_sub(e0->linear_velocity, v2_mul(joint->linear_impulse, inv_m0)));
|
||||||
sim_ent_set_linear_velocity(e1, v2_add(e1->linear_velocity, v2_mul(joint->linear_impulse, inv_m1)));
|
sim_ent_set_linear_velocity(e1, v2_add(e1->linear_velocity, v2_mul(joint->linear_impulse, inv_m1)));
|
||||||
@ -675,16 +675,16 @@ void phys_solve_motor_joints(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||||
|
|
||||||
struct xform e0_xf = sim_ent_get_xform(e0);
|
Xform e0_xf = sim_ent_get_xform(e0);
|
||||||
struct xform e1_xf = sim_ent_get_xform(e1);
|
Xform e1_xf = sim_ent_get_xform(e1);
|
||||||
|
|
||||||
f32 inv_m0 = joint->inv_m0;
|
f32 inv_m0 = joint->inv_m0;
|
||||||
f32 inv_m1 = joint->inv_m1;
|
f32 inv_m1 = joint->inv_m1;
|
||||||
f32 inv_i0 = joint->inv_i0;
|
f32 inv_i0 = joint->inv_i0;
|
||||||
f32 inv_i1 = joint->inv_i1;
|
f32 inv_i1 = joint->inv_i1;
|
||||||
|
|
||||||
struct v2 v0 = e0->linear_velocity;
|
V2 v0 = e0->linear_velocity;
|
||||||
struct v2 v1 = e1->linear_velocity;
|
V2 v1 = e1->linear_velocity;
|
||||||
f32 w0 = e0->angular_velocity;
|
f32 w0 = e0->angular_velocity;
|
||||||
f32 w1 = e1->angular_velocity;
|
f32 w1 = e1->angular_velocity;
|
||||||
|
|
||||||
@ -709,22 +709,22 @@ void phys_solve_motor_joints(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
|
|
||||||
/* Linear constraint */
|
/* Linear constraint */
|
||||||
{
|
{
|
||||||
struct v2 vcp0 = v2_sub(xform_mul_v2(e0_xf, joint->point_local_e0), e0_xf.og);
|
V2 vcp0 = v2_sub(xform_mul_v2(e0_xf, joint->point_local_e0), e0_xf.og);
|
||||||
struct v2 vcp1 = v2_sub(xform_mul_v2(e1_xf, joint->point_local_e1), e1_xf.og);
|
V2 vcp1 = v2_sub(xform_mul_v2(e1_xf, joint->point_local_e1), e1_xf.og);
|
||||||
|
|
||||||
f32 max_impulse = joint->max_force * dt;
|
f32 max_impulse = joint->max_force * dt;
|
||||||
|
|
||||||
struct v2 linear_separation = v2_sub(v2_add(e1_xf.og, vcp1), v2_add(e0_xf.og, vcp0));
|
V2 linear_separation = v2_sub(v2_add(e1_xf.og, vcp1), v2_add(e0_xf.og, vcp0));
|
||||||
struct v2 linear_bias = v2_mul(linear_separation, correction_rate * inv_dt);
|
V2 linear_bias = v2_mul(linear_separation, correction_rate * inv_dt);
|
||||||
|
|
||||||
struct v2 vrel = v2_sub(v2_add(v1, v2_perp_mul(vcp1, w1)), v2_add(v0, v2_perp_mul(vcp0, w0)));
|
V2 vrel = v2_sub(v2_add(v1, v2_perp_mul(vcp1, w1)), v2_add(v0, v2_perp_mul(vcp0, w0)));
|
||||||
struct v2 impulse = v2_neg(xform_basis_mul_v2(joint->linear_mass_xf, v2_add(vrel, linear_bias)));
|
V2 impulse = v2_neg(xform_basis_mul_v2(joint->linear_mass_xf, v2_add(vrel, linear_bias)));
|
||||||
|
|
||||||
struct v2 old_impulse = joint->linear_impulse;
|
V2 old_impulse = joint->linear_impulse;
|
||||||
struct v2 new_impulse = v2_clamp_len(v2_add(old_impulse, impulse), max_impulse);
|
V2 new_impulse = v2_clamp_len(v2_add(old_impulse, impulse), max_impulse);
|
||||||
joint->linear_impulse = new_impulse;
|
joint->linear_impulse = new_impulse;
|
||||||
|
|
||||||
struct v2 delta = v2_sub(new_impulse, old_impulse);
|
V2 delta = v2_sub(new_impulse, old_impulse);
|
||||||
v0 = v2_sub(v0, v2_mul(delta, inv_m0));
|
v0 = v2_sub(v0, v2_mul(delta, inv_m0));
|
||||||
v1 = v2_add(v1, v2_mul(delta, inv_m1));
|
v1 = v2_add(v1, v2_mul(delta, inv_m1));
|
||||||
w0 -= v2_wedge(vcp0, delta) * inv_i0;
|
w0 -= v2_wedge(vcp0, delta) * inv_i0;
|
||||||
@ -779,7 +779,7 @@ void phys_prepare_mouse_joints(struct phys_step_ctx *ctx)
|
|||||||
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
|
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
|
||||||
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
||||||
if (sim_ent_should_simulate(ent)) {
|
if (sim_ent_should_simulate(ent)) {
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
|
|
||||||
/* TODO: Cache this */
|
/* TODO: Cache this */
|
||||||
/* Calculate masses */
|
/* Calculate masses */
|
||||||
@ -793,9 +793,9 @@ void phys_prepare_mouse_joints(struct phys_step_ctx *ctx)
|
|||||||
joint->inv_m = inv_m;
|
joint->inv_m = inv_m;
|
||||||
joint->inv_i = inv_i;
|
joint->inv_i = inv_i;
|
||||||
|
|
||||||
struct v2 vcp = v2_sub(xform_mul_v2(xf, joint->point_local_start), xf.og);
|
V2 vcp = v2_sub(xform_mul_v2(xf, joint->point_local_start), xf.og);
|
||||||
|
|
||||||
struct xform linear_mass_xf = ZI;
|
Xform linear_mass_xf = ZI;
|
||||||
linear_mass_xf.bx.x = inv_m + inv_i * vcp.y * vcp.y;
|
linear_mass_xf.bx.x = inv_m + inv_i * vcp.y * vcp.y;
|
||||||
linear_mass_xf.bx.y = -inv_i * vcp.x * vcp.y;
|
linear_mass_xf.bx.y = -inv_i * vcp.x * vcp.y;
|
||||||
linear_mass_xf.by.x = linear_mass_xf.bx.y;
|
linear_mass_xf.by.x = linear_mass_xf.bx.y;
|
||||||
@ -803,7 +803,7 @@ void phys_prepare_mouse_joints(struct phys_step_ctx *ctx)
|
|||||||
joint->linear_mass_xf = xform_invert(linear_mass_xf);
|
joint->linear_mass_xf = xform_invert(linear_mass_xf);
|
||||||
|
|
||||||
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
||||||
joint->linear_impulse = V2(0, 0);
|
joint->linear_impulse = V2FromXY(0, 0);
|
||||||
joint->angular_impulse = 0;
|
joint->angular_impulse = 0;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@ -828,8 +828,8 @@ void phys_warm_start_mouse_joints(struct phys_step_ctx *ctx)
|
|||||||
if (sim_ent_should_simulate(ent)) {
|
if (sim_ent_should_simulate(ent)) {
|
||||||
f32 inv_m = joint->inv_m;
|
f32 inv_m = joint->inv_m;
|
||||||
f32 inv_i = joint->inv_i;
|
f32 inv_i = joint->inv_i;
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
struct v2 vcp = v2_sub(xform_mul_v2(xf, joint->point_local_start), xf.og);
|
V2 vcp = v2_sub(xform_mul_v2(xf, joint->point_local_start), xf.og);
|
||||||
sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(joint->linear_impulse, inv_m)));
|
sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(joint->linear_impulse, inv_m)));
|
||||||
sim_ent_set_angular_velocity(ent, ent->angular_velocity + ((v2_wedge(vcp, joint->linear_impulse) + joint->angular_impulse) * inv_i));
|
sim_ent_set_angular_velocity(ent, ent->angular_velocity + ((v2_wedge(vcp, joint->linear_impulse) + joint->angular_impulse) * inv_i));
|
||||||
}
|
}
|
||||||
@ -848,7 +848,7 @@ void phys_solve_mouse_joints(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
|
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
|
||||||
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
|
||||||
if (sim_ent_should_simulate(ent)) {
|
if (sim_ent_should_simulate(ent)) {
|
||||||
struct v2 v = ent->linear_velocity;
|
V2 v = ent->linear_velocity;
|
||||||
f32 w = ent->angular_velocity;
|
f32 w = ent->angular_velocity;
|
||||||
|
|
||||||
f32 inv_m = joint->inv_m;
|
f32 inv_m = joint->inv_m;
|
||||||
@ -856,7 +856,7 @@ void phys_solve_mouse_joints(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
|
|
||||||
/* Angular impulse */
|
/* Angular impulse */
|
||||||
{
|
{
|
||||||
struct math_spring softness = math_spring_init(joint->angular_spring_hz, joint->angular_spring_damp, dt);
|
SoftSpring softness = math_spring_init(joint->angular_spring_hz, joint->angular_spring_damp, dt);
|
||||||
f32 mass_scale = softness.mass_scale;
|
f32 mass_scale = softness.mass_scale;
|
||||||
f32 impulse_scale = softness.impulse_scale;
|
f32 impulse_scale = softness.impulse_scale;
|
||||||
f32 impulse = mass_scale * (-w / inv_i) - impulse_scale * joint->angular_impulse;
|
f32 impulse = mass_scale * (-w / inv_i) - impulse_scale * joint->angular_impulse;
|
||||||
@ -868,27 +868,27 @@ void phys_solve_mouse_joints(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
{
|
{
|
||||||
f32 max_impulse = joint->max_force / dt;
|
f32 max_impulse = joint->max_force / dt;
|
||||||
|
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
|
|
||||||
struct v2 point_start = xform_mul_v2(xf, joint->point_local_start);
|
V2 point_start = xform_mul_v2(xf, joint->point_local_start);
|
||||||
struct v2 point_end = joint->point_end;
|
V2 point_end = joint->point_end;
|
||||||
|
|
||||||
struct v2 vcp = v2_sub(point_start, xf.og);
|
V2 vcp = v2_sub(point_start, xf.og);
|
||||||
struct v2 separation = v2_sub(point_start, point_end);
|
V2 separation = v2_sub(point_start, point_end);
|
||||||
|
|
||||||
struct math_spring softness = math_spring_init(joint->linear_spring_hz, joint->linear_spring_damp, dt);
|
SoftSpring softness = math_spring_init(joint->linear_spring_hz, joint->linear_spring_damp, dt);
|
||||||
f32 bias_rate = softness.bias_rate;
|
f32 bias_rate = softness.bias_rate;
|
||||||
f32 mass_scale = softness.mass_scale;
|
f32 mass_scale = softness.mass_scale;
|
||||||
f32 impulse_scale = softness.impulse_scale;
|
f32 impulse_scale = softness.impulse_scale;
|
||||||
|
|
||||||
struct v2 bias = v2_mul(separation, bias_rate);
|
V2 bias = v2_mul(separation, bias_rate);
|
||||||
struct v2 vel = v2_add(v, v2_perp_mul(vcp, w));
|
V2 vel = v2_add(v, v2_perp_mul(vcp, w));
|
||||||
struct v2 b = xform_basis_mul_v2(joint->linear_mass_xf, v2_add(vel, bias));
|
V2 b = xform_basis_mul_v2(joint->linear_mass_xf, v2_add(vel, bias));
|
||||||
|
|
||||||
struct v2 impulse = v2_mul(b, -mass_scale);
|
V2 impulse = v2_mul(b, -mass_scale);
|
||||||
impulse = v2_sub(impulse, v2_mul(joint->linear_impulse, impulse_scale));
|
impulse = v2_sub(impulse, v2_mul(joint->linear_impulse, impulse_scale));
|
||||||
|
|
||||||
struct v2 old_impulse = joint->linear_impulse;
|
V2 old_impulse = joint->linear_impulse;
|
||||||
joint->linear_impulse = v2_add(joint->linear_impulse, impulse);
|
joint->linear_impulse = v2_add(joint->linear_impulse, impulse);
|
||||||
|
|
||||||
joint->linear_impulse = v2_clamp_len(joint->linear_impulse, max_impulse);
|
joint->linear_impulse = v2_clamp_len(joint->linear_impulse, max_impulse);
|
||||||
@ -947,8 +947,8 @@ void phys_prepare_weld_joints(struct phys_step_ctx *ctx)
|
|||||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||||
struct xform e0_xf = sim_ent_get_xform(e0);
|
Xform e0_xf = sim_ent_get_xform(e0);
|
||||||
struct xform e1_xf = sim_ent_get_xform(e1);
|
Xform e1_xf = sim_ent_get_xform(e1);
|
||||||
|
|
||||||
f32 inv_m0;
|
f32 inv_m0;
|
||||||
f32 inv_m1;
|
f32 inv_m1;
|
||||||
@ -968,8 +968,8 @@ void phys_prepare_weld_joints(struct phys_step_ctx *ctx)
|
|||||||
joint->inv_i1 = inv_i1;
|
joint->inv_i1 = inv_i1;
|
||||||
|
|
||||||
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
||||||
joint->linear_impulse0 = V2(0, 0);
|
joint->linear_impulse0 = V2FromXY(0, 0);
|
||||||
joint->linear_impulse1 = V2(0, 0);
|
joint->linear_impulse1 = V2FromXY(0, 0);
|
||||||
joint->angular_impulse0 = 0;
|
joint->angular_impulse0 = 0;
|
||||||
joint->angular_impulse1 = 0;
|
joint->angular_impulse1 = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -997,8 +997,8 @@ void phys_warm_start_weld_joints(struct phys_step_ctx *ctx)
|
|||||||
if (sim_ent_should_simulate(e0)) {
|
if (sim_ent_should_simulate(e0)) {
|
||||||
f32 inv_m = joint->inv_m0;
|
f32 inv_m = joint->inv_m0;
|
||||||
f32 inv_i = joint->inv_i0;
|
f32 inv_i = joint->inv_i0;
|
||||||
struct xform xf = sim_ent_get_xform(e1);
|
Xform xf = sim_ent_get_xform(e1);
|
||||||
struct v2 vcp = v2_sub(xform_mul_v2(xf, joint->point_local_start), xf.og);
|
V2 vcp = v2_sub(xform_mul_v2(xf, joint->point_local_start), xf.og);
|
||||||
sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(joint->linear_impulse, inv_m)));
|
sim_ent_set_linear_velocity(ent, v2_add(ent->linear_velocity, v2_mul(joint->linear_impulse, inv_m)));
|
||||||
ent->angular_velocity += (v2_wedge(vcp, joint->linear_impulse) + joint->angular_impulse) * inv_i;
|
ent->angular_velocity += (v2_wedge(vcp, joint->linear_impulse) + joint->angular_impulse) * inv_i;
|
||||||
}
|
}
|
||||||
@ -1031,17 +1031,17 @@ void phys_solve_weld_joints(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
|
||||||
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1);
|
||||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||||
struct xform xf0 = sim_ent_get_xform(e0);
|
Xform xf0 = sim_ent_get_xform(e0);
|
||||||
struct xform xf1 = sim_ent_get_xform(e1);
|
Xform xf1 = sim_ent_get_xform(e1);
|
||||||
|
|
||||||
struct xform target_xf1 = xform_mul(xf0, joint->xf0_to_xf1);
|
Xform target_xf1 = xform_mul(xf0, joint->xf0_to_xf1);
|
||||||
|
|
||||||
struct v2 v1 = e1->linear_velocity;
|
V2 v1 = e1->linear_velocity;
|
||||||
f32 w1 = e1->angular_velocity;
|
f32 w1 = e1->angular_velocity;
|
||||||
|
|
||||||
/* Angular constraint */
|
/* Angular constraint */
|
||||||
{
|
{
|
||||||
struct math_spring softness = math_spring_init(joint->angular_spring_hz, joint->angular_spring_damp, dt);
|
SoftSpring softness = math_spring_init(joint->angular_spring_hz, joint->angular_spring_damp, dt);
|
||||||
f32 inv_i1 = joint->inv_i1;
|
f32 inv_i1 = joint->inv_i1;
|
||||||
f32 k = 1 / inv_i1;
|
f32 k = 1 / inv_i1;
|
||||||
f32 separation = math_unwind_angle(xform_get_rotation(target_xf1) - xform_get_rotation(xf1));
|
f32 separation = math_unwind_angle(xform_get_rotation(target_xf1) - xform_get_rotation(xf1));
|
||||||
@ -1054,20 +1054,20 @@ void phys_solve_weld_joints(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
|
|
||||||
/* Linear constraint */
|
/* Linear constraint */
|
||||||
{
|
{
|
||||||
struct math_spring softness = math_spring_init(joint->linear_spring_hz, joint->linear_spring_damp, dt);
|
SoftSpring softness = math_spring_init(joint->linear_spring_hz, joint->linear_spring_damp, dt);
|
||||||
f32 inv_m1 = joint->inv_m1;
|
f32 inv_m1 = joint->inv_m1;
|
||||||
|
|
||||||
struct v2 separation = v2_sub(xf1.og, target_xf1.og);
|
V2 separation = v2_sub(xf1.og, target_xf1.og);
|
||||||
|
|
||||||
f32 k = 1 / inv_m1;
|
f32 k = 1 / inv_m1;
|
||||||
|
|
||||||
struct v2 bias = v2_mul(separation, softness.bias_rate);
|
V2 bias = v2_mul(separation, softness.bias_rate);
|
||||||
struct v2 b = v2_mul(v2_add(v1, bias), k);
|
V2 b = v2_mul(v2_add(v1, bias), k);
|
||||||
|
|
||||||
struct v2 impulse = v2_mul(b, -softness.mass_scale);
|
V2 impulse = v2_mul(b, -softness.mass_scale);
|
||||||
impulse = v2_sub(impulse, v2_mul(joint->linear_impulse1, softness.impulse_scale));
|
impulse = v2_sub(impulse, v2_mul(joint->linear_impulse1, softness.impulse_scale));
|
||||||
|
|
||||||
struct v2 old_impulse = joint->linear_impulse1;
|
V2 old_impulse = joint->linear_impulse1;
|
||||||
joint->linear_impulse1 = v2_add(joint->linear_impulse1, impulse);
|
joint->linear_impulse1 = v2_add(joint->linear_impulse1, impulse);
|
||||||
|
|
||||||
impulse = v2_sub(joint->linear_impulse1, old_impulse);
|
impulse = v2_sub(joint->linear_impulse1, old_impulse);
|
||||||
@ -1086,11 +1086,11 @@ void phys_solve_weld_joints(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
* Integration
|
* Integration
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct xform get_derived_xform(struct sim_ent *ent, f32 dt)
|
INTERNAL Xform get_derived_xform(struct sim_ent *ent, f32 dt)
|
||||||
{
|
{
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
|
|
||||||
struct v2 step_linear_velocity = v2_mul(ent->linear_velocity, dt);
|
V2 step_linear_velocity = v2_mul(ent->linear_velocity, dt);
|
||||||
f32 step_angular_velocity = ent->angular_velocity * dt;
|
f32 step_angular_velocity = ent->angular_velocity * dt;
|
||||||
|
|
||||||
xf.og = v2_add(xf.og, step_linear_velocity);
|
xf.og = v2_add(xf.og, step_linear_velocity);
|
||||||
@ -1109,18 +1109,18 @@ void phys_integrate_forces(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
b32 is_dynamic = sim_ent_has_prop(ent, SEPROP_DYNAMIC);
|
b32 is_dynamic = sim_ent_has_prop(ent, SEPROP_DYNAMIC);
|
||||||
b32 is_kinematic = sim_ent_has_prop(ent, SEPROP_KINEMATIC);
|
b32 is_kinematic = sim_ent_has_prop(ent, SEPROP_KINEMATIC);
|
||||||
if (is_dynamic || is_kinematic) {
|
if (is_dynamic || is_kinematic) {
|
||||||
struct v2 linear_velocity = ent->linear_velocity;
|
V2 linear_velocity = ent->linear_velocity;
|
||||||
f32 angular_velocity = ent->angular_velocity;
|
f32 angular_velocity = ent->angular_velocity;
|
||||||
f32 linear_damping_factor = max_f32(1.0f - (ent->linear_damping * dt), 0);
|
f32 linear_damping_factor = max_f32(1.0f - (ent->linear_damping * dt), 0);
|
||||||
f32 angular_damping_factor = max_f32(1.0f - (ent->angular_damping * dt), 0);
|
f32 angular_damping_factor = max_f32(1.0f - (ent->angular_damping * dt), 0);
|
||||||
|
|
||||||
/* Integrate forces */
|
/* Integrate forces */
|
||||||
if (is_dynamic) {
|
if (is_dynamic) {
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
f32 det_abs = math_fabs(xform_get_determinant(xf));
|
f32 det_abs = math_fabs(xform_get_determinant(xf));
|
||||||
f32 mass = ent->mass_unscaled * det_abs;
|
f32 mass = ent->mass_unscaled * det_abs;
|
||||||
f32 inertia = ent->inertia_unscaled * det_abs;
|
f32 inertia = ent->inertia_unscaled * det_abs;
|
||||||
struct v2 force_accel = v2_mul(v2_div(ent->force, mass), dt);
|
V2 force_accel = v2_mul(v2_div(ent->force, mass), dt);
|
||||||
f32 torque_accel = (ent->torque / inertia) * dt;
|
f32 torque_accel = (ent->torque / inertia) * dt;
|
||||||
linear_velocity = v2_add(linear_velocity, force_accel);
|
linear_velocity = v2_add(linear_velocity, force_accel);
|
||||||
angular_velocity += torque_accel;
|
angular_velocity += torque_accel;
|
||||||
@ -1133,7 +1133,7 @@ void phys_integrate_forces(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
/* Update entity */
|
/* Update entity */
|
||||||
sim_ent_set_linear_velocity(ent, linear_velocity);
|
sim_ent_set_linear_velocity(ent, linear_velocity);
|
||||||
sim_ent_set_angular_velocity(ent, angular_velocity);
|
sim_ent_set_angular_velocity(ent, angular_velocity);
|
||||||
ent->force = V2(0, 0);
|
ent->force = V2FromXY(0, 0);
|
||||||
ent->torque = 0;
|
ent->torque = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1149,7 +1149,7 @@ void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt)
|
|||||||
if (!sim_ent_should_simulate(ent)) continue;
|
if (!sim_ent_should_simulate(ent)) continue;
|
||||||
if (!sim_ent_has_prop(ent, SEPROP_DYNAMIC) && !sim_ent_has_prop(ent, SEPROP_KINEMATIC)) continue;
|
if (!sim_ent_has_prop(ent, SEPROP_DYNAMIC) && !sim_ent_has_prop(ent, SEPROP_KINEMATIC)) continue;
|
||||||
|
|
||||||
struct xform xf = get_derived_xform(ent, dt);
|
Xform xf = get_derived_xform(ent, dt);
|
||||||
sim_ent_set_xform(ent, xf);
|
sim_ent_set_xform(ent, xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1172,14 +1172,14 @@ f32 phys_determine_earliest_toi(struct phys_step_ctx *ctx, f32 step_dt, f32 tole
|
|||||||
if (!sim_ent_has_prop(e0, SEPROP_TOI)) continue;
|
if (!sim_ent_has_prop(e0, SEPROP_TOI)) continue;
|
||||||
if (e0->local_collider.count <= 0) continue;
|
if (e0->local_collider.count <= 0) continue;
|
||||||
|
|
||||||
struct collider_shape e0_collider = e0->local_collider;
|
CLD_Shape e0_collider = e0->local_collider;
|
||||||
struct xform e0_xf_t0 = sim_ent_get_xform(e0);
|
Xform e0_xf_t0 = sim_ent_get_xform(e0);
|
||||||
struct xform e0_xf_t1 = get_derived_xform(e0, step_dt);
|
Xform e0_xf_t1 = get_derived_xform(e0, step_dt);
|
||||||
|
|
||||||
/* TODO: Use swept aabb rather than combined aabb. This should prevent spikes from bullets returning 0 positive TOIs with irrelevant entities. */
|
/* TODO: Use swept aabb rather than combined aabb. This should prevent spikes from bullets returning 0 positive TOIs with irrelevant entities. */
|
||||||
struct aabb aabb_t0 = collider_aabb_from_collider(&e0_collider, e0_xf_t0);
|
Aabb aabb_t0 = collider_aabb_from_collider(&e0_collider, e0_xf_t0);
|
||||||
struct aabb aabb_t1 = collider_aabb_from_collider(&e0_collider, e0_xf_t1);
|
Aabb aabb_t1 = collider_aabb_from_collider(&e0_collider, e0_xf_t1);
|
||||||
struct aabb combined_aabb = collider_aabb_from_combined_aabb(aabb_t0, aabb_t1);
|
Aabb combined_aabb = collider_aabb_from_combined_aabb(aabb_t0, aabb_t1);
|
||||||
|
|
||||||
struct space_iter iter = space_iter_begin_aabb(space, combined_aabb);
|
struct space_iter iter = space_iter_begin_aabb(space, combined_aabb);
|
||||||
struct space_entry *entry;
|
struct space_entry *entry;
|
||||||
@ -1190,9 +1190,9 @@ f32 phys_determine_earliest_toi(struct phys_step_ctx *ctx, f32 step_dt, f32 tole
|
|||||||
if (e1->local_collider.count <= 0) continue;
|
if (e1->local_collider.count <= 0) continue;
|
||||||
if (!can_contact(e0, e1)) continue;
|
if (!can_contact(e0, e1)) continue;
|
||||||
|
|
||||||
struct collider_shape e1_collider = e1->local_collider;
|
CLD_Shape e1_collider = e1->local_collider;
|
||||||
struct xform e1_xf_t0 = sim_ent_get_xform(e1);
|
Xform e1_xf_t0 = sim_ent_get_xform(e1);
|
||||||
struct xform e1_xf_t1 = get_derived_xform(e1, step_dt);
|
Xform e1_xf_t1 = get_derived_xform(e1, step_dt);
|
||||||
|
|
||||||
f32 t = collider_time_of_impact(&e0_collider, &e1_collider, e0_xf_t0, e1_xf_t0, e0_xf_t1, e1_xf_t1, tolerance, max_iterations);
|
f32 t = collider_time_of_impact(&e0_collider, &e1_collider, e0_xf_t0, e1_xf_t0, e0_xf_t1, e1_xf_t1, tolerance, max_iterations);
|
||||||
if (t != 0 && t < smallest_t) {
|
if (t != 0 && t < smallest_t) {
|
||||||
@ -1218,13 +1218,13 @@ void phys_update_aabbs(struct phys_step_ctx *ctx)
|
|||||||
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
struct sim_ent *ent = &ss->ents[sim_ent_index];
|
||||||
if (!sim_ent_is_valid_and_active(ent)) continue;
|
if (!sim_ent_is_valid_and_active(ent)) continue;
|
||||||
if (ent->local_collider.count > 0) {
|
if (ent->local_collider.count > 0) {
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
struct space_entry *space_entry = space_entry_from_handle(space, ent->space_handle);
|
struct space_entry *space_entry = space_entry_from_handle(space, ent->space_handle);
|
||||||
if (!space_entry->valid) {
|
if (!space_entry->valid) {
|
||||||
space_entry = space_entry_alloc(space, ent->id);
|
space_entry = space_entry_alloc(space, ent->id);
|
||||||
ent->space_handle = space_entry->handle;
|
ent->space_handle = space_entry->handle;
|
||||||
}
|
}
|
||||||
struct aabb aabb = collider_aabb_from_collider(&ent->local_collider, xf);
|
Aabb aabb = collider_aabb_from_collider(&ent->local_collider, xf);
|
||||||
space_entry_update_aabb(space_entry, aabb);
|
space_entry_update_aabb(space_entry, aabb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1248,7 +1248,7 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep)
|
|||||||
while (remaining_dt > 0) {
|
while (remaining_dt > 0) {
|
||||||
__profn("Step part");
|
__profn("Step part");
|
||||||
++phys_iteration;
|
++phys_iteration;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
/* TOI */
|
/* TOI */
|
||||||
f32 step_dt = remaining_dt;
|
f32 step_dt = remaining_dt;
|
||||||
|
|||||||
@ -6,9 +6,9 @@ struct phys_contact_constraint;
|
|||||||
struct phys_collision_data {
|
struct phys_collision_data {
|
||||||
struct sim_ent_id e0;
|
struct sim_ent_id e0;
|
||||||
struct sim_ent_id e1;
|
struct sim_ent_id e1;
|
||||||
struct v2 point;
|
V2 point;
|
||||||
struct v2 normal; /* Normal of the collision from e0 to e1 */
|
V2 normal; /* Normal of the collision from e0 to e1 */
|
||||||
struct v2 vrel; /* Relative velocity at point of collision */
|
V2 vrel; /* Relative velocity at point of collision */
|
||||||
b32 is_start; /* Did this collision just begin */
|
b32 is_start; /* Did this collision just begin */
|
||||||
f32 dt; /* How much time elapsed in the step when this event occurred (this will equal the physics timestep unless an early time of impact occurred) */
|
f32 dt; /* How much time elapsed in the step when this event occurred (this will equal the physics timestep unless an early time of impact occurred) */
|
||||||
};
|
};
|
||||||
@ -35,8 +35,8 @@ struct phys_contact_point {
|
|||||||
* shouldn't really be affected by rotation accross substeps
|
* shouldn't really be affected by rotation accross substeps
|
||||||
* (imagine re-building the manifold of a rotated shape, it would still be
|
* (imagine re-building the manifold of a rotated shape, it would still be
|
||||||
* on the same side of the shape that it originally occured on) */
|
* on the same side of the shape that it originally occured on) */
|
||||||
struct v2 vcp0;
|
V2 vcp0;
|
||||||
struct v2 vcp1;
|
V2 vcp1;
|
||||||
|
|
||||||
u32 id; /* ID generated during clipping */
|
u32 id; /* ID generated during clipping */
|
||||||
f32 starting_separation; /* How far are original points along normal */
|
f32 starting_separation; /* How far are original points along normal */
|
||||||
@ -48,7 +48,7 @@ struct phys_contact_point {
|
|||||||
|
|
||||||
/* Debugging */
|
/* Debugging */
|
||||||
#if DEVELOPER
|
#if DEVELOPER
|
||||||
struct v2 dbg_pt;
|
V2 dbg_pt;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ struct phys_contact_constraint {
|
|||||||
f32 inv_i0;
|
f32 inv_i0;
|
||||||
f32 inv_i1;
|
f32 inv_i1;
|
||||||
|
|
||||||
struct v2 normal; /* Normal vector of collision from e0 -> e1 */
|
V2 normal; /* Normal vector of collision from e0 -> e1 */
|
||||||
u64 last_iteration;
|
u64 last_iteration;
|
||||||
struct phys_contact_point points[2];
|
struct phys_contact_point points[2];
|
||||||
u32 num_points;
|
u32 num_points;
|
||||||
@ -76,16 +76,16 @@ struct phys_contact_constraint {
|
|||||||
struct phys_collision_debug {
|
struct phys_collision_debug {
|
||||||
struct sim_ent_id e0;
|
struct sim_ent_id e0;
|
||||||
struct sim_ent_id e1;
|
struct sim_ent_id e1;
|
||||||
struct collider_collision_points_result res;
|
CLD_CollisionResult res;
|
||||||
|
|
||||||
struct phys_contact_point points[2];
|
struct phys_contact_point points[2];
|
||||||
u32 num_points;
|
u32 num_points;
|
||||||
|
|
||||||
struct v2 closest0;
|
V2 closest0;
|
||||||
struct v2 closest1;
|
V2 closest1;
|
||||||
|
|
||||||
struct xform xf0;
|
Xform xf0;
|
||||||
struct xform xf1;
|
Xform xf1;
|
||||||
};
|
};
|
||||||
|
|
||||||
void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt, u64 phys_iteration);
|
void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt, u64 phys_iteration);
|
||||||
@ -117,13 +117,13 @@ struct phys_motor_joint {
|
|||||||
f32 inv_i0;
|
f32 inv_i0;
|
||||||
f32 inv_i1;
|
f32 inv_i1;
|
||||||
|
|
||||||
struct v2 linear_impulse;
|
V2 linear_impulse;
|
||||||
f32 angular_impulse;
|
f32 angular_impulse;
|
||||||
|
|
||||||
struct v2 point_local_e0;
|
V2 point_local_e0;
|
||||||
struct v2 point_local_e1;
|
V2 point_local_e1;
|
||||||
|
|
||||||
struct xform linear_mass_xf;
|
Xform linear_mass_xf;
|
||||||
f32 angular_mass;
|
f32 angular_mass;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,8 +139,8 @@ void phys_solve_motor_joints(struct phys_step_ctx *ctx, f32 dt);
|
|||||||
|
|
||||||
struct phys_mouse_joint_def {
|
struct phys_mouse_joint_def {
|
||||||
struct sim_ent_id target;
|
struct sim_ent_id target;
|
||||||
struct v2 point_local_start;
|
V2 point_local_start;
|
||||||
struct v2 point_end;
|
V2 point_end;
|
||||||
f32 linear_spring_hz;
|
f32 linear_spring_hz;
|
||||||
f32 linear_spring_damp;
|
f32 linear_spring_damp;
|
||||||
f32 angular_spring_hz;
|
f32 angular_spring_hz;
|
||||||
@ -150,8 +150,8 @@ struct phys_mouse_joint_def {
|
|||||||
|
|
||||||
struct phys_mouse_joint {
|
struct phys_mouse_joint {
|
||||||
struct sim_ent_id target;
|
struct sim_ent_id target;
|
||||||
struct v2 point_local_start;
|
V2 point_local_start;
|
||||||
struct v2 point_end;
|
V2 point_end;
|
||||||
f32 linear_spring_hz;
|
f32 linear_spring_hz;
|
||||||
f32 linear_spring_damp;
|
f32 linear_spring_damp;
|
||||||
f32 angular_spring_hz;
|
f32 angular_spring_hz;
|
||||||
@ -161,10 +161,10 @@ struct phys_mouse_joint {
|
|||||||
f32 inv_m;
|
f32 inv_m;
|
||||||
f32 inv_i;
|
f32 inv_i;
|
||||||
|
|
||||||
struct v2 linear_impulse;
|
V2 linear_impulse;
|
||||||
f32 angular_impulse;
|
f32 angular_impulse;
|
||||||
|
|
||||||
struct xform linear_mass_xf;
|
Xform linear_mass_xf;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct phys_mouse_joint_def phys_mouse_joint_def_init(void);
|
struct phys_mouse_joint_def phys_mouse_joint_def_init(void);
|
||||||
@ -182,8 +182,8 @@ struct phys_weld_joint_def {
|
|||||||
struct sim_ent_id e1;
|
struct sim_ent_id e1;
|
||||||
|
|
||||||
/* The xform that transforms a point in e0's space into the desired e1 space
|
/* The xform that transforms a point in e0's space into the desired e1 space
|
||||||
* (IE `xf` * V2(0, 0) should evaluate to the local point that e1's origin will lie) */
|
* (IE `xf` * V2FromXY(0, 0) should evaluate to the local point that e1's origin will lie) */
|
||||||
struct xform xf;
|
Xform xf;
|
||||||
|
|
||||||
f32 linear_spring_hz;
|
f32 linear_spring_hz;
|
||||||
f32 linear_spring_damp;
|
f32 linear_spring_damp;
|
||||||
@ -194,7 +194,7 @@ struct phys_weld_joint_def {
|
|||||||
struct phys_weld_joint {
|
struct phys_weld_joint {
|
||||||
struct sim_ent_id e0;
|
struct sim_ent_id e0;
|
||||||
struct sim_ent_id e1;
|
struct sim_ent_id e1;
|
||||||
struct xform xf0_to_xf1;
|
Xform xf0_to_xf1;
|
||||||
|
|
||||||
f32 linear_spring_hz;
|
f32 linear_spring_hz;
|
||||||
f32 linear_spring_damp;
|
f32 linear_spring_damp;
|
||||||
@ -206,8 +206,8 @@ struct phys_weld_joint {
|
|||||||
f32 inv_i0;
|
f32 inv_i0;
|
||||||
f32 inv_i1;
|
f32 inv_i1;
|
||||||
|
|
||||||
struct v2 linear_impulse0;
|
V2 linear_impulse0;
|
||||||
struct v2 linear_impulse1;
|
V2 linear_impulse1;
|
||||||
f32 angular_impulse0;
|
f32 angular_impulse0;
|
||||||
f32 angular_impulse1;
|
f32 angular_impulse1;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -19,7 +19,7 @@ struct space *space_alloc(f32 cell_size, u32 num_bins_sqrt)
|
|||||||
{
|
{
|
||||||
struct space *space;
|
struct space *space;
|
||||||
{
|
{
|
||||||
struct arena *arena = arena_alloc(GIBI(64));
|
Arena *arena = arena_alloc(GIBI(64));
|
||||||
space = arena_push(arena, struct space);
|
space = arena_push(arena, struct space);
|
||||||
space->entry_arena = arena;
|
space->entry_arena = arena;
|
||||||
}
|
}
|
||||||
@ -69,16 +69,16 @@ struct space *space_from_entry(struct space_entry *entry)
|
|||||||
* Cell
|
* Cell
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct v2i32 world_to_cell_coords(f32 cell_size, struct v2 world_pos)
|
INTERNAL V2i32 world_to_cell_coords(f32 cell_size, V2 world_pos)
|
||||||
{
|
{
|
||||||
f32 x = world_pos.x;
|
f32 x = world_pos.x;
|
||||||
f32 y = world_pos.y;
|
f32 y = world_pos.y;
|
||||||
x = (x + ((x >= 0) - (x < 0)) * cell_size) / cell_size;
|
x = (x + ((x >= 0) - (x < 0)) * cell_size) / cell_size;
|
||||||
y = (y + ((y >= 0) - (y < 0)) * cell_size) / cell_size;
|
y = (y + ((y >= 0) - (y < 0)) * cell_size) / cell_size;
|
||||||
return V2I32((i32)x, (i32)y);
|
return V2i32FromXY((i32)x, (i32)y);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL i32 cell_coords_to_bin_index(struct space *space, struct v2i32 cell_pos)
|
INTERNAL i32 cell_coords_to_bin_index(struct space *space, V2i32 cell_pos)
|
||||||
{
|
{
|
||||||
i32 num_bins_sqrt = space->num_bins_sqrt;
|
i32 num_bins_sqrt = space->num_bins_sqrt;
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ INTERNAL i32 cell_coords_to_bin_index(struct space *space, struct v2i32 cell_pos
|
|||||||
return bin_index;
|
return bin_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct space_cell *space_get_cell(struct space *space, struct v2i32 cell_pos)
|
struct space_cell *space_get_cell(struct space *space, V2i32 cell_pos)
|
||||||
{
|
{
|
||||||
i32 bin_index = cell_coords_to_bin_index(space, cell_pos);
|
i32 bin_index = cell_coords_to_bin_index(space, cell_pos);
|
||||||
struct space_cell_bin *bin = &space->bins[bin_index];
|
struct space_cell_bin *bin = &space->bins[bin_index];
|
||||||
@ -114,7 +114,7 @@ struct space_cell *space_get_cell(struct space *space, struct v2i32 cell_pos)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void space_cell_node_alloc(struct v2i32 cell_pos, struct space_entry *entry)
|
INTERNAL void space_cell_node_alloc(V2i32 cell_pos, struct space_entry *entry)
|
||||||
{
|
{
|
||||||
struct space *space = space_from_entry(entry);
|
struct space *space = space_from_entry(entry);
|
||||||
i32 bin_index = cell_coords_to_bin_index(space, cell_pos);
|
i32 bin_index = cell_coords_to_bin_index(space, cell_pos);
|
||||||
@ -306,27 +306,27 @@ void space_entry_release(struct space_entry *entry)
|
|||||||
space->first_free_entry = entry;
|
space->first_free_entry = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void space_entry_update_aabb(struct space_entry *entry, struct aabb new_aabb)
|
void space_entry_update_aabb(struct space_entry *entry, Aabb new_aabb)
|
||||||
{
|
{
|
||||||
struct space *space = space_from_entry(entry);
|
struct space *space = space_from_entry(entry);
|
||||||
f32 cell_size = space->cell_size;
|
f32 cell_size = space->cell_size;
|
||||||
|
|
||||||
struct v2i32 old_cell_p0 = V2I32(0, 0);
|
V2i32 old_cell_p0 = V2i32FromXY(0, 0);
|
||||||
struct v2i32 old_cell_p1 = V2I32(0, 0);
|
V2i32 old_cell_p1 = V2i32FromXY(0, 0);
|
||||||
if (entry->first_node) {
|
if (entry->first_node) {
|
||||||
struct aabb old_aabb = entry->aabb;
|
Aabb old_aabb = entry->aabb;
|
||||||
old_cell_p0 = world_to_cell_coords(cell_size, old_aabb.p0);
|
old_cell_p0 = world_to_cell_coords(cell_size, old_aabb.p0);
|
||||||
old_cell_p1 = world_to_cell_coords(cell_size, old_aabb.p1);
|
old_cell_p1 = world_to_cell_coords(cell_size, old_aabb.p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2i32 new_cell_p0 = world_to_cell_coords(cell_size, new_aabb.p0);
|
V2i32 new_cell_p0 = world_to_cell_coords(cell_size, new_aabb.p0);
|
||||||
struct v2i32 new_cell_p1 = world_to_cell_coords(cell_size, new_aabb.p1);
|
V2i32 new_cell_p1 = world_to_cell_coords(cell_size, new_aabb.p1);
|
||||||
|
|
||||||
/* Release outdated nodes */
|
/* Release outdated nodes */
|
||||||
struct space_cell_node *n = entry->first_node;
|
struct space_cell_node *n = entry->first_node;
|
||||||
while (n) {
|
while (n) {
|
||||||
struct space_cell *cell = n->cell;
|
struct space_cell *cell = n->cell;
|
||||||
struct v2i32 cell_pos = cell->pos;
|
V2i32 cell_pos = cell->pos;
|
||||||
if (cell_pos.x < new_cell_p0.x || cell_pos.x > new_cell_p1.x || cell_pos.y < new_cell_p0.y || cell_pos.y > new_cell_p1.y) {
|
if (cell_pos.x < new_cell_p0.x || cell_pos.x > new_cell_p1.x || cell_pos.y < new_cell_p0.y || cell_pos.y > new_cell_p1.y) {
|
||||||
/* Cell is outside of new AABB */
|
/* Cell is outside of new AABB */
|
||||||
struct space_cell_node *next = n->next_in_entry;
|
struct space_cell_node *next = n->next_in_entry;
|
||||||
@ -342,7 +342,7 @@ void space_entry_update_aabb(struct space_entry *entry, struct aabb new_aabb)
|
|||||||
for (i32 x = new_cell_p0.x; x <= new_cell_p1.x; ++x) {
|
for (i32 x = new_cell_p0.x; x <= new_cell_p1.x; ++x) {
|
||||||
if (x != 0 && y != 0 && (x < old_cell_p0.x || x > old_cell_p1.x || y < old_cell_p0.y || y > old_cell_p1.y)) {
|
if (x != 0 && y != 0 && (x < old_cell_p0.x || x > old_cell_p1.x || y < old_cell_p0.y || y > old_cell_p1.y)) {
|
||||||
/* Cell is outside of old AABB */
|
/* Cell is outside of old AABB */
|
||||||
space_cell_node_alloc(V2I32(x, y), entry);
|
space_cell_node_alloc(V2i32FromXY(x, y), entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,7 +354,7 @@ void space_entry_update_aabb(struct space_entry *entry, struct aabb new_aabb)
|
|||||||
* Iter
|
* Iter
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct space_iter space_iter_begin_aabb(struct space *space, struct aabb aabb)
|
struct space_iter space_iter_begin_aabb(struct space *space, Aabb aabb)
|
||||||
{
|
{
|
||||||
struct space_iter iter = ZI;
|
struct space_iter iter = ZI;
|
||||||
f32 cell_size = space->cell_size;
|
f32 cell_size = space->cell_size;
|
||||||
@ -364,7 +364,7 @@ struct space_iter space_iter_begin_aabb(struct space *space, struct aabb aabb)
|
|||||||
iter.cell_end = world_to_cell_coords(cell_size, aabb.p1);
|
iter.cell_end = world_to_cell_coords(cell_size, aabb.p1);
|
||||||
if (iter.cell_start.x > iter.cell_end.x || iter.cell_start.y > iter.cell_end.y) {
|
if (iter.cell_start.x > iter.cell_end.x || iter.cell_start.y > iter.cell_end.y) {
|
||||||
/* Swap cell_start & cell_end */
|
/* Swap cell_start & cell_end */
|
||||||
struct v2i32 tmp = iter.cell_start;
|
V2i32 tmp = iter.cell_start;
|
||||||
iter.cell_start = iter.cell_end;
|
iter.cell_start = iter.cell_end;
|
||||||
iter.cell_end = tmp;
|
iter.cell_end = tmp;
|
||||||
}
|
}
|
||||||
@ -380,10 +380,10 @@ struct space_iter space_iter_begin_aabb(struct space *space, struct aabb aabb)
|
|||||||
struct space_entry *space_iter_next(struct space_iter *iter)
|
struct space_entry *space_iter_next(struct space_iter *iter)
|
||||||
{
|
{
|
||||||
struct space *space = iter->space;
|
struct space *space = iter->space;
|
||||||
struct aabb iter_aabb = iter->aabb;
|
Aabb iter_aabb = iter->aabb;
|
||||||
struct v2i32 cell_start = iter->cell_start;
|
V2i32 cell_start = iter->cell_start;
|
||||||
struct v2i32 cell_end = iter->cell_end;
|
V2i32 cell_end = iter->cell_end;
|
||||||
struct v2i32 cell_cur = iter->cell_cur;
|
V2i32 cell_cur = iter->cell_cur;
|
||||||
i32 span = cell_end.x - cell_start.x;
|
i32 span = cell_end.x - cell_start.x;
|
||||||
|
|
||||||
struct space_cell_node *next_node = 0;
|
struct space_cell_node *next_node = 0;
|
||||||
@ -399,7 +399,7 @@ struct space_entry *space_iter_next(struct space_iter *iter)
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
if (next_node) {
|
if (next_node) {
|
||||||
struct space_entry *entry = next_node->entry;
|
struct space_entry *entry = next_node->entry;
|
||||||
struct aabb entry_aabb = entry->aabb;
|
Aabb entry_aabb = entry->aabb;
|
||||||
if (collider_test_aabb(entry_aabb, iter_aabb)) {
|
if (collider_test_aabb(entry_aabb, iter_aabb)) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -12,7 +12,7 @@ struct space_entry {
|
|||||||
struct space_cell_node *first_node;
|
struct space_cell_node *first_node;
|
||||||
struct space_cell_node *last_node;
|
struct space_cell_node *last_node;
|
||||||
|
|
||||||
struct aabb aabb;
|
Aabb aabb;
|
||||||
struct sim_ent_id ent;
|
struct sim_ent_id ent;
|
||||||
|
|
||||||
struct space_entry *next_free;
|
struct space_entry *next_free;
|
||||||
@ -37,7 +37,7 @@ struct space_cell_node {
|
|||||||
|
|
||||||
struct space_cell {
|
struct space_cell {
|
||||||
b32 valid;
|
b32 valid;
|
||||||
struct v2i32 pos;
|
V2i32 pos;
|
||||||
|
|
||||||
struct space_cell_node *first_node;
|
struct space_cell_node *first_node;
|
||||||
struct space_cell_node *last_node;
|
struct space_cell_node *last_node;
|
||||||
@ -58,25 +58,25 @@ struct space {
|
|||||||
b32 valid;
|
b32 valid;
|
||||||
f32 cell_size;
|
f32 cell_size;
|
||||||
|
|
||||||
struct arena *cell_arena;
|
Arena *cell_arena;
|
||||||
struct space_cell_bin *bins;
|
struct space_cell_bin *bins;
|
||||||
i32 num_bins;
|
i32 num_bins;
|
||||||
i32 num_bins_sqrt;
|
i32 num_bins_sqrt;
|
||||||
struct space_cell *first_free_cell;
|
struct space_cell *first_free_cell;
|
||||||
struct space_cell_node *first_free_cell_node;
|
struct space_cell_node *first_free_cell_node;
|
||||||
|
|
||||||
struct arena *entry_arena;
|
Arena *entry_arena;
|
||||||
u64 num_entries_reserved;
|
u64 num_entries_reserved;
|
||||||
struct space_entry *entries;
|
struct space_entry *entries;
|
||||||
struct space_entry *first_free_entry;
|
struct space_entry *first_free_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct space_iter {
|
struct space_iter {
|
||||||
struct aabb aabb;
|
Aabb aabb;
|
||||||
struct space *space;
|
struct space *space;
|
||||||
struct v2i32 cell_start;
|
V2i32 cell_start;
|
||||||
struct v2i32 cell_end;
|
V2i32 cell_end;
|
||||||
struct v2i32 cell_cur;
|
V2i32 cell_cur;
|
||||||
struct space_cell_node *prev;
|
struct space_cell_node *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ struct space *space_from_entry(struct space_entry *entry);
|
|||||||
* Cell
|
* Cell
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct space_cell *space_get_cell(struct space *space, struct v2i32 cell_pos);
|
struct space_cell *space_get_cell(struct space *space, V2i32 cell_pos);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Entry
|
* Entry
|
||||||
@ -125,12 +125,12 @@ struct space_cell *space_get_cell(struct space *space, struct v2i32 cell_pos);
|
|||||||
struct space_entry *space_entry_from_handle(struct space *space, struct space_entry_handle handle);
|
struct space_entry *space_entry_from_handle(struct space *space, struct space_entry_handle handle);
|
||||||
struct space_entry *space_entry_alloc(struct space *space, struct sim_ent_id entity);
|
struct space_entry *space_entry_alloc(struct space *space, struct sim_ent_id entity);
|
||||||
void space_entry_release(struct space_entry *entry);
|
void space_entry_release(struct space_entry *entry);
|
||||||
void space_entry_update_aabb(struct space_entry *entry, struct aabb new_aabb);
|
void space_entry_update_aabb(struct space_entry *entry, Aabb new_aabb);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Iter
|
* Iter
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct space_iter space_iter_begin_aabb(struct space *space, struct aabb aabb);
|
struct space_iter space_iter_begin_aabb(struct space *space, Aabb aabb);
|
||||||
struct space_entry *space_iter_next(struct space_iter *iter);
|
struct space_entry *space_iter_next(struct space_iter *iter);
|
||||||
#define space_iter_end(i)
|
#define space_iter_end(i)
|
||||||
|
|||||||
@ -88,9 +88,9 @@ INTERNAL struct sim_ent *test_spawn_chucker(struct sim_ent *parent)
|
|||||||
zone->attach_slice = LIT("out");
|
zone->attach_slice = LIT("out");
|
||||||
|
|
||||||
sim_ent_enable_prop(zone, SEPROP_SENSOR);
|
sim_ent_enable_prop(zone, SEPROP_SENSOR);
|
||||||
struct collider_shape collider = ZI;
|
CLD_Shape collider = ZI;
|
||||||
collider.count = 2;
|
collider.count = 2;
|
||||||
collider.points[1] = V2(0, -0.5);
|
collider.points[1] = V2FromXY(0, -0.5);
|
||||||
collider.radius = 0.1f;
|
collider.radius = 0.1f;
|
||||||
zone->local_collider = collider;
|
zone->local_collider = collider;
|
||||||
|
|
||||||
@ -108,11 +108,11 @@ INTERNAL struct sim_ent *test_spawn_employee(struct sim_ent *parent)
|
|||||||
|
|
||||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||||
|
|
||||||
struct v2 pos = V2(1, -1);
|
V2 pos = V2FromXY(1, -1);
|
||||||
|
|
||||||
//struct v2 size = V2(0.5, 0.5);
|
//V2 size = V2FromXY(0.5, 0.5);
|
||||||
//struct v2 size = V2(0.5, 0.25);
|
//V2 size = V2FromXY(0.5, 0.25);
|
||||||
struct v2 size = V2(1.0, 1.0);
|
V2 size = V2FromXY(1.0, 1.0);
|
||||||
|
|
||||||
//f32 r = PI / 4;
|
//f32 r = PI / 4;
|
||||||
f32 r = 0;
|
f32 r = 0;
|
||||||
@ -130,11 +130,11 @@ INTERNAL struct sim_ent *test_spawn_employee(struct sim_ent *parent)
|
|||||||
e->sprite_span_name = LIT("idle.two_handed");
|
e->sprite_span_name = LIT("idle.two_handed");
|
||||||
e->layer = SIM_LAYER_SHOULDERS;
|
e->layer = SIM_LAYER_SHOULDERS;
|
||||||
|
|
||||||
e->local_collider.points[0] = V2(0, 0);
|
e->local_collider.points[0] = V2FromXY(0, 0);
|
||||||
e->local_collider.count = 1;
|
e->local_collider.count = 1;
|
||||||
e->local_collider.radius = 0.25f;
|
e->local_collider.radius = 0.25f;
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
Xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
//xf.bx.y = -1.f;
|
//xf.bx.y = -1.f;
|
||||||
|
|
||||||
sim_ent_set_xform(e, xf);
|
sim_ent_set_xform(e, xf);
|
||||||
@ -148,7 +148,7 @@ INTERNAL struct sim_ent *test_spawn_employee(struct sim_ent *parent)
|
|||||||
|
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
||||||
e->sprite_emittance = V3(1, 1, 1);
|
e->sprite_emittance = V3FromXYZ(1, 1, 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ INTERNAL struct sim_ent *test_spawn_employee(struct sim_ent *parent)
|
|||||||
employee->equipped = e->id;
|
employee->equipped = e->id;
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
||||||
e->sprite_emittance = V3(1, 1, 1);
|
e->sprite_emittance = V3FromXYZ(1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return employee;
|
return employee;
|
||||||
@ -197,13 +197,13 @@ INTERNAL struct sim_ent *test_spawn_camera(struct sim_ent *parent, struct sim_en
|
|||||||
|
|
||||||
f32 width = (f32)DEFAULT_CAMERA_WIDTH;
|
f32 width = (f32)DEFAULT_CAMERA_WIDTH;
|
||||||
f32 height = (f32)DEFAULT_CAMERA_HEIGHT;
|
f32 height = (f32)DEFAULT_CAMERA_HEIGHT;
|
||||||
camera_ent->camera_quad_xform = XFORM_TRS(.s = V2(width, height));
|
camera_ent->camera_quad_xform = XFORM_TRS(.s = V2FromXY(width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
return camera_ent;
|
return camera_ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct sim_ent *test_spawn_explosion(struct sim_ent *parent, struct v2 pos, f32 strength, f32 radius)
|
INTERNAL struct sim_ent *test_spawn_explosion(struct sim_ent *parent, V2 pos, f32 strength, f32 radius)
|
||||||
{
|
{
|
||||||
struct sim_ent *ent = sim_ent_alloc_sync_src(parent);
|
struct sim_ent *ent = sim_ent_alloc_sync_src(parent);
|
||||||
sim_ent_set_xform(ent, XFORM_POS(pos));
|
sim_ent_set_xform(ent, XFORM_POS(pos));
|
||||||
@ -219,28 +219,28 @@ INTERNAL struct sim_ent *test_spawn_explosion(struct sim_ent *parent, struct v2
|
|||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void test_teleport(struct sim_ent *ent, struct v2 pos)
|
INTERNAL void test_teleport(struct sim_ent *ent, V2 pos)
|
||||||
{
|
{
|
||||||
//++ent->continuity_gen;
|
//++ent->continuity_gen;
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
xf.og = pos;
|
xf.og = pos;
|
||||||
sim_ent_set_xform(ent, xf);
|
sim_ent_set_xform(ent, xf);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void test_spawn_entities1(struct sim_ent *parent, struct v2 pos)
|
INTERNAL void test_spawn_entities1(struct sim_ent *parent, V2 pos)
|
||||||
{
|
{
|
||||||
(UNUSED)pos;
|
(UNUSED)pos;
|
||||||
|
|
||||||
/* Enemy */
|
/* Enemy */
|
||||||
{
|
{
|
||||||
struct sim_ent *e = test_spawn_employee(parent);
|
struct sim_ent *e = test_spawn_employee(parent);
|
||||||
struct xform xf = sim_ent_get_xform(e);
|
Xform xf = sim_ent_get_xform(e);
|
||||||
xf.og = pos;
|
xf.og = pos;
|
||||||
sim_ent_set_xform(e, xf);
|
sim_ent_set_xform(e, xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void test_spawn_entities2(struct sim_ent *parent, struct v2 pos)
|
INTERNAL void test_spawn_entities2(struct sim_ent *parent, V2 pos)
|
||||||
{
|
{
|
||||||
(UNUSED)pos;
|
(UNUSED)pos;
|
||||||
|
|
||||||
@ -251,8 +251,8 @@ INTERNAL void test_spawn_entities2(struct sim_ent *parent, struct v2 pos)
|
|||||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||||
|
|
||||||
f32 rot = 0;
|
f32 rot = 0;
|
||||||
struct v2 size = V2(0.125, 0.125);
|
V2 size = V2FromXY(0.125, 0.125);
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = rot, .s = size);
|
Xform xf = XFORM_TRS(.t = pos, .r = rot, .s = size);
|
||||||
sim_ent_set_xform(e, xf);
|
sim_ent_set_xform(e, xf);
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(LIT("sprite/tile.ase"));
|
e->sprite = sprite_tag_from_path(LIT("sprite/tile.ase"));
|
||||||
@ -262,18 +262,18 @@ INTERNAL void test_spawn_entities2(struct sim_ent *parent, struct v2 pos)
|
|||||||
//e->sprite_tint = ALPHA32_F(COLOR_WHITE, 1);
|
//e->sprite_tint = ALPHA32_F(COLOR_WHITE, 1);
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SEPROP_SOLID);
|
sim_ent_enable_prop(e, SEPROP_SOLID);
|
||||||
struct quad collider_quad = quad_from_rect(RECT(-0.5, -0.5, 1, 1));
|
Quad collider_quad = quad_from_rect(RECT(-0.5, -0.5, 1, 1));
|
||||||
e->local_collider = collider_from_quad(collider_quad);
|
e->local_collider = collider_from_quad(collider_quad);
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
||||||
|
|
||||||
/* FIXME: Remove this */
|
/* FIXME: Remove this */
|
||||||
{
|
{
|
||||||
static struct rand_state rand = ZI;
|
static RandState rand = ZI;
|
||||||
f32 r = rand_f64_from_state(&rand, 1, 5);
|
f32 r = rand_f64_from_state(&rand, 1, 5);
|
||||||
f32 g = rand_f64_from_state(&rand, 1, 5);
|
f32 g = rand_f64_from_state(&rand, 1, 5);
|
||||||
f32 b = rand_f64_from_state(&rand, 1, 5);
|
f32 b = rand_f64_from_state(&rand, 1, 5);
|
||||||
e->sprite_emittance = V3(r, g, b);
|
e->sprite_emittance = V3FromXYZ(r, g, b);
|
||||||
e->sprite_tint = RGBA32_F(r / 5, g / 5, b / 5, 1);
|
e->sprite_tint = RGBA32_F(r / 5, g / 5, b / 5, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,8 +293,8 @@ INTERNAL void test_spawn_entities2(struct sim_ent *parent, struct v2 pos)
|
|||||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||||
|
|
||||||
f32 r = PI / 4;
|
f32 r = PI / 4;
|
||||||
struct v2 size = V2(0.5, 0.25);
|
V2 size = V2FromXY(0.5, 0.25);
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
Xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
sim_ent_set_xform(e, xf);
|
sim_ent_set_xform(e, xf);
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(LIT("sprite/bullet.ase"));
|
e->sprite = sprite_tag_from_path(LIT("sprite/bullet.ase"));
|
||||||
@ -311,7 +311,7 @@ INTERNAL void test_spawn_entities2(struct sim_ent *parent, struct v2 pos)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void test_spawn_entities3(struct sim_ent *parent, struct v2 pos)
|
INTERNAL void test_spawn_entities3(struct sim_ent *parent, V2 pos)
|
||||||
{
|
{
|
||||||
(UNUSED)pos;
|
(UNUSED)pos;
|
||||||
|
|
||||||
@ -321,8 +321,8 @@ INTERNAL void test_spawn_entities3(struct sim_ent *parent, struct v2 pos)
|
|||||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||||
|
|
||||||
f32 r = 0;
|
f32 r = 0;
|
||||||
struct v2 size = V2(1, 1);
|
V2 size = V2FromXY(1, 1);
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
Xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
sim_ent_set_xform(e, xf);
|
sim_ent_set_xform(e, xf);
|
||||||
|
|
||||||
e->sprite = sprite_tag_from_path(LIT("sprite/box.ase"));
|
e->sprite = sprite_tag_from_path(LIT("sprite/box.ase"));
|
||||||
@ -331,12 +331,12 @@ INTERNAL void test_spawn_entities3(struct sim_ent *parent, struct v2 pos)
|
|||||||
e->sprite_tint = COLOR_RED;
|
e->sprite_tint = COLOR_RED;
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SEPROP_SOLID);
|
sim_ent_enable_prop(e, SEPROP_SOLID);
|
||||||
struct quad collider_quad = quad_from_rect(RECT(-0.5, -0.5, 1, 1));
|
Quad collider_quad = quad_from_rect(RECT(-0.5, -0.5, 1, 1));
|
||||||
e->local_collider = collider_from_quad(collider_quad);
|
e->local_collider = collider_from_quad(collider_quad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void test_spawn_entities4(struct sim_ent *parent, struct v2 pos)
|
INTERNAL void test_spawn_entities4(struct sim_ent *parent, V2 pos)
|
||||||
{
|
{
|
||||||
(UNUSED)pos;
|
(UNUSED)pos;
|
||||||
|
|
||||||
@ -344,8 +344,8 @@ INTERNAL void test_spawn_entities4(struct sim_ent *parent, struct v2 pos)
|
|||||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||||
|
|
||||||
f32 r = 0;
|
f32 r = 0;
|
||||||
struct v2 size = V2(2, 1);
|
V2 size = V2FromXY(2, 1);
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
Xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
sim_ent_set_xform(e, xf);
|
sim_ent_set_xform(e, xf);
|
||||||
|
|
||||||
//e->sprite = sprite_tag_from_path(LIT("sprite/box.ase"));
|
//e->sprite = sprite_tag_from_path(LIT("sprite/box.ase"));
|
||||||
@ -353,28 +353,28 @@ INTERNAL void test_spawn_entities4(struct sim_ent *parent, struct v2 pos)
|
|||||||
e->layer = SIM_LAYER_SHOULDERS;
|
e->layer = SIM_LAYER_SHOULDERS;
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
|
||||||
e->sprite_emittance = V3(2, 2, 2);
|
e->sprite_emittance = V3FromXYZ(2, 2, 2);
|
||||||
|
|
||||||
e->sprite_tint = RGB32_F(1, 1, 1);
|
e->sprite_tint = RGB32_F(1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void test_spawn_tile(struct sim_snapshot *world, struct v2 world_pos)
|
INTERNAL void test_spawn_tile(struct sim_snapshot *world, V2 world_pos)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
struct sim_ent *e = sim_ent_alloc_sync_src(parent);
|
||||||
|
|
||||||
i32 sign_x = (world_pos.x >= 0) - (world_pos.x < 0);
|
i32 sign_x = (world_pos.x >= 0) - (world_pos.x < 0);
|
||||||
i32 sign_y = (world_pos.y >= 0) - (world_pos.y < 0);
|
i32 sign_y = (world_pos.y >= 0) - (world_pos.y < 0);
|
||||||
struct v2i32 tile_index = V2I32(world_pos.x * SIM_TILES_PER_UNIT_SQRT, world_pos.y * SIM_TILES_PER_UNIT_SQRT);
|
V2i32 tile_index = V2i32FromXY(world_pos.x * SIM_TILES_PER_UNIT_SQRT, world_pos.y * SIM_TILES_PER_UNIT_SQRT);
|
||||||
world_pos.x -= sign_x < 0;
|
world_pos.x -= sign_x < 0;
|
||||||
world_pos.y -= sign_y < 0;
|
world_pos.y -= sign_y < 0;
|
||||||
|
|
||||||
struct v2 tile_size = V2(1.f / SIM_TILES_PER_UNIT_SQRT, 1.f / SIM_TILES_PER_UNIT_SQRT);
|
V2 tile_size = V2FromXY(1.f / SIM_TILES_PER_UNIT_SQRT, 1.f / SIM_TILES_PER_UNIT_SQRT);
|
||||||
|
|
||||||
struct v2 pos = V2((f32)tile_index.x / SIM_TILES_PER_UNIT_SQRT, (f32)tile_index.y / SIM_TILES_PER_UNIT_SQRT);
|
V2 pos = V2FromXY((f32)tile_index.x / SIM_TILES_PER_UNIT_SQRT, (f32)tile_index.y / SIM_TILES_PER_UNIT_SQRT);
|
||||||
pos = v2_add(pos, v2_mul(V2(tile_size.x * sign_x, tile_size.y * sign_y), 0.5));
|
pos = v2_add(pos, v2_mul(V2FromXY(tile_size.x * sign_x, tile_size.y * sign_y), 0.5));
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos);
|
Xform xf = XFORM_TRS(.t = pos);
|
||||||
sim_ent_set_xform(e, xf);
|
sim_ent_set_xform(e, xf);
|
||||||
|
|
||||||
e->layer = SIM_LAYER_WALLS;
|
e->layer = SIM_LAYER_WALLS;
|
||||||
@ -389,10 +389,10 @@ INTERNAL void test_spawn_tile(struct sim_snapshot *world, struct v2 world_pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sim_ent_enable_prop(e, SEPROP_SOLID);
|
sim_ent_enable_prop(e, SEPROP_SOLID);
|
||||||
struct quad collider_quad = quad_from_rect(RECT(-tile_size.x / 2, -tile_size.y / 2, tile_size.y, tile_size.y));
|
Quad collider_quad = quad_from_rect(RECT(-tile_size.x / 2, -tile_size.y / 2, tile_size.y, tile_size.y));
|
||||||
e->local_collider = collider_from_quad(collider_quad);
|
e->local_collider = collider_from_quad(collider_quad);
|
||||||
#else
|
#else
|
||||||
struct v2i32 tile_index = sim_world_tile_index_from_pos(world_pos);
|
V2i32 tile_index = sim_world_tile_index_from_pos(world_pos);
|
||||||
sim_snapshot_set_tile(world, tile_index, SIM_TILE_KIND_WALL);
|
sim_snapshot_set_tile(world, tile_index, SIM_TILE_KIND_WALL);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -434,7 +434,7 @@ INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort_y, arg_a, arg_b, udata)
|
|||||||
INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||||
|
|
||||||
/* Release existing walls and gather tile chunks.
|
/* Release existing walls and gather tile chunks.
|
||||||
@ -467,25 +467,25 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct wall_node {
|
struct wall_node {
|
||||||
struct v2i32 start;
|
V2i32 start;
|
||||||
struct v2i32 end;
|
V2i32 end;
|
||||||
i32 wall_dir; /* = 0 up, 1 = right, 2 = down, 3 = left */
|
i32 wall_dir; /* = 0 up, 1 = right, 2 = down, 3 = left */
|
||||||
struct wall_node *next;
|
struct wall_node *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Dicts containing walls that end on edge of tile chunk, keyed by tile end index.
|
/* Dicts containing walls that end on edge of tile chunk, keyed by tile end index.
|
||||||
* Used to merge walls accross tile chunks. */
|
* Used to merge walls accross tile chunks. */
|
||||||
struct dict *horizontal_ends_dict = dict_init(scratch.arena, 1024);
|
Dict *horizontal_ends_dict = dict_init(scratch.arena, 1024);
|
||||||
struct dict *vertical_ends_dict = dict_init(scratch.arena, 1024);
|
Dict *vertical_ends_dict = dict_init(scratch.arena, 1024);
|
||||||
|
|
||||||
struct wall_node *first_wall = 0;
|
struct wall_node *first_wall = 0;
|
||||||
|
|
||||||
/* Generate horizontal wall nodes */
|
/* Generate horizontal wall nodes */
|
||||||
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
||||||
struct sim_ent *chunk = x_sorted_tile_chunks[sorted_index];
|
struct sim_ent *chunk = x_sorted_tile_chunks[sorted_index];
|
||||||
struct v2i32 chunk_index = chunk->tile_chunk_index;
|
V2i32 chunk_index = chunk->tile_chunk_index;
|
||||||
struct sim_ent *top_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x, chunk_index.y - 1));
|
struct sim_ent *top_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x, chunk_index.y - 1));
|
||||||
struct sim_ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x, chunk_index.y + 1));
|
struct sim_ent *bottom_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x, chunk_index.y + 1));
|
||||||
/* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */
|
/* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */
|
||||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid;
|
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid;
|
||||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||||
@ -497,17 +497,17 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
i32 desired_wall_dir = -1;
|
i32 desired_wall_dir = -1;
|
||||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x, tile_y));
|
||||||
}
|
}
|
||||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT) {
|
if (tile_x < SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
enum sim_tile_kind top_tile = SIM_TILE_KIND_NONE;
|
enum sim_tile_kind top_tile = SIM_TILE_KIND_NONE;
|
||||||
if (tile_y == 0) {
|
if (tile_y == 0) {
|
||||||
if (top_chunk->valid) {
|
if (top_chunk->valid) {
|
||||||
struct v2i32 top_tile_local_index = V2I32(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1);
|
V2i32 top_tile_local_index = V2i32FromXY(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1);
|
||||||
top_tile = sim_get_chunk_tile(top_chunk, top_tile_local_index);
|
top_tile = sim_get_chunk_tile(top_chunk, top_tile_local_index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
top_tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y - 1));
|
top_tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x, tile_y - 1));
|
||||||
}
|
}
|
||||||
if (tile == SIM_TILE_KIND_WALL) {
|
if (tile == SIM_TILE_KIND_WALL) {
|
||||||
/* Process wall tile */
|
/* Process wall tile */
|
||||||
@ -524,13 +524,13 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
|
|
||||||
/* Stop wall */
|
/* Stop wall */
|
||||||
if (wall_dir >= 0 && desired_wall_dir != wall_dir) {
|
if (wall_dir >= 0 && desired_wall_dir != wall_dir) {
|
||||||
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_start, tile_y));
|
V2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2i32FromXY(wall_start, tile_y));
|
||||||
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_end, tile_y));
|
V2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2i32FromXY(wall_end, tile_y));
|
||||||
struct wall_node *node = 0;
|
struct wall_node *node = 0;
|
||||||
if (wall_start == 0) {
|
if (wall_start == 0) {
|
||||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
||||||
start_hash = rand_u64_from_seeds(start_hash, wall_dir);
|
start_hash = rand_u64_from_seeds(start_hash, wall_dir);
|
||||||
struct dict_entry *entry = dict_get_entry(horizontal_ends_dict, start_hash);
|
DictEntry *entry = dict_get_entry(horizontal_ends_dict, start_hash);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
/* Existing wall exists accross chunk boundary */
|
/* Existing wall exists accross chunk boundary */
|
||||||
node = (struct wall_node *)entry->value;
|
node = (struct wall_node *)entry->value;
|
||||||
@ -572,9 +572,9 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
/* Generate vertical wall nodes */
|
/* Generate vertical wall nodes */
|
||||||
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
for (u64 sorted_index = 0; sorted_index < sorted_tile_chunks_count; ++sorted_index) {
|
||||||
struct sim_ent *chunk = y_sorted_tile_chunks[sorted_index];
|
struct sim_ent *chunk = y_sorted_tile_chunks[sorted_index];
|
||||||
struct v2i32 chunk_index = chunk->tile_chunk_index;
|
V2i32 chunk_index = chunk->tile_chunk_index;
|
||||||
struct sim_ent *left_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x - 1, chunk_index.y));
|
struct sim_ent *left_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x - 1, chunk_index.y));
|
||||||
struct sim_ent *right_chunk = sim_tile_chunk_from_chunk_index(world, V2I32(chunk_index.x + 1, chunk_index.y));
|
struct sim_ent *right_chunk = sim_tile_chunk_from_chunk_index(world, V2i32FromXY(chunk_index.x + 1, chunk_index.y));
|
||||||
/* If there's no chunk to the right of this one, then do an extra iteration (since walls are created on the left of each tile) */
|
/* If there's no chunk to the right of this one, then do an extra iteration (since walls are created on the left of each tile) */
|
||||||
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
|
||||||
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + !right_chunk->valid;
|
i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + !right_chunk->valid;
|
||||||
@ -586,18 +586,18 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
i32 desired_wall_dir = -1;
|
i32 desired_wall_dir = -1;
|
||||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x, tile_y));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
if (tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
enum sim_tile_kind left_tile = SIM_TILE_KIND_NONE;
|
enum sim_tile_kind left_tile = SIM_TILE_KIND_NONE;
|
||||||
if (tile_x == 0) {
|
if (tile_x == 0) {
|
||||||
if (left_chunk->valid) {
|
if (left_chunk->valid) {
|
||||||
struct v2i32 left_tile_local_index = V2I32(SIM_TILES_PER_CHUNK_SQRT - 1, tile_y);
|
V2i32 left_tile_local_index = V2i32FromXY(SIM_TILES_PER_CHUNK_SQRT - 1, tile_y);
|
||||||
left_tile = sim_get_chunk_tile(left_chunk, left_tile_local_index);
|
left_tile = sim_get_chunk_tile(left_chunk, left_tile_local_index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
left_tile = sim_get_chunk_tile(chunk, V2I32(tile_x - 1, tile_y));
|
left_tile = sim_get_chunk_tile(chunk, V2i32FromXY(tile_x - 1, tile_y));
|
||||||
}
|
}
|
||||||
if (tile == SIM_TILE_KIND_WALL) {
|
if (tile == SIM_TILE_KIND_WALL) {
|
||||||
/* Process wall tile */
|
/* Process wall tile */
|
||||||
@ -614,13 +614,13 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
|
|
||||||
/* Stop wall */
|
/* Stop wall */
|
||||||
if (wall_dir >= 0 && desired_wall_dir != wall_dir) {
|
if (wall_dir >= 0 && desired_wall_dir != wall_dir) {
|
||||||
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_start));
|
V2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2i32FromXY(tile_x, wall_start));
|
||||||
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_end));
|
V2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2i32FromXY(tile_x, wall_end));
|
||||||
struct wall_node *node = 0;
|
struct wall_node *node = 0;
|
||||||
if (wall_start == 0) {
|
if (wall_start == 0) {
|
||||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
||||||
start_hash = rand_u64_from_seeds(start_hash, wall_dir);
|
start_hash = rand_u64_from_seeds(start_hash, wall_dir);
|
||||||
struct dict_entry *entry = dict_get_entry(vertical_ends_dict, start_hash);
|
DictEntry *entry = dict_get_entry(vertical_ends_dict, start_hash);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
/* Existing wall exists accross chunk boundary */
|
/* Existing wall exists accross chunk boundary */
|
||||||
node = (struct wall_node *)entry->value;
|
node = (struct wall_node *)entry->value;
|
||||||
@ -664,17 +664,17 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
struct sim_ent *wall_ent = sim_ent_alloc_sync_src(root);
|
struct sim_ent *wall_ent = sim_ent_alloc_sync_src(root);
|
||||||
sim_ent_enable_prop(wall_ent, SEPROP_WALL);
|
sim_ent_enable_prop(wall_ent, SEPROP_WALL);
|
||||||
|
|
||||||
struct v2 start = sim_pos_from_world_tile_index(node->start);
|
V2 start = sim_pos_from_world_tile_index(node->start);
|
||||||
struct v2 end = sim_pos_from_world_tile_index(node->end);
|
V2 end = sim_pos_from_world_tile_index(node->end);
|
||||||
|
|
||||||
struct xform xf = XFORM_POS(start);
|
Xform xf = XFORM_POS(start);
|
||||||
sim_ent_set_xform(wall_ent, xf);
|
sim_ent_set_xform(wall_ent, xf);
|
||||||
|
|
||||||
sim_ent_enable_prop(wall_ent, SEPROP_SOLID);
|
sim_ent_enable_prop(wall_ent, SEPROP_SOLID);
|
||||||
wall_ent->local_collider.count = 2;
|
wall_ent->local_collider.count = 2;
|
||||||
wall_ent->local_collider.points[1] = v2_sub(end, start);
|
wall_ent->local_collider.points[1] = v2_sub(end, start);
|
||||||
|
|
||||||
struct v2 dirs[4] = { V2(0, -1), V2(1, 0), V2(0, 1), V2(-1, 0) };
|
V2 dirs[4] = { V2FromXY(0, -1), V2FromXY(1, 0), V2FromXY(0, 1), V2FromXY(-1, 0) };
|
||||||
ASSERT(node->wall_dir >= 0 && (u32)node->wall_dir < countof(dirs));
|
ASSERT(node->wall_dir >= 0 && (u32)node->wall_dir < countof(dirs));
|
||||||
wall_ent->collision_dir = dirs[node->wall_dir];
|
wall_ent->collision_dir = dirs[node->wall_dir];
|
||||||
|
|
||||||
@ -721,8 +721,8 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
|||||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||||
/* Bullet impact */
|
/* Bullet impact */
|
||||||
if (sim_ent_has_prop(e0, SEPROP_BULLET)) {
|
if (sim_ent_has_prop(e0, SEPROP_BULLET)) {
|
||||||
struct v2 normal = data->normal; /* Impact normal */
|
V2 normal = data->normal; /* Impact normal */
|
||||||
struct v2 vrel = data->vrel; /* Impact velocity */
|
V2 vrel = data->vrel; /* Impact velocity */
|
||||||
|
|
||||||
struct sim_ent *bullet = e0;
|
struct sim_ent *bullet = e0;
|
||||||
struct sim_ent *target = e1;
|
struct sim_ent *target = e1;
|
||||||
@ -730,25 +730,25 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
|||||||
|
|
||||||
/* Process collision if bullet already spent or * target share same top level parent */
|
/* Process collision if bullet already spent or * target share same top level parent */
|
||||||
if (!bullet->bullet_has_hit && !sim_ent_id_eq(src->top, target->top) && sim_ent_has_prop(target, SEPROP_SOLID)) {
|
if (!bullet->bullet_has_hit && !sim_ent_id_eq(src->top, target->top) && sim_ent_has_prop(target, SEPROP_SOLID)) {
|
||||||
struct v2 point = data->point;
|
V2 point = data->point;
|
||||||
|
|
||||||
/* Update tracer */
|
/* Update tracer */
|
||||||
struct sim_ent *tracer = sim_ent_from_id(world, bullet->bullet_tracer);
|
struct sim_ent *tracer = sim_ent_from_id(world, bullet->bullet_tracer);
|
||||||
if (sim_ent_should_simulate(tracer)) {
|
if (sim_ent_should_simulate(tracer)) {
|
||||||
struct xform xf = sim_ent_get_xform(tracer);
|
Xform xf = sim_ent_get_xform(tracer);
|
||||||
xf.og = point;
|
xf.og = point;
|
||||||
sim_ent_set_xform(tracer, xf);
|
sim_ent_set_xform(tracer, xf);
|
||||||
sim_ent_set_linear_velocity(tracer, V2(0, 0));
|
sim_ent_set_linear_velocity(tracer, V2FromXY(0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update target */
|
/* Update target */
|
||||||
struct v2 knockback = v2_mul(v2_norm(vrel), bullet->bullet_knockback);
|
V2 knockback = v2_mul(v2_norm(vrel), bullet->bullet_knockback);
|
||||||
sim_ent_apply_linear_impulse(target, knockback, point);
|
sim_ent_apply_linear_impulse(target, knockback, point);
|
||||||
|
|
||||||
/* Create test blood */
|
/* Create test blood */
|
||||||
/* TODO: Remove this */
|
/* TODO: Remove this */
|
||||||
{
|
{
|
||||||
struct xform xf = XFORM_TRS(.t = point, .r = rand_f64_from_state(&step_ctx->rand, 0, TAU));
|
Xform xf = XFORM_TRS(.t = point, .r = rand_f64_from_state(&step_ctx->rand, 0, TAU));
|
||||||
struct sim_ent *decal = sim_ent_alloc_sync_src(root);
|
struct sim_ent *decal = sim_ent_alloc_sync_src(root);
|
||||||
decal->sprite = sprite_tag_from_path(LIT("sprite/blood.ase"));
|
decal->sprite = sprite_tag_from_path(LIT("sprite/blood.ase"));
|
||||||
decal->sprite_tint = RGBA32_F(1, 1, 1, 0.25f);
|
decal->sprite_tint = RGBA32_F(1, 1, 1, 0.25f);
|
||||||
@ -756,7 +756,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
|||||||
sim_ent_set_xform(decal, xf);
|
sim_ent_set_xform(decal, xf);
|
||||||
|
|
||||||
f32 perp_range = 0.5;
|
f32 perp_range = 0.5;
|
||||||
struct v2 linear_velocity = v2_mul(normal, 0.5);
|
V2 linear_velocity = v2_mul(normal, 0.5);
|
||||||
linear_velocity = v2_add(linear_velocity, v2_mul(v2_perp(normal), rand_f64_from_state(&step_ctx->rand, -perp_range, perp_range)));
|
linear_velocity = v2_add(linear_velocity, v2_mul(v2_perp(normal), rand_f64_from_state(&step_ctx->rand, -perp_range, perp_range)));
|
||||||
|
|
||||||
f32 angular_velocity_range = 5;
|
f32 angular_velocity_range = 5;
|
||||||
@ -786,15 +786,15 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
|||||||
struct sim_ent *exp = e0;
|
struct sim_ent *exp = e0;
|
||||||
struct sim_ent *victim = e1;
|
struct sim_ent *victim = e1;
|
||||||
|
|
||||||
struct xform xf = sim_ent_get_xform(exp);
|
Xform xf = sim_ent_get_xform(exp);
|
||||||
|
|
||||||
struct collider_shape origin_collider = ZI;
|
CLD_Shape origin_collider = ZI;
|
||||||
origin_collider.count = 1;
|
origin_collider.count = 1;
|
||||||
|
|
||||||
struct xform victim_xf = sim_ent_get_xform(victim);
|
Xform victim_xf = sim_ent_get_xform(victim);
|
||||||
struct collider_closest_points_result closest_points = collider_closest_points(&origin_collider, &victim->local_collider, xf, victim_xf);
|
CLD_ClosestResult closest_points = collider_closest_points(&origin_collider, &victim->local_collider, xf, victim_xf);
|
||||||
struct v2 dir = v2_sub(closest_points.p1, closest_points.p0);
|
V2 dir = v2_sub(closest_points.p1, closest_points.p0);
|
||||||
struct v2 point = closest_points.p1;
|
V2 point = closest_points.p1;
|
||||||
f32 distance = v2_len(dir);
|
f32 distance = v2_len(dir);
|
||||||
#if 0
|
#if 0
|
||||||
if (closest_points.colliding) {
|
if (closest_points.colliding) {
|
||||||
@ -815,7 +815,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
|||||||
if (distance < radius) {
|
if (distance < radius) {
|
||||||
const f32 falloff_curve = 3; /* Cubic falloff */
|
const f32 falloff_curve = 3; /* Cubic falloff */
|
||||||
f32 strength_factor = math_pow(1 - distance/radius, falloff_curve);
|
f32 strength_factor = math_pow(1 - distance/radius, falloff_curve);
|
||||||
struct v2 impulse = v2_with_len(dir, strength_center * strength_factor);
|
V2 impulse = v2_with_len(dir, strength_center * strength_factor);
|
||||||
sim_ent_apply_linear_impulse(victim, impulse, point);
|
sim_ent_apply_linear_impulse(victim, impulse, point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -839,7 +839,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
|||||||
void sim_step(struct sim_step_ctx *ctx)
|
void sim_step(struct sim_step_ctx *ctx)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
b32 is_master = ctx->is_master;
|
b32 is_master = ctx->is_master;
|
||||||
struct sim_snapshot *world = ctx->world;
|
struct sim_snapshot *world = ctx->world;
|
||||||
@ -1032,7 +1032,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
u32 count = 1;
|
u32 count = 1;
|
||||||
f32 spread = 0;
|
f32 spread = 0;
|
||||||
for (u32 j = 0; j < count; ++j) {
|
for (u32 j = 0; j < count; ++j) {
|
||||||
struct v2 pos = player->player_cursor_pos;
|
V2 pos = player->player_cursor_pos;
|
||||||
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
||||||
test_spawn_entities1(root, pos);
|
test_spawn_entities1(root, pos);
|
||||||
}
|
}
|
||||||
@ -1042,7 +1042,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
u32 count = 1;
|
u32 count = 1;
|
||||||
f32 spread = 0;
|
f32 spread = 0;
|
||||||
for (u32 j = 0; j < count; ++j) {
|
for (u32 j = 0; j < count; ++j) {
|
||||||
struct v2 pos = player->player_cursor_pos;
|
V2 pos = player->player_cursor_pos;
|
||||||
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
||||||
test_spawn_entities2(root, pos);
|
test_spawn_entities2(root, pos);
|
||||||
}
|
}
|
||||||
@ -1052,7 +1052,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
u32 count = 1;
|
u32 count = 1;
|
||||||
f32 spread = 0;
|
f32 spread = 0;
|
||||||
for (u32 j = 0; j < count; ++j) {
|
for (u32 j = 0; j < count; ++j) {
|
||||||
struct v2 pos = player->player_cursor_pos;
|
V2 pos = player->player_cursor_pos;
|
||||||
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
||||||
test_spawn_entities3(root, pos);
|
test_spawn_entities3(root, pos);
|
||||||
}
|
}
|
||||||
@ -1062,7 +1062,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
u32 count = 1;
|
u32 count = 1;
|
||||||
f32 spread = 0;
|
f32 spread = 0;
|
||||||
for (u32 j = 0; j < count; ++j) {
|
for (u32 j = 0; j < count; ++j) {
|
||||||
struct v2 pos = player->player_cursor_pos;
|
V2 pos = player->player_cursor_pos;
|
||||||
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
pos.y += (((f32)j / (f32)count) - 0.5) * spread;
|
||||||
test_spawn_entities4(root, pos);
|
test_spawn_entities4(root, pos);
|
||||||
}
|
}
|
||||||
@ -1088,7 +1088,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
case SIM_CMD_KIND_CHAT:
|
case SIM_CMD_KIND_CHAT:
|
||||||
{
|
{
|
||||||
struct sim_data_key msg_key = cmd_ent->cmd_chat_msg;
|
struct sim_data_key msg_key = cmd_ent->cmd_chat_msg;
|
||||||
struct string msg = sim_data_from_key(sim_data_store, msg_key);
|
String msg = sim_data_from_key(sim_data_store, msg_key);
|
||||||
if (msg.len > 0) {
|
if (msg.len > 0) {
|
||||||
struct sim_ent *chat_ent = sim_ent_alloc_sync_src(root);
|
struct sim_ent *chat_ent = sim_ent_alloc_sync_src(root);
|
||||||
sim_ent_enable_prop(chat_ent, SEPROP_CHAT);
|
sim_ent_enable_prop(chat_ent, SEPROP_CHAT);
|
||||||
@ -1206,12 +1206,12 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
/* Update sprite local xform */
|
/* Update sprite local xform */
|
||||||
{
|
{
|
||||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("pivot"), ent->animation_frame);
|
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("pivot"), ent->animation_frame);
|
||||||
struct v2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT);
|
V2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT);
|
||||||
|
|
||||||
struct v2 dir = v2_mul_v2(sprite_size, slice.dir);
|
V2 dir = v2_mul_v2(sprite_size, slice.dir);
|
||||||
f32 rot = v2_angle(dir) + PI / 2;
|
f32 rot = v2_angle(dir) + PI / 2;
|
||||||
|
|
||||||
struct xform xf = XFORM_IDENT;
|
Xform xf = XFORM_IDENT;
|
||||||
xf = xform_rotated(xf, -rot);
|
xf = xform_rotated(xf, -rot);
|
||||||
xf = xform_scaled(xf, sprite_size);
|
xf = xform_scaled(xf, sprite_size);
|
||||||
xf = xform_translated(xf, v2_neg(slice.center));
|
xf = xform_translated(xf, v2_neg(slice.center));
|
||||||
@ -1221,7 +1221,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
|
|
||||||
/* Update collider from sprite */
|
/* Update collider from sprite */
|
||||||
if (ent->sprite_collider_slice.len > 0) {
|
if (ent->sprite_collider_slice.len > 0) {
|
||||||
struct xform cxf = ent->sprite_local_xform;
|
Xform cxf = ent->sprite_local_xform;
|
||||||
|
|
||||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame);
|
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame);
|
||||||
ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect)));
|
ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect)));
|
||||||
@ -1232,24 +1232,24 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
if (sim_ent_has_prop(ent, SEPROP_TEST)) {
|
if (sim_ent_has_prop(ent, SEPROP_TEST)) {
|
||||||
//if ((1)) {
|
//if ((1)) {
|
||||||
#if 0
|
#if 0
|
||||||
ent->local_collider.points[0] = V2(0, 0);
|
ent->local_collider.points[0] = V2FromXY(0, 0);
|
||||||
ent->local_collider.count = 1;
|
ent->local_collider.count = 1;
|
||||||
ent->local_collider.radius = 0.5;
|
ent->local_collider.radius = 0.5;
|
||||||
#elif 0
|
#elif 0
|
||||||
ent->local_collider.points[0] = v2_with_len(V2(0.08f, 0.17f), 0.15f);
|
ent->local_collider.points[0] = v2_with_len(V2FromXY(0.08f, 0.17f), 0.15f);
|
||||||
ent->local_collider.points[1] = v2_with_len(V2(-0.07f, -0.2f), 0.15f);
|
ent->local_collider.points[1] = v2_with_len(V2FromXY(-0.07f, -0.2f), 0.15f);
|
||||||
ent->local_collider.count = 2;
|
ent->local_collider.count = 2;
|
||||||
ent->local_collider.radius = 0.075f;
|
ent->local_collider.radius = 0.075f;
|
||||||
#elif 1
|
#elif 1
|
||||||
#if 0
|
#if 0
|
||||||
/* "Bad" winding order */
|
/* "Bad" winding order */
|
||||||
ent->local_collider.points[0] = V2(-0.15, 0.15);
|
ent->local_collider.points[0] = V2FromXY(-0.15, 0.15);
|
||||||
ent->local_collider.points[1] = V2(0.15, 0.15);
|
ent->local_collider.points[1] = V2FromXY(0.15, 0.15);
|
||||||
ent->local_collider.points[2] = V2(0, -0.15);
|
ent->local_collider.points[2] = V2FromXY(0, -0.15);
|
||||||
#else
|
#else
|
||||||
ent->local_collider.points[0] = V2(0, -0.15);
|
ent->local_collider.points[0] = V2FromXY(0, -0.15);
|
||||||
ent->local_collider.points[1] = V2(0.15, 0.15);
|
ent->local_collider.points[1] = V2FromXY(0.15, 0.15);
|
||||||
ent->local_collider.points[2] = V2(-0.15, 0.15);
|
ent->local_collider.points[2] = V2FromXY(-0.15, 0.15);
|
||||||
#endif
|
#endif
|
||||||
ent->local_collider.count = 3;
|
ent->local_collider.count = 3;
|
||||||
ent->local_collider.radius = 0.25;
|
ent->local_collider.radius = 0.25;
|
||||||
@ -1276,13 +1276,13 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
struct sprite_tag parent_sprite = parent->sprite;
|
struct sprite_tag parent_sprite = parent->sprite;
|
||||||
struct sprite_sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite);
|
struct sprite_sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite);
|
||||||
|
|
||||||
struct xform parent_sprite_xf = parent->sprite_local_xform;
|
Xform parent_sprite_xf = parent->sprite_local_xform;
|
||||||
|
|
||||||
struct sprite_sheet_slice attach_slice = sprite_sheet_get_slice(parent_sheet, ent->attach_slice, parent->animation_frame);
|
struct sprite_sheet_slice attach_slice = sprite_sheet_get_slice(parent_sheet, ent->attach_slice, parent->animation_frame);
|
||||||
struct v2 attach_pos = xform_mul_v2(parent_sprite_xf, attach_slice.center);
|
V2 attach_pos = xform_mul_v2(parent_sprite_xf, attach_slice.center);
|
||||||
struct v2 attach_dir = xform_basis_mul_v2(parent_sprite_xf, attach_slice.dir);
|
V2 attach_dir = xform_basis_mul_v2(parent_sprite_xf, attach_slice.dir);
|
||||||
|
|
||||||
struct xform xf = sim_ent_get_local_xform(ent);
|
Xform xf = sim_ent_get_local_xform(ent);
|
||||||
xf.og = attach_pos;
|
xf.og = attach_pos;
|
||||||
xf = xform_basis_with_rotation_world(xf, v2_angle(attach_dir) + PI / 2);
|
xf = xform_basis_with_rotation_world(xf, v2_angle(attach_dir) + PI / 2);
|
||||||
sim_ent_set_local_xform(ent, xf);
|
sim_ent_set_local_xform(ent, xf);
|
||||||
@ -1353,10 +1353,10 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
struct sprite_tag sprite = ent->sprite;
|
struct sprite_tag sprite = ent->sprite;
|
||||||
u32 animation_frame = ent->animation_frame;
|
u32 animation_frame = ent->animation_frame;
|
||||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
|
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
|
||||||
struct xform sprite_local_xform = ent->sprite_local_xform;
|
Xform sprite_local_xform = ent->sprite_local_xform;
|
||||||
struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
|
struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
|
||||||
struct v2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center);
|
V2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center);
|
||||||
struct v2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
|
V2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
|
||||||
|
|
||||||
/* Spawn bullet */
|
/* Spawn bullet */
|
||||||
struct sim_ent *bullet;
|
struct sim_ent *bullet;
|
||||||
@ -1374,7 +1374,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/* Point collider */
|
/* Point collider */
|
||||||
bullet->local_collider.points[0] = V2(0, 0);
|
bullet->local_collider.points[0] = V2FromXY(0, 0);
|
||||||
bullet->local_collider.count = 1;
|
bullet->local_collider.count = 1;
|
||||||
#else
|
#else
|
||||||
bullet->sprite = sprite_tag_from_path(LIT("sprite/bullet.ase"));
|
bullet->sprite = sprite_tag_from_path(LIT("sprite/bullet.ase"));
|
||||||
@ -1400,10 +1400,10 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
struct sprite_tag sprite = ent->sprite;
|
struct sprite_tag sprite = ent->sprite;
|
||||||
u32 animation_frame = ent->animation_frame;
|
u32 animation_frame = ent->animation_frame;
|
||||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
|
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite);
|
||||||
struct xform sprite_local_xform = ent->sprite_local_xform;
|
Xform sprite_local_xform = ent->sprite_local_xform;
|
||||||
struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
|
struct sprite_sheet_slice out_slice = sprite_sheet_get_slice(sheet, LIT("out"), animation_frame);
|
||||||
struct v2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center);
|
V2 rel_pos = xform_mul_v2(sprite_local_xform, out_slice.center);
|
||||||
struct v2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
|
V2 rel_dir = xform_basis_mul_v2(sprite_local_xform, out_slice.dir);
|
||||||
|
|
||||||
/* Spawn bullet */
|
/* Spawn bullet */
|
||||||
struct sim_ent *bullet;
|
struct sim_ent *bullet;
|
||||||
@ -1422,7 +1422,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
bullet->layer = SIM_LAYER_BULLETS;
|
bullet->layer = SIM_LAYER_BULLETS;
|
||||||
|
|
||||||
/* Point collider */
|
/* Point collider */
|
||||||
bullet->local_collider.points[0] = V2(0, 0);
|
bullet->local_collider.points[0] = V2FromXY(0, 0);
|
||||||
bullet->local_collider.count = 1;
|
bullet->local_collider.count = 1;
|
||||||
bullet->local_collider.radius = 0.05f;
|
bullet->local_collider.radius = 0.05f;
|
||||||
|
|
||||||
@ -1453,9 +1453,9 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
struct sim_ent *joint_ent = sim_ent_alloc_sync_src(root);
|
struct sim_ent *joint_ent = sim_ent_alloc_sync_src(root);
|
||||||
sim_ent_enable_prop(joint_ent, SEPROP_ACTIVE);
|
sim_ent_enable_prop(joint_ent, SEPROP_ACTIVE);
|
||||||
|
|
||||||
struct xform xf0 = sim_ent_get_xform(ent);
|
Xform xf0 = sim_ent_get_xform(ent);
|
||||||
struct xform xf1 = sim_ent_get_xform(target);
|
Xform xf1 = sim_ent_get_xform(target);
|
||||||
struct xform xf0_to_xf1 = xform_mul(xform_invert(xf0), xf1);
|
Xform xf0_to_xf1 = xform_mul(xform_invert(xf0), xf1);
|
||||||
|
|
||||||
sim_ent_enable_prop(joint_ent, SEPROP_WELD_JOINT);
|
sim_ent_enable_prop(joint_ent, SEPROP_WELD_JOINT);
|
||||||
struct phys_weld_joint_def def = phys_weld_joint_def_init();
|
struct phys_weld_joint_def def = phys_weld_joint_def_init();
|
||||||
@ -1524,8 +1524,8 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
if (!sim_ent_should_simulate(ent)) continue;
|
if (!sim_ent_should_simulate(ent)) continue;
|
||||||
|
|
||||||
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
if (sim_ent_has_prop(ent, SEPROP_CONTROLLED)) {
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
struct xform sprite_xf = xform_mul(xf, ent->sprite_local_xform);
|
Xform sprite_xf = xform_mul(xf, ent->sprite_local_xform);
|
||||||
|
|
||||||
/* Retrieve / create aim joint */
|
/* Retrieve / create aim joint */
|
||||||
struct sim_ent *joint_ent = sim_ent_from_id(world, ent->aim_joint);
|
struct sim_ent *joint_ent = sim_ent_from_id(world, ent->aim_joint);
|
||||||
@ -1555,11 +1555,11 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
/* Solve for final angle using law of sines */
|
/* Solve for final angle using law of sines */
|
||||||
f32 new_angle;
|
f32 new_angle;
|
||||||
{
|
{
|
||||||
struct v2 ent_pos = xf.og;
|
V2 ent_pos = xf.og;
|
||||||
struct v2 focus_pos = v2_add(ent_pos, ent->control.focus);
|
V2 focus_pos = v2_add(ent_pos, ent->control.focus);
|
||||||
|
|
||||||
struct v2 sprite_hold_pos;
|
V2 sprite_hold_pos;
|
||||||
struct v2 sprite_hold_dir;
|
V2 sprite_hold_dir;
|
||||||
{
|
{
|
||||||
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
|
||||||
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame);
|
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame);
|
||||||
@ -1567,23 +1567,23 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
sprite_hold_dir = slice.dir;
|
sprite_hold_dir = slice.dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 hold_dir = xform_basis_mul_v2(sprite_xf, sprite_hold_dir);
|
V2 hold_dir = xform_basis_mul_v2(sprite_xf, sprite_hold_dir);
|
||||||
struct v2 hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos);
|
V2 hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos);
|
||||||
if (v2_eq(hold_pos, ent_pos)) {
|
if (v2_eq(hold_pos, ent_pos)) {
|
||||||
/* If hold pos is same as origin (E.G if pivot is being used as hold pos), then move hold pos forward a tad to avoid issue */
|
/* If hold pos is same as origin (E.G if pivot is being used as hold pos), then move hold pos forward a tad to avoid issue */
|
||||||
sprite_hold_pos = v2_add(sprite_hold_pos, V2(0, -1));
|
sprite_hold_pos = v2_add(sprite_hold_pos, V2FromXY(0, -1));
|
||||||
hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos);
|
hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 forward_hold_angle_offset;
|
f32 forward_hold_angle_offset;
|
||||||
{
|
{
|
||||||
struct xform xf_unrotated = xform_basis_with_rotation_world(xf, 0);
|
Xform xf_unrotated = xform_basis_with_rotation_world(xf, 0);
|
||||||
struct v2 hold_pos_unrotated = xform_mul_v2(xf_unrotated, xform_mul_v2(ent->sprite_local_xform, sprite_hold_pos));
|
V2 hold_pos_unrotated = xform_mul_v2(xf_unrotated, xform_mul_v2(ent->sprite_local_xform, sprite_hold_pos));
|
||||||
forward_hold_angle_offset = v2_angle_from_dirs(V2(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og));
|
forward_hold_angle_offset = v2_angle_from_dirs(V2FromXY(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 hold_ent_dir = v2_sub(ent_pos, hold_pos);
|
V2 hold_ent_dir = v2_sub(ent_pos, hold_pos);
|
||||||
struct v2 focus_ent_dir = v2_sub(ent_pos, focus_pos);
|
V2 focus_ent_dir = v2_sub(ent_pos, focus_pos);
|
||||||
|
|
||||||
f32 hold_ent_len = v2_len(hold_ent_dir);
|
f32 hold_ent_len = v2_len(hold_ent_dir);
|
||||||
f32 focus_ent_len = v2_len(focus_ent_dir);
|
f32 focus_ent_len = v2_len(focus_ent_dir);
|
||||||
@ -1592,13 +1592,13 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
f32 final_focus_angle_btw_ent_and_hold = math_asin((math_sin(final_hold_angle_btw_ent_and_focus) * hold_ent_len) / focus_ent_len);
|
f32 final_focus_angle_btw_ent_and_hold = math_asin((math_sin(final_hold_angle_btw_ent_and_focus) * hold_ent_len) / focus_ent_len);
|
||||||
f32 final_ent_angle_btw_focus_and_hold = PI - (final_focus_angle_btw_ent_and_hold + final_hold_angle_btw_ent_and_focus);
|
f32 final_ent_angle_btw_focus_and_hold = PI - (final_focus_angle_btw_ent_and_hold + final_hold_angle_btw_ent_and_focus);
|
||||||
|
|
||||||
new_angle = math_unwind_angle(v2_angle_from_dirs(V2(0, -1), v2_sub(focus_pos, ent_pos)) + final_ent_angle_btw_focus_and_hold - forward_hold_angle_offset);
|
new_angle = math_unwind_angle(v2_angle_from_dirs(V2FromXY(0, -1), v2_sub(focus_pos, ent_pos)) + final_ent_angle_btw_focus_and_hold - forward_hold_angle_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 new_vel = 0;
|
f32 new_vel = 0;
|
||||||
if (!F32_IS_NAN(new_angle)) {
|
if (!F32_IS_NAN(new_angle)) {
|
||||||
const f32 angle_error_allowed = 0.001f;
|
const f32 angle_error_allowed = 0.001f;
|
||||||
struct xform joint_xf = sim_ent_get_xform(joint_ent);
|
Xform joint_xf = sim_ent_get_xform(joint_ent);
|
||||||
f32 diff = math_unwind_angle(new_angle - xform_get_rotation(joint_xf));
|
f32 diff = math_unwind_angle(new_angle - xform_get_rotation(joint_xf));
|
||||||
if (math_fabs(diff) > angle_error_allowed) {
|
if (math_fabs(diff) > angle_error_allowed) {
|
||||||
/* Instantly snap joint ent to new angle */
|
/* Instantly snap joint ent to new angle */
|
||||||
@ -1653,7 +1653,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
if (!sim_ent_should_simulate(player)) continue;
|
if (!sim_ent_should_simulate(player)) continue;
|
||||||
if (!sim_ent_has_prop(player, SEPROP_PLAYER)) continue;
|
if (!sim_ent_has_prop(player, SEPROP_PLAYER)) continue;
|
||||||
|
|
||||||
struct v2 cursor = player->player_cursor_pos;
|
V2 cursor = player->player_cursor_pos;
|
||||||
b32 start_dragging = player->player_dbg_drag_start;
|
b32 start_dragging = player->player_dbg_drag_start;
|
||||||
b32 stop_dragging = player->player_dbg_drag_stop;
|
b32 stop_dragging = player->player_dbg_drag_stop;
|
||||||
|
|
||||||
@ -1676,7 +1676,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
sim_ent_enable_prop(joint_ent, SEPROP_MOUSE_JOINT);
|
sim_ent_enable_prop(joint_ent, SEPROP_MOUSE_JOINT);
|
||||||
sim_ent_enable_prop(joint_ent, SEPROP_ACTIVE);
|
sim_ent_enable_prop(joint_ent, SEPROP_ACTIVE);
|
||||||
}
|
}
|
||||||
struct xform xf = sim_ent_get_xform(target_ent);
|
Xform xf = sim_ent_get_xform(target_ent);
|
||||||
|
|
||||||
struct phys_mouse_joint_def def = phys_mouse_joint_def_init();
|
struct phys_mouse_joint_def def = phys_mouse_joint_def_init();
|
||||||
def.target = target_ent->id;
|
def.target = target_ent->id;
|
||||||
@ -1731,11 +1731,11 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
if (!sim_ent_should_simulate(ent)) continue;
|
if (!sim_ent_should_simulate(ent)) continue;
|
||||||
if (!sim_ent_has_prop(ent, SEPROP_TRACER)) continue;
|
if (!sim_ent_has_prop(ent, SEPROP_TRACER)) continue;
|
||||||
|
|
||||||
struct v2 end = sim_ent_get_xform(ent).og;
|
V2 end = sim_ent_get_xform(ent).og;
|
||||||
|
|
||||||
struct v2 tick_velocity = v2_mul(ent->tracer_start_velocity, sim_dt);
|
V2 tick_velocity = v2_mul(ent->tracer_start_velocity, sim_dt);
|
||||||
struct v2 gradient_start = v2_add(ent->tracer_gradient_start, tick_velocity);
|
V2 gradient_start = v2_add(ent->tracer_gradient_start, tick_velocity);
|
||||||
struct v2 gradient_end = v2_add(ent->tracer_gradient_end, tick_velocity);
|
V2 gradient_end = v2_add(ent->tracer_gradient_end, tick_velocity);
|
||||||
|
|
||||||
if (v2_dot(tick_velocity, v2_sub(gradient_start, end)) > 0) {
|
if (v2_dot(tick_velocity, v2_sub(gradient_start, end)) > 0) {
|
||||||
/* Tracer has disappeared */
|
/* Tracer has disappeared */
|
||||||
@ -1757,14 +1757,14 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
|
|
||||||
if (ent->activation_tick == world->tick) {
|
if (ent->activation_tick == world->tick) {
|
||||||
struct sim_ent *src = sim_ent_from_id(world, ent->bullet_src);
|
struct sim_ent *src = sim_ent_from_id(world, ent->bullet_src);
|
||||||
struct xform src_xf = sim_ent_get_xform(src);
|
Xform src_xf = sim_ent_get_xform(src);
|
||||||
|
|
||||||
/* Activate collision */
|
/* Activate collision */
|
||||||
sim_ent_enable_prop(ent, SEPROP_SENSOR);
|
sim_ent_enable_prop(ent, SEPROP_SENSOR);
|
||||||
sim_ent_enable_prop(ent, SEPROP_TOI);
|
sim_ent_enable_prop(ent, SEPROP_TOI);
|
||||||
|
|
||||||
struct v2 pos = xform_mul_v2(src_xf, ent->bullet_src_pos);
|
V2 pos = xform_mul_v2(src_xf, ent->bullet_src_pos);
|
||||||
struct v2 vel = xform_basis_mul_v2(src_xf, ent->bullet_src_dir);
|
V2 vel = xform_basis_mul_v2(src_xf, ent->bullet_src_dir);
|
||||||
vel = v2_with_len(vel, ent->bullet_launch_velocity);
|
vel = v2_with_len(vel, ent->bullet_launch_velocity);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -1776,7 +1776,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = v2_angle(vel) + PI / 2);
|
Xform xf = XFORM_TRS(.t = pos, .r = v2_angle(vel) + PI / 2);
|
||||||
sim_ent_set_xform(ent, xf);
|
sim_ent_set_xform(ent, xf);
|
||||||
|
|
||||||
sim_ent_enable_prop(ent, SEPROP_KINEMATIC);
|
sim_ent_enable_prop(ent, SEPROP_KINEMATIC);
|
||||||
@ -1814,7 +1814,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
if (!sim_ent_should_simulate(ent)) continue;
|
if (!sim_ent_should_simulate(ent)) continue;
|
||||||
if (!sim_ent_has_prop(ent, SEPROP_CAMERA)) continue;
|
if (!sim_ent_has_prop(ent, SEPROP_CAMERA)) continue;
|
||||||
|
|
||||||
struct xform xf = sim_ent_get_xform(ent);
|
Xform xf = sim_ent_get_xform(ent);
|
||||||
|
|
||||||
/* Camera follow */
|
/* Camera follow */
|
||||||
{
|
{
|
||||||
@ -1822,16 +1822,16 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
|
|
||||||
f32 aspect_ratio = 1.0;
|
f32 aspect_ratio = 1.0;
|
||||||
{
|
{
|
||||||
struct xform quad_xf = xform_mul(sim_ent_get_xform(ent), ent->camera_quad_xform);
|
Xform quad_xf = xform_mul(sim_ent_get_xform(ent), ent->camera_quad_xform);
|
||||||
struct v2 camera_size = xform_get_scale(quad_xf);
|
V2 camera_size = xform_get_scale(quad_xf);
|
||||||
if (!v2_is_zero(camera_size)) {
|
if (!v2_is_zero(camera_size)) {
|
||||||
aspect_ratio = camera_size.x / camera_size.y;
|
aspect_ratio = camera_size.x / camera_size.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f32 ratio_y = 0.33f;
|
f32 ratio_y = 0.33f;
|
||||||
f32 ratio_x = ratio_y / aspect_ratio;
|
f32 ratio_x = ratio_y / aspect_ratio;
|
||||||
struct v2 camera_focus_dir = v2_mul_v2(follow->control.focus, V2(ratio_x, ratio_y));
|
V2 camera_focus_dir = v2_mul_v2(follow->control.focus, V2FromXY(ratio_x, ratio_y));
|
||||||
struct v2 camera_focus_pos = v2_add(sim_ent_get_xform(follow).og, camera_focus_dir);
|
V2 camera_focus_pos = v2_add(sim_ent_get_xform(follow).og, camera_focus_dir);
|
||||||
ent->camera_xform_target = xf;
|
ent->camera_xform_target = xf;
|
||||||
ent->camera_xform_target.og = camera_focus_pos;
|
ent->camera_xform_target.og = camera_focus_pos;
|
||||||
|
|
||||||
@ -1881,7 +1881,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
{
|
{
|
||||||
struct arena_temp temp = arena_temp_begin(scratch.arena);
|
TempArena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
struct sim_ent **stack = arena_push_no_zero(temp.arena, struct sim_ent *);
|
struct sim_ent **stack = arena_push_no_zero(temp.arena, struct sim_ent *);
|
||||||
u64 stack_count = 1;
|
u64 stack_count = 1;
|
||||||
|
|||||||
@ -24,7 +24,7 @@ void sim_accel_reset(struct sim_snapshot *ss, struct sim_accel *accel);
|
|||||||
struct sim_step_ctx {
|
struct sim_step_ctx {
|
||||||
b32 is_master;
|
b32 is_master;
|
||||||
struct sim_accel *accel;
|
struct sim_accel *accel;
|
||||||
struct rand_state rand; /* TODO: Replace with per-sim rand for deterministic rng */
|
RandState rand; /* TODO: Replace with per-sim rand for deterministic rng */
|
||||||
|
|
||||||
struct sim_snapshot *world; /* The world to simulate */
|
struct sim_snapshot *world; /* The world to simulate */
|
||||||
i64 sim_dt_ns; /* How much sim time should progress */
|
i64 sim_dt_ns; /* How much sim time should progress */
|
||||||
|
|||||||
@ -4,14 +4,14 @@ struct sound_task_params {
|
|||||||
struct sound_task_params *next_free;
|
struct sound_task_params *next_free;
|
||||||
|
|
||||||
u32 flags;
|
u32 flags;
|
||||||
struct asset *asset;
|
AC_Asset *asset;
|
||||||
u64 path_len;
|
u64 path_len;
|
||||||
char path_cstr[1024];
|
char path_cstr[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sound_task_params_store {
|
struct sound_task_params_store {
|
||||||
struct sound_task_params *head_free;
|
struct sound_task_params *head_free;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct snc_mutex mutex;
|
struct snc_mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ GLOBAL struct {
|
|||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sound_startup_receipt sound_startup(struct asset_cache_startup_receipt *asset_cache_sr)
|
struct sound_startup_receipt sound_startup(AC_StartupReceipt *asset_cache_sr)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
(UNUSED)asset_cache_sr;
|
(UNUSED)asset_cache_sr;
|
||||||
@ -71,22 +71,22 @@ INTERNAL SYS_JOB_DEF(sound_load_asset_job, job)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct sound_task_params *params = job.sig;
|
struct sound_task_params *params = job.sig;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct string path = STRING(params->path_len, (u8 *)params->path_cstr);
|
String path = STRING(params->path_len, (u8 *)params->path_cstr);
|
||||||
struct asset *asset = params->asset;
|
AC_Asset *asset = params->asset;
|
||||||
u32 flags = params->flags;
|
u32 flags = params->flags;
|
||||||
|
|
||||||
logf_info("Loading sound \"%F\"", FMT_STR(path));
|
logf_info("Loading sound \"%F\"", FMT_STR(path));
|
||||||
i64 start_ns = sys_time_ns();
|
i64 start_ns = sys_time_ns();
|
||||||
|
|
||||||
struct string error_msg = LIT("Unknown error");
|
String error_msg = LIT("Unknown error");
|
||||||
|
|
||||||
ASSERT(string_ends_with(path, LIT(".mp3")));
|
ASSERT(string_ends_with(path, LIT(".mp3")));
|
||||||
|
|
||||||
/* Decode */
|
/* Decode */
|
||||||
struct mp3_decode_result decoded = ZI;
|
MP3_Result decoded = ZI;
|
||||||
{
|
{
|
||||||
struct resource sound_rs = resource_open(path);
|
R_Resource sound_rs = resource_open(path);
|
||||||
if (resource_exists(&sound_rs)) {
|
if (resource_exists(&sound_rs)) {
|
||||||
u64 decode_flags = 0;
|
u64 decode_flags = 0;
|
||||||
if (flags & SOUND_FLAG_STEREO) {
|
if (flags & SOUND_FLAG_STEREO) {
|
||||||
@ -107,7 +107,7 @@ INTERNAL SYS_JOB_DEF(sound_load_asset_job, job)
|
|||||||
struct sound *sound = 0;
|
struct sound *sound = 0;
|
||||||
i16 *samples = 0;
|
i16 *samples = 0;
|
||||||
{
|
{
|
||||||
struct asset_cache_store store = asset_cache_store_open();
|
AC_Store store = asset_cache_store_open();
|
||||||
sound = arena_push_no_zero(store.arena, struct sound);
|
sound = arena_push_no_zero(store.arena, struct sound);
|
||||||
samples = arena_push_array_no_zero(store.arena, i16, decoded.pcm.count);
|
samples = arena_push_array_no_zero(store.arena, i16, decoded.pcm.count);
|
||||||
asset_cache_store_close(&store);
|
asset_cache_store_close(&store);
|
||||||
@ -128,7 +128,7 @@ INTERNAL SYS_JOB_DEF(sound_load_asset_job, job)
|
|||||||
/* Store */
|
/* Store */
|
||||||
struct sound *sound = 0;
|
struct sound *sound = 0;
|
||||||
{
|
{
|
||||||
struct asset_cache_store store = asset_cache_store_open();
|
AC_Store store = asset_cache_store_open();
|
||||||
sound = arena_push_no_zero(store.arena, struct sound);
|
sound = arena_push_no_zero(store.arena, struct sound);
|
||||||
asset_cache_store_close(&store);
|
asset_cache_store_close(&store);
|
||||||
}
|
}
|
||||||
@ -141,19 +141,19 @@ INTERNAL SYS_JOB_DEF(sound_load_asset_job, job)
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct asset *sound_load_asset(struct string path, u32 flags, b32 wait)
|
AC_Asset *sound_load_asset(String path, u32 flags, b32 wait)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
/* Generate and append sound flags to path key */
|
/* Generate and append sound flags to path key */
|
||||||
struct string key = string_format(scratch.arena,
|
String key = string_format(scratch.arena,
|
||||||
LIT("%F%F_sound"),
|
LIT("%F%F_sound"),
|
||||||
FMT_STR(path),
|
FMT_STR(path),
|
||||||
FMT_UINT((u64)flags));
|
FMT_UINT((u64)flags));
|
||||||
u64 hash = asset_cache_hash(key);
|
u64 hash = asset_cache_hash(key);
|
||||||
b32 is_first_touch;
|
b32 is_first_touch;
|
||||||
struct asset *asset = asset_cache_touch(key, hash, &is_first_touch);
|
AC_Asset *asset = asset_cache_touch(key, hash, &is_first_touch);
|
||||||
|
|
||||||
if (is_first_touch) {
|
if (is_first_touch) {
|
||||||
/* Assemble task params */
|
/* Assemble task params */
|
||||||
@ -180,19 +180,19 @@ struct asset *sound_load_asset(struct string path, u32 flags, b32 wait)
|
|||||||
return asset;
|
return asset;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sound *sound_load_async(struct string path, u32 flags)
|
struct sound *sound_load_async(String path, u32 flags)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct asset *asset = sound_load_asset(path, flags, 0);
|
AC_Asset *asset = sound_load_asset(path, flags, 0);
|
||||||
struct sound *sound = (struct sound *)asset_cache_get_store_data(asset);
|
struct sound *sound = (struct sound *)asset_cache_get_store_data(asset);
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct sound *sound_load(struct string path, u32 flags)
|
struct sound *sound_load(String path, u32 flags)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct asset *asset = sound_load_asset(path, flags, 1);
|
AC_Asset *asset = sound_load_asset(path, flags, 1);
|
||||||
asset_cache_wait(asset);
|
asset_cache_wait(asset);
|
||||||
struct sound *sound = (struct sound *)asset_cache_get_store_data(asset);
|
struct sound *sound = (struct sound *)asset_cache_get_store_data(asset);
|
||||||
return sound;
|
return sound;
|
||||||
|
|||||||
@ -1,17 +1,14 @@
|
|||||||
#define SOUND_FLAG_NONE 0x0
|
#define SOUND_FLAG_NONE 0x0
|
||||||
#define SOUND_FLAG_STEREO 0x1
|
#define SOUND_FLAG_STEREO 0x1
|
||||||
|
|
||||||
struct asset;
|
|
||||||
struct asset_cache_startup_receipt;
|
|
||||||
|
|
||||||
struct sound {
|
struct sound {
|
||||||
u32 flags;
|
u32 flags;
|
||||||
struct pcm pcm;
|
PcmData pcm;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sound_startup_receipt { i32 _; };
|
struct sound_startup_receipt { i32 _; };
|
||||||
struct sound_startup_receipt sound_startup(struct asset_cache_startup_receipt *asset_cache_sr);
|
struct sound_startup_receipt sound_startup(AC_StartupReceipt *asset_cache_sr);
|
||||||
|
|
||||||
struct asset *sound_load_asset(struct string path, u32 flags, b32 wait);
|
AC_Asset *sound_load_asset(String path, u32 flags, b32 wait);
|
||||||
struct sound *sound_load_async(struct string path, u32 flags);
|
struct sound *sound_load_async(String path, u32 flags);
|
||||||
struct sound *sound_load(struct string path, u32 flags);
|
struct sound *sound_load(String path, u32 flags);
|
||||||
|
|||||||
@ -52,14 +52,14 @@ struct cache_entry_hash {
|
|||||||
struct cache_entry {
|
struct cache_entry {
|
||||||
enum cache_entry_kind kind;
|
enum cache_entry_kind kind;
|
||||||
struct cache_entry_hash hash;
|
struct cache_entry_hash hash;
|
||||||
struct atomic32 state;
|
Atomic32 state;
|
||||||
struct atomic64_padded refcount_struct; /* Cast fetched result to `cache_refcount` */
|
Atomic64Padded refcount_struct; /* Cast fetched result to `cache_refcount` */
|
||||||
|
|
||||||
/* Allocated data */
|
/* Allocated data */
|
||||||
/* NOTE: This data is finalized once entry state = loaded */
|
/* NOTE: This data is finalized once entry state = loaded */
|
||||||
i64 load_time_ns;
|
i64 load_time_ns;
|
||||||
u64 memory_usage;
|
u64 memory_usage;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct sprite_texture *texture;
|
struct sprite_texture *texture;
|
||||||
struct sprite_sheet *sheet;
|
struct sprite_sheet *sheet;
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ struct cache_entry {
|
|||||||
struct cache_entry *next_free;
|
struct cache_entry *next_free;
|
||||||
|
|
||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
struct atomic32 out_of_date; /* Has the resource changed since this entry was loaded */
|
Atomic32 out_of_date; /* Has the resource changed since this entry was loaded */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -82,8 +82,8 @@ struct cache_bin {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cache {
|
struct cache {
|
||||||
struct atomic64_padded memory_usage;
|
Atomic64Padded memory_usage;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
struct cache_bin *bins;
|
struct cache_bin *bins;
|
||||||
struct snc_mutex entry_pool_mutex;
|
struct snc_mutex entry_pool_mutex;
|
||||||
struct cache_entry *entry_pool_first_free;
|
struct cache_entry *entry_pool_first_free;
|
||||||
@ -117,7 +117,7 @@ struct load_cmd {
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct arena *perm_arena;
|
Arena *perm_arena;
|
||||||
struct sprite_texture *nil_texture;
|
struct sprite_texture *nil_texture;
|
||||||
struct sprite_texture *loading_texture;
|
struct sprite_texture *loading_texture;
|
||||||
struct sprite_sheet *nil_sheet;
|
struct sprite_sheet *nil_sheet;
|
||||||
@ -128,16 +128,16 @@ GLOBAL struct {
|
|||||||
|
|
||||||
/* Load cmds */
|
/* Load cmds */
|
||||||
struct snc_mutex load_cmds_mutex;
|
struct snc_mutex load_cmds_mutex;
|
||||||
struct arena *load_cmds_arena;
|
Arena *load_cmds_arena;
|
||||||
struct load_cmd *first_free_load_cmd;
|
struct load_cmd *first_free_load_cmd;
|
||||||
|
|
||||||
/* Scopes */
|
/* Scopes */
|
||||||
struct snc_mutex scopes_mutex;
|
struct snc_mutex scopes_mutex;
|
||||||
struct arena *scopes_arena;
|
Arena *scopes_arena;
|
||||||
struct sprite_scope *first_free_scope;
|
struct sprite_scope *first_free_scope;
|
||||||
|
|
||||||
/* Evictor */
|
/* Evictor */
|
||||||
struct atomic32_padded evictor_cycle;
|
Atomic32Padded evictor_cycle;
|
||||||
struct snc_counter shutdown_counter;
|
struct snc_counter shutdown_counter;
|
||||||
b32 evictor_scheduler_shutdown;
|
b32 evictor_scheduler_shutdown;
|
||||||
struct snc_mutex evictor_scheduler_mutex;
|
struct snc_mutex evictor_scheduler_mutex;
|
||||||
@ -148,7 +148,7 @@ GLOBAL struct {
|
|||||||
* Purple-black image
|
* Purple-black image
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct image_rgba generate_purple_black_image(struct arena *arena, u32 width, u32 height)
|
INTERNAL ImageDataRgba generate_purple_black_image(Arena *arena, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
u32 *pixels = arena_push_array_no_zero(arena, u32, width * height);
|
u32 *pixels = arena_push_array_no_zero(arena, u32, width * height);
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ INTERNAL struct image_rgba generate_purple_black_image(struct arena *arena, u32
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (struct image_rgba) {
|
return (ImageDataRgba) {
|
||||||
.width = width,
|
.width = width,
|
||||||
.height = height,
|
.height = height,
|
||||||
.pixels = pixels
|
.pixels = pixels
|
||||||
@ -206,21 +206,21 @@ struct sprite_startup_receipt sprite_startup(void)
|
|||||||
G.nil_texture = arena_push(G.perm_arena, struct sprite_texture);
|
G.nil_texture = arena_push(G.perm_arena, struct sprite_texture);
|
||||||
G.nil_texture->loaded = 1;
|
G.nil_texture->loaded = 1;
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct image_rgba purple_black_image = generate_purple_black_image(scratch.arena, 64, 64);
|
ImageDataRgba purple_black_image = generate_purple_black_image(scratch.arena, 64, 64);
|
||||||
G.nil_texture->gp_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2I32(purple_black_image.width, purple_black_image.height), purple_black_image.pixels);
|
G.nil_texture->gp_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM, 0, V2i32FromXY(purple_black_image.width, purple_black_image.height), purple_black_image.pixels);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init loading sheet */
|
/* Init loading sheet */
|
||||||
G.loading_sheet = arena_push(G.perm_arena, struct sprite_sheet);
|
G.loading_sheet = arena_push(G.perm_arena, struct sprite_sheet);
|
||||||
G.loading_sheet->image_size = V2(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
G.loading_sheet->image_size = V2FromXY(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
||||||
G.loading_sheet->frame_size = V2(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
G.loading_sheet->frame_size = V2FromXY(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
||||||
|
|
||||||
/* Init nil sheet */
|
/* Init nil sheet */
|
||||||
G.nil_sheet = arena_push(G.perm_arena, struct sprite_sheet);
|
G.nil_sheet = arena_push(G.perm_arena, struct sprite_sheet);
|
||||||
G.nil_sheet->image_size = V2(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
G.nil_sheet->image_size = V2FromXY(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
||||||
G.nil_sheet->frame_size = V2(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
G.nil_sheet->frame_size = V2FromXY(PIXELS_PER_UNIT, PIXELS_PER_UNIT);
|
||||||
G.nil_sheet->loaded = 1;
|
G.nil_sheet->loaded = 1;
|
||||||
}
|
}
|
||||||
arena_set_readonly(G.perm_arena);
|
arena_set_readonly(G.perm_arena);
|
||||||
@ -258,7 +258,7 @@ INTERNAL SYS_EXIT_FUNC(sprite_shutdown)
|
|||||||
* Tag
|
* Tag
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sprite_tag sprite_tag_from_path(struct string path)
|
struct sprite_tag sprite_tag_from_path(String path)
|
||||||
{
|
{
|
||||||
struct sprite_tag res = ZI;
|
struct sprite_tag res = ZI;
|
||||||
res.hash = hash_fnv64(HASH_FNV64_BASIS, path);
|
res.hash = hash_fnv64(HASH_FNV64_BASIS, path);
|
||||||
@ -318,11 +318,11 @@ INTERNAL void push_load_job(struct cache_ref ref, struct sprite_tag tag)
|
|||||||
INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag tag)
|
INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag tag)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct cache_entry *e = ref.e;
|
struct cache_entry *e = ref.e;
|
||||||
|
|
||||||
atomic32_fetch_set(&e->state, CACHE_ENTRY_STATE_WORKING);
|
atomic32_fetch_set(&e->state, CACHE_ENTRY_STATE_WORKING);
|
||||||
struct string path = tag.path;
|
String path = tag.path;
|
||||||
|
|
||||||
logf_info("Loading sprite texture [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
logf_info("Loading sprite texture [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||||
b32 success = 0;
|
b32 success = 0;
|
||||||
@ -337,9 +337,9 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
|||||||
u64 memory_size = 0;
|
u64 memory_size = 0;
|
||||||
{
|
{
|
||||||
/* Decode */
|
/* Decode */
|
||||||
struct ase_decode_image_result decoded = ZI;
|
Ase_DecodedImage decoded = ZI;
|
||||||
{
|
{
|
||||||
struct resource texture_rs = resource_open(path);
|
R_Resource texture_rs = resource_open(path);
|
||||||
if (resource_exists(&texture_rs)) {
|
if (resource_exists(&texture_rs)) {
|
||||||
decoded = ase_decode_image(scratch.arena, resource_get_data(&texture_rs));
|
decoded = ase_decode_image(scratch.arena, resource_get_data(&texture_rs));
|
||||||
} else {
|
} else {
|
||||||
@ -355,7 +355,7 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
|||||||
e->texture->height = decoded.image.height;
|
e->texture->height = decoded.image.height;
|
||||||
e->texture->valid = 1;
|
e->texture->valid = 1;
|
||||||
e->texture->loaded = 1;
|
e->texture->loaded = 1;
|
||||||
e->texture->gp_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB, 0, V2I32(decoded.image.width, decoded.image.height), decoded.image.pixels);
|
e->texture->gp_texture = gp_texture_alloc(GP_TEXTURE_FORMAT_R8G8B8A8_UNORM_SRGB, 0, V2i32FromXY(decoded.image.width, decoded.image.height), decoded.image.pixels);
|
||||||
/* TODO: Query gpu for more accurate texture size in VRAM */
|
/* TODO: Query gpu for more accurate texture size in VRAM */
|
||||||
memory_size += (decoded.image.width * decoded.image.height) * sizeof(*decoded.image.pixels);
|
memory_size += (decoded.image.width * decoded.image.height) * sizeof(*decoded.image.pixels);
|
||||||
success = 1;
|
success = 1;
|
||||||
@ -392,15 +392,15 @@ INTERNAL void cache_entry_load_texture(struct cache_ref ref, struct sprite_tag t
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, struct ase_decode_sheet_result ase)
|
INTERNAL struct sprite_sheet init_sheet_from_ase_result(Arena *arena, Ase_DecodedSheet ase)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct sprite_sheet sheet = ZI;
|
struct sprite_sheet sheet = ZI;
|
||||||
|
|
||||||
ASSERT(ase.num_frames >= 1);
|
ASSERT(ase.num_frames >= 1);
|
||||||
|
|
||||||
struct v2 frame_size = ase.frame_size;
|
V2 frame_size = ase.frame_size;
|
||||||
struct v2 frame_center = v2_mul(ase.frame_size, 0.5f);
|
V2 frame_center = v2_mul(ase.frame_size, 0.5f);
|
||||||
|
|
||||||
/* Init frames */
|
/* Init frames */
|
||||||
{
|
{
|
||||||
@ -409,16 +409,16 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
sheet.frame_size = ase.frame_size;
|
sheet.frame_size = ase.frame_size;
|
||||||
sheet.frames = arena_push_array(arena, struct sprite_sheet_frame, ase.num_frames);
|
sheet.frames = arena_push_array(arena, struct sprite_sheet_frame, ase.num_frames);
|
||||||
sheet.frames_count = ase.num_frames;
|
sheet.frames_count = ase.num_frames;
|
||||||
for (struct ase_frame *ase_frame = ase.frame_head; ase_frame; ase_frame = ase_frame->next) {
|
for (Ase_Frame *ase_frame = ase.frame_head; ase_frame; ase_frame = ase_frame->next) {
|
||||||
u32 index = ase_frame->index;
|
u32 index = ase_frame->index;
|
||||||
|
|
||||||
struct v2 clip_p1 = { (f32)ase_frame->x1 / (f32)ase.image_size.x, (f32)ase_frame->y1 / (f32)ase.image_size.y };
|
V2 clip_p1 = { (f32)ase_frame->x1 / (f32)ase.image_size.x, (f32)ase_frame->y1 / (f32)ase.image_size.y };
|
||||||
struct v2 clip_p2 = { (f32)ase_frame->x2 / (f32)ase.image_size.x, (f32)ase_frame->y2 / (f32)ase.image_size.y };
|
V2 clip_p2 = { (f32)ase_frame->x2 / (f32)ase.image_size.x, (f32)ase_frame->y2 / (f32)ase.image_size.y };
|
||||||
|
|
||||||
sheet.frames[index] = (struct sprite_sheet_frame) {
|
sheet.frames[index] = (struct sprite_sheet_frame) {
|
||||||
.index = index,
|
.index = index,
|
||||||
.duration = ase_frame->duration,
|
.duration = ase_frame->duration,
|
||||||
.clip = (struct clip_rect) { clip_p1, clip_p2 }
|
.clip = (ClipRect) { clip_p1, clip_p2 }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -430,8 +430,8 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
sheet.spans = arena_push_array(arena, struct sprite_sheet_span, sheet.spans_count);
|
sheet.spans = arena_push_array(arena, struct sprite_sheet_span, sheet.spans_count);
|
||||||
sheet.spans_dict = dict_init(arena, (u64)(ase.num_spans * SHEET_SPAN_LOOKUP_TABLE_BIN_RATIO));
|
sheet.spans_dict = dict_init(arena, (u64)(ase.num_spans * SHEET_SPAN_LOOKUP_TABLE_BIN_RATIO));
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
for (struct ase_span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) {
|
for (Ase_Span *ase_span = ase.span_head; ase_span; ase_span = ase_span->next) {
|
||||||
struct string name = string_copy(arena, ase_span->name);
|
String name = string_copy(arena, ase_span->name);
|
||||||
struct sprite_sheet_span *span = &sheet.spans[index];
|
struct sprite_sheet_span *span = &sheet.spans[index];
|
||||||
span->name = name;
|
span->name = name;
|
||||||
span->start = ase_span->start;
|
span->start = ase_span->start;
|
||||||
@ -445,10 +445,10 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
/* Init slices */
|
/* Init slices */
|
||||||
if (ase.num_slice_keys > 0) {
|
if (ase.num_slice_keys > 0) {
|
||||||
__profn("Init slices");
|
__profn("Init slices");
|
||||||
struct arena_temp scratch = scratch_begin(arena);
|
TempArena scratch = scratch_begin(arena);
|
||||||
|
|
||||||
struct temp_ase_slice_key_node {
|
struct temp_ase_slice_key_node {
|
||||||
struct ase_slice_key *key;
|
Ase_SliceKey *key;
|
||||||
struct temp_ase_slice_key_node *next;
|
struct temp_ase_slice_key_node *next;
|
||||||
|
|
||||||
u32 index_in_frame;
|
u32 index_in_frame;
|
||||||
@ -456,7 +456,7 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct temp_slice_group_node {
|
struct temp_slice_group_node {
|
||||||
struct string name;
|
String name;
|
||||||
u64 per_frame_count;
|
u64 per_frame_count;
|
||||||
struct temp_ase_slice_key_node *temp_ase_slice_key_head;
|
struct temp_ase_slice_key_node *temp_ase_slice_key_head;
|
||||||
struct temp_slice_group_node *next;
|
struct temp_slice_group_node *next;
|
||||||
@ -468,9 +468,9 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
u64 num_temp_slice_group_nodes = 0;
|
u64 num_temp_slice_group_nodes = 0;
|
||||||
struct temp_slice_group_node *temp_slice_group_head = 0;
|
struct temp_slice_group_node *temp_slice_group_head = 0;
|
||||||
{
|
{
|
||||||
struct dict *temp_slice_dict = dict_init(scratch.arena, (u64)(ase.num_slice_keys * 2));
|
Dict *temp_slice_dict = dict_init(scratch.arena, (u64)(ase.num_slice_keys * 2));
|
||||||
for (struct ase_slice_key *ase_slice_key = ase.slice_key_head; ase_slice_key; ase_slice_key = ase_slice_key->next) {
|
for (Ase_SliceKey *ase_slice_key = ase.slice_key_head; ase_slice_key; ase_slice_key = ase_slice_key->next) {
|
||||||
struct string name = ase_slice_key->name;
|
String name = ase_slice_key->name;
|
||||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||||
struct temp_slice_group_node *temp_slice_group_node = (struct temp_slice_group_node *)dict_get(temp_slice_dict, hash);
|
struct temp_slice_group_node *temp_slice_group_node = (struct temp_slice_group_node *)dict_get(temp_slice_dict, hash);
|
||||||
if (!temp_slice_group_node) {
|
if (!temp_slice_group_node) {
|
||||||
@ -509,9 +509,9 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
|
|
||||||
u64 index_in_frame = 0;
|
u64 index_in_frame = 0;
|
||||||
for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) {
|
for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) {
|
||||||
struct ase_slice_key *key = node->key;
|
Ase_SliceKey *key = node->key;
|
||||||
|
|
||||||
for (struct ase_slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) {
|
for (Ase_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) {
|
||||||
u32 start = ase_slice->start;
|
u32 start = ase_slice->start;
|
||||||
|
|
||||||
struct sprite_sheet_slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame];
|
struct sprite_sheet_slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame];
|
||||||
@ -532,14 +532,14 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
f32 height = y2 - y1;
|
f32 height = y2 - y1;
|
||||||
|
|
||||||
/* Rect */
|
/* Rect */
|
||||||
struct rect rect_px = RECT(x1_px, y1_px, width_px, height_px);
|
Rect rect_px = RECT(x1_px, y1_px, width_px, height_px);
|
||||||
struct rect rect = RECT(x1, y1, width, height);
|
Rect rect = RECT(x1, y1, width, height);
|
||||||
/* Center */
|
/* Center */
|
||||||
struct v2 center_px = V2(x1_px + (width_px * 0.5f), y1_px + (height_px * 0.5f));
|
V2 center_px = V2FromXY(x1_px + (width_px * 0.5f), y1_px + (height_px * 0.5f));
|
||||||
struct v2 center = V2(x1 + (width * 0.5f), y1 + (height * 0.5f));
|
V2 center = V2FromXY(x1 + (width * 0.5f), y1 + (height * 0.5f));
|
||||||
/* Dir */
|
/* Dir */
|
||||||
struct v2 dir_px = V2(center_px.x, -1);
|
V2 dir_px = V2FromXY(center_px.x, -1);
|
||||||
struct v2 dir = V2(0, -1);
|
V2 dir = V2FromXY(0, -1);
|
||||||
|
|
||||||
slice->rect_px = rect_px;
|
slice->rect_px = rect_px;
|
||||||
slice->center_px = center_px;
|
slice->center_px = center_px;
|
||||||
@ -569,9 +569,9 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
struct sprite_sheet_slice_group *slice_group = temp_slice_group_node->final_slice_group;
|
struct sprite_sheet_slice_group *slice_group = temp_slice_group_node->final_slice_group;
|
||||||
|
|
||||||
for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) {
|
for (struct temp_ase_slice_key_node *node = temp_slice_group_node->temp_ase_slice_key_head; node; node = node->next) {
|
||||||
struct ase_slice_key *key = node->key;
|
Ase_SliceKey *key = node->key;
|
||||||
u32 index_in_frame = node->index_in_frame;
|
u32 index_in_frame = node->index_in_frame;
|
||||||
for (struct ase_slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) {
|
for (Ase_Slice *ase_slice = key->slice_head; ase_slice; ase_slice = ase_slice->next) {
|
||||||
u32 start = ase_slice->start;
|
u32 start = ase_slice->start;
|
||||||
|
|
||||||
struct sprite_sheet_slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame];
|
struct sprite_sheet_slice *slice = &slice_group->frame_slices[(start * slice_group->per_frame_count) + index_in_frame];
|
||||||
@ -601,12 +601,12 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
|
|
||||||
/* Calculate direction vectors */
|
/* Calculate direction vectors */
|
||||||
for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) {
|
for (struct temp_slice_group_node *temp_slice_group_node = temp_slice_group_head; temp_slice_group_node; temp_slice_group_node = temp_slice_group_node->next) {
|
||||||
struct string ray_suffix = LIT(".ray");
|
String ray_suffix = LIT(".ray");
|
||||||
|
|
||||||
struct sprite_sheet_slice_group *ray_slice_group = temp_slice_group_node->final_slice_group;
|
struct sprite_sheet_slice_group *ray_slice_group = temp_slice_group_node->final_slice_group;
|
||||||
struct string ray_slice_name = ray_slice_group->name;
|
String ray_slice_name = ray_slice_group->name;
|
||||||
if (string_ends_with(ray_slice_name, ray_suffix)) {
|
if (string_ends_with(ray_slice_name, ray_suffix)) {
|
||||||
struct string point_slice_name = ray_slice_name;
|
String point_slice_name = ray_slice_name;
|
||||||
point_slice_name.len -= ray_suffix.len;
|
point_slice_name.len -= ray_suffix.len;
|
||||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, point_slice_name);
|
u64 hash = hash_fnv64(HASH_FNV64_BASIS, point_slice_name);
|
||||||
struct sprite_sheet_slice_group *point_slice_group = (struct sprite_sheet_slice_group *)dict_get(sheet.slice_groups_dict, hash);
|
struct sprite_sheet_slice_group *point_slice_group = (struct sprite_sheet_slice_group *)dict_get(sheet.slice_groups_dict, hash);
|
||||||
@ -616,8 +616,8 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
for (u32 i = 0; i < ase.num_frames; ++i) {
|
for (u32 i = 0; i < ase.num_frames; ++i) {
|
||||||
/* Use ray slice in ray group */
|
/* Use ray slice in ray group */
|
||||||
struct sprite_sheet_slice *ray_slice = &ray_slice_group->frame_slices[i * point_slices_per_frame];
|
struct sprite_sheet_slice *ray_slice = &ray_slice_group->frame_slices[i * point_slices_per_frame];
|
||||||
struct v2 ray_end = ray_slice->center_px;
|
V2 ray_end = ray_slice->center_px;
|
||||||
struct v2 ray_end_norm = ray_slice->center;
|
V2 ray_end_norm = ray_slice->center;
|
||||||
|
|
||||||
/* Apply to each point slice in point group */
|
/* Apply to each point slice in point group */
|
||||||
for (u32 j = 0; j < point_slices_per_frame; ++j) {
|
for (u32 j = 0; j < point_slices_per_frame; ++j) {
|
||||||
@ -641,11 +641,11 @@ INTERNAL struct sprite_sheet init_sheet_from_ase_result(struct arena *arena, str
|
|||||||
INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag)
|
INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct cache_entry *e = ref.e;
|
struct cache_entry *e = ref.e;
|
||||||
|
|
||||||
atomic32_fetch_set(&e->state, CACHE_ENTRY_STATE_WORKING);
|
atomic32_fetch_set(&e->state, CACHE_ENTRY_STATE_WORKING);
|
||||||
struct string path = tag.path;
|
String path = tag.path;
|
||||||
|
|
||||||
logf_info("Loading sprite sheet [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
logf_info("Loading sprite sheet [%F] \"%F\"", FMT_HEX(e->hash.v), FMT_STR(path));
|
||||||
b32 success = 0;
|
b32 success = 0;
|
||||||
@ -657,9 +657,9 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
|||||||
e->arena = arena_alloc(SHEET_ARENA_RESERVE);
|
e->arena = arena_alloc(SHEET_ARENA_RESERVE);
|
||||||
{
|
{
|
||||||
/* Decode */
|
/* Decode */
|
||||||
struct ase_decode_sheet_result decoded = ZI;
|
Ase_DecodedSheet decoded = ZI;
|
||||||
{
|
{
|
||||||
struct resource sheet_rs = resource_open(path);
|
R_Resource sheet_rs = resource_open(path);
|
||||||
if (resource_exists(&sheet_rs)) {
|
if (resource_exists(&sheet_rs)) {
|
||||||
decoded = ase_decode_sheet(scratch.arena, resource_get_data(&sheet_rs));
|
decoded = ase_decode_sheet(scratch.arena, resource_get_data(&sheet_rs));
|
||||||
} else {
|
} else {
|
||||||
@ -669,7 +669,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (decoded.success) {
|
if (decoded.success) {
|
||||||
struct resource sheet_rs = resource_open(path);
|
R_Resource sheet_rs = resource_open(path);
|
||||||
decoded = ase_decode_sheet(scratch.arena, resource_get_data(&sheet_rs));
|
decoded = ase_decode_sheet(scratch.arena, resource_get_data(&sheet_rs));
|
||||||
resource_close(&sheet_rs);
|
resource_close(&sheet_rs);
|
||||||
|
|
||||||
@ -720,7 +720,7 @@ INTERNAL void cache_entry_load_sheet(struct cache_ref ref, struct sprite_tag tag
|
|||||||
INTERNAL void refcount_add(struct cache_entry *e, i32 amount)
|
INTERNAL void refcount_add(struct cache_entry *e, i32 amount)
|
||||||
{
|
{
|
||||||
i32 evictor_cycle = atomic32_fetch(&G.evictor_cycle.v);
|
i32 evictor_cycle = atomic32_fetch(&G.evictor_cycle.v);
|
||||||
struct atomic64 *refcount_atomic = &e->refcount_struct.v;
|
Atomic64 *refcount_atomic = &e->refcount_struct.v;
|
||||||
u64 old_refcount_uncast = atomic64_fetch(refcount_atomic);
|
u64 old_refcount_uncast = atomic64_fetch(refcount_atomic);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct cache_refcount new_refcount = *(struct cache_refcount *)&old_refcount_uncast;
|
struct cache_refcount new_refcount = *(struct cache_refcount *)&old_refcount_uncast;
|
||||||
@ -1053,7 +1053,7 @@ struct sprite_sheet_frame sprite_sheet_get_frame(struct sprite_sheet *sheet, u32
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sprite_sheet_span sprite_sheet_get_span(struct sprite_sheet *sheet, struct string name)
|
struct sprite_sheet_span sprite_sheet_get_span(struct sprite_sheet *sheet, String name)
|
||||||
{
|
{
|
||||||
struct sprite_sheet_span res = ZI;
|
struct sprite_sheet_span res = ZI;
|
||||||
if (sheet->spans_count > 0) {
|
if (sheet->spans_count > 0) {
|
||||||
@ -1066,7 +1066,7 @@ struct sprite_sheet_span sprite_sheet_get_span(struct sprite_sheet *sheet, struc
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, struct string name, u32 frame_index)
|
struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, String name, u32 frame_index)
|
||||||
{
|
{
|
||||||
if (sheet->slice_groups_count > 0) {
|
if (sheet->slice_groups_count > 0) {
|
||||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||||
@ -1080,10 +1080,10 @@ struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, str
|
|||||||
struct sprite_sheet_slice res = ZI;
|
struct sprite_sheet_slice res = ZI;
|
||||||
if (string_eq(name, LIT("pivot"))) {
|
if (string_eq(name, LIT("pivot"))) {
|
||||||
/* 'pivot' slice does not exist, return center */
|
/* 'pivot' slice does not exist, return center */
|
||||||
res.center = V2(0, 0);
|
res.center = V2FromXY(0, 0);
|
||||||
res.center_px = v2_mul(sheet->frame_size, 0.5f);
|
res.center_px = v2_mul(sheet->frame_size, 0.5f);
|
||||||
res.dir_px = V2(res.center_px.x, 0);
|
res.dir_px = V2FromXY(res.center_px.x, 0);
|
||||||
res.dir = V2(0, -0.5);
|
res.dir = V2FromXY(0, -0.5);
|
||||||
} else {
|
} else {
|
||||||
res = sprite_sheet_get_slice(sheet, LIT("pivot"), frame_index);
|
res = sprite_sheet_get_slice(sheet, LIT("pivot"), frame_index);
|
||||||
}
|
}
|
||||||
@ -1091,7 +1091,7 @@ struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, str
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sprite_sheet_slice_array sprite_sheet_get_slices(struct sprite_sheet *sheet, struct string name, u32 frame_index)
|
struct sprite_sheet_slice_array sprite_sheet_get_slices(struct sprite_sheet *sheet, String name, u32 frame_index)
|
||||||
{
|
{
|
||||||
struct sprite_sheet_slice_array res = ZI;
|
struct sprite_sheet_slice_array res = ZI;
|
||||||
if (sheet->slice_groups_count > 0) {
|
if (sheet->slice_groups_count > 0) {
|
||||||
@ -1217,7 +1217,7 @@ INTERNAL SYS_JOB_DEF(sprite_evictor_job, _)
|
|||||||
while (!shutdown) {
|
while (!shutdown) {
|
||||||
{
|
{
|
||||||
__profn("Sprite evictor cycle");
|
__profn("Sprite evictor cycle");
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
u64 evict_array_count = 0;
|
u64 evict_array_count = 0;
|
||||||
struct evict_node *evict_array = arena_push_dry(scratch.arena, struct evict_node);
|
struct evict_node *evict_array = arena_push_dry(scratch.arena, struct evict_node);
|
||||||
{
|
{
|
||||||
|
|||||||
@ -14,12 +14,12 @@ struct sprite_startup_receipt sprite_startup(void);
|
|||||||
|
|
||||||
struct sprite_tag {
|
struct sprite_tag {
|
||||||
u64 hash;
|
u64 hash;
|
||||||
struct string path;
|
String path;
|
||||||
};
|
};
|
||||||
|
|
||||||
INLINE struct sprite_tag sprite_tag_nil(void) { return (struct sprite_tag) { 0 }; }
|
INLINE struct sprite_tag sprite_tag_nil(void) { return (struct sprite_tag) { 0 }; }
|
||||||
|
|
||||||
struct sprite_tag sprite_tag_from_path(struct string path);
|
struct sprite_tag sprite_tag_from_path(String path);
|
||||||
b32 sprite_tag_is_nil(struct sprite_tag tag);
|
b32 sprite_tag_is_nil(struct sprite_tag tag);
|
||||||
b32 sprite_tag_eq(struct sprite_tag t1, struct sprite_tag t2);
|
b32 sprite_tag_eq(struct sprite_tag t1, struct sprite_tag t2);
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ void sprite_scope_end(struct sprite_scope *scope);
|
|||||||
struct sprite_texture {
|
struct sprite_texture {
|
||||||
b32 loaded;
|
b32 loaded;
|
||||||
b32 valid;
|
b32 valid;
|
||||||
struct gp_resource *gp_texture;
|
G_Resource *gp_texture;
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
};
|
};
|
||||||
@ -60,19 +60,19 @@ void sprite_texture_from_tag_prefetch(struct sprite_scope *scope, struct sprite_
|
|||||||
struct sprite_sheet {
|
struct sprite_sheet {
|
||||||
b32 loaded;
|
b32 loaded;
|
||||||
b32 valid;
|
b32 valid;
|
||||||
struct v2 image_size;
|
V2 image_size;
|
||||||
struct v2 frame_size;
|
V2 frame_size;
|
||||||
|
|
||||||
u32 frames_count;
|
u32 frames_count;
|
||||||
struct sprite_sheet_frame *frames;
|
struct sprite_sheet_frame *frames;
|
||||||
|
|
||||||
u32 spans_count;
|
u32 spans_count;
|
||||||
struct sprite_sheet_span *spans;
|
struct sprite_sheet_span *spans;
|
||||||
struct dict *spans_dict;
|
Dict *spans_dict;
|
||||||
|
|
||||||
u32 slice_groups_count;
|
u32 slice_groups_count;
|
||||||
struct sprite_sheet_slice_group *slice_groups;
|
struct sprite_sheet_slice_group *slice_groups;
|
||||||
struct dict *slice_groups_dict;
|
Dict *slice_groups_dict;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sprite_sheet *sprite_sheet_from_tag_await(struct sprite_scope *scope, struct sprite_tag tag);
|
struct sprite_sheet *sprite_sheet_from_tag_await(struct sprite_scope *scope, struct sprite_tag tag);
|
||||||
@ -86,11 +86,11 @@ void sprite_sheet_from_tag_prefetch(struct sprite_scope *scope, struct sprite_ta
|
|||||||
struct sprite_sheet_frame {
|
struct sprite_sheet_frame {
|
||||||
u32 index;
|
u32 index;
|
||||||
f64 duration;
|
f64 duration;
|
||||||
struct clip_rect clip;
|
ClipRect clip;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sprite_sheet_span {
|
struct sprite_sheet_span {
|
||||||
struct string name;
|
String name;
|
||||||
u32 start;
|
u32 start;
|
||||||
u32 end;
|
u32 end;
|
||||||
};
|
};
|
||||||
@ -103,14 +103,14 @@ struct sprite_sheet_slice {
|
|||||||
b32 has_ray;
|
b32 has_ray;
|
||||||
|
|
||||||
/* Values are in the range -0.5 (top / left edge) -> +0.5 (bottom / right edge) */
|
/* Values are in the range -0.5 (top / left edge) -> +0.5 (bottom / right edge) */
|
||||||
struct rect rect;
|
Rect rect;
|
||||||
struct v2 center;
|
V2 center;
|
||||||
struct v2 dir;
|
V2 dir;
|
||||||
|
|
||||||
/* '_px' values retain the original sprite pixel dimensions */
|
/* '_px' values retain the original sprite pixel dimensions */
|
||||||
struct rect rect_px;
|
Rect rect_px;
|
||||||
struct v2 center_px;
|
V2 center_px;
|
||||||
struct v2 dir_px;
|
V2 dir_px;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sprite_sheet_slice_array {
|
struct sprite_sheet_slice_array {
|
||||||
@ -119,7 +119,7 @@ struct sprite_sheet_slice_array {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct sprite_sheet_slice_group {
|
struct sprite_sheet_slice_group {
|
||||||
struct string name;
|
String name;
|
||||||
u64 per_frame_count;
|
u64 per_frame_count;
|
||||||
|
|
||||||
/* 2d array of slices with length (num frames) * (num slices per frame).
|
/* 2d array of slices with length (num frames) * (num slices per frame).
|
||||||
@ -129,10 +129,10 @@ struct sprite_sheet_slice_group {
|
|||||||
|
|
||||||
struct sprite_sheet_frame sprite_sheet_get_frame(struct sprite_sheet *sheet, u32 index);
|
struct sprite_sheet_frame sprite_sheet_get_frame(struct sprite_sheet *sheet, u32 index);
|
||||||
|
|
||||||
struct sprite_sheet_span sprite_sheet_get_span(struct sprite_sheet *sheet, struct string name);
|
struct sprite_sheet_span sprite_sheet_get_span(struct sprite_sheet *sheet, String name);
|
||||||
|
|
||||||
/* Returns first slice with name in frame */
|
/* Returns first slice with name in frame */
|
||||||
struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, struct string name, u32 frame_index);
|
struct sprite_sheet_slice sprite_sheet_get_slice(struct sprite_sheet *sheet, String name, u32 frame_index);
|
||||||
|
|
||||||
/* Returns all slices with name in frame */
|
/* Returns all slices with name in frame */
|
||||||
struct sprite_sheet_slice_array sprite_sheet_get_slices(struct sprite_sheet *sheet, struct string name, u32 frame_index);
|
struct sprite_sheet_slice_array sprite_sheet_get_slices(struct sprite_sheet *sheet, String name, u32 frame_index);
|
||||||
|
|||||||
@ -82,27 +82,27 @@ struct sys_file_time {
|
|||||||
struct sys_datetime modified;
|
struct sys_datetime modified;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string sys_get_write_path(struct arena *arena);
|
String sys_get_write_path(Arena *arena);
|
||||||
|
|
||||||
b32 sys_is_file(struct string path);
|
b32 sys_is_file(String path);
|
||||||
|
|
||||||
b32 sys_is_dir(struct string path);
|
b32 sys_is_dir(String path);
|
||||||
|
|
||||||
void sys_mkdir(struct string path);
|
void sys_mkdir(String path);
|
||||||
|
|
||||||
struct sys_file sys_file_open_read(struct string path);
|
struct sys_file sys_file_open_read(String path);
|
||||||
|
|
||||||
struct sys_file sys_file_open_read_wait(struct string path); /* Waits until file is not being used by another program */
|
struct sys_file sys_file_open_read_wait(String path); /* Waits until file is not being used by another program */
|
||||||
|
|
||||||
struct sys_file sys_file_open_write(struct string path);
|
struct sys_file sys_file_open_write(String path);
|
||||||
|
|
||||||
struct sys_file sys_file_open_append(struct string path);
|
struct sys_file sys_file_open_append(String path);
|
||||||
|
|
||||||
void sys_file_close(struct sys_file file);
|
void sys_file_close(struct sys_file file);
|
||||||
|
|
||||||
struct string sys_file_read_all(struct arena *arena, struct sys_file file);
|
String sys_file_read_all(Arena *arena, struct sys_file file);
|
||||||
|
|
||||||
void sys_file_write(struct sys_file file, struct string data);
|
void sys_file_write(struct sys_file file, String data);
|
||||||
|
|
||||||
u64 sys_file_get_size(struct sys_file file);
|
u64 sys_file_get_size(struct sys_file file);
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ struct sys_file_time sys_file_get_time(struct sys_file file);
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sys_file_map {
|
struct sys_file_map {
|
||||||
struct string mapped_memory;
|
String mapped_memory;
|
||||||
u64 handle;
|
u64 handle;
|
||||||
b32 valid;
|
b32 valid;
|
||||||
};
|
};
|
||||||
@ -122,14 +122,14 @@ struct sys_file_map sys_file_map_open_read(struct sys_file file);
|
|||||||
|
|
||||||
void sys_file_map_close(struct sys_file_map map);
|
void sys_file_map_close(struct sys_file_map map);
|
||||||
|
|
||||||
struct string sys_file_map_data(struct sys_file_map map);
|
String sys_file_map_data(struct sys_file_map map);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Dir iter
|
* Dir iter
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct sys_file_filter_result {
|
struct sys_file_filter_result {
|
||||||
struct string filename;
|
String filename;
|
||||||
b32 is_dir;
|
b32 is_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,9 +139,9 @@ struct sys_file_filter {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Iterate all files in a directory */
|
/* Iterate all files in a directory */
|
||||||
struct sys_file_filter sys_file_filter_begin(struct arena *arena, struct string pattern);
|
struct sys_file_filter sys_file_filter_begin(Arena *arena, String pattern);
|
||||||
|
|
||||||
b32 sys_file_filter_next(struct arena *arena, struct sys_file_filter *iter);
|
b32 sys_file_filter_next(Arena *arena, struct sys_file_filter *iter);
|
||||||
|
|
||||||
void sys_file_filter_end(struct sys_file_filter *iter);
|
void sys_file_filter_end(struct sys_file_filter *iter);
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ enum sys_watch_info_kind {
|
|||||||
|
|
||||||
struct sys_watch_info {
|
struct sys_watch_info {
|
||||||
enum sys_watch_info_kind kind;
|
enum sys_watch_info_kind kind;
|
||||||
struct string name;
|
String name;
|
||||||
struct sys_watch_info *next;
|
struct sys_watch_info *next;
|
||||||
struct sys_watch_info *prev;
|
struct sys_watch_info *prev;
|
||||||
};
|
};
|
||||||
@ -172,11 +172,11 @@ struct sys_watch_info_list {
|
|||||||
u64 count;
|
u64 count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_watch *sys_watch_alloc(struct string path);
|
struct sys_watch *sys_watch_alloc(String path);
|
||||||
|
|
||||||
void sys_watch_release(struct sys_watch *dw);
|
void sys_watch_release(struct sys_watch *dw);
|
||||||
|
|
||||||
struct sys_watch_info_list sys_watch_read_wait(struct arena *arena, struct sys_watch *dw);
|
struct sys_watch_info_list sys_watch_read_wait(Arena *arena, struct sys_watch *dw);
|
||||||
|
|
||||||
void sys_watch_wake(struct sys_watch *dw);
|
void sys_watch_wake(struct sys_watch *dw);
|
||||||
|
|
||||||
@ -313,10 +313,10 @@ struct sys_window_event {
|
|||||||
u32 text_codepoint;
|
u32 text_codepoint;
|
||||||
|
|
||||||
/* SYS_EVENT_KIND_CURSOR_MOVE */
|
/* SYS_EVENT_KIND_CURSOR_MOVE */
|
||||||
struct v2 cursor_position;
|
V2 cursor_position;
|
||||||
|
|
||||||
/* SYS_EVENT_KIND_MOUSE_MOVE */
|
/* SYS_EVENT_KIND_MOUSE_MOVE */
|
||||||
struct v2 mouse_delta;
|
V2 mouse_delta;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_window_event_array {
|
struct sys_window_event_array {
|
||||||
@ -364,7 +364,7 @@ struct sys_window *sys_window_alloc(void);
|
|||||||
|
|
||||||
void sys_window_release(struct sys_window *sys_window);
|
void sys_window_release(struct sys_window *sys_window);
|
||||||
|
|
||||||
struct sys_window_event_array sys_window_pop_events(struct arena *arena, struct sys_window *sys_window);
|
struct sys_window_event_array sys_window_pop_events(Arena *arena, struct sys_window *sys_window);
|
||||||
|
|
||||||
void sys_window_update_settings(struct sys_window *sys_window, struct sys_window_settings *settings);
|
void sys_window_update_settings(struct sys_window *sys_window, struct sys_window_settings *settings);
|
||||||
|
|
||||||
@ -372,20 +372,20 @@ struct sys_window_settings sys_window_get_settings(struct sys_window *sys_window
|
|||||||
|
|
||||||
void sys_window_show(struct sys_window *sys_window);
|
void sys_window_show(struct sys_window *sys_window);
|
||||||
|
|
||||||
struct v2 sys_window_get_size(struct sys_window *sys_window);
|
V2 sys_window_get_size(struct sys_window *sys_window);
|
||||||
|
|
||||||
struct v2 sys_window_get_monitor_size(struct sys_window *sys_window);
|
V2 sys_window_get_monitor_size(struct sys_window *sys_window);
|
||||||
|
|
||||||
/* Returns a platform specific representation of the window. E.g. `hwnd` on win32. */
|
/* Returns a platform specific representation of the window. E.g. `hwnd` on win32. */
|
||||||
u64 sys_window_get_internal_handle(struct sys_window *sys_window);
|
u64 sys_window_get_internal_handle(struct sys_window *sys_window);
|
||||||
|
|
||||||
void sys_window_cursor_set_pos(struct sys_window *sys_window, struct v2 pos);
|
void sys_window_cursor_set_pos(struct sys_window *sys_window, V2 pos);
|
||||||
|
|
||||||
void sys_window_cursor_show(struct sys_window *sys_window);
|
void sys_window_cursor_show(struct sys_window *sys_window);
|
||||||
|
|
||||||
void sys_window_cursor_hide(struct sys_window *sys_window);
|
void sys_window_cursor_hide(struct sys_window *sys_window);
|
||||||
|
|
||||||
void sys_window_cursor_enable_clip(struct sys_window *sys_window, struct rect bounds);
|
void sys_window_cursor_enable_clip(struct sys_window *sys_window, Rect bounds);
|
||||||
|
|
||||||
void sys_window_cursor_disable_clip(struct sys_window *sys_window);
|
void sys_window_cursor_disable_clip(struct sys_window *sys_window);
|
||||||
|
|
||||||
@ -408,11 +408,11 @@ struct sys_address {
|
|||||||
u16 portnb;
|
u16 portnb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_address sys_address_from_string(struct string str);
|
struct sys_address sys_address_from_string(String str);
|
||||||
|
|
||||||
struct sys_address sys_address_from_port(u16 port);
|
struct sys_address sys_address_from_port(u16 port);
|
||||||
|
|
||||||
struct string sys_string_from_address(struct arena *arena, struct sys_address address);
|
String sys_string_from_address(Arena *arena, struct sys_address address);
|
||||||
|
|
||||||
b32 sys_address_eq(struct sys_address a, struct sys_address b);
|
b32 sys_address_eq(struct sys_address a, struct sys_address b);
|
||||||
|
|
||||||
@ -423,16 +423,16 @@ b32 sys_address_eq(struct sys_address a, struct sys_address b);
|
|||||||
struct sys_sock_read_result {
|
struct sys_sock_read_result {
|
||||||
b32 valid; /* Since data.len = 0 can be valid */
|
b32 valid; /* Since data.len = 0 can be valid */
|
||||||
struct sys_address address;
|
struct sys_address address;
|
||||||
struct string data;
|
String data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_sock *sys_sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
|
struct sys_sock *sys_sock_alloc(u16 listen_port, u64 sndbuf_size, u64 rcvbuf_size);
|
||||||
|
|
||||||
void sys_sock_release(struct sys_sock *sock);
|
void sys_sock_release(struct sys_sock *sock);
|
||||||
|
|
||||||
struct sys_sock_read_result sys_sock_read(struct arena *arena, struct sys_sock *sock);
|
struct sys_sock_read_result sys_sock_read(Arena *arena, struct sys_sock *sock);
|
||||||
|
|
||||||
void sys_sock_write(struct sys_sock *sock, struct sys_address address, struct string data);
|
void sys_sock_write(struct sys_sock *sock, struct sys_address address, String data);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Util
|
* Util
|
||||||
@ -445,11 +445,11 @@ enum sys_message_box_kind {
|
|||||||
SYS_MESSAGE_BOX_KIND_FATAL
|
SYS_MESSAGE_BOX_KIND_FATAL
|
||||||
};
|
};
|
||||||
|
|
||||||
void sys_message_box(enum sys_message_box_kind kind, struct string message);
|
void sys_message_box(enum sys_message_box_kind kind, String message);
|
||||||
|
|
||||||
void sys_set_clipboard_text(struct string str);
|
void sys_set_clipboard_text(String str);
|
||||||
|
|
||||||
struct string sys_get_clipboard_text(struct arena *arena);
|
String sys_get_clipboard_text(Arena *arena);
|
||||||
|
|
||||||
u32 sys_num_logical_processors(void);
|
u32 sys_num_logical_processors(void);
|
||||||
|
|
||||||
@ -472,11 +472,11 @@ void sys_on_exit(sys_exit_func *func);
|
|||||||
void sys_exit(void);
|
void sys_exit(void);
|
||||||
|
|
||||||
/* Forcefully exits the program and displays `msg` to the user */
|
/* Forcefully exits the program and displays `msg` to the user */
|
||||||
void sys_panic(struct string msg);
|
void sys_panic(String msg);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* App entry point
|
* App entry point
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* Must be defined by app */
|
/* Must be defined by app */
|
||||||
void sys_app_startup(struct string args_str);
|
void sys_app_startup(String args_str);
|
||||||
|
|||||||
@ -51,8 +51,8 @@ typedef THREAD_DEF(thread_func, data);
|
|||||||
#define WAKE_ALL_THRESHOLD 16
|
#define WAKE_ALL_THRESHOLD 16
|
||||||
|
|
||||||
struct ticket_mutex {
|
struct ticket_mutex {
|
||||||
struct atomic64_padded ticket;
|
Atomic64Padded ticket;
|
||||||
struct atomic64_padded serving;
|
Atomic64Padded serving;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct thread {
|
struct thread {
|
||||||
@ -97,19 +97,19 @@ struct win32_window {
|
|||||||
/* FIXME: Use a cmd buffer for updating cursor (and maybe also settings).
|
/* FIXME: Use a cmd buffer for updating cursor (and maybe also settings).
|
||||||
* Current setup means cursor_set calls can be applied out of order */
|
* Current setup means cursor_set calls can be applied out of order */
|
||||||
u32 cursor_set_flags;
|
u32 cursor_set_flags;
|
||||||
struct v2 cursor_set_position;
|
V2 cursor_set_position;
|
||||||
struct rect cursor_clip_bounds;
|
Rect cursor_clip_bounds;
|
||||||
|
|
||||||
struct atomic32 topmost_toggles;
|
Atomic32 topmost_toggles;
|
||||||
b32 is_topmost;
|
b32 is_topmost;
|
||||||
|
|
||||||
struct snc_mutex event_arena_swp_mutex;
|
struct snc_mutex event_arena_swp_mutex;
|
||||||
i32 current_event_arena_index;
|
i32 current_event_arena_index;
|
||||||
struct arena *event_arenas[2];
|
Arena *event_arenas[2];
|
||||||
|
|
||||||
struct thread *window_thread;
|
struct thread *window_thread;
|
||||||
|
|
||||||
struct atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
struct win32_window *next_free;
|
struct win32_window *next_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ struct alignas(64) fiber {
|
|||||||
/* ---------------------------------------------------- */
|
/* ---------------------------------------------------- */
|
||||||
char *name_cstr; /* 08 bytes */
|
char *name_cstr; /* 08 bytes */
|
||||||
/* ---------------------------------------------------- */
|
/* ---------------------------------------------------- */
|
||||||
struct atomic32 wake_lock; /* 04 bytes (4 byte alignment) */
|
Atomic32 wake_lock; /* 04 bytes (4 byte alignment) */
|
||||||
i16 id; /* 02 bytes */
|
i16 id; /* 02 bytes */
|
||||||
i16 parent_id; /* 02 bytes */
|
i16 parent_id; /* 02 bytes */
|
||||||
/* ---------------------------------------------------- */
|
/* ---------------------------------------------------- */
|
||||||
@ -231,7 +231,7 @@ struct job_info {
|
|||||||
|
|
||||||
struct alignas(64) job_queue {
|
struct alignas(64) job_queue {
|
||||||
struct ticket_mutex lock;
|
struct ticket_mutex lock;
|
||||||
struct arena *arena;
|
Arena *arena;
|
||||||
|
|
||||||
struct job_info *first;
|
struct job_info *first;
|
||||||
struct job_info *last;
|
struct job_info *last;
|
||||||
@ -247,15 +247,15 @@ struct alignas(64) job_pool {
|
|||||||
i16 first_free_fiber_id;
|
i16 first_free_fiber_id;
|
||||||
|
|
||||||
/* Workers */
|
/* Workers */
|
||||||
struct atomic32_padded workers_shutdown;
|
Atomic32Padded workers_shutdown;
|
||||||
struct atomic64_padded num_jobs_in_queue;
|
Atomic64Padded num_jobs_in_queue;
|
||||||
struct ticket_mutex workers_wake_lock;
|
struct ticket_mutex workers_wake_lock;
|
||||||
|
|
||||||
i32 num_worker_threads;
|
i32 num_worker_threads;
|
||||||
i32 thread_priority;
|
i32 thread_priority;
|
||||||
u64 thread_affinity_mask;
|
u64 thread_affinity_mask;
|
||||||
b32 thread_is_audio;
|
b32 thread_is_audio;
|
||||||
struct arena *worker_threads_arena;
|
Arena *worker_threads_arena;
|
||||||
struct thread **worker_threads;
|
struct thread **worker_threads;
|
||||||
struct worker_ctx *worker_contexts;
|
struct worker_ctx *worker_contexts;
|
||||||
};
|
};
|
||||||
@ -269,12 +269,12 @@ GLOBAL struct {
|
|||||||
i64 timer_start_qpc;
|
i64 timer_start_qpc;
|
||||||
i64 ns_per_qpc;
|
i64 ns_per_qpc;
|
||||||
u32 main_thread_id;
|
u32 main_thread_id;
|
||||||
struct atomic32 shutdown;
|
Atomic32 shutdown;
|
||||||
|
|
||||||
wchar_t cmdline_args_wstr[8192];
|
wchar_t cmdline_args_wstr[8192];
|
||||||
|
|
||||||
/* Application control flow */
|
/* Application control flow */
|
||||||
struct atomic32 panicking;
|
Atomic32 panicking;
|
||||||
wchar_t panic_wstr[4096];
|
wchar_t panic_wstr[4096];
|
||||||
HANDLE panic_event;
|
HANDLE panic_event;
|
||||||
HANDLE startup_end_event;
|
HANDLE startup_end_event;
|
||||||
@ -286,48 +286,48 @@ GLOBAL struct {
|
|||||||
|
|
||||||
/* Threads pool */
|
/* Threads pool */
|
||||||
struct snc_mutex threads_mutex;
|
struct snc_mutex threads_mutex;
|
||||||
struct arena *threads_arena;
|
Arena *threads_arena;
|
||||||
struct thread *first_thread;
|
struct thread *first_thread;
|
||||||
struct thread *last_thread;
|
struct thread *last_thread;
|
||||||
struct thread *first_free_thread;
|
struct thread *first_free_thread;
|
||||||
|
|
||||||
/* Watches pool */
|
/* Watches pool */
|
||||||
struct snc_mutex watches_mutex;
|
struct snc_mutex watches_mutex;
|
||||||
struct arena *watches_arena;
|
Arena *watches_arena;
|
||||||
struct win32_watch *watches_first_free;
|
struct win32_watch *watches_first_free;
|
||||||
|
|
||||||
/* Windows pool */
|
/* Windows pool */
|
||||||
WNDCLASSEXW window_class;
|
WNDCLASSEXW window_class;
|
||||||
struct snc_mutex windows_mutex;
|
struct snc_mutex windows_mutex;
|
||||||
struct arena *windows_arena;
|
Arena *windows_arena;
|
||||||
struct win32_window *first_free_window;
|
struct win32_window *first_free_window;
|
||||||
|
|
||||||
/* Sockets pool */
|
/* Sockets pool */
|
||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
struct arena *socks_arena;
|
Arena *socks_arena;
|
||||||
struct snc_mutex socks_mutex;
|
struct snc_mutex socks_mutex;
|
||||||
struct win32_sock *first_free_sock;
|
struct win32_sock *first_free_sock;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Exit funcs */
|
/* Exit funcs */
|
||||||
struct atomic32 num_exit_funcs;
|
Atomic32 num_exit_funcs;
|
||||||
sys_exit_func *exit_funcs[MAX_EXIT_FUNCS];
|
sys_exit_func *exit_funcs[MAX_EXIT_FUNCS];
|
||||||
|
|
||||||
/* Scheduler */
|
/* Scheduler */
|
||||||
struct atomic64_padded current_scheduler_cycle;
|
Atomic64Padded current_scheduler_cycle;
|
||||||
struct atomic64_padded current_scheduler_cycle_period_ns;
|
Atomic64Padded current_scheduler_cycle_period_ns;
|
||||||
|
|
||||||
/* Fibers */
|
/* Fibers */
|
||||||
struct ticket_mutex fibers_lock;
|
struct ticket_mutex fibers_lock;
|
||||||
i16 num_fibers;
|
i16 num_fibers;
|
||||||
struct arena *fiber_names_arena;
|
Arena *fiber_names_arena;
|
||||||
struct fiber fibers[MAX_FIBERS];
|
struct fiber fibers[MAX_FIBERS];
|
||||||
|
|
||||||
/* Wait lists */
|
/* Wait lists */
|
||||||
struct atomic64_padded waiter_wake_gen;
|
Atomic64Padded waiter_wake_gen;
|
||||||
struct ticket_mutex wait_lists_arena_lock;
|
struct ticket_mutex wait_lists_arena_lock;
|
||||||
struct arena *wait_lists_arena;
|
Arena *wait_lists_arena;
|
||||||
|
|
||||||
/* Wait tables */
|
/* Wait tables */
|
||||||
struct wait_bin wait_addr_bins[NUM_WAIT_ADDR_BINS];
|
struct wait_bin wait_addr_bins[NUM_WAIT_ADDR_BINS];
|
||||||
@ -394,10 +394,10 @@ INTERNAL DWORD WINAPI win32_thread_proc(LPVOID vt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct thread *thread_alloc(thread_func *entry_point, void *thread_data, struct string thread_name, i32 profiler_group)
|
INTERNAL struct thread *thread_alloc(thread_func *entry_point, void *thread_data, String thread_name, i32 profiler_group)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
ASSERT(entry_point != 0);
|
ASSERT(entry_point != 0);
|
||||||
logf_info("Creating thread \"%F\"", FMT_STR(thread_name));
|
logf_info("Creating thread \"%F\"", FMT_STR(thread_name));
|
||||||
|
|
||||||
@ -435,7 +435,7 @@ INTERNAL struct thread *thread_alloc(thread_func *entry_point, void *thread_data
|
|||||||
t->thread_name_cstr[cstr_len] = 0;
|
t->thread_name_cstr[cstr_len] = 0;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
struct string16 thread_name16 = string16_from_string(scratch.arena, thread_name);
|
String16 thread_name16 = string16_from_string(scratch.arena, thread_name);
|
||||||
u64 wstr_len = min_u64((countof(t->thread_name_wstr) - 1), thread_name16.len);
|
u64 wstr_len = min_u64((countof(t->thread_name_wstr) - 1), thread_name16.len);
|
||||||
MEMCPY(t->thread_name_wstr, thread_name16.text, wstr_len * sizeof(*t->thread_name_wstr));
|
MEMCPY(t->thread_name_wstr, thread_name16.text, wstr_len * sizeof(*t->thread_name_wstr));
|
||||||
t->thread_name_wstr[wstr_len] = 0;
|
t->thread_name_wstr[wstr_len] = 0;
|
||||||
@ -715,7 +715,7 @@ INTERNAL void wake_fibers_locked(i32 num_fibers, struct fiber **fibers)
|
|||||||
|
|
||||||
INTERNAL void wake_address(void *addr, i32 count)
|
INTERNAL void wake_address(void *addr, i32 count)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
u64 wait_addr_bin_index = (u64)addr % NUM_WAIT_ADDR_BINS;
|
u64 wait_addr_bin_index = (u64)addr % NUM_WAIT_ADDR_BINS;
|
||||||
struct wait_bin *wait_addr_bin = &G.wait_addr_bins[wait_addr_bin_index];
|
struct wait_bin *wait_addr_bin = &G.wait_addr_bins[wait_addr_bin_index];
|
||||||
@ -766,7 +766,7 @@ INTERNAL void wake_address(void *addr, i32 count)
|
|||||||
|
|
||||||
INTERNAL void wake_time(u64 time)
|
INTERNAL void wake_time(u64 time)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
u64 wait_time_bin_index = (u64)time % NUM_WAIT_TIME_BINS;
|
u64 wait_time_bin_index = (u64)time % NUM_WAIT_TIME_BINS;
|
||||||
struct wait_bin *wait_time_bin = &G.wait_time_bins[wait_time_bin_index];
|
struct wait_bin *wait_time_bin = &G.wait_time_bins[wait_time_bin_index];
|
||||||
@ -1195,7 +1195,7 @@ INTERNAL THREAD_DEF(job_worker_entry, worker_ctx_arg)
|
|||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
/* Invalid yield kind */
|
/* Invalid yield kind */
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
sys_panic(string_format(scratch.arena, LIT("Invalid fiber yield kind \"%F\""), FMT_SINT(yield.kind)));
|
sys_panic(string_format(scratch.arena, LIT("Invalid fiber yield kind \"%F\""), FMT_SINT(yield.kind)));
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
} break;
|
} break;
|
||||||
@ -1475,17 +1475,17 @@ i64 sys_time_ns(void)
|
|||||||
* File system
|
* File system
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL struct string string_from_win32_path(struct arena *arena, wchar_t *src)
|
INTERNAL String string_from_win32_path(Arena *arena, wchar_t *src)
|
||||||
{
|
{
|
||||||
struct string res = {
|
String res = {
|
||||||
.len = 0,
|
.len = 0,
|
||||||
.text = arena_push_dry(arena, u8)
|
.text = arena_push_dry(arena, u8)
|
||||||
};
|
};
|
||||||
|
|
||||||
while (*src) {
|
while (*src) {
|
||||||
struct string16 decode_str = { .len = *(src + 1) ? 2 : 1, .text = src };
|
String16 decode_str = { .len = *(src + 1) ? 2 : 1, .text = src };
|
||||||
struct uni_decode_utf16_result decoded = uni_decode_utf16(decode_str);
|
Utf16DecodeResult decoded = uni_decode_utf16(decode_str);
|
||||||
struct uni_encode_utf8_result encoded = uni_encode_utf8(decoded.codepoint);
|
Utf8EncodeResult encoded = uni_encode_utf8(decoded.codepoint);
|
||||||
u8 *dest = arena_push_array_no_zero(arena, u8, encoded.count8);
|
u8 *dest = arena_push_array_no_zero(arena, u8, encoded.count8);
|
||||||
for (u32 i = 0; i < encoded.count8; ++i) {
|
for (u32 i = 0; i < encoded.count8; ++i) {
|
||||||
u8 byte = encoded.chars8[i];
|
u8 byte = encoded.chars8[i];
|
||||||
@ -1501,7 +1501,7 @@ INTERNAL struct string string_from_win32_path(struct arena *arena, wchar_t *src)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string sys_get_write_path(struct arena *arena)
|
String sys_get_write_path(Arena *arena)
|
||||||
{
|
{
|
||||||
u16 *p = 0;
|
u16 *p = 0;
|
||||||
/* TODO: cache this? */
|
/* TODO: cache this? */
|
||||||
@ -1511,7 +1511,7 @@ struct string sys_get_write_path(struct arena *arena)
|
|||||||
0,
|
0,
|
||||||
&p
|
&p
|
||||||
);
|
);
|
||||||
struct string path = ZI;
|
String path = ZI;
|
||||||
if (res == S_OK) {
|
if (res == S_OK) {
|
||||||
path = string_from_win32_path(arena, p);
|
path = string_from_win32_path(arena, p);
|
||||||
}
|
}
|
||||||
@ -1519,32 +1519,32 @@ struct string sys_get_write_path(struct arena *arena)
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 sys_is_file(struct string path)
|
b32 sys_is_file(String path)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
DWORD attributes = GetFileAttributesW(path_wstr);
|
DWORD attributes = GetFileAttributesW(path_wstr);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
|
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 sys_is_dir(struct string path)
|
b32 sys_is_dir(String path)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
DWORD attributes = GetFileAttributesW(path_wstr);
|
DWORD attributes = GetFileAttributesW(path_wstr);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY);
|
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_mkdir(struct string path)
|
void sys_mkdir(String path)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
int err_code = SHCreateDirectory(0, path_wstr);
|
int err_code = SHCreateDirectory(0, path_wstr);
|
||||||
struct string err = ZI;
|
String err = ZI;
|
||||||
switch (err_code) {
|
switch (err_code) {
|
||||||
case ERROR_BAD_PATHNAME:
|
case ERROR_BAD_PATHNAME:
|
||||||
{
|
{
|
||||||
@ -1569,7 +1569,7 @@ void sys_mkdir(struct string path)
|
|||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
if (err.len > 0) {
|
if (err.len > 0) {
|
||||||
struct string msg = string_format(scratch.arena,
|
String msg = string_format(scratch.arena,
|
||||||
LIT("Failed to create directory \"%F\": %F"),
|
LIT("Failed to create directory \"%F\": %F"),
|
||||||
FMT_STR(path),
|
FMT_STR(path),
|
||||||
FMT_STR(err));
|
FMT_STR(err));
|
||||||
@ -1578,10 +1578,10 @@ void sys_mkdir(struct string path)
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_file sys_file_open_read(struct string path)
|
struct sys_file sys_file_open_read(String path)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct sys_file file = ZI;
|
struct sys_file file = ZI;
|
||||||
|
|
||||||
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
@ -1601,10 +1601,10 @@ struct sys_file sys_file_open_read(struct string path)
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_file sys_file_open_read_wait(struct string path)
|
struct sys_file sys_file_open_read_wait(String path)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct sys_file file = ZI;
|
struct sys_file file = ZI;
|
||||||
|
|
||||||
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
@ -1628,10 +1628,10 @@ struct sys_file sys_file_open_read_wait(struct string path)
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_file sys_file_open_write(struct string path)
|
struct sys_file sys_file_open_write(String path)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct sys_file file = ZI;
|
struct sys_file file = ZI;
|
||||||
|
|
||||||
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
@ -1651,10 +1651,10 @@ struct sys_file sys_file_open_write(struct string path)
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_file sys_file_open_append(struct string path)
|
struct sys_file sys_file_open_append(String path)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct sys_file file = ZI;
|
struct sys_file file = ZI;
|
||||||
|
|
||||||
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
wchar_t *path_wstr = wstr_from_string(scratch.arena, path);
|
||||||
@ -1682,13 +1682,13 @@ void sys_file_close(struct sys_file file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string sys_file_read_all(struct arena *arena, struct sys_file file)
|
String sys_file_read_all(Arena *arena, struct sys_file file)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
i64 size = 0;
|
i64 size = 0;
|
||||||
GetFileSizeEx((HANDLE)file.handle, (PLARGE_INTEGER)&size);
|
GetFileSizeEx((HANDLE)file.handle, (PLARGE_INTEGER)&size);
|
||||||
|
|
||||||
struct string s = {
|
String s = {
|
||||||
.len = size,
|
.len = size,
|
||||||
.text = 0
|
.text = 0
|
||||||
};
|
};
|
||||||
@ -1710,13 +1710,13 @@ struct string sys_file_read_all(struct arena *arena, struct sys_file file)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_file_write(struct sys_file file, struct string data)
|
void sys_file_write(struct sys_file file, String data)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
/* TODO: Check what the real data limit is and chunk sequentially based on
|
/* TODO: Check what the real data limit is and chunk sequentially based on
|
||||||
* that (rather than failing) */
|
* that (rather than failing) */
|
||||||
if (data.len >= 0x7FFF) {
|
if (data.len >= 0x7FFF) {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
sys_panic(string_format(scratch.arena,
|
sys_panic(string_format(scratch.arena,
|
||||||
LIT("Tried to write too many bytes to disk (%F)"),
|
LIT("Tried to write too many bytes to disk (%F)"),
|
||||||
FMT_UINT(data.len)));
|
FMT_UINT(data.len)));
|
||||||
@ -1832,7 +1832,7 @@ void sys_file_map_close(struct sys_file_map map)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string sys_file_map_data(struct sys_file_map map)
|
String sys_file_map_data(struct sys_file_map map)
|
||||||
{
|
{
|
||||||
return map.mapped_memory;
|
return map.mapped_memory;
|
||||||
}
|
}
|
||||||
@ -1846,7 +1846,7 @@ struct win32_file_filter {
|
|||||||
wchar_t *filter_wstr;
|
wchar_t *filter_wstr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_file_filter sys_file_filter_begin(struct arena *arena, struct string pattern)
|
struct sys_file_filter sys_file_filter_begin(Arena *arena, String pattern)
|
||||||
{
|
{
|
||||||
struct sys_file_filter filter = ZI;
|
struct sys_file_filter filter = ZI;
|
||||||
struct win32_file_filter *filter_internal = arena_push(arena, struct win32_file_filter);
|
struct win32_file_filter *filter_internal = arena_push(arena, struct win32_file_filter);
|
||||||
@ -1855,7 +1855,7 @@ struct sys_file_filter sys_file_filter_begin(struct arena *arena, struct string
|
|||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 sys_file_filter_next(struct arena *arena, struct sys_file_filter *filter)
|
b32 sys_file_filter_next(Arena *arena, struct sys_file_filter *filter)
|
||||||
{
|
{
|
||||||
struct win32_file_filter *filter_internal = (struct win32_file_filter *)filter->handle;
|
struct win32_file_filter *filter_internal = (struct win32_file_filter *)filter->handle;
|
||||||
|
|
||||||
@ -1870,7 +1870,7 @@ b32 sys_file_filter_next(struct arena *arena, struct sys_file_filter *filter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
struct string file_name = string_from_wstr_no_limit(arena, find_file_data.cFileName);
|
String file_name = string_from_wstr_no_limit(arena, find_file_data.cFileName);
|
||||||
if (string_eq(file_name, LIT(".")) || string_eq(file_name, LIT(".."))) {
|
if (string_eq(file_name, LIT(".")) || string_eq(file_name, LIT(".."))) {
|
||||||
/* Skip initial '.' and '..' matches */
|
/* Skip initial '.' and '..' matches */
|
||||||
found = sys_file_filter_next(arena, filter);
|
found = sys_file_filter_next(arena, filter);
|
||||||
@ -1902,9 +1902,9 @@ struct win32_watch {
|
|||||||
u8 results_buff[KIBI(64)];
|
u8 results_buff[KIBI(64)];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sys_watch *sys_watch_alloc(struct string dir_path)
|
struct sys_watch *sys_watch_alloc(String dir_path)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct win32_watch *w32_watch = 0;
|
struct win32_watch *w32_watch = 0;
|
||||||
{
|
{
|
||||||
@ -1952,7 +1952,7 @@ void sys_watch_release(struct sys_watch *dw)
|
|||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_watch_info_list sys_watch_read_wait(struct arena *arena, struct sys_watch *dw)
|
struct sys_watch_info_list sys_watch_read_wait(Arena *arena, struct sys_watch *dw)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct win32_watch *w32_watch = (struct win32_watch *)dw;
|
struct win32_watch *w32_watch = (struct win32_watch *)dw;
|
||||||
@ -2001,7 +2001,7 @@ struct sys_watch_info_list sys_watch_read_wait(struct arena *arena, struct sys_w
|
|||||||
list.last = info;
|
list.last = info;
|
||||||
++list.count;
|
++list.count;
|
||||||
|
|
||||||
struct string16 name16 = ZI;
|
String16 name16 = ZI;
|
||||||
name16.text = res->FileName;
|
name16.text = res->FileName;
|
||||||
name16.len = res->FileNameLength / sizeof(wchar_t);
|
name16.len = res->FileNameLength / sizeof(wchar_t);
|
||||||
|
|
||||||
@ -2193,7 +2193,7 @@ INTERNAL void win32_window_release(struct win32_window *window)
|
|||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_window_event_array sys_window_pop_events(struct arena *arena, struct sys_window *sys_window)
|
struct sys_window_event_array sys_window_pop_events(Arena *arena, struct sys_window *sys_window)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct win32_window *window = (struct win32_window *)sys_window;
|
struct win32_window *window = (struct win32_window *)sys_window;
|
||||||
@ -2205,7 +2205,7 @@ struct sys_window_event_array sys_window_pop_events(struct arena *arena, struct
|
|||||||
window->current_event_arena_index = 1 - window->current_event_arena_index;
|
window->current_event_arena_index = 1 - window->current_event_arena_index;
|
||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
struct arena *events_arena = window->event_arenas[event_arena_index];
|
Arena *events_arena = window->event_arenas[event_arena_index];
|
||||||
struct sys_window_event_array events = ZI;
|
struct sys_window_event_array events = ZI;
|
||||||
events.count = events_arena->pos / sizeof(struct sys_window_event);
|
events.count = events_arena->pos / sizeof(struct sys_window_event);
|
||||||
events.events = arena_push_array_no_zero(arena, struct sys_window_event, events.count);
|
events.events = arena_push_array_no_zero(arena, struct sys_window_event, events.count);
|
||||||
@ -2330,7 +2330,7 @@ INTERNAL void win32_update_window_from_settings(struct win32_window *window, str
|
|||||||
SetWindowPlacement(hwnd, &wp);
|
SetWindowPlacement(hwnd, &wp);
|
||||||
|
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
wchar_t *title_wstr = wstr_from_string(scratch.arena, string_from_cstr_no_limit(settings->title));
|
wchar_t *title_wstr = wstr_from_string(scratch.arena, string_from_cstr_no_limit(settings->title));
|
||||||
SetWindowTextW(hwnd, title_wstr);
|
SetWindowTextW(hwnd, title_wstr);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
@ -2368,7 +2368,7 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
|||||||
|
|
||||||
/* Update position */
|
/* Update position */
|
||||||
if (cursor_flags & WIN32_WINDOW_CURSOR_SET_FLAG_POSITION) {
|
if (cursor_flags & WIN32_WINDOW_CURSOR_SET_FLAG_POSITION) {
|
||||||
struct v2 window_space_pos = window->cursor_set_position;
|
V2 window_space_pos = window->cursor_set_position;
|
||||||
POINT p = { window_space_pos.x, window_space_pos.y };
|
POINT p = { window_space_pos.x, window_space_pos.y };
|
||||||
ClientToScreen(window->hwnd, &p);
|
ClientToScreen(window->hwnd, &p);
|
||||||
SetCursorPos(p.x, p.y);
|
SetCursorPos(p.x, p.y);
|
||||||
@ -2483,7 +2483,7 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
|||||||
u16 low = utf16_char;
|
u16 low = utf16_char;
|
||||||
if (high) {
|
if (high) {
|
||||||
u16 utf16_pair_bytes[2] = { high, low };
|
u16 utf16_pair_bytes[2] = { high, low };
|
||||||
struct uni_decode_utf16_result decoded = uni_decode_utf16((struct string16) { .len = countof(utf16_pair_bytes), .text = utf16_pair_bytes });
|
Utf16DecodeResult decoded = uni_decode_utf16((String16) { .len = countof(utf16_pair_bytes), .text = utf16_pair_bytes });
|
||||||
if (decoded.advance16 == 2 && decoded.codepoint < U32_MAX) {
|
if (decoded.advance16 == 2 && decoded.codepoint < U32_MAX) {
|
||||||
codepoint = decoded.codepoint;
|
codepoint = decoded.codepoint;
|
||||||
}
|
}
|
||||||
@ -2576,14 +2576,14 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
|||||||
window,
|
window,
|
||||||
(struct sys_window_event) {
|
(struct sys_window_event) {
|
||||||
.kind = SYS_EVENT_KIND_CURSOR_MOVE,
|
.kind = SYS_EVENT_KIND_CURSOR_MOVE,
|
||||||
.cursor_position = V2(x, y)
|
.cursor_position = V2FromXY(x, y)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* Raw mouse move */
|
/* Raw mouse move */
|
||||||
case WM_INPUT: {
|
case WM_INPUT: {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
/* Read raw input buffer */
|
/* Read raw input buffer */
|
||||||
UINT buff_size;
|
UINT buff_size;
|
||||||
@ -2599,7 +2599,7 @@ INTERNAL LRESULT CALLBACK win32_window_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
|||||||
if (raw.header.dwType == RIM_TYPEMOUSE) {
|
if (raw.header.dwType == RIM_TYPEMOUSE) {
|
||||||
i32 x = raw.data.mouse.lLastX;
|
i32 x = raw.data.mouse.lLastX;
|
||||||
i32 y = raw.data.mouse.lLastY;
|
i32 y = raw.data.mouse.lLastY;
|
||||||
struct v2 delta = V2(x, y);
|
V2 delta = V2FromXY(x, y);
|
||||||
win32_window_process_event(
|
win32_window_process_event(
|
||||||
window,
|
window,
|
||||||
(struct sys_window_event) {
|
(struct sys_window_event) {
|
||||||
@ -2680,16 +2680,16 @@ void sys_window_show(struct sys_window *sys_window)
|
|||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 sys_window_get_size(struct sys_window *sys_window)
|
V2 sys_window_get_size(struct sys_window *sys_window)
|
||||||
{
|
{
|
||||||
struct win32_window *window = (struct win32_window *)sys_window;
|
struct win32_window *window = (struct win32_window *)sys_window;
|
||||||
return V2((f32)window->width, (f32)window->height);
|
return V2FromXY((f32)window->width, (f32)window->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct v2 sys_window_get_monitor_size(struct sys_window *sys_window)
|
V2 sys_window_get_monitor_size(struct sys_window *sys_window)
|
||||||
{
|
{
|
||||||
struct win32_window *window = (struct win32_window *)sys_window;
|
struct win32_window *window = (struct win32_window *)sys_window;
|
||||||
return V2((f32)window->monitor_width, (f32)window->monitor_height);
|
return V2FromXY((f32)window->monitor_width, (f32)window->monitor_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 sys_window_get_internal_handle(struct sys_window *sys_window)
|
u64 sys_window_get_internal_handle(struct sys_window *sys_window)
|
||||||
@ -2698,7 +2698,7 @@ u64 sys_window_get_internal_handle(struct sys_window *sys_window)
|
|||||||
return (u64)window->hwnd;
|
return (u64)window->hwnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_window_cursor_set_pos(struct sys_window *sys_window, struct v2 pos)
|
void sys_window_cursor_set_pos(struct sys_window *sys_window, V2 pos)
|
||||||
{
|
{
|
||||||
struct win32_window *window = (struct win32_window *)sys_window;
|
struct win32_window *window = (struct win32_window *)sys_window;
|
||||||
window->cursor_set_position = pos;
|
window->cursor_set_position = pos;
|
||||||
@ -2720,7 +2720,7 @@ void sys_window_cursor_hide(struct sys_window *sys_window)
|
|||||||
win32_window_wake(window);
|
win32_window_wake(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_window_cursor_enable_clip(struct sys_window *sys_window, struct rect bounds)
|
void sys_window_cursor_enable_clip(struct sys_window *sys_window, Rect bounds)
|
||||||
{
|
{
|
||||||
struct win32_window *window = (struct win32_window *)sys_window;
|
struct win32_window *window = (struct win32_window *)sys_window;
|
||||||
window->cursor_clip_bounds = bounds;
|
window->cursor_clip_bounds = bounds;
|
||||||
@ -2787,7 +2787,7 @@ INTERNAL struct sys_address sys_address_from_ip_port_cstr(char *ip_cstr, char *p
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_address sys_address_from_string(struct string str)
|
struct sys_address sys_address_from_string(String str)
|
||||||
{
|
{
|
||||||
/* Parse string into ip & port */
|
/* Parse string into ip & port */
|
||||||
u8 ip_buff[1024];
|
u8 ip_buff[1024];
|
||||||
@ -2887,9 +2887,9 @@ struct sys_address sys_address_from_port(u16 port)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string sys_string_from_address(struct arena *arena, struct sys_address address)
|
String sys_string_from_address(Arena *arena, struct sys_address address)
|
||||||
{
|
{
|
||||||
struct string res = ZI;
|
String res = ZI;
|
||||||
|
|
||||||
if (address.family == SYS_ADDRESS_FAMILY_IPV6) {
|
if (address.family == SYS_ADDRESS_FAMILY_IPV6) {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
@ -3028,12 +3028,12 @@ void sys_sock_release(struct sys_sock *sock)
|
|||||||
snc_unlock(&lock);
|
snc_unlock(&lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sys_sock_read_result sys_sock_read(struct arena *arena, struct sys_sock *sock)
|
struct sys_sock_read_result sys_sock_read(Arena *arena, struct sys_sock *sock)
|
||||||
{
|
{
|
||||||
struct win32_sock *ws = (struct win32_sock *)sock;
|
struct win32_sock *ws = (struct win32_sock *)sock;
|
||||||
|
|
||||||
u64 read_buff_size = KIBI(64);
|
u64 read_buff_size = KIBI(64);
|
||||||
struct string read_buff = ZI;
|
String read_buff = ZI;
|
||||||
read_buff.len = read_buff_size;
|
read_buff.len = read_buff_size;
|
||||||
read_buff.text = arena_push_array_no_zero(arena, u8, read_buff_size);
|
read_buff.text = arena_push_array_no_zero(arena, u8, read_buff_size);
|
||||||
|
|
||||||
@ -3066,7 +3066,7 @@ struct sys_sock_read_result sys_sock_read(struct arena *arena, struct sys_sock *
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_sock_write(struct sys_sock *sock, struct sys_address address, struct string data)
|
void sys_sock_write(struct sys_sock *sock, struct sys_address address, String data)
|
||||||
{
|
{
|
||||||
struct win32_sock *ws = (struct win32_sock *)sock;
|
struct win32_sock *ws = (struct win32_sock *)sock;
|
||||||
struct win32_address ws_addr = win32_address_from_sys_address(address);
|
struct win32_address ws_addr = win32_address_from_sys_address(address);
|
||||||
@ -3087,9 +3087,9 @@ void sys_sock_write(struct sys_sock *sock, struct sys_address address, struct st
|
|||||||
* Util
|
* Util
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void sys_message_box(enum sys_message_box_kind kind, struct string message)
|
void sys_message_box(enum sys_message_box_kind kind, String message)
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
wchar_t *message_wstr = wstr_from_string(scratch.arena, message);
|
wchar_t *message_wstr = wstr_from_string(scratch.arena, message);
|
||||||
const wchar_t *title = L"";
|
const wchar_t *title = L"";
|
||||||
@ -3126,11 +3126,11 @@ void sys_message_box(enum sys_message_box_kind kind, struct string message)
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_set_clipboard_text(struct string str)
|
void sys_set_clipboard_text(String str)
|
||||||
{
|
{
|
||||||
if (OpenClipboard(0)) {
|
if (OpenClipboard(0)) {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct string16 str16 = string16_from_string(scratch.arena, str);
|
String16 str16 = string16_from_string(scratch.arena, str);
|
||||||
u64 str16_size_bytes = str16.len * 2;
|
u64 str16_size_bytes = str16.len * 2;
|
||||||
EmptyClipboard();
|
EmptyClipboard();
|
||||||
HANDLE handle = GlobalAlloc(GMEM_MOVEABLE, str16_size_bytes + 1);
|
HANDLE handle = GlobalAlloc(GMEM_MOVEABLE, str16_size_bytes + 1);
|
||||||
@ -3146,9 +3146,9 @@ void sys_set_clipboard_text(struct string str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string sys_get_clipboard_text(struct arena *arena)
|
String sys_get_clipboard_text(Arena *arena)
|
||||||
{
|
{
|
||||||
struct string res = ZI;
|
String res = ZI;
|
||||||
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(0)) {
|
if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(0)) {
|
||||||
HANDLE handle = GetClipboardData(CF_UNICODETEXT);
|
HANDLE handle = GetClipboardData(CF_UNICODETEXT);
|
||||||
if (handle) {
|
if (handle) {
|
||||||
@ -3194,7 +3194,7 @@ void sys_exit(void)
|
|||||||
SetEvent(G.exit_begin_event);
|
SetEvent(G.exit_begin_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_panic(struct string msg)
|
void sys_panic(String msg)
|
||||||
{
|
{
|
||||||
if (atomic32_fetch_test_set(&G.panicking, 0, 1) == 0) {
|
if (atomic32_fetch_test_set(&G.panicking, 0, 1) == 0) {
|
||||||
log_panic(msg);
|
log_panic(msg);
|
||||||
@ -3208,12 +3208,12 @@ void sys_panic(struct string msg)
|
|||||||
|
|
||||||
/* Perform manual string encode to avoid any implicit memory
|
/* Perform manual string encode to avoid any implicit memory
|
||||||
* allocation (in case allocation is unreliable) */
|
* allocation (in case allocation is unreliable) */
|
||||||
struct string str8 = msg;
|
String str8 = msg;
|
||||||
u64 pos8 = 0;
|
u64 pos8 = 0;
|
||||||
while (pos8 < str8.len) {
|
while (pos8 < str8.len) {
|
||||||
struct string str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 };
|
String str8_remaining = { .len = (str8.len - pos8), .text = str8.text + pos8 };
|
||||||
struct uni_decode_utf8_result decoded = uni_decode_utf8(str8_remaining);
|
Utf8DecodeResult decoded = uni_decode_utf8(str8_remaining);
|
||||||
struct uni_encode_utf16_result encoded = uni_encode_utf16(decoded.codepoint);
|
Utf16EncodeResult encoded = uni_encode_utf16(decoded.codepoint);
|
||||||
u64 wstr_new_len = wstr_len + encoded.count16;
|
u64 wstr_new_len = wstr_len + encoded.count16;
|
||||||
if (wstr_new_len < (countof(G.panic_wstr) - 1)) {
|
if (wstr_new_len < (countof(G.panic_wstr) - 1)) {
|
||||||
u16 *dest = wstr + wstr_len;
|
u16 *dest = wstr + wstr_len;
|
||||||
@ -3292,9 +3292,9 @@ INTERNAL void win32_init_vk_btn_table(void)
|
|||||||
INTERNAL SYS_JOB_DEF(sys_app_startup_job, _)
|
INTERNAL SYS_JOB_DEF(sys_app_startup_job, _)
|
||||||
{
|
{
|
||||||
(UNUSED)_;
|
(UNUSED)_;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
{
|
{
|
||||||
struct string cmdline_args = string_from_wstr(scratch.arena, G.cmdline_args_wstr, countof(G.cmdline_args_wstr));
|
String cmdline_args = string_from_wstr(scratch.arena, G.cmdline_args_wstr, countof(G.cmdline_args_wstr));
|
||||||
sys_app_startup(cmdline_args);
|
sys_app_startup(cmdline_args);
|
||||||
SetEvent(G.startup_end_event);
|
SetEvent(G.startup_end_event);
|
||||||
}
|
}
|
||||||
@ -3497,7 +3497,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
__profn("Start job workers");
|
__profn("Start job workers");
|
||||||
for (enum sys_pool pool_kind = 0; pool_kind < (i32)countof(G.job_pools); ++pool_kind) {
|
for (enum sys_pool pool_kind = 0; pool_kind < (i32)countof(G.job_pools); ++pool_kind) {
|
||||||
struct job_pool *pool = &G.job_pools[pool_kind];
|
struct job_pool *pool = &G.job_pools[pool_kind];
|
||||||
struct string name_fmt = ZI;
|
String name_fmt = ZI;
|
||||||
i32 prof_group = PROF_THREAD_GROUP_FIBERS - MEBI(pool_kind);
|
i32 prof_group = PROF_THREAD_GROUP_FIBERS - MEBI(pool_kind);
|
||||||
switch (pool_kind) {
|
switch (pool_kind) {
|
||||||
default: ASSERT(0); break;
|
default: ASSERT(0); break;
|
||||||
@ -3548,7 +3548,7 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
struct worker_ctx *ctx = &pool->worker_contexts[i];
|
struct worker_ctx *ctx = &pool->worker_contexts[i];
|
||||||
ctx->pool_kind = pool_kind;
|
ctx->pool_kind = pool_kind;
|
||||||
ctx->id = i;
|
ctx->id = i;
|
||||||
struct string name = string_format(pool->worker_threads_arena, name_fmt, FMT_SINT(i));
|
String name = string_format(pool->worker_threads_arena, name_fmt, FMT_SINT(i));
|
||||||
pool->worker_threads[i] = thread_alloc(job_worker_entry, ctx, name, prof_group + i);
|
pool->worker_threads[i] = thread_alloc(job_worker_entry, ctx, name, prof_group + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3632,12 +3632,12 @@ int CALLBACK wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev_instance,
|
|||||||
if (!atomic32_fetch(&G.panicking)) {
|
if (!atomic32_fetch(&G.panicking)) {
|
||||||
struct snc_lock lock = snc_lock_s(&G.threads_mutex);
|
struct snc_lock lock = snc_lock_s(&G.threads_mutex);
|
||||||
if (G.first_thread) {
|
if (G.first_thread) {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
u64 num_dangling_threads = 0;
|
u64 num_dangling_threads = 0;
|
||||||
struct string threads_msg = ZI;
|
String threads_msg = ZI;
|
||||||
threads_msg.text = arena_push_dry(scratch.arena, u8);
|
threads_msg.text = arena_push_dry(scratch.arena, u8);
|
||||||
for (struct thread *t = G.first_thread; t; t = t->next) {
|
for (struct thread *t = G.first_thread; t; t = t->next) {
|
||||||
struct string name = string_from_cstr(t->thread_name_cstr, countof(t->thread_name_cstr));
|
String name = string_from_cstr(t->thread_name_cstr, countof(t->thread_name_cstr));
|
||||||
threads_msg.len += string_format(scratch.arena, LIT(" \"%F\"\n"), FMT_STR(name)).len;
|
threads_msg.len += string_format(scratch.arena, LIT(" \"%F\"\n"), FMT_STR(name)).len;
|
||||||
++num_dangling_threads;
|
++num_dangling_threads;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,10 @@ struct log_event_callback {
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct shared_log_ctx {
|
struct shared_log_ctx {
|
||||||
struct atomic32 initialized;
|
Atomic32 initialized;
|
||||||
|
|
||||||
struct snc_mutex callbacks_mutex;
|
struct snc_mutex callbacks_mutex;
|
||||||
struct arena *callbacks_arena;
|
Arena *callbacks_arena;
|
||||||
struct log_event_callback *first_callback;
|
struct log_event_callback *first_callback;
|
||||||
struct log_event_callback *last_callback;
|
struct log_event_callback *last_callback;
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ GLOBAL READONLY struct log_level_settings g_log_settings[LOG_LEVEL_COUNT] = {
|
|||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void log_startup(struct string logfile_path)
|
void log_startup(String logfile_path)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||||
@ -101,15 +101,15 @@ void log_register_callback(log_event_callback_func *func, i32 level)
|
|||||||
* Log
|
* Log
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL void append_to_logfile(struct string msg)
|
INTERNAL void append_to_logfile(String msg)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||||
|
|
||||||
if (ctx->file_valid) {
|
if (ctx->file_valid) {
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct string msg_line = string_cat(scratch.arena, msg, LIT("\n"));
|
String msg_line = string_cat(scratch.arena, msg, LIT("\n"));
|
||||||
sys_file_write(ctx->file, msg_line);
|
sys_file_write(ctx->file, msg_line);
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ INTERNAL void append_to_logfile(struct string msg)
|
|||||||
|
|
||||||
/* Panic log function is separate to enforce zero side effects other than
|
/* Panic log function is separate to enforce zero side effects other than
|
||||||
* writing to log file. */
|
* writing to log file. */
|
||||||
void _log_panic(struct string msg)
|
void _log_panic(String msg)
|
||||||
{
|
{
|
||||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||||
@ -130,9 +130,9 @@ void _log_panic(struct string msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
void _log(i32 level, struct string file, u32 line, struct string msg)
|
void _log(i32 level, String file, u32 line, String msg)
|
||||||
#else
|
#else
|
||||||
void _log(i32 level, struct string msg)
|
void _log(i32 level, String msg)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
@ -143,7 +143,7 @@ void _log(i32 level, struct string msg)
|
|||||||
sys_panic(LIT("Invalid log level"));
|
sys_panic(LIT("Invalid log level"));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct sys_datetime datetime = sys_local_time();
|
struct sys_datetime datetime = sys_local_time();
|
||||||
i64 time_ns = sys_time_ns();
|
i64 time_ns = sys_time_ns();
|
||||||
@ -151,10 +151,10 @@ void _log(i32 level, struct string msg)
|
|||||||
u32 tid = sys_current_thread_id();
|
u32 tid = sys_current_thread_id();
|
||||||
|
|
||||||
struct log_level_settings settings = g_log_settings[level];
|
struct log_level_settings settings = g_log_settings[level];
|
||||||
struct string shorthand = settings.shorthand;
|
String shorthand = settings.shorthand;
|
||||||
|
|
||||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
struct string msg_formatted = string_format(
|
String msg_formatted = string_format(
|
||||||
scratch.arena,
|
scratch.arena,
|
||||||
LIT("[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F"),
|
LIT("[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F"),
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ void _log(i32 level, struct string msg)
|
|||||||
FMT_STR(msg)
|
FMT_STR(msg)
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
struct string msg_formatted = string_format(
|
String msg_formatted = string_format(
|
||||||
scratch.arena,
|
scratch.arena,
|
||||||
LIT("[%F:%F:%F.%F] |%F| [%F] %F"),
|
LIT("[%F:%F:%F.%F] |%F| [%F] %F"),
|
||||||
|
|
||||||
@ -228,15 +228,15 @@ void _log(i32 level, struct string msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
void _logfv(i32 level, struct string file, u32 line, struct string fmt, va_list args)
|
void _logfv(i32 level, String file, u32 line, String fmt, va_list args)
|
||||||
#else
|
#else
|
||||||
void _logfv(i32 level, struct string fmt, va_list args)
|
void _logfv(i32 level, String fmt, va_list args)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||||
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
if (!atomic32_fetch(&ctx->initialized)) { return; }
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct string msg = string_formatv(scratch.arena, fmt, args);
|
String msg = string_formatv(scratch.arena, fmt, args);
|
||||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
_log(level, file, line, msg);
|
_log(level, file, line, msg);
|
||||||
#else
|
#else
|
||||||
@ -246,9 +246,9 @@ void _logfv(i32 level, struct string fmt, va_list args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
void _logf(i32 level, struct string file, u32 line, struct string fmt, ...)
|
void _logf(i32 level, String file, u32 line, String fmt, ...)
|
||||||
#else
|
#else
|
||||||
void _logf(i32 level, struct string fmt, ...)
|
void _logf(i32 level, String fmt, ...)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
struct shared_log_ctx *ctx = &g_shared_log_ctx;
|
||||||
|
|||||||
@ -28,20 +28,20 @@
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct log_level_settings {
|
struct log_level_settings {
|
||||||
struct string shorthand;
|
String shorthand;
|
||||||
u32 color;
|
u32 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct log_event {
|
struct log_event {
|
||||||
/* Msg lifetime is only as long as callback duration */
|
/* Msg lifetime is only as long as callback duration */
|
||||||
struct string msg;
|
String msg;
|
||||||
i32 level;
|
i32 level;
|
||||||
|
|
||||||
struct sys_datetime datetime;
|
struct sys_datetime datetime;
|
||||||
i64 time_ns;
|
i64 time_ns;
|
||||||
|
|
||||||
/* These will be zeroed if LOG_INCLUDE_SOURCE_LOCATION is disabled */
|
/* These will be zeroed if LOG_INCLUDE_SOURCE_LOCATION is disabled */
|
||||||
struct string file;
|
String file;
|
||||||
i32 line;
|
i32 line;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -138,24 +138,24 @@ void log_register_callback(log_event_callback_func *func, i32 level);
|
|||||||
* Function declarations
|
* Function declarations
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
void log_startup(struct string logfile_path);
|
void log_startup(String logfile_path);
|
||||||
|
|
||||||
void _log_panic(struct string msg);
|
void _log_panic(String msg);
|
||||||
|
|
||||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
void _log(i32 level, struct string file, u32 line, struct string msg);
|
void _log(i32 level, String file, u32 line, String msg);
|
||||||
#else
|
#else
|
||||||
void _log(i32 level, struct string msg);
|
void _log(i32 level, String msg);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
void _logfv(i32 level, struct string file, u32 line, struct string fmt, va_list args);
|
void _logfv(i32 level, String file, u32 line, String fmt, va_list args);
|
||||||
#else
|
#else
|
||||||
void _logfv(i32 level, struct string fmt, va_list args);
|
void _logfv(i32 level, String fmt, va_list args);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
void _logf(i32 level, struct string file, u32 line, struct string fmt, ...);
|
void _logf(i32 level, String file, u32 line, String fmt, ...);
|
||||||
#else
|
#else
|
||||||
void _logf(i32 level, struct string fmt, ...);
|
void _logf(i32 level, String fmt, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -12,10 +12,10 @@ struct alignas(64) snc_mutex {
|
|||||||
* Bit 30 = Exclusive lock is pending
|
* Bit 30 = Exclusive lock is pending
|
||||||
* Bit 0-30 = Shared locks count
|
* Bit 0-30 = Shared locks count
|
||||||
*/
|
*/
|
||||||
struct atomic32 v;
|
Atomic32 v;
|
||||||
|
|
||||||
#if RTC
|
#if RTC
|
||||||
struct atomic32 exclusive_fiber_id;
|
Atomic32 exclusive_fiber_id;
|
||||||
u8 _pad[56];
|
u8 _pad[56];
|
||||||
#else
|
#else
|
||||||
u8 _pad[60];
|
u8 _pad[60];
|
||||||
@ -43,7 +43,7 @@ void snc_unlock(struct snc_lock *lock);
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct alignas(64) snc_cv {
|
struct alignas(64) snc_cv {
|
||||||
struct atomic64 wake_gen;
|
Atomic64 wake_gen;
|
||||||
u8 _pad[56];
|
u8 _pad[56];
|
||||||
};
|
};
|
||||||
STATIC_ASSERT(sizeof(struct snc_cv) == 64); /* Padding validation */
|
STATIC_ASSERT(sizeof(struct snc_cv) == 64); /* Padding validation */
|
||||||
@ -58,7 +58,7 @@ void snc_cv_signal(struct snc_cv *cv, i32 count);
|
|||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct alignas(64) snc_counter {
|
struct alignas(64) snc_counter {
|
||||||
struct atomic64 v;
|
Atomic64 v;
|
||||||
u8 _pad[56];
|
u8 _pad[56];
|
||||||
};
|
};
|
||||||
STATIC_ASSERT(sizeof(struct snc_counter) == 64); /* Padding validation */
|
STATIC_ASSERT(sizeof(struct snc_counter) == 64); /* Padding validation */
|
||||||
|
|||||||
@ -44,7 +44,7 @@ PACK(struct tar_header {
|
|||||||
u8 padding[12];
|
u8 padding[12];
|
||||||
});
|
});
|
||||||
|
|
||||||
INTERNAL u64 str_oct_to_u64(struct string str)
|
INTERNAL u64 str_oct_to_u64(String str)
|
||||||
{
|
{
|
||||||
u64 n = 0;
|
u64 n = 0;
|
||||||
for (u64 i = 0; i < str.len; ++i) {
|
for (u64 i = 0; i < str.len; ++i) {
|
||||||
@ -59,13 +59,13 @@ INTERNAL u64 str_oct_to_u64(struct string str)
|
|||||||
* NOTE: The resulting archive merely points into the supplied tar data, no
|
* NOTE: The resulting archive merely points into the supplied tar data, no
|
||||||
* copying is done. Accessing the archive assumes that the data string is still valid.
|
* copying is done. Accessing the archive assumes that the data string is still valid.
|
||||||
*/
|
*/
|
||||||
struct tar_archive tar_parse(struct arena *arena, struct string data, struct string prefix)
|
struct tar_archive tar_parse(Arena *arena, String data, String prefix)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
struct tar_archive archive = ZI;
|
struct tar_archive archive = ZI;
|
||||||
struct bitbuff bb = bitbuff_from_string(data);
|
Bitbuff bb = bitbuff_from_string(data);
|
||||||
struct bitbuff_reader br = br_from_bitbuff_no_debug(&bb);
|
BitbuffReader br = br_from_bitbuff_no_debug(&bb);
|
||||||
|
|
||||||
u64 num_files = 0;
|
u64 num_files = 0;
|
||||||
while (br_num_bytes_left(&br) > 1024) {
|
while (br_num_bytes_left(&br) > 1024) {
|
||||||
@ -85,14 +85,14 @@ struct tar_archive tar_parse(struct arena *arena, struct string data, struct str
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string file_size_oct_str = { .len = 11, .text = header.file_size };
|
String file_size_oct_str = { .len = 11, .text = header.file_size };
|
||||||
|
|
||||||
u64 file_size = str_oct_to_u64(file_size_oct_str);
|
u64 file_size = str_oct_to_u64(file_size_oct_str);
|
||||||
u8 *file_data_ptr = br_read_bytes_raw(&br, file_size);
|
u8 *file_data_ptr = br_read_bytes_raw(&br, file_size);
|
||||||
if (!file_data_ptr) {
|
if (!file_data_ptr) {
|
||||||
file_size = 0;
|
file_size = 0;
|
||||||
}
|
}
|
||||||
struct string file_data = STRING(file_size, file_data_ptr);
|
String file_data = STRING(file_size, file_data_ptr);
|
||||||
|
|
||||||
/* Skip sector padding */
|
/* Skip sector padding */
|
||||||
u64 remaining = (512 - (file_size % 512)) % 512;
|
u64 remaining = (512 - (file_size % 512)) % 512;
|
||||||
@ -106,13 +106,13 @@ struct tar_archive tar_parse(struct arena *arena, struct string data, struct str
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct string file_name_cstr = string_from_cstr_no_limit((char *)header.file_name);
|
String file_name_cstr = string_from_cstr_no_limit((char *)header.file_name);
|
||||||
if (file_name_cstr.len >= 2) {
|
if (file_name_cstr.len >= 2) {
|
||||||
/* Chop off './' prefix */
|
/* Chop off './' prefix */
|
||||||
file_name_cstr.len -= 2;
|
file_name_cstr.len -= 2;
|
||||||
file_name_cstr.text += 2;
|
file_name_cstr.text += 2;
|
||||||
}
|
}
|
||||||
struct string file_name = string_cat(arena, prefix, file_name_cstr);
|
String file_name = string_cat(arena, prefix, file_name_cstr);
|
||||||
|
|
||||||
struct tar_entry *entry = arena_push(arena, struct tar_entry);
|
struct tar_entry *entry = arena_push(arena, struct tar_entry);
|
||||||
entry->valid = 1;
|
entry->valid = 1;
|
||||||
@ -140,7 +140,7 @@ struct tar_archive tar_parse(struct arena *arena, struct string data, struct str
|
|||||||
if (!entry->is_dir) {
|
if (!entry->is_dir) {
|
||||||
/* Find parent entry */
|
/* Find parent entry */
|
||||||
struct tar_entry *parent_entry = 0;
|
struct tar_entry *parent_entry = 0;
|
||||||
for (struct string parent_dir_name = entry->file_name; parent_dir_name.len > 0; --parent_dir_name.len) {
|
for (String parent_dir_name = entry->file_name; parent_dir_name.len > 0; --parent_dir_name.len) {
|
||||||
if (parent_dir_name.text[parent_dir_name.len - 1] == '/') {
|
if (parent_dir_name.text[parent_dir_name.len - 1] == '/') {
|
||||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, parent_dir_name);
|
u64 hash = hash_fnv64(HASH_FNV64_BASIS, parent_dir_name);
|
||||||
parent_entry = (struct tar_entry *)dict_get(archive.lookup, hash);
|
parent_entry = (struct tar_entry *)dict_get(archive.lookup, hash);
|
||||||
@ -159,7 +159,7 @@ struct tar_archive tar_parse(struct arena *arena, struct string data, struct str
|
|||||||
}
|
}
|
||||||
|
|
||||||
READONLY GLOBAL struct tar_entry g_nil_tar_entry = ZI;
|
READONLY GLOBAL struct tar_entry g_nil_tar_entry = ZI;
|
||||||
struct tar_entry *tar_get(struct tar_archive *archive, struct string name)
|
struct tar_entry *tar_get(struct tar_archive *archive, String name)
|
||||||
{
|
{
|
||||||
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
u64 hash = hash_fnv64(HASH_FNV64_BASIS, name);
|
||||||
struct tar_entry *lookup = (struct tar_entry *)dict_get(archive->lookup, hash);
|
struct tar_entry *lookup = (struct tar_entry *)dict_get(archive->lookup, hash);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
struct tar_entry {
|
struct tar_entry {
|
||||||
b32 valid;
|
b32 valid;
|
||||||
struct string file_name;
|
String file_name;
|
||||||
struct string data;
|
String data;
|
||||||
|
|
||||||
b32 is_dir;
|
b32 is_dir;
|
||||||
struct tar_entry *next;
|
struct tar_entry *next;
|
||||||
@ -9,9 +9,9 @@ struct tar_entry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct tar_archive {
|
struct tar_archive {
|
||||||
struct dict *lookup;
|
Dict *lookup;
|
||||||
struct tar_entry *head;
|
struct tar_entry *head;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tar_archive tar_parse(struct arena *arena, struct string data, struct string prefix);
|
struct tar_archive tar_parse(Arena *arena, String data, String prefix);
|
||||||
struct tar_entry *tar_get(struct tar_archive *archive, struct string name);
|
struct tar_entry *tar_get(struct tar_archive *archive, String name);
|
||||||
|
|||||||
@ -1,12 +1,23 @@
|
|||||||
struct font_glyph;
|
typedef struct TTF_Glyph TTF_Glyph;
|
||||||
|
struct TTF_Glyph {
|
||||||
struct ttf_decode_result {
|
f32 off_x;
|
||||||
struct font_glyph *glyphs;
|
f32 off_y;
|
||||||
u16 glyphs_count;
|
i32 advance;
|
||||||
u16 *cache_indices; /* Array of indices into the `glyphs` array in order of `cache_chars` */
|
f32 width;
|
||||||
struct image_rgba image_data;
|
f32 height;
|
||||||
|
Rect atlas_rect;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ttf_startup_receipt { i32 _; };
|
typedef struct TTF_Result TTF_Result;
|
||||||
struct ttf_startup_receipt ttf_startup(void);
|
struct TTF_Result {
|
||||||
struct ttf_decode_result ttf_decode(struct arena *arena, struct string encoded, f32 point_size, u32 *cache_codes, u32 cache_codes_count);
|
TTF_Glyph *glyphs;
|
||||||
|
u16 glyphs_count;
|
||||||
|
u16 *cache_indices; /* Array of indices into the `glyphs` array in order of `cache_chars` */
|
||||||
|
ImageDataRgba image_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct TTF_StartupReceipt TTF_StartupReceipt;
|
||||||
|
struct TTF_StartupReceipt { i32 _; };
|
||||||
|
TTF_StartupReceipt ttf_startup(void);
|
||||||
|
|
||||||
|
TTF_Result ttf_decode(Arena *arena, String encoded, f32 point_size, u32 *cache_codes, u32 cache_codes_count);
|
||||||
|
|||||||
@ -1,11 +1,6 @@
|
|||||||
/* Based on Allen Webster's dwrite rasterizer example -
|
/* Based on Allen Webster's dwrite rasterizer example -
|
||||||
* https://github.com/4th-dimention/examps */
|
* https://github.com/4th-dimention/examps */
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "../font/font.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma warning(push, 0)
|
#pragma warning(push, 0)
|
||||||
# include <dwrite.h>
|
# include <dwrite.h>
|
||||||
# include <dwrite_3.h>
|
# include <dwrite_3.h>
|
||||||
@ -26,7 +21,7 @@ extern "C"
|
|||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
/* FIXME: Do we need to wrap this in a mutex? */
|
/* FIXME: Do we need to wrap this in a mutex? */
|
||||||
IDWriteFactory5 *factory;
|
IDWriteFactory5 *factory;
|
||||||
} G = ZI, DEBUG_ALIAS(G, L_ttf_dwrite);
|
} G = ZI, DEBUG_ALIAS(G, G_ttf_dwrite);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Decode font
|
* Decode font
|
||||||
@ -42,7 +37,7 @@ INTERNAL i32 round_up(f32 x)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Call this during font system startup */
|
/* Call this during font system startup */
|
||||||
struct ttf_startup_receipt ttf_startup(void)
|
TTF_StartupReceipt ttf_startup(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
ASSERT(!G.factory);
|
ASSERT(!G.factory);
|
||||||
@ -71,7 +66,7 @@ struct ttf_startup_receipt ttf_startup(void)
|
|||||||
return { 0 };
|
return { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ttf_decode_result ttf_decode(struct arena *arena, struct string encoded, f32 point_size, u32 *cache_codes, u32 cache_codes_count)
|
TTF_Result ttf_decode(Arena *arena, String encoded, f32 point_size, u32 *cache_codes, u32 cache_codes_count)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
COLORREF bg_color = RGB32(0,0,0);
|
COLORREF bg_color = RGB32(0,0,0);
|
||||||
@ -157,7 +152,7 @@ struct ttf_decode_result ttf_decode(struct arena *arena, struct string encoded,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate font memory */
|
/* Allocate font memory */
|
||||||
struct font_glyph *glyphs = (struct font_glyph *)arena_push_array(arena, struct font_glyph, glyph_count);
|
TTF_Glyph *glyphs = (TTF_Glyph *)arena_push_array(arena, TTF_Glyph, glyph_count);
|
||||||
|
|
||||||
/* Allocate (starting) atlas memory
|
/* Allocate (starting) atlas memory
|
||||||
* NOTE: This is unecessary since atlas memory will grow anyway. Could
|
* NOTE: This is unecessary since atlas memory will grow anyway. Could
|
||||||
@ -210,7 +205,7 @@ struct ttf_decode_result ttf_decode(struct arena *arena, struct string encoded,
|
|||||||
i32 tex_w = bounding_box.right - bounding_box.left;
|
i32 tex_w = bounding_box.right - bounding_box.left;
|
||||||
i32 tex_h = bounding_box.bottom - bounding_box.top;
|
i32 tex_h = bounding_box.bottom - bounding_box.top;
|
||||||
|
|
||||||
struct font_glyph *glyph = &glyphs[i];
|
TTF_Glyph *glyph = &glyphs[i];
|
||||||
glyph->off_x = off_x;
|
glyph->off_x = off_x;
|
||||||
glyph->off_y = off_y;
|
glyph->off_y = off_y;
|
||||||
glyph->advance = round_up(advance);
|
glyph->advance = round_up(advance);
|
||||||
@ -297,7 +292,7 @@ struct ttf_decode_result ttf_decode(struct arena *arena, struct string encoded,
|
|||||||
factory->Release();
|
factory->Release();
|
||||||
|
|
||||||
/* Return */
|
/* Return */
|
||||||
struct ttf_decode_result result = ZI;
|
TTF_Result result = ZI;
|
||||||
result.glyphs = glyphs;
|
result.glyphs = glyphs;
|
||||||
result.glyphs_count = glyph_count;
|
result.glyphs_count = glyph_count;
|
||||||
result.cache_indices = cache_indices;
|
result.cache_indices = cache_indices;
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
#include "../font/font.h"
|
#include "../font/font.h"
|
||||||
#include "../collider/collider.h"
|
#include "../collider/collider.h"
|
||||||
#include "../draw/draw.h"
|
#include "../draw/draw.h"
|
||||||
#include "../host/host.h"
|
#include "../net/net.h"
|
||||||
|
|
||||||
#include "user_core.h"
|
#include "user_core.h"
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,10 +1,5 @@
|
|||||||
struct font_startup_receipt;
|
|
||||||
struct sprite_startup_receipt;
|
struct sprite_startup_receipt;
|
||||||
struct draw_startup_receipt;
|
|
||||||
struct asset_cache_startup_receipt;
|
|
||||||
struct sound_startup_receipt;
|
struct sound_startup_receipt;
|
||||||
struct mixer_startup_receipt;
|
|
||||||
struct host_startup_receipt;
|
|
||||||
struct sim_startup_receipt;
|
struct sim_startup_receipt;
|
||||||
|
|
||||||
enum user_bind_kind {
|
enum user_bind_kind {
|
||||||
@ -57,12 +52,12 @@ enum user_bind_kind {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct user_startup_receipt { i32 _; };
|
struct user_startup_receipt { i32 _; };
|
||||||
struct user_startup_receipt user_startup(struct font_startup_receipt *font_sr,
|
struct user_startup_receipt user_startup(F_StartupReceipt *font_sr,
|
||||||
struct sprite_startup_receipt *sprite_sr,
|
struct sprite_startup_receipt *sprite_sr,
|
||||||
struct draw_startup_receipt *draw_sr,
|
D_StartupReceipt *draw_sr,
|
||||||
struct asset_cache_startup_receipt *asset_cache_sr,
|
AC_StartupReceipt *asset_cache_sr,
|
||||||
struct sound_startup_receipt *sound_sr,
|
struct sound_startup_receipt *sound_sr,
|
||||||
struct mixer_startup_receipt *mixer_sr,
|
M_StartupReceipt *mixer_sr,
|
||||||
struct host_startup_receipt *host_sr,
|
N_StartupReceipt *host_sr,
|
||||||
struct sim_startup_receipt *sim_sr,
|
struct sim_startup_receipt *sim_sr,
|
||||||
struct string connect_address_str);
|
String connect_address_str);
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
#if RESOURCE_RELOADING
|
#if RESOURCE_RELOADING
|
||||||
|
|
||||||
struct watch_event {
|
struct watch_event {
|
||||||
struct string name;
|
String name;
|
||||||
struct watch_event *next;
|
struct watch_event *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct sys_watch *watch;
|
struct sys_watch *watch;
|
||||||
struct atomic32 watch_shutdown;
|
Atomic32 watch_shutdown;
|
||||||
struct snc_counter watch_jobs_counter;
|
struct snc_counter watch_jobs_counter;
|
||||||
|
|
||||||
struct snc_mutex watch_dispatcher_mutex;
|
struct snc_mutex watch_dispatcher_mutex;
|
||||||
struct arena *watch_events_arena;
|
Arena *watch_events_arena;
|
||||||
struct watch_event *first_watch_event;
|
struct watch_event *first_watch_event;
|
||||||
struct watch_event *last_watch_event;
|
struct watch_event *last_watch_event;
|
||||||
struct snc_cv watch_dispatcher_cv;
|
struct snc_cv watch_dispatcher_cv;
|
||||||
@ -74,21 +74,21 @@ void watch_register_callback(watch_callback *callback)
|
|||||||
INTERNAL SYS_JOB_DEF(watch_monitor_job, _)
|
INTERNAL SYS_JOB_DEF(watch_monitor_job, _)
|
||||||
{
|
{
|
||||||
(UNUSED)_;
|
(UNUSED)_;
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
|
|
||||||
struct string ignored[] = {
|
String ignored[] = {
|
||||||
LIT(".vs"),
|
LIT(".vs"),
|
||||||
LIT(".git")
|
LIT(".git")
|
||||||
};
|
};
|
||||||
|
|
||||||
while (!atomic32_fetch(&G.watch_shutdown)) {
|
while (!atomic32_fetch(&G.watch_shutdown)) {
|
||||||
struct arena_temp temp = arena_temp_begin(scratch.arena);
|
TempArena temp = arena_temp_begin(scratch.arena);
|
||||||
struct sys_watch_info_list info_list = sys_watch_read_wait(temp.arena, G.watch);
|
struct sys_watch_info_list info_list = sys_watch_read_wait(temp.arena, G.watch);
|
||||||
if (info_list.first && !atomic32_fetch(&G.watch_shutdown)) {
|
if (info_list.first && !atomic32_fetch(&G.watch_shutdown)) {
|
||||||
struct snc_lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
struct snc_lock lock = snc_lock_e(&G.watch_dispatcher_mutex);
|
||||||
{
|
{
|
||||||
for (struct sys_watch_info *info = info_list.first; info; info = info->next) {
|
for (struct sys_watch_info *info = info_list.first; info; info = info->next) {
|
||||||
struct string name_src = info->name;
|
String name_src = info->name;
|
||||||
b32 ignore = 0;
|
b32 ignore = 0;
|
||||||
for (u32 i = 0; i < countof(ignored); ++i) {
|
for (u32 i = 0; i < countof(ignored); ++i) {
|
||||||
if (string_starts_with(name_src, ignored[i])) {
|
if (string_starts_with(name_src, ignored[i])) {
|
||||||
@ -125,7 +125,7 @@ INTERNAL SYS_JOB_DEF(watch_monitor_job, _)
|
|||||||
#define WATCH_DISPATCHER_DEDUP_DICT_BINS 128
|
#define WATCH_DISPATCHER_DEDUP_DICT_BINS 128
|
||||||
|
|
||||||
struct watch_callback_job_sig {
|
struct watch_callback_job_sig {
|
||||||
struct string name;
|
String name;
|
||||||
watch_callback **callbacks;
|
watch_callback **callbacks;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ INTERNAL SYS_JOB_DEF(watch_callback_job, job)
|
|||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct watch_callback_job_sig *sig = job.sig;
|
struct watch_callback_job_sig *sig = job.sig;
|
||||||
struct string name = sig->name;
|
String name = sig->name;
|
||||||
watch_callback *callback = sig->callbacks[job.id];
|
watch_callback *callback = sig->callbacks[job.id];
|
||||||
callback(name);
|
callback(name);
|
||||||
}
|
}
|
||||||
@ -145,7 +145,7 @@ INTERNAL SYS_JOB_DEF(watch_dispatcher_job, _)
|
|||||||
b32 shutdown = 0;
|
b32 shutdown = 0;
|
||||||
while (!shutdown) {
|
while (!shutdown) {
|
||||||
{
|
{
|
||||||
struct arena_temp scratch = scratch_begin_no_conflict();
|
TempArena scratch = scratch_begin_no_conflict();
|
||||||
struct watch_event *first_watch_event = 0;
|
struct watch_event *first_watch_event = 0;
|
||||||
struct watch_event *last_watch_event = 0;
|
struct watch_event *last_watch_event = 0;
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ INTERNAL SYS_JOB_DEF(watch_dispatcher_job, _)
|
|||||||
|
|
||||||
/* Run callbacks */
|
/* Run callbacks */
|
||||||
{
|
{
|
||||||
struct dict *dedup_dict = dict_init(scratch.arena, WATCH_DISPATCHER_DEDUP_DICT_BINS);
|
Dict *dedup_dict = dict_init(scratch.arena, WATCH_DISPATCHER_DEDUP_DICT_BINS);
|
||||||
for (struct watch_event *e = first_watch_event; e; e = e->next) {
|
for (struct watch_event *e = first_watch_event; e; e = e->next) {
|
||||||
__profn("Dispatch");
|
__profn("Dispatch");
|
||||||
/* Do not run callbacks for the same file more than once */
|
/* Do not run callbacks for the same file more than once */
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#define WATCH_CALLBACK_FUNC_DEF(func_name, arg_name) void func_name(struct string arg_name)
|
#define WATCH_CALLBACK_FUNC_DEF(func_name, arg_name) void func_name(String arg_name)
|
||||||
typedef WATCH_CALLBACK_FUNC_DEF(watch_callback, name);
|
typedef WATCH_CALLBACK_FUNC_DEF(watch_callback, name);
|
||||||
|
|
||||||
void watch_startup(void);
|
void watch_startup(void);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user