main
Dominik Madarász 2023-11-26 16:06:55 +01:00
parent 5540ff54ca
commit 4291c2590b
24 changed files with 1026 additions and 765 deletions

View File

@ -93,6 +93,122 @@ TODO("bug: missing code completions popup")
// https://github.com/rxi/lite/commit/236a585756cb9fa70130eee6c9a604780aced424 > suru.png
// https://github.com/rxi/lite/commit/f90b00748e1fe1cd2340aaa06d2526a1b2ea54ec
#if 0 // good UI/UX blender ideas
ui density is perfect: font face, font size and icon sizes are perfect even in a low res 1366x768 scenario
viewport: not cluttered at all. vertical floating toolbar on the left, floating icons on the right
left icons are tools related to current edition mode, right icons are camera only.
left icons can be long pressed for a hovered submenu, right icons can be clicked or dragged.
non-matching text filtering works by disabling widgets, not by hiding them
window contents can be promoted to any display any other window content by clicking their [icon V]
there are no windows or minimize/maximize buttons
windows are grouped with a vertical toolbar inside the right bar docked section
you can only display 1 window at time.
panels can be dragged within a window and make much more sense than our approach
scene tree: can make collections/groups
widget tree drawing is much simpler than us, just a vertical parent line per collection and indented arrows per child
context menus are always like: optional icon (white), text (white), either optional input binding (gray) or submenu arrow
input boxes are super reactive
< > are hidden unless hovered
< > can be clicked to de/increment (release)
< > can be horizontally dragged to de/increment larger quantities (hold)
< > can be vertically dragged to include other Y,Z properties in the selection (hold)
0.53m can be clicked (release) or dragged (<-> hovered icon) (hold).
0.53m whole text is automatically selected when clicked.
you can enter units when entering values 350m, 350km, 12mi
you can enter math values: 30+20+sin(1)
numeric: units always specified: 0 m, 90o, 1.25x
numeric: epsilons (non-zero) displayed as -0.00000 even if digits cannot fit widget rect
operation context is split into different sections in menu bar: modeling, sculpting, uv editing, shading, anim, etc
cam 3d orientation gizmo top right: can be dragged (orbit cam) or clicked (reposition)
rotation gizmo: anchor can be positioned within world
gizmo: will display always initial position while dragging, and tape distance so far
right floating icons can be dragged: cam orientation, cam panning, cam zooming, cam iso/dimetric
ctrl-z undo, ctrl-shift-z redo
#endif
static const char* codepoint_to_utf8_(unsigned c) { //< @r-lyeh
static char s[4+1];
memset(s, 0, 5);
/**/ if (c < 0x80) s[0] = c, s[1] = 0;
else if (c < 0x800) s[0] = 0xC0 | ((c >> 6) & 0x1F), s[1] = 0x80 | ( c & 0x3F), s[2] = 0;
else if (c < 0x10000) s[0] = 0xE0 | ((c >> 12) & 0x0F), s[1] = 0x80 | ((c >> 6) & 0x3F), s[2] = 0x80 | ( c & 0x3F), s[3] = 0;
else if (c < 0x110000) s[0] = 0xF0 | ((c >> 18) & 0x07), s[1] = 0x80 | ((c >> 12) & 0x3F), s[2] = 0x80 | ((c >> 6) & 0x3F), s[3] = 0x80 | (c & 0x3F), s[4] = 0;
return s;
}
bool is_hovering(vec4 rect, vec2 mouse) { // rect(x,y,x2,y2)
if( mouse.x < rect.x ) return 0;
if( mouse.x > rect.z ) return 0;
if( mouse.y < rect.y ) return 0;
if( mouse.y > rect.w ) return 0;
return 1;
}
vec4 editor_toolbar_drag; // xy mouse, z time
vec4 editor_toolbar_rect;
int editor_toolbar_hovered() {
return is_hovering(editor_toolbar_rect, vec2(input(MOUSE_X),input(MOUSE_Y)));
}
vec2 editor_toolbar_dragged() {
return vec2( editor_toolbar_drag.x, editor_toolbar_drag.y );
}
int editor_toolbar(int x, int y, int incw, int inch, const char *sym) {
array(uint32_t) codepoints = string32(sym);
if( incw < 0 ) return editor_toolbar(x + incw * (array_count(codepoints)-1), y, -incw, inch, sym);
if( inch < 0 ) return editor_toolbar(x, y + inch * (array_count(codepoints)-1), incw, -inch, sym);
int mx = input(MOUSE_X);
int my = input(MOUSE_Y);
int inc = maxi(incw, inch);
static int ox = 0, oy = 0, dragging = 0; // drag origin
editor_toolbar_rect = vec4(x,y,x + (incw ? incw * array_count(codepoints) : inch), y + (inch ? inch * array_count(codepoints) : incw) );
int oo = is_hovering(editor_toolbar_rect, vec2(ox,oy));
int ix = x, iy = y;
for each_array(codepoints, uint32_t, g) {
int selected = oo ? is_hovering(vec4(ix,iy,ix+inc,iy+inc),vec2(ox,oy)) : 0;
int hovering = dragging ? 0 : is_hovering(vec4(ix,iy,ix+inc,iy+inc), vec2(mx,my));
const char *str8 = va("%s%s", selected || hovering ? FONT_COLOR1 : FONT_COLOR2, codepoint_to_utf8_(g));
editor_symbol(ix + inc/8, iy + inc/3 + 2, str8);
ix += incw;
iy += inch;
}
// debug:
// ddraw_push_2d();
// ddraw_aabb(vec3(editor_toolbar_rect.x,editor_toolbar_rect.y,0),vec3(editor_toolbar_rect.z,editor_toolbar_rect.w,0));
// ddraw_pop_2d();
if( 1 ) // is_hovering(editor_toolbar_rect, vec2(mx,my)) )
{
if( input_down(MOUSE_L) && editor_toolbar_hovered() ) {
window_cursor_shape(0);
editor_toolbar_drag = vec4(0,0, mx,my);
ox = mx, oy = my, dragging = 1;
int mcx = ((ox - x) / inc) + 1, mcy = ((oy - y) / inc) + 1; // mouse cells
return incw ? -mcx : -mcy;
}
if( input(MOUSE_L) && dragging ) {
int mcx = ((ox - x) / inc) + 1, mcy = ((oy - y) / inc) + 1; // mouse cells
editor_toolbar_drag.x = mx - editor_toolbar_drag.z;
editor_toolbar_drag.y = my - editor_toolbar_drag.w;
API void editor_cursorpos(int x, int y);
editor_cursorpos(ox, oy);
editor_toolbar_drag.z = ox;
editor_toolbar_drag.w = oy;
return incw ? -mcx : -mcy;
}
if( input_up(MOUSE_L) && dragging ) {
int mcx = ((ox - x) / inc) + 1, mcy = ((oy - y) / inc) + 1; // mouse cells
window_cursor_shape(CURSOR_SW_AUTO);
ox = oy = 0, dragging = 0;
return incw ? mcx : mcy;
}
}
editor_toolbar_drag = vec4(0,0,0,0);
return 0;
}
// ----------------------------------------------------------------------------
// demo
@ -327,13 +443,14 @@ void game(unsigned frame, float dt, double t) {
window_cursor( !active );
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed * active);
camera_moveby(&cam, wasdecq);
camera_fps(&cam, mouse.x,mouse.y);
// draw world
ddraw_ontop_push(0);
ddraw_grid(0);
ddraw_grid(0); // 1+10+100
ddraw_grid(1000);
ddraw_ontop_pop();
ddraw_flush();
@ -344,6 +461,8 @@ void game(unsigned frame, float dt, double t) {
}
int main(){
argvadd("--cook-on-demand");
// borderless, see:
// https://github.com/glfw/glfw/pull/1420
// https://github.com/glfw/glfw/pull/987
@ -351,14 +470,27 @@ int main(){
// https://github.com/glfw/glfw/pull/990
window_title("Editor " EDITOR_VERSION);
if( flag("--transparent") )
window_create(101, 0);
else
window_create(80, flag("--windowed") ? 0 : WINDOW_BORDERLESS);
window_create( flag("--transparent") ? 101 : 80, flag("--windowed") ? 0 : WINDOW_BORDERLESS);
window_icon("scale-ruler-icon.png");
while( window_swap() ) {
editor_frame(game);
editor_gizmos(2);
int choice1 = editor_toolbar(window_width()-32, ui_has_menubar() ? 34 : 0, 0, 32, ICON_MD_VISIBILITY ICON_MD_360 ICON_MD_ZOOM_OUT_MAP ICON_MD_GRID_ON ); // ICON_MDI_ORBIT ICON_MDI_LOUPE ICON_MDI_GRID );
//int choice2 = editor_toolbar(window_width()-32*2, ui_has_menubar() ? 34 : 0, -32, 0, ICON_MD_360 ICON_MD_ZOOM_OUT_MAP ICON_MD_GRID_ON ); // ICON_MDI_ORBIT ICON_MDI_LOUPE ICON_MDI_GRID );
if( choice1 > 0 ) { // clicked[>0]
camera_t *cam = camera_get_active();
if( choice1 == 4 ) cam->orthographic ^= 1, camera_fps(cam, 0, 0);
}
if( choice1 < 0 ) { // dragged[<0]
vec2 mouse_sensitivity = vec2(0.1, -0.1); // sensitivity + polarity
vec2 drag = mul2( editor_toolbar_dragged(), mouse_sensitivity );
camera_t *cam = camera_get_active();
if( choice1 == -1 ) camera_fps(cam, drag.x, drag.y );
if( choice1 == -2 ) camera_orbit(cam, drag.x, drag.y, 0); //len3(cam->position) );
if( choice1 == -3 ) camera_fov(cam, cam->fov += drag.y - drag.x);
}
}
}

View File

@ -14331,12 +14331,6 @@ extern "C" {
static void fn(void)
#endif
#if 0 // autorun demo
void byebye(void) { puts("seen after main()"); }
AUTORUN { puts("seen before main()"); }
AUTORUN { puts("seen before main() too"); atexit( byebye ); }
#endif
// -----------------------------------------------------------------------------
// build info
@ -15334,32 +15328,32 @@ void* obj_free(void *o);
#define obj_vtable(method,RC,...) RC macro(obj_##method)(){ __VA_ARGS__ }; RC (*obj_##method[256])() = { REPEAT256(macro(obj_##method)) };
#define obj_vtable_null(method,RC) RC (*obj_##method[256])() = { 0 }; // null virtual table. will crash unless obj_extend'ed
#define REPEAT16(f) f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f
#define REPEAT64(f) REPEAT16(f),REPEAT16(f),REPEAT16(f),REPEAT16(f)
#define REPEAT256(f) REPEAT64(f),REPEAT64(f),REPEAT64(f),REPEAT64(f)
#define REPEAT16(f) f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f ///-
#define REPEAT64(f) REPEAT16(f),REPEAT16(f),REPEAT16(f),REPEAT16(f) ///-
#define REPEAT256(f) REPEAT64(f),REPEAT64(f),REPEAT64(f),REPEAT64(f) ///-
#undef EXTEND
#define EXTEND(...) EXPAND(EXTEND, __VA_ARGS__)
#define EXTEND2(o,F1) obj_extend(o,F1)
#define EXTEND3(o,F1,F2) obj_extend(o,F1), obj_extend(o,F2)
#define EXTEND4(o,F1,F2,F3) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3)
#define EXTEND5(o,F1,F2,F3,F4) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4)
#define EXTEND6(o,F1,F2,F3,F4,F5) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5)
#define EXTEND7(o,F1,F2,F3,F4,F5,F6) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6)
#define EXTEND8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7)
#define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8)
#define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9)
#define EXTEND2(o,F1) obj_extend(o,F1) ///-
#define EXTEND3(o,F1,F2) obj_extend(o,F1), obj_extend(o,F2) ///-
#define EXTEND4(o,F1,F2,F3) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3) ///-
#define EXTEND5(o,F1,F2,F3,F4) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4) ///-
#define EXTEND6(o,F1,F2,F3,F4,F5) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5) ///-
#define EXTEND7(o,F1,F2,F3,F4,F5,F6) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6) ///-
#define EXTEND8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7) ///-
#define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8) ///-
#define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9) ///-
#define EXTEND_T(...) EXPAND(EXTEND_T, __VA_ARGS__)
#define EXTEND_T2(o,F1) obj_extend_t(o,F1)
#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2)
#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3)
#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4)
#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5)
#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6)
#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7)
#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8)
#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9)
#define EXTEND_T2(o,F1) obj_extend_t(o,F1) ///-
#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2) ///-
#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3) ///-
#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4) ///-
#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5) ///-
#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6) ///-
#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7) ///-
#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8) ///-
#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9) ///-
// --- declare vtables
@ -17694,6 +17688,12 @@ API void ddraw_prism(vec3 center, float radius, float height, vec3 normal, int s
API void ddraw_demo();
API void ddraw_flush();
API void ddraw_flush_projview(mat44 proj, mat44 view);
// transform gizmos
API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
API bool gizmo_active();
API bool gizmo_hover();
#line 0
#line 1 "v4k_scene.h"
@ -17713,6 +17713,11 @@ typedef struct camera_t {
float look_friction, look_damping;
vec2 last_look; vec3 last_move; // used for friction and damping
bool damping;
bool orthographic; // 0 perspective, 1 orthographic; when ortho: dimetric[if pitch == -30o], isometric[if pitch == 35.264o]
float distance; // distance to pivot, when orbiting
// vec2 polarity = { +1,-1 }; // @todo
// vec2 sensitivity = { 2,2 }; // @todo
} camera_t;
API camera_t camera();
@ -18118,6 +18123,7 @@ API void thread_destroy( void *thd );
API int argc();
API char* argv(int);
API void argvadd(const char *arg);
API int flag(const char *commalist); // --arg // app_flag?
API const char* option(const char *commalist, const char *defaults); // --arg=string or --arg string
@ -18600,6 +18606,7 @@ API void window_setclipboard(const char *text);
#define EDITOR_VERSION "2023.10"
// ----------------------------------------------------------------------------
// editor bindings
typedef struct editor_bind_t {
const char *command;
@ -18613,6 +18620,7 @@ API void editor_addbind(editor_bind_t bind);
void macro(editor_bind_##CMD##_fn_)() { __VA_ARGS__ }; AUTORUN { array_push(editor_binds, ((editor_bind_t){#CMD,KEYS,macro(editor_bind_##CMD##_fn_)}) ); }
// ----------------------------------------------------------------------------
// editor properties
#define EDITOR_PROPERTYDEF(T,property_name) \
typedef map(void*,T) editor_##property_name##_map_t; \
@ -18622,25 +18630,26 @@ API void editor_set##property_name(const void *obj, T value); \
API void editor_alt##property_name(const void *obj); \
API void editor_no##property_name(void *obj);
EDITOR_PROPERTYDEF(int, open); // whether object is tree opened in tree editor
EDITOR_PROPERTYDEF(int, selected); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, changed); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, popup); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, bookmarked);
EDITOR_PROPERTYDEF(int, visible);
EDITOR_PROPERTYDEF(int, script);
EDITOR_PROPERTYDEF(int, event);
EDITOR_PROPERTYDEF(char*,iconinstance);
EDITOR_PROPERTYDEF(char*,iconclass);
EDITOR_PROPERTYDEF(int, treeoffsety);
EDITOR_PROPERTYDEF(int, open); ///- whether object is tree opened in tree editor
EDITOR_PROPERTYDEF(int, selected); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, changed); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, popup); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, bookmarked); ///-
EDITOR_PROPERTYDEF(int, visible); ///-
EDITOR_PROPERTYDEF(int, script); ///-
EDITOR_PROPERTYDEF(int, event); ///-
EDITOR_PROPERTYDEF(char*,iconinstance); ///-
EDITOR_PROPERTYDEF(char*,iconclass); ///-
EDITOR_PROPERTYDEF(int, treeoffsety); ///-
API void editor_destroy_properties(void *o);
API void editor_load_on_boot(void);
API void editor_save_on_quit(void);
// ----------------------------------------------------------------------------
// editor ui
enum {
enum EDITOR_MODE {
EDITOR_PANEL,
EDITOR_WINDOW,
EDITOR_WINDOW_NK,
@ -18650,6 +18659,9 @@ enum {
API int editor_begin(const char *title, int mode);
API int editor_end(int mode);
// ----------------------------------------------------------------------------------------
// editor selection
API int editor_filter();
API void editor_select(const char *mask);
API void editor_unselect(); // same than editor_select("!**");
@ -18660,6 +18672,7 @@ API void* editor_first_selected();
API void* editor_last_selected();
// ----------------------------------------------------------------------------------------
// editor instancing
API void editor_addtoworld(obj *o);
API void editor_watch(const void *o);
@ -18670,44 +18683,34 @@ API void editor_destroy_selected();
API void editor_inspect(obj *o);
// ----------------------------------------------------------------------------------------
// tty
API int editor_send(const char *cmd); // return job-id
API const char* editor_recv(int jobid, double timeout_ss);
API void editor_pump();
// ----------------------------------------------------------------------------------------
API void editor_symbol(int x, int y, const char *sym);
API void editor_frame( void (*game)(unsigned, float, double) );
API void editor_gizmos(int dim);
// ----------------------------------------------------------------------------------------
API int editor_send(const char *command);
// editor utils
//API void editor();
//API bool editor_active();
API vec3 editor_pick(float mouse_x, float mouse_y);
API char* editor_path(const char *path);
API void editor_symbol(int x, int y, const char *sym);
API void editor_gizmos(int dim);
// ----------------------------------------------------------------------------------------
// editor loop
API int editor_send(const char *cmd); // returns job-id
API const char* editor_recv(int jobid, double timeout_ss);
API void editor_pump();
API void editor_frame( void (*game)(unsigned, float, double) );
// ----------------------------------------------------------------------------------------
// engine section: @todo: expand me
API float* engine_getf(const char *key);
API int* engine_geti(const char *key);
API char** engine_gets(const char *key);
API int engine_send(const char *cmd, const char *optional_value);
API int ui_debug();
// open file dialog
API char* dialog_load();
API char* dialog_save();
// transform gizmos
API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
API bool gizmo_active();
API bool gizmo_hover();
API int ui_engine();
#line 0
// ----
@ -18722,13 +18725,13 @@ API bool gizmo_hover();
#include <GLFW/glfw3.h>
#include <emscripten.h>
#include <emscripten/html5.h>
#define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK)
#define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK) ///-
#else
#if is(win32) /*&& is(tcc)*/ // && ENABLE_DLL
#ifdef GLAD_API_CALL
#undef GLAD_API_CALL
#endif
#define GLAD_API_CALL extern API
#define GLAD_API_CALL extern API ///-
#endif
#ifndef GLAD_GL_H_
#include "v4k"
@ -346213,8 +346216,12 @@ static void gleq_key_callback(GLFWwindow* window, int key, int scancode, int act
event->type = GLEQ_KEY_REPEATED;
}
static void (*gleq_char_callback_prev)(GLFWwindow* window, unsigned int codepoint) = 0;
static void gleq_char_callback(GLFWwindow* window, unsigned int codepoint)
{
if( gleq_char_callback_prev )
gleq_char_callback_prev(window, codepoint);
GLEQevent* event = gleq_new_event();
event->type = GLEQ_CODEPOINT_INPUT;
event->window = window;
@ -346303,6 +346310,7 @@ GLEQDEF void gleqTrackWindow(GLFWwindow* window)
glfwSetCursorEnterCallback(window, gleq_cursor_enter_callback);
glfwSetScrollCallback(window, gleq_scroll_callback);
glfwSetKeyCallback(window, gleq_key_callback);
gleq_char_callback_prev = //< @r-lyeh
glfwSetCharCallback(window, gleq_char_callback);
#if GLFW_VERSION_MINOR >= 1
glfwSetDropCallback(window, gleq_file_drop_callback);
@ -349124,6 +349132,10 @@ static int ui_using_v2_menubar = 0;
#define UI_FONT_TERMINAL_SIZE UI_FONT_ENUM(14,14)
#endif
#define UI_FONT_REGULAR_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#define UI_FONT_HEADING_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#define UI_FONT_TERMINAL_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#if UI_ICONS_SMALL
#define UI_ICON_FONTSIZE UI_FONT_ENUM(16.5f,16.5f)
#define UI_ICON_SPACING_X UI_FONT_ENUM(-2,-2)
@ -349162,8 +349174,12 @@ static void nk_config_custom_fonts() {
for( char *data = vfs_load(UI_FONT_REGULAR, &datalen); data; data = 0 ) {
float font_size = UI_FONT_REGULAR_SIZE;
struct nk_font_config cfg = nk_font_config(font_size);
cfg.oversample_v = 2;
cfg.pixel_snap = 0;
cfg.oversample_h = UI_FONT_REGULAR_SAMPLING.x;
cfg.oversample_v = UI_FONT_REGULAR_SAMPLING.y;
cfg.pixel_snap = UI_FONT_REGULAR_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
// win32: struct nk_font *arial = nk_font_atlas_add_from_file(atlas, va("%s/fonts/arial.ttf",getenv("windir")), font_size, &cfg); font = arial ? arial : font;
// struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "nuklear/extra_font/DroidSans.ttf", font_size, &cfg); font = droid ? droid : font;
struct nk_font *regular = nk_font_atlas_add_from_memory(atlas, data, datalen, font_size, &cfg); font = regular ? regular : font;
@ -349171,10 +349187,10 @@ static void nk_config_custom_fonts() {
// ...with icons embedded on it.
static struct icon_font {
const char *file; int yspacing; nk_rune range[3];
const char *file; int yspacing; vec3 sampling; nk_rune range[3];
} icons[] = {
{"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf"
{"materialdesignicons-webfont.ttf", 2, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}},
{"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {1,1,1}, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf"
{"materialdesignicons-webfont.ttf", 2, {1,1,1}, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}},
};
for( int f = 0; f < countof(icons); ++f )
for( char *data = vfs_load(icons[f].file, &datalen); data; data = 0 ) {
@ -349187,9 +349203,13 @@ static void nk_config_custom_fonts() {
// cfg.font->ascent += ICON_ASCENT;
// cfg.font->height += ICON_HEIGHT;
cfg.oversample_h = 1;
cfg.oversample_v = 1;
cfg.pixel_snap = 1;
cfg.oversample_h = icons[f].sampling.x;
cfg.oversample_v = icons[f].sampling.y;
cfg.pixel_snap = icons[f].sampling.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
struct nk_font *icons = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_ICON_FONTSIZE, &cfg);
}
@ -349197,15 +349217,19 @@ static void nk_config_custom_fonts() {
// Monospaced font. Used in terminals or consoles.
for( char *data = vfs_load(UI_FONT_TERMINAL, &datalen); data; data = 0 ) {
const float font_size = UI_FONT_REGULAR_SIZE;
const float font_size = UI_FONT_TERMINAL_SIZE;
static const nk_rune icon_range[] = {32, 127, 0};
struct nk_font_config cfg = nk_font_config(font_size);
cfg.range = icon_range;
cfg.oversample_h = 1;
cfg.oversample_v = 1;
cfg.pixel_snap = 1;
cfg.oversample_h = UI_FONT_TERMINAL_SAMPLING.x;
cfg.oversample_v = UI_FONT_TERMINAL_SAMPLING.y;
cfg.pixel_snap = UI_FONT_TERMINAL_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
// struct nk_font *proggy = nk_font_atlas_add_default(atlas, font_size, &cfg);
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, font_size, &cfg);
@ -349214,7 +349238,17 @@ static void nk_config_custom_fonts() {
// Extra optional fonts from here...
for( char *data = vfs_load(UI_FONT_HEADING, &datalen); data; data = 0 ) {
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_FONT_HEADING_SIZE, 0); // font = bold ? bold : font;
struct nk_font_config cfg = nk_font_config(UI_FONT_HEADING_SIZE);
cfg.oversample_h = UI_FONT_HEADING_SAMPLING.x;
cfg.oversample_v = UI_FONT_HEADING_SAMPLING.y;
cfg.pixel_snap = UI_FONT_HEADING_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_FONT_HEADING_SIZE, &cfg);
// font = bold ? bold : font;
}
nk_glfw3_font_stash_end(&nk_glfw); // nk_sdl_font_stash_end();
@ -349369,7 +349403,7 @@ int ui_menu_editbox(char *buf, int bufcap) {
}
int ui_has_menubar() {
return ui_using_v2_menubar || !!ui_items; // array_count(ui_items) > 0;
return ui_using_v2_menubar || !!ui_items; // ? UI_MENUROW_HEIGHT + 8 : 0; // array_count(ui_items) > 0;
}
static
@ -354872,9 +354906,8 @@ static void *xml_path(struct xml *node, char *path, int down) {
const char *(xml_string)(char *key) {
struct xml *node = xml_path(*array_back(xml_docs), key, 0);
if( !node ) return "";
if( strchr(key, '@') ) return (const char *)node;
if( strchr(key, '$') ) return (const char *)node;
if( node && strchr(key, '@') ) return (const char *)node;
if( node && strchr(key, '$') ) return (const char *)node;
return "";
}
unsigned (xml_count)(char *key) {
@ -355461,7 +355494,10 @@ array(char*) file_list(const char *pathmasks) {
ASSERT(strend(cwd, "/"), "Error: dirs like '%s' must end with slash", cwd);
dir *d = dir_open(cwd, strstr(masks,"**") ? "r" : "");
int recurse = strstr(cwd, "**") || strstr(masks, "**");
strswap(cwd, "**", "./");
dir *d = dir_open(cwd, recurse ? "r" : "");
if( d ) {
for( int i = 0; i < dir_count(d); ++i ) {
if( dir_file(d,i) ) {
@ -355825,8 +355861,6 @@ static bool vfs_mount_hints(const char *path);
void vfs_reload() {
const char *app = app_name();
dir_cache = 0; // @leak
array_resize(vfs_hints, 0); // @leak
array_resize(vfs_entries, 0); // @leak
@ -358455,6 +358489,8 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
// convert to vbo data
int cp = ch; // f->cp2iter[ch];
//if(cp == 0xFFFD) continue;
//if(cp > f->num_glyphs) cp = 0xFFFD;
*t++ = X;
*t++ = Y;
*t++ = f->cp2iter[cp];
@ -366575,6 +366611,13 @@ int fx_load(const char *filemask) {
set_insert(added, name);
(void)postfx_load_from_mem(&fx, file_name(name), vfs_read(name));
}
if( 1 )
for each_array( file_list(filemask), char*, list ) {
if( set_find(added, list) ) continue;
char *name = STRDUP(list); // @leak
set_insert(added, name);
(void)postfx_load_from_mem(&fx, file_name(name), file_read(name));
}
return 1;
}
void fx_begin() {
@ -368738,6 +368781,117 @@ void ddraw_demo() {
ddraw_color_pop();
}
static int gizmo__mode;
static int gizmo__active;
static int gizmo__hover;
bool gizmo_active() {
return gizmo__active;
}
bool gizmo_hover() {
return gizmo__hover;
}
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
#if 0
ddraw_flush();
mat44 copy; copy44(copy, camera_get_active()->view);
if( 1 ) {
float *mv = camera_get_active()->view;
float d = sqrt(mv[4*0+0] * mv[4*0+0] + mv[4*1+1] * mv[4*1+1] + mv[4*2+2] * mv[4*2+2]);
if(4) mv[4*0+0] = d, mv[4*0+1] = 0, mv[4*0+2] = 0;
if(2) mv[4*1+0] = 0, mv[4*1+1] = d, mv[4*1+2] = 0;
if(1) mv[4*2+0] = 0, mv[4*2+1] = 0, mv[4*2+2] = d;
}
#endif
ddraw_color_push(dd_color);
ddraw_ontop_push(1);
int enabled = !ui_active() && !ui_hover();
vec3 mouse = enabled ? vec3(input(MOUSE_X),input(MOUSE_Y),input_down(MOUSE_L)) : vec3(0,0,0); // x,y,l
vec3 from = camera_get_active()->position;
vec3 to = editor_pick(mouse.x, mouse.y);
ray r = ray(from, to);
static vec3 src3, hit3, off3; static vec2 src2;
#define on_gizmo_dragged(X,Y,Z,COLOR,DRAWCMD, ...) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(Y?1:0,Y?0:1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
ddraw_color( hit_arrow || gizmo__active == (X*4+Y*2+Z) ? gizmo__hover = 1, YELLOW : COLOR ); \
DRAWCMD; \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), src3 = *pos, hit3 = hit_ground->p, off3 = mul3(sub3(src3,hit3),vec3(X,Y,Z)), gizmo__active = X*4+Y*2+Z; \
if( (gizmo__active && gizmo__active==(X*4+Y*2+Z)) || (!gizmo__active && hit_arrow) ) { ddraw_color( COLOR ); ( 1 ? ddraw_line : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active == (X*4+Y*2+Z) && hit_ground ) {{ __VA_ARGS__ }; modified = 1; gizmo__active *= !!input(MOUSE_L); } \
} while(0)
#define gizmo_translate(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, ddraw_arrow(*pos,add3(*pos,vec3(X,Y,Z))), { \
*pos = add3(line_closest_point(axis, hit_ground->p), off3); \
} )
#define gizmo_scale(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, (ddraw_line(*pos,add3(*pos,vec3(X,Y,Z))),ddraw_sphere(add3(*pos,vec3(X-0.1*X,Y-0.1*Y,Z-0.1*Z)),0.1)), { /*ddraw_aabb(arrow.min,arrow.max)*/ \
int component = (X*1+Y*2+Z*3)-1; \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
sca->v3[component] -= sgn * mag * 0.01; \
src2 = vec2(mouse.x, mouse.y); \
} )
#define gizmo_rotate(X,Y,Z,COLOR) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(0,1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
int hover = (hit_arrow ? (X*4+Y*2+Z) : 0); \
if( gizmo__active == (X*4+Y*2+Z) ) { ddraw_color(gizmo__active ? gizmo__hover = 1, YELLOW : WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active && hover == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color(COLOR); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active ) { ddraw_color(WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), gizmo__active = hover; \
if( (!gizmo__active && hover == (X*4+Y*2+Z)) || gizmo__active == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color( COLOR ); ( 1 ? ddraw_line_thin : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active && gizmo__active == (X*4+Y*2+Z) && hit_ground && enabled ) { \
int component = (Y*1+X*2+Z*3)-1; /*pitch,yaw,roll*/ \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
rot->v3[component] += sgn * mag; \
/*rot->v3[component] = clampf(rot->v3[component], -360, +360);*/ \
src2 = vec2(mouse.x, mouse.y); \
\
} \
gizmo__active *= enabled && !!input(MOUSE_L); \
} while(0)
gizmo__hover = 0;
int modified = 0;
if(enabled && input_down(KEY_SPACE)) gizmo__active = 0, gizmo__mode = (gizmo__mode + 1) % 3;
if(gizmo__mode == 0) gizmo_translate(1,0,0, RED);
if(gizmo__mode == 0) gizmo_translate(0,1,0, GREEN);
if(gizmo__mode == 0) gizmo_translate(0,0,1, BLUE);
if(gizmo__mode == 1) gizmo_scale(1,0,0, RED);
if(gizmo__mode == 1) gizmo_scale(0,1,0, GREEN);
if(gizmo__mode == 1) gizmo_scale(0,0,1, BLUE);
if(gizmo__mode == 2) gizmo_rotate(1,0,0, RED);
if(gizmo__mode == 2) gizmo_rotate(0,1,0, GREEN);
if(gizmo__mode == 2) gizmo_rotate(0,0,1, BLUE);
#if 0
ddraw_flush();
copy44(camera_get_active()->view, copy);
#endif
ddraw_ontop_pop();
ddraw_color_pop();
return modified;
}
#line 0
#line 1 "v4k_scene.c"
@ -368755,6 +368909,8 @@ camera_t camera() {
cam.position = vec3(10,10,10);
cam.updir = vec3(0,1,0);
cam.fov = 45;
cam.orthographic = false;
cam.distance = 3; // len3(cam.position);
cam.damping = false;
cam.move_friction = 0.09f;
@ -368846,19 +369002,18 @@ void camera_enable(camera_t *cam) {
void camera_fov(camera_t *cam, float fov) {
last_camera = cam;
#if 0 // isometric/dimetric
#define orthogonal(proj, fov, aspect, znear, zfar) \
ortho44((proj), -(fov) * (aspect), (fov) * (aspect), -(fov), (fov), (znear), (zfar))
float DIMETRIC = 30.000f;
float ISOMETRIC = 35.264f;
float aspect = window_width() / ((float)window_height()+!window_height());
orthogonal(cam->proj, 45, aspect, -1000, 1000); // why -1000?
// cam->yaw = 45;
cam->pitch = -ISOMETRIC;
#endif
cam->fov = fov;
perspective44(cam->proj, cam->fov, window_width() / ((float)window_height()+!window_height()), 0.01f, 1000.f);
if( cam->orthographic ) {
ortho44(cam->proj, -cam->fov * aspect, cam->fov * aspect, -cam->fov, cam->fov, 0.01f, 2000);
// [ref] https://commons.wikimedia.org/wiki/File:Isometric_dimetric_camera_views.png
// float pitch = cam->dimetric ? 30.000f : 35.264f; // dimetric or isometric
// cam->pitch = -pitch; // quickly reorient towards origin
} else {
perspective44(cam->proj, cam->fov, aspect, 0.01f, 2000.f);
}
}
void camera_fps(camera_t *cam, float yaw, float pitch) {
@ -368889,34 +369044,21 @@ void camera_fps(camera_t *cam, float yaw, float pitch) {
void camera_orbit( camera_t *cam, float yaw, float pitch, float inc_distance ) {
last_camera = cam;
vec2 inc_mouse = vec2(yaw, pitch);
// @todo: worth moving all these members into camera_t ?
static vec2 _mouse = {0,0};
static vec2 _polarity = { +1,-1 };
static vec2 _sensitivity = { 2,2 };
static float _friction = 0.75; //99;
static float _distance; do_once _distance = len3(cam->position);
// update dummy state
camera_fps(cam, 0,0);
// add smooth input
_mouse = mix2(_mouse, add2(_mouse, mul2(mul2(inc_mouse,_sensitivity),_polarity)), _friction);
_distance = mixf(_distance, _distance+inc_distance, _friction);
// @todo: add damping
vec3 _mouse = vec3(yaw, pitch, inc_distance);
cam->yaw += _mouse.x;
cam->pitch += _mouse.y;
cam->distance += _mouse.z;
// look: update angles
vec2 offset = sub2( _mouse, ptr2(&cam->last_move.x) );
if( 1 ) { // if _enabled
cam->yaw += offset.x;
cam->pitch += offset.y;
// look: limit pitch angle [-89..89]
cam->pitch = cam->pitch > 89 ? 89 : cam->pitch < -89 ? -89 : cam->pitch;
}
// compute view matrix
float x = rad(cam->yaw), y = rad(cam->pitch), cx = cosf(x), cy = cosf(y), sx = sinf(x), sy = sinf(y);
lookat44(cam->view, vec3( cx*cy*_distance, sy*_distance, sx*cy*_distance ), vec3(0,0,0), vec3(0,1,0) );
float x = rad(cam->yaw), y = rad(-cam->pitch), cx = cosf(x), cy = cosf(y), sx = sinf(x), sy = sinf(y);
lookat44(cam->view, vec3( cx*cy*cam->distance, sy*cam->distance, sx*cy*cam->distance ), vec3(0,0,0), vec3(0,1,0) );
// save for next call
cam->last_move.x = _mouse.x;
@ -368925,6 +369067,7 @@ void camera_orbit( camera_t *cam, float yaw, float pitch, float inc_distance ) {
int ui_camera( camera_t *cam ) {
int changed = 0;
changed |= ui_bool("Orthographic", &cam->orthographic);
changed |= ui_bool("Damping", &cam->damping);
if( !cam->damping ) ui_disable();
changed |= ui_slider2("Move friction", &cam->move_friction, va("%5.3f", cam->move_friction));
@ -368942,6 +369085,7 @@ int ui_camera( camera_t *cam ) {
ui_enable();
ui_separator();
changed |= ui_float("FOV (degrees)", &cam->fov);
changed |= ui_float("Orbit distance", &cam->distance);
ui_disable();
changed |= ui_mat44("Projection matrix", cam->proj);
ui_enable();
@ -370833,6 +370977,16 @@ __attribute__((constructor)) void init_argcv(int argc, char **argv) { __argc = a
#endif
#endif
void argvadd(const char *arg) {
char **argv = MALLOC( sizeof(char*) * (__argc+1) );
for( int i = 0; i < __argc; ++i ) {
argv[i] = __argv[i];
}
argv[__argc] = STRDUP(arg);
__argv = argv;
++__argc;
}
const char *app_path() { // @fixme: should return absolute path always. see tcc -g -run
static char buffer[1024] = {0};
if( buffer[0] ) return buffer;
@ -373268,8 +373422,7 @@ int window_frame_begin() {
// generate Debug panel contents
if( may_render_debug_panel ) {
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
API int ui_debug();
ui_debug();
ui_engine();
(has_menu ? ui_window_end : ui_panel_end)();
}
@ -375858,7 +376011,7 @@ int engine_tick() {
return 0;
}
int ui_debug() {
int ui_engine() {
static int time_factor = 0;
static int playing = 0;
static int paused = 0;
@ -376086,118 +376239,6 @@ int ui_debug() {
return 0;
}
static int gizmo__mode;
static int gizmo__active;
static int gizmo__hover;
bool gizmo_active() {
return gizmo__active;
}
bool gizmo_hover() {
return gizmo__hover;
}
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
#if 0
ddraw_flush();
mat44 copy; copy44(copy, camera_get_active()->view);
if( 1 ) {
float *mv = camera_get_active()->view;
float d = sqrt(mv[4*0+0] * mv[4*0+0] + mv[4*1+1] * mv[4*1+1] + mv[4*2+2] * mv[4*2+2]);
if(4) mv[4*0+0] = d, mv[4*0+1] = 0, mv[4*0+2] = 0;
if(2) mv[4*1+0] = 0, mv[4*1+1] = d, mv[4*1+2] = 0;
if(1) mv[4*2+0] = 0, mv[4*2+1] = 0, mv[4*2+2] = d;
}
#endif
ddraw_color_push(dd_color);
ddraw_ontop_push(1);
int enabled = !ui_active() && !ui_hover();
vec3 mouse = enabled ? vec3(input(MOUSE_X),input(MOUSE_Y),input_down(MOUSE_L)) : vec3(0,0,0); // x,y,l
vec3 from = camera_get_active()->position;
vec3 to = editor_pick(mouse.x, mouse.y);
ray r = ray(from, to);
static vec3 src3, hit3, off3; static vec2 src2;
#define on_gizmo_dragged(X,Y,Z,COLOR,DRAWCMD, ...) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(Y?1:0,Y?0:1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
ddraw_color( hit_arrow || gizmo__active == (X*4+Y*2+Z) ? gizmo__hover = 1, YELLOW : COLOR ); \
DRAWCMD; \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), src3 = *pos, hit3 = hit_ground->p, off3 = mul3(sub3(src3,hit3),vec3(X,Y,Z)), gizmo__active = X*4+Y*2+Z; \
if( (gizmo__active && gizmo__active==(X*4+Y*2+Z)) || (!gizmo__active && hit_arrow) ) { ddraw_color( COLOR ); ( 1 ? ddraw_line : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active == (X*4+Y*2+Z) && hit_ground ) {{ __VA_ARGS__ }; modified = 1; gizmo__active *= !!input(MOUSE_L); } \
} while(0)
#define gizmo_translate(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, ddraw_arrow(*pos,add3(*pos,vec3(X,Y,Z))), { \
*pos = add3(line_closest_point(axis, hit_ground->p), off3); \
} )
#define gizmo_scale(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, (ddraw_line(*pos,add3(*pos,vec3(X,Y,Z))),ddraw_sphere(add3(*pos,vec3(X-0.1*X,Y-0.1*Y,Z-0.1*Z)),0.1)), { /*ddraw_aabb(arrow.min,arrow.max)*/ \
int component = (X*1+Y*2+Z*3)-1; \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
sca->v3[component] -= sgn * mag * 0.01; \
src2 = vec2(mouse.x, mouse.y); \
} )
#define gizmo_rotate(X,Y,Z,COLOR) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(0,1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
int hover = (hit_arrow ? (X*4+Y*2+Z) : 0); \
if( gizmo__active == (X*4+Y*2+Z) ) { ddraw_color(gizmo__active ? gizmo__hover = 1, YELLOW : WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active && hover == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color(COLOR); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active ) { ddraw_color(WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), gizmo__active = hover; \
if( (!gizmo__active && hover == (X*4+Y*2+Z)) || gizmo__active == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color( COLOR ); ( 1 ? ddraw_line_thin : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active && gizmo__active == (X*4+Y*2+Z) && hit_ground && enabled ) { \
int component = (Y*1+X*2+Z*3)-1; /*pitch,yaw,roll*/ \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
rot->v3[component] += sgn * mag; \
/*rot->v3[component] = clampf(rot->v3[component], -360, +360);*/ \
src2 = vec2(mouse.x, mouse.y); \
\
} \
gizmo__active *= enabled && !!input(MOUSE_L); \
} while(0)
gizmo__hover = 0;
int modified = 0;
if(enabled && input_down(KEY_SPACE)) gizmo__active = 0, gizmo__mode = (gizmo__mode + 1) % 3;
if(gizmo__mode == 0) gizmo_translate(1,0,0, RED);
if(gizmo__mode == 0) gizmo_translate(0,1,0, GREEN);
if(gizmo__mode == 0) gizmo_translate(0,0,1, BLUE);
if(gizmo__mode == 1) gizmo_scale(1,0,0, RED);
if(gizmo__mode == 1) gizmo_scale(0,1,0, GREEN);
if(gizmo__mode == 1) gizmo_scale(0,0,1, BLUE);
if(gizmo__mode == 2) gizmo_rotate(1,0,0, RED);
if(gizmo__mode == 2) gizmo_rotate(0,1,0, GREEN);
if(gizmo__mode == 2) gizmo_rotate(0,0,1, BLUE);
#if 0
ddraw_flush();
copy44(camera_get_active()->view, copy);
#endif
ddraw_ontop_pop();
ddraw_color_pop();
return modified;
}
#line 0
#line 1 "v4k_main.c"
@ -376804,21 +376845,22 @@ void editor_pump() {
// ----------------------------------------------------------------------------------------
API void editor_cursorpos(int x, int y);
void editor_cursorpos(int x, int y) {
glfwSetCursorPos( window_handle(), x, y );
}
void editor_symbol(int x, int y, const char *sym) {
#define FONT_SYMBOLS FONT_FACE2
#define FONT_WHITE FONT_COLOR1
#define FONT_YELLOW FONT_COLOR2
#define FONT_ORANGE FONT_COLOR3
#define FONT_CYAN FONT_COLOR4
// style: atlas size, unicode ranges and 6 font faces max
do_once font_face(FONT_SYMBOLS, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
do_once font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
// style: 10 colors max
do_once font_color(FONT_WHITE, WHITE);
do_once font_color(FONT_YELLOW, YELLOW);
do_once font_color(FONT_CYAN, CYAN);
do_once font_color(FONT_ORANGE, ORANGE);
do_once font_color(FONT_COLOR1, WHITE);
do_once font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY);
do_once font_color(FONT_COLOR3, YELLOW);
do_once font_color(FONT_COLOR4, ORANGE);
do_once font_color(FONT_COLOR5, CYAN);
font_goto(x,y);
font_print(va(FONT_SYMBOLS FONT_WHITE FONT_H1 "%s", sym));
font_print(va(FONT_FACE2 /*FONT_WHITE*/ FONT_H1 "%s", sym));
}
void editor_frame( void (*game)(unsigned, float, double) ) {
@ -376831,7 +376873,7 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
window_cursor_shape(CURSOR_SW_AUTO);
editor.hz_high = window_fps_target();
fx_load("editorOutline.fs");
fx_load("**/editorOutline.fs");
fx_enable(0, 1);
obj_setname(editor.root = obj_new(obj), "Signals");
@ -376887,26 +376929,27 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
int is_borderless = !glfwGetWindowAttrib(window, GLFW_DECORATED);
int ingame = !editor.active;
static double clicked_titlebar = 0;
UI_MENU(14+is_borderless, \
UI_MENU(14+2*is_borderless, \
if(ingame) ui_disable(); \
UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \
UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_engine()) \
if(ingame) ui_enable(); \
UI_MENU_ITEM(ICON_PL4Y, if(editor.t == 0) editor_send("eject"); editor_send(window_has_pause() ? "play" : "pause")) \
UI_MENU_ITEM(ICON_SKIP, editor_send(window_has_pause() ? "frame" : "slomo")) \
UI_MENU_ITEM(ICON_MDI_STOP, editor_send("stop")) \
UI_MENU_ITEM(ICON_MDI_EJECT, editor_send("eject")) \
UI_MENU_ITEM(STATS, stats_mode = (++stats_mode) % 3) \
UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+34 + 32*is_borderless, clicked_titlebar = time_ms()) \
UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+32 + 32*2*is_borderless + 10, clicked_titlebar = time_ms()) \
if(ingame) ui_disable(); \
UI_MENU_ITEM(ICON_MD_FOLDER_SPECIAL, editor_send("browser")) \
UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \
UI_MENU_ITEM(ICON_MDI_SCRIPT_TEXT, editor_send("script")) \
UI_MENU_ITEM(ICON_MDI_CHART_TIMELINE, editor_send("timeline")) \
UI_MENU_ITEM(ICON_MDI_CONSOLE, editor_send("console")) \
UI_MENU_ITEM(ICON_MDI_GRAPH, editor_send("nodes")) \
UI_MENU_ITEM(ICON_MD_SEARCH, editor_send("filter")) \
UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_debug()) \
UI_MENU_ITEM(ICON_MDI_MAGNIFY, editor_send("filter")) /*MD_SEARCH*/ \
if(ingame) ui_enable(); \
UI_MENU_ITEM(ICON_MD_CLOSE, editor_send("quit")) \
UI_MENU_ITEM(window_has_maximize() ? ICON_MDI_WINDOW_MINIMIZE : ICON_MDI_WINDOW_MAXIMIZE, window_maximize(1 ^ window_has_maximize())) \
UI_MENU_ITEM(ICON_MDI_CLOSE, editor_send("quit")) \
);
if( is_borderless ) {
@ -376951,7 +376994,7 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
fx_end();
// draw box selection
if( !ui_active() ) { //< check that we're not moving a window
if( !ui_active() && window_has_cursor() && cursorshape ) { //< check that we're not moving a window + not in fps cam
static vec2 from = {0}, to = {0};
if( input_down(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)), from = to;
if( input(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y));

View File

@ -286,8 +286,12 @@ static void gleq_key_callback(GLFWwindow* window, int key, int scancode, int act
event->type = GLEQ_KEY_REPEATED;
}
static void (*gleq_char_callback_prev)(GLFWwindow* window, unsigned int codepoint) = 0;
static void gleq_char_callback(GLFWwindow* window, unsigned int codepoint)
{
if( gleq_char_callback_prev )
gleq_char_callback_prev(window, codepoint);
GLEQevent* event = gleq_new_event();
event->type = GLEQ_CODEPOINT_INPUT;
event->window = window;
@ -376,6 +380,7 @@ GLEQDEF void gleqTrackWindow(GLFWwindow* window)
glfwSetCursorEnterCallback(window, gleq_cursor_enter_callback);
glfwSetScrollCallback(window, gleq_scroll_callback);
glfwSetKeyCallback(window, gleq_key_callback);
gleq_char_callback_prev = //< @r-lyeh
glfwSetCharCallback(window, gleq_char_callback);
#if GLFW_VERSION_MINOR >= 1
glfwSetDropCallback(window, gleq_file_drop_callback);

View File

@ -172,13 +172,13 @@ extern "C" {
#include <GLFW/glfw3.h>
#include <emscripten.h>
#include <emscripten/html5.h>
#define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK)
#define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK) ///-
#else
#if is(win32) /*&& is(tcc)*/ // && ENABLE_DLL
#ifdef GLAD_API_CALL
#undef GLAD_API_CALL
#endif
#define GLAD_API_CALL extern API
#define GLAD_API_CALL extern API ///-
#endif
#ifndef GLAD_GL_H_
#include "v4k"

View File

@ -300,12 +300,6 @@
static void fn(void)
#endif
#if 0 // autorun demo
void byebye(void) { puts("seen after main()"); }
AUTORUN { puts("seen before main()"); }
AUTORUN { puts("seen before main() too"); atexit( byebye ); }
#endif
// -----------------------------------------------------------------------------
// build info

View File

@ -153,9 +153,8 @@ static void *xml_path(struct xml *node, char *path, int down) {
const char *(xml_string)(char *key) {
struct xml *node = xml_path(*array_back(xml_docs), key, 0);
if( !node ) return "";
if( strchr(key, '@') ) return (const char *)node;
if( strchr(key, '$') ) return (const char *)node;
if( node && strchr(key, '@') ) return (const char *)node;
if( node && strchr(key, '$') ) return (const char *)node;
return "";
}
unsigned (xml_count)(char *key) {

View File

@ -507,21 +507,22 @@ void editor_pump() {
// ----------------------------------------------------------------------------------------
API void editor_cursorpos(int x, int y);
void editor_cursorpos(int x, int y) {
glfwSetCursorPos( window_handle(), x, y );
}
void editor_symbol(int x, int y, const char *sym) {
#define FONT_SYMBOLS FONT_FACE2
#define FONT_WHITE FONT_COLOR1
#define FONT_YELLOW FONT_COLOR2
#define FONT_ORANGE FONT_COLOR3
#define FONT_CYAN FONT_COLOR4
// style: atlas size, unicode ranges and 6 font faces max
do_once font_face(FONT_SYMBOLS, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
do_once font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
// style: 10 colors max
do_once font_color(FONT_WHITE, WHITE);
do_once font_color(FONT_YELLOW, YELLOW);
do_once font_color(FONT_CYAN, CYAN);
do_once font_color(FONT_ORANGE, ORANGE);
do_once font_color(FONT_COLOR1, WHITE);
do_once font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY);
do_once font_color(FONT_COLOR3, YELLOW);
do_once font_color(FONT_COLOR4, ORANGE);
do_once font_color(FONT_COLOR5, CYAN);
font_goto(x,y);
font_print(va(FONT_SYMBOLS FONT_WHITE FONT_H1 "%s", sym));
font_print(va(FONT_FACE2 /*FONT_WHITE*/ FONT_H1 "%s", sym));
}
void editor_frame( void (*game)(unsigned, float, double) ) {
@ -534,7 +535,7 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
window_cursor_shape(CURSOR_SW_AUTO);
editor.hz_high = window_fps_target();
fx_load("editorOutline.fs");
fx_load("**/editorOutline.fs");
fx_enable(0, 1);
obj_setname(editor.root = obj_new(obj), "Signals");
@ -590,26 +591,27 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
int is_borderless = !glfwGetWindowAttrib(window, GLFW_DECORATED);
int ingame = !editor.active;
static double clicked_titlebar = 0;
UI_MENU(14+is_borderless, \
UI_MENU(14+2*is_borderless, \
if(ingame) ui_disable(); \
UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \
UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_engine()) \
if(ingame) ui_enable(); \
UI_MENU_ITEM(ICON_PL4Y, if(editor.t == 0) editor_send("eject"); editor_send(window_has_pause() ? "play" : "pause")) \
UI_MENU_ITEM(ICON_SKIP, editor_send(window_has_pause() ? "frame" : "slomo")) \
UI_MENU_ITEM(ICON_MDI_STOP, editor_send("stop")) \
UI_MENU_ITEM(ICON_MDI_EJECT, editor_send("eject")) \
UI_MENU_ITEM(STATS, stats_mode = (++stats_mode) % 3) \
UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+34 + 32*is_borderless, clicked_titlebar = time_ms()) \
UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+32 + 32*2*is_borderless + 10, clicked_titlebar = time_ms()) \
if(ingame) ui_disable(); \
UI_MENU_ITEM(ICON_MD_FOLDER_SPECIAL, editor_send("browser")) \
UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \
UI_MENU_ITEM(ICON_MDI_SCRIPT_TEXT, editor_send("script")) \
UI_MENU_ITEM(ICON_MDI_CHART_TIMELINE, editor_send("timeline")) \
UI_MENU_ITEM(ICON_MDI_CONSOLE, editor_send("console")) \
UI_MENU_ITEM(ICON_MDI_GRAPH, editor_send("nodes")) \
UI_MENU_ITEM(ICON_MD_SEARCH, editor_send("filter")) \
UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_debug()) \
UI_MENU_ITEM(ICON_MDI_MAGNIFY, editor_send("filter")) /*MD_SEARCH*/ \
if(ingame) ui_enable(); \
UI_MENU_ITEM(ICON_MD_CLOSE, editor_send("quit")) \
UI_MENU_ITEM(window_has_maximize() ? ICON_MDI_WINDOW_MINIMIZE : ICON_MDI_WINDOW_MAXIMIZE, window_maximize(1 ^ window_has_maximize())) \
UI_MENU_ITEM(ICON_MDI_CLOSE, editor_send("quit")) \
);
if( is_borderless ) {
@ -654,7 +656,7 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
fx_end();
// draw box selection
if( !ui_active() ) { //< check that we're not moving a window
if( !ui_active() && window_has_cursor() && cursorshape ) { //< check that we're not moving a window + not in fps cam
static vec2 from = {0}, to = {0};
if( input_down(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)), from = to;
if( input(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y));

View File

@ -5,6 +5,7 @@
#define EDITOR_VERSION "2023.10"
// ----------------------------------------------------------------------------
// editor bindings
typedef struct editor_bind_t {
const char *command;
@ -18,6 +19,7 @@ API void editor_addbind(editor_bind_t bind);
void macro(editor_bind_##CMD##_fn_)() { __VA_ARGS__ }; AUTORUN { array_push(editor_binds, ((editor_bind_t){#CMD,KEYS,macro(editor_bind_##CMD##_fn_)}) ); }
// ----------------------------------------------------------------------------
// editor properties
#define EDITOR_PROPERTYDEF(T,property_name) \
typedef map(void*,T) editor_##property_name##_map_t; \
@ -27,25 +29,26 @@ API void editor_set##property_name(const void *obj, T value); \
API void editor_alt##property_name(const void *obj); \
API void editor_no##property_name(void *obj);
EDITOR_PROPERTYDEF(int, open); // whether object is tree opened in tree editor
EDITOR_PROPERTYDEF(int, selected); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, changed); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, popup); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, bookmarked);
EDITOR_PROPERTYDEF(int, visible);
EDITOR_PROPERTYDEF(int, script);
EDITOR_PROPERTYDEF(int, event);
EDITOR_PROPERTYDEF(char*,iconinstance);
EDITOR_PROPERTYDEF(char*,iconclass);
EDITOR_PROPERTYDEF(int, treeoffsety);
EDITOR_PROPERTYDEF(int, open); ///- whether object is tree opened in tree editor
EDITOR_PROPERTYDEF(int, selected); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, changed); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, popup); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, bookmarked); ///-
EDITOR_PROPERTYDEF(int, visible); ///-
EDITOR_PROPERTYDEF(int, script); ///-
EDITOR_PROPERTYDEF(int, event); ///-
EDITOR_PROPERTYDEF(char*,iconinstance); ///-
EDITOR_PROPERTYDEF(char*,iconclass); ///-
EDITOR_PROPERTYDEF(int, treeoffsety); ///-
API void editor_destroy_properties(void *o);
API void editor_load_on_boot(void);
API void editor_save_on_quit(void);
// ----------------------------------------------------------------------------
// editor ui
enum {
enum EDITOR_MODE {
EDITOR_PANEL,
EDITOR_WINDOW,
EDITOR_WINDOW_NK,
@ -55,6 +58,9 @@ enum {
API int editor_begin(const char *title, int mode);
API int editor_end(int mode);
// ----------------------------------------------------------------------------------------
// editor selection
API int editor_filter();
API void editor_select(const char *mask);
API void editor_unselect(); // same than editor_select("!**");
@ -65,6 +71,7 @@ API void* editor_first_selected();
API void* editor_last_selected();
// ----------------------------------------------------------------------------------------
// editor instancing
API void editor_addtoworld(obj *o);
API void editor_watch(const void *o);
@ -75,41 +82,31 @@ API void editor_destroy_selected();
API void editor_inspect(obj *o);
// ----------------------------------------------------------------------------------------
// tty
API int editor_send(const char *cmd); // return job-id
API const char* editor_recv(int jobid, double timeout_ss);
API void editor_pump();
// ----------------------------------------------------------------------------------------
API void editor_symbol(int x, int y, const char *sym);
API void editor_frame( void (*game)(unsigned, float, double) );
API void editor_gizmos(int dim);
// ----------------------------------------------------------------------------------------
API int editor_send(const char *command);
// editor utils
//API void editor();
//API bool editor_active();
API vec3 editor_pick(float mouse_x, float mouse_y);
API char* editor_path(const char *path);
API void editor_symbol(int x, int y, const char *sym);
API void editor_gizmos(int dim);
// ----------------------------------------------------------------------------------------
// editor loop
API int editor_send(const char *cmd); // returns job-id
API const char* editor_recv(int jobid, double timeout_ss);
API void editor_pump();
API void editor_frame( void (*game)(unsigned, float, double) );
// ----------------------------------------------------------------------------------------
// engine section: @todo: expand me
API float* engine_getf(const char *key);
API int* engine_geti(const char *key);
API char** engine_gets(const char *key);
API int engine_send(const char *cmd, const char *optional_value);
API int ui_debug();
// open file dialog
API char* dialog_load();
API char* dialog_save();
// transform gizmos
API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
API bool gizmo_active();
API bool gizmo_hover();
API int ui_engine();

View File

@ -190,7 +190,7 @@ int engine_tick() {
return 0;
}
int ui_debug() {
int ui_engine() {
static int time_factor = 0;
static int playing = 0;
static int paused = 0;
@ -418,115 +418,3 @@ int ui_debug() {
return 0;
}
static int gizmo__mode;
static int gizmo__active;
static int gizmo__hover;
bool gizmo_active() {
return gizmo__active;
}
bool gizmo_hover() {
return gizmo__hover;
}
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
#if 0
ddraw_flush();
mat44 copy; copy44(copy, camera_get_active()->view);
if( 1 ) {
float *mv = camera_get_active()->view;
float d = sqrt(mv[4*0+0] * mv[4*0+0] + mv[4*1+1] * mv[4*1+1] + mv[4*2+2] * mv[4*2+2]);
if(4) mv[4*0+0] = d, mv[4*0+1] = 0, mv[4*0+2] = 0;
if(2) mv[4*1+0] = 0, mv[4*1+1] = d, mv[4*1+2] = 0;
if(1) mv[4*2+0] = 0, mv[4*2+1] = 0, mv[4*2+2] = d;
}
#endif
ddraw_color_push(dd_color);
ddraw_ontop_push(1);
int enabled = !ui_active() && !ui_hover();
vec3 mouse = enabled ? vec3(input(MOUSE_X),input(MOUSE_Y),input_down(MOUSE_L)) : vec3(0,0,0); // x,y,l
vec3 from = camera_get_active()->position;
vec3 to = editor_pick(mouse.x, mouse.y);
ray r = ray(from, to);
static vec3 src3, hit3, off3; static vec2 src2;
#define on_gizmo_dragged(X,Y,Z,COLOR,DRAWCMD, ...) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(Y?1:0,Y?0:1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
ddraw_color( hit_arrow || gizmo__active == (X*4+Y*2+Z) ? gizmo__hover = 1, YELLOW : COLOR ); \
DRAWCMD; \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), src3 = *pos, hit3 = hit_ground->p, off3 = mul3(sub3(src3,hit3),vec3(X,Y,Z)), gizmo__active = X*4+Y*2+Z; \
if( (gizmo__active && gizmo__active==(X*4+Y*2+Z)) || (!gizmo__active && hit_arrow) ) { ddraw_color( COLOR ); ( 1 ? ddraw_line : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active == (X*4+Y*2+Z) && hit_ground ) {{ __VA_ARGS__ }; modified = 1; gizmo__active *= !!input(MOUSE_L); } \
} while(0)
#define gizmo_translate(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, ddraw_arrow(*pos,add3(*pos,vec3(X,Y,Z))), { \
*pos = add3(line_closest_point(axis, hit_ground->p), off3); \
} )
#define gizmo_scale(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, (ddraw_line(*pos,add3(*pos,vec3(X,Y,Z))),ddraw_sphere(add3(*pos,vec3(X-0.1*X,Y-0.1*Y,Z-0.1*Z)),0.1)), { /*ddraw_aabb(arrow.min,arrow.max)*/ \
int component = (X*1+Y*2+Z*3)-1; \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
sca->v3[component] -= sgn * mag * 0.01; \
src2 = vec2(mouse.x, mouse.y); \
} )
#define gizmo_rotate(X,Y,Z,COLOR) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(0,1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
int hover = (hit_arrow ? (X*4+Y*2+Z) : 0); \
if( gizmo__active == (X*4+Y*2+Z) ) { ddraw_color(gizmo__active ? gizmo__hover = 1, YELLOW : WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active && hover == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color(COLOR); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active ) { ddraw_color(WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), gizmo__active = hover; \
if( (!gizmo__active && hover == (X*4+Y*2+Z)) || gizmo__active == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color( COLOR ); ( 1 ? ddraw_line_thin : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active && gizmo__active == (X*4+Y*2+Z) && hit_ground && enabled ) { \
int component = (Y*1+X*2+Z*3)-1; /*pitch,yaw,roll*/ \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
rot->v3[component] += sgn * mag; \
/*rot->v3[component] = clampf(rot->v3[component], -360, +360);*/ \
src2 = vec2(mouse.x, mouse.y); \
\
} \
gizmo__active *= enabled && !!input(MOUSE_L); \
} while(0)
gizmo__hover = 0;
int modified = 0;
if(enabled && input_down(KEY_SPACE)) gizmo__active = 0, gizmo__mode = (gizmo__mode + 1) % 3;
if(gizmo__mode == 0) gizmo_translate(1,0,0, RED);
if(gizmo__mode == 0) gizmo_translate(0,1,0, GREEN);
if(gizmo__mode == 0) gizmo_translate(0,0,1, BLUE);
if(gizmo__mode == 1) gizmo_scale(1,0,0, RED);
if(gizmo__mode == 1) gizmo_scale(0,1,0, GREEN);
if(gizmo__mode == 1) gizmo_scale(0,0,1, BLUE);
if(gizmo__mode == 2) gizmo_rotate(1,0,0, RED);
if(gizmo__mode == 2) gizmo_rotate(0,1,0, GREEN);
if(gizmo__mode == 2) gizmo_rotate(0,0,1, BLUE);
#if 0
ddraw_flush();
copy44(camera_get_active()->view, copy);
#endif
ddraw_ontop_pop();
ddraw_color_pop();
return modified;
}

View File

@ -221,7 +221,10 @@ array(char*) file_list(const char *pathmasks) {
ASSERT(strend(cwd, "/"), "Error: dirs like '%s' must end with slash", cwd);
dir *d = dir_open(cwd, strstr(masks,"**") ? "r" : "");
int recurse = strstr(cwd, "**") || strstr(masks, "**");
strswap(cwd, "**", "./");
dir *d = dir_open(cwd, recurse ? "r" : "");
if( d ) {
for( int i = 0; i < dir_count(d); ++i ) {
if( dir_file(d,i) ) {
@ -585,8 +588,6 @@ static bool vfs_mount_hints(const char *path);
void vfs_reload() {
const char *app = app_name();
dir_cache = 0; // @leak
array_resize(vfs_hints, 0); // @leak
array_resize(vfs_entries, 0); // @leak

View File

@ -2060,6 +2060,8 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
// convert to vbo data
int cp = ch; // f->cp2iter[ch];
//if(cp == 0xFFFD) continue;
//if(cp > f->num_glyphs) cp = 0xFFFD;
*t++ = X;
*t++ = Y;
*t++ = f->cp2iter[cp];

View File

@ -168,32 +168,32 @@ void* obj_free(void *o);
#define obj_vtable(method,RC,...) RC macro(obj_##method)(){ __VA_ARGS__ }; RC (*obj_##method[256])() = { REPEAT256(macro(obj_##method)) };
#define obj_vtable_null(method,RC) RC (*obj_##method[256])() = { 0 }; // null virtual table. will crash unless obj_extend'ed
#define REPEAT16(f) f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f
#define REPEAT64(f) REPEAT16(f),REPEAT16(f),REPEAT16(f),REPEAT16(f)
#define REPEAT256(f) REPEAT64(f),REPEAT64(f),REPEAT64(f),REPEAT64(f)
#define REPEAT16(f) f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f ///-
#define REPEAT64(f) REPEAT16(f),REPEAT16(f),REPEAT16(f),REPEAT16(f) ///-
#define REPEAT256(f) REPEAT64(f),REPEAT64(f),REPEAT64(f),REPEAT64(f) ///-
#undef EXTEND
#define EXTEND(...) EXPAND(EXTEND, __VA_ARGS__)
#define EXTEND2(o,F1) obj_extend(o,F1)
#define EXTEND3(o,F1,F2) obj_extend(o,F1), obj_extend(o,F2)
#define EXTEND4(o,F1,F2,F3) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3)
#define EXTEND5(o,F1,F2,F3,F4) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4)
#define EXTEND6(o,F1,F2,F3,F4,F5) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5)
#define EXTEND7(o,F1,F2,F3,F4,F5,F6) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6)
#define EXTEND8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7)
#define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8)
#define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9)
#define EXTEND2(o,F1) obj_extend(o,F1) ///-
#define EXTEND3(o,F1,F2) obj_extend(o,F1), obj_extend(o,F2) ///-
#define EXTEND4(o,F1,F2,F3) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3) ///-
#define EXTEND5(o,F1,F2,F3,F4) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4) ///-
#define EXTEND6(o,F1,F2,F3,F4,F5) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5) ///-
#define EXTEND7(o,F1,F2,F3,F4,F5,F6) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6) ///-
#define EXTEND8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7) ///-
#define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8) ///-
#define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9) ///-
#define EXTEND_T(...) EXPAND(EXTEND_T, __VA_ARGS__)
#define EXTEND_T2(o,F1) obj_extend_t(o,F1)
#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2)
#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3)
#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4)
#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5)
#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6)
#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7)
#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8)
#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9)
#define EXTEND_T2(o,F1) obj_extend_t(o,F1) ///-
#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2) ///-
#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3) ///-
#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4) ///-
#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5) ///-
#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6) ///-
#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7) ///-
#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8) ///-
#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9) ///-
// --- declare vtables

View File

@ -2390,6 +2390,13 @@ int fx_load(const char *filemask) {
set_insert(added, name);
(void)postfx_load_from_mem(&fx, file_name(name), vfs_read(name));
}
if( 1 )
for each_array( file_list(filemask), char*, list ) {
if( set_find(added, list) ) continue;
char *name = STRDUP(list); // @leak
set_insert(added, name);
(void)postfx_load_from_mem(&fx, file_name(name), file_read(name));
}
return 1;
}
void fx_begin() {

View File

@ -843,3 +843,114 @@ void ddraw_demo() {
ddraw_color_pop();
}
static int gizmo__mode;
static int gizmo__active;
static int gizmo__hover;
bool gizmo_active() {
return gizmo__active;
}
bool gizmo_hover() {
return gizmo__hover;
}
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
#if 0
ddraw_flush();
mat44 copy; copy44(copy, camera_get_active()->view);
if( 1 ) {
float *mv = camera_get_active()->view;
float d = sqrt(mv[4*0+0] * mv[4*0+0] + mv[4*1+1] * mv[4*1+1] + mv[4*2+2] * mv[4*2+2]);
if(4) mv[4*0+0] = d, mv[4*0+1] = 0, mv[4*0+2] = 0;
if(2) mv[4*1+0] = 0, mv[4*1+1] = d, mv[4*1+2] = 0;
if(1) mv[4*2+0] = 0, mv[4*2+1] = 0, mv[4*2+2] = d;
}
#endif
ddraw_color_push(dd_color);
ddraw_ontop_push(1);
int enabled = !ui_active() && !ui_hover();
vec3 mouse = enabled ? vec3(input(MOUSE_X),input(MOUSE_Y),input_down(MOUSE_L)) : vec3(0,0,0); // x,y,l
vec3 from = camera_get_active()->position;
vec3 to = editor_pick(mouse.x, mouse.y);
ray r = ray(from, to);
static vec3 src3, hit3, off3; static vec2 src2;
#define on_gizmo_dragged(X,Y,Z,COLOR,DRAWCMD, ...) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(Y?1:0,Y?0:1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
ddraw_color( hit_arrow || gizmo__active == (X*4+Y*2+Z) ? gizmo__hover = 1, YELLOW : COLOR ); \
DRAWCMD; \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), src3 = *pos, hit3 = hit_ground->p, off3 = mul3(sub3(src3,hit3),vec3(X,Y,Z)), gizmo__active = X*4+Y*2+Z; \
if( (gizmo__active && gizmo__active==(X*4+Y*2+Z)) || (!gizmo__active && hit_arrow) ) { ddraw_color( COLOR ); ( 1 ? ddraw_line : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active == (X*4+Y*2+Z) && hit_ground ) {{ __VA_ARGS__ }; modified = 1; gizmo__active *= !!input(MOUSE_L); } \
} while(0)
#define gizmo_translate(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, ddraw_arrow(*pos,add3(*pos,vec3(X,Y,Z))), { \
*pos = add3(line_closest_point(axis, hit_ground->p), off3); \
} )
#define gizmo_scale(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, (ddraw_line(*pos,add3(*pos,vec3(X,Y,Z))),ddraw_sphere(add3(*pos,vec3(X-0.1*X,Y-0.1*Y,Z-0.1*Z)),0.1)), { /*ddraw_aabb(arrow.min,arrow.max)*/ \
int component = (X*1+Y*2+Z*3)-1; \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
sca->v3[component] -= sgn * mag * 0.01; \
src2 = vec2(mouse.x, mouse.y); \
} )
#define gizmo_rotate(X,Y,Z,COLOR) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(0,1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
int hover = (hit_arrow ? (X*4+Y*2+Z) : 0); \
if( gizmo__active == (X*4+Y*2+Z) ) { ddraw_color(gizmo__active ? gizmo__hover = 1, YELLOW : WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active && hover == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color(COLOR); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active ) { ddraw_color(WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), gizmo__active = hover; \
if( (!gizmo__active && hover == (X*4+Y*2+Z)) || gizmo__active == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color( COLOR ); ( 1 ? ddraw_line_thin : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active && gizmo__active == (X*4+Y*2+Z) && hit_ground && enabled ) { \
int component = (Y*1+X*2+Z*3)-1; /*pitch,yaw,roll*/ \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
rot->v3[component] += sgn * mag; \
/*rot->v3[component] = clampf(rot->v3[component], -360, +360);*/ \
src2 = vec2(mouse.x, mouse.y); \
\
} \
gizmo__active *= enabled && !!input(MOUSE_L); \
} while(0)
gizmo__hover = 0;
int modified = 0;
if(enabled && input_down(KEY_SPACE)) gizmo__active = 0, gizmo__mode = (gizmo__mode + 1) % 3;
if(gizmo__mode == 0) gizmo_translate(1,0,0, RED);
if(gizmo__mode == 0) gizmo_translate(0,1,0, GREEN);
if(gizmo__mode == 0) gizmo_translate(0,0,1, BLUE);
if(gizmo__mode == 1) gizmo_scale(1,0,0, RED);
if(gizmo__mode == 1) gizmo_scale(0,1,0, GREEN);
if(gizmo__mode == 1) gizmo_scale(0,0,1, BLUE);
if(gizmo__mode == 2) gizmo_rotate(1,0,0, RED);
if(gizmo__mode == 2) gizmo_rotate(0,1,0, GREEN);
if(gizmo__mode == 2) gizmo_rotate(0,0,1, BLUE);
#if 0
ddraw_flush();
copy44(camera_get_active()->view, copy);
#endif
ddraw_ontop_pop();
ddraw_color_pop();
return modified;
}

View File

@ -62,3 +62,9 @@ API void ddraw_prism(vec3 center, float radius, float height, vec3 normal, int s
API void ddraw_demo();
API void ddraw_flush();
API void ddraw_flush_projview(mat44 proj, mat44 view);
// transform gizmos
API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
API bool gizmo_active();
API bool gizmo_hover();

View File

@ -12,6 +12,8 @@ camera_t camera() {
cam.position = vec3(10,10,10);
cam.updir = vec3(0,1,0);
cam.fov = 45;
cam.orthographic = false;
cam.distance = 3; // len3(cam.position);
cam.damping = false;
cam.move_friction = 0.09f;
@ -103,19 +105,18 @@ void camera_enable(camera_t *cam) {
void camera_fov(camera_t *cam, float fov) {
last_camera = cam;
#if 0 // isometric/dimetric
#define orthogonal(proj, fov, aspect, znear, zfar) \
ortho44((proj), -(fov) * (aspect), (fov) * (aspect), -(fov), (fov), (znear), (zfar))
float DIMETRIC = 30.000f;
float ISOMETRIC = 35.264f;
float aspect = window_width() / ((float)window_height()+!window_height());
orthogonal(cam->proj, 45, aspect, -1000, 1000); // why -1000?
// cam->yaw = 45;
cam->pitch = -ISOMETRIC;
#endif
cam->fov = fov;
perspective44(cam->proj, cam->fov, window_width() / ((float)window_height()+!window_height()), 0.01f, 1000.f);
if( cam->orthographic ) {
ortho44(cam->proj, -cam->fov * aspect, cam->fov * aspect, -cam->fov, cam->fov, 0.01f, 2000);
// [ref] https://commons.wikimedia.org/wiki/File:Isometric_dimetric_camera_views.png
// float pitch = cam->dimetric ? 30.000f : 35.264f; // dimetric or isometric
// cam->pitch = -pitch; // quickly reorient towards origin
} else {
perspective44(cam->proj, cam->fov, aspect, 0.01f, 2000.f);
}
}
void camera_fps(camera_t *cam, float yaw, float pitch) {
@ -146,34 +147,21 @@ void camera_fps(camera_t *cam, float yaw, float pitch) {
void camera_orbit( camera_t *cam, float yaw, float pitch, float inc_distance ) {
last_camera = cam;
vec2 inc_mouse = vec2(yaw, pitch);
// @todo: worth moving all these members into camera_t ?
static vec2 _mouse = {0,0};
static vec2 _polarity = { +1,-1 };
static vec2 _sensitivity = { 2,2 };
static float _friction = 0.75; //99;
static float _distance; do_once _distance = len3(cam->position);
// update dummy state
camera_fps(cam, 0,0);
// add smooth input
_mouse = mix2(_mouse, add2(_mouse, mul2(mul2(inc_mouse,_sensitivity),_polarity)), _friction);
_distance = mixf(_distance, _distance+inc_distance, _friction);
// @todo: add damping
vec3 _mouse = vec3(yaw, pitch, inc_distance);
cam->yaw += _mouse.x;
cam->pitch += _mouse.y;
cam->distance += _mouse.z;
// look: update angles
vec2 offset = sub2( _mouse, ptr2(&cam->last_move.x) );
if( 1 ) { // if _enabled
cam->yaw += offset.x;
cam->pitch += offset.y;
// look: limit pitch angle [-89..89]
cam->pitch = cam->pitch > 89 ? 89 : cam->pitch < -89 ? -89 : cam->pitch;
}
// compute view matrix
float x = rad(cam->yaw), y = rad(cam->pitch), cx = cosf(x), cy = cosf(y), sx = sinf(x), sy = sinf(y);
lookat44(cam->view, vec3( cx*cy*_distance, sy*_distance, sx*cy*_distance ), vec3(0,0,0), vec3(0,1,0) );
float x = rad(cam->yaw), y = rad(-cam->pitch), cx = cosf(x), cy = cosf(y), sx = sinf(x), sy = sinf(y);
lookat44(cam->view, vec3( cx*cy*cam->distance, sy*cam->distance, sx*cy*cam->distance ), vec3(0,0,0), vec3(0,1,0) );
// save for next call
cam->last_move.x = _mouse.x;
@ -182,6 +170,7 @@ void camera_orbit( camera_t *cam, float yaw, float pitch, float inc_distance ) {
int ui_camera( camera_t *cam ) {
int changed = 0;
changed |= ui_bool("Orthographic", &cam->orthographic);
changed |= ui_bool("Damping", &cam->damping);
if( !cam->damping ) ui_disable();
changed |= ui_slider2("Move friction", &cam->move_friction, va("%5.3f", cam->move_friction));
@ -199,6 +188,7 @@ int ui_camera( camera_t *cam ) {
ui_enable();
ui_separator();
changed |= ui_float("FOV (degrees)", &cam->fov);
changed |= ui_float("Orbit distance", &cam->distance);
ui_disable();
changed |= ui_mat44("Projection matrix", cam->proj);
ui_enable();

View File

@ -14,6 +14,11 @@ typedef struct camera_t {
float look_friction, look_damping;
vec2 last_look; vec3 last_move; // used for friction and damping
bool damping;
bool orthographic; // 0 perspective, 1 orthographic; when ortho: dimetric[if pitch == -30o], isometric[if pitch == 35.264o]
float distance; // distance to pivot, when orbiting
// vec2 polarity = { +1,-1 }; // @todo
// vec2 sensitivity = { 2,2 }; // @todo
} camera_t;
API camera_t camera();

View File

@ -5,6 +5,16 @@ __attribute__((constructor)) void init_argcv(int argc, char **argv) { __argc = a
#endif
#endif
void argvadd(const char *arg) {
char **argv = MALLOC( sizeof(char*) * (__argc+1) );
for( int i = 0; i < __argc; ++i ) {
argv[i] = __argv[i];
}
argv[__argc] = STRDUP(arg);
__argv = argv;
++__argc;
}
const char *app_path() { // @fixme: should return absolute path always. see tcc -g -run
static char buffer[1024] = {0};
if( buffer[0] ) return buffer;

View File

@ -10,6 +10,7 @@ API void thread_destroy( void *thd );
API int argc();
API char* argv(int);
API void argvadd(const char *arg);
API int flag(const char *commalist); // --arg // app_flag?
API const char* option(const char *commalist, const char *defaults); // --arg=string or --arg string

View File

@ -149,6 +149,10 @@ static int ui_using_v2_menubar = 0;
#define UI_FONT_TERMINAL_SIZE UI_FONT_ENUM(14,14)
#endif
#define UI_FONT_REGULAR_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#define UI_FONT_HEADING_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#define UI_FONT_TERMINAL_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#if UI_ICONS_SMALL
#define UI_ICON_FONTSIZE UI_FONT_ENUM(16.5f,16.5f)
#define UI_ICON_SPACING_X UI_FONT_ENUM(-2,-2)
@ -187,8 +191,12 @@ static void nk_config_custom_fonts() {
for( char *data = vfs_load(UI_FONT_REGULAR, &datalen); data; data = 0 ) {
float font_size = UI_FONT_REGULAR_SIZE;
struct nk_font_config cfg = nk_font_config(font_size);
cfg.oversample_v = 2;
cfg.pixel_snap = 0;
cfg.oversample_h = UI_FONT_REGULAR_SAMPLING.x;
cfg.oversample_v = UI_FONT_REGULAR_SAMPLING.y;
cfg.pixel_snap = UI_FONT_REGULAR_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
// win32: struct nk_font *arial = nk_font_atlas_add_from_file(atlas, va("%s/fonts/arial.ttf",getenv("windir")), font_size, &cfg); font = arial ? arial : font;
// struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "nuklear/extra_font/DroidSans.ttf", font_size, &cfg); font = droid ? droid : font;
struct nk_font *regular = nk_font_atlas_add_from_memory(atlas, data, datalen, font_size, &cfg); font = regular ? regular : font;
@ -196,10 +204,10 @@ static void nk_config_custom_fonts() {
// ...with icons embedded on it.
static struct icon_font {
const char *file; int yspacing; nk_rune range[3];
const char *file; int yspacing; vec3 sampling; nk_rune range[3];
} icons[] = {
{"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf"
{"materialdesignicons-webfont.ttf", 2, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}},
{"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {1,1,1}, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf"
{"materialdesignicons-webfont.ttf", 2, {1,1,1}, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}},
};
for( int f = 0; f < countof(icons); ++f )
for( char *data = vfs_load(icons[f].file, &datalen); data; data = 0 ) {
@ -212,9 +220,13 @@ static void nk_config_custom_fonts() {
// cfg.font->ascent += ICON_ASCENT;
// cfg.font->height += ICON_HEIGHT;
cfg.oversample_h = 1;
cfg.oversample_v = 1;
cfg.pixel_snap = 1;
cfg.oversample_h = icons[f].sampling.x;
cfg.oversample_v = icons[f].sampling.y;
cfg.pixel_snap = icons[f].sampling.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
struct nk_font *icons = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_ICON_FONTSIZE, &cfg);
}
@ -222,15 +234,19 @@ static void nk_config_custom_fonts() {
// Monospaced font. Used in terminals or consoles.
for( char *data = vfs_load(UI_FONT_TERMINAL, &datalen); data; data = 0 ) {
const float font_size = UI_FONT_REGULAR_SIZE;
const float font_size = UI_FONT_TERMINAL_SIZE;
static const nk_rune icon_range[] = {32, 127, 0};
struct nk_font_config cfg = nk_font_config(font_size);
cfg.range = icon_range;
cfg.oversample_h = 1;
cfg.oversample_v = 1;
cfg.pixel_snap = 1;
cfg.oversample_h = UI_FONT_TERMINAL_SAMPLING.x;
cfg.oversample_v = UI_FONT_TERMINAL_SAMPLING.y;
cfg.pixel_snap = UI_FONT_TERMINAL_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
// struct nk_font *proggy = nk_font_atlas_add_default(atlas, font_size, &cfg);
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, font_size, &cfg);
@ -239,7 +255,17 @@ static void nk_config_custom_fonts() {
// Extra optional fonts from here...
for( char *data = vfs_load(UI_FONT_HEADING, &datalen); data; data = 0 ) {
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_FONT_HEADING_SIZE, 0); // font = bold ? bold : font;
struct nk_font_config cfg = nk_font_config(UI_FONT_HEADING_SIZE);
cfg.oversample_h = UI_FONT_HEADING_SAMPLING.x;
cfg.oversample_v = UI_FONT_HEADING_SAMPLING.y;
cfg.pixel_snap = UI_FONT_HEADING_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_FONT_HEADING_SIZE, &cfg);
// font = bold ? bold : font;
}
nk_glfw3_font_stash_end(&nk_glfw); // nk_sdl_font_stash_end();
@ -394,7 +420,7 @@ int ui_menu_editbox(char *buf, int bufcap) {
}
int ui_has_menubar() {
return ui_using_v2_menubar || !!ui_items; // array_count(ui_items) > 0;
return ui_using_v2_menubar || !!ui_items; // ? UI_MENUROW_HEIGHT + 8 : 0; // array_count(ui_items) > 0;
}
static

View File

@ -539,8 +539,7 @@ int window_frame_begin() {
// generate Debug panel contents
if( may_render_debug_panel ) {
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
API int ui_debug();
ui_debug();
ui_engine();
(has_menu ? ui_window_end : ui_panel_end)();
}

View File

@ -327473,8 +327473,12 @@ static void gleq_key_callback(GLFWwindow* window, int key, int scancode, int act
event->type = GLEQ_KEY_REPEATED;
}
static void (*gleq_char_callback_prev)(GLFWwindow* window, unsigned int codepoint) = 0;
static void gleq_char_callback(GLFWwindow* window, unsigned int codepoint)
{
if( gleq_char_callback_prev )
gleq_char_callback_prev(window, codepoint);
GLEQevent* event = gleq_new_event();
event->type = GLEQ_CODEPOINT_INPUT;
event->window = window;
@ -327563,6 +327567,7 @@ GLEQDEF void gleqTrackWindow(GLFWwindow* window)
glfwSetCursorEnterCallback(window, gleq_cursor_enter_callback);
glfwSetScrollCallback(window, gleq_scroll_callback);
glfwSetKeyCallback(window, gleq_key_callback);
gleq_char_callback_prev = //< @r-lyeh
glfwSetCharCallback(window, gleq_char_callback);
#if GLFW_VERSION_MINOR >= 1
glfwSetDropCallback(window, gleq_file_drop_callback);

View File

@ -1343,6 +1343,10 @@ static int ui_using_v2_menubar = 0;
#define UI_FONT_TERMINAL_SIZE UI_FONT_ENUM(14,14)
#endif
#define UI_FONT_REGULAR_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#define UI_FONT_HEADING_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#define UI_FONT_TERMINAL_SAMPLING UI_FONT_ENUM(vec3(1,1,1),vec3(1,1,1))
#if UI_ICONS_SMALL
#define UI_ICON_FONTSIZE UI_FONT_ENUM(16.5f,16.5f)
#define UI_ICON_SPACING_X UI_FONT_ENUM(-2,-2)
@ -1381,8 +1385,12 @@ static void nk_config_custom_fonts() {
for( char *data = vfs_load(UI_FONT_REGULAR, &datalen); data; data = 0 ) {
float font_size = UI_FONT_REGULAR_SIZE;
struct nk_font_config cfg = nk_font_config(font_size);
cfg.oversample_v = 2;
cfg.pixel_snap = 0;
cfg.oversample_h = UI_FONT_REGULAR_SAMPLING.x;
cfg.oversample_v = UI_FONT_REGULAR_SAMPLING.y;
cfg.pixel_snap = UI_FONT_REGULAR_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
// win32: struct nk_font *arial = nk_font_atlas_add_from_file(atlas, va("%s/fonts/arial.ttf",getenv("windir")), font_size, &cfg); font = arial ? arial : font;
// struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "nuklear/extra_font/DroidSans.ttf", font_size, &cfg); font = droid ? droid : font;
struct nk_font *regular = nk_font_atlas_add_from_memory(atlas, data, datalen, font_size, &cfg); font = regular ? regular : font;
@ -1390,10 +1398,10 @@ static void nk_config_custom_fonts() {
// ...with icons embedded on it.
static struct icon_font {
const char *file; int yspacing; nk_rune range[3];
const char *file; int yspacing; vec3 sampling; nk_rune range[3];
} icons[] = {
{"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf"
{"materialdesignicons-webfont.ttf", 2, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}},
{"MaterialIconsSharp-Regular.otf", UI_ICON_SPACING_Y, {1,1,1}, {UI_ICON_MIN, UI_ICON_MED /*MAX*/, 0}}, // "MaterialIconsOutlined-Regular.otf" "MaterialIcons-Regular.ttf"
{"materialdesignicons-webfont.ttf", 2, {1,1,1}, {0xF68C /*ICON_MIN_MDI*/, 0xF1CC7/*ICON_MAX_MDI*/, 0}},
};
for( int f = 0; f < countof(icons); ++f )
for( char *data = vfs_load(icons[f].file, &datalen); data; data = 0 ) {
@ -1406,9 +1414,13 @@ static void nk_config_custom_fonts() {
// cfg.font->ascent += ICON_ASCENT;
// cfg.font->height += ICON_HEIGHT;
cfg.oversample_h = 1;
cfg.oversample_v = 1;
cfg.pixel_snap = 1;
cfg.oversample_h = icons[f].sampling.x;
cfg.oversample_v = icons[f].sampling.y;
cfg.pixel_snap = icons[f].sampling.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
struct nk_font *icons = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_ICON_FONTSIZE, &cfg);
}
@ -1416,15 +1428,19 @@ static void nk_config_custom_fonts() {
// Monospaced font. Used in terminals or consoles.
for( char *data = vfs_load(UI_FONT_TERMINAL, &datalen); data; data = 0 ) {
const float font_size = UI_FONT_REGULAR_SIZE;
const float font_size = UI_FONT_TERMINAL_SIZE;
static const nk_rune icon_range[] = {32, 127, 0};
struct nk_font_config cfg = nk_font_config(font_size);
cfg.range = icon_range;
cfg.oversample_h = 1;
cfg.oversample_v = 1;
cfg.pixel_snap = 1;
cfg.oversample_h = UI_FONT_TERMINAL_SAMPLING.x;
cfg.oversample_v = UI_FONT_TERMINAL_SAMPLING.y;
cfg.pixel_snap = UI_FONT_TERMINAL_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
// struct nk_font *proggy = nk_font_atlas_add_default(atlas, font_size, &cfg);
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, font_size, &cfg);
@ -1433,7 +1449,17 @@ static void nk_config_custom_fonts() {
// Extra optional fonts from here...
for( char *data = vfs_load(UI_FONT_HEADING, &datalen); data; data = 0 ) {
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_FONT_HEADING_SIZE, 0); // font = bold ? bold : font;
struct nk_font_config cfg = nk_font_config(UI_FONT_HEADING_SIZE);
cfg.oversample_h = UI_FONT_HEADING_SAMPLING.x;
cfg.oversample_v = UI_FONT_HEADING_SAMPLING.y;
cfg.pixel_snap = UI_FONT_HEADING_SAMPLING.z;
#if UI_LESSER_SPACING
cfg.spacing.x -= 1.0;
#endif
struct nk_font *bold = nk_font_atlas_add_from_memory(atlas, data, datalen, UI_FONT_HEADING_SIZE, &cfg);
// font = bold ? bold : font;
}
nk_glfw3_font_stash_end(&nk_glfw); // nk_sdl_font_stash_end();
@ -1588,7 +1614,7 @@ int ui_menu_editbox(char *buf, int bufcap) {
}
int ui_has_menubar() {
return ui_using_v2_menubar || !!ui_items; // array_count(ui_items) > 0;
return ui_using_v2_menubar || !!ui_items; // ? UI_MENUROW_HEIGHT + 8 : 0; // array_count(ui_items) > 0;
}
static
@ -7091,9 +7117,8 @@ static void *xml_path(struct xml *node, char *path, int down) {
const char *(xml_string)(char *key) {
struct xml *node = xml_path(*array_back(xml_docs), key, 0);
if( !node ) return "";
if( strchr(key, '@') ) return (const char *)node;
if( strchr(key, '$') ) return (const char *)node;
if( node && strchr(key, '@') ) return (const char *)node;
if( node && strchr(key, '$') ) return (const char *)node;
return "";
}
unsigned (xml_count)(char *key) {
@ -7680,7 +7705,10 @@ array(char*) file_list(const char *pathmasks) {
ASSERT(strend(cwd, "/"), "Error: dirs like '%s' must end with slash", cwd);
dir *d = dir_open(cwd, strstr(masks,"**") ? "r" : "");
int recurse = strstr(cwd, "**") || strstr(masks, "**");
strswap(cwd, "**", "./");
dir *d = dir_open(cwd, recurse ? "r" : "");
if( d ) {
for( int i = 0; i < dir_count(d); ++i ) {
if( dir_file(d,i) ) {
@ -8044,8 +8072,6 @@ static bool vfs_mount_hints(const char *path);
void vfs_reload() {
const char *app = app_name();
dir_cache = 0; // @leak
array_resize(vfs_hints, 0); // @leak
array_resize(vfs_entries, 0); // @leak
@ -10674,6 +10700,8 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
// convert to vbo data
int cp = ch; // f->cp2iter[ch];
//if(cp == 0xFFFD) continue;
//if(cp > f->num_glyphs) cp = 0xFFFD;
*t++ = X;
*t++ = Y;
*t++ = f->cp2iter[cp];
@ -18794,6 +18822,13 @@ int fx_load(const char *filemask) {
set_insert(added, name);
(void)postfx_load_from_mem(&fx, file_name(name), vfs_read(name));
}
if( 1 )
for each_array( file_list(filemask), char*, list ) {
if( set_find(added, list) ) continue;
char *name = STRDUP(list); // @leak
set_insert(added, name);
(void)postfx_load_from_mem(&fx, file_name(name), file_read(name));
}
return 1;
}
void fx_begin() {
@ -20957,6 +20992,117 @@ void ddraw_demo() {
ddraw_color_pop();
}
static int gizmo__mode;
static int gizmo__active;
static int gizmo__hover;
bool gizmo_active() {
return gizmo__active;
}
bool gizmo_hover() {
return gizmo__hover;
}
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
#if 0
ddraw_flush();
mat44 copy; copy44(copy, camera_get_active()->view);
if( 1 ) {
float *mv = camera_get_active()->view;
float d = sqrt(mv[4*0+0] * mv[4*0+0] + mv[4*1+1] * mv[4*1+1] + mv[4*2+2] * mv[4*2+2]);
if(4) mv[4*0+0] = d, mv[4*0+1] = 0, mv[4*0+2] = 0;
if(2) mv[4*1+0] = 0, mv[4*1+1] = d, mv[4*1+2] = 0;
if(1) mv[4*2+0] = 0, mv[4*2+1] = 0, mv[4*2+2] = d;
}
#endif
ddraw_color_push(dd_color);
ddraw_ontop_push(1);
int enabled = !ui_active() && !ui_hover();
vec3 mouse = enabled ? vec3(input(MOUSE_X),input(MOUSE_Y),input_down(MOUSE_L)) : vec3(0,0,0); // x,y,l
vec3 from = camera_get_active()->position;
vec3 to = editor_pick(mouse.x, mouse.y);
ray r = ray(from, to);
static vec3 src3, hit3, off3; static vec2 src2;
#define on_gizmo_dragged(X,Y,Z,COLOR,DRAWCMD, ...) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(Y?1:0,Y?0:1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
ddraw_color( hit_arrow || gizmo__active == (X*4+Y*2+Z) ? gizmo__hover = 1, YELLOW : COLOR ); \
DRAWCMD; \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), src3 = *pos, hit3 = hit_ground->p, off3 = mul3(sub3(src3,hit3),vec3(X,Y,Z)), gizmo__active = X*4+Y*2+Z; \
if( (gizmo__active && gizmo__active==(X*4+Y*2+Z)) || (!gizmo__active && hit_arrow) ) { ddraw_color( COLOR ); ( 1 ? ddraw_line : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active == (X*4+Y*2+Z) && hit_ground ) {{ __VA_ARGS__ }; modified = 1; gizmo__active *= !!input(MOUSE_L); } \
} while(0)
#define gizmo_translate(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, ddraw_arrow(*pos,add3(*pos,vec3(X,Y,Z))), { \
*pos = add3(line_closest_point(axis, hit_ground->p), off3); \
} )
#define gizmo_scale(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, (ddraw_line(*pos,add3(*pos,vec3(X,Y,Z))),ddraw_sphere(add3(*pos,vec3(X-0.1*X,Y-0.1*Y,Z-0.1*Z)),0.1)), { /*ddraw_aabb(arrow.min,arrow.max)*/ \
int component = (X*1+Y*2+Z*3)-1; \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
sca->v3[component] -= sgn * mag * 0.01; \
src2 = vec2(mouse.x, mouse.y); \
} )
#define gizmo_rotate(X,Y,Z,COLOR) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(0,1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
int hover = (hit_arrow ? (X*4+Y*2+Z) : 0); \
if( gizmo__active == (X*4+Y*2+Z) ) { ddraw_color(gizmo__active ? gizmo__hover = 1, YELLOW : WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active && hover == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color(COLOR); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active ) { ddraw_color(WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), gizmo__active = hover; \
if( (!gizmo__active && hover == (X*4+Y*2+Z)) || gizmo__active == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color( COLOR ); ( 1 ? ddraw_line_thin : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active && gizmo__active == (X*4+Y*2+Z) && hit_ground && enabled ) { \
int component = (Y*1+X*2+Z*3)-1; /*pitch,yaw,roll*/ \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
rot->v3[component] += sgn * mag; \
/*rot->v3[component] = clampf(rot->v3[component], -360, +360);*/ \
src2 = vec2(mouse.x, mouse.y); \
\
} \
gizmo__active *= enabled && !!input(MOUSE_L); \
} while(0)
gizmo__hover = 0;
int modified = 0;
if(enabled && input_down(KEY_SPACE)) gizmo__active = 0, gizmo__mode = (gizmo__mode + 1) % 3;
if(gizmo__mode == 0) gizmo_translate(1,0,0, RED);
if(gizmo__mode == 0) gizmo_translate(0,1,0, GREEN);
if(gizmo__mode == 0) gizmo_translate(0,0,1, BLUE);
if(gizmo__mode == 1) gizmo_scale(1,0,0, RED);
if(gizmo__mode == 1) gizmo_scale(0,1,0, GREEN);
if(gizmo__mode == 1) gizmo_scale(0,0,1, BLUE);
if(gizmo__mode == 2) gizmo_rotate(1,0,0, RED);
if(gizmo__mode == 2) gizmo_rotate(0,1,0, GREEN);
if(gizmo__mode == 2) gizmo_rotate(0,0,1, BLUE);
#if 0
ddraw_flush();
copy44(camera_get_active()->view, copy);
#endif
ddraw_ontop_pop();
ddraw_color_pop();
return modified;
}
#line 0
#line 1 "v4k_scene.c"
@ -20974,6 +21120,8 @@ camera_t camera() {
cam.position = vec3(10,10,10);
cam.updir = vec3(0,1,0);
cam.fov = 45;
cam.orthographic = false;
cam.distance = 3; // len3(cam.position);
cam.damping = false;
cam.move_friction = 0.09f;
@ -21065,19 +21213,18 @@ void camera_enable(camera_t *cam) {
void camera_fov(camera_t *cam, float fov) {
last_camera = cam;
#if 0 // isometric/dimetric
#define orthogonal(proj, fov, aspect, znear, zfar) \
ortho44((proj), -(fov) * (aspect), (fov) * (aspect), -(fov), (fov), (znear), (zfar))
float DIMETRIC = 30.000f;
float ISOMETRIC = 35.264f;
float aspect = window_width() / ((float)window_height()+!window_height());
orthogonal(cam->proj, 45, aspect, -1000, 1000); // why -1000?
// cam->yaw = 45;
cam->pitch = -ISOMETRIC;
#endif
cam->fov = fov;
perspective44(cam->proj, cam->fov, window_width() / ((float)window_height()+!window_height()), 0.01f, 1000.f);
if( cam->orthographic ) {
ortho44(cam->proj, -cam->fov * aspect, cam->fov * aspect, -cam->fov, cam->fov, 0.01f, 2000);
// [ref] https://commons.wikimedia.org/wiki/File:Isometric_dimetric_camera_views.png
// float pitch = cam->dimetric ? 30.000f : 35.264f; // dimetric or isometric
// cam->pitch = -pitch; // quickly reorient towards origin
} else {
perspective44(cam->proj, cam->fov, aspect, 0.01f, 2000.f);
}
}
void camera_fps(camera_t *cam, float yaw, float pitch) {
@ -21108,34 +21255,21 @@ void camera_fps(camera_t *cam, float yaw, float pitch) {
void camera_orbit( camera_t *cam, float yaw, float pitch, float inc_distance ) {
last_camera = cam;
vec2 inc_mouse = vec2(yaw, pitch);
// @todo: worth moving all these members into camera_t ?
static vec2 _mouse = {0,0};
static vec2 _polarity = { +1,-1 };
static vec2 _sensitivity = { 2,2 };
static float _friction = 0.75; //99;
static float _distance; do_once _distance = len3(cam->position);
// update dummy state
camera_fps(cam, 0,0);
// add smooth input
_mouse = mix2(_mouse, add2(_mouse, mul2(mul2(inc_mouse,_sensitivity),_polarity)), _friction);
_distance = mixf(_distance, _distance+inc_distance, _friction);
// @todo: add damping
vec3 _mouse = vec3(yaw, pitch, inc_distance);
cam->yaw += _mouse.x;
cam->pitch += _mouse.y;
cam->distance += _mouse.z;
// look: update angles
vec2 offset = sub2( _mouse, ptr2(&cam->last_move.x) );
if( 1 ) { // if _enabled
cam->yaw += offset.x;
cam->pitch += offset.y;
// look: limit pitch angle [-89..89]
cam->pitch = cam->pitch > 89 ? 89 : cam->pitch < -89 ? -89 : cam->pitch;
}
// compute view matrix
float x = rad(cam->yaw), y = rad(cam->pitch), cx = cosf(x), cy = cosf(y), sx = sinf(x), sy = sinf(y);
lookat44(cam->view, vec3( cx*cy*_distance, sy*_distance, sx*cy*_distance ), vec3(0,0,0), vec3(0,1,0) );
float x = rad(cam->yaw), y = rad(-cam->pitch), cx = cosf(x), cy = cosf(y), sx = sinf(x), sy = sinf(y);
lookat44(cam->view, vec3( cx*cy*cam->distance, sy*cam->distance, sx*cy*cam->distance ), vec3(0,0,0), vec3(0,1,0) );
// save for next call
cam->last_move.x = _mouse.x;
@ -21144,6 +21278,7 @@ void camera_orbit( camera_t *cam, float yaw, float pitch, float inc_distance ) {
int ui_camera( camera_t *cam ) {
int changed = 0;
changed |= ui_bool("Orthographic", &cam->orthographic);
changed |= ui_bool("Damping", &cam->damping);
if( !cam->damping ) ui_disable();
changed |= ui_slider2("Move friction", &cam->move_friction, va("%5.3f", cam->move_friction));
@ -21161,6 +21296,7 @@ int ui_camera( camera_t *cam ) {
ui_enable();
ui_separator();
changed |= ui_float("FOV (degrees)", &cam->fov);
changed |= ui_float("Orbit distance", &cam->distance);
ui_disable();
changed |= ui_mat44("Projection matrix", cam->proj);
ui_enable();
@ -23052,6 +23188,16 @@ __attribute__((constructor)) void init_argcv(int argc, char **argv) { __argc = a
#endif
#endif
void argvadd(const char *arg) {
char **argv = MALLOC( sizeof(char*) * (__argc+1) );
for( int i = 0; i < __argc; ++i ) {
argv[i] = __argv[i];
}
argv[__argc] = STRDUP(arg);
__argv = argv;
++__argc;
}
const char *app_path() { // @fixme: should return absolute path always. see tcc -g -run
static char buffer[1024] = {0};
if( buffer[0] ) return buffer;
@ -25487,8 +25633,7 @@ int window_frame_begin() {
// generate Debug panel contents
if( may_render_debug_panel ) {
if( has_menu ? ui_window("Debug " ICON_MD_SETTINGS, 0) : ui_panel("Debug " ICON_MD_SETTINGS, 0) ) {
API int ui_debug();
ui_debug();
ui_engine();
(has_menu ? ui_window_end : ui_panel_end)();
}
@ -28077,7 +28222,7 @@ int engine_tick() {
return 0;
}
int ui_debug() {
int ui_engine() {
static int time_factor = 0;
static int playing = 0;
static int paused = 0;
@ -28305,118 +28450,6 @@ int ui_debug() {
return 0;
}
static int gizmo__mode;
static int gizmo__active;
static int gizmo__hover;
bool gizmo_active() {
return gizmo__active;
}
bool gizmo_hover() {
return gizmo__hover;
}
int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) {
#if 0
ddraw_flush();
mat44 copy; copy44(copy, camera_get_active()->view);
if( 1 ) {
float *mv = camera_get_active()->view;
float d = sqrt(mv[4*0+0] * mv[4*0+0] + mv[4*1+1] * mv[4*1+1] + mv[4*2+2] * mv[4*2+2]);
if(4) mv[4*0+0] = d, mv[4*0+1] = 0, mv[4*0+2] = 0;
if(2) mv[4*1+0] = 0, mv[4*1+1] = d, mv[4*1+2] = 0;
if(1) mv[4*2+0] = 0, mv[4*2+1] = 0, mv[4*2+2] = d;
}
#endif
ddraw_color_push(dd_color);
ddraw_ontop_push(1);
int enabled = !ui_active() && !ui_hover();
vec3 mouse = enabled ? vec3(input(MOUSE_X),input(MOUSE_Y),input_down(MOUSE_L)) : vec3(0,0,0); // x,y,l
vec3 from = camera_get_active()->position;
vec3 to = editor_pick(mouse.x, mouse.y);
ray r = ray(from, to);
static vec3 src3, hit3, off3; static vec2 src2;
#define on_gizmo_dragged(X,Y,Z,COLOR,DRAWCMD, ...) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(Y?1:0,Y?0:1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
ddraw_color( hit_arrow || gizmo__active == (X*4+Y*2+Z) ? gizmo__hover = 1, YELLOW : COLOR ); \
DRAWCMD; \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), src3 = *pos, hit3 = hit_ground->p, off3 = mul3(sub3(src3,hit3),vec3(X,Y,Z)), gizmo__active = X*4+Y*2+Z; \
if( (gizmo__active && gizmo__active==(X*4+Y*2+Z)) || (!gizmo__active && hit_arrow) ) { ddraw_color( COLOR ); ( 1 ? ddraw_line : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active == (X*4+Y*2+Z) && hit_ground ) {{ __VA_ARGS__ }; modified = 1; gizmo__active *= !!input(MOUSE_L); } \
} while(0)
#define gizmo_translate(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, ddraw_arrow(*pos,add3(*pos,vec3(X,Y,Z))), { \
*pos = add3(line_closest_point(axis, hit_ground->p), off3); \
} )
#define gizmo_scale(X,Y,Z,COLOR) \
on_gizmo_dragged(X,Y,Z,COLOR, (ddraw_line(*pos,add3(*pos,vec3(X,Y,Z))),ddraw_sphere(add3(*pos,vec3(X-0.1*X,Y-0.1*Y,Z-0.1*Z)),0.1)), { /*ddraw_aabb(arrow.min,arrow.max)*/ \
int component = (X*1+Y*2+Z*3)-1; \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
sca->v3[component] -= sgn * mag * 0.01; \
src2 = vec2(mouse.x, mouse.y); \
} )
#define gizmo_rotate(X,Y,Z,COLOR) do { \
vec3 dir = vec3(X,Y,Z); \
line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \
plane ground = { vec3(0,0,0), vec3(0,1,0) }; \
vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \
aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \
hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \
int hover = (hit_arrow ? (X*4+Y*2+Z) : 0); \
if( gizmo__active == (X*4+Y*2+Z) ) { ddraw_color(gizmo__active ? gizmo__hover = 1, YELLOW : WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active && hover == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color(COLOR); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
else if( !gizmo__active ) { ddraw_color(WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \
if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), gizmo__active = hover; \
if( (!gizmo__active && hover == (X*4+Y*2+Z)) || gizmo__active == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color( COLOR ); ( 1 ? ddraw_line_thin : ddraw_line_dashed)(axis.a, axis.b); } \
if( gizmo__active && gizmo__active == (X*4+Y*2+Z) && hit_ground && enabled ) { \
int component = (Y*1+X*2+Z*3)-1; /*pitch,yaw,roll*/ \
float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \
float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \
float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \
float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \
rot->v3[component] += sgn * mag; \
/*rot->v3[component] = clampf(rot->v3[component], -360, +360);*/ \
src2 = vec2(mouse.x, mouse.y); \
\
} \
gizmo__active *= enabled && !!input(MOUSE_L); \
} while(0)
gizmo__hover = 0;
int modified = 0;
if(enabled && input_down(KEY_SPACE)) gizmo__active = 0, gizmo__mode = (gizmo__mode + 1) % 3;
if(gizmo__mode == 0) gizmo_translate(1,0,0, RED);
if(gizmo__mode == 0) gizmo_translate(0,1,0, GREEN);
if(gizmo__mode == 0) gizmo_translate(0,0,1, BLUE);
if(gizmo__mode == 1) gizmo_scale(1,0,0, RED);
if(gizmo__mode == 1) gizmo_scale(0,1,0, GREEN);
if(gizmo__mode == 1) gizmo_scale(0,0,1, BLUE);
if(gizmo__mode == 2) gizmo_rotate(1,0,0, RED);
if(gizmo__mode == 2) gizmo_rotate(0,1,0, GREEN);
if(gizmo__mode == 2) gizmo_rotate(0,0,1, BLUE);
#if 0
ddraw_flush();
copy44(camera_get_active()->view, copy);
#endif
ddraw_ontop_pop();
ddraw_color_pop();
return modified;
}
#line 0
#line 1 "v4k_main.c"
@ -29023,21 +29056,22 @@ void editor_pump() {
// ----------------------------------------------------------------------------------------
API void editor_cursorpos(int x, int y);
void editor_cursorpos(int x, int y) {
glfwSetCursorPos( window_handle(), x, y );
}
void editor_symbol(int x, int y, const char *sym) {
#define FONT_SYMBOLS FONT_FACE2
#define FONT_WHITE FONT_COLOR1
#define FONT_YELLOW FONT_COLOR2
#define FONT_ORANGE FONT_COLOR3
#define FONT_CYAN FONT_COLOR4
// style: atlas size, unicode ranges and 6 font faces max
do_once font_face(FONT_SYMBOLS, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
do_once font_face(FONT_FACE2, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048);
// style: 10 colors max
do_once font_color(FONT_WHITE, WHITE);
do_once font_color(FONT_YELLOW, YELLOW);
do_once font_color(FONT_CYAN, CYAN);
do_once font_color(FONT_ORANGE, ORANGE);
do_once font_color(FONT_COLOR1, WHITE);
do_once font_color(FONT_COLOR2, RGBX(0xE8F1FF,128)); // GRAY);
do_once font_color(FONT_COLOR3, YELLOW);
do_once font_color(FONT_COLOR4, ORANGE);
do_once font_color(FONT_COLOR5, CYAN);
font_goto(x,y);
font_print(va(FONT_SYMBOLS FONT_WHITE FONT_H1 "%s", sym));
font_print(va(FONT_FACE2 /*FONT_WHITE*/ FONT_H1 "%s", sym));
}
void editor_frame( void (*game)(unsigned, float, double) ) {
@ -29050,7 +29084,7 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
window_cursor_shape(CURSOR_SW_AUTO);
editor.hz_high = window_fps_target();
fx_load("editorOutline.fs");
fx_load("**/editorOutline.fs");
fx_enable(0, 1);
obj_setname(editor.root = obj_new(obj), "Signals");
@ -29106,26 +29140,27 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
int is_borderless = !glfwGetWindowAttrib(window, GLFW_DECORATED);
int ingame = !editor.active;
static double clicked_titlebar = 0;
UI_MENU(14+is_borderless, \
UI_MENU(14+2*is_borderless, \
if(ingame) ui_disable(); \
UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \
UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_engine()) \
if(ingame) ui_enable(); \
UI_MENU_ITEM(ICON_PL4Y, if(editor.t == 0) editor_send("eject"); editor_send(window_has_pause() ? "play" : "pause")) \
UI_MENU_ITEM(ICON_SKIP, editor_send(window_has_pause() ? "frame" : "slomo")) \
UI_MENU_ITEM(ICON_MDI_STOP, editor_send("stop")) \
UI_MENU_ITEM(ICON_MDI_EJECT, editor_send("eject")) \
UI_MENU_ITEM(STATS, stats_mode = (++stats_mode) % 3) \
UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+34 + 32*is_borderless, clicked_titlebar = time_ms()) \
UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+32 + 32*2*is_borderless + 10, clicked_titlebar = time_ms()) \
if(ingame) ui_disable(); \
UI_MENU_ITEM(ICON_MD_FOLDER_SPECIAL, editor_send("browser")) \
UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \
UI_MENU_ITEM(ICON_MDI_SCRIPT_TEXT, editor_send("script")) \
UI_MENU_ITEM(ICON_MDI_CHART_TIMELINE, editor_send("timeline")) \
UI_MENU_ITEM(ICON_MDI_CONSOLE, editor_send("console")) \
UI_MENU_ITEM(ICON_MDI_GRAPH, editor_send("nodes")) \
UI_MENU_ITEM(ICON_MD_SEARCH, editor_send("filter")) \
UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_debug()) \
UI_MENU_ITEM(ICON_MDI_MAGNIFY, editor_send("filter")) /*MD_SEARCH*/ \
if(ingame) ui_enable(); \
UI_MENU_ITEM(ICON_MD_CLOSE, editor_send("quit")) \
UI_MENU_ITEM(window_has_maximize() ? ICON_MDI_WINDOW_MINIMIZE : ICON_MDI_WINDOW_MAXIMIZE, window_maximize(1 ^ window_has_maximize())) \
UI_MENU_ITEM(ICON_MDI_CLOSE, editor_send("quit")) \
);
if( is_borderless ) {
@ -29170,7 +29205,7 @@ void editor_frame( void (*game)(unsigned, float, double) ) {
fx_end();
// draw box selection
if( !ui_active() ) { //< check that we're not moving a window
if( !ui_active() && window_has_cursor() && cursorshape ) { //< check that we're not moving a window + not in fps cam
static vec2 from = {0}, to = {0};
if( input_down(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)), from = to;
if( input(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y));

View File

@ -398,12 +398,6 @@ extern "C" {
static void fn(void)
#endif
#if 0 // autorun demo
void byebye(void) { puts("seen after main()"); }
AUTORUN { puts("seen before main()"); }
AUTORUN { puts("seen before main() too"); atexit( byebye ); }
#endif
// -----------------------------------------------------------------------------
// build info
@ -1401,32 +1395,32 @@ void* obj_free(void *o);
#define obj_vtable(method,RC,...) RC macro(obj_##method)(){ __VA_ARGS__ }; RC (*obj_##method[256])() = { REPEAT256(macro(obj_##method)) };
#define obj_vtable_null(method,RC) RC (*obj_##method[256])() = { 0 }; // null virtual table. will crash unless obj_extend'ed
#define REPEAT16(f) f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f
#define REPEAT64(f) REPEAT16(f),REPEAT16(f),REPEAT16(f),REPEAT16(f)
#define REPEAT256(f) REPEAT64(f),REPEAT64(f),REPEAT64(f),REPEAT64(f)
#define REPEAT16(f) f,f,f,f,f,f,f,f,f,f,f,f,f,f,f,f ///-
#define REPEAT64(f) REPEAT16(f),REPEAT16(f),REPEAT16(f),REPEAT16(f) ///-
#define REPEAT256(f) REPEAT64(f),REPEAT64(f),REPEAT64(f),REPEAT64(f) ///-
#undef EXTEND
#define EXTEND(...) EXPAND(EXTEND, __VA_ARGS__)
#define EXTEND2(o,F1) obj_extend(o,F1)
#define EXTEND3(o,F1,F2) obj_extend(o,F1), obj_extend(o,F2)
#define EXTEND4(o,F1,F2,F3) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3)
#define EXTEND5(o,F1,F2,F3,F4) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4)
#define EXTEND6(o,F1,F2,F3,F4,F5) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5)
#define EXTEND7(o,F1,F2,F3,F4,F5,F6) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6)
#define EXTEND8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7)
#define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8)
#define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9)
#define EXTEND2(o,F1) obj_extend(o,F1) ///-
#define EXTEND3(o,F1,F2) obj_extend(o,F1), obj_extend(o,F2) ///-
#define EXTEND4(o,F1,F2,F3) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3) ///-
#define EXTEND5(o,F1,F2,F3,F4) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4) ///-
#define EXTEND6(o,F1,F2,F3,F4,F5) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5) ///-
#define EXTEND7(o,F1,F2,F3,F4,F5,F6) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6) ///-
#define EXTEND8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7) ///-
#define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8) ///-
#define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9) ///-
#define EXTEND_T(...) EXPAND(EXTEND_T, __VA_ARGS__)
#define EXTEND_T2(o,F1) obj_extend_t(o,F1)
#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2)
#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3)
#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4)
#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5)
#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6)
#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7)
#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8)
#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9)
#define EXTEND_T2(o,F1) obj_extend_t(o,F1) ///-
#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2) ///-
#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3) ///-
#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4) ///-
#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5) ///-
#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6) ///-
#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7) ///-
#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8) ///-
#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9) ///-
// --- declare vtables
@ -3761,6 +3755,12 @@ API void ddraw_prism(vec3 center, float radius, float height, vec3 normal, int s
API void ddraw_demo();
API void ddraw_flush();
API void ddraw_flush_projview(mat44 proj, mat44 view);
// transform gizmos
API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
API bool gizmo_active();
API bool gizmo_hover();
#line 0
#line 1 "v4k_scene.h"
@ -3780,6 +3780,11 @@ typedef struct camera_t {
float look_friction, look_damping;
vec2 last_look; vec3 last_move; // used for friction and damping
bool damping;
bool orthographic; // 0 perspective, 1 orthographic; when ortho: dimetric[if pitch == -30o], isometric[if pitch == 35.264o]
float distance; // distance to pivot, when orbiting
// vec2 polarity = { +1,-1 }; // @todo
// vec2 sensitivity = { 2,2 }; // @todo
} camera_t;
API camera_t camera();
@ -4185,6 +4190,7 @@ API void thread_destroy( void *thd );
API int argc();
API char* argv(int);
API void argvadd(const char *arg);
API int flag(const char *commalist); // --arg // app_flag?
API const char* option(const char *commalist, const char *defaults); // --arg=string or --arg string
@ -4667,6 +4673,7 @@ API void window_setclipboard(const char *text);
#define EDITOR_VERSION "2023.10"
// ----------------------------------------------------------------------------
// editor bindings
typedef struct editor_bind_t {
const char *command;
@ -4680,6 +4687,7 @@ API void editor_addbind(editor_bind_t bind);
void macro(editor_bind_##CMD##_fn_)() { __VA_ARGS__ }; AUTORUN { array_push(editor_binds, ((editor_bind_t){#CMD,KEYS,macro(editor_bind_##CMD##_fn_)}) ); }
// ----------------------------------------------------------------------------
// editor properties
#define EDITOR_PROPERTYDEF(T,property_name) \
typedef map(void*,T) editor_##property_name##_map_t; \
@ -4689,25 +4697,26 @@ API void editor_set##property_name(const void *obj, T value); \
API void editor_alt##property_name(const void *obj); \
API void editor_no##property_name(void *obj);
EDITOR_PROPERTYDEF(int, open); // whether object is tree opened in tree editor
EDITOR_PROPERTYDEF(int, selected); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, changed); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, popup); // whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, bookmarked);
EDITOR_PROPERTYDEF(int, visible);
EDITOR_PROPERTYDEF(int, script);
EDITOR_PROPERTYDEF(int, event);
EDITOR_PROPERTYDEF(char*,iconinstance);
EDITOR_PROPERTYDEF(char*,iconclass);
EDITOR_PROPERTYDEF(int, treeoffsety);
EDITOR_PROPERTYDEF(int, open); ///- whether object is tree opened in tree editor
EDITOR_PROPERTYDEF(int, selected); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, changed); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, popup); ///- whether object is displaying a contextual popup or not
EDITOR_PROPERTYDEF(int, bookmarked); ///-
EDITOR_PROPERTYDEF(int, visible); ///-
EDITOR_PROPERTYDEF(int, script); ///-
EDITOR_PROPERTYDEF(int, event); ///-
EDITOR_PROPERTYDEF(char*,iconinstance); ///-
EDITOR_PROPERTYDEF(char*,iconclass); ///-
EDITOR_PROPERTYDEF(int, treeoffsety); ///-
API void editor_destroy_properties(void *o);
API void editor_load_on_boot(void);
API void editor_save_on_quit(void);
// ----------------------------------------------------------------------------
// editor ui
enum {
enum EDITOR_MODE {
EDITOR_PANEL,
EDITOR_WINDOW,
EDITOR_WINDOW_NK,
@ -4717,6 +4726,9 @@ enum {
API int editor_begin(const char *title, int mode);
API int editor_end(int mode);
// ----------------------------------------------------------------------------------------
// editor selection
API int editor_filter();
API void editor_select(const char *mask);
API void editor_unselect(); // same than editor_select("!**");
@ -4727,6 +4739,7 @@ API void* editor_first_selected();
API void* editor_last_selected();
// ----------------------------------------------------------------------------------------
// editor instancing
API void editor_addtoworld(obj *o);
API void editor_watch(const void *o);
@ -4737,44 +4750,34 @@ API void editor_destroy_selected();
API void editor_inspect(obj *o);
// ----------------------------------------------------------------------------------------
// tty
API int editor_send(const char *cmd); // return job-id
API const char* editor_recv(int jobid, double timeout_ss);
API void editor_pump();
// ----------------------------------------------------------------------------------------
API void editor_symbol(int x, int y, const char *sym);
API void editor_frame( void (*game)(unsigned, float, double) );
API void editor_gizmos(int dim);
// ----------------------------------------------------------------------------------------
API int editor_send(const char *command);
// editor utils
//API void editor();
//API bool editor_active();
API vec3 editor_pick(float mouse_x, float mouse_y);
API char* editor_path(const char *path);
API void editor_symbol(int x, int y, const char *sym);
API void editor_gizmos(int dim);
// ----------------------------------------------------------------------------------------
// editor loop
API int editor_send(const char *cmd); // returns job-id
API const char* editor_recv(int jobid, double timeout_ss);
API void editor_pump();
API void editor_frame( void (*game)(unsigned, float, double) );
// ----------------------------------------------------------------------------------------
// engine section: @todo: expand me
API float* engine_getf(const char *key);
API int* engine_geti(const char *key);
API char** engine_gets(const char *key);
API int engine_send(const char *cmd, const char *optional_value);
API int ui_debug();
// open file dialog
API char* dialog_load();
API char* dialog_save();
// transform gizmos
API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca);
API bool gizmo_active();
API bool gizmo_hover();
API int ui_engine();
#line 0
// ----
@ -4789,13 +4792,13 @@ API bool gizmo_hover();
#include <GLFW/glfw3.h>
#include <emscripten.h>
#include <emscripten/html5.h>
#define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK)
#define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK) ///-
#else
#if is(win32) /*&& is(tcc)*/ // && ENABLE_DLL
#ifdef GLAD_API_CALL
#undef GLAD_API_CALL
#endif
#define GLAD_API_CALL extern API
#define GLAD_API_CALL extern API ///-
#endif
#ifndef GLAD_GL_H_
#include "v4k"