From 5850a5d918a6c307c1c1f9d3221d9337187fddde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Thu, 2 Nov 2023 11:22:42 +0100 Subject: [PATCH] sync fwk --- tools/editor/fwk_editor.h | 724 ----------------------- tools/editor/fwk_editor1_scene.h | 184 ------ tools/editor/fwk_editor2_browser.h | 21 - tools/editor/fwk_editor3_timeline.h | 172 ------ tools/editor/fwk_editor4_console.h | 56 -- tools/editor/fwk_editor5_nodes.h | 881 ---------------------------- tools/editor_rename.bat | 2 +- 7 files changed, 1 insertion(+), 2039 deletions(-) delete mode 100644 tools/editor/fwk_editor.h delete mode 100644 tools/editor/fwk_editor1_scene.h delete mode 100644 tools/editor/fwk_editor2_browser.h delete mode 100644 tools/editor/fwk_editor3_timeline.h delete mode 100644 tools/editor/fwk_editor4_console.h delete mode 100644 tools/editor/fwk_editor5_nodes.h diff --git a/tools/editor/fwk_editor.h b/tools/editor/fwk_editor.h deleted file mode 100644 index a9eaad4..0000000 --- a/tools/editor/fwk_editor.h +++ /dev/null @@ -1,724 +0,0 @@ -// ## Editor long-term plan -// - editor = tree of nodes. levels and objects are nodes, and their widgets are also nodes -// - you can perform actions on nodes, with or without descendants, top-bottom or bottom-top -// - these operations include load/save, undo/redo, reset, play/render, ddraw, etc -// - nodes are saved to disk as a filesystem layout: parents are folders, and leafs are files -// - network replication can be done by external tools by comparing the filesystems and by sending the resulting diff zipped -// -// ## Editor roadmap -// - Gizmos✱, scene tree, property editor✱, load/save✱, undo/redo✱, copy/paste, on/off (vis,tick,ddraw,log), vcs. -// - Scenenode pass: node singleton display, node console, node labels, node outlines✱. -// - Render pass: billboards✱, materials, un/lit, cast shadows, wireframe, skybox✱/mie✱, fog/atmosphere -// - Level pass: volumes, triggers, platforms, level streaming, collide✱, physics -// - Edit pass: Procedural content, brushes, noise and CSG. -// - GUI pass: timeline and data tracks, node graphs. - -// ## Alt plan -// editor is a database + window/tile manager + ui toolkit; all network driven. -// to be precise, editor is a dumb app and ... -// - does not know a thing about what it stores. -// - does not know how to render the game graphics. -// - does not know how to run the game logic. -// -// the editor will create a canvas for your game to render. -// your game will be responsible to tick the logic and render the window inside the editor. -// -// that being said, editor... -// - can store datas hierarchically. -// - can perform diffs and merges, and version the datas into repositories. -// - can be instructed to render UI on top of game and window views. -// - can download new .natvis and plugins quickly. -// - can dump whole project in a filesystem form (zip). - -// - editor reflects database contents up-to-date. -// - database can be queried and modified via OSC(UDP) commands. - -// editor database uses one table, and stores two kind of payload types: -// - classes: defines typename and dna. class names are prefixed by '@' -// - instances: defines typename and datas. instance names are as-is, not prefixed. -// -// every save contains 5Ws: what, who, when, where, how, -// every save can be diffed/merged. - -// ---------------------------------------------------------------------------- - -#define EDITOR_VERSION "2023.10" - -// ---------------------------------------------------------------------------- - -typedef struct editor_bind_t { - const char *command; - const char *bindings; - void (*fn)(); -} editor_bind_t; - -array(editor_bind_t) editor_binds; - -#define EDITOR_BIND(CMD,KEYS,...) void macro(editor_bind_##CMD##_fn_)() { __VA_ARGS__ }; AUTORUN { array_push(editor_binds, ((editor_bind_t){#CMD,KEYS,macro(editor_bind_##CMD##_fn_)}) ); } - -// ---------------------------------------------------------------------------- - -typedef void (*editor_no_property)(void *); -array(void*) editor_persist_kv; -array(editor_no_property) editor_no_properties; - -#define EDITOR_PROPERTY(property_name,T,defaults) \ -typedef map(void*,T) editor_##property_name##_map_t; \ -editor_##property_name##_map_t *editor_##property_name##_map() { \ - static editor_##property_name##_map_t map = 0; do_once map_init_ptr(map); \ - return ↦ \ -} \ -T editor_##property_name(const void *obj) { \ - return *map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ -} \ -void editor_set##property_name(const void *obj, T value) { \ - *map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) value)) = ((T) value); \ -} \ -void editor_alt##property_name(const void *obj) { \ - T* found = map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ - *found = (T)(uintptr_t)!(*found); \ -} \ -void editor_no##property_name(void *obj) { \ - T* found = map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ - map_erase(*editor_##property_name##_map(), (void*)obj); \ -} \ -AUTORUN { array_push(editor_persist_kv, #T); array_push(editor_persist_kv, editor_##property_name##_map()); array_push(editor_no_properties, editor_no##property_name); } - -EDITOR_PROPERTY(open, int, 0); // whether object is tree opened in tree editor -EDITOR_PROPERTY(selected, int, 0); // whether object is displaying a contextual popup or not -EDITOR_PROPERTY(changed, int, 0); // whether object is displaying a contextual popup or not -EDITOR_PROPERTY(popup, int, 0); // whether object is displaying a contextual popup or not -EDITOR_PROPERTY(visible, int, 0); -EDITOR_PROPERTY(script, int, 0); -EDITOR_PROPERTY(event, int, 0); -EDITOR_PROPERTY(iconinstance, char*, 0); -EDITOR_PROPERTY(iconclass, char*, 0); -EDITOR_PROPERTY(treeoffsety, int, 0); -// new prop: breakpoint: request to break on any given node -// new prop: persist: objects with this property will be saved on disk - -void editor_destroy_properties(void *o) { - for each_array(editor_no_properties,editor_no_property,fn) { - fn(o); - } -} - -void editor_load_on_boot(void) { - puts("@todo: load editor"); -} -void editor_save_on_quit(void) { - puts("@todo: save editor"); -} -AUTORUN { - editor_load_on_boot(); - (atexit)(editor_save_on_quit); -} - -// ---------------------------------------------------------------------------- - -typedef int(*subeditor)(int mode); - -struct editor_t { - // time - unsigned frame; - double t, dt, slomo; - // controls - int transparent; - int attached; - int active; // focus? does_grabinput instead? - int key; - vec2 mouse; // 2d coord for ray/picking - bool gamepad; // mask instead? |1|2|4|8 - int hz_high, hz_medium, hz_low; - int filter; - bool battery; // battery mode: low fps - bool unlit; - bool ddraw; - // event root nodes - obj* root; - obj* on_init; - obj* on_tick; - obj* on_draw; - obj* on_edit; - obj* on_quit; - // all of them (hierarchical) - array(obj*) objs; // @todo:set() world? - // all of them (flat) - set(obj*) world; - // - array(char*) cmds; - // subeditors - array(subeditor) subeditors; -} editor = { - .active = 1, - .gamepad = 1, - .hz_high = 60, .hz_medium = 18, .hz_low = 5, -}; - -enum { - EDITOR_PANEL, - EDITOR_WINDOW, - EDITOR_WINDOW_NK, - EDITOR_WINDOW_NK_SMALL, -}; - -int editor_begin(const char *title, int mode) { - if( mode == 0 ) return ui_panel(title, PANEL_OPEN); - if( mode == 1 ) return ui_window(title, 0); - - int ww = window_width(), w = ww * 0.66; - int hh = window_height(), h = hh * 0.66; - - struct nk_rect position = { (ww-w)/2,(hh-h)/2, w,h }; - nk_flags win_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER | - NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | - NK_WINDOW_CLOSABLE | NK_WINDOW_MINIMIZABLE | - // NK_WINDOW_SCALE_LEFT|NK_WINDOW_SCALE_TOP| //< @fixme: move this logic into nuklear - // NK_WINDOW_MAXIMIZABLE | NK_WINDOW_PINNABLE | - 0; // NK_WINDOW_SCROLL_AUTO_HIDE; - - if( mode == 3 ) { - mode = 2, position.x = input(MOUSE_X), position.w = w/3, win_flags = - NK_WINDOW_TITLE|NK_WINDOW_CLOSABLE| - NK_WINDOW_SCALABLE|NK_WINDOW_MOVABLE| //< nuklear requires these two to `remember` popup rects - 0; - } - - if( mode == 2 || mode == 3 ) - if (nk_begin(ui_ctx, title, position, win_flags)) - return 1; - else - return nk_end(ui_ctx), 0; - - return 0; -} -int editor_end(int mode) { - if( mode == 0 ) return ui_panel_end(); - if( mode == 1 ) return ui_window_end(); - if( mode == 2 ) nk_end(ui_ctx); - if( mode == 3 ) nk_end(ui_ctx); - return 0; -} - -#if 0 // deprecate -bool editor_active() { - return ui_hover() || ui_active() || gizmo_active() ? editor.active : 0; -} -#endif - -int editor_filter() { - if( editor.filter ) { - if (nk_begin(ui_ctx, "Filter", nk_rect(window_width()-window_width()*0.33,32, window_width()*0.33, 40), - NK_WINDOW_NO_SCROLLBAR)) { - - char *bak = ui_filter; ui_filter = 0; - ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &bak); - ui_filter = bak; - - if( input(KEY_ESC) || ( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 )) { - if( ui_filter ) ui_filter[0] = '\0'; - editor.filter = 0; - } - } - nk_end(ui_ctx); - } - - return editor.filter; -} - -static -int editor_select_(void *o, const char *mask) { - int matches = 0; - int off = mask[0] == '!', inv = mask[0] == '~'; - int match = strmatchi(obj_type(o), mask+off+inv) || strmatchi(obj_name(o), mask+off+inv); - if( match ) { - editor_setselected(o, inv ? editor_selected(o) ^ 1 : !off); - ++matches; - } - for each_objchild(o, obj*, oo) { - matches += editor_select_(oo, mask); - } - return matches; -} -void editor_select(const char *mask) { - for each_array( editor.objs, obj*, o ) - editor_select_(o, mask); -} -void editor_unselect() { // same than editor_select("!**"); - for each_map_ptr(*editor_selected_map(), void*,o, int, k) { - if( *k ) *k = 0; - } -} - -void editor_select_aabb(aabb box) { - int is_inv = input_held(KEY_CTRL); - int is_add = input_held(KEY_SHIFT); - if( !is_inv && !is_add ) editor_unselect(); - - aabb item = {0}; - for each_set_ptr( editor.world, obj*, o ) { - if( obj_hasmethod(*o,aabb) && obj_aabb(*o, &item) ) { - if( aabb_test_aabb(item, box) ) { - if( is_inv ) - editor_altselected(*o); - else - editor_setselected(*o, 1); - } - } - } -} - -static obj* active_ = 0; -static void editor_selectgroup_(obj *o, obj *first, obj *last) { - // printf("%s (looking for %s in [%s..%s])\n", obj_name(o), active_ ? obj_name(active_) : "", obj_name(first), obj_name(last)); - if( !active_ ) if( o == first || o == last ) active_ = o == first ? last : first; - if( active_ ) editor_setselected(o, 1); - if( o == active_ ) active_ = 0; - for each_objchild(o, obj*, oo) { - editor_selectgroup_(oo, first, last); - } -} -void editor_selectgroup(obj *first, obj *last) { - if( last ) { - if( !first ) first = array_count(editor.objs) ? editor.objs[0] : NULL; - if( !first ) editor_setselected(last, 1); - else { - active_ = 0; - for each_array(editor.objs,obj*,o) { - editor_selectgroup_(o, first, last); - } - } - } -} - -static obj *find_any_selected_(obj *o) { - if( editor_selected(o) ) return o; - for each_objchild(o,obj*,oo) { - obj *ooo = find_any_selected_(oo); - if( ooo ) - return ooo; - } - return 0; -} -void* editor_first_selected() { - for each_array(editor.objs,obj*,o) { - obj *oo = find_any_selected_(o); - // if( oo ) printf("1st found: %s\n", obj_name(oo)); - if( oo ) return oo; - } - return 0; -} - -static obj *find_last_selected_(obj *o) { - void *last = 0; - if( editor_selected(o) ) last = o; - for each_objchild(o,obj*,oo) { - obj *ooo = find_last_selected_(oo); - if( ooo ) - last = ooo; - } - return last; -} -void* editor_last_selected() { - void *last = 0; - for each_array(editor.objs,obj*,o) { - obj *oo = find_last_selected_(o); - // if( oo ) printf("last found: %s\n", obj_name(oo)); - if( oo ) last = oo; - } - return last; -} - -// ---------------------------------------------------------------------------------------- - -void editor_addtoworld(obj *o) { - set_find_or_add(editor.world, o); - for each_objchild(o, obj*, oo) { - editor_addtoworld(oo); - } -} - -void editor_watch(const void *o) { - array_push(editor.objs, (obj*)o); - obj_push(o); // save state - - editor_addtoworld((obj*)o); -} -void* editor_spawn(const char *ini) { // deprecate? - obj *o = obj_make(ini); - editor_watch(o); - return o; -} -void editor_spawn1() { - obj *selected = editor_first_selected(); - obj *o = selected ? obj_make(obj_saveini(selected)) : obj_new(obj); - if( selected ) obj_attach(selected, o), editor_setopen(selected, 1); - else - editor_watch(o); - - editor_unselect(); - editor_setselected(o, 1); -} - -typedef set(obj*) set_objp_t; -static -void editor_glob_recurse(set_objp_t*list, obj *o) { - set_find_or_add(*list, o); - for each_objchild(o,obj*,oo) { - editor_glob_recurse(list, oo); - } -} -void editor_destroy_selected() { - set_objp_t list = 0; - set_init_ptr(list); - for each_map_ptr(*editor_selected_map(), obj*,o, int,selected) { - if( *selected ) { editor_glob_recurse(&list, *o); } - } - for each_set(list, obj*, o) { - obj_detach(o); - } - for each_set(list, obj*, o) { - // printf("deleting %p %s\n", o, obj_name(o)); - // remove from watched items - for (int i = 0, end = array_count(editor.objs); i < end; ++i) { - if (editor.objs[i] == o) { - editor.objs[i] = 0; - array_erase_slow(editor.objs, i); - --end; - --i; - } - } - // delete from world - set_erase(editor.world, o); - // delete properties + obj - editor_destroy_properties(o); - obj_free(o); - } - set_free(list); -} -void editor_inspect(obj *o) { - ui_section(va("%s (%s)", obj_type(o), obj_name(o))); - - if( obj_hasmethod(o, menu) ) { - obj_menu(o); - } - - for each_objmember(o,TYPE,NAME,PTR) { - if( !editor_changed(PTR) ) { - obj_push(o); - } - ui_label_icon_highlight = editor_changed(PTR); // @hack: remove ui_label_icon_highlight hack - char *label = va(ICON_MD_UNDO "%s", NAME); - int changed = 0; - /**/ if( !strcmp(TYPE,"float") ) changed = ui_float(label, PTR); - else if( !strcmp(TYPE,"int") ) changed = ui_int(label, PTR); - else if( !strcmp(TYPE,"vec2") ) changed = ui_float2(label, PTR); - else if( !strcmp(TYPE,"vec3") ) changed = ui_float3(label, PTR); - else if( !strcmp(TYPE,"vec4") ) changed = ui_float4(label, PTR); - else if( !strcmp(TYPE,"color") ) changed = ui_color4(label, PTR); - else if( !strcmp(TYPE,"char*") ) changed = ui_string(label, PTR); - else ui_label2(label, va("(%s)", TYPE)); // INFO instead of (TYPE)? - if( changed ) { - editor_setchanged(PTR, 1); - } - if( ui_label_icon_highlight ) - if( ui_label_icon_clicked_L.x >= 6 && ui_label_icon_clicked_L.x <= 26 ) { // @hack: if clicked on UNDO icon (1st icon) - editor_setchanged(PTR, 0); - } - if( !editor_changed(PTR) ) { - obj_pop(o); - } - } -} - -// ---------------------------------------------------------------------------------------- -// tty - -static thread_mutex_t *console_lock; -static array(char*) editor_jobs; -int editor_send(const char *cmd) { // return job-id - int skip = strspn(cmd, " \t\r\n"); - char *buf = STRDUP(cmd + skip); - strswap(buf, "\r\n", ""); - int jobid; - do_threadlock(console_lock) { - array_push(editor_jobs, buf); - jobid = array_count(editor_jobs) - 1; - } - return jobid; -} -const char* editor_recv(int jobid, double timeout_ss) { - char *answer = 0; - - while(!answer && timeout_ss >= 0 ) { - do_threadlock(console_lock) { - if( editor_jobs[jobid][0] == '\0' ) - answer = editor_jobs[jobid]; - } - timeout_ss -= 0.1; - if( timeout_ss > 0 ) sleep_ms(100); // thread_yield() - } - - return answer + 1; -} - -// plain and ctrl keys -EDITOR_BIND(play, "down(F5)", { window_pause(0); /* if(!editor.slomo) editor.active = 0; */ editor.slomo = 1; } ); -EDITOR_BIND(stop, "down(ESC)", { if(editor.t > 0) { window_pause(1), editor.frame = 0, editor.t = 0, editor.dt = 0, editor.slomo = 0, editor.active = 1; editor_select("**"); editor_destroy_selected(); }} ); -EDITOR_BIND(eject, "down(F1)", { /*window_pause(!editor.active); editor.slomo = !!editor.active;*/ editor.active ^= 1; } ); -EDITOR_BIND(pause, "(held(CTRL) & down(P)) | down(PAUSE)", { window_pause( window_has_pause() ^ 1 ); } ); -EDITOR_BIND(frame, "held(CTRL) & down(LEFT)", { window_pause(1); editor.frame++, editor.t += (editor.dt = 1/60.f); } ); -EDITOR_BIND(slomo, "held(CTRL) & down(RIGHT)", { window_pause(0); editor.slomo = maxf(fmod(editor.slomo * 2, 16), 0.125); } ); -EDITOR_BIND(reload, "held(CTRL) & down(F5)", { window_reload(); } ); -EDITOR_BIND(filter, "held(CTRL) & down(F)", { editor.filter ^= 1; } ); - -// alt keys -EDITOR_BIND(quit, "held(ALT) & down(F4)", { record_stop(), exit(0); } ); -EDITOR_BIND(mute, "held(ALT) & down(M)", { audio_volume_master( 1 ^ !!audio_volume_master(-1) ); } ); -EDITOR_BIND(gamepad, "held(ALT) & down(G)", { editor.gamepad ^= 1; } ); -EDITOR_BIND(transparent, "held(ALT) & down(T)", { editor.transparent ^= 1; } ); -EDITOR_BIND(record, "held(ALT) & down(Z)", { if(record_active()) record_stop(), ui_notify(va("Video recorded"), date_string()); else { char *name = file_counter(va("%s.mp4",app_name())); app_beep(), window_record(name); } } ); -EDITOR_BIND(screenshot, "held(ALT) & down(S)", { char *name = file_counter(va("%s.png",app_name())); window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string()); } ); -EDITOR_BIND(battery, "held(ALT) & down(B)", { editor.battery ^= 1; } ); -EDITOR_BIND(outliner, "held(ALT) & down(O)", { ui_show("Outliner", ui_visible("Outliner") ^ true); } ); -EDITOR_BIND(profiler, "held(ALT) & down(P)", { ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true)); } ); -EDITOR_BIND(fullscreen, "(held(ALT)&down(ENTER))|down(F11)",{ record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); } ); // close any recording before framebuffer resizing, which would corrupt video stream -EDITOR_BIND(unlit, "held(ALT) & down(U)", { editor.unlit ^= 1; } ); -EDITOR_BIND(ddraw, "held(ALT) & down(D)", { editor.ddraw ^= 1; } ); - -void editor_pump() { - for each_array(editor_binds,editor_bind_t,b) { - if( input_eval(b.bindings) ) { - editor_send(b.command); - } - } - - do_threadlock(console_lock) { - for each_array_ptr(editor_jobs,char*,cmd) { - if( (*cmd)[0] ) { - int found = 0; - for each_array(editor_binds,editor_bind_t,b) { - if( !strcmpi(b.command, *cmd)) { - b.fn(); - found = 1; - break; - } - } - - if( !found ) { - // alert(va("Editor: could not handle `%s` command.", *cmd)); - (*cmd)[0] = '\0'; strcatf(&(*cmd), "\1%s\n", "Err\n"); (*cmd)[0] = '\0'; - } - - if( (*cmd)[0] ) { - (*cmd)[0] = '\0'; strcatf(&(*cmd), "\1%s\n", "Ok\n"); (*cmd)[0] = '\0'; - } - } - } - } -} - -// ---------------------------------------------------------------------------------------- - -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); - // 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); - font_goto(x,y); - font_print(va(FONT_SYMBOLS FONT_WHITE FONT_H1 "%s", sym)); -} - -void editor_frame( void (*game)(unsigned, float, double) ) { - do_once { - set_init_ptr(editor.world); - //set_init_ptr(editor.selection); - profiler_enable( false ); - - window_pause( true ); - window_cursor_shape(CURSOR_SW_AUTO); - - fx_load("editorOutline.fs"); - fx_enable(0, 1); - - obj_setname(editor.root = obj_new(obj), "Signals"); - obj_setname(editor.on_init = obj_new(obj), "onInit"); - obj_setname(editor.on_tick = obj_new(obj), "onTick"); - obj_setname(editor.on_draw = obj_new(obj), "onDraw"); - obj_setname(editor.on_edit = obj_new(obj), "onEdit"); - obj_setname(editor.on_quit = obj_new(obj), "onQuit"); - - obj_attach(editor.root, editor.on_init); - obj_attach(editor.root, editor.on_tick); - obj_attach(editor.root, editor.on_draw); - obj_attach(editor.root, editor.on_edit); - obj_attach(editor.root, editor.on_quit); - - editor_seticoninstance(editor.root, ICON_MDI_SIGNAL_VARIANT); - editor_seticoninstance(editor.on_init, ICON_MDI_SIGNAL_VARIANT); - editor_seticoninstance(editor.on_tick, ICON_MDI_SIGNAL_VARIANT); - editor_seticoninstance(editor.on_draw, ICON_MDI_SIGNAL_VARIANT); - editor_seticoninstance(editor.on_edit, ICON_MDI_SIGNAL_VARIANT); - editor_seticoninstance(editor.on_quit, ICON_MDI_SIGNAL_VARIANT); - - editor_seticonclass(obj_type(editor.root), ICON_MDI_CUBE_OUTLINE); - } - - // game tick - game(editor.frame, editor.dt, editor.t); - - // timing - editor.dt = clampf(window_delta(), 0, 1/60.f) * !window_has_pause() * editor.slomo; - editor.t += editor.dt; - editor.frame += !window_has_pause(); - editor.frame += !editor.frame; - - // process inputs & messages - editor_pump(); - - // adaptive framerate - int app_on_background = !window_has_focus(); - int hz = app_on_background ? editor.hz_low : editor.battery ? editor.hz_medium : editor.hz_high; - window_fps_lock( hz < 5 ? 5 : hz ); - - // draw menubar - static int stats_mode = 1; - static double last_fps = 0; if(!window_has_pause()) last_fps = window_fps(); - const char *STATS = va("x%4.3f %03d.%03dss %02dF %s", - editor.slomo, (int)editor.t, (int)(1000 * (editor.t - (int)editor.t)), - (editor.frame-1) % ((int)window_fps_target() + !(int)window_fps_target()), - stats_mode == 1 ? va("%5.2f/%dfps", last_fps, (int)window_fps_target()) : stats_mode == 0 ? "0/0 KiB" : xstats()); - const char *ICON_PL4Y = window_has_pause() ? ICON_MDI_PLAY : ICON_MDI_PAUSE; - const char *ICON_SKIP = window_has_pause() ? ICON_MDI_STEP_FORWARD/*ICON_MDI_SKIP_NEXT*/ : ICON_MDI_FAST_FORWARD; - - int ingame = !editor.active; - UI_MENU(14, \ - if(ingame) ui_disable(); \ - UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \ - 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) \ - if(ingame) ui_disable(); \ - UI_MENU_ITEM(ICON_MD_FOLDER_SPECIAL, editor_send("browser")) \ - 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()) \ - if(ingame) ui_enable(); \ - UI_MENU_ITEM(ICON_MD_CLOSE, editor_send("quit")) \ - ); - - if( !editor.active ) return; - - // draw edit view (gizmos, position markers, etc). - for each_set_ptr(editor.world,obj*,o) { - if( obj_hasmethod(*o,edit) ) { - obj_edit(*o); - } - } - - // draw silhouettes - sprite_flush(); - fx_begin(); - for each_map_ptr(*editor_selected_map(),void*,o,int,selected) { - if( !*selected ) continue; - if( obj_hasmethod(*o,draw) ) { - obj_draw(*o); - } - if( obj_hasmethod(*o,edit) ) { - obj_edit(*o); - } - } - sprite_flush(); - fx_end(); - - // draw box selection - if( !ui_active() ) { //< check that we're not moving a window - 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)); - if( len2sq(sub2(from,to)) > 0 ) { - vec2 a = min2(from, to), b = max2(from, to); - ddraw_push_2d(); - ddraw_color_push(YELLOW); - ddraw_line( vec3(a.x,a.y,0),vec3(b.x-1,a.y,0) ); - ddraw_line( vec3(b.x,a.y,0),vec3(b.x,b.y-1,0) ); - ddraw_line( vec3(b.x,b.y,0),vec3(a.x-1,b.y,0) ); - ddraw_line( vec3(a.x,b.y,0),vec3(a.x,a.y-1,0) ); - ddraw_color_pop(); - ddraw_pop_2d(); - } - if( input_up(MOUSE_L) ) { - vec2 a = min2(from, to), b = max2(from, to); - from = to = vec2(0,0); - - editor_select_aabb(aabb(vec3(a.x,a.y,0),vec3(b.x,b.y,0))); - } - } - - // draw mouse aabb - aabb mouse = { vec3(input(MOUSE_X),input(MOUSE_Y),0), vec3(input(MOUSE_X),input(MOUSE_Y),1)}; - if( 1 ) { - ddraw_color_push(YELLOW); - ddraw_push_2d(); - ddraw_aabb(mouse.min, mouse.max); - ddraw_pop_2d(); - ddraw_color_pop(); - } - - // tick mouse aabb selection and contextual tab (RMB) - aabb box = {0}; - for each_set(editor.world,obj*,o) { - if( !obj_hasmethod(o, aabb) ) continue; - if( !obj_aabb(o, &box) ) continue; - - // trigger contextual inspector - if( input_down(MOUSE_R) ) { - int is_selected = editor_selected(o); - editor_setpopup(o, is_selected); - } - - // draw contextual inspector - if( editor_popup(o) ) { - if( editor_begin(va("%s (%s)", obj_name(o), obj_type(o)),EDITOR_WINDOW_NK_SMALL) ) { - ui_label2(obj_name(o), obj_type(o)); - editor_inspect(o); - editor_end(EDITOR_WINDOW_NK_SMALL); - } else { - editor_setpopup(o, 0); - } - } - } - - - // draw subeditors - static int preferred_window_mode = EDITOR_WINDOW; - static struct nk_color bak, *on = 0; do_once bak = ui_ctx->style.window.fixed_background.data.color; // ui_ctx->style.window.fixed_background.data.color = !!(on = (on ? NULL : &bak)) ? AS_NKCOLOR(0) : bak; }; - if( editor.transparent ) ui_ctx->style.window.fixed_background.data.color = AS_NKCOLOR(0); - for each_array(editor.subeditors, subeditor, fn) { - fn(preferred_window_mode); - } - ui_ctx->style.window.fixed_background.data.color = bak; - - // draw ui filter (note: render at end-of-frame, so it's hopefully on-top) - editor_filter(); -} - -#include "v4k_editor1_scene.h" -#include "v4k_editor2_browser.h" -#include "v4k_editor3_timeline.h" -#include "v4k_editor4_console.h" -#include "v4k_editor5_nodes.h" diff --git a/tools/editor/fwk_editor1_scene.h b/tools/editor/fwk_editor1_scene.h deleted file mode 100644 index 2d9a590..0000000 --- a/tools/editor/fwk_editor1_scene.h +++ /dev/null @@ -1,184 +0,0 @@ -#define SCENE_ICON ICON_MDI_FILE_TREE -#define SCENE_TITLE "Scene " SCENE_ICON - -EDITOR_BIND(scene, "held(CTRL)&down(1)", { ui_show(SCENE_TITLE, ui_visible(SCENE_TITLE) ^ true); }); - -EDITOR_PROPERTY(bookmarked, int, 0); - -EDITOR_BIND(node_new, "down(INS)", { editor_spawn1(); } ); -EDITOR_BIND(node_del, "down(DEL)", { editor_destroy_selected(); } ); -EDITOR_BIND(node_save, "held(CTRL)&down(S)", { puts("@todo"); } ); -EDITOR_BIND(scene_save, "held(CTRL)&down(S)&held(SHIFT)",{ puts("@todo"); } ); -EDITOR_BIND(select_all, "held(CTRL) & down(A)", { editor_select("**"); } ); -EDITOR_BIND(select_none, "held(CTRL) & down(D)", { editor_select("!**"); } ); -EDITOR_BIND(select_invert, "held(CTRL) & down(I)", { editor_select("~**"); } ); -EDITOR_BIND(bookmark, "held(CTRL) & down(B)", { editor_selected_map_t *map = editor_selected_map(); \ - int on = 0; \ - for each_map_ptr(*map,void*,o,int,selected) if(*selected) on |= !editor_bookmarked(*o); \ - for each_map_ptr(*map,void*,o,int,selected) if(*selected) editor_setbookmarked(*o, on); \ -} ); - -enum { - SCENE_RECURSE = 1, - SCENE_SELECTION = 2, - SCENE_CHECKBOX = 4, - SCENE_INDENT = 8, - SCENE_ALL = ~0u -}; - -static -void editor_scene_(obj *o, unsigned flags) { - static unsigned tabs = ~0u; - ++tabs; - - if( o ) { - unsigned do_tags = 1; - unsigned do_indent = !!(flags & SCENE_INDENT); - unsigned do_checkbox = !!(flags & SCENE_CHECKBOX); - unsigned do_recurse = !!(flags & SCENE_RECURSE); - unsigned do_selection = !!(flags & SCENE_SELECTION); - - nk_layout_row_dynamic(ui_ctx, 25, 1); - - const char *objicon = editor_iconinstance(o); - if(!objicon) objicon = editor_iconclass(obj_type(o)); - if(!objicon) objicon = ICON_MDI_CUBE_OUTLINE; - - const char *objname = va("%s (%s)", obj_type(o), obj_name(o)); - - const char *objchevron = - !do_recurse || array_count(*obj_children(o)) <= 1 ? ICON_MDI_CIRCLE_SMALL : - editor_open(o) ? ICON_MDI_CHEVRON_DOWN : ICON_MDI_CHEVRON_RIGHT; - - char *label = va("%*s%s%s %s", do_indent*(4+2*tabs), "", objchevron, objicon, objname); - - const char *iconsL = - //editor_selected(o) ? ICON_MD_CHECK_BOX : ICON_MD_CHECK_BOX_OUTLINE_BLANK; - editor_selected(o) ? ICON_MDI_CHECKBOX_MARKED : ICON_MDI_CHECKBOX_BLANK_OUTLINE; - - const char *iconsR = va("%s%s%s", - editor_script(o) ? ICON_MDI_SCRIPT : ICON_MDI_CIRCLE_SMALL, - editor_event(o) ? ICON_MDI_CALENDAR : ICON_MDI_CIRCLE_SMALL, - editor_visible(o) ? ICON_MDI_EYE_OUTLINE : ICON_MDI_EYE_CLOSED ); - - UI_TOOLBAR_OVERLAY_DECLARE(int choiceL, choiceR); - - struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); - struct nk_rect bounds; nk_layout_peek(&bounds, ui_ctx); - - int clicked = nk_hovered_text(ui_ctx, label, strlen(label), NK_TEXT_LEFT, editor_selected(o)); - if( clicked && nk_input_is_mouse_hovering_rect(&ui_ctx->input, ((struct nk_rect) { bounds.x,bounds.y,bounds.w*0.66,bounds.h })) ) - editor_altselected( o ); - - vec2i offset_in_tree = {0}; - - if( do_indent ) { - float thickness = 2.f; - struct nk_color color = {255,255,255,64}; - - int offsx = 30; - int spacx = 10; - int lenx = (tabs+1)*spacx; - int halfy = bounds.h / 2; - int offsy = halfy + 2; - - offset_in_tree = vec2i(bounds.x+offsx+lenx-spacx,bounds.y+offsy); - - editor_settreeoffsety(o, offset_in_tree.y); - - for( obj *p = obj_parent(o); p ; p = 0 ) - nk_stroke_line(canvas, offset_in_tree.x-6,offset_in_tree.y, offset_in_tree.x-spacx,offset_in_tree.y, thickness, color), - nk_stroke_line(canvas, offset_in_tree.x-spacx,offset_in_tree.y,offset_in_tree.x-spacx,editor_treeoffsety(p)+4, thickness, color); - } - - if( ui_contextual() ) { - API int editor_send(const char *); - - int choice = ui_label(ICON_MD_BOOKMARK_ADDED "Toggle bookmarks (CTRL+B)"); - if( choice & 1 ) editor_send("bookmark"); - - ui_contextual_end(!!choice); - } - - UI_TOOLBAR_OVERLAY(choiceL,iconsL,nk_rgba_f(1,1,1,do_checkbox*ui_alpha*0.65),NK_TEXT_LEFT); - - if( do_tags ) - UI_TOOLBAR_OVERLAY(choiceR,iconsR,nk_rgba_f(1,1,1,ui_alpha*0.65),NK_TEXT_RIGHT); - - if( choiceR == 3 ) editor_altscript( o ); - if( choiceR == 2 ) editor_altevent( o); - if( choiceR == 1 ) editor_altvisible( o ); - - if( do_recurse && editor_open(o) ) { - for each_objchild(o,obj*,oo) { - editor_scene_(oo,flags); - } - } - - if( clicked && !choiceL && !choiceR ) { - int is_picking = input(KEY_CTRL); - if( !is_picking ) { - if( input(KEY_SHIFT) ) { - editor_selectgroup( editor_first_selected(), editor_last_selected() ); - } else { - editor_unselect(); - editor_setselected(o, 1); - } - } - for( obj *p = obj_parent(o); p; p = obj_parent(p) ) { - editor_setopen(p, 1); - } - if( nk_input_is_mouse_hovering_rect(&ui_ctx->input, ((struct nk_rect) { bounds.x,bounds.y,offset_in_tree.x-bounds.x+UI_ICON_FONTSIZE/2,bounds.h })) ) { - editor_altopen( o ); - } - } - } - - --tabs; -} - -int editor_scene(int window_mode) { - window_mode = EDITOR_WINDOW; // force window - - if( editor_begin(SCENE_TITLE, window_mode)) { - // #define HELP ICON_MDI_INFORMATION_OUTLINE "@-A\n-B\n-C\n" ";" - int choice = ui_toolbar(ICON_MDI_PLUS "@New node (CTRL+N);" ICON_MDI_DOWNLOAD "@Save node (CTRL+S);" ICON_MDI_DOWNLOAD "@Save scene (SHIFT+CTRL+S);" ICON_MD_BOOKMARK_ADDED "@Toggle Bookmark (CTRL+B);"); - if( choice == 1 ) editor_send("node_new"); - if( choice == 2 ) editor_send("node_save"); - if( choice == 3 ) editor_send("scene_save"); - if( choice == 4 ) editor_send("bookmark"); - - array(obj*) bookmarks = 0; - for each_map_ptr(*editor_bookmarked_map(), void*,o,int,bookmarked) { - if( *bookmarked ) { - array_push(bookmarks, *o); - } - } - if( ui_collapse("!" ICON_MD_BOOKMARK "Bookmarks", "DEBUG:BOOKMARK")) { - for each_array( bookmarks, obj*, o ) - editor_scene_( o, SCENE_ALL & ~(SCENE_RECURSE|SCENE_INDENT|SCENE_CHECKBOX) ); - ui_collapse_end(); - } - array_free(bookmarks); - - editor_scene_( editor.root, SCENE_ALL ); - - for each_array( editor.objs, obj*, o ) - editor_scene_( o, SCENE_ALL ); - - ui_separator(); - - // edit selection - for each_map(*editor_selected_map(), void*,o, int, k) { - if( k ) editor_inspect(o); - } - - editor_end(window_mode); - } - - return 0; -} - -AUTORUN { - array_push(editor.subeditors, editor_scene); -} diff --git a/tools/editor/fwk_editor2_browser.h b/tools/editor/fwk_editor2_browser.h deleted file mode 100644 index 1f932ce..0000000 --- a/tools/editor/fwk_editor2_browser.h +++ /dev/null @@ -1,21 +0,0 @@ -#define BROWSER_ICON ICON_MD_FOLDER_SPECIAL -#define BROWSER_TITLE "Browser " BROWSER_ICON - -EDITOR_BIND(browser, "held(CTRL)&down(2)", { ui_show(BROWSER_TITLE, ui_visible(BROWSER_TITLE) ^ true); }); - -int editor_browser(int window_mode) { - window_mode = EDITOR_WINDOW; // force window - if( editor_begin(BROWSER_TITLE, window_mode) ) { - const char *file = 0; - if( ui_browse(&file, NULL) ) { - const char *sep = ifdef(win32, "\"", "'"); - app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep)); - } - editor_end(window_mode); - } - return 0; -} - -AUTORUN { - array_push(editor.subeditors, editor_browser); -} diff --git a/tools/editor/fwk_editor3_timeline.h b/tools/editor/fwk_editor3_timeline.h deleted file mode 100644 index 6a513f4..0000000 --- a/tools/editor/fwk_editor3_timeline.h +++ /dev/null @@ -1,172 +0,0 @@ -#define TIMELINE_ICON ICON_MDI_CHART_TIMELINE -#define TIMELINE_TITLE "Timeline " TIMELINE_ICON - -EDITOR_BIND(timeline, "held(CTRL)&down(3)", { ui_show(TIMELINE_TITLE, ui_visible(TIMELINE_TITLE) ^ true); }); - -int ui_tween(const char *label, tween_t *t) { - if( ui_filter && ui_filter[0] ) if( !strstr(label, ui_filter) ) return 0; - - int expand_keys = label[0] == '!'; label += expand_keys; - const char *id = label; - if( strchr(id, '@') ) *strchr((char*)(id = (const char*)va("%s", label)), '@') = '\0'; - - enum { LABEL_SPACING = 250 }; - enum { ROUNDING = 0 }; - enum { THICKNESS = 1 }; - enum { PIXELS_PER_SECOND = 60 }; - enum { KEY_WIDTH = 5, KEY_HEIGHT = 5 }; - enum { TIMELINE_HEIGHT = 25 }; - enum { MARKER1_HEIGHT = 5, MARKER10_HEIGHT = 20, MARKER5_HEIGHT = (MARKER1_HEIGHT + MARKER10_HEIGHT) / 2 }; - unsigned base_color = WHITE; - unsigned time_color = YELLOW; - unsigned duration_color = ORANGE; - unsigned key_color = GREEN; - - int changed = 0; - -#if 0 - // two rows with height:30 composed of three widgets - nk_layout_row_template_begin(ui_ctx, 30); - nk_layout_row_template_push_variable(ui_ctx, t->duration * PIXELS_PER_SECOND); // min 80px. can grow - nk_layout_row_template_end(ui_ctx); -#endif - - char *sid = va("%s.%d", id, 0); - uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; - for(int i = 0; sid[i]; ++i) hash = (hash ^ sid[i]) * mult; - ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; - - ui_label(label); - - struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); - struct nk_rect bounds; nk_layout_peek(&bounds, ui_ctx); - bounds.y -= 30; - - struct nk_rect baseline = bounds; baseline.y += 30/2; - baseline.x += LABEL_SPACING; - baseline.w -= LABEL_SPACING; - - // tween duration - { - struct nk_rect pos = baseline; - pos.w = pos.x + t->duration * PIXELS_PER_SECOND; - pos.y -= TIMELINE_HEIGHT/2; - pos.h = TIMELINE_HEIGHT; - nk_stroke_rect(canvas, pos, ROUNDING, THICKNESS*2, AS_NKCOLOR(duration_color)); - } - - // tween ranges - for(int i = 0, end = array_count(t->keyframes) - 1; i < end; ++i) { - tween_keyframe_t *k = t->keyframes + i; - tween_keyframe_t *next = k + 1; - - struct nk_rect pos = baseline; - pos.x += k->t * PIXELS_PER_SECOND; - pos.w = (next->t - k->t) * PIXELS_PER_SECOND; - pos.y -= TIMELINE_HEIGHT/2; - pos.h = TIMELINE_HEIGHT; - - char *sid = va("%s.%d", id, i); - uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; - for(int i = 0; sid[i]; ++i) hash = (hash ^ sid[i]) * mult; - ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; - - struct nk_color c = nk_hsva_f(ui_hue, 0.75f, 0.8f, ui_alpha); - nk_fill_rect(canvas, pos, ROUNDING, k->ease == EASE_NOP ? AS_NKCOLOR(0) : c); // AS_NKCOLOR(track_color)); - } - - // horizontal line - nk_stroke_line(canvas, baseline.x, baseline.y, baseline.x+baseline.w,baseline.y, THICKNESS, AS_NKCOLOR(base_color)); - - // unit, 5-unit and 10-unit markers - for( float i = 0, j = 0; i < baseline.w; i += PIXELS_PER_SECOND/10, ++j ) { - int len = !((int)j%10) ? MARKER10_HEIGHT : !((int)j%5) ? MARKER5_HEIGHT : MARKER1_HEIGHT; - nk_stroke_line(canvas, baseline.x+i, baseline.y-len, baseline.x+i, baseline.y+len, THICKNESS, AS_NKCOLOR(base_color)); - } - - // time marker - float px = t->time * PIXELS_PER_SECOND; - nk_stroke_line(canvas, baseline.x+px, bounds.y, baseline.x+px, bounds.y+bounds.h, THICKNESS*2, AS_NKCOLOR(time_color)); - nk_draw_symbol(canvas, NK_SYMBOL_TRIANGLE_DOWN, ((struct nk_rect){ baseline.x+px-4,bounds.y-4-8,8,8}), /*bg*/AS_NKCOLOR(0), /*fg*/AS_NKCOLOR(time_color), 0.f/*border_width*/, ui_ctx->style.font); - - // key markers - for each_array_ptr(t->keyframes, tween_keyframe_t, k) { - struct nk_rect pos = baseline; - pos.x += k->t * PIXELS_PER_SECOND; - - vec2 romboid[] = { - {pos.x-KEY_WIDTH,pos.y}, {pos.x,pos.y-KEY_HEIGHT}, - {pos.x+KEY_WIDTH,pos.y}, {pos.x,pos.y+KEY_HEIGHT} - }; - - nk_fill_polygon(canvas, (float*)romboid, countof(romboid), AS_NKCOLOR(key_color)); - } - - // keys ui - if( expand_keys ) - for(int i = 0, end = array_count(t->keyframes); i < end; ++i) { - tween_keyframe_t *k = t->keyframes + i; - if( ui_collapse(va("Key %d", i), va("%s.%d", id, i))) { - changed |= ui_float("Time", &k->t); - changed |= ui_float3("Value", &k->v.x); - changed |= ui_list("Ease", ease_enums(), EASE_NUM, &k->ease ); - ui_collapse_end(); - } - } - - return changed; -} - -tween_t* rand_tween() { - tween_t demo = tween(); - int num_keys = randi(2,8); - double t = 0; - for( int i = 0; i < num_keys; ++i) { - tween_setkey(&demo, t, scale3(vec3(randf(),randf(),randf()),randi(-5,5)), randi(0,EASE_NUM) ); - t += randi(1,5) / ((float)(1 << randi(0,2))); - } - tween_t *p = CALLOC(1, sizeof(tween_t)); - memcpy(p, &demo, sizeof(tween_t)); - return p; -} - -int editor_timeline(int window_mode) { - static array(tween_t*) tweens = 0; - - do_once { - array_push(tweens, rand_tween()); - } - - if( editor.t == 0 ) - for each_array(tweens, tween_t*,t) { - tween_reset(t); - } - else - for each_array(tweens, tween_t*,t) { - tween_update(t, editor.dt); - } - - static void *selected = NULL; - if( editor_begin(TIMELINE_TITLE, window_mode) ) { - - int choice = ui_toolbar(ICON_MDI_PLUS ";" ICON_MDI_MINUS ); - if( choice == 1 ) array_push(tweens, rand_tween()); - if( choice == 2 && selected ) { - int target = -1; - for( int i = 0, end = array_count(tweens); i < end; ++i ) if( tweens[i] == selected ) { target = i; break; } - if( target >= 0 ) { array_erase_slow(tweens, target); selected = NULL; } - } - - for each_array(tweens, tween_t*,t) { - ui_tween(va("%s%p@%05.2fs Value: %s", t == selected ? "!":"", t, t->time, ftoa3(t->result)), t); - if(ui_label_icon_clicked_L.x) selected = (t != selected) ? t : NULL; - } - - editor_end(window_mode); - } - return 0; -} - -AUTORUN { - array_push(editor.subeditors, editor_timeline); -} diff --git a/tools/editor/fwk_editor4_console.h b/tools/editor/fwk_editor4_console.h deleted file mode 100644 index ffe12be..0000000 --- a/tools/editor/fwk_editor4_console.h +++ /dev/null @@ -1,56 +0,0 @@ -#define CONSOLE_ICON ICON_MDI_CONSOLE -#define CONSOLE_TITLE "Console " CONSOLE_ICON - -EDITOR_BIND(console, "held(CTRL)&down(4)", { ui_show(CONSOLE_TITLE, ui_visible(CONSOLE_TITLE) ^ true); }); - -int editor_console(int window_mode) { - if( editor_begin(CONSOLE_TITLE, window_mode) ) { - - // peek complete window space - struct nk_rect bounds = nk_window_get_content_region(ui_ctx); - - enum { CONSOLE_LINE_HEIGHT = 20 }; - static array(char*) lines = 0; - do_once { - array_push(lines, stringf("> Editor v%s. Type `%s` for help.", EDITOR_VERSION, "")); - } - int max_lines = (bounds.h - UI_ROW_HEIGHT) / (CONSOLE_LINE_HEIGHT * 2); - if( max_lines >= 1 ) { - nk_layout_row_static(ui_ctx, bounds.h - UI_ROW_HEIGHT, bounds.w, 1); - if(nk_group_begin(ui_ctx, "console.group", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { - nk_layout_row_static(ui_ctx, CONSOLE_LINE_HEIGHT, bounds.w, 1); - for( int i = array_count(lines); i < max_lines; ++i ) - array_push_front(lines, 0); - for( int i = array_count(lines) - max_lines; i < array_count(lines); ++i ) { - if( !lines[i] ) { - #if 0 // debug - nk_label_wrap(ui_ctx, va("%d.A/%d",i+1,max_lines)); - nk_label_wrap(ui_ctx, va("%d.B/%d",i+1,max_lines)); - #else - nk_label_wrap(ui_ctx, ""); - nk_label_wrap(ui_ctx, ""); - #endif - } else { - nk_label_wrap(ui_ctx, lines[i]); - const char *answer = isdigit(*lines[i]) ? editor_recv( atoi(lines[i]), 0 ) : NULL; - nk_label_wrap(ui_ctx, answer ? answer : ""); - } - } - nk_group_end(ui_ctx); - } - } - static char *cmd = 0; - if( ui_string(NULL, &cmd) ) { - int jobid = editor_send(cmd); - array_push(lines, stringf("%d> %s", jobid, cmd)); - cmd[0] = 0; - } - - editor_end(window_mode); - } - return 0; -} - -AUTORUN { - array_push(editor.subeditors, editor_console); -} diff --git a/tools/editor/fwk_editor5_nodes.h b/tools/editor/fwk_editor5_nodes.h deleted file mode 100644 index 4881334..0000000 --- a/tools/editor/fwk_editor5_nodes.h +++ /dev/null @@ -1,881 +0,0 @@ -#define NODES_ICON ICON_MDI_GRAPH -#define NODES_TITLE "Nodes " NODES_ICON - -EDITOR_BIND(nodes, "held(CTRL)&down(5)", { ui_show(NODES_TITLE, ui_visible(NODES_TITLE) ^ true); }); - -/* -A basic node-based UI built with Nuklear. -Builds on the node editor example included in Nuklear v1.00, with the aim of -being used as a prototype for implementing a functioning node editor. - -Features: -- Nodes of different types. Currently their implementations are #included in - the main file, but they could easily be turned into eg. a plugin system. -- Pins/pins of different types -- currently float values and colors. -- Adding and removing nodes. -- Linking nodes, with validation (one link per input, only link similar pins). -- Detaching and moving links. -- Evaluation of output values of connected nodes. -- Memory management based on fixed size arrays for links and node pointers -- Multiple node types -- Multiple pin types -- Linking between pins of the same type -- Detaching and reattaching links -- Getting value from linked node if pin is connected - -Todo: -- Complete pin types. -- Allow dragging from output to input pin. -- Cut link by CTRL+clicking input pin. -- Cut link by drawing intersect line on a link. -- Group elemnts together with mouse, or LSHIFT+clicking. -- Drag groups. -- DEL elements. -- DEL groups. -- CTRL-C/CTRL-V/CTRL-X elements. -- CTRL-C/CTRL-V/CTRL-X groups. -- CTRL-Z,CTRL-Y. -- CTRL-N. -- CTRL-L,CTRL-S. -- CTRL-F. -- CTRL-Wheel Zooming. -- Allow to extend node types from Lua. - -Extra todo: -- Execution Flow (see: nk_stroke_triangle, nk_fill_triangle) -- Complete missing nodes (see: nk_draw_image, nk_draw_text) -- Right-click could visualize node/board diagram as Lua script. -- Once that done, copy/pasting scripts should work within editor. - -Sources: -- https://github.com/Immediate-Mode-UI/Nuklear/pull/561 -- https://github.com/vurtun/nuklear/blob/master/demo/node_editor.c -*/ - -typedef enum pin_type_t { - type_flow, - type_int,type_float, - type_block,type_texture,type_image, - type_color, - /* - type_bool, - type_char, type_string, - type_int2, type_int3, type_int4, - type_float2, type_float3, type_float4, - type_array, type_map, - */ - - type_total -} pin_type_t; - -struct node_pin { - pin_type_t pin_type; - nk_bool is_connected; - struct node* connected_node; - int connected_pin; -}; - -struct node { - int ID; - char name[32]; - struct nk_rect bounds; - int input_count; - int output_count; - struct node_pin *inputs; - struct node_pin *outputs; - struct { - float in_padding_x; - float in_padding_y; - float in_spacing_y; - float out_padding_x; - float out_padding_y; - float out_spacing_y; - } pin_spacing; /* Maybe this should be called "node_layout" and include the bounds? */ - struct node *next; /* Z ordering only */ - struct node *prev; /* Z ordering only */ - - void* (*eval_func)(struct node*, int oIndex); - void (*display_func)(struct nk_context*, struct node*); -}; - -struct node_link { - struct node* input_node; - int input_pin; - struct node* output_node; - int output_pin; - nk_bool is_active; -}; - -struct node_linking { - int active; - struct node *node; - int input_id; - int input_pin; -}; - -struct node_editor { - int initialized; - struct node *node_buf[32]; - struct node_link links[64]; - struct node *output_node; - struct node *begin; - struct node *end; - int node_count; - int link_count; - struct nk_rect bounds; - struct node *selected; - int show_grid; - struct nk_vec2 scrolling; - struct node_linking linking; -}; - -/* === PROTOTYPES === */ -/* The node implementations need these two functions. */ -/* These could/should go in a header file along with the node and node_pin structs and be #included in the node implementations */ - -struct node* node_editor_add(struct node_editor *editor, size_t nodeSize, const char *name, struct nk_rect bounds, int in_count, int out_count); -void* node_editor_eval_connected(struct node *node, int input_pin_number); -/* ================== */ - -/* === NODE TYPE IMPLEMENTATIONS === */ - -#define NODE_DEFAULT_ROW_HEIGHT 25 - - -// ---------------------------------------------------------------------------------------------------- -// #include "node_output.h" - -struct node_type_output { - struct node node; - struct nk_colorf input_val; -}; - -struct nk_colorf *node_output_get(struct node* node) { - struct node_type_output *output_node = (struct node_type_output*)node; - if (!node->inputs[0].is_connected) { - struct nk_colorf black = {0.0f, 0.0f, 0.0f, 0.0f}; - output_node->input_val = black; - } - return &output_node->input_val; -} - -static void node_output_display(struct nk_context *ctx, struct node *node) { - if (node->inputs[0].is_connected) { - struct node_type_output *output_node = (struct node_type_output*)node; - output_node->input_val = *(struct nk_colorf*)node_editor_eval_connected(node, 0); - nk_layout_row_dynamic(ctx, 60, 1); - nk_button_color(ctx, nk_rgba_cf(output_node->input_val)); - } -} - -struct node* node_output_create(struct node_editor *editor, struct nk_vec2 position) { - struct node_type_output *output_node = (struct node_type_output*)node_editor_add(editor, sizeof(struct node_type_output), "Output", nk_rect(position.x, position.y, 100, 100), 1, 0); - if (output_node){ - output_node->node.inputs[0].pin_type = type_color; - output_node->node.display_func = node_output_display; - } - return (struct node*)output_node; -} - -// ---------------------------------------------------------------------------------------------------- -// #include "node_float.h" - -struct node_type_float { - struct node node; - float output_val; -}; - -static float *node_float_eval(struct node* node, int oIndex) { - struct node_type_float *float_node = (struct node_type_float*)node; - NK_ASSERT(oIndex == 0); - return &float_node->output_val; -} - -static void node_float_draw(struct nk_context *ctx, struct node *node) { - struct node_type_float *float_node = (struct node_type_float*)node; - nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); - float_node->output_val = nk_propertyf(ctx, "#Value:", 0.0f, float_node->output_val, 1.0f, 0.01f, 0.01f); -} - -void node_float_create(struct node_editor *editor, struct nk_vec2 position) { - struct node_type_float *float_node = (struct node_type_float*)node_editor_add(editor, sizeof(struct node_type_float), "Float", nk_rect(position.x, position.y, 180, 75), 0, 1); - if (float_node) - { - float_node->output_val = 1.0f; - float_node->node.display_func = node_float_draw; - float_node->node.eval_func = (void*(*)(struct node*, int)) node_float_eval; - } -} - -// ---------------------------------------------------------------------------------------------------- -// #include "node_color.h" - -struct node_type_color { - struct node node; - float input_val[4]; - struct nk_colorf output_val; -}; - -static struct nk_colorf *node_color_eval(struct node* node, int oIndex) -{ - struct node_type_color *color_node = (struct node_type_color*)node; - NK_ASSERT(oIndex == 0); /* only one output connector */ - - return &color_node->output_val; -} - - -static void node_color_draw(struct nk_context *ctx, struct node *node) -{ - struct node_type_color *color_node = (struct node_type_color*)node; - float eval_result; /* Get the values from connected nodes into this so the inputs revert on disconnect */ - const char* labels[4] = {"#R:","#G:","#B:","#A:"}; - float color_val[4]; /* Because we can't just loop through the struct... */ - nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); - nk_button_color(ctx, nk_rgba_cf(color_node->output_val)); - - for (int i = 0; i < 4; i++) - { - if (color_node->node.inputs[i].is_connected) { - eval_result = *(float*)node_editor_eval_connected(node, i); - eval_result = nk_propertyf(ctx, labels[i], eval_result, eval_result, eval_result, 0.01f, 0.01f); - color_val[i] = eval_result; - } - else { - color_node->input_val[i] = nk_propertyf(ctx, labels[i], 0.0f, color_node->input_val[i], 1.0f, 0.01f, 0.01f); - color_val[i] = color_node->input_val[i]; - } - } - - color_node->output_val.r = color_val[0]; - color_node->output_val.g = color_val[1]; - color_node->output_val.b = color_val[2]; - color_node->output_val.a = color_val[3]; -} - -void node_color_create(struct node_editor *editor, struct nk_vec2 position) -{ - struct node_type_color *color_node = (struct node_type_color*)node_editor_add(editor, sizeof(struct node_type_color), "Color", nk_rect(position.x, position.y, 180, 190), 4, 1); - if (color_node) - { - const struct nk_colorf black = {0.0f, 0.0f, 0.0f, 1.0f}; - - for (int i = 0; i < color_node->node.input_count; i++) - color_node->node.inputs[i].pin_type = type_float; - color_node->node.outputs[0].pin_type = type_color; - - color_node->node.pin_spacing.in_padding_y += NODE_DEFAULT_ROW_HEIGHT; - - color_node->input_val[0] = 0.0f; - color_node->input_val[1] = 0.0f; - color_node->input_val[2] = 0.0f; - color_node->input_val[3] = 1.0f; - - color_node->output_val = black; - - color_node->node.display_func = node_color_draw; - color_node->node.eval_func = (void*(*)(struct node*, int)) node_color_eval; - } -} - -// ---------------------------------------------------------------------------------------------------- -// #include "node_blend.h" - -struct node_type_blend { - struct node node; - struct nk_colorf input_val[2]; - struct nk_colorf output_val; - float blend_val; -}; - -static struct nk_colorf *node_blend_eval(struct node *node, int oIndex) { - struct node_type_blend* blend_node = (struct node_type_blend*)node; - return &blend_node->output_val; -} - -static void node_blend_display(struct nk_context *ctx, struct node *node) { - struct node_type_blend *blend_node = (struct node_type_blend*)node; - const struct nk_colorf blank = {0.0f, 0.0f, 0.0f, 0.0f}; - float blend_amnt; - - nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); - for (int i = 0; i < 2; i++){ - if(node->inputs[i].is_connected) { - blend_node->input_val[i] = *(struct nk_colorf*)node_editor_eval_connected(node, i); - } - else { - blend_node->input_val[i] = blank; - } - nk_button_color(ctx, nk_rgba_cf(blend_node->input_val[i])); - } - - if (node->inputs[2].is_connected) { - blend_amnt = *(float*)node_editor_eval_connected(node, 2); - blend_amnt = nk_propertyf(ctx, "#Blend", blend_amnt, blend_amnt, blend_amnt, 0.01f, 0.01f); - } - else { - blend_node->blend_val = nk_propertyf(ctx, "#Blend", 0.0f, blend_node->blend_val, 1.0f, 0.01f, 0.01f); - blend_amnt = blend_node->blend_val; - } - - - if(node->inputs[0].is_connected && node->inputs[1].is_connected) { - blend_node->output_val.r = blend_node->input_val[0].r * (1.0f-blend_amnt) + blend_node->input_val[1].r * blend_amnt; - blend_node->output_val.g = blend_node->input_val[0].g * (1.0f-blend_amnt) + blend_node->input_val[1].g * blend_amnt; - blend_node->output_val.b = blend_node->input_val[0].b * (1.0f-blend_amnt) + blend_node->input_val[1].b * blend_amnt; - blend_node->output_val.a = blend_node->input_val[0].a * (1.0f-blend_amnt) + blend_node->input_val[1].a * blend_amnt; - } - else { - blend_node->output_val = blank; - } -} - -void node_blend_create(struct node_editor *editor, struct nk_vec2 position) { - struct node_type_blend* blend_node = (struct node_type_blend*)node_editor_add(editor, sizeof(struct node_type_blend), "Blend", nk_rect(position.x, position.y, 180, 130), 3, 1); - if (blend_node) { - const struct nk_colorf blank = {0.0f, 0.0f, 0.0f, 0.0f}; - for (int i = 0; i < (int)NK_LEN(blend_node->input_val); i++) - blend_node->node.inputs[i].pin_type = type_color; - blend_node->node.outputs[0].pin_type = type_color; - - // blend_node->node.pin_spacing.in_padding_y = 42.0f; - // blend_node->node.pin_spacing.in_spacing_y = 29.0f; - - for (int i = 0; i < (int)NK_LEN(blend_node->input_val); i++) - blend_node->input_val[i] = blank; - blend_node->output_val = blank; - - blend_node->blend_val = 0.5f; - - blend_node->node.display_func = node_blend_display; - blend_node->node.eval_func = (void*(*)(struct node*, int)) node_blend_eval; - - } -} - -/* ================================= */ - -#define NK_RGB3(r,g,b) {r,g,b,255} -#define BG_COLOR ((struct nk_color){60,60,60,192}) // nk_rgba(0,0,0,192) - -static -struct editor_node_style { - int pin_type; - const char *shape; - struct nk_color color_idle; - struct nk_color color_hover; -} styles[] = { - // order matters: - { type_flow, "triangle_right", NK_RGB3(200,200,200), NK_RGB3(255,255,255) }, // if .num_links == 0 - { type_int, "circle", NK_RGB3(33,227,175), NK_RGB3(135,239,195) }, - { type_float, "circle", NK_RGB3(156,253,65), NK_RGB3(144,225,137) }, - { type_block, "circle", NK_RGB3(6,165,239), NK_RGB3(137,196,247) }, - { type_texture, "circle", NK_RGB3(148,0,0), NK_RGB3(183,137,137) }, - { type_image, "circle", NK_RGB3(200,130,255), NK_RGB3(220,170,255) }, - { type_color, "circle", NK_RGB3(252,200,35), NK_RGB3(255,217,140) }, -}; - -#define COLOR_FLOW_HI styles[type_flow].color_hover -#define COLOR_FLOW_LO styles[type_flow].color_idle - -#define GRID_SIZE 64.0f -#define GRID_COLOR ((struct nk_color)NK_RGB3(80,80,120)) -#define GRID_THICKNESS 1.0f - -// 4 colors: top-left, top-right, bottom-right, bottom-left -#define GRID_BG_COLORS ((struct nk_color){30,30,30,255}), ((struct nk_color){40,20,0,255}), ((struct nk_color){30,30,30,255}), ((struct nk_color){20,30,40,255}) - -#define LINK_THICKNESS 1.0f -#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ - vec2 a = (POINT_A); \ - vec2 b = (POINT_B); \ - nk_stroke_line(canvas, a.x, a.y, b.x, b.y, LINK_THICKNESS, COLOR); \ -} while(0) -#undef LINK_DRAW -#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ - vec2 a = (POINT_A); \ - vec2 b = (POINT_B); \ - nk_stroke_curve(canvas, a.x, a.y, a.x+50, a.y, b.x-50, b.y, b.x, b.y, LINK_THICKNESS, COLOR); \ -} while(0) -#undef LINK_DRAW -#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ - vec2 a = (POINT_A); \ - vec2 b = (POINT_B); \ - float dist2 = len2( sub2( ptr2(&b.x), ptr2(&a.x) ) ); \ - vec2 mid_a = mix2( ptr2(&a.x), ptr2(&b.x), 0.25 ); mid_a.y += dist2/2; \ - vec2 mid_b = mix2( ptr2(&a.x), ptr2(&b.x), 0.75 ); mid_b.y += dist2/3; \ - nk_stroke_curve(canvas, a.x, a.y, mid_a.x, mid_a.y, mid_b.x, mid_b.y, b.x, b.y, LINK_THICKNESS, COLOR); \ -} while(0) - - -#define PIN_RADIUS 12 -#define PIN_THICKNESS 1.0f -#define PIN_DRAW(PIN_ADDR,POINT,RADIUS) do { \ - circle.x = (POINT).x - (RADIUS) / 2; \ - circle.y = (POINT).y - (RADIUS) / 2; \ - circle.w = circle.h = (RADIUS); \ - struct nk_color color = node_get_type_color((PIN_ADDR).pin_type); \ - if((PIN_ADDR).is_connected) \ - nk_fill_circle(canvas, circle, color); \ - else \ - nk_stroke_circle(canvas, circle, PIN_THICKNESS, color); \ -} while(0) - - -static struct nk_color node_get_type_color(unsigned pin_type) { - for( int i = 0; i < type_total; ++i ) - if( styles[i].pin_type == pin_type ) - return styles[i].color_idle; - return ((struct nk_color)NK_RGB3(255,0,255)); -} - -static void node_editor_push(struct node_editor *editor, struct node *node) { - if (!editor->begin) { - node->next = NULL; - node->prev = NULL; - editor->begin = node; - editor->end = node; - } else { - node->prev = editor->end; - if (editor->end) - editor->end->next = node; - node->next = NULL; - editor->end = node; - } -} - -static void node_editor_pop(struct node_editor *editor, struct node *node) { - if (node->next) - node->next->prev = node->prev; - if (node->prev) - node->prev->next = node->next; - if (editor->end == node) - editor->end = node->prev; - if (editor->begin == node) - editor->begin = node->next; - node->next = NULL; - node->prev = NULL; -} - -static struct node* node_editor_find_by_id(struct node_editor *editor, int ID) { - struct node *iter = editor->begin; - while (iter) { - if (iter->ID == ID) - return iter; - iter = iter->next; - } - return NULL; -} - -static struct node_link* node_editor_find_link_by_output(struct node_editor *editor, struct node *output_node, int node_input_connector) { - for( int i = 0; i < editor->link_count; i++ ) { - if (editor->links[i].output_node == output_node && - editor->links[i].output_pin == node_input_connector && - editor->links[i].is_active == nk_true) { - return &editor->links[i]; - } - } - return NULL; -} - -static struct node_link* node_editor_find_link_by_input(struct node_editor *editor, struct node *input_node, int node_output_connector) { - for( int i = 0; i < editor->link_count; i++ ) { - if (editor->links[i].input_node == input_node && - editor->links[i].input_pin == node_output_connector && - editor->links[i].is_active == nk_true) { - return &editor->links[i]; - } - } - return NULL; -} - -static void node_editor_delete_link(struct node_link *link) { - link->is_active = nk_false; - link->input_node->outputs[link->input_pin].is_connected = nk_false; - link->output_node->inputs[link->output_pin].is_connected = nk_false; -} - -struct node* node_editor_add(struct node_editor *editor, size_t nodeSize, const char *name, struct nk_rect bounds, int in_count, int out_count) { - static int IDs = 0; - struct node *node = NULL; - - if ((nk_size)editor->node_count < NK_LEN(editor->node_buf)) { - /* node_buf has unused pins */ - node = MALLOC(nodeSize); - editor->node_buf[editor->node_count++] = node; - node->ID = IDs++; - } else { - /* check for freed up pins in node_buf */ - for (int i = 0; i < editor->node_count; i++) { - if (editor->node_buf[i] == NULL) { - node = MALLOC(nodeSize); - editor->node_buf[i] = node; - node->ID = i; - break; - } - } - } - if (node == NULL) { - puts("Node creation failed"); - return NULL; - } - - node->bounds = bounds; - - node->input_count = in_count; - node->output_count = out_count; - - node->inputs = MALLOC(node->input_count * sizeof(struct node_pin)); - node->outputs = MALLOC(node->output_count * sizeof(struct node_pin)); - - for (int i = 0; i < node->input_count; i++) { - node->inputs[i].is_connected = nk_false; - node->inputs[i].pin_type = type_float; /* default pin type */ - } - for (int i = 0; i < node->output_count; i++) { - node->outputs[i].is_connected = nk_false; - node->outputs[i].pin_type = type_float; /* default pin type */ - } - - /* default pin spacing */ - node->pin_spacing.in_padding_x = 2; - node->pin_spacing.in_padding_y = 32 + 25/2 + 6; // titlebar height + next half row + adjust - node->pin_spacing.in_spacing_y = 25; // row height+border - node->pin_spacing.out_padding_x = 3; - node->pin_spacing.out_padding_y = 32 + 25/2 + 6; // titlebar height + next half row + adjust - node->pin_spacing.out_spacing_y = 25; // row height+border - - strcpy(node->name, name); - node_editor_push(editor, node); - - return node; -} - -void *node_editor_eval_connected(struct node* node, int input_pin_number) { - NK_ASSERT(node->inputs[input_pin_number].is_connected); - return node->inputs[input_pin_number].connected_node->eval_func(node->inputs[input_pin_number].connected_node, node->inputs[input_pin_number].connected_pin); -} - -static void node_editor_link(struct node_editor *editor, struct node *in_node, int in_pin, struct node *out_node, int out_pin) { - /* Confusingly, in and out nodes/pins here refer to the inputs and outputs OF THE LINK ITSELF, not the nodes */ - struct node_link *link = NULL; - - if ((nk_size)editor->link_count < NK_LEN(editor->links)) { - link = &editor->links[editor->link_count++]; - } else { - for (int i = 0; i < (int)NK_LEN(editor->links); i++) - { - if (editor->links[i].is_active == nk_false) { - link = &editor->links[i]; - break; - } - } - } - if (link) { - out_node->inputs[out_pin].is_connected = nk_true; - in_node->outputs[in_pin].is_connected = nk_true; - out_node->inputs[out_pin].connected_node = in_node; - out_node->inputs[out_pin].connected_pin = in_pin; - - link->input_node = in_node; - link->input_pin = in_pin; - link->output_node = out_node; - link->output_pin = out_pin; - link->is_active = nk_true; - } else { - puts("Too many links"); - } -} - -static void node_editor_init(struct node_editor *editor) { - if (editor->initialized) return; - - struct nk_rect total_space = nk_window_get_content_region(ui_ctx); - struct nk_vec2 output_node_position = { total_space.w*2/3, total_space.h/3 }; - struct nk_vec2 color_node_position = { total_space.w*1/4, total_space.h/3 }; - - memset(editor, 0, sizeof(*editor)); - - editor->output_node = node_output_create(editor, output_node_position); - node_color_create(editor, color_node_position); - editor->show_grid = nk_true; - - editor->initialized = 1; -} - -static int node_editor(struct node_editor *editor) { - int n = 0; - struct nk_rect total_space; - const struct nk_input *in = &ui_ctx->input; - struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); - struct node *updated = 0; - - node_editor_init(editor); - - { - /* allocate complete window space */ - total_space = nk_window_get_content_region(ui_ctx); - nk_layout_space_begin(ui_ctx, NK_STATIC, total_space.h, editor->node_count); - { - struct node *it = editor->begin; - struct nk_rect size = nk_layout_space_bounds(ui_ctx); - struct nk_panel *nodePanel = 0; - - //nk_fill_rect(canvas, size, 0/*rounding*/, ((struct nk_color){30,30,30,255})); // 20,30,40,255 - nk_fill_rect_multi_color(canvas, size, GRID_BG_COLORS); - - if (editor->show_grid) { - /* display grid */ - for (float x = (float)fmod(size.x - editor->scrolling.x, GRID_SIZE); x < size.w; x += GRID_SIZE) - nk_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, GRID_THICKNESS, GRID_COLOR); - for (float y = (float)fmod(size.y - editor->scrolling.y, GRID_SIZE); y < size.h; y += GRID_SIZE) - nk_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, GRID_THICKNESS, GRID_COLOR); - } - - /* execute each node as a movable group */ - /* loop through nodes */ - while (it) { - /* Output node window should not have a close button */ - nk_flags nodePanel_flags = NK_WINDOW_MOVABLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_TITLE; - if (it != editor->output_node) - nodePanel_flags |= NK_WINDOW_CLOSABLE; - - /* calculate scrolled node window position and size */ - nk_layout_space_push(ui_ctx, nk_rect(it->bounds.x - editor->scrolling.x, - it->bounds.y - editor->scrolling.y, it->bounds.w, it->bounds.h)); - - /* execute node window */ - char *name = va(" " ICON_MD_MENU " %s",it->name); //< @r-lyeh added some spacing+icon because of our UI customizations - -struct nk_color bak = ui_ctx->style.window.fixed_background.data.color; -ui_ctx->style.window.fixed_background.data.color = BG_COLOR; - - if (nk_group_begin(ui_ctx, name, nodePanel_flags)) - { - /* always have last selected node on top */ - - nodePanel = nk_window_get_panel(ui_ctx); - if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nodePanel->bounds) && - (!(it->prev && nk_input_mouse_clicked(in, NK_BUTTON_LEFT, - nk_layout_space_rect_to_screen(ui_ctx, nodePanel->bounds)))) && - editor->end != it) - { - updated = it; - } - - if ((nodePanel->flags & NK_WINDOW_HIDDEN)) /* Node close button has been clicked */ - { - /* Delete node */ - struct node_link *link_remove; - node_editor_pop(editor, it); - for (int n = 0; n < it->input_count; n++) { - if ((link_remove = node_editor_find_link_by_output(editor, it, n))) - { - node_editor_delete_link(link_remove); - } - } - for (int n = 0; n < it -> output_count; n++) { - while((link_remove = node_editor_find_link_by_input(editor, it, n))) - { - node_editor_delete_link(link_remove); - } - } - NK_ASSERT(editor->node_buf[it->ID] == it); - editor->node_buf[it->ID] = NULL; - FREE(it->inputs); - FREE(it->outputs); - FREE(it); - } - else { - - /* ================= NODE CONTENT ===================== */ - - it->display_func(ui_ctx, it); - - /* ==================================================== */ - - } - nk_group_end(ui_ctx); - - } - -ui_ctx->style.window.fixed_background.data.color = bak; - - if (!(nodePanel->flags & NK_WINDOW_HIDDEN)) - { - /* node pin and linking */ - struct nk_rect bounds; - bounds = nk_layout_space_rect_to_local(ui_ctx, nodePanel->bounds); - bounds.x += editor->scrolling.x; - bounds.y += editor->scrolling.y; - it->bounds = bounds; - - /* output pins */ - for (int n = 0; n < it->output_count; ++n) { - struct nk_rect circle; - struct nk_vec2 pt = {nodePanel->bounds.x, nodePanel->bounds.y}; - pt.x += nodePanel->bounds.w - PIN_RADIUS / 2 + it->pin_spacing.out_padding_x; - pt.y += it->pin_spacing.out_padding_y + it->pin_spacing.out_spacing_y * (n); - PIN_DRAW(it->outputs[n],pt,PIN_RADIUS); - - /* start linking process */ - /* set linking active */ - if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true)) { - editor->linking.active = nk_true; - editor->linking.node = it; - editor->linking.input_id = it->ID; - editor->linking.input_pin = n; - } - - /* draw link being dragged (from linked pin to mouse position) */ - if (editor->linking.active && editor->linking.node == it && - editor->linking.input_pin == n) { - LINK_DRAW(vec2(circle.x+3,circle.y+3),ptr2(&in->mouse.pos.x),COLOR_FLOW_HI); - } - } - - /* input pins */ - for (int n = 0; n < it->input_count; ++n) { - struct nk_rect circle; - struct nk_vec2 pt = {nodePanel->bounds.x, nodePanel->bounds.y}; - pt.x += it->pin_spacing.in_padding_x; - pt.y += it->pin_spacing.in_padding_y + it->pin_spacing.in_spacing_y * (n); - PIN_DRAW(it->inputs[n],pt,PIN_RADIUS); - - /* Detach link */ - if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true) && - editor->linking.active == nk_false && - it->inputs[n].is_connected == nk_true) { - struct node_link *node_relink = node_editor_find_link_by_output(editor, it, n); - editor->linking.active = nk_true; - editor->linking.node = node_relink->input_node; - editor->linking.input_id = node_relink->input_node->ID; - editor->linking.input_pin = node_relink->input_pin; - node_editor_delete_link(node_relink); - } - - /* Create link */ - if (nk_input_is_mouse_released(in, NK_BUTTON_LEFT) && - nk_input_is_mouse_hovering_rect(in, circle) && - editor->linking.active && - editor->linking.node != it && - it->inputs[n].pin_type == editor->linking.node->outputs[editor->linking.input_pin].pin_type && - it->inputs[n].is_connected != nk_true) { - editor->linking.active = nk_false; - - node_editor_link(editor, editor->linking.node, - editor->linking.input_pin, it, n); - } - } - } - it = it->next; - } - - /* reset (output) linking connection */ - if (editor->linking.active && (!!input(KEY_LCTRL) || !!input(KEY_RCTRL) || nk_input_is_mouse_released(in, NK_BUTTON_LEFT))) { - editor->linking.active = nk_false; - editor->linking.node = NULL; - } - - /* draw each static link */ - for (int n = 0; n < editor->link_count; ++n) { - struct node_link *link = &editor->links[n]; - if (link->is_active == nk_true){ - struct node *ni = link->input_node; - struct node *no = link->output_node; - struct nk_vec2 l0 = nk_layout_space_to_screen(ui_ctx, nk_vec2(ni->bounds.x + ni->bounds.w + ni->pin_spacing.out_padding_x, 3.0f + ni->bounds.y + ni->pin_spacing.out_padding_y + ni->pin_spacing.out_spacing_y * (link->input_pin))); - struct nk_vec2 l1 = nk_layout_space_to_screen(ui_ctx, nk_vec2(no->bounds.x + no->pin_spacing.in_padding_x, 3.0f + no->bounds.y + no->pin_spacing.in_padding_y + no->pin_spacing.in_spacing_y * (link->output_pin))); - - l0.x -= editor->scrolling.x; - l0.y -= editor->scrolling.y; - l1.x -= editor->scrolling.x; - l1.y -= editor->scrolling.y; - - struct nk_color color = node_get_type_color(no->inputs[link->output_pin].pin_type); - LINK_DRAW(ptr2(&l0.x), ptr2(&l1.x), color); - } - } - - if (updated) { - /* reshuffle nodes to have least recently selected node on top */ - node_editor_pop(editor, updated); - node_editor_push(editor, updated); - } - - /* node selection */ - if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nk_layout_space_bounds(ui_ctx))) { - it = editor->begin; - editor->selected = NULL; - editor->bounds = nk_rect(in->mouse.pos.x, in->mouse.pos.y, 100, 200); - while (it) { - struct nk_rect b = nk_layout_space_rect_to_screen(ui_ctx, it->bounds); - b.x -= editor->scrolling.x; - b.y -= editor->scrolling.y; - if (nk_input_is_mouse_hovering_rect(in, b)) - editor->selected = it; - it = it->next; - } - } - - /* contextual menu */ - if (nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 220), nk_window_get_bounds(ui_ctx))) { - struct nk_vec2 wincoords = { in->mouse.pos.x-total_space.x-50, in->mouse.pos.y-total_space.y-32 }; - -#if 1 - static char *filter = 0; - static int do_filter = 0; - if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1; - int choice = ui_toolbar(ICON_MD_SEARCH ";"); - if( choice == 1 ) do_filter = 1; - if( do_filter ) { - ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter); - if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon) - do_filter = 0; - } - } else { - if( filter ) filter[0] = '\0'; - } - char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*"; -#endif - - #define ui_label_filtered(lbl) (strmatchi(lbl,filter_mask) && ui_label(lbl)) - - int close = 0; - if (ui_label_filtered("=Add Color node")) close=1,node_color_create(editor, wincoords); - if (ui_label_filtered("=Add Float node")) close=1,node_float_create(editor, wincoords); - if (ui_label_filtered("=Add Blend Node")) close=1,node_blend_create(editor, wincoords); - if (ui_label_filtered(editor->show_grid ? "=Hide Grid" : "=Show Grid")) - close=1,editor->show_grid = !editor->show_grid; - if(close) do_filter = 0, (filter ? filter[0] = '\0' : '\0'), nk_contextual_close(ui_ctx); - nk_contextual_end(ui_ctx); - } - } - nk_layout_space_end(ui_ctx); - - /* window content scrolling */ - if (nk_input_is_mouse_hovering_rect(in, nk_window_get_bounds(ui_ctx)) && - nk_input_is_mouse_down(in, NK_BUTTON_MIDDLE)) { - editor->scrolling.x += in->mouse.delta.x; - editor->scrolling.y += in->mouse.delta.y; - } - } - - return !nk_window_is_closed(ui_ctx, "NodeEdit"); -} - -int editor_nodes(int window_mode) { - window_mode = EDITOR_WINDOW; // force window - - if( editor_begin(NODES_TITLE, window_mode) ) { - - static struct node_editor nodeEditor = {0}; - node_editor(&nodeEditor); - - editor_end(window_mode); - } - return 0; -} - -AUTORUN { - array_push(editor.subeditors, editor_nodes); -} diff --git a/tools/editor_rename.bat b/tools/editor_rename.bat index e3b0665..61838db 100644 --- a/tools/editor_rename.bat +++ b/tools/editor_rename.bat @@ -25,7 +25,7 @@ pushd tools\editor set "filename=%%~nf" set "newname=v4k!filename:fwk=!%%~xf" echo Renaming "%%f" to "!newname!" - copy "%%f" "!newname!" + move "%%f" "!newname!" ) echo All done. endlocal