main
Dominik Madarász 2023-10-27 09:42:40 +02:00
parent 7eeddad656
commit b8b1043aad
50 changed files with 19554 additions and 1995 deletions

View File

@ -2470,7 +2470,7 @@ enum { NETWORK_USERID = 7, NETWORK_COUNT , NETWORK_CAPACITY };
void server_send_bin(int64_t handle, const void *ptr, int len);
void server_drop(int64_t handle);
int64_t client_join(const char *ip, int port);
typedef struct obj { struct { union { uintptr_t objheader; struct { uintptr_t objtype:8; uintptr_t objsizew:8; uintptr_t objrefs:8; uintptr_t objheap:1; uintptr_t objcomps:1; uintptr_t objunused:64-8-8-8-1-1-16-3; uintptr_t objid:16+3; }; }; }; } obj;
typedef struct obj { struct { union { uintptr_t objheader; struct { uintptr_t objtype:8; uintptr_t objsizew:8; uintptr_t objrefs:8; uintptr_t objheap:1; uintptr_t objcomps:1; uintptr_t objunused:64-8-8-8-1-1-16-3; uintptr_t objid:16+3; }; }; ifdef(debug,const char *objname;) }; } obj;
typedef struct entity { struct { union { uintptr_t objheader; struct { uintptr_t objtype:8; uintptr_t objsizew:8; uintptr_t objrefs:8; uintptr_t objheap:1; uintptr_t objcomps:1; uintptr_t objunused:64-8-8-8-1-1-16-3; uintptr_t objid:16+3; }; }; union { struct { uintptr_t objenabled:32, objflagged:32; }; uintptr_t cflags; }; void *c[32]; }; } entity;
obj *objtmp;
void* obj_malloc(unsigned sz);

View File

@ -1,12 +1,7 @@
#include "v4k.h"
void handle_crash() {
alert("crash!");
}
int main() {
trap_install();
atexit(handle_crash);
app_crash();
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

Binary file not shown.

View File

@ -0,0 +1,31 @@
--------------------------------------------------------------------------------------
Files:
1. webcamBig.png
2. tex10.png
3. tex11.png
4. tex12.png
5. tex12_orig.png
6. tex14.png
7. tex15.png
8. tex16.png
Downloaded from Shadertoy.com by Inigo Quilez and Pol Jeremias (http://www.beautypi.com/)
Licensed under CC NC-SA 3.0 Unported License
http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_US
--------------------------------------------------------------------------------------
Files:
1. tex09.jpg
2. tex00.jpg
3. tex01.jpg
4. tex02.jpg
5. tex03.jpg
6. tex04.jpg
7. tex05.jpg
8. tex06.jpg
9. tex07.jpg
10. tex08.jpg
Downloaded from Shadertoy.com

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 415 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 402 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

View File

@ -14570,7 +14570,7 @@ static __thread unsigned array_n_;
array_pop(t); \
} while(0)
#define array_erase(t, i) do { \
#define array_erase_slow(t, i) do { /*preserves ordering*/ \
memmove( &(t)[i], &(t)[i + 1], sizeof(0[t])*(array_count(t) - i - 1)); \
array_pop(t); \
} while(0)
@ -16682,7 +16682,7 @@ API int64_t client_join(const char *ip, int port);
};
#define OBJ \
struct { OBJHEADER };
struct { OBJHEADER ifdef(debug,const char *objname;) };
// ----------------------------------------------------------------------------
// syntax sugars
@ -16834,10 +16834,10 @@ API void* obj_unref(void *oo);
// ----------------------------------------------------------------------------
// scene tree
#define each_objchild(p,t,o) /*non-recursive*/ \
#define each_objchild(p,T,o) /*non-recursive*/ \
(array(obj*)* children = obj_children(p); children; children = 0) \
for(int _i = 1, _end = array_count(*children); _i < _end; ++_i) \
for(t *o = (t *)((*children)[_i]); o && (obj_parent(o) == p); o = 0)
for(T o = (T)((*children)[_i]); o && (obj_parent(o) == p); o = 0)
API obj* obj_detach(void *c);
API obj* obj_attach(void *o, void *c);
@ -339804,7 +339804,6 @@ void font_face_from_mem(const char *tag, const void *ttf_bufferv, unsigned ttf_l
const char *vs = vs_filename ? file_read(vs_filename) : mv_vs_source;
const char *fs = fs_filename ? file_read(fs_filename) : mv_fs_source;
f->program = shader(vs, fs, "vertexPosition,instanceGlyph", "outColor", NULL);
ASSERT(f->program > 0);
// figure out what ranges we're about to bake
#define MERGE_TABLE(table) do { \
@ -345435,22 +345434,31 @@ char** shader_property(unsigned shader, unsigned property) {
void shader_apply_param(unsigned shader, unsigned param_no) {
unsigned num_properties = shader_properties(shader);
if( param_no < num_properties ) {
char *line = *shader_property(shader, param_no);
char *buf = *shader_property(shader, param_no);
char type[32], name[32];
char type[32], name[32], line[128]; snprintf(line, 127, "%s", buf);
if( sscanf(line, "%*s %s %[^ =;/]", type, name) != 2 ) return;
char *mins = strstr(line, "min:");
char *sets = strstr(line, "set:");
char *maxs = strstr(line, "max:");
char *tips = strstr(line, "tip:");
if( mins ) *mins = 0, mins += 4;
if( sets ) *sets = 0, sets += 4;
if( maxs ) *maxs = 0, maxs += 4;
if( tips ) *tips = 0, tips += 4;
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
vec4 minv = mins ? atof4(mins) : vec4(0,0,0,0);
vec4 setv = sets ? atof4(sets) : vec4(0,0,0,0);
vec4 maxv = maxs ? atof4(maxs) : vec4(top,top,top,top);
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
if( !strstr(line, "max:") ) {
if( !maxs ) {
if(setv.x > maxv.x) maxv.x = setv.x;
if(setv.y > maxv.y) maxv.y = setv.y;
if(setv.z > maxv.z) maxv.z = setv.z;
@ -345492,26 +345500,35 @@ int ui_shader(unsigned shader) {
for( unsigned i = 0; i < num_properties; ++i ) {
char **ptr = shader_property(shader,i);
const char *line = *ptr; // debug: ui_label(line);
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
char line[128]; snprintf(line, 127, "%s", *ptr); // debug: ui_label(line);
char uniform[32], type[32], name[32], early_exit = '\0';
if( sscanf(line, "%s %s %[^ =;/]", uniform, type, name) != 3 ) continue; // @todo optimize: move to shader()
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tip) ui_label(va(ICON_MD_INFO "%s", tip)); continue; } // @todo optimize: move to shader()
char *mins = strstr(line, "min:");
char *sets = strstr(line, "set:");
char *maxs = strstr(line, "max:");
char *tips = strstr(line, "tip:");
if( mins ) *mins = 0, mins += 4;
if( sets ) *sets = 0, sets += 4;
if( maxs ) *maxs = 0, maxs += 4;
if( tips ) *tips = 0, tips += 4;
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tips) ui_label(va(ICON_MD_INFO "%s", tips)); continue; } // @todo optimize: move to shader()
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
char *label = !tip ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
vec4 minv = mins ? atof4(mins) : vec4(0,0,0,0);
vec4 setv = sets ? atof4(sets) : vec4(0,0,0,0);
vec4 maxv = maxs ? atof4(maxs) : vec4(top,top,top,top);
char *label = !tips ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tips);
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x); // @optimize: move to shader()
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y); // @optimize: move to shader()
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z); // @optimize: move to shader()
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w); // @optimize: move to shader()
if( !strstr(line, "max:") ) {
if( !maxs ) {
if(setv.x > maxv.x) maxv.x = setv.x;
if(setv.y > maxv.y) maxv.y = setv.y;
if(setv.z > maxv.z) maxv.z = setv.z;
@ -345538,7 +345555,7 @@ int ui_shader(unsigned shader) {
}
else if( type[0] == 'f' ) {
setv.x = clampf(setv.x, minv.x, maxv.x);
char *caption = va("%5.2f", setv.x);
char *caption = va("%5.3f", setv.x);
setv.x = (setv.x - minv.x) / (maxv.x - minv.x);
if( (touched = ui_slider2(label, &setv.x, caption)) != 0 ) {
@ -345566,12 +345583,12 @@ int ui_shader(unsigned shader) {
setv = clamp4(setv,minv,maxv);
}
}
else if( tip ) ui_label( tip );
else if( tips ) ui_label( tips );
if( touched ) {
// upgrade value
*ptr = FREE(*ptr);
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tip?tip:"");
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tips?tips:"");
// apply
shader_apply_param(shader, i);
@ -352095,22 +352112,31 @@ const char *trap_name(int signal) {
ifndef(win32, if(signal == SIGQUIT) return "SIGQUIT");
return "??";
}
void trap_on_ignore(int signal_) {
signal(signal_, trap_on_ignore);
void trap_on_ignore(int sgn) {
signal(sgn, trap_on_ignore);
}
void trap_on_quit(int signal) {
// fprintf(stderr, "Ok: caught signal %s (%d)\n", trap_name(signal), signal);
void trap_on_quit(int sgn) {
signal(sgn, trap_on_quit);
exit(0);
}
void trap_on_abort(int signal) {
fprintf(stderr, "Error: unexpected signal %s (%d)\n%s\n", trap_name(signal), signal, callstack(16));
exit(-1);
void trap_on_abort(int sgn) {
char *cs = va("Error: unexpected signal %s (%d)\n%s", trap_name(sgn), sgn, callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
signal(sgn, trap_on_abort);
exit(-sgn);
}
void trap_on_debug(int signal) {
alert("Error: unexpected signal"), breakpoint();
fprintf(stderr, "Error: unexpected signal %s (%d)\n%s\n", trap_name(signal), signal, callstack(16));
exit(-1);
void trap_on_debug(int sgn) { // @todo: rename to trap_on_choice() and ask the developer what to do next? abort, continue, debug
char *cs = va("Error: unexpected signal %s (%d)\n%s", trap_name(sgn), sgn, callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
signal(sgn, trap_on_debug);
}
#if is(win32)
LONG WINAPI trap_on_SEH(PEXCEPTION_POINTERS pExceptionPtrs) {
char *cs = va("Error: unexpected SEH exception\n%s", callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
return EXCEPTION_EXECUTE_HANDLER; // Execute default exception handler next
}
#endif
void trap_install(void) {
// expected signals
signal(SIGINT, trap_on_quit);
@ -352123,6 +352149,8 @@ void trap_install(void) {
signal(SIGSEGV, trap_on_abort);
ifndef(win32, signal(SIGBUS, trap_on_abort));
ifdef(linux, signal(SIGSTKFLT, trap_on_abort));
// others
ifdef(win32,SetUnhandledExceptionFilter(trap_on_SEH));
}
#ifdef TRAP_DEMO
@ -356422,7 +356450,7 @@ int window_frame_begin() {
// @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") {
EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%dfps", window_fps(), (int)window_fps_target()), "Debug.Profiler") {
ui_profiler();
}
EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") {
@ -357029,6 +357057,7 @@ void *obj_malloc(unsigned sz) {
}
void *obj_free(void *o) {
if( !((obj*)o)->objrefs ) {
obj_detach(o);
obj_dtor(o);
//obj_zero(o);
if( ((obj*)o)->objheap ) {
@ -357188,6 +357217,7 @@ obj* obj_detach(void *c) {
{
if( obj_id(v) == id ) {
obj_reparent(c, 0);
array_erase_slow(*oo, i);
return c;
}
}
@ -357208,7 +357238,7 @@ obj* obj_attach(void *o, void *c) {
int obj_dumptree(const void *o) {
static int tabs = 0;
printf("%*s" "+- %s\n", tabs++, "", obj_name(o));
for each_objchild(o, obj, v) {
for each_objchild(o, obj*, v) {
obj_dumptree(v);
}
--tabs;
@ -357261,19 +357291,19 @@ void test_obj_scene() {
test( obj_root(gc2) == r );
test( obj_root(gc3) == r );
for each_objchild(r, obj, o) test( o == c1 || o == c2 );
for each_objchild(c1, obj, o) test( o == gc1 );
for each_objchild(c2, obj, o) test( o == gc2 || o == gc3 );
for each_objchild(r, obj*, o) test( o == c1 || o == c2 );
for each_objchild(c1, obj*, o) test( o == gc1 );
for each_objchild(c2, obj*, o) test( o == gc2 || o == gc3 );
obj_detach(c1);
test( !obj_parent(c1) );
for each_objchild(r, obj, o) test( o != c1 );
for each_objchild(c1, obj, o) test( o == gc1 );
for each_objchild(r, obj*, o) test( o != c1 );
for each_objchild(c1, obj*, o) test( o == gc1 );
obj_detach(c2);
test( !obj_parent(c2) );
for each_objchild(r, obj, o) test( o != c2 );
for each_objchild(c2, obj, o) test( o == gc2 || o == gc3 );
for each_objchild(r, obj*, o) test( o != c2 );
for each_objchild(c2, obj*, o) test( o == gc2 || o == gc3 );
}
// ----------------------------------------------------------------------------
@ -357300,6 +357330,7 @@ const char* obj_meta(const void *o, const char *key) {
}
void *obj_setname(void *o, const char *name) {
ifdef(debug,((obj*)o)->objname = name);
return obj_setmeta(o, "name", name);
}
const char *obj_name(const void *o) {
@ -357808,7 +357839,7 @@ void *obj_make(const char *str) {
unsigned Tid = intern(name);
reflect_init();
reflect_t *found = map_find(reflects, Tid);
if(!found) return 0;
if(!found) return obj_new(obj);
obj *ptr = CALLOC(1, found->sz + (has_components+1) * sizeof(array(obj*)));
void *ret = (T == I ? obj_mergeini : obj_mergejson)(ptr, str);
@ -359207,7 +359238,9 @@ void v4k_init() {
atexit(v4k_quit);
}
}
#line 0
#line 1 "engine/split/v4k_end.c"
// Enable more performant GPUs on laptops. Does this work into a dll?
// int NvOptimusEnablement = 1;
// int AmdPowerXpressRequestHighPerformance = 1;

View File

@ -184,3 +184,5 @@ API void *ui_handle();
// editor is last in place, so it can use all internals from above headers
{{FILE:v4k_main.c}}
{{FILE:v4k_end.c}}

View File

@ -126,7 +126,7 @@ static __thread unsigned array_n_;
array_pop(t); \
} while(0)
#define array_erase(t, i) do { \
#define array_erase_slow(t, i) do { /*preserves ordering*/ \
memmove( &(t)[i], &(t)[i + 1], sizeof(0[t])*(array_count(t) - i - 1)); \
array_pop(t); \
} while(0)

View File

@ -0,0 +1,36 @@
// Enable more performant GPUs on laptops. Does this work into a dll?
// int NvOptimusEnablement = 1;
// int AmdPowerXpressRequestHighPerformance = 1;
#if is(linux) && is(tcc) // fixes `tcc: error: undefined symbol '__dso_handle'`
int __dso_handle; // compiled with: `tcc demo.c v4k.c -D__STDC_NO_VLA__ -lX11`
#endif
#if is(win32) && is(tcc) // fixes `tcc: error: undefined symbol '_InterlockedExchangeAdd'` when compiling with `-m64` flag
__CRT_INLINE LONG _InterlockedExchangeAdd(LONG volatile *add, LONG val) {
LONG old;
do old = *add; while( InterlockedCompareExchange(add, old + val, old) != old );
return old;
}
__CRT_INLINE LONGLONG _InterlockedExchangeAdd64(LONGLONG volatile *add, LONGLONG val) { // 64bit version, for completeness
LONGLONG old;
do old = *add; while( InterlockedCompareExchange64(add, old + val, old) != old );
return old;
}
#endif
#ifdef ZIG_CC
static int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *a) { return ((a->s6_words[0]==0) && (a->s6_words[1]==0) && (a->s6_words[2]==0) && (a->s6_words[3]==0) && (a->s6_words[4]==0) && (a->s6_words[5]==0xffff)); }
const struct in6_addr in6addr_any; // = IN6ADDR_ANY_INIT;
//static const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
#endif
ifdef(retail, AUTORUN {
fclose(stderr);
fclose(stdout);
const char* null_stream = ifdef(win32, "nul:", "/dev/null");
if (!freopen(null_stream, "a", stdout)) PANIC("cannot recreate standard streams");
if (!freopen(null_stream, "a", stderr)) PANIC("cannot recreate standard streams");
} )

View File

@ -1695,7 +1695,6 @@ void font_face_from_mem(const char *tag, const void *ttf_bufferv, unsigned ttf_l
const char *vs = vs_filename ? file_read(vs_filename) : mv_vs_source;
const char *fs = fs_filename ? file_read(fs_filename) : mv_fs_source;
f->program = shader(vs, fs, "vertexPosition,instanceGlyph", "outColor", NULL);
ASSERT(f->program > 0);
// figure out what ranges we're about to bake
#define MERGE_TABLE(table) do { \

View File

@ -88,40 +88,3 @@ void v4k_init() {
atexit(v4k_quit);
}
}
// Enable more performant GPUs on laptops. Does this work into a dll?
// int NvOptimusEnablement = 1;
// int AmdPowerXpressRequestHighPerformance = 1;
#if is(linux) && is(tcc) // fixes `tcc: error: undefined symbol '__dso_handle'`
int __dso_handle; // compiled with: `tcc demo.c v4k.c -D__STDC_NO_VLA__ -lX11`
#endif
#if is(win32) && is(tcc) // fixes `tcc: error: undefined symbol '_InterlockedExchangeAdd'` when compiling with `-m64` flag
__CRT_INLINE LONG _InterlockedExchangeAdd(LONG volatile *add, LONG val) {
LONG old;
do old = *add; while( InterlockedCompareExchange(add, old + val, old) != old );
return old;
}
__CRT_INLINE LONGLONG _InterlockedExchangeAdd64(LONGLONG volatile *add, LONGLONG val) { // 64bit version, for completeness
LONGLONG old;
do old = *add; while( InterlockedCompareExchange64(add, old + val, old) != old );
return old;
}
#endif
#ifdef ZIG_CC
static int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *a) { return ((a->s6_words[0]==0) && (a->s6_words[1]==0) && (a->s6_words[2]==0) && (a->s6_words[3]==0) && (a->s6_words[4]==0) && (a->s6_words[5]==0xffff)); }
const struct in6_addr in6addr_any; // = IN6ADDR_ANY_INIT;
//static const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
#endif
ifdef(retail, AUTORUN {
fclose(stderr);
fclose(stdout);
const char* null_stream = ifdef(win32, "nul:", "/dev/null");
if (!freopen(null_stream, "a", stdout)) PANIC("cannot recreate standard streams");
if (!freopen(null_stream, "a", stderr)) PANIC("cannot recreate standard streams");
} )

View File

@ -33,6 +33,7 @@ void *obj_malloc(unsigned sz) {
}
void *obj_free(void *o) {
if( !((obj*)o)->objrefs ) {
obj_detach(o);
obj_dtor(o);
//obj_zero(o);
if( ((obj*)o)->objheap ) {
@ -192,6 +193,7 @@ obj* obj_detach(void *c) {
{
if( obj_id(v) == id ) {
obj_reparent(c, 0);
array_erase_slow(*oo, i);
return c;
}
}
@ -212,7 +214,7 @@ obj* obj_attach(void *o, void *c) {
int obj_dumptree(const void *o) {
static int tabs = 0;
printf("%*s" "+- %s\n", tabs++, "", obj_name(o));
for each_objchild(o, obj, v) {
for each_objchild(o, obj*, v) {
obj_dumptree(v);
}
--tabs;
@ -265,19 +267,19 @@ void test_obj_scene() {
test( obj_root(gc2) == r );
test( obj_root(gc3) == r );
for each_objchild(r, obj, o) test( o == c1 || o == c2 );
for each_objchild(c1, obj, o) test( o == gc1 );
for each_objchild(c2, obj, o) test( o == gc2 || o == gc3 );
for each_objchild(r, obj*, o) test( o == c1 || o == c2 );
for each_objchild(c1, obj*, o) test( o == gc1 );
for each_objchild(c2, obj*, o) test( o == gc2 || o == gc3 );
obj_detach(c1);
test( !obj_parent(c1) );
for each_objchild(r, obj, o) test( o != c1 );
for each_objchild(c1, obj, o) test( o == gc1 );
for each_objchild(r, obj*, o) test( o != c1 );
for each_objchild(c1, obj*, o) test( o == gc1 );
obj_detach(c2);
test( !obj_parent(c2) );
for each_objchild(r, obj, o) test( o != c2 );
for each_objchild(c2, obj, o) test( o == gc2 || o == gc3 );
for each_objchild(r, obj*, o) test( o != c2 );
for each_objchild(c2, obj*, o) test( o == gc2 || o == gc3 );
}
// ----------------------------------------------------------------------------
@ -304,6 +306,7 @@ const char* obj_meta(const void *o, const char *key) {
}
void *obj_setname(void *o, const char *name) {
ifdef(debug,((obj*)o)->objname = name);
return obj_setmeta(o, "name", name);
}
const char *obj_name(const void *o) {
@ -812,7 +815,7 @@ void *obj_make(const char *str) {
unsigned Tid = intern(name);
reflect_init();
reflect_t *found = map_find(reflects, Tid);
if(!found) return 0;
if(!found) return obj_new(obj);
obj *ptr = CALLOC(1, found->sz + (has_components+1) * sizeof(array(obj*)));
void *ret = (T == I ? obj_mergeini : obj_mergejson)(ptr, str);

View File

@ -34,7 +34,7 @@
};
#define OBJ \
struct { OBJHEADER };
struct { OBJHEADER ifdef(debug,const char *objname;) };
// ----------------------------------------------------------------------------
// syntax sugars
@ -186,10 +186,10 @@ API void* obj_unref(void *oo);
// ----------------------------------------------------------------------------
// scene tree
#define each_objchild(p,t,o) /*non-recursive*/ \
#define each_objchild(p,T,o) /*non-recursive*/ \
(array(obj*)* children = obj_children(p); children; children = 0) \
for(int _i = 1, _end = array_count(*children); _i < _end; ++_i) \
for(t *o = (t *)((*children)[_i]); o && (obj_parent(o) == p); o = 0)
for(T o = (T)((*children)[_i]); o && (obj_parent(o) == p); o = 0)
API obj* obj_detach(void *c);
API obj* obj_attach(void *o, void *c);

View File

@ -230,22 +230,31 @@ char** shader_property(unsigned shader, unsigned property) {
void shader_apply_param(unsigned shader, unsigned param_no) {
unsigned num_properties = shader_properties(shader);
if( param_no < num_properties ) {
char *line = *shader_property(shader, param_no);
char *buf = *shader_property(shader, param_no);
char type[32], name[32];
char type[32], name[32], line[128]; snprintf(line, 127, "%s", buf);
if( sscanf(line, "%*s %s %[^ =;/]", type, name) != 2 ) return;
char *mins = strstr(line, "min:");
char *sets = strstr(line, "set:");
char *maxs = strstr(line, "max:");
char *tips = strstr(line, "tip:");
if( mins ) *mins = 0, mins += 4;
if( sets ) *sets = 0, sets += 4;
if( maxs ) *maxs = 0, maxs += 4;
if( tips ) *tips = 0, tips += 4;
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
vec4 minv = mins ? atof4(mins) : vec4(0,0,0,0);
vec4 setv = sets ? atof4(sets) : vec4(0,0,0,0);
vec4 maxv = maxs ? atof4(maxs) : vec4(top,top,top,top);
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
if( !strstr(line, "max:") ) {
if( !maxs ) {
if(setv.x > maxv.x) maxv.x = setv.x;
if(setv.y > maxv.y) maxv.y = setv.y;
if(setv.z > maxv.z) maxv.z = setv.z;
@ -287,26 +296,35 @@ int ui_shader(unsigned shader) {
for( unsigned i = 0; i < num_properties; ++i ) {
char **ptr = shader_property(shader,i);
const char *line = *ptr; // debug: ui_label(line);
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
char line[128]; snprintf(line, 127, "%s", *ptr); // debug: ui_label(line);
char uniform[32], type[32], name[32], early_exit = '\0';
if( sscanf(line, "%s %s %[^ =;/]", uniform, type, name) != 3 ) continue; // @todo optimize: move to shader()
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tip) ui_label(va(ICON_MD_INFO "%s", tip)); continue; } // @todo optimize: move to shader()
char *mins = strstr(line, "min:");
char *sets = strstr(line, "set:");
char *maxs = strstr(line, "max:");
char *tips = strstr(line, "tip:");
if( mins ) *mins = 0, mins += 4;
if( sets ) *sets = 0, sets += 4;
if( maxs ) *maxs = 0, maxs += 4;
if( tips ) *tips = 0, tips += 4;
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tips) ui_label(va(ICON_MD_INFO "%s", tips)); continue; } // @todo optimize: move to shader()
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
char *label = !tip ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
vec4 minv = mins ? atof4(mins) : vec4(0,0,0,0);
vec4 setv = sets ? atof4(sets) : vec4(0,0,0,0);
vec4 maxv = maxs ? atof4(maxs) : vec4(top,top,top,top);
char *label = !tips ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tips);
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x); // @optimize: move to shader()
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y); // @optimize: move to shader()
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z); // @optimize: move to shader()
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w); // @optimize: move to shader()
if( !strstr(line, "max:") ) {
if( !maxs ) {
if(setv.x > maxv.x) maxv.x = setv.x;
if(setv.y > maxv.y) maxv.y = setv.y;
if(setv.z > maxv.z) maxv.z = setv.z;
@ -333,7 +351,7 @@ int ui_shader(unsigned shader) {
}
else if( type[0] == 'f' ) {
setv.x = clampf(setv.x, minv.x, maxv.x);
char *caption = va("%5.2f", setv.x);
char *caption = va("%5.3f", setv.x);
setv.x = (setv.x - minv.x) / (maxv.x - minv.x);
if( (touched = ui_slider2(label, &setv.x, caption)) != 0 ) {
@ -361,12 +379,12 @@ int ui_shader(unsigned shader) {
setv = clamp4(setv,minv,maxv);
}
}
else if( tip ) ui_label( tip );
else if( tips ) ui_label( tips );
if( touched ) {
// upgrade value
*ptr = FREE(*ptr);
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tip?tip:"");
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tips?tips:"");
// apply
shader_apply_param(shader, i);

View File

@ -267,22 +267,31 @@ const char *trap_name(int signal) {
ifndef(win32, if(signal == SIGQUIT) return "SIGQUIT");
return "??";
}
void trap_on_ignore(int signal_) {
signal(signal_, trap_on_ignore);
void trap_on_ignore(int sgn) {
signal(sgn, trap_on_ignore);
}
void trap_on_quit(int signal) {
// fprintf(stderr, "Ok: caught signal %s (%d)\n", trap_name(signal), signal);
void trap_on_quit(int sgn) {
signal(sgn, trap_on_quit);
exit(0);
}
void trap_on_abort(int signal) {
fprintf(stderr, "Error: unexpected signal %s (%d)\n%s\n", trap_name(signal), signal, callstack(16));
exit(-1);
void trap_on_abort(int sgn) {
char *cs = va("Error: unexpected signal %s (%d)\n%s", trap_name(sgn), sgn, callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
signal(sgn, trap_on_abort);
exit(-sgn);
}
void trap_on_debug(int signal) {
alert("Error: unexpected signal"), breakpoint();
fprintf(stderr, "Error: unexpected signal %s (%d)\n%s\n", trap_name(signal), signal, callstack(16));
exit(-1);
void trap_on_debug(int sgn) { // @todo: rename to trap_on_choice() and ask the developer what to do next? abort, continue, debug
char *cs = va("Error: unexpected signal %s (%d)\n%s", trap_name(sgn), sgn, callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
signal(sgn, trap_on_debug);
}
#if is(win32)
LONG WINAPI trap_on_SEH(PEXCEPTION_POINTERS pExceptionPtrs) {
char *cs = va("Error: unexpected SEH exception\n%s", callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
return EXCEPTION_EXECUTE_HANDLER; // Execute default exception handler next
}
#endif
void trap_install(void) {
// expected signals
signal(SIGINT, trap_on_quit);
@ -295,6 +304,8 @@ void trap_install(void) {
signal(SIGSEGV, trap_on_abort);
ifndef(win32, signal(SIGBUS, trap_on_abort));
ifdef(linux, signal(SIGSTKFLT, trap_on_abort));
// others
ifdef(win32,SetUnhandledExceptionFilter(trap_on_SEH));
}
#ifdef TRAP_DEMO

View File

@ -715,7 +715,7 @@ int window_frame_begin() {
// @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") {
EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%dfps", window_fps(), (int)window_fps_target()), "Debug.Profiler") {
ui_profiler();
}
EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") {

View File

@ -7828,7 +7828,6 @@ void font_face_from_mem(const char *tag, const void *ttf_bufferv, unsigned ttf_l
const char *vs = vs_filename ? file_read(vs_filename) : mv_vs_source;
const char *fs = fs_filename ? file_read(fs_filename) : mv_fs_source;
f->program = shader(vs, fs, "vertexPosition,instanceGlyph", "outColor", NULL);
ASSERT(f->program > 0);
// figure out what ranges we're about to bake
#define MERGE_TABLE(table) do { \
@ -13459,22 +13458,31 @@ char** shader_property(unsigned shader, unsigned property) {
void shader_apply_param(unsigned shader, unsigned param_no) {
unsigned num_properties = shader_properties(shader);
if( param_no < num_properties ) {
char *line = *shader_property(shader, param_no);
char *buf = *shader_property(shader, param_no);
char type[32], name[32];
char type[32], name[32], line[128]; snprintf(line, 127, "%s", buf);
if( sscanf(line, "%*s %s %[^ =;/]", type, name) != 2 ) return;
char *mins = strstr(line, "min:");
char *sets = strstr(line, "set:");
char *maxs = strstr(line, "max:");
char *tips = strstr(line, "tip:");
if( mins ) *mins = 0, mins += 4;
if( sets ) *sets = 0, sets += 4;
if( maxs ) *maxs = 0, maxs += 4;
if( tips ) *tips = 0, tips += 4;
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
vec4 minv = mins ? atof4(mins) : vec4(0,0,0,0);
vec4 setv = sets ? atof4(sets) : vec4(0,0,0,0);
vec4 maxv = maxs ? atof4(maxs) : vec4(top,top,top,top);
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
if( !strstr(line, "max:") ) {
if( !maxs ) {
if(setv.x > maxv.x) maxv.x = setv.x;
if(setv.y > maxv.y) maxv.y = setv.y;
if(setv.z > maxv.z) maxv.z = setv.z;
@ -13516,26 +13524,35 @@ int ui_shader(unsigned shader) {
for( unsigned i = 0; i < num_properties; ++i ) {
char **ptr = shader_property(shader,i);
const char *line = *ptr; // debug: ui_label(line);
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
char line[128]; snprintf(line, 127, "%s", *ptr); // debug: ui_label(line);
char uniform[32], type[32], name[32], early_exit = '\0';
if( sscanf(line, "%s %s %[^ =;/]", uniform, type, name) != 3 ) continue; // @todo optimize: move to shader()
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tip) ui_label(va(ICON_MD_INFO "%s", tip)); continue; } // @todo optimize: move to shader()
char *mins = strstr(line, "min:");
char *sets = strstr(line, "set:");
char *maxs = strstr(line, "max:");
char *tips = strstr(line, "tip:");
if( mins ) *mins = 0, mins += 4;
if( sets ) *sets = 0, sets += 4;
if( maxs ) *maxs = 0, maxs += 4;
if( tips ) *tips = 0, tips += 4;
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tips) ui_label(va(ICON_MD_INFO "%s", tips)); continue; } // @todo optimize: move to shader()
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
char *label = !tip ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
vec4 minv = mins ? atof4(mins) : vec4(0,0,0,0);
vec4 setv = sets ? atof4(sets) : vec4(0,0,0,0);
vec4 maxv = maxs ? atof4(maxs) : vec4(top,top,top,top);
char *label = !tips ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tips);
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x); // @optimize: move to shader()
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y); // @optimize: move to shader()
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z); // @optimize: move to shader()
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w); // @optimize: move to shader()
if( !strstr(line, "max:") ) {
if( !maxs ) {
if(setv.x > maxv.x) maxv.x = setv.x;
if(setv.y > maxv.y) maxv.y = setv.y;
if(setv.z > maxv.z) maxv.z = setv.z;
@ -13562,7 +13579,7 @@ int ui_shader(unsigned shader) {
}
else if( type[0] == 'f' ) {
setv.x = clampf(setv.x, minv.x, maxv.x);
char *caption = va("%5.2f", setv.x);
char *caption = va("%5.3f", setv.x);
setv.x = (setv.x - minv.x) / (maxv.x - minv.x);
if( (touched = ui_slider2(label, &setv.x, caption)) != 0 ) {
@ -13590,12 +13607,12 @@ int ui_shader(unsigned shader) {
setv = clamp4(setv,minv,maxv);
}
}
else if( tip ) ui_label( tip );
else if( tips ) ui_label( tips );
if( touched ) {
// upgrade value
*ptr = FREE(*ptr);
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tip?tip:"");
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tips?tips:"");
// apply
shader_apply_param(shader, i);
@ -20119,22 +20136,31 @@ const char *trap_name(int signal) {
ifndef(win32, if(signal == SIGQUIT) return "SIGQUIT");
return "??";
}
void trap_on_ignore(int signal_) {
signal(signal_, trap_on_ignore);
void trap_on_ignore(int sgn) {
signal(sgn, trap_on_ignore);
}
void trap_on_quit(int signal) {
// fprintf(stderr, "Ok: caught signal %s (%d)\n", trap_name(signal), signal);
void trap_on_quit(int sgn) {
signal(sgn, trap_on_quit);
exit(0);
}
void trap_on_abort(int signal) {
fprintf(stderr, "Error: unexpected signal %s (%d)\n%s\n", trap_name(signal), signal, callstack(16));
exit(-1);
void trap_on_abort(int sgn) {
char *cs = va("Error: unexpected signal %s (%d)\n%s", trap_name(sgn), sgn, callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
signal(sgn, trap_on_abort);
exit(-sgn);
}
void trap_on_debug(int signal) {
alert("Error: unexpected signal"), breakpoint();
fprintf(stderr, "Error: unexpected signal %s (%d)\n%s\n", trap_name(signal), signal, callstack(16));
exit(-1);
void trap_on_debug(int sgn) { // @todo: rename to trap_on_choice() and ask the developer what to do next? abort, continue, debug
char *cs = va("Error: unexpected signal %s (%d)\n%s", trap_name(sgn), sgn, callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
signal(sgn, trap_on_debug);
}
#if is(win32)
LONG WINAPI trap_on_SEH(PEXCEPTION_POINTERS pExceptionPtrs) {
char *cs = va("Error: unexpected SEH exception\n%s", callstack(+16));
fprintf(stderr, "%s\n", cs), alert(cs), breakpoint();
return EXCEPTION_EXECUTE_HANDLER; // Execute default exception handler next
}
#endif
void trap_install(void) {
// expected signals
signal(SIGINT, trap_on_quit);
@ -20147,6 +20173,8 @@ void trap_install(void) {
signal(SIGSEGV, trap_on_abort);
ifndef(win32, signal(SIGBUS, trap_on_abort));
ifdef(linux, signal(SIGSTKFLT, trap_on_abort));
// others
ifdef(win32,SetUnhandledExceptionFilter(trap_on_SEH));
}
#ifdef TRAP_DEMO
@ -24446,7 +24474,7 @@ int window_frame_begin() {
// @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") {
EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%dfps", window_fps(), (int)window_fps_target()), "Debug.Profiler") {
ui_profiler();
}
EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") {
@ -25053,6 +25081,7 @@ void *obj_malloc(unsigned sz) {
}
void *obj_free(void *o) {
if( !((obj*)o)->objrefs ) {
obj_detach(o);
obj_dtor(o);
//obj_zero(o);
if( ((obj*)o)->objheap ) {
@ -25212,6 +25241,7 @@ obj* obj_detach(void *c) {
{
if( obj_id(v) == id ) {
obj_reparent(c, 0);
array_erase_slow(*oo, i);
return c;
}
}
@ -25232,7 +25262,7 @@ obj* obj_attach(void *o, void *c) {
int obj_dumptree(const void *o) {
static int tabs = 0;
printf("%*s" "+- %s\n", tabs++, "", obj_name(o));
for each_objchild(o, obj, v) {
for each_objchild(o, obj*, v) {
obj_dumptree(v);
}
--tabs;
@ -25285,19 +25315,19 @@ void test_obj_scene() {
test( obj_root(gc2) == r );
test( obj_root(gc3) == r );
for each_objchild(r, obj, o) test( o == c1 || o == c2 );
for each_objchild(c1, obj, o) test( o == gc1 );
for each_objchild(c2, obj, o) test( o == gc2 || o == gc3 );
for each_objchild(r, obj*, o) test( o == c1 || o == c2 );
for each_objchild(c1, obj*, o) test( o == gc1 );
for each_objchild(c2, obj*, o) test( o == gc2 || o == gc3 );
obj_detach(c1);
test( !obj_parent(c1) );
for each_objchild(r, obj, o) test( o != c1 );
for each_objchild(c1, obj, o) test( o == gc1 );
for each_objchild(r, obj*, o) test( o != c1 );
for each_objchild(c1, obj*, o) test( o == gc1 );
obj_detach(c2);
test( !obj_parent(c2) );
for each_objchild(r, obj, o) test( o != c2 );
for each_objchild(c2, obj, o) test( o == gc2 || o == gc3 );
for each_objchild(r, obj*, o) test( o != c2 );
for each_objchild(c2, obj*, o) test( o == gc2 || o == gc3 );
}
// ----------------------------------------------------------------------------
@ -25324,6 +25354,7 @@ const char* obj_meta(const void *o, const char *key) {
}
void *obj_setname(void *o, const char *name) {
ifdef(debug,((obj*)o)->objname = name);
return obj_setmeta(o, "name", name);
}
const char *obj_name(const void *o) {
@ -25832,7 +25863,7 @@ void *obj_make(const char *str) {
unsigned Tid = intern(name);
reflect_init();
reflect_t *found = map_find(reflects, Tid);
if(!found) return 0;
if(!found) return obj_new(obj);
obj *ptr = CALLOC(1, found->sz + (has_components+1) * sizeof(array(obj*)));
void *ret = (T == I ? obj_mergeini : obj_mergejson)(ptr, str);
@ -27231,7 +27262,9 @@ void v4k_init() {
atexit(v4k_quit);
}
}
#line 0
#line 1 "engine/split/v4k_end.c"
// Enable more performant GPUs on laptops. Does this work into a dll?
// int NvOptimusEnablement = 1;
// int AmdPowerXpressRequestHighPerformance = 1;

View File

@ -637,7 +637,7 @@ static __thread unsigned array_n_;
array_pop(t); \
} while(0)
#define array_erase(t, i) do { \
#define array_erase_slow(t, i) do { /*preserves ordering*/ \
memmove( &(t)[i], &(t)[i + 1], sizeof(0[t])*(array_count(t) - i - 1)); \
array_pop(t); \
} while(0)
@ -2749,7 +2749,7 @@ API int64_t client_join(const char *ip, int port);
};
#define OBJ \
struct { OBJHEADER };
struct { OBJHEADER ifdef(debug,const char *objname;) };
// ----------------------------------------------------------------------------
// syntax sugars
@ -2901,10 +2901,10 @@ API void* obj_unref(void *oo);
// ----------------------------------------------------------------------------
// scene tree
#define each_objchild(p,t,o) /*non-recursive*/ \
#define each_objchild(p,T,o) /*non-recursive*/ \
(array(obj*)* children = obj_children(p); children; children = 0) \
for(int _i = 1, _end = array_count(*children); _i < _end; ++_i) \
for(t *o = (t *)((*children)[_i]); o && (obj_parent(o) == p); o = 0)
for(T o = (T)((*children)[_i]); o && (obj_parent(o) == p); o = 0)
API obj* obj_detach(void *c);
API obj* obj_attach(void *o, void *c);

View File

@ -7,7 +7,7 @@
; syntax: symbols are defined in KEY=value form, as seen below.
TOOLS=./ ; folder where our pipeline tools are located
ART=../demos/art/,../engine/art/ ; comma-separated folder(s) that store all our asset files
ART=../demos/art/,../engine/art/,../tools/editor/art/ ; comma-separated folder(s) that store all our asset files
; lines starting with @windows, @linux or @osx will be processed only where OS matches.
; we are defining here some symbols differently for each platform.

View File

@ -1,501 +0,0 @@
/* A mathematical expression evaluator.
* It uses a recursive descent parser internally.
* Author: Werner Stoop
* This is free and unencumbered software released into the public domain.
* http://unlicense.org/
*/
#include <assert.h>
#include <ctype.h>
#include <math.h> /* remember to compile with -lm */
#include <setjmp.h>
#include <stdlib.h>
#include <string.h>
/* Special tokens used by the lexer function lex()
* they've been chosen as non-printable characters
* so that printable characters can be used for other
* purposes
*/
#define TOK_END 0 /* end of text */
#define TOK_INI 1 /* Initial state */
#define TOK_ID 2 /* identifier */
#define TOK_NUM 3 /* number */
/* Types of errors */
// 0 /* "no error" */
#define ERR_MEMORY 1 /* "out of memory" */
#define ERR_LEXER 2 /* "unknown token" */
#define ERR_LONGID 3 /* "identifier too long" */
#define ERR_VALUE 4 /* "value expected" */
#define ERR_BRACKET 5 /* "missing ')'" */
#define ERR_FUNC 6 /* "unknown function" */
#define ERR_ARGS 7 /* "wrong number of arguments" */
#define ERR_CONST 8 /* "unknown constant" */
/* Other definitions */
#define MAX_ID_LEN 11 /* Max length of an identifier */
#define OPERATORS "+-*/%(),^" /* Valid operators */
#define EVAL_PI 3.141592654
#define EVAL_E 2.718281828
#define EVAL_DEG (EVAL_PI/180)
/* Internal structure for the parser/evaluator */
struct eval {
jmp_buf j; /* For error handling */
const char *p; /* Position in the text being parsed */
double *st; /* Stack */
int st_size; /* Stack size */
int sp; /* Stack pointer */
/* The current and next tokens identified by the lexer */
struct {
int type; /* Type of the token */
double n_val; /* Numeric value of the previous lexed token */
char s_val[MAX_ID_LEN]; /* String (identifier) value of the previous lexed token */
} token[2];
int cur_tok; /* Current token, either 0 or 1 (see the comments of lex()) */
};
/* Prototypes */
static double pop(struct eval *ev);
static void push(struct eval *ev, double d);
static int lex(struct eval *ev);
/* Prototypes for the recursive descent parser */
static void expr(struct eval *ev);
static void add_expr(struct eval *ev);
static void mul_expr(struct eval *ev);
static void pow_expr(struct eval *ev);
static void uni_expr(struct eval *ev);
static void bra_expr(struct eval *ev);
static void id_expr(struct eval *ev);
static void num_expr(struct eval *ev);
/*
* Evaluates a mathemeatical expression
*/
double eval(const char *exp/*, int *ep*/) {
int _ep, *ep = &_ep;
struct eval ev;
double ans = 0.0;
assert(ep != NULL);
/* Allocate a stack */
ev.st_size = 10;
ev.st = CALLOC(ev.st_size, sizeof *ev.st);
if(!ev.st)
{
*ep = ERR_MEMORY;
return NAN; //0.0;
}
ev.sp = 0;
/* Manage errors */
*ep = setjmp(ev.j);
if(*ep != 0)
{
FREE(ev.st);
return NAN; //0.0;
}
/* Initialize the lexer */
ev.token[0].type = TOK_INI;
ev.token[0].s_val[0] = '\0';
ev.token[1].type = TOK_INI;
ev.token[1].s_val[0] = '\0';
ev.cur_tok = 0;
/* Initialize the parser */
ev.p = exp;
/* lex once to initialize the lexer */
if(lex(&ev) != TOK_END)
{
expr(&ev);
ans = pop(&ev);
}
FREE(ev.st);
return ans;
}
/*
* Pushes a value onto the stack, increases the stack size if necessary
*/
static void push(struct eval *ev, double d) {
if(ev->sp == ev->st_size) {
/* Resize the stack by 1.5 */
double *old = ev->st;
int new_size = ev->st_size + (ev->st_size >> 1);
ev->st = REALLOC(ev->st, new_size);
if(!ev->st) {
ev->st = old;
longjmp(ev->j, ERR_MEMORY);
}
ev->st_size = new_size;
}
ev->st[ev->sp++] = d;
}
// Pops a value from the top of the stack
static double pop(struct eval *ev) {
assert(ev->sp > 0);
return ev->st[--ev->sp];
}
// stricmp() is common, but not standard, so I provide my own
static int istrcmp(const char *p, const char *q) {
for(; tolower(p[0]) == tolower(q[0]) && p[0]; p++, q++);
return tolower(p[0]) - tolower(q[0]);
}
/*
* Lexical analyzer function
*
* In order to implement LL(1), struct eval has an array of two token structures,
* and its cur_tok member is used to point to the _current_ token, while the other
* element contains the _next_ token. This implements a 2 element ring buffer where
* the lexer always writes to the _next_ token so that the recursive descent parser can
* _peek_ at the next token.
*/
static int lex(struct eval *ev) {
int next_tok;
start:
/* Cycle the tokens */
next_tok = ev->cur_tok;
ev->cur_tok = ev->cur_tok?0:1;
while(isspace(ev->p[0])) ev->p++;
if(!ev->p[0]) {
/* End of the expression */
ev->token[next_tok].type = TOK_END;
goto end;
}
else if(isdigit(ev->p[0]) || ev->p[0] == '.') {
/* Number */
char *endp;
ev->token[next_tok].type = TOK_NUM;
ev->token[next_tok].n_val = strtod(ev->p, &endp);
ev->p = endp;
goto end;
}
else if(isalpha(ev->p[0])) {
/* Identifier */
int i;
for(i = 0; isalnum(ev->p[0]) && i < MAX_ID_LEN - 1; i++, ev->p++)
ev->token[next_tok].s_val[i] = ev->p[0];
if(isalpha(ev->p[0])) longjmp(ev->j, ERR_LONGID);
ev->token[next_tok].s_val[i] = '\0';
ev->token[next_tok].type = TOK_ID;
goto end;
}
else if(strchr(OPERATORS, ev->p[0])) {
/* Operator */
ev->token[next_tok].type = ev->p[0];
ev->p++;
goto end;
}
else /* Unknown token */
longjmp(ev->j, ERR_LEXER);
end:
/* If this was the first call, cycle the tokens again */
if(ev->token[ev->cur_tok].type == TOK_INI)
goto start;
return ev->token[ev->cur_tok].type;
}
#define EVAL_TYPE(e) (e->token[e->cur_tok].type)
#define EVAL_ERROR(c) longjmp(ev->j, (c))
// num_expr ::= NUMBER
static void num_expr(struct eval *ev) {
if(EVAL_TYPE(ev) != TOK_NUM)
EVAL_ERROR(ERR_VALUE);
push(ev, ev->token[ev->cur_tok].n_val);
lex(ev);
}
// expr ::= add_expr
static void expr(struct eval *ev) {
add_expr(ev);
}
// add_expr ::= mul_expr [('+'|'-') mul_expr]
static void add_expr(struct eval *ev) {
int t;
mul_expr(ev);
while((t =EVAL_TYPE(ev)) == '+' || t == '-') {
double a,b;
lex(ev);
mul_expr(ev);
b = pop(ev);
a = pop(ev);
if(t == '+')
push(ev, a + b);
else
push(ev, a - b);
}
}
// mul_expr ::= pow_expr [('*'|'/'|'%') pow_expr]
static void mul_expr(struct eval *ev) {
int t;
pow_expr(ev);
while((t = EVAL_TYPE(ev)) == '*' || t == '/' || t == '%') {
double a,b;
lex(ev);
pow_expr(ev);
b = pop(ev);
a = pop(ev);
if(t == '*')
push(ev, a * b);
else if(t == '/')
push(ev, a / b);
else
push(ev, fmod(a, b));
}
}
// pow_expr ::= uni_expr ['^' pow_expr]
static void pow_expr(struct eval *ev) {
/* Note that exponentiation is right associative:
2^3^4 is 2^(3^4), not (2^3)^4 */
uni_expr(ev);
if(EVAL_TYPE(ev) == '^') {
double a,b;
lex(ev);
pow_expr(ev);
b = pop(ev);
a = pop(ev);
push(ev, pow(a,b));
}
}
// uni_expr ::= ['+'|'-'] bra_expr
static void uni_expr(struct eval *ev) {
int t = '+';
if(EVAL_TYPE(ev) == '-' || EVAL_TYPE(ev) == '+') {
t = EVAL_TYPE(ev);
lex(ev);
}
bra_expr(ev);
if(t == '-') {
double a = pop(ev);
push(ev, -a);
}
}
// bra_expr ::= '(' add_expr ')' | id_expr
static void bra_expr(struct eval *ev) {
if(EVAL_TYPE(ev) == '(') {
lex(ev);
add_expr(ev);
if(EVAL_TYPE(ev) != ')')
EVAL_ERROR(ERR_BRACKET);
lex(ev);
}
else
id_expr(ev);
}
// id_expr ::= ID '(' add_expr [',' add_expr]* ')' | ID | num_expr
static void id_expr(struct eval *ev) {
int nargs = 0;
char id[MAX_ID_LEN];
if(EVAL_TYPE(ev) != TOK_ID) {
num_expr(ev);
} else {
strcpy(id, ev->token[ev->cur_tok].s_val);
lex(ev);
if(EVAL_TYPE(ev) != '(') {
/**/ if(!istrcmp(id, "true")) push(ev, 1.0);
else if(!istrcmp(id, "false")) push(ev, 0.0);
else if(!istrcmp(id, "on")) push(ev, 1.0);
else if(!istrcmp(id, "off")) push(ev, 0.0);
// pi - 3.141592654
else if(!istrcmp(id, "pi"))
push(ev, EVAL_PI);
// e - base of natural logarithms, 2.718281828
else if(!istrcmp(id, "e"))
push(ev, EVAL_E);
// deg - deg2rad, allows to degree conversion `sin(90*deg) = 1`
else if(!istrcmp(id, "deg"))
push(ev, EVAL_DEG);
else
EVAL_ERROR(ERR_CONST);
} else {
lex(ev);
while(EVAL_TYPE(ev) != ')') {
add_expr(ev);
nargs++;
if(EVAL_TYPE(ev) == ')') break;
if(EVAL_TYPE(ev) != ',')
EVAL_ERROR(ERR_BRACKET);
lex(ev);
}
lex(ev);
// abs(x) - absolute value of x
if(!istrcmp(id, "abs")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, fabs(pop(ev)));
}
// ceil(x) - smallest integer greater than x
else if(!istrcmp(id, "ceil")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, ceil(pop(ev)));
}
// floor(x) - largest integer smaller than x
else if(!istrcmp(id, "floor")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, floor(pop(ev)));
}
// sin(x) - sine of x, in radians
else if(!istrcmp(id, "sin")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, sin(pop(ev)));
}
// asin(x) - arcsine of x, in radians
else if(!istrcmp(id, "asin")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, asin(pop(ev)));
}
// cos(x) - cosine of x, in radians
else if(!istrcmp(id, "cos")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, cos(pop(ev)));
}
// acos(x) - arccosine of x, in radians
else if(!istrcmp(id, "acos")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, acos(pop(ev)));
}
// tan(x) - tangent of x, in radians
else if(!istrcmp(id, "tan")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, tan(pop(ev)));
}
// atan(x) - arctangent of x, in radians
else if(!istrcmp(id, "atan")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, atan(pop(ev)));
}
// atan(y,x) - arctangent of y/x, in radians.
else if(!istrcmp(id, "atan2")) {
double a, b;
if(nargs != 2) EVAL_ERROR(ERR_ARGS);
b = pop(ev);
a = pop(ev);
push(ev, atan2(a,b));
}
// sinh(x) - hyperbolic sine of x, in radians
else if(!istrcmp(id, "sinh")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, sinh(pop(ev)));
}
// cosh(x) - hyperbolic cosine of x, in radians
else if(!istrcmp(id, "cosh")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, cosh(pop(ev)));
}
// tanh(x) - hyperbolic tangent of x, in radians
else if(!istrcmp(id, "tanh")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, tanh(pop(ev)));
}
// log(x) - natural logarithm of x
else if(!istrcmp(id, "log")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, log(pop(ev)));
}
// log10(x) - logarithm of x, base-10
else if(!istrcmp(id, "log10")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, log10(pop(ev)));
}
// exp(x) - computes e^x
else if(!istrcmp(id, "exp")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, exp(pop(ev)));
}
// sqrt(x) - square root of x
else if(!istrcmp(id, "sqrt")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, sqrt(pop(ev)));
}
// rad(x) - converts x from degrees to radians
else if(!istrcmp(id, "rad")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, pop(ev)*EVAL_PI/180);
}
// deg(x) - converts x from radians to degrees
else if(!istrcmp(id, "deg")) {
if(nargs != 1) EVAL_ERROR(ERR_ARGS);
push(ev, pop(ev)*180/EVAL_PI);
}
// pow(x,y) - computes x^y
else if(!istrcmp(id, "pow")) {
double a, b;
if(nargs != 2) EVAL_ERROR(ERR_ARGS);
b = pop(ev);
a = pop(ev);
push(ev, pow(a,b));
}
// hypot(x,y) - computes sqrt(x*x + y*y)
else if(!istrcmp(id, "hypot")) {
double a, b;
if(nargs != 2) EVAL_ERROR(ERR_ARGS);
b = pop(ev);
a = pop(ev);
push(ev, sqrt(a*a + b*b));
}
else
EVAL_ERROR(ERR_FUNC);
}
}
}
//
#ifdef EVALDEMO
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
double e;
for(i = 1; i < argc; i++) {
e = eval(argv[i]);
if(e != e)
fprintf(stderr, "Error in expression %s\n", argv[i]);
else
printf("%s = %g\n", argv[i], e);
}
assert( eval("1+1") == 2 );
assert( eval("1+") != eval("1+") );
assert(~puts("Ok") );
}
#endif

View File

@ -7,7 +7,7 @@
#define ICON_MIN_MDI 0xF68C
#define ICON_MAX_16_MDI 0xF68C
#define ICON_MAX_MDI 0xF1C80
#define ICON_MAX_MDI 0xF1CC7
#define ICON_MDI_AB_TESTING "\xf3\xb0\x87\x89" // U+F01C9
#define ICON_MDI_ABACUS "\xf3\xb1\x9b\xa0" // U+F16E0
#define ICON_MDI_ABJAD_ARABIC "\xf3\xb1\x8c\xa8" // U+F1328
@ -68,6 +68,10 @@
#define ICON_MDI_ACCOUNT_EDIT_OUTLINE "\xf3\xb0\xbf\xbb" // U+F0FFB
#define ICON_MDI_ACCOUNT_EYE "\xf3\xb0\x90\xa0" // U+F0420
#define ICON_MDI_ACCOUNT_EYE_OUTLINE "\xf3\xb1\x89\xbb" // U+F127B
#define ICON_MDI_ACCOUNT_FILE "\xf3\xb1\xb2\xa7" // U+F1CA7
#define ICON_MDI_ACCOUNT_FILE_OUTLINE "\xf3\xb1\xb2\xa8" // U+F1CA8
#define ICON_MDI_ACCOUNT_FILE_TEXT "\xf3\xb1\xb2\xa9" // U+F1CA9
#define ICON_MDI_ACCOUNT_FILE_TEXT_OUTLINE "\xf3\xb1\xb2\xaa" // U+F1CAA
#define ICON_MDI_ACCOUNT_FILTER "\xf3\xb0\xa4\xb6" // U+F0936
#define ICON_MDI_ACCOUNT_FILTER_OUTLINE "\xf3\xb0\xbe\x9d" // U+F0F9D
#define ICON_MDI_ACCOUNT_GROUP "\xf3\xb0\xa1\x89" // U+F0849
@ -556,6 +560,8 @@
#define ICON_MDI_ARROW_LEFT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x9a" // U+F159A
#define ICON_MDI_ARROW_LEFT_TOP "\xf3\xb1\x9e\xa7" // U+F17A7
#define ICON_MDI_ARROW_LEFT_TOP_BOLD "\xf3\xb1\x9e\xa8" // U+F17A8
#define ICON_MDI_ARROW_OSCILLATING "\xf3\xb1\xb2\x91" // U+F1C91
#define ICON_MDI_ARROW_OSCILLATING_OFF "\xf3\xb1\xb2\x92" // U+F1C92
#define ICON_MDI_ARROW_PROJECTILE "\xf3\xb1\xa1\x80" // U+F1840
#define ICON_MDI_ARROW_PROJECTILE_MULTIPLE "\xf3\xb1\xa0\xbf" // U+F183F
#define ICON_MDI_ARROW_RIGHT "\xf3\xb0\x81\x94" // U+F0054
@ -727,6 +733,8 @@
#define ICON_MDI_BAG_PERSONAL_OFF "\xf3\xb0\xb8\x91" // U+F0E11
#define ICON_MDI_BAG_PERSONAL_OFF_OUTLINE "\xf3\xb0\xb8\x92" // U+F0E12
#define ICON_MDI_BAG_PERSONAL_OUTLINE "\xf3\xb0\xb8\x93" // U+F0E13
#define ICON_MDI_BAG_PERSONAL_PLUS "\xf3\xb1\xb2\xa4" // U+F1CA4
#define ICON_MDI_BAG_PERSONAL_PLUS_OUTLINE "\xf3\xb1\xb2\xa5" // U+F1CA5
#define ICON_MDI_BAG_PERSONAL_TAG "\xf3\xb1\xac\x8c" // U+F1B0C
#define ICON_MDI_BAG_PERSONAL_TAG_OUTLINE "\xf3\xb1\xac\x8d" // U+F1B0D
#define ICON_MDI_BAG_SUITCASE "\xf3\xb1\x96\x8b" // U+F158B
@ -1226,9 +1234,11 @@
#define ICON_MDI_BUS_MULTIPLE "\xf3\xb0\xbc\xbf" // U+F0F3F
#define ICON_MDI_BUS_SCHOOL "\xf3\xb0\x9e\x9f" // U+F079F
#define ICON_MDI_BUS_SIDE "\xf3\xb0\x9e\xa0" // U+F07A0
#define ICON_MDI_BUS_SIGN "\xf3\xb1\xb3\x81" // U+F1CC1
#define ICON_MDI_BUS_STOP "\xf3\xb1\x80\x92" // U+F1012
#define ICON_MDI_BUS_STOP_COVERED "\xf3\xb1\x80\x93" // U+F1013
#define ICON_MDI_BUS_STOP_UNCOVERED "\xf3\xb1\x80\x94" // U+F1014
#define ICON_MDI_BUS_WRENCH "\xf3\xb1\xb3\x82" // U+F1CC2
#define ICON_MDI_BUTTERFLY "\xf3\xb1\x96\x89" // U+F1589
#define ICON_MDI_BUTTERFLY_OUTLINE "\xf3\xb1\x96\x8a" // U+F158A
#define ICON_MDI_BUTTON_CURSOR "\xf3\xb1\xad\x8f" // U+F1B4F
@ -1408,6 +1418,7 @@
#define ICON_MDI_CAR_DEFROST_REAR "\xf3\xb0\xb5\xa2" // U+F0D62
#define ICON_MDI_CAR_DOOR "\xf3\xb0\xad\xab" // U+F0B6B
#define ICON_MDI_CAR_DOOR_LOCK "\xf3\xb1\x82\x9d" // U+F109D
#define ICON_MDI_CAR_DOOR_LOCK_OPEN "\xf3\xb1\xb2\x81" // U+F1C81
#define ICON_MDI_CAR_ELECTRIC "\xf3\xb0\xad\xac" // U+F0B6C
#define ICON_MDI_CAR_ELECTRIC_OUTLINE "\xf3\xb1\x96\xb5" // U+F15B5
#define ICON_MDI_CAR_EMERGENCY "\xf3\xb1\x98\x8f" // U+F160F
@ -1526,6 +1537,7 @@
#define ICON_MDI_CASH_100 "\xf3\xb0\x84\x95" // U+F0115
#define ICON_MDI_CASH_CHECK "\xf3\xb1\x93\xae" // U+F14EE
#define ICON_MDI_CASH_CLOCK "\xf3\xb1\xaa\x91" // U+F1A91
#define ICON_MDI_CASH_EDIT "\xf3\xb1\xb2\xab" // U+F1CAB
#define ICON_MDI_CASH_FAST "\xf3\xb1\xa1\x9c" // U+F185C
#define ICON_MDI_CASH_LOCK "\xf3\xb1\x93\xaa" // U+F14EA
#define ICON_MDI_CASH_LOCK_OPEN "\xf3\xb1\x93\xab" // U+F14EB
@ -1589,6 +1601,7 @@
#define ICON_MDI_CHAIR_SCHOOL "\xf3\xb0\x84\xa5" // U+F0125
#define ICON_MDI_CHANDELIER "\xf3\xb1\x9e\x93" // U+F1793
#define ICON_MDI_CHARITY "\xf3\xb0\xb1\x8f" // U+F0C4F
#define ICON_MDI_CHARITY_SEARCH "\xf3\xb1\xb2\x82" // U+F1C82
#define ICON_MDI_CHART_ARC "\xf3\xb0\x84\xa6" // U+F0126
#define ICON_MDI_CHART_AREASPLINE "\xf3\xb0\x84\xa7" // U+F0127
#define ICON_MDI_CHART_AREASPLINE_VARIANT "\xf3\xb0\xba\x91" // U+F0E91
@ -1913,6 +1926,8 @@
#define ICON_MDI_CLOUD_COG_OUTLINE "\xf3\xb1\xaf\xb1" // U+F1BF1
#define ICON_MDI_CLOUD_DOWNLOAD "\xf3\xb0\x85\xa2" // U+F0162
#define ICON_MDI_CLOUD_DOWNLOAD_OUTLINE "\xf3\xb0\xad\xbd" // U+F0B7D
#define ICON_MDI_CLOUD_KEY "\xf3\xb1\xb2\xa1" // U+F1CA1
#define ICON_MDI_CLOUD_KEY_OUTLINE "\xf3\xb1\xb2\xa2" // U+F1CA2
#define ICON_MDI_CLOUD_LOCK "\xf3\xb1\x87\xb1" // U+F11F1
#define ICON_MDI_CLOUD_LOCK_OPEN "\xf3\xb1\xaf\xb2" // U+F1BF2
#define ICON_MDI_CLOUD_LOCK_OPEN_OUTLINE "\xf3\xb1\xaf\xb3" // U+F1BF3
@ -1950,6 +1965,10 @@
#define ICON_MDI_COACH_LAMP_VARIANT "\xf3\xb1\xa8\xb7" // U+F1A37
#define ICON_MDI_COAT_RACK "\xf3\xb1\x82\x9e" // U+F109E
#define ICON_MDI_CODE_ARRAY "\xf3\xb0\x85\xa8" // U+F0168
#define ICON_MDI_CODE_BLOCK_BRACES "\xf3\xb1\xb2\x83" // U+F1C83
#define ICON_MDI_CODE_BLOCK_BRACKETS "\xf3\xb1\xb2\x84" // U+F1C84
#define ICON_MDI_CODE_BLOCK_PARENTHESES "\xf3\xb1\xb2\x85" // U+F1C85
#define ICON_MDI_CODE_BLOCK_TAGS "\xf3\xb1\xb2\x86" // U+F1C86
#define ICON_MDI_CODE_BRACES "\xf3\xb0\x85\xa9" // U+F0169
#define ICON_MDI_CODE_BRACES_BOX "\xf3\xb1\x83\x96" // U+F10D6
#define ICON_MDI_CODE_BRACKETS "\xf3\xb0\x85\xaa" // U+F016A
@ -2471,6 +2490,7 @@
#define ICON_MDI_DONKEY "\xf3\xb0\x9f\x82" // U+F07C2
#define ICON_MDI_DOOR "\xf3\xb0\xa0\x9a" // U+F081A
#define ICON_MDI_DOOR_CLOSED "\xf3\xb0\xa0\x9b" // U+F081B
#define ICON_MDI_DOOR_CLOSED_CANCEL "\xf3\xb1\xb2\x93" // U+F1C93
#define ICON_MDI_DOOR_CLOSED_LOCK "\xf3\xb1\x82\xaf" // U+F10AF
#define ICON_MDI_DOOR_OPEN "\xf3\xb0\xa0\x9c" // U+F081C
#define ICON_MDI_DOOR_SLIDING "\xf3\xb1\xa0\x9e" // U+F181E
@ -2530,7 +2550,10 @@
#define ICON_MDI_EARBUDS_OFF_OUTLINE "\xf3\xb1\xa1\x91" // U+F1851
#define ICON_MDI_EARBUDS_OUTLINE "\xf3\xb1\xa1\x92" // U+F1852
#define ICON_MDI_EARTH "\xf3\xb0\x87\xa7" // U+F01E7
#define ICON_MDI_EARTH_ARROW_DOWN "\xf3\xb1\xb2\x87" // U+F1C87
#define ICON_MDI_EARTH_ARROW_LEFT "\xf3\xb1\xb2\x88" // U+F1C88
#define ICON_MDI_EARTH_ARROW_RIGHT "\xf3\xb1\x8c\x91" // U+F1311
#define ICON_MDI_EARTH_ARROW_UP "\xf3\xb1\xb2\x89" // U+F1C89
#define ICON_MDI_EARTH_BOX "\xf3\xb0\x9b\x8d" // U+F06CD
#define ICON_MDI_EARTH_BOX_MINUS "\xf3\xb1\x90\x87" // U+F1407
#define ICON_MDI_EARTH_BOX_OFF "\xf3\xb0\x9b\x8e" // U+F06CE
@ -2634,11 +2657,17 @@
#define ICON_MDI_EMOTICON_KISS_OUTLINE "\xf3\xb0\xb1\xb3" // U+F0C73
#define ICON_MDI_EMOTICON_LOL "\xf3\xb1\x88\x94" // U+F1214
#define ICON_MDI_EMOTICON_LOL_OUTLINE "\xf3\xb1\x88\x95" // U+F1215
#define ICON_MDI_EMOTICON_MINUS "\xf3\xb1\xb2\xb2" // U+F1CB2
#define ICON_MDI_EMOTICON_MINUS_OUTLINE "\xf3\xb1\xb2\xb3" // U+F1CB3
#define ICON_MDI_EMOTICON_NEUTRAL "\xf3\xb0\xb1\xb4" // U+F0C74
#define ICON_MDI_EMOTICON_NEUTRAL_OUTLINE "\xf3\xb0\x87\xb6" // U+F01F6
#define ICON_MDI_EMOTICON_OUTLINE "\xf3\xb0\x87\xb2" // U+F01F2
#define ICON_MDI_EMOTICON_PLUS "\xf3\xb1\xb2\xb4" // U+F1CB4
#define ICON_MDI_EMOTICON_PLUS_OUTLINE "\xf3\xb1\xb2\xb5" // U+F1CB5
#define ICON_MDI_EMOTICON_POOP "\xf3\xb0\x87\xb7" // U+F01F7
#define ICON_MDI_EMOTICON_POOP_OUTLINE "\xf3\xb0\xb1\xb5" // U+F0C75
#define ICON_MDI_EMOTICON_REMOVE "\xf3\xb1\xb2\xb6" // U+F1CB6
#define ICON_MDI_EMOTICON_REMOVE_OUTLINE "\xf3\xb1\xb2\xb7" // U+F1CB7
#define ICON_MDI_EMOTICON_SAD "\xf3\xb0\xb1\xb6" // U+F0C76
#define ICON_MDI_EMOTICON_SAD_OUTLINE "\xf3\xb0\x87\xb8" // U+F01F8
#define ICON_MDI_EMOTICON_SICK "\xf3\xb1\x95\xbc" // U+F157C
@ -2698,6 +2727,7 @@
#define ICON_MDI_EYE_CHECK_OUTLINE "\xf3\xb0\xb4\x85" // U+F0D05
#define ICON_MDI_EYE_CIRCLE "\xf3\xb0\xae\x94" // U+F0B94
#define ICON_MDI_EYE_CIRCLE_OUTLINE "\xf3\xb0\xae\x95" // U+F0B95
#define ICON_MDI_EYE_CLOSED "\xf3\xb1\xb2\xa3" // U+F1CA3
#define ICON_MDI_EYE_LOCK "\xf3\xb1\xb0\x86" // U+F1C06
#define ICON_MDI_EYE_LOCK_OPEN "\xf3\xb1\xb0\x87" // U+F1C07
#define ICON_MDI_EYE_LOCK_OPEN_OUTLINE "\xf3\xb1\xb0\x88" // U+F1C08
@ -2977,6 +3007,7 @@
#define ICON_MDI_FIRE_HYDRANT_ALERT "\xf3\xb1\x84\xb8" // U+F1138
#define ICON_MDI_FIRE_HYDRANT_OFF "\xf3\xb1\x84\xb9" // U+F1139
#define ICON_MDI_FIRE_OFF "\xf3\xb1\x9c\xa2" // U+F1722
#define ICON_MDI_FIRE_STATION "\xf3\xb1\xb3\x83" // U+F1CC3
#define ICON_MDI_FIRE_TRUCK "\xf3\xb0\xa2\xab" // U+F08AB
#define ICON_MDI_FIREBASE "\xf3\xb0\xa5\xa7" // U+F0967
#define ICON_MDI_FIREFOX "\xf3\xb0\x88\xb9" // U+F0239
@ -3418,6 +3449,8 @@
#define ICON_MDI_GAS_BURNER "\xf3\xb1\xa8\x9b" // U+F1A1B
#define ICON_MDI_GAS_CYLINDER "\xf3\xb0\x99\x87" // U+F0647
#define ICON_MDI_GAS_STATION "\xf3\xb0\x8a\x98" // U+F0298
#define ICON_MDI_GAS_STATION_IN_USE "\xf3\xb1\xb3\x84" // U+F1CC4
#define ICON_MDI_GAS_STATION_IN_USE_OUTLINE "\xf3\xb1\xb3\x85" // U+F1CC5
#define ICON_MDI_GAS_STATION_OFF "\xf3\xb1\x90\x89" // U+F1409
#define ICON_MDI_GAS_STATION_OFF_OUTLINE "\xf3\xb1\x90\x8a" // U+F140A
#define ICON_MDI_GAS_STATION_OUTLINE "\xf3\xb0\xba\xb8" // U+F0EB8
@ -3446,6 +3479,9 @@
#define ICON_MDI_GENDER_MALE_FEMALE_VARIANT "\xf3\xb1\x84\xbf" // U+F113F
#define ICON_MDI_GENDER_NON_BINARY "\xf3\xb1\x85\x80" // U+F1140
#define ICON_MDI_GENDER_TRANSGENDER "\xf3\xb0\x8a\x9f" // U+F029F
#define ICON_MDI_GENERATOR_MOBILE "\xf3\xb1\xb2\x8a" // U+F1C8A
#define ICON_MDI_GENERATOR_PORTABLE "\xf3\xb1\xb2\x8b" // U+F1C8B
#define ICON_MDI_GENERATOR_STATIONARY "\xf3\xb1\xb2\x8c" // U+F1C8C
#define ICON_MDI_GENTOO "\xf3\xb0\xa3\xa8" // U+F08E8
#define ICON_MDI_GESTURE "\xf3\xb0\x9f\x8b" // U+F07CB
#define ICON_MDI_GESTURE_DOUBLE_TAP "\xf3\xb0\x9c\xbc" // U+F073C
@ -3681,6 +3717,7 @@
#define ICON_MDI_HEART_PULSE "\xf3\xb0\x97\xb6" // U+F05F6
#define ICON_MDI_HEART_REMOVE "\xf3\xb1\x90\xb0" // U+F1430
#define ICON_MDI_HEART_REMOVE_OUTLINE "\xf3\xb1\x90\xb3" // U+F1433
#define ICON_MDI_HEART_SEARCH "\xf3\xb1\xb2\x8d" // U+F1C8D
#define ICON_MDI_HEART_SETTINGS "\xf3\xb1\x99\xa5" // U+F1665
#define ICON_MDI_HEART_SETTINGS_OUTLINE "\xf3\xb1\x99\xa6" // U+F1666
#define ICON_MDI_HEAT_PUMP "\xf3\xb1\xa9\x83" // U+F1A43
@ -3805,7 +3842,10 @@
#define ICON_MDI_HOSPITAL_BUILDING "\xf3\xb0\x8b\xa1" // U+F02E1
#define ICON_MDI_HOSPITAL_MARKER "\xf3\xb0\x8b\xa2" // U+F02E2
#define ICON_MDI_HOT_TUB "\xf3\xb0\xa0\xa8" // U+F0828
#define ICON_MDI_HOURS_12 "\xf3\xb1\xb2\x94" // U+F1C94
#define ICON_MDI_HOURS_24 "\xf3\xb1\x91\xb8" // U+F1478
#define ICON_MDI_HUB "\xf3\xb1\xb2\x95" // U+F1C95
#define ICON_MDI_HUB_OUTLINE "\xf3\xb1\xb2\x96" // U+F1C96
#define ICON_MDI_HUBSPOT "\xf3\xb0\xb4\x97" // U+F0D17
#define ICON_MDI_HULU "\xf3\xb0\xa0\xa9" // U+F0829
#define ICON_MDI_HUMAN "\xf3\xb0\x8b\xa6" // U+F02E6
@ -3820,6 +3860,7 @@
#define ICON_MDI_HUMAN_FEMALE_BOY "\xf3\xb0\xa9\x99" // U+F0A59
#define ICON_MDI_HUMAN_FEMALE_DANCE "\xf3\xb1\x97\x89" // U+F15C9
#define ICON_MDI_HUMAN_FEMALE_FEMALE "\xf3\xb0\xa9\x9a" // U+F0A5A
#define ICON_MDI_HUMAN_FEMALE_FEMALE_CHILD "\xf3\xb1\xb2\x8e" // U+F1C8E
#define ICON_MDI_HUMAN_FEMALE_GIRL "\xf3\xb0\xa9\x9b" // U+F0A5B
#define ICON_MDI_HUMAN_GREETING "\xf3\xb1\x9f\x84" // U+F17C4
#define ICON_MDI_HUMAN_GREETING_PROXIMITY "\xf3\xb1\x96\x9d" // U+F159D
@ -3837,6 +3878,7 @@
#define ICON_MDI_HUMAN_MALE_HEIGHT "\xf3\xb0\xbb\xbb" // U+F0EFB
#define ICON_MDI_HUMAN_MALE_HEIGHT_VARIANT "\xf3\xb0\xbb\xbc" // U+F0EFC
#define ICON_MDI_HUMAN_MALE_MALE "\xf3\xb0\xa9\x9e" // U+F0A5E
#define ICON_MDI_HUMAN_MALE_MALE_CHILD "\xf3\xb1\xb2\x8f" // U+F1C8F
#define ICON_MDI_HUMAN_NON_BINARY "\xf3\xb1\xa1\x88" // U+F1848
#define ICON_MDI_HUMAN_PREGNANT "\xf3\xb0\x97\x8f" // U+F05CF
#define ICON_MDI_HUMAN_QUEUE "\xf3\xb1\x95\xb1" // U+F1571
@ -3960,6 +4002,7 @@
#define ICON_MDI_IRON_BOARD "\xf3\xb1\xa0\xb8" // U+F1838
#define ICON_MDI_IRON_OUTLINE "\xf3\xb1\xa0\xa5" // U+F1825
#define ICON_MDI_ISLAND "\xf3\xb1\x81\x8f" // U+F104F
#define ICON_MDI_ISLAND_VARIANT "\xf3\xb1\xb3\x86" // U+F1CC6
#define ICON_MDI_IV_BAG "\xf3\xb1\x82\xb9" // U+F10B9
#define ICON_MDI_JABBER "\xf3\xb0\xb7\x95" // U+F0DD5
#define ICON_MDI_JEEPNEY "\xf3\xb0\x8c\x82" // U+F0302
@ -4200,6 +4243,9 @@
#define ICON_MDI_LINK_BOX_OUTLINE "\xf3\xb0\xb4\x9b" // U+F0D1B
#define ICON_MDI_LINK_BOX_VARIANT "\xf3\xb0\xb4\x9c" // U+F0D1C
#define ICON_MDI_LINK_BOX_VARIANT_OUTLINE "\xf3\xb0\xb4\x9d" // U+F0D1D
#define ICON_MDI_LINK_CIRCLE "\xf3\xb1\xb2\xac" // U+F1CAC
#define ICON_MDI_LINK_CIRCLE_OUTLINE "\xf3\xb1\xb2\xad" // U+F1CAD
#define ICON_MDI_LINK_EDIT "\xf3\xb1\xb2\xae" // U+F1CAE
#define ICON_MDI_LINK_LOCK "\xf3\xb1\x82\xba" // U+F10BA
#define ICON_MDI_LINK_OFF "\xf3\xb0\x8c\xb8" // U+F0338
#define ICON_MDI_LINK_PLUS "\xf3\xb0\xb2\x94" // U+F0C94
@ -4374,9 +4420,11 @@
#define ICON_MDI_MEDICATION_OUTLINE "\xf3\xb1\xac\x95" // U+F1B15
#define ICON_MDI_MEDITATION "\xf3\xb1\x85\xbb" // U+F117B
#define ICON_MDI_MEMORY "\xf3\xb0\x8d\x9b" // U+F035B
#define ICON_MDI_MEMORY_ARROW_DOWN "\xf3\xb1\xb2\xa6" // U+F1CA6
#define ICON_MDI_MENORAH "\xf3\xb1\x9f\x94" // U+F17D4
#define ICON_MDI_MENORAH_FIRE "\xf3\xb1\x9f\x95" // U+F17D5
#define ICON_MDI_MENU "\xf3\xb0\x8d\x9c" // U+F035C
#define ICON_MDI_MENU_CLOSE "\xf3\xb1\xb2\x90" // U+F1C90
#define ICON_MDI_MENU_DOWN "\xf3\xb0\x8d\x9d" // U+F035D
#define ICON_MDI_MENU_DOWN_OUTLINE "\xf3\xb0\x9a\xb6" // U+F06B6
#define ICON_MDI_MENU_LEFT "\xf3\xb0\x8d\x9e" // U+F035E
@ -5026,7 +5074,13 @@
#define ICON_MDI_PARKING "\xf3\xb0\x8f\xa3" // U+F03E3
#define ICON_MDI_PARTY_POPPER "\xf3\xb1\x81\x96" // U+F1056
#define ICON_MDI_PASSPORT "\xf3\xb0\x9f\xa3" // U+F07E3
#define ICON_MDI_PASSPORT_ALERT "\xf3\xb1\xb2\xb8" // U+F1CB8
#define ICON_MDI_PASSPORT_BIOMETRIC "\xf3\xb0\xb7\xa1" // U+F0DE1
#define ICON_MDI_PASSPORT_CANCEL "\xf3\xb1\xb2\xb9" // U+F1CB9
#define ICON_MDI_PASSPORT_CHECK "\xf3\xb1\xb2\xba" // U+F1CBA
#define ICON_MDI_PASSPORT_MINUS "\xf3\xb1\xb2\xbb" // U+F1CBB
#define ICON_MDI_PASSPORT_PLUS "\xf3\xb1\xb2\xbc" // U+F1CBC
#define ICON_MDI_PASSPORT_REMOVE "\xf3\xb1\xb2\xbd" // U+F1CBD
#define ICON_MDI_PASTA "\xf3\xb1\x85\xa0" // U+F1160
#define ICON_MDI_PATIO_HEATER "\xf3\xb0\xbe\x80" // U+F0F80
#define ICON_MDI_PATREON "\xf3\xb0\xa2\x82" // U+F0882
@ -5236,6 +5290,7 @@
#define ICON_MDI_PLUS_NETWORK_OUTLINE "\xf3\xb0\xb2\xba" // U+F0CBA
#define ICON_MDI_PLUS_OUTLINE "\xf3\xb0\x9c\x85" // U+F0705
#define ICON_MDI_PLUS_THICK "\xf3\xb1\x87\xac" // U+F11EC
#define ICON_MDI_POCKET "\xf3\xb1\xb2\xbe" // U+F1CBE
#define ICON_MDI_PODCAST "\xf3\xb0\xa6\x94" // U+F0994
#define ICON_MDI_PODIUM "\xf3\xb0\xb4\xa5" // U+F0D25
#define ICON_MDI_PODIUM_BRONZE "\xf3\xb0\xb4\xa6" // U+F0D26
@ -5418,6 +5473,7 @@
#define ICON_MDI_QUALITY_HIGH "\xf3\xb0\x90\xb5" // U+F0435
#define ICON_MDI_QUALITY_LOW "\xf3\xb0\xa8\x8c" // U+F0A0C
#define ICON_MDI_QUALITY_MEDIUM "\xf3\xb0\xa8\x8d" // U+F0A0D
#define ICON_MDI_QUEUE_FIRST_IN_LAST_OUT "\xf3\xb1\xb2\xaf" // U+F1CAF
#define ICON_MDI_QUORA "\xf3\xb0\xb4\xa9" // U+F0D29
#define ICON_MDI_RABBIT "\xf3\xb0\xa4\x87" // U+F0907
#define ICON_MDI_RABBIT_VARIANT "\xf3\xb1\xa9\xa1" // U+F1A61
@ -5666,6 +5722,7 @@
#define ICON_MDI_ROUNDED_CORNER "\xf3\xb0\x98\x87" // U+F0607
#define ICON_MDI_ROUTER "\xf3\xb1\x87\xa2" // U+F11E2
#define ICON_MDI_ROUTER_NETWORK "\xf3\xb1\x82\x87" // U+F1087
#define ICON_MDI_ROUTER_NETWORK_WIRELESS "\xf3\xb1\xb2\x97" // U+F1C97
#define ICON_MDI_ROUTER_WIRELESS "\xf3\xb0\x91\xa9" // U+F0469
#define ICON_MDI_ROUTER_WIRELESS_OFF "\xf3\xb1\x96\xa3" // U+F15A3
#define ICON_MDI_ROUTER_WIRELESS_SETTINGS "\xf3\xb0\xa9\xa9" // U+F0A69
@ -5810,10 +5867,14 @@
#define ICON_MDI_SERIAL_PORT "\xf3\xb0\x99\x9c" // U+F065C
#define ICON_MDI_SERVER "\xf3\xb0\x92\x8b" // U+F048B
#define ICON_MDI_SERVER_MINUS "\xf3\xb0\x92\x8c" // U+F048C
#define ICON_MDI_SERVER_MINUS_OUTLINE "\xf3\xb1\xb2\x98" // U+F1C98
#define ICON_MDI_SERVER_NETWORK "\xf3\xb0\x92\x8d" // U+F048D
#define ICON_MDI_SERVER_NETWORK_OFF "\xf3\xb0\x92\x8e" // U+F048E
#define ICON_MDI_SERVER_NETWORK_OUTLINE "\xf3\xb1\xb2\x99" // U+F1C99
#define ICON_MDI_SERVER_OFF "\xf3\xb0\x92\x8f" // U+F048F
#define ICON_MDI_SERVER_OUTLINE "\xf3\xb1\xb2\x9a" // U+F1C9A
#define ICON_MDI_SERVER_PLUS "\xf3\xb0\x92\x90" // U+F0490
#define ICON_MDI_SERVER_PLUS_OUTLINE "\xf3\xb1\xb2\x9b" // U+F1C9B
#define ICON_MDI_SERVER_REMOVE "\xf3\xb0\x92\x91" // U+F0491
#define ICON_MDI_SERVER_SECURITY "\xf3\xb0\x92\x92" // U+F0492
#define ICON_MDI_SET_ALL "\xf3\xb0\x9d\xb8" // U+F0778
@ -6450,6 +6511,8 @@
#define ICON_MDI_TAG_ARROW_UP_OUTLINE "\xf3\xb1\x9c\xb2" // U+F1732
#define ICON_MDI_TAG_CHECK "\xf3\xb1\xa9\xba" // U+F1A7A
#define ICON_MDI_TAG_CHECK_OUTLINE "\xf3\xb1\xa9\xbb" // U+F1A7B
#define ICON_MDI_TAG_EDIT "\xf3\xb1\xb2\x9c" // U+F1C9C
#define ICON_MDI_TAG_EDIT_OUTLINE "\xf3\xb1\xb2\x9d" // U+F1C9D
#define ICON_MDI_TAG_FACES "\xf3\xb0\x93\xba" // U+F04FA
#define ICON_MDI_TAG_HEART "\xf3\xb0\x9a\x8b" // U+F068B
#define ICON_MDI_TAG_HEART_OUTLINE "\xf3\xb0\xaf\x8f" // U+F0BCF
@ -6725,6 +6788,7 @@
#define ICON_MDI_TRAFFIC_LIGHT "\xf3\xb0\x94\xab" // U+F052B
#define ICON_MDI_TRAFFIC_LIGHT_OUTLINE "\xf3\xb1\xa0\xaa" // U+F182A
#define ICON_MDI_TRAIN "\xf3\xb0\x94\xac" // U+F052C
#define ICON_MDI_TRAIN_BUS "\xf3\xb1\xb3\x87" // U+F1CC7
#define ICON_MDI_TRAIN_CAR "\xf3\xb0\xaf\x98" // U+F0BD8
#define ICON_MDI_TRAIN_CAR_AUTORACK "\xf3\xb1\xac\xad" // U+F1B2D
#define ICON_MDI_TRAIN_CAR_BOX "\xf3\xb1\xac\xae" // U+F1B2E
@ -6818,6 +6882,8 @@
#define ICON_MDI_TRUCK_FLATBED "\xf3\xb1\xa2\x91" // U+F1891
#define ICON_MDI_TRUCK_MINUS "\xf3\xb1\xa6\xae" // U+F19AE
#define ICON_MDI_TRUCK_MINUS_OUTLINE "\xf3\xb1\xa6\xbd" // U+F19BD
#define ICON_MDI_TRUCK_OFF_ROAD "\xf3\xb1\xb2\x9e" // U+F1C9E
#define ICON_MDI_TRUCK_OFF_ROAD_OFF "\xf3\xb1\xb2\x9f" // U+F1C9F
#define ICON_MDI_TRUCK_OUTLINE "\xf3\xb1\x8a\x9d" // U+F129D
#define ICON_MDI_TRUCK_PLUS "\xf3\xb1\xa6\xad" // U+F19AD
#define ICON_MDI_TRUCK_PLUS_OUTLINE "\xf3\xb1\xa6\xbc" // U+F19BC
@ -6886,6 +6952,7 @@
#define ICON_MDI_UPLOAD_OFF_OUTLINE "\xf3\xb1\x83\x87" // U+F10C7
#define ICON_MDI_UPLOAD_OUTLINE "\xf3\xb0\xb8\x87" // U+F0E07
#define ICON_MDI_USB "\xf3\xb0\x95\x93" // U+F0553
#define ICON_MDI_USB_C_PORT "\xf3\xb1\xb2\xbf" // U+F1CBF
#define ICON_MDI_USB_FLASH_DRIVE "\xf3\xb1\x8a\x9e" // U+F129E
#define ICON_MDI_USB_FLASH_DRIVE_OUTLINE "\xf3\xb1\x8a\x9f" // U+F129F
#define ICON_MDI_USB_PORT "\xf3\xb1\x87\xb0" // U+F11F0
@ -6970,6 +7037,7 @@
#define ICON_MDI_VIDEO_PLUS "\xf3\xb0\xa6\xb3" // U+F09B3
#define ICON_MDI_VIDEO_PLUS_OUTLINE "\xf3\xb0\x87\x93" // U+F01D3
#define ICON_MDI_VIDEO_STABILIZATION "\xf3\xb0\xa4\x9b" // U+F091B
#define ICON_MDI_VIDEO_STANDARD_DEFINITION "\xf3\xb1\xb2\xa0" // U+F1CA0
#define ICON_MDI_VIDEO_SWITCH "\xf3\xb0\x95\xa9" // U+F0569
#define ICON_MDI_VIDEO_SWITCH_OUTLINE "\xf3\xb0\x9e\x90" // U+F0790
#define ICON_MDI_VIDEO_VINTAGE "\xf3\xb0\xa8\x9c" // U+F0A1C
@ -7120,6 +7188,9 @@
#define ICON_MDI_WATERING_CAN_OUTLINE "\xf3\xb1\x92\x82" // U+F1482
#define ICON_MDI_WATERMARK "\xf3\xb0\x98\x92" // U+F0612
#define ICON_MDI_WAVE "\xf3\xb0\xbc\xae" // U+F0F2E
#define ICON_MDI_WAVE_ARROW_DOWN "\xf3\xb1\xb2\xb0" // U+F1CB0
#define ICON_MDI_WAVE_ARROW_UP "\xf3\xb1\xb2\xb1" // U+F1CB1
#define ICON_MDI_WAVE_UNDERCURRENT "\xf3\xb1\xb3\x80" // U+F1CC0
#define ICON_MDI_WAVEFORM "\xf3\xb1\x91\xbd" // U+F147D
#define ICON_MDI_WAVES "\xf3\xb0\x9e\x8d" // U+F078D
#define ICON_MDI_WAVES_ARROW_LEFT "\xf3\xb1\xa1\x99" // U+F1859

View File

@ -1,436 +0,0 @@
/*
<!-- editor = tree of nodes. levels and objects are nodes, and their widgets are also nodes -->
<!-- you can perform actions on nodes, with or without descendants, top-bottom or bottom-top -->
<!-- these operations include load/save, undo/redo, reset, play/render, ddraw, etc -->
<!-- nodes are saved to disk as a filesystem layout: parents are folders, and leafs are files -->
<!-- network replication can be done by external tools by comparing the filesystems and by sending the resulting zipped .diff -->
- [ ] Editor: Gizmos, scene tree, property editor, load/save, undo/redo, copy/paste, on/off (vis,tick,ddraw,log), vcs.
- [ ] Editor: Scenenode pass: node singleton display, node console, node labels, node outlines.<!-- node == gameobj ? -->
- [ ] Editor: Debug pass: toggles on/off (billboards, materials, un/lit, cast shadows, wireframe, skybox/mie, fog/atmosphere, collide, physics).
- [ ] Editor: Level pass: volumes, triggers, platforms, level streaming.
- [ ] Editor: Edit pass: Procedural content, brushes, noise and CSG.
- [ ] Editor: GUI pass: timeline and data tracks, node graphs. <!-- worthy: will be reused into materials, animgraphs and blueprints -->
*/
#include "v4k.c"
#include "editor2.h" // old editor interface
#define ui_push_hspace(px) \
(int xx = px; xx; xx = 0) \
for(struct nk_panel *layout = ui_ctx->current->layout; layout; ) \
for( xx = (layout->at_x += px, layout->bounds.w -= px, 0); layout; layout->at_x -= px, layout->bounds.w += px, layout = 0 )
// ----------------------------------------------------------------------------------------
#define expr expr2 // 3rd_lua.h
#include "3rd_eval.h"
// ----------------------------------------------------------------------------------------
int *meta_changed(void *value) {
static map(void*,int) changes = 0;
do_once map_init_ptr(changes);
return map_find_or_add(changes, value, 0);
}
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", info);
int changed = 0;
/**/ 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", type, name));
if( changed ) {
*meta_changed(value) = 1;
}
if( ui_label_icon_clicked_L.x >= 6 && ui_label_icon_clicked_L.x <= 26 ) { // @hack: if clicked on UNDO icon (1st icon)
*meta_changed(value) = 0;
}
}
bool reflect_parse(void *obj, const char *type, const char *val) {
/**/ if( !strcmp(type, "int") ) *((int*)obj) = eval(val);
// 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);
else if( !strcmp(type, "unsigned") ) *((unsigned*)obj) = eval(val); // = v[0] == '~' ? (float)~atoi(val+1) : atof(val); // = atof(val);
else if( !strcmp(type, "color") ) *(((float*)obj)+3) = 255, sscanf(val, "%f %f %f %f", ((float*)obj)+0, ((float*)obj)+1, ((float*)obj)+2, ((float*)obj)+3);
else if( !strcmp(type, "vec3") ) sscanf(val, "%f %f %f", ((float*)obj)+0, ((float*)obj)+1, ((float*)obj)+2);
else return 0;
return 1;
}
// ----------------------------------------------------------------------------
#define POD_TYPES \
vec2i v2i; \
vec2 v2; \
vec3 v3; \
vec4 v4; \
quat q; \
char *s; \
double d; \
int64_t i; \
unsigned color; \
void *ptr; \
void (*fun)(void*); \
char *nametype; /* "name\0type" */
typedef union pod {
POD_TYPES
} pod;
typedef union var {
POD_TYPES
array(pod) array;
array(pod) pair; // array of 2: first,second. maybe used as key,value
array(pod) tuple; // array of N: first,second,third... maybe used as array of N*2: NAME1,val1,NAME2,val2, ...
map(pod,pod) map;
set(pod) set;
} var;
typedef struct node {
var k;
var v;
struct node *up;
struct node *next;
struct node *down;
} node;
char* node_name(node *n) {
return n->k.nametype;
}
char* node_type(node *n) {
return n->k.nametype + strlen(n->k.nametype) + 1;
}
char* node_set_nametype(node *n, const char *name, const char *type) {
*strchr(n->k.nametype = stringf("%s\1%s", name, type), '\1') = '\0'; // @leak
return n->k.nametype;
}
node* node_find(node *n, const char *path) {
if (!n->k.nametype) return 0;
if( !strcmp(node_name(n), path) ) return n;
node *r = 0;
if( n->next ) r = node_find(n->next, path);
if( n->down && !r ) if( !strcmp(node_name(n->down), path) ) return n->down; // r = node_find(n->down, path);
return r;
}
node* node_find_recurse(node *n, const char *path) {
array(char*) split = strsplit(path, "/");
while( n && array_count(split) ) {
n = node_find(n, split[0]);
array_pop(split);
}
return n;
}
node* node_attach_sibling(node *n, node *sibling) {
while( n->next ) n = n->next;
return n->next = sibling;
}
node* node_attach_child(node *n, node *child) {
child->up = n;
if( n->down ) return node_attach_sibling(n->down, child);
return n->down = child;
}
unsigned node_children(node *n) {
unsigned c = 0;
if( n->down ) {
n = n->down;
do ++c; while( (n = n->next) );
}
return c;
}
unsigned node_siblings(node *n) {
return n->up ? node_children( n->up->down ) : 0;
}
void node_init(node *n) {
profile_incstat("Editor.inits", +1);
if(n->next) node_init(n->next);
if(n->down) node_init(n->down);
}
void node_tick(node *n) {
profile_incstat("Editor.ticks", +1);
if(n->next) node_tick(n->next);
if(n->down) node_tick(n->down);
}
void node_draw(node *n) {
profile_incstat("Editor.draws", +1);
if(n->next) node_draw(n->next);
if(n->down) node_draw(n->down);
}
void node_quit(node *n) {
profile_incstat("Editor.quits", +1);
if(n->next) node_quit(n->next);
if(n->down) node_quit(n->down);
}
void node_edit(node *n, node *root) {
profile_incstat("Editor.edits", +1);
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( 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
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,
flags[2] ? ICON_MD_CODE : ICON_DOT,
flags[1] ? ICON_MD_FLAG : ICON_DOT,
flags[0] ? ICON_MD_VISIBILITY : ICON_MD_VISIBILITY_OFF
);
ui_label_icon_highlight = *meta_changed(n); // @hack: remove ui_label_icon_highlight hack
char *section = va("*" ICON_MD_UNDO "%s", node_type(n));
int choice = ui_label2_toolbar(section, toolbar);
if( choice ) flags[ choice - 1 ] = (flags[ choice - 1 ] + 1 ) % ( choice == 4 ? 2/*3*/ : 2);
for each_member( node_type(n), R ) {
reflect_ui(R->type, R->name, R->info, n->v.ptr); // @fixme v.ptr
}
}
}
ui_collapse_end();
}
if(n->next) node_edit(n->next,root);
}
// ---
struct editor_t {
unsigned frame;
// root nodes
node init;
node tick;
node draw;
node edit;
node quit;
} editor;
enum { EDITOR_BUCKETS = 5 }; // init+tick+draw+edit+quit
void editor_reset() {
node_quit(&editor.quit);
editor.frame = 0;
}
void editor_frame() {
editor_init(); // old editor interface
editor_tick_(); // old editor interface
editor_menubar(); // old editor interface
if( input_down(KEY_F5) ) {
editor_reset();
}
if( editor.frame++ == 0 ) {
node_init(&editor.init);
}
node_tick(&editor.tick);
node_draw(&editor.draw);
// content browser
if( ui_window("File Browser", 0) ) {
const char *file = 0;
if( ui_browse(&file, NULL) ) {
const char *sep = ifdef(win32, "\"", "'");
app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep));
}
ui_window_end();
}
// console/terminal window
if( 0 && ui_window("Console", 0) ) { // @fixme half-working
ui_console();
ui_window_end();
}
if( ui_window("Outliner", 0) ) {
#if 1
static char *filter = 0;
{
static int do_filter = 0;
int choice = ui_toolbar(ICON_MD_SEARCH ";" ICON_MD_REFRESH ";" ICON_MD_SD_CARD);
if( choice == 1 ) do_filter = 1;
if( do_filter ) {
ui_string(ICON_CANCEL " 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)
do_filter = 0;
}
} else {
if( filter ) filter[0] = '\0';
}
char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*";
}
#endif
for( int c = ui_collapse(ICON_MD_FOLDER_SPECIAL " Art/", "ART"); c; ui_collapse_end(), c = 0) {
static const char *file;
static bool show_browser = 1;
if( ui_browse(&file, &show_browser) ) {
app_exec(va("%s %s", ifdef(win32, "start", ifdef(osx, "open", "xdg-open")), file));
//puts(file);
show_browser = 1;
}
}
for( int c = ui_collapse(ICON_MD_BOOKMARK " Bookmarks/", "BOOK"); c; ui_collapse_end(), c = 0) {
}
for( int c = ui_collapse(ICON_MD_BUBBLE_CHART/*ICON_MD_SCATTER_PLOT*/ " Entities/", "ENT"); c; ui_collapse_end(), c = 0) {
}
for( int c = ui_collapse(ICON_MD_TUNE " Components/", "COM"); c; ui_collapse_end(), c = 0) {
}
for( int c = ui_collapse(ICON_MD_PRECISION_MANUFACTURING " Systems/", "SYS"); c; ui_collapse_end(), c = 0) {
}
for( int c = ui_collapse(ICON_MD_ACCOUNT_TREE " Hierarchy/", "ORD"); c; ui_collapse_end(), c = 0) {
for( int c = ui_collapse(ICON_MD_ACCOUNT_TREE " Init/", "ORD1"); c; ui_collapse_end(), c = 0) {}
for( int c = ui_collapse(ICON_MD_ACCOUNT_TREE " Draw/", "ORD2"); c; ui_collapse_end(), c = 0) {}
for( int c = ui_collapse(ICON_MD_ACCOUNT_TREE " Tick/", "ORD3"); c; ui_collapse_end(), c = 0) {}
for( int c = ui_collapse(ICON_MD_ACCOUNT_TREE " Edit/", "ORD4"); c; ui_collapse_end(), c = 0) {}
for( int c = ui_collapse(ICON_MD_ACCOUNT_TREE " Quit/", "ORD5"); c; ui_collapse_end(), c = 0) {}
// 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);
}
for( int c = ui_collapse(ICON_MD_PUBLIC " World/", "WORLD"); c; ui_collapse_end(), c = 0) {
node_edit(editor.edit.down,&editor.edit);
}
ui_window_end();
}
}
unsigned editor_spawn(const char *path_id, const char *keytype, void *val) {
do_once {
node_set_nametype(&editor.init, "Init Group", "init_nodes"); // @leak
node_set_nametype(&editor.tick, "Tick Group", "tick_nodes"); // @leak
node_set_nametype(&editor.draw, "Draw Group", "draw_nodes"); // @leak
node_set_nametype(&editor.edit, "Edit Group", "edit_nodes"); // @leak
node_set_nametype(&editor.quit, "Quit Group", "quit_nodes"); // @leak
}
array(char*) tokens = strsplit(path_id, "/");
char *keyname = *array_back(tokens);
array(node) n = 0;
array_resize(n, EDITOR_BUCKETS);
for( int i = 0; i < EDITOR_BUCKETS; ++i ) {
node_set_nametype(&n[i], keyname, keytype); // @leak
n[i].v.ptr = val;
}
array_pop(tokens);
char *joint = array_count(tokens) ? strjoin(tokens, "/") : "/";
node *p = 0;
p = node_find_recurse(&editor.init, joint), node_attach_child(p ? p : &editor.init, n+0);
p = node_find_recurse(&editor.tick, joint), node_attach_child(p ? p : &editor.tick, n+1);
p = node_find_recurse(&editor.draw, joint), node_attach_child(p ? p : &editor.draw, n+2);
p = node_find_recurse(&editor.edit, joint), node_attach_child(p ? p : &editor.edit, n+3);
p = node_find_recurse(&editor.quit, joint), node_attach_child(p ? p : &editor.quit, n+4);
return 0;
}
// demo -----------------------------------------------------------------------
typedef struct my_sprite {
char *filename;
vec3 position;
float tilt;
vec4 tint;
// --- private
texture_t texture_;
unsigned bgra_;
} my_sprite;
void my_sprite_ctor(my_sprite *obj) {
obj->texture_ = texture(obj->filename, TEXTURE_RGBA);
obj->bgra_ = bgraf( obj->tint.r/255.0, obj->tint.g/255.0, obj->tint.b/255.0, obj->tint.a/255.0 );
}
void my_sprite_draw(my_sprite *obj) {
obj->bgra_ = bgraf( obj->tint.r/255.0, obj->tint.g/255.0, obj->tint.b/255.0, obj->tint.a/255.0 ); // @fixme: del me
sprite( obj->texture_, &(obj->position.x), obj->tilt, obj->bgra_ );
}
int main() {
typedef char* string;
typedef vec4 color;
STRUCT( vec3, float, x, "X" );
STRUCT( vec3, float, y, "Y" );
STRUCT( vec3, float, z, "Z" );
// STRUCT( texture_t, unsigned, flags, "Flags");
// STRUCT( texture_t, string, filename, "Filename");
STRUCT( my_sprite, string, filename, "Filename" );
STRUCT( my_sprite, vec3, position, "Position" );
STRUCT( my_sprite, float, tilt, "Tilt degrees" );
STRUCT( my_sprite, color, tint, "Tint color" );
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));
// cook_config("../../tools/cook.ini");
window_create(0.80, 0);
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();
while( window_swap() ) {
editor_frame();
// @fixme: this should be drawn by game, not editor!
my_sprite_draw(&spr1);
my_sprite_draw(&spr2);
my_sprite_draw(&spr3);
// spr1.tilt = 5 * sin(time_ss());
}
}

View File

@ -1,343 +0,0 @@
#define EDITOR_VERSION "2022.7"
#if 1
#define EDITOR_PRINTF PRINTF
#else
#define EDITOR_PRINTF(...) do {} while(0)
#endif
#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
// state - retained mode
typedef int property; // @fixme
typedef struct editor_state_t {
array(property) properties;
array(char) buffer;
array(vec2i) history;
unsigned cursor;
} editor_state_t;
typedef map(char*, char*) editor_dict_t;
static map(void*, editor_state_t) editor_state; // world
static map(void*, editor_dict_t) editor_dicts;
static set(void*) editor_world;
static set(void*) editor_selection; // objects selected in scene
// editor controls
//static int editor_attached = 1;
static int editor_enabled = 1;
static void* editor_selected_obj = 0;
static int editor_key = 0;
static vec2 editor_mouse = {0}; // 2d coord for ray/picking
static bool editor_gamepad = 1;
static int editor_hz = 60;
static int editor_hz_mid = 18;
static int editor_hz_low = 5;
static bool editor_power_saving = 0;
static double editor_t = 0, editor_dt = 0;
static bool editor_lit = 1;
static bool editor_ddraw = 1;
static
void editor_init() {
do_once {
map_init_ptr(editor_state);
map_init_ptr(editor_dicts);
set_init_ptr(editor_world);
set_init_ptr(editor_selection);
profiler_enable( false );
window_pause( true );
}
}
void editor_tick_() {
// timing
editor_dt = window_delta() * !window_has_pause(); if(editor_dt > 1/60.f) editor_dt = 1/60.f;
}
bool editor_active() {
return ui_hover() || ui_active() || gizmo_active() ? editor_enabled : 0;
}
double editor_ss() {
return 1000 + editor_t;
}
double editor_delta() {
return editor_dt;
}
void editor_select_all() {}
void editor_select_none() {}
enum editor_keys {
key_none,
key_pause,
key_reload,
key_browser,
key_recording,
key_fullscreen,
key_screenshot, // @todo: add meta-info in exif or invisibile pixels (cam details, player details, map level, map location, level state, etc)
key_quit,
key_mute,
key_battery,
key_profiler,
key_stop,
key_outliner,
key_undo,
key_redo,
key_save_mem,
key_save_disk,
key_load_disk,
key_reset,
key_debugger,
key_gamepad,
key_lit,
key_ddraw,
};
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
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;
if( input_down(KEY_PRINT) ) editor_key = (mods ? key_recording : key_screenshot);
// if( input_down(KEY_W) && input_held(KEY_LCTRL) ) editor_key = key_quit;
if( ctrls ) {
/**/ if( input_down(KEY_Z) ) editor_key = key_undo;
else if( input_down(KEY_Y) ) editor_key = key_redo;
else if( input_down(KEY_S) ) editor_key = key_save_disk;
else if( input_down(KEY_A) ) editor_select_all();
else if( input_down(KEY_D) ) editor_select_none();
}
if( !editor_key && editor_selected_obj ) {
if( input_up(MOUSE_L) ) editor_key = key_save_mem;
if( input_down(MOUSE_R) ) ui_show("Properties", true);
}
// @fixme: send all editor keys to game?
// if( input_repeat(KEY_ESC, 300)) {}
// if( input_repeat(KEY_F1, 300)) {}
// etc...
// menubar
if( ui_menu( ICON_SETTINGS "@Preferences;"
ICON_LANGUAGE " Language;"
ICON_PERSONA " Profile;" // editor account, but also fake profile and 1st party credentials
ICON_SOCIAL " Social;"
ICON_GAME " Game;" //
ICON_KEYBOARD " Keyboard;"
ICON_MOUSE " Mouse;"
ICON_GAMEPAD " Gamepad;"
ICON_MONITOR " Display;" // @todo: RENDER settings, AUDIO settings
ICON_WIFI " Network;"
ICON_BUDGET " Budget;" // mem,gfx,net,hdd,... also logging
ICON_NEW_FOLDER " Folders;" // including project folders
ICON_PLUGIN " Plugins;" // including VCS
ICON_RESTART " Restart;"
ICON_QUIT " Quit;"
"-" ICON_MD_RECYCLING " Reset all preferences;" ICON_MD_SAVE_AS " Save all preferences"
) ) {
if( ui_item() == 3 ) {} // key mappings
if( ui_item() == 4 ) {} // sensitivity, invert xylrw
if( ui_item() == 5 ) {} // sensitivity, invert xy,ab, deadzones
if( ui_item() == 7 ) {} // name,email,icon,link,github
if( ui_item() == 13) editor_key = key_reload;
if( ui_item() == 14) editor_key = key_quit;
}
static char game_args[16] = "--game-args"; // @fixme @todo remove '_' special char to signal that ui_menu() is writeable (inputbox)
if( ui_menu_editbox( game_args, 16 ) ) {}
if( ui_menu( ICON_CANCEL "@Cancel" ) ) {}
if( ui_menu( window_has_pause() ? ICON_PLAY "@Tap to Play Game" : ICON_PAUSE "@Tap to Pause Game" )) editor_key = key_pause;
if( ui_menu( ICON_MD_SKIP_NEXT "@Next frame") ) {}
if( ui_menu( ICON_MD_FAST_FORWARD "@Fast forward") ) {}
//if( ui_menu( ICON_STOP "@Stop game" )) editor_key = key_stop;
if( ui_menu( va(ICON_BUILD "@Build game"))) ui_notify("Build", ICON_WARNING " Not implemented.");
if( ui_menu( va(ICON_MD_ROCKET_LAUNCH "@Launch game"))) ui_notify("Launch", ICON_WARNING " Not implemented.");
// ICON_MD_TROUBLESHOOT -> PROFILER
// ICON_MD_SCHEMA -> GRAPHNODES
// ICON_MD_ACCOUNT_TREE -> GRAPHNODES
// ICON_MD_TIPS_AND_UPDATES -> BULB
// if( ui_menu( ICON_MD_MENU )) {}
// if( ui_menu( ICON_BROWSER "@Content browser" )) editor_key = key_browser;
// if( ui_menu( va(ICON_OUTLINER " %d/%d@World outliner", set_count(editor_selection), map_count(editor_state) ))) editor_key = key_outliner;
if( ui_menu( ICON_SCREENSHOT "@Take Screenshot" )) editor_key = key_screenshot; // MD_SCREENSHOT_MONITOR
if( ui_menu( record_active() ? ICON_CAMERA_OFF "@Stop video recording" : ICON_CAMERA_ON "@Start video recording" )) { if(record_active()) record_stop(); else editor_key = key_recording; }
if( ui_menu( editor_gamepad ? ICON_GAMEPAD_ON "@Gamepad is enabled. Tap to disable." : ICON_GAMEPAD_OFF "@Gamepad is disabled. Tap to enable." )) editor_key = key_gamepad;
if( ui_menu( audio_volume_master(-1) > 0 ? ICON_AUDIO_ON "@Audio is enabled. Tap to mute." : ICON_AUDIO_OFF "@Audio is muted. Tap to enable." )) editor_key = key_mute;
if( ui_menu( window_has_fullscreen() ? ICON_WINDOWED "@Fullscreen. Tap to go Windowed." : ICON_FULLSCREEN "@Windowed. Tap to go Fullscreen." )) editor_key = key_fullscreen;
if( ui_menu( editor_ddraw ? ICON_RENDER_BASIC "@Debug renderer. Tap to go Retail Renderer." : ICON_RENDER_FULL "@Retail renderer. Tap to go Debug Renderer." )) editor_key = key_ddraw; // ICON_MD_ADD_PHOTO_ALTERNATE
if( ui_menu( editor_lit ? ICON_LIGHTS_ON "@Lit. Tap to disable lighting." : ICON_LIGHTS_OFF "@Unlit. Tap to enable lighting." )) editor_key = key_lit;
// 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 *battery_levels[] = { // @todo: remap [7%..100%] -> [0..1] ?
ICON_BATTERY_LEVELS
};
if( ui_menu( !editor_power_saving ? ICON_POWER"@Full power. Tap to save power." :
va("%s@Power saving. Tap to go full power. %3d%% battery.",
battery_read == 0 ? battery_levels[0] :
battery_discharging ? battery_levels[(int)((countof(battery_levels)-1)*clampf(battery_level/100.f,0,1))] :
ICON_BATTERY_CHARGING, battery_level) ))
editor_key = key_battery;
// @todo: combine-in-1? cycle mem -> cpu/profiler -> network mon -> debugger
// bug report, signal status, disk status, framerate status
if( ui_menu(va(ICON_SIGNAL " 0/0KiB" ))) {} // SIGNAL_CELLULAR_1_BAR SIGNAL_CELLULAR_2_BAR
if( ui_menu(va(ICON_DISK " %s", xstats() ))) {} // 012/136MB
if( ui_menu(va(ICON_RATE " %5.2f/%d", window_fps(), (int)window_fps_target()))) editor_key = key_profiler; // 012/136MB
// bug report, profile, warnings, time/chrono (@todo: alarm/snooze? calendar?)
if( ui_menu( ICON_MD_BUG_REPORT /*"^"*/ "0" ) ) {}
if( ui_menu( ICON_MD_FACE /*"^"*/ "3" ) ) {} // @todo: do both messaging/warnings + profile settings here
{
static double base = 0, tap = 0;
if( tap == 0 ) tap = time_ss();
double delta = time_ss() - tap;
tap = time_ss();
base += delta * !window_has_pause();
if( ui_menu( base == 0 ?
va(ICON_CLOCK "%02d:%02d", (int)((date() / 10000) % 100), (int)((date() / 100) % 100))
:
va(ICON_CHRONO "%03dm:%02ds:%02df@Tap to reset chrono.",((int)(base/60))%60,((int)base)%60,(int)((base - (int)base)*window_fps_target())))
|| editor_key == key_stop
) {
base = 0, tap = 0;
}
}
for each_map_ptr(editor_state, void *, o, editor_state_t, ed) {
profile_incstat("Editor.num_objects", +1);
void *obj = *o;
#if 1
#elif 0
// auto-load from disk during init. @fixme kvdb database
if( array_count(ed->history) == 0 )
if( editor_load_disk(obj, editor_obj_string(obj, ".path")) )
{}
// auto-save in-mem during first edit
if( array_count(ed->history) == 0 )
editor_save_mem(obj);
#endif
// @todo: continue if obj not found in selection set
if( obj != editor_selected_obj )
continue;
if( editor_key == key_debugger ) { breakpoint("User requested breakpoint on this object"); }
#if 1
#elif 0
if( editor_key == key_reset ) { const char *ok = editor_reset(obj) ? "ok" : "err"; EDITOR_PRINTF("reset: %s\n", ok); }
if( editor_key == key_save_mem ) { const char *ok = editor_save_mem(obj) ? "ok" : "err"; EDITOR_PRINTF("mem saved: %s\n", ok); }
if( editor_key == key_undo ) { const char *ok = editor_undo(obj) ? "ok" : "err"; EDITOR_PRINTF("undo: %s\n", ok); }
if( editor_key == key_redo ) { const char *ok = editor_redo(obj) ? "ok" : "err"; EDITOR_PRINTF("redo: %s\n", ok); }
if( editor_key == key_save_disk ) { const char *ok = editor_save_disk(obj, editor_obj_string(obj, ".path")) ? "ok" : "err"; EDITOR_PRINTF("save: %s\n", ok); }
if( editor_key == key_load_disk ) { const char *ok = editor_load_disk(obj, editor_obj_string(obj, ".path")) ? "ok" : "err"; EDITOR_PRINTF("load: %s\n", ok); }
#endif
}
char *name;
switch( editor_key ) {
default:
break; case key_quit: record_stop(), exit(0);
break; case key_stop: window_pause(1);
break; case key_mute: audio_volume_master( 1 ^ !!audio_volume_master(-1) );
break; case key_pause: window_pause( window_has_pause() ^ 1 );
break; case key_reload: window_reload();
break; case key_battery: editor_power_saving ^= 1;
break; case key_browser: ui_show("File Browser", ui_visible("File Browser") ^ true);
break; case key_outliner: ui_show("Outliner", ui_visible("Outliner") ^ true);
break; case key_recording: name = file_counter(va("%s.mp4",app_name())), window_record(name), ui_notify(va("Video capturing: %s", name), date_string());
break; case key_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", 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;
break; case key_ddraw: editor_ddraw ^= 1;
}
editor_key = 0;
}

View File

@ -1,386 +0,0 @@
// missing //M(eta), DNA,
// meta_parse(file), meta_load, meta_save
#define REFLECT_C
//#define REFLECT_DEMO
// C reflection: enums, functions, structs, nested structs, members and pointers.
// - rlyeh, public domain
#ifndef REFLECT_H
#define REFLECT_H
// # reflection api
//
// - reflected symbol struct
//
// - define reflected symbol (3 quick macros).
// - define reflected symbol (complete function).
//
// - size of reflected symbol.
// - find reflected function (by name).
// - find reflected enum (by name).
// - find reflected field in struct (by name).
//
// - iterate all reflected fields in struct.
// - iterate all reflected symbols in registry.
//
// - @todo: reflect* reflect_find()
// - @todo: code annotations? "display-name", "min", "max", "range", "default"
// - @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/)
typedef struct reflect {
union {
void *any;
int offs;
};
const char *type, *name, *base, *info;
unsigned size:23, is_pod:1, is_ptr:6, internal_type:2;
} reflect;
#define ENUM(type, name, ...) reflect_add(0, (void*)name, #type, #name, "", "" #__VA_ARGS__ "\0", sizeof(enum type))
#define FUNCTION(type, name, ...) reflect_add(1, &name, #type, #name, "", "" #__VA_ARGS__ "\0", sizeof(void *))
#define STRUCT(struct, type, name, ...) reflect_add(2, &(((struct *)0)->name), #type, #name, #struct, "" #__VA_ARGS__ "\0", (int)sizeof(type) )
void reflect_add( int internal_type, void *any, const char *type, const char *name, const char *base, const char *info, int size );
int reflect_sizeof( const char *type );
void* reflect_function( const char *name );
int reflect_enum( const char *name );
void* reflect_field( const char *type, void *obj, const char *name, const char **opt_type );
bool reflect_has_fields( const char *base, void *obj );
void reflect_iterate_fields( const char *type, void *obj, void (*callback)( const reflect *r, void *value, void *userdata ), void *userdata );
void reflect_iterate_registry( void (*callback)( const reflect *r, void *userdata ), void *userdata );
#endif
// ----------------------------------------------------------------------------
#ifdef REFLECT_C
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef REFLECT_REGISTRY_LIMIT
#define REFLECT_REGISTRY_LIMIT 0 // 0 for unlimited registry size (using heap), or N for fixed max entries (using stack)
#endif
#if REFLECT_REGISTRY_LIMIT > 0
static reflect *registry[REFLECT_REGISTRY_LIMIT] = {0}, registry_[REFLECT_REGISTRY_LIMIT] = {0};
#else
static reflect **registry = 0;
#endif
enum {
REFLECT_TYPE_ENUM,
REFLECT_TYPE_FUNCTION,
REFLECT_TYPE_FIELD,
};
static int reflect_counter = 0;
void reflect_add( int internal_type, void *any, const char *type, const char *name, const char *base, const char *info, int size ) {
++reflect_counter;
#if REFLECT_REGISTRY_LIMIT > 0
registry[reflect_counter-1] = &registry_[reflect_counter-1];
#else
registry = (reflect **)realloc( registry, reflect_counter * sizeof(reflect *));
registry[reflect_counter-1] = (reflect *)malloc( sizeof(reflect) );
#endif
reflect s = { any, type, name, base, info, size, 1, 0, internal_type };
reflect *r = registry[reflect_counter-1];
*r = s;
// evaluate is_ptr
for( int i = strlen(r->type); !r->is_ptr && --i; ) {
r->is_ptr = r->type[i] == '*' ? i : 0;
}
for( int i = r->is_ptr; i >= 0; --i ) {
r->is_ptr = r->type[i] == ' ' ? i : r->is_ptr;
}
// @fixme: try to avoid dynamic allocs
// future me: removing this will break some strcmps(type) below
if( r->is_ptr ) {
char buf[128]; sprintf(buf, "%.*s", r->is_ptr, r->type);
r->type = (const char *)strdup(buf);
}
// evaluate is_pod. kind of bubble sort.
for( int i = 0; i < reflect_counter; ++i ) {
for( int j = 0; j < reflect_counter; ++j ) {
if( !strcmp(registry[i]->base, registry[j]->type) ) {
registry[j]->is_pod = 0;
}
}
}
}
int reflect_sizeof( const char *base ) {
int size = 0;
if( base ) for( int i = 0; i < reflect_counter; ++i ) {
if( !strcmp(registry[i]->base, base) ) size += registry[i]->size;
}
return size;
}
void *reflect_field( const char *base, void *obj, const char *name, const char **opt_type ) {
if( base ) for( int i = 0; i < reflect_counter; ++i ) {
if( registry[i]->internal_type == REFLECT_TYPE_FIELD && strcmp(registry[i]->base, base) ) continue;
if(!strcmp(registry[i]->name, name) ) return (opt_type ? *opt_type = registry[i]->type : NULL), (char*)obj + (long long int)registry[i]->any;
}
return 0;
}
int reflect_enum( const char *name ) {
if( name ) for( int i = 0; i < reflect_counter; ++i ) {
if( registry[i]->internal_type == REFLECT_TYPE_ENUM && !strcmp( registry[i]->name, name ) ) {
return (int)(long long int)registry[i]->any;
}
}
return 0;
}
// do not use void(void) signature here
static void* reflect_dummy_call() {
return 0;
}
void* reflect_function( const char *name ) {
if( name ) for( int i = 0; i < reflect_counter; ++i ) {
if( registry[i]->internal_type == REFLECT_TYPE_FUNCTION && !strcmp( registry[i]->name, name ) ) {
return registry[i]->any;
}
}
return &reflect_dummy_call; // return NULL instead?
}
void reflect_iterate_registry( void (*callback)( const reflect *r, void *userdata ), void *userdata ) {
for( int i = 0; i < reflect_counter; ++i ) {
callback( registry[i], userdata );
}
}
#ifdef _MSC_VER
__declspec(thread)
#else
__thread
#endif
struct reflect_context {
const char *name;
const char *info;
} reflect_ctx = { "", "" };
void reflect_iterate_fields( const char *base, void *obj, void (*callback)( const reflect *r, void *value, void *userdata ), void *userdata ) {
if( base ) for( int i = 0, nb = strlen(base); i < reflect_counter; ++i ) {
if( registry[i]->internal_type == REFLECT_TYPE_FIELD && !strncmp(registry[i]->base, base, nb) ) {
for( ; i < reflect_counter && !strncmp(registry[i]->base, base, nb); ++i ) {
void *any = ((char*)obj + (long long int)registry[i]->any);
if( any && registry[i]->is_ptr ) {
any = (void*)*((long long int *)any);
}
if( any ) {
struct reflect_context copy = reflect_ctx;
char buf1[128]; sprintf(buf1, "%s.%s", reflect_ctx.name, registry[i]->name);
char buf2[128] = {0}; if( registry[i]->info[0] ) sprintf(buf2, "%s%s%.*s", reflect_ctx.info, reflect_ctx.info[0] ? " > " : "", (int)(strlen(registry[i]->info) - 2), 1+registry[i]->info);
reflect_ctx.name = buf1 + (buf1[0] == '.');
reflect_ctx.info = buf2;
if( registry[i]->is_pod ) {
reflect m = *registry[i];
m.name = reflect_ctx.name;
m.info = reflect_ctx.info;
callback( &m, any, userdata );
} else {
char buf3[128], *rebase = (char*)registry[i]->type;
if(registry[i]->is_ptr) sprintf( rebase = buf3, "%.*s", registry[i]->is_ptr, registry[i]->type );
reflect_iterate_fields( rebase, any, callback, userdata );
}
reflect_ctx = copy;
}
}
return;
}
}
}
bool reflect_has_fields( const char *base, void *obj ) {
if( base ) for( int i = 0, nb = strlen(base); i < reflect_counter; ++i ) {
if( registry[i]->internal_type == REFLECT_TYPE_FIELD && !strncmp(registry[i]->base, base, nb) ) {
for( ; i < reflect_counter && !strncmp(registry[i]->base, base, nb); ++i ) {
return true;
}
}
}
return false;
}
void reflect_dump_registry(FILE *fp) {
fprintf( fp, "%s {\n", __FUNCTION__ );
fprintf( fp, "\tsizeof(reflect)=%d\n", (int)sizeof(reflect) );
for( int i = 0; i < reflect_counter; ++i ) {
reflect *r = registry[i];
/**/ if( r->internal_type == REFLECT_TYPE_FUNCTION )
fprintf(fp, "\tfunction %s = %s; // %d@[%p] %s\n", r->name, r->type, r->size, r->any, r->info);
else if( r->internal_type == REFLECT_TYPE_ENUM )
fprintf(fp, "\tenum %s%s%s = %d; // %d %s\n", r->type[0] ? r->type : "", r->type[0] ? "." : "", r->name, (int)(long long int)r->any, r->size, r->info );
else if( r->internal_type == REFLECT_TYPE_FIELD )
fprintf(fp, "\t%s%s%s %s.%s; // %d@%d %s\n", r->is_pod ? "field " : "struct ", r->type, r->is_ptr ? "*" : "", r->base, r->name, r->size, (int)(long long int)r->any, r->info );
}
fprintf( fp, "} %s\n", __FUNCTION__ );
}
#endif
// ----------------------------------------------------------------------------
#ifdef META_DEMO_IMMEDIATE
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
void echo( const reflect *r, void *value, void *userdata ) {
FILE *fp = (FILE*)userdata;
if( fp ) {
/**/ if( !strcmp(r->type, "int") ) fprintf(fp, "%6s %-32s = %d;\t// %s\n", r->type, r->name, *(int*)value, r->info);
else if( !strcmp(r->type, "string") ) fprintf(fp, "%6s %-32s = %s;\t// %s\n", r->type, r->name, *(char**)value, r->info);
else if( !strcmp(r->type, "float") ) fprintf(fp, "%6s %-32s = %f;\t// %s\n", r->type, r->name, *(float*)value, r->info);
else if( !strcmp(r->type, "double") ) fprintf(fp, "%6s %-32s = %f;\t// %s\n", r->type, r->name, *(double*)value, r->info);
}
}
enum MY_ENUM {
TEXTURE = 101,
IMAGE = 102,
};
typedef char* string;
typedef struct MyVec3 {
double x,y,z;
} MyVec3;
typedef struct MyTransform {
MyVec3 location;
MyVec3 rotation;
float scale;
} MyTransform;
typedef struct MyObject {
struct MyObject *parent;
string id;
int hash;
MyTransform transform;
} MyObject;
int MyAddFunction( int a,int b ) {
return a + b;
}
int main( int argc, char **argv ) {
// # enums
// - register
// - reflect
ENUM( MY_ENUM, TEXTURE );
ENUM( MY_ENUM, IMAGE );
assert( 101 == reflect_enum("TEXTURE") );
assert( 102 == reflect_enum("IMAGE") );
// # functions
// - register
// - find
// - call
// - try call (undefined functions are also safe to call)
FUNCTION( int(int a, int b), MyAddFunction, "Function adding two numbers" );
FUNCTION( int(const char *fmt, ...), printf, "Print text to console" );
int (*add_hook)() = reflect_function("MyAddFunction");
int (*print_hook)(const char *, ...) = reflect_function("printf");
assert( 123 == add_hook(100,23) );
print_hook("hello from reflected function %d\n", 123);
print_hook = reflect_function("undefined_symbol_here$(·!!");
print_hook("this call should never print\n");
puts("---");
// # structs
// - register simple
// - register nested
// - register nested with pointers
// - print struct sizes
// - iterate simple
// - iterate nested
// - iterate nested with pointers
STRUCT( MyVec3, double, x, "Right" );
STRUCT( MyVec3, double, y, "Forward" );
STRUCT( MyVec3, double, z, "Up" );
STRUCT( MyTransform, MyVec3, location, "World location (absolute)" );
STRUCT( MyTransform, MyVec3, rotation, "Local rotation (in degrees)" );
STRUCT( MyTransform, float, scale, "Local scale (in centimeters)" );
STRUCT( MyObject, int, hash, "Actor hash" );
STRUCT( MyObject, string, id, "Actor name" );
STRUCT( MyObject, MyTransform, transform, "Actor transform" );
STRUCT( MyObject, MyObject *, parent, "Actor parent" );
printf("reflect_sizeof(MyVec3)=%d\n", reflect_sizeof("MyVec3"));
printf("reflect_sizeof(MyTransform)=%d\n", reflect_sizeof("MyTransform"));
printf("reflect_sizeof(MyObject)=%d\n", reflect_sizeof("MyObject"));
puts("---");
MyVec3 vec = {1.1,2.2,3.3};
reflect_iterate_fields( "MyVec3", &vec, echo, stdout );
puts("---");
MyTransform tf = { {1.1,2.2,3.3}, {45,90,180}, 10 };
reflect_iterate_fields( "MyTransform", &tf, echo, stdout );
puts("---");
MyObject root = { NULL, "Scene root", 0, { {0,0,0}, {0,0,0}, 1 } };
MyObject obj = { &root, "Name identifier", 123, { {1.1,2.2,3.3}, {45,90,180}, 10 } };
reflect_iterate_fields( "MyObject", &obj, echo, stdout );
puts("---");
// # dump internals
reflect_dump_registry(stdout);
puts("---");
// # benchmark
#ifndef N
#define N (argc > 1 ? atoi(argv[1]) : 500 * 1000)
#endif
clock_t t0 = clock();
for( int i = 0; i < N; ++i) {
reflect_iterate_fields( "MyObject", &obj, echo, NULL );
}
clock_t t1 = clock();
double t = (t1 - t0) / (double)CLOCKS_PER_SEC;
printf("Benchmark: processed %.f members in %5.2fs = %5.2f members/sec\n", N*9.0, t, (N*9.0)/t ); // 9 total members in MyObject
}
#endif

View File

@ -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

View File

@ -1,17 +1,3 @@
// 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) {
@ -56,138 +42,3 @@ void *obj_mutate(void **dst_, const void *src) {
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(&copy, obj);
obj_hexdump(copy);
obj_del(copy);
}
{
MyObject *copy = obj_new(MyObject, "A different identifier!", 0x33, 0x44, 0.0f, root );
obj_copy(&copy, obj);
obj_hexdump(copy);
obj_del(copy);
}
{
void *copy = obj_malloc(100, "an untyped class" );
obj_mutate(&copy, obj);
obj_hexdump(copy);
obj_copy(&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()
}