sync fwk
|
@ -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);
|
||||
|
|
|
@ -1,12 +1,7 @@
|
|||
#include "v4k.h"
|
||||
|
||||
void handle_crash() {
|
||||
alert("crash!");
|
||||
}
|
||||
|
||||
int main() {
|
||||
trap_install();
|
||||
atexit(handle_crash);
|
||||
app_crash();
|
||||
return 0;
|
||||
}
|
|
@ -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.
|
|
@ -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
|
After Width: | Height: | Size: 258 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 112 KiB |
After Width: | Height: | Size: 415 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 117 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 354 KiB |
After Width: | Height: | Size: 440 KiB |
After Width: | Height: | Size: 213 KiB |
After Width: | Height: | Size: 165 KiB |
After Width: | Height: | Size: 402 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 256 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 387 B |
After Width: | Height: | Size: 256 KiB |
After Width: | Height: | Size: 298 KiB |
After Width: | Height: | Size: 387 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 199 KiB |
|
@ -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;
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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");
|
||||
} )
|
|
@ -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 { \
|
||||
|
|
|
@ -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");
|
||||
} )
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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") {
|
||||
|
|
113
engine/v4k.c
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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] = ®istry_[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
|
||||
|
|
@ -21,9 +21,9 @@ cl ..\editor2.c -I ..\..\tools -DCOOK_ON_DEMAND
|
|||
pushd ..\.. && call make amalgamation && popd
|
||||
|
||||
taskkill /im "oscedit.exe" > nul 2> nul
|
||||
call ..\..\tools\tcc oscgame.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||
call ..\..\tools\tcc oscsend.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||
call ..\..\tools\tcc oscedit.c -I ..\.. -DV4K_IMPLEMENTATION -DCOOK_ON_DEMAND %* && start oscedit.exe
|
||||
call ..\..\tools\tcc oscgame.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||
call ..\..\tools\tcc oscsend.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %*
|
||||
call ..\..\tools\tcc oscedit.c -I ..\.. -DFWK_IMPLEMENTATION -DCOOK_ON_DEMAND %* && start oscedit.exe
|
||||
|
||||
timeout 3
|
||||
|
||||
|
|
|
@ -1,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(©, obj);
|
||||
obj_hexdump(copy);
|
||||
obj_del(copy);
|
||||
}
|
||||
|
||||
{
|
||||
MyObject *copy = obj_new(MyObject, "A different identifier!", 0x33, 0x44, 0.0f, root );
|
||||
obj_copy(©, obj);
|
||||
obj_hexdump(copy);
|
||||
obj_del(copy);
|
||||
}
|
||||
|
||||
{
|
||||
void *copy = obj_malloc(100, "an untyped class" );
|
||||
obj_mutate(©, obj);
|
||||
obj_hexdump(copy);
|
||||
obj_copy(©, obj);
|
||||
obj_hexdump(copy);
|
||||
obj_del(copy);
|
||||
}
|
||||
|
||||
// Benchmarking call overhead.
|
||||
// We're here using dtor as a method to test. Since there is actually no
|
||||
// destructor associated to this class, it will be safe to call it extensively (no double frees).
|
||||
//
|
||||
// results:
|
||||
// 427 million calls/s @ old i5-4300/1.90Ghz laptop. compiled with "cl /Ox /Os /MT /DNDEBUG /GL /GF /arch:AVX2"
|
||||
|
||||
#ifndef N
|
||||
#define N (INT32_MAX-1)
|
||||
#endif
|
||||
|
||||
double t = (puts("benchmarking..."), -clock() / (double)CLOCKS_PER_SEC);
|
||||
for( int i = 0; i < N; ++i ) {
|
||||
dtor(root);
|
||||
}
|
||||
t += clock() / (double)CLOCKS_PER_SEC;
|
||||
printf("Benchmark: %5.2f objcalls/s %5.2fM objcalls/s\n", N/(t), (N/1000)/(t*1000)); // ((N+N)*5) / (t) );
|
||||
|
||||
}
|
||||
|
||||
void tests2() {
|
||||
REGISTER_BOX
|
||||
REGISTER_RECT
|
||||
|
||||
box *b = obj_new(box, 100);
|
||||
rect *r = obj_new(rect, 100, 200);
|
||||
|
||||
dump(b);
|
||||
dump(r);
|
||||
|
||||
printf("%f\n", area(b));
|
||||
printf("%f\n", area(r));
|
||||
|
||||
obj_del(b);
|
||||
obj_ref(r); obj_unref(r); //obj_del(r);
|
||||
|
||||
int *untyped = obj_malloc( sizeof(int) );
|
||||
int *my_number = obj_malloc( sizeof(int), "a comment about my_number" );
|
||||
char *my_text = obj_malloc( 32, "some debug info here" );
|
||||
|
||||
*untyped = 100;
|
||||
*my_number = 123;
|
||||
sprintf( my_text, "hello world" );
|
||||
|
||||
struct my_bitmap { int w, h, bpp; const char *pixels; };
|
||||
struct my_bitmap *my_bitmap = obj_new(struct my_bitmap, 2,2,8, "\1\2\3\4");
|
||||
|
||||
printf( "%p(%s,%u)\n", my_bitmap, obj_typeof(my_bitmap), obj_typeid(my_bitmap) );
|
||||
printf( "%d(%s,%d)\n", *untyped, obj_typeof(untyped), obj_typeid(untyped) );
|
||||
printf( "%d(%s,%d)\n", *my_number, obj_typeof(my_number), obj_typeid(my_number) );
|
||||
printf( "%s(%s,%d)\n", my_text, obj_typeof(my_text), obj_typeid(my_text) );
|
||||
|
||||
obj_printf(my_text, "hello world #1\n");
|
||||
obj_printf(my_text, "hello world #2\n");
|
||||
puts(obj_output(my_text));
|
||||
|
||||
printf( "%s(%s,%d)\n", my_text, obj_typeof(my_text), obj_typeid(my_text) );
|
||||
|
||||
printf( "equal?:%d\n", obj_typeeq(my_number, untyped) );
|
||||
printf( "equal?:%d\n", obj_typeeq(my_number, my_number) );
|
||||
printf( "equal?:%d\n", obj_typeeq(my_number, my_text) );
|
||||
printf( "equal?:%d\n", obj_typeeq(my_number, my_bitmap) );
|
||||
|
||||
obj_free( untyped );
|
||||
obj_free( my_text );
|
||||
obj_free( my_bitmap );
|
||||
obj_del( my_number ); // should not crash, even if allocated with obj_malloc()
|
||||
}
|
||||
|
|