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 [pull] ; pull changes from origin
|
||||
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 [depot] ; sync depot changes
|
||||
echo %0 [fuse] ; fuse all binaries and cooked zipfiles found together
|
||||
echo %0 [git] ; prepare for commit
|
||||
echo %0 [vps] ; upload the release to VPS
|
||||
echo %0 [tidy] ; clean up temp files
|
||||
|
@ -138,7 +140,7 @@ if "%1"=="git" (
|
|||
rem call make.bat docs
|
||||
|
||||
call make.bat amalgamation
|
||||
call make.bat split
|
||||
rem call make.bat split
|
||||
|
||||
rem rd /q /s engine\split
|
||||
rem md engine\split
|
||||
|
@ -227,6 +229,17 @@ if "%1"=="join" (
|
|||
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
|
||||
if "%1"=="checkmem" (
|
||||
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_stream(float gain);
|
||||
float audio_volume_master(float gain);
|
||||
int audio_mute(int mute);
|
||||
int audio_muted();
|
||||
int ui_audio();
|
||||
enum AUDIO_FLAGS {
|
||||
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);
|
||||
vec3 editor_pick(float mouse_x, float mouse_y);
|
||||
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_save();
|
||||
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
|
||||
|
@ -3069,6 +3075,8 @@ typedef vec3i guid;
|
|||
void app_crash();
|
||||
void app_singleton(const char *guid);
|
||||
bool app_open(const char *folder_file_or_url);
|
||||
const char* app_loadfile();
|
||||
const char* app_savefile();
|
||||
char* callstack( int traces );
|
||||
int callstackf( FILE *fp, int traces );
|
||||
void die(const char *message);
|
||||
|
@ -3140,7 +3148,7 @@ PANEL_OPEN = 1,
|
|||
int ui_label2_toolbar(const char *label, const char *icons);
|
||||
int ui_slider(const char *label, float *value);
|
||||
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_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_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_stream(float gain); // set bgm volume if gain is in [0..1] range. return 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_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. returns current bgm 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();
|
||||
|
||||
|
@ -15683,6 +15686,11 @@ API void* dll(const char *filename, const char *symbol);
|
|||
API vec3 editor_pick(float mouse_x, float mouse_y);
|
||||
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
|
||||
|
||||
API char* dialog_load();
|
||||
|
@ -16520,7 +16528,9 @@ extern API int profiler_enabled; ///-
|
|||
// @todo: nested structs? pointers in members?
|
||||
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
||||
|
||||
#ifndef ifdef_objapi
|
||||
#define ifdef_objapi(T,...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
typedef struct reflected_t {
|
||||
unsigned id, objtype;
|
||||
|
@ -17519,9 +17529,10 @@ char* strtok_s(char* str,const char* delimiters,char** context); // tcc misses t
|
|||
|
||||
#if 1
|
||||
#define each_substring(str, delims, keyname) \
|
||||
( int len_ = strlen(str) + 1; len_; len_ = 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( char *next_token = 0, *keyname = strtok_r(_bak, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
||||
( char *str_ = (char*)(str); str_; str_ = 0 ) \
|
||||
for( int len_ = strlen(str_) + 1, heap_ = len_ < 1024; len_ > 1; len_ = 0 ) \
|
||||
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
|
||||
#define each_substring(str, delims, keyname) \
|
||||
( 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 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 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_slider(const char *label, float *value);
|
||||
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_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;
|
||||
|
||||
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
|
||||
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
|
||||
// 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
fileHeader.relativeOffsetOflocalHeader += (uintptr_t)user_data2;
|
||||
|
||||
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
||||
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
||||
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
||||
|
@ -252939,11 +252957,7 @@ common:;
|
|||
|
||||
// zip common
|
||||
|
||||
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");
|
||||
zip* zip_open_handle(FILE *fp, const char *mode) {
|
||||
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
||||
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
||||
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' ) {
|
||||
z->in = fp;
|
||||
|
||||
unsigned long long seekcur = ftell(z->in);
|
||||
|
||||
JZEndRecord jzEndRecord = {0};
|
||||
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
||||
REALLOC(z, 0);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
if( z->out && z->count ) {
|
||||
// prepare end record
|
||||
|
@ -253166,8 +253193,7 @@ tar *tar_open(const char *filename, const char *mode) {
|
|||
|
||||
*t = zero;
|
||||
t->in = in;
|
||||
tar__parse(in, tar__push_entry, t);
|
||||
return t;
|
||||
return tar__parse(in, tar__push_entry, t) ? t : NULL;
|
||||
}
|
||||
|
||||
int tar_find(tar *t, const char *entryname) {
|
||||
|
@ -331461,16 +331487,26 @@ char* tempvl(const char *fmt, va_list vl) {
|
|||
|
||||
int reqlen = sz;
|
||||
#if 0
|
||||
int heap = 0;
|
||||
enum { STACK_ALLOC = 16384 };
|
||||
static __thread char buf[STACK_ALLOC];
|
||||
#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
|
||||
#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");
|
||||
char* ptr = buf + (cur *= (cur+reqlen) < len, (cur += reqlen) - reqlen);
|
||||
if( reqlen >= STACK_ALLOC ) {
|
||||
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 );
|
||||
return (char *)ptr;
|
||||
|
@ -332366,10 +332402,17 @@ float audio_volume_master(float gain) {
|
|||
mixer.gain = 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 ) {
|
||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||
if(muted) return 1;
|
||||
if(audio_muted()) return 1;
|
||||
|
||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||
// 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
|
||||
uint64_t hash = hash_str(fname);
|
||||
unsigned bucket = (hash >> 32) % numthreads;
|
||||
unsigned bucket = (hash /*>> 32*/) % numthreads;
|
||||
if(bucket != threadid) continue;
|
||||
|
||||
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 *w = strchr( ART, ' ' ); if(w) *w = 0;
|
||||
char *out = 0; const char *sep = "";
|
||||
const char *v4k_title = getenv("V4K_TITLE");
|
||||
for each_substring(ART, ",", t) {
|
||||
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] = '/';
|
||||
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
||||
assert( out[strlen(out) - 1] == '/' );
|
||||
|
@ -336162,7 +336203,7 @@ bool file_delete(const char *pathfile) {
|
|||
}
|
||||
bool file_copy(const char *src, const char *dst) {
|
||||
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 *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
||||
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
||||
|
@ -336487,6 +336528,8 @@ void vfs_reload() {
|
|||
#if defined(EMSCRIPTEN)
|
||||
vfs_mount("index.zip");
|
||||
#else
|
||||
// mount fused executables
|
||||
vfs_mount(va("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")));
|
||||
/* // old way
|
||||
for( int i = 0; i < JOBS_MAX; ++i) {
|
||||
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
|
||||
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||
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 ) t = tar_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;
|
||||
|
||||
// normalize input -> "././" to ""
|
||||
|
@ -336699,9 +336771,9 @@ if( found && *found == 0 ) {
|
|||
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
||||
|
||||
// search (last item)
|
||||
static char last_item[256] = { 0 };
|
||||
static void *last_ptr = 0;
|
||||
static int last_size = 0;
|
||||
static __thread char last_item[256] = { 0 };
|
||||
static __thread void *last_ptr = 0;
|
||||
static __thread int last_size = 0;
|
||||
if( !strcmpi(lookup_id, last_item)) {
|
||||
ptr = last_ptr;
|
||||
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( !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
|
||||
archive_dir zero = {0}, *old = dir_cache;
|
||||
*(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);
|
||||
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;
|
||||
if( added < MAX_CACHED_FILES ) {
|
||||
++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 ) {
|
||||
if( !dir->next ) {
|
||||
prev->next = 0; // break link
|
||||
void *data = dir->data;
|
||||
found = dir->data;
|
||||
dir->path = REALLOC(dir->path, 0);
|
||||
dir->data = REALLOC(dir->data, 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;
|
||||
|
||||
void reflected_printf(reflected_t *r) {
|
||||
printf("id:%u objtype:%u sz:%u name:%s info:%s 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 : "");
|
||||
printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s",
|
||||
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() {
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
@ -352817,11 +352917,12 @@ int ui_collapse_end() {
|
|||
|
||||
|
||||
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;
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
@ -352832,7 +352933,7 @@ int ui_submenu(const char *options) {
|
|||
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
||||
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
||||
}
|
||||
ui_contextual_end();
|
||||
ui_contextual_end(0);
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
@ -352966,8 +353067,10 @@ int ui_label(const char *text) {
|
|||
int ui_label2(const char *label, const char *text_) {
|
||||
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 align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||
int align1 = 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);
|
||||
|
||||
const struct nk_input *input = &ui_ctx->input;
|
||||
|
@ -354702,12 +354805,38 @@ int window_frame_begin() {
|
|||
if( may_render_stats ) {
|
||||
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
||||
|
||||
#if 1
|
||||
static char *filter = 0;
|
||||
static int time_factor = 0;
|
||||
static int playing = 0;
|
||||
static int paused = 0;
|
||||
int advance_frame = 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;
|
||||
int choice = ui_toolbar(ICON_MD_SEARCH ";");
|
||||
if( choice == 1 ) do_filter = 1;
|
||||
int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS);
|
||||
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 ) {
|
||||
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)
|
||||
|
@ -354717,13 +354846,44 @@ int window_frame_begin() {
|
|||
if( filter ) filter[0] = '\0';
|
||||
}
|
||||
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;
|
||||
|
||||
#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;
|
||||
const char *file = 0;
|
||||
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));
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
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();
|
||||
}
|
||||
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() );
|
||||
}
|
||||
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) {
|
||||
// @todo
|
||||
EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") {
|
||||
// @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) {
|
||||
// @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) {
|
||||
EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.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();
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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");
|
||||
if( choice == 1 ) ui_layout_all_reset("*");
|
||||
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)();
|
||||
}
|
||||
|
||||
API int editor_tick();
|
||||
editor_tick();
|
||||
}
|
||||
|
||||
#if 0 // deprecated
|
||||
|
@ -356186,6 +356430,61 @@ int ui_bt(bt_t *b) {
|
|||
// editing:
|
||||
// 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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__active;
|
||||
static int gizmo__hover;
|
||||
|
@ -356361,26 +356729,6 @@ int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
|
|||
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
|
||||
|
||||
static const char *kit_lang = "enUS", *kit_langs =
|
||||
|
@ -356554,18 +356902,20 @@ static void v4k_pre_init() {
|
|||
// window_swap();
|
||||
}
|
||||
static void v4k_post_init(float refresh_rate) {
|
||||
int i;
|
||||
|
||||
// cook cleanup
|
||||
cook_stop();
|
||||
|
||||
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
|
||||
int i;
|
||||
#if 1 // #ifdef PARALLEL_INIT
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
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 == 2 ) script_init(), kit_init(), midi_init();
|
||||
else if( i == 3 ) input_init(), network_init();
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
typedef struct zip zip;
|
||||
|
||||
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
|
||||
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
|
||||
// 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
fileHeader.relativeOffsetOflocalHeader += (uintptr_t)user_data2;
|
||||
|
||||
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
||||
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
||||
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
||||
|
@ -753,11 +756,7 @@ common:;
|
|||
|
||||
// zip common
|
||||
|
||||
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");
|
||||
zip* zip_open_handle(FILE *fp, const char *mode) {
|
||||
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
||||
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
||||
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' ) {
|
||||
z->in = fp;
|
||||
|
||||
unsigned long long seekcur = ftell(z->in);
|
||||
|
||||
JZEndRecord jzEndRecord = {0};
|
||||
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
||||
REALLOC(z, 0);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
if( z->out && z->count ) {
|
||||
// prepare end record
|
||||
|
@ -980,8 +992,7 @@ tar *tar_open(const char *filename, const char *mode) {
|
|||
|
||||
*t = zero;
|
||||
t->in = in;
|
||||
tar__parse(in, tar__push_entry, t);
|
||||
return t;
|
||||
return tar__parse(in, tar__push_entry, t) ? t : NULL;
|
||||
}
|
||||
|
||||
int tar_find(tar *t, const char *entryname) {
|
||||
|
|
|
@ -385,10 +385,17 @@ float audio_volume_master(float gain) {
|
|||
mixer.gain = 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 ) {
|
||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||
if(muted) return 1;
|
||||
if(audio_muted()) return 1;
|
||||
|
||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||
// 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_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_stream(float gain); // set bgm volume if gain is in [0..1] range. return 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_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. returns current bgm 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();
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ array(struct fs) zipscan_filter(int threadid, int numthreads) {
|
|||
|
||||
// skip if list item does not belong to this thread bucket
|
||||
uint64_t hash = hash_str(fname);
|
||||
unsigned bucket = (hash >> 32) % numthreads;
|
||||
unsigned bucket = (hash /*>> 32*/) % numthreads;
|
||||
if(bucket != threadid) continue;
|
||||
|
||||
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 *w = strchr( ART, ' ' ); if(w) *w = 0;
|
||||
char *out = 0; const char *sep = "";
|
||||
const char *v4k_title = getenv("V4K_TITLE");
|
||||
for each_substring(ART, ",", t) {
|
||||
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] = '/';
|
||||
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
||||
assert( out[strlen(out) - 1] == '/' );
|
||||
|
|
|
@ -1,6 +1,61 @@
|
|||
// editing:
|
||||
// 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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__active;
|
||||
static int gizmo__hover;
|
||||
|
@ -176,26 +300,6 @@ int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
|
|||
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
|
||||
|
||||
static const char *kit_lang = "enUS", *kit_langs =
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
API vec3 editor_pick(float mouse_x, float mouse_y);
|
||||
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
|
||||
|
||||
API char* dialog_load();
|
||||
|
|
|
@ -257,7 +257,7 @@ bool file_delete(const char *pathfile) {
|
|||
}
|
||||
bool file_copy(const char *src, const char *dst) {
|
||||
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 *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
||||
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
||||
|
@ -582,6 +582,8 @@ void vfs_reload() {
|
|||
#if defined(EMSCRIPTEN)
|
||||
vfs_mount("index.zip");
|
||||
#else
|
||||
// mount fused executables
|
||||
vfs_mount(va("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")));
|
||||
/* // old way
|
||||
for( int i = 0; i < JOBS_MAX; ++i) {
|
||||
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
|
||||
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||
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 ) t = tar_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;
|
||||
|
||||
// normalize input -> "././" to ""
|
||||
|
@ -794,9 +825,9 @@ if( found && *found == 0 ) {
|
|||
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
||||
|
||||
// search (last item)
|
||||
static char last_item[256] = { 0 };
|
||||
static void *last_ptr = 0;
|
||||
static int last_size = 0;
|
||||
static __thread char last_item[256] = { 0 };
|
||||
static __thread void *last_ptr = 0;
|
||||
static __thread int last_size = 0;
|
||||
if( !strcmpi(lookup_id, last_item)) {
|
||||
ptr = last_ptr;
|
||||
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( !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
|
||||
archive_dir zero = {0}, *old = dir_cache;
|
||||
*(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);
|
||||
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;
|
||||
if( added < MAX_CACHED_FILES ) {
|
||||
++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 ) {
|
||||
if( !dir->next ) {
|
||||
prev->next = 0; // break link
|
||||
void *data = dir->data;
|
||||
found = dir->data;
|
||||
dir->path = REALLOC(dir->path, 0);
|
||||
dir->data = REALLOC(dir->data, 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();
|
||||
}
|
||||
static void v4k_post_init(float refresh_rate) {
|
||||
int i;
|
||||
|
||||
// cook cleanup
|
||||
cook_stop();
|
||||
|
||||
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
|
||||
int i;
|
||||
#if 1 // #ifdef PARALLEL_INIT
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
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 == 2 ) script_init(), kit_init(), midi_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;
|
||||
|
||||
void reflected_printf(reflected_t *r) {
|
||||
printf("id:%u objtype:%u sz:%u name:%s info:%s 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 : "");
|
||||
printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s",
|
||||
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() {
|
||||
for each_map_ptr(reflects, unsigned, k, reflected_t, p) {
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
// @todo: nested structs? pointers in members?
|
||||
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
||||
|
||||
#ifndef ifdef_objapi
|
||||
#define ifdef_objapi(T,...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
typedef struct reflected_t {
|
||||
unsigned id, objtype;
|
||||
|
|
|
@ -8,16 +8,26 @@ char* tempvl(const char *fmt, va_list vl) {
|
|||
|
||||
int reqlen = sz;
|
||||
#if 0
|
||||
int heap = 0;
|
||||
enum { STACK_ALLOC = 16384 };
|
||||
static __thread char buf[STACK_ALLOC];
|
||||
#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
|
||||
#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");
|
||||
char* ptr = buf + (cur *= (cur+reqlen) < len, (cur += reqlen) - reqlen);
|
||||
if( reqlen >= STACK_ALLOC ) {
|
||||
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 );
|
||||
return (char *)ptr;
|
||||
|
|
|
@ -21,9 +21,10 @@ char* strtok_s(char* str,const char* delimiters,char** context); // tcc misses t
|
|||
|
||||
#if 1
|
||||
#define each_substring(str, delims, keyname) \
|
||||
( int len_ = strlen(str) + 1; len_; len_ = 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( char *next_token = 0, *keyname = strtok_r(_bak, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
||||
( char *str_ = (char*)(str); str_; str_ = 0 ) \
|
||||
for( int len_ = strlen(str_) + 1, heap_ = len_ < 1024; len_ > 1; len_ = 0 ) \
|
||||
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
|
||||
#define each_substring(str, delims, keyname) \
|
||||
( 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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -38,6 +38,10 @@ API void app_crash();
|
|||
API void app_singleton(const char *guid);
|
||||
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 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() {
|
||||
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;
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1416,7 +1417,7 @@ int ui_submenu(const char *options) {
|
|||
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
||||
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
||||
}
|
||||
ui_contextual_end();
|
||||
ui_contextual_end(0);
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
@ -1550,8 +1551,10 @@ int ui_label(const char *text) {
|
|||
int ui_label2(const char *label, const char *text_) {
|
||||
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 align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||
int align1 = 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);
|
||||
|
||||
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_slider(const char *label, float *value);
|
||||
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_end();
|
||||
API int ui_panel_end();
|
||||
|
|
|
@ -536,12 +536,38 @@ int window_frame_begin() {
|
|||
if( may_render_stats ) {
|
||||
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
||||
|
||||
#if 1
|
||||
static char *filter = 0;
|
||||
static int time_factor = 0;
|
||||
static int playing = 0;
|
||||
static int paused = 0;
|
||||
int advance_frame = 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;
|
||||
int choice = ui_toolbar(ICON_MD_SEARCH ";");
|
||||
if( choice == 1 ) do_filter = 1;
|
||||
int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS);
|
||||
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 ) {
|
||||
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)
|
||||
|
@ -551,13 +577,44 @@ int window_frame_begin() {
|
|||
if( filter ) filter[0] = '\0';
|
||||
}
|
||||
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;
|
||||
|
||||
#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;
|
||||
const char *file = 0;
|
||||
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));
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
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();
|
||||
}
|
||||
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() );
|
||||
}
|
||||
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) {
|
||||
// @todo
|
||||
EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") {
|
||||
// @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) {
|
||||
// @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) {
|
||||
EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.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();
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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");
|
||||
if( choice == 1 ) ui_layout_all_reset("*");
|
||||
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)();
|
||||
}
|
||||
|
||||
API int editor_tick();
|
||||
editor_tick();
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
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
|
||||
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
|
||||
// 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
fileHeader.relativeOffsetOflocalHeader += (uintptr_t)user_data2;
|
||||
|
||||
JZGlobalFileHeader *g = &fileHeader, copy = *g;
|
||||
FPRINTF(stdout, "\tsignature: %u %#x\n", g->signature, g->signature); // 0x02014B50
|
||||
FPRINTF(stdout, "\tversionMadeBy: %u %#x\n", g->versionMadeBy, g->versionMadeBy); // unsupported
|
||||
|
@ -234967,11 +234970,7 @@ common:;
|
|||
|
||||
// zip common
|
||||
|
||||
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");
|
||||
zip* zip_open_handle(FILE *fp, const char *mode) {
|
||||
if( !fp ) return ERR(NULL, "cannot open file for %s mode", mode);
|
||||
zip zero = {0}, *z = (zip*)REALLOC(0, sizeof(zip));
|
||||
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' ) {
|
||||
z->in = fp;
|
||||
|
||||
unsigned long long seekcur = ftell(z->in);
|
||||
|
||||
JZEndRecord jzEndRecord = {0};
|
||||
if(jzReadEndRecord(fp, &jzEndRecord) != JZ_OK) {
|
||||
REALLOC(z, 0);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
if( z->out && z->count ) {
|
||||
// prepare end record
|
||||
|
@ -235194,8 +235206,7 @@ tar *tar_open(const char *filename, const char *mode) {
|
|||
|
||||
*t = zero;
|
||||
t->in = in;
|
||||
tar__parse(in, tar__push_entry, t);
|
||||
return t;
|
||||
return tar__parse(in, tar__push_entry, t) ? t : NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
#if 0
|
||||
int heap = 0;
|
||||
enum { STACK_ALLOC = 16384 };
|
||||
static __thread char buf[STACK_ALLOC];
|
||||
#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
|
||||
#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");
|
||||
char* ptr = buf + (cur *= (cur+reqlen) < len, (cur += reqlen) - reqlen);
|
||||
if( reqlen >= STACK_ALLOC ) {
|
||||
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 );
|
||||
return (char *)ptr;
|
||||
|
@ -1430,10 +1440,17 @@ float audio_volume_master(float gain) {
|
|||
mixer.gain = 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 ) {
|
||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||
if(muted) return 1;
|
||||
if(audio_muted()) return 1;
|
||||
|
||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||
// 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
|
||||
uint64_t hash = hash_str(fname);
|
||||
unsigned bucket = (hash >> 32) % numthreads;
|
||||
unsigned bucket = (hash /*>> 32*/) % numthreads;
|
||||
if(bucket != threadid) continue;
|
||||
|
||||
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 *w = strchr( ART, ' ' ); if(w) *w = 0;
|
||||
char *out = 0; const char *sep = "";
|
||||
const char *v4k_title = getenv("V4K_TITLE");
|
||||
for each_substring(ART, ",", t) {
|
||||
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] = '/';
|
||||
strcatf(&out, "%s%s%s", sep, tmp, strendi(tmp, "/") ? "" : "/");
|
||||
assert( out[strlen(out) - 1] == '/' );
|
||||
|
@ -5226,7 +5241,7 @@ bool file_delete(const char *pathfile) {
|
|||
}
|
||||
bool file_copy(const char *src, const char *dst) {
|
||||
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 *out = fopen(dst, "wb"); out; fclose(out), out = 0, ok = 1) {
|
||||
for( int n; !!(n = fread( buffer, 1, BUFSIZE, in )); ){
|
||||
|
@ -5551,6 +5566,8 @@ void vfs_reload() {
|
|||
#if defined(EMSCRIPTEN)
|
||||
vfs_mount("index.zip");
|
||||
#else
|
||||
// mount fused executables
|
||||
vfs_mount(va("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")));
|
||||
/* // old way
|
||||
for( int i = 0; i < JOBS_MAX; ++i) {
|
||||
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
|
||||
bool vfs_mount_(const char *path, array(struct vfs_entry) *entries) {
|
||||
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 ) t = tar_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;
|
||||
|
||||
// normalize input -> "././" to ""
|
||||
|
@ -5763,9 +5809,9 @@ if( found && *found == 0 ) {
|
|||
const char *lookup_id = /*file_normalize_with_folder*/(pathfile);
|
||||
|
||||
// search (last item)
|
||||
static char last_item[256] = { 0 };
|
||||
static void *last_ptr = 0;
|
||||
static int last_size = 0;
|
||||
static __thread char last_item[256] = { 0 };
|
||||
static __thread void *last_ptr = 0;
|
||||
static __thread int last_size = 0;
|
||||
if( !strcmpi(lookup_id, last_item)) {
|
||||
ptr = last_ptr;
|
||||
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( !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
|
||||
archive_dir zero = {0}, *old = dir_cache;
|
||||
*(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);
|
||||
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;
|
||||
if( added < MAX_CACHED_FILES ) {
|
||||
++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 ) {
|
||||
if( !dir->next ) {
|
||||
prev->next = 0; // break link
|
||||
void *data = dir->data;
|
||||
found = dir->data;
|
||||
dir->path = REALLOC(dir->path, 0);
|
||||
dir->data = REALLOC(dir->data, 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;
|
||||
|
||||
void reflected_printf(reflected_t *r) {
|
||||
printf("id:%u objtype:%u sz:%u name:%s info:%s 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 : "");
|
||||
printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s",
|
||||
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() {
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
@ -21881,11 +21955,12 @@ int ui_collapse_end() {
|
|||
|
||||
|
||||
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;
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
@ -21896,7 +21971,7 @@ int ui_submenu(const char *options) {
|
|||
for( int i = 0; i < array_count(tokens) ; ++i ) {
|
||||
if( ui_button_transparent(tokens[i]) ) choice = i + 1;
|
||||
}
|
||||
ui_contextual_end();
|
||||
ui_contextual_end(0);
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
@ -22030,8 +22105,10 @@ int ui_label(const char *text) {
|
|||
int ui_label2(const char *label, const char *text_) {
|
||||
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 align2 = text_[0] == '>' ? (text_++, NK_TEXT_RIGHT) : text_[0] == '=' ? (text_++, NK_TEXT_CENTERED) : text_[0] == '<' ? (text_++, NK_TEXT_LEFT) : NK_TEXT_LEFT;
|
||||
int align1 = 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);
|
||||
|
||||
const struct nk_input *input = &ui_ctx->input;
|
||||
|
@ -23766,12 +23843,38 @@ int window_frame_begin() {
|
|||
if( may_render_stats ) {
|
||||
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
|
||||
|
||||
#if 1
|
||||
static char *filter = 0;
|
||||
static int time_factor = 0;
|
||||
static int playing = 0;
|
||||
static int paused = 0;
|
||||
int advance_frame = 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;
|
||||
int choice = ui_toolbar(ICON_MD_SEARCH ";");
|
||||
if( choice == 1 ) do_filter = 1;
|
||||
int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS);
|
||||
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 ) {
|
||||
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)
|
||||
|
@ -23781,13 +23884,44 @@ int window_frame_begin() {
|
|||
if( filter ) filter[0] = '\0';
|
||||
}
|
||||
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;
|
||||
|
||||
#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;
|
||||
const char *file = 0;
|
||||
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));
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
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();
|
||||
}
|
||||
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() );
|
||||
}
|
||||
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) {
|
||||
// @todo
|
||||
EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") {
|
||||
// @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) {
|
||||
// @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) {
|
||||
EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.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();
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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");
|
||||
if( choice == 1 ) ui_layout_all_reset("*");
|
||||
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)();
|
||||
}
|
||||
|
||||
API int editor_tick();
|
||||
editor_tick();
|
||||
}
|
||||
|
||||
#if 0 // deprecated
|
||||
|
@ -25250,6 +25468,61 @@ int ui_bt(bt_t *b) {
|
|||
// editing:
|
||||
// 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) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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__active;
|
||||
static int gizmo__hover;
|
||||
|
@ -25425,26 +25767,6 @@ int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
|
|||
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
|
||||
|
||||
static const char *kit_lang = "enUS", *kit_langs =
|
||||
|
@ -25618,18 +25940,20 @@ static void v4k_pre_init() {
|
|||
// window_swap();
|
||||
}
|
||||
static void v4k_post_init(float refresh_rate) {
|
||||
int i;
|
||||
|
||||
// cook cleanup
|
||||
cook_stop();
|
||||
|
||||
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
|
||||
int i;
|
||||
#if 1 // #ifdef PARALLEL_INIT
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
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 == 2 ) script_init(), kit_init(), midi_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_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_stream(float gain); // set bgm volume if gain is in [0..1] range. return 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_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. returns current bgm 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();
|
||||
|
||||
|
@ -1750,6 +1753,11 @@ API void* dll(const char *filename, const char *symbol);
|
|||
API vec3 editor_pick(float mouse_x, float mouse_y);
|
||||
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
|
||||
|
||||
API char* dialog_load();
|
||||
|
@ -2587,7 +2595,9 @@ extern API int profiler_enabled; ///-
|
|||
// @todo: nested structs? pointers in members?
|
||||
// @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
|
||||
|
||||
#ifndef ifdef_objapi
|
||||
#define ifdef_objapi(T,...) __VA_ARGS__
|
||||
#endif
|
||||
|
||||
typedef struct reflected_t {
|
||||
unsigned id, objtype;
|
||||
|
@ -3586,9 +3596,10 @@ char* strtok_s(char* str,const char* delimiters,char** context); // tcc misses t
|
|||
|
||||
#if 1
|
||||
#define each_substring(str, delims, keyname) \
|
||||
( int len_ = strlen(str) + 1; len_; len_ = 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( char *next_token = 0, *keyname = strtok_r(_bak, delims, &next_token); keyname; keyname = strtok_r(NULL, delims, &next_token) )
|
||||
( char *str_ = (char*)(str); str_; str_ = 0 ) \
|
||||
for( int len_ = strlen(str_) + 1, heap_ = len_ < 1024; len_ > 1; len_ = 0 ) \
|
||||
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
|
||||
#define each_substring(str, delims, keyname) \
|
||||
( 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 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 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_slider(const char *label, float *value);
|
||||
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_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)
|
||||
// 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.
|
||||
// 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
|
||||
//
|
||||
// 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)
|
||||
// - world: streaming, migration
|
||||
|
||||
#include "v4k.h"
|
||||
#include "fwk.h"
|
||||
|
||||
// #include "labs.vm/ecs.c"
|
||||
|
||||
|
@ -839,10 +839,10 @@ void editor_obj_render_max_properties(void *obj, const char *mask) { // headless
|
|||
// main editor interface
|
||||
|
||||
void editor_render_menubar() {
|
||||
int alts = input(KEY_LALT) || input(KEY_RALT); // @todo: move to v4k.c
|
||||
int ctrls = input(KEY_LCTRL) || input(KEY_RCTRL); // @todo: move to v4k.c
|
||||
int shifts = input(KEY_LSHIFT) || input(KEY_RSHIFT); // @todo: move to v4k.c
|
||||
int mods = alts || ctrls || shifts; // @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 fwk.c
|
||||
int shifts = input(KEY_LSHIFT) || input(KEY_RSHIFT); // @todo: move to fwk.c
|
||||
int mods = alts || ctrls || shifts; // @todo: move to fwk.c
|
||||
if( input_down(KEY_F5) ) editor_key = key_reload;
|
||||
if( input_down(KEY_F11) ) editor_key = key_fullscreen;
|
||||
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("<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);
|
||||
ui_contextual_end();
|
||||
ui_contextual_end(0);
|
||||
}
|
||||
|
||||
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("<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);
|
||||
ui_contextual_end();
|
||||
ui_contextual_end(0);
|
||||
}
|
||||
|
||||
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 -->
|
||||
*/
|
||||
|
||||
#include "v4k.c"
|
||||
#include "fwk.c"
|
||||
#include "editor2.h" // old editor interface
|
||||
|
||||
#define ui_push_hspace(px) \
|
||||
|
@ -28,8 +28,6 @@
|
|||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
#include "labs.meta/meta_reflect.c"
|
||||
|
||||
int *meta_changed(void *value) {
|
||||
static map(void*,int) changes = 0;
|
||||
do_once map_init_ptr(changes);
|
||||
|
@ -37,20 +35,20 @@ int *meta_changed(void *value) {
|
|||
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
|
||||
char *title = va(ICON_MD_UNDO "%s", r->info);
|
||||
char *title = va(ICON_MD_UNDO "%s", info);
|
||||
|
||||
int changed = 0;
|
||||
/**/ if( !strcmp(r->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(r->type, "string") ) changed = ui_string(title, (char**)value);
|
||||
else if( !strcmp(r->type, "float") ) changed = ui_float(title, (float*)value);
|
||||
else if( !strcmp(r->type, "double") ) changed = ui_double(title, (double*)value);
|
||||
else if( !strcmp(r->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);
|
||||
/**/ if( !strcmp(type, "int") ) changed = ui_int(title, (int*)value);
|
||||
else if( !strcmp(type, "char*") ) changed = ui_buffer(title, (char*)value, strlen((char*)value)+1);
|
||||
else if( !strcmp(type, "string") ) changed = ui_string(title, (char**)value);
|
||||
else if( !strcmp(type, "float") ) changed = ui_float(title, (float*)value);
|
||||
else if( !strcmp(type, "double") ) changed = ui_double(title, (double*)value);
|
||||
else if( !strcmp(type, "unsigned") ) changed = ui_unsigned(title, (unsigned*)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 ui_label2(title, va("(%s)%s", r->type, r->name));
|
||||
else ui_label2(title, va("(%s)%s", type, name));
|
||||
|
||||
if( changed ) {
|
||||
*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) {
|
||||
/**/ 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, "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);
|
||||
|
@ -73,42 +71,6 @@ bool reflect_parse(void *obj, const char *type, const char *val) {
|
|||
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 \
|
||||
|
@ -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( 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 ) {
|
||||
#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};
|
||||
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,
|
||||
|
@ -239,7 +201,10 @@ void node_edit(node *n, node *root) {
|
|||
|
||||
int choice = ui_label2_toolbar(section, toolbar);
|
||||
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() {
|
||||
editor_init(); // old editor interface
|
||||
editor_tick(); // old editor interface
|
||||
editor_tick_(); // old editor interface
|
||||
editor_menubar(); // old editor interface
|
||||
|
||||
if( input_down(KEY_F5) ) {
|
||||
|
@ -422,42 +387,42 @@ int main() {
|
|||
STRUCT( my_sprite, vec3, position, "Position" );
|
||||
STRUCT( my_sprite, float, tilt, "Tilt degrees" );
|
||||
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("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");
|
||||
window_create(0.80, 0);
|
||||
|
||||
struct my_sprite spr1 = {0}, spr2 = {0}, spr3 = {0};
|
||||
obj_make(&spr1,
|
||||
"[my_sprite]\n"
|
||||
"filename=cat.png\n"
|
||||
"position=5 2 100\n"
|
||||
"tilt=45 + 45 -90\n"
|
||||
"tint=255 255 0\n"
|
||||
);
|
||||
obj_make(&spr2,
|
||||
"[my_sprite]\n"
|
||||
"filename=cat.png\n"
|
||||
"position=1 2 100\n"
|
||||
"tilt=45 + 45 -90\n"
|
||||
"tint=255 0 0\n"
|
||||
);
|
||||
obj_make(&spr3,
|
||||
"[my_sprite]\n"
|
||||
"filename=cat.png\n"
|
||||
"position=1 2 100\n"
|
||||
"tilt=45\n"
|
||||
"tint=0 0 255\n"
|
||||
);
|
||||
struct my_sprite
|
||||
spr1 = {
|
||||
.filename="cat.png",
|
||||
.position = vec3(5, 2, 100),
|
||||
.tilt=45 + 45 -90,
|
||||
.tint=vec4(255, 255, 0, 255)
|
||||
},
|
||||
spr2 = {
|
||||
.filename="cat.png",
|
||||
.position = vec3(1, 2, 100),
|
||||
.tilt=45 + 45 -90,
|
||||
.tint=vec4(255, 0, 0, 255)
|
||||
},
|
||||
spr3 = {
|
||||
.filename="cat.png",
|
||||
.position = vec3(1, 2, 100),
|
||||
.tilt=45,
|
||||
.tint=vec4(0, 0, 255, 255)
|
||||
};
|
||||
|
||||
my_sprite_ctor(&spr1);
|
||||
my_sprite_ctor(&spr2);
|
||||
my_sprite_ctor(&spr3);
|
||||
|
||||
int hero1 = editor_spawn("/hero1", "my_sprite", &spr1);
|
||||
int hero2 = editor_spawn("/hero2", "my_sprite", &spr2);
|
||||
int hero3 = editor_spawn("/hero1/heroB", "my_sprite", &spr3);
|
||||
|
||||
camera_t cam = camera();
|
||||
camera_enable(&cam);
|
||||
|
||||
while( window_swap() ) {
|
||||
editor_frame();
|
||||
|
|
|
@ -102,12 +102,12 @@ void editor_init() {
|
|||
map_init_ptr(editor_dicts);
|
||||
set_init_ptr(editor_world);
|
||||
set_init_ptr(editor_selection);
|
||||
profile_enable( false );
|
||||
profiler_enable( false );
|
||||
window_pause( true );
|
||||
}
|
||||
}
|
||||
|
||||
void editor_tick() {
|
||||
void editor_tick_() {
|
||||
// timing
|
||||
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() {
|
||||
do_once editor_init();
|
||||
|
||||
int alts = input(KEY_LALT) || input(KEY_RALT); // @todo: move to v4k.c
|
||||
int ctrls = input(KEY_LCTRL) || input(KEY_RCTRL); // @todo: move to v4k.c
|
||||
int shifts = input(KEY_LSHIFT) || input(KEY_RSHIFT); // @todo: move to v4k.c
|
||||
int mods = alts || ctrls || shifts; // @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 fwk.c
|
||||
int shifts = input(KEY_LSHIFT) || input(KEY_RSHIFT); // @todo: move to fwk.c
|
||||
int mods = alts || ctrls || shifts; // @todo: move to fwk.c
|
||||
if( input_down(KEY_F5) ) editor_key = key_reload;
|
||||
if( input_down(KEY_F11) ) editor_key = key_fullscreen;
|
||||
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_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_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_gamepad: editor_gamepad ^= 1;
|
||||
break; case key_lit: editor_lit ^= 1;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//#define META_DEMO
|
||||
|
||||
#include "v4k.h"
|
||||
#include "fwk.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#define V4K_C
|
||||
#include "v4k.h"
|
||||
#define FWK_C
|
||||
#include "fwk.h"
|
||||
|
||||
bool parse_struct(const char *line) {
|
||||
return strstr(line, "s""truct ");
|
||||
|
|
|
@ -21,9 +21,9 @@ cl ..\editor2.c -I ..\..\tools -DCOOK_ON_DEMAND
|
|||
pushd ..\.. && call make amalgamation && popd
|
||||
|
||||
taskkill /im "oscedit.exe" > nul 2> nul
|
||||
call ..\..\tools\tcc oscgame.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||
call ..\..\tools\tcc oscsend.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||
call ..\..\tools\tcc oscedit.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %* && start oscedit.exe
|
||||
call ..\..\tools\tcc oscgame.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||
call ..\..\tools\tcc oscsend.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||
call ..\..\tools\tcc oscedit.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %* && start oscedit.exe
|
||||
|
||||
timeout 3
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "v4k.h"
|
||||
#include "fwk.h"
|
||||
#include "oscedit.h"
|
||||
|
||||
// demo
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "v4k.h"
|
||||
#include "fwk.h"
|
||||
#include "oscedit.h"
|
||||
|
||||
// game
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "v4k.h"
|
||||
#include "fwk.h"
|
||||
|
||||
#define OSCPACK_C
|
||||
#define OSCRECV_C
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// networked gui demo
|
||||
// - rlyeh, public domain
|
||||
|
||||
#include "v4k.h"
|
||||
#include "fwk.h"
|
||||
|
||||
#define OSCPACK_C
|
||||
#define OSCRECV_C
|
||||
|
@ -46,7 +46,6 @@ int main() {
|
|||
|
||||
// camera
|
||||
camera_t cam = camera();
|
||||
cam.speed = 0.2f;
|
||||
|
||||
// demo loop
|
||||
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);
|
||||
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);
|
||||
camera_move(&cam, wasdecq.x,wasdecq.y,wasdecq.z);
|
||||
camera_moveby(&cam, wasdecq);
|
||||
camera_fps(&cam, mouse.x,mouse.y);
|
||||
|
||||
// queue model scale bounces
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "v4k.h"
|
||||
#include "fwk.h"
|
||||
#include "oscsend.h"
|
||||
#include "oscedit.h"
|
||||
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