fwk sync
parent
fb2aefca71
commit
3da7b6dc9a
15
MAKE.bat
15
MAKE.bat
|
@ -19,8 +19,10 @@ if "%1"=="help" (
|
||||||
echo %0 [web] ; run Python webserver in html5 dir
|
echo %0 [web] ; run Python webserver in html5 dir
|
||||||
echo %0 [pull] ; pull changes from origin
|
echo %0 [pull] ; pull changes from origin
|
||||||
echo %0 [push] ; prepare for commit, stage changes and commit them
|
echo %0 [push] ; prepare for commit, stage changes and commit them
|
||||||
|
echo %0 [dstat] ; show depot changes
|
||||||
echo %0 [dpush] ; push depot changes
|
echo %0 [dpush] ; push depot changes
|
||||||
echo %0 [depot] ; sync depot changes
|
echo %0 [depot] ; sync depot changes
|
||||||
|
echo %0 [fuse] ; fuse all binaries and cooked zipfiles found together
|
||||||
echo %0 [git] ; prepare for commit
|
echo %0 [git] ; prepare for commit
|
||||||
echo %0 [vps] ; upload the release to VPS
|
echo %0 [vps] ; upload the release to VPS
|
||||||
echo %0 [tidy] ; clean up temp files
|
echo %0 [tidy] ; clean up temp files
|
||||||
|
@ -138,7 +140,7 @@ if "%1"=="git" (
|
||||||
rem call make.bat docs
|
rem call make.bat docs
|
||||||
|
|
||||||
call make.bat amalgamation
|
call make.bat amalgamation
|
||||||
call make.bat split
|
rem call make.bat split
|
||||||
|
|
||||||
rem rd /q /s engine\split
|
rem rd /q /s engine\split
|
||||||
rem md engine\split
|
rem md engine\split
|
||||||
|
@ -227,6 +229,17 @@ if "%1"=="join" (
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rem fuse binaries and zipfiles
|
||||||
|
if "%1"=="fuse" (
|
||||||
|
setlocal enableDelayedExpansion
|
||||||
|
if "%2"=="cook" (
|
||||||
|
del *.zip 2> nul 1> nul & tools\cook --cook-jobs=1
|
||||||
|
)
|
||||||
|
for %%i in (*.exe) do set "var=%%i" && if not "!var:~0,6!"=="fused_" ( copy /y !var! fused_!var! 2>nul 1>nul & tools\ark fused_!var! *.zip )
|
||||||
|
endlocal
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
rem check memory api calls
|
rem check memory api calls
|
||||||
if "%1"=="checkmem" (
|
if "%1"=="checkmem" (
|
||||||
findstr /RNC:"[^_xv]realloc[(]" engine\v4k.c engine\split\v4k*
|
findstr /RNC:"[^_xv]realloc[(]" engine\v4k.c engine\split\v4k*
|
||||||
|
|
2
_mirror
2
_mirror
|
@ -1 +1 @@
|
||||||
Subproject commit 18db6da2d1c9b1dbf954be2692f289ca54ec81d8
|
Subproject commit b82b5ab54dae8de6498e566956b6163b3f4c27cd
|
10
bind/v4k.lua
10
bind/v4k.lua
|
@ -1902,6 +1902,8 @@ typedef struct audio_handle* audio_t;
|
||||||
float audio_volume_clip(float gain);
|
float audio_volume_clip(float gain);
|
||||||
float audio_volume_stream(float gain);
|
float audio_volume_stream(float gain);
|
||||||
float audio_volume_master(float gain);
|
float audio_volume_master(float gain);
|
||||||
|
int audio_mute(int mute);
|
||||||
|
int audio_muted();
|
||||||
int ui_audio();
|
int ui_audio();
|
||||||
enum AUDIO_FLAGS {
|
enum AUDIO_FLAGS {
|
||||||
AUDIO_1CH = 0,
|
AUDIO_1CH = 0,
|
||||||
|
@ -2103,6 +2105,10 @@ typedef union json_t { char* s; double f; int64_t i; uintptr_t p; union json_t*
|
||||||
void* dll(const char *filename, const char *symbol);
|
void* dll(const char *filename, const char *symbol);
|
||||||
vec3 editor_pick(float mouse_x, float mouse_y);
|
vec3 editor_pick(float mouse_x, float mouse_y);
|
||||||
char* editor_path(const char *path);
|
char* editor_path(const char *path);
|
||||||
|
float* editor_getf(const char *key);
|
||||||
|
int* editor_geti(const char *key);
|
||||||
|
char** editor_gets(const char *key);
|
||||||
|
int editor_send(const char *cmd, const char *optional_value);
|
||||||
char* dialog_load();
|
char* dialog_load();
|
||||||
char* dialog_save();
|
char* dialog_save();
|
||||||
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
|
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
|
||||||
|
@ -3069,6 +3075,8 @@ typedef vec3i guid;
|
||||||
void app_crash();
|
void app_crash();
|
||||||
void app_singleton(const char *guid);
|
void app_singleton(const char *guid);
|
||||||
bool app_open(const char *folder_file_or_url);
|
bool app_open(const char *folder_file_or_url);
|
||||||
|
const char* app_loadfile();
|
||||||
|
const char* app_savefile();
|
||||||
char* callstack( int traces );
|
char* callstack( int traces );
|
||||||
int callstackf( FILE *fp, int traces );
|
int callstackf( FILE *fp, int traces );
|
||||||
void die(const char *message);
|
void die(const char *message);
|
||||||
|
@ -3140,7 +3148,7 @@ PANEL_OPEN = 1,
|
||||||
int ui_label2_toolbar(const char *label, const char *icons);
|
int ui_label2_toolbar(const char *label, const char *icons);
|
||||||
int ui_slider(const char *label, float *value);
|
int ui_slider(const char *label, float *value);
|
||||||
int ui_slider2(const char *label, float *value, const char *caption);
|
int ui_slider2(const char *label, float *value, const char *caption);
|
||||||
int ui_contextual_end();
|
int ui_contextual_end(int close);
|
||||||
int ui_collapse_clicked();
|
int ui_collapse_clicked();
|
||||||
int ui_collapse_end();
|
int ui_collapse_end();
|
||||||
int ui_panel_end();
|
int ui_panel_end();
|
||||||
|
|
|
@ -15292,9 +15292,12 @@ API int audio_play_gain_pitch( audio_t a, int flags, float gain, float pitch
|
||||||
API int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan/*0*/ );
|
API int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan/*0*/ );
|
||||||
API int audio_stop( audio_t a );
|
API int audio_stop( audio_t a );
|
||||||
|
|
||||||
API float audio_volume_clip(float gain); // set fx volume if gain is in [0..1] range. return current fx volume in any case
|
API float audio_volume_clip(float gain); // set fx volume if gain is in [0..1] range. returns current fx volume in any case
|
||||||
API float audio_volume_stream(float gain); // set bgm volume if gain is in [0..1] range. return current bgm volume in any case
|
API float audio_volume_stream(float gain); // set bgm volume if gain is in [0..1] range. returns current bgm volume in any case
|
||||||
API float audio_volume_master(float gain); // set master volume if gain is in [0..1] range. return current master volume in any case
|
API float audio_volume_master(float gain); // set master volume if gain is in [0..1] range. returns current master volume in any case
|
||||||
|
|
||||||
|
API int audio_mute(int mute);
|
||||||
|
API int audio_muted();
|
||||||
|
|
||||||
API int ui_audio();
|
API int ui_audio();
|
||||||
|
|
||||||
|
@ -15683,6 +15686,11 @@ API void* dll(const char *filename, const char *symbol);
|
||||||
API vec3 editor_pick(float mouse_x, float mouse_y);
|
API vec3 editor_pick(float mouse_x, float mouse_y);
|
||||||
API char* editor_path(const char *path);
|
API char* editor_path(const char *path);
|
||||||
|
|
||||||
|
API float* editor_getf(const char *key);
|
||||||
|
API int* editor_geti(const char *key);
|
||||||
|
API char** editor_gets(const char *key);
|
||||||
|
API int editor_send(const char *cmd, const char *optional_value);
|
||||||
|
|
||||||
// open file dialog
|
// open file dialog
|
||||||
|
|
||||||
API char* dialog_load();
|
API char* dialog_load();
|
||||||
|
@ -16520,7 +16528,9 @@ extern API int profiler_enabled; ///-
|
||||||
// @todo: nested structs? pointers in members?
|
// @todo: nested structs? pointers in members?
|
||||||
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
||||||
|
|
||||||
|
#ifndef ifdef_objapi
|
||||||
#define ifdef_objapi(T,...) __VA_ARGS__
|
#define ifdef_objapi(T,...) __VA_ARGS__
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct reflected_t {
|
typedef struct reflected_t {
|
||||||
unsigned id, objtype;
|
unsigned id, objtype;
|
||||||
|
@ -17519,9 +17529,10 @@ char* strtok_s(char* str,const char* delimiters,char** context); // tcc misses t
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
#define each_substring(str, delims, keyname) \
|
#define each_substring(str, delims, keyname) \
|
||||||
( int len_ = strlen(str) + 1; len_; len_ = 0 ) \
|
( char *str_ = (char*)(str); str_; str_ = 0 ) \
|
||||||
for( char buf_[1024], *ptr_ = len_ < 1024 ? buf_ : REALLOC(0, len_), *lit_ = (char*)(str), *_bak = (snprintf(ptr_, len_, "%s", lit_), ptr_); _bak; _bak = 0, (ptr_ == buf_ ? 0 : REALLOC(ptr_, 0)) ) \
|
for( int len_ = strlen(str_) + 1, heap_ = len_ < 1024; len_ > 1; len_ = 0 ) \
|
||||||
for( char *next_token = 0, *keyname = strtok_r(_bak, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
for( char *ptr_ = (heap_ ? REALLOC(0, len_) : ALLOCA(len_)), *cpy_ = (snprintf(ptr_, len_, "%s", str_), ptr_); ptr_; (heap_ ? REALLOC(ptr_, 0) : 0), ptr_ = 0 ) \
|
||||||
|
for( char *next_token = 0, *keyname = strtok_r(cpy_, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
||||||
#else
|
#else
|
||||||
#define each_substring(str, delims, keyname) \
|
#define each_substring(str, delims, keyname) \
|
||||||
( char** tokens_ = strsplit((str), (delims)), *keyname = 0; tokens_; tokens_ = 0) \
|
( char** tokens_ = strsplit((str), (delims)), *keyname = 0; tokens_; tokens_ = 0) \
|
||||||
|
@ -17676,6 +17687,10 @@ API void app_crash();
|
||||||
API void app_singleton(const char *guid);
|
API void app_singleton(const char *guid);
|
||||||
API bool app_open(const char *folder_file_or_url);
|
API bool app_open(const char *folder_file_or_url);
|
||||||
|
|
||||||
|
API const char* app_loadfile();
|
||||||
|
API const char* app_savefile();
|
||||||
|
|
||||||
|
|
||||||
API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free().
|
API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free().
|
||||||
API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order.
|
API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order.
|
||||||
|
|
||||||
|
@ -17775,7 +17790,7 @@ API int ui_label2_float(const char *label, float value);
|
||||||
API int ui_label2_toolbar(const char *label, const char *icons);
|
API int ui_label2_toolbar(const char *label, const char *icons);
|
||||||
API int ui_slider(const char *label, float *value);
|
API int ui_slider(const char *label, float *value);
|
||||||
API int ui_slider2(const char *label, float *value, const char *caption);
|
API int ui_slider2(const char *label, float *value, const char *caption);
|
||||||
API int ui_contextual_end();
|
API int ui_contextual_end(int close);
|
||||||
API int ui_collapse_clicked();
|
API int ui_collapse_clicked();
|
||||||
API int ui_collapse_end();
|
API int ui_collapse_end();
|
||||||
API int ui_panel_end();
|
API int ui_panel_end();
|
||||||
|
@ -252217,6 +252232,7 @@ unsigned file_decode(FILE* in, FILE* out, FILE *logfile) { // multi decoder
|
||||||
typedef struct zip zip;
|
typedef struct zip zip;
|
||||||
|
|
||||||
zip* zip_open(const char *file, const char *mode /*r,w,a*/);
|
zip* zip_open(const char *file, const char *mode /*r,w,a*/);
|
||||||
|
zip* zip_open_handle(FILE*fp, const char *mode /*r,w,a*/);
|
||||||
|
|
||||||
// only for (w)rite or (a)ppend mode
|
// only for (w)rite or (a)ppend mode
|
||||||
bool zip_append_file(zip*, const char *entryname, const char *comment, FILE *in, unsigned compress_level);
|
bool zip_append_file(zip*, const char *entryname, const char *comment, FILE *in, unsigned compress_level);
|
||||||
|
@ -252432,7 +252448,7 @@ int jzReadEndRecord(FILE *fp, JZEndRecord *endRecord) {
|
||||||
|
|
||||||
// Read ZIP file global directory. Will move within file. Returns Z_OK, or error code
|
// Read ZIP file global directory. Will move within file. Returns Z_OK, or error code
|
||||||
// Callback is called for each record, until callback returns zero
|
// Callback is called for each record, until callback returns zero
|
||||||
int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback callback, void *user_data) {
|
int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback callback, void *user_data, void *user_data2) {
|
||||||
JZGlobalFileHeader fileHeader;
|
JZGlobalFileHeader fileHeader;
|
||||||
|
|
||||||
if(fseek(fp, endRecord->centralDirectoryOffset, SEEK_SET)) {
|
if(fseek(fp, endRecord->centralDirectoryOffset, SEEK_SET)) {
|
||||||
|
@ -252447,6 +252463,8 @@ int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback ca
|
||||||
return ERR(JZ_ERRNO, "Couldn't read file header #%d!", i);
|
return ERR(JZ_ERRNO, "Couldn't read file header #%d!", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileHeader.relativeOffsetOflocalHeader += (uintptr_t)user_data2;
|
||||||
|
|
||||||
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
||||||
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
||||||
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
||||||
|
@ -252939,11 +252957,7 @@ common:;
|
||||||
|
|
||||||
// zip common
|
// zip common
|
||||||
|
|
||||||
zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
zip* zip_open_handle(FILE *fp, const char *mode) {
|
||||||
struct stat buffer;
|
|
||||||
int exists = (stat(file, &buffer) == 0);
|
|
||||||
if( mode[0] == 'a' && !exists ) mode = "wb";
|
|
||||||
FILE *fp = fopen(file, mode[0] == 'w' ? "wb" : mode[0] == 'a' ? "a+b" : "rb");
|
|
||||||
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
||||||
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
||||||
if( !z ) return fclose(fp), ERR(NULL, "out of mem"); else *z = zero;
|
if( !z ) return fclose(fp), ERR(NULL, "out of mem"); else *z = zero;
|
||||||
|
@ -252954,12 +252968,17 @@ zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
if( mode[0] == 'r' || mode[0] == 'a' ) {
|
if( mode[0] == 'r' || mode[0] == 'a' ) {
|
||||||
z->in = fp;
|
z->in = fp;
|
||||||
|
|
||||||
|
unsigned long long seekcur = ftell(z->in);
|
||||||
|
|
||||||
JZEndRecord jzEndRecord = {0};
|
JZEndRecord jzEndRecord = {0};
|
||||||
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
||||||
REALLOC(z, 0);
|
REALLOC(z, 0);
|
||||||
return fclose(fp), ERR(NULL, "Couldn't read ZIP file end record.");
|
return fclose(fp), ERR(NULL, "Couldn't read ZIP file end record.");
|
||||||
}
|
}
|
||||||
if(jzReadCentralDirectory(fp, &jzEndRecord, zip__callback, z) != JZ_OK) {
|
|
||||||
|
jzEndRecord.centralDirectoryOffset += seekcur;
|
||||||
|
|
||||||
|
if(jzReadCentralDirectory(fp, &jzEndRecord, zip__callback, z, (void*)(uintptr_t)seekcur ) != JZ_OK) {
|
||||||
REALLOC(z, 0);
|
REALLOC(z, 0);
|
||||||
return fclose(fp), ERR(NULL, "Couldn't read ZIP file central directory.");
|
return fclose(fp), ERR(NULL, "Couldn't read ZIP file central directory.");
|
||||||
}
|
}
|
||||||
|
@ -252987,6 +253006,14 @@ zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
return fclose(fp), ERR(NULL, "Unknown open mode %s", mode);
|
return fclose(fp), ERR(NULL, "Unknown open mode %s", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
|
struct stat buffer;
|
||||||
|
int exists = (stat(file, &buffer) == 0);
|
||||||
|
if( mode[0] == 'a' && !exists ) mode = "wb";
|
||||||
|
FILE *fp = fopen(file, mode[0] == 'w' ? "wb" : mode[0] == 'a' ? "a+b" : "rb");
|
||||||
|
return zip_open_handle(fp, mode);
|
||||||
|
}
|
||||||
|
|
||||||
void zip_close(zip* z) {
|
void zip_close(zip* z) {
|
||||||
if( z->out && z->count ) {
|
if( z->out && z->count ) {
|
||||||
// prepare end record
|
// prepare end record
|
||||||
|
@ -253166,8 +253193,7 @@ tar *tar_open(const char *filename, const char *mode) {
|
||||||
|
|
||||||
*t = zero;
|
*t = zero;
|
||||||
t->in = in;
|
t->in = in;
|
||||||
tar__parse(in, tar__push_entry, t);
|
return tar__parse(in, tar__push_entry, t) ? t : NULL;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tar_find(tar *t, const char *entryname) {
|
int tar_find(tar *t, const char *entryname) {
|
||||||
|
@ -331461,16 +331487,26 @@ char* tempvl(const char *fmt, va_list vl) {
|
||||||
|
|
||||||
int reqlen = sz;
|
int reqlen = sz;
|
||||||
#if 0
|
#if 0
|
||||||
|
int heap = 0;
|
||||||
enum { STACK_ALLOC = 16384 };
|
enum { STACK_ALLOC = 16384 };
|
||||||
static __thread char buf[STACK_ALLOC];
|
static __thread char buf[STACK_ALLOC];
|
||||||
#else
|
#else
|
||||||
enum { STACK_ALLOC = 128*1024 };
|
int heap = 1;
|
||||||
|
static __thread int STACK_ALLOC = 128*1024;
|
||||||
static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak
|
static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak
|
||||||
#endif
|
#endif
|
||||||
static __thread int cur = 0, len = STACK_ALLOC - 1; //printf("string stack %d/%d\n", cur, STACK_ALLOC);
|
static __thread int cur = 0; //printf("string stack %d/%d\n", cur, STACK_ALLOC);
|
||||||
|
|
||||||
assert(reqlen < STACK_ALLOC && "no stack enough, increase STACK_ALLOC variable above");
|
if( reqlen >= STACK_ALLOC ) {
|
||||||
char* ptr = buf + (cur *= (cur+reqlen) < len, (cur += reqlen) - reqlen);
|
tty_color(RED);
|
||||||
|
printf("no stack enough, increase STACK_ALLOC variable above (reqlen:%d) (fmt: %s)\n", reqlen, fmt);
|
||||||
|
tty_color(0);
|
||||||
|
//assert(reqlen < STACK_ALLOC);
|
||||||
|
STACK_ALLOC = reqlen * 2;
|
||||||
|
buf = REALLOC(0, STACK_ALLOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* ptr = buf + (cur *= (cur+reqlen) < (STACK_ALLOC - 1), (cur += reqlen) - reqlen);
|
||||||
|
|
||||||
/*stbsp_*/vsnprintf( ptr, sz, fmt, vl );
|
/*stbsp_*/vsnprintf( ptr, sz, fmt, vl );
|
||||||
return (char *)ptr;
|
return (char *)ptr;
|
||||||
|
@ -332366,10 +332402,17 @@ float audio_volume_master(float gain) {
|
||||||
mixer.gain = volume_master;
|
mixer.gain = volume_master;
|
||||||
return sqrt( volume_master );
|
return sqrt( volume_master );
|
||||||
}
|
}
|
||||||
|
int audio_mute(int mute) {
|
||||||
|
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||||
|
if( mute >= 0 && mute <= 1 ) muted = mute;
|
||||||
|
return muted;
|
||||||
|
}
|
||||||
|
int audio_muted() {
|
||||||
|
return audio_mute(-1);
|
||||||
|
}
|
||||||
|
|
||||||
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
||||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
if(audio_muted()) return 1;
|
||||||
if(muted) return 1;
|
|
||||||
|
|
||||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||||
// do nothing, gain used as-is
|
// do nothing, gain used as-is
|
||||||
|
@ -335115,7 +335158,7 @@ array(struct fs) zipscan_filter(int threadid, int numthreads) {
|
||||||
|
|
||||||
// skip if list item does not belong to this thread bucket
|
// skip if list item does not belong to this thread bucket
|
||||||
uint64_t hash = hash_str(fname);
|
uint64_t hash = hash_str(fname);
|
||||||
unsigned bucket = (hash >> 32) % numthreads;
|
unsigned bucket = (hash /*>> 32*/) % numthreads;
|
||||||
if(bucket != threadid) continue;
|
if(bucket != threadid) continue;
|
||||||
|
|
||||||
array_push(fs, fs_now[i]);
|
array_push(fs, fs_now[i]);
|
||||||
|
@ -335372,10 +335415,8 @@ bool cook_start( const char *cook_ini, const char *masks, int flags ) {
|
||||||
char *s = strchr( ART, ';' ); if(s) *s = 0;
|
char *s = strchr( ART, ';' ); if(s) *s = 0;
|
||||||
char *w = strchr( ART, ' ' ); if(w) *w = 0;
|
char *w = strchr( ART, ' ' ); if(w) *w = 0;
|
||||||
char *out = 0; const char *sep = "";
|
char *out = 0; const char *sep = "";
|
||||||
const char *v4k_title = getenv("V4K_TITLE");
|
|
||||||
for each_substring(ART, ",", t) {
|
for each_substring(ART, ",", t) {
|
||||||
char *tmp = file_pathabs(va("%s%s", HOME, t)) + ART_LEN;
|
char *tmp = file_pathabs(va("%s%s", HOME, t)) + ART_LEN;
|
||||||
PRINTF("ART mount+=%s\n", tmp);
|
|
||||||
for(int i = 0; tmp[i]; ++i) if(tmp[i]=='\\') tmp[i] = '/';
|
for(int i = 0; tmp[i]; ++i) if(tmp[i]=='\\') tmp[i] = '/';
|
||||||
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
||||||
assert( out[strlen(out) - 1] == '/' );
|
assert( out[strlen(out) - 1] == '/' );
|
||||||
|
@ -336162,7 +336203,7 @@ bool file_delete(const char *pathfile) {
|
||||||
}
|
}
|
||||||
bool file_copy(const char *src, const char *dst) {
|
bool file_copy(const char *src, const char *dst) {
|
||||||
int ok = 0, BUFSIZE = 1 << 20; // 1 MiB
|
int ok = 0, BUFSIZE = 1 << 20; // 1 MiB
|
||||||
static __thread char *buffer = 0; do_once buffer = REALLOC(0, BUFSIZE);
|
static __thread char *buffer = 0; do_once buffer = REALLOC(0, BUFSIZE); // @leak
|
||||||
for( FILE *in = fopen(src, "rb"); in; fclose(in), in = 0) {
|
for( FILE *in = fopen(src, "rb"); in; fclose(in), in = 0) {
|
||||||
for( FILE *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
for( FILE *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
||||||
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
||||||
|
@ -336487,6 +336528,8 @@ void vfs_reload() {
|
||||||
#if defined(EMSCRIPTEN)
|
#if defined(EMSCRIPTEN)
|
||||||
vfs_mount("index.zip");
|
vfs_mount("index.zip");
|
||||||
#else
|
#else
|
||||||
|
// mount fused executables
|
||||||
|
vfs_mount(va("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")));
|
||||||
/* // old way
|
/* // old way
|
||||||
for( int i = 0; i < JOBS_MAX; ++i) {
|
for( int i = 0; i < JOBS_MAX; ++i) {
|
||||||
if( vfs_mount(va(".art[%02x].zip", i)) ) continue;
|
if( vfs_mount(va(".art[%02x].zip", i)) ) continue;
|
||||||
|
@ -336506,6 +336549,34 @@ void vfs_reload() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define ARK1 'ArK\x1'
|
||||||
|
#define ARK1_PADDING (512 - 40) // 472
|
||||||
|
#define ARK_PRINTF(f,...) 0 // printf(f,__VA_ARGS__)
|
||||||
|
#define ARK_SWAP32(x) (x)
|
||||||
|
#define ARK_SWAP64(x) (x)
|
||||||
|
#define ARK_REALLOC REALLOC
|
||||||
|
static uint64_t ark_fget64( FILE *in ) { uint64_t v; fread( &v, 1, 8, in ); return ARK_SWAP64(v); }
|
||||||
|
void ark_list( const char *infile, zip **z ) {
|
||||||
|
for( FILE *in = fopen(infile, "rb"); in; fclose(in), in = 0 )
|
||||||
|
while(!feof(in)) {
|
||||||
|
if( 0 != (ftell(in) % ARK1_PADDING) ) fseek(in, ARK1_PADDING - (ftell(in) % ARK1_PADDING), SEEK_CUR);
|
||||||
|
ARK_PRINTF("Reading at #%d\n", (int)ftell(in));
|
||||||
|
uint64_t mark = ark_fget64(in);
|
||||||
|
if( mark != ARK1 ) continue;
|
||||||
|
uint64_t stamp = ark_fget64(in);
|
||||||
|
uint64_t datalen = ark_fget64(in);
|
||||||
|
uint64_t datahash = ark_fget64(in);
|
||||||
|
uint64_t namelen = ark_fget64(in);
|
||||||
|
|
||||||
|
*z = zip_open_handle(in, "rb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||||
zip *z = NULL; tar *t = NULL; pak *p = NULL; dir *d = NULL;
|
zip *z = NULL; tar *t = NULL; pak *p = NULL; dir *d = NULL;
|
||||||
|
@ -336515,6 +336586,7 @@ bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||||
if( !is_folder ) z = zip_open(path, "rb");
|
if( !is_folder ) z = zip_open(path, "rb");
|
||||||
if( !is_folder && !z ) t = tar_open(path, "rb");
|
if( !is_folder && !z ) t = tar_open(path, "rb");
|
||||||
if( !is_folder && !z && !t ) p = pak_open(path, "rb");
|
if( !is_folder && !z && !t ) p = pak_open(path, "rb");
|
||||||
|
if( !is_folder && !z && !t && !p ) ark_list(path, &z); // last resort. try as .ark
|
||||||
if( !is_folder && !z && !t && !p ) return 0;
|
if( !is_folder && !z && !t && !p ) return 0;
|
||||||
|
|
||||||
// normalize input -> "././" to ""
|
// normalize input -> "././" to ""
|
||||||
|
@ -336699,9 +336771,9 @@ if( found && *found == 0 ) {
|
||||||
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
||||||
|
|
||||||
// search (last item)
|
// search (last item)
|
||||||
static char last_item[256] = { 0 };
|
static __thread char last_item[256] = { 0 };
|
||||||
static void *last_ptr = 0;
|
static __thread void *last_ptr = 0;
|
||||||
static int last_size = 0;
|
static __thread int last_size = 0;
|
||||||
if( !strcmpi(lookup_id, last_item)) {
|
if( !strcmpi(lookup_id, last_item)) {
|
||||||
ptr = last_ptr;
|
ptr = last_ptr;
|
||||||
size = last_size;
|
size = last_size;
|
||||||
|
@ -336858,6 +336930,10 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
if( !MAX_CACHED_FILES ) return 0;
|
if( !MAX_CACHED_FILES ) return 0;
|
||||||
if( !ptr || !size ) return 0;
|
if( !ptr || !size ) return 0;
|
||||||
|
|
||||||
|
// keep cached files within limits
|
||||||
|
static thread_mutex_t mutex, *init = 0; if(!init) thread_mutex_init(init = &mutex);
|
||||||
|
thread_mutex_lock(&mutex);
|
||||||
|
|
||||||
// append to cache
|
// append to cache
|
||||||
archive_dir zero = {0}, *old = dir_cache;
|
archive_dir zero = {0}, *old = dir_cache;
|
||||||
*(dir_cache = REALLOC(0, sizeof(archive_dir))) = zero;
|
*(dir_cache = REALLOC(0, sizeof(archive_dir))) = zero;
|
||||||
|
@ -336867,7 +336943,8 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
dir_cache->data = REALLOC(0, size+1);
|
dir_cache->data = REALLOC(0, size+1);
|
||||||
memcpy(dir_cache->data, ptr, size); size[(char*)dir_cache->data] = 0; // copy+terminator
|
memcpy(dir_cache->data, ptr, size); size[(char*)dir_cache->data] = 0; // copy+terminator
|
||||||
|
|
||||||
// keep cached files within limits
|
void *found = 0;
|
||||||
|
|
||||||
static int added = 0;
|
static int added = 0;
|
||||||
if( added < MAX_CACHED_FILES ) {
|
if( added < MAX_CACHED_FILES ) {
|
||||||
++added;
|
++added;
|
||||||
|
@ -336876,15 +336953,18 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
for( archive_dir *prev = dir_cache, *dir = prev; dir ; prev = dir, dir = dir->next ) {
|
for( archive_dir *prev = dir_cache, *dir = prev; dir ; prev = dir, dir = dir->next ) {
|
||||||
if( !dir->next ) {
|
if( !dir->next ) {
|
||||||
prev->next = 0; // break link
|
prev->next = 0; // break link
|
||||||
void *data = dir->data;
|
found = dir->data;
|
||||||
dir->path = REALLOC(dir->path, 0);
|
dir->path = REALLOC(dir->path, 0);
|
||||||
dir->data = REALLOC(dir->data, 0);
|
dir->data = REALLOC(dir->data, 0);
|
||||||
dir = REALLOC(dir, 0);
|
dir = REALLOC(dir, 0);
|
||||||
return data;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
thread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -343657,8 +343737,8 @@ static map(unsigned, reflected_t) reflects;
|
||||||
static map(unsigned, array(reflected_t)) members;
|
static map(unsigned, array(reflected_t)) members;
|
||||||
|
|
||||||
void reflected_printf(reflected_t *r) {
|
void reflected_printf(reflected_t *r) {
|
||||||
printf("id:%u objtype:%u sz:%u name:%s info:%s addr:%p parent:%u type:%s",
|
printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s",
|
||||||
r->id, r->objtype, r->sz, r->name ? r->name : "", r->info ? r->info : "", r->addr, r->parent, r->type ? r->type : "");
|
r->name ? r->name : "", r->info ? r->info : "", r->id, r->objtype, r->sz, r->addr, r->parent, r->type ? r->type : "");
|
||||||
}
|
}
|
||||||
void reflected_printf_all() {
|
void reflected_printf_all() {
|
||||||
for each_map_ptr(reflects, unsigned, k, reflected_t, p) {
|
for each_map_ptr(reflects, unsigned, k, reflected_t, p) {
|
||||||
|
@ -351231,6 +351311,26 @@ bool app_open(const char *link) {
|
||||||
return app_open_url(link);
|
return app_open_url(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* app_loadfile() {
|
||||||
|
const char *windowTitle = NULL;
|
||||||
|
const char *defaultPathFile = NULL;
|
||||||
|
const char *filterHints = NULL; // "image files"
|
||||||
|
const char *filters[] = { "*.*" };
|
||||||
|
int allowMultipleSelections = 0;
|
||||||
|
|
||||||
|
tinyfd_assumeGraphicDisplay = 1;
|
||||||
|
return tinyfd_openFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints, allowMultipleSelections );
|
||||||
|
}
|
||||||
|
const char* app_savefile() {
|
||||||
|
const char *windowTitle = NULL;
|
||||||
|
const char *defaultPathFile = NULL;
|
||||||
|
const char *filterHints = NULL; // "image files"
|
||||||
|
const char *filters[] = { "*.*" };
|
||||||
|
|
||||||
|
tinyfd_assumeGraphicDisplay = 1;
|
||||||
|
return tinyfd_saveFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints );
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// tests
|
// tests
|
||||||
|
|
||||||
|
@ -352817,11 +352917,12 @@ int ui_collapse_end() {
|
||||||
|
|
||||||
|
|
||||||
int ui_contextual() {
|
int ui_contextual() {
|
||||||
struct nk_rect bounds = nk_widget_bounds(ui_ctx);
|
struct nk_rect bounds = nk_widget_bounds(ui_ctx); // = nk_window_get_bounds(ui_ctx);
|
||||||
bounds.y -= 25;
|
bounds.y -= 25;
|
||||||
return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds);
|
return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds);
|
||||||
}
|
}
|
||||||
int ui_contextual_end() {
|
int ui_contextual_end(int close) {
|
||||||
|
if(close) nk_contextual_close(ui_ctx);
|
||||||
nk_contextual_end(ui_ctx);
|
nk_contextual_end(ui_ctx);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -352832,7 +352933,7 @@ int ui_submenu(const char *options) {
|
||||||
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
||||||
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
||||||
}
|
}
|
||||||
ui_contextual_end();
|
ui_contextual_end(0);
|
||||||
}
|
}
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
@ -352966,8 +353067,10 @@ int ui_label(const char *text) {
|
||||||
int ui_label2(const char *label, const char *text_) {
|
int ui_label2(const char *label, const char *text_) {
|
||||||
nk_layout_row_dynamic(ui_ctx, 0, 2);
|
nk_layout_row_dynamic(ui_ctx, 0, 2);
|
||||||
|
|
||||||
int align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
int align1 = NK_TEXT_LEFT;
|
||||||
int align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
int align2 = NK_TEXT_LEFT;
|
||||||
|
if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||||
|
if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||||
ui_label_(label, align1);
|
ui_label_(label, align1);
|
||||||
|
|
||||||
const struct nk_input *input = &ui_ctx->input;
|
const struct nk_input *input = &ui_ctx->input;
|
||||||
|
@ -354702,12 +354805,38 @@ int window_frame_begin() {
|
||||||
if( may_render_stats ) {
|
if( may_render_stats ) {
|
||||||
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
||||||
|
|
||||||
#if 1
|
static int time_factor = 0;
|
||||||
static char *filter = 0;
|
static int playing = 0;
|
||||||
|
static int paused = 0;
|
||||||
|
int advance_frame = 0;
|
||||||
|
|
||||||
static int do_filter = 0;
|
static int do_filter = 0;
|
||||||
|
static int do_profile = 0;
|
||||||
|
static int do_extra = 0;
|
||||||
|
|
||||||
|
char *EDITOR_TOOLBAR_ICONS = va("%s;%s;%s;%s;%s;%s;%s;%s",
|
||||||
|
do_filter ? ICON_MD_CLOSE : ICON_MD_SEARCH,
|
||||||
|
ICON_MD_PLAY_ARROW,
|
||||||
|
paused ? ICON_MD_SKIP_NEXT : ICON_MD_PAUSE,
|
||||||
|
ICON_MD_FAST_FORWARD,
|
||||||
|
ICON_MD_STOP,
|
||||||
|
ICON_MD_REPLAY,
|
||||||
|
ICON_MD_FACE,
|
||||||
|
ICON_MD_MENU
|
||||||
|
);
|
||||||
|
|
||||||
if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1;
|
if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1;
|
||||||
int choice = ui_toolbar(ICON_MD_SEARCH ";");
|
int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS);
|
||||||
if( choice == 1 ) do_filter = 1;
|
if( choice == 1 ) do_filter ^= 1, do_profile = 0, do_extra = 0;
|
||||||
|
if( choice == 2 ) playing = 1, paused = 0;
|
||||||
|
if( choice == 3 ) advance_frame = !!paused, paused = 1;
|
||||||
|
if( choice == 4 ) paused = 0, time_factor = (++time_factor) % 4;
|
||||||
|
if( choice == 5 ) playing = 0, paused = 0, advance_frame = 0, time_factor = 0;
|
||||||
|
if( choice == 6 ) window_reload();
|
||||||
|
if( choice == 7 ) do_filter = 0, do_profile ^= 1, do_extra = 0;
|
||||||
|
if( choice == 8 ) do_filter = 0, do_profile = 0, do_extra ^= 1;
|
||||||
|
|
||||||
|
static char *filter = 0;
|
||||||
if( do_filter ) {
|
if( do_filter ) {
|
||||||
ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter);
|
ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter);
|
||||||
if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon)
|
if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon)
|
||||||
|
@ -354717,13 +354846,44 @@ int window_frame_begin() {
|
||||||
if( filter ) filter[0] = '\0';
|
if( filter ) filter[0] = '\0';
|
||||||
}
|
}
|
||||||
char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*";
|
char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*";
|
||||||
#endif
|
|
||||||
|
static char *username = 0;
|
||||||
|
static char *userpass = 0;
|
||||||
|
if( do_profile ) {
|
||||||
|
ui_string(ICON_MD_FACE " Username", &username);
|
||||||
|
ui_string(ICON_MD_FACE " Password", &userpass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( do_extra ) {
|
||||||
|
int choice2 = ui_label2_toolbar(NULL,
|
||||||
|
ICON_MD_VIEW_IN_AR
|
||||||
|
ICON_MD_MESSAGE
|
||||||
|
ICON_MD_TIPS_AND_UPDATES ICON_MD_LIGHTBULB ICON_MD_LIGHTBULB_OUTLINE
|
||||||
|
ICON_MD_IMAGE_SEARCH ICON_MD_INSERT_PHOTO
|
||||||
|
ICON_MD_VIDEOGAME_ASSET ICON_MD_VIDEOGAME_ASSET_OFF
|
||||||
|
|
||||||
|
ICON_MD_VOLUME_UP ICON_MD_VOLUME_OFF // audio_volume_master(-1) > 0
|
||||||
|
|
||||||
|
ICON_MD_TROUBLESHOOT ICON_MD_SCHEMA ICON_MD_MENU
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
int open = 0, clicked_or_toggled = 0;
|
int open = 0, clicked_or_toggled = 0;
|
||||||
|
|
||||||
#define ui_collapse_filtered(lbl,id) (strmatchi(lbl,filter_mask) && ui_collapse(lbl,id))
|
#define ui_collapse_filtered(lbl,id) (strmatchi(lbl,filter_mask) && ui_collapse(lbl,id))
|
||||||
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
#define EDITOR_UI_COLLAPSE(f,...) \
|
||||||
|
for( int macro(p) = (open = ui_collapse_filtered(f,__VA_ARGS__)), macro(dummy) = (clicked_or_toggled = ui_collapse_clicked()); macro(p); ui_collapse_end(), macro(p) = 0)
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUG_REPORT " Bugs 0", "Debug.Bugs") {
|
||||||
|
// @todo. parse /bugs.ini, includes saved screenshots & videos.
|
||||||
|
// @todo. screenshot include parseable level, position screen markers (same info as /bugs.ini)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Art and bookmarks
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art") {
|
||||||
bool inlined = true;
|
bool inlined = true;
|
||||||
const char *file = 0;
|
const char *file = 0;
|
||||||
if( ui_browse(&file, &inlined) ) {
|
if( ui_browse(&file, &inlined) ) {
|
||||||
|
@ -354731,47 +354891,78 @@ int window_frame_begin() {
|
||||||
app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep));
|
app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_BOOKMARK " Bookmarks", "Debug.Bookmarks") { /* @todo */ }
|
||||||
|
|
||||||
|
|
||||||
|
// E,C,S,W
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Scene", "Debug.Scene") {
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUBBLE_CHART/*ICON_MD_SCATTER_PLOT*/ " Entities", "Debug.Entities") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_TUNE " Components", "Debug.Components") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_PRECISION_MANUFACTURING " Systems", "Debug.Systems") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_PUBLIC " Levels", "Debug.Levels") {
|
||||||
|
//node_edit(editor.edit.down,&editor.edit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Init", "Debug.HierarchyInit") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Draw", "Debug.HierarchyDraw") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Tick", "Debug.HierarchyTick") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Edit", "Debug.HierarchyEdit") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Quit", "Debug.HierarchyQuit") { /* @todo */ }
|
||||||
|
|
||||||
|
// node_edit(&editor.init,&editor.init);
|
||||||
|
// node_edit(&editor.draw,&editor.draw);
|
||||||
|
// node_edit(&editor.tick,&editor.tick);
|
||||||
|
// node_edit(&editor.edit,&editor.edit);
|
||||||
|
// node_edit(&editor.quit,&editor.quit);
|
||||||
|
}
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI") {
|
||||||
// @todo
|
// @todo
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VOLUME_UP " Audio", "Debug.Audio")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_VOLUME_UP " Audio", "Debug.Audio") {
|
||||||
ui_audio();
|
ui_audio();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VIDEOCAM " Camera", "Debug.Camera")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_VIDEOCAM " Camera", "Debug.Camera") {
|
||||||
ui_camera( camera_get_active() );
|
ui_camera( camera_get_active() );
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_BUILD " Cook", "Debug.Cook")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") {
|
||||||
// @todo
|
// @todo: fps lock, fps target, aspect ratio, fullscreen
|
||||||
|
char *text = va("%s;%s;%s",
|
||||||
|
window_has_fullscreen() ? ICON_MD_FULLSCREEN_EXIT : ICON_MD_FULLSCREEN,
|
||||||
|
ICON_MD_PHOTO_CAMERA,
|
||||||
|
record_active() ? ICON_MD_VIDEOCAM_OFF : ICON_MD_VIDEOCAM
|
||||||
|
);
|
||||||
|
|
||||||
|
int choice = ui_toolbar(text);
|
||||||
|
if( choice == 1 ) editor_send("key_fullscreen",0);
|
||||||
|
if( choice == 2 ) editor_send("key_screenshot",0);
|
||||||
|
if( choice == 3 ) editor_send("key_record",0);
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_SIGNAL_CELLULAR_ALT " Network", "Debug.Network")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") {
|
||||||
// @todo
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
// @todo
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_MOVIE " FXs", "Debug.FXs")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_fxs();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_SPEED " Profiler", "Debug.Profiler")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_profiler();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_shaders();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_keyboard();
|
ui_keyboard();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_MOUSE " Mouse", "Debug.Mouse")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_MOUSE " Mouse", "Debug.Mouse") {
|
||||||
ui_mouse();
|
ui_mouse();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads") {
|
||||||
for( int q = 0; q < 4; ++q ) {
|
for( int q = 0; q < 4; ++q ) {
|
||||||
for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) {
|
for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) {
|
||||||
ui_gamepad(q);
|
ui_gamepad(q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VIEW_QUILT " UI", "Debug.UI")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders") {
|
||||||
|
ui_shaders();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_MOVIE " FXs", "Debug.FXs") {
|
||||||
|
ui_fxs();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_VIEW_QUILT " UI", "Debug.UI") {
|
||||||
int choice = ui_toolbar(ICON_MD_RECYCLING " Reset layout;" ICON_MD_SAVE_AS " Save layout");
|
int choice = ui_toolbar(ICON_MD_RECYCLING " Reset layout;" ICON_MD_SAVE_AS " Save layout");
|
||||||
if( choice == 1 ) ui_layout_all_reset("*");
|
if( choice == 1 ) ui_layout_all_reset("*");
|
||||||
if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*");
|
if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*");
|
||||||
|
@ -354784,8 +354975,61 @@ int window_frame_begin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_SAVINGS " Budgets", "Debug.Budgets") {
|
||||||
|
// @todo. // mem,fps,gfx,net,hdd,... also logging
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_WIFI/*ICON_MD_SIGNAL_CELLULAR_ALT*/ " Network 0/0 KiB", "Debug.Network") {
|
||||||
|
// @todo
|
||||||
|
// SIGNAL_CELLULAR_1_BAR SIGNAL_CELLULAR_2_BAR
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%d", window_fps(), (int)window_fps_target()), "Debug.Profiler") {
|
||||||
|
ui_profiler();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// logic: either plug icon (power saving off) or one of the following ones (power saving on):
|
||||||
|
// if 0% batt (no batt): battery alert
|
||||||
|
// if discharging: battery levels [alert,0..6,full]
|
||||||
|
// if charging: battery charging
|
||||||
|
int battery_read = app_battery();
|
||||||
|
int battery_level = abs(battery_read);
|
||||||
|
int battery_discharging = battery_read < 0 && battery_level < 100;
|
||||||
|
const char *power_icon_label = ICON_MD_POWER " Power";
|
||||||
|
if( battery_level ) {
|
||||||
|
const char *battery_levels[9] = { // @todo: remap [7%..100%] -> [0..1] ?
|
||||||
|
ICON_MD_BATTERY_ALERT,ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR,
|
||||||
|
ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR,ICON_MD_BATTERY_4_BAR,
|
||||||
|
ICON_MD_BATTERY_5_BAR,ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL,
|
||||||
|
};
|
||||||
|
power_icon_label = (const char*)va("%s Power %d%%",
|
||||||
|
battery_discharging ? battery_levels[(int)((9-1)*clampf(battery_level/100.f,0,1))] : ICON_MD_BATTERY_CHARGING_FULL,
|
||||||
|
battery_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") {
|
||||||
|
int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT );
|
||||||
|
if( choice == 1 ) editor_send("key_battery","0");
|
||||||
|
if( choice == 2 ) editor_send("key_battery","1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_EXTENSION " Plugins", "Debug.Plugins") {
|
||||||
|
// @todo. include VCS
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUILD " Cook", "Debug.Cook") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(has_menu ? ui_window_end : ui_panel_end)();
|
(has_menu ? ui_window_end : ui_panel_end)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API int editor_tick();
|
||||||
|
editor_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // deprecated
|
#if 0 // deprecated
|
||||||
|
@ -356186,6 +356430,61 @@ int ui_bt(bt_t *b) {
|
||||||
// editing:
|
// editing:
|
||||||
// nope > functions: add/rem property
|
// nope > functions: add/rem property
|
||||||
|
|
||||||
|
#define ICON_PLAY ICON_MD_PLAY_ARROW
|
||||||
|
#define ICON_PAUSE ICON_MD_PAUSE
|
||||||
|
#define ICON_STOP ICON_MD_STOP
|
||||||
|
#define ICON_CANCEL ICON_MD_CLOSE
|
||||||
|
|
||||||
|
#define ICON_WARNING ICON_MD_WARNING
|
||||||
|
#define ICON_BROWSER ICON_MD_FOLDER_SPECIAL
|
||||||
|
#define ICON_OUTLINER ICON_MD_VIEW_IN_AR
|
||||||
|
#define ICON_BUILD ICON_MD_BUILD
|
||||||
|
#define ICON_SCREENSHOT ICON_MD_PHOTO_CAMERA
|
||||||
|
#define ICON_CAMERA_ON ICON_MD_VIDEOCAM
|
||||||
|
#define ICON_CAMERA_OFF ICON_MD_VIDEOCAM_OFF
|
||||||
|
#define ICON_GAMEPAD_ON ICON_MD_VIDEOGAME_ASSET
|
||||||
|
#define ICON_GAMEPAD_OFF ICON_MD_VIDEOGAME_ASSET_OFF
|
||||||
|
#define ICON_AUDIO_ON ICON_MD_VOLUME_UP
|
||||||
|
#define ICON_AUDIO_OFF ICON_MD_VOLUME_OFF
|
||||||
|
#define ICON_WINDOWED ICON_MD_FULLSCREEN_EXIT
|
||||||
|
#define ICON_FULLSCREEN ICON_MD_FULLSCREEN
|
||||||
|
#define ICON_LIGHTS_ON ICON_MD_LIGHTBULB
|
||||||
|
#define ICON_LIGHTS_OFF ICON_MD_LIGHTBULB_OUTLINE
|
||||||
|
#define ICON_RENDER_BASIC ICON_MD_IMAGE_SEARCH
|
||||||
|
#define ICON_RENDER_FULL ICON_MD_INSERT_PHOTO
|
||||||
|
|
||||||
|
#define ICON_SIGNAL ICON_MD_SIGNAL_CELLULAR_ALT
|
||||||
|
#define ICON_DISK ICON_MD_STORAGE
|
||||||
|
#define ICON_RATE ICON_MD_SPEED
|
||||||
|
|
||||||
|
#define ICON_CLOCK ICON_MD_TODAY
|
||||||
|
#define ICON_CHRONO ICON_MD_TIMELAPSE
|
||||||
|
|
||||||
|
#define ICON_SETTINGS ICON_MD_SETTINGS
|
||||||
|
#define ICON_LANGUAGE ICON_MD_G_TRANSLATE
|
||||||
|
#define ICON_PERSONA ICON_MD_FACE
|
||||||
|
#define ICON_SOCIAL ICON_MD_MESSAGE
|
||||||
|
#define ICON_GAME ICON_MD_ROCKET_LAUNCH
|
||||||
|
#define ICON_KEYBOARD ICON_MD_KEYBOARD
|
||||||
|
#define ICON_MOUSE ICON_MD_MOUSE
|
||||||
|
#define ICON_GAMEPAD ICON_MD_GAMEPAD
|
||||||
|
#define ICON_MONITOR ICON_MD_MONITOR
|
||||||
|
#define ICON_WIFI ICON_MD_WIFI
|
||||||
|
#define ICON_BUDGET ICON_MD_SAVINGS
|
||||||
|
#define ICON_NEW_FOLDER ICON_MD_CREATE_NEW_FOLDER
|
||||||
|
#define ICON_PLUGIN ICON_MD_EXTENSION
|
||||||
|
#define ICON_RESTART ICON_MD_REPLAY
|
||||||
|
#define ICON_QUIT ICON_MD_CLOSE
|
||||||
|
|
||||||
|
#define ICON_POWER ICON_MD_BOLT // ICON_MD_POWER
|
||||||
|
#define ICON_BATTERY_CHARGING ICON_MD_BATTERY_CHARGING_FULL
|
||||||
|
#define ICON_BATTERY_LEVELS \
|
||||||
|
ICON_MD_BATTERY_ALERT, \
|
||||||
|
ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR, \
|
||||||
|
ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR, \
|
||||||
|
ICON_MD_BATTERY_4_BAR,ICON_MD_BATTERY_5_BAR, \
|
||||||
|
ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL
|
||||||
|
|
||||||
char *editor_path(const char *path) {
|
char *editor_path(const char *path) {
|
||||||
return va("%s/%s", EDITOR, path);
|
return va("%s/%s", EDITOR, path);
|
||||||
}
|
}
|
||||||
|
@ -356250,6 +356549,75 @@ int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate
|
||||||
return clicked | (copy ^ *enabled);
|
return clicked | (copy ^ *enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef union editor_var {
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
char *s;
|
||||||
|
} editor_var;
|
||||||
|
static map(char*,editor_var) editor_vars;
|
||||||
|
float *editor_getf(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
return &found->f;
|
||||||
|
}
|
||||||
|
int *editor_geti(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
return &found->i;
|
||||||
|
}
|
||||||
|
char **editor_gets(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
if(!found->s) found->s = stringf("%s","");
|
||||||
|
return &found->s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editor_send(const char *cmd, const char *optional_value) {
|
||||||
|
unsigned *gamepads = editor_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)...
|
||||||
|
unsigned *renders = editor_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes
|
||||||
|
float *speed = editor_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8)
|
||||||
|
unsigned *powersave = editor_geti("powersave");
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
/**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0);
|
||||||
|
else if( !strcmp(cmd, "key_stop" )) window_pause(1);
|
||||||
|
else if( !strcmp(cmd, "key_mute" )) audio_volume_master( 1 ^ !!audio_volume_master(-1) );
|
||||||
|
else if( !strcmp(cmd, "key_pause" )) window_pause( window_has_pause() ^ 1 );
|
||||||
|
else if( !strcmp(cmd, "key_reload" )) window_reload();
|
||||||
|
else if( !strcmp(cmd, "key_battery" )) *powersave = optional_value ? !!atoi(optional_value) : *powersave ^ 1;
|
||||||
|
else if( !strcmp(cmd, "key_browser" )) ui_show("File Browser", ui_visible("File Browser") ^ true);
|
||||||
|
else if( !strcmp(cmd, "key_outliner" )) ui_show("Outliner", ui_visible("Outliner") ^ true);
|
||||||
|
else if( !strcmp(cmd, "key_record" )) if(record_active()) record_stop(); else
|
||||||
|
name = file_counter(va("%s.mp4",app_name())), window_record(name), ui_notify(va("Video capturing: %s", name), date_string());
|
||||||
|
else if( !strcmp(cmd, "key_screenshot" )) name = file_counter(va("%s.png",app_name())), window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string());
|
||||||
|
else if( !strcmp(cmd, "key_profiler" )) ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true));
|
||||||
|
else if( !strcmp(cmd, "key_fullscreen" )) record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); // framebuffer resizing corrupts video stream, so stop any recording beforehand
|
||||||
|
else if( !strcmp(cmd, "key_gamepad" )) *gamepads = (*gamepads & ~1u) | ((*gamepads & 1) ^ 1);
|
||||||
|
else if( !strcmp(cmd, "key_lit" )) *renders = (*renders & ~1u) | ((*renders & 1) ^ 1);
|
||||||
|
else if( !strcmp(cmd, "key_ddraw" )) *renders = (*renders & ~2u) | ((*renders & 2) ^ 2);
|
||||||
|
else alert(va("editor could not handle `%s` command.", cmd));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editor_tick() {
|
||||||
|
enum { editor_hz = 60 };
|
||||||
|
enum { editor_hz_mid = 18 };
|
||||||
|
enum { editor_hz_low = 5 };
|
||||||
|
if( *editor_geti("powersave") ) {
|
||||||
|
// adaptive framerate
|
||||||
|
int app_on_background = !window_has_focus();
|
||||||
|
int hz = app_on_background ? editor_hz_low : editor_hz_mid;
|
||||||
|
window_fps_lock( hz < 5 ? 5 : hz );
|
||||||
|
} else {
|
||||||
|
// window_fps_lock( editor_hz );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int gizmo__mode;
|
static int gizmo__mode;
|
||||||
static int gizmo__active;
|
static int gizmo__active;
|
||||||
static int gizmo__hover;
|
static int gizmo__hover;
|
||||||
|
@ -356361,26 +356729,6 @@ int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* dialog_load() {
|
|
||||||
const char *windowTitle = NULL;
|
|
||||||
const char *defaultPathFile = NULL;
|
|
||||||
const char *filterHints = NULL; // "image files"
|
|
||||||
const char *filters[] = { "*.*" };
|
|
||||||
int allowMultipleSelections = 0;
|
|
||||||
|
|
||||||
tinyfd_assumeGraphicDisplay = 1;
|
|
||||||
return tinyfd_openFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints, allowMultipleSelections );
|
|
||||||
}
|
|
||||||
char* dialog_save() {
|
|
||||||
const char *windowTitle = NULL;
|
|
||||||
const char *defaultPathFile = NULL;
|
|
||||||
const char *filterHints = NULL; // "image files"
|
|
||||||
const char *filters[] = { "*.*" };
|
|
||||||
|
|
||||||
tinyfd_assumeGraphicDisplay = 1;
|
|
||||||
return tinyfd_saveFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints );
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- localization kit
|
// -- localization kit
|
||||||
|
|
||||||
static const char *kit_lang = "enUS", *kit_langs =
|
static const char *kit_lang = "enUS", *kit_langs =
|
||||||
|
@ -356554,18 +356902,20 @@ static void v4k_pre_init() {
|
||||||
// window_swap();
|
// window_swap();
|
||||||
}
|
}
|
||||||
static void v4k_post_init(float refresh_rate) {
|
static void v4k_post_init(float refresh_rate) {
|
||||||
|
int i;
|
||||||
|
|
||||||
// cook cleanup
|
// cook cleanup
|
||||||
cook_stop();
|
cook_stop();
|
||||||
|
|
||||||
vfs_reload();
|
vfs_reload();
|
||||||
|
|
||||||
|
// init subsystems that depend on cooked assets now. ui_init() is special case and needs to be safely in single thread
|
||||||
|
ui_init();
|
||||||
|
|
||||||
// init more subsystems; beware of VFS mounting, as some of these may need cooked assets at this point
|
// init more subsystems; beware of VFS mounting, as some of these may need cooked assets at this point
|
||||||
int i;
|
|
||||||
#if 1 // #ifdef PARALLEL_INIT
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
#endif
|
|
||||||
for( i = 0; i <= 3; ++i) {
|
for( i = 0; i <= 3; ++i) {
|
||||||
/**/ if( i == 0 ) ui_init(), scene_init(); // init these on thread #0, since both will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
/**/ if( i == 0 ) scene_init(); // init these on thread #0, since both will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
||||||
else if( i == 1 ) audio_init(0); // initialize audio after cooking // reasoning for this: do not launch audio threads while cooks are in progress, so there is more cpu for cooking actually
|
else if( i == 1 ) audio_init(0); // initialize audio after cooking // reasoning for this: do not launch audio threads while cooks are in progress, so there is more cpu for cooking actually
|
||||||
else if( i == 2 ) script_init(), kit_init(), midi_init();
|
else if( i == 2 ) script_init(), kit_init(), midi_init();
|
||||||
else if( i == 3 ) input_init(), network_init();
|
else if( i == 3 ) input_init(), network_init();
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
typedef struct zip zip;
|
typedef struct zip zip;
|
||||||
|
|
||||||
zip* zip_open(const char *file, const char *mode /*r,w,a*/);
|
zip* zip_open(const char *file, const char *mode /*r,w,a*/);
|
||||||
|
zip* zip_open_handle(FILE*fp, const char *mode /*r,w,a*/);
|
||||||
|
|
||||||
// only for (w)rite or (a)ppend mode
|
// only for (w)rite or (a)ppend mode
|
||||||
bool zip_append_file(zip*, const char *entryname, const char *comment, FILE *in, unsigned compress_level);
|
bool zip_append_file(zip*, const char *entryname, const char *comment, FILE *in, unsigned compress_level);
|
||||||
|
@ -246,7 +247,7 @@ int jzReadEndRecord(FILE *fp, JZEndRecord *endRecord) {
|
||||||
|
|
||||||
// Read ZIP file global directory. Will move within file. Returns Z_OK, or error code
|
// Read ZIP file global directory. Will move within file. Returns Z_OK, or error code
|
||||||
// Callback is called for each record, until callback returns zero
|
// Callback is called for each record, until callback returns zero
|
||||||
int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback callback, void *user_data) {
|
int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback callback, void *user_data, void *user_data2) {
|
||||||
JZGlobalFileHeader fileHeader;
|
JZGlobalFileHeader fileHeader;
|
||||||
|
|
||||||
if(fseek(fp, endRecord->centralDirectoryOffset, SEEK_SET)) {
|
if(fseek(fp, endRecord->centralDirectoryOffset, SEEK_SET)) {
|
||||||
|
@ -261,6 +262,8 @@ int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback ca
|
||||||
return ERR(JZ_ERRNO, "Couldn't read file header #%d!", i);
|
return ERR(JZ_ERRNO, "Couldn't read file header #%d!", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileHeader.relativeOffsetOflocalHeader += (uintptr_t)user_data2;
|
||||||
|
|
||||||
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
||||||
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
||||||
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
||||||
|
@ -753,11 +756,7 @@ common:;
|
||||||
|
|
||||||
// zip common
|
// zip common
|
||||||
|
|
||||||
zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
zip* zip_open_handle(FILE *fp, const char *mode) {
|
||||||
struct stat buffer;
|
|
||||||
int exists = (stat(file, &buffer) == 0);
|
|
||||||
if( mode[0] == 'a' && !exists ) mode = "wb";
|
|
||||||
FILE *fp = fopen(file, mode[0] == 'w' ? "wb" : mode[0] == 'a' ? "a+b" : "rb");
|
|
||||||
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
||||||
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
||||||
if( !z ) return fclose(fp), ERR(NULL, "out of mem"); else *z = zero;
|
if( !z ) return fclose(fp), ERR(NULL, "out of mem"); else *z = zero;
|
||||||
|
@ -768,12 +767,17 @@ zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
if( mode[0] == 'r' || mode[0] == 'a' ) {
|
if( mode[0] == 'r' || mode[0] == 'a' ) {
|
||||||
z->in = fp;
|
z->in = fp;
|
||||||
|
|
||||||
|
unsigned long long seekcur = ftell(z->in);
|
||||||
|
|
||||||
JZEndRecord jzEndRecord = {0};
|
JZEndRecord jzEndRecord = {0};
|
||||||
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
||||||
REALLOC(z, 0);
|
REALLOC(z, 0);
|
||||||
return fclose(fp), ERR(NULL, "Couldn't read ZIP file end record.");
|
return fclose(fp), ERR(NULL, "Couldn't read ZIP file end record.");
|
||||||
}
|
}
|
||||||
if(jzReadCentralDirectory(fp, &jzEndRecord, zip__callback, z) != JZ_OK) {
|
|
||||||
|
jzEndRecord.centralDirectoryOffset += seekcur;
|
||||||
|
|
||||||
|
if(jzReadCentralDirectory(fp, &jzEndRecord, zip__callback, z, (void*)(uintptr_t)seekcur ) != JZ_OK) {
|
||||||
REALLOC(z, 0);
|
REALLOC(z, 0);
|
||||||
return fclose(fp), ERR(NULL, "Couldn't read ZIP file central directory.");
|
return fclose(fp), ERR(NULL, "Couldn't read ZIP file central directory.");
|
||||||
}
|
}
|
||||||
|
@ -801,6 +805,14 @@ zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
return fclose(fp), ERR(NULL, "Unknown open mode %s", mode);
|
return fclose(fp), ERR(NULL, "Unknown open mode %s", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
|
struct stat buffer;
|
||||||
|
int exists = (stat(file, &buffer) == 0);
|
||||||
|
if( mode[0] == 'a' && !exists ) mode = "wb";
|
||||||
|
FILE *fp = fopen(file, mode[0] == 'w' ? "wb" : mode[0] == 'a' ? "a+b" : "rb");
|
||||||
|
return zip_open_handle(fp, mode);
|
||||||
|
}
|
||||||
|
|
||||||
void zip_close(zip* z) {
|
void zip_close(zip* z) {
|
||||||
if( z->out && z->count ) {
|
if( z->out && z->count ) {
|
||||||
// prepare end record
|
// prepare end record
|
||||||
|
@ -980,8 +992,7 @@ tar *tar_open(const char *filename, const char *mode) {
|
||||||
|
|
||||||
*t = zero;
|
*t = zero;
|
||||||
t->in = in;
|
t->in = in;
|
||||||
tar__parse(in, tar__push_entry, t);
|
return tar__parse(in, tar__push_entry, t) ? t : NULL;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tar_find(tar *t, const char *entryname) {
|
int tar_find(tar *t, const char *entryname) {
|
||||||
|
|
|
@ -385,10 +385,17 @@ float audio_volume_master(float gain) {
|
||||||
mixer.gain = volume_master;
|
mixer.gain = volume_master;
|
||||||
return sqrt( volume_master );
|
return sqrt( volume_master );
|
||||||
}
|
}
|
||||||
|
int audio_mute(int mute) {
|
||||||
|
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||||
|
if( mute >= 0 && mute <= 1 ) muted = mute;
|
||||||
|
return muted;
|
||||||
|
}
|
||||||
|
int audio_muted() {
|
||||||
|
return audio_mute(-1);
|
||||||
|
}
|
||||||
|
|
||||||
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
||||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
if(audio_muted()) return 1;
|
||||||
if(muted) return 1;
|
|
||||||
|
|
||||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||||
// do nothing, gain used as-is
|
// do nothing, gain used as-is
|
||||||
|
|
|
@ -24,9 +24,12 @@ API int audio_play_gain_pitch( audio_t a, int flags, float gain, float pitch
|
||||||
API int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan/*0*/ );
|
API int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan/*0*/ );
|
||||||
API int audio_stop( audio_t a );
|
API int audio_stop( audio_t a );
|
||||||
|
|
||||||
API float audio_volume_clip(float gain); // set fx volume if gain is in [0..1] range. return current fx volume in any case
|
API float audio_volume_clip(float gain); // set fx volume if gain is in [0..1] range. returns current fx volume in any case
|
||||||
API float audio_volume_stream(float gain); // set bgm volume if gain is in [0..1] range. return current bgm volume in any case
|
API float audio_volume_stream(float gain); // set bgm volume if gain is in [0..1] range. returns current bgm volume in any case
|
||||||
API float audio_volume_master(float gain); // set master volume if gain is in [0..1] range. return current master volume in any case
|
API float audio_volume_master(float gain); // set master volume if gain is in [0..1] range. returns current master volume in any case
|
||||||
|
|
||||||
|
API int audio_mute(int mute);
|
||||||
|
API int audio_muted();
|
||||||
|
|
||||||
API int ui_audio();
|
API int ui_audio();
|
||||||
|
|
||||||
|
|
|
@ -364,7 +364,7 @@ array(struct fs) zipscan_filter(int threadid, int numthreads) {
|
||||||
|
|
||||||
// skip if list item does not belong to this thread bucket
|
// skip if list item does not belong to this thread bucket
|
||||||
uint64_t hash = hash_str(fname);
|
uint64_t hash = hash_str(fname);
|
||||||
unsigned bucket = (hash >> 32) % numthreads;
|
unsigned bucket = (hash /*>> 32*/) % numthreads;
|
||||||
if(bucket != threadid) continue;
|
if(bucket != threadid) continue;
|
||||||
|
|
||||||
array_push(fs, fs_now[i]);
|
array_push(fs, fs_now[i]);
|
||||||
|
@ -621,10 +621,8 @@ bool cook_start( const char *cook_ini, const char *masks, int flags ) {
|
||||||
char *s = strchr( ART, ';' ); if(s) *s = 0;
|
char *s = strchr( ART, ';' ); if(s) *s = 0;
|
||||||
char *w = strchr( ART, ' ' ); if(w) *w = 0;
|
char *w = strchr( ART, ' ' ); if(w) *w = 0;
|
||||||
char *out = 0; const char *sep = "";
|
char *out = 0; const char *sep = "";
|
||||||
const char *v4k_title = getenv("V4K_TITLE");
|
|
||||||
for each_substring(ART, ",", t) {
|
for each_substring(ART, ",", t) {
|
||||||
char *tmp = file_pathabs(va("%s%s", HOME, t)) + ART_LEN;
|
char *tmp = file_pathabs(va("%s%s", HOME, t)) + ART_LEN;
|
||||||
PRINTF("ART mount+=%s\n", tmp);
|
|
||||||
for(int i = 0; tmp[i]; ++i) if(tmp[i]=='\\') tmp[i] = '/';
|
for(int i = 0; tmp[i]; ++i) if(tmp[i]=='\\') tmp[i] = '/';
|
||||||
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
||||||
assert( out[strlen(out) - 1] == '/' );
|
assert( out[strlen(out) - 1] == '/' );
|
||||||
|
|
|
@ -1,6 +1,61 @@
|
||||||
// editing:
|
// editing:
|
||||||
// nope > functions: add/rem property
|
// nope > functions: add/rem property
|
||||||
|
|
||||||
|
#define ICON_PLAY ICON_MD_PLAY_ARROW
|
||||||
|
#define ICON_PAUSE ICON_MD_PAUSE
|
||||||
|
#define ICON_STOP ICON_MD_STOP
|
||||||
|
#define ICON_CANCEL ICON_MD_CLOSE
|
||||||
|
|
||||||
|
#define ICON_WARNING ICON_MD_WARNING
|
||||||
|
#define ICON_BROWSER ICON_MD_FOLDER_SPECIAL
|
||||||
|
#define ICON_OUTLINER ICON_MD_VIEW_IN_AR
|
||||||
|
#define ICON_BUILD ICON_MD_BUILD
|
||||||
|
#define ICON_SCREENSHOT ICON_MD_PHOTO_CAMERA
|
||||||
|
#define ICON_CAMERA_ON ICON_MD_VIDEOCAM
|
||||||
|
#define ICON_CAMERA_OFF ICON_MD_VIDEOCAM_OFF
|
||||||
|
#define ICON_GAMEPAD_ON ICON_MD_VIDEOGAME_ASSET
|
||||||
|
#define ICON_GAMEPAD_OFF ICON_MD_VIDEOGAME_ASSET_OFF
|
||||||
|
#define ICON_AUDIO_ON ICON_MD_VOLUME_UP
|
||||||
|
#define ICON_AUDIO_OFF ICON_MD_VOLUME_OFF
|
||||||
|
#define ICON_WINDOWED ICON_MD_FULLSCREEN_EXIT
|
||||||
|
#define ICON_FULLSCREEN ICON_MD_FULLSCREEN
|
||||||
|
#define ICON_LIGHTS_ON ICON_MD_LIGHTBULB
|
||||||
|
#define ICON_LIGHTS_OFF ICON_MD_LIGHTBULB_OUTLINE
|
||||||
|
#define ICON_RENDER_BASIC ICON_MD_IMAGE_SEARCH
|
||||||
|
#define ICON_RENDER_FULL ICON_MD_INSERT_PHOTO
|
||||||
|
|
||||||
|
#define ICON_SIGNAL ICON_MD_SIGNAL_CELLULAR_ALT
|
||||||
|
#define ICON_DISK ICON_MD_STORAGE
|
||||||
|
#define ICON_RATE ICON_MD_SPEED
|
||||||
|
|
||||||
|
#define ICON_CLOCK ICON_MD_TODAY
|
||||||
|
#define ICON_CHRONO ICON_MD_TIMELAPSE
|
||||||
|
|
||||||
|
#define ICON_SETTINGS ICON_MD_SETTINGS
|
||||||
|
#define ICON_LANGUAGE ICON_MD_G_TRANSLATE
|
||||||
|
#define ICON_PERSONA ICON_MD_FACE
|
||||||
|
#define ICON_SOCIAL ICON_MD_MESSAGE
|
||||||
|
#define ICON_GAME ICON_MD_ROCKET_LAUNCH
|
||||||
|
#define ICON_KEYBOARD ICON_MD_KEYBOARD
|
||||||
|
#define ICON_MOUSE ICON_MD_MOUSE
|
||||||
|
#define ICON_GAMEPAD ICON_MD_GAMEPAD
|
||||||
|
#define ICON_MONITOR ICON_MD_MONITOR
|
||||||
|
#define ICON_WIFI ICON_MD_WIFI
|
||||||
|
#define ICON_BUDGET ICON_MD_SAVINGS
|
||||||
|
#define ICON_NEW_FOLDER ICON_MD_CREATE_NEW_FOLDER
|
||||||
|
#define ICON_PLUGIN ICON_MD_EXTENSION
|
||||||
|
#define ICON_RESTART ICON_MD_REPLAY
|
||||||
|
#define ICON_QUIT ICON_MD_CLOSE
|
||||||
|
|
||||||
|
#define ICON_POWER ICON_MD_BOLT // ICON_MD_POWER
|
||||||
|
#define ICON_BATTERY_CHARGING ICON_MD_BATTERY_CHARGING_FULL
|
||||||
|
#define ICON_BATTERY_LEVELS \
|
||||||
|
ICON_MD_BATTERY_ALERT, \
|
||||||
|
ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR, \
|
||||||
|
ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR, \
|
||||||
|
ICON_MD_BATTERY_4_BAR,ICON_MD_BATTERY_5_BAR, \
|
||||||
|
ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL
|
||||||
|
|
||||||
char *editor_path(const char *path) {
|
char *editor_path(const char *path) {
|
||||||
return va("%s/%s", EDITOR, path);
|
return va("%s/%s", EDITOR, path);
|
||||||
}
|
}
|
||||||
|
@ -65,6 +120,75 @@ int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate
|
||||||
return clicked | (copy ^ *enabled);
|
return clicked | (copy ^ *enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef union editor_var {
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
char *s;
|
||||||
|
} editor_var;
|
||||||
|
static map(char*,editor_var) editor_vars;
|
||||||
|
float *editor_getf(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
return &found->f;
|
||||||
|
}
|
||||||
|
int *editor_geti(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
return &found->i;
|
||||||
|
}
|
||||||
|
char **editor_gets(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
if(!found->s) found->s = stringf("%s","");
|
||||||
|
return &found->s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editor_send(const char *cmd, const char *optional_value) {
|
||||||
|
unsigned *gamepads = editor_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)...
|
||||||
|
unsigned *renders = editor_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes
|
||||||
|
float *speed = editor_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8)
|
||||||
|
unsigned *powersave = editor_geti("powersave");
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
/**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0);
|
||||||
|
else if( !strcmp(cmd, "key_stop" )) window_pause(1);
|
||||||
|
else if( !strcmp(cmd, "key_mute" )) audio_volume_master( 1 ^ !!audio_volume_master(-1) );
|
||||||
|
else if( !strcmp(cmd, "key_pause" )) window_pause( window_has_pause() ^ 1 );
|
||||||
|
else if( !strcmp(cmd, "key_reload" )) window_reload();
|
||||||
|
else if( !strcmp(cmd, "key_battery" )) *powersave = optional_value ? !!atoi(optional_value) : *powersave ^ 1;
|
||||||
|
else if( !strcmp(cmd, "key_browser" )) ui_show("File Browser", ui_visible("File Browser") ^ true);
|
||||||
|
else if( !strcmp(cmd, "key_outliner" )) ui_show("Outliner", ui_visible("Outliner") ^ true);
|
||||||
|
else if( !strcmp(cmd, "key_record" )) if(record_active()) record_stop(); else
|
||||||
|
name = file_counter(va("%s.mp4",app_name())), window_record(name), ui_notify(va("Video capturing: %s", name), date_string());
|
||||||
|
else if( !strcmp(cmd, "key_screenshot" )) name = file_counter(va("%s.png",app_name())), window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string());
|
||||||
|
else if( !strcmp(cmd, "key_profiler" )) ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true));
|
||||||
|
else if( !strcmp(cmd, "key_fullscreen" )) record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); // framebuffer resizing corrupts video stream, so stop any recording beforehand
|
||||||
|
else if( !strcmp(cmd, "key_gamepad" )) *gamepads = (*gamepads & ~1u) | ((*gamepads & 1) ^ 1);
|
||||||
|
else if( !strcmp(cmd, "key_lit" )) *renders = (*renders & ~1u) | ((*renders & 1) ^ 1);
|
||||||
|
else if( !strcmp(cmd, "key_ddraw" )) *renders = (*renders & ~2u) | ((*renders & 2) ^ 2);
|
||||||
|
else alert(va("editor could not handle `%s` command.", cmd));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editor_tick() {
|
||||||
|
enum { editor_hz = 60 };
|
||||||
|
enum { editor_hz_mid = 18 };
|
||||||
|
enum { editor_hz_low = 5 };
|
||||||
|
if( *editor_geti("powersave") ) {
|
||||||
|
// adaptive framerate
|
||||||
|
int app_on_background = !window_has_focus();
|
||||||
|
int hz = app_on_background ? editor_hz_low : editor_hz_mid;
|
||||||
|
window_fps_lock( hz < 5 ? 5 : hz );
|
||||||
|
} else {
|
||||||
|
// window_fps_lock( editor_hz );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int gizmo__mode;
|
static int gizmo__mode;
|
||||||
static int gizmo__active;
|
static int gizmo__active;
|
||||||
static int gizmo__hover;
|
static int gizmo__hover;
|
||||||
|
@ -176,26 +300,6 @@ int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* dialog_load() {
|
|
||||||
const char *windowTitle = NULL;
|
|
||||||
const char *defaultPathFile = NULL;
|
|
||||||
const char *filterHints = NULL; // "image files"
|
|
||||||
const char *filters[] = { "*.*" };
|
|
||||||
int allowMultipleSelections = 0;
|
|
||||||
|
|
||||||
tinyfd_assumeGraphicDisplay = 1;
|
|
||||||
return tinyfd_openFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints, allowMultipleSelections );
|
|
||||||
}
|
|
||||||
char* dialog_save() {
|
|
||||||
const char *windowTitle = NULL;
|
|
||||||
const char *defaultPathFile = NULL;
|
|
||||||
const char *filterHints = NULL; // "image files"
|
|
||||||
const char *filters[] = { "*.*" };
|
|
||||||
|
|
||||||
tinyfd_assumeGraphicDisplay = 1;
|
|
||||||
return tinyfd_saveFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints );
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- localization kit
|
// -- localization kit
|
||||||
|
|
||||||
static const char *kit_lang = "enUS", *kit_langs =
|
static const char *kit_lang = "enUS", *kit_langs =
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
API vec3 editor_pick(float mouse_x, float mouse_y);
|
API vec3 editor_pick(float mouse_x, float mouse_y);
|
||||||
API char* editor_path(const char *path);
|
API char* editor_path(const char *path);
|
||||||
|
|
||||||
|
API float* editor_getf(const char *key);
|
||||||
|
API int* editor_geti(const char *key);
|
||||||
|
API char** editor_gets(const char *key);
|
||||||
|
API int editor_send(const char *cmd, const char *optional_value);
|
||||||
|
|
||||||
// open file dialog
|
// open file dialog
|
||||||
|
|
||||||
API char* dialog_load();
|
API char* dialog_load();
|
||||||
|
|
|
@ -257,7 +257,7 @@ bool file_delete(const char *pathfile) {
|
||||||
}
|
}
|
||||||
bool file_copy(const char *src, const char *dst) {
|
bool file_copy(const char *src, const char *dst) {
|
||||||
int ok = 0, BUFSIZE = 1 << 20; // 1 MiB
|
int ok = 0, BUFSIZE = 1 << 20; // 1 MiB
|
||||||
static __thread char *buffer = 0; do_once buffer = REALLOC(0, BUFSIZE);
|
static __thread char *buffer = 0; do_once buffer = REALLOC(0, BUFSIZE); // @leak
|
||||||
for( FILE *in = fopen(src, "rb"); in; fclose(in), in = 0) {
|
for( FILE *in = fopen(src, "rb"); in; fclose(in), in = 0) {
|
||||||
for( FILE *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
for( FILE *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
||||||
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
||||||
|
@ -582,6 +582,8 @@ void vfs_reload() {
|
||||||
#if defined(EMSCRIPTEN)
|
#if defined(EMSCRIPTEN)
|
||||||
vfs_mount("index.zip");
|
vfs_mount("index.zip");
|
||||||
#else
|
#else
|
||||||
|
// mount fused executables
|
||||||
|
vfs_mount(va("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")));
|
||||||
/* // old way
|
/* // old way
|
||||||
for( int i = 0; i < JOBS_MAX; ++i) {
|
for( int i = 0; i < JOBS_MAX; ++i) {
|
||||||
if( vfs_mount(va(".art[%02x].zip", i)) ) continue;
|
if( vfs_mount(va(".art[%02x].zip", i)) ) continue;
|
||||||
|
@ -601,6 +603,34 @@ void vfs_reload() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define ARK1 'ArK\x1'
|
||||||
|
#define ARK1_PADDING (512 - 40) // 472
|
||||||
|
#define ARK_PRINTF(f,...) 0 // printf(f,__VA_ARGS__)
|
||||||
|
#define ARK_SWAP32(x) (x)
|
||||||
|
#define ARK_SWAP64(x) (x)
|
||||||
|
#define ARK_REALLOC REALLOC
|
||||||
|
static uint64_t ark_fget64( FILE *in ) { uint64_t v; fread( &v, 1, 8, in ); return ARK_SWAP64(v); }
|
||||||
|
void ark_list( const char *infile, zip **z ) {
|
||||||
|
for( FILE *in = fopen(infile, "rb"); in; fclose(in), in = 0 )
|
||||||
|
while(!feof(in)) {
|
||||||
|
if( 0 != (ftell(in) % ARK1_PADDING) ) fseek(in, ARK1_PADDING - (ftell(in) % ARK1_PADDING), SEEK_CUR);
|
||||||
|
ARK_PRINTF("Reading at #%d\n", (int)ftell(in));
|
||||||
|
uint64_t mark = ark_fget64(in);
|
||||||
|
if( mark != ARK1 ) continue;
|
||||||
|
uint64_t stamp = ark_fget64(in);
|
||||||
|
uint64_t datalen = ark_fget64(in);
|
||||||
|
uint64_t datahash = ark_fget64(in);
|
||||||
|
uint64_t namelen = ark_fget64(in);
|
||||||
|
|
||||||
|
*z = zip_open_handle(in, "rb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||||
zip *z = NULL; tar *t = NULL; pak *p = NULL; dir *d = NULL;
|
zip *z = NULL; tar *t = NULL; pak *p = NULL; dir *d = NULL;
|
||||||
|
@ -610,6 +640,7 @@ bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||||
if( !is_folder ) z = zip_open(path, "rb");
|
if( !is_folder ) z = zip_open(path, "rb");
|
||||||
if( !is_folder && !z ) t = tar_open(path, "rb");
|
if( !is_folder && !z ) t = tar_open(path, "rb");
|
||||||
if( !is_folder && !z && !t ) p = pak_open(path, "rb");
|
if( !is_folder && !z && !t ) p = pak_open(path, "rb");
|
||||||
|
if( !is_folder && !z && !t && !p ) ark_list(path, &z); // last resort. try as .ark
|
||||||
if( !is_folder && !z && !t && !p ) return 0;
|
if( !is_folder && !z && !t && !p ) return 0;
|
||||||
|
|
||||||
// normalize input -> "././" to ""
|
// normalize input -> "././" to ""
|
||||||
|
@ -794,9 +825,9 @@ if( found && *found == 0 ) {
|
||||||
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
||||||
|
|
||||||
// search (last item)
|
// search (last item)
|
||||||
static char last_item[256] = { 0 };
|
static __thread char last_item[256] = { 0 };
|
||||||
static void *last_ptr = 0;
|
static __thread void *last_ptr = 0;
|
||||||
static int last_size = 0;
|
static __thread int last_size = 0;
|
||||||
if( !strcmpi(lookup_id, last_item)) {
|
if( !strcmpi(lookup_id, last_item)) {
|
||||||
ptr = last_ptr;
|
ptr = last_ptr;
|
||||||
size = last_size;
|
size = last_size;
|
||||||
|
@ -953,6 +984,10 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
if( !MAX_CACHED_FILES ) return 0;
|
if( !MAX_CACHED_FILES ) return 0;
|
||||||
if( !ptr || !size ) return 0;
|
if( !ptr || !size ) return 0;
|
||||||
|
|
||||||
|
// keep cached files within limits
|
||||||
|
static thread_mutex_t mutex, *init = 0; if(!init) thread_mutex_init(init = &mutex);
|
||||||
|
thread_mutex_lock(&mutex);
|
||||||
|
|
||||||
// append to cache
|
// append to cache
|
||||||
archive_dir zero = {0}, *old = dir_cache;
|
archive_dir zero = {0}, *old = dir_cache;
|
||||||
*(dir_cache = REALLOC(0, sizeof(archive_dir))) = zero;
|
*(dir_cache = REALLOC(0, sizeof(archive_dir))) = zero;
|
||||||
|
@ -962,7 +997,8 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
dir_cache->data = REALLOC(0, size+1);
|
dir_cache->data = REALLOC(0, size+1);
|
||||||
memcpy(dir_cache->data, ptr, size); size[(char*)dir_cache->data] = 0; // copy+terminator
|
memcpy(dir_cache->data, ptr, size); size[(char*)dir_cache->data] = 0; // copy+terminator
|
||||||
|
|
||||||
// keep cached files within limits
|
void *found = 0;
|
||||||
|
|
||||||
static int added = 0;
|
static int added = 0;
|
||||||
if( added < MAX_CACHED_FILES ) {
|
if( added < MAX_CACHED_FILES ) {
|
||||||
++added;
|
++added;
|
||||||
|
@ -971,15 +1007,18 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
for( archive_dir *prev = dir_cache, *dir = prev; dir ; prev = dir, dir = dir->next ) {
|
for( archive_dir *prev = dir_cache, *dir = prev; dir ; prev = dir, dir = dir->next ) {
|
||||||
if( !dir->next ) {
|
if( !dir->next ) {
|
||||||
prev->next = 0; // break link
|
prev->next = 0; // break link
|
||||||
void *data = dir->data;
|
found = dir->data;
|
||||||
dir->path = REALLOC(dir->path, 0);
|
dir->path = REALLOC(dir->path, 0);
|
||||||
dir->data = REALLOC(dir->data, 0);
|
dir->data = REALLOC(dir->data, 0);
|
||||||
dir = REALLOC(dir, 0);
|
dir = REALLOC(dir, 0);
|
||||||
return data;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
thread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
@ -19,18 +19,20 @@ static void v4k_pre_init() {
|
||||||
// window_swap();
|
// window_swap();
|
||||||
}
|
}
|
||||||
static void v4k_post_init(float refresh_rate) {
|
static void v4k_post_init(float refresh_rate) {
|
||||||
|
int i;
|
||||||
|
|
||||||
// cook cleanup
|
// cook cleanup
|
||||||
cook_stop();
|
cook_stop();
|
||||||
|
|
||||||
vfs_reload();
|
vfs_reload();
|
||||||
|
|
||||||
|
// init subsystems that depend on cooked assets now. ui_init() is special case and needs to be safely in single thread
|
||||||
|
ui_init();
|
||||||
|
|
||||||
// init more subsystems; beware of VFS mounting, as some of these may need cooked assets at this point
|
// init more subsystems; beware of VFS mounting, as some of these may need cooked assets at this point
|
||||||
int i;
|
|
||||||
#if 1 // #ifdef PARALLEL_INIT
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
#endif
|
|
||||||
for( i = 0; i <= 3; ++i) {
|
for( i = 0; i <= 3; ++i) {
|
||||||
/**/ if( i == 0 ) ui_init(), scene_init(); // init these on thread #0, since both will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
/**/ if( i == 0 ) scene_init(); // init these on thread #0, since both will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
||||||
else if( i == 1 ) audio_init(0); // initialize audio after cooking // reasoning for this: do not launch audio threads while cooks are in progress, so there is more cpu for cooking actually
|
else if( i == 1 ) audio_init(0); // initialize audio after cooking // reasoning for this: do not launch audio threads while cooks are in progress, so there is more cpu for cooking actually
|
||||||
else if( i == 2 ) script_init(), kit_init(), midi_init();
|
else if( i == 2 ) script_init(), kit_init(), midi_init();
|
||||||
else if( i == 3 ) input_init(), network_init();
|
else if( i == 3 ) input_init(), network_init();
|
||||||
|
|
|
@ -8,8 +8,8 @@ static map(unsigned, reflected_t) reflects;
|
||||||
static map(unsigned, array(reflected_t)) members;
|
static map(unsigned, array(reflected_t)) members;
|
||||||
|
|
||||||
void reflected_printf(reflected_t *r) {
|
void reflected_printf(reflected_t *r) {
|
||||||
printf("id:%u objtype:%u sz:%u name:%s info:%s addr:%p parent:%u type:%s",
|
printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s",
|
||||||
r->id, r->objtype, r->sz, r->name ? r->name : "", r->info ? r->info : "", r->addr, r->parent, r->type ? r->type : "");
|
r->name ? r->name : "", r->info ? r->info : "", r->id, r->objtype, r->sz, r->addr, r->parent, r->type ? r->type : "");
|
||||||
}
|
}
|
||||||
void reflected_printf_all() {
|
void reflected_printf_all() {
|
||||||
for each_map_ptr(reflects, unsigned, k, reflected_t, p) {
|
for each_map_ptr(reflects, unsigned, k, reflected_t, p) {
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
// @todo: nested structs? pointers in members?
|
// @todo: nested structs? pointers in members?
|
||||||
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
||||||
|
|
||||||
|
#ifndef ifdef_objapi
|
||||||
#define ifdef_objapi(T,...) __VA_ARGS__
|
#define ifdef_objapi(T,...) __VA_ARGS__
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct reflected_t {
|
typedef struct reflected_t {
|
||||||
unsigned id, objtype;
|
unsigned id, objtype;
|
||||||
|
|
|
@ -8,16 +8,26 @@ char* tempvl(const char *fmt, va_list vl) {
|
||||||
|
|
||||||
int reqlen = sz;
|
int reqlen = sz;
|
||||||
#if 0
|
#if 0
|
||||||
|
int heap = 0;
|
||||||
enum { STACK_ALLOC = 16384 };
|
enum { STACK_ALLOC = 16384 };
|
||||||
static __thread char buf[STACK_ALLOC];
|
static __thread char buf[STACK_ALLOC];
|
||||||
#else
|
#else
|
||||||
enum { STACK_ALLOC = 128*1024 };
|
int heap = 1;
|
||||||
|
static __thread int STACK_ALLOC = 128*1024;
|
||||||
static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak
|
static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak
|
||||||
#endif
|
#endif
|
||||||
static __thread int cur = 0, len = STACK_ALLOC - 1; //printf("string stack %d/%d\n", cur, STACK_ALLOC);
|
static __thread int cur = 0; //printf("string stack %d/%d\n", cur, STACK_ALLOC);
|
||||||
|
|
||||||
assert(reqlen < STACK_ALLOC && "no stack enough, increase STACK_ALLOC variable above");
|
if( reqlen >= STACK_ALLOC ) {
|
||||||
char* ptr = buf + (cur *= (cur+reqlen) < len, (cur += reqlen) - reqlen);
|
tty_color(RED);
|
||||||
|
printf("no stack enough, increase STACK_ALLOC variable above (reqlen:%d) (fmt: %s)\n", reqlen, fmt);
|
||||||
|
tty_color(0);
|
||||||
|
//assert(reqlen < STACK_ALLOC);
|
||||||
|
STACK_ALLOC = reqlen * 2;
|
||||||
|
buf = REALLOC(0, STACK_ALLOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* ptr = buf + (cur *= (cur+reqlen) < (STACK_ALLOC - 1), (cur += reqlen) - reqlen);
|
||||||
|
|
||||||
/*stbsp_*/vsnprintf( ptr, sz, fmt, vl );
|
/*stbsp_*/vsnprintf( ptr, sz, fmt, vl );
|
||||||
return (char *)ptr;
|
return (char *)ptr;
|
||||||
|
|
|
@ -21,9 +21,10 @@ char* strtok_s(char* str,const char* delimiters,char** context); // tcc misses t
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
#define each_substring(str, delims, keyname) \
|
#define each_substring(str, delims, keyname) \
|
||||||
( int len_ = strlen(str) + 1; len_; len_ = 0 ) \
|
( char *str_ = (char*)(str); str_; str_ = 0 ) \
|
||||||
for( char buf_[1024], *ptr_ = len_ < 1024 ? buf_ : REALLOC(0, len_), *lit_ = (char*)(str), *_bak = (snprintf(ptr_, len_, "%s", lit_), ptr_); _bak; _bak = 0, (ptr_ == buf_ ? 0 : REALLOC(ptr_, 0)) ) \
|
for( int len_ = strlen(str_) + 1, heap_ = len_ < 1024; len_ > 1; len_ = 0 ) \
|
||||||
for( char *next_token = 0, *keyname = strtok_r(_bak, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
for( char *ptr_ = (heap_ ? REALLOC(0, len_) : ALLOCA(len_)), *cpy_ = (snprintf(ptr_, len_, "%s", str_), ptr_); ptr_; (heap_ ? REALLOC(ptr_, 0) : 0), ptr_ = 0 ) \
|
||||||
|
for( char *next_token = 0, *keyname = strtok_r(cpy_, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
||||||
#else
|
#else
|
||||||
#define each_substring(str, delims, keyname) \
|
#define each_substring(str, delims, keyname) \
|
||||||
( char** tokens_ = strsplit((str), (delims)), *keyname = 0; tokens_; tokens_ = 0) \
|
( char** tokens_ = strsplit((str), (delims)), *keyname = 0; tokens_; tokens_ = 0) \
|
||||||
|
|
|
@ -850,6 +850,26 @@ bool app_open(const char *link) {
|
||||||
return app_open_url(link);
|
return app_open_url(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* app_loadfile() {
|
||||||
|
const char *windowTitle = NULL;
|
||||||
|
const char *defaultPathFile = NULL;
|
||||||
|
const char *filterHints = NULL; // "image files"
|
||||||
|
const char *filters[] = { "*.*" };
|
||||||
|
int allowMultipleSelections = 0;
|
||||||
|
|
||||||
|
tinyfd_assumeGraphicDisplay = 1;
|
||||||
|
return tinyfd_openFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints, allowMultipleSelections );
|
||||||
|
}
|
||||||
|
const char* app_savefile() {
|
||||||
|
const char *windowTitle = NULL;
|
||||||
|
const char *defaultPathFile = NULL;
|
||||||
|
const char *filterHints = NULL; // "image files"
|
||||||
|
const char *filters[] = { "*.*" };
|
||||||
|
|
||||||
|
tinyfd_assumeGraphicDisplay = 1;
|
||||||
|
return tinyfd_saveFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints );
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// tests
|
// tests
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,10 @@ API void app_crash();
|
||||||
API void app_singleton(const char *guid);
|
API void app_singleton(const char *guid);
|
||||||
API bool app_open(const char *folder_file_or_url);
|
API bool app_open(const char *folder_file_or_url);
|
||||||
|
|
||||||
|
API const char* app_loadfile();
|
||||||
|
API const char* app_savefile();
|
||||||
|
|
||||||
|
|
||||||
API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free().
|
API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free().
|
||||||
API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order.
|
API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order.
|
||||||
|
|
||||||
|
|
|
@ -1401,11 +1401,12 @@ int ui_collapse_end() {
|
||||||
|
|
||||||
|
|
||||||
int ui_contextual() {
|
int ui_contextual() {
|
||||||
struct nk_rect bounds = nk_widget_bounds(ui_ctx);
|
struct nk_rect bounds = nk_widget_bounds(ui_ctx); // = nk_window_get_bounds(ui_ctx);
|
||||||
bounds.y -= 25;
|
bounds.y -= 25;
|
||||||
return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds);
|
return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds);
|
||||||
}
|
}
|
||||||
int ui_contextual_end() {
|
int ui_contextual_end(int close) {
|
||||||
|
if(close) nk_contextual_close(ui_ctx);
|
||||||
nk_contextual_end(ui_ctx);
|
nk_contextual_end(ui_ctx);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1416,7 +1417,7 @@ int ui_submenu(const char *options) {
|
||||||
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
||||||
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
||||||
}
|
}
|
||||||
ui_contextual_end();
|
ui_contextual_end(0);
|
||||||
}
|
}
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
@ -1550,8 +1551,10 @@ int ui_label(const char *text) {
|
||||||
int ui_label2(const char *label, const char *text_) {
|
int ui_label2(const char *label, const char *text_) {
|
||||||
nk_layout_row_dynamic(ui_ctx, 0, 2);
|
nk_layout_row_dynamic(ui_ctx, 0, 2);
|
||||||
|
|
||||||
int align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
int align1 = NK_TEXT_LEFT;
|
||||||
int align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
int align2 = NK_TEXT_LEFT;
|
||||||
|
if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||||
|
if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||||
ui_label_(label, align1);
|
ui_label_(label, align1);
|
||||||
|
|
||||||
const struct nk_input *input = &ui_ctx->input;
|
const struct nk_input *input = &ui_ctx->input;
|
||||||
|
|
|
@ -60,7 +60,7 @@ API int ui_label2_float(const char *label, float value);
|
||||||
API int ui_label2_toolbar(const char *label, const char *icons);
|
API int ui_label2_toolbar(const char *label, const char *icons);
|
||||||
API int ui_slider(const char *label, float *value);
|
API int ui_slider(const char *label, float *value);
|
||||||
API int ui_slider2(const char *label, float *value, const char *caption);
|
API int ui_slider2(const char *label, float *value, const char *caption);
|
||||||
API int ui_contextual_end();
|
API int ui_contextual_end(int close);
|
||||||
API int ui_collapse_clicked();
|
API int ui_collapse_clicked();
|
||||||
API int ui_collapse_end();
|
API int ui_collapse_end();
|
||||||
API int ui_panel_end();
|
API int ui_panel_end();
|
||||||
|
|
|
@ -536,12 +536,38 @@ int window_frame_begin() {
|
||||||
if( may_render_stats ) {
|
if( may_render_stats ) {
|
||||||
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
||||||
|
|
||||||
#if 1
|
static int time_factor = 0;
|
||||||
static char *filter = 0;
|
static int playing = 0;
|
||||||
|
static int paused = 0;
|
||||||
|
int advance_frame = 0;
|
||||||
|
|
||||||
static int do_filter = 0;
|
static int do_filter = 0;
|
||||||
|
static int do_profile = 0;
|
||||||
|
static int do_extra = 0;
|
||||||
|
|
||||||
|
char *EDITOR_TOOLBAR_ICONS = va("%s;%s;%s;%s;%s;%s;%s;%s",
|
||||||
|
do_filter ? ICON_MD_CLOSE : ICON_MD_SEARCH,
|
||||||
|
ICON_MD_PLAY_ARROW,
|
||||||
|
paused ? ICON_MD_SKIP_NEXT : ICON_MD_PAUSE,
|
||||||
|
ICON_MD_FAST_FORWARD,
|
||||||
|
ICON_MD_STOP,
|
||||||
|
ICON_MD_REPLAY,
|
||||||
|
ICON_MD_FACE,
|
||||||
|
ICON_MD_MENU
|
||||||
|
);
|
||||||
|
|
||||||
if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1;
|
if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1;
|
||||||
int choice = ui_toolbar(ICON_MD_SEARCH ";");
|
int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS);
|
||||||
if( choice == 1 ) do_filter = 1;
|
if( choice == 1 ) do_filter ^= 1, do_profile = 0, do_extra = 0;
|
||||||
|
if( choice == 2 ) playing = 1, paused = 0;
|
||||||
|
if( choice == 3 ) advance_frame = !!paused, paused = 1;
|
||||||
|
if( choice == 4 ) paused = 0, time_factor = (++time_factor) % 4;
|
||||||
|
if( choice == 5 ) playing = 0, paused = 0, advance_frame = 0, time_factor = 0;
|
||||||
|
if( choice == 6 ) window_reload();
|
||||||
|
if( choice == 7 ) do_filter = 0, do_profile ^= 1, do_extra = 0;
|
||||||
|
if( choice == 8 ) do_filter = 0, do_profile = 0, do_extra ^= 1;
|
||||||
|
|
||||||
|
static char *filter = 0;
|
||||||
if( do_filter ) {
|
if( do_filter ) {
|
||||||
ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter);
|
ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter);
|
||||||
if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon)
|
if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon)
|
||||||
|
@ -551,13 +577,44 @@ int window_frame_begin() {
|
||||||
if( filter ) filter[0] = '\0';
|
if( filter ) filter[0] = '\0';
|
||||||
}
|
}
|
||||||
char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*";
|
char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*";
|
||||||
#endif
|
|
||||||
|
static char *username = 0;
|
||||||
|
static char *userpass = 0;
|
||||||
|
if( do_profile ) {
|
||||||
|
ui_string(ICON_MD_FACE " Username", &username);
|
||||||
|
ui_string(ICON_MD_FACE " Password", &userpass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( do_extra ) {
|
||||||
|
int choice2 = ui_label2_toolbar(NULL,
|
||||||
|
ICON_MD_VIEW_IN_AR
|
||||||
|
ICON_MD_MESSAGE
|
||||||
|
ICON_MD_TIPS_AND_UPDATES ICON_MD_LIGHTBULB ICON_MD_LIGHTBULB_OUTLINE
|
||||||
|
ICON_MD_IMAGE_SEARCH ICON_MD_INSERT_PHOTO
|
||||||
|
ICON_MD_VIDEOGAME_ASSET ICON_MD_VIDEOGAME_ASSET_OFF
|
||||||
|
|
||||||
|
ICON_MD_VOLUME_UP ICON_MD_VOLUME_OFF // audio_volume_master(-1) > 0
|
||||||
|
|
||||||
|
ICON_MD_TROUBLESHOOT ICON_MD_SCHEMA ICON_MD_MENU
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
int open = 0, clicked_or_toggled = 0;
|
int open = 0, clicked_or_toggled = 0;
|
||||||
|
|
||||||
#define ui_collapse_filtered(lbl,id) (strmatchi(lbl,filter_mask) && ui_collapse(lbl,id))
|
#define ui_collapse_filtered(lbl,id) (strmatchi(lbl,filter_mask) && ui_collapse(lbl,id))
|
||||||
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
#define EDITOR_UI_COLLAPSE(f,...) \
|
||||||
|
for( int macro(p) = (open = ui_collapse_filtered(f,__VA_ARGS__)), macro(dummy) = (clicked_or_toggled = ui_collapse_clicked()); macro(p); ui_collapse_end(), macro(p) = 0)
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUG_REPORT " Bugs 0", "Debug.Bugs") {
|
||||||
|
// @todo. parse /bugs.ini, includes saved screenshots & videos.
|
||||||
|
// @todo. screenshot include parseable level, position screen markers (same info as /bugs.ini)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Art and bookmarks
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art") {
|
||||||
bool inlined = true;
|
bool inlined = true;
|
||||||
const char *file = 0;
|
const char *file = 0;
|
||||||
if( ui_browse(&file, &inlined) ) {
|
if( ui_browse(&file, &inlined) ) {
|
||||||
|
@ -565,47 +622,78 @@ int window_frame_begin() {
|
||||||
app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep));
|
app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_BOOKMARK " Bookmarks", "Debug.Bookmarks") { /* @todo */ }
|
||||||
|
|
||||||
|
|
||||||
|
// E,C,S,W
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Scene", "Debug.Scene") {
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUBBLE_CHART/*ICON_MD_SCATTER_PLOT*/ " Entities", "Debug.Entities") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_TUNE " Components", "Debug.Components") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_PRECISION_MANUFACTURING " Systems", "Debug.Systems") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_PUBLIC " Levels", "Debug.Levels") {
|
||||||
|
//node_edit(editor.edit.down,&editor.edit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Init", "Debug.HierarchyInit") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Draw", "Debug.HierarchyDraw") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Tick", "Debug.HierarchyTick") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Edit", "Debug.HierarchyEdit") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Quit", "Debug.HierarchyQuit") { /* @todo */ }
|
||||||
|
|
||||||
|
// node_edit(&editor.init,&editor.init);
|
||||||
|
// node_edit(&editor.draw,&editor.draw);
|
||||||
|
// node_edit(&editor.tick,&editor.tick);
|
||||||
|
// node_edit(&editor.edit,&editor.edit);
|
||||||
|
// node_edit(&editor.quit,&editor.quit);
|
||||||
|
}
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI") {
|
||||||
// @todo
|
// @todo
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VOLUME_UP " Audio", "Debug.Audio")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_VOLUME_UP " Audio", "Debug.Audio") {
|
||||||
ui_audio();
|
ui_audio();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VIDEOCAM " Camera", "Debug.Camera")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_VIDEOCAM " Camera", "Debug.Camera") {
|
||||||
ui_camera( camera_get_active() );
|
ui_camera( camera_get_active() );
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_BUILD " Cook", "Debug.Cook")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") {
|
||||||
// @todo
|
// @todo: fps lock, fps target, aspect ratio, fullscreen
|
||||||
|
char *text = va("%s;%s;%s",
|
||||||
|
window_has_fullscreen() ? ICON_MD_FULLSCREEN_EXIT : ICON_MD_FULLSCREEN,
|
||||||
|
ICON_MD_PHOTO_CAMERA,
|
||||||
|
record_active() ? ICON_MD_VIDEOCAM_OFF : ICON_MD_VIDEOCAM
|
||||||
|
);
|
||||||
|
|
||||||
|
int choice = ui_toolbar(text);
|
||||||
|
if( choice == 1 ) editor_send("key_fullscreen",0);
|
||||||
|
if( choice == 2 ) editor_send("key_screenshot",0);
|
||||||
|
if( choice == 3 ) editor_send("key_record",0);
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_SIGNAL_CELLULAR_ALT " Network", "Debug.Network")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") {
|
||||||
// @todo
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
// @todo
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_MOVIE " FXs", "Debug.FXs")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_fxs();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_SPEED " Profiler", "Debug.Profiler")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_profiler();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_shaders();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_keyboard();
|
ui_keyboard();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_MOUSE " Mouse", "Debug.Mouse")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_MOUSE " Mouse", "Debug.Mouse") {
|
||||||
ui_mouse();
|
ui_mouse();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads") {
|
||||||
for( int q = 0; q < 4; ++q ) {
|
for( int q = 0; q < 4; ++q ) {
|
||||||
for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) {
|
for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) {
|
||||||
ui_gamepad(q);
|
ui_gamepad(q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VIEW_QUILT " UI", "Debug.UI")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders") {
|
||||||
|
ui_shaders();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_MOVIE " FXs", "Debug.FXs") {
|
||||||
|
ui_fxs();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_VIEW_QUILT " UI", "Debug.UI") {
|
||||||
int choice = ui_toolbar(ICON_MD_RECYCLING " Reset layout;" ICON_MD_SAVE_AS " Save layout");
|
int choice = ui_toolbar(ICON_MD_RECYCLING " Reset layout;" ICON_MD_SAVE_AS " Save layout");
|
||||||
if( choice == 1 ) ui_layout_all_reset("*");
|
if( choice == 1 ) ui_layout_all_reset("*");
|
||||||
if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*");
|
if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*");
|
||||||
|
@ -618,8 +706,61 @@ int window_frame_begin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_SAVINGS " Budgets", "Debug.Budgets") {
|
||||||
|
// @todo. // mem,fps,gfx,net,hdd,... also logging
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_WIFI/*ICON_MD_SIGNAL_CELLULAR_ALT*/ " Network 0/0 KiB", "Debug.Network") {
|
||||||
|
// @todo
|
||||||
|
// SIGNAL_CELLULAR_1_BAR SIGNAL_CELLULAR_2_BAR
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%d", window_fps(), (int)window_fps_target()), "Debug.Profiler") {
|
||||||
|
ui_profiler();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// logic: either plug icon (power saving off) or one of the following ones (power saving on):
|
||||||
|
// if 0% batt (no batt): battery alert
|
||||||
|
// if discharging: battery levels [alert,0..6,full]
|
||||||
|
// if charging: battery charging
|
||||||
|
int battery_read = app_battery();
|
||||||
|
int battery_level = abs(battery_read);
|
||||||
|
int battery_discharging = battery_read < 0 && battery_level < 100;
|
||||||
|
const char *power_icon_label = ICON_MD_POWER " Power";
|
||||||
|
if( battery_level ) {
|
||||||
|
const char *battery_levels[9] = { // @todo: remap [7%..100%] -> [0..1] ?
|
||||||
|
ICON_MD_BATTERY_ALERT,ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR,
|
||||||
|
ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR,ICON_MD_BATTERY_4_BAR,
|
||||||
|
ICON_MD_BATTERY_5_BAR,ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL,
|
||||||
|
};
|
||||||
|
power_icon_label = (const char*)va("%s Power %d%%",
|
||||||
|
battery_discharging ? battery_levels[(int)((9-1)*clampf(battery_level/100.f,0,1))] : ICON_MD_BATTERY_CHARGING_FULL,
|
||||||
|
battery_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") {
|
||||||
|
int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT );
|
||||||
|
if( choice == 1 ) editor_send("key_battery","0");
|
||||||
|
if( choice == 2 ) editor_send("key_battery","1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_EXTENSION " Plugins", "Debug.Plugins") {
|
||||||
|
// @todo. include VCS
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUILD " Cook", "Debug.Cook") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(has_menu ? ui_window_end : ui_panel_end)();
|
(has_menu ? ui_window_end : ui_panel_end)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API int editor_tick();
|
||||||
|
editor_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // deprecated
|
#if 0 // deprecated
|
||||||
|
|
29
engine/v4k
29
engine/v4k
|
@ -234245,6 +234245,7 @@ unsigned file_decode(FILE* in, FILE* out, FILE *logfile) { // multi decoder
|
||||||
typedef struct zip zip;
|
typedef struct zip zip;
|
||||||
|
|
||||||
zip* zip_open(const char *file, const char *mode /*r,w,a*/);
|
zip* zip_open(const char *file, const char *mode /*r,w,a*/);
|
||||||
|
zip* zip_open_handle(FILE*fp, const char *mode /*r,w,a*/);
|
||||||
|
|
||||||
// only for (w)rite or (a)ppend mode
|
// only for (w)rite or (a)ppend mode
|
||||||
bool zip_append_file(zip*, const char *entryname, const char *comment, FILE *in, unsigned compress_level);
|
bool zip_append_file(zip*, const char *entryname, const char *comment, FILE *in, unsigned compress_level);
|
||||||
|
@ -234460,7 +234461,7 @@ int jzReadEndRecord(FILE *fp, JZEndRecord *endRecord) {
|
||||||
|
|
||||||
// Read ZIP file global directory. Will move within file. Returns Z_OK, or error code
|
// Read ZIP file global directory. Will move within file. Returns Z_OK, or error code
|
||||||
// Callback is called for each record, until callback returns zero
|
// Callback is called for each record, until callback returns zero
|
||||||
int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback callback, void *user_data) {
|
int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback callback, void *user_data, void *user_data2) {
|
||||||
JZGlobalFileHeader fileHeader;
|
JZGlobalFileHeader fileHeader;
|
||||||
|
|
||||||
if(fseek(fp, endRecord->centralDirectoryOffset, SEEK_SET)) {
|
if(fseek(fp, endRecord->centralDirectoryOffset, SEEK_SET)) {
|
||||||
|
@ -234475,6 +234476,8 @@ int jzReadCentralDirectory(FILE *fp, JZEndRecord *endRecord, JZRecordCallback ca
|
||||||
return ERR(JZ_ERRNO, "Couldn't read file header #%d!", i);
|
return ERR(JZ_ERRNO, "Couldn't read file header #%d!", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileHeader.relativeOffsetOflocalHeader += (uintptr_t)user_data2;
|
||||||
|
|
||||||
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
||||||
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
||||||
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
||||||
|
@ -234967,11 +234970,7 @@ common:;
|
||||||
|
|
||||||
// zip common
|
// zip common
|
||||||
|
|
||||||
zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
zip* zip_open_handle(FILE *fp, const char *mode) {
|
||||||
struct stat buffer;
|
|
||||||
int exists = (stat(file, &buffer) == 0);
|
|
||||||
if( mode[0] == 'a' && !exists ) mode = "wb";
|
|
||||||
FILE *fp = fopen(file, mode[0] == 'w' ? "wb" : mode[0] == 'a' ? "a+b" : "rb");
|
|
||||||
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
||||||
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
||||||
if( !z ) return fclose(fp), ERR(NULL, "out of mem"); else *z = zero;
|
if( !z ) return fclose(fp), ERR(NULL, "out of mem"); else *z = zero;
|
||||||
|
@ -234982,12 +234981,17 @@ zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
if( mode[0] == 'r' || mode[0] == 'a' ) {
|
if( mode[0] == 'r' || mode[0] == 'a' ) {
|
||||||
z->in = fp;
|
z->in = fp;
|
||||||
|
|
||||||
|
unsigned long long seekcur = ftell(z->in);
|
||||||
|
|
||||||
JZEndRecord jzEndRecord = {0};
|
JZEndRecord jzEndRecord = {0};
|
||||||
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
||||||
REALLOC(z, 0);
|
REALLOC(z, 0);
|
||||||
return fclose(fp), ERR(NULL, "Couldn't read ZIP file end record.");
|
return fclose(fp), ERR(NULL, "Couldn't read ZIP file end record.");
|
||||||
}
|
}
|
||||||
if(jzReadCentralDirectory(fp, &jzEndRecord, zip__callback, z) != JZ_OK) {
|
|
||||||
|
jzEndRecord.centralDirectoryOffset += seekcur;
|
||||||
|
|
||||||
|
if(jzReadCentralDirectory(fp, &jzEndRecord, zip__callback, z, (void*)(uintptr_t)seekcur ) != JZ_OK) {
|
||||||
REALLOC(z, 0);
|
REALLOC(z, 0);
|
||||||
return fclose(fp), ERR(NULL, "Couldn't read ZIP file central directory.");
|
return fclose(fp), ERR(NULL, "Couldn't read ZIP file central directory.");
|
||||||
}
|
}
|
||||||
|
@ -235015,6 +235019,14 @@ zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
return fclose(fp), ERR(NULL, "Unknown open mode %s", mode);
|
return fclose(fp), ERR(NULL, "Unknown open mode %s", mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zip* zip_open(const char *file, const char *mode /*r,w,a*/) {
|
||||||
|
struct stat buffer;
|
||||||
|
int exists = (stat(file, &buffer) == 0);
|
||||||
|
if( mode[0] == 'a' && !exists ) mode = "wb";
|
||||||
|
FILE *fp = fopen(file, mode[0] == 'w' ? "wb" : mode[0] == 'a' ? "a+b" : "rb");
|
||||||
|
return zip_open_handle(fp, mode);
|
||||||
|
}
|
||||||
|
|
||||||
void zip_close(zip* z) {
|
void zip_close(zip* z) {
|
||||||
if( z->out && z->count ) {
|
if( z->out && z->count ) {
|
||||||
// prepare end record
|
// prepare end record
|
||||||
|
@ -235194,8 +235206,7 @@ tar *tar_open(const char *filename, const char *mode) {
|
||||||
|
|
||||||
*t = zero;
|
*t = zero;
|
||||||
t->in = in;
|
t->in = in;
|
||||||
tar__parse(in, tar__push_entry, t);
|
return tar__parse(in, tar__push_entry, t) ? t : NULL;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int tar_find(tar *t, const char *entryname) {
|
int tar_find(tar *t, const char *entryname) {
|
||||||
|
|
480
engine/v4k.c
480
engine/v4k.c
|
@ -525,16 +525,26 @@ char* tempvl(const char *fmt, va_list vl) {
|
||||||
|
|
||||||
int reqlen = sz;
|
int reqlen = sz;
|
||||||
#if 0
|
#if 0
|
||||||
|
int heap = 0;
|
||||||
enum { STACK_ALLOC = 16384 };
|
enum { STACK_ALLOC = 16384 };
|
||||||
static __thread char buf[STACK_ALLOC];
|
static __thread char buf[STACK_ALLOC];
|
||||||
#else
|
#else
|
||||||
enum { STACK_ALLOC = 128*1024 };
|
int heap = 1;
|
||||||
|
static __thread int STACK_ALLOC = 128*1024;
|
||||||
static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak
|
static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak
|
||||||
#endif
|
#endif
|
||||||
static __thread int cur = 0, len = STACK_ALLOC - 1; //printf("string stack %d/%d\n", cur, STACK_ALLOC);
|
static __thread int cur = 0; //printf("string stack %d/%d\n", cur, STACK_ALLOC);
|
||||||
|
|
||||||
assert(reqlen < STACK_ALLOC && "no stack enough, increase STACK_ALLOC variable above");
|
if( reqlen >= STACK_ALLOC ) {
|
||||||
char* ptr = buf + (cur *= (cur+reqlen) < len, (cur += reqlen) - reqlen);
|
tty_color(RED);
|
||||||
|
printf("no stack enough, increase STACK_ALLOC variable above (reqlen:%d) (fmt: %s)\n", reqlen, fmt);
|
||||||
|
tty_color(0);
|
||||||
|
//assert(reqlen < STACK_ALLOC);
|
||||||
|
STACK_ALLOC = reqlen * 2;
|
||||||
|
buf = REALLOC(0, STACK_ALLOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* ptr = buf + (cur *= (cur+reqlen) < (STACK_ALLOC - 1), (cur += reqlen) - reqlen);
|
||||||
|
|
||||||
/*stbsp_*/vsnprintf( ptr, sz, fmt, vl );
|
/*stbsp_*/vsnprintf( ptr, sz, fmt, vl );
|
||||||
return (char *)ptr;
|
return (char *)ptr;
|
||||||
|
@ -1430,10 +1440,17 @@ float audio_volume_master(float gain) {
|
||||||
mixer.gain = volume_master;
|
mixer.gain = volume_master;
|
||||||
return sqrt( volume_master );
|
return sqrt( volume_master );
|
||||||
}
|
}
|
||||||
|
int audio_mute(int mute) {
|
||||||
|
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||||
|
if( mute >= 0 && mute <= 1 ) muted = mute;
|
||||||
|
return muted;
|
||||||
|
}
|
||||||
|
int audio_muted() {
|
||||||
|
return audio_mute(-1);
|
||||||
|
}
|
||||||
|
|
||||||
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
||||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
if(audio_muted()) return 1;
|
||||||
if(muted) return 1;
|
|
||||||
|
|
||||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||||
// do nothing, gain used as-is
|
// do nothing, gain used as-is
|
||||||
|
@ -4179,7 +4196,7 @@ array(struct fs) zipscan_filter(int threadid, int numthreads) {
|
||||||
|
|
||||||
// skip if list item does not belong to this thread bucket
|
// skip if list item does not belong to this thread bucket
|
||||||
uint64_t hash = hash_str(fname);
|
uint64_t hash = hash_str(fname);
|
||||||
unsigned bucket = (hash >> 32) % numthreads;
|
unsigned bucket = (hash /*>> 32*/) % numthreads;
|
||||||
if(bucket != threadid) continue;
|
if(bucket != threadid) continue;
|
||||||
|
|
||||||
array_push(fs, fs_now[i]);
|
array_push(fs, fs_now[i]);
|
||||||
|
@ -4436,10 +4453,8 @@ bool cook_start( const char *cook_ini, const char *masks, int flags ) {
|
||||||
char *s = strchr( ART, ';' ); if(s) *s = 0;
|
char *s = strchr( ART, ';' ); if(s) *s = 0;
|
||||||
char *w = strchr( ART, ' ' ); if(w) *w = 0;
|
char *w = strchr( ART, ' ' ); if(w) *w = 0;
|
||||||
char *out = 0; const char *sep = "";
|
char *out = 0; const char *sep = "";
|
||||||
const char *v4k_title = getenv("V4K_TITLE");
|
|
||||||
for each_substring(ART, ",", t) {
|
for each_substring(ART, ",", t) {
|
||||||
char *tmp = file_pathabs(va("%s%s", HOME, t)) + ART_LEN;
|
char *tmp = file_pathabs(va("%s%s", HOME, t)) + ART_LEN;
|
||||||
PRINTF("ART mount+=%s\n", tmp);
|
|
||||||
for(int i = 0; tmp[i]; ++i) if(tmp[i]=='\\') tmp[i] = '/';
|
for(int i = 0; tmp[i]; ++i) if(tmp[i]=='\\') tmp[i] = '/';
|
||||||
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
||||||
assert( out[strlen(out) - 1] == '/' );
|
assert( out[strlen(out) - 1] == '/' );
|
||||||
|
@ -5226,7 +5241,7 @@ bool file_delete(const char *pathfile) {
|
||||||
}
|
}
|
||||||
bool file_copy(const char *src, const char *dst) {
|
bool file_copy(const char *src, const char *dst) {
|
||||||
int ok = 0, BUFSIZE = 1 << 20; // 1 MiB
|
int ok = 0, BUFSIZE = 1 << 20; // 1 MiB
|
||||||
static __thread char *buffer = 0; do_once buffer = REALLOC(0, BUFSIZE);
|
static __thread char *buffer = 0; do_once buffer = REALLOC(0, BUFSIZE); // @leak
|
||||||
for( FILE *in = fopen(src, "rb"); in; fclose(in), in = 0) {
|
for( FILE *in = fopen(src, "rb"); in; fclose(in), in = 0) {
|
||||||
for( FILE *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
for( FILE *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
||||||
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
||||||
|
@ -5551,6 +5566,8 @@ void vfs_reload() {
|
||||||
#if defined(EMSCRIPTEN)
|
#if defined(EMSCRIPTEN)
|
||||||
vfs_mount("index.zip");
|
vfs_mount("index.zip");
|
||||||
#else
|
#else
|
||||||
|
// mount fused executables
|
||||||
|
vfs_mount(va("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")));
|
||||||
/* // old way
|
/* // old way
|
||||||
for( int i = 0; i < JOBS_MAX; ++i) {
|
for( int i = 0; i < JOBS_MAX; ++i) {
|
||||||
if( vfs_mount(va(".art[%02x].zip", i)) ) continue;
|
if( vfs_mount(va(".art[%02x].zip", i)) ) continue;
|
||||||
|
@ -5570,6 +5587,34 @@ void vfs_reload() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define ARK1 'ArK\x1'
|
||||||
|
#define ARK1_PADDING (512 - 40) // 472
|
||||||
|
#define ARK_PRINTF(f,...) 0 // printf(f,__VA_ARGS__)
|
||||||
|
#define ARK_SWAP32(x) (x)
|
||||||
|
#define ARK_SWAP64(x) (x)
|
||||||
|
#define ARK_REALLOC REALLOC
|
||||||
|
static uint64_t ark_fget64( FILE *in ) { uint64_t v; fread( &v, 1, 8, in ); return ARK_SWAP64(v); }
|
||||||
|
void ark_list( const char *infile, zip **z ) {
|
||||||
|
for( FILE *in = fopen(infile, "rb"); in; fclose(in), in = 0 )
|
||||||
|
while(!feof(in)) {
|
||||||
|
if( 0 != (ftell(in) % ARK1_PADDING) ) fseek(in, ARK1_PADDING - (ftell(in) % ARK1_PADDING), SEEK_CUR);
|
||||||
|
ARK_PRINTF("Reading at #%d\n", (int)ftell(in));
|
||||||
|
uint64_t mark = ark_fget64(in);
|
||||||
|
if( mark != ARK1 ) continue;
|
||||||
|
uint64_t stamp = ark_fget64(in);
|
||||||
|
uint64_t datalen = ark_fget64(in);
|
||||||
|
uint64_t datahash = ark_fget64(in);
|
||||||
|
uint64_t namelen = ark_fget64(in);
|
||||||
|
|
||||||
|
*z = zip_open_handle(in, "rb");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||||
zip *z = NULL; tar *t = NULL; pak *p = NULL; dir *d = NULL;
|
zip *z = NULL; tar *t = NULL; pak *p = NULL; dir *d = NULL;
|
||||||
|
@ -5579,6 +5624,7 @@ bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||||
if( !is_folder ) z = zip_open(path, "rb");
|
if( !is_folder ) z = zip_open(path, "rb");
|
||||||
if( !is_folder && !z ) t = tar_open(path, "rb");
|
if( !is_folder && !z ) t = tar_open(path, "rb");
|
||||||
if( !is_folder && !z && !t ) p = pak_open(path, "rb");
|
if( !is_folder && !z && !t ) p = pak_open(path, "rb");
|
||||||
|
if( !is_folder && !z && !t && !p ) ark_list(path, &z); // last resort. try as .ark
|
||||||
if( !is_folder && !z && !t && !p ) return 0;
|
if( !is_folder && !z && !t && !p ) return 0;
|
||||||
|
|
||||||
// normalize input -> "././" to ""
|
// normalize input -> "././" to ""
|
||||||
|
@ -5763,9 +5809,9 @@ if( found && *found == 0 ) {
|
||||||
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
||||||
|
|
||||||
// search (last item)
|
// search (last item)
|
||||||
static char last_item[256] = { 0 };
|
static __thread char last_item[256] = { 0 };
|
||||||
static void *last_ptr = 0;
|
static __thread void *last_ptr = 0;
|
||||||
static int last_size = 0;
|
static __thread int last_size = 0;
|
||||||
if( !strcmpi(lookup_id, last_item)) {
|
if( !strcmpi(lookup_id, last_item)) {
|
||||||
ptr = last_ptr;
|
ptr = last_ptr;
|
||||||
size = last_size;
|
size = last_size;
|
||||||
|
@ -5922,6 +5968,10 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
if( !MAX_CACHED_FILES ) return 0;
|
if( !MAX_CACHED_FILES ) return 0;
|
||||||
if( !ptr || !size ) return 0;
|
if( !ptr || !size ) return 0;
|
||||||
|
|
||||||
|
// keep cached files within limits
|
||||||
|
static thread_mutex_t mutex, *init = 0; if(!init) thread_mutex_init(init = &mutex);
|
||||||
|
thread_mutex_lock(&mutex);
|
||||||
|
|
||||||
// append to cache
|
// append to cache
|
||||||
archive_dir zero = {0}, *old = dir_cache;
|
archive_dir zero = {0}, *old = dir_cache;
|
||||||
*(dir_cache = REALLOC(0, sizeof(archive_dir))) = zero;
|
*(dir_cache = REALLOC(0, sizeof(archive_dir))) = zero;
|
||||||
|
@ -5931,7 +5981,8 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
dir_cache->data = REALLOC(0, size+1);
|
dir_cache->data = REALLOC(0, size+1);
|
||||||
memcpy(dir_cache->data, ptr, size); size[(char*)dir_cache->data] = 0; // copy+terminator
|
memcpy(dir_cache->data, ptr, size); size[(char*)dir_cache->data] = 0; // copy+terminator
|
||||||
|
|
||||||
// keep cached files within limits
|
void *found = 0;
|
||||||
|
|
||||||
static int added = 0;
|
static int added = 0;
|
||||||
if( added < MAX_CACHED_FILES ) {
|
if( added < MAX_CACHED_FILES ) {
|
||||||
++added;
|
++added;
|
||||||
|
@ -5940,15 +5991,18 @@ void* cache_insert(const char *pathfile, void *ptr, int size) { // append key/va
|
||||||
for( archive_dir *prev = dir_cache, *dir = prev; dir ; prev = dir, dir = dir->next ) {
|
for( archive_dir *prev = dir_cache, *dir = prev; dir ; prev = dir, dir = dir->next ) {
|
||||||
if( !dir->next ) {
|
if( !dir->next ) {
|
||||||
prev->next = 0; // break link
|
prev->next = 0; // break link
|
||||||
void *data = dir->data;
|
found = dir->data;
|
||||||
dir->path = REALLOC(dir->path, 0);
|
dir->path = REALLOC(dir->path, 0);
|
||||||
dir->data = REALLOC(dir->data, 0);
|
dir->data = REALLOC(dir->data, 0);
|
||||||
dir = REALLOC(dir, 0);
|
dir = REALLOC(dir, 0);
|
||||||
return data;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
thread_mutex_unlock(&mutex);
|
||||||
|
|
||||||
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -12721,8 +12775,8 @@ static map(unsigned, reflected_t) reflects;
|
||||||
static map(unsigned, array(reflected_t)) members;
|
static map(unsigned, array(reflected_t)) members;
|
||||||
|
|
||||||
void reflected_printf(reflected_t *r) {
|
void reflected_printf(reflected_t *r) {
|
||||||
printf("id:%u objtype:%u sz:%u name:%s info:%s addr:%p parent:%u type:%s",
|
printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s",
|
||||||
r->id, r->objtype, r->sz, r->name ? r->name : "", r->info ? r->info : "", r->addr, r->parent, r->type ? r->type : "");
|
r->name ? r->name : "", r->info ? r->info : "", r->id, r->objtype, r->sz, r->addr, r->parent, r->type ? r->type : "");
|
||||||
}
|
}
|
||||||
void reflected_printf_all() {
|
void reflected_printf_all() {
|
||||||
for each_map_ptr(reflects, unsigned, k, reflected_t, p) {
|
for each_map_ptr(reflects, unsigned, k, reflected_t, p) {
|
||||||
|
@ -20295,6 +20349,26 @@ bool app_open(const char *link) {
|
||||||
return app_open_url(link);
|
return app_open_url(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* app_loadfile() {
|
||||||
|
const char *windowTitle = NULL;
|
||||||
|
const char *defaultPathFile = NULL;
|
||||||
|
const char *filterHints = NULL; // "image files"
|
||||||
|
const char *filters[] = { "*.*" };
|
||||||
|
int allowMultipleSelections = 0;
|
||||||
|
|
||||||
|
tinyfd_assumeGraphicDisplay = 1;
|
||||||
|
return tinyfd_openFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints, allowMultipleSelections );
|
||||||
|
}
|
||||||
|
const char* app_savefile() {
|
||||||
|
const char *windowTitle = NULL;
|
||||||
|
const char *defaultPathFile = NULL;
|
||||||
|
const char *filterHints = NULL; // "image files"
|
||||||
|
const char *filters[] = { "*.*" };
|
||||||
|
|
||||||
|
tinyfd_assumeGraphicDisplay = 1;
|
||||||
|
return tinyfd_saveFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints );
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// tests
|
// tests
|
||||||
|
|
||||||
|
@ -21881,11 +21955,12 @@ int ui_collapse_end() {
|
||||||
|
|
||||||
|
|
||||||
int ui_contextual() {
|
int ui_contextual() {
|
||||||
struct nk_rect bounds = nk_widget_bounds(ui_ctx);
|
struct nk_rect bounds = nk_widget_bounds(ui_ctx); // = nk_window_get_bounds(ui_ctx);
|
||||||
bounds.y -= 25;
|
bounds.y -= 25;
|
||||||
return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds);
|
return ui_popups() ? 0 : nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 300), bounds);
|
||||||
}
|
}
|
||||||
int ui_contextual_end() {
|
int ui_contextual_end(int close) {
|
||||||
|
if(close) nk_contextual_close(ui_ctx);
|
||||||
nk_contextual_end(ui_ctx);
|
nk_contextual_end(ui_ctx);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -21896,7 +21971,7 @@ int ui_submenu(const char *options) {
|
||||||
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
||||||
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
||||||
}
|
}
|
||||||
ui_contextual_end();
|
ui_contextual_end(0);
|
||||||
}
|
}
|
||||||
return choice;
|
return choice;
|
||||||
}
|
}
|
||||||
|
@ -22030,8 +22105,10 @@ int ui_label(const char *text) {
|
||||||
int ui_label2(const char *label, const char *text_) {
|
int ui_label2(const char *label, const char *text_) {
|
||||||
nk_layout_row_dynamic(ui_ctx, 0, 2);
|
nk_layout_row_dynamic(ui_ctx, 0, 2);
|
||||||
|
|
||||||
int align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
int align1 = NK_TEXT_LEFT;
|
||||||
int align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
int align2 = NK_TEXT_LEFT;
|
||||||
|
if( label ) align1 = label[0] == '>' ? (label++, NK_TEXT_RIGHT) : label[0] == '=' ? (label++, NK_TEXT_CENTERED) : label[0] == '<' ? (label++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||||
|
if( text_ ) align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||||
ui_label_(label, align1);
|
ui_label_(label, align1);
|
||||||
|
|
||||||
const struct nk_input *input = &ui_ctx->input;
|
const struct nk_input *input = &ui_ctx->input;
|
||||||
|
@ -23766,12 +23843,38 @@ int window_frame_begin() {
|
||||||
if( may_render_stats ) {
|
if( may_render_stats ) {
|
||||||
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
||||||
|
|
||||||
#if 1
|
static int time_factor = 0;
|
||||||
static char *filter = 0;
|
static int playing = 0;
|
||||||
|
static int paused = 0;
|
||||||
|
int advance_frame = 0;
|
||||||
|
|
||||||
static int do_filter = 0;
|
static int do_filter = 0;
|
||||||
|
static int do_profile = 0;
|
||||||
|
static int do_extra = 0;
|
||||||
|
|
||||||
|
char *EDITOR_TOOLBAR_ICONS = va("%s;%s;%s;%s;%s;%s;%s;%s",
|
||||||
|
do_filter ? ICON_MD_CLOSE : ICON_MD_SEARCH,
|
||||||
|
ICON_MD_PLAY_ARROW,
|
||||||
|
paused ? ICON_MD_SKIP_NEXT : ICON_MD_PAUSE,
|
||||||
|
ICON_MD_FAST_FORWARD,
|
||||||
|
ICON_MD_STOP,
|
||||||
|
ICON_MD_REPLAY,
|
||||||
|
ICON_MD_FACE,
|
||||||
|
ICON_MD_MENU
|
||||||
|
);
|
||||||
|
|
||||||
if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1;
|
if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1;
|
||||||
int choice = ui_toolbar(ICON_MD_SEARCH ";");
|
int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS);
|
||||||
if( choice == 1 ) do_filter = 1;
|
if( choice == 1 ) do_filter ^= 1, do_profile = 0, do_extra = 0;
|
||||||
|
if( choice == 2 ) playing = 1, paused = 0;
|
||||||
|
if( choice == 3 ) advance_frame = !!paused, paused = 1;
|
||||||
|
if( choice == 4 ) paused = 0, time_factor = (++time_factor) % 4;
|
||||||
|
if( choice == 5 ) playing = 0, paused = 0, advance_frame = 0, time_factor = 0;
|
||||||
|
if( choice == 6 ) window_reload();
|
||||||
|
if( choice == 7 ) do_filter = 0, do_profile ^= 1, do_extra = 0;
|
||||||
|
if( choice == 8 ) do_filter = 0, do_profile = 0, do_extra ^= 1;
|
||||||
|
|
||||||
|
static char *filter = 0;
|
||||||
if( do_filter ) {
|
if( do_filter ) {
|
||||||
ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter);
|
ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter);
|
||||||
if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon)
|
if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon)
|
||||||
|
@ -23781,13 +23884,44 @@ int window_frame_begin() {
|
||||||
if( filter ) filter[0] = '\0';
|
if( filter ) filter[0] = '\0';
|
||||||
}
|
}
|
||||||
char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*";
|
char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*";
|
||||||
#endif
|
|
||||||
|
static char *username = 0;
|
||||||
|
static char *userpass = 0;
|
||||||
|
if( do_profile ) {
|
||||||
|
ui_string(ICON_MD_FACE " Username", &username);
|
||||||
|
ui_string(ICON_MD_FACE " Password", &userpass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( do_extra ) {
|
||||||
|
int choice2 = ui_label2_toolbar(NULL,
|
||||||
|
ICON_MD_VIEW_IN_AR
|
||||||
|
ICON_MD_MESSAGE
|
||||||
|
ICON_MD_TIPS_AND_UPDATES ICON_MD_LIGHTBULB ICON_MD_LIGHTBULB_OUTLINE
|
||||||
|
ICON_MD_IMAGE_SEARCH ICON_MD_INSERT_PHOTO
|
||||||
|
ICON_MD_VIDEOGAME_ASSET ICON_MD_VIDEOGAME_ASSET_OFF
|
||||||
|
|
||||||
|
ICON_MD_VOLUME_UP ICON_MD_VOLUME_OFF // audio_volume_master(-1) > 0
|
||||||
|
|
||||||
|
ICON_MD_TROUBLESHOOT ICON_MD_SCHEMA ICON_MD_MENU
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
int open = 0, clicked_or_toggled = 0;
|
int open = 0, clicked_or_toggled = 0;
|
||||||
|
|
||||||
#define ui_collapse_filtered(lbl,id) (strmatchi(lbl,filter_mask) && ui_collapse(lbl,id))
|
#define ui_collapse_filtered(lbl,id) (strmatchi(lbl,filter_mask) && ui_collapse(lbl,id))
|
||||||
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
#define EDITOR_UI_COLLAPSE(f,...) \
|
||||||
|
for( int macro(p) = (open = ui_collapse_filtered(f,__VA_ARGS__)), macro(dummy) = (clicked_or_toggled = ui_collapse_clicked()); macro(p); ui_collapse_end(), macro(p) = 0)
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUG_REPORT " Bugs 0", "Debug.Bugs") {
|
||||||
|
// @todo. parse /bugs.ini, includes saved screenshots & videos.
|
||||||
|
// @todo. screenshot include parseable level, position screen markers (same info as /bugs.ini)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Art and bookmarks
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art") {
|
||||||
bool inlined = true;
|
bool inlined = true;
|
||||||
const char *file = 0;
|
const char *file = 0;
|
||||||
if( ui_browse(&file, &inlined) ) {
|
if( ui_browse(&file, &inlined) ) {
|
||||||
|
@ -23795,47 +23929,78 @@ int window_frame_begin() {
|
||||||
app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep));
|
app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_BOOKMARK " Bookmarks", "Debug.Bookmarks") { /* @todo */ }
|
||||||
|
|
||||||
|
|
||||||
|
// E,C,S,W
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Scene", "Debug.Scene") {
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUBBLE_CHART/*ICON_MD_SCATTER_PLOT*/ " Entities", "Debug.Entities") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_TUNE " Components", "Debug.Components") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_PRECISION_MANUFACTURING " Systems", "Debug.Systems") { /* @todo */ }
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_PUBLIC " Levels", "Debug.Levels") {
|
||||||
|
//node_edit(editor.edit.down,&editor.edit);
|
||||||
|
}
|
||||||
|
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Init", "Debug.HierarchyInit") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Draw", "Debug.HierarchyDraw") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Tick", "Debug.HierarchyTick") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Edit", "Debug.HierarchyEdit") { /* @todo */ }
|
||||||
|
//EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Quit", "Debug.HierarchyQuit") { /* @todo */ }
|
||||||
|
|
||||||
|
// node_edit(&editor.init,&editor.init);
|
||||||
|
// node_edit(&editor.draw,&editor.draw);
|
||||||
|
// node_edit(&editor.tick,&editor.tick);
|
||||||
|
// node_edit(&editor.edit,&editor.edit);
|
||||||
|
// node_edit(&editor.quit,&editor.quit);
|
||||||
|
}
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI") {
|
||||||
// @todo
|
// @todo
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VOLUME_UP " Audio", "Debug.Audio")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_VOLUME_UP " Audio", "Debug.Audio") {
|
||||||
ui_audio();
|
ui_audio();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VIDEOCAM " Camera", "Debug.Camera")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_VIDEOCAM " Camera", "Debug.Camera") {
|
||||||
ui_camera( camera_get_active() );
|
ui_camera( camera_get_active() );
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_BUILD " Cook", "Debug.Cook")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") {
|
||||||
// @todo
|
// @todo: fps lock, fps target, aspect ratio, fullscreen
|
||||||
|
char *text = va("%s;%s;%s",
|
||||||
|
window_has_fullscreen() ? ICON_MD_FULLSCREEN_EXIT : ICON_MD_FULLSCREEN,
|
||||||
|
ICON_MD_PHOTO_CAMERA,
|
||||||
|
record_active() ? ICON_MD_VIDEOCAM_OFF : ICON_MD_VIDEOCAM
|
||||||
|
);
|
||||||
|
|
||||||
|
int choice = ui_toolbar(text);
|
||||||
|
if( choice == 1 ) editor_send("key_fullscreen",0);
|
||||||
|
if( choice == 2 ) editor_send("key_screenshot",0);
|
||||||
|
if( choice == 3 ) editor_send("key_record",0);
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_SIGNAL_CELLULAR_ALT " Network", "Debug.Network")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") {
|
||||||
// @todo
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
// @todo
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_MOVIE " FXs", "Debug.FXs")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_fxs();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_SPEED " Profiler", "Debug.Profiler")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_profiler();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_shaders();
|
|
||||||
}
|
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
ui_keyboard();
|
ui_keyboard();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_MOUSE " Mouse", "Debug.Mouse")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_MOUSE " Mouse", "Debug.Mouse") {
|
||||||
ui_mouse();
|
ui_mouse();
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
EDITOR_UI_COLLAPSE(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads") {
|
||||||
for( int q = 0; q < 4; ++q ) {
|
for( int q = 0; q < 4; ++q ) {
|
||||||
for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) {
|
for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) {
|
||||||
ui_gamepad(q);
|
ui_gamepad(q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for( int p = (open = ui_collapse_filtered(ICON_MD_VIEW_QUILT " UI", "Debug.UI")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders") {
|
||||||
|
ui_shaders();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_MOVIE " FXs", "Debug.FXs") {
|
||||||
|
ui_fxs();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_VIEW_QUILT " UI", "Debug.UI") {
|
||||||
int choice = ui_toolbar(ICON_MD_RECYCLING " Reset layout;" ICON_MD_SAVE_AS " Save layout");
|
int choice = ui_toolbar(ICON_MD_RECYCLING " Reset layout;" ICON_MD_SAVE_AS " Save layout");
|
||||||
if( choice == 1 ) ui_layout_all_reset("*");
|
if( choice == 1 ) ui_layout_all_reset("*");
|
||||||
if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*");
|
if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*");
|
||||||
|
@ -23848,8 +24013,61 @@ int window_frame_begin() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_SAVINGS " Budgets", "Debug.Budgets") {
|
||||||
|
// @todo. // mem,fps,gfx,net,hdd,... also logging
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_WIFI/*ICON_MD_SIGNAL_CELLULAR_ALT*/ " Network 0/0 KiB", "Debug.Network") {
|
||||||
|
// @todo
|
||||||
|
// SIGNAL_CELLULAR_1_BAR SIGNAL_CELLULAR_2_BAR
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%d", window_fps(), (int)window_fps_target()), "Debug.Profiler") {
|
||||||
|
ui_profiler();
|
||||||
|
}
|
||||||
|
EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// logic: either plug icon (power saving off) or one of the following ones (power saving on):
|
||||||
|
// if 0% batt (no batt): battery alert
|
||||||
|
// if discharging: battery levels [alert,0..6,full]
|
||||||
|
// if charging: battery charging
|
||||||
|
int battery_read = app_battery();
|
||||||
|
int battery_level = abs(battery_read);
|
||||||
|
int battery_discharging = battery_read < 0 && battery_level < 100;
|
||||||
|
const char *power_icon_label = ICON_MD_POWER " Power";
|
||||||
|
if( battery_level ) {
|
||||||
|
const char *battery_levels[9] = { // @todo: remap [7%..100%] -> [0..1] ?
|
||||||
|
ICON_MD_BATTERY_ALERT,ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR,
|
||||||
|
ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR,ICON_MD_BATTERY_4_BAR,
|
||||||
|
ICON_MD_BATTERY_5_BAR,ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL,
|
||||||
|
};
|
||||||
|
power_icon_label = (const char*)va("%s Power %d%%",
|
||||||
|
battery_discharging ? battery_levels[(int)((9-1)*clampf(battery_level/100.f,0,1))] : ICON_MD_BATTERY_CHARGING_FULL,
|
||||||
|
battery_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") {
|
||||||
|
int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT );
|
||||||
|
if( choice == 1 ) editor_send("key_battery","0");
|
||||||
|
if( choice == 2 ) editor_send("key_battery","1");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_EXTENSION " Plugins", "Debug.Plugins") {
|
||||||
|
// @todo. include VCS
|
||||||
|
EDITOR_UI_COLLAPSE(ICON_MD_BUILD " Cook", "Debug.Cook") {
|
||||||
|
// @todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(has_menu ? ui_window_end : ui_panel_end)();
|
(has_menu ? ui_window_end : ui_panel_end)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API int editor_tick();
|
||||||
|
editor_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 // deprecated
|
#if 0 // deprecated
|
||||||
|
@ -25250,6 +25468,61 @@ int ui_bt(bt_t *b) {
|
||||||
// editing:
|
// editing:
|
||||||
// nope > functions: add/rem property
|
// nope > functions: add/rem property
|
||||||
|
|
||||||
|
#define ICON_PLAY ICON_MD_PLAY_ARROW
|
||||||
|
#define ICON_PAUSE ICON_MD_PAUSE
|
||||||
|
#define ICON_STOP ICON_MD_STOP
|
||||||
|
#define ICON_CANCEL ICON_MD_CLOSE
|
||||||
|
|
||||||
|
#define ICON_WARNING ICON_MD_WARNING
|
||||||
|
#define ICON_BROWSER ICON_MD_FOLDER_SPECIAL
|
||||||
|
#define ICON_OUTLINER ICON_MD_VIEW_IN_AR
|
||||||
|
#define ICON_BUILD ICON_MD_BUILD
|
||||||
|
#define ICON_SCREENSHOT ICON_MD_PHOTO_CAMERA
|
||||||
|
#define ICON_CAMERA_ON ICON_MD_VIDEOCAM
|
||||||
|
#define ICON_CAMERA_OFF ICON_MD_VIDEOCAM_OFF
|
||||||
|
#define ICON_GAMEPAD_ON ICON_MD_VIDEOGAME_ASSET
|
||||||
|
#define ICON_GAMEPAD_OFF ICON_MD_VIDEOGAME_ASSET_OFF
|
||||||
|
#define ICON_AUDIO_ON ICON_MD_VOLUME_UP
|
||||||
|
#define ICON_AUDIO_OFF ICON_MD_VOLUME_OFF
|
||||||
|
#define ICON_WINDOWED ICON_MD_FULLSCREEN_EXIT
|
||||||
|
#define ICON_FULLSCREEN ICON_MD_FULLSCREEN
|
||||||
|
#define ICON_LIGHTS_ON ICON_MD_LIGHTBULB
|
||||||
|
#define ICON_LIGHTS_OFF ICON_MD_LIGHTBULB_OUTLINE
|
||||||
|
#define ICON_RENDER_BASIC ICON_MD_IMAGE_SEARCH
|
||||||
|
#define ICON_RENDER_FULL ICON_MD_INSERT_PHOTO
|
||||||
|
|
||||||
|
#define ICON_SIGNAL ICON_MD_SIGNAL_CELLULAR_ALT
|
||||||
|
#define ICON_DISK ICON_MD_STORAGE
|
||||||
|
#define ICON_RATE ICON_MD_SPEED
|
||||||
|
|
||||||
|
#define ICON_CLOCK ICON_MD_TODAY
|
||||||
|
#define ICON_CHRONO ICON_MD_TIMELAPSE
|
||||||
|
|
||||||
|
#define ICON_SETTINGS ICON_MD_SETTINGS
|
||||||
|
#define ICON_LANGUAGE ICON_MD_G_TRANSLATE
|
||||||
|
#define ICON_PERSONA ICON_MD_FACE
|
||||||
|
#define ICON_SOCIAL ICON_MD_MESSAGE
|
||||||
|
#define ICON_GAME ICON_MD_ROCKET_LAUNCH
|
||||||
|
#define ICON_KEYBOARD ICON_MD_KEYBOARD
|
||||||
|
#define ICON_MOUSE ICON_MD_MOUSE
|
||||||
|
#define ICON_GAMEPAD ICON_MD_GAMEPAD
|
||||||
|
#define ICON_MONITOR ICON_MD_MONITOR
|
||||||
|
#define ICON_WIFI ICON_MD_WIFI
|
||||||
|
#define ICON_BUDGET ICON_MD_SAVINGS
|
||||||
|
#define ICON_NEW_FOLDER ICON_MD_CREATE_NEW_FOLDER
|
||||||
|
#define ICON_PLUGIN ICON_MD_EXTENSION
|
||||||
|
#define ICON_RESTART ICON_MD_REPLAY
|
||||||
|
#define ICON_QUIT ICON_MD_CLOSE
|
||||||
|
|
||||||
|
#define ICON_POWER ICON_MD_BOLT // ICON_MD_POWER
|
||||||
|
#define ICON_BATTERY_CHARGING ICON_MD_BATTERY_CHARGING_FULL
|
||||||
|
#define ICON_BATTERY_LEVELS \
|
||||||
|
ICON_MD_BATTERY_ALERT, \
|
||||||
|
ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR, \
|
||||||
|
ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR, \
|
||||||
|
ICON_MD_BATTERY_4_BAR,ICON_MD_BATTERY_5_BAR, \
|
||||||
|
ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL
|
||||||
|
|
||||||
char *editor_path(const char *path) {
|
char *editor_path(const char *path) {
|
||||||
return va("%s/%s", EDITOR, path);
|
return va("%s/%s", EDITOR, path);
|
||||||
}
|
}
|
||||||
|
@ -25314,6 +25587,75 @@ int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate
|
||||||
return clicked | (copy ^ *enabled);
|
return clicked | (copy ^ *enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef union editor_var {
|
||||||
|
int i;
|
||||||
|
float f;
|
||||||
|
char *s;
|
||||||
|
} editor_var;
|
||||||
|
static map(char*,editor_var) editor_vars;
|
||||||
|
float *editor_getf(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
return &found->f;
|
||||||
|
}
|
||||||
|
int *editor_geti(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
return &found->i;
|
||||||
|
}
|
||||||
|
char **editor_gets(const char *key) {
|
||||||
|
if(!editor_vars) map_init_str(editor_vars);
|
||||||
|
editor_var *found = map_find_or_add(editor_vars, (char*)key, ((editor_var){0}) );
|
||||||
|
if(!found->s) found->s = stringf("%s","");
|
||||||
|
return &found->s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editor_send(const char *cmd, const char *optional_value) {
|
||||||
|
unsigned *gamepads = editor_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)...
|
||||||
|
unsigned *renders = editor_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes
|
||||||
|
float *speed = editor_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8)
|
||||||
|
unsigned *powersave = editor_geti("powersave");
|
||||||
|
|
||||||
|
char *name;
|
||||||
|
/**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0);
|
||||||
|
else if( !strcmp(cmd, "key_stop" )) window_pause(1);
|
||||||
|
else if( !strcmp(cmd, "key_mute" )) audio_volume_master( 1 ^ !!audio_volume_master(-1) );
|
||||||
|
else if( !strcmp(cmd, "key_pause" )) window_pause( window_has_pause() ^ 1 );
|
||||||
|
else if( !strcmp(cmd, "key_reload" )) window_reload();
|
||||||
|
else if( !strcmp(cmd, "key_battery" )) *powersave = optional_value ? !!atoi(optional_value) : *powersave ^ 1;
|
||||||
|
else if( !strcmp(cmd, "key_browser" )) ui_show("File Browser", ui_visible("File Browser") ^ true);
|
||||||
|
else if( !strcmp(cmd, "key_outliner" )) ui_show("Outliner", ui_visible("Outliner") ^ true);
|
||||||
|
else if( !strcmp(cmd, "key_record" )) if(record_active()) record_stop(); else
|
||||||
|
name = file_counter(va("%s.mp4",app_name())), window_record(name), ui_notify(va("Video capturing: %s", name), date_string());
|
||||||
|
else if( !strcmp(cmd, "key_screenshot" )) name = file_counter(va("%s.png",app_name())), window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string());
|
||||||
|
else if( !strcmp(cmd, "key_profiler" )) ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true));
|
||||||
|
else if( !strcmp(cmd, "key_fullscreen" )) record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); // framebuffer resizing corrupts video stream, so stop any recording beforehand
|
||||||
|
else if( !strcmp(cmd, "key_gamepad" )) *gamepads = (*gamepads & ~1u) | ((*gamepads & 1) ^ 1);
|
||||||
|
else if( !strcmp(cmd, "key_lit" )) *renders = (*renders & ~1u) | ((*renders & 1) ^ 1);
|
||||||
|
else if( !strcmp(cmd, "key_ddraw" )) *renders = (*renders & ~2u) | ((*renders & 2) ^ 2);
|
||||||
|
else alert(va("editor could not handle `%s` command.", cmd));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editor_tick() {
|
||||||
|
enum { editor_hz = 60 };
|
||||||
|
enum { editor_hz_mid = 18 };
|
||||||
|
enum { editor_hz_low = 5 };
|
||||||
|
if( *editor_geti("powersave") ) {
|
||||||
|
// adaptive framerate
|
||||||
|
int app_on_background = !window_has_focus();
|
||||||
|
int hz = app_on_background ? editor_hz_low : editor_hz_mid;
|
||||||
|
window_fps_lock( hz < 5 ? 5 : hz );
|
||||||
|
} else {
|
||||||
|
// window_fps_lock( editor_hz );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int gizmo__mode;
|
static int gizmo__mode;
|
||||||
static int gizmo__active;
|
static int gizmo__active;
|
||||||
static int gizmo__hover;
|
static int gizmo__hover;
|
||||||
|
@ -25425,26 +25767,6 @@ int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* dialog_load() {
|
|
||||||
const char *windowTitle = NULL;
|
|
||||||
const char *defaultPathFile = NULL;
|
|
||||||
const char *filterHints = NULL; // "image files"
|
|
||||||
const char *filters[] = { "*.*" };
|
|
||||||
int allowMultipleSelections = 0;
|
|
||||||
|
|
||||||
tinyfd_assumeGraphicDisplay = 1;
|
|
||||||
return tinyfd_openFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints, allowMultipleSelections );
|
|
||||||
}
|
|
||||||
char* dialog_save() {
|
|
||||||
const char *windowTitle = NULL;
|
|
||||||
const char *defaultPathFile = NULL;
|
|
||||||
const char *filterHints = NULL; // "image files"
|
|
||||||
const char *filters[] = { "*.*" };
|
|
||||||
|
|
||||||
tinyfd_assumeGraphicDisplay = 1;
|
|
||||||
return tinyfd_saveFileDialog( windowTitle, defaultPathFile, countof(filters), filters, filterHints );
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- localization kit
|
// -- localization kit
|
||||||
|
|
||||||
static const char *kit_lang = "enUS", *kit_langs =
|
static const char *kit_lang = "enUS", *kit_langs =
|
||||||
|
@ -25618,18 +25940,20 @@ static void v4k_pre_init() {
|
||||||
// window_swap();
|
// window_swap();
|
||||||
}
|
}
|
||||||
static void v4k_post_init(float refresh_rate) {
|
static void v4k_post_init(float refresh_rate) {
|
||||||
|
int i;
|
||||||
|
|
||||||
// cook cleanup
|
// cook cleanup
|
||||||
cook_stop();
|
cook_stop();
|
||||||
|
|
||||||
vfs_reload();
|
vfs_reload();
|
||||||
|
|
||||||
|
// init subsystems that depend on cooked assets now. ui_init() is special case and needs to be safely in single thread
|
||||||
|
ui_init();
|
||||||
|
|
||||||
// init more subsystems; beware of VFS mounting, as some of these may need cooked assets at this point
|
// init more subsystems; beware of VFS mounting, as some of these may need cooked assets at this point
|
||||||
int i;
|
|
||||||
#if 1 // #ifdef PARALLEL_INIT
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
#endif
|
|
||||||
for( i = 0; i <= 3; ++i) {
|
for( i = 0; i <= 3; ++i) {
|
||||||
/**/ if( i == 0 ) ui_init(), scene_init(); // init these on thread #0, since both will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
/**/ if( i == 0 ) scene_init(); // init these on thread #0, since both will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
||||||
else if( i == 1 ) audio_init(0); // initialize audio after cooking // reasoning for this: do not launch audio threads while cooks are in progress, so there is more cpu for cooking actually
|
else if( i == 1 ) audio_init(0); // initialize audio after cooking // reasoning for this: do not launch audio threads while cooks are in progress, so there is more cpu for cooking actually
|
||||||
else if( i == 2 ) script_init(), kit_init(), midi_init();
|
else if( i == 2 ) script_init(), kit_init(), midi_init();
|
||||||
else if( i == 3 ) input_init(), network_init();
|
else if( i == 3 ) input_init(), network_init();
|
||||||
|
|
29
engine/v4k.h
29
engine/v4k.h
|
@ -1359,9 +1359,12 @@ API int audio_play_gain_pitch( audio_t a, int flags, float gain, float pitch
|
||||||
API int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan/*0*/ );
|
API int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan/*0*/ );
|
||||||
API int audio_stop( audio_t a );
|
API int audio_stop( audio_t a );
|
||||||
|
|
||||||
API float audio_volume_clip(float gain); // set fx volume if gain is in [0..1] range. return current fx volume in any case
|
API float audio_volume_clip(float gain); // set fx volume if gain is in [0..1] range. returns current fx volume in any case
|
||||||
API float audio_volume_stream(float gain); // set bgm volume if gain is in [0..1] range. return current bgm volume in any case
|
API float audio_volume_stream(float gain); // set bgm volume if gain is in [0..1] range. returns current bgm volume in any case
|
||||||
API float audio_volume_master(float gain); // set master volume if gain is in [0..1] range. return current master volume in any case
|
API float audio_volume_master(float gain); // set master volume if gain is in [0..1] range. returns current master volume in any case
|
||||||
|
|
||||||
|
API int audio_mute(int mute);
|
||||||
|
API int audio_muted();
|
||||||
|
|
||||||
API int ui_audio();
|
API int ui_audio();
|
||||||
|
|
||||||
|
@ -1750,6 +1753,11 @@ API void* dll(const char *filename, const char *symbol);
|
||||||
API vec3 editor_pick(float mouse_x, float mouse_y);
|
API vec3 editor_pick(float mouse_x, float mouse_y);
|
||||||
API char* editor_path(const char *path);
|
API char* editor_path(const char *path);
|
||||||
|
|
||||||
|
API float* editor_getf(const char *key);
|
||||||
|
API int* editor_geti(const char *key);
|
||||||
|
API char** editor_gets(const char *key);
|
||||||
|
API int editor_send(const char *cmd, const char *optional_value);
|
||||||
|
|
||||||
// open file dialog
|
// open file dialog
|
||||||
|
|
||||||
API char* dialog_load();
|
API char* dialog_load();
|
||||||
|
@ -2587,7 +2595,9 @@ extern API int profiler_enabled; ///-
|
||||||
// @todo: nested structs? pointers in members?
|
// @todo: nested structs? pointers in members?
|
||||||
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
||||||
|
|
||||||
|
#ifndef ifdef_objapi
|
||||||
#define ifdef_objapi(T,...) __VA_ARGS__
|
#define ifdef_objapi(T,...) __VA_ARGS__
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct reflected_t {
|
typedef struct reflected_t {
|
||||||
unsigned id, objtype;
|
unsigned id, objtype;
|
||||||
|
@ -3586,9 +3596,10 @@ char* strtok_s(char* str,const char* delimiters,char** context); // tcc misses t
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
#define each_substring(str, delims, keyname) \
|
#define each_substring(str, delims, keyname) \
|
||||||
( int len_ = strlen(str) + 1; len_; len_ = 0 ) \
|
( char *str_ = (char*)(str); str_; str_ = 0 ) \
|
||||||
for( char buf_[1024], *ptr_ = len_ < 1024 ? buf_ : REALLOC(0, len_), *lit_ = (char*)(str), *_bak = (snprintf(ptr_, len_, "%s", lit_), ptr_); _bak; _bak = 0, (ptr_ == buf_ ? 0 : REALLOC(ptr_, 0)) ) \
|
for( int len_ = strlen(str_) + 1, heap_ = len_ < 1024; len_ > 1; len_ = 0 ) \
|
||||||
for( char *next_token = 0, *keyname = strtok_r(_bak, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
for( char *ptr_ = (heap_ ? REALLOC(0, len_) : ALLOCA(len_)), *cpy_ = (snprintf(ptr_, len_, "%s", str_), ptr_); ptr_; (heap_ ? REALLOC(ptr_, 0) : 0), ptr_ = 0 ) \
|
||||||
|
for( char *next_token = 0, *keyname = strtok_r(cpy_, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
||||||
#else
|
#else
|
||||||
#define each_substring(str, delims, keyname) \
|
#define each_substring(str, delims, keyname) \
|
||||||
( char** tokens_ = strsplit((str), (delims)), *keyname = 0; tokens_; tokens_ = 0) \
|
( char** tokens_ = strsplit((str), (delims)), *keyname = 0; tokens_; tokens_ = 0) \
|
||||||
|
@ -3743,6 +3754,10 @@ API void app_crash();
|
||||||
API void app_singleton(const char *guid);
|
API void app_singleton(const char *guid);
|
||||||
API bool app_open(const char *folder_file_or_url);
|
API bool app_open(const char *folder_file_or_url);
|
||||||
|
|
||||||
|
API const char* app_loadfile();
|
||||||
|
API const char* app_savefile();
|
||||||
|
|
||||||
|
|
||||||
API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free().
|
API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free().
|
||||||
API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order.
|
API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order.
|
||||||
|
|
||||||
|
@ -3842,7 +3857,7 @@ API int ui_label2_float(const char *label, float value);
|
||||||
API int ui_label2_toolbar(const char *label, const char *icons);
|
API int ui_label2_toolbar(const char *label, const char *icons);
|
||||||
API int ui_slider(const char *label, float *value);
|
API int ui_slider(const char *label, float *value);
|
||||||
API int ui_slider2(const char *label, float *value, const char *caption);
|
API int ui_slider2(const char *label, float *value, const char *caption);
|
||||||
API int ui_contextual_end();
|
API int ui_contextual_end(int close);
|
||||||
API int ui_collapse_clicked();
|
API int ui_collapse_clicked();
|
||||||
API int ui_collapse_end();
|
API int ui_collapse_end();
|
||||||
API int ui_panel_end();
|
API int ui_panel_end();
|
||||||
|
|
|
@ -0,0 +1,138 @@
|
||||||
|
// ARK: lightweight, append-only, header-less journaling file format specification.
|
||||||
|
// - rlyeh, public domain.
|
||||||
|
|
||||||
|
// Features:
|
||||||
|
// - [x] Journaling support: data can be rolled back to an earlier state to retrieve older versions of files.
|
||||||
|
// - [x] Append-only format: create or update new entries just by appending stuff to the journal file.
|
||||||
|
// - [x] Compaction support: compact archives by keeping, for each duplicated file, its latest revision only.
|
||||||
|
// - [x] Concat friendly: journals can be glued together, and the result will still be a valid journey file.
|
||||||
|
// - [x] Foreign support: append random data to a foreign file and result will still be a valid journey file.
|
||||||
|
// - [x] Always aligned: file data is always 512-byte aligned for safe/fast memory access.
|
||||||
|
// - [x] Simple, tiny, portable, cross-platform, header-only.
|
||||||
|
// - [x] Public domain, CC0, 0-BSD, unlicensed (pick one).
|
||||||
|
|
||||||
|
// Extension:
|
||||||
|
// .ark
|
||||||
|
|
||||||
|
// File format:
|
||||||
|
// [foreign data]
|
||||||
|
// [...]
|
||||||
|
// [archive-entry #1]
|
||||||
|
// [archive-entry #2]
|
||||||
|
// [...]
|
||||||
|
// [archive-entry #N]
|
||||||
|
// [EOF]
|
||||||
|
//
|
||||||
|
// Where, each archive-entry is {
|
||||||
|
// [zero] 472-byte aligned zero padding
|
||||||
|
// [mark] 64-bit magic id 'Ark\x1' (if \1krA is found, swap endianness)
|
||||||
|
// [time] 64-bit time stamp in seconds (unix epoch)
|
||||||
|
// [dlen] 64-bit data length
|
||||||
|
// [hash] 64-bit data hash
|
||||||
|
// [nlen] 64-bit name length+1
|
||||||
|
// [data] file data (512-byte aligned)
|
||||||
|
// [name] file name+NUL
|
||||||
|
// }
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define ARK1 'ArK\x1'
|
||||||
|
#define ARK1_PADDING (512 - 40) // 472
|
||||||
|
|
||||||
|
#ifndef ARK_PRINTF
|
||||||
|
#define ARK_PRINTF printf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARK_SWAP32
|
||||||
|
#define ARK_SWAP32(x) x
|
||||||
|
#define ARK_SWAP64(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARK_REALLOC
|
||||||
|
#define ARK_REALLOC realloc
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int ark_fput64( FILE *out, uint64_t v ) { return fwrite( (v = ARK_SWAP64(v), &v), 1, 8, out); }
|
||||||
|
static uint64_t ark_fget64( FILE *in ) { uint64_t v; fread( &v, 1, 8, in ); return ARK_SWAP64(v); }
|
||||||
|
static const char ark1_zero[ARK1_PADDING] = {0};
|
||||||
|
|
||||||
|
// `outfile` must be fopen("file.ark", "a+b") beforehand
|
||||||
|
int ark_append_mem( FILE *out, const char *name, const void *data, int datalen, uint64_t stamp ) {
|
||||||
|
fseek( out, 0L, SEEK_END );
|
||||||
|
while( 0 != (ftell(out) % ARK1_PADDING) ) fwrite(ark1_zero, 1, ARK1_PADDING - (ftell(out) % ARK1_PADDING), out);
|
||||||
|
ARK_PRINTF("Writing %s at #%d\n", name, (int)ftell(out));
|
||||||
|
int namelen = strlen(name) + 1;
|
||||||
|
uint64_t mark = ARK1;
|
||||||
|
ark_fput64(out, mark);
|
||||||
|
ark_fput64(out, stamp);
|
||||||
|
ark_fput64(out, datalen);
|
||||||
|
ark_fput64(out, 0ULL/*hash*/);
|
||||||
|
ark_fput64(out, namelen);
|
||||||
|
fwrite(data, 1, datalen, out);
|
||||||
|
fwrite(name, 1, namelen, out);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `outfile` must be fopen("file.ark", "a+b") beforehand
|
||||||
|
int ark_append_file( FILE *out, const char *name ) {
|
||||||
|
FILE *in = fopen(name, "rb");
|
||||||
|
if( in ) {
|
||||||
|
fseek(in, 0L, SEEK_END);
|
||||||
|
size_t sz = ftell(in);
|
||||||
|
fseek(in, 0L, SEEK_SET);
|
||||||
|
char *buffer = ARK_REALLOC(0, sz);
|
||||||
|
if( !buffer ) return fclose(in), 0;
|
||||||
|
fread(buffer, 1, sz, in);
|
||||||
|
fclose(in);
|
||||||
|
int rc = ark_append_mem(out, name, buffer, sz, 0ULL);
|
||||||
|
ARK_REALLOC(buffer, 0);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ark_list( FILE *in, void *yield_fn ) {
|
||||||
|
int (*ark_yield_fn)() = yield_fn;
|
||||||
|
while( !feof(in) ) {
|
||||||
|
while( 0 != (ftell(in) % ARK1_PADDING) && !feof(in) ) fseek(in, ARK1_PADDING - (ftell(in) % ARK1_PADDING), SEEK_CUR);
|
||||||
|
ARK_PRINTF("Reading at #%d\n", (int)ftell(in));
|
||||||
|
uint64_t mark = ark_fget64(in);
|
||||||
|
if( mark != ARK1 ) continue;
|
||||||
|
uint64_t stamp = ark_fget64(in);
|
||||||
|
uint64_t datalen = ark_fget64(in);
|
||||||
|
uint64_t datahash = ark_fget64(in);
|
||||||
|
uint64_t namelen = ark_fget64(in);
|
||||||
|
char *data = ARK_REALLOC(0, datalen);
|
||||||
|
fread(data, 1, datalen, in);
|
||||||
|
char *name = ARK_REALLOC(0, namelen);
|
||||||
|
fread(name, 1, namelen, in);
|
||||||
|
|
||||||
|
if( yield_fn == printf ) {
|
||||||
|
printf("Found %s (%d bytes)\n", name, (int)datalen );
|
||||||
|
ARK_REALLOC(name, 0);
|
||||||
|
ARK_REALLOC(data, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if( !ark_yield_fn(name, data, datalen, datahash, stamp) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
if( argc > 2 ) {
|
||||||
|
FILE *ark = fopen(argv[1], "a+b");
|
||||||
|
if( ark ) for( int i = 2; i < argc; ++i) ark_append_file( ark, argv[i] );
|
||||||
|
if( ark ) fclose(ark);
|
||||||
|
}
|
||||||
|
else if( argc == 2 ) {
|
||||||
|
FILE *ark = fopen(argv[1], "rb");
|
||||||
|
if( ark ) ark_list(ark, printf), fclose(ark);
|
||||||
|
}
|
||||||
|
else printf("%s infile.ark\n%s outfile.ark infile1 [infile2...]\n", argv[0], argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// cl ark.c /MT /O2 /DNDEBUG /link setargv.obj
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,20 @@
|
||||||
|
Pictogrammers Free License
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
This icon collection is released as free, open source, and GPL friendly by
|
||||||
|
the [Pictogrammers](http://pictogrammers.com/) icon group. You may use it
|
||||||
|
for commercial projects, open source projects, or anything really.
|
||||||
|
|
||||||
|
# Icons: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
Some of the icons are redistributed under the Apache 2.0 license. All other
|
||||||
|
icons are either redistributed under their respective licenses or are
|
||||||
|
distributed under the Apache 2.0 license.
|
||||||
|
|
||||||
|
# Fonts: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
All web and desktop fonts are distributed under the Apache 2.0 license. Web
|
||||||
|
and desktop fonts contain some icons that are redistributed under the Apache
|
||||||
|
2.0 license. All other icons are either redistributed under their respective
|
||||||
|
licenses or are distributed under the Apache 2.0 license.
|
||||||
|
|
||||||
|
# Code: MIT (https://opensource.org/licenses/MIT)
|
||||||
|
The MIT license applies to all non-font and non-icon files.
|
Binary file not shown.
|
@ -61,7 +61,7 @@
|
||||||
// ### editor (v4)
|
// ### editor (v4)
|
||||||
// Bring in remote datas into the editor.
|
// Bring in remote datas into the editor.
|
||||||
// Go social & marketplace. Allow others to expand, share, publish, subscribe, discuss their sub-editors within a small community.
|
// Go social & marketplace. Allow others to expand, share, publish, subscribe, discuss their sub-editors within a small community.
|
||||||
// I really like the way the way OpenFrameworks.cc does their addons, and I think we should do same: just discover and monitor github repos, and list everything on a website (v4k- prefix?).
|
// I really like the way the way OpenFrameworks.cc does their addons, and I think we should do same: just discover and monitor github repos, and list everything on a website (fwk- prefix?).
|
||||||
// Wishlist for a github-based community flow: discovery, transparent installs, publish on github, star there, watch commits & releases, track issues+discussions, etc
|
// Wishlist for a github-based community flow: discovery, transparent installs, publish on github, star there, watch commits & releases, track issues+discussions, etc
|
||||||
//
|
//
|
||||||
// We should have a generic, extensible, script/plugin-driven, working editor at this point (hopefully) that does not require maintenance.
|
// We should have a generic, extensible, script/plugin-driven, working editor at this point (hopefully) that does not require maintenance.
|
||||||
|
@ -153,7 +153,7 @@
|
||||||
// - ecs: sys are modules, ecs: char *messaging, ecs: filesystem (e/dir,c/files,s/dll)
|
// - ecs: sys are modules, ecs: char *messaging, ecs: filesystem (e/dir,c/files,s/dll)
|
||||||
// - world: streaming, migration
|
// - world: streaming, migration
|
||||||
|
|
||||||
#include "v4k.h"
|
#include "fwk.h"
|
||||||
|
|
||||||
// #include "labs.vm/ecs.c"
|
// #include "labs.vm/ecs.c"
|
||||||
|
|
||||||
|
@ -839,10 +839,10 @@ void editor_obj_render_max_properties(void *obj, const char *mask) { // headless
|
||||||
// main editor interface
|
// main editor interface
|
||||||
|
|
||||||
void editor_render_menubar() {
|
void editor_render_menubar() {
|
||||||
int alts = input(KEY_LALT) || input(KEY_RALT); // @todo: move to v4k.c
|
int alts = input(KEY_LALT) || input(KEY_RALT); // @todo: move to fwk.c
|
||||||
int ctrls = input(KEY_LCTRL) || input(KEY_RCTRL); // @todo: move to v4k.c
|
int ctrls = input(KEY_LCTRL) || input(KEY_RCTRL); // @todo: move to fwk.c
|
||||||
int shifts = input(KEY_LSHIFT) || input(KEY_RSHIFT); // @todo: move to v4k.c
|
int shifts = input(KEY_LSHIFT) || input(KEY_RSHIFT); // @todo: move to fwk.c
|
||||||
int mods = alts || ctrls || shifts; // @todo: move to v4k.c
|
int mods = alts || ctrls || shifts; // @todo: move to fwk.c
|
||||||
if( input_down(KEY_F5) ) editor_key = key_reload;
|
if( input_down(KEY_F5) ) editor_key = key_reload;
|
||||||
if( input_down(KEY_F11) ) editor_key = key_fullscreen;
|
if( input_down(KEY_F11) ) editor_key = key_fullscreen;
|
||||||
if( input_down(KEY_PAUSE) ) editor_key = key_pause;
|
if( input_down(KEY_PAUSE) ) editor_key = key_pause;
|
||||||
|
@ -1046,7 +1046,7 @@ void editor_obj_render_properties_recursively(void *obj, const char *mask) {
|
||||||
if( ui_button_transparent("<Cut" ) ) do_context_obj = obj, do_context_cmd = cc3(c,u,t);
|
if( ui_button_transparent("<Cut" ) ) do_context_obj = obj, do_context_cmd = cc3(c,u,t);
|
||||||
if( ui_button_transparent("<Copy" ) ) do_context_obj = obj, do_context_cmd = cc4(c,o,p,y);
|
if( ui_button_transparent("<Copy" ) ) do_context_obj = obj, do_context_cmd = cc4(c,o,p,y);
|
||||||
if( ui_button_transparent("<Paste") ) do_context_obj = obj, do_context_cmd = cc5(p,a,s,t,e);
|
if( ui_button_transparent("<Paste") ) do_context_obj = obj, do_context_cmd = cc5(p,a,s,t,e);
|
||||||
ui_contextual_end();
|
ui_contextual_end(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for( int i = 0; i < num_subobjects; ++i ) {
|
for( int i = 0; i < num_subobjects; ++i ) {
|
||||||
|
@ -1067,7 +1067,7 @@ void editor_obj_render_properties_recursively(void *obj, const char *mask) {
|
||||||
if( ui_button_transparent("<Cut" ) ) do_context_obj = obj, do_context_cmd = cc3(c,u,t);
|
if( ui_button_transparent("<Cut" ) ) do_context_obj = obj, do_context_cmd = cc3(c,u,t);
|
||||||
if( ui_button_transparent("<Copy" ) ) do_context_obj = obj, do_context_cmd = cc4(c,o,p,y);
|
if( ui_button_transparent("<Copy" ) ) do_context_obj = obj, do_context_cmd = cc4(c,o,p,y);
|
||||||
if( ui_button_transparent("<Paste") ) do_context_obj = obj, do_context_cmd = cc5(p,a,s,t,e);
|
if( ui_button_transparent("<Paste") ) do_context_obj = obj, do_context_cmd = cc5(p,a,s,t,e);
|
||||||
ui_contextual_end();
|
ui_contextual_end(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( clicked_or_toggled & 1 ) {
|
if( clicked_or_toggled & 1 ) {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
- [ ] Editor: GUI pass: timeline and data tracks, node graphs. <!-- worthy: will be reused into materials, animgraphs and blueprints -->
|
- [ ] Editor: GUI pass: timeline and data tracks, node graphs. <!-- worthy: will be reused into materials, animgraphs and blueprints -->
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "v4k.c"
|
#include "fwk.c"
|
||||||
#include "editor2.h" // old editor interface
|
#include "editor2.h" // old editor interface
|
||||||
|
|
||||||
#define ui_push_hspace(px) \
|
#define ui_push_hspace(px) \
|
||||||
|
@ -28,8 +28,6 @@
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "labs.meta/meta_reflect.c"
|
|
||||||
|
|
||||||
int *meta_changed(void *value) {
|
int *meta_changed(void *value) {
|
||||||
static map(void*,int) changes = 0;
|
static map(void*,int) changes = 0;
|
||||||
do_once map_init_ptr(changes);
|
do_once map_init_ptr(changes);
|
||||||
|
@ -37,20 +35,20 @@ int *meta_changed(void *value) {
|
||||||
return map_find_or_add(changes, value, 0);
|
return map_find_or_add(changes, value, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reflect_ui( const reflect *r, void *value, void *userdata ) {
|
void reflect_ui( const char *type, const char *name, const char *info, void *value ) {
|
||||||
ui_label_icon_highlight = *meta_changed(value); // @hack: remove ui_label_icon_highlight hack
|
ui_label_icon_highlight = *meta_changed(value); // @hack: remove ui_label_icon_highlight hack
|
||||||
char *title = va(ICON_MD_UNDO "%s", r->info);
|
char *title = va(ICON_MD_UNDO "%s", info);
|
||||||
|
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
/**/ if( !strcmp(r->type, "int") ) changed = ui_int(title, (int*)value);
|
/**/ if( !strcmp(type, "int") ) changed = ui_int(title, (int*)value);
|
||||||
else if( !strcmp(r->type, "char") && r->is_ptr ) changed = ui_buffer(title, (char*)value, strlen((char*)value)+1);
|
else if( !strcmp(type, "char*") ) changed = ui_buffer(title, (char*)value, strlen((char*)value)+1);
|
||||||
else if( !strcmp(r->type, "string") ) changed = ui_string(title, (char**)value);
|
else if( !strcmp(type, "string") ) changed = ui_string(title, (char**)value);
|
||||||
else if( !strcmp(r->type, "float") ) changed = ui_float(title, (float*)value);
|
else if( !strcmp(type, "float") ) changed = ui_float(title, (float*)value);
|
||||||
else if( !strcmp(r->type, "double") ) changed = ui_double(title, (double*)value);
|
else if( !strcmp(type, "double") ) changed = ui_double(title, (double*)value);
|
||||||
else if( !strcmp(r->type, "unsigned") ) changed = ui_unsigned(title, (unsigned*)value);
|
else if( !strcmp(type, "unsigned") ) changed = ui_unsigned(title, (unsigned*)value);
|
||||||
else if( !strcmp(r->type, "color") ) changed = ui_color4(va("%s #%02X%02X%02X%02X", title, (int)(0[(float*)value]),(int)(1[(float*)value]),(int)(2[(float*)value]),(int)(3[(float*)value])), (float*)value);
|
else if( !strcmp(type, "color") ) changed = ui_color4(va("%s #%02X%02X%02X%02X", title, (int)(0[(float*)value]),(int)(1[(float*)value]),(int)(2[(float*)value]),(int)(3[(float*)value])), (float*)value);
|
||||||
// else if( !strcmp(type, "vec3") ) ; // not supported. decays to 3 floats
|
// else if( !strcmp(type, "vec3") ) ; // not supported. decays to 3 floats
|
||||||
else ui_label2(title, va("(%s)%s", r->type, r->name));
|
else ui_label2(title, va("(%s)%s", type, name));
|
||||||
|
|
||||||
if( changed ) {
|
if( changed ) {
|
||||||
*meta_changed(value) = 1;
|
*meta_changed(value) = 1;
|
||||||
|
@ -62,7 +60,7 @@ void reflect_ui( const reflect *r, void *value, void *userdata ) {
|
||||||
}
|
}
|
||||||
bool reflect_parse(void *obj, const char *type, const char *val) {
|
bool reflect_parse(void *obj, const char *type, const char *val) {
|
||||||
/**/ if( !strcmp(type, "int") ) *((int*)obj) = eval(val);
|
/**/ if( !strcmp(type, "int") ) *((int*)obj) = eval(val);
|
||||||
// else if( !strcmp(r->type, "char") && r->is_ptr ) ; // @fixme: not supported, unless we do strncpy() or similar.
|
// else if( !strcmp(type, "char*") ) ; // @fixme: not supported, unless we do strncpy() or similar.
|
||||||
else if( !strcmp(type, "string") ) *((char**)obj) = stringf("%s", val);
|
else if( !strcmp(type, "string") ) *((char**)obj) = stringf("%s", val);
|
||||||
else if( !strcmp(type, "float") ) *((float*)obj) = eval(val); // = v[0] == '~' ? (float)~atoi(val+1) : atof(val); // = atof(val);
|
else if( !strcmp(type, "float") ) *((float*)obj) = eval(val); // = v[0] == '~' ? (float)~atoi(val+1) : atof(val); // = atof(val);
|
||||||
else if( !strcmp(type, "double") ) *((double*)obj) = eval(val); // = v[0] == '~' ? (float)~atoi(val+1) : atof(val); // = atof(val);
|
else if( !strcmp(type, "double") ) *((double*)obj) = eval(val); // = v[0] == '~' ? (float)~atoi(val+1) : atof(val); // = atof(val);
|
||||||
|
@ -73,42 +71,6 @@ bool reflect_parse(void *obj, const char *type, const char *val) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
typedef void(*obj_ctor)(void*);
|
|
||||||
static map(char*, obj_ctor) obj_ctors;
|
|
||||||
|
|
||||||
#define STRUCT_CTOR(type, ctor) STRUCT_CTOR(#type, (obj_ctor)ctor)
|
|
||||||
void (STRUCT_CTOR)( const char *type, obj_ctor ctor ) {
|
|
||||||
do_once map_init_str(obj_ctors);
|
|
||||||
map_find_or_add(obj_ctors, STRDUP(type), ctor);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool obj_make(void *obj, const char *ini_data) { // initialize object from ini datas
|
|
||||||
char *hint = 0;
|
|
||||||
|
|
||||||
for( ini_t read = ini_from_mem(ini_data); !!read; map_free(read), read = 0) {
|
|
||||||
for each_map(read, char*, k, char*, v) {
|
|
||||||
array(char*) tokens = strsplit(k, ".");
|
|
||||||
if( array_count(tokens) != 2 ) continue;
|
|
||||||
|
|
||||||
const char *type = 0;
|
|
||||||
void *found = reflect_field( tokens[0], obj, tokens[1], &type );
|
|
||||||
if( !found ) continue;
|
|
||||||
|
|
||||||
if( reflect_parse(found, type, v) ) {
|
|
||||||
hint = tokens[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// constructor (post-init call)
|
|
||||||
obj_ctor *ctor = map_find(obj_ctors, hint);
|
|
||||||
if( ctor ) (*ctor)( obj );
|
|
||||||
}
|
|
||||||
|
|
||||||
return hint != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define POD_TYPES \
|
#define POD_TYPES \
|
||||||
|
@ -223,9 +185,9 @@ void node_edit(node *n, node *root) {
|
||||||
if( ui_collapse(va("%s %s (%u)", n->down ? ICON_MD_SOURCE : ICON_MD_FOLDER, node_name(n), node_children(n)), va("%p%p",root,n->v.ptr)) ) { // @fixme v.ptr
|
if( ui_collapse(va("%s %s (%u)", n->down ? ICON_MD_SOURCE : ICON_MD_FOLDER, node_name(n), node_children(n)), va("%p%p",root,n->v.ptr)) ) { // @fixme v.ptr
|
||||||
if( n->down ) node_edit(n->down,root);
|
if( n->down ) node_edit(n->down,root);
|
||||||
|
|
||||||
if( reflect_has_fields( node_type(n), n->v.ptr ) ) {
|
if( 1 ) { // reflect_has_fields( node_type(n), n->v.ptr ) ) {
|
||||||
for ui_push_hspace( 4 ) {
|
for ui_push_hspace( 4 ) {
|
||||||
#define ICON_DOT ICON_CANCEL // ICON_MD_WIFI_1_BAR // ICON_MD_RADIO_BUTTON_UNCHECKED // ICON_MD_LENS_BLUR
|
#define ICON_DOT " · " // ICON_CANCEL // ICON_MD_WIFI_1_BAR // ICON_MD_RADIO_BUTTON_UNCHECKED // ICON_MD_LENS_BLUR
|
||||||
static int flags[4] = {0};
|
static int flags[4] = {0};
|
||||||
char *toolbar = va("%s%s%s%s",
|
char *toolbar = va("%s%s%s%s",
|
||||||
flags[3] ? ICON_MD_STAR : ICON_MD_STAR_OUTLINE, // ICON_MD_BOOKMARK : ICON_MD_BOOKMARK_BORDER, // flags[3] == 0 ? ICON_MD_STAR_OUTLINE : flags[3] == 1 ? ICON_MD_STAR_HALF : ICON_MD_STAR,
|
flags[3] ? ICON_MD_STAR : ICON_MD_STAR_OUTLINE, // ICON_MD_BOOKMARK : ICON_MD_BOOKMARK_BORDER, // flags[3] == 0 ? ICON_MD_STAR_OUTLINE : flags[3] == 1 ? ICON_MD_STAR_HALF : ICON_MD_STAR,
|
||||||
|
@ -239,7 +201,10 @@ void node_edit(node *n, node *root) {
|
||||||
|
|
||||||
int choice = ui_label2_toolbar(section, toolbar);
|
int choice = ui_label2_toolbar(section, toolbar);
|
||||||
if( choice ) flags[ choice - 1 ] = (flags[ choice - 1 ] + 1 ) % ( choice == 4 ? 2/*3*/ : 2);
|
if( choice ) flags[ choice - 1 ] = (flags[ choice - 1 ] + 1 ) % ( choice == 4 ? 2/*3*/ : 2);
|
||||||
reflect_iterate_fields( node_type(n), n->v.ptr, reflect_ui, NULL ); // @fixme v.ptr
|
|
||||||
|
for each_member( node_type(n), R ) {
|
||||||
|
reflect_ui(R->type, R->name, R->info, n->v.ptr); // @fixme v.ptr
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +234,7 @@ void editor_reset() {
|
||||||
}
|
}
|
||||||
void editor_frame() {
|
void editor_frame() {
|
||||||
editor_init(); // old editor interface
|
editor_init(); // old editor interface
|
||||||
editor_tick(); // old editor interface
|
editor_tick_(); // old editor interface
|
||||||
editor_menubar(); // old editor interface
|
editor_menubar(); // old editor interface
|
||||||
|
|
||||||
if( input_down(KEY_F5) ) {
|
if( input_down(KEY_F5) ) {
|
||||||
|
@ -422,42 +387,42 @@ int main() {
|
||||||
STRUCT( my_sprite, vec3, position, "Position" );
|
STRUCT( my_sprite, vec3, position, "Position" );
|
||||||
STRUCT( my_sprite, float, tilt, "Tilt degrees" );
|
STRUCT( my_sprite, float, tilt, "Tilt degrees" );
|
||||||
STRUCT( my_sprite, color, tint, "Tint color" );
|
STRUCT( my_sprite, color, tint, "Tint color" );
|
||||||
STRUCT_CTOR( my_sprite, my_sprite_ctor );
|
|
||||||
|
|
||||||
PRINTF("pod:%d, var:%d, node:%d warn\n", (int)sizeof(pod), (int)sizeof(var), (int)sizeof(node));
|
PRINTF("pod:%d, var:%d, node:%d warn\n", (int)sizeof(pod), (int)sizeof(var), (int)sizeof(node));
|
||||||
PRINTF("reflected:%d bytes vs real:%d bytes warn\n", reflect_sizeof("my_sprite"), (int)sizeof(my_sprite));
|
// PRINTF("reflected:%d bytes vs real:%d bytes warn\n", reflect_sizeof("my_sprite"), (int)sizeof(my_sprite));
|
||||||
|
|
||||||
// cook_config("../../tools/cook.ini");
|
// cook_config("../../tools/cook.ini");
|
||||||
window_create(0.80, 0);
|
window_create(0.80, 0);
|
||||||
|
|
||||||
struct my_sprite spr1 = {0}, spr2 = {0}, spr3 = {0};
|
struct my_sprite
|
||||||
obj_make(&spr1,
|
spr1 = {
|
||||||
"[my_sprite]\n"
|
.filename="cat.png",
|
||||||
"filename=cat.png\n"
|
.position = vec3(5, 2, 100),
|
||||||
"position=5 2 100\n"
|
.tilt=45 + 45 -90,
|
||||||
"tilt=45 + 45 -90\n"
|
.tint=vec4(255, 255, 0, 255)
|
||||||
"tint=255 255 0\n"
|
},
|
||||||
);
|
spr2 = {
|
||||||
obj_make(&spr2,
|
.filename="cat.png",
|
||||||
"[my_sprite]\n"
|
.position = vec3(1, 2, 100),
|
||||||
"filename=cat.png\n"
|
.tilt=45 + 45 -90,
|
||||||
"position=1 2 100\n"
|
.tint=vec4(255, 0, 0, 255)
|
||||||
"tilt=45 + 45 -90\n"
|
},
|
||||||
"tint=255 0 0\n"
|
spr3 = {
|
||||||
);
|
.filename="cat.png",
|
||||||
obj_make(&spr3,
|
.position = vec3(1, 2, 100),
|
||||||
"[my_sprite]\n"
|
.tilt=45,
|
||||||
"filename=cat.png\n"
|
.tint=vec4(0, 0, 255, 255)
|
||||||
"position=1 2 100\n"
|
};
|
||||||
"tilt=45\n"
|
|
||||||
"tint=0 0 255\n"
|
my_sprite_ctor(&spr1);
|
||||||
);
|
my_sprite_ctor(&spr2);
|
||||||
|
my_sprite_ctor(&spr3);
|
||||||
|
|
||||||
int hero1 = editor_spawn("/hero1", "my_sprite", &spr1);
|
int hero1 = editor_spawn("/hero1", "my_sprite", &spr1);
|
||||||
int hero2 = editor_spawn("/hero2", "my_sprite", &spr2);
|
int hero2 = editor_spawn("/hero2", "my_sprite", &spr2);
|
||||||
int hero3 = editor_spawn("/hero1/heroB", "my_sprite", &spr3);
|
int hero3 = editor_spawn("/hero1/heroB", "my_sprite", &spr3);
|
||||||
|
|
||||||
camera_t cam = camera();
|
camera_t cam = camera();
|
||||||
camera_enable(&cam);
|
|
||||||
|
|
||||||
while( window_swap() ) {
|
while( window_swap() ) {
|
||||||
editor_frame();
|
editor_frame();
|
||||||
|
|
|
@ -102,12 +102,12 @@ void editor_init() {
|
||||||
map_init_ptr(editor_dicts);
|
map_init_ptr(editor_dicts);
|
||||||
set_init_ptr(editor_world);
|
set_init_ptr(editor_world);
|
||||||
set_init_ptr(editor_selection);
|
set_init_ptr(editor_selection);
|
||||||
profile_enable( false );
|
profiler_enable( false );
|
||||||
window_pause( true );
|
window_pause( true );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void editor_tick() {
|
void editor_tick_() {
|
||||||
// timing
|
// timing
|
||||||
editor_dt = window_delta() * !window_has_pause(); if(editor_dt > 1/60.f) editor_dt = 1/60.f;
|
editor_dt = window_delta() * !window_has_pause(); if(editor_dt > 1/60.f) editor_dt = 1/60.f;
|
||||||
}
|
}
|
||||||
|
@ -155,10 +155,10 @@ enum editor_keys {
|
||||||
void editor_menubar() {
|
void editor_menubar() {
|
||||||
do_once editor_init();
|
do_once editor_init();
|
||||||
|
|
||||||
int alts = input(KEY_LALT) || input(KEY_RALT); // @todo: move to v4k.c
|
int alts = input(KEY_LALT) || input(KEY_RALT); // @todo: move to fwk.c
|
||||||
int ctrls = input(KEY_LCTRL) || input(KEY_RCTRL); // @todo: move to v4k.c
|
int ctrls = input(KEY_LCTRL) || input(KEY_RCTRL); // @todo: move to fwk.c
|
||||||
int shifts = input(KEY_LSHIFT) || input(KEY_RSHIFT); // @todo: move to v4k.c
|
int shifts = input(KEY_LSHIFT) || input(KEY_RSHIFT); // @todo: move to fwk.c
|
||||||
int mods = alts || ctrls || shifts; // @todo: move to v4k.c
|
int mods = alts || ctrls || shifts; // @todo: move to fwk.c
|
||||||
if( input_down(KEY_F5) ) editor_key = key_reload;
|
if( input_down(KEY_F5) ) editor_key = key_reload;
|
||||||
if( input_down(KEY_F11) ) editor_key = key_fullscreen;
|
if( input_down(KEY_F11) ) editor_key = key_fullscreen;
|
||||||
if( input_down(KEY_PAUSE) ) editor_key = key_pause;
|
if( input_down(KEY_PAUSE) ) editor_key = key_pause;
|
||||||
|
@ -332,7 +332,7 @@ void editor_menubar() {
|
||||||
break; case key_outliner: ui_show("Outliner", ui_visible("Outliner") ^ true);
|
break; case key_outliner: ui_show("Outliner", ui_visible("Outliner") ^ true);
|
||||||
break; case key_recording: name = file_counter(va("%s.mp4",app_name())), window_record(name), ui_notify(va("Video capturing: %s", name), date_string());
|
break; case key_recording: name = file_counter(va("%s.mp4",app_name())), window_record(name), ui_notify(va("Video capturing: %s", name), date_string());
|
||||||
break; case key_screenshot: name = file_counter(va("%s.png",app_name())), window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string());
|
break; case key_screenshot: name = file_counter(va("%s.png",app_name())), window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string());
|
||||||
break; case key_profiler: ui_show("Profiler", profile_enable(ui_visible("Profiler") ^ true));
|
break; case key_profiler: ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true));
|
||||||
break; case key_fullscreen: record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); // framebuffer resizing corrupts video stream, so stop any recording beforehand
|
break; case key_fullscreen: record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); // framebuffer resizing corrupts video stream, so stop any recording beforehand
|
||||||
break; case key_gamepad: editor_gamepad ^= 1;
|
break; case key_gamepad: editor_gamepad ^= 1;
|
||||||
break; case key_lit: editor_lit ^= 1;
|
break; case key_lit: editor_lit ^= 1;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//#define META_DEMO
|
//#define META_DEMO
|
||||||
|
|
||||||
#include "v4k.h"
|
#include "fwk.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#define V4K_C
|
#define FWK_C
|
||||||
#include "v4k.h"
|
#include "fwk.h"
|
||||||
|
|
||||||
bool parse_struct(const char *line) {
|
bool parse_struct(const char *line) {
|
||||||
return strstr(line, "s""truct ");
|
return strstr(line, "s""truct ");
|
||||||
|
|
|
@ -21,9 +21,9 @@ cl ..\editor2.c -I ..\..\tools -DCOOK_ON_DEMAND
|
||||||
pushd ..\.. && call make amalgamation && popd
|
pushd ..\.. && call make amalgamation && popd
|
||||||
|
|
||||||
taskkill /im "oscedit.exe" > nul 2> nul
|
taskkill /im "oscedit.exe" > nul 2> nul
|
||||||
call ..\..\tools\tcc oscgame.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
call ..\..\tools\tcc oscgame.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||||
call ..\..\tools\tcc oscsend.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
call ..\..\tools\tcc oscsend.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||||
call ..\..\tools\tcc oscedit.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %* && start oscedit.exe
|
call ..\..\tools\tcc oscedit.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %* && start oscedit.exe
|
||||||
|
|
||||||
timeout 3
|
timeout 3
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "v4k.h"
|
#include "fwk.h"
|
||||||
#include "oscedit.h"
|
#include "oscedit.h"
|
||||||
|
|
||||||
// demo
|
// demo
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "v4k.h"
|
#include "fwk.h"
|
||||||
#include "oscedit.h"
|
#include "oscedit.h"
|
||||||
|
|
||||||
// game
|
// game
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "v4k.h"
|
#include "fwk.h"
|
||||||
|
|
||||||
#define OSCPACK_C
|
#define OSCPACK_C
|
||||||
#define OSCRECV_C
|
#define OSCRECV_C
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// networked gui demo
|
// networked gui demo
|
||||||
// - rlyeh, public domain
|
// - rlyeh, public domain
|
||||||
|
|
||||||
#include "v4k.h"
|
#include "fwk.h"
|
||||||
|
|
||||||
#define OSCPACK_C
|
#define OSCPACK_C
|
||||||
#define OSCRECV_C
|
#define OSCRECV_C
|
||||||
|
@ -46,7 +46,6 @@ int main() {
|
||||||
|
|
||||||
// camera
|
// camera
|
||||||
camera_t cam = camera();
|
camera_t cam = camera();
|
||||||
cam.speed = 0.2f;
|
|
||||||
|
|
||||||
// demo loop
|
// demo loop
|
||||||
while (window_swap())
|
while (window_swap())
|
||||||
|
@ -61,7 +60,7 @@ int main() {
|
||||||
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||||
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||||
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
|
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||||
camera_move(&cam, wasdecq.x,wasdecq.y,wasdecq.z);
|
camera_moveby(&cam, wasdecq);
|
||||||
camera_fps(&cam, mouse.x,mouse.y);
|
camera_fps(&cam, mouse.x,mouse.y);
|
||||||
|
|
||||||
// queue model scale bounces
|
// queue model scale bounces
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#include "v4k.h"
|
#include "fwk.h"
|
||||||
#include "oscsend.h"
|
#include "oscsend.h"
|
||||||
#include "oscedit.h"
|
#include "oscedit.h"
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
given a string A, we want it to be B.
|
||||||
|
|
||||||
|
A: hello world and thanks for the fish.
|
||||||
|
B: hello cruel o_o world and thanks for the fish!
|
||||||
|
|
||||||
|
however, the instructions to reconstruct B must be as small as possible, to minimize transmission costs. this is why we dont send B entirely.
|
||||||
|
|
||||||
|
different algorithms as follow:
|
||||||
|
|
||||||
|
## ALGORITHM 1
|
||||||
|
|
||||||
|
- identify the first mismatching character (S).
|
||||||
|
|
||||||
|
v-- 6(S)
|
||||||
|
A: hello world and thanks for the fish.
|
||||||
|
B: hello cruel o_o world and thanks for the fish!
|
||||||
|
|
||||||
|
- identify the last mismatch character (E).
|
||||||
|
|
||||||
|
v-- 0(E)
|
||||||
|
A: hello world and thanks for the fish.
|
||||||
|
B: hello cruel o_o world and thanks for the fish!
|
||||||
|
|
||||||
|
- we construct the patch now with 3 numbers:
|
||||||
|
- number of bytes to copy from beginning(A) till S(A)
|
||||||
|
- number of bytes to copy from S(B) till E(B). plus the substring that is get copied.
|
||||||
|
- number of bytes to copy from E(A) till end of string.
|
||||||
|
|
||||||
|
6 40 "cruel o_o world and thanks for the fish!" 0
|
||||||
|
|
||||||
|
- total patch size is 3 control bytes + 40 (string) = 43 bytes
|
||||||
|
|
||||||
|
## ALGORITHM 2
|
||||||
|
|
||||||
|
- We delta every character in both strings, from beginning to end, and from end to beginning.
|
||||||
|
|
||||||
|
A: hello world and thanks for the fish.0000000000
|
||||||
|
B: hello cruel o_o world and thanks for the fish!
|
||||||
|
C: 000000XXXXX0XXX0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX (-)
|
||||||
|
|
||||||
|
A: 0000000000hello world and thanks for the fish.
|
||||||
|
B: hello cruel o_o world and thanks for the fish!
|
||||||
|
C: XXXXXXXXXXXXXX0000000000000000000000000000000X (-)
|
||||||
|
|
||||||
|
- Pick the option with most zeros (2nd). Aka, select the option with less Xs.
|
||||||
|
|
||||||
|
do { Encode every XXXX island in C as a positive operation indicating how many bytes to copy from.
|
||||||
|
Run-length the number of zeros into a negative operation.
|
||||||
|
} repeat till lane is exhausted.
|
||||||
|
|
||||||
|
XXXXXXXXXXXXXXX: +14 "hello cruel o_"
|
||||||
|
0000000000000000000000000000000: -29
|
||||||
|
X: +1 "!"
|
||||||
|
|
||||||
|
- Patch size is 3 control bytes + 14 (string) + 1 (string) = 18 bytes
|
||||||
|
|
||||||
|
## ALGORITHM 3
|
||||||
|
|
||||||
|
- start source (A) and target (B) strings. start with A:
|
||||||
|
- select how many bytes to copy (positive), how many to skip (negative), or switch A<-->B lanes (zero).
|
||||||
|
- repeat previous step over and over until both lanes do reach their respective string ends.
|
||||||
|
|
||||||
|
A: hello world and thanks for the fish.
|
||||||
|
B: hello cruel o_o world and thanks for the fish!
|
||||||
|
|
||||||
|
A: +6 0 >> hello
|
||||||
|
B: -6 +10 0 >> hello cruel o_o
|
||||||
|
A: +24 -1 0 >> hello cruel o_o world and thanks for the fish
|
||||||
|
B: -29 +1 >> hello cruel o_o world and thanks for the fish!
|
||||||
|
(10 bytes)
|
||||||
|
|
||||||
|
what if we always specify a dual +/- operation per lane?
|
||||||
|
lanes changed automatically after every tuple. in this case a 0 shall indicate a no op.
|
||||||
|
|
||||||
|
A: +6 0 >> hello
|
||||||
|
B: -6 +10 >> hello cruel o_o
|
||||||
|
A: +24 -1 >> hello cruel o_o world and thanks for the fish
|
||||||
|
B: -29 +1 >> hello cruel o_o world and thanks for the fish!
|
||||||
|
(8 bytes)
|
||||||
|
|
||||||
|
- we construct the patch now. a substring excerpt must come after any positive operations on lane B.
|
||||||
|
|
||||||
|
+6 0 -6 +10 "cruel o_o " +24 -1 -29 +1 "!"
|
||||||
|
|
||||||
|
- total patch size is 8 control bytes + 10 (string) + 1 (string) = 19 bytes
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
// object: method dispatch tables
|
||||||
|
|
||||||
|
#define ctor(obj) obj_method0(obj, ctor) // ctor[obj_typeid(obj)](obj)
|
||||||
|
#define dtor(obj) obj_method0(obj, dtor) // dtor[obj_typeid(obj)](obj)
|
||||||
|
|
||||||
|
API extern void (*ctor[256])(); ///-
|
||||||
|
API extern void (*dtor[256])(); ///-
|
||||||
|
|
||||||
|
const char *obj_typeof( const void *obj ) {
|
||||||
|
int obj_typeeq(a,b)
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
|
||||||
|
// ---
|
||||||
|
|
||||||
|
void *obj_copy(void **dst, const void *src) {
|
||||||
|
if(!*dst) return *dst = obj_clone(src);
|
||||||
|
|
||||||
|
if( obj_typeeq(*dst, src) ) {
|
||||||
|
return memcpy(*dst, src, obj_sizeof(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *obj_mutate(void **dst_, const void *src) {
|
||||||
|
// mutate a class. ie, convert a given object class into a different one,
|
||||||
|
// while preserving the original metas and references as much as possible.
|
||||||
|
//
|
||||||
|
// @fixme: systems might be tracking objects in the future. the fact that we
|
||||||
|
// can reallocate a pointer (and hence, change its address) seems way too dangerous,
|
||||||
|
// as the tracking systems could crash when referencing a mutated object.
|
||||||
|
// solutions: do not reallocate if sizeof(new_class) > sizeof(old_class) maybe? good enough?
|
||||||
|
// also, optimization hint: no need to reallocate if both sizes matches, just copy contents.
|
||||||
|
|
||||||
|
if(!*dst_) return *dst_ = obj_clone(src);
|
||||||
|
|
||||||
|
void *dst = *dst_;
|
||||||
|
dtor(dst);
|
||||||
|
|
||||||
|
unsigned src_sz = obj_sizeof(src);
|
||||||
|
unsigned src_id = obj_typeid(src);
|
||||||
|
|
||||||
|
void *dst_ptr = *((void**)dst - 1);
|
||||||
|
unsigned payload = (OBJPAYLOAD16(dst_ptr) & 255) | src_id << 8;
|
||||||
|
FREE( OBJUNBOX(dst_ptr) );
|
||||||
|
*((void**)dst - 1) = OBJBOX( STRDUP( OBJUNBOX(*((void**)src - 1)) ), payload);
|
||||||
|
|
||||||
|
void *base = (void*)((void**)dst - 1);
|
||||||
|
base = REALLOC(base, src_sz + sizeof(void*));
|
||||||
|
*dst_ = (char*)base + sizeof(void*);
|
||||||
|
dst = (char*)base + sizeof(void*);
|
||||||
|
memcpy(dst, src, src_sz);
|
||||||
|
|
||||||
|
ctor(dst);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OBJ_DEMO
|
||||||
|
|
||||||
|
typedef struct MyObject {
|
||||||
|
char* id;
|
||||||
|
int x,y;
|
||||||
|
float rotation;
|
||||||
|
struct MyObject *next;
|
||||||
|
} MyObject;
|
||||||
|
|
||||||
|
void tests1() {
|
||||||
|
// Construct two objects
|
||||||
|
MyObject *root = obj_new(MyObject, 0);
|
||||||
|
MyObject *obj = obj_new(MyObject, "An identifier!", 0x11, 0x22, 3.1415f, root );
|
||||||
|
|
||||||
|
// Dump contents of our objects
|
||||||
|
|
||||||
|
obj_hexdump(root);
|
||||||
|
obj_hexdump(obj);
|
||||||
|
|
||||||
|
// Save to mem
|
||||||
|
|
||||||
|
char* buffer = obj_save(obj);
|
||||||
|
printf("%d bytes\n", (int)strlen(buffer));
|
||||||
|
|
||||||
|
// Clear
|
||||||
|
|
||||||
|
obj_zero( obj );
|
||||||
|
obj_hexdump( obj );
|
||||||
|
|
||||||
|
// Reload
|
||||||
|
|
||||||
|
obj_load( obj, buffer );
|
||||||
|
obj_hexdump( obj );
|
||||||
|
|
||||||
|
// Copy tests
|
||||||
|
|
||||||
|
{
|
||||||
|
MyObject *clone = obj_clone(obj);
|
||||||
|
obj_hexdump(clone);
|
||||||
|
obj_del(clone);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MyObject *copy = 0;
|
||||||
|
obj_copy(©, obj);
|
||||||
|
obj_hexdump(copy);
|
||||||
|
obj_del(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
MyObject *copy = obj_new(MyObject, "A different identifier!", 0x33, 0x44, 0.0f, root );
|
||||||
|
obj_copy(©, obj);
|
||||||
|
obj_hexdump(copy);
|
||||||
|
obj_del(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
void *copy = obj_malloc(100, "an untyped class" );
|
||||||
|
obj_mutate(©, obj);
|
||||||
|
obj_hexdump(copy);
|
||||||
|
obj_copy(©, obj);
|
||||||
|
obj_hexdump(copy);
|
||||||
|
obj_del(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Benchmarking call overhead.
|
||||||
|
// We're here using dtor as a method to test. Since there is actually no
|
||||||
|
// destructor associated to this class, it will be safe to call it extensively (no double frees).
|
||||||
|
//
|
||||||
|
// results:
|
||||||
|
// 427 million calls/s @ old i5-4300/1.90Ghz laptop. compiled with "cl /Ox /Os /MT /DNDEBUG /GL /GF /arch:AVX2"
|
||||||
|
|
||||||
|
#ifndef N
|
||||||
|
#define N (INT32_MAX-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
double t = (puts("benchmarking..."), -clock() / (double)CLOCKS_PER_SEC);
|
||||||
|
for( int i = 0; i < N; ++i ) {
|
||||||
|
dtor(root);
|
||||||
|
}
|
||||||
|
t += clock() / (double)CLOCKS_PER_SEC;
|
||||||
|
printf("Benchmark: %5.2f objcalls/s %5.2fM objcalls/s\n", N/(t), (N/1000)/(t*1000)); // ((N+N)*5) / (t) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void tests2() {
|
||||||
|
REGISTER_BOX
|
||||||
|
REGISTER_RECT
|
||||||
|
|
||||||
|
box *b = obj_new(box, 100);
|
||||||
|
rect *r = obj_new(rect, 100, 200);
|
||||||
|
|
||||||
|
dump(b);
|
||||||
|
dump(r);
|
||||||
|
|
||||||
|
printf("%f\n", area(b));
|
||||||
|
printf("%f\n", area(r));
|
||||||
|
|
||||||
|
obj_del(b);
|
||||||
|
obj_ref(r); obj_unref(r); //obj_del(r);
|
||||||
|
|
||||||
|
int *untyped = obj_malloc( sizeof(int) );
|
||||||
|
int *my_number = obj_malloc( sizeof(int), "a comment about my_number" );
|
||||||
|
char *my_text = obj_malloc( 32, "some debug info here" );
|
||||||
|
|
||||||
|
*untyped = 100;
|
||||||
|
*my_number = 123;
|
||||||
|
sprintf( my_text, "hello world" );
|
||||||
|
|
||||||
|
struct my_bitmap { int w, h, bpp; const char *pixels; };
|
||||||
|
struct my_bitmap *my_bitmap = obj_new(struct my_bitmap, 2,2,8, "\1\2\3\4");
|
||||||
|
|
||||||
|
printf( "%p(%s,%u)\n", my_bitmap, obj_typeof(my_bitmap), obj_typeid(my_bitmap) );
|
||||||
|
printf( "%d(%s,%d)\n", *untyped, obj_typeof(untyped), obj_typeid(untyped) );
|
||||||
|
printf( "%d(%s,%d)\n", *my_number, obj_typeof(my_number), obj_typeid(my_number) );
|
||||||
|
printf( "%s(%s,%d)\n", my_text, obj_typeof(my_text), obj_typeid(my_text) );
|
||||||
|
|
||||||
|
obj_printf(my_text, "hello world #1\n");
|
||||||
|
obj_printf(my_text, "hello world #2\n");
|
||||||
|
puts(obj_output(my_text));
|
||||||
|
|
||||||
|
printf( "%s(%s,%d)\n", my_text, obj_typeof(my_text), obj_typeid(my_text) );
|
||||||
|
|
||||||
|
printf( "equal?:%d\n", obj_typeeq(my_number, untyped) );
|
||||||
|
printf( "equal?:%d\n", obj_typeeq(my_number, my_number) );
|
||||||
|
printf( "equal?:%d\n", obj_typeeq(my_number, my_text) );
|
||||||
|
printf( "equal?:%d\n", obj_typeeq(my_number, my_bitmap) );
|
||||||
|
|
||||||
|
obj_free( untyped );
|
||||||
|
obj_free( my_text );
|
||||||
|
obj_free( my_bitmap );
|
||||||
|
obj_del( my_number ); // should not crash, even if allocated with obj_malloc()
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
[myWindow]
|
||||||
|
x=0.166667
|
||||||
|
y=0.194444
|
||||||
|
w=0.666667
|
||||||
|
h=0.666667
|
||||||
|
visible=1
|
||||||
|
[Outliner]
|
||||||
|
x=-0.000000
|
||||||
|
y=0.107495
|
||||||
|
w=0.249929
|
||||||
|
h=0.333728
|
||||||
|
visible=1
|
||||||
|
[Properties]
|
||||||
|
x=0.749973
|
||||||
|
y=0.052117
|
||||||
|
w=0.250028
|
||||||
|
h=0.333860
|
||||||
|
visible=1
|
Loading…
Reference in New Issue