From dce6a379194a80bac15b56247cf02e58ba40966d Mon Sep 17 00:00:00 2001 From: Tanasart Date: Sat, 20 Apr 2024 10:00:28 +0700 Subject: [PATCH] palette alpha fix --- .../o_dialog_palette.yy.backup0 | 442 +++ .../o_dialog_palette.yy.backup1 | 442 +++ .../node_canvas/node_canvas.gml.backup0 | 2 +- .../node_canvas/node_canvas.gml.backup1 | 2 +- .../node_functions/node_functions.gml.backup0 | 305 ++ .../node_functions/node_functions.gml.backup1 | 305 ++ .../node_keyframe/node_keyframe.gml.backup0 | 740 +++++ .../node_keyframe/node_keyframe.gml.backup1 | 740 +++++ .../node_palette/node_palette.gml.backup0 | 53 + .../node_palette/node_palette.gml.backup1 | 63 + .../scripts/node_value/node_value.gml.backup0 | 2773 +++++++++++------ .../scripts/node_value/node_value.gml.backup1 | 2773 +++++++++++------ .../string_decimal/string_decimal.gml.backup0 | 61 + .../string_decimal/string_decimal.gml.backup1 | 61 + .../string_hexadecimal.gml.backup0 | 62 + objects/o_dialog_palette/Create_0.gml | 4 +- .../node_color_adjust/node_color_adjust.gml | 2 +- .../node_color_remove/node_color_remove.gml | 2 +- .../node_color_replace/node_color_replace.gml | 4 +- scripts/node_dither/node_dither.gml | 2 +- .../node_gradient_palette.gml | 2 +- .../node_gradient_points.gml | 2 +- .../node_gradient_replace_color.gml | 4 +- scripts/node_keyframe/node_keyframe.gml | 6 +- scripts/node_palette/node_palette.gml | 2 +- .../node_palette_replace.gml | 6 +- .../node_palette_shift/node_palette_shift.gml | 2 +- .../node_palette_sort/node_palette_sort.gml | 2 +- scripts/node_posterize/node_posterize.gml | 2 +- scripts/node_region_fill/node_region_fill.gml | 2 +- .../node_surface_from_color.gml | 2 +- scripts/node_value/node_value.gml | 4 +- scripts/node_widget_test/node_widget_test.gml | 2 +- scripts/string_decimal/string_decimal.gml | 2 + .../string_hexadecimal/string_hexadecimal.gml | 2 +- 35 files changed, 6962 insertions(+), 1918 deletions(-) create mode 100644 #backups/objects/o_dialog_palette/o_dialog_palette.yy.backup0 create mode 100644 #backups/objects/o_dialog_palette/o_dialog_palette.yy.backup1 create mode 100644 #backups/scripts/node_functions/node_functions.gml.backup0 create mode 100644 #backups/scripts/node_functions/node_functions.gml.backup1 create mode 100644 #backups/scripts/node_keyframe/node_keyframe.gml.backup0 create mode 100644 #backups/scripts/node_keyframe/node_keyframe.gml.backup1 create mode 100644 #backups/scripts/node_palette/node_palette.gml.backup0 create mode 100644 #backups/scripts/node_palette/node_palette.gml.backup1 create mode 100644 #backups/scripts/string_decimal/string_decimal.gml.backup0 create mode 100644 #backups/scripts/string_decimal/string_decimal.gml.backup1 create mode 100644 #backups/scripts/string_hexadecimal/string_hexadecimal.gml.backup0 diff --git a/#backups/objects/o_dialog_palette/o_dialog_palette.yy.backup0 b/#backups/objects/o_dialog_palette/o_dialog_palette.yy.backup0 new file mode 100644 index 000000000..c0e85c2f9 --- /dev/null +++ b/#backups/objects/o_dialog_palette/o_dialog_palette.yy.backup0 @@ -0,0 +1,442 @@ +// 2024-04-20 10:00:16 +#event properties (no comments/etc. here are saved) +parent_index = _p_dialog_undo_block; +uses_physics = false; + +#event create init +event_inherited(); + +#region data + dialog_w = ui(812); + dialog_h = ui(440); + title_height = 52; + destroy_on_click_out = true; + + name = __txtx("palette_editor_title", "Palette editor"); + palette = 0; + + index_selecting = 0; + index_dragging = -1; + interactable = true; + + index_drag_x = 0; index_drag_x_to = 0; + index_drag_y = 0; index_drag_y_to = 0; + index_drag_w = 0; index_drag_w_to = 0; + index_drag_h = 0; index_drag_h_to = 0; + + setColor = function(color) { + if(index_selecting == -1 || palette == 0) return; + palette[index_selecting] = color; + + if(onApply == noone) return; + onApply(palette); + } + + onApply = noone; + selector = new colorSelector(setColor); + selector.dropper_close = false; + selector.discretize_pal = false; + + previous_palette = c_black; + + function setDefault(pal) { + setPalette(pal); + previous_palette = array_clone(pal); + } + + b_cancel = button(function() { + onApply(previous_palette); + instance_destroy(); + }).setIcon(THEME.undo, 0, COLORS._main_icon) + .setTooltip(__txtx("dialog_revert_and_exit", "Revert and exit")); + + b_apply = button(function() { + onApply(palette); + instance_destroy(); + }).setIcon(THEME.accept, 0, COLORS._main_icon_dark); + + function setPalette(pal) { + palette = pal; + index_selecting = 0; + if(array_length(palette) > 0) + selector.setColor(palette[0]); + } +#endregion + +#region presets + hovering_name = ""; + + sp_preset_w = ui(240 - 32 - 16); + sp_presets = new scrollPane(sp_preset_w, dialog_h - ui(62), function(_y, _m) { + var ww = sp_preset_w - ui(40); + var hh = ui(32); + var yy = _y + ui(8); + var hg = ui(52); + draw_clear_alpha(COLORS.panel_bg_clear, 0); + + for(var i = -1; i < array_length(PALETTES); i++) { + var pal = i == -1? { + name: "project", + palette: PROJECT.attributes.palette, + path: "" + } : PALETTES[i]; + var isHover = sHOVER && sp_presets.hover && point_in_rectangle(_m[0], _m[1], ui(4), yy, ui(4) + sp_preset_w - ui(16), yy + hg); + draw_sprite_stretched(THEME.ui_panel_bg, 3, ui(4), yy, sp_preset_w - ui(16), hg); + if(isHover) + draw_sprite_stretched_ext(THEME.node_active, 1, ui(4), yy, sp_preset_w - ui(16), hg, COLORS._main_accent, 1); + + draw_set_text(f_p2, fa_left, fa_top, COLORS._main_text_sub); + draw_text(ui(16), yy + ui(8), pal.name); + drawPalette(pal.palette, ui(16), yy + ui(28), ww, ui(16)); + + if(isHover) { + if(mouse_press(mb_left, interactable && sFOCUS)) { + palette = array_clone(pal.palette); + onApply(palette); + + index_selecting = 0; + selector.setColor(palette[index_selecting], false); + } + + if(i >= 0 && mouse_press(mb_right, interactable && sFOCUS)) { + hovering = pal; + + menuCall("palette_window_preset_menu",,, [ + menuItem(__txtx("palette_editor_set_default", "Set as default"), function() { + DEF_PALETTE = array_clone(hovering.palette); + }), + menuItem(__txtx("palette_editor_delete", "Delete palette"), function() { + file_delete(hovering.path); + __initPalette(); + }), + ]); + } + } + + yy += hg + ui(4); + hh += hg + ui(4); + } + + return hh; + }); + + sp_presets.always_scroll = true; +#endregion + +#region tools + function sortPalette(sortFunc) { + array_sort(palette, sortFunc); + onApply(palette); + } +#endregion + +#region action + onResize = function() { + sp_presets.resize(sp_preset_w, dialog_h - ui(62)); + } + + function checkMouse() {} +#endregion + +#event step_begin init +if !ready exit; + +#region destroy + selector.interactable = interactable; + if(!selector.dropper_active) { + if(sHOVER && !point_in_rectangle(mouse_mx, mouse_my, dialog_x, dialog_y, dialog_x + dialog_w, dialog_y + dialog_h)) { + if(destroy_on_click_out && mouse_press(mb_left)) + instance_destroy(self); + } + doDrag(); + } + + if(sFOCUS && WIDGET_CURRENT == noone) { + if(keyboard_check_pressed(vk_enter)) { + onApply(palette); + instance_destroy(); + } + + if(keyboard_check_pressed(vk_escape)) { + onApply(previous_palette); + instance_destroy(); + } + } +#endregion + +#region resize + if(_dialog_h != dialog_h || _dialog_w != dialog_w) { + _dialog_h = dialog_h; + _dialog_w = dialog_w; + + if(onResize != -1) onResize(); + } +#endregion + +#event draw_gui init +if !ready exit; +if palette == 0 exit; + +#region dropper + selector.interactable = interactable; + if(selector.dropper_active) { + selector.drawDropper(self); + exit; + } +#endregion + +#region base UI + var presets_x = dialog_x; + var presets_w = ui(240); + + var content_x = dialog_x + presets_w + ui(16); + var content_w = dialog_w - presets_w - ui(16); + + var p = DIALOG_PAD; + var p2 = DIALOG_PAD * 2; + + draw_sprite_stretched(THEME.dialog_bg, 0, presets_x - p, dialog_y - p, presets_w + p2, dialog_h + p2); + if(sFOCUS) draw_sprite_stretched_ext(THEME.dialog_active, 0, presets_x - p, dialog_y - p, presets_w + p2, dialog_h + p2, COLORS._main_accent, 1); + + draw_sprite_stretched(THEME.dialog_bg, 0, content_x - p, dialog_y - p, content_w + p2, dialog_h + p2); + if(sFOCUS) draw_sprite_stretched_ext(THEME.dialog_active, 0, content_x - p, dialog_y - p, content_w + p2, dialog_h + p2, COLORS._main_accent, 1); + + draw_set_text(f_p0, fa_left, fa_top, COLORS._main_text); + draw_text(presets_x + ui(24), dialog_y + ui(16), __txt("Presets")); + draw_text(content_x + (!interactable * ui(32)) + ui(24), dialog_y + ui(16), name); + if(!interactable) + draw_sprite_ui(THEME.lock, 0, content_x + ui(24 + 12), dialog_y + ui(16 + 12),,,, COLORS._main_icon); +#endregion + +#region presets + draw_sprite_stretched(THEME.ui_panel_bg, 1, presets_x + ui(16), dialog_y + ui(44), ui(240 - 32), dialog_h - ui(60)); + + sp_presets.setFocusHover(sFOCUS, sHOVER); + sp_presets.draw(presets_x + ui(24), dialog_y + ui(44)); + + var bx = presets_x + presets_w - ui(44); + var by = dialog_y + ui(12); + var bs = ui(28); + + if(buttonInstant(THEME.button_hide, bx, by, bs, bs, mouse_ui, sFOCUS, sHOVER, __txtx("add_preset", "Add to preset"), THEME.add_20) == 2) { + var dia = dialogCall(o_dialog_file_name, mouse_mx + ui(8), mouse_my + ui(8)); + dia.onModify = function (txt) { + var file = file_text_open_write(txt + ".hex"); + for(var i = 0; i < array_length(palette); i++) { + var cc = palette[i]; + var r = number_to_hex(color_get_red(cc)); + var g = number_to_hex(color_get_green(cc)); + var b = number_to_hex(color_get_blue(cc)); + var a = number_to_hex(color_get_alpha(cc)); + + file_text_write_string(file, $"{r}{g}{b}{a}\n"); + } + file_text_close(file); + __initPalette(); + }; + dia.path = DIRECTORY + "Palettes/" + } + bx -= ui(32); + + if(buttonInstant(THEME.button_hide, bx, by, bs, bs, mouse_ui, sFOCUS, sHOVER, __txt("Refresh"), THEME.refresh_20) == 2) + __initPalette(); + bx -= ui(32); + + if(buttonInstant(THEME.button_hide, bx, by, bs, bs, mouse_ui, sFOCUS, sHOVER, __txtx("color_selector_open_palette", "Open palette folder"), THEME.path_open_20) == 2) { + var _realpath = DIRECTORY + "Palettes"; + shellOpenExplorer(_realpath) + } + draw_sprite_ui_uniform(THEME.path_open_20, 1, bx + bs / 2, by + bs / 2, 1, c_white); + bx -= ui(32); +#endregion + +#region palette + var pl_x = content_x + ui(60); + var pl_y = dialog_y + ui(54); + var pl_w = content_w - ui(154); + var pl_h = ui(24); + + var max_col = 8; + var col = min(array_length(palette), max_col); + var row = ceil(array_length(palette) / col); + var ww = round(pl_w / col); + var hh = (pl_h + ui(6)) * row; + dialog_h = ui(408) + hh; + + draw_sprite_stretched(THEME.textbox, 3, pl_x - ui(6), pl_y - ui(6), pl_w + ui(12), hh + ui(6)); + draw_sprite_stretched(THEME.textbox, 0, pl_x - ui(6), pl_y - ui(6), pl_w + ui(12), hh + ui(6)); + + #region tools + var bx = content_x + content_w - ui(50); + var by = dialog_y + ui(16); + + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, __txtx("palette_editor_sort", "Sort color"), THEME.sort) == 2) { + menuCall("palette_window_sort_menu", bx + ui(32), by, [ + menuItem(__txtx("palette_editor_sort_brighter", "Brighter"), function() { sortPalette(__sortBright); }), + menuItem(__txtx("palette_editor_sort_darker", "Darker"), function() { sortPalette(__sortDark); }), + -1, + menuItem(__txtx("palette_editor_sort_hue", "Hue"), function() { sortPalette(__sortHue); }), + menuItem(__txtx("palette_editor_sort_sat", "Saturation"), function() { sortPalette(__sortSat); }), + menuItem(__txtx("palette_editor_sort_val", "Value"), function() { sortPalette(__sortVal); }), + ],, palette); + } + bx -= ui(32); + + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, __txtx("palette_editor_reverse", "Reverse palette"), THEME.reverse) == 2) { + palette = array_reverse(palette); + onApply(palette); + } + bx -= ui(32); + #endregion + + var hover = -1, hvx, hvy; + var _pd = ui(5); + + for(var i = 0; i < row; i++) + for(var j = 0; j < col; j++) { + var index = i * col + j; + if(index >= array_length(palette)) break; + + var _p = palette[index]; + var _pa = _color_get_alpha(_p); + var _kx = pl_x + j * ww; + var _ky = pl_y + i * (pl_h + ui(6)); + + var _px = _kx + ui(2); + var _py = _ky; + var _pw = ww - ui(4); + var _ph = pl_h; + + if(index == index_dragging) { + index_drag_x_to = _px; + index_drag_y_to = _py; + index_drag_w_to = _pw; + index_drag_h_to = _ph; + continue; + } + + if(_pa < 1) { + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py, _pw, _ph - ui(8), _p, 1); + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py + _ph - ui(6), _pw, ui(6), c_black, 1); + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py + _ph - ui(6), _pw * _pa, ui(6), c_white, 1); + } else + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py, _pw, _ph, _p, 1); + + if(index == index_selecting) + draw_sprite_stretched_ext(THEME.palette_selecting, 0, _px - _pd, _py - _pd, _pw + _pd * 2, _ph + _pd * 2, c_white, 1); + + if(sHOVER && point_in_rectangle(mouse_mx, mouse_my, _kx, _ky, _kx + ww, _ky + pl_h)) { + hover = index; + hvx = _kx; + hvy = _ky; + } + } + + if(index_dragging > -1) { + index_drag_x = index_drag_x == 0? index_drag_x_to : lerp_float(index_drag_x, index_drag_x_to, 5); + index_drag_y = index_drag_y == 0? index_drag_y_to : lerp_float(index_drag_y, index_drag_y_to, 5); + index_drag_w = index_drag_w == 0? index_drag_w_to : lerp_float(index_drag_w, index_drag_w_to, 5); + index_drag_h = index_drag_h == 0? index_drag_h_to : lerp_float(index_drag_h, index_drag_h_to, 5); + + _px = index_drag_x; + _py = index_drag_y; + _pw = index_drag_w; + _ph = index_drag_h; + _p = palette[index_dragging]; + _pa = _color_get_alpha(_p); + + if(_pa < 1) { + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py, _pw, _ph - ui(8), _p, 1); + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py + _ph - ui(6), _pw, ui(6), c_black, 1); + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py + _ph - ui(6), _pw * _pa, ui(6), c_white, 1); + } else + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py, _pw, _ph, _p, 1); + draw_sprite_stretched_ext(THEME.palette_selecting, 0, _px - _pd, _py - _pd, _pw + _pd * 2, _ph + _pd * 2, c_white, 1); + + if(hover > -1 && hover != index_dragging) { + draw_set_color(COLORS.dialog_palette_divider); + var sx = hvx; + if(hover >= index_dragging) sx += ww; + + var tt = palette[index_dragging]; + + array_delete(palette, index_dragging, 1); + array_insert(palette, hover, tt); + index_selecting = hover; + index_dragging = hover; + + onApply(palette); + } + + if(mouse_release(mb_left)) + index_dragging = -1; + } else { + index_drag_x = 0; + index_drag_y = 0; + index_drag_w = 0; + index_drag_h = 0; + } + + if(mouse_press(mb_left, sFOCUS) && hover > -1) { + index_selecting = hover; + if(interactable) + index_dragging = hover; + selector.setColor(palette[hover]); + } + + var bx = content_x + content_w - ui(50); + var by = pl_y - ui(2); + + if(array_length(palette) > 1) { + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, "", THEME.minus) == 2) { + array_delete(palette, index_selecting, 1); + index_selecting = clamp(index_selecting - 1, 0, array_length(palette) - 1); + onApply(palette); + } + } else { + draw_sprite_ui_uniform(THEME.minus, 0, bx + ui(14), by + ui(14), 1, COLORS._main_icon, 0.5); + } + + bx -= ui(32); + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, "", THEME.add) == 2) { + index_selecting = array_length(palette); + palette[array_length(palette)] = c_black; + onApply(palette); + } + + bx = content_x + ui(18); + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, __txtx("palette_editor_load", "Load palette file") + " (.hex)", THEME.file) == 2) { + var path = get_open_filename("HEX palette|*.hex", ""); + key_release(); + + if(isPaletteFile(path)) { + palette = loadPalette(path); + onApply(palette); + } + } + draw_sprite_ui_uniform(THEME.file, 0, bx + ui(14), by + ui(14), 1, COLORS._main_icon); +#endregion + +#region selector + var col_x = content_x + ui(20); + var col_y = dialog_y + ui(70) + hh; + + selector.draw(col_x, col_y, sFOCUS, sHOVER); +#endregion + +#region controls + var bx = content_x + content_w - ui(36); + var by = dialog_y + dialog_h - ui(36); + + b_apply.register(); + b_apply.setFocusHover(sFOCUS, sHOVER); + b_apply.draw(bx - ui(18), by - ui(18), ui(36), ui(36), mouse_ui, THEME.button_lime); + + bx -= ui(48); + b_cancel.register(); + b_cancel.setFocusHover(sFOCUS, sHOVER); + b_cancel.draw(bx - ui(18), by - ui(18), ui(36), ui(36), mouse_ui, THEME.button_hide); +#endregion + +#event draw_gui_end +selector.colorPicker(); \ No newline at end of file diff --git a/#backups/objects/o_dialog_palette/o_dialog_palette.yy.backup1 b/#backups/objects/o_dialog_palette/o_dialog_palette.yy.backup1 new file mode 100644 index 000000000..ebe13a253 --- /dev/null +++ b/#backups/objects/o_dialog_palette/o_dialog_palette.yy.backup1 @@ -0,0 +1,442 @@ +// 2024-04-20 09:59:48 +#event properties (no comments/etc. here are saved) +parent_index = _p_dialog_undo_block; +uses_physics = false; + +#event create init +event_inherited(); + +#region data + dialog_w = ui(812); + dialog_h = ui(440); + title_height = 52; + destroy_on_click_out = true; + + name = __txtx("palette_editor_title", "Palette editor"); + palette = 0; + + index_selecting = 0; + index_dragging = -1; + interactable = true; + + index_drag_x = 0; index_drag_x_to = 0; + index_drag_y = 0; index_drag_y_to = 0; + index_drag_w = 0; index_drag_w_to = 0; + index_drag_h = 0; index_drag_h_to = 0; + + setColor = function(color) { + if(index_selecting == -1 || palette == 0) return; + palette[index_selecting] = color; + + if(onApply == noone) return; + onApply(palette); + } + + onApply = noone; + selector = new colorSelector(setColor); + selector.dropper_close = false; + selector.discretize_pal = false; + + previous_palette = c_black; + + function setDefault(pal) { + setPalette(pal); + previous_palette = array_clone(pal); + } + + b_cancel = button(function() { + onApply(previous_palette); + instance_destroy(); + }).setIcon(THEME.undo, 0, COLORS._main_icon) + .setTooltip(__txtx("dialog_revert_and_exit", "Revert and exit")); + + b_apply = button(function() { + onApply(palette); + instance_destroy(); + }).setIcon(THEME.accept, 0, COLORS._main_icon_dark); + + function setPalette(pal) { + palette = pal; + index_selecting = 0; + if(array_length(palette) > 0) + selector.setColor(palette[0]); + } +#endregion + +#region presets + hovering_name = ""; + + sp_preset_w = ui(240 - 32 - 16); + sp_presets = new scrollPane(sp_preset_w, dialog_h - ui(62), function(_y, _m) { + var ww = sp_preset_w - ui(40); + var hh = ui(32); + var yy = _y + ui(8); + var hg = ui(52); + draw_clear_alpha(COLORS.panel_bg_clear, 0); + + for(var i = -1; i < array_length(PALETTES); i++) { + var pal = i == -1? { + name: "project", + palette: PROJECT.attributes.palette, + path: "" + } : PALETTES[i]; + var isHover = sHOVER && sp_presets.hover && point_in_rectangle(_m[0], _m[1], ui(4), yy, ui(4) + sp_preset_w - ui(16), yy + hg); + draw_sprite_stretched(THEME.ui_panel_bg, 3, ui(4), yy, sp_preset_w - ui(16), hg); + if(isHover) + draw_sprite_stretched_ext(THEME.node_active, 1, ui(4), yy, sp_preset_w - ui(16), hg, COLORS._main_accent, 1); + + draw_set_text(f_p2, fa_left, fa_top, COLORS._main_text_sub); + draw_text(ui(16), yy + ui(8), pal.name); + drawPalette(pal.palette, ui(16), yy + ui(28), ww, ui(16)); + + if(isHover) { + if(mouse_press(mb_left, interactable && sFOCUS)) { + palette = array_clone(pal.palette); + onApply(palette); + + index_selecting = 0; + selector.setColor(palette[index_selecting], false); + } + + if(i >= 0 && mouse_press(mb_right, interactable && sFOCUS)) { + hovering = pal; + + menuCall("palette_window_preset_menu",,, [ + menuItem(__txtx("palette_editor_set_default", "Set as default"), function() { + DEF_PALETTE = array_clone(hovering.palette); + }), + menuItem(__txtx("palette_editor_delete", "Delete palette"), function() { + file_delete(hovering.path); + __initPalette(); + }), + ]); + } + } + + yy += hg + ui(4); + hh += hg + ui(4); + } + + return hh; + }); + + sp_presets.always_scroll = true; +#endregion + +#region tools + function sortPalette(sortFunc) { + array_sort(palette, sortFunc); + onApply(palette); + } +#endregion + +#region action + onResize = function() { + sp_presets.resize(sp_preset_w, dialog_h - ui(62)); + } + + function checkMouse() {} +#endregion + +#event step_begin init +if !ready exit; + +#region destroy + selector.interactable = interactable; + if(!selector.dropper_active) { + if(sHOVER && !point_in_rectangle(mouse_mx, mouse_my, dialog_x, dialog_y, dialog_x + dialog_w, dialog_y + dialog_h)) { + if(destroy_on_click_out && mouse_press(mb_left)) + instance_destroy(self); + } + doDrag(); + } + + if(sFOCUS && WIDGET_CURRENT == noone) { + if(keyboard_check_pressed(vk_enter)) { + onApply(palette); + instance_destroy(); + } + + if(keyboard_check_pressed(vk_escape)) { + onApply(previous_palette); + instance_destroy(); + } + } +#endregion + +#region resize + if(_dialog_h != dialog_h || _dialog_w != dialog_w) { + _dialog_h = dialog_h; + _dialog_w = dialog_w; + + if(onResize != -1) onResize(); + } +#endregion + +#event draw_gui init +if !ready exit; +if palette == 0 exit; + +#region dropper + selector.interactable = interactable; + if(selector.dropper_active) { + selector.drawDropper(self); + exit; + } +#endregion + +#region base UI + var presets_x = dialog_x; + var presets_w = ui(240); + + var content_x = dialog_x + presets_w + ui(16); + var content_w = dialog_w - presets_w - ui(16); + + var p = DIALOG_PAD; + var p2 = DIALOG_PAD * 2; + + draw_sprite_stretched(THEME.dialog_bg, 0, presets_x - p, dialog_y - p, presets_w + p2, dialog_h + p2); + if(sFOCUS) draw_sprite_stretched_ext(THEME.dialog_active, 0, presets_x - p, dialog_y - p, presets_w + p2, dialog_h + p2, COLORS._main_accent, 1); + + draw_sprite_stretched(THEME.dialog_bg, 0, content_x - p, dialog_y - p, content_w + p2, dialog_h + p2); + if(sFOCUS) draw_sprite_stretched_ext(THEME.dialog_active, 0, content_x - p, dialog_y - p, content_w + p2, dialog_h + p2, COLORS._main_accent, 1); + + draw_set_text(f_p0, fa_left, fa_top, COLORS._main_text); + draw_text(presets_x + ui(24), dialog_y + ui(16), __txt("Presets")); + draw_text(content_x + (!interactable * ui(32)) + ui(24), dialog_y + ui(16), name); + if(!interactable) + draw_sprite_ui(THEME.lock, 0, content_x + ui(24 + 12), dialog_y + ui(16 + 12),,,, COLORS._main_icon); +#endregion + +#region presets + draw_sprite_stretched(THEME.ui_panel_bg, 1, presets_x + ui(16), dialog_y + ui(44), ui(240 - 32), dialog_h - ui(60)); + + sp_presets.setFocusHover(sFOCUS, sHOVER); + sp_presets.draw(presets_x + ui(24), dialog_y + ui(44)); + + var bx = presets_x + presets_w - ui(44); + var by = dialog_y + ui(12); + var bs = ui(28); + + if(buttonInstant(THEME.button_hide, bx, by, bs, bs, mouse_ui, sFOCUS, sHOVER, __txtx("add_preset", "Add to preset"), THEME.add_20) == 2) { + var dia = dialogCall(o_dialog_file_name, mouse_mx + ui(8), mouse_my + ui(8)); + dia.onModify = function (txt) { + var file = file_text_open_write(txt + ".hex"); + for(var i = 0; i < array_length(palette); i++) { + var cc = palette[i]; + var r = number_to_hex(color_get_red(cc)); + var g = number_to_hex(color_get_green(cc)); + var b = number_to_hex(color_get_blue(cc)); + var a = number_to_hex(color_get_alpha(cc)); + + file_text_write_string(file, $"{r}{g}{b}{a}\n"); + } + file_text_close(file); + __initPalette(); + }; + dia.path = DIRECTORY + "Palettes/" + } + bx -= ui(32); + + if(buttonInstant(THEME.button_hide, bx, by, bs, bs, mouse_ui, sFOCUS, sHOVER, __txt("Refresh"), THEME.refresh_20) == 2) + __initPalette(); + bx -= ui(32); + + if(buttonInstant(THEME.button_hide, bx, by, bs, bs, mouse_ui, sFOCUS, sHOVER, __txtx("color_selector_open_palette", "Open palette folder"), THEME.path_open_20) == 2) { + var _realpath = DIRECTORY + "Palettes"; + shellOpenExplorer(_realpath) + } + draw_sprite_ui_uniform(THEME.path_open_20, 1, bx + bs / 2, by + bs / 2, 1, c_white); + bx -= ui(32); +#endregion + +#region palette + var pl_x = content_x + ui(60); + var pl_y = dialog_y + ui(54); + var pl_w = content_w - ui(154); + var pl_h = ui(24); + + var max_col = 8; + var col = min(array_length(palette), max_col); + var row = ceil(array_length(palette) / col); + var ww = round(pl_w / col); + var hh = (pl_h + ui(6)) * row; + dialog_h = ui(408) + hh; + + draw_sprite_stretched(THEME.textbox, 3, pl_x - ui(6), pl_y - ui(6), pl_w + ui(12), hh + ui(6)); + draw_sprite_stretched(THEME.textbox, 0, pl_x - ui(6), pl_y - ui(6), pl_w + ui(12), hh + ui(6)); + + #region tools + var bx = content_x + content_w - ui(50); + var by = dialog_y + ui(16); + + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, __txtx("palette_editor_sort", "Sort color"), THEME.sort) == 2) { + menuCall("palette_window_sort_menu", bx + ui(32), by, [ + menuItem(__txtx("palette_editor_sort_brighter", "Brighter"), function() { sortPalette(__sortBright); }), + menuItem(__txtx("palette_editor_sort_darker", "Darker"), function() { sortPalette(__sortDark); }), + -1, + menuItem(__txtx("palette_editor_sort_hue", "Hue"), function() { sortPalette(__sortHue); }), + menuItem(__txtx("palette_editor_sort_sat", "Saturation"), function() { sortPalette(__sortSat); }), + menuItem(__txtx("palette_editor_sort_val", "Value"), function() { sortPalette(__sortVal); }), + ],, palette); + } + bx -= ui(32); + + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, __txtx("palette_editor_reverse", "Reverse palette"), THEME.reverse) == 2) { + palette = array_reverse(palette); + onApply(palette); + } + bx -= ui(32); + #endregion + + var hover = -1, hvx, hvy; + var _pd = ui(5); + + for(var i = 0; i < row; i++) + for(var j = 0; j < col; j++) { + var index = i * col + j; + if(index >= array_length(palette)) break; + + var _p = palette[index]; + var _pa = _color_get_alpha(_p); + var _kx = pl_x + j * ww; + var _ky = pl_y + i * (pl_h + ui(6)); + + var _px = _kx + ui(2); + var _py = _ky; + var _pw = ww - ui(4); + var _ph = pl_h; + + if(index == index_dragging) { + index_drag_x_to = _px; + index_drag_y_to = _py; + index_drag_w_to = _pw; + index_drag_h_to = _ph; + continue; + } + + if(_pa < 1) { + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py, _pw, _ph - ui(8), _p, 1); + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py + _ph - ui(6), _pw, ui(6), c_black, 1); + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py + _ph - ui(6), _pw * _pa, ui(6), c_white, 1); + } else + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py, _pw, _ph, _p, 1); + + if(index == index_selecting) + draw_sprite_stretched_ext(THEME.palette_selecting, 0, _px - _pd, _py - _pd, _pw + _pd * 2, _ph + _pd * 2, c_white, 1); + + if(sHOVER && point_in_rectangle(mouse_mx, mouse_my, _kx, _ky, _kx + ww, _ky + pl_h)) { + hover = index; + hvx = _kx; + hvy = _ky; + } + } + + if(index_dragging > -1) { + index_drag_x = index_drag_x == 0? index_drag_x_to : lerp_float(index_drag_x, index_drag_x_to, 5); + index_drag_y = index_drag_y == 0? index_drag_y_to : lerp_float(index_drag_y, index_drag_y_to, 5); + index_drag_w = index_drag_w == 0? index_drag_w_to : lerp_float(index_drag_w, index_drag_w_to, 5); + index_drag_h = index_drag_h == 0? index_drag_h_to : lerp_float(index_drag_h, index_drag_h_to, 5); + + _px = index_drag_x; + _py = index_drag_y; + _pw = index_drag_w; + _ph = index_drag_h; + _p = palette[index_dragging]; + _pa = _color_get_alpha(_p); + + if(_pa < 1) { + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py, _pw, _ph - ui(8), _p, 1); + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py + _ph - ui(6), _pw, ui(6), c_black, 1); + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py + _ph - ui(6), _pw * _pa, ui(6), c_white, 1); + } else + draw_sprite_stretched_ext(THEME.palette_mask, 1, _px, _py, _pw, _ph, _p, 1); + draw_sprite_stretched_ext(THEME.palette_selecting, 0, _px - _pd, _py - _pd, _pw + _pd * 2, _ph + _pd * 2, c_white, 1); + + if(hover > -1 && hover != index_dragging) { + draw_set_color(COLORS.dialog_palette_divider); + var sx = hvx; + if(hover >= index_dragging) sx += ww; + + var tt = palette[index_dragging]; + + array_delete(palette, index_dragging, 1); + array_insert(palette, hover, tt); + index_selecting = hover; + index_dragging = hover; + + onApply(palette); + } + + if(mouse_release(mb_left)) + index_dragging = -1; + } else { + index_drag_x = 0; + index_drag_y = 0; + index_drag_w = 0; + index_drag_h = 0; + } + + if(mouse_press(mb_left, sFOCUS) && hover > -1) { + index_selecting = hover; + if(interactable) + index_dragging = hover; + selector.setColor(palette[hover]); + } + + var bx = content_x + content_w - ui(50); + var by = pl_y - ui(2); + + if(array_length(palette) > 1) { + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, "", THEME.minus) == 2) { + array_delete(palette, index_selecting, 1); + index_selecting = clamp(index_selecting - 1, 0, array_length(palette) - 1); + onApply(palette); + } + } else { + draw_sprite_ui_uniform(THEME.minus, 0, bx + ui(14), by + ui(14), 1, COLORS._main_icon, 0.5); + } + + bx -= ui(32); + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, "", THEME.add) == 2) { + index_selecting = array_length(palette); + palette[array_length(palette)] = c_black; + onApply(palette); + } + + bx = content_x + ui(18); + if(buttonInstant(THEME.button_hide, bx, by, ui(28), ui(28), mouse_ui, interactable && sFOCUS, sHOVER, __txtx("palette_editor_load", "Load palette file") + " (.hex)", THEME.file) == 2) { + var path = get_open_filename("HEX palette|*.hex", ""); + key_release(); + + if(isPaletteFile(path)) { + palette = loadPalette(path); + onApply(palette); + } + } + draw_sprite_ui_uniform(THEME.file, 0, bx + ui(14), by + ui(14), 1, COLORS._main_icon); +#endregion + +#region selector + var col_x = content_x + ui(20); + var col_y = dialog_y + ui(70) + hh; + + selector.draw(col_x, col_y, sFOCUS, sHOVER); +#endregion + +#region controls + var bx = content_x + content_w - ui(36); + var by = dialog_y + dialog_h - ui(36); + + b_apply.register(); + b_apply.setFocusHover(sFOCUS, sHOVER); + b_apply.draw(bx - ui(18), by - ui(18), ui(36), ui(36), mouse_ui, THEME.button_lime); + + bx -= ui(48); + b_cancel.register(); + b_cancel.setFocusHover(sFOCUS, sHOVER); + b_cancel.draw(bx - ui(18), by - ui(18), ui(36), ui(36), mouse_ui, THEME.button_hide); +#endregion + +#event draw_gui_end +selector.colorPicker(); \ No newline at end of file diff --git a/#backups/scripts/node_canvas/node_canvas.gml.backup0 b/#backups/scripts/node_canvas/node_canvas.gml.backup0 index daf6e9a80..f43e302db 100644 --- a/#backups/scripts/node_canvas/node_canvas.gml.backup0 +++ b/#backups/scripts/node_canvas/node_canvas.gml.backup0 @@ -1,4 +1,4 @@ -// 2024-04-19 07:55:21 +// 2024-04-20 08:26:31 function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { name = "Canvas"; color = COLORS.node_blend_canvas; diff --git a/#backups/scripts/node_canvas/node_canvas.gml.backup1 b/#backups/scripts/node_canvas/node_canvas.gml.backup1 index cb59628a2..106e7849d 100644 --- a/#backups/scripts/node_canvas/node_canvas.gml.backup1 +++ b/#backups/scripts/node_canvas/node_canvas.gml.backup1 @@ -1,4 +1,4 @@ -// 2024-04-18 18:31:59 +// 2024-04-20 08:25:39 function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { name = "Canvas"; color = COLORS.node_blend_canvas; diff --git a/#backups/scripts/node_functions/node_functions.gml.backup0 b/#backups/scripts/node_functions/node_functions.gml.backup0 new file mode 100644 index 000000000..12e6f777e --- /dev/null +++ b/#backups/scripts/node_functions/node_functions.gml.backup0 @@ -0,0 +1,305 @@ +// 2024-04-20 08:21:26 +#macro DEF_SURF_W PROJECT.attributes.surface_dimension[0] +#macro DEF_SURF_H PROJECT.attributes.surface_dimension[1] +#macro DEF_SURF PROJECT.attributes.surface_dimension + +#macro DEF_PALETTE PROJECT.attributes.palette + +#region + function node_draw_transform_init() { + drag_type = -1; + dragging_sx = 0; + dragging_sy = 0; + dragging_mx = 0; + dragging_my = 0; + rot_anc_x = 0; + rot_anc_y = 0; + } + + function node_draw_transform_box(active, _x, _y, _s, _mx, _my, _snx, _sny, _posInd, _rotInd, _scaInd, _scaUnit = false) { + var _pos = getInputData(_posInd); + var _rot = getInputData(_rotInd); + var _sca = getInputData(_scaInd); + + if(drag_type > -1) { + if(drag_type == 0) { + var _dx = (_mx - dragging_mx) / _s; + var _dy = (_my - dragging_my) / _s; + + if(key_mod_press(SHIFT)) { + if(abs(_dx) > abs(_dy) + ui(16)) + _dy = 0; + else if(abs(_dy) > abs(_dx) + ui(16)) + _dx = 0; + else { + _dx = max(_dx, _dy); + _dy = _dx; + } + } + + _pos[0] = value_snap(dragging_sx + _dx, _snx); + _pos[1] = value_snap(dragging_sy + _dy, _sny); + + if(inputs[| _posInd].setValue(_pos)) + UNDO_HOLDING = true; + + if(inputs[| _posInd].unit.mode == VALUE_UNIT.reference) { + var p = [ _pos[0], _pos[1] ]; + _pos = inputs[| _posInd].unit.apply(p); + } + } else if(drag_type == 1) { + var aa = point_direction(rot_anc_x, rot_anc_y, _mx, _my); + var da = angle_difference(dragging_mx, aa); + + if(key_mod_press(CTRL)) + _rot = round((dragging_sx - da) / 15) * 15; + else + _rot = dragging_sx - da; + + if(inputs[| _rotInd].setValue(_rot)) + UNDO_HOLDING = true; + } else if(drag_type == 2) { + var _p = point_rotate(_mx - dragging_mx, _my - dragging_my, 0, 0, -_rot); + _sca[0] = _p[0] / _s; + _sca[1] = _p[1] / _s; + + if(key_mod_press(SHIFT)) { + _sca[0] = min(_sca[0], _sca[1]); + _sca[1] = min(_sca[0], _sca[1]); + } + + if(inputs[| _scaInd].setValue(_sca)) + UNDO_HOLDING = true; + + if(_scaUnit && inputs[| _scaInd].unit.mode == VALUE_UNIT.reference) { + var s = [ _sca[0], _sca[1] ]; + _sca = inputs[| _scaInd].unit.apply(s); + } + } + + if(mouse_release(mb_left)) { + drag_type = -1; + UNDO_HOLDING = false; + } + } + + var p0 = point_rotate(-_sca[0], -_sca[1], 0, 0, _rot); + var p1 = point_rotate( _sca[0], -_sca[1], 0, 0, _rot); + var p2 = point_rotate(-_sca[0], _sca[1], 0, 0, _rot); + var p3 = point_rotate( _sca[0], _sca[1], 0, 0, _rot); + var pr = point_rotate( 0, -_sca[1] - 1, 0, 0, _rot); + + var pd0x = _x + (p0[0] + _pos[0]) * _s; var pd0y = _y + (p0[1] + _pos[1]) * _s; + var pd1x = _x + (p1[0] + _pos[0]) * _s; var pd1y = _y + (p1[1] + _pos[1]) * _s; + var pd2x = _x + (p2[0] + _pos[0]) * _s; var pd2y = _y + (p2[1] + _pos[1]) * _s; + var pd3x = _x + (p3[0] + _pos[0]) * _s; var pd3y = _y + (p3[1] + _pos[1]) * _s; + var prx = _x + (pr[0] + _pos[0]) * _s; var pry = _y + (pr[1] + _pos[1]) * _s; + + var hovering = -1; + + if(drag_type == -1) { + if(point_in_rectangle_points(_mx, _my, pd0x, pd0y, pd1x, pd1y, pd2x, pd2y, pd3x, pd3y)) + hovering = 0; + if(point_in_circle(_mx, _my, prx, pry, 12)) + hovering = 1; + if(point_in_circle(_mx, _my, pd3x, pd3y, 12)) + hovering = 2; + } + + draw_set_color(COLORS._main_accent); + draw_line_width(pd0x, pd0y, pd1x, pd1y, hovering == 0? 2 : 1); + draw_line_width(pd0x, pd0y, pd2x, pd2y, hovering == 0? 2 : 1); + draw_line_width(pd3x, pd3y, pd1x, pd1y, hovering == 0? 2 : 1); + draw_line_width(pd3x, pd3y, pd2x, pd2y, hovering == 0? 2 : 1); + + draw_sprite_colored(THEME.anchor_rotate, hovering == 1, prx, pry,, _rot); + draw_sprite_colored(THEME.anchor_scale, hovering == 2, pd3x, pd3y,, _rot); + + if(hovering == -1) return; + if(drag_type > -1) return; + + if(mouse_press(mb_left, active)) { + drag_type = hovering; + if(hovering == 0) { + dragging_sx = _pos[0]; + dragging_sy = _pos[1]; + dragging_mx = _mx; + dragging_my = _my; + } else if(hovering == 1) { //rot + dragging_sx = _rot; + rot_anc_x = _x + _pos[0] * _s; + rot_anc_y = _y + _pos[1] * _s; + dragging_mx = point_direction(rot_anc_x, rot_anc_y, _mx, _my); + } else if(hovering == 2) { //sca + dragging_sx = _sca[0]; + dragging_sy = _sca[1]; + dragging_mx = _x + _pos[0] * _s; + dragging_my = _y + _pos[1] * _s; + } + } + } +#endregion + +#region node function + function nodeLoad(_data, scale = false, _group = noone) { + INLINE + if(!is_struct(_data)) return; + + var _x = _data.x; + var _y = _data.y; + var _type = _data.type; + + if(ds_map_exists(APPEND_MAP, _data.id)) { + var _node = APPEND_MAP[? _data.id]; + _node.x = _x; + _node.y = _y; + _node.deserialize(_data, scale); + return _node; + } + + var _node = nodeBuild(_type, _x, _y, _group); + if(_node) _node.deserialize(_data, scale); + + return _node; + } + + function nodeCleanUp() { + var key = ds_map_find_first(PROJECT.nodeMap); + repeat(ds_map_size(PROJECT.nodeMap)) { + if(PROJECT.nodeMap[? key]) { + PROJECT.nodeMap[? key].active = false; + PROJECT.nodeMap[? key].cleanUp(); + delete PROJECT.nodeMap[? key]; + } + key = ds_map_find_next(PROJECT.nodeMap, key); + } + + ds_map_clear(APPEND_MAP); + } + + function graphFocusNode(node) { + PANEL_INSPECTOR.setInspecting(node); + PANEL_GRAPH.nodes_selecting = [ node ]; + PANEL_GRAPH.fullView(); + } + + function refreshNodeMap() { + ds_map_clear(PROJECT.nodeNameMap); + var key = ds_map_find_first(PROJECT.nodeMap); + var amo = ds_map_size(PROJECT.nodeMap); + + repeat(amo) { + var node = PROJECT.nodeMap[? key]; + + if(node.internalName != "") + PROJECT.nodeNameMap[? node.internalName] = node; + + key = ds_map_find_next(PROJECT.nodeMap, key); + } + } + + function nodeGetData(str) { + str = string_trim(str); + var strs = string_splice(str, "."); + + if(array_length(strs) == 0) return 0; + + if(array_length(strs) == 1) { + var splt = string_splice(strs[0], "["); + var inp = PROJECT.globalNode.getInput(strs[0]); + if(inp == 0) return 0; + + var _arr = [ 0, 0 ]; + inp.getValueRecursive(_arr); + + return _arr[0]; + + } else if(struct_has(PROJECT_VARIABLES, strs[0])) { + var _str_var = PROJECT_VARIABLES[$ strs[0]]; + if(!struct_has(_str_var, strs[1])) return 0; + + var val = _str_var[$ strs[1]][0]; + if(is_callable(val)) + return val(); + return val; + } else if(array_length(strs) > 2) { + var key = strs[0]; + if(!ds_map_exists(PROJECT.nodeNameMap, key)) return 0; + + var node = PROJECT.nodeNameMap[? key]; + var map = noone; + switch(string_lower(strs[1])) { + case "inputs" : + case "input" : + map = node.inputMap; + break; + case "outputs" : + case "output" : + map = node.outputMap; + break; + default : return 0; + } + + var _junc_key = string_lower(strs[2]); + var _junc = ds_map_try_get(map, _junc_key, noone); + + if(_junc == noone) return 0; + + return _junc.getValue(); + } + + return 0; + } + + function nodeGetDataAnim(str) { + str = string_trim(str); + var strs = string_splice(str, "."); + + if(array_length(strs) == 0) return 0; + + if(array_length(strs) == 1) { + return EXPRESS_TREE_ANIM.none; + } else if(struct_has(PROJECT_VARIABLES, strs[0])) { + var _str_var = PROJECT_VARIABLES[$ strs[0]]; + if(!struct_has(_str_var, strs[1])) return EXPRESS_TREE_ANIM.none; + + var val = _str_var[$ strs[1]][1]; + return val; + } else if(array_length(strs) > 2) { + var key = strs[0]; + if(!ds_map_exists(PROJECT.nodeNameMap, key)) return EXPRESS_TREE_ANIM.none; + + var node = PROJECT.nodeNameMap[? key]; + var map = noone; + switch(string_lower(strs[1])) { + case "inputs" : + case "input" : + map = node.inputMap; + break; + case "outputs" : + case "output" : + map = node.outputMap; + break; + default : return EXPRESS_TREE_ANIM.none; + } + + var _junc_key = string_lower(strs[2]); + var _junc = ds_map_try_get(map, _junc_key, noone); + + if(_junc == noone) return EXPRESS_TREE_ANIM.none; + + return _junc.is_anim * 2; + } + + return EXPRESS_TREE_ANIM.none; + } + + function create_preview_window(node) { + if(node == noone) return; + var win = new Panel_Preview_Window(); + win.node_target = node; + win.preview_channel = node.preview_channel; + var dia = dialogPanelCall(win, mouse_mx, mouse_my); + dia.destroy_on_click_out = false; + } +#endregion \ No newline at end of file diff --git a/#backups/scripts/node_functions/node_functions.gml.backup1 b/#backups/scripts/node_functions/node_functions.gml.backup1 new file mode 100644 index 000000000..b8bdebaee --- /dev/null +++ b/#backups/scripts/node_functions/node_functions.gml.backup1 @@ -0,0 +1,305 @@ +// 2024-04-20 08:21:22 +#macro DEF_SURF_W PROJECT.attributes.surface_dimension[0] +#macro DEF_SURF_H PROJECT.attributes.surface_dimension[1] +#macro DEF_SURF PROJECT.attributes.surface_dimension + +#macro DEF_PALETTE PROJECT.attributes.palette + +#region + function node_draw_transform_init() { + drag_type = -1; + dragging_sx = 0; + dragging_sy = 0; + dragging_mx = 0; + dragging_my = 0; + rot_anc_x = 0; + rot_anc_y = 0; + } + + function node_draw_transform_box(active, _x, _y, _s, _mx, _my, _snx, _sny, _posInd, _rotInd, _scaInd, _scaUnit = false) { + var _pos = getInputData(_posInd); + var _rot = getInputData(_rotInd); + var _sca = getInputData(_scaInd); + + if(drag_type > -1) { + if(drag_type == 0) { + var _dx = (_mx - dragging_mx) / _s; + var _dy = (_my - dragging_my) / _s; + + if(key_mod_press(SHIFT)) { + if(abs(_dx) > abs(_dy) + ui(16)) + _dy = 0; + else if(abs(_dy) > abs(_dx) + ui(16)) + _dx = 0; + else { + _dx = max(_dx, _dy); + _dy = _dx; + } + } + + _pos[0] = value_snap(dragging_sx + _dx, _snx); + _pos[1] = value_snap(dragging_sy + _dy, _sny); + + if(inputs[| _posInd].setValue(_pos)) + UNDO_HOLDING = true; + + if(inputs[| _posInd].unit.mode == VALUE_UNIT.reference) { + var p = [ _pos[0], _pos[1] ]; + _pos = inputs[| _posInd].unit.apply(p); + } + } else if(drag_type == 1) { + var aa = point_direction(rot_anc_x, rot_anc_y, _mx, _my); + var da = angle_difference(dragging_mx, aa); + + if(key_mod_press(CTRL)) + _rot = round((dragging_sx - da) / 15) * 15; + else + _rot = dragging_sx - da; + + if(inputs[| _rotInd].setValue(_rot)) + UNDO_HOLDING = true; + } else if(drag_type == 2) { + var _p = point_rotate(_mx - dragging_mx, _my - dragging_my, 0, 0, -_rot); + _sca[0] = _p[0] / _s; + _sca[1] = _p[1] / _s; + + if(key_mod_press(SHIFT)) { + _sca[0] = min(_sca[0], _sca[1]); + _sca[1] = min(_sca[0], _sca[1]); + } + + if(inputs[| _scaInd].setValue(_sca)) + UNDO_HOLDING = true; + + if(_scaUnit && inputs[| _scaInd].unit.mode == VALUE_UNIT.reference) { + var s = [ _sca[0], _sca[1] ]; + _sca = inputs[| _scaInd].unit.apply(s); + } + } + + if(mouse_release(mb_left)) { + drag_type = -1; + UNDO_HOLDING = false; + } + } + + var p0 = point_rotate(-_sca[0], -_sca[1], 0, 0, _rot); + var p1 = point_rotate( _sca[0], -_sca[1], 0, 0, _rot); + var p2 = point_rotate(-_sca[0], _sca[1], 0, 0, _rot); + var p3 = point_rotate( _sca[0], _sca[1], 0, 0, _rot); + var pr = point_rotate( 0, -_sca[1] - 1, 0, 0, _rot); + + var pd0x = _x + (p0[0] + _pos[0]) * _s; var pd0y = _y + (p0[1] + _pos[1]) * _s; + var pd1x = _x + (p1[0] + _pos[0]) * _s; var pd1y = _y + (p1[1] + _pos[1]) * _s; + var pd2x = _x + (p2[0] + _pos[0]) * _s; var pd2y = _y + (p2[1] + _pos[1]) * _s; + var pd3x = _x + (p3[0] + _pos[0]) * _s; var pd3y = _y + (p3[1] + _pos[1]) * _s; + var prx = _x + (pr[0] + _pos[0]) * _s; var pry = _y + (pr[1] + _pos[1]) * _s; + + var hovering = -1; + + if(drag_type == -1) { + if(point_in_rectangle_points(_mx, _my, pd0x, pd0y, pd1x, pd1y, pd2x, pd2y, pd3x, pd3y)) + hovering = 0; + if(point_in_circle(_mx, _my, prx, pry, 12)) + hovering = 1; + if(point_in_circle(_mx, _my, pd3x, pd3y, 12)) + hovering = 2; + } + + draw_set_color(COLORS._main_accent); + draw_line_width(pd0x, pd0y, pd1x, pd1y, hovering == 0? 2 : 1); + draw_line_width(pd0x, pd0y, pd2x, pd2y, hovering == 0? 2 : 1); + draw_line_width(pd3x, pd3y, pd1x, pd1y, hovering == 0? 2 : 1); + draw_line_width(pd3x, pd3y, pd2x, pd2y, hovering == 0? 2 : 1); + + draw_sprite_colored(THEME.anchor_rotate, hovering == 1, prx, pry,, _rot); + draw_sprite_colored(THEME.anchor_scale, hovering == 2, pd3x, pd3y,, _rot); + + if(hovering == -1) return; + if(drag_type > -1) return; + + if(mouse_press(mb_left, active)) { + drag_type = hovering; + if(hovering == 0) { + dragging_sx = _pos[0]; + dragging_sy = _pos[1]; + dragging_mx = _mx; + dragging_my = _my; + } else if(hovering == 1) { //rot + dragging_sx = _rot; + rot_anc_x = _x + _pos[0] * _s; + rot_anc_y = _y + _pos[1] * _s; + dragging_mx = point_direction(rot_anc_x, rot_anc_y, _mx, _my); + } else if(hovering == 2) { //sca + dragging_sx = _sca[0]; + dragging_sy = _sca[1]; + dragging_mx = _x + _pos[0] * _s; + dragging_my = _y + _pos[1] * _s; + } + } + } +#endregion + +#region node function + function nodeLoad(_data, scale = false, _group = noone) { + INLINE + if(!is_struct(_data)) return; + + var _x = _data.x; + var _y = _data.y; + var _type = _data.type; + + if(ds_map_exists(APPEND_MAP, _data.id)) { + var _node = APPEND_MAP[? _data.id]; + _node.x = _x; + _node.y = _y; + _node.deserialize(_data, scale); + return _node; + } + + var _node = nodeBuild(_type, _x, _y, _group); + if(_node) _node.deserialize(_data, scale); + + return _node; + } + + function nodeCleanUp() { + var key = ds_map_find_first(PROJECT.nodeMap); + repeat(ds_map_size(PROJECT.nodeMap)) { + if(PROJECT.nodeMap[? key]) { + PROJECT.nodeMap[? key].active = false; + PROJECT.nodeMap[? key].cleanUp(); + delete PROJECT.nodeMap[? key]; + } + key = ds_map_find_next(PROJECT.nodeMap, key); + } + + ds_map_clear(APPEND_MAP); + } + + function graphFocusNode(node) { + PANEL_INSPECTOR.setInspecting(node); + PANEL_GRAPH.nodes_selecting = [ node ]; + PANEL_GRAPH.fullView(); + } + + function refreshNodeMap() { + ds_map_clear(PROJECT.nodeNameMap); + var key = ds_map_find_first(PROJECT.nodeMap); + var amo = ds_map_size(PROJECT.nodeMap); + + repeat(amo) { + var node = PROJECT.nodeMap[? key]; + + if(node.internalName != "") + PROJECT.nodeNameMap[? node.internalName] = node; + + key = ds_map_find_next(PROJECT.nodeMap, key); + } + } + + function nodeGetData(str) { + str = string_trim(str); + var strs = string_splice(str, "."); + + if(array_length(strs) == 0) return 0; + + if(array_length(strs) == 1) { + var splt = string_splice(strs[0], "["); + var inp = PROJECT.globalNode.getInput(strs[0]); + if(inp == 0) return 0; + + var _arr = [ 0, 0 ]; + inp.getValueRecursive(_arr); + + return _arr[0]; + + } else if(struct_has(PROJECT_VARIABLES, strs[0])) { + var _str_var = PROJECT_VARIABLES[$ strs[0]]; + if(!struct_has(_str_var, strs[1])) return 0; + + var val = _str_var[$ strs[1]][0]; + if(is_callable(val)) + return val(); + return val; + } else if(array_length(strs) > 2) { + var key = strs[0]; + if(!ds_map_exists(PROJECT.nodeNameMap, key)) return 0; + + var node = PROJECT.nodeNameMap[? key]; + var map = noone; + switch(string_lower(strs[1])) { + case "inputs" : + case "input" : + map = node.inputMap; + break; + case "outputs" : + case "output" : + map = node.outputMap; + break; + default : return 0; + } + + var _junc_key = string_lower(strs[2]); + var _junc = ds_map_try_get(map, _junc_key, noone); + + if(_junc == noone) return 0; + + return _junc.getValue(); + } + + return 0; + } + + function nodeGetDataAnim(str) { + str = string_trim(str); + var strs = string_splice(str, "."); + + if(array_length(strs) == 0) return 0; + + if(array_length(strs) == 1) { + return EXPRESS_TREE_ANIM.none; + } else if(struct_has(PROJECT_VARIABLES, strs[0])) { + var _str_var = PROJECT_VARIABLES[$ strs[0]]; + if(!struct_has(_str_var, strs[1])) return EXPRESS_TREE_ANIM.none; + + var val = _str_var[$ strs[1]][1]; + return val; + } else if(array_length(strs) > 2) { + var key = strs[0]; + if(!ds_map_exists(PROJECT.nodeNameMap, key)) return EXPRESS_TREE_ANIM.none; + + var node = PROJECT.nodeNameMap[? key]; + var map = noone; + switch(string_lower(strs[1])) { + case "inputs" : + case "input" : + map = node.inputMap; + break; + case "outputs" : + case "output" : + map = node.outputMap; + break; + default : return EXPRESS_TREE_ANIM.none; + } + + var _junc_key = string_lower(strs[2]); + var _junc = ds_map_try_get(map, _junc_key, noone); + + if(_junc == noone) return EXPRESS_TREE_ANIM.none; + + return _junc.is_anim * 2; + } + + return EXPRESS_TREE_ANIM.none; + } + + function create_preview_window(node) { + if(node == noone) return; + var win = new Panel_Preview_Window(); + win.node_target = node; + win.preview_channel = node.preview_channel; + var dia = dialogPanelCall(win, mouse_mx, mouse_my); + dia.destroy_on_click_out = false; + } +#endregion \ No newline at end of file diff --git a/#backups/scripts/node_keyframe/node_keyframe.gml.backup0 b/#backups/scripts/node_keyframe/node_keyframe.gml.backup0 new file mode 100644 index 000000000..b32e7be10 --- /dev/null +++ b/#backups/scripts/node_keyframe/node_keyframe.gml.backup0 @@ -0,0 +1,740 @@ +// 2024-04-20 09:03:18 +enum KEY_TYPE { normal, adder } +enum CURVE_TYPE { linear, bezier, cut } +enum DRIVER_TYPE { none, linear, wiggle, sine } + +function valueKey(_time, _value, _anim = noone, _in = 0, _ot = 0) constructor { + #region ---- main ---- + time = _time; + ratio = time / (TOTAL_FRAMES - 1); + value = _value; + anim = _anim; + + ease_y_lock = true; + ease_in = is_array(_in)? _in : [_in, 1]; + ease_out = is_array(_ot)? _ot : [_ot, 0]; + + var _int = anim? anim.prop.key_inter : CURVE_TYPE.linear; + ease_in_type = _int; + ease_out_type = _int; + + dopesheet_x = 0; + + drivers = { + seed : irandom_range(100000, 999999), + type : DRIVER_TYPE.none, + speed : 1, + octave : 2, + frequency : 4, + amplitude : 1, + axis_sync : false, + phase : 0, + }; + #endregion + + static setTime = function(time) { #region + self.time = time; + ratio = time / (TOTAL_FRAMES - 1); + } #endregion + + static clone = function(target = noone) { #region + var key = new valueKey(time, value, target); + key.ease_in = ease_in; + key.ease_out = ease_out; + key.ease_in_type = ease_in_type; + key.ease_out_type = ease_out_type; + + return key; + } #endregion + + static cloneAnimator = function(shift = 0, anim = noone, removeDup = true) { #region + if(anim != noone) { //check value compat between animator + if(value_bit(self.anim.prop.type) & value_bit(anim.prop.type) == 0) { + noti_warning("Type incompatible"); + return noone; + } + + if(typeArray(self.anim.prop.display_type) != typeArray(anim.prop.display_type)) { + noti_warning("Type incompatible"); + return noone; + } + } + + if(anim == noone) anim = self.anim; + + var key = new valueKey(time + shift, value, anim); + key.ease_in = ease_in; + key.ease_out = ease_out; + key.ease_in_type = ease_in_type; + key.ease_out_type = ease_out_type; + ds_list_add(anim.values, key); + anim.setKeyTime(key, time + shift, removeDup); + + return key; + } #endregion + + static getDrawIndex = function() { #region + if(anim.prop.type == VALUE_TYPE.trigger) + return 1; + + if(drivers.type) + return 2; + + if(ease_in_type == CURVE_TYPE.cut) + return 1; + + return 0; + } #endregion + + static toString = function() { return $"[Keyframe] {time}: {value}"; } +} + +function valueAnimator(_val, _prop, _sep_axis = false) constructor { + #region ---- main ---- + suffix = ""; + values = ds_list_create(); + //staticValue = 0; + + length = 1; + sep_axis = _sep_axis; + + index = 0; + prop = _prop; + y = 0; + key_map = array_create(TOTAL_FRAMES); + key_map_mode = KEYFRAME_END.hold; + + animate_frames = []; + + if(_prop.type != VALUE_TYPE.trigger) + ds_list_add(values, new valueKey(0, _val, self)); + #endregion + + static refreshAnimation = function() { #region + animate_frames = array_verify(animate_frames, TOTAL_FRAMES); + + var _anim = false; + var _fr = noone; + + for( var i = 0, n = ds_list_size(values); i < n; i++ ) { + var _key = values[| i]; + + if(_fr == noone) { + array_fill(animate_frames, 0, _key.time, 0); + } else { + if(array_equals(_fr.ease_out, [0, 0]) && array_equals(_fr.ease_in, [0, 1]) && isEqual(_fr.value, _key.value)) + array_fill(animate_frames, _fr.time, _key.time, 0); + else + array_fill(animate_frames, _fr.time, _key.time, 1); + } + + _fr = _key; + } + + if(_fr) array_fill(animate_frames, _fr.time, TOTAL_FRAMES, 0); + } #endregion + + static updateKeyMap = function() { #region + length = ds_list_size(values); + + if(!prop.is_anim && !LOADING && !APPENDING) return; + + if(ds_list_empty(values)) { + array_resize(key_map, TOTAL_FRAMES); + return; + } + + var _len = max(TOTAL_FRAMES, values[| ds_list_size(values) - 1].time); + key_map_mode = prop.on_end; + + if(array_length(key_map) != _len) + array_resize(key_map, _len); + + if(prop.type == VALUE_TYPE.trigger) { + array_fill(key_map, 0, _len, 0); + for( var i = 0, n = ds_list_size(values); i < n; i++ ) + key_map[values[| i].time] = true; + return; + } + + if(ds_list_size(values) < 2) { + array_fill(key_map, 0, _len, 0); + return; + } + + var _firstKey = values[| 0].time; + array_fill(key_map, 0, _firstKey, -1); + var _keyIndex = _firstKey; + + for( var i = 1, n = ds_list_size(values); i < n; i++ ) { + var _k1 = values[| i].time; + array_fill(key_map, _keyIndex, _k1, i - 1); + _keyIndex = _k1; + } + + array_fill(key_map, _keyIndex, _len, 999_999); + } #endregion + + static interpolate = function(from, to, rat) { #region + if(prop.type == VALUE_TYPE.boolean) + return 0; + + if(to.ease_in_type == CURVE_TYPE.linear && from.ease_out_type == CURVE_TYPE.linear) + return rat; + if(to.ease_in_type == CURVE_TYPE.cut) + return 0; + if(from.ease_out_type == CURVE_TYPE.cut) + return 1; + if(rat == 0 || rat == 1) + return rat; + + var eox = clamp(from.ease_out[0], 0, 0.9); + var eix = clamp(to.ease_in[0], 0, 0.9); + var eoy = from.ease_out[1]; + var eiy = to.ease_in[1]; + + var bz = [0, eox, eoy, 1. - eix, eiy, 1]; + return eval_curve_segment_x(bz, rat); + } #endregion + + static lerpValue = function(from, to, _lrp) { #region + var _f = from.value; + var _t = to.value; + + if(is_struct(_f)) { + if(!struct_has(_f, "lerpTo")) return _f; + return _f.lerpTo(_t, _lrp); + } + + if(prop.display_type == VALUE_DISPLAY.d3quarternion) { + if(prop.display_data.angle_display == 0) { + var _qf = new BBMOD_Quaternion(_f[0], _f[1], _f[2], _f[3]); + var _qt = new BBMOD_Quaternion(_t[0], _t[1], _t[2], _t[3]); + var _ql = _qf.Slerp(_qt, _lrp); + + return _ql.ToArray(); + } else { + return [ + lerp(_f[0], _t[0], _lrp), + lerp(_f[1], _t[1], _lrp), + lerp(_f[2], _t[2], _lrp), + 0, + ]; + } + } + + if(prop.type == VALUE_TYPE.color) { + if(is_array(_f) && is_array(_t)) { + var _len = ceil(lerp(array_length(_f), array_length(_t), _lrp)); + var res = array_create(_len); + + for( var i = 0; i < _len; i++ ) { + var rat = i / (_len - 1); + + var rf = rat * (array_length(_f) - 1); + var rt = rat * (array_length(_t) - 1); + + var cf = array_get_decimal(_f, rf, true); + var ct = array_get_decimal(_t, rt, true); + + res[i] = merge_color(cf, ct, _lrp); + } + + return res; + } + + return processType(merge_color(_f, _t, _lrp)); + } + + if(is_array(_f) || is_array(_t)) { + var _len = max(array_safe_length(_f), array_safe_length(_t)); + var _vec = array_create(_len); + + for(var i = 0; i < _len; i++) + _vec[i] = processType( + lerp( + is_array(_f)? array_safe_get_fast(_f, i, 0) : _f, + is_array(_t)? array_safe_get_fast(_t, i, 0) : _t, + _lrp) + ); + return _vec; + } + + if(prop.type == VALUE_TYPE.text) + return processType(_f); + + return processType(lerp(_f, _t, _lrp)); + } #endregion + + static getName = function() { return prop.name + suffix; } + + static getValue = function(_time = CURRENT_FRAME) { #region + //if(!prop.is_anim) return staticValue; + length = ds_list_size(values); + + ///////////////////////////////////////////////////////////// TRIGGER TYPE ///////////////////////////////////////////////////////////// + + if(prop.type == VALUE_TYPE.trigger) { + if(length == 0 || !prop.is_anim) return false; + + if(array_length(key_map) != TOTAL_FRAMES) updateKeyMap(); + + return key_map[_time]; + } + + ///////////////////////////////////////////////////////////// OPTIMIZATION ///////////////////////////////////////////////////////////// + + if(length == 0) return processTypeDefault(); + if(length == 1) { + var _key = values[| 0]; + + if(_key.drivers.type && _time >= _key.time) + return processType(processDriver(_time, _key)); + + return processType(_key.value); + } + + if(prop.type == VALUE_TYPE.path) return processType(values[| 0].value); + if(!prop.is_anim) return processType(values[| 0].value); + var _len = max(TOTAL_FRAMES, values[| length - 1].time); + if(array_length(key_map) != _len) updateKeyMap(); + + var _time_first = prop.loop_range == -1? values[| 0].time : values[| length - 1 - prop.loop_range].time; + var _time_last = values[| length - 1].time; + var _time_dura = _time_last - _time_first; + + ////////////////////////////////////////////////////////////// LOOP TIME /////////////////////////////////////////////////////////////// + + if(_time > _time_last) { + switch(prop.on_end) { + case KEYFRAME_END.loop : + _time = _time_first + safe_mod(_time - _time_last, _time_dura + 1); + break; + case KEYFRAME_END.ping : + var time_in_loop = safe_mod(_time - _time_first, _time_dura * 2); + if(time_in_loop < _time_dura) + _time = _time_first + time_in_loop; + else + _time = _time_first + _time_dura * 2 - time_in_loop; + break; + } + } + + var _keyIndex; + if(_time >= _len) _keyIndex = 999_999; + else if(_time <= 0) _keyIndex = -1; + else _keyIndex = array_safe_get_fast(key_map, _time); + + //////////////////////////////////////////////////////////// BEFORE FIRST ////////////////////////////////////////////////////////////// + + if(_keyIndex == -1) { + if(prop.on_end == KEYFRAME_END.wrap) { + var from = values[| length - 1]; + var to = values[| 0]; + + var fTime = from.time; + var tTime = to.time; + + var prog = TOTAL_FRAMES - fTime + _time; + var totl = TOTAL_FRAMES - fTime + tTime; + + var rat = prog / totl; + var _lrp = interpolate(from, to, rat); + + return lerpValue(from, to, _lrp); + } + + return processType(values[| 0].value); //First frame + } + + ///////////////////////////////////////////////////////////// AFTER LAST /////////////////////////////////////////////////////////////// + + if(_keyIndex == 999_999) { + var _lstKey = values[| length - 1]; + + if(_lstKey.drivers.type) + return processType(processDriver(_time, _lstKey)); + + if(prop.on_end == KEYFRAME_END.wrap) { + var from = _lstKey; + var to = values[| 0]; + var prog = _time - from.time; + var totl = TOTAL_FRAMES - from.time + to.time; + + var rat = prog / totl; + var _lrp = interpolate(from, to, rat); + + return lerpValue(from, to, _lrp); + } + + return processType(_lstKey.value); //Last frame + } + + ///////////////////////////////////////////////////////////// INBETWEEN //////////////////////////////////////////////////////////////// + + var from = values[| _keyIndex]; + var to = values[| _keyIndex + 1]; + + var rat = (_time - from.time) / (to.time - from.time); + var _lrp = interpolate(from, to, rat); + + if(from.drivers.type) + return processDriver(_time, from, lerpValue(from, to, _lrp), rat); + + return lerpValue(from, to, _lrp); + + } #endregion + + static processTypeDefault = function() { #region + if(!sep_axis && typeArray(prop.display_type)) return []; + return 0; + } #endregion + + static processDriver = function(_time, _key, _val = undefined, _intp = 0) { #region + + static _processDriver = function(val, drivers, _t, _index = 0, _intp = 0) { + switch(drivers.type) { + case DRIVER_TYPE.linear : + return val + _t * drivers.speed; + + case DRIVER_TYPE.wiggle : + var w = perlin1D(_t, drivers.seed + _index, drivers.frequency / 10, drivers.octave, -1, 1) * drivers.amplitude; + return val + w; + + case DRIVER_TYPE.sine : + var w = sin((drivers.phase * (_index + 1) + _t * drivers.frequency / TOTAL_FRAMES) * pi * 2) * drivers.amplitude; + return val + w; + } + + return 0; + } + + var _dt = _time - _key.time; + _val = _val == undefined? _key.value : _val; + var _res = _val; + + if(prop.type == VALUE_TYPE.integer || prop.type == VALUE_TYPE.float) { + if(is_array(_val)) { + _res = array_create(array_length(_val)); + for( var i = 0, n = array_length(_val); i < n; i++ ) + _res[i] = is_numeric(_val[i])? _processDriver(_val[i], _key.drivers, _dt, _key.drivers.axis_sync? 0 : i, _intp) : _val[i]; + } else + _res = _processDriver(_val, _key.drivers, _dt, 0, _intp); + } + + return _res; + } #endregion + + static processType = function(_val) { #region + INLINE + + var _res = _val; + + if(!sep_axis && typeArray(prop.display_type) && is_array(_val)) { + for(var i = 0; i < array_length(_val); i++) + _res[i] = processValue(_val[i]); + } else + _res = processValue(_val); + + return _res; + } #endregion + + static processValue = function(_val) { #region + INLINE + + if(is_array(_val)) return _val; + if(is_struct(_val)) return _val; + //if(is_undefined(_val)) return 0; + + switch(prop.type) { + case VALUE_TYPE.integer : return prop.unit.mode == VALUE_UNIT.constant? round(_val) : _val; + case VALUE_TYPE.float : return _val; + case VALUE_TYPE.text : return is_string(_val)? _val : string_real(_val); + case VALUE_TYPE.color : return is_real(_val)? cola(_val) : _val; + case VALUE_TYPE.surface : return is_string(_val)? get_asset(_val) : _val; + } + + return _val; + } #endregion + + static insertKey = function(_key, _index) { ds_list_insert(values, _index, _key); } + + static setKeyTime = function(_key, _time, _replace = true, record = false) { #region + if(!ds_list_exist(values, _key)) return 0; + if(_key.time == _time && !_replace) return 0; + + if(!LOADING) PROJECT.modified = true; + + var _prevTime = _key.time; + _time = max(_time, 0); + _key.setTime(_time); + ds_list_remove(values, _key); + + if(_replace) + for( var i = 0; i < ds_list_size(values); i++ ) { + if(values[| i].time != _time) continue; + + if(record) { + var act = new Action(ACTION_TYPE.custom, function(data) { + if(data.undo) insertKey(data.overKey, data.index); + updateKeyMap(); + + data.undo = !data.undo; + }, { overKey : values[| i], index : i, undo : true }); + mergeAction(act); + } + + values[| i] = _key; + updateKeyMap(); + return 2; + } + + for( var i = 0; i < ds_list_size(values); i++ ) { //insert key before the last key + if(values[| i].time < _time) continue; + + if(record) recordAction(ACTION_TYPE.custom, function(data) { + var _prevTime = data.key.time; + setKeyTime(data.key, data.time, false); + + data.time = _prevTime; + }, { key : _key, time : _prevTime }); + + ds_list_insert(values, i, _key); + if(_replace) updateKeyMap(); + return 1; + } + + if(record) recordAction(ACTION_TYPE.custom, function(data) { // insert key after the last key + var _prevTime = data.key.time; + setKeyTime(data.key, data.time, false); + + data.time = _prevTime; + }, { key : _key, time : _prevTime }); + + ds_list_add(values, _key); + if(_replace) updateKeyMap(); + return 1; + } #endregion + + static setValue = function(_val = 0, _record = true, _time = CURRENT_FRAME, ease_in = 0, ease_out = 0) { #region + //staticValue = _val; + + if(prop.type == VALUE_TYPE.trigger) { + if(!prop.is_anim) { + values[| 0] = new valueKey(0, _val, self); + updateKeyMap(); + return true; + } + + for(var i = 0; i < ds_list_size(values); i++) { //Find trigger + var _key = values[| i]; + if(_key.time == _time) { + if(!global.FLAG.keyframe_override) return false; + + _key.value = _val; + return false; + + } else if(_key.time > _time) { + ds_list_insert(values, i, new valueKey(_time, _val, self)); + updateKeyMap(); + return true; + } + } + + //print($"{_time}: {_val} | Insert last"); + ds_list_add(values, new valueKey(_time, _val, self)); + updateKeyMap(); + return true; + } + + if(!prop.is_anim) { + if(isEqual(values[| 0].value, _val)) + return false; + + if(_record) recordAction(ACTION_TYPE.var_modify, values[| 0], [ values[| 0].value, "value", prop.name ]); + + values[| 0].value = _val; + return true; + } + + if(ds_list_size(values) == 0) { // Should not be called normally + var k = new valueKey(_time, _val, self, ease_in, ease_out); + ds_list_add(values, k); + if(_record) recordAction(ACTION_TYPE.list_insert, values, [ k, ds_list_size(values) - 1, $"add {prop.name} keyframe" ], function() { updateKeyMap(); }); + return true; + } + + for(var i = 0; i < ds_list_size(values); i++) { + var _key = values[| i]; + if(_key.time == _time) { + if(!global.FLAG.keyframe_override) return false; + + if(_key.value != _val) { + if(_record) recordAction(ACTION_TYPE.var_modify, _key, [ _key.value, "value", prop.name ]); + _key.value = _val; + return true; + } + return false; + } else if(_key.time > _time) { + var k = new valueKey(_time, _val, self, ease_in, ease_out); + ds_list_insert(values, i, k); + if(_record) recordAction(ACTION_TYPE.list_insert, values, [k, i, $"add {prop.name} keyframe" ], function() { updateKeyMap(); }); + updateKeyMap(); + return true; + } + } + + var k = new valueKey(_time, _val, self, ease_in, ease_out); + if(_record) recordAction(ACTION_TYPE.list_insert, values, [ k, ds_list_size(values), $"add {prop.name} keyframe" ], function() { updateKeyMap(); }); + ds_list_add(values, k); + updateKeyMap(); + return true; + } #endregion + + static removeKey = function(key) { #region + if(ds_list_size(values) > 1) + ds_list_remove(values, key); + else + prop.is_anim = false; + updateKeyMap(); + } #endregion + + static serialize = function(scale = false) { #region + var _data = []; + + for(var i = 0; i < ds_list_size(values); i++) { + var _value_list = []; + if(scale) + _value_list[0] = values[| i].time / (TOTAL_FRAMES - 1); + else + _value_list[0] = values[| i].time; + + var val = values[| i].value; + + if(prop.type == VALUE_TYPE.struct) { + val = json_stringify(val); + + } else if(is_struct(val)) { + val = val.serialize(); + + } else if(!sep_axis && typeArray(prop.display_type) && is_array(val)) { + var __v = []; + for(var j = 0; j < array_length(val); j++) { + if(is_struct(val[j]) && struct_has(val[j], "serialize")) + array_push(__v, val[j].serialize()); + else + array_push(__v, val[j]); + } + val = __v; + + } + + _value_list[1] = val; + _value_list[2] = values[| i].ease_in; + _value_list[3] = values[| i].ease_out; + _value_list[4] = values[| i].ease_in_type; + _value_list[5] = values[| i].ease_out_type; + _value_list[6] = values[| i].ease_y_lock; + _value_list[7] = values[| i].drivers; + + array_push(_data, _value_list); + } + + return _data; + } #endregion + + static deserialize = function(_data, scale = false) { #region + ds_list_clear(values); + + if(prop.type == VALUE_TYPE.gradient && LOADING_VERSION < 1340 && !CLONING) { #region //backward compat: Gradient + var _val = []; + var value = _data[0][1]; + + if(is_array(value)) + for(var i = 0; i < array_length(value); i++) { + var _keyframe = value[i]; + var _t = struct_try_get(_keyframe, "time"); + var _v = struct_try_get(_keyframe, "value"); + + array_push(_val, new gradientKey(_t, _v)); + } + + var grad = new gradientObject(); + grad.keys = _val; + ds_list_add(values, new valueKey(0, grad, self)); + + updateKeyMap(); + return; + } #endregion + + var base = prop.def_val; + + for(var i = 0; i < array_length(_data); i++) { + var _keyframe = _data[i]; + var _time = array_safe_get_fast(_keyframe, 0); + + if(scale && _time <= 1) + _time = round(_time * (TOTAL_FRAMES - 1)); + + var value = array_safe_get_fast(_keyframe, 1); + var ease_in = array_safe_get_fast(_keyframe, 2); + var ease_out = array_safe_get_fast(_keyframe, 3); + var ease_in_type = array_safe_get_fast(_keyframe, 4); + var ease_out_type = array_safe_get_fast(_keyframe, 5); + var ease_y_lock = array_safe_get_fast(_keyframe, 6, true); + var driver = array_safe_get_fast(_keyframe, 7, {}); + + var _val = value; + + if(prop.type == VALUE_TYPE.struct) + _val = json_try_parse(value); + + else if(prop.type == VALUE_TYPE.path && prop.display_type == VALUE_DISPLAY.path_array) { + for(var j = 0; j < array_length(value); j++) + _val[j] = value[j]; + + } else if(prop.type == VALUE_TYPE.gradient) { + var grad = new gradientObject(); + _val = grad.deserialize(value); + + } else if(prop.type == VALUE_TYPE.d3Material) { + var mat = new __d3dMaterial(); + _val = mat.deserialize(value); + + } else if(prop.type == VALUE_TYPE.color) { + if(is_array(_val)) { + for( var i = 0, n = array_length(_val); i < n; i++ ) + _val[i] = LOADING_VERSION < 11640 && !is_int64(_val[i])? cola(_val[i]) : int64(_val[i]); + } else + _val = LOADING_VERSION < 11640 && !is_int64(_val)? cola(_val) : int64(_val); + + } else if(!sep_axis && typeArray(prop.display_type)) { + _val = []; + + if(is_array(value)) { + for(var j = 0; j < array_length(value); j++) + _val[j] = processValue(value[j]); + } else if(is_array(base)) { + for(var j = 0; j < array_length(base); j++) + _val[j] = processValue(value); + } + } + + //print($"Deserialize {prop.node.name}:{prop.name} = {_val} "); + var vk = new valueKey(_time, _val, self, ease_in, ease_out); + vk.ease_in_type = ease_in_type; + vk.ease_out_type = ease_out_type; + vk.ease_y_lock = ease_y_lock; + struct_override(vk.drivers, driver); + + ds_list_add(values, vk); + } + + //staticValue = ds_list_empty(values)? 0 : values[| 0].value; + updateKeyMap(); + } #endregion + + static cleanUp = function() { #region + ds_list_destroy(values); + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_keyframe/node_keyframe.gml.backup1 b/#backups/scripts/node_keyframe/node_keyframe.gml.backup1 new file mode 100644 index 000000000..6444ad653 --- /dev/null +++ b/#backups/scripts/node_keyframe/node_keyframe.gml.backup1 @@ -0,0 +1,740 @@ +// 2024-04-20 09:02:54 +enum KEY_TYPE { normal, adder } +enum CURVE_TYPE { linear, bezier, cut } +enum DRIVER_TYPE { none, linear, wiggle, sine } + +function valueKey(_time, _value, _anim = noone, _in = 0, _ot = 0) constructor { + #region ---- main ---- + time = _time; + ratio = time / (TOTAL_FRAMES - 1); + value = _value; + anim = _anim; + + ease_y_lock = true; + ease_in = is_array(_in)? _in : [_in, 1]; + ease_out = is_array(_ot)? _ot : [_ot, 0]; + + var _int = anim? anim.prop.key_inter : CURVE_TYPE.linear; + ease_in_type = _int; + ease_out_type = _int; + + dopesheet_x = 0; + + drivers = { + seed : irandom_range(100000, 999999), + type : DRIVER_TYPE.none, + speed : 1, + octave : 2, + frequency : 4, + amplitude : 1, + axis_sync : false, + phase : 0, + }; + #endregion + + static setTime = function(time) { #region + self.time = time; + ratio = time / (TOTAL_FRAMES - 1); + } #endregion + + static clone = function(target = noone) { #region + var key = new valueKey(time, value, target); + key.ease_in = ease_in; + key.ease_out = ease_out; + key.ease_in_type = ease_in_type; + key.ease_out_type = ease_out_type; + + return key; + } #endregion + + static cloneAnimator = function(shift = 0, anim = noone, removeDup = true) { #region + if(anim != noone) { //check value compat between animator + if(value_bit(self.anim.prop.type) & value_bit(anim.prop.type) == 0) { + noti_warning("Type incompatible"); + return noone; + } + + if(typeArray(self.anim.prop.display_type) != typeArray(anim.prop.display_type)) { + noti_warning("Type incompatible"); + return noone; + } + } + + if(anim == noone) anim = self.anim; + + var key = new valueKey(time + shift, value, anim); + key.ease_in = ease_in; + key.ease_out = ease_out; + key.ease_in_type = ease_in_type; + key.ease_out_type = ease_out_type; + ds_list_add(anim.values, key); + anim.setKeyTime(key, time + shift, removeDup); + + return key; + } #endregion + + static getDrawIndex = function() { #region + if(anim.prop.type == VALUE_TYPE.trigger) + return 1; + + if(drivers.type) + return 2; + + if(ease_in_type == CURVE_TYPE.cut) + return 1; + + return 0; + } #endregion + + static toString = function() { return $"[Keyframe] {time}: {value}"; } +} + +function valueAnimator(_val, _prop, _sep_axis = false) constructor { + #region ---- main ---- + suffix = ""; + values = ds_list_create(); + //staticValue = 0; + + length = 1; + sep_axis = _sep_axis; + + index = 0; + prop = _prop; + y = 0; + key_map = array_create(TOTAL_FRAMES); + key_map_mode = KEYFRAME_END.hold; + + animate_frames = []; + + if(_prop.type != VALUE_TYPE.trigger) + ds_list_add(values, new valueKey(0, _val, self)); + #endregion + + static refreshAnimation = function() { #region + animate_frames = array_verify(animate_frames, TOTAL_FRAMES); + + var _anim = false; + var _fr = noone; + + for( var i = 0, n = ds_list_size(values); i < n; i++ ) { + var _key = values[| i]; + + if(_fr == noone) { + array_fill(animate_frames, 0, _key.time, 0); + } else { + if(array_equals(_fr.ease_out, [0, 0]) && array_equals(_fr.ease_in, [0, 1]) && isEqual(_fr.value, _key.value)) + array_fill(animate_frames, _fr.time, _key.time, 0); + else + array_fill(animate_frames, _fr.time, _key.time, 1); + } + + _fr = _key; + } + + if(_fr) array_fill(animate_frames, _fr.time, TOTAL_FRAMES, 0); + } #endregion + + static updateKeyMap = function() { #region + length = ds_list_size(values); + + if(!prop.is_anim && !LOADING && !APPENDING) return; + + if(ds_list_empty(values)) { + array_resize(key_map, TOTAL_FRAMES); + return; + } + + var _len = max(TOTAL_FRAMES, values[| ds_list_size(values) - 1].time); + key_map_mode = prop.on_end; + + if(array_length(key_map) != _len) + array_resize(key_map, _len); + + if(prop.type == VALUE_TYPE.trigger) { + array_fill(key_map, 0, _len, 0); + for( var i = 0, n = ds_list_size(values); i < n; i++ ) + key_map[values[| i].time] = true; + return; + } + + if(ds_list_size(values) < 2) { + array_fill(key_map, 0, _len, 0); + return; + } + + var _firstKey = values[| 0].time; + array_fill(key_map, 0, _firstKey, -1); + var _keyIndex = _firstKey; + + for( var i = 1, n = ds_list_size(values); i < n; i++ ) { + var _k1 = values[| i].time; + array_fill(key_map, _keyIndex, _k1, i - 1); + _keyIndex = _k1; + } + + array_fill(key_map, _keyIndex, _len, 999_999); + } #endregion + + static interpolate = function(from, to, rat) { #region + if(prop.type == VALUE_TYPE.boolean) + return 0; + + if(to.ease_in_type == CURVE_TYPE.linear && from.ease_out_type == CURVE_TYPE.linear) + return rat; + if(to.ease_in_type == CURVE_TYPE.cut) + return 0; + if(from.ease_out_type == CURVE_TYPE.cut) + return 1; + if(rat == 0 || rat == 1) + return rat; + + var eox = clamp(from.ease_out[0], 0, 0.9); + var eix = clamp(to.ease_in[0], 0, 0.9); + var eoy = from.ease_out[1]; + var eiy = to.ease_in[1]; + + var bz = [0, eox, eoy, 1. - eix, eiy, 1]; + return eval_curve_segment_x(bz, rat); + } #endregion + + static lerpValue = function(from, to, _lrp) { #region + var _f = from.value; + var _t = to.value; + + if(is_struct(_f)) { + if(!struct_has(_f, "lerpTo")) return _f; + return _f.lerpTo(_t, _lrp); + } + + if(prop.display_type == VALUE_DISPLAY.d3quarternion) { + if(prop.display_data.angle_display == 0) { + var _qf = new BBMOD_Quaternion(_f[0], _f[1], _f[2], _f[3]); + var _qt = new BBMOD_Quaternion(_t[0], _t[1], _t[2], _t[3]); + var _ql = _qf.Slerp(_qt, _lrp); + + return _ql.ToArray(); + } else { + return [ + lerp(_f[0], _t[0], _lrp), + lerp(_f[1], _t[1], _lrp), + lerp(_f[2], _t[2], _lrp), + 0, + ]; + } + } + + if(prop.type == VALUE_TYPE.color) { + if(is_array(_f) && is_array(_t)) { + var _len = ceil(lerp(array_length(_f), array_length(_t), _lrp)); + var res = array_create(_len); + + for( var i = 0; i < _len; i++ ) { + var rat = i / (_len - 1); + + var rf = rat * (array_length(_f) - 1); + var rt = rat * (array_length(_t) - 1); + + var cf = array_get_decimal(_f, rf, true); + var ct = array_get_decimal(_t, rt, true); + + res[i] = merge_color(cf, ct, _lrp); + } + + return res; + } + + return processType(merge_color(_f, _t, _lrp)); + } + + if(is_array(_f) || is_array(_t)) { + var _len = max(array_safe_length(_f), array_safe_length(_t)); + var _vec = array_create(_len); + + for(var i = 0; i < _len; i++) + _vec[i] = processType( + lerp( + is_array(_f)? array_safe_get_fast(_f, i, 0) : _f, + is_array(_t)? array_safe_get_fast(_t, i, 0) : _t, + _lrp) + ); + return _vec; + } + + if(prop.type == VALUE_TYPE.text) + return processType(_f); + + return processType(lerp(_f, _t, _lrp)); + } #endregion + + static getName = function() { return prop.name + suffix; } + + static getValue = function(_time = CURRENT_FRAME) { #region + //if(!prop.is_anim) return staticValue; + length = ds_list_size(values); + + ///////////////////////////////////////////////////////////// TRIGGER TYPE ///////////////////////////////////////////////////////////// + + if(prop.type == VALUE_TYPE.trigger) { + if(length == 0 || !prop.is_anim) return false; + + if(array_length(key_map) != TOTAL_FRAMES) updateKeyMap(); + + return key_map[_time]; + } + + ///////////////////////////////////////////////////////////// OPTIMIZATION ///////////////////////////////////////////////////////////// + + if(length == 0) return processTypeDefault(); + if(length == 1) { + var _key = values[| 0]; + + if(_key.drivers.type && _time >= _key.time) + return processType(processDriver(_time, _key)); + + return processType(_key.value); + } + + if(prop.type == VALUE_TYPE.path) return processType(values[| 0].value); + if(!prop.is_anim) return processType(values[| 0].value); + var _len = max(TOTAL_FRAMES, values[| length - 1].time); + if(array_length(key_map) != _len) updateKeyMap(); + + var _time_first = prop.loop_range == -1? values[| 0].time : values[| length - 1 - prop.loop_range].time; + var _time_last = values[| length - 1].time; + var _time_dura = _time_last - _time_first; + + ////////////////////////////////////////////////////////////// LOOP TIME /////////////////////////////////////////////////////////////// + + if(_time > _time_last) { + switch(prop.on_end) { + case KEYFRAME_END.loop : + _time = _time_first + safe_mod(_time - _time_last, _time_dura + 1); + break; + case KEYFRAME_END.ping : + var time_in_loop = safe_mod(_time - _time_first, _time_dura * 2); + if(time_in_loop < _time_dura) + _time = _time_first + time_in_loop; + else + _time = _time_first + _time_dura * 2 - time_in_loop; + break; + } + } + + var _keyIndex; + if(_time >= _len) _keyIndex = 999_999; + else if(_time <= 0) _keyIndex = -1; + else _keyIndex = array_safe_get_fast(key_map, _time); + + //////////////////////////////////////////////////////////// BEFORE FIRST ////////////////////////////////////////////////////////////// + + if(_keyIndex == -1) { + if(prop.on_end == KEYFRAME_END.wrap) { + var from = values[| length - 1]; + var to = values[| 0]; + + var fTime = from.time; + var tTime = to.time; + + var prog = TOTAL_FRAMES - fTime + _time; + var totl = TOTAL_FRAMES - fTime + tTime; + + var rat = prog / totl; + var _lrp = interpolate(from, to, rat); + + return lerpValue(from, to, _lrp); + } + + return processType(values[| 0].value); //First frame + } + + ///////////////////////////////////////////////////////////// AFTER LAST /////////////////////////////////////////////////////////////// + + if(_keyIndex == 999_999) { + var _lstKey = values[| length - 1]; + + if(_lstKey.drivers.type) + return processType(processDriver(_time, _lstKey)); + + if(prop.on_end == KEYFRAME_END.wrap) { + var from = _lstKey; + var to = values[| 0]; + var prog = _time - from.time; + var totl = TOTAL_FRAMES - from.time + to.time; + + var rat = prog / totl; + var _lrp = interpolate(from, to, rat); + + return lerpValue(from, to, _lrp); + } + + return processType(_lstKey.value); //Last frame + } + + ///////////////////////////////////////////////////////////// INBETWEEN //////////////////////////////////////////////////////////////// + + var from = values[| _keyIndex]; + var to = values[| _keyIndex + 1]; + + var rat = (_time - from.time) / (to.time - from.time); + var _lrp = interpolate(from, to, rat); + + if(from.drivers.type) + return processDriver(_time, from, lerpValue(from, to, _lrp), rat); + + return lerpValue(from, to, _lrp); + + } #endregion + + static processTypeDefault = function() { #region + if(!sep_axis && typeArray(prop.display_type)) return []; + return 0; + } #endregion + + static processDriver = function(_time, _key, _val = undefined, _intp = 0) { #region + + static _processDriver = function(val, drivers, _t, _index = 0, _intp = 0) { + switch(drivers.type) { + case DRIVER_TYPE.linear : + return val + _t * drivers.speed; + + case DRIVER_TYPE.wiggle : + var w = perlin1D(_t, drivers.seed + _index, drivers.frequency / 10, drivers.octave, -1, 1) * drivers.amplitude; + return val + w; + + case DRIVER_TYPE.sine : + var w = sin((drivers.phase * (_index + 1) + _t * drivers.frequency / TOTAL_FRAMES) * pi * 2) * drivers.amplitude; + return val + w; + } + + return 0; + } + + var _dt = _time - _key.time; + _val = _val == undefined? _key.value : _val; + var _res = _val; + + if(prop.type == VALUE_TYPE.integer || prop.type == VALUE_TYPE.float) { + if(is_array(_val)) { + _res = array_create(array_length(_val)); + for( var i = 0, n = array_length(_val); i < n; i++ ) + _res[i] = is_numeric(_val[i])? _processDriver(_val[i], _key.drivers, _dt, _key.drivers.axis_sync? 0 : i, _intp) : _val[i]; + } else + _res = _processDriver(_val, _key.drivers, _dt, 0, _intp); + } + + return _res; + } #endregion + + static processType = function(_val) { #region + INLINE + + var _res = _val; + + if(!sep_axis && typeArray(prop.display_type) && is_array(_val)) { + for(var i = 0; i < array_length(_val); i++) + _res[i] = processValue(_val[i]); + } else + _res = processValue(_val); + + return _res; + } #endregion + + static processValue = function(_val) { #region + INLINE + + if(is_array(_val)) return _val; + if(is_struct(_val)) return _val; + //if(is_undefined(_val)) return 0; + + switch(prop.type) { + case VALUE_TYPE.integer : return prop.unit.mode == VALUE_UNIT.constant? round(_val) : _val; + case VALUE_TYPE.float : return _val; + case VALUE_TYPE.text : return is_string(_val)? _val : string_real(_val); + case VALUE_TYPE.color : return _val; + case VALUE_TYPE.surface : return is_string(_val)? get_asset(_val) : _val; + } + + return _val; + } #endregion + + static insertKey = function(_key, _index) { ds_list_insert(values, _index, _key); } + + static setKeyTime = function(_key, _time, _replace = true, record = false) { #region + if(!ds_list_exist(values, _key)) return 0; + if(_key.time == _time && !_replace) return 0; + + if(!LOADING) PROJECT.modified = true; + + var _prevTime = _key.time; + _time = max(_time, 0); + _key.setTime(_time); + ds_list_remove(values, _key); + + if(_replace) + for( var i = 0; i < ds_list_size(values); i++ ) { + if(values[| i].time != _time) continue; + + if(record) { + var act = new Action(ACTION_TYPE.custom, function(data) { + if(data.undo) insertKey(data.overKey, data.index); + updateKeyMap(); + + data.undo = !data.undo; + }, { overKey : values[| i], index : i, undo : true }); + mergeAction(act); + } + + values[| i] = _key; + updateKeyMap(); + return 2; + } + + for( var i = 0; i < ds_list_size(values); i++ ) { //insert key before the last key + if(values[| i].time < _time) continue; + + if(record) recordAction(ACTION_TYPE.custom, function(data) { + var _prevTime = data.key.time; + setKeyTime(data.key, data.time, false); + + data.time = _prevTime; + }, { key : _key, time : _prevTime }); + + ds_list_insert(values, i, _key); + if(_replace) updateKeyMap(); + return 1; + } + + if(record) recordAction(ACTION_TYPE.custom, function(data) { // insert key after the last key + var _prevTime = data.key.time; + setKeyTime(data.key, data.time, false); + + data.time = _prevTime; + }, { key : _key, time : _prevTime }); + + ds_list_add(values, _key); + if(_replace) updateKeyMap(); + return 1; + } #endregion + + static setValue = function(_val = 0, _record = true, _time = CURRENT_FRAME, ease_in = 0, ease_out = 0) { #region + //staticValue = _val; + + if(prop.type == VALUE_TYPE.trigger) { + if(!prop.is_anim) { + values[| 0] = new valueKey(0, _val, self); + updateKeyMap(); + return true; + } + + for(var i = 0; i < ds_list_size(values); i++) { //Find trigger + var _key = values[| i]; + if(_key.time == _time) { + if(!global.FLAG.keyframe_override) return false; + + _key.value = _val; + return false; + + } else if(_key.time > _time) { + ds_list_insert(values, i, new valueKey(_time, _val, self)); + updateKeyMap(); + return true; + } + } + + //print($"{_time}: {_val} | Insert last"); + ds_list_add(values, new valueKey(_time, _val, self)); + updateKeyMap(); + return true; + } + + if(!prop.is_anim) { + if(isEqual(values[| 0].value, _val)) + return false; + + if(_record) recordAction(ACTION_TYPE.var_modify, values[| 0], [ values[| 0].value, "value", prop.name ]); + + values[| 0].value = _val; + return true; + } + + if(ds_list_size(values) == 0) { // Should not be called normally + var k = new valueKey(_time, _val, self, ease_in, ease_out); + ds_list_add(values, k); + if(_record) recordAction(ACTION_TYPE.list_insert, values, [ k, ds_list_size(values) - 1, $"add {prop.name} keyframe" ], function() { updateKeyMap(); }); + return true; + } + + for(var i = 0; i < ds_list_size(values); i++) { + var _key = values[| i]; + if(_key.time == _time) { + if(!global.FLAG.keyframe_override) return false; + + if(_key.value != _val) { + if(_record) recordAction(ACTION_TYPE.var_modify, _key, [ _key.value, "value", prop.name ]); + _key.value = _val; + return true; + } + return false; + } else if(_key.time > _time) { + var k = new valueKey(_time, _val, self, ease_in, ease_out); + ds_list_insert(values, i, k); + if(_record) recordAction(ACTION_TYPE.list_insert, values, [k, i, $"add {prop.name} keyframe" ], function() { updateKeyMap(); }); + updateKeyMap(); + return true; + } + } + + var k = new valueKey(_time, _val, self, ease_in, ease_out); + if(_record) recordAction(ACTION_TYPE.list_insert, values, [ k, ds_list_size(values), $"add {prop.name} keyframe" ], function() { updateKeyMap(); }); + ds_list_add(values, k); + updateKeyMap(); + return true; + } #endregion + + static removeKey = function(key) { #region + if(ds_list_size(values) > 1) + ds_list_remove(values, key); + else + prop.is_anim = false; + updateKeyMap(); + } #endregion + + static serialize = function(scale = false) { #region + var _data = []; + + for(var i = 0; i < ds_list_size(values); i++) { + var _value_list = []; + if(scale) + _value_list[0] = values[| i].time / (TOTAL_FRAMES - 1); + else + _value_list[0] = values[| i].time; + + var val = values[| i].value; + + if(prop.type == VALUE_TYPE.struct) { + val = json_stringify(val); + + } else if(is_struct(val)) { + val = val.serialize(); + + } else if(!sep_axis && typeArray(prop.display_type) && is_array(val)) { + var __v = []; + for(var j = 0; j < array_length(val); j++) { + if(is_struct(val[j]) && struct_has(val[j], "serialize")) + array_push(__v, val[j].serialize()); + else + array_push(__v, val[j]); + } + val = __v; + + } + + _value_list[1] = val; + _value_list[2] = values[| i].ease_in; + _value_list[3] = values[| i].ease_out; + _value_list[4] = values[| i].ease_in_type; + _value_list[5] = values[| i].ease_out_type; + _value_list[6] = values[| i].ease_y_lock; + _value_list[7] = values[| i].drivers; + + array_push(_data, _value_list); + } + + return _data; + } #endregion + + static deserialize = function(_data, scale = false) { #region + ds_list_clear(values); + + if(prop.type == VALUE_TYPE.gradient && LOADING_VERSION < 1340 && !CLONING) { #region //backward compat: Gradient + var _val = []; + var value = _data[0][1]; + + if(is_array(value)) + for(var i = 0; i < array_length(value); i++) { + var _keyframe = value[i]; + var _t = struct_try_get(_keyframe, "time"); + var _v = struct_try_get(_keyframe, "value"); + + array_push(_val, new gradientKey(_t, _v)); + } + + var grad = new gradientObject(); + grad.keys = _val; + ds_list_add(values, new valueKey(0, grad, self)); + + updateKeyMap(); + return; + } #endregion + + var base = prop.def_val; + + for(var i = 0; i < array_length(_data); i++) { + var _keyframe = _data[i]; + var _time = array_safe_get_fast(_keyframe, 0); + + if(scale && _time <= 1) + _time = round(_time * (TOTAL_FRAMES - 1)); + + var value = array_safe_get_fast(_keyframe, 1); + var ease_in = array_safe_get_fast(_keyframe, 2); + var ease_out = array_safe_get_fast(_keyframe, 3); + var ease_in_type = array_safe_get_fast(_keyframe, 4); + var ease_out_type = array_safe_get_fast(_keyframe, 5); + var ease_y_lock = array_safe_get_fast(_keyframe, 6, true); + var driver = array_safe_get_fast(_keyframe, 7, {}); + + var _val = value; + + if(prop.type == VALUE_TYPE.struct) + _val = json_try_parse(value); + + else if(prop.type == VALUE_TYPE.path && prop.display_type == VALUE_DISPLAY.path_array) { + for(var j = 0; j < array_length(value); j++) + _val[j] = value[j]; + + } else if(prop.type == VALUE_TYPE.gradient) { + var grad = new gradientObject(); + _val = grad.deserialize(value); + + } else if(prop.type == VALUE_TYPE.d3Material) { + var mat = new __d3dMaterial(); + _val = mat.deserialize(value); + + } else if(prop.type == VALUE_TYPE.color) { + if(is_array(_val)) { + for( var i = 0, n = array_length(_val); i < n; i++ ) + _val[i] = LOADING_VERSION < 11640 && !is_int64(_val[i])? cola(_val[i]) : int64(_val[i]); + } else + _val = LOADING_VERSION < 11640 && !is_int64(_val)? cola(_val) : int64(_val); + + } else if(!sep_axis && typeArray(prop.display_type)) { + _val = []; + + if(is_array(value)) { + for(var j = 0; j < array_length(value); j++) + _val[j] = processValue(value[j]); + } else if(is_array(base)) { + for(var j = 0; j < array_length(base); j++) + _val[j] = processValue(value); + } + } + + //print($"Deserialize {prop.node.name}:{prop.name} = {_val} "); + var vk = new valueKey(_time, _val, self, ease_in, ease_out); + vk.ease_in_type = ease_in_type; + vk.ease_out_type = ease_out_type; + vk.ease_y_lock = ease_y_lock; + struct_override(vk.drivers, driver); + + ds_list_add(values, vk); + } + + //staticValue = ds_list_empty(values)? 0 : values[| 0].value; + updateKeyMap(); + } #endregion + + static cleanUp = function() { #region + ds_list_destroy(values); + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_palette/node_palette.gml.backup0 b/#backups/scripts/node_palette/node_palette.gml.backup0 new file mode 100644 index 000000000..842cc3132 --- /dev/null +++ b/#backups/scripts/node_palette/node_palette.gml.backup0 @@ -0,0 +1,53 @@ +// 2024-04-20 09:44:05 +function Node_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "Palette"; + setDimension(96); + + inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) + .setDisplay(VALUE_DISPLAY.palette); + + inputs[| 1] = nodeValue("Trim range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 1 ]) + .setDisplay(VALUE_DISPLAY.slider_range); + + outputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.output, VALUE_TYPE.color, []) + .setDisplay(VALUE_DISPLAY.palette); + + input_display_list = [0, + ["Trim", true], 1 + ]; + + static processData = function(_outSurf, _data, _output_index, _array_index) { #region + var pal = _data[0]; + var ran = _data[1]; + + var st = floor(clamp(min(ran[0], ran[1]), 0, 1) * array_length(pal)); + var en = floor(clamp(max(ran[0], ran[1]), 0, 1) * array_length(pal)); + var ar = []; + + for( var i = st; i < en; i++ ) + ar[i - st] = array_safe_get_fast(pal, i); + + return ar; + } #endregion + + static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region + var bbox = drawGetBbox(xx, yy, _s); + if(bbox.h < 1) return; + + var pal = outputs[| 0].getValue(); + if(array_empty(pal)) return; + if(!is_array(pal[0])) pal = [ pal ]; + + var _h = array_length(pal) * 32; + var _y = bbox.y0; + var gh = bbox.h / array_length(pal); + + for( var i = 0, n = array_length(pal); i < n; i++ ) { + drawPalette(pal[i], bbox.x0, _y, bbox.w, gh); + _y += gh; + } + + if(_h != min_h) will_setHeight = true; + min_h = _h; + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_palette/node_palette.gml.backup1 b/#backups/scripts/node_palette/node_palette.gml.backup1 new file mode 100644 index 000000000..76853dc19 --- /dev/null +++ b/#backups/scripts/node_palette/node_palette.gml.backup1 @@ -0,0 +1,63 @@ +// 2024-04-20 09:23:40 +function Node_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "Palette"; + setDimension(96); + + inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) + .setDisplay(VALUE_DISPLAY.palette); + + var p = ""; + var pl = inputs[| 0].animator.values[| 0].value; + for (var i = 0, n = array_length(pl); i < n; i++) p += number_to_hex(pl[i]) + ", "; + print(p); + + var p = ""; + var pl = DEF_PALETTE; + for (var i = 0, n = array_length(pl); i < n; i++) p += number_to_hex(pl[i]) + ", "; + print(p); + + inputs[| 1] = nodeValue("Trim range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 1 ]) + .setDisplay(VALUE_DISPLAY.slider_range); + + outputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.output, VALUE_TYPE.color, []) + .setDisplay(VALUE_DISPLAY.palette); + + input_display_list = [0, + ["Trim", true], 1 + ]; + + static processData = function(_outSurf, _data, _output_index, _array_index) { #region + var pal = _data[0]; + var ran = _data[1]; + + var st = floor(clamp(min(ran[0], ran[1]), 0, 1) * array_length(pal)); + var en = floor(clamp(max(ran[0], ran[1]), 0, 1) * array_length(pal)); + var ar = []; + + for( var i = st; i < en; i++ ) + ar[i - st] = array_safe_get_fast(pal, i); + + return ar; + } #endregion + + static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region + var bbox = drawGetBbox(xx, yy, _s); + if(bbox.h < 1) return; + + var pal = outputs[| 0].getValue(); + if(array_empty(pal)) return; + if(!is_array(pal[0])) pal = [ pal ]; + + var _h = array_length(pal) * 32; + var _y = bbox.y0; + var gh = bbox.h / array_length(pal); + + for( var i = 0, n = array_length(pal); i < n; i++ ) { + drawPalette(pal[i], bbox.x0, _y, bbox.w, gh); + _y += gh; + } + + if(_h != min_h) will_setHeight = true; + min_h = _h; + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/node_value/node_value.gml.backup0 b/#backups/scripts/node_value/node_value.gml.backup0 index 653af2d96..d1f3bb594 100644 --- a/#backups/scripts/node_value/node_value.gml.backup0 +++ b/#backups/scripts/node_value/node_value.gml.backup0 @@ -1,4 +1,14 @@ -// 2023-08-08 15:35:35 +// 2024-04-20 09:57:04 +#region ---- global names ---- + global.junctionEndName = [ "Hold", "Loop", "Ping pong", "Wrap" ]; + + global.displaySuffix_Range = [ "min", "max" ]; + global.displaySuffix_Area = [ "x", "y", "w", "h", "shape" ]; + global.displaySuffix_Padding = [ "right", "top", "left", "bottom" ]; + global.displaySuffix_VecRange = [ "x min", "x max", "y min", "y max" ]; + global.displaySuffix_Axis = [ "x", "y", "z", "w" ]; +#endregion + enum JUNCTION_CONNECT { input, output @@ -23,7 +33,7 @@ enum VALUE_TYPE { pathnode = 12, particle = 13, rigid = 14, - fdomain = 15, + sdomain = 15, struct = 16, strands = 17, mesh = 18, @@ -37,11 +47,25 @@ enum VALUE_TYPE { pbBox = 25, + d3Mesh = 26, + d3Light = 27, + d3Camera = 28, + d3Scene = 29, + d3Material = 30, + + dynaSurface = 31, + PCXnode = 32, + + audioBit = 33, + + fdomain = 34, + action = 99, } enum VALUE_DISPLAY { _default, + none, range, //Int @@ -49,6 +73,7 @@ enum VALUE_DISPLAY { enum_button, rotation, rotation_range, + rotation_random, slider, slider_range, @@ -60,9 +85,12 @@ enum VALUE_DISPLAY { vector, vector_range, area, - kernel, transform, corner, + toggle, + matrix, + path_anchor, + gradient_range, //Curve curve, @@ -76,62 +104,151 @@ enum VALUE_DISPLAY { path_array, //Text - export_format, - code, - node_title, + codeLUA, + codeHLSL, text_array, + text_box, + text_tunnel, //path path_save, path_load, path_font, - //vertex + //d3d d3vertex, + d3quarternion, } -function value_color(i) { +enum KEYFRAME_END { + hold, + loop, + ping, + wrap, +} + +enum VALIDATION { + pass, + warning, + error +} + +enum VALUE_UNIT { + constant, + reference +} + +enum VALUE_TAG { + updateInTrigger = -2, + updateOutTrigger = -3, + none = 0 +} + +enum LINE_STYLE { + solid, + dashed +} + +function value_color(i) { #region static JUNCTION_COLORS = [ - $6691ff, //int - $78e4ff, //float - $5d3f8c, //bool - $5dde8f, //color - $976bff, //surface - $4b00eb, //path - $d1c2c2, //curve - $e3ff66, //text - $b5b5ff, //object - $ffa64d, //node + #ff9166, //int + #ffe478, //float + #8c3f5d, //bool + #8fde5d, //color + #ff6b97, //surface + #eb004b, //path + #c2c2d1, //curve + #66ffe3, //text + #ffb5b5, //object + #4da6ff, //node #c1007c, //3D - $808080, //any - $b5b5ff, //path - $5dde8f, //particle - $e3ff66, //rigid - #4da6ff, //fdomain - $5d3f8c, //struct - $6691ff, //strand - $d1c2c2, //mesh - $5dde8f, //trigger - $976bff, //atlas + #808080, //any + #ffb5b5, //path + #8fde5d, //particle + #88ffe9, //rigid + #6d6e71, //sdomain + #8c3f5d, //struct + #ff9166, //strand + #c2c2d1, //mesh + #8fde5d, //trigger + #ff6b97, //atlas #c1007c, //d3vertex - $5dde8f, //gradient - $6691ff, //armature - $808080, //buffer - $976bff, //pbBox + #8fde5d, //gradient + #ff9166, //armature + #808080, //buffer + #ff6b97, //pbBox + #4da6ff, //d3Mesh + #4da6ff, //d3Light + #4da6ff, //d3Camera + #4da6ff, //d3Scene + #ff6b97, //d3Material + #ff6b97, //dynaSurf + #c2c2d1, //PCX + #8fde5d, //audiobit + #4da6ff, //flipfluid + ]; + static JUNCTION_COLORS_LENGTH = array_length(JUNCTION_COLORS); + + if(i == 99) return #8fde5d; + + return JUNCTION_COLORS[i]; +} #endregion + +function value_color_bg(i) { #region + return #3b3b4e; +} #endregion + +function value_color_bg_array(i) { #region + static JUNCTION_COLORS = [ + #e36956, //int + #ff9166, //float + #5e315b, //bool + #3ca370, //color + #bd4882, //surface + #bb003c, //path + #83839b, //curve + #4da6ff, //text + #e28989, //object + #4b5bab, //node + #64003f, //3D + #4d4d4d, //any + #e28989, //path + #3ca370, //particle + #4da6ff, //rigid + #4b5bab, //sdomain + #5e315b, //struct + #e36956, //strand + #83839b, //mesh + #3ca370, //trigger + #9e2a69, //atlas + #64003f, //d3vertex + #3ca370, //gradient + #e36956, //armature + #4d4d4d, //buffer + #bd4882, //pbBox + #4b5bab, //d3Mesh + #4b5bab, //d3Light + #4b5bab, //d3Camera + #4b5bab, //d3Scene + #bd4882, //d3Material + #bd4882, //dynaSurf + #83839b, //PCX + #3ca370, //audiobit ]; if(i == 99) return $5dde8f; return JUNCTION_COLORS[safe_mod(max(0, i), array_length(JUNCTION_COLORS))]; -} +} #endregion -function value_bit(i) { +function value_bit(i) { #region switch(i) { case VALUE_TYPE.integer : return 1 << 0 | 1 << 1; case VALUE_TYPE.float : return 1 << 2 | 1 << 1; case VALUE_TYPE.boolean : return 1 << 3 | 1 << 1; case VALUE_TYPE.color : return 1 << 4; case VALUE_TYPE.gradient : return 1 << 25; - case VALUE_TYPE.surface : return 1 << 5; + case VALUE_TYPE.dynaSurface : + case VALUE_TYPE.surface : return 1 << 5 | 1 << 23; case VALUE_TYPE.path : return 1 << 10; case VALUE_TYPE.text : return 1 << 10; case VALUE_TYPE.object : return 1 << 13; @@ -141,11 +258,10 @@ function value_bit(i) { case VALUE_TYPE.pathnode : return 1 << 15; case VALUE_TYPE.particle : return 1 << 16; case VALUE_TYPE.rigid : return 1 << 17; - case VALUE_TYPE.fdomain : return 1 << 18; + case VALUE_TYPE.sdomain : return 1 << 18; case VALUE_TYPE.struct : return 1 << 19; case VALUE_TYPE.strands : return 1 << 20; case VALUE_TYPE.mesh : return 1 << 21; - case VALUE_TYPE.atlas : return 1 << 23; case VALUE_TYPE.armature : return 1 << 26 | 1 << 19; case VALUE_TYPE.node : return 1 << 32; @@ -157,12 +273,22 @@ function value_bit(i) { case VALUE_TYPE.trigger : return 1 << 22; case VALUE_TYPE.action : return 1 << 22 | 1 << 3; + case VALUE_TYPE.d3Mesh : return 1 << 29; + case VALUE_TYPE.d3Light : return 1 << 29; + case VALUE_TYPE.d3Camera : return 1 << 29; + case VALUE_TYPE.d3Scene : return 1 << 29 | 1 << 30; + case VALUE_TYPE.d3Material : return 1 << 33; + + case VALUE_TYPE.PCXnode : return 1 << 34; + case VALUE_TYPE.audioBit : return 1 << 35; + case VALUE_TYPE.fdomain : return 1 << 36; + case VALUE_TYPE.any : return ~0 & ~(1 << 32); } return 0; -} +} #endregion -function value_type_directional(f, t) { +function value_type_directional(f, t) { #region if(f == VALUE_TYPE.surface && t == VALUE_TYPE.integer) return true; if(f == VALUE_TYPE.surface && t == VALUE_TYPE.float) return true; @@ -178,24 +304,83 @@ function value_type_directional(f, t) { if(f == VALUE_TYPE.strands && t == VALUE_TYPE.pathnode ) return true; - if(f == VALUE_TYPE.color && t == VALUE_TYPE.struct ) return true; - if(f == VALUE_TYPE.mesh && t == VALUE_TYPE.struct ) return true; + if(f == VALUE_TYPE.color && t == VALUE_TYPE.struct ) return true; + if(f == VALUE_TYPE.mesh && t == VALUE_TYPE.struct ) return true; + if(f == VALUE_TYPE.particle && t == VALUE_TYPE.struct ) return true; + + if(f == VALUE_TYPE.surface && t == VALUE_TYPE.d3Material ) return true; return false; -} +} #endregion -function typeArray(_type) { +function value_type_from_string(str) { #region + switch(str) { + case "integer" : return VALUE_TYPE.integer; + case "float" : return VALUE_TYPE.float; + case "boolean" : return VALUE_TYPE.boolean; + case "color" : return VALUE_TYPE.color; + case "surface" : return VALUE_TYPE.surface; + + case "path" : return VALUE_TYPE.path; + case "curve" : return VALUE_TYPE.curve; + case "text" : return VALUE_TYPE.text; + case "object" : return VALUE_TYPE.object; + case "node" : return VALUE_TYPE.node; + case "d3object" : return VALUE_TYPE.d3object; + + case "any" : return VALUE_TYPE.any; + + case "pathnode" : return VALUE_TYPE.pathnode; + case "particle" : return VALUE_TYPE.particle; + case "rigid" : return VALUE_TYPE.rigid; + case "sdomain" : return VALUE_TYPE.sdomain; + case "struct" : return VALUE_TYPE.struct; + case "strands" : return VALUE_TYPE.strands; + case "mesh" : return VALUE_TYPE.mesh; + case "trigger" : return VALUE_TYPE.trigger; + case "atlas" : return VALUE_TYPE.atlas; + + case "d3vertex" : return VALUE_TYPE.d3vertex; + case "gradient" : return VALUE_TYPE.gradient; + case "armature" : return VALUE_TYPE.armature; + case "buffer" : return VALUE_TYPE.buffer; + + case "pbBox" : return VALUE_TYPE.pbBox; + + case "d3Mesh" : return VALUE_TYPE.d3Mesh; + case "d3Light" : return VALUE_TYPE.d3Light; + case "d3Camera" : return VALUE_TYPE.d3Camera; + case "d3Scene" : return VALUE_TYPE.d3Scene; + case "d3Material" : return VALUE_TYPE.d3Material; + + case "dynaSurface" : return VALUE_TYPE.dynaSurface; + case "PCXnode" : return VALUE_TYPE.PCXnode; + + case "audioBit" : return VALUE_TYPE.audioBit; + + case "fDomain" : return VALUE_TYPE.fdomain; + + case "action" : return VALUE_TYPE.action; + } + + return VALUE_TYPE.any; +} #endregion + +function typeArray(_type) { #region switch(_type) { case VALUE_DISPLAY.range : case VALUE_DISPLAY.vector_range : case VALUE_DISPLAY.rotation_range : + case VALUE_DISPLAY.rotation_random : case VALUE_DISPLAY.slider_range : + case VALUE_DISPLAY.path_anchor : + case VALUE_DISPLAY.gradient_range : case VALUE_DISPLAY.vector : case VALUE_DISPLAY.padding : case VALUE_DISPLAY.area : case VALUE_DISPLAY.puppet_control : - case VALUE_DISPLAY.kernel : + case VALUE_DISPLAY.matrix : case VALUE_DISPLAY.transform : case VALUE_DISPLAY.curve : @@ -205,33 +390,25 @@ function typeArray(_type) { case VALUE_DISPLAY.text_array : case VALUE_DISPLAY.d3vertex : + case VALUE_DISPLAY.d3quarternion : return 1; } return 0; -} +} #endregion -function typeArrayDynamic(_type) { - switch(_type) { - case VALUE_DISPLAY.curve : - case VALUE_DISPLAY.palette : - return true; - } - return false; -} - -function typeCompatible(fromType, toType, directional_cast = true) { +function typeCompatible(fromType, toType, directional_cast = true) { #region if(value_bit(fromType) & value_bit(toType) != 0) return true; if(!directional_cast) return false; return value_type_directional(fromType, toType); -} +} #endregion -function typeIncompatible(from, to) { +function typeIncompatible(from, to) { #region if(from.type == VALUE_TYPE.surface && (to.type == VALUE_TYPE.integer || to.type == VALUE_TYPE.float)) { switch(to.display_type) { case VALUE_DISPLAY.area : - case VALUE_DISPLAY.kernel : + case VALUE_DISPLAY.matrix : case VALUE_DISPLAY.vector_range : case VALUE_DISPLAY.puppet_control : case VALUE_DISPLAY.padding : @@ -241,30 +418,9 @@ function typeIncompatible(from, to) { } return false; -} +} #endregion -enum KEYFRAME_END { - hold, - loop, - ping, - wrap, -} - -globalvar ON_END_NAME; -ON_END_NAME = [ "Hold", "Loop", "Ping pong", "Wrap" ]; - -enum VALIDATION { - pass, - warning, - error -} - -enum VALUE_UNIT { - constant, - reference -} - -function isGraphable(prop) { +function isGraphable(prop) { #region if(prop.type == VALUE_TYPE.integer || prop.type == VALUE_TYPE.float) { if(prop.display_type == VALUE_DISPLAY.puppet_control) return false; @@ -274,206 +430,305 @@ function isGraphable(prop) { return true; return false; -} +} #endregion -function nodeValueUnit(value) constructor { - self.value = value; +function nodeValueUnit(_nodeValue) constructor { #region + self._nodeValue = _nodeValue; mode = VALUE_UNIT.constant; reference = noone; triggerButton = button(function() { mode = !mode; - value.cache_value[0] = false; - value.unitConvert(mode); - value.node.doUpdate(); + _nodeValue.cache_value[0] = false; + _nodeValue.unitConvert(mode); + _nodeValue.node.doUpdate(); }); triggerButton.icon_blend = COLORS._main_icon_light; - triggerButton.icon = THEME.unit_ref; + triggerButton.icon = THEME.unit_ref; + triggerButton.tooltip = new tooltipSelector("Unit", ["Pixel", "Fraction"]); - static setMode = function(type) { + static setMode = function(type) { #region if(type == "constant" && mode == VALUE_UNIT.constant) return; if(type == "relative" && mode == VALUE_UNIT.reference) return; mode = type == "constant"? VALUE_UNIT.constant : VALUE_UNIT.reference; - value.cache_value[0] = false; - value.unitConvert(mode); - value.node.doUpdate(); - } + _nodeValue.cache_value[0] = false; + _nodeValue.unitConvert(mode); + _nodeValue.node.doUpdate(); + } #endregion - static draw = function(_x, _y, _w, _h, _m) { + static draw = function(_x, _y, _w, _h, _m) { #region triggerButton.icon_index = mode; - triggerButton.tooltip = (mode? "Fraction" : "Pixel") + " unit"; + triggerButton.tooltip.index = mode; triggerButton.draw(_x, _y, _w, _h, _m, THEME.button_hide); - } + } #endregion - static invApply = function(value, index = 0) { + static invApply = function(value, index = 0) { #region if(mode == VALUE_UNIT.constant) return value; if(reference == noone) return value; return convertUnit(value, VALUE_UNIT.reference, index); - } + } #endregion - static apply = function(value, index = 0) { - if(mode == VALUE_UNIT.constant) - return value; - if(reference == noone) - return value; + static apply = function(value, index = 0) { #region + if(mode == VALUE_UNIT.constant) return value; + if(reference == noone) return value; return convertUnit(value, VALUE_UNIT.constant, index); - } + } #endregion - static convertUnit = function(value, unitTo, index = 0) { - var disp = self.value.display_type; + static convertUnit = function(value, unitTo, index = 0) { #region + var disp = _nodeValue.display_type; var base = reference(index); - var inv = unitTo == VALUE_UNIT.reference; + var inv = unitTo == VALUE_UNIT.reference; if(!is_array(base) && !is_array(value)) return inv? value / base : value * base; if(!is_array(base) && is_array(value)) { + var _val = array_create(array_length(value)); for( var i = 0, n = array_length(value); i < n; i++ ) - value[i] = inv? value[i] / base : value[i] * base; - return value; + _val[i] = inv? value[i] / base : value[i] * base; + return _val; } - if(is_array(base) && !is_array(value)) { + if(is_array(base) && !is_array(value)) return value; - } + var _val = array_create(array_length(value)); + switch(disp) { case VALUE_DISPLAY.padding : case VALUE_DISPLAY.vector : case VALUE_DISPLAY.vector_range : for( var i = 0, n = array_length(value); i < n; i++ ) - value[i] = inv? value[i] / base[i % 2] : value[i] * base[i % 2]; - return value; + _val[i] = inv? value[i] / base[i % 2] : value[i] * base[i % 2]; + return _val; case VALUE_DISPLAY.area : for( var i = 0; i < 4; i++ ) - value[i] = inv? value[i] / base[i % 2] : value[i] * base[i % 2]; - return value; + _val[i] = inv? value[i] / base[i % 2] : value[i] * base[i % 2]; + return _val; } return value; - } -} + } #endregion +} #endregion -global.displaySuffix_Range = [ "min", "max" ]; -global.displaySuffix_Area = [ "x", "y", "w", "h" ]; -global.displaySuffix_Padding = [ "right", "top", "left", "bottom" ]; -global.displaySuffix_VecRange = [ "x min", "x max", "y min", "y max" ]; -global.displaySuffix_Axis = [ "x", "y", "z", "w"]; - -function nodeValue(_name, _node, _connect, _type, _value, _tooltip = "") { - return new NodeValue(_name, _node, _connect, _type, _value, _tooltip); -} +function nodeValue(_name, _node, _connect, _type, _value, _tooltip = "") { return new NodeValue(_name, _node, _connect, _type, _value, _tooltip); } +function nodeValueMap(_name, _node, _junc = noone) { return new NodeValue(_name, _node, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone).setVisible(false, false).setMapped(_junc); } +function nodeValueGradientRange(_name, _node, _junc = noone) { return new NodeValue(_name, _node, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 1, 0 ]).setDisplay(VALUE_DISPLAY.gradient_range).setVisible(false, false).setMapped(_junc); } function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constructor { - node = _node; - x = node.x; - y = node.y; - index = _connect == JUNCTION_CONNECT.input? ds_list_size(node.inputs) : ds_list_size(node.outputs); - type = _type; - forward = true; + static DISPLAY_DATA_KEYS = [ "linked", "angle_display", "bone_id", "unit", "atlas_crop" ]; - _initName = _name; - name = __txt_junction_name(instanceof(node), type, index, _name); - name = _name; + #region ---- main ---- + active = true; + node = _node; + x = node.x; + y = node.y; + index = _connect == JUNCTION_CONNECT.input? ds_list_size(node.inputs) : ds_list_size(node.outputs); + type = _type; + forward = true; + _initName = _name; + + node.will_setHeight = true; + + static updateName = function(_name) { + name = _name; + internalName = string_to_var(name); + name_custom = true; + } updateName(_name); + + name_custom = false; + + switch(type) { + case VALUE_TYPE.PCXnode : + accept_array = false; + break; + } + + if(struct_has(node, "inputMap")) { + if(_connect == JUNCTION_CONNECT.input) node.inputMap[? internalName] = self; + else if(_connect == JUNCTION_CONNECT.output) node.outputMap[? internalName] = self; + } + + tooltip = _tooltip; + editWidget = noone; + editWidgetRaw = noone; + graphWidget = noone; + graphWidgetH = 0; + graphWidgetP = new widgetParam(0, 0, 0, 0, 0); + mapWidget = noone; + active_tooltip = ""; + + tags = VALUE_TAG.none; + #endregion - static updateName = function() { - internalName = string_lower(string_replace_all(name, " ", "_")); - } updateName(); + #region ---- connection ---- + connect_type = _connect; + value_from = noone; + value_from_loop = noone; + + value_to = []; + value_to_loop = []; + + accept_array = true; + array_depth = 0; + auto_connect = true; + setFrom_condition = -1; + + onSetFrom = noone; + onSetTo = noone; + #endregion - if(struct_has(node, "inputMap")) { - if(_connect == JUNCTION_CONNECT.input) node.inputMap[? internalName] = self; - else if(_connect == JUNCTION_CONNECT.output) node.outputMap[? internalName] = self; - } + #region ---- animation ---- + if(_type == VALUE_TYPE.color) { + if(is_array(_value)) { + for( var i = 0, n = array_length(_value); i < n; i++ ) + _value[i] = cola(_value[i], _color_get_alpha(_value[i])); + } else + _value = cola(_value, _color_get_alpha(_value)); + } + + key_inter = CURVE_TYPE.linear; + + is_anim = false; + sep_axis = false; + animable = true; + sepable = is_array(_value) && array_length(_value) > 1; + animator = new valueAnimator(_value, self, false); + animators = []; + + if(is_array(_value)) + for( var i = 0, n = array_length(_value); i < n; i++ ) { + animators[i] = new valueAnimator(_value[i], self, true); + animators[i].index = i; + } + + on_end = KEYFRAME_END.hold; + loop_range = -1; + #endregion - tooltip = _tooltip; - editWidget = noone; + #region ---- value ---- + def_val = _value; + def_length = is_array(def_val)? array_length(def_val) : 0; + def_depth = array_get_depth(def_val); + unit = new nodeValueUnit(self); + def_unit = VALUE_UNIT.constant; + dyna_depo = ds_list_create(); + value_tag = ""; + + is_modified = false; + cache_value = [ false, false, undefined, undefined ]; + cache_array = [ false, false ]; + use_cache = true; + + process_array = true; + dynamic_array = false; + validateValue = true; + runInUI = false; + + fullUpdate = false; + + attributes = {}; + + node.inputs_data[index] = _value; + node.input_value_map[$ internalName] = _value; + + __curr_get_val = [ 0, 0 ]; + #endregion - connect_type = _connect; - value_from = noone; - value_to = ds_list_create(); - value_to_arr = []; - accept_array = true; - array_depth = 0; - auto_connect = true; - setFrom_condition = -1; + #region ---- draw ---- + draw_line_shift_x = 0; + draw_line_shift_y = 0; + draw_line_thick = 1; + draw_line_shift_hover = false; + draw_line_blend = 1; + draw_line_feed = false; + drawLineIndex = 1; + draw_line_vb = noone; + draw_junction_index = type; + + junction_drawing = [ THEME.node_junctions_single, type ]; + hover_in_graph = false; + + drag_type = 0; + drag_mx = 0; + drag_my = 0; + drag_sx = 0; + drag_sy = 0; + + color = -1; + color_display = 0; + + draw_bg = c_black; + draw_fg = c_black; + + draw_blend = 1; + draw_blend_color = 1; + #endregion - is_anim = false; - sep_axis = false; - sepable = is_array(_value) && array_length(_value) > 1; - animator = new valueAnimator(_value, self, false); - animators = []; - if(is_array(_value)) - for( var i = 0, n = array_length(_value); i < n; i++ ) { - animators[i] = new valueAnimator(_value[i], self, true); - animators[i].index = i; - } + #region ---- timeline ---- + show_graph = false; + graph_h = ui(64); + #endregion - def_val = _value; - on_end = KEYFRAME_END.hold; - loop_range = -1; + #region ---- inspector ---- + visible = _connect == JUNCTION_CONNECT.output || _type == VALUE_TYPE.surface || _type == VALUE_TYPE.path || _type == VALUE_TYPE.PCXnode; + show_in_inspector = true; + visible_in_list = true; - unit = new nodeValueUnit(self); - extra_data = {}; - dyna_depo = ds_list_create(); + display_type = VALUE_DISPLAY._default; + if(_type == VALUE_TYPE.curve) display_type = VALUE_DISPLAY.curve; + else if(_type == VALUE_TYPE.d3vertex) display_type = VALUE_DISPLAY.d3vertex; + + display_data = {}; + display_attribute = noone; + + popup_dialog = noone; + #endregion - draw_line_shift_x = 0; - draw_line_shift_y = 0; - draw_line_thick = 1; - draw_line_shift_hover = false; - drawLineIndex = 1; - draw_line_vb = noone; + #region ---- graph ---- + value_validation = VALIDATION.pass; + error_notification = noone; + + extract_node = ""; + #endregion - show_graph = false; - graph_h = ui(64); + #region ---- expression ---- + expUse = false; + expression = ""; + expTree = noone; + expContext = { + name: name, + node_name: node.display_name, + value: 0, + node_values: node.input_value_map, + }; + + express_edit = new textArea(TEXTBOX_INPUT.text, function(str) { + expression = str; + expressionUpdate(); + }); + express_edit.autocomplete_server = pxl_autocomplete_server; + express_edit.autocomplete_context = expContext; + express_edit.function_guide_server = pxl_function_guide_server; + express_edit.parser_server = pxl_document_parser; + express_edit.format = TEXT_AREA_FORMAT.codeLUA; + express_edit.font = f_code; + express_edit.boxColor = COLORS._main_value_positive; + express_edit.align = fa_left; + #endregion - visible = _connect == JUNCTION_CONNECT.output || _type == VALUE_TYPE.surface || _type == VALUE_TYPE.path; - show_in_inspector = true; + #region ---- serialization ---- + con_node = -1; + con_index = -1; + #endregion - display_type = VALUE_DISPLAY._default; - if(_type == VALUE_TYPE.curve) display_type = VALUE_DISPLAY.curve; - else if(_type == VALUE_TYPE.d3vertex) display_type = VALUE_DISPLAY.d3vertex; - - display_data = -1; - display_attribute = noone; - - value_validation = VALIDATION.pass; - error_notification = noone; - - extract_node = ""; - - is_changed = true; - cache_value = [ false, false, undefined ]; - cache_array = [ false, false ]; - use_cache = true; - - expUse = false; - expression = ""; - expTree = noone; - - express_edit = new textArea(TEXTBOX_INPUT.text, function(str) { - expression = str; - expressionUpdate(); - }); - express_edit.autocomplete_server = pxl_autocomplete_server; - express_edit.function_guide_server = pxl_function_guide_server; - express_edit.parser_server = pxl_document_parser; - express_edit.format = TEXT_AREA_FORMAT.code; - express_edit.font = f_code; - express_edit.boxColor = COLORS._main_value_positive; - express_edit.align = fa_left; - - process_array = true; - validateValue = true; - - fullUpdate = false; - - static setDefault = function(vals) { + static setDefault = function(vals) { #region if(LOADING || APPENDING) return self; ds_list_clear(animator.values); @@ -481,79 +736,121 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru ds_list_add(animator.values, new valueKey(vals[i][0], vals[i][1], animator)); return self; - } + } #endregion - static resetValue = function() { setValue(def_val); } + static getName = function() { #region + if(name_custom) return name; + return __txt_junction_name(instanceof(node), connect_type, index, name); + } #endregion - static setUnitRef = function(ref, mode = VALUE_UNIT.constant) { + static setName = function(_name) { #region + INLINE + name = _name; + return self; + } #endregion + + static setActive = function(_active, _tooltip) { #region + INLINE + active = _active; + active_tooltip = _tooltip; + + return self; + } #endregion + + static setWindows = function() { #region + INLINE + setActive(OS == os_windows, "Not available on MacOS"); + + return self; + } #endregion + + static resetValue = function() { #region + unit.mode = def_unit; + setValue(unit.apply(def_val)); + attributes.mapped = false; + + is_modified = false; + } #endregion + + static setUnitRef = function(ref, mode = VALUE_UNIT.constant) { #region unit.reference = ref; unit.mode = mode; + def_unit = mode; cache_value[0] = false; return self; - } + } #endregion - static setVisible = function(inspector) { + static setVisible = function(inspector) { #region if(connect_type == JUNCTION_CONNECT.input) { show_in_inspector = inspector; visible = argument_count > 1? argument[1] : visible; } else visible = inspector; - + node.will_setHeight = true; return self; - } + } #endregion - static setDisplay = function(_type = VALUE_DISPLAY._default, _data = -1, _attr = noone) { + static setDisplay = function(_type = VALUE_DISPLAY._default, _data = {}) { #region display_type = _type; display_data = _data; - display_attribute = _attr; resetDisplay(); return self; - } + } #endregion - static rejectArray = function() { + static setAnimable = function(_anim) { #region + animable = _anim; + return self; + } #endregion + + static rejectArray = function() { #region accept_array = false; return self; - } + } #endregion - static uncache = function() { + static uncache = function() { #region use_cache = false; return self; - } + } #endregion - static setArrayDepth = function(aDepth) { + static setArrayDepth = function(aDepth) { #region array_depth = aDepth; return self; - } + } #endregion - static rejectConnect = function() { + static setArrayDynamic = function() { #region + dynamic_array = true; + return self; + } #endregion + + static rejectConnect = function() { #region auto_connect = false; return self; - } + } #endregion - static rejectArrayProcess = function() { + static rejectArrayProcess = function() { #region process_array = false; return self; - } + } #endregion - static nonForward = function() { + static nonForward = function() { #region forward = false; return self; - } + } #endregion - static nonValidate = function() { + static nonValidate = function() { #region validateValue = false; return self; - } + } #endregion - static isAnimable = function() { - //if(type == VALUE_TYPE.gradient) return false; + static isAnimable = function() { #region + if(type == VALUE_TYPE.PCXnode) return false; if(display_type == VALUE_DISPLAY.text_array) return false; - return true; - } + return animable; + } #endregion - static setDropKey = function() { + static setDropKey = function() { #region switch(type) { case VALUE_TYPE.integer : drop_key = "Number"; break; case VALUE_TYPE.float : drop_key = "Number"; break; @@ -573,17 +870,26 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru default: drop_key = "None"; } - } - setDropKey(); + } setDropKey(); #endregion - static resetDisplay = function() { + static resetDisplay = function() { #region //////////////////// RESET DISPLAY //////////////////// editWidget = noone; switch(display_type) { - case VALUE_DISPLAY.button : - editWidget = button(display_data[0]); - editWidget.text = display_data[1]; + case VALUE_DISPLAY.button : #region + var _onClick; + + if(struct_has(display_data, "onClick")) + _onClick = method(node, display_data.onClick); + else + _onClick = function() { setAnim(true); setValueDirect(true); }; + + editWidget = button(_onClick).setText(struct_try_get(display_data, "name", "Trigger")); + runInUI = struct_try_get(display_data, "UI", false); + visible = false; - return; + rejectArray(); + + return; #endregion } switch(type) { @@ -591,64 +897,76 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru case VALUE_TYPE.integer : var _txt = TEXTBOX_INPUT.number; - switch(display_type) { - case VALUE_DISPLAY._default : - editWidget = new textBox(_txt, function(val) { - return setValueDirect(val); - } ); - editWidget.slidable = true; - if(type == VALUE_TYPE.integer) editWidget.slide_speed = 1; - if(display_data != -1) editWidget.slide_speed = display_data; + switch(display_type) { + case VALUE_DISPLAY._default : #region + editWidget = new textBox(_txt, function(val) { return setValueInspector(val); } ); + editWidget.setSlidable(); + + if(struct_has(display_data, "slide_speed")) editWidget.setSlidable(display_data.slide_speed); + if(struct_has(display_data, "unit")) editWidget.unit = display_data.unit; + if(struct_has(display_data, "side_button")) editWidget.side_button = display_data.side_button; extract_node = "Node_Number"; - break; - case VALUE_DISPLAY.range : - editWidget = new rangeBox(_txt, function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); - } ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.extras = display_data; + break; #endregion + case VALUE_DISPLAY.range : #region + editWidget = new rangeBox(_txt, function(index, val) { return setValueInspector(val, index); } ); + + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); + + if(!struct_has(display_data, "linked")) display_data.linked = false; for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Range, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Range, i); extract_node = "Node_Number"; - break; - case VALUE_DISPLAY.vector : + break; #endregion + case VALUE_DISPLAY.vector : #region var val = animator.getValue(); - if(array_length(val) <= 4) { - editWidget = new vectorBox(array_length(animator.getValue()), function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); - }, unit ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.extras = display_data; + var len = array_length(val); + + if(len <= 4) { + editWidget = new vectorBox(len, function(index, val) { return setValueInspector(val, index); }, unit ); - if(array_length(val) == 2) { + if(struct_has(display_data, "label")) editWidget.axis = display_data.label; + if(struct_has(display_data, "linkable")) editWidget.linkable = display_data.linkable; + if(struct_has(display_data, "per_line")) editWidget.per_line = display_data.per_line; + if(struct_has(display_data, "linked")) editWidget.linked = display_data.linked; + if(struct_has(display_data, "side_button")) editWidget.side_button = display_data.side_button; + + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); + + if(len == 2) { + var _dim = struct_try_get(display_data, "useGlobal", true); extract_node = [ "Node_Vector2", "Node_Path" ]; - } else if(array_length(val) == 3) + + if(_dim && def_val == DEF_SURF) { + value_tag = "dimension"; + node.attributes.use_project_dimension = true; + editWidget.side_button = button(function() { + node.attributes.use_project_dimension = !node.attributes.use_project_dimension; + node.triggerRender(); + }).setIcon(THEME.node_use_project, 0, COLORS._main_icon).setTooltip("Use project dimension"); + } + } else if(len == 3) extract_node = "Node_Vector3"; - else if(array_length(val) == 4) + else if(len == 4) extract_node = "Node_Vector4"; } for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + string(array_safe_get(global.displaySuffix_Axis, i)); + animators[i].suffix = " " + string(array_safe_get_fast(global.displaySuffix_Axis, i)); - break; - case VALUE_DISPLAY.vector_range : + break; #endregion + case VALUE_DISPLAY.vector_range : #region var val = animator.getValue(); editWidget = new vectorRangeBox(array_length(val), _txt, function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); + return setValueInspector(val, index); }, unit ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.extras = display_data; + + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); + + if(!struct_has(display_data, "linked")) display_data.linked = false; if(array_length(val) == 2) extract_node = "Node_Vector2"; @@ -658,269 +976,426 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru extract_node = "Node_Vector4"; for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + string(array_safe_get(global.displaySuffix_VecRange, i)); + animators[i].suffix = " " + string(array_safe_get_fast(global.displaySuffix_VecRange, i)); + + break; #endregion + case VALUE_DISPLAY.rotation : #region + var _step = struct_try_get(display_data, "step", -1); - break; - case VALUE_DISPLAY.rotation : editWidget = new rotator(function(val) { - return setValueDirect(val); - }, display_data ); + return setValueInspector(val); + }, _step ); extract_node = "Node_Number"; - break; - case VALUE_DISPLAY.rotation_range : + break; #endregion + case VALUE_DISPLAY.rotation_range : #region editWidget = new rotatorRange(function(index, val) { - //var _val = animator.getValue(); - //_val[index] = round(val); - return setValueDirect(val, index); + return setValueInspector(val, index); } ); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Range, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Range, i); extract_node = "Node_Vector2"; - break; - case VALUE_DISPLAY.slider : - editWidget = new slider(display_data[0], display_data[1], display_data[2], function(val) { - return setValueDirect(toNumber(val)); + break; #endregion + case VALUE_DISPLAY.rotation_random: #region + editWidget = new rotatorRandom(function(index, val) { + return setValueInspector(val, index); } ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); + + extract_node = "Node_Vector2"; + break; #endregion + case VALUE_DISPLAY.slider : #region + var _range = struct_try_get(display_data, "range", [ 0, 1, 0.01 ]); + + editWidget = new textBox(TEXTBOX_INPUT.number, function(val) { return setValueInspector(toNumber(val)); } ) + .setSlidable(_range[2], type == VALUE_TYPE.integer, [ _range[0], _range[1] ]); + + if(struct_has(display_data, "update_stat")) + editWidget.update_stat = display_data.update_stat; extract_node = "Node_Number"; - break; - case VALUE_DISPLAY.slider_range : - editWidget = new sliderRange(display_data[0], display_data[1], display_data[2], function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); - } ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); + break; #endregion + case VALUE_DISPLAY.slider_range : #region + var _range = struct_try_get(display_data, "range", [ 0, 1, 0.01 ]); + + editWidget = new sliderRange(_range[2], type == VALUE_TYPE.integer, [ _range[0], _range[1] ], + function(index, val) { return setValueInspector(val, index); } ); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Range, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Range, i); extract_node = "Node_Vector2"; - break; - case VALUE_DISPLAY.area : + break; #endregion + case VALUE_DISPLAY.area : #region editWidget = new areaBox(function(index, val) { - return setValueDirect(val, index); + return setValueInspector(val, index); }, unit); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.onSurfaceSize = display_data; + + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); + + editWidget.onSurfaceSize = struct_try_get(display_data, "onSurfaceSize", noone); + editWidget.showShape = struct_try_get(display_data, "useShape", true); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Area, i, ""); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Area, i, ""); - extra_data.area_type = AREA_MODE.area; extract_node = "Node_Area"; - break; - case VALUE_DISPLAY.padding : + break; #endregion + case VALUE_DISPLAY.padding : #region editWidget = new paddingBox(function(index, val) { //var _val = animator.getValue(); //_val[index] = val; - return setValueDirect(val, index); + return setValueInspector(val, index); }, unit); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Padding, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Padding, i); extract_node = "Node_Vector4"; - break; - case VALUE_DISPLAY.corner : + break; #endregion + case VALUE_DISPLAY.corner : #region editWidget = new cornerBox(function(index, val) { - return setValueDirect(val, index); + return setValueInspector(val, index); }, unit); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Padding, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Padding, i); extract_node = "Node_Vector4"; - break; - case VALUE_DISPLAY.puppet_control : + break; #endregion + case VALUE_DISPLAY.puppet_control : #region editWidget = new controlPointBox(function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); + return setValueInspector(val, index); }); extract_node = ""; - break; - case VALUE_DISPLAY.enum_scroll : - editWidget = new scrollBox(display_data, function(val) { + break; #endregion + case VALUE_DISPLAY.enum_scroll : #region + if(!is_struct(display_data)) display_data = { data: display_data }; + var choices = __txt_junction_data(instanceof(node), connect_type, index, display_data.data); + + editWidget = new scrollBox(choices, function(val) { if(val == -1) return; - return setValueDirect(toNumber(val)); + return setValueInspector(toNumber(val)); } ); - if(is_struct(display_attribute)) { - editWidget.update_hover = display_attribute[$ "update_hover"]; - } + if(struct_has(display_data, "update_hover")) + editWidget.update_hover = display_data.update_hover; rejectConnect(); + key_inter = CURVE_TYPE.cut; extract_node = ""; - break; - case VALUE_DISPLAY.enum_button : - editWidget = new buttonGroup(display_data, function(val) { - return setValueDirect(val); + break; #endregion + case VALUE_DISPLAY.enum_button : #region + if(!is_struct(display_data)) display_data = { data: display_data }; + var choices = __txt_junction_data(instanceof(node), connect_type, index, display_data.data); + + editWidget = new buttonGroup(choices, function(val) { + return setValueInspector(val); } ); rejectConnect(); + key_inter = CURVE_TYPE.cut; extract_node = ""; - break; - case VALUE_DISPLAY.kernel : - editWidget = new matrixGrid(_txt, function(index, val) { - var _val = animator.getValue(); - _val[index] = val; - return setValueDirect(_val); + break; #endregion + case VALUE_DISPLAY.matrix : #region + editWidget = new matrixGrid(_txt, display_data.size, function(index, val) { + return setValueInspector(val, index); }, unit ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.extras = display_data; + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); for( var i = 0, n = array_length(animators); i < n; i++ ) animators[i].suffix = " " + string(i); extract_node = ""; - break; - case VALUE_DISPLAY.transform : - editWidget = new transformBox(function(index, val) { - var _val = animator.getValue(); - _val[index] = val; - return setValueDirect(_val); - }); + break; #endregion + case VALUE_DISPLAY.transform : #region + editWidget = new transformBox(function(index, val) { return setValueInspector(val, index); }); extract_node = "Node_Transform_Array"; - break; + break; #endregion + case VALUE_DISPLAY.toggle : #region + editWidget = new toggleGroup(display_data.data, function(val) { + return setValueInspector(val); + } ); + + rejectConnect(); + key_inter = CURVE_TYPE.cut; + extract_node = ""; + break; #endregion + case VALUE_DISPLAY.d3quarternion : #region + editWidget = new quarternionBox(function(index, val) { + return setValueInspector(val, index); + }); + + extract_node = "Node_Vector4"; + display_data.angle_display = QUARTERNION_DISPLAY.quarterion; + break; #endregion + case VALUE_DISPLAY.path_anchor : #region + editWidget = new pathAnchorBox(function(index, val) { + return setValueInspector(val, index); + }); + + extract_node = "Node_Path_Anchor"; + break; #endregion + } break; - case VALUE_TYPE.boolean : - editWidget = new checkBox(function() { - return setValueDirect(!animator.getValue()); - } ); + case VALUE_TYPE.boolean : #region + if(name == "Active") editWidget = new checkBoxActive(function() { return setValueInspector(!animator.getValue()); } ); + else editWidget = new checkBox( function() { return setValueInspector(!animator.getValue()); } ); + key_inter = CURVE_TYPE.cut; extract_node = "Node_Boolean"; - break; - case VALUE_TYPE.color : + break; #endregion + case VALUE_TYPE.color : #region switch(display_type) { case VALUE_DISPLAY._default : - editWidget = new buttonColor(function(color) { - return setValueDirect(color); - } ); + editWidget = new buttonColor(function(color) { return setValueInspector(color); } ); graph_h = ui(16); extract_node = "Node_Color"; break; case VALUE_DISPLAY.palette : - editWidget = new buttonPalette(function(color) { - return setValueDirect(color); - } ); + editWidget = new buttonPalette(function(color) { return setValueInspector(color); } ); extract_node = "Node_Palette"; break; } - break; - case VALUE_TYPE.gradient : - editWidget = new buttonGradient(function(gradient) { - return setValueDirect(gradient); - } ); + break; #endregion + case VALUE_TYPE.gradient : #region + editWidget = new buttonGradient(function(gradient) { return setValueInspector(gradient); } ); extract_node = "Node_Gradient_Out"; - break; - case VALUE_TYPE.path : + break; #endregion + case VALUE_TYPE.path : #region switch(display_type) { case VALUE_DISPLAY.path_array : - editWidget = new pathArrayBox(node, display_data, function(path) { setValueDirect(path); } ); + editWidget = new pathArrayBox(node, display_data.filter, function(path) { setValueInspector(path); } ); break; case VALUE_DISPLAY.path_load : - editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { setValueDirect(str); }, - button(function() { - var path = get_open_filename(display_data[0], display_data[1]); - key_release(); - if(path == "") return noone; - return setValueDirect(path); - }, THEME.button_path_icon) - ); + editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { setValueInspector(str); } ); + editWidget.align = fa_left; + editWidget.side_button = button(function() { + var path = get_open_filename(display_data.filter, ""); + key_release(); + if(path == "") return noone; + return setValueInspector(path); + }, THEME.button_path_icon); extract_node = "Node_String"; break; case VALUE_DISPLAY.path_save : - editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { setValueDirect(str); }, - button(function() { - var path = get_save_filename(display_data[0], display_data[1]); - key_release(); - if(path == "") return noone; - return setValueDirect(path); - }, THEME.button_path_icon) - ); + editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { setValueInspector(str); } ); + editWidget.align = fa_left; + editWidget.side_button = button(function() { + var path = get_save_filename(display_data.filter, ""); + key_release(); + if(path == "") return noone; + return setValueInspector(path); + }, THEME.button_path_icon); extract_node = "Node_String"; break; case VALUE_DISPLAY.path_font : - editWidget = new fontScrollBox( - function(val) { - return setValueDirect(DIRECTORY + "Fonts/" + FONT_INTERNAL[val]); - } - ); + editWidget = new fontScrollBox( function(val) { return setValueInspector(DIRECTORY + "Fonts/" + FONT_INTERNAL[val]); } ); break; } - break; - case VALUE_TYPE.curve : + break; #endregion + case VALUE_TYPE.curve : #region display_type = VALUE_DISPLAY.curve; - editWidget = new curveBox(function(_modified) { - return setValueDirect(_modified); - }); - break; - case VALUE_TYPE.text : + editWidget = new curveBox(function(_modified) { return setValueInspector(_modified); }); + break; #endregion + case VALUE_TYPE.text : #region switch(display_type) { case VALUE_DISPLAY._default : - editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { - return setValueDirect(str); - }); + editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); + extract_node = "Node_String"; + break; + + case VALUE_DISPLAY.text_box : + editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); extract_node = "Node_String"; break; - case VALUE_DISPLAY.code : - editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { - return setValueDirect(str); - }); + case VALUE_DISPLAY.codeLUA : + editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); editWidget.font = f_code; - editWidget.format = TEXT_AREA_FORMAT.code; + editWidget.format = TEXT_AREA_FORMAT.codeLUA; + editWidget.min_lines = 4; + extract_node = "Node_String"; + break; + + case VALUE_DISPLAY.codeHLSL: + editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); + + editWidget.autocomplete_server = hlsl_autocomplete_server; + editWidget.function_guide_server = hlsl_function_guide_server; + editWidget.parser_server = hlsl_document_parser; + editWidget.autocomplete_object = node; + + editWidget.font = f_code; + editWidget.format = TEXT_AREA_FORMAT.codeHLSL; editWidget.min_lines = 4; extract_node = "Node_String"; break; + case VALUE_DISPLAY.text_tunnel : + editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); + extract_node = "Node_String"; + break; + case VALUE_DISPLAY.text_array : - editWidget = new textArrayBox(function() { - return animator.values[| 0].value; }, display_data, function() { node.doUpdate(); - }); + editWidget = new textArrayBox(function() { return animator.values[| 0].value; }, display_data.data, function() { node.doUpdate(); }); break; } - break; - case VALUE_TYPE.surface : - editWidget = new surfaceBox(function(ind) { - return setValueDirect(ind); - }, display_data ); + break; #endregion + case VALUE_TYPE.d3Material : #region + editWidget = new materialBox(function(ind) { + var res = setValueInspector(ind); + node.triggerRender(); + return res; + } ); + + if(!struct_has(display_data, "atlas")) display_data.atlas = true; show_in_inspector = true; extract_node = "Node_Canvas"; - break; - case VALUE_TYPE.pathnode : + break; #endregion + case VALUE_TYPE.surface : #region + editWidget = new surfaceBox(function(ind) { return setValueInspector(ind); } ); + + if(!struct_has(display_data, "atlas")) display_data.atlas = true; + show_in_inspector = true; + extract_node = "Node_Canvas"; + break; #endregion + case VALUE_TYPE.pathnode : #region extract_node = "Node_Path"; - break; + break; #endregion + } + + editWidgetRaw = editWidget; + if(editWidget) graphWidget = editWidget.clone(); + + for( var i = 0, n = ds_list_size(animator.values); i < n; i++ ) { + animator.values[| i].ease_in_type = key_inter; + animator.values[| i].ease_out_type = key_inter; } setDropKey(); - } - resetDisplay(); + updateColor(); + } resetDisplay(); #endregion - static expressionUpdate = function() { - expTree = evaluateFunctionList(expression); + static setMappable = function(index) { #region + attributes.mapped = false; + attributes.map_index = index; + + mapButton = button(function() { + attributes.mapped = !attributes.mapped; + var val = getValue(); + if( attributes.mapped && is_numeric(val)) setValue([0, val]); + if(!attributes.mapped && is_array(val)) setValue(array_safe_get_fast(val, 0)); + setArrayDepth(attributes.mapped); + + node.triggerRender(); + }) + .setIcon( THEME.value_use_surface, [ function() { return attributes.mapped; } ], COLORS._main_icon ) + .setTooltip("Toggle map"); + + switch(type) { + case VALUE_TYPE.gradient : + mapWidget = noone; + break; + + default : + mapWidget = new rangeBox(TEXTBOX_INPUT.number, function(index, val) { return setValueDirect(val, index); }); + mapWidget.side_button = mapButton; + break; + } + + editWidget.side_button = mapButton; + + return self; + } #endregion + + static setMapped = function(junc) { #region + mappedJunc = junc; + isTimelineVisible = function() { INLINE return is_anim && value_from == noone && mappedJunc.attributes.mapped; } + return self; + } #endregion + + static mappableStep = function() { #region + editWidget = mapWidget && attributes.mapped? mapWidget : editWidgetRaw; + setArrayDepth(attributes.mapped); + + var inp = node.inputs[| attributes.map_index]; + var vis = attributes.mapped && show_in_inspector; + + if(inp.visible != vis) { + inp.visible = vis; + node.refreshNodeDisplay(); + } + } #endregion + + static setColor = function(col) { #region + color = col; + updateColor(); + + if(value_from != noone) + value_from.setColor(col); + + return self; + } #endregion + + static updateColor = function(val = undefined) { #region + INLINE + + if(color == -1) { + draw_bg = isArray(val)? value_color_bg_array(draw_junction_index) : value_color_bg(draw_junction_index); + draw_fg = value_color(draw_junction_index); + } else { + draw_bg = isArray(val)? merge_color(color, colorMultiply(color, CDEF.main_dkgrey), 0.5) : value_color_bg(draw_junction_index); + draw_fg = color; + } + + color_display = type == VALUE_TYPE.action? #8fde5d : draw_fg; + } #endregion + + static setType = function(_type) { #region + if(type == _type) return false; + + type = _type; + draw_junction_index = type; + updateColor(); + + return true; + } #endregion + + static setUseExpression = function(useExp) { #region + INLINE + if(expUse == useExp) return; + expUse = useExp; node.triggerRender(); - } + } #endregion - static onValidate = function() { + static setExpression = function(_expression) { #region + expUse = true; + expression = _expression; + expressionUpdate(); + } #endregion + + static expressionUpdate = function() { #region + expTree = evaluateFunctionList(expression); + resetCache(); + node.triggerRender(); + } #endregion + + static onValidate = function() { #region if(!validateValue) return; var _val = value_validation, str = ""; value_validation = VALIDATION.pass; @@ -931,16 +1406,22 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru case VALUE_DISPLAY.path_load: var path = animator.getValue(); if(is_array(path)) path = path[0]; - if(try_get_path(path) == -1) { + + if(!is_string(path) || path == "") { + str = $"Path invalid: {path}"; + break; + } + + if(path_get(path) == -1) { value_validation = VALIDATION.error; - str = "File not exist: " + string(path); + str = $"File not exist: {path}"; } break; case VALUE_DISPLAY.path_array: var paths = animator.getValue(); if(is_array(paths)) { for( var i = 0, n = array_length(paths); i < n; i++ ) { - if(try_get_path(paths[i]) != -1) continue; + if(path_get(paths[i]) != -1) continue; value_validation = VALIDATION.error; str = "File not exist: " + string(paths[i]); } @@ -970,77 +1451,91 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru #endregion return self; - } + } #endregion - static valueProcess = function(value, nodeFrom, applyUnit = true, arrIndex = 0) { + static valueProcess = function(value, nodeFrom, applyUnit = true, arrIndex = 0) { #region var typeFrom = nodeFrom.type; - var display = nodeFrom.display_type; - if(type == VALUE_TYPE.gradient && typeFrom == VALUE_TYPE.color) { - if(is_struct(value) && instanceof(value) == "gradientObject") - return value; - if(is_array(value)) { - var amo = array_length(value); - var grad = array_create(amo); - for( var i = 0; i < amo; i++ ) - grad[i] = new gradientKey(i / amo, value[i]); - var g = new gradientObject(); - g.keys = grad; - return g; - } + #region color compatibility [ color, palette, gradient ] + if(type == VALUE_TYPE.gradient && typeFrom == VALUE_TYPE.color) { + if(is_instanceof(value, gradientObject)) + return value; + + if(is_array(value)) { + var amo = array_length(value); + var grad = array_create(amo); + for( var i = 0; i < amo; i++ ) + grad[i] = new gradientKey(i / amo, value[i]); + var g = new gradientObject(); + g.keys = grad; + return g; + } + + if(is_real(value)) return new gradientObject(value); + return new gradientObject(0); + } + + if(display_type == VALUE_DISPLAY.palette && !is_array(value)) { + return [ value ]; + } + #endregion + + if(display_type == VALUE_DISPLAY.area) { #region - var grad = new gradientObject(value); - return grad; - } - - if(display_type == VALUE_DISPLAY.palette && !is_array(value)) { - return [ value ]; - } - - if(display_type == VALUE_DISPLAY.area) { - var dispType = struct_try_get(nodeFrom.extra_data, "area_type", AREA_MODE.area); - var surfGet = nodeFrom.display_data; - if(!applyUnit || surfGet == -1) { - //print($" {value}"); - return value; + if(struct_has(nodeFrom.display_data, "onSurfaceSize")) { + var surf = nodeFrom.display_data.onSurfaceSize(); + + var ww = surf[0]; + var hh = surf[1]; + + var dispType = array_safe_get_fast(value, 5, AREA_MODE.area); + + switch(dispType) { + case AREA_MODE.area : + break; + + case AREA_MODE.padding : + var cx = (ww - value[0] + value[2]) / 2 + var cy = (value[1] + hh - value[3]) / 2; + var sw = abs((ww - value[0]) - value[2]) / 2; + var sh = abs(value[1] - (hh - value[3])) / 2; + + value = [cx, cy, sw, sh, value[4], value[5]]; + break; + + case AREA_MODE.two_point : + var cx = (value[0] + value[2]) / 2 + var cy = (value[1] + value[3]) / 2; + var sw = abs(value[0] - value[2]) / 2; + var sh = abs(value[1] - value[3]) / 2; + + value = [cx, cy, sw, sh, value[4], value[5]]; + break; + } } - var surf = surfGet(); - var ww = surf[0]; - var hh = surf[1]; + return applyUnit? unit.apply(value, arrIndex) : value; + } #endregion + + if(display_type == VALUE_DISPLAY.d3quarternion) { #region + if(!applyUnit) return value; + var dispType = display_data.angle_display; switch(dispType) { - case AREA_MODE.area : - return value; - - case AREA_MODE.padding : - var cx = (ww - value[0] + value[2]) / 2 - var cy = (value[1] + hh - value[3]) / 2; - var sw = abs((ww - value[0]) - value[2]) / 2; - var sh = abs(value[1] - (hh - value[3])) / 2; - return [cx, cy, sw, sh, value[4]]; - - case AREA_MODE.two_point : - var cx = (value[0] + value[2]) / 2 - var cy = (value[1] + value[3]) / 2; - var sw = abs(value[0] - value[2]) / 2; - var sh = abs(value[1] - value[3]) / 2; - return [cx, cy, sw, sh, value[4]]; - } - } - - - if(type == VALUE_TYPE.text) { - switch(display_type) { - case VALUE_DISPLAY.text_array : + case QUARTERNION_DISPLAY.quarterion : return value; - default: - return string_real(value); + case QUARTERNION_DISPLAY.euler : + var euler = new BBMOD_Quaternion().FromEuler(value[0], value[1], value[2]).ToArray(); + return euler; } - } + } #endregion - if(typeFrom == VALUE_TYPE.integer && type == VALUE_TYPE.color) - return value; + if(type == VALUE_TYPE.text) { #region + switch(display_type) { + case VALUE_DISPLAY.text_array : return value; + default: return string_real(value); + } + } #endregion if((typeFrom == VALUE_TYPE.integer || typeFrom == VALUE_TYPE.float || typeFrom == VALUE_TYPE.boolean) && type == VALUE_TYPE.color) return value >= 1? value : make_color_hsv(0, 0, value * 255); @@ -1048,75 +1543,163 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(typeFrom == VALUE_TYPE.boolean && type == VALUE_TYPE.text) return value? "true" : "false"; - if(type == VALUE_TYPE.integer || type == VALUE_TYPE.float) { + if(type == VALUE_TYPE.integer || type == VALUE_TYPE.float) { #region if(typeFrom == VALUE_TYPE.text) value = toNumber(value); - if(applyUnit) - return unit.apply(value, arrIndex); - } + value = applyUnit? unit.apply(value, arrIndex) : value; + + if(value_tag == "dimension") { + for( var i = 0, n = array_length(value); i < n; i++ ) + value[i] = clamp(value[i], 0, 8192); + } + + return value; + } #endregion if(type == VALUE_TYPE.surface && connect_type == JUNCTION_CONNECT.input && !is_surface(value) && def_val == USE_DEF) return DEF_SURFACE; return value; - } + } #endregion - static resetCache = function() { - cache_value[0] = false; - } + static valueExpressionProcess = function(value) { #region + switch(type) { + case VALUE_TYPE.float : + case VALUE_TYPE.integer : + if(!is_numeric(value)) + return toNumber(value); + break; + case VALUE_TYPE.boolean : + return bool(value); + } + + return value; + } #endregion - #region[#eb004b20] === GetValue === - static getValue = function(_time = PROJECT.animator.current_frame, applyUnit = true, arrIndex = 0, useCache = false) { + static resetCache = function() { cache_value[0] = false; } + + static getStaticValue = function() { INLINE return ds_list_empty(animator.values)? 0 : animator.values[| 0].value; } + + static getValue = function(_time = CURRENT_FRAME, applyUnit = true, arrIndex = 0, useCache = false, log = false) { #region if(type == VALUE_TYPE.trigger) - useCache = false; - - global.cache_call++; + return _getValue(_time, false, 0, false); + + //global.cache_call++; if(useCache && use_cache) { var cache_hit = cache_value[0]; - cache_hit &= (!is_anim && value_from == noone) || cache_value[1] == _time; + cache_hit &= !isActiveDynamic(_time) || cache_value[1] == _time; cache_hit &= cache_value[2] != undefined; + cache_hit &= cache_value[3] == applyUnit; cache_hit &= connect_type == JUNCTION_CONNECT.input; cache_hit &= unit.reference == noone || unit.mode == VALUE_UNIT.constant; - cache_hit &= !expUse; if(cache_hit) { - global.cache_hit++; + //global.cache_hit++; return cache_value[2]; } } - var val = _getValue(_time, applyUnit, arrIndex); + var val = _getValue(_time, applyUnit, arrIndex, log); + if(!accept_array && array_get_depth(val) > def_depth) { + noti_warning($"{name} does not accept array data.",, node); + return 0; + } + + draw_junction_index = type; + if(type == VALUE_TYPE.surface || type == VALUE_TYPE.any) { + var _sval = val; + if(is_array(_sval) && !array_empty(_sval)) + _sval = _sval[0]; + if(is_instanceof(_sval, SurfaceAtlas)) + draw_junction_index = VALUE_TYPE.atlas; + } if(useCache) { - is_changed = !isEqual(cache_value[2], val); cache_value[0] = true; cache_value[1] = _time; } cache_value[2] = val; + cache_value[3] = applyUnit; + + if(!IS_PLAYING) updateColor(val); return val; - } + } #endregion - static __getAnimValue = function(_time = PROJECT.animator.current_frame) { + static __getAnimValue = function(_time = CURRENT_FRAME) { #region + + if(value_tag == "dimension" && node.attributes.use_project_dimension) + return PROJECT.attributes.surface_dimension; + + if(!is_anim) { + if(sep_axis) { + if(ds_list_empty(animators[i].values)) return 0; + + var val = array_verify(val, array_length(animators)); + for( var i = 0, n = array_length(animators); i < n; i++ ) + val[i] = animators[i].processType(animators[i].values[| 0].value); + return val; + } + + if(ds_list_empty(animator.values)) return 0; + + return animator.processType(animator.values[| 0].value); + } + if(sep_axis) { var val = []; for( var i = 0, n = array_length(animators); i < n; i++ ) val[i] = animators[i].getValue(_time); return val; - } else - return animator.getValue(_time); - } + } + + return animator.getValue(_time); + } #endregion - static _getValue = function(_time = PROJECT.animator.current_frame, applyUnit = true, arrIndex = 0) { - var _val = getValueRecursive(_time); - var val = _val[0]; - var nod = _val[1]; + static arrayBalance = function(val) { #region // Balance array (generate uniform array from single values) + if(!is_array(def_val)) + return val; + + if(isDynamicArray()) + return val; + + if(isArray(val)) + return val; + + if(!is_array(val)) + return array_create(def_length, val); + + if(array_length(val) < def_length) + array_resize(val, def_length); + + return val; + } #endregion + + static _getValue = function(_time = CURRENT_FRAME, applyUnit = true, arrIndex = 0, log = false) { #region + + getValueRecursive(self.__curr_get_val, _time); + var val = __curr_get_val[0]; + var nod = __curr_get_val[1]; + var typ = nod.type; var dis = nod.display_type; - if(typ == VALUE_TYPE.surface && (type == VALUE_TYPE.integer || type == VALUE_TYPE.float) && accept_array) { //Dimension conversion + if(connect_type == JUNCTION_CONNECT.output) + return val; + + if(expUse) { #region expression + if(is_array(val)) { + for( var i = 0, n = array_length(val); i < n; i++ ) + val[i] = valueExpressionProcess(val[i]); + } else + val = valueExpressionProcess(val); + return arrayBalance(val); + + } #endregion + + if(typ == VALUE_TYPE.surface && (type == VALUE_TYPE.integer || type == VALUE_TYPE.float)) { #region Dimension conversion if(is_array(val)) { var eqSize = true; var sArr = []; @@ -1125,7 +1708,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru for( var i = 0, n = array_length(val); i < n; i++ ) { if(!is_surface(val[i])) continue; - var surfSz = [ surface_get_width(val[i]), surface_get_height(val[i]) ]; + var surfSz = [ surface_get_width_safe(val[i]), surface_get_height_safe(val[i]) ]; array_push(sArr, surfSz); if(i && !array_equals(surfSz, _osZ)) @@ -1137,299 +1720,427 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(eqSize) return _osZ; return sArr; } else if (is_surface(val)) - return [ surface_get_width(val), surface_get_height(val) ]; - return [1, 1]; - } + return [ surface_get_width_safe(val), surface_get_height_safe(val) ]; + return [ 1, 1 ]; + + } #endregion - if(is_array(def_val) && !typeArrayDynamic(display_type)) { //Balance array (generate uniform array from single values) - if(!is_array(val)) { - val = array_create(array_length(def_val), val); - return valueProcess(val, nod, applyUnit, arrIndex); - } else if(array_length(val) < array_length(def_val)) { - for( var i = array_length(val); i < array_length(def_val); i++ ) - val[i] = 0; + if(type == VALUE_TYPE.d3Material) { #region + if(nod == self) { + return def_val; + + } else if(typ == VALUE_TYPE.surface) { + if(!is_array(val)) return def_val.clone(val); + + var _val = array_create(array_length(val)); + for( var i = 0, n = array_length(val); i < n; i++ ) + _val[i] = def_val.clone(value[i]); + + return _val; } - } + } #endregion - if(isArray(val) && array_length(val) < 128) { //Process data + val = arrayBalance(val); + + if(isArray(val) && array_length(val) < 1024) { #region Process data + var _val = array_create(array_length(val)); for( var i = 0, n = array_length(val); i < n; i++ ) - val[i] = valueProcess(val[i], nod, applyUnit, arrIndex); - } else - val = valueProcess(val, nod, applyUnit, arrIndex); + _val[i] = valueProcess(val[i], nod, applyUnit, arrIndex); + return _val; + + } #endregion - return val; - } + return valueProcess(val, nod, applyUnit, arrIndex); + } #endregion - static getValueRecursive = function(_time = PROJECT.animator.current_frame) { - var val = [ -1, self ]; + static getValueRecursive = function(arr = __curr_get_val, _time = CURRENT_FRAME) { #region - if(type == VALUE_TYPE.trigger && connect_type == JUNCTION_CONNECT.output) //trigger even will not propagate from input to output, need to be done manually - return [ __getAnimValue(_time), self ]; + arr[@ 0] = __getAnimValue(_time); + arr[@ 1] = self; - if(value_from == noone) { - var _val = __getAnimValue(_time); - val = [ _val, self ]; - } else if(value_from != self) - val = value_from.getValueRecursive(_time); + if(value_from_loop && value_from_loop.bypassConnection() && value_from_loop.junc_out) + value_from_loop.getValue(arr); + + else if(value_from && value_from != self) + value_from.getValueRecursive(arr, _time); if(expUse && is_struct(expTree) && expTree.validate()) { - //print($"========== EXPRESSION CALLED =========="); - //print(debug_get_callstack(8)); if(global.EVALUATE_HEAD != noone && global.EVALUATE_HEAD == self) { - //noti_warning($"Expression evaluation error : recursive call detected."); + noti_warning($"Expression evaluation error : recursive call detected."); + } else { - printIf(global.LOG_EXPRESSION, $"==================== EVAL BEGIN {expTree} ===================="); - //print(json_beautify(json_stringify(expTree))); - //printCallStack(); global.EVALUATE_HEAD = self; - var params = { - name: name, - node_name: node.display_name, - value: val[0] + expContext = { + name : name, + node_name : node.display_name, + value : arr[0], + node_values : node.input_value_map, }; - var _exp_res = expTree.eval(variable_clone(params)); + var _exp_res = expTree.eval(variable_clone(expContext)); + printIf(global.LOG_EXPRESSION, $">>>> Result = {_exp_res}"); + if(is_undefined(_exp_res)) { - val[0] = 0; - noti_warning("Expression not returning any values."); + arr[@ 0] = 0; + noti_warning("Expression not returning valid values."); } else - val[0] = _exp_res; + arr[@ 0] = _exp_res; global.EVALUATE_HEAD = noone; } } - - return val; - } - #endregion + } #endregion - static setAnim = function(anim) { + static setAnim = function(anim, record = false) { #region + if(is_anim == anim) return; + if(record) { + recordAction(ACTION_TYPE.custom, function(data) { + setAnim(data.is_anim); + data.is_anim = !data.is_anim; + }, { anim: is_anim }); + } is_anim = anim; - PANEL_ANIMATION.updatePropertyList(); - } + + if(is_anim) { + if(ds_list_empty(animator.values)) + ds_list_add(animator.values, new valueKey(CURRENT_FRAME, animator.getValue(), animator)); + animator.values[| 0].time = CURRENT_FRAME; + animator.updateKeyMap(); + + for( var i = 0, n = array_length(animators); i < n; i++ ) { + if(ds_list_empty(animators[i].values)) + ds_list_add(animators[i].values, new valueKey(CURRENT_FRAME, animators[i].getValue(), animators[i])); + animators[i].values[| 0].time = CURRENT_FRAME; + animators[i].updateKeyMap(); + } + } else { + var _val = animator.getValue(); + ds_list_clear(animator.values); + animator.values[| 0] = new valueKey(0, _val, animator); + animator.updateKeyMap(); + + for( var i = 0, n = array_length(animators); i < n; i++ ) { + var _val = animators[i].getValue(); + ds_list_clear(animators[i].values); + animators[i].values[| 0] = new valueKey(0, _val, animators[i]); + animators[i].updateKeyMap(); + } + } + + if(type == VALUE_TYPE.gradient && struct_has(attributes, "map_index")) + node.inputs[| attributes.map_index + 1].setAnim(anim); + + node.refreshTimeline(); + } #endregion + + static isTimelineVisible = function() { INLINE return is_anim && value_from == noone; } - static __anim = function() { - if(node.update_on_frame) return true; + static isActiveDynamic = function(frame = CURRENT_FRAME) { #region + INLINE + + if(value_from_loop) return true; + if(value_from != noone) return false; + if(expUse) { if(!is_struct(expTree)) return false; - var res = expTree.isAnimated(); + var res = expTree.isDynamic(); + switch(res) { case EXPRESS_TREE_ANIM.none : return false; - case EXPRESS_TREE_ANIM.base_value : return is_anim; - case EXPRESS_TREE_ANIM.animated : return true; + case EXPRESS_TREE_ANIM.base_value : force_requeue = true; return is_anim; + case EXPRESS_TREE_ANIM.animated : force_requeue = true; return true; } } return is_anim; - } + } #endregion - static isAnimated = function() { - if(value_from == noone) return __anim(); - else return value_from.isAnimated() || value_from.__anim(); - } - - static showValue = function() { - var useCache = true; - if(display_type == VALUE_DISPLAY.area) - useCache = false; + show_val = []; + static showValue = function() { #region + INLINE - var val = getValue(, false, 0, useCache); + var val = 0; + + if(value_from != noone || is_anim || expUse) + val = getValue(CURRENT_FRAME, false, 0, true, true); + + else if(sep_axis) { + show_val = array_verify(show_val, array_length(animators)); + for( var i = 0, n = array_length(animators); i < n; i++ ) + show_val[i] = ds_list_empty(animators[i].values)? 0 : animators[i].processType(animators[i].values[| 0].value); + val = show_val; + } else + val = ds_list_empty(animator.values)? 0 : animator.processType(animator.values[| 0].value); - if(isArray()) { - if(array_length(val) == 0) return 0; - var v = val[safe_mod(node.preview_index, array_length(val))]; - if(array_length(v) >= 100) return $"[{array_length(v)}]"; - } return val; - } + } #endregion - static isArray = function(val = undefined) { - if(val == undefined) { - if(cache_array[0]) - return cache_array[1]; + static isDynamicArray = function() { #region + if(dynamic_array) return true; + + switch(display_type) { + case VALUE_DISPLAY.curve : + case VALUE_DISPLAY.palette : + return true; + } + + return false; + } #endregion + + static isArray = function(val = undefined) { #region + var _cac = val == undefined; + + if(_cac) { + if(cache_array[0]) return cache_array[1]; val = getValue(); + cache_array[0] = true; } - cache_array[0] = true; - - if(!is_array(val)) { //Value is array - cache_array[1] = false; - return cache_array[1]; + if(!is_array(val)) { //Value is scalar + if(_cac) cache_array[1] = false; + return false; } - if(array_depth == 0 && !typeArray(display_type)) { //Value is not an array by default, and no array depth enforced - cache_array[1] = true; - return cache_array[1]; + if(array_depth == 0 && !typeArray(display_type)) { // Value is not an array by default, and no array depth enforced + if(_cac) cache_array[1] = true; + return true; } var ar = val; repeat(array_depth + typeArray(display_type)) { //Recursively get the first member of subarray to check if value has depth of "array_depth" or not if(!is_array(ar) || !array_length(ar)) { //empty array - cache_array[1] = false; - return cache_array[1]; + if(_cac) cache_array[1] = false; + return false; } ar = ar[0]; } - cache_array[1] = is_array(ar); - return cache_array[1]; - } + if(_cac) cache_array[1] = is_array(ar); + return is_array(ar); + } #endregion - static arrayLength = function(val = undefined) { - if(val == undefined) - val = getValue(); + static arrayLength = function(val = undefined) { #region + val ??= getValue(); if(!isArray(val)) - return 0; + return -1; if(array_depth == 0 && !typeArray(display_type)) return array_length(val); - var ar = val; - repeat(array_depth - 1 + typeArray(display_type)) + var ar = val; + var _depth = max(0, array_depth + typeArray(display_type) - 1); + repeat(_depth) ar = ar[0]; return array_length(ar); - } + } #endregion - #region[#8fde5d16] === SetValue === - static setValue = function(val = 0, record = true, time = PROJECT.animator.current_frame, _update = true) { - //if(type == VALUE_TYPE.d3vertex && !is_array(val)) - // print(val); - + static setValue = function(val = 0, record = true, time = CURRENT_FRAME, _update = true) { #region val = unit.invApply(val); return setValueDirect(val, noone, record, time, _update); - } + } #endregion - static setValueDirect = function(val = 0, index = noone, record = true, time = PROJECT.animator.current_frame, _update = true) { - var updated = false; + static overrideValue = function(_val) { #region + ds_list_clear(animator.values); + ds_list_add(animator.values, new valueKey(0, _val, animator)); - //if(display_type == VALUE_DISPLAY.area) { - // print($"===== Set: {index} = {val} ====="); - // printCallStack(); - // print(""); - //} + for( var i = 0, n = array_length(animators); i < n; i++ ) { + ds_list_clear(animators[i].values); + ds_list_add(animators[i].values, new valueKey(0, array_safe_get_fast(_val, i), animators[i])); + } + } #endregion + + static setValueInspector = function(val = 0, index = noone) { #region + INLINE + var res = false; + val = unit.invApply(val); + + if(PANEL_INSPECTOR && PANEL_INSPECTOR.inspectGroup == 1) { + var ind = self.index; + + for( var i = 0, n = array_length(PANEL_INSPECTOR.inspectings); i < n; i++ ) { + var _node = PANEL_INSPECTOR.inspectings[i]; + if(ind >= ds_list_size(_node.inputs)) continue; + + var r = _node.inputs[| ind].setValueDirect(val, index); + if(_node == node) res = r; + } + } else { + res = setValueDirect(val, index); + + //print($"Node {node} : {node.name} {node.internalName}"); + //print($"Inspecting {PANEL_INSPECTOR.inspecting} : {PANEL_INSPECTOR.inspecting.name} {PANEL_INSPECTOR.inspecting.internalName}"); + //print($"{node == PANEL_INSPECTOR.inspecting}"); + //print(""); + } + + return res; + } #endregion + + static setValueDirect = function(val = 0, index = noone, record = true, time = CURRENT_FRAME, _update = true) { #region + is_modified = true; + var updated = false; + var _val = val; + var _inp = connect_type == JUNCTION_CONNECT.input; if(sep_axis) { if(index == noone) { for( var i = 0, n = array_length(animators); i < n; i++ ) - updated |= animators[i].setValue(val[i], connect_type == JUNCTION_CONNECT.input && record, time); + updated |= animators[i].setValue(val[i], _inp && record, time); } else - updated = animators[index].setValue(val, connect_type == JUNCTION_CONNECT.input && record, time); + updated = animators[index].setValue(val, _inp && record, time); + } else { if(index != noone) { - var _val = variable_clone(animator.getValue(time)); + _val = animator.getValue(time); + if(_inp) _val = variable_clone(_val); + _val[index] = val; - updated = animator.setValue(_val, connect_type == JUNCTION_CONNECT.input && record, time); - } else - updated = animator.setValue(val, connect_type == JUNCTION_CONNECT.input && record, time); + } + + updated = animator.setValue(_val, _inp && record, time); + //print($"{updated}: {index} - {_val}"); } if(type == VALUE_TYPE.gradient) updated = true; if(display_type == VALUE_DISPLAY.palette) updated = true; - if(display_type == VALUE_DISPLAY.transform) updated = true; - if(updated) { - if(connect_type == JUNCTION_CONNECT.input) { - node.triggerRender(); - if(_update) node.valueUpdate(self.index); - node.clearCacheForward(); - - if(fullUpdate) UPDATE |= RENDER_TYPE.full; - else UPDATE |= RENDER_TYPE.partial; - } - - if(!LOADING) PROJECT.modified = true; - cache_value[0] = false; + for( var i = 0, n = array_length(value_to_loop); i < n; i++ ) + value_to_loop[i].updateValue(); + + if(!updated) return false; + + if(value_tag == "dimension") + node.attributes.use_project_dimension = false; + + draw_junction_index = type; + if(type == VALUE_TYPE.surface) { + var _sval = val; + if(is_array(_sval) && !array_empty(_sval)) + _sval = _sval[0]; + if(is_instanceof(_sval, SurfaceAtlas)) + draw_junction_index = VALUE_TYPE.atlas; } + if(connect_type == JUNCTION_CONNECT.output) { + if(self.index == 0) { + node.preview_value = getValue(); + node.preview_array = "[" + array_shape(node.preview_value) + "]"; + } + return; + } + + if(is_instanceof(node, Node)) + node.setInputData(self.index, animator.getValue(time)); + + if(tags == VALUE_TAG.updateInTrigger || tags == VALUE_TAG.updateOutTrigger) return true; + + if(_update) { + if(!IS_PLAYING) node.triggerRender(); + node.valueUpdate(self.index); + node.clearCacheForward(); + } + + if(fullUpdate) RENDER_ALL + + if(!LOADING) PROJECT.modified = true; + + cache_value[0] = false; onValidate(); - return updated; - } - #endregion + return true; + } #endregion - static isConnectable = function(_valueFrom, checkRecur = true, log = false) { + static isConnectable = function(_valueFrom, checkRecur = true, log = false) { #region if(_valueFrom == -1 || _valueFrom == undefined || _valueFrom == noone) { - if(log) - noti_warning("LOAD: Cannot set node connection from " + string(_valueFrom) + " to " + string(name) + " of node " + string(node.name) + ".",, node); - return false; + if(log) noti_warning($"LOAD: Cannot set node connection from {_valueFrom} to {name} of node {node.name}.",, node); + return -1; } if(_valueFrom == value_from) { - print("whaT"); - return false; + if(log) noti_warning("whaT"); + return -1; } if(_valueFrom == self) { - if(log) - noti_warning("setFrom: Self connection is not allowed.",, node); - return false; + if(log) noti_warning("setFrom: Self connection is not allowed.",, node); + return -1; } if(!typeCompatible(_valueFrom.type, type)) { - if(log) - noti_warning($"setFrom: Type mismatch {_valueFrom.type} to {type}",, node); - return false; + if(log) noti_warning($"setFrom: Type mismatch {_valueFrom.type} to {type}",, node); + return -1; } if(typeIncompatible(_valueFrom, self)) { - if(log) - noti_warning("setFrom: Type mismatch",, node); - return false; + if(log) noti_warning("setFrom: Type mismatch",, node); + return -1; } if(connect_type == _valueFrom.connect_type) { - if(log) - noti_warning("setFrom: Connect type mismatch",, node); - return false; + if(log) noti_warning("setFrom: Connect type mismatch",, node); + return -1; } if(checkRecur && _valueFrom.searchNodeBackward(node)) { - if(log) - noti_warning("setFrom: Cyclic connection not allowed.",, node); - return false; + if(log) noti_warning("setFrom: Cyclic connection not allowed.",, node); + return -9; } if(!accept_array && isArray(_valueFrom.getValue())) { - if(log) - noti_warning("setFrom: Array mismatch",, node); - return false; + if(log) noti_warning("setFrom: Array mismatch",, node); + return -1; } if(!accept_array && _valueFrom.type == VALUE_TYPE.surface && (type == VALUE_TYPE.integer || type == VALUE_TYPE.float)) { - if(log) - noti_warning("setFrom: Array mismatch",, node); - return false; + if(log) noti_warning("setFrom: Array mismatch",, node); + return -1; } - return true; - } + return 1; + } #endregion - static setFrom = function(_valueFrom, _update = true, checkRecur = true, log = false) { + static isLeaf = function() { INLINE return value_from == noone; } + static isLeafList = function(list = noone) { INLINE return value_from == noone || !ds_list_exist(list, value_from.node); } + + static isRendered = function() { #region + if(type == VALUE_TYPE.node) return true; + + if( value_from == noone) return true; + + var controlNode = struct_has(value_from, "from")? value_from.from : value_from.node; + if(!controlNode.active) return true; + if(!controlNode.isRenderActive()) return true; + + return controlNode.rendered; + } #endregion + + static setFrom = function(_valueFrom, _update = true, checkRecur = true, log = false) { #region + //print($"Connecting {_valueFrom.name} to {name}"); + if(_valueFrom == noone) return removeFrom(); - if(!isConnectable(_valueFrom, checkRecur, log)) - return -1; + var conn = isConnectable(_valueFrom, checkRecur, log); + if(conn < 0) return conn; if(setFrom_condition != -1 && !setFrom_condition(_valueFrom)) return -2; if(value_from != noone) - ds_list_remove(value_from.value_to, self); + array_remove(value_from.value_to, self); var _o = animator.getValue(); recordAction(ACTION_TYPE.junction_connect, self, value_from); value_from = _valueFrom; - ds_list_add(_valueFrom.value_to, self); - //show_debug_message("connected " + name + " to " + _valueFrom.name) + array_push(_valueFrom.value_to, self); node.valueUpdate(index, _o); if(_update && connect_type == JUNCTION_CONNECT.input) { - node.onValueFromUpdate(index); + node.valueFromUpdate(index); node.triggerRender(); node.clearCacheForward(); @@ -1439,33 +2150,50 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru cache_array[0] = false; cache_value[0] = false; - draw_line_shift_x = 0; - draw_line_shift_y = 0; + if(!LOADING) { + draw_line_shift_x = 0; + draw_line_shift_y = 0; + PROJECT.modified = true; + } - if(!LOADING) PROJECT.modified = true; + RENDER_ALL_REORDER + + if(onSetFrom != noone) onSetFrom(_valueFrom); + if(_valueFrom.onSetTo != noone) _valueFrom.onSetTo(self); return true; - } + } #endregion - static removeFrom = function(_remove_list = true) { + static removeFrom = function(_remove_list = true) { #region recordAction(ACTION_TYPE.junction_disconnect, self, value_from); if(_remove_list && value_from != noone) - ds_list_remove(value_from.value_to, self); + array_remove(value_from.value_to, self); value_from = noone; if(connect_type == JUNCTION_CONNECT.input) - node.onValueFromUpdate(index); + node.valueFromUpdate(index); node.clearCacheForward(); + PROJECT.modified = true; + + RENDER_ALL_REORDER return false; - } + } #endregion - static getShowString = function() { + static removeFromLoop = function(_remove_list = true) { #region + if(value_from_loop != noone) + value_from_loop.destroy(); + + PROJECT.modified = true; + } #endregion + + static getShowString = function() { #region var val = showValue(); return string_real(val); - } + } #endregion - static setString = function(str) { + static setString = function(str) { #region + if(connect_type == JUNCTION_CONNECT.output) return; var _o = animator.getValue(); if(string_pos(",", str) > 0) { @@ -1500,16 +2228,16 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru setValue(toNumber(str)); } } - } + } #endregion - static checkConnection = function(_remove_list = true) { - if(value_from == noone) return; + static checkConnection = function(_remove_list = true) { #region + if(isLeaf()) return; if(value_from.node.active) return; removeFrom(_remove_list); - } + } #endregion - static searchNodeBackward = function(_node) { + static searchNodeBackward = function(_node) { #region if(node == _node) return true; for(var i = 0; i < ds_list_size(node.inputs); i++) { var _in = node.inputs[| i].value_from; @@ -1517,85 +2245,103 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru return true; } return false; - } + } #endregion - static unitConvert = function(mode) { + static unitConvert = function(mode) { #region var _v = animator.values; for( var i = 0; i < ds_list_size(_v); i++ ) _v[| i].value = unit.convertUnit(_v[| i].value, mode); - } + } #endregion - drag_type = 0; - drag_mx = 0; - drag_my = 0; - drag_sx = 0; - drag_sy = 0; - static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) { + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region if(type != VALUE_TYPE.integer && type != VALUE_TYPE.float) return -1; if(value_from != noone) return -1; if(expUse) return -1; + var arc = 9; + switch(display_type) { case VALUE_DISPLAY._default : - var _angle = argument_count > 8? argument[ 8] : 0; - var _scale = argument_count > 9? argument[ 9] : 1; - var _spr = argument_count > 10? argument[10] : THEME.anchor_selector; - return preview_overlay_scalar(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny, _angle, _scale, _spr); + var _angle = argument_count > arc + 0? argument[arc + 0] : 0; + var _scale = argument_count > arc + 1? argument[arc + 1] : 1; + var _spr = argument_count > arc + 2? argument[arc + 2] : THEME.anchor_selector; + return preview_overlay_scalar(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _angle, _scale, _spr); case VALUE_DISPLAY.rotation : - var _rad = argument_count > 8? argument[ 8] : 64; - return preview_overlay_rotation(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny, _rad); + var _rad = argument_count > arc + 0? argument[ arc + 0] : 64; + return preview_overlay_rotation(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _rad); case VALUE_DISPLAY.vector : - var _spr = argument_count > 8? argument[8] : THEME.anchor_selector; - var _sca = argument_count > 9? argument[9] : 1; - return preview_overlay_vector(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny, _spr); + var _spr = argument_count > arc + 0? argument[arc + 0] : THEME.anchor_selector; + var _sca = argument_count > arc + 1? argument[arc + 1] : 1; + return preview_overlay_vector(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _spr); + + case VALUE_DISPLAY.gradient_range : + var _dim = argument[arc]; + + if(mappedJunc.attributes.mapped) + return preview_overlay_gradient_range(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _dim); + break; case VALUE_DISPLAY.area : - return preview_overlay_area(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny, display_data); + var _flag = argument_count > arc + 0? argument[arc + 0] : 0b0011; + return preview_overlay_area(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _flag, struct_try_get(display_data, "onSurfaceSize")); case VALUE_DISPLAY.puppet_control : - return preview_overlay_puppet(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny); + return preview_overlay_puppet(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny); } return -1; - } + } #endregion - junction_drawing = [ THEME.node_junctions_single, type ]; - static drawJunction = function(_s, _mx, _my, sca = 1) { - if(!isVisible()) return false; + static drawJunction_fast = function(_s, _mx, _my) { #region + INLINE - var ss = max(0.25, _s / 2); - var is_hover = false; + var hov = PANEL_GRAPH.pHOVER && (PANEL_GRAPH.node_hovering == noone || PANEL_GRAPH.node_hovering == node); + var is_hover = hov && abs(_mx - x) + abs(_my - y) < _s; - if(PANEL_GRAPH.pHOVER && point_in_circle(_mx, _my, x, y, 10 * _s * sca)) { - //var _to = getJunctionTo(); - //var _ss = ""; - //for( var i = 0, n = array_length(_to); i < n; i++ ) - // _ss += (i? ", " : "") + _to[i].internalName; - //TOOLTIP = _ss; + draw_set_color(draw_fg); + draw_circle(x, y, _s, false); - is_hover = true; - if(type == VALUE_TYPE.action) - junction_drawing = [THEME.node_junction_inspector, 1]; - else - junction_drawing = [isArray()? THEME.node_junctions_array_hover : THEME.node_junctions_single_hover, type]; + return is_hover; + } #endregion + + static drawJunction = function(_s, _mx, _my) { #region + _s /= 2; + + var hov = PANEL_GRAPH.pHOVER && (PANEL_GRAPH.node_hovering == noone || PANEL_GRAPH.node_hovering == node); + var _d = 12 * _s; + var is_hover = hov && point_in_rectangle(_mx, _my, x - _d, y - _d, x + _d, y + _d); + hover_in_graph = is_hover; + + var _bgS = THEME.node_junctions_bg; + var _fgS = is_hover? THEME.node_junctions_outline_hover : THEME.node_junctions_outline; + + if(type == VALUE_TYPE.action) { + var _cbg = c_white; + + if(draw_blend != -1) + _cbg = merge_color(draw_blend_color, _cbg, draw_blend); + + __draw_sprite_ext(THEME.node_junction_inspector, is_hover, x, y, _s, _s, 0, _cbg, 1); } else { - if(type == VALUE_TYPE.action) - junction_drawing = [THEME.node_junction_inspector, 0]; - else - junction_drawing = [isArray()? THEME.node_junctions_array : THEME.node_junctions_single, type]; + var _cbg = draw_bg; + var _cfg = draw_fg; + + if(draw_blend != -1) { + _cbg = merge_color(draw_blend_color, _cbg, draw_blend); + _cfg = merge_color(draw_blend_color, _cfg, draw_blend); + } + + __draw_sprite_ext(_bgS, draw_junction_index, x, y, _s, _s, 0, _cbg, 1); + __draw_sprite_ext(_fgS, draw_junction_index, x, y, _s, _s, 0, _cfg, 1); } - draw_sprite_ext(junction_drawing[0], junction_drawing[1], x, y, ss, ss, 0, c_white, 1); - return is_hover; - } + } #endregion - static drawNameBG = function(_s) { - if(!isVisible()) return false; - + static drawNameBG = function(_s) { #region draw_set_text(f_p1, fa_left, fa_center); var tw = string_width(name) + 32; @@ -1611,177 +2357,114 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru var tx = x + 12 * _s; draw_sprite_stretched_ext(THEME.node_junction_name_bg, 0, tx - 16, y - th / 2, tw, th, c_white, 0.5); } - } - static drawName = function(_s, _mx, _my) { - if(!isVisible()) return false; + } #endregion + + static drawName = function(_s, _mx, _my) { #region - var _hover = PANEL_GRAPH.pHOVER && point_in_circle(_mx, _my, x, y, 10 * _s); - var _draw_cc = _hover? COLORS._main_text : COLORS._main_text_sub; + var _draw_cc = hover_in_graph? COLORS._main_text : COLORS._main_text_sub; draw_set_text(f_p1, fa_left, fa_center, _draw_cc); if(type == VALUE_TYPE.action) { var tx = x; draw_set_text(f_p1, fa_center, fa_center, _draw_cc); - draw_text(tx, y - (line_get_height() + 16) / 2, name); + draw_text_int(tx, y - (line_get_height() + 16) / 2, name); + } else if(connect_type == JUNCTION_CONNECT.input) { var tx = x - 12 * _s; draw_set_halign(fa_right); - draw_text(tx, y, name); + draw_text_int(tx, y, name); + } else { var tx = x + 12 * _s; draw_set_halign(fa_left); - draw_text(tx, y, name); + draw_text_int(tx, y, name); + } - } + } #endregion - static drawConnections = function(_x, _y, _s, mx, my, _active, aa = 1, minx = undefined, miny = undefined, maxx = undefined, maxy = undefined) { - if(value_from == noone) return noone; + static drawConnections = function(params = {}) { #region + if(isLeaf()) return noone; if(!value_from.node.active) return noone; if(!isVisible()) return noone; - var hovering = noone; - var jx = x; - var jy = y; - - var frx = value_from.x; - var fry = value_from.y; - - if(!is_undefined(minx)) { - if(jx < minx && frx < minx) return noone; - if(jx > maxx && frx > maxx) return noone; - - if(jy < miny && fry < miny) return noone; - if(jy > maxy && fry > maxy) return noone; - } - - var c0 = value_color(value_from.type); - var c1 = value_color(type); - - var shx = draw_line_shift_x * _s; - var shy = draw_line_shift_y * _s; - - var cx = round((frx + jx) / 2 + shx); - var cy = round((fry + jy) / 2 + shy); - - var hover = false; - var th = max(1, PREF_MAP[? "connection_line_width"] * _s); - draw_line_shift_hover = false; - - var downDirection = type == VALUE_TYPE.action || value_from.type == VALUE_TYPE.action; - - if(PANEL_GRAPH.pHOVER) - switch(PREF_MAP[? "curve_connection_line"]) { - case 0 : - hover = distance_to_line(mx, my, jx, jy, frx, fry) < max(th * 2, 6); - break; - case 1 : - if(downDirection) - hover = distance_to_curve_corner(mx, my, jx, jy, frx, fry, _s) < max(th * 2, 6); - else - hover = distance_to_curve(mx, my, jx, jy, frx, fry, cx, cy, _s) < max(th * 2, 6); - - if(PANEL_GRAPH._junction_hovering == noone) - draw_line_shift_hover = hover; - break; - case 2 : - if(downDirection) - hover = distance_to_elbow_corner(mx, my, frx, fry, jx, jy) < max(th * 2, 6); - else - hover = distance_to_elbow(mx, my, frx, fry, jx, jy, cx, cy, _s, value_from.drawLineIndex, drawLineIndex) < max(th * 2, 6); - - if(PANEL_GRAPH._junction_hovering == noone) - draw_line_shift_hover = hover; - break; - case 3 : - if(downDirection) - hover = distance_to_elbow_diag_corner(mx, my, frx, fry, jx, jy) < max(th * 2, 6); - else - hover = distance_to_elbow_diag(mx, my, frx, fry, jx, jy, cx, cy, _s, value_from.drawLineIndex, drawLineIndex) < max(th * 2, 6); - - if(PANEL_GRAPH._junction_hovering == noone) - draw_line_shift_hover = hover; - break; - } - - if(_active && hover) - hovering = self; - - var thicken = false; - thicken |= PANEL_GRAPH.nodes_junction_d == self; - thicken |= _active && PANEL_GRAPH.junction_hovering == self && PANEL_GRAPH._junction_hovering == noone; - thicken |= instance_exists(o_dialog_add_node) && o_dialog_add_node.junction_hovering == self; - - th *= thicken? 2 : 1; - - var corner = PREF_MAP[? "connection_line_corner"] * _s; - var ty = LINE_STYLE.solid; - if(type == VALUE_TYPE.node) - ty = LINE_STYLE.dashed; - - var ss = _s * aa; - jx *= aa; - jy *= aa; - frx *= aa; - fry *= aa; - th *= aa; - cx *= aa; - cy *= aa; - corner *= aa; - th = max(1, round(th)); - - draw_set_color(c0); - - var fromIndex = value_from.drawLineIndex; - var toIndex = drawLineIndex; + return drawJuncConnection(value_from, self, params); + } #endregion + + static drawConnectionMouse = function(params, _mx, _my, target) { #region + var ss = params.s; + var aa = params.aa; // 1 - switch(PREF_MAP[? "curve_connection_line"]) { - case 0 : - if(ty == LINE_STYLE.solid) - draw_line_width_color(jx, jy, frx, fry, th, c1, c0); - else - draw_line_dashed_color(jx, jy, frx, fry, th, c1, c0, 12 * ss); - break; + var drawCorner = type == VALUE_TYPE.action; + if(target != noone) + drawCorner |= target.type == VALUE_TYPE.action; + + var corner = PREFERENCES.connection_line_corner * ss; + var th = max(1, PREFERENCES.connection_line_width * ss); + + var sx = x; + var sy = y; + + corner *= aa; + th *= aa; + ss *= aa; + sx *= aa; + sy *= aa; + _mx *= aa; + _my *= aa; + + var col = color_display; + draw_set_color(col); + + var _action = type == VALUE_TYPE.action; + var _output = connect_type == JUNCTION_CONNECT.output; + + switch(PREFERENCES.curve_connection_line) { + case 0 : draw_line_width(sx, sy, _mx, _my, th); break; case 1 : - if(downDirection) - draw_line_curve_corner(jx, jy, frx, fry, ss, th, c0, c1); - else - draw_line_curve_color(jx, jy, frx, fry, cx, cy, ss, th, c0, c1, ty); + if(drawCorner) { + if(_action) draw_line_curve_corner(_mx, _my, sx, sy, ss, th, col, col); + else draw_line_curve_corner(sx, sy, _mx, _my, ss, th, col, col); + } else { + if(_output) draw_line_curve_color(_mx, _my, sx, sy,,, ss, th, col, col); + else draw_line_curve_color(sx, sy, _mx, _my,,, ss, th, col, col); + } break; case 2 : - if(downDirection) - draw_line_elbow_corner(frx, fry, jx, jy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); - else - draw_line_elbow_color(frx, fry, jx, jy, cx, cy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + if(drawCorner) { + if(_action) draw_line_elbow_corner(_mx, _my, sx, sy, ss, th, col, col, corner); + else draw_line_elbow_corner(sx, sy, _mx, _my, ss, th, col, col, corner); + } else { + if(_output) draw_line_elbow_color(sx, sy, _mx, _my,,, ss, th, col, col, corner); + else draw_line_elbow_color(_mx, _my, sx, sy,,, ss, th, col, col, corner); + } break; case 3 : - if(downDirection) - draw_line_elbow_diag_corner(frx, fry, jx, jy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); - else - draw_line_elbow_diag_color(frx, fry, jx, jy, cx, cy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + if(drawCorner) { + if(_action) draw_line_elbow_diag_corner(_mx, _my, sx, sy, ss, th, col, col, corner); + else draw_line_elbow_diag_corner(sx, sy, _mx, _my, ss, th, col, col, corner); + } else { + if(_output) draw_line_elbow_diag_color(sx, sy, _mx, _my,,, ss, th, col, col, corner); + else draw_line_elbow_diag_color(_mx, _my, sx, sy,,, ss, th, col, col, corner); + } break; } - - return hovering; - } + } #endregion - static isVisible = function() { - if(!node.active) - return false; - - if(value_from) - return true; + static isVisible = function() { #region + if(!node.active) return false; - if(connect_type == JUNCTION_CONNECT.input) { - if(!visible) - return false; - - if(is_array(node.input_display_list)) - return array_exists(node.input_display_list, index); - } - return visible; - } + if(connect_type == JUNCTION_CONNECT.output) + return visible || !array_empty(value_to); + + if(value_from) return true; + if(!visible) return false; + + if(index == -1) return true; + + return visible_in_list; + } #endregion - static extractNode = function(_type = extract_node) { + static extractNode = function(_type = extract_node) { #region if(_type == "") return noone; var ext = nodeBuild(_type, node.x, node.y); @@ -1832,24 +2515,25 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru } ext.doUpdate(); - PANEL_ANIMATION.updatePropertyList(); - } + } #endregion - static getJunctionTo = function() { - var to = []; + static hasJunctionFrom = function() { INLINE return value_from != noone; } + + static getJunctionTo = function() { #region + var _junc_to = []; - for(var j = 0; j < ds_list_size(value_to); j++) { - var _to = value_to[| j]; - if(!_to.node.active || _to.value_from == noone) continue; + for(var i = 0; i < array_length(value_to); i++) { + var _to = value_to[i]; + if(!_to.node.active || _to.isLeaf()) continue; if(_to.value_from != self) continue; - array_push(to, _to); + array_push(_junc_to, _to); } - - return to; - } + + return _junc_to; + } #endregion - static dragValue = function() { + static dragValue = function() { #region if(drop_key == "None") return; DRAGGING = { @@ -1864,13 +2548,13 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(connect_type == JUNCTION_CONNECT.input) DRAGGING.from = self; - } + } #endregion - #region[#88ffe916] === Save Load === - static serialize = function(scale = false, preset = false) { + static serialize = function(scale = false, preset = false) { #region var _map = {}; _map.visible = visible; + _map.color = color; if(connect_type == JUNCTION_CONNECT.output) return _map; @@ -1882,8 +2566,18 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru _map.sep_axis = sep_axis; _map.shift_x = draw_line_shift_x; _map.shift_y = draw_line_shift_y; - _map.from_node = !preset && value_from? value_from.node.node_id : -1; - _map.from_index = !preset && value_from? value_from.index : -1; + _map.is_modified= is_modified; + + if(!preset && value_from) { + _map.from_node = value_from.node.node_id; + + if(value_from.tags != 0) _map.from_index = value_from.tags; + else _map.from_index = value_from.index; + } else { + _map.from_node = -1; + _map.from_index = -1; + } + _map.global_use = expUse; _map.global_key = expression; _map.anim = is_anim; @@ -1893,26 +2587,26 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru var _anims = []; for( var i = 0, n = array_length(animators); i < n; i++ ) array_push(_anims, animators[i].serialize(scale)); - _map.animators = _anims; - _map.data = extra_data; + _map.animators = _anims; + _map.display_data = display_data; + _map.attributes = attributes; + _map.name_custom = name_custom; return _map; - } + } #endregion - con_node = -1; - con_index = -1; - - static applyDeserialize = function(_map, scale = false, preset = false) { + static applyDeserialize = function(_map, scale = false, preset = false) { #region if(_map == undefined) return; if(_map == noone) return; if(!is_struct(_map)) return; visible = struct_try_get(_map, "visible", visible); + color = struct_try_get(_map, "color", -1); + if(connect_type == JUNCTION_CONNECT.output) return; - //printIf(TESTING, " |- Applying deserialize to junction " + name + " of node " + node.name); - name = struct_try_get(_map, "name", name); + //print($" > Applying deserialize to junction {name} 0"); on_end = struct_try_get(_map, "on_end"); loop_range = struct_try_get(_map, "loop_range", -1); unit.mode = struct_try_get(_map, "unit"); @@ -1921,10 +2615,15 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru expTree = evaluateFunctionList(expression); sep_axis = struct_try_get(_map, "sep_axis"); - is_anim = struct_try_get(_map, "anim"); + setAnim(struct_try_get(_map, "anim")); draw_line_shift_x = struct_try_get(_map, "shift_x"); draw_line_shift_y = struct_try_get(_map, "shift_y"); + is_modified = struct_try_get(_map, "is_modified", true); + + struct_append(attributes, struct_try_get(_map, "attributes")) + name_custom = struct_try_get(_map, "name_custom", false); + if(name_custom) name = struct_try_get(_map, "name", name); animator.deserialize(struct_try_get(_map, "raw_value"), scale); @@ -1940,15 +2639,30 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru con_index = struct_try_get(_map, "from_index", -1); } - if(struct_has(_map, "data") && is_struct(_map.data)) - extra_data = _map.data; + if(struct_has(_map, "display_data")) { + for( var i = 0, n = array_length(DISPLAY_DATA_KEYS); i < n; i++ ) + struct_try_override(display_data, _map.display_data, DISPLAY_DATA_KEYS[i]); + } - if(APPENDING) def_val = getValue(0); + if(connect_type == JUNCTION_CONNECT.input && index >= 0) { + var _value = animator.getValue(0); + node.inputs_data[index] = _value; + node.input_value_map[$ internalName] = _value; + } + + attributeApply(); onValidate(); - } + } #endregion - static connect = function(log = false) { + static attributeApply = function() { #region + if(struct_has(attributes, "mapped") && attributes.mapped) + mappableStep(); + } #endregion + + static connect = function(log = false) { #region + //print($"{node} | {con_node} : {con_index}"); + if(con_node == -1 || con_index == -1) return true; @@ -1970,7 +2684,9 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(log) log_warning("LOAD", $"[Connect] Reconnecting {node.name} to {_nd.name}", node); - if(con_index < _ol) { + if(con_index == VALUE_TAG.updateInTrigger) setFrom(_nd.updatedInTrigger); + else if(con_index == VALUE_TAG.updateOutTrigger) setFrom(_nd.updatedOutTrigger); + else if(con_index < _ol) { var _set = setFrom(_nd.outputs[| con_index], false, true); if(_set) return true; @@ -1982,19 +2698,188 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru log_warning("LOAD", $"[Connect] Connection conflict {node.name} to {_nd.name} : Output not exist.", node); return false; - } - #endregion + } #endregion - static destroy = function() { + static destroy = function() { #region if(error_notification != noone) { noti_remove(error_notification); error_notification = noone; } - } + } #endregion - static cleanUp = function() { - ds_list_destroy(value_to); - animator.cleanUp(); - delete animator; - } -} \ No newline at end of file + static cleanUp = function() { #region + + } #endregion + + static toString = function() { return (connect_type == JUNCTION_CONNECT.input? "Input" : "Output") + $" junction {index} of [{name}]: {node}"; } +} + +function drawJuncConnection(from, to, params) { #region + #region parameters + var log = params.log; + var high = params.highlight; + var bg = params.bg; + var aa = params.aa; + + var _x = params.x; + var _y = params.y; + var _s = params.s; + var mx = params.mx; + var my = params.my; + var _active = params.active; + var cur_layer = params.cur_layer; + var max_layer = params.max_layer; + + var hovering = noone; + + var jx = to.x; + var jy = to.y; + + var frx = from.x; + var fry = from.y; + + var fromIndex = from.drawLineIndex; + var toIndex = to.drawLineIndex; + + if(params.minx != 0 && params.maxx != 0) { + var minx = params.minx; + var miny = params.miny; + var maxx = params.maxx; + var maxy = params.maxy; + + if(jx < minx && frx < minx) return noone; + if(jx > maxx && frx > maxx) return noone; + + if(jy < miny && fry < miny) return noone; + if(jy > maxy && fry > maxy) return noone; + } + + var shx = to.draw_line_shift_x * _s; + var shy = to.draw_line_shift_y * _s; + + var cx = round((frx + jx) / 2 + shx); + var cy = round((fry + jy) / 2 + shy); + + var hover = false; + var th = max(1, PREFERENCES.connection_line_width * _s); + to.draw_line_shift_hover = false; + + var downDirection = to.type == VALUE_TYPE.action || from.type == VALUE_TYPE.action; + #endregion + + #region +++++ CHECK HOVER +++++ + var hovDist = max(th * 2, 6); + + if(PANEL_GRAPH.pHOVER) { + if(from.node == to.node) { + hover = distance_line_feedback(mx, my, jx, jy, frx, fry, _s) < hovDist; + } else { + switch(PREFERENCES.curve_connection_line) { + case 0 : + hover = distance_to_line(mx, my, jx, jy, frx, fry) < hovDist; + break; + case 1 : + if(downDirection) hover = distance_to_curve_corner(mx, my, jx, jy, frx, fry, _s) < hovDist; + else hover = distance_to_curve(mx, my, jx, jy, frx, fry, cx, cy, _s) < hovDist; + + if(PANEL_GRAPH.value_focus == noone) + to.draw_line_shift_hover = hover; + break; + case 2 : + if(downDirection) hover = distance_to_elbow_corner(mx, my, frx, fry, jx, jy) < hovDist; + else hover = distance_to_elbow(mx, my, frx, fry, jx, jy, cx, cy, _s, fromIndex, toIndex) < hovDist; + + if(PANEL_GRAPH.value_focus == noone) + to.draw_line_shift_hover = hover; + break; + case 3 : + if(downDirection) hover = distance_to_elbow_diag_corner(mx, my, frx, fry, jx, jy) < hovDist; + else hover = distance_to_elbow_diag(mx, my, frx, fry, jx, jy, cx, cy, _s, fromIndex, toIndex) < hovDist; + + if(PANEL_GRAPH.value_focus == noone) + to.draw_line_shift_hover = hover; + break; + } + } + } + + if(_active && hover) + hovering = self; + #endregion + + #region draw parameters + var thicken = false; + thicken |= PANEL_GRAPH.nodes_junction_d == self; + thicken |= _active && PANEL_GRAPH.junction_hovering == self && PANEL_GRAPH.value_focus == noone; + thicken |= instance_exists(o_dialog_add_node) && o_dialog_add_node.junction_hovering == self; + + th *= thicken? 2 : 1; + + var corner = PREFERENCES.connection_line_corner * _s; + + var ty = LINE_STYLE.solid; + if(to.type == VALUE_TYPE.node || struct_try_get(params, "dashed")) + ty = LINE_STYLE.dashed; + + var c0, c1; + var _selc = to.node.branch_drawing && from.node.branch_drawing; + + if(high) { + var _fade = PREFERENCES.connection_line_highlight_fade; + var _colr = _selc? 1 : _fade; + + c0 = merge_color(bg, from.color_display, _colr); + c1 = merge_color(bg, to.color_display, _colr); + + to.draw_blend_color = bg; + to.draw_blend = _colr; + from.draw_blend = max(from.draw_blend, _colr); + } else { + c0 = from.color_display; + c1 = to.color_display; + + to.draw_blend_color = bg; + to.draw_blend = -1; + } + #endregion + + #region +++++ DRAW LINE +++++ + var ss = _s * aa; + jx *= aa; + jy *= aa; + frx *= aa; + fry *= aa; + th *= aa; + cx *= aa; + cy *= aa; + corner *= aa; + th = max(1, round(th)); + + draw_set_color(c0); + + if(from.node == to.node) { + draw_line_feedback(jx, jy, frx, fry, th, c1, c0, ss); + } else { + switch(PREFERENCES.curve_connection_line) { + case 0 : + if(ty == LINE_STYLE.solid) draw_line_width_color(jx, jy, frx, fry, th, c1, c0); + else draw_line_dashed_color(jx, jy, frx, fry, th, c1, c0, 6 * ss); + break; + case 1 : + if(downDirection) draw_line_curve_corner(jx, jy, frx, fry, ss, th, c0, c1); + else draw_line_curve_color(jx, jy, frx, fry, cx, cy, ss, th, c0, c1, ty); + break; + case 2 : + if(downDirection) draw_line_elbow_corner(frx, fry, jx, jy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + else draw_line_elbow_color(frx, fry, jx, jy, cx, cy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + break; + case 3 : + if(downDirection) draw_line_elbow_diag_corner(frx, fry, jx, jy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + else draw_line_elbow_diag_color(frx, fry, jx, jy, cx, cy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + break; + } + } + #endregion + + return hovering; +} #endregion \ No newline at end of file diff --git a/#backups/scripts/node_value/node_value.gml.backup1 b/#backups/scripts/node_value/node_value.gml.backup1 index 59da2f891..63e880bd3 100644 --- a/#backups/scripts/node_value/node_value.gml.backup1 +++ b/#backups/scripts/node_value/node_value.gml.backup1 @@ -1,4 +1,14 @@ -// 2023-08-08 14:41:45 +// 2024-04-20 09:57:02 +#region ---- global names ---- + global.junctionEndName = [ "Hold", "Loop", "Ping pong", "Wrap" ]; + + global.displaySuffix_Range = [ "min", "max" ]; + global.displaySuffix_Area = [ "x", "y", "w", "h", "shape" ]; + global.displaySuffix_Padding = [ "right", "top", "left", "bottom" ]; + global.displaySuffix_VecRange = [ "x min", "x max", "y min", "y max" ]; + global.displaySuffix_Axis = [ "x", "y", "z", "w" ]; +#endregion + enum JUNCTION_CONNECT { input, output @@ -23,7 +33,7 @@ enum VALUE_TYPE { pathnode = 12, particle = 13, rigid = 14, - fdomain = 15, + sdomain = 15, struct = 16, strands = 17, mesh = 18, @@ -37,11 +47,25 @@ enum VALUE_TYPE { pbBox = 25, + d3Mesh = 26, + d3Light = 27, + d3Camera = 28, + d3Scene = 29, + d3Material = 30, + + dynaSurface = 31, + PCXnode = 32, + + audioBit = 33, + + fdomain = 34, + action = 99, } enum VALUE_DISPLAY { _default, + none, range, //Int @@ -49,6 +73,7 @@ enum VALUE_DISPLAY { enum_button, rotation, rotation_range, + rotation_random, slider, slider_range, @@ -60,9 +85,12 @@ enum VALUE_DISPLAY { vector, vector_range, area, - kernel, transform, corner, + toggle, + matrix, + path_anchor, + gradient_range, //Curve curve, @@ -76,62 +104,151 @@ enum VALUE_DISPLAY { path_array, //Text - export_format, - code, - node_title, + codeLUA, + codeHLSL, text_array, + text_box, + text_tunnel, //path path_save, path_load, path_font, - //vertex + //d3d d3vertex, + d3quarternion, } -function value_color(i) { +enum KEYFRAME_END { + hold, + loop, + ping, + wrap, +} + +enum VALIDATION { + pass, + warning, + error +} + +enum VALUE_UNIT { + constant, + reference +} + +enum VALUE_TAG { + updateInTrigger = -2, + updateOutTrigger = -3, + none = 0 +} + +enum LINE_STYLE { + solid, + dashed +} + +function value_color(i) { #region static JUNCTION_COLORS = [ - $6691ff, //int - $78e4ff, //float - $5d3f8c, //bool - $5dde8f, //color - $976bff, //surface - $4b00eb, //path - $d1c2c2, //curve - $e3ff66, //text - $b5b5ff, //object - $ffa64d, //node + #ff9166, //int + #ffe478, //float + #8c3f5d, //bool + #8fde5d, //color + #ff6b97, //surface + #eb004b, //path + #c2c2d1, //curve + #66ffe3, //text + #ffb5b5, //object + #4da6ff, //node #c1007c, //3D - $808080, //any - $b5b5ff, //path - $5dde8f, //particle - $e3ff66, //rigid - #4da6ff, //fdomain - $5d3f8c, //struct - $6691ff, //strand - $d1c2c2, //mesh - $5dde8f, //trigger - $976bff, //atlas + #808080, //any + #ffb5b5, //path + #8fde5d, //particle + #88ffe9, //rigid + #6d6e71, //sdomain + #8c3f5d, //struct + #ff9166, //strand + #c2c2d1, //mesh + #8fde5d, //trigger + #ff6b97, //atlas #c1007c, //d3vertex - $5dde8f, //gradient - $6691ff, //armature - $808080, //buffer - $976bff, //pbBox + #8fde5d, //gradient + #ff9166, //armature + #808080, //buffer + #ff6b97, //pbBox + #4da6ff, //d3Mesh + #4da6ff, //d3Light + #4da6ff, //d3Camera + #4da6ff, //d3Scene + #ff6b97, //d3Material + #ff6b97, //dynaSurf + #c2c2d1, //PCX + #8fde5d, //audiobit + #4da6ff, //flipfluid + ]; + static JUNCTION_COLORS_LENGTH = array_length(JUNCTION_COLORS); + + if(i == 99) return #8fde5d; + + return JUNCTION_COLORS[i]; +} #endregion + +function value_color_bg(i) { #region + return #3b3b4e; +} #endregion + +function value_color_bg_array(i) { #region + static JUNCTION_COLORS = [ + #e36956, //int + #ff9166, //float + #5e315b, //bool + #3ca370, //color + #bd4882, //surface + #bb003c, //path + #83839b, //curve + #4da6ff, //text + #e28989, //object + #4b5bab, //node + #64003f, //3D + #4d4d4d, //any + #e28989, //path + #3ca370, //particle + #4da6ff, //rigid + #4b5bab, //sdomain + #5e315b, //struct + #e36956, //strand + #83839b, //mesh + #3ca370, //trigger + #9e2a69, //atlas + #64003f, //d3vertex + #3ca370, //gradient + #e36956, //armature + #4d4d4d, //buffer + #bd4882, //pbBox + #4b5bab, //d3Mesh + #4b5bab, //d3Light + #4b5bab, //d3Camera + #4b5bab, //d3Scene + #bd4882, //d3Material + #bd4882, //dynaSurf + #83839b, //PCX + #3ca370, //audiobit ]; if(i == 99) return $5dde8f; return JUNCTION_COLORS[safe_mod(max(0, i), array_length(JUNCTION_COLORS))]; -} +} #endregion -function value_bit(i) { +function value_bit(i) { #region switch(i) { case VALUE_TYPE.integer : return 1 << 0 | 1 << 1; case VALUE_TYPE.float : return 1 << 2 | 1 << 1; case VALUE_TYPE.boolean : return 1 << 3 | 1 << 1; case VALUE_TYPE.color : return 1 << 4; case VALUE_TYPE.gradient : return 1 << 25; - case VALUE_TYPE.surface : return 1 << 5; + case VALUE_TYPE.dynaSurface : + case VALUE_TYPE.surface : return 1 << 5 | 1 << 23; case VALUE_TYPE.path : return 1 << 10; case VALUE_TYPE.text : return 1 << 10; case VALUE_TYPE.object : return 1 << 13; @@ -141,11 +258,10 @@ function value_bit(i) { case VALUE_TYPE.pathnode : return 1 << 15; case VALUE_TYPE.particle : return 1 << 16; case VALUE_TYPE.rigid : return 1 << 17; - case VALUE_TYPE.fdomain : return 1 << 18; + case VALUE_TYPE.sdomain : return 1 << 18; case VALUE_TYPE.struct : return 1 << 19; case VALUE_TYPE.strands : return 1 << 20; case VALUE_TYPE.mesh : return 1 << 21; - case VALUE_TYPE.atlas : return 1 << 23; case VALUE_TYPE.armature : return 1 << 26 | 1 << 19; case VALUE_TYPE.node : return 1 << 32; @@ -157,12 +273,22 @@ function value_bit(i) { case VALUE_TYPE.trigger : return 1 << 22; case VALUE_TYPE.action : return 1 << 22 | 1 << 3; + case VALUE_TYPE.d3Mesh : return 1 << 29; + case VALUE_TYPE.d3Light : return 1 << 29; + case VALUE_TYPE.d3Camera : return 1 << 29; + case VALUE_TYPE.d3Scene : return 1 << 29 | 1 << 30; + case VALUE_TYPE.d3Material : return 1 << 33; + + case VALUE_TYPE.PCXnode : return 1 << 34; + case VALUE_TYPE.audioBit : return 1 << 35; + case VALUE_TYPE.fdomain : return 1 << 36; + case VALUE_TYPE.any : return ~0 & ~(1 << 32); } return 0; -} +} #endregion -function value_type_directional(f, t) { +function value_type_directional(f, t) { #region if(f == VALUE_TYPE.surface && t == VALUE_TYPE.integer) return true; if(f == VALUE_TYPE.surface && t == VALUE_TYPE.float) return true; @@ -178,24 +304,83 @@ function value_type_directional(f, t) { if(f == VALUE_TYPE.strands && t == VALUE_TYPE.pathnode ) return true; - if(f == VALUE_TYPE.color && t == VALUE_TYPE.struct ) return true; - if(f == VALUE_TYPE.mesh && t == VALUE_TYPE.struct ) return true; + if(f == VALUE_TYPE.color && t == VALUE_TYPE.struct ) return true; + if(f == VALUE_TYPE.mesh && t == VALUE_TYPE.struct ) return true; + if(f == VALUE_TYPE.particle && t == VALUE_TYPE.struct ) return true; + + if(f == VALUE_TYPE.surface && t == VALUE_TYPE.d3Material ) return true; return false; -} +} #endregion -function typeArray(_type) { +function value_type_from_string(str) { #region + switch(str) { + case "integer" : return VALUE_TYPE.integer; + case "float" : return VALUE_TYPE.float; + case "boolean" : return VALUE_TYPE.boolean; + case "color" : return VALUE_TYPE.color; + case "surface" : return VALUE_TYPE.surface; + + case "path" : return VALUE_TYPE.path; + case "curve" : return VALUE_TYPE.curve; + case "text" : return VALUE_TYPE.text; + case "object" : return VALUE_TYPE.object; + case "node" : return VALUE_TYPE.node; + case "d3object" : return VALUE_TYPE.d3object; + + case "any" : return VALUE_TYPE.any; + + case "pathnode" : return VALUE_TYPE.pathnode; + case "particle" : return VALUE_TYPE.particle; + case "rigid" : return VALUE_TYPE.rigid; + case "sdomain" : return VALUE_TYPE.sdomain; + case "struct" : return VALUE_TYPE.struct; + case "strands" : return VALUE_TYPE.strands; + case "mesh" : return VALUE_TYPE.mesh; + case "trigger" : return VALUE_TYPE.trigger; + case "atlas" : return VALUE_TYPE.atlas; + + case "d3vertex" : return VALUE_TYPE.d3vertex; + case "gradient" : return VALUE_TYPE.gradient; + case "armature" : return VALUE_TYPE.armature; + case "buffer" : return VALUE_TYPE.buffer; + + case "pbBox" : return VALUE_TYPE.pbBox; + + case "d3Mesh" : return VALUE_TYPE.d3Mesh; + case "d3Light" : return VALUE_TYPE.d3Light; + case "d3Camera" : return VALUE_TYPE.d3Camera; + case "d3Scene" : return VALUE_TYPE.d3Scene; + case "d3Material" : return VALUE_TYPE.d3Material; + + case "dynaSurface" : return VALUE_TYPE.dynaSurface; + case "PCXnode" : return VALUE_TYPE.PCXnode; + + case "audioBit" : return VALUE_TYPE.audioBit; + + case "fDomain" : return VALUE_TYPE.fdomain; + + case "action" : return VALUE_TYPE.action; + } + + return VALUE_TYPE.any; +} #endregion + +function typeArray(_type) { #region switch(_type) { case VALUE_DISPLAY.range : case VALUE_DISPLAY.vector_range : case VALUE_DISPLAY.rotation_range : + case VALUE_DISPLAY.rotation_random : case VALUE_DISPLAY.slider_range : + case VALUE_DISPLAY.path_anchor : + case VALUE_DISPLAY.gradient_range : case VALUE_DISPLAY.vector : case VALUE_DISPLAY.padding : case VALUE_DISPLAY.area : case VALUE_DISPLAY.puppet_control : - case VALUE_DISPLAY.kernel : + case VALUE_DISPLAY.matrix : case VALUE_DISPLAY.transform : case VALUE_DISPLAY.curve : @@ -205,33 +390,25 @@ function typeArray(_type) { case VALUE_DISPLAY.text_array : case VALUE_DISPLAY.d3vertex : + case VALUE_DISPLAY.d3quarternion : return 1; } return 0; -} +} #endregion -function typeArrayDynamic(_type) { - switch(_type) { - case VALUE_DISPLAY.curve : - case VALUE_DISPLAY.palette : - return true; - } - return false; -} - -function typeCompatible(fromType, toType, directional_cast = true) { +function typeCompatible(fromType, toType, directional_cast = true) { #region if(value_bit(fromType) & value_bit(toType) != 0) return true; if(!directional_cast) return false; return value_type_directional(fromType, toType); -} +} #endregion -function typeIncompatible(from, to) { +function typeIncompatible(from, to) { #region if(from.type == VALUE_TYPE.surface && (to.type == VALUE_TYPE.integer || to.type == VALUE_TYPE.float)) { switch(to.display_type) { case VALUE_DISPLAY.area : - case VALUE_DISPLAY.kernel : + case VALUE_DISPLAY.matrix : case VALUE_DISPLAY.vector_range : case VALUE_DISPLAY.puppet_control : case VALUE_DISPLAY.padding : @@ -241,30 +418,9 @@ function typeIncompatible(from, to) { } return false; -} +} #endregion -enum KEYFRAME_END { - hold, - loop, - ping, - wrap, -} - -globalvar ON_END_NAME; -ON_END_NAME = [ "Hold", "Loop", "Ping pong", "Wrap" ]; - -enum VALIDATION { - pass, - warning, - error -} - -enum VALUE_UNIT { - constant, - reference -} - -function isGraphable(prop) { +function isGraphable(prop) { #region if(prop.type == VALUE_TYPE.integer || prop.type == VALUE_TYPE.float) { if(prop.display_type == VALUE_DISPLAY.puppet_control) return false; @@ -274,206 +430,305 @@ function isGraphable(prop) { return true; return false; -} +} #endregion -function nodeValueUnit(value) constructor { - self.value = value; +function nodeValueUnit(_nodeValue) constructor { #region + self._nodeValue = _nodeValue; mode = VALUE_UNIT.constant; reference = noone; triggerButton = button(function() { mode = !mode; - value.cache_value[0] = false; - value.unitConvert(mode); - value.node.doUpdate(); + _nodeValue.cache_value[0] = false; + _nodeValue.unitConvert(mode); + _nodeValue.node.doUpdate(); }); triggerButton.icon_blend = COLORS._main_icon_light; - triggerButton.icon = THEME.unit_ref; + triggerButton.icon = THEME.unit_ref; + triggerButton.tooltip = new tooltipSelector("Unit", ["Pixel", "Fraction"]); - static setMode = function(type) { + static setMode = function(type) { #region if(type == "constant" && mode == VALUE_UNIT.constant) return; if(type == "relative" && mode == VALUE_UNIT.reference) return; mode = type == "constant"? VALUE_UNIT.constant : VALUE_UNIT.reference; - value.cache_value[0] = false; - value.unitConvert(mode); - value.node.doUpdate(); - } + _nodeValue.cache_value[0] = false; + _nodeValue.unitConvert(mode); + _nodeValue.node.doUpdate(); + } #endregion - static draw = function(_x, _y, _w, _h, _m) { + static draw = function(_x, _y, _w, _h, _m) { #region triggerButton.icon_index = mode; - triggerButton.tooltip = (mode? "Fraction" : "Pixel") + " unit"; + triggerButton.tooltip.index = mode; triggerButton.draw(_x, _y, _w, _h, _m, THEME.button_hide); - } + } #endregion - static invApply = function(value, index = 0) { + static invApply = function(value, index = 0) { #region if(mode == VALUE_UNIT.constant) return value; if(reference == noone) return value; return convertUnit(value, VALUE_UNIT.reference, index); - } + } #endregion - static apply = function(value, index = 0) { - if(mode == VALUE_UNIT.constant) - return value; - if(reference == noone) - return value; + static apply = function(value, index = 0) { #region + if(mode == VALUE_UNIT.constant) return value; + if(reference == noone) return value; return convertUnit(value, VALUE_UNIT.constant, index); - } + } #endregion - static convertUnit = function(value, unitTo, index = 0) { - var disp = self.value.display_type; + static convertUnit = function(value, unitTo, index = 0) { #region + var disp = _nodeValue.display_type; var base = reference(index); - var inv = unitTo == VALUE_UNIT.reference; + var inv = unitTo == VALUE_UNIT.reference; if(!is_array(base) && !is_array(value)) return inv? value / base : value * base; if(!is_array(base) && is_array(value)) { + var _val = array_create(array_length(value)); for( var i = 0, n = array_length(value); i < n; i++ ) - value[i] = inv? value[i] / base : value[i] * base; - return value; + _val[i] = inv? value[i] / base : value[i] * base; + return _val; } - if(is_array(base) && !is_array(value)) { + if(is_array(base) && !is_array(value)) return value; - } + var _val = array_create(array_length(value)); + switch(disp) { case VALUE_DISPLAY.padding : case VALUE_DISPLAY.vector : case VALUE_DISPLAY.vector_range : for( var i = 0, n = array_length(value); i < n; i++ ) - value[i] = inv? value[i] / base[i % 2] : value[i] * base[i % 2]; - return value; + _val[i] = inv? value[i] / base[i % 2] : value[i] * base[i % 2]; + return _val; case VALUE_DISPLAY.area : for( var i = 0; i < 4; i++ ) - value[i] = inv? value[i] / base[i % 2] : value[i] * base[i % 2]; - return value; + _val[i] = inv? value[i] / base[i % 2] : value[i] * base[i % 2]; + return _val; } return value; - } -} + } #endregion +} #endregion -global.displaySuffix_Range = [ "min", "max" ]; -global.displaySuffix_Area = [ "x", "y", "w", "h" ]; -global.displaySuffix_Padding = [ "right", "top", "left", "bottom" ]; -global.displaySuffix_VecRange = [ "x min", "x max", "y min", "y max" ]; -global.displaySuffix_Axis = [ "x", "y", "z", "w"]; - -function nodeValue(_name, _node, _connect, _type, _value, _tooltip = "") { - return new NodeValue(_name, _node, _connect, _type, _value, _tooltip); -} +function nodeValue(_name, _node, _connect, _type, _value, _tooltip = "") { return new NodeValue(_name, _node, _connect, _type, _value, _tooltip); } +function nodeValueMap(_name, _node, _junc = noone) { return new NodeValue(_name, _node, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone).setVisible(false, false).setMapped(_junc); } +function nodeValueGradientRange(_name, _node, _junc = noone) { return new NodeValue(_name, _node, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 1, 0 ]).setDisplay(VALUE_DISPLAY.gradient_range).setVisible(false, false).setMapped(_junc); } function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constructor { - node = _node; - x = node.x; - y = node.y; - index = _connect == JUNCTION_CONNECT.input? ds_list_size(node.inputs) : ds_list_size(node.outputs); - type = _type; - forward = true; + static DISPLAY_DATA_KEYS = [ "linked", "angle_display", "bone_id", "unit", "atlas_crop" ]; - _initName = _name; - name = __txt_junction_name(instanceof(node), type, index, _name); - name = _name; + #region ---- main ---- + active = true; + node = _node; + x = node.x; + y = node.y; + index = _connect == JUNCTION_CONNECT.input? ds_list_size(node.inputs) : ds_list_size(node.outputs); + type = _type; + forward = true; + _initName = _name; + + node.will_setHeight = true; + + static updateName = function(_name) { + name = _name; + internalName = string_to_var(name); + name_custom = true; + } updateName(_name); + + name_custom = false; + + switch(type) { + case VALUE_TYPE.PCXnode : + accept_array = false; + break; + } + + if(struct_has(node, "inputMap")) { + if(_connect == JUNCTION_CONNECT.input) node.inputMap[? internalName] = self; + else if(_connect == JUNCTION_CONNECT.output) node.outputMap[? internalName] = self; + } + + tooltip = _tooltip; + editWidget = noone; + editWidgetRaw = noone; + graphWidget = noone; + graphWidgetH = 0; + graphWidgetP = new widgetParam(0, 0, 0, 0, 0); + mapWidget = noone; + active_tooltip = ""; + + tags = VALUE_TAG.none; + #endregion - static updateName = function() { - internalName = string_lower(string_replace_all(name, " ", "_")); - } updateName(); + #region ---- connection ---- + connect_type = _connect; + value_from = noone; + value_from_loop = noone; + + value_to = []; + value_to_loop = []; + + accept_array = true; + array_depth = 0; + auto_connect = true; + setFrom_condition = -1; + + onSetFrom = noone; + onSetTo = noone; + #endregion - if(struct_has(node, "inputMap")) { - if(_connect == JUNCTION_CONNECT.input) node.inputMap[? internalName] = self; - else if(_connect == JUNCTION_CONNECT.output) node.outputMap[? internalName] = self; - } + #region ---- animation ---- + if(_type == VALUE_TYPE.color) { + if(is_array(_value)) { + for( var i = 0, n = array_length(_value); i < n; i++ ) + _value[i] = cola(_value[i], _color_get_alpha(_value[i])); + } else + _value = cola(_value, _color_get_alpha(_value)); + } + + key_inter = CURVE_TYPE.linear; + + is_anim = false; + sep_axis = false; + animable = true; + sepable = is_array(_value) && array_length(_value) > 1; + animator = new valueAnimator(_value, self, false); + animators = []; + + if(is_array(_value)) + for( var i = 0, n = array_length(_value); i < n; i++ ) { + animators[i] = new valueAnimator(_value[i], self, true); + animators[i].index = i; + } + + on_end = KEYFRAME_END.hold; + loop_range = -1; + #endregion - tooltip = _tooltip; - editWidget = noone; + #region ---- value ---- + def_val = _value; + def_length = is_array(def_val)? array_length(def_val) : 0; + def_depth = array_get_depth(def_val); + unit = new nodeValueUnit(self); + def_unit = VALUE_UNIT.constant; + dyna_depo = ds_list_create(); + value_tag = ""; + + is_modified = false; + cache_value = [ false, false, undefined, undefined ]; + cache_array = [ false, false ]; + use_cache = true; + + process_array = true; + dynamic_array = false; + validateValue = true; + runInUI = false; + + fullUpdate = false; + + attributes = {}; + + node.inputs_data[index] = _value; + node.input_value_map[$ internalName] = _value; + + __curr_get_val = [ 0, 0 ]; + #endregion - connect_type = _connect; - value_from = noone; - value_to = ds_list_create(); - value_to_arr = []; - accept_array = true; - array_depth = 0; - auto_connect = true; - setFrom_condition = -1; + #region ---- draw ---- + draw_line_shift_x = 0; + draw_line_shift_y = 0; + draw_line_thick = 1; + draw_line_shift_hover = false; + draw_line_blend = 1; + draw_line_feed = false; + drawLineIndex = 1; + draw_line_vb = noone; + draw_junction_index = type; + + junction_drawing = [ THEME.node_junctions_single, type ]; + hover_in_graph = false; + + drag_type = 0; + drag_mx = 0; + drag_my = 0; + drag_sx = 0; + drag_sy = 0; + + color = -1; + color_display = 0; + + draw_bg = c_black; + draw_fg = c_black; + + draw_blend = 1; + draw_blend_color = 1; + #endregion - is_anim = false; - sep_axis = false; - sepable = is_array(_value) && array_length(_value) > 1; - animator = new valueAnimator(_value, self, false); - animators = []; - if(is_array(_value)) - for( var i = 0, n = array_length(_value); i < n; i++ ) { - animators[i] = new valueAnimator(_value[i], self, true); - animators[i].index = i; - } + #region ---- timeline ---- + show_graph = false; + graph_h = ui(64); + #endregion - def_val = _value; - on_end = KEYFRAME_END.hold; - loop_range = -1; + #region ---- inspector ---- + visible = _connect == JUNCTION_CONNECT.output || _type == VALUE_TYPE.surface || _type == VALUE_TYPE.path || _type == VALUE_TYPE.PCXnode; + show_in_inspector = true; + visible_in_list = true; - unit = new nodeValueUnit(self); - extra_data = {}; - dyna_depo = ds_list_create(); + display_type = VALUE_DISPLAY._default; + if(_type == VALUE_TYPE.curve) display_type = VALUE_DISPLAY.curve; + else if(_type == VALUE_TYPE.d3vertex) display_type = VALUE_DISPLAY.d3vertex; + + display_data = {}; + display_attribute = noone; + + popup_dialog = noone; + #endregion - draw_line_shift_x = 0; - draw_line_shift_y = 0; - draw_line_thick = 1; - draw_line_shift_hover = false; - drawLineIndex = 1; - draw_line_vb = noone; + #region ---- graph ---- + value_validation = VALIDATION.pass; + error_notification = noone; + + extract_node = ""; + #endregion - show_graph = false; - graph_h = ui(64); + #region ---- expression ---- + expUse = false; + expression = ""; + expTree = noone; + expContext = { + name: name, + node_name: node.display_name, + value: 0, + node_values: node.input_value_map, + }; + + express_edit = new textArea(TEXTBOX_INPUT.text, function(str) { + expression = str; + expressionUpdate(); + }); + express_edit.autocomplete_server = pxl_autocomplete_server; + express_edit.autocomplete_context = expContext; + express_edit.function_guide_server = pxl_function_guide_server; + express_edit.parser_server = pxl_document_parser; + express_edit.format = TEXT_AREA_FORMAT.codeLUA; + express_edit.font = f_code; + express_edit.boxColor = COLORS._main_value_positive; + express_edit.align = fa_left; + #endregion - visible = _connect == JUNCTION_CONNECT.output || _type == VALUE_TYPE.surface || _type == VALUE_TYPE.path; - show_in_inspector = true; + #region ---- serialization ---- + con_node = -1; + con_index = -1; + #endregion - display_type = VALUE_DISPLAY._default; - if(_type == VALUE_TYPE.curve) display_type = VALUE_DISPLAY.curve; - else if(_type == VALUE_TYPE.d3vertex) display_type = VALUE_DISPLAY.d3vertex; - - display_data = -1; - display_attribute = noone; - - value_validation = VALIDATION.pass; - error_notification = noone; - - extract_node = ""; - - is_changed = true; - cache_value = [ false, false, undefined ]; - cache_array = [ false, false ]; - use_cache = true; - - expUse = false; - expression = ""; - expTree = noone; - - express_edit = new textArea(TEXTBOX_INPUT.text, function(str) { - expression = str; - expressionUpdate(); - }); - express_edit.autocomplete_server = pxl_autocomplete_server; - express_edit.function_guide_server = pxl_function_guide_server; - express_edit.parser_server = pxl_document_parser; - express_edit.format = TEXT_AREA_FORMAT.code; - express_edit.font = f_code; - express_edit.boxColor = COLORS._main_value_positive; - express_edit.align = fa_left; - - process_array = true; - validateValue = true; - - fullUpdate = false; - - static setDefault = function(vals) { + static setDefault = function(vals) { #region if(LOADING || APPENDING) return self; ds_list_clear(animator.values); @@ -481,79 +736,121 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru ds_list_add(animator.values, new valueKey(vals[i][0], vals[i][1], animator)); return self; - } + } #endregion - static resetValue = function() { setValue(def_val); } + static getName = function() { #region + if(name_custom) return name; + return __txt_junction_name(instanceof(node), connect_type, index, name); + } #endregion - static setUnitRef = function(ref, mode = VALUE_UNIT.constant) { + static setName = function(_name) { #region + INLINE + name = _name; + return self; + } #endregion + + static setActive = function(_active, _tooltip) { #region + INLINE + active = _active; + active_tooltip = _tooltip; + + return self; + } #endregion + + static setWindows = function() { #region + INLINE + setActive(OS == os_windows, "Not available on MacOS"); + + return self; + } #endregion + + static resetValue = function() { #region + unit.mode = def_unit; + setValue(unit.apply(def_val)); + attributes.mapped = false; + + is_modified = false; + } #endregion + + static setUnitRef = function(ref, mode = VALUE_UNIT.constant) { #region unit.reference = ref; unit.mode = mode; + def_unit = mode; cache_value[0] = false; return self; - } + } #endregion - static setVisible = function(inspector) { + static setVisible = function(inspector) { #region if(connect_type == JUNCTION_CONNECT.input) { show_in_inspector = inspector; visible = argument_count > 1? argument[1] : visible; } else visible = inspector; - + node.will_setHeight = true; return self; - } + } #endregion - static setDisplay = function(_type = VALUE_DISPLAY._default, _data = -1, _attr = noone) { + static setDisplay = function(_type = VALUE_DISPLAY._default, _data = {}) { #region display_type = _type; display_data = _data; - display_attribute = _attr; resetDisplay(); return self; - } + } #endregion - static rejectArray = function() { + static setAnimable = function(_anim) { #region + animable = _anim; + return self; + } #endregion + + static rejectArray = function() { #region accept_array = false; return self; - } + } #endregion - static uncache = function() { + static uncache = function() { #region use_cache = false; return self; - } + } #endregion - static setArrayDepth = function(aDepth) { + static setArrayDepth = function(aDepth) { #region array_depth = aDepth; return self; - } + } #endregion - static rejectConnect = function() { + static setArrayDynamic = function() { #region + dynamic_array = true; + return self; + } #endregion + + static rejectConnect = function() { #region auto_connect = false; return self; - } + } #endregion - static rejectArrayProcess = function() { + static rejectArrayProcess = function() { #region process_array = false; return self; - } + } #endregion - static nonForward = function() { + static nonForward = function() { #region forward = false; return self; - } + } #endregion - static nonValidate = function() { + static nonValidate = function() { #region validateValue = false; return self; - } + } #endregion - static isAnimable = function() { - //if(type == VALUE_TYPE.gradient) return false; + static isAnimable = function() { #region + if(type == VALUE_TYPE.PCXnode) return false; if(display_type == VALUE_DISPLAY.text_array) return false; - return true; - } + return animable; + } #endregion - static setDropKey = function() { + static setDropKey = function() { #region switch(type) { case VALUE_TYPE.integer : drop_key = "Number"; break; case VALUE_TYPE.float : drop_key = "Number"; break; @@ -573,17 +870,26 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru default: drop_key = "None"; } - } - setDropKey(); + } setDropKey(); #endregion - static resetDisplay = function() { + static resetDisplay = function() { #region //////////////////// RESET DISPLAY //////////////////// editWidget = noone; switch(display_type) { - case VALUE_DISPLAY.button : - editWidget = button(display_data[0]); - editWidget.text = display_data[1]; + case VALUE_DISPLAY.button : #region + var _onClick; + + if(struct_has(display_data, "onClick")) + _onClick = method(node, display_data.onClick); + else + _onClick = function() { setAnim(true); setValueDirect(true); }; + + editWidget = button(_onClick).setText(struct_try_get(display_data, "name", "Trigger")); + runInUI = struct_try_get(display_data, "UI", false); + visible = false; - return; + rejectArray(); + + return; #endregion } switch(type) { @@ -591,64 +897,76 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru case VALUE_TYPE.integer : var _txt = TEXTBOX_INPUT.number; - switch(display_type) { - case VALUE_DISPLAY._default : - editWidget = new textBox(_txt, function(val) { - return setValueDirect(val); - } ); - editWidget.slidable = true; - if(type == VALUE_TYPE.integer) editWidget.slide_speed = 1; - if(display_data != -1) editWidget.slide_speed = display_data; + switch(display_type) { + case VALUE_DISPLAY._default : #region + editWidget = new textBox(_txt, function(val) { return setValueInspector(val); } ); + editWidget.setSlidable(); + + if(struct_has(display_data, "slide_speed")) editWidget.setSlidable(display_data.slide_speed); + if(struct_has(display_data, "unit")) editWidget.unit = display_data.unit; + if(struct_has(display_data, "side_button")) editWidget.side_button = display_data.side_button; extract_node = "Node_Number"; - break; - case VALUE_DISPLAY.range : - editWidget = new rangeBox(_txt, function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); - } ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.extras = display_data; + break; #endregion + case VALUE_DISPLAY.range : #region + editWidget = new rangeBox(_txt, function(index, val) { return setValueInspector(val, index); } ); + + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); + + if(!struct_has(display_data, "linked")) display_data.linked = false; for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Range, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Range, i); extract_node = "Node_Number"; - break; - case VALUE_DISPLAY.vector : + break; #endregion + case VALUE_DISPLAY.vector : #region var val = animator.getValue(); - if(array_length(val) <= 4) { - editWidget = new vectorBox(array_length(animator.getValue()), function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); - }, unit ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.extras = display_data; + var len = array_length(val); + + if(len <= 4) { + editWidget = new vectorBox(len, function(index, val) { return setValueInspector(val, index); }, unit ); - if(array_length(val) == 2) { + if(struct_has(display_data, "label")) editWidget.axis = display_data.label; + if(struct_has(display_data, "linkable")) editWidget.linkable = display_data.linkable; + if(struct_has(display_data, "per_line")) editWidget.per_line = display_data.per_line; + if(struct_has(display_data, "linked")) editWidget.linked = display_data.linked; + if(struct_has(display_data, "side_button")) editWidget.side_button = display_data.side_button; + + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); + + if(len == 2) { + var _dim = struct_try_get(display_data, "useGlobal", true); extract_node = [ "Node_Vector2", "Node_Path" ]; - } else if(array_length(val) == 3) + + if(_dim && def_val == DEF_SURF) { + value_tag = "dimension"; + node.attributes.use_project_dimension = true; + editWidget.side_button = button(function() { + node.attributes.use_project_dimension = !node.attributes.use_project_dimension; + node.triggerRender(); + }).setIcon(THEME.node_use_project, 0, COLORS._main_icon).setTooltip("Use project dimension"); + } + } else if(len == 3) extract_node = "Node_Vector3"; - else if(array_length(val) == 4) + else if(len == 4) extract_node = "Node_Vector4"; } for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + string(array_safe_get(global.displaySuffix_Axis, i)); + animators[i].suffix = " " + string(array_safe_get_fast(global.displaySuffix_Axis, i)); - break; - case VALUE_DISPLAY.vector_range : + break; #endregion + case VALUE_DISPLAY.vector_range : #region var val = animator.getValue(); editWidget = new vectorRangeBox(array_length(val), _txt, function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); + return setValueInspector(val, index); }, unit ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.extras = display_data; + + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); + + if(!struct_has(display_data, "linked")) display_data.linked = false; if(array_length(val) == 2) extract_node = "Node_Vector2"; @@ -658,269 +976,426 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru extract_node = "Node_Vector4"; for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + string(array_safe_get(global.displaySuffix_VecRange, i)); + animators[i].suffix = " " + string(array_safe_get_fast(global.displaySuffix_VecRange, i)); + + break; #endregion + case VALUE_DISPLAY.rotation : #region + var _step = struct_try_get(display_data, "step", -1); - break; - case VALUE_DISPLAY.rotation : editWidget = new rotator(function(val) { - return setValueDirect(val); - }, display_data ); + return setValueInspector(val); + }, _step ); extract_node = "Node_Number"; - break; - case VALUE_DISPLAY.rotation_range : + break; #endregion + case VALUE_DISPLAY.rotation_range : #region editWidget = new rotatorRange(function(index, val) { - //var _val = animator.getValue(); - //_val[index] = round(val); - return setValueDirect(val, index); + return setValueInspector(val, index); } ); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Range, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Range, i); extract_node = "Node_Vector2"; - break; - case VALUE_DISPLAY.slider : - editWidget = new slider(display_data[0], display_data[1], display_data[2], function(val) { - return setValueDirect(toNumber(val)); + break; #endregion + case VALUE_DISPLAY.rotation_random: #region + editWidget = new rotatorRandom(function(index, val) { + return setValueInspector(val, index); } ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); + + extract_node = "Node_Vector2"; + break; #endregion + case VALUE_DISPLAY.slider : #region + var _range = struct_try_get(display_data, "range", [ 0, 1, 0.01 ]); + + editWidget = new textBox(TEXTBOX_INPUT.number, function(val) { return setValueInspector(toNumber(val)); } ) + .setSlidable(_range[2], type == VALUE_TYPE.integer, [ _range[0], _range[1] ]); + + if(struct_has(display_data, "update_stat")) + editWidget.update_stat = display_data.update_stat; extract_node = "Node_Number"; - break; - case VALUE_DISPLAY.slider_range : - editWidget = new sliderRange(display_data[0], display_data[1], display_data[2], function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); - } ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); + break; #endregion + case VALUE_DISPLAY.slider_range : #region + var _range = struct_try_get(display_data, "range", [ 0, 1, 0.01 ]); + + editWidget = new sliderRange(_range[2], type == VALUE_TYPE.integer, [ _range[0], _range[1] ], + function(index, val) { return setValueInspector(val, index); } ); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Range, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Range, i); extract_node = "Node_Vector2"; - break; - case VALUE_DISPLAY.area : + break; #endregion + case VALUE_DISPLAY.area : #region editWidget = new areaBox(function(index, val) { - return setValueDirect(val, index); + return setValueInspector(val, index); }, unit); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.onSurfaceSize = display_data; + + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); + + editWidget.onSurfaceSize = struct_try_get(display_data, "onSurfaceSize", noone); + editWidget.showShape = struct_try_get(display_data, "useShape", true); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Area, i, ""); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Area, i, ""); - extra_data.area_type = AREA_MODE.area; extract_node = "Node_Area"; - break; - case VALUE_DISPLAY.padding : + break; #endregion + case VALUE_DISPLAY.padding : #region editWidget = new paddingBox(function(index, val) { //var _val = animator.getValue(); //_val[index] = val; - return setValueDirect(val, index); + return setValueInspector(val, index); }, unit); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Padding, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Padding, i); extract_node = "Node_Vector4"; - break; - case VALUE_DISPLAY.corner : + break; #endregion + case VALUE_DISPLAY.corner : #region editWidget = new cornerBox(function(index, val) { - return setValueDirect(val, index); + return setValueInspector(val, index); }, unit); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); for( var i = 0, n = array_length(animators); i < n; i++ ) - animators[i].suffix = " " + array_safe_get(global.displaySuffix_Padding, i); + animators[i].suffix = " " + array_safe_get_fast(global.displaySuffix_Padding, i); extract_node = "Node_Vector4"; - break; - case VALUE_DISPLAY.puppet_control : + break; #endregion + case VALUE_DISPLAY.puppet_control : #region editWidget = new controlPointBox(function(index, val) { - //var _val = animator.getValue(); - //_val[index] = val; - return setValueDirect(val, index); + return setValueInspector(val, index); }); extract_node = ""; - break; - case VALUE_DISPLAY.enum_scroll : - editWidget = new scrollBox(display_data, function(val) { + break; #endregion + case VALUE_DISPLAY.enum_scroll : #region + if(!is_struct(display_data)) display_data = { data: display_data }; + var choices = __txt_junction_data(instanceof(node), connect_type, index, display_data.data); + + editWidget = new scrollBox(choices, function(val) { if(val == -1) return; - return setValueDirect(toNumber(val)); + return setValueInspector(toNumber(val)); } ); - if(is_struct(display_attribute)) { - editWidget.update_hover = display_attribute[$ "update_hover"]; - } + if(struct_has(display_data, "update_hover")) + editWidget.update_hover = display_data.update_hover; rejectConnect(); + key_inter = CURVE_TYPE.cut; extract_node = ""; - break; - case VALUE_DISPLAY.enum_button : - editWidget = new buttonGroup(display_data, function(val) { - return setValueDirect(val); + break; #endregion + case VALUE_DISPLAY.enum_button : #region + if(!is_struct(display_data)) display_data = { data: display_data }; + var choices = __txt_junction_data(instanceof(node), connect_type, index, display_data.data); + + editWidget = new buttonGroup(choices, function(val) { + return setValueInspector(val); } ); rejectConnect(); + key_inter = CURVE_TYPE.cut; extract_node = ""; - break; - case VALUE_DISPLAY.kernel : - editWidget = new matrixGrid(_txt, function(index, val) { - var _val = animator.getValue(); - _val[index] = val; - return setValueDirect(_val); + break; #endregion + case VALUE_DISPLAY.matrix : #region + editWidget = new matrixGrid(_txt, display_data.size, function(index, val) { + return setValueInspector(val, index); }, unit ); - if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1); - if(display_data != -1) editWidget.extras = display_data; + if(type == VALUE_TYPE.integer) editWidget.setSlideSpeed(1 / 10); for( var i = 0, n = array_length(animators); i < n; i++ ) animators[i].suffix = " " + string(i); extract_node = ""; - break; - case VALUE_DISPLAY.transform : - editWidget = new transformBox(function(index, val) { - var _val = animator.getValue(); - _val[index] = val; - return setValueDirect(_val); - }); + break; #endregion + case VALUE_DISPLAY.transform : #region + editWidget = new transformBox(function(index, val) { return setValueInspector(val, index); }); extract_node = "Node_Transform_Array"; - break; + break; #endregion + case VALUE_DISPLAY.toggle : #region + editWidget = new toggleGroup(display_data.data, function(val) { + return setValueInspector(val); + } ); + + rejectConnect(); + key_inter = CURVE_TYPE.cut; + extract_node = ""; + break; #endregion + case VALUE_DISPLAY.d3quarternion : #region + editWidget = new quarternionBox(function(index, val) { + return setValueInspector(val, index); + }); + + extract_node = "Node_Vector4"; + display_data.angle_display = QUARTERNION_DISPLAY.quarterion; + break; #endregion + case VALUE_DISPLAY.path_anchor : #region + editWidget = new pathAnchorBox(function(index, val) { + return setValueInspector(val, index); + }); + + extract_node = "Node_Path_Anchor"; + break; #endregion + } break; - case VALUE_TYPE.boolean : - editWidget = new checkBox(function() { - return setValueDirect(!animator.getValue()); - } ); + case VALUE_TYPE.boolean : #region + if(name == "Active") editWidget = new checkBoxActive(function() { return setValueInspector(!animator.getValue()); } ); + else editWidget = new checkBox( function() { return setValueInspector(!animator.getValue()); } ); + key_inter = CURVE_TYPE.cut; extract_node = "Node_Boolean"; - break; - case VALUE_TYPE.color : + break; #endregion + case VALUE_TYPE.color : #region switch(display_type) { case VALUE_DISPLAY._default : - editWidget = new buttonColor(function(color) { - return setValueDirect(color); - } ); + editWidget = new buttonColor(function(color) { return setValueInspector(color); } ); graph_h = ui(16); extract_node = "Node_Color"; break; case VALUE_DISPLAY.palette : - editWidget = new buttonPalette(function(color) { - return setValueDirect(color); - } ); + editWidget = new buttonPalette(function(color) { return setValueInspector(color); } ); extract_node = "Node_Palette"; break; } - break; - case VALUE_TYPE.gradient : - editWidget = new buttonGradient(function(gradient) { - return setValueDirect(gradient); - } ); + break; #endregion + case VALUE_TYPE.gradient : #region + editWidget = new buttonGradient(function(gradient) { return setValueInspector(gradient); } ); extract_node = "Node_Gradient_Out"; - break; - case VALUE_TYPE.path : + break; #endregion + case VALUE_TYPE.path : #region switch(display_type) { case VALUE_DISPLAY.path_array : - editWidget = new pathArrayBox(node, display_data, function(path) { setValueDirect(path); } ); + editWidget = new pathArrayBox(node, display_data.filter, function(path) { setValueInspector(path); } ); break; case VALUE_DISPLAY.path_load : - editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { setValueDirect(str); }, - button(function() { - var path = get_open_filename(display_data[0], display_data[1]); - key_release(); - if(path == "") return noone; - return setValueDirect(path); - }, THEME.button_path_icon) - ); + editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { setValueInspector(str); } ); + editWidget.align = fa_left; + editWidget.side_button = button(function() { + var path = get_open_filename(display_data.filter, ""); + key_release(); + if(path == "") return noone; + return setValueInspector(path); + }, THEME.button_path_icon); extract_node = "Node_String"; break; case VALUE_DISPLAY.path_save : - editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { setValueDirect(str); }, - button(function() { - var path = get_save_filename(display_data[0], display_data[1]); - key_release(); - if(path == "") return noone; - return setValueDirect(path); - }, THEME.button_path_icon) - ); + editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { setValueInspector(str); } ); + editWidget.align = fa_left; + editWidget.side_button = button(function() { + var path = get_save_filename(display_data.filter, ""); + key_release(); + if(path == "") return noone; + return setValueInspector(path); + }, THEME.button_path_icon); extract_node = "Node_String"; break; case VALUE_DISPLAY.path_font : - editWidget = new fontScrollBox( - function(val) { - return setValueDirect(DIRECTORY + "Fonts/" + FONT_INTERNAL[val]); - } - ); + editWidget = new fontScrollBox( function(val) { return setValueInspector(DIRECTORY + "Fonts/" + FONT_INTERNAL[val]); } ); break; } - break; - case VALUE_TYPE.curve : + break; #endregion + case VALUE_TYPE.curve : #region display_type = VALUE_DISPLAY.curve; - editWidget = new curveBox(function(_modified) { - return setValueDirect(_modified); - }); - break; - case VALUE_TYPE.text : + editWidget = new curveBox(function(_modified) { return setValueInspector(_modified); }); + break; #endregion + case VALUE_TYPE.text : #region switch(display_type) { case VALUE_DISPLAY._default : - editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { - return setValueDirect(str); - }); + editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); + extract_node = "Node_String"; + break; + + case VALUE_DISPLAY.text_box : + editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); extract_node = "Node_String"; break; - case VALUE_DISPLAY.code : - editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { - return setValueDirect(str); - }); + case VALUE_DISPLAY.codeLUA : + editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); editWidget.font = f_code; - editWidget.format = TEXT_AREA_FORMAT.code; + editWidget.format = TEXT_AREA_FORMAT.codeLUA; + editWidget.min_lines = 4; + extract_node = "Node_String"; + break; + + case VALUE_DISPLAY.codeHLSL: + editWidget = new textArea(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); + + editWidget.autocomplete_server = hlsl_autocomplete_server; + editWidget.function_guide_server = hlsl_function_guide_server; + editWidget.parser_server = hlsl_document_parser; + editWidget.autocomplete_object = node; + + editWidget.font = f_code; + editWidget.format = TEXT_AREA_FORMAT.codeHLSL; editWidget.min_lines = 4; extract_node = "Node_String"; break; + case VALUE_DISPLAY.text_tunnel : + editWidget = new textBox(TEXTBOX_INPUT.text, function(str) { return setValueInspector(str); }); + extract_node = "Node_String"; + break; + case VALUE_DISPLAY.text_array : - editWidget = new textArrayBox(function() { - return animator.values[| 0].value; }, display_data, function() { node.doUpdate(); - }); + editWidget = new textArrayBox(function() { return animator.values[| 0].value; }, display_data.data, function() { node.doUpdate(); }); break; } - break; - case VALUE_TYPE.surface : - editWidget = new surfaceBox(function(ind) { - return setValueDirect(ind); - }, display_data ); + break; #endregion + case VALUE_TYPE.d3Material : #region + editWidget = new materialBox(function(ind) { + var res = setValueInspector(ind); + node.triggerRender(); + return res; + } ); + + if(!struct_has(display_data, "atlas")) display_data.atlas = true; show_in_inspector = true; extract_node = "Node_Canvas"; - break; - case VALUE_TYPE.pathnode : + break; #endregion + case VALUE_TYPE.surface : #region + editWidget = new surfaceBox(function(ind) { return setValueInspector(ind); } ); + + if(!struct_has(display_data, "atlas")) display_data.atlas = true; + show_in_inspector = true; + extract_node = "Node_Canvas"; + break; #endregion + case VALUE_TYPE.pathnode : #region extract_node = "Node_Path"; - break; + break; #endregion + } + + editWidgetRaw = editWidget; + if(editWidget) graphWidget = editWidget.clone(); + + for( var i = 0, n = ds_list_size(animator.values); i < n; i++ ) { + animator.values[| i].ease_in_type = key_inter; + animator.values[| i].ease_out_type = key_inter; } setDropKey(); - } - resetDisplay(); + updateColor(); + } resetDisplay(); #endregion - static expressionUpdate = function() { - expTree = evaluateFunctionList(expression); + static setMappable = function(index) { #region + attributes.mapped = false; + attributes.map_index = index; + + mapButton = button(function() { + attributes.mapped = !attributes.mapped; + var val = getValue(); + if( attributes.mapped && is_numeric(val)) setValue([0, val]); + if(!attributes.mapped && is_array(val)) setValue(array_safe_get_fast(val, 0)); + setArrayDepth(attributes.mapped); + + node.triggerRender(); + }) + .setIcon( THEME.value_use_surface, [ function() { return attributes.mapped; } ], COLORS._main_icon ) + .setTooltip("Toggle map"); + + switch(type) { + case VALUE_TYPE.gradient : + mapWidget = noone; + break; + + default : + mapWidget = new rangeBox(TEXTBOX_INPUT.number, function(index, val) { return setValueDirect(val, index); }); + mapWidget.side_button = mapButton; + break; + } + + editWidget.side_button = mapButton; + + return self; + } #endregion + + static setMapped = function(junc) { #region + mappedJunc = junc; + isTimelineVisible = function() { INLINE return is_anim && value_from == noone && mappedJunc.attributes.mapped; } + return self; + } #endregion + + static mappableStep = function() { #region + editWidget = mapWidget && attributes.mapped? mapWidget : editWidgetRaw; + setArrayDepth(attributes.mapped); + + var inp = node.inputs[| attributes.map_index]; + var vis = attributes.mapped && show_in_inspector; + + if(inp.visible != vis) { + inp.visible = vis; + node.refreshNodeDisplay(); + } + } #endregion + + static setColor = function(col) { #region + color = col; + updateColor(); + + if(value_from != noone) + value_from.setColor(col); + + return self; + } #endregion + + static updateColor = function(val = undefined) { #region + INLINE + + if(color == -1) { + draw_bg = isArray(val)? value_color_bg_array(draw_junction_index) : value_color_bg(draw_junction_index); + draw_fg = value_color(draw_junction_index); + } else { + draw_bg = isArray(val)? merge_color(color, colorMultiply(color, CDEF.main_dkgrey), 0.5) : value_color_bg(draw_junction_index); + draw_fg = color; + } + + color_display = type == VALUE_TYPE.action? #8fde5d : draw_fg; + } #endregion + + static setType = function(_type) { #region + if(type == _type) return false; + + type = _type; + draw_junction_index = type; + updateColor(); + + return true; + } #endregion + + static setUseExpression = function(useExp) { #region + INLINE + if(expUse == useExp) return; + expUse = useExp; node.triggerRender(); - } + } #endregion - static onValidate = function() { + static setExpression = function(_expression) { #region + expUse = true; + expression = _expression; + expressionUpdate(); + } #endregion + + static expressionUpdate = function() { #region + expTree = evaluateFunctionList(expression); + resetCache(); + node.triggerRender(); + } #endregion + + static onValidate = function() { #region if(!validateValue) return; var _val = value_validation, str = ""; value_validation = VALIDATION.pass; @@ -931,16 +1406,22 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru case VALUE_DISPLAY.path_load: var path = animator.getValue(); if(is_array(path)) path = path[0]; - if(try_get_path(path) == -1) { + + if(!is_string(path) || path == "") { + str = $"Path invalid: {path}"; + break; + } + + if(path_get(path) == -1) { value_validation = VALIDATION.error; - str = "File not exist: " + string(path); + str = $"File not exist: {path}"; } break; case VALUE_DISPLAY.path_array: var paths = animator.getValue(); if(is_array(paths)) { for( var i = 0, n = array_length(paths); i < n; i++ ) { - if(try_get_path(paths[i]) != -1) continue; + if(path_get(paths[i]) != -1) continue; value_validation = VALIDATION.error; str = "File not exist: " + string(paths[i]); } @@ -970,77 +1451,91 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru #endregion return self; - } + } #endregion - static valueProcess = function(value, nodeFrom, applyUnit = true, arrIndex = 0) { + static valueProcess = function(value, nodeFrom, applyUnit = true, arrIndex = 0) { #region var typeFrom = nodeFrom.type; - var display = nodeFrom.display_type; - if(type == VALUE_TYPE.gradient && typeFrom == VALUE_TYPE.color) { - if(is_struct(value) && instanceof(value) == "gradientObject") - return value; - if(is_array(value)) { - var amo = array_length(value); - var grad = array_create(amo); - for( var i = 0; i < amo; i++ ) - grad[i] = new gradientKey(i / amo, value[i]); - var g = new gradientObject(); - g.keys = grad; - return g; - } + #region color compatibility [ color, palette, gradient ] + if(type == VALUE_TYPE.gradient && typeFrom == VALUE_TYPE.color) { + if(is_instanceof(value, gradientObject)) + return value; + + if(is_array(value)) { + var amo = array_length(value); + var grad = array_create(amo); + for( var i = 0; i < amo; i++ ) + grad[i] = new gradientKey(i / amo, value[i]); + var g = new gradientObject(); + g.keys = grad; + return g; + } + + if(is_real(value)) return new gradientObject(value); + return new gradientObject(0); + } + + if(display_type == VALUE_DISPLAY.palette && !is_array(value)) { + return [ value ]; + } + #endregion + + if(display_type == VALUE_DISPLAY.area) { #region - var grad = new gradientObject(value); - return grad; - } - - if(display_type == VALUE_DISPLAY.palette && !is_array(value)) { - return [ value ]; - } - - if(display_type == VALUE_DISPLAY.area) { - var dispType = struct_try_get(nodeFrom.extra_data, "area_type", AREA_MODE.area); - var surfGet = nodeFrom.display_data; - if(!applyUnit || surfGet == -1) { - //print($" {value}"); - return value; + if(struct_has(nodeFrom.display_data, "onSurfaceSize")) { + var surf = nodeFrom.display_data.onSurfaceSize(); + + var ww = surf[0]; + var hh = surf[1]; + + var dispType = array_safe_get_fast(value, 5, AREA_MODE.area); + + switch(dispType) { + case AREA_MODE.area : + break; + + case AREA_MODE.padding : + var cx = (ww - value[0] + value[2]) / 2 + var cy = (value[1] + hh - value[3]) / 2; + var sw = abs((ww - value[0]) - value[2]) / 2; + var sh = abs(value[1] - (hh - value[3])) / 2; + + value = [cx, cy, sw, sh, value[4], value[5]]; + break; + + case AREA_MODE.two_point : + var cx = (value[0] + value[2]) / 2 + var cy = (value[1] + value[3]) / 2; + var sw = abs(value[0] - value[2]) / 2; + var sh = abs(value[1] - value[3]) / 2; + + value = [cx, cy, sw, sh, value[4], value[5]]; + break; + } } - var surf = surfGet(); - var ww = surf[0]; - var hh = surf[1]; + return applyUnit? unit.apply(value, arrIndex) : value; + } #endregion + + if(display_type == VALUE_DISPLAY.d3quarternion) { #region + if(!applyUnit) return value; + var dispType = display_data.angle_display; switch(dispType) { - case AREA_MODE.area : - return value; - - case AREA_MODE.padding : - var cx = (ww - value[0] + value[2]) / 2 - var cy = (value[1] + hh - value[3]) / 2; - var sw = abs((ww - value[0]) - value[2]) / 2; - var sh = abs(value[1] - (hh - value[3])) / 2; - return [cx, cy, sw, sh, value[4]]; - - case AREA_MODE.two_point : - var cx = (value[0] + value[2]) / 2 - var cy = (value[1] + value[3]) / 2; - var sw = abs(value[0] - value[2]) / 2; - var sh = abs(value[1] - value[3]) / 2; - return [cx, cy, sw, sh, value[4]]; - } - } - - - if(type == VALUE_TYPE.text) { - switch(display_type) { - case VALUE_DISPLAY.text_array : + case QUARTERNION_DISPLAY.quarterion : return value; - default: - return string_real(value); + case QUARTERNION_DISPLAY.euler : + var euler = new BBMOD_Quaternion().FromEuler(value[0], value[1], value[2]).ToArray(); + return euler; } - } + } #endregion - if(typeFrom == VALUE_TYPE.integer && type == VALUE_TYPE.color) - return value; + if(type == VALUE_TYPE.text) { #region + switch(display_type) { + case VALUE_DISPLAY.text_array : return value; + default: return string_real(value); + } + } #endregion if((typeFrom == VALUE_TYPE.integer || typeFrom == VALUE_TYPE.float || typeFrom == VALUE_TYPE.boolean) && type == VALUE_TYPE.color) return value >= 1? value : make_color_hsv(0, 0, value * 255); @@ -1048,75 +1543,163 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(typeFrom == VALUE_TYPE.boolean && type == VALUE_TYPE.text) return value? "true" : "false"; - if(type == VALUE_TYPE.integer || type == VALUE_TYPE.float) { + if(type == VALUE_TYPE.integer || type == VALUE_TYPE.float) { #region if(typeFrom == VALUE_TYPE.text) value = toNumber(value); - if(applyUnit) - return unit.apply(value, arrIndex); - } + value = applyUnit? unit.apply(value, arrIndex) : value; + + if(value_tag == "dimension") { + for( var i = 0, n = array_length(value); i < n; i++ ) + value[i] = clamp(value[i], 0, 8192); + } + + return value; + } #endregion if(type == VALUE_TYPE.surface && connect_type == JUNCTION_CONNECT.input && !is_surface(value) && def_val == USE_DEF) return DEF_SURFACE; return value; - } + } #endregion - static resetCache = function() { - cache_value[0] = false; - } + static valueExpressionProcess = function(value) { #region + switch(type) { + case VALUE_TYPE.float : + case VALUE_TYPE.integer : + if(!is_numeric(value)) + return toNumber(value); + break; + case VALUE_TYPE.boolean : + return bool(value); + } + + return value; + } #endregion - #region[#eb004b20] === GetValue === - static getValue = function(_time = PROJECT.animator.current_frame, applyUnit = true, arrIndex = 0, useCache = false) { + static resetCache = function() { cache_value[0] = false; } + + static getStaticValue = function() { INLINE return ds_list_empty(animator.values)? 0 : animator.values[| 0].value; } + + static getValue = function(_time = CURRENT_FRAME, applyUnit = true, arrIndex = 0, useCache = false, log = false) { #region if(type == VALUE_TYPE.trigger) - useCache = false; - - global.cache_call++; + return _getValue(_time, false, 0, false); + + //global.cache_call++; if(useCache && use_cache) { var cache_hit = cache_value[0]; - cache_hit &= (!is_anim && value_from == noone) || cache_value[1] == _time; + cache_hit &= !isActiveDynamic(_time) || cache_value[1] == _time; cache_hit &= cache_value[2] != undefined; + cache_hit &= cache_value[3] == applyUnit; cache_hit &= connect_type == JUNCTION_CONNECT.input; cache_hit &= unit.reference == noone || unit.mode == VALUE_UNIT.constant; - cache_hit &= !expUse; if(cache_hit) { - global.cache_hit++; + //global.cache_hit++; return cache_value[2]; } } - var val = _getValue(_time, applyUnit, arrIndex); + var val = _getValue(_time, applyUnit, arrIndex, log); + if(!accept_array && array_get_depth(val) > def_depth) { + noti_warning($"{name} does not accept array data.",, node); + return 0; + } + + draw_junction_index = type; + if(type == VALUE_TYPE.surface || type == VALUE_TYPE.any) { + var _sval = val; + if(is_array(_sval) && !array_empty(_sval)) + _sval = _sval[0]; + if(is_instanceof(_sval, SurfaceAtlas)) + draw_junction_index = VALUE_TYPE.atlas; + } if(useCache) { - is_changed = !isEqual(cache_value[2], val); cache_value[0] = true; cache_value[1] = _time; } cache_value[2] = val; + cache_value[3] = applyUnit; + + if(!IS_PLAYING) updateColor(val); return val; - } + } #endregion - static __getAnimValue = function(_time = PROJECT.animator.current_frame) { + static __getAnimValue = function(_time = CURRENT_FRAME) { #region + + if(value_tag == "dimension" && node.attributes.use_project_dimension) + return PROJECT.attributes.surface_dimension; + + if(!is_anim) { + if(sep_axis) { + if(ds_list_empty(animators[i].values)) return 0; + + var val = array_verify(val, array_length(animators)); + for( var i = 0, n = array_length(animators); i < n; i++ ) + val[i] = animators[i].processType(animators[i].values[| 0].value); + return val; + } + + if(ds_list_empty(animator.values)) return 0; + + return animator.processType(animator.values[| 0].value); + } + if(sep_axis) { var val = []; for( var i = 0, n = array_length(animators); i < n; i++ ) val[i] = animators[i].getValue(_time); return val; - } else - return animator.getValue(_time); - } + } + + return animator.getValue(_time); + } #endregion - static _getValue = function(_time = PROJECT.animator.current_frame, applyUnit = true, arrIndex = 0) { - var _val = getValueRecursive(_time); - var val = _val[0]; - var nod = _val[1]; + static arrayBalance = function(val) { #region // Balance array (generate uniform array from single values) + if(!is_array(def_val)) + return val; + + if(isDynamicArray()) + return val; + + if(isArray(val)) + return val; + + if(!is_array(val)) + return array_create(def_length, val); + + if(array_length(val) < def_length) + array_resize(val, def_length); + + return val; + } #endregion + + static _getValue = function(_time = CURRENT_FRAME, applyUnit = true, arrIndex = 0, log = false) { #region + + getValueRecursive(self.__curr_get_val, _time); + var val = __curr_get_val[0]; + var nod = __curr_get_val[1]; + var typ = nod.type; var dis = nod.display_type; - if(typ == VALUE_TYPE.surface && (type == VALUE_TYPE.integer || type == VALUE_TYPE.float) && accept_array) { //Dimension conversion + if(connect_type == JUNCTION_CONNECT.output) + return val; + + if(expUse) { #region expression + if(is_array(val)) { + for( var i = 0, n = array_length(val); i < n; i++ ) + val[i] = valueExpressionProcess(val[i]); + } else + val = valueExpressionProcess(val); + return arrayBalance(val); + + } #endregion + + if(typ == VALUE_TYPE.surface && (type == VALUE_TYPE.integer || type == VALUE_TYPE.float)) { #region Dimension conversion if(is_array(val)) { var eqSize = true; var sArr = []; @@ -1125,7 +1708,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru for( var i = 0, n = array_length(val); i < n; i++ ) { if(!is_surface(val[i])) continue; - var surfSz = [ surface_get_width(val[i]), surface_get_height(val[i]) ]; + var surfSz = [ surface_get_width_safe(val[i]), surface_get_height_safe(val[i]) ]; array_push(sArr, surfSz); if(i && !array_equals(surfSz, _osZ)) @@ -1137,299 +1720,427 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(eqSize) return _osZ; return sArr; } else if (is_surface(val)) - return [ surface_get_width(val), surface_get_height(val) ]; - return [1, 1]; - } + return [ surface_get_width_safe(val), surface_get_height_safe(val) ]; + return [ 1, 1 ]; + + } #endregion - if(is_array(def_val) && !typeArrayDynamic(display_type)) { //Balance array (generate uniform array from single values) - if(!is_array(val)) { - val = array_create(array_length(def_val), val); - return valueProcess(val, nod, applyUnit, arrIndex); - } else if(array_length(val) < array_length(def_val)) { - for( var i = array_length(val); i < array_length(def_val); i++ ) - val[i] = 0; + if(type == VALUE_TYPE.d3Material) { #region + if(nod == self) { + return def_val; + + } else if(typ == VALUE_TYPE.surface) { + if(!is_array(val)) return def_val.clone(val); + + var _val = array_create(array_length(val)); + for( var i = 0, n = array_length(val); i < n; i++ ) + _val[i] = def_val.clone(value[i]); + + return _val; } - } + } #endregion - if(isArray(val) && array_length(val) < 128) { //Process data + val = arrayBalance(val); + + if(isArray(val) && array_length(val) < 1024) { #region Process data + var _val = array_create(array_length(val)); for( var i = 0, n = array_length(val); i < n; i++ ) - val[i] = valueProcess(val[i], nod, applyUnit, arrIndex); - } else - val = valueProcess(val, nod, applyUnit, arrIndex); + _val[i] = valueProcess(val[i], nod, applyUnit, arrIndex); + return _val; + + } #endregion - return val; - } + return valueProcess(val, nod, applyUnit, arrIndex); + } #endregion - static getValueRecursive = function(_time = PROJECT.animator.current_frame) { - var val = [ -1, self ]; + static getValueRecursive = function(arr = __curr_get_val, _time = CURRENT_FRAME) { #region - if(type == VALUE_TYPE.trigger && connect_type == JUNCTION_CONNECT.output) //trigger even will not propagate from input to output, need to be done manually - return [ __getAnimValue(_time), self ]; + arr[@ 0] = __getAnimValue(_time); + arr[@ 1] = self; - if(value_from == noone) { - var _val = __getAnimValue(_time); - val = [ _val, self ]; - } else if(value_from != self) - val = value_from.getValueRecursive(_time); + if(value_from_loop && value_from_loop.bypassConnection() && value_from_loop.junc_out) + value_from_loop.getValue(arr); + + else if(value_from && value_from != self) + value_from.getValueRecursive(arr, _time); if(expUse && is_struct(expTree) && expTree.validate()) { - //print($"========== EXPRESSION CALLED =========="); - //print(debug_get_callstack(8)); if(global.EVALUATE_HEAD != noone && global.EVALUATE_HEAD == self) { - //noti_warning($"Expression evaluation error : recursive call detected."); + noti_warning($"Expression evaluation error : recursive call detected."); + } else { - printIf(global.LOG_EXPRESSION, $"==================== EVAL BEGIN {expTree} ===================="); - //print(json_beautify(json_stringify(expTree))); - //printCallStack(); global.EVALUATE_HEAD = self; - var params = { - name: name, - node_name: node.display_name, - value: val[0] + expContext = { + name : name, + node_name : node.display_name, + value : arr[0], + node_values : node.input_value_map, }; - var _exp_res = expTree.eval(variable_clone(params)); + var _exp_res = expTree.eval(variable_clone(expContext)); + printIf(global.LOG_EXPRESSION, $">>>> Result = {_exp_res}"); + if(is_undefined(_exp_res)) { - val[0] = 0; - noti_warning("Expression not returning any values."); + arr[@ 0] = 0; + noti_warning("Expression not returning valid values."); } else - val[0] = _exp_res; + arr[@ 0] = _exp_res; global.EVALUATE_HEAD = noone; } } - - return val; - } - #endregion + } #endregion - static setAnim = function(anim) { + static setAnim = function(anim, record = false) { #region + if(is_anim == anim) return; + if(record) { + recordAction(ACTION_TYPE.custom, function(data) { + setAnim(data.is_anim); + data.is_anim = !data.is_anim; + }, { anim: is_anim }); + } is_anim = anim; - PANEL_ANIMATION.updatePropertyList(); - } + + if(is_anim) { + if(ds_list_empty(animator.values)) + ds_list_add(animator.values, new valueKey(CURRENT_FRAME, animator.getValue(), animator)); + animator.values[| 0].time = CURRENT_FRAME; + animator.updateKeyMap(); + + for( var i = 0, n = array_length(animators); i < n; i++ ) { + if(ds_list_empty(animators[i].values)) + ds_list_add(animators[i].values, new valueKey(CURRENT_FRAME, animators[i].getValue(), animators[i])); + animators[i].values[| 0].time = CURRENT_FRAME; + animators[i].updateKeyMap(); + } + } else { + var _val = animator.getValue(); + ds_list_clear(animator.values); + animator.values[| 0] = new valueKey(0, _val, animator); + animator.updateKeyMap(); + + for( var i = 0, n = array_length(animators); i < n; i++ ) { + var _val = animators[i].getValue(); + ds_list_clear(animators[i].values); + animators[i].values[| 0] = new valueKey(0, _val, animators[i]); + animators[i].updateKeyMap(); + } + } + + if(type == VALUE_TYPE.gradient && struct_has(attributes, "map_index")) + node.inputs[| attributes.map_index + 1].setAnim(anim); + + node.refreshTimeline(); + } #endregion + + static isTimelineVisible = function() { INLINE return is_anim && value_from == noone; } - static __anim = function() { - if(node.update_on_frame) return true; + static isActiveDynamic = function(frame = CURRENT_FRAME) { #region + INLINE + + if(value_from_loop) return true; + if(value_from != noone) return false; + if(expUse) { if(!is_struct(expTree)) return false; - var res = expTree.isAnimated(); + var res = expTree.isDynamic(); + switch(res) { case EXPRESS_TREE_ANIM.none : return false; - case EXPRESS_TREE_ANIM.base_value : return is_anim; - case EXPRESS_TREE_ANIM.animated : return true; + case EXPRESS_TREE_ANIM.base_value : force_requeue = true; return is_anim; + case EXPRESS_TREE_ANIM.animated : force_requeue = true; return true; } } return is_anim; - } + } #endregion - static isAnimated = function() { - if(value_from == noone) return __anim(); - else return value_from.isAnimated() || value_from.__anim(); - } - - static showValue = function() { - var useCache = true; - if(display_type == VALUE_DISPLAY.area) - useCache = false; + show_val = []; + static showValue = function() { #region + INLINE - var val = getValue(, false, 0, useCache); + var val = 0; + + if(value_from != noone || is_anim || expUse) + val = getValue(CURRENT_FRAME, false, 0, true, true); + + else if(sep_axis) { + show_val = array_verify(show_val, array_length(animators)); + for( var i = 0, n = array_length(animators); i < n; i++ ) + show_val[i] = ds_list_empty(animators[i].values)? 0 : animators[i].processType(animators[i].values[| 0].value); + val = show_val; + } else + val = ds_list_empty(animator.values)? 0 : animator.processType(animator.values[| 0].value); - if(isArray()) { - if(array_length(val) == 0) return 0; - var v = val[safe_mod(node.preview_index, array_length(val))]; - if(array_length(v) >= 100) return $"[{array_length(v)}]"; - } return val; - } + } #endregion - static isArray = function(val = undefined) { - if(val == undefined) { - if(cache_array[0]) - return cache_array[1]; + static isDynamicArray = function() { #region + if(dynamic_array) return true; + + switch(display_type) { + case VALUE_DISPLAY.curve : + case VALUE_DISPLAY.palette : + return true; + } + + return false; + } #endregion + + static isArray = function(val = undefined) { #region + var _cac = val == undefined; + + if(_cac) { + if(cache_array[0]) return cache_array[1]; val = getValue(); + cache_array[0] = true; } - cache_array[0] = true; - - if(!is_array(val)) { //Value is array - cache_array[1] = false; - return cache_array[1]; + if(!is_array(val)) { //Value is scalar + if(_cac) cache_array[1] = false; + return false; } - if(array_depth == 0 && !typeArray(display_type)) { //Value is not an array by default, and no array depth enforced - cache_array[1] = true; - return cache_array[1]; + if(array_depth == 0 && !typeArray(display_type)) { // Value is not an array by default, and no array depth enforced + if(_cac) cache_array[1] = true; + return true; } var ar = val; repeat(array_depth + typeArray(display_type)) { //Recursively get the first member of subarray to check if value has depth of "array_depth" or not if(!is_array(ar) || !array_length(ar)) { //empty array - cache_array[1] = false; - return cache_array[1]; + if(_cac) cache_array[1] = false; + return false; } ar = ar[0]; } - cache_array[1] = is_array(ar); - return cache_array[1]; - } + if(_cac) cache_array[1] = is_array(ar); + return is_array(ar); + } #endregion - static arrayLength = function(val = undefined) { - if(val == undefined) - val = getValue(); + static arrayLength = function(val = undefined) { #region + val ??= getValue(); if(!isArray(val)) - return 0; + return -1; if(array_depth == 0 && !typeArray(display_type)) return array_length(val); - var ar = val; - repeat(array_depth - 1 + typeArray(display_type)) + var ar = val; + var _depth = max(0, array_depth + typeArray(display_type) - 1); + repeat(_depth) ar = ar[0]; return array_length(ar); - } + } #endregion - #region[#8fde5d16] === SetValue === - static setValue = function(val = 0, record = true, time = PROJECT.animator.current_frame, _update = true) { - //if(type == VALUE_TYPE.d3vertex && !is_array(val)) - // print(val); - + static setValue = function(val = 0, record = true, time = CURRENT_FRAME, _update = true) { #region val = unit.invApply(val); return setValueDirect(val, noone, record, time, _update); - } + } #endregion - static setValueDirect = function(val = 0, index = noone, record = true, time = PROJECT.animator.current_frame, _update = true) { - var updated = false; + static overrideValue = function(_val) { #region + ds_list_clear(animator.values); + ds_list_add(animator.values, new valueKey(0, _val, animator)); - //if(display_type == VALUE_DISPLAY.area) { - // print($"===== Set: {index} = {val} ====="); - // printCallStack(); - // print(""); - //} + for( var i = 0, n = array_length(animators); i < n; i++ ) { + ds_list_clear(animators[i].values); + ds_list_add(animators[i].values, new valueKey(0, array_safe_get_fast(_val, i), animators[i])); + } + } #endregion + + static setValueInspector = function(val = 0, index = noone) { #region + INLINE + var res = false; + val = unit.invApply(val); + + if(PANEL_INSPECTOR && PANEL_INSPECTOR.inspectGroup == 1) { + var ind = self.index; + + for( var i = 0, n = array_length(PANEL_INSPECTOR.inspectings); i < n; i++ ) { + var _node = PANEL_INSPECTOR.inspectings[i]; + if(ind >= ds_list_size(_node.inputs)) continue; + + var r = _node.inputs[| ind].setValueDirect(val, index); + if(_node == node) res = r; + } + } else { + res = setValueDirect(val, index); + + //print($"Node {node} : {node.name} {node.internalName}"); + //print($"Inspecting {PANEL_INSPECTOR.inspecting} : {PANEL_INSPECTOR.inspecting.name} {PANEL_INSPECTOR.inspecting.internalName}"); + //print($"{node == PANEL_INSPECTOR.inspecting}"); + //print(""); + } + + return res; + } #endregion + + static setValueDirect = function(val = 0, index = noone, record = true, time = CURRENT_FRAME, _update = true) { #region + is_modified = true; + var updated = false; + var _val = val; + var _inp = connect_type == JUNCTION_CONNECT.input; if(sep_axis) { if(index == noone) { for( var i = 0, n = array_length(animators); i < n; i++ ) - updated |= animators[i].setValue(val[i], connect_type == JUNCTION_CONNECT.input && record, time); + updated |= animators[i].setValue(val[i], _inp && record, time); } else - updated = animators[index].setValue(val, connect_type == JUNCTION_CONNECT.input && record, time); + updated = animators[index].setValue(val, _inp && record, time); + } else { if(index != noone) { - var _val = variable_clone(animator.getValue(time)); + _val = animator.getValue(time); + if(_inp) _val = variable_clone(_val); + _val[index] = val; - updated = animator.setValue(_val, connect_type == JUNCTION_CONNECT.input && record, time); - } else - updated = animator.setValue(val, connect_type == JUNCTION_CONNECT.input && record, time); + } + + updated = animator.setValue(_val, _inp && record, time); + //print($"{updated}: {index} - {_val}"); } if(type == VALUE_TYPE.gradient) updated = true; if(display_type == VALUE_DISPLAY.palette) updated = true; - if(display_type == VALUE_DISPLAY.transform) updated = true; - if(updated) { - if(connect_type == JUNCTION_CONNECT.input) { - node.triggerRender(); - if(_update) node.valueUpdate(self.index); - node.clearCacheForward(); - - if(fullUpdate) UPDATE |= RENDER_TYPE.full; - else UPDATE |= RENDER_TYPE.partial; - } - - if(!LOADING) PROJECT.modified = true; - cache_value[0] = false; + for( var i = 0, n = array_length(value_to_loop); i < n; i++ ) + value_to_loop[i].updateValue(); + + if(!updated) return false; + + if(value_tag == "dimension") + node.attributes.use_project_dimension = false; + + draw_junction_index = type; + if(type == VALUE_TYPE.surface) { + var _sval = val; + if(is_array(_sval) && !array_empty(_sval)) + _sval = _sval[0]; + if(is_instanceof(_sval, SurfaceAtlas)) + draw_junction_index = VALUE_TYPE.atlas; } + if(connect_type == JUNCTION_CONNECT.output) { + if(self.index == 0) { + node.preview_value = getValue(); + node.preview_array = "[" + array_shape(node.preview_value) + "]"; + } + return; + } + + if(is_instanceof(node, Node)) + node.setInputData(self.index, animator.getValue(time)); + + if(tags == VALUE_TAG.updateInTrigger || tags == VALUE_TAG.updateOutTrigger) return true; + + if(_update) { + if(!IS_PLAYING) node.triggerRender(); + node.valueUpdate(self.index); + node.clearCacheForward(); + } + + if(fullUpdate) RENDER_ALL + + if(!LOADING) PROJECT.modified = true; + + cache_value[0] = false; onValidate(); - return updated; - } - #endregion + return true; + } #endregion - static isConnectable = function(_valueFrom, checkRecur = true, log = false) { + static isConnectable = function(_valueFrom, checkRecur = true, log = false) { #region if(_valueFrom == -1 || _valueFrom == undefined || _valueFrom == noone) { - if(log) - noti_warning("LOAD: Cannot set node connection from " + string(_valueFrom) + " to " + string(name) + " of node " + string(node.name) + ".",, node); - return false; + if(log) noti_warning($"LOAD: Cannot set node connection from {_valueFrom} to {name} of node {node.name}.",, node); + return -1; } if(_valueFrom == value_from) { - print("whaT"); - return false; + if(log) noti_warning("whaT"); + return -1; } if(_valueFrom == self) { - if(log) - noti_warning("setFrom: Self connection is not allowed.",, node); - return false; + if(log) noti_warning("setFrom: Self connection is not allowed.",, node); + return -1; } if(!typeCompatible(_valueFrom.type, type)) { - if(log) - noti_warning($"setFrom: Type mismatch {_valueFrom.type} to {type}",, node); - return false; + if(log) noti_warning($"setFrom: Type mismatch {_valueFrom.type} to {type}",, node); + return -1; } if(typeIncompatible(_valueFrom, self)) { - if(log) - noti_warning("setFrom: Type mismatch",, node); - return false; + if(log) noti_warning("setFrom: Type mismatch",, node); + return -1; } if(connect_type == _valueFrom.connect_type) { - if(log) - noti_warning("setFrom: Connect type mismatch",, node); - return false; + if(log) noti_warning("setFrom: Connect type mismatch",, node); + return -1; } if(checkRecur && _valueFrom.searchNodeBackward(node)) { - if(log) - noti_warning("setFrom: Cyclic connection not allowed.",, node); - return false; + if(log) noti_warning("setFrom: Cyclic connection not allowed.",, node); + return -9; } if(!accept_array && isArray(_valueFrom.getValue())) { - if(log) - noti_warning("setFrom: Array mismatch",, node); - return false; + if(log) noti_warning("setFrom: Array mismatch",, node); + return -1; } if(!accept_array && _valueFrom.type == VALUE_TYPE.surface && (type == VALUE_TYPE.integer || type == VALUE_TYPE.float)) { - if(log) - noti_warning("setFrom: Array mismatch",, node); - return false; + if(log) noti_warning("setFrom: Array mismatch",, node); + return -1; } - return true; - } + return 1; + } #endregion - static setFrom = function(_valueFrom, _update = true, checkRecur = true, log = false) { + static isLeaf = function() { INLINE return value_from == noone; } + static isLeafList = function(list = noone) { INLINE return value_from == noone || !ds_list_exist(list, value_from.node); } + + static isRendered = function() { #region + if(type == VALUE_TYPE.node) return true; + + if( value_from == noone) return true; + + var controlNode = struct_has(value_from, "from")? value_from.from : value_from.node; + if(!controlNode.active) return true; + if(!controlNode.isRenderActive()) return true; + + return controlNode.rendered; + } #endregion + + static setFrom = function(_valueFrom, _update = true, checkRecur = true, log = false) { #region + //print($"Connecting {_valueFrom.name} to {name}"); + if(_valueFrom == noone) return removeFrom(); - if(!isConnectable(_valueFrom, checkRecur, log)) - return -1; + var conn = isConnectable(_valueFrom, checkRecur, log); + if(conn < 0) return conn; if(setFrom_condition != -1 && !setFrom_condition(_valueFrom)) return -2; if(value_from != noone) - ds_list_remove(value_from.value_to, self); + array_remove(value_from.value_to, self); var _o = animator.getValue(); recordAction(ACTION_TYPE.junction_connect, self, value_from); value_from = _valueFrom; - ds_list_add(_valueFrom.value_to, self); - //show_debug_message("connected " + name + " to " + _valueFrom.name) + array_push(_valueFrom.value_to, self); node.valueUpdate(index, _o); if(_update && connect_type == JUNCTION_CONNECT.input) { - node.onValueFromUpdate(index); + node.valueFromUpdate(index); node.triggerRender(); node.clearCacheForward(); @@ -1439,33 +2150,50 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru cache_array[0] = false; cache_value[0] = false; - draw_line_shift_x = 0; - draw_line_shift_y = 0; + if(!LOADING) { + draw_line_shift_x = 0; + draw_line_shift_y = 0; + PROJECT.modified = true; + } - if(!LOADING) PROJECT.modified = true; + RENDER_ALL_REORDER + + if(onSetFrom != noone) onSetFrom(_valueFrom); + if(_valueFrom.onSetTo != noone) _valueFrom.onSetTo(self); return true; - } + } #endregion - static removeFrom = function(_remove_list = true) { + static removeFrom = function(_remove_list = true) { #region recordAction(ACTION_TYPE.junction_disconnect, self, value_from); if(_remove_list && value_from != noone) - ds_list_remove(value_from.value_to, self); + array_remove(value_from.value_to, self); value_from = noone; if(connect_type == JUNCTION_CONNECT.input) - node.onValueFromUpdate(index); + node.valueFromUpdate(index); node.clearCacheForward(); + PROJECT.modified = true; + + RENDER_ALL_REORDER return false; - } + } #endregion - static getShowString = function() { + static removeFromLoop = function(_remove_list = true) { #region + if(value_from_loop != noone) + value_from_loop.destroy(); + + PROJECT.modified = true; + } #endregion + + static getShowString = function() { #region var val = showValue(); return string_real(val); - } + } #endregion - static setString = function(str) { + static setString = function(str) { #region + if(connect_type == JUNCTION_CONNECT.output) return; var _o = animator.getValue(); if(string_pos(",", str) > 0) { @@ -1500,16 +2228,16 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru setValue(toNumber(str)); } } - } + } #endregion - static checkConnection = function(_remove_list = true) { - if(value_from == noone) return; + static checkConnection = function(_remove_list = true) { #region + if(isLeaf()) return; if(value_from.node.active) return; removeFrom(_remove_list); - } + } #endregion - static searchNodeBackward = function(_node) { + static searchNodeBackward = function(_node) { #region if(node == _node) return true; for(var i = 0; i < ds_list_size(node.inputs); i++) { var _in = node.inputs[| i].value_from; @@ -1517,85 +2245,103 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru return true; } return false; - } + } #endregion - static unitConvert = function(mode) { + static unitConvert = function(mode) { #region var _v = animator.values; for( var i = 0; i < ds_list_size(_v); i++ ) _v[| i].value = unit.convertUnit(_v[| i].value, mode); - } + } #endregion - drag_type = 0; - drag_mx = 0; - drag_my = 0; - drag_sx = 0; - drag_sy = 0; - static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) { + static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region if(type != VALUE_TYPE.integer && type != VALUE_TYPE.float) return -1; if(value_from != noone) return -1; if(expUse) return -1; + var arc = 9; + switch(display_type) { case VALUE_DISPLAY._default : - var _angle = argument_count > 8? argument[ 8] : 0; - var _scale = argument_count > 9? argument[ 9] : 1; - var _spr = argument_count > 10? argument[10] : THEME.anchor_selector; - return preview_overlay_scalar(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny, _angle, _scale, _spr); + var _angle = argument_count > arc + 0? argument[arc + 0] : 0; + var _scale = argument_count > arc + 1? argument[arc + 1] : 1; + var _spr = argument_count > arc + 2? argument[arc + 2] : THEME.anchor_selector; + return preview_overlay_scalar(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _angle, _scale, _spr); case VALUE_DISPLAY.rotation : - var _rad = argument_count > 8? argument[ 8] : 64; - return preview_overlay_rotation(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny, _rad); + var _rad = argument_count > arc + 0? argument[ arc + 0] : 64; + return preview_overlay_rotation(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _rad); case VALUE_DISPLAY.vector : - var _spr = argument_count > 8? argument[8] : THEME.anchor_selector; - var _sca = argument_count > 9? argument[9] : 1; - return preview_overlay_vector(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny, _spr); + var _spr = argument_count > arc + 0? argument[arc + 0] : THEME.anchor_selector; + var _sca = argument_count > arc + 1? argument[arc + 1] : 1; + return preview_overlay_vector(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _spr); + + case VALUE_DISPLAY.gradient_range : + var _dim = argument[arc]; + + if(mappedJunc.attributes.mapped) + return preview_overlay_gradient_range(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _dim); + break; case VALUE_DISPLAY.area : - return preview_overlay_area(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny, display_data); + var _flag = argument_count > arc + 0? argument[arc + 0] : 0b0011; + return preview_overlay_area(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny, _flag, struct_try_get(display_data, "onSurfaceSize")); case VALUE_DISPLAY.puppet_control : - return preview_overlay_puppet(value_from == noone, active, _x, _y, _s, _mx, _my, _snx, _sny); + return preview_overlay_puppet(isLeaf(), active, _x, _y, _s, _mx, _my, _snx, _sny); } return -1; - } + } #endregion - junction_drawing = [ THEME.node_junctions_single, type ]; - static drawJunction = function(_s, _mx, _my, sca = 1) { - if(!isVisible()) return false; + static drawJunction_fast = function(_s, _mx, _my) { #region + INLINE - var ss = max(0.25, _s / 2); - var is_hover = false; + var hov = PANEL_GRAPH.pHOVER && (PANEL_GRAPH.node_hovering == noone || PANEL_GRAPH.node_hovering == node); + var is_hover = hov && abs(_mx - x) + abs(_my - y) < _s; - if(PANEL_GRAPH.pHOVER && point_in_circle(_mx, _my, x, y, 10 * _s * sca)) { - //var _to = getJunctionTo(); - //var _ss = ""; - //for( var i = 0, n = array_length(_to); i < n; i++ ) - // _ss += (i? ", " : "") + _to[i].internalName; - //TOOLTIP = _ss; + draw_set_color(draw_fg); + draw_circle(x, y, _s, false); - is_hover = true; - if(type == VALUE_TYPE.action) - junction_drawing = [THEME.node_junction_inspector, 1]; - else - junction_drawing = [isArray()? THEME.node_junctions_array_hover : THEME.node_junctions_single_hover, type]; + return is_hover; + } #endregion + + static drawJunction = function(_s, _mx, _my) { #region + _s /= 2; + + var hov = PANEL_GRAPH.pHOVER && (PANEL_GRAPH.node_hovering == noone || PANEL_GRAPH.node_hovering == node); + var _d = 12 * _s; + var is_hover = hov && point_in_rectangle(_mx, _my, x - _d, y - _d, x + _d, y + _d); + hover_in_graph = is_hover; + + var _bgS = THEME.node_junctions_bg; + var _fgS = is_hover? THEME.node_junctions_outline_hover : THEME.node_junctions_outline; + + if(type == VALUE_TYPE.action) { + var _cbg = c_white; + + if(draw_blend != -1) + _cbg = merge_color(draw_blend_color, _cbg, draw_blend); + + __draw_sprite_ext(THEME.node_junction_inspector, is_hover, x, y, _s, _s, 0, _cbg, 1); } else { - if(type == VALUE_TYPE.action) - junction_drawing = [THEME.node_junction_inspector, 0]; - else - junction_drawing = [isArray()? THEME.node_junctions_array : THEME.node_junctions_single, type]; + var _cbg = draw_bg; + var _cfg = draw_fg; + + if(draw_blend != -1) { + _cbg = merge_color(draw_blend_color, _cbg, draw_blend); + _cfg = merge_color(draw_blend_color, _cfg, draw_blend); + } + + __draw_sprite_ext(_bgS, draw_junction_index, x, y, _s, _s, 0, _cbg, 1); + __draw_sprite_ext(_fgS, draw_junction_index, x, y, _s, _s, 0, _cfg, 1); } - draw_sprite_ext(junction_drawing[0], junction_drawing[1], x, y, ss, ss, 0, c_white, 1); - return is_hover; - } + } #endregion - static drawNameBG = function(_s) { - if(!isVisible()) return false; - + static drawNameBG = function(_s) { #region draw_set_text(f_p1, fa_left, fa_center); var tw = string_width(name) + 32; @@ -1611,177 +2357,114 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru var tx = x + 12 * _s; draw_sprite_stretched_ext(THEME.node_junction_name_bg, 0, tx - 16, y - th / 2, tw, th, c_white, 0.5); } - } - static drawName = function(_s, _mx, _my) { - if(!isVisible()) return false; + } #endregion + + static drawName = function(_s, _mx, _my) { #region - var _hover = PANEL_GRAPH.pHOVER && point_in_circle(_mx, _my, x, y, 10 * _s); - var _draw_cc = _hover? COLORS._main_text : COLORS._main_text_sub; + var _draw_cc = hover_in_graph? COLORS._main_text : COLORS._main_text_sub; draw_set_text(f_p1, fa_left, fa_center, _draw_cc); if(type == VALUE_TYPE.action) { var tx = x; draw_set_text(f_p1, fa_center, fa_center, _draw_cc); - draw_text(tx, y - (line_get_height() + 16) / 2, name); + draw_text_int(tx, y - (line_get_height() + 16) / 2, name); + } else if(connect_type == JUNCTION_CONNECT.input) { var tx = x - 12 * _s; draw_set_halign(fa_right); - draw_text(tx, y, name); + draw_text_int(tx, y, name); + } else { var tx = x + 12 * _s; draw_set_halign(fa_left); - draw_text(tx, y, name); + draw_text_int(tx, y, name); + } - } + } #endregion - static drawConnections = function(_x, _y, _s, mx, my, _active, aa = 1, minx = undefined, miny = undefined, maxx = undefined, maxy = undefined) { - if(value_from == noone) return noone; + static drawConnections = function(params = {}) { #region + if(isLeaf()) return noone; if(!value_from.node.active) return noone; if(!isVisible()) return noone; - var hovering = noone; - var jx = x; - var jy = y; - - var frx = value_from.x; - var fry = value_from.y; - - if(!is_undefined(minx)) { - if(jx < minx && frx < minx) return noone; - if(jx > maxx && frx > maxx) return noone; - - if(jy < miny && fry < miny) return noone; - if(jy > maxy && fry > maxy) return noone; - } - - var c0 = value_color(value_from.type); - var c1 = value_color(type); - - var shx = draw_line_shift_x * _s; - var shy = draw_line_shift_y * _s; - - var cx = round((frx + jx) / 2 + shx); - var cy = round((fry + jy) / 2 + shy); - - var hover = false; - var th = max(1, PREF_MAP[? "connection_line_width"] * _s); - draw_line_shift_hover = false; - - var downDirection = type == VALUE_TYPE.action || value_from.type == VALUE_TYPE.action; - - if(PANEL_GRAPH.pHOVER) - switch(PREF_MAP[? "curve_connection_line"]) { - case 0 : - hover = distance_to_line(mx, my, jx, jy, frx, fry) < max(th * 2, 6); - break; - case 1 : - if(downDirection) - hover = distance_to_curve_corner(mx, my, jx, jy, frx, fry, _s) < max(th * 2, 6); - else - hover = distance_to_curve(mx, my, jx, jy, frx, fry, cx, cy, _s) < max(th * 2, 6); - - if(PANEL_GRAPH._junction_hovering == noone) - draw_line_shift_hover = hover; - break; - case 2 : - if(downDirection) - hover = distance_to_elbow_corner(mx, my, frx, fry, jx, jy) < max(th * 2, 6); - else - hover = distance_to_elbow(mx, my, frx, fry, jx, jy, cx, cy, _s, value_from.drawLineIndex, drawLineIndex) < max(th * 2, 6); - - if(PANEL_GRAPH._junction_hovering == noone) - draw_line_shift_hover = hover; - break; - case 3 : - if(downDirection) - hover = distance_to_elbow_diag_corner(mx, my, frx, fry, jx, jy) < max(th * 2, 6); - else - hover = distance_to_elbow_diag(mx, my, frx, fry, jx, jy, cx, cy, _s, value_from.drawLineIndex, drawLineIndex) < max(th * 2, 6); - - if(PANEL_GRAPH._junction_hovering == noone) - draw_line_shift_hover = hover; - break; - } - - if(_active && hover) - hovering = self; - - var thicken = false; - thicken |= PANEL_GRAPH.nodes_junction_d == self; - thicken |= _active && PANEL_GRAPH.junction_hovering == self && PANEL_GRAPH._junction_hovering == noone; - thicken |= instance_exists(o_dialog_add_node) && o_dialog_add_node.junction_hovering == self; - - th *= thicken? 2 : 1; - - var corner = PREF_MAP[? "connection_line_corner"] * _s; - var ty = LINE_STYLE.solid; - if(type == VALUE_TYPE.node) - ty = LINE_STYLE.dashed; - - var ss = _s * aa; - jx *= aa; - jy *= aa; - frx *= aa; - fry *= aa; - th *= aa; - cx *= aa; - cy *= aa; - corner *= aa; - th = max(1, round(th)); - - draw_set_color(c0); - - var fromIndex = value_from.drawLineIndex; - var toIndex = drawLineIndex; + return drawJuncConnection(value_from, self, params); + } #endregion + + static drawConnectionMouse = function(params, _mx, _my, target) { #region + var ss = params.s; + var aa = params.aa; // 1 - switch(PREF_MAP[? "curve_connection_line"]) { - case 0 : - if(ty == LINE_STYLE.solid) - draw_line_width_color(jx, jy, frx, fry, th, c1, c0); - else - draw_line_dashed_color(jx, jy, frx, fry, th, c1, c0, 12 * ss); - break; + var drawCorner = type == VALUE_TYPE.action; + if(target != noone) + drawCorner |= target.type == VALUE_TYPE.action; + + var corner = PREFERENCES.connection_line_corner * ss; + var th = max(1, PREFERENCES.connection_line_width * ss); + + var sx = x; + var sy = y; + + corner *= aa; + th *= aa; + ss *= aa; + sx *= aa; + sy *= aa; + _mx *= aa; + _my *= aa; + + var col = color_display; + draw_set_color(col); + + var _action = type == VALUE_TYPE.action; + var _output = connect_type == JUNCTION_CONNECT.output; + + switch(PREFERENCES.curve_connection_line) { + case 0 : draw_line_width(sx, sy, _mx, _my, th); break; case 1 : - if(downDirection) - draw_line_curve_corner(jx, jy, frx, fry, ss, th, c0, c1); - else - draw_line_curve_color(jx, jy, frx, fry, cx, cy, ss, th, c0, c1, ty); + if(drawCorner) { + if(_action) draw_line_curve_corner(_mx, _my, sx, sy, ss, th, col, col); + else draw_line_curve_corner(sx, sy, _mx, _my, ss, th, col, col); + } else { + if(_output) draw_line_curve_color(_mx, _my, sx, sy,,, ss, th, col, col); + else draw_line_curve_color(sx, sy, _mx, _my,,, ss, th, col, col); + } break; case 2 : - if(downDirection) - draw_line_elbow_corner(frx, fry, jx, jy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); - else - draw_line_elbow_color(frx, fry, jx, jy, cx, cy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + if(drawCorner) { + if(_action) draw_line_elbow_corner(_mx, _my, sx, sy, ss, th, col, col, corner); + else draw_line_elbow_corner(sx, sy, _mx, _my, ss, th, col, col, corner); + } else { + if(_output) draw_line_elbow_color(sx, sy, _mx, _my,,, ss, th, col, col, corner); + else draw_line_elbow_color(_mx, _my, sx, sy,,, ss, th, col, col, corner); + } break; case 3 : - if(downDirection) - draw_line_elbow_diag_corner(frx, fry, jx, jy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); - else - draw_line_elbow_diag_color(frx, fry, jx, jy, cx, cy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + if(drawCorner) { + if(_action) draw_line_elbow_diag_corner(_mx, _my, sx, sy, ss, th, col, col, corner); + else draw_line_elbow_diag_corner(sx, sy, _mx, _my, ss, th, col, col, corner); + } else { + if(_output) draw_line_elbow_diag_color(sx, sy, _mx, _my,,, ss, th, col, col, corner); + else draw_line_elbow_diag_color(_mx, _my, sx, sy,,, ss, th, col, col, corner); + } break; } - - return hovering; - } + } #endregion - static isVisible = function() { - if(!node.active) - return false; - - if(value_from) - return true; + static isVisible = function() { #region + if(!node.active) return false; - if(connect_type == JUNCTION_CONNECT.input) { - if(!visible) - return false; - - if(is_array(node.input_display_list)) - return array_exists(node.input_display_list, index); - } - return visible; - } + if(connect_type == JUNCTION_CONNECT.output) + return visible || !array_empty(value_to); + + if(value_from) return true; + if(!visible) return false; + + if(index == -1) return true; + + return visible_in_list; + } #endregion - static extractNode = function(_type = extract_node) { + static extractNode = function(_type = extract_node) { #region if(_type == "") return noone; var ext = nodeBuild(_type, node.x, node.y); @@ -1832,24 +2515,25 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru } ext.doUpdate(); - PANEL_ANIMATION.updatePropertyList(); - } + } #endregion - static getJunctionTo = function() { - var to = []; + static hasJunctionFrom = function() { INLINE return value_from != noone; } + + static getJunctionTo = function() { #region + var _junc_to = []; - for(var j = 0; j < ds_list_size(value_to); j++) { - var _to = value_to[| j]; - if(!_to.node.active || _to.value_from == noone) continue; + for(var i = 0; i < array_length(value_to); i++) { + var _to = value_to[i]; + if(!_to.node.active || _to.isLeaf()) continue; if(_to.value_from != self) continue; - array_push(to, _to); + array_push(_junc_to, _to); } - - return to; - } + + return _junc_to; + } #endregion - static dragValue = function() { + static dragValue = function() { #region if(drop_key == "None") return; DRAGGING = { @@ -1864,13 +2548,13 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(connect_type == JUNCTION_CONNECT.input) DRAGGING.from = self; - } + } #endregion - #region[#88ffe916] === Save Load === - static serialize = function(scale = false, preset = false) { + static serialize = function(scale = false, preset = false) { #region var _map = {}; _map.visible = visible; + _map.color = color; if(connect_type == JUNCTION_CONNECT.output) return _map; @@ -1882,8 +2566,18 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru _map.sep_axis = sep_axis; _map.shift_x = draw_line_shift_x; _map.shift_y = draw_line_shift_y; - _map.from_node = !preset && value_from? value_from.node.node_id : -1; - _map.from_index = !preset && value_from? value_from.index : -1; + _map.is_modified= is_modified; + + if(!preset && value_from) { + _map.from_node = value_from.node.node_id; + + if(value_from.tags != 0) _map.from_index = value_from.tags; + else _map.from_index = value_from.index; + } else { + _map.from_node = -1; + _map.from_index = -1; + } + _map.global_use = expUse; _map.global_key = expression; _map.anim = is_anim; @@ -1893,26 +2587,26 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru var _anims = []; for( var i = 0, n = array_length(animators); i < n; i++ ) array_push(_anims, animators[i].serialize(scale)); - _map.animators = _anims; - _map.data = extra_data; + _map.animators = _anims; + _map.display_data = display_data; + _map.attributes = attributes; + _map.name_custom = name_custom; return _map; - } + } #endregion - con_node = -1; - con_index = -1; - - static applyDeserialize = function(_map, scale = false, preset = false) { + static applyDeserialize = function(_map, scale = false, preset = false) { #region if(_map == undefined) return; if(_map == noone) return; if(!is_struct(_map)) return; visible = struct_try_get(_map, "visible", visible); + color = struct_try_get(_map, "color", -1); + if(connect_type == JUNCTION_CONNECT.output) return; - //printIf(TESTING, " |- Applying deserialize to junction " + name + " of node " + node.name); - name = struct_try_get(_map, "name", name); + //print($" > Applying deserialize to junction {name} 0"); on_end = struct_try_get(_map, "on_end"); loop_range = struct_try_get(_map, "loop_range", -1); unit.mode = struct_try_get(_map, "unit"); @@ -1921,10 +2615,15 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru expTree = evaluateFunctionList(expression); sep_axis = struct_try_get(_map, "sep_axis"); - is_anim = struct_try_get(_map, "anim"); + setAnim(struct_try_get(_map, "anim")); draw_line_shift_x = struct_try_get(_map, "shift_x"); draw_line_shift_y = struct_try_get(_map, "shift_y"); + is_modified = struct_try_get(_map, "is_modified", true); + + struct_append(attributes, struct_try_get(_map, "attributes")) + name_custom = struct_try_get(_map, "name_custom", false); + if(name_custom) name = struct_try_get(_map, "name", name); animator.deserialize(struct_try_get(_map, "raw_value"), scale); @@ -1940,15 +2639,30 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru con_index = struct_try_get(_map, "from_index", -1); } - if(struct_has(_map, "data") && is_struct(_map.data)) - extra_data = _map.data; + if(struct_has(_map, "display_data")) { + for( var i = 0, n = array_length(DISPLAY_DATA_KEYS); i < n; i++ ) + struct_try_override(display_data, _map.display_data, DISPLAY_DATA_KEYS[i]); + } - if(APPENDING) def_val = getValue(0); + if(connect_type == JUNCTION_CONNECT.input && index >= 0) { + var _value = animator.getValue(0); + node.inputs_data[index] = _value; + node.input_value_map[$ internalName] = _value; + } + + attributeApply(); onValidate(); - } + } #endregion - static connect = function(log = false) { + static attributeApply = function() { #region + if(struct_has(attributes, "mapped") && attributes.mapped) + mappableStep(); + } #endregion + + static connect = function(log = false) { #region + //print($"{node} | {con_node} : {con_index}"); + if(con_node == -1 || con_index == -1) return true; @@ -1970,7 +2684,9 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(log) log_warning("LOAD", $"[Connect] Reconnecting {node.name} to {_nd.name}", node); - if(con_index < _ol) { + if(con_index == VALUE_TAG.updateInTrigger) setFrom(_nd.updatedInTrigger); + else if(con_index == VALUE_TAG.updateOutTrigger) setFrom(_nd.updatedOutTrigger); + else if(con_index < _ol) { var _set = setFrom(_nd.outputs[| con_index], false, true); if(_set) return true; @@ -1982,19 +2698,188 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru log_warning("LOAD", $"[Connect] Connection conflict {node.name} to {_nd.name} : Output not exist.", node); return false; - } - #endregion + } #endregion - static destroy = function() { + static destroy = function() { #region if(error_notification != noone) { noti_remove(error_notification); error_notification = noone; } - } + } #endregion - static cleanUp = function() { - ds_list_destroy(value_to); - animator.cleanUp(); - delete animator; - } -} \ No newline at end of file + static cleanUp = function() { #region + + } #endregion + + static toString = function() { return (connect_type == JUNCTION_CONNECT.input? "Input" : "Output") + $" junction {index} of [{name}]: {node}"; } +} + +function drawJuncConnection(from, to, params) { #region + #region parameters + var log = params.log; + var high = params.highlight; + var bg = params.bg; + var aa = params.aa; + + var _x = params.x; + var _y = params.y; + var _s = params.s; + var mx = params.mx; + var my = params.my; + var _active = params.active; + var cur_layer = params.cur_layer; + var max_layer = params.max_layer; + + var hovering = noone; + + var jx = to.x; + var jy = to.y; + + var frx = from.x; + var fry = from.y; + + var fromIndex = from.drawLineIndex; + var toIndex = to.drawLineIndex; + + if(params.minx != 0 && params.maxx != 0) { + var minx = params.minx; + var miny = params.miny; + var maxx = params.maxx; + var maxy = params.maxy; + + if(jx < minx && frx < minx) return noone; + if(jx > maxx && frx > maxx) return noone; + + if(jy < miny && fry < miny) return noone; + if(jy > maxy && fry > maxy) return noone; + } + + var shx = to.draw_line_shift_x * _s; + var shy = to.draw_line_shift_y * _s; + + var cx = round((frx + jx) / 2 + shx); + var cy = round((fry + jy) / 2 + shy); + + var hover = false; + var th = max(1, PREFERENCES.connection_line_width * _s); + to.draw_line_shift_hover = false; + + var downDirection = to.type == VALUE_TYPE.action || from.type == VALUE_TYPE.action; + #endregion + + #region +++++ CHECK HOVER +++++ + var hovDist = max(th * 2, 6); + + if(PANEL_GRAPH.pHOVER) { + if(from.node == to.node) { + hover = distance_line_feedback(mx, my, jx, jy, frx, fry, _s) < hovDist; + } else { + switch(PREFERENCES.curve_connection_line) { + case 0 : + hover = distance_to_line(mx, my, jx, jy, frx, fry) < hovDist; + break; + case 1 : + if(downDirection) hover = distance_to_curve_corner(mx, my, jx, jy, frx, fry, _s) < hovDist; + else hover = distance_to_curve(mx, my, jx, jy, frx, fry, cx, cy, _s) < hovDist; + + if(PANEL_GRAPH.value_focus == noone) + to.draw_line_shift_hover = hover; + break; + case 2 : + if(downDirection) hover = distance_to_elbow_corner(mx, my, frx, fry, jx, jy) < hovDist; + else hover = distance_to_elbow(mx, my, frx, fry, jx, jy, cx, cy, _s, fromIndex, toIndex) < hovDist; + + if(PANEL_GRAPH.value_focus == noone) + to.draw_line_shift_hover = hover; + break; + case 3 : + if(downDirection) hover = distance_to_elbow_diag_corner(mx, my, frx, fry, jx, jy) < hovDist; + else hover = distance_to_elbow_diag(mx, my, frx, fry, jx, jy, cx, cy, _s, fromIndex, toIndex) < hovDist; + + if(PANEL_GRAPH.value_focus == noone) + to.draw_line_shift_hover = hover; + break; + } + } + } + + if(_active && hover) + hovering = self; + #endregion + + #region draw parameters + var thicken = false; + thicken |= PANEL_GRAPH.nodes_junction_d == self; + thicken |= _active && PANEL_GRAPH.junction_hovering == self && PANEL_GRAPH.value_focus == noone; + thicken |= instance_exists(o_dialog_add_node) && o_dialog_add_node.junction_hovering == self; + + th *= thicken? 2 : 1; + + var corner = PREFERENCES.connection_line_corner * _s; + + var ty = LINE_STYLE.solid; + if(to.type == VALUE_TYPE.node || struct_try_get(params, "dashed")) + ty = LINE_STYLE.dashed; + + var c0, c1; + var _selc = to.node.branch_drawing && from.node.branch_drawing; + + if(high) { + var _fade = PREFERENCES.connection_line_highlight_fade; + var _colr = _selc? 1 : _fade; + + c0 = merge_color(bg, from.color_display, _colr); + c1 = merge_color(bg, to.color_display, _colr); + + to.draw_blend_color = bg; + to.draw_blend = _colr; + from.draw_blend = max(from.draw_blend, _colr); + } else { + c0 = from.color_display; + c1 = to.color_display; + + to.draw_blend_color = bg; + to.draw_blend = -1; + } + #endregion + + #region +++++ DRAW LINE +++++ + var ss = _s * aa; + jx *= aa; + jy *= aa; + frx *= aa; + fry *= aa; + th *= aa; + cx *= aa; + cy *= aa; + corner *= aa; + th = max(1, round(th)); + + draw_set_color(c0); + + if(from.node == to.node) { + draw_line_feedback(jx, jy, frx, fry, th, c1, c0, ss); + } else { + switch(PREFERENCES.curve_connection_line) { + case 0 : + if(ty == LINE_STYLE.solid) draw_line_width_color(jx, jy, frx, fry, th, c1, c0); + else draw_line_dashed_color(jx, jy, frx, fry, th, c1, c0, 6 * ss); + break; + case 1 : + if(downDirection) draw_line_curve_corner(jx, jy, frx, fry, ss, th, c0, c1); + else draw_line_curve_color(jx, jy, frx, fry, cx, cy, ss, th, c0, c1, ty); + break; + case 2 : + if(downDirection) draw_line_elbow_corner(frx, fry, jx, jy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + else draw_line_elbow_color(frx, fry, jx, jy, cx, cy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + break; + case 3 : + if(downDirection) draw_line_elbow_diag_corner(frx, fry, jx, jy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + else draw_line_elbow_diag_color(frx, fry, jx, jy, cx, cy, ss, th, c0, c1, corner, fromIndex, toIndex, ty); + break; + } + } + #endregion + + return hovering; +} #endregion \ No newline at end of file diff --git a/#backups/scripts/string_decimal/string_decimal.gml.backup0 b/#backups/scripts/string_decimal/string_decimal.gml.backup0 new file mode 100644 index 000000000..7be5df91a --- /dev/null +++ b/#backups/scripts/string_decimal/string_decimal.gml.backup0 @@ -0,0 +1,61 @@ +// 2024-04-20 09:11:58 +function string_variable_valid(str) { + static valid_char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"; + + for( var i = 1; i <= string_length(str); i++ ) { + var cch = string_char_at(str, i); + if(string_pos(cch, valid_char) == 0) return false; + } + + return true; +} + +function string_decimal(str) { + var neg = string_char_at(str, 1) == "-"; + if(neg) str = string_copy(str, 2, string_length(str) - 1); + + var dec = string_pos(".", str); + if(dec == 0) return (neg? "-" : "") + string_digits(str); + + var pre = string_copy(str, 1, dec - 1); + var pos = string_copy(str, dec + 1, string_length(str) - dec); + + return (neg? "-" : "") + string_digits(pre) + "." + string_digits(pos); +} + +function toNumber(str) { + INLINE + + if(is_numeric(str)) return str; + + try { return real(str); } + catch(e) {} + + return 0; +} + +//function toNumber(str) { +// INLINE + +// if(is_real(str)) return str; +// if(!isNumber(str)) return 0; + +// var expo = 0; +// if(string_pos("e", str)) { +// var pos = string_pos("e", str); +// expo = real(string_copy(str, pos + 1, string_length(str) - pos)); +// } + +// str = string_replace_all(str, ",", "."); +// str = string_decimal(str); +// if(str == "") return 0; +// if(str == ".") return 0; +// if(str == "-") return 0; +// return real(str) * power(10, expo); +//} + +function isNumber(str) { + if(is_real(str)) return true; + str = string_trim(str); + return str == string_decimal(str); +} \ No newline at end of file diff --git a/#backups/scripts/string_decimal/string_decimal.gml.backup1 b/#backups/scripts/string_decimal/string_decimal.gml.backup1 new file mode 100644 index 000000000..bd94558ad --- /dev/null +++ b/#backups/scripts/string_decimal/string_decimal.gml.backup1 @@ -0,0 +1,61 @@ +// 2024-04-20 09:11:25 +function string_variable_valid(str) { + static valid_char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789"; + + for( var i = 1; i <= string_length(str); i++ ) { + var cch = string_char_at(str, i); + if(string_pos(cch, valid_char) == 0) return false; + } + + return true; +} + +function string_decimal(str) { + var neg = string_char_at(str, 1) == "-"; + if(neg) str = string_copy(str, 2, string_length(str) - 1); + + var dec = string_pos(".", str); + if(dec == 0) return (neg? "-" : "") + string_digits(str); + + var pre = string_copy(str, 1, dec - 1); + var pos = string_copy(str, dec + 1, string_length(str) - dec); + + return (neg? "-" : "") + string_digits(pre) + "." + string_digits(pos); +} + +function toNumber(str) { + INLINE + + if(is_numeric(str)) return str; + + try { return real(str); } + catch(e) {} + + return 0; +} + +//function toNumber(str) { +// INLINE + +// if(is_real(str)) return str; +// if(!isNumber(str)) return 0; + +// var expo = 0; +// if(string_pos("e", str)) { +// var pos = string_pos("e", str); +// expo = real(string_copy(str, pos + 1, string_length(str) - pos)); +// } + +// str = string_replace_all(str, ",", "."); +// str = string_decimal(str); +// if(str == "") return 0; +// if(str == ".") return 0; +// if(str == "-") return 0; +// return real(str) * power(10, expo); +//} + +function isNumber(str) { + if(is_real(str)) return true; + str = string_trim(str); + return str == string_decimal(str); +} \ No newline at end of file diff --git a/#backups/scripts/string_hexadecimal/string_hexadecimal.gml.backup0 b/#backups/scripts/string_hexadecimal/string_hexadecimal.gml.backup0 new file mode 100644 index 000000000..5e31a607c --- /dev/null +++ b/#backups/scripts/string_hexadecimal/string_hexadecimal.gml.backup0 @@ -0,0 +1,62 @@ +// 2024-04-20 08:32:56 +function string_hexadecimal(str) { + static HEX = "0123456789ABCDEF"; + + var i = string_length(str); + var d = 1; + var v = 0; + + while(i > 0) { + var ch = string_char_at(str, i); + var val = string_pos(string_upper(ch), HEX) - 1; + v += val * d; + + d *= 16; + i--; + } + + return v; +} + +function number_to_hex(val) { + static HEX = "0123456789ABCDEF"; + var ss = ""; + while(val > 0) { + var i = val % 16; + ss = string_char_at(HEX, i + 1) + ss; + val = floor(val / 16); + } + while(string_length(ss) < 2) { + ss = "0" + ss; + } + + return ss; +} + +function color_get_hex(color) { + var arr = is_array(color) && array_length(color) == 4; + var r = arr? round(color[0] * 256) : color_get_red(color); + var g = arr? round(color[1] * 256) : color_get_green(color); + var b = arr? round(color[2] * 256) : color_get_blue(color); + var a = arr? round(color[3] * 256) : color_get_alpha(color); + + return number_to_hex(r) + number_to_hex(g) + number_to_hex(b) + (is_int64(color)? number_to_hex(a) : ""); +} + +function color_from_rgb(str) { + var _r = string_hexadecimal(string_copy(str, 1, 2)); + var _g = string_hexadecimal(string_copy(str, 3, 2)); + var _b = string_hexadecimal(string_copy(str, 5, 2)); + + return make_color_rgb(_r, _g, _b); +} + +function colorFromHex(hex) { + if(string_length(hex) != 6) return 0; + + var rr = string_hexadecimal(string_copy(hex, 1, 2)); + var gg = string_hexadecimal(string_copy(hex, 3, 2)); + var bb = string_hexadecimal(string_copy(hex, 5, 2)); + + return make_color_rgb(rr, gg, bb); +} \ No newline at end of file diff --git a/objects/o_dialog_palette/Create_0.gml b/objects/o_dialog_palette/Create_0.gml index 8e6807527..ccf9c8cde 100644 --- a/objects/o_dialog_palette/Create_0.gml +++ b/objects/o_dialog_palette/Create_0.gml @@ -86,9 +86,7 @@ event_inherited(); if(isHover) { if(mouse_press(mb_left, interactable && sFOCUS)) { - palette = array_create(array_length(pal.palette)); - for( var j = 0; j < array_length(pal.palette); j++ ) - palette[j] = cola(pal.palette[j]); + palette = array_clone(pal.palette); onApply(palette); index_selecting = 0; diff --git a/scripts/node_color_adjust/node_color_adjust.gml b/scripts/node_color_adjust/node_color_adjust.gml index 28af3a59e..3b0d51b0c 100644 --- a/scripts/node_color_adjust/node_color_adjust.gml +++ b/scripts/node_color_adjust/node_color_adjust.gml @@ -45,7 +45,7 @@ function Node_Color_adjust(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro inputs[| 12] = nodeValue("Input Type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) .setDisplay(VALUE_DISPLAY.enum_button, [ "Surface", "Color" ]); - inputs[| 13] = nodeValue("Color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 13] = nodeValue("Color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette) .setVisible(true, true); diff --git a/scripts/node_color_remove/node_color_remove.gml b/scripts/node_color_remove/node_color_remove.gml index 06ef9dd05..097a7954c 100644 --- a/scripts/node_color_remove/node_color_remove.gml +++ b/scripts/node_color_remove/node_color_remove.gml @@ -3,7 +3,7 @@ function Node_Color_Remove(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); - inputs[| 1] = nodeValue("Colors", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 1] = nodeValue("Colors", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 2] = nodeValue("Threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1) diff --git a/scripts/node_color_replace/node_color_replace.gml b/scripts/node_color_replace/node_color_replace.gml index 0d715ca4d..e36b39157 100644 --- a/scripts/node_color_replace/node_color_replace.gml +++ b/scripts/node_color_replace/node_color_replace.gml @@ -2,10 +2,10 @@ function Node_Color_replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _gr name = "Replace Palette"; inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); - inputs[| 1] = nodeValue("Palette from", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE, "Color to be replaced.") + inputs[| 1] = nodeValue("Palette from", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE), "Color to be replaced.") .setDisplay(VALUE_DISPLAY.palette); - inputs[| 2] = nodeValue("Palette to", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE, "Palette to be replaced to.") + inputs[| 2] = nodeValue("Palette to", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE), "Palette to be replaced to.") .setDisplay(VALUE_DISPLAY.palette); inputs[| 3] = nodeValue("Threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1) diff --git a/scripts/node_dither/node_dither.gml b/scripts/node_dither/node_dither.gml index 36afec855..88e14f8bc 100644 --- a/scripts/node_dither/node_dither.gml +++ b/scripts/node_dither/node_dither.gml @@ -18,7 +18,7 @@ function Node_Dither(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) co inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); - inputs[| 1] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 1] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 2] = nodeValue("Pattern", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) diff --git a/scripts/node_gradient_palette/node_gradient_palette.gml b/scripts/node_gradient_palette/node_gradient_palette.gml index 7a2f18b8f..73011e72d 100644 --- a/scripts/node_gradient_palette/node_gradient_palette.gml +++ b/scripts/node_gradient_palette/node_gradient_palette.gml @@ -2,7 +2,7 @@ function Node_Gradient_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, name = "Palette to Gradient"; w = 96; - inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette) .setVisible(true, true); diff --git a/scripts/node_gradient_points/node_gradient_points.gml b/scripts/node_gradient_points/node_gradient_points.gml index 33afdb73a..c1f1c4852 100644 --- a/scripts/node_gradient_points/node_gradient_points.gml +++ b/scripts/node_gradient_points/node_gradient_points.gml @@ -26,7 +26,7 @@ function Node_Gradient_Points(_x, _y, _group = noone) : Node_Processor(_x, _y, _ inputs[| 9] = nodeValue("Use palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false ); - inputs[| 10] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 10] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 11] = nodeValue("Falloff 1", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 6 ) diff --git a/scripts/node_gradient_replace_color/node_gradient_replace_color.gml b/scripts/node_gradient_replace_color/node_gradient_replace_color.gml index 5e953142f..ec9487086 100644 --- a/scripts/node_gradient_replace_color/node_gradient_replace_color.gml +++ b/scripts/node_gradient_replace_color/node_gradient_replace_color.gml @@ -5,10 +5,10 @@ function Node_Gradient_Replace_Color(_x, _y, _group = noone) : Node_Processor(_x inputs[| 0] = nodeValue("Gradient", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white) ) .setVisible(true, true); - inputs[| 1] = nodeValue("Color from", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 1] = nodeValue("Color from", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); - inputs[| 2] = nodeValue("Color to", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 2] = nodeValue("Color to", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 3] = nodeValue("Threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1) diff --git a/scripts/node_keyframe/node_keyframe.gml b/scripts/node_keyframe/node_keyframe.gml index 6714da61b..2f5f1e812 100644 --- a/scripts/node_keyframe/node_keyframe.gml +++ b/scripts/node_keyframe/node_keyframe.gml @@ -448,9 +448,9 @@ function valueAnimator(_val, _prop, _sep_axis = false) constructor { switch(prop.type) { case VALUE_TYPE.integer : return prop.unit.mode == VALUE_UNIT.constant? round(_val) : _val; case VALUE_TYPE.float : return _val; - case VALUE_TYPE.text : return is_string(_val)? _val : string_real(_val); - case VALUE_TYPE.color : return is_real(_val)? cola(_val) : _val; - case VALUE_TYPE.surface : return is_string(_val)? get_asset(_val) : _val; + case VALUE_TYPE.text : return is_string(_val)? _val : string_real(_val); + case VALUE_TYPE.color : return is_real(_val)? cola(_val) : _val; + case VALUE_TYPE.surface : return is_string(_val)? get_asset(_val) : _val; } return _val; diff --git a/scripts/node_palette/node_palette.gml b/scripts/node_palette/node_palette.gml index de495c3cf..208774bef 100644 --- a/scripts/node_palette/node_palette.gml +++ b/scripts/node_palette/node_palette.gml @@ -2,7 +2,7 @@ function Node_Palette(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) c name = "Palette"; setDimension(96); - inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE) + inputs[| 0] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 1] = nodeValue("Trim range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 1 ]) diff --git a/scripts/node_palette_replace/node_palette_replace.gml b/scripts/node_palette_replace/node_palette_replace.gml index cce542df8..beaa09054 100644 --- a/scripts/node_palette_replace/node_palette_replace.gml +++ b/scripts/node_palette_replace/node_palette_replace.gml @@ -2,14 +2,14 @@ function Node_Palette_Replace(_x, _y, _group = noone) : Node_Processor(_x, _y, _ name = "Palette Replace"; setDimension(96); - inputs[| 0] = nodeValue("Palette in", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 0] = nodeValue("Palette in", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette) .setVisible(true, true); - inputs[| 1] = nodeValue("Palette from", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 1] = nodeValue("Palette from", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); - inputs[| 2] = nodeValue("Palette to", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 2] = nodeValue("Palette to", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 3] = nodeValue("Threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.1) diff --git a/scripts/node_palette_shift/node_palette_shift.gml b/scripts/node_palette_shift/node_palette_shift.gml index 594b8e302..bb6533c8f 100644 --- a/scripts/node_palette_shift/node_palette_shift.gml +++ b/scripts/node_palette_shift/node_palette_shift.gml @@ -3,7 +3,7 @@ function Node_Palette_Shift(_x, _y, _group = noone) : Node_Processor(_x, _y, _gr inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); - inputs[| 1] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE) + inputs[| 1] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 2] = nodeValue("Shift", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) diff --git a/scripts/node_palette_sort/node_palette_sort.gml b/scripts/node_palette_sort/node_palette_sort.gml index 56be556b2..ddb01233f 100644 --- a/scripts/node_palette_sort/node_palette_sort.gml +++ b/scripts/node_palette_sort/node_palette_sort.gml @@ -2,7 +2,7 @@ function Node_Palette_Sort(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro name = "Sort Palette"; setDimension(96); - inputs[| 0] = nodeValue("Palette in", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 0] = nodeValue("Palette in", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette) .setVisible(true, true); diff --git a/scripts/node_posterize/node_posterize.gml b/scripts/node_posterize/node_posterize.gml index 919ad3721..925b88e40 100644 --- a/scripts/node_posterize/node_posterize.gml +++ b/scripts/node_posterize/node_posterize.gml @@ -3,7 +3,7 @@ function Node_Posterize(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); - inputs[| 1] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 1] = nodeValue("Palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 2] = nodeValue("Use palette", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true); diff --git a/scripts/node_region_fill/node_region_fill.gml b/scripts/node_region_fill/node_region_fill.gml index 6e52c93c7..fb01f479e 100644 --- a/scripts/node_region_fill/node_region_fill.gml +++ b/scripts/node_region_fill/node_region_fill.gml @@ -5,7 +5,7 @@ function Node_Region_Fill(_x, _y, _group = noone) : Node_Processor(_x, _y, _grou inputs[| 1] = nodeValue("Mask", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); - inputs[| 2] = nodeValue("Fill Colors", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 2] = nodeValue("Fill Colors", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); inputs[| 3] = nodeValue("Fill", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true); diff --git a/scripts/node_surface_from_color/node_surface_from_color.gml b/scripts/node_surface_from_color/node_surface_from_color.gml index 2ed26fc69..fe10a2eb5 100644 --- a/scripts/node_surface_from_color/node_surface_from_color.gml +++ b/scripts/node_surface_from_color/node_surface_from_color.gml @@ -1,7 +1,7 @@ function Node_Surface_From_Color(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { name = "Surface from Color"; - inputs[| 0] = nodeValue("Color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE ) + inputs[| 0] = nodeValue("Color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette); outputs[| 0] = nodeValue("Surface", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); diff --git a/scripts/node_value/node_value.gml b/scripts/node_value/node_value.gml index 91931d70a..0bf139191 100644 --- a/scripts/node_value/node_value.gml +++ b/scripts/node_value/node_value.gml @@ -587,9 +587,9 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru if(_type == VALUE_TYPE.color) { if(is_array(_value)) { for( var i = 0, n = array_length(_value); i < n; i++ ) - _value[i] = int64(cola(_value[i])); + _value[i] = cola(_value[i], _color_get_alpha(_value[i])); } else - _value = int64(cola(_value)); + _value = cola(_value, _color_get_alpha(_value)); } key_inter = CURVE_TYPE.linear; diff --git a/scripts/node_widget_test/node_widget_test.gml b/scripts/node_widget_test/node_widget_test.gml index fc1171847..4f3e7633a 100644 --- a/scripts/node_widget_test/node_widget_test.gml +++ b/scripts/node_widget_test/node_widget_test.gml @@ -26,7 +26,7 @@ function Node_Widget_Test(_x, _y, _group = noone) : Node(_x, _y, _group) constru inputs[| 19] = nodeValue("checkBox", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false) .setDisplay(VALUE_DISPLAY._default) inputs[| 20] = nodeValue("buttonColor", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, 0) .setDisplay(VALUE_DISPLAY._default) - inputs[| 21] = nodeValue("buttonPalette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, DEF_PALETTE) .setDisplay(VALUE_DISPLAY.palette) + inputs[| 21] = nodeValue("buttonPalette", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, array_clone(DEF_PALETTE)) .setDisplay(VALUE_DISPLAY.palette) inputs[| 22] = nodeValue("buttonGradient", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white)) .setDisplay(VALUE_DISPLAY._default) inputs[| 23] = nodeValue("pathArrayBox", self, JUNCTION_CONNECT.input, VALUE_TYPE.path, []) .setDisplay(VALUE_DISPLAY.path_array, { filter: [ "image|*.png;*.jpg", "" ] }) diff --git a/scripts/string_decimal/string_decimal.gml b/scripts/string_decimal/string_decimal.gml index 529333f8f..c909ff0e4 100644 --- a/scripts/string_decimal/string_decimal.gml +++ b/scripts/string_decimal/string_decimal.gml @@ -25,6 +25,8 @@ function string_decimal(str) { function toNumber(str) { INLINE + if(is_numeric(str)) return str; + try { return real(str); } catch(e) {} diff --git a/scripts/string_hexadecimal/string_hexadecimal.gml b/scripts/string_hexadecimal/string_hexadecimal.gml index 481e4a943..b2ed5b2db 100644 --- a/scripts/string_hexadecimal/string_hexadecimal.gml +++ b/scripts/string_hexadecimal/string_hexadecimal.gml @@ -6,7 +6,7 @@ function string_hexadecimal(str) { var v = 0; while(i > 0) { - var ch = string_char_at(str, i); + var ch = string_char_at(str, i); var val = string_pos(string_upper(ch), HEX) - 1; v += val * d;