Pixel-Composer/scripts/node_seperate_shapes/node_seperate_shapes.gml

179 lines
5.3 KiB
Text
Raw Normal View History

2023-02-28 09:43:01 +01:00
function Node_Seperate_Shape(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
2023-01-25 06:49:00 +01:00
name = "Separate Shape";
2023-03-24 05:55:34 +01:00
//error_update_enabled = true;
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, 0)
.rejectArray();
2022-01-13 05:24:03 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 1] = nodeValue("Tolerance", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.2)
2023-10-08 04:14:35 +02:00
.setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 1, 0.01 ], update_stat: SLIDER_UPDATE.release })
2023-02-14 05:32:32 +01:00
.rejectArray();
2023-01-25 06:49:00 +01:00
2023-03-28 06:58:28 +02:00
inputs[| 2] = nodeValue("Override color", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false)
2023-02-14 05:32:32 +01:00
.rejectArray();
2023-01-25 06:49:00 +01:00
2023-02-14 05:32:32 +01:00
inputs[| 3] = nodeValue("Color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white)
.rejectArray();
2023-01-25 06:49:00 +01:00
2023-03-28 06:58:28 +02:00
inputs[| 4] = nodeValue("Ignore blank", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true, "Skip empty and black shape.")
2023-02-14 05:32:32 +01:00
.rejectArray();
2022-01-17 02:19:01 +01:00
2023-02-14 05:32:32 +01:00
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
2023-01-17 08:11:55 +01:00
2023-10-06 11:51:11 +02:00
outputs[| 1] = nodeValue("Atlas", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, []);
2022-01-13 05:24:03 +01:00
2023-01-25 06:49:00 +01:00
input_display_list = [
["Shape", false], 0, 1, 4,
2024-01-08 08:10:50 +01:00
["Override Color", true, 2], 3,
2023-01-25 06:49:00 +01:00
]
2023-03-19 09:17:39 +01:00
attribute_surface_depth();
2023-02-23 07:02:19 +01:00
temp_surface = [ surface_create(1, 1), surface_create(1, 1) ];
surface_buffer = buffer_create(1 * 1 * 4, buffer_fixed, 2);
2023-02-14 05:32:32 +01:00
surface_w = 1;
surface_h = 1;
attributes.max_shape = 64;
2023-07-14 20:34:35 +02:00
array_push(attributeEditors, ["Maximum shapes", function() { return attributes.max_shape; },
2023-04-11 20:29:20 +02:00
new textBox(TEXTBOX_INPUT.number, function(val) {
2023-06-13 14:42:06 +02:00
attributes.max_shape = val;
2023-04-11 20:29:20 +02:00
triggerRender();
})]);
2023-03-19 09:17:39 +01:00
2023-02-14 05:32:32 +01:00
function get_color_buffer(_x, _y) {
buffer_seek(surface_buffer, buffer_seek_start, (surface_w * _y + _x) * 4);
var c = buffer_read(surface_buffer, buffer_u32);
return c;
}
_prev_type = -1;
2022-01-13 05:24:03 +01:00
2023-03-28 06:58:28 +02:00
static onInspector1Update = function() { separateShape(); }
2023-03-24 05:55:34 +01:00
static update = function() {
2023-10-06 11:51:11 +02:00
separateShape();
2023-03-24 05:55:34 +01:00
}
static separateShape = function() {
var _inSurf = getInputData(0);
var _thres = getInputData(1);
var _ovr = getInputData(2);
var _ovrclr = getInputData(3);
var _ignore = getInputData(4);
var t = current_time;
2022-01-13 05:24:03 +01:00
if(!is_surface(_inSurf)) return;
2023-09-08 21:37:36 +02:00
var ww = surface_get_width_safe(_inSurf);
var hh = surface_get_height_safe(_inSurf);
2023-02-14 05:32:32 +01:00
surface_w = ww;
surface_h = hh;
2022-01-13 05:24:03 +01:00
for(var i = 0; i < 2; i++) {
2023-03-19 09:17:39 +01:00
temp_surface[i] = surface_verify(temp_surface[i], ww, hh, attrDepth());
2022-01-13 05:24:03 +01:00
2023-02-23 07:02:19 +01:00
surface_set_target(temp_surface[i]);
2023-03-19 09:17:39 +01:00
DRAW_CLEAR
2022-01-13 05:24:03 +01:00
surface_reset_target();
}
#region region indexing
surface_set_shader(temp_surface[1], sh_seperate_shape_index);
shader_set_i("ignore", _ignore);
draw_sprite_stretched(s_fx_pixel, 0, 0, 0, ww, hh);
surface_reset_shader();
2022-01-13 05:24:03 +01:00
shader_set(sh_seperate_shape_ite);
shader_set_i("ignore", _ignore);
shader_set_f("dimension", ww, hh);
shader_set_f("threshold", _thres);
shader_set_surface("map", _inSurf);
shader_reset();
2022-01-13 05:24:03 +01:00
var res_index = 0, iteration = ww + hh;
for(var i = 0; i <= iteration; i++) {
var bg = i % 2;
var fg = !bg;
2022-01-13 05:24:03 +01:00
surface_set_shader(temp_surface[bg], sh_seperate_shape_ite,, BLEND.over);
draw_surface_safe(temp_surface[fg], 0, 0);
surface_reset_shader();
2022-01-13 05:24:03 +01:00
res_index = bg;
}
#endregion
2022-01-13 05:24:03 +01:00
#region count and match color
var _pixel_surface = surface_create_valid(attributes.max_shape, 1);
surface_set_shader(_pixel_surface, sh_seperate_shape_counter);
shader_set_surface("surface", temp_surface[res_index]);
shader_set_f("dimension", [ ww, hh ]);
shader_set_i("maxShape", attributes.max_shape);
shader_set_i("ignore", _ignore);
2023-06-13 14:42:06 +02:00
draw_sprite_ext(s_fx_pixel, 0, 0, 0, attributes.max_shape, 1, 0, c_white, 1);
surface_reset_shader();
2022-01-13 05:24:03 +01:00
var px = surface_get_pixel(_pixel_surface, 0, 0);
if(px == 0) return;
#endregion
2023-01-25 06:49:00 +01:00
#region extract region
var _outSurf, _val;
_val = array_create(px);
outputs[| 0].setValue(_val);
2022-01-13 05:24:03 +01:00
var _atlas = array_create(px);
2023-10-06 11:51:11 +02:00
var _pad = 0;
buffer_delete(surface_buffer);
surface_buffer = buffer_create(ww * hh * 4, buffer_fixed, 2);
buffer_get_surface(surface_buffer, temp_surface[res_index], 0);
for(var i = 0; i < px; i++) {
2023-10-06 11:51:11 +02:00
var ccx = surface_get_pixel_ext(_pixel_surface, 1 + i, 0);
var alpha = (ccx >> 24) & 255;
var blue = (ccx >> 16) & 255;
var green = (ccx >> 8) & 255;
var red = ccx & 255;
2022-01-13 05:24:03 +01:00
2023-10-06 11:51:11 +02:00
var min_x = floor(red / 255 * ww);
var min_y = floor(green / 255 * hh);
var max_x = ceil(blue / 255 * ww);
var max_y = ceil(alpha / 255 * hh);
var t = max_y;
var b = min_y;
var l = max_x;
var r = min_x;
for( var j = min_x; j < max_x; j++ )
for( var k = min_y; k < max_y; k++ ) {
var _sc = get_color_buffer(j, k);
if(_sc != ccx) continue;
2023-01-25 06:49:00 +01:00
2023-10-06 11:51:11 +02:00
t = min(t, k);
b = max(b, k);
l = min(l, j);
r = max(r, j);
}
2023-10-06 11:51:11 +02:00
_outSurf = surface_create_valid(r - l + 1 + _pad * 2, b - t + 1 + _pad * 2);
_val[i] = _outSurf;
surface_set_shader(_outSurf, sh_seperate_shape_sep);
shader_set_surface("original", _inSurf);
shader_set_f("color", red, green, blue, alpha);
shader_set_i("override", _ovr);
shader_set_f("overColor", colToVec4(_ovrclr));
2023-10-06 11:51:11 +02:00
draw_surface_safe(temp_surface[res_index], -l + _pad, -t + _pad);
surface_reset_shader();
2023-10-06 11:51:11 +02:00
_atlas[i] = new SurfaceAtlas(_outSurf, l, t).setOrginalSurface(_inSurf);
}
2023-01-25 06:49:00 +01:00
outputs[| 1].setValue(_atlas);
#endregion
2022-01-13 05:24:03 +01:00
}
}