From 71b248fdfe8674cd0d01a485ba6ac778101cb309 Mon Sep 17 00:00:00 2001 From: MakhamDev Date: Fri, 14 Jan 2022 19:47:15 +0700 Subject: [PATCH] Pixel cloud, shape separation, particle node improvement, --- objects/o_dialog_preference/Create_0.gml | 135 +++++++++++------- objects/o_dialog_preference/Destroy_0.gml | 5 + objects/o_dialog_preference/Draw_64.gml | 5 + .../o_dialog_preference.yy | 1 + scripts/node_particle/node_particle.gml | 88 +++++++++--- .../node_particle_effector.gml | 66 +++++---- .../node_seperate_shapes.gml | 70 +++++++-- scripts/node_value/node_value.gml | 4 +- scripts/preferences/preferences.gml | 2 + shaders/sh_polar/sh_polar.fsh | 3 +- .../50aa9e0a-4597-4759-be8c-aea0dfc294f6.png | Bin 0 -> 364 bytes .../90f3e43f-6cad-4a92-8e7c-8764bdde2faf.png | Bin 377 -> 0 bytes .../510fcb08-c7a7-45d8-a16a-11ddc2105fea.png | Bin 0 -> 364 bytes .../2d92f87b-0c00-4e67-b5e5-80435b8a9954.png | Bin 377 -> 0 bytes .../s_node_pixel_cloud/s_node_pixel_cloud.yy | 12 +- 15 files changed, 280 insertions(+), 111 deletions(-) create mode 100644 objects/o_dialog_preference/Destroy_0.gml create mode 100644 sprites/s_node_pixel_cloud/50aa9e0a-4597-4759-be8c-aea0dfc294f6.png delete mode 100644 sprites/s_node_pixel_cloud/90f3e43f-6cad-4a92-8e7c-8764bdde2faf.png create mode 100644 sprites/s_node_pixel_cloud/layers/50aa9e0a-4597-4759-be8c-aea0dfc294f6/510fcb08-c7a7-45d8-a16a-11ddc2105fea.png delete mode 100644 sprites/s_node_pixel_cloud/layers/90f3e43f-6cad-4a92-8e7c-8764bdde2faf/2d92f87b-0c00-4e67-b5e5-80435b8a9954.png diff --git a/objects/o_dialog_preference/Create_0.gml b/objects/o_dialog_preference/Create_0.gml index eb98d02b6..495e5b950 100644 --- a/objects/o_dialog_preference/Create_0.gml +++ b/objects/o_dialog_preference/Create_0.gml @@ -25,56 +25,87 @@ event_inherited(); #region pages page_current = 0; page[0] = "Global data"; - page[1] = "Hotkeys"; + page[1] = "Node data"; + page[2] = "Hotkeys"; - pref[0][0] = "Show welcome screen"; - pref[0][1] = "show_splash"; - pref[0][2] = new checkBox(function() { - PREF_MAP[? "show_splash"] = !PREF_MAP[? "show_splash"]; - PREF_SAVE(); - }); + pref_global = ds_list_create(); + pref_node = ds_list_create(); - pref[1][0] = "Reset preview on focus"; - pref[1][1] = "reset_display"; - pref[1][2] = new checkBox(function() { - PREF_MAP[? "reset_display"] = !PREF_MAP[? "reset_display"]; - PREF_SAVE(); - }); + ds_list_add(pref_global, [ + "Show welcome screen", + "show_splash", + new checkBox(function() { + PREF_MAP[? "show_splash"] = !PREF_MAP[? "show_splash"]; + PREF_SAVE(); + }) + ]); - pref[2][0] = "Curve connection line"; - pref[2][1] = "curve_connection_line"; - pref[2][2] = new checkBox(function() { - PREF_MAP[? "curve_connection_line"] = !PREF_MAP[? "curve_connection_line"]; - PREF_SAVE(); - }); + ds_list_add(pref_global, [ + "Reset preview on focus", + "reset_display", + new checkBox(function() { + PREF_MAP[? "reset_display"] = !PREF_MAP[? "reset_display"]; + PREF_SAVE(); + }) + ]); - pref[3][0] = "Max particles"; - pref[3][1] = "part_max_amount"; - pref[3][2] = new textBox(TEXTBOX_INPUT.number, function(str) { - PREF_MAP[? "part_max_amount"] = real(str); - PREF_SAVE(); - }); + ds_list_add(pref_global, [ + "Curve connection line", + "curve_connection_line", + new checkBox(function() { + PREF_MAP[? "curve_connection_line"] = !PREF_MAP[? "curve_connection_line"]; + PREF_SAVE(); + }) + ]); - pref[4][0] = "Double click delay"; - pref[4][1] = "double_click_delay"; - pref[4][2] = new textBox(TEXTBOX_INPUT.number, function(str) { - PREF_MAP[? "double_click_delay"] = real(str); - PREF_SAVE(); - }); + ds_list_add(pref_global, [ + "Double click delay", + "double_click_delay", + new textBox(TEXTBOX_INPUT.number, function(str) { + PREF_MAP[? "double_click_delay"] = real(str); + PREF_SAVE(); + }) + ]); - pref[5][0] = "Default surface size"; - pref[5][1] = "default_surface_side"; - pref[5][2] = new textBox(TEXTBOX_INPUT.number, function(str) { - PREF_MAP[? "default_surface_side"] = max(1, round(real(str))); - PREF_SAVE(); - }); + ds_list_add(pref_global, [ + "Default surface size", + "default_surface_side", + new textBox(TEXTBOX_INPUT.number, function(str) { + PREF_MAP[? "default_surface_side"] = max(1, round(real(str))); + PREF_SAVE(); + }) + ]); - pref[6][0] = "Node snapping (set to 1 for no snap)"; - pref[6][1] = "node_snapping"; - pref[6][2] = new textBox(TEXTBOX_INPUT.number, function(str) { - PREF_MAP[? "node_snapping"] = max(1, round(real(str))); - PREF_SAVE(); - }); + ds_list_add(pref_global, [ + "Node snapping (set to 1 for no snap)", + "node_snapping", + new textBox(TEXTBOX_INPUT.number, function(str) { + PREF_MAP[? "node_snapping"] = max(1, round(real(str))); + PREF_SAVE(); + }) + ]); + + //NODE + + ds_list_add(pref_node, [ + "[Particle] Max particles", + "part_max_amount", + new textBox(TEXTBOX_INPUT.number, function(str) { + PREF_MAP[? "part_max_amount"] = real(str); + PREF_SAVE(); + }) + ]); + + ds_list_add(pref_node, [ + "[Separate shape] Max shapes", + "shape_separation_max", + new textBox(TEXTBOX_INPUT.number, function(str) { + PREF_MAP[? "shape_separation_max"] = real(str); + PREF_SAVE(); + }) + ]); + + current_list = pref_global; sp_pref = new scrollPane(dialog_w - 160 - 32, dialog_h - 64 - 28, function(_y, _m) { draw_clear_alpha(c_ui_blue_black, 0); @@ -84,24 +115,26 @@ event_inherited(); var yy = _y + 8; var padd = 6; - for(var i = 0; i < array_length(pref); i++) { - var name = pref[i][0]; + for(var i = 0; i < ds_list_size(current_list); i++) { + var _pref = current_list[| i]; + var name = _pref[0]; + if(search_text == "" || string_pos(string_lower(search_text), string_lower(name)) > 0) { if(i % 2 == 0) { draw_sprite_stretched_ext(s_ui_panel_bg, 0, 0, yy - padd, dialog_w - 200, th + padd * 2, c_ui_blue_white, 1); } draw_set_text(f_p1, fa_left, fa_center, c_white); - draw_text(8, yy + 17, pref[i][0]); - pref[i][2].active = FOCUS == self; - pref[i][2].hover = HOVER == self; + draw_text(8, yy + 17, _pref[0]); + _pref[2].active = FOCUS == self; + _pref[2].hover = HOVER == self; - switch(instanceof(pref[i][2])) { + switch(instanceof(_pref[2])) { case "textBox" : - pref[i][2].draw(x1 - 100, yy, 96, 34, PREF_MAP[? pref[i][1]], _m); + _pref[2].draw(x1 - 100, yy, 96, 34, PREF_MAP[? _pref[1]], _m); break; case "checkBox" : - pref[i][2].draw(x1 - 36, yy + 2, PREF_MAP[? pref[i][1]], _m); + _pref[2].draw(x1 - 36, yy + 2, PREF_MAP[? _pref[1]], _m); break; } diff --git a/objects/o_dialog_preference/Destroy_0.gml b/objects/o_dialog_preference/Destroy_0.gml new file mode 100644 index 000000000..09d81eeeb --- /dev/null +++ b/objects/o_dialog_preference/Destroy_0.gml @@ -0,0 +1,5 @@ +/// @description +event_inherited(); + +ds_list_destroy(pref_global); +ds_list_destroy(pref_node); \ No newline at end of file diff --git a/objects/o_dialog_preference/Draw_64.gml b/objects/o_dialog_preference/Draw_64.gml index 606d2ecbd..a37f13f4f 100644 --- a/objects/o_dialog_preference/Draw_64.gml +++ b/objects/o_dialog_preference/Draw_64.gml @@ -43,9 +43,14 @@ if !ready exit; draw_sprite_ext(s_search_16, 0, dialog_x + dialog_w - 16 - 200 - 16, dialog_y + 16 + 12, 1, 1, 0, c_ui_blue_grey, 1); if(page_current == 0) { + current_list = pref_global; sp_pref.active = HOVER == self; sp_pref.draw(dialog_x + 160 + 8, yy); } else if(page_current == 1) { + current_list = pref_node; + sp_pref.active = HOVER == self; + sp_pref.draw(dialog_x + 160 + 8, yy); + } else if(page_current == 2) { if(mouse_check_button_pressed(mb_left)) hk_editing = noone; sp_hotkey.active = HOVER == self; diff --git a/objects/o_dialog_preference/o_dialog_preference.yy b/objects/o_dialog_preference/o_dialog_preference.yy index 2c7d13b85..8c4e77363 100644 --- a/objects/o_dialog_preference/o_dialog_preference.yy +++ b/objects/o_dialog_preference/o_dialog_preference.yy @@ -23,6 +23,7 @@ "eventList": [ {"isDnD":false,"eventNum":0,"eventType":0,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",}, {"isDnD":false,"eventNum":64,"eventType":8,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",}, + {"isDnD":false,"eventNum":0,"eventType":1,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",}, ], "properties": [], "overriddenProperties": [], diff --git a/scripts/node_particle/node_particle.gml b/scripts/node_particle/node_particle.gml index 094c9e964..b92b32560 100644 --- a/scripts/node_particle/node_particle.gml +++ b/scripts/node_particle/node_particle.gml @@ -16,6 +16,8 @@ function __part() constructor { g = 0; wig = 0; + boundary_data = []; + fx = 0; fy = 0; @@ -32,6 +34,7 @@ function __part() constructor { col = -1; alp = 1; + alp_draw = alp; alp_fade = 0; life = 0; @@ -72,6 +75,7 @@ function __part() constructor { function setDraw(_col, _alp, _fade) { col = _col; alp = _alp; + alp_draw = _alp; alp_fade = _fade; } @@ -106,7 +110,7 @@ function __part() constructor { rot = point_direction(xp, yp, x, y); else rot += rot_s; - alp = clamp(alp + alp_fade, 0, 1); + alp_draw = alp * eval_bezier_cubic(life / life_total, alp_fade[0], alp_fade[1], alp_fade[2], alp_fade[3]); if(life-- < 0) kill(); } @@ -119,18 +123,45 @@ function __part() constructor { if(!is_surface(ss)) return; var cc = (col == -1)? c_white : gradient_eval(col, 1 - life / life_total); + var _xx, _yy; var s_w = surface_get_width(ss) * scx; var s_h = surface_get_height(ss) * scy; - var _pp = point_rotate(-s_w / 2, -s_h / 2, 0, 0, rot); - _pp[0] = x + _pp[0]; - _pp[1] = y + _pp[1]; + if(boundary_data == -1) { + var _pp = point_rotate(-s_w / 2, -s_h / 2, 0, 0, rot); + _xx = x + _pp[0]; + _yy = y + _pp[1]; + } else { + var ww = boundary_data[2] + boundary_data[0]; + var hh = boundary_data[3] + boundary_data[1]; + + var cx = (boundary_data[0] + boundary_data[2]) / 2; + var cy = (boundary_data[1] + boundary_data[3]) / 2; + + var _pp = point_rotate(-cx, -cy, 0, 0, rot); + + _xx = x + cx + _pp[0] * scx; + _yy = y + cy + _pp[1] * scy; + } + if(exact) { - _pp[0] = round(_pp[0]); - _pp[1] = round(_pp[1]); + _xx = round(_xx); + _yy = round(_yy); } - draw_surface_ext_safe(ss, _pp[0], _pp[1], scx, scy, rot, cc, alp); + draw_surface_ext_safe(ss, _xx, _yy, scx, scy, rot, cc, alp_draw); + } + + function getPivot() { + if(boundary_data == -1) + return [x, y]; + + var ww = boundary_data[2] + boundary_data[0] * scx; + var hh = boundary_data[3] + boundary_data[1] * scy; + var cx = x + boundary_data[0] + ww / 2; + var cy = y + boundary_data[1] + hh / 2; + + return [cx, cy]; } } @@ -192,7 +223,7 @@ function Node_Particle(_x, _y) : Node(_x, _y) constructor { inputs[| 14] = nodeValue(14, "Alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ]) .setDisplay(VALUE_DISPLAY.range) .setVisible(false); - inputs[| 15] = nodeValue(15, "Alpha over time", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + inputs[| 15] = nodeValue(15, "Alpha over time", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, [1, 1, 1, 1]) .setVisible(false); inputs[| 16] = nodeValue(16, "Rotate by direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false) @@ -234,13 +265,16 @@ function Node_Particle(_x, _y) : Node(_x, _y) constructor { .setVisible(false, false); inputs[| 27] = nodeValue(27, "Scatter", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1) - .setDisplay(VALUE_DISPLAY.enum_button, [ "Uniform", "Random" ]) + .setDisplay(VALUE_DISPLAY.enum_button, [ "Uniform", "Random", "Data" ]) .setVisible(false); + inputs[| 28] = nodeValue(28, "Boundary data", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, []) + .setVisible(true, false); + input_display_list = [ ["Output", true], 1, ["Sprite", true], 0, 25, - ["Spawn", true], 17, 2, 3, 4, 5, 27, 6, + ["Spawn", true], 17, 2, 3, 4, 5, 27, 28, 6, ["Movement", true], 7, 20, 8, ["Physics", true], 21, 22, ["Rotation", true], 16, 9, 10, @@ -307,20 +341,34 @@ function Node_Particle(_x, _y) : Node(_x, _y) constructor { for(var i = 0; i < PREF_MAP[? "part_max_amount"]; i++) { if(!parts[| i].active) { - var _spr = _inSurf; + var _spr = _inSurf, _index = 0; if(is_array(_inSurf)) { - if(_arr_type == 0) - _spr = _inSurf[irandom(array_length(_inSurf) - 1)]; - else if(_arr_type == 1) - _spr = _inSurf[safe_mod(spawn_index, array_length(_inSurf))]; - else if(_arr_type == 2) + if(_arr_type == 0) { + _index = irandom(array_length(_inSurf) - 1); + _spr = _inSurf[_index]; + } else if(_arr_type == 1) { + _index = safe_mod(spawn_index, array_length(_inSurf)); + _spr = _inSurf[_index]; + } else if(_arr_type == 2) _spr = _inSurf; } var xx, yy; - var sp = area_get_random_point(_spawn_area, _distrib, _scatter, spawn_index, _spawn_amount); - xx = sp[0]; - yy = sp[1]; + if(_scatter == 2) { + var _b_data = inputs[| 28].getValue(); + if(!is_array(_b_data) || array_length(_b_data) <= 0) return; + var _b = _b_data[safe_mod(_index, array_length(_b_data))]; + if(!is_array(_b) || array_length(_b) != 4) return; + + xx = array_safe_get(_spawn_area, 0) - array_safe_get(_spawn_area, 2); + yy = array_safe_get(_spawn_area, 1) - array_safe_get(_spawn_area, 3); + + parts[| i].boundary_data = _b; + } else { + var sp = area_get_random_point(_spawn_area, _distrib, _scatter, spawn_index, _spawn_amount); + xx = sp[0]; + yy = sp[1]; + } var _lif = random_range(_life[0], _life[1]); @@ -396,9 +444,11 @@ function Node_Particle(_x, _y) : Node(_x, _y) constructor { function step() { var _inSurf = inputs[| 0].getValue(); + var _scatt = inputs[| 27].getValue(); inputs[| 25].show_in_inspector = false; inputs[| 26].show_in_inspector = false; + inputs[| 28].show_in_inspector = _scatt == 2; if(is_array(_inSurf)) { inputs[| 25].show_in_inspector = true; diff --git a/scripts/node_particle_effector/node_particle_effector.gml b/scripts/node_particle_effector/node_particle_effector.gml index 67417ec75..ac230bef1 100644 --- a/scripts/node_particle_effector/node_particle_effector.gml +++ b/scripts/node_particle_effector/node_particle_effector.gml @@ -19,30 +19,40 @@ function Node_Particle_Effector(_x, _y) : Node(_x, _y) constructor { inputs[| 0] = nodeValue(0, "Particle data", self, JUNCTION_CONNECT.input, VALUE_TYPE.object, -1 ); inputs[| 1] = nodeValue(1, "Output dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, def_surf_size2, VALUE_TAG.dimension_2d ) - .setDisplay(VALUE_DISPLAY.vector); + .setDisplay(VALUE_DISPLAY.vector) + .setVisible(false, false); inputs[| 2] = nodeValue(2, "Area", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 16, 16, 4, 4, AREA_SHAPE.rectangle ]) - .setDisplay(VALUE_DISPLAY.area); + .setDisplay(VALUE_DISPLAY.area) + .setVisible(false); inputs[| 3] = nodeValue(3, "Falloff", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, [0, 0, 1, 1] ) - .setDisplay(VALUE_DISPLAY.curve); + .setDisplay(VALUE_DISPLAY.curve) + .setVisible(false); - inputs[| 4] = nodeValue(4, "Falloff distance", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 4 ); + inputs[| 4] = nodeValue(4, "Falloff distance", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 4 ) + .setVisible(false); inputs[| 5] = nodeValue(5, "Effect type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0 ) - .setDisplay(VALUE_DISPLAY.enum_scroll, [ "Wind", "Attract", "Repel", "Vortex", "Turbulence", "Destroy" ] ); + .setDisplay(VALUE_DISPLAY.enum_scroll, [ "Wind", "Attract", "Repel", "Vortex", "Turbulence", "Destroy" ] ) + .setVisible(false); inputs[| 6] = nodeValue(6, "Effect Vector", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ -1, 0 ] ) - .setDisplay(VALUE_DISPLAY.vector); + .setDisplay(VALUE_DISPLAY.vector) + .setVisible(false); - inputs[| 7] = nodeValue(7, "Strength", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1 ); + inputs[| 7] = nodeValue(7, "Strength", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1 ) + .setVisible(false); - inputs[| 8] = nodeValue(8, "Rotate particle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0 ); + inputs[| 8] = nodeValue(8, "Rotate particle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0 ) + .setVisible(false); inputs[| 9] = nodeValue(9, "Scale particle", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ] ) - .setDisplay(VALUE_DISPLAY.vector); + .setDisplay(VALUE_DISPLAY.vector) + .setVisible(false); - inputs[| 10] = nodeValue(10, "Turbulence scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 16 ); + inputs[| 10] = nodeValue(10, "Turbulence scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 16 ) + .setVisible(false); input_display_list = [ 0, 1, ["Area", false], 2, 3, 4, @@ -83,7 +93,6 @@ function Node_Particle_Effector(_x, _y) : Node(_x, _y) constructor { function affect(part) { if(!part.active) return; - if(array_length(current_data) < ds_list_size(inputs)) return; var _area = current_data[2]; var _fall = current_data[3]; @@ -107,18 +116,19 @@ function Node_Particle_Effector(_x, _y) : Node(_x, _y) constructor { var _area_y1 = _area_y + _area_h; var str = 0; + var pv = part.getPivot(); if(_area_t == AREA_SHAPE.rectangle) { - if(point_in_rectangle(part.x, part.y, _area_x0, _area_y0, _area_x1, _area_y1)) { - var _dst = min( distance_to_line(part.x, part.y, _area_x0, _area_y0, _area_x1, _area_y0), - distance_to_line(part.x, part.y, _area_x0, _area_y1, _area_x1, _area_y1), - distance_to_line(part.x, part.y, _area_x0, _area_y0, _area_x0, _area_y1), - distance_to_line(part.x, part.y, _area_x1, _area_y0, _area_x1, _area_y1)); + if(point_in_rectangle(pv[0], pv[1], _area_x0, _area_y0, _area_x1, _area_y1)) { + var _dst = min( distance_to_line(pv[0], pv[1], _area_x0, _area_y0, _area_x1, _area_y0), + distance_to_line(pv[0], pv[1], _area_x0, _area_y1, _area_x1, _area_y1), + distance_to_line(pv[0], pv[1], _area_x0, _area_y0, _area_x0, _area_y1), + distance_to_line(pv[0], pv[1], _area_x1, _area_y0, _area_x1, _area_y1)); str = eval_curve_bezier_cubic(_fall, clamp(_dst / _fads, 0., 1.)); } } else if(_area_t == AREA_SHAPE.elipse) { - if(point_in_circle(part.x, part.y, _area_x, _area_y, min(_area_w, _area_h))) { - var _dst = point_distance(part.x, part.y, _area_x, _area_y); + if(point_in_circle(pv[0], pv[1], _area_x, _area_y, min(_area_w, _area_h))) { + var _dst = point_distance(pv[0], pv[1], _area_x, _area_y); str = eval_curve_bezier_cubic(_fall, clamp(_dst / _fads, 0., 1.)); } } @@ -128,32 +138,42 @@ function Node_Particle_Effector(_x, _y) : Node(_x, _y) constructor { case FORCE_TYPE.Wind : part.x = part.x + _vect[0] * _sten * str; part.y = part.y + _vect[1] * _sten * str; + + part.rot += _rot * str; break; case FORCE_TYPE.Attract : - var dirr = point_direction(part.x, part.y, _area_x, _area_y); + var dirr = point_direction(pv[0], pv[1], _area_x, _area_y); part.x = part.x + lengthdir_x(_sten * str, dirr); part.y = part.y + lengthdir_y(_sten * str, dirr); + + part.rot += _rot * str; break; case FORCE_TYPE.Repel : - var dirr = point_direction(_area_x, _area_y, part.x, part.y); + var dirr = point_direction(_area_x, _area_y, pv[0], pv[1]); part.x = part.x + lengthdir_x(_sten * str, dirr); part.y = part.y + lengthdir_y(_sten * str, dirr); + + part.rot += _rot * str; break; case FORCE_TYPE.Vortex : - var dirr = point_direction(_area_x, _area_y, part.x, part.y) + 90; + var dirr = point_direction(_area_x, _area_y, pv[0], pv[1]) + 90; part.x = part.x + lengthdir_x(_sten * str, dirr); part.y = part.y + lengthdir_y(_sten * str, dirr); + + part.rot += _rot * str; break; case FORCE_TYPE.Turbulence : var t_scale = current_data[10]; - var per = (perlin_noise(part.x / t_scale, part.y / t_scale, 4, part.seed) - 0.5) * 2; + var per = (perlin_noise(pv[0] / t_scale, pv[1] / t_scale, 4, part.seed) - 0.5) * 2; per *= str; part.x = part.x + _vect[0] * per; part.y = part.y + _vect[1] * per; + + part.rot += _rot * per; break; case FORCE_TYPE.Destroy : if(random(1) < _sten) @@ -167,8 +187,6 @@ function Node_Particle_Effector(_x, _y) : Node(_x, _y) constructor { else part.scx += sign(part.scx) * scx_s; if(scy_s < 0) part.scy = lerp_linear(part.scy, 0, abs(scy_s)); else part.scy += sign(part.scy) * scy_s; - - part.rot += _rot * str; } } diff --git a/scripts/node_seperate_shapes/node_seperate_shapes.gml b/scripts/node_seperate_shapes/node_seperate_shapes.gml index a55ab83b0..69ad0de0b 100644 --- a/scripts/node_seperate_shapes/node_seperate_shapes.gml +++ b/scripts/node_seperate_shapes/node_seperate_shapes.gml @@ -5,9 +5,8 @@ function Node_create_Seperate_Shape(_x, _y) { } function Node_Seperate_Shape(_x, _y) : Node(_x, _y) constructor { - name = "Seperate shape"; + name = "Separate shape"; auto_update = false; - max_part = 32; uniform_it_dim = shader_get_uniform(sh_seperate_shape_ite, "dimension"); @@ -26,6 +25,19 @@ function Node_Seperate_Shape(_x, _y) : Node(_x, _y) constructor { } temp_surf = [ surface_create(1, 1), surface_create(1, 1) ]; + surface_buffer = buffer_create(1 * 1 * 4, buffer_fixed, 2); + + function get_color_buffer(_x, _y, w, h) { + buffer_seek(surface_buffer, buffer_seek_start, (w * _y + _x) * 4); + var c = buffer_read(surface_buffer, buffer_u32); + var _r = c & 255; + var _g = (c >> 8) & 255; + var _b = (c >> 16) & 255; + + return make_color_rgb(_r, _g, _b); + } + + _prev_type = -1; function update() { var _inSurf = inputs[| 0].getValue(); @@ -70,14 +82,14 @@ function Node_Seperate_Shape(_x, _y) : Node(_x, _y) constructor { res_index = bg; } - var _pixel_surface = surface_create(max_part, 1); + var _pixel_surface = surface_create(PREF_MAP[? "shape_separation_max"], 1); surface_set_target(_pixel_surface); draw_clear_alpha(0, 0); BLEND_ADD shader_set(sh_seperate_shape_counter); texture_set_stage(shader_get_sampler_index(sh_seperate_shape_counter, "surface"), surface_get_texture(temp_surf[res_index])); shader_set_uniform_f_array(shader_get_uniform(sh_seperate_shape_counter, "dimension"), [ surface_get_width(_inSurf), surface_get_height(_inSurf) ]); - draw_sprite_ext(s_fx_pixel, 0, 0, 0, max_part, 1, 0, c_white, 1); + draw_sprite_ext(s_fx_pixel, 0, 0, 0, PREF_MAP[? "shape_separation_max"], 1, 0, c_white, 1); shader_reset(); BLEND_NORMAL surface_reset_target(); @@ -90,14 +102,26 @@ function Node_Seperate_Shape(_x, _y) : Node(_x, _y) constructor { if(_out_type == 0) { while(ds_list_size(outputs) > px) ds_list_delete(outputs, px - 1); - } else { - ds_list_clear(outputs); - outputs[| 0] = nodeValue(0, "Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, array_create(px)); - _val = outputs[| 0].getValue(); + } else if(_out_type == 1) { + _val = array_create(px); + if(_prev_type != _out_type) { + ds_list_clear(outputs); + outputs[| 0] = nodeValue(0, "Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, _val); + outputs[| 1] = nodeValue(1, "Shape map", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, temp_surf[res_index]); + outputs[| 2] = nodeValue(2, "Boundary data", self, JUNCTION_CONNECT.output, VALUE_TYPE.integer, []); - outputs[| 1] = nodeValue(1, "Shape map", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, temp_surf[res_index]); + _prev_type = _out_type; + } } + var _boundary = array_create(px); + var _sw = surface_get_width(temp_surf[res_index]); + var _sh = surface_get_height(temp_surf[res_index]); + + buffer_delete(surface_buffer); + surface_buffer = buffer_create(_sw * _sh * 4, buffer_fixed, 2); + buffer_get_surface(surface_buffer, temp_surf[res_index], 0); + for(var i = 0; i < px; i++) { if(_out_type == 0) { if(i >= ds_list_size(outputs)) { @@ -116,6 +140,30 @@ function Node_Seperate_Shape(_x, _y) : Node(_x, _y) constructor { BLEND_ADD shader_set(sh_seperate_shape_sep); var cc = surface_getpixel(_pixel_surface, 1 + i, 0); + + #region boundary search (brute force) + if(_out_type == 1) { + var t = _sh; + var b = 0; + var l = 0; + var r = _sw; + + for( var j = 0; j < surface_get_width(_inSurf); j++ ) { + for( var k = 0; k < surface_get_height(_inSurf); k++ ) { + var _sc = get_color_buffer(j, k, _sw, _sh); + if(_sc == cc) { + t = min(t, k); + b = max(b, k); + l = max(l, j); + r = min(r, j); + } + } + } + + _boundary[i] = [l, t, r, b]; + } + #endregion + texture_set_stage(shader_get_sampler_index(sh_seperate_shape_sep, "original"), surface_get_texture(_inSurf)); shader_set_uniform_f_array(shader_get_uniform(sh_seperate_shape_sep, "color"), [ color_get_red(cc), color_get_green(cc) ]); draw_surface_safe(temp_surf[res_index], 0, 0); @@ -123,6 +171,10 @@ function Node_Seperate_Shape(_x, _y) : Node(_x, _y) constructor { BLEND_NORMAL surface_reset_target(); } + + if(_out_type == 1) { + outputs[| 2].setValue(_boundary); + } } } } \ No newline at end of file diff --git a/scripts/node_value/node_value.gml b/scripts/node_value/node_value.gml index 317bd569b..3b6b41abc 100644 --- a/scripts/node_value/node_value.gml +++ b/scripts/node_value/node_value.gml @@ -985,7 +985,9 @@ function NodeValue(_index, _name, _node, _connect, _type, _value, _tag = VALUE_T } } - PANEL_MENU.addNotiExtra("Node connect error : Node ID " + string(con_node + APPEND_ID) + " not found."); + var txt = "Node connect error : Node ID " + string(con_node + APPEND_ID) + " not found."; + log_warning("LOAD", txt); + PANEL_MENU.addNotiExtra(txt); return true; } } \ No newline at end of file diff --git a/scripts/preferences/preferences.gml b/scripts/preferences/preferences.gml index 5e0a046eb..bf565cb70 100644 --- a/scripts/preferences/preferences.gml +++ b/scripts/preferences/preferences.gml @@ -27,6 +27,8 @@ PREF_MAP[? "panel_collection"] = true; PREF_MAP[? "node_snapping"] = 32; + + PREF_MAP[? "shape_separation_max"] = 32; #endregion #region hotkeys diff --git a/shaders/sh_polar/sh_polar.fsh b/shaders/sh_polar/sh_polar.fsh index 5a60012cd..128bbdb8b 100644 --- a/shaders/sh_polar/sh_polar.fsh +++ b/shaders/sh_polar/sh_polar.fsh @@ -5,11 +5,12 @@ varying vec2 v_vTexcoord; varying vec4 v_vColour; #define pi2 1.57079 +#define pi 3.14159265 void main() { vec2 center = v_vTexcoord - vec2(0.5, 0.5); float radius = distance(v_vTexcoord, vec2(0.5, 0.5)) / (sqrt(2.) * .5); - float angle = (atan(center.y, center.x) / pi2 + 1.) / 2.; + float angle = (atan(center.y, center.x) / pi + 1.) / 2.; vec2 polar = vec2(radius, angle); gl_FragColor = v_vColour * texture2D( gm_BaseTexture, polar ); diff --git a/sprites/s_node_pixel_cloud/50aa9e0a-4597-4759-be8c-aea0dfc294f6.png b/sprites/s_node_pixel_cloud/50aa9e0a-4597-4759-be8c-aea0dfc294f6.png new file mode 100644 index 0000000000000000000000000000000000000000..719c281bc8587c8975f7fe6bfa167c835c3b59e7 GIT binary patch literal 364 zcmV-y0h9iTP)L1X0XV)&E$h4}AqhYlb4SuC?~{&Y9|S-KvqZI5IwBn}&5Dr^p=gLE`Ootv;k4UM7It|6Y;dPYpO3Kt_m8#%)ol z0NU59C9Sw*1C-PXu-pZ5qd~>*9VLCZNy zIvy#L1X0XV)&E$h4}AqhYlb4SuC?~{&Y9|S-KvqZI5IwBn}&5Dr^p=gLE`Ootv;k4UM7It|6Y;dPYpO3Kt_m8#%)ol z0NU59C9Sw*1C-PXu-pZ5qd~>*9VLCZNy zIvy#",}, "tracks": [ {"name":"frames","spriteId":null,"keyframes":{"Keyframes":[ - {"id":"10ae1b26-149a-4837-b0ef-ebc91848d562","Key":0.0,"Length":1.0,"Stretch":false,"Disabled":false,"IsCreationKey":false,"Channels":{"0":{"Id":{"name":"90f3e43f-6cad-4a92-8e7c-8764bdde2faf","path":"sprites/s_node_pixel_cloud/s_node_pixel_cloud.yy",},"resourceVersion":"1.0","resourceType":"SpriteFrameKeyframe",},},"resourceVersion":"1.0","resourceType":"Keyframe",}, + {"id":"f15ff1e5-a53c-4c00-8da2-ec5ef0de1206","Key":0.0,"Length":1.0,"Stretch":false,"Disabled":false,"IsCreationKey":false,"Channels":{"0":{"Id":{"name":"50aa9e0a-4597-4759-be8c-aea0dfc294f6","path":"sprites/s_node_pixel_cloud/s_node_pixel_cloud.yy",},"resourceVersion":"1.0","resourceType":"SpriteFrameKeyframe",},},"resourceVersion":"1.0","resourceType":"Keyframe",}, ],"resourceVersion":"1.0","resourceType":"KeyframeStore",},"trackColour":0,"inheritsTrackColour":true,"builtinName":0,"traits":0,"interpolation":1,"tracks":[],"events":[],"isCreationTrack":false,"resourceVersion":"1.0","tags":[],"resourceType":"GMSpriteFramesTrack","modifiers":[],}, ], - "visibleRange": {"x":0.0,"y":0.0,}, + "visibleRange": null, "lockOrigin": false, "showBackdrop": true, "showBackdropImage": false, @@ -65,7 +65,7 @@ "resourceType": "GMSequence", }, "layers": [ - {"visible":true,"isLocked":false,"blendMode":0,"opacity":100.0,"displayName":"default","resourceVersion":"1.0","name":"2d92f87b-0c00-4e67-b5e5-80435b8a9954","tags":[],"resourceType":"GMImageLayer",}, + {"visible":true,"isLocked":false,"blendMode":0,"opacity":100.0,"displayName":"default","resourceVersion":"1.0","name":"510fcb08-c7a7-45d8-a16a-11ddc2105fea","tags":[],"resourceType":"GMImageLayer",}, ], "nineSlice": null, "parent": {