function Node_Seperate_Shape(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { name = "Separate Shape"; newInput(0, nodeValue_Surface("Surface in", self)) .rejectArray(); newInput(1, nodeValue_Float("Tolerance", self, 0.2)) .setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 1, 0.01 ], update_stat: SLIDER_UPDATE.release }) .rejectArray(); newInput(2, nodeValue_Bool("Override color", self, false)) .rejectArray(); newInput(3, nodeValue_Color("Color", self, c_white)) .rejectArray(); newInput(4, nodeValue_Bool("Ignore blank", self, true, "Skip empty and black shape.")) .rejectArray(); newInput(5, nodeValue_Enum_Button("Mode", self, 0 , [ "Greyscale", "Alpha" ] )) outputs[0] = nodeValue_Output("Surface out", self, VALUE_TYPE.surface, noone); outputs[1] = nodeValue_Output("Atlas", self, VALUE_TYPE.surface, []); input_display_list = [ ["Shape", false], 0, 5, 1, 4, ["Override Color", true, 2], 3, ] temp_surface = [ noone, noone ]; surface_buffer = buffer_create(1 * 1 * 4, buffer_fixed, 2); surface_w = 1; surface_h = 1; _prev_type = -1; static onInspector1Update = function() { separateShape(); } static update = function() { separateShape(); } static separateShape = function() { var _inSurf = getInputData(0); var _thres = getInputData(1); var _ovr = getInputData(2); var _ovrclr = getInputData(3); var _ignore = getInputData(4); var _mode = getInputData(5); var t = current_time; if(!is_surface(_inSurf)) return; var ww = surface_get_width_safe(_inSurf); var hh = surface_get_height_safe(_inSurf); for(var i = 0; i < 2; i++) temp_surface[i] = surface_verify(temp_surface[i], ww, hh, surface_rgba32float); #region region indexing surface_set_shader(temp_surface[1], sh_seperate_shape_index); shader_set_i("mode", _mode); shader_set_i("ignore", _ignore); shader_set_f("dimension", ww, hh); draw_sprite_stretched(s_fx_pixel, 0, 0, 0, ww, hh); surface_reset_shader(); shader_set(sh_seperate_shape_ite); shader_set_i("mode", _mode); shader_set_i("ignore", _ignore); shader_set_f("dimension", ww, hh); shader_set_f("threshold", _thres); shader_set_surface("map", _inSurf); shader_reset(); var res_index = 0, iteration = ww + hh; for(var i = 0; i <= iteration; i++) { var bg = i % 2; var fg = !bg; surface_set_shader(temp_surface[bg], sh_seperate_shape_ite,, BLEND.over); draw_surface_safe(temp_surface[fg]); surface_reset_shader(); res_index = bg; } #endregion #region count and match color var i = 0, pxc = ww * hh; var reg = ds_map_create(); var b = buffer_create(pxc * 16, buffer_fixed, 1); buffer_get_surface(b, temp_surface[res_index], 0); buffer_seek(b, buffer_seek_start, 0); repeat(pxc) { var _r = buffer_read(b, buffer_f32); var _g = buffer_read(b, buffer_f32); var _b = buffer_read(b, buffer_f32); var _a = buffer_read(b, buffer_f32); if(_r == 0 && _g == 0 && _b == 0 && _a == 0) continue; reg[? _g * ww + _r] = [ _r, _g, _b, _a ]; } var px = ds_map_size(reg); if(px == 0) return; #endregion #region extract region var _outSurf, _val; _val = array_create(px); var _atlas = array_create(px); var key = ds_map_keys_to_array(reg); var _ind = 0; for(var i = 0; i < px; i++) { var _k = key[i]; var ccx = reg[? _k]; var min_x = round(ccx[0]); var min_y = round(ccx[1]); var max_x = round(ccx[2]); var max_y = round(ccx[3]); var _sw = max_x - min_x + 1; var _sh = max_y - min_y + 1; if(_sw <= 1 || _sh <= 1) continue; _outSurf = surface_create_valid(_sw, _sh); _val[_ind] = _outSurf; surface_set_shader(_outSurf, sh_seperate_shape_sep); shader_set_surface("original", _inSurf); shader_set_f("color", ccx); shader_set_i("override", _ovr); shader_set_color("overColor", _ovrclr); draw_surface_safe(temp_surface[res_index], -min_x, -min_y); surface_reset_shader(); _atlas[_ind] = new SurfaceAtlas(_outSurf, min_x, min_y).setOrginalSurface(_inSurf); _ind++; } array_resize(_val, _ind); array_resize(_atlas, _ind); ds_map_destroy(reg); outputs[0].setValue(_val); outputs[1].setValue(_atlas); #endregion } }