From 26c8441062439b03960a8aefe6b69ff2e21ccd4e Mon Sep 17 00:00:00 2001 From: MakhamDev Date: Tue, 25 Jan 2022 16:58:11 +0700 Subject: [PATCH] Search collection from add node --- objects/_p_dialog/Create_0.gml | 4 +- objects/_p_dialog/Destroy_0.gml | 2 +- objects/o_dialog_add_node/CleanUp_0.gml | 2 + objects/o_dialog_add_node/Create_0.gml | 217 ++++++++----- .../o_dialog_add_node/o_dialog_add_node.yy | 1 + objects/o_dialog_preference/Create_0.gml | 9 + objects/o_dialog_preference/Draw_64.gml | 2 +- objects/o_main/Create_0.gml | 2 +- scripts/collection_data/collection_data.gml | 138 +++++++- scripts/ds_extra/ds_extra.gml | 6 + scripts/node_condition/node_condition.gml | 11 +- scripts/node_data/node_data.gml | 4 +- .../node_group_output/node_group_output.gml | 10 +- scripts/node_iterate/node_iterate.gml | 11 +- .../node_iteration_output.gml | 10 +- scripts/node_line/node_line.gml | 2 + scripts/node_pin/node_pin.gml | 4 +- scripts/node_registry/node_registry.gml | 8 +- scripts/node_value/node_value.gml | 16 +- scripts/panel_collection/panel_collection.gml | 303 ++++++------------ scripts/panel_data/panel_data.gml | 19 +- scripts/panel_function/panel_function.gml | 2 +- scripts/panel_graph/panel_graph.gml | 1 + scripts/preferences/preferences.gml | 2 + scripts/sample_projects/sample_projects.gml | 2 +- scripts/save_function/save_function.gml | 2 +- 26 files changed, 463 insertions(+), 327 deletions(-) create mode 100644 objects/o_dialog_add_node/CleanUp_0.gml diff --git a/objects/_p_dialog/Create_0.gml b/objects/_p_dialog/Create_0.gml index 331df4ed4..0d522b446 100644 --- a/objects/_p_dialog/Create_0.gml +++ b/objects/_p_dialog/Create_0.gml @@ -64,7 +64,7 @@ #endregion #region focus - FOCUS = self; + setFocus(self); FOCUS_STR = "Dialog"; function checkFocus() { @@ -82,7 +82,7 @@ mouse_check_button_pressed(mb_right) || mouse_check_button_pressed(mb_middle)) { - FOCUS = self; + setFocus(self); FOCUS_STR = "Dialog"; } } diff --git a/objects/_p_dialog/Destroy_0.gml b/objects/_p_dialog/Destroy_0.gml index 18bb2a976..bd37b463f 100644 --- a/objects/_p_dialog/Destroy_0.gml +++ b/objects/_p_dialog/Destroy_0.gml @@ -1,5 +1,5 @@ /// @description init if(HOVER == self) HOVER = noone; -if(FOCUS == self) FOCUS = noone; +if(FOCUS == self) setFocus(noone); TEXTBOX_ACTIVE = noone; \ No newline at end of file diff --git a/objects/o_dialog_add_node/CleanUp_0.gml b/objects/o_dialog_add_node/CleanUp_0.gml new file mode 100644 index 000000000..c09dd12e8 --- /dev/null +++ b/objects/o_dialog_add_node/CleanUp_0.gml @@ -0,0 +1,2 @@ +/// @description +ds_list_destroy(search_list); \ No newline at end of file diff --git a/objects/o_dialog_add_node/Create_0.gml b/objects/o_dialog_add_node/Create_0.gml index 1fe3d6c7b..01e52c824 100644 --- a/objects/o_dialog_add_node/Create_0.gml +++ b/objects/o_dialog_add_node/Create_0.gml @@ -27,43 +27,70 @@ event_inherited(); if(!_node) return; - var _new_node = _node.build(node_target_x, node_target_y, _param); + var _inputs = 0, _outputs = 0; + if(is_struct(_node) && instanceof(_node) == "NodeObject") { + var _new_node = _node.build(node_target_x, node_target_y, _param); + if(!_new_node) return; + _inputs = _new_node.inputs; + _outputs = _new_node.outputs; + } else { + var _new_list = APPEND(_node.path); + _inputs = ds_list_create(); + _outputs = ds_list_create(); + + for( var i = 0; i < ds_list_size(_new_list); i++ ) { + var _in = _new_list[| i].inputs; + for( var j = 0; j < ds_list_size(_in); j++ ) { + if(_in[| j].value_from == noone) + ds_list_add(_inputs, _in[| j]); + } + + var _ot = _new_list[| i].outputs; + for( var j = 0; j < ds_list_size(_ot); j++ ) { + if(ds_list_empty(_ot[| j].value_to)) + ds_list_add(_outputs, _ot[| j]); + } + } + + ds_list_destroy(_new_list); + } - if(_new_node) { - if(node_called != noone) { - var _node_list = node_called.connect_type == JUNCTION_CONNECT.input? _new_node.outputs : _new_node.inputs; - for(var i = 0; i < ds_list_size(_node_list); i++) { - var _target = _node_list[| i]; - if(_target.isVisible() && (value_bit(_target.type) & value_bit(node_called.type))) { - if(node_called.connect_type == JUNCTION_CONNECT.input) { - node_called.setFrom(_node_list[| i]); - _new_node.x -= _new_node.w; - } else - _node_list[| i].setFrom(node_called); - break; - } + if(node_called != noone) { + var _node_list = node_called.connect_type == JUNCTION_CONNECT.input? _outputs : _inputs; + for(var i = 0; i < ds_list_size(_node_list); i++) { + var _target = _node_list[| i]; + if( _target.isVisible() && (value_bit(_target.type) & value_bit(node_called.type)) ) { + if(node_called.connect_type == JUNCTION_CONNECT.input) { + node_called.setFrom(_node_list[| i]); + _new_node.x -= _new_node.w; + } else + _node_list[| i].setFrom(node_called); + break; } - } else if(junction_hovering != noone) { - var to = junction_hovering; - var from = junction_hovering.value_from; + } + } else if(junction_hovering != noone) { + var to = junction_hovering; + var from = junction_hovering.value_from; - for( var i = 0; i < ds_list_size(_new_node.inputs); i++ ) { - var _in = _new_node.inputs[| i]; - if(value_bit(_in.type) & value_bit(from.type)) { - _in.setFrom(from); - break; - } + for( var i = 0; i < ds_list_size(_inputs); i++ ) { + var _in = _inputs[| i]; + if(value_bit(_in.type) & value_bit(from.type)) { + _in.setFrom(from); + break; } + } - for( var i = 0; i < ds_list_size(_new_node.outputs); i++ ) { - var _ot = _new_node.outputs[| i]; - if(value_bit(_ot.type) & value_bit(to.type)) { - to.setFrom(_ot); - break; - } + for( var i = 0; i < ds_list_size(_outputs); i++ ) { + var _ot = _outputs[| i]; + if(value_bit(_ot.type) & value_bit(to.type)) { + to.setFrom(_ot); + break; } } } + + ds_list_destroy(_inputs); + ds_list_destroy(_outputs); } catagory_pane = new scrollPane(132, dialog_h - 28, function(_y, _m) { @@ -184,41 +211,31 @@ event_inherited(); #region search search_string = ""; + search_list = ds_list_create(); keyboard_lastchar = ""; keyboard_string = ""; keyboard_lastkey = -1; - tb_search = new textBox(TEXTBOX_INPUT.text, function(str) { search_string = string(str); }); + tb_search = new textBox(TEXTBOX_INPUT.text, function(str) { + search_string = string(str); + searchNodes(); + }); tb_search.auto_update = true; TEXTBOX_ACTIVE = tb_search; - search_pane = new scrollPane(dialog_w - 32, dialog_h - 52 - 14, function(_y, _m) { - draw_clear_alpha(c_ui_blue_black, 0); + function searchNodes() { + ds_list_clear(search_list); - var grid_size = 64; - var grid_width = 80; - var grid_space = 16; - var col = floor(search_pane.surface_w / (grid_width + grid_space)); - var hh = (grid_space + grid_size) * 2; - var yy = _y + grid_space; - var index = 0; - var name_height = 0; - var amo = 0; var cnt = PANEL_GRAPH.getCurrentContext(); var context = cnt == -1? "" : instanceof(cnt); - var search_lower = string_lower(search_string); for(var i = 0; i < ds_list_size(NODE_CATAGORY); i++) { var key = NODE_CATAGORY[| i]; switch(key) { - case "Group" : - if(context != "Node_Group") continue; - break; - case "Loop" : - if(context != "Node_Iterate") continue; - break; + case "Group" : if(context != "Node_Group") continue; break; + case "Loop" : if(context != "Node_Iterate") continue; break; } var _page = ALL_NODES[? key]; @@ -237,47 +254,77 @@ event_inherited(); } if(match) { - var _nx = grid_space + (grid_width + grid_space) * index; - var _boxx = _nx + (grid_width - grid_size) / 2; - - draw_sprite_stretched(s_node_bg, 0, _boxx, yy, grid_size, grid_size); - - if(variable_struct_exists(_node, "spr") && sprite_exists(_node.spr)) - draw_sprite(_node.spr, 0, _boxx + grid_size / 2, yy + grid_size / 2); - - draw_set_text(f_p1, fa_center, fa_top, c_white); - name_height = max(name_height, string_height_ext(_node.name, -1, grid_size) + 8); - draw_text_ext(_boxx + grid_size / 2, yy + grid_size + 4, _node.name, -1, grid_width); - - if(point_in_rectangle(_m[0], _m[1], _nx, yy, _nx + grid_width, yy + grid_size)) { - node_selecting = amo; - if(mouse_check_button_pressed(mb_left)) - buildNode(_node, param); - } - - if(node_selecting == amo) { - draw_sprite_stretched(s_node_active, 0, _boxx, yy, grid_size, grid_size); - if(keyboard_check_pressed(vk_enter)) - buildNode(_node, param); - } - - if(node_focusing == amo) { - search_pane.scroll_y_to = -max(0, hh - search_pane.h); - } - - if(++index >= col) { - index = 0; - var hght = grid_size + grid_space + name_height; - name_height = 0; - hh += hght; - yy += hght; - } - - amo++; + ds_list_add(search_list, [_node, param]); } } } + searchCollection(search_list, search_string, false); + } + + search_pane = new scrollPane(dialog_w - 32, dialog_h - 52 - 14, function(_y, _m) { + draw_clear_alpha(c_ui_blue_black, 0); + + var grid_size = 64; + var grid_width = 80; + var grid_space = 16; + var col = floor(search_pane.surface_w / (grid_width + grid_space)); + var hh = (grid_space + grid_size) * 2; + var yy = _y + grid_space; + var index = 0; + var name_height = 0; + var amo = ds_list_size(search_list); + + for(var i = 0; i < ds_list_size(search_list); i++) { + var s_res = search_list[| i]; + var _node, _param = ""; + if(is_array(s_res)) { + _node = s_res[0]; + _param = s_res[1]; + } else { + _node = s_res; + } + + var _nx = grid_space + (grid_width + grid_space) * index; + var _boxx = _nx + (grid_width - grid_size) / 2; + + if(is_array(s_res)) + draw_sprite_stretched(s_node_bg, 0, _boxx, yy, grid_size, grid_size); + else + draw_sprite_stretched_ext(s_node_bg, 0, _boxx, yy, grid_size, grid_size, merge_color(c_white, c_ui_orange_light, 0.5), 1); + + if(variable_struct_exists(_node, "spr") && sprite_exists(_node.spr)) + draw_sprite(_node.spr, current_time * PREF_MAP[? "collection_preview_speed"] / 3000, _boxx + grid_size / 2, yy + grid_size / 2); + + draw_set_text(f_p1, fa_center, fa_top, c_white); + name_height = max(name_height, string_height_ext(_node.name, -1, grid_size) + 8); + draw_text_ext(_boxx + grid_size / 2, yy + grid_size + 4, _node.name, -1, grid_width); + + if(point_in_rectangle(_m[0], _m[1], _nx, yy, _nx + grid_width, yy + grid_size)) { + node_selecting = i; + if(mouse_check_button_pressed(mb_left)) + buildNode(_node, _param); + } + + if(node_selecting == i) { + draw_sprite_stretched(s_node_active, 0, _boxx, yy, grid_size, grid_size); + if(keyboard_check_pressed(vk_enter)) + buildNode(_node, _param); + } + + if(node_focusing == i) { + search_pane.scroll_y_to = -max(0, hh - search_pane.h); + } + + if(++index >= col) { + index = 0; + var hght = grid_size + grid_space + name_height; + name_height = 0; + hh += hght; + yy += hght; + } + } + node_focusing = -1; if(keyboard_check_pressed(vk_up)) { diff --git a/objects/o_dialog_add_node/o_dialog_add_node.yy b/objects/o_dialog_add_node/o_dialog_add_node.yy index 11308f551..78b0e58cf 100644 --- a/objects/o_dialog_add_node/o_dialog_add_node.yy +++ b/objects/o_dialog_add_node/o_dialog_add_node.yy @@ -24,6 +24,7 @@ {"isDnD":false,"eventNum":64,"eventType":8,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",}, {"isDnD":false,"eventNum":0,"eventType":0,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",}, {"isDnD":false,"eventNum":0,"eventType":1,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",}, + {"isDnD":false,"eventNum":0,"eventType":12,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",}, ], "properties": [], "overriddenProperties": [], diff --git a/objects/o_dialog_preference/Create_0.gml b/objects/o_dialog_preference/Create_0.gml index b8fe9fb01..fd0a5e876 100644 --- a/objects/o_dialog_preference/Create_0.gml +++ b/objects/o_dialog_preference/Create_0.gml @@ -94,6 +94,15 @@ event_inherited(); }) ]); + ds_list_add(pref_global, [ + "Collection preview speed", + "collection_preview_speed", + new textBox(TEXTBOX_INPUT.number, function(str) { + PREF_MAP[? "collection_preview_speed"] = max(1, round(real(str))); + PREF_SAVE(); + }) + ]); + //NODE ds_list_add(pref_node, [ diff --git a/objects/o_dialog_preference/Draw_64.gml b/objects/o_dialog_preference/Draw_64.gml index a37f13f4f..6b16cdfd0 100644 --- a/objects/o_dialog_preference/Draw_64.gml +++ b/objects/o_dialog_preference/Draw_64.gml @@ -40,7 +40,7 @@ if !ready exit; tb_search.active = FOCUS == self; tb_search.hover = HOVER == self; tb_search.draw(dialog_x + dialog_w - 16 - 200, dialog_y + 16, 200, 32, search_text, [mouse_mx, mouse_my]); - draw_sprite_ext(s_search_16, 0, dialog_x + dialog_w - 16 - 200 - 16, dialog_y + 16 + 12, 1, 1, 0, c_ui_blue_grey, 1); + draw_sprite_ext(s_search_16, 0, dialog_x + dialog_w - 16 - 200 - 16, dialog_y + 16 + 16, 1, 1, 0, c_ui_blue_grey, 1); if(page_current == 0) { current_list = pref_global; diff --git a/objects/o_main/Create_0.gml b/objects/o_main/Create_0.gml index 58c78a0dd..31f0ecab6 100644 --- a/objects/o_main/Create_0.gml +++ b/objects/o_main/Create_0.gml @@ -12,7 +12,7 @@ file_text_close(f); #endregion -display_reset(0, 1); +display_reset(8, 1); #region window depth = 0; diff --git a/scripts/collection_data/collection_data.gml b/scripts/collection_data/collection_data.gml index 0caaf7a58..376d8b0cb 100644 --- a/scripts/collection_data/collection_data.gml +++ b/scripts/collection_data/collection_data.gml @@ -1,9 +1,108 @@ -function FileContext(_name, _path, _subfolder = false) constructor { +function DirectoryObject(name, path) constructor { + self.name = name; + self.path = path; + + subDir = ds_list_create(); + content = ds_list_create(); + open = false; + + static destroy = function() { + ds_list_destroy(subDir); + } + + static getSub = function() { + var _temp_name = ds_list_create(); + var folder = file_find_first(path + "/*", fa_directory); + while(folder != "") { + ds_list_add(_temp_name, folder); + folder = file_find_next(); + } + file_find_close(); + + ds_list_clear(subDir); + ds_list_clear(content); + + ds_list_sort(_temp_name, true); + for( var i = 0; i < ds_list_size(_temp_name); i++ ) { + var file = _temp_name[| i]; + + if(directory_exists(path + "\\" + file)) { + var _fol_path = path + "\\" + file; + var fol = new DirectoryObject(file, _fol_path); + ds_list_add(subDir, fol); + } else if(filename_ext(file) == ".json" || filename_ext(file) == ".pxcc") { + var f = new FileObject(string_copy(file, 1, string_length(file) - 5), path + "\\" + file); + ds_list_add(content, f); + var icon_path = path + "\\" + string_copy(file, 1, string_length(file) - 5) + ".png"; + + if(file_exists(icon_path)) { + var _temp = sprite_add(icon_path, 0, false, false, 0, 0); + var ww = sprite_get_width(_temp); + var hh = sprite_get_height(_temp); + var amo = ww % hh == 0? ww / hh : 1; + sprite_delete(_temp); + + f.spr = sprite_add(icon_path, amo, false, false, 0, 0); + sprite_set_offset(f.spr, sprite_get_width(f.spr) / 2, sprite_get_height(f.spr) / 2); + } + } + } + + ds_list_destroy(_temp_name); + } + getSub(); + + static draw = function(_x, _y, _m, _w) { + var hg = 28; + var hh = 0; + + if(path == PANEL_COLLECTION.context.path) + draw_sprite_stretched_ext(s_ui_panel_bg, 0, _x, _y, _w, hg, c_ui_blue_ltgrey, 1); + + if(HOVER == PANEL_COLLECTION.panel && point_in_rectangle(_m[0], _m[1], 0, _y, _w, _y + hg - 1)) { + draw_sprite_stretched_ext(s_ui_panel_bg, 0, _x, _y, _w, hg, c_ui_blue_white, 1); + if(FOCUS == PANEL_COLLECTION.panel && mouse_check_button_pressed(mb_left)) { + open = !open; + + if(PANEL_COLLECTION.context = self) + PANEL_COLLECTION.setContext(COLLECTIONS); + else + PANEL_COLLECTION.setContext(self); + } + } + + draw_set_text(f_p0, fa_left, fa_center, c_white); + if(ds_list_empty(subDir)) { + draw_sprite_ext(s_folder_24, 0, _x + 16, _y + hg / 2 - 1, 1, 1, 0, c_ui_blue_dkgrey, 1); + } else { + draw_sprite_ext(s_folder_content_24, open, _x + 16, _y + hg / 2 - 1, 1, 1, 0, c_ui_blue_grey, 1); + } + draw_text(_x + 8 + 24, _y + hg / 2, name); + hh += hg; + _y += hg; + + if(open && !ds_list_empty(subDir)) { + var l_y = _y; + for(var i = 0; i < ds_list_size(subDir); i++) { + var _hg = subDir[| i].draw(_x + 16, _y, _m, _w - 16); + draw_set_color(c_ui_blue_dkgrey); + draw_line(_x + 12, _y + hg / 2, _x + 12 + 4, _y + hg / 2); + + hh += _hg; + _y += _hg; + } + draw_set_color(c_ui_blue_dkgrey); + draw_line(_x + 12, l_y, _x + 12, _y - hg / 2); + } + + return hh; + } +} + +function FileObject(_name, _path) constructor { name = _name; path = _path; spr = -1; - - subfolder = _subfolder; } function __init_collection() { @@ -23,10 +122,10 @@ function __init_collection() { zip_unzip("Collections.zip", _); } - searchCollections(); + refreshCollections(); } -function searchCollections() { +function refreshCollections() { log_message("COLLECTION", "refreshing collection base folder."); if(!directory_exists(DIRECTORY + "Collections")) { @@ -36,4 +135,33 @@ function searchCollections() { COLLECTIONS = new DirectoryObject("Collections", DIRECTORY + "Collections"); COLLECTIONS.open = true; +} + +function searchCollection(_list, _search_str, _claer_list = true) { + if(_claer_list) + ds_list_clear(_list); + + if(_search_str == "") return; + var search_lower = string_lower(_search_str); + + var st = ds_stack_create(); + ds_stack_push(st, COLLECTIONS); + + while(!ds_stack_empty(st)) { + var _st = ds_stack_pop(st); + for( var i = 0; i < ds_list_size(_st.content); i++ ) { + var _nd = _st.content[| i]; + + var match = string_pos(search_lower, string_lower(_nd.name)) > 0; + if(match) { + ds_list_add(_list, _nd); + } + } + + for( var i = 0; i < ds_list_size(_st.subDir); i++ ) { + ds_stack_push(st, _st.subDir[| i]); + } + } + + ds_stack_destroy(st); } \ No newline at end of file diff --git a/scripts/ds_extra/ds_extra.gml b/scripts/ds_extra/ds_extra.gml index cc4d67bb4..68b2109b5 100644 --- a/scripts/ds_extra/ds_extra.gml +++ b/scripts/ds_extra/ds_extra.gml @@ -35,4 +35,10 @@ function ds_list_clone(list) { function ds_list_remove(list, item) { var in = ds_list_find_index(list, item); if(in >= 0) ds_list_delete(list, in); +} + +function ds_list_append(list, _append) { + for( var i = 0; i < ds_list_size(_append); i++ ) { + ds_list_add(list, _append[| i]); + } } \ No newline at end of file diff --git a/scripts/node_condition/node_condition.gml b/scripts/node_condition/node_condition.gml index 36cce2d8b..061746aa9 100644 --- a/scripts/node_condition/node_condition.gml +++ b/scripts/node_condition/node_condition.gml @@ -38,6 +38,9 @@ function Node_Condition(_x, _y) : Node(_x, _y) constructor { var _true = inputs[| 3].getValue(); var _fals = inputs[| 4].getValue(); + inputs[| 3].type = inputs[| 3].value_from == noone? VALUE_TYPE.any : inputs[| 3].value_from.type; + inputs[| 4].type = inputs[| 4].value_from == noone? VALUE_TYPE.any : inputs[| 4].value_from.type; + var res = false; switch(_cond) { @@ -49,6 +52,12 @@ function Node_Condition(_x, _y) : Node(_x, _y) constructor { case 5 : res = _chck >= _valu; break; } - output[| 0].setValue(res? _true : _fals); + if(res) { + outputs[| 0].setValue(_true); + outputs[| 0].type = inputs[| 3].type; + } else { + outputs[| 0].setValue(_fals); + outputs[| 0].type = inputs[| 4].type; + } } } \ No newline at end of file diff --git a/scripts/node_data/node_data.gml b/scripts/node_data/node_data.gml index cc7a891da..a66ea080b 100644 --- a/scripts/node_data/node_data.gml +++ b/scripts/node_data/node_data.gml @@ -521,13 +521,13 @@ function Node(_x, _y) constructor { var _ou = outputs[| i]; for(var j = 0; j < ds_list_size(_ou.value_to); j++) { var _to = _ou.value_to[| j]; - if(_to.node.active && _to.node.group != group) { + if(_to.value_from == _ou && _to.node.active && _to.node.group != group) { var output_node; switch(_type) { case "group" : output_node = new Node_Group_Output(x + w + 64, y, group); break; case "loop" : output_node = new Node_Iterator_Output(x + w + 64, y, group); break; } - + ds_list_add(group.nodes, output_node); _to.setFrom(output_node.outParent); diff --git a/scripts/node_group_output/node_group_output.gml b/scripts/node_group_output/node_group_output.gml index 1166048a7..f27b2af89 100644 --- a/scripts/node_group_output/node_group_output.gml +++ b/scripts/node_group_output/node_group_output.gml @@ -59,13 +59,9 @@ function Node_Group_Output(_x, _y, _group) : Node(_x, _y) constructor { if(is_undefined(outParent)) return; outParent.name = name; - - if(inputs[| 0].value_from) { - outParent.type = inputs[| 0].value_from.type; - inputs[| 0].type = inputs[| 0].value_from.type; - } else { - inputs[| 0].type = VALUE_TYPE.any; - } + + inputs[| 0].type = inputs[| 0].value_from == noone? VALUE_TYPE.any : inputs[| 0].value_from.type; + outParent.type = inputs[| 0].type; } static doUpdateForward = function() { if(is_undefined(outParent)) return; diff --git a/scripts/node_iterate/node_iterate.gml b/scripts/node_iterate/node_iterate.gml index aa16af5ce..cb099f125 100644 --- a/scripts/node_iterate/node_iterate.gml +++ b/scripts/node_iterate/node_iterate.gml @@ -14,10 +14,14 @@ function Node_Iterate(_x, _y) : Node_Collection(_x, _y) constructor { inputs[| 0] = nodeValue( 0, "Repeat", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1 ); custom_input_index = 1; + loop_start_time = 0; static setRenderStatus = function(result) { rendered = result; - if(!rendered) iterated = 0; + if(!rendered) { + iterated = 0; + loop_start_time = get_timer(); + } } static outputRendered = function() { @@ -28,9 +32,10 @@ function Node_Iterate(_x, _y) : Node_Collection(_x, _y) constructor { } if(iter) { - if(++iterated == inputs[| 0].getValue()) + if(++iterated == inputs[| 0].getValue()) { + render_time = get_timer() - loop_start_time; return 2; - else if(iterated > inputs[| 0].getValue()) + } else if(iterated > inputs[| 0].getValue()) return 3; resetRenderStatus(); diff --git a/scripts/node_iteration_output/node_iteration_output.gml b/scripts/node_iteration_output/node_iteration_output.gml index c5ed84e4a..c5c182733 100644 --- a/scripts/node_iteration_output/node_iteration_output.gml +++ b/scripts/node_iteration_output/node_iteration_output.gml @@ -62,13 +62,9 @@ function Node_Iterator_Output(_x, _y, _group) : Node(_x, _y) constructor { if(is_undefined(outParent)) return; outParent.name = name; - - if(inputs[| 0].value_from) { - outParent.type = inputs[| 0].value_from.type; - inputs[| 0].type = inputs[| 0].value_from.type; - } else { - inputs[| 0].type = VALUE_TYPE.any; - } + + inputs[| 0].type = inputs[| 0].value_from == noone? VALUE_TYPE.any : inputs[| 0].value_from.type; + outParent.type = inputs[| 0].type; } static doUpdateForward = function() { if(is_undefined(outParent)) return; diff --git a/scripts/node_line/node_line.gml b/scripts/node_line/node_line.gml index aa5e36e3d..501863011 100644 --- a/scripts/node_line/node_line.gml +++ b/scripts/node_line/node_line.gml @@ -5,6 +5,8 @@ function Node_create_Line(_x, _y) { } function Node_Line(_x, _y) : Node(_x, _y) constructor { + display_reset(0, 1); + name = "Line"; inputs[| 0] = nodeValue(0, "Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, def_surf_size2, VALUE_TAG.dimension_2d ) diff --git a/scripts/node_pin/node_pin.gml b/scripts/node_pin/node_pin.gml index 94ffe5668..bdde17873 100644 --- a/scripts/node_pin/node_pin.gml +++ b/scripts/node_pin/node_pin.gml @@ -21,7 +21,9 @@ function Node_Pin(_x, _y) : Node(_x, _y) constructor { outputs[| 0] = nodeValue(0, "Out", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0); static update = function() { - if(inputs[| 0].value_from != noone) { + inputs[| 0].type = inputs[| 0].value_from == noone? VALUE_TYPE.any : inputs[| 0].value_from.type; + + if(inputs[| 0].value_from != noone) { outputs[| 0].value_from = inputs[| 0].value_from; } } diff --git a/scripts/node_registry/node_registry.gml b/scripts/node_registry/node_registry.gml index f1d851b22..f7afe0d30 100644 --- a/scripts/node_registry/node_registry.gml +++ b/scripts/node_registry/node_registry.gml @@ -195,10 +195,10 @@ function NodeObject(_name, _spr, _create, tags = []) constructor { var node = ds_list_create(); addNodeCatagory("Node", node); - addNodeObject(node, "Pin", s_node_pin, "Node_Pin", Node_create_Pin); - addNodeObject(node, "Frame", s_node_frame, "Node_Frame", Node_create_Frame); - addNodeObject(node, "Display text", s_node_frame, "Node_Display_Text", Node_create_Display_Text); - addNodeObject(node, "Condition", s_node_condition, "Node_Condition", Node_create_Condition); + addNodeObject(node, "Pin", s_node_pin, "Node_Pin", Node_create_Pin); + addNodeObject(node, "Frame", s_node_frame, "Node_Frame", Node_create_Frame); + addNodeObject(node, "Display text", s_node_text, "Node_Display_Text", Node_create_Display_Text); + addNodeObject(node, "Condition", s_node_condition, "Node_Condition", Node_create_Condition); NODE_CREATE_FUCTION[? "Node_Group"] = Node_create_Group; NODE_CREATE_FUCTION[? "Node_Iterate"] = Node_create_Iterate; diff --git a/scripts/node_value/node_value.gml b/scripts/node_value/node_value.gml index ff44b67af..f72cf72fd 100644 --- a/scripts/node_value/node_value.gml +++ b/scripts/node_value/node_value.gml @@ -14,6 +14,7 @@ enum VALUE_TYPE { curve = 6, text = 7, object = 8, + any = -1, } @@ -491,8 +492,8 @@ function NodeValue(_index, _name, _node, _connect, _type, _value, _tag = VALUE_T return false; } - if(_valueFrom == noone) { - removeFrom(); + if(_valueFrom == value_from) { + show_debug_message("setFrom : Repeated connection"); return false; } @@ -521,6 +522,15 @@ function NodeValue(_index, _name, _node, _connect, _type, _value, _tag = VALUE_T return false; } + if(value_from != noone) { + ds_list_remove(value_from.value_to, self); + } + + if(_valueFrom == noone) { + removeFrom(); + return false; + } + recordAction(ACTION_TYPE.junction_connect, self, value_from); value_from = _valueFrom; ds_list_add(_valueFrom.value_to, self); @@ -535,7 +545,7 @@ function NodeValue(_index, _name, _node, _connect, _type, _value, _tag = VALUE_T static removeFrom = function() { recordAction(ACTION_TYPE.junction_connect, self, value_from); if(value_from) - ds_list_delete(value_from.value_to, ds_list_find_index(value_from.value_to, self)); + ds_list_remove(value_from.value_to, self); value_from = noone; node.updateValueFrom(index); diff --git a/scripts/panel_collection/panel_collection.gml b/scripts/panel_collection/panel_collection.gml index 182a8a311..7df26292c 100644 --- a/scripts/panel_collection/panel_collection.gml +++ b/scripts/panel_collection/panel_collection.gml @@ -1,104 +1,53 @@ -function DirectoryObject(name, path) constructor { - self.name = name; - self.path = path; - - subDir = ds_list_create(); - open = false; - - static destroy = function() { - ds_list_destroy(subDir); - } - - static getSub = function() { - var _temp_name = ds_list_create(); - var folder = file_find_first(path + "/*", fa_directory); - while(folder != "") { - ds_list_add(_temp_name, folder); - folder = file_find_next(); - } - file_find_close(); - - ds_list_clear(subDir); - - ds_list_sort(_temp_name, true); - for( var i = 0; i < ds_list_size(_temp_name); i++ ) { - var file = _temp_name[| i]; - - if(directory_exists(path + "/" + file)) { - var _fol_path = path + "/" + file; - var fol = new DirectoryObject(file, _fol_path); - ds_list_add(subDir, fol); - } - } - - ds_list_destroy(_temp_name); - } - getSub(); - - static draw = function(_x, _y, _m, _w) { - var hg = 28; - var hh = 0; - - if(path == PANEL_COLLECTION.context.path) - draw_sprite_stretched_ext(s_ui_panel_bg, 0, _x, _y, _w, hg, c_ui_blue_ltgrey, 1); - - if(HOVER == PANEL_COLLECTION.panel && point_in_rectangle(_m[0], _m[1], 0, _y, _w, _y + hg - 1)) { - draw_sprite_stretched_ext(s_ui_panel_bg, 0, _x, _y, _w, hg, c_ui_blue_white, 1); - if(FOCUS == PANEL_COLLECTION.panel && mouse_check_button_pressed(mb_left)) { - open = !open; - - if(PANEL_COLLECTION.context = self) - PANEL_COLLECTION.setContext(COLLECTIONS); - else - PANEL_COLLECTION.setContext(self); - } - } - - draw_set_text(f_p0, fa_left, fa_center, c_white); - if(ds_list_empty(subDir)) { - draw_sprite_ext(s_folder_24, 0, _x + 16, _y + hg / 2 - 1, 1, 1, 0, c_ui_blue_dkgrey, 1); - } else { - draw_sprite_ext(s_folder_content_24, open, _x + 16, _y + hg / 2 - 1, 1, 1, 0, c_ui_blue_grey, 1); - } - draw_text(_x + 8 + 24, _y + hg / 2, name); - hh += hg; - _y += hg; - - if(open) { - for(var i = 0; i < ds_list_size(subDir); i++) { - var hg = subDir[| i].draw(_x + 16, _y, _m, _w - 16); - hh += hg; - _y += hg; - } - } - - return hh; - } -} - function Panel_Collection(_panel) : PanelContent(_panel) constructor { group_w = 180; content_w = w - 24 - group_w; - content_h = h - 32 - 16; + content_h = h - 40 - 16; min_w = group_w + 40; min_h = 40; context = COLLECTIONS; - content_list = ds_list_create(); + search_list = ds_list_create(); file_dragging = noone; _menu_node = noone; + + contentMenu = [ + [ "Replace with selected", function() { + saveCollection(_menu_node.path, false); + } ], + [ "Delete", function() { + file_delete(_menu_node.path); + refreshContext(); + } ], + ]; + + search_string = ""; + tb_search = new textBox(TEXTBOX_INPUT.text, function(str) { + search_string = string(str); + searchCollection(search_list, search_string); + }); + tb_search.auto_update = true; + + //function onFocusBegin() { + // TEXTBOX_ACTIVE = tb_search; + //} + //function onFocusEnd() { + // if(TEXTBOX_ACTIVE == tb_search) + // TEXTBOX_ACTIVE = noone; + // search_string = ""; + // tb_search._input_text = search_string; + //} + contentPane = new scrollPane(content_w, content_h, function(_y, _m) { draw_clear_alpha(c_ui_blue_black, 0); - if(content_list == -1) return 0; var grid_size = 64; var grid_width = 80; var grid_space = 12; - var nodes = content_list; + var nodes = search_string == ""? context.content : search_list; var node_count = ds_list_size(nodes); var col = max(1, floor(content_w / (grid_width + grid_space))); var row = ceil(node_count / col); @@ -125,20 +74,13 @@ function Panel_Collection(_panel) : PanelContent(_panel) constructor { if(mouse_check_button_pressed(mb_right)) { _menu_node = _node; var dia = dialogCall(o_dialog_menubox, mouse_mx + 8, mouse_my + 8); - dia.setMenu([ - [ "Replace with selected", function() { - saveCollection(_menu_node.path, false); - } ], - [ "Delete", function() { - file_delete(_menu_node.path); - } ], - ]); + dia.setMenu(contentMenu); } } if(_node.spr) { var ss = 32 / max(sprite_get_width(_node.spr), sprite_get_height(_node.spr)); - draw_sprite_ext(_node.spr, current_time / 60, _boxx + grid_size / 2, yy + grid_size / 2, ss, ss, 0, c_white, 1); + draw_sprite_ext(_node.spr, current_time * PREF_MAP[? "collection_preview_speed"] / 3000, _boxx + grid_size / 2, yy + grid_size / 2, ss, ss, 0, c_white, 1); } else { draw_sprite_ext(s_group_24, 0, _boxx + grid_size / 2, yy + grid_size / 2, 1, 1, 0, c_white, 1); } @@ -171,68 +113,19 @@ function Panel_Collection(_panel) : PanelContent(_panel) constructor { function onResize() { content_w = w - 24 - group_w; - content_h = h - 32 - 16; + content_h = h - 40 - 16; contentPane.resize(content_w, content_h); folderPane.resize(group_w - 8, content_h); } - function buildNode(_node) { - if(!_node) return noone; - return _node.build(0, 0); - } - function setContext(cont) { context = cont; - searchContent(); contentPane.scroll_y_raw = 0; contentPane.scroll_y_to = 0; } - function searchContent() { - if(content_list != -1 && ds_exists(content_list, ds_type_list)) { - for( var i = 0; i < ds_list_size(content_list); i++ ) { - var _f = content_list[| i]; - if(_f.spr && sprite_exists(_f.spr)) - sprite_delete(_f.spr); - delete _f; - } - ds_list_clear(content_list); - } else - content_list = ds_list_create(); - - var _path = context.path; - - var _temp_name = ds_list_create(); - var folder = file_find_first(_path + "/*", fa_directory); - while(folder != "") { - ds_list_add(_temp_name, folder); - folder = file_find_next(); - } - file_find_close(); - - ds_list_sort(_temp_name, true); - for( var i = 0; i < ds_list_size(_temp_name); i++ ) { - var file = _temp_name[| i]; - - if(filename_ext(file) == ".json" || filename_ext(file) == ".pxcc") { - var f = new FileContext(string_copy(file, 1, string_length(file) - 5), _path + "/" + file); - ds_list_add(content_list, f); - var icon_path = _path + "/" + string_copy(file, 1, string_length(file) - 5) + ".png"; - - if(file_exists(icon_path)) { - var _temp = sprite_add(icon_path, 0, false, false, 0, 0); - var ww = sprite_get_width(_temp); - var hh = sprite_get_height(_temp); - var amo = ww % hh == 0? ww / hh : 1; - sprite_delete(_temp); - - f.spr = sprite_add(icon_path, amo, false, false, 0, 0); - sprite_set_offset(f.spr, sprite_get_width(f.spr) / 2, sprite_get_height(f.spr) / 2); - } - } - } - - ds_list_destroy(_temp_name); + function refreshContext() { + context.getSub(); } function saveCollection(_path, save_surface = true) { @@ -248,68 +141,85 @@ function Panel_Collection(_panel) : PanelContent(_panel) constructor { function drawContent() { draw_clear_alpha(c_ui_blue_black, 0); - draw_sprite_stretched(s_ui_panel_bg, 1, group_w, 40, content_w + 16, content_h); + var content_y = 48; + draw_sprite_stretched(s_ui_panel_bg, 1, group_w, content_y, content_w + 16, content_h); contentPane.active = HOVER == panel; - contentPane.draw(group_w + 8, 40, mx - group_w - 8, my - 40); + contentPane.draw(group_w + 8, content_y, mx - group_w - 8, my - content_y); folderPane.active = HOVER == panel; - folderPane.draw(0, 40, mx, my - 40); + folderPane.draw(0, content_y, mx, my - content_y); draw_set_text(f_p0b, fa_left, fa_center, c_ui_blue_ltgrey); - draw_text(24, 20, "Collections"); + draw_text(24, content_y / 2, "Collections"); - var bx = w - 8 - 24; - var by = 8; + var bx = w - 16 - 24; + var by = 12; - if(context != COLLECTIONS) { - if(buttonInstant(s_button_hide, bx, by, 24, 24, [mx, my], FOCUS == panel, HOVER == panel, "Add selecting node as collection", s_add_24, 0, c_ui_lime) == 2) { - if(PANEL_INSPECTOR.inspecting != noone) { - var dia = dialogCall(o_dialog_file_name, mouse_mx + 8, mouse_my + 8); - data_path = context.path; - if(PANEL_INSPECTOR.inspecting) - dia.tb_name._input_text = PANEL_INSPECTOR.inspecting.name; - dia.onModify = function (txt) { - var _pre_name = data_path + "/" + txt; - var _name = _pre_name + ".pxcc"; - var _i = 0; - while(file_exists(_name)) { - _name = _pre_name + string(_i) + ".pxcc"; - _i++; - } - - saveCollection(_name); - }; - } - } - } else { - draw_sprite_ext(s_add_24, 0, bx + 12, by + 12, 1, 1, 0, c_ui_blue_dkgrey, 1); - } - bx -= 32; + tb_search.hover = HOVER == panel; + tb_search.focus = FOCUS == panel; + if(tb_search.focus) + TEXTBOX_ACTIVE = tb_search; + else if(TEXTBOX_ACTIVE == tb_search) + TEXTBOX_ACTIVE = noone; - if(buttonInstant(s_button_hide, bx, by, 24, 24, [mx, my], FOCUS == panel, HOVER == panel, "Add folder") == 2) { - var dia = dialogCall(o_dialog_file_name, mouse_mx + 8, mouse_my + 8); - dia.onModify = function (txt) { - directory_create(txt); - }; - dia.path = context.path + "/"; - } - draw_sprite_ext(s_folder_add, 0, bx + 12, by + 12, 1, 1, 0, c_ui_blue_grey, 1); - draw_sprite_ext(s_folder_add, 1, bx + 12, by + 12, 1, 1, 0, c_ui_lime, 1); - bx -= 32; - - if(buttonInstant(s_button_hide, bx, by, 24, 24, [mx, my], FOCUS == panel, HOVER == panel, "Open in file explorer", s_folder_24) == 2) { - var _realpath = context.path; - var _windir = environment_get_variable("WINDIR") + "\\explorer.exe"; + if(search_string == "") { + if(FOCUS == panel) + tb_search.editText(); - execute_shell(_windir, _realpath); - } - bx -= 32; + if(context != COLLECTIONS) { + if(buttonInstant(s_button_hide, bx, by, 24, 24, [mx, my], FOCUS == panel, HOVER == panel, "Add selecting node as collection", s_add_24, 0, c_ui_lime) == 2) { + if(PANEL_INSPECTOR.inspecting != noone) { + var dia = dialogCall(o_dialog_file_name, mouse_mx + 8, mouse_my + 8); + data_path = context.path; + if(PANEL_INSPECTOR.inspecting) + dia.tb_name._input_text = PANEL_INSPECTOR.inspecting.name; + dia.onModify = function (txt) { + var _pre_name = data_path + "/" + txt; + var _name = _pre_name + ".pxcc"; + var _i = 0; + while(file_exists(_name)) { + _name = _pre_name + string(_i) + ".pxcc"; + _i++; + } + + saveCollection(_name); + }; + } + } + } else { + draw_sprite_ext(s_add_24, 0, bx + 12, by + 12, 1, 1, 0, c_ui_blue_dkgrey, 1); + } + bx -= 32; - if(buttonInstant(s_button_hide, bx, by, 24, 24, [mx, my], FOCUS == panel, HOVER == panel, "Refresh", s_refresh_16) == 2) { - searchCollections(); - searchContent(); + if(buttonInstant(s_button_hide, bx, by, 24, 24, [mx, my], FOCUS == panel, HOVER == panel, "Add folder") == 2) { + var dia = dialogCall(o_dialog_file_name, mouse_mx + 8, mouse_my + 8); + dia.onModify = function (txt) { + directory_create(txt); + }; + dia.path = context.path + "\\"; + } + draw_sprite_ext(s_folder_add, 0, bx + 12, by + 12, 1, 1, 0, c_ui_blue_grey, 1); + draw_sprite_ext(s_folder_add, 1, bx + 12, by + 12, 1, 1, 0, c_ui_lime, 1); + bx -= 32; + + if(buttonInstant(s_button_hide, bx, by, 24, 24, [mx, my], FOCUS == panel, HOVER == panel, "Open in file explorer", s_folder_24) == 2) { + var _realpath = context.path; + var _windir = environment_get_variable("WINDIR") + "\\explorer.exe"; + execute_shell(_windir, _realpath); + } + bx -= 32; + + if(buttonInstant(s_button_hide, bx, by, 24, 24, [mx, my], FOCUS == panel, HOVER == panel, "Refresh", s_refresh_16) == 2) { + refreshContext(); + } + bx -= 32; + } else { + var tb_w = 200; + var tb_x = w - 10 - tb_w; + var tb_y = 10; + + tb_search.draw(tb_x, tb_y, tb_w, 32, search_string, [mx, my]); } - bx -= 32; if(file_dragging) { if(file_dragging.spr) { @@ -320,10 +230,7 @@ function Panel_Collection(_panel) : PanelContent(_panel) constructor { var app = noone; ds_list_clear(PANEL_GRAPH.nodes_select_list); - if(instanceof(file_dragging) == "FileContext") { - app = APPEND(file_dragging.path); - } else - app = buildNode(file_dragging); + app = APPEND(file_dragging.path); file_dragging = false; if(!is_struct(app) && ds_exists(app, ds_type_list)) { diff --git a/scripts/panel_data/panel_data.gml b/scripts/panel_data/panel_data.gml index 2fa9d10f4..a015ce4a4 100644 --- a/scripts/panel_data/panel_data.gml +++ b/scripts/panel_data/panel_data.gml @@ -275,9 +275,9 @@ function Panel(_parent, _x, _y, _w, _h) constructor { if(ds_list_empty(childs)) { if(point_in_rectangle(mouse_mx, mouse_my, x + 2, y + 2, x + w - 4, y + h - 4)) { HOVER = self; - if(mouse_check_button_pressed(mb_left)) FOCUS = self; - if(mouse_check_button_pressed(mb_right)) FOCUS = self; - if(mouse_check_button_pressed(mb_middle)) FOCUS = self; + if(mouse_check_button_pressed(mb_left)) setFocus(self); + if(mouse_check_button_pressed(mb_right)) setFocus(self); + if(mouse_check_button_pressed(mb_middle)) setFocus(self); if(FOCUS == self && content) FOCUS_STR = content.context_str; } @@ -400,6 +400,9 @@ function PanelContent(_panel) constructor { function onResize() {} + function onFocusBegin() {} + function onFocusEnd() {} + function onStepBegin() { mx = mouse_mx - x; my = mouse_my - y; @@ -414,4 +417,14 @@ function PanelContent(_panel) constructor { } function drawContent() {} +} + +function setFocus(target) { + if(FOCUS != noone && is_struct(FOCUS) && FOCUS.content) + FOCUS.content.onFocusEnd(); + + FOCUS = target; + + if(FOCUS != noone && is_struct(FOCUS) && FOCUS.content) + FOCUS.content.onFocusBegin(); } \ No newline at end of file diff --git a/scripts/panel_function/panel_function.gml b/scripts/panel_function/panel_function.gml index 27c27da25..d8bf06058 100644 --- a/scripts/panel_function/panel_function.gml +++ b/scripts/panel_function/panel_function.gml @@ -44,7 +44,7 @@ } break; case 1 : - var split_anim = split_ins[0].split_v(-240); + var split_anim = split_ins[0].split_v(-300); PANEL_ANIMATION = new Panel_Animation(split_anim[1]); var split_prev = split_anim[0].split_h(400); diff --git a/scripts/panel_graph/panel_graph.gml b/scripts/panel_graph/panel_graph.gml index 0b1c5d518..80e4b222e 100644 --- a/scripts/panel_graph/panel_graph.gml +++ b/scripts/panel_graph/panel_graph.gml @@ -572,6 +572,7 @@ function Panel_Graph(_panel) : PanelContent(_panel) constructor { function doGroup() { if(ds_list_empty(nodes_select_list) && node_focus != noone) ds_list_add(nodes_select_list, node_focus); + node_focus = noone; if(!ds_list_empty(nodes_select_list)) { var cx = 0; diff --git a/scripts/preferences/preferences.gml b/scripts/preferences/preferences.gml index 074a7d1d5..ba938df36 100644 --- a/scripts/preferences/preferences.gml +++ b/scripts/preferences/preferences.gml @@ -30,6 +30,8 @@ PREF_MAP[? "node_show_time"] = true; PREF_MAP[? "shape_separation_max"] = 32; + + PREF_MAP[? "collection_preview_speed"] = 60; #endregion #region hotkeys diff --git a/scripts/sample_projects/sample_projects.gml b/scripts/sample_projects/sample_projects.gml index 8d8e2b81b..2269c5a73 100644 --- a/scripts/sample_projects/sample_projects.gml +++ b/scripts/sample_projects/sample_projects.gml @@ -10,7 +10,7 @@ function LOAD_SAMPLE() { while(file != "") { if(filename_ext(file) == ".json" || filename_ext(file) == ".pxc") { var full_path = _l + "\\" + file; - var f = new FileContext(string_replace(filename_name(file), filename_ext(file), ""), full_path); + var f = new FileObject(string_replace(filename_name(file), filename_ext(file), ""), full_path); var icon_path = string_replace(full_path, filename_ext(full_path), ".png"); if(file_exists(icon_path)) { diff --git a/scripts/save_function/save_function.gml b/scripts/save_function/save_function.gml index a40752f71..9d67e89a4 100644 --- a/scripts/save_function/save_function.gml +++ b/scripts/save_function/save_function.gml @@ -148,7 +148,7 @@ function SAVE_COLLECTION(_node, _path, save_surface = true) { ds_map_destroy(_map); var pane = findPanel("Panel_Collection", PANEL_MAIN, noone); - if(pane) pane.searchContent(); + if(pane) pane.refreshContext(); } function SAVE_NODE(_list, _node, dx = 0, dy = 0, scale = false) {