From 196daeb8494a33c3f8d0705f4e56828c4cada00c Mon Sep 17 00:00:00 2001 From: Tanasart Date: Wed, 29 May 2024 11:30:01 +0700 Subject: [PATCH] - [Canvas] Fix flood fill, magic selector combine black and fully transparent pixels. --- objects/o_dialog_color_selector/Create_0.gml | 2 +- objects/o_dialog_gradient/Create_0.gml | 2 +- .../canvas_flood_fill_functions.gml | 61 ++++++---- .../canvas_magic_selection_functions.gml | 60 ++++++---- scripts/canvas_tool_fill/canvas_tool_fill.gml | 6 +- scripts/color_function/color_function.gml | 35 ++++-- scripts/node_de_corner/node_de_corner.gml | 8 +- shaders/sh_de_corner/sh_de_corner.fsh | 112 ++++++++++-------- 8 files changed, 177 insertions(+), 109 deletions(-) diff --git a/objects/o_dialog_color_selector/Create_0.gml b/objects/o_dialog_color_selector/Create_0.gml index 7e03f9703..0d8cb8303 100644 --- a/objects/o_dialog_color_selector/Create_0.gml +++ b/objects/o_dialog_color_selector/Create_0.gml @@ -77,7 +77,7 @@ event_inherited(); } if(preset_selecting == i) - var _palRes = drawPaletteGrid(pal.palette, ui(16), yy + ui(28), ww, _gs, selector.current_color); + var _palRes = drawPaletteGrid(pal.palette, ui(16), yy + ui(28), ww, _gs, { color : selector.current_color, mx : _m[0], my : _m[1] }); else drawPalette(pal.palette, ui(16), yy + ui(28), ww, ui(20)); diff --git a/objects/o_dialog_gradient/Create_0.gml b/objects/o_dialog_gradient/Create_0.gml index 18d278b80..575fbef66 100644 --- a/objects/o_dialog_gradient/Create_0.gml +++ b/objects/o_dialog_gradient/Create_0.gml @@ -190,7 +190,7 @@ event_inherited(); } if(palette_selecting == i) - var _palRes = drawPaletteGrid(pal.palette, ui(16), yy + ui(28), ww, _gs); + var _palRes = drawPaletteGrid(pal.palette, ui(16), yy + ui(28), ww, _gs, { mx : _m[0], my : _m[1] }); else drawPalette(pal.palette, ui(16), yy + ui(28), ww, ui(20)); diff --git a/scripts/canvas_flood_fill_functions/canvas_flood_fill_functions.gml b/scripts/canvas_flood_fill_functions/canvas_flood_fill_functions.gml index d036d90ef..fd285a557 100644 --- a/scripts/canvas_flood_fill_functions/canvas_flood_fill_functions.gml +++ b/scripts/canvas_flood_fill_functions/canvas_flood_fill_functions.gml @@ -2,13 +2,15 @@ function _ff_getPixel(_x, _y) { return buffer_read_at(_ff_buff, (_y * _ff_w + _x function canvas_ff_fillable(colorBase, colorFill, _x, _y, _thres) { #region var c = _ff_getPixel(_x, _y); - var d = color_diff(colorBase, c, true, true); + var d = color_diff_alpha(colorBase, c); + //print($"Checking [{_x}, {_y}]: {colorBase} - {c} : {_color_get_alpha(colorBase)} - {_color_get_alpha(c)} | {d}"); return d <= _thres && c != colorFill; } #endregion function canvas_flood_fill_scanline(_surf, _x, _y, _thres, _corner = false) { #region + var colorFill = CURRENT_COLOR; - var colorBase = surface_getpixel_ext(_surf, _x, _y); + var colorBase = int64(surface_getpixel_ext(_surf, _x, _y)); if(colorFill == colorBase) return; //Clicking on the same color as the fill color @@ -24,13 +26,15 @@ function canvas_flood_fill_scanline(_surf, _x, _y, _thres, _corner = false) { #r var spanAbove, spanBelow; var thr = _thres * _thres; - var queue = ds_queue_create(); - ds_queue_enqueue(queue, [_x, _y]); + var qx = ds_queue_create(); + var qy = ds_queue_create(); + ds_queue_enqueue(qx, _x); + ds_queue_enqueue(qy, _y); - while(!ds_queue_empty(queue)) { - var pos = ds_queue_dequeue(queue); - x1 = pos[0]; - y1 = pos[1]; + while(!ds_queue_empty(qx)) { + + x1 = ds_queue_dequeue(qx); + y1 = ds_queue_dequeue(qy); if(_ff_getPixel(x1, y1) == colorFill) continue; //Color in queue is already filled @@ -47,32 +51,47 @@ function canvas_flood_fill_scanline(_surf, _x, _y, _thres, _corner = false) { #r buffer_write(_ff_buff, buffer_u32, _c); if(y1 > 0) { - if(_corner && x1 > 0 && canvas_ff_fillable(colorBase, colorFill, x1 - 1, y1 - 1, thr)) //Check top left pixel - ds_queue_enqueue(queue, [x1 - 1, y1 - 1]); + if(_corner && x1 > 0 && canvas_ff_fillable(colorBase, colorFill, x1 - 1, y1 - 1, thr)) { //Check top left pixel + ds_queue_enqueue(qx, x1 - 1); + ds_queue_enqueue(qy, y1 - 1); + } - if(canvas_ff_fillable(colorBase, colorFill, x1, y1 - 1, thr)) //Check top pixel - ds_queue_enqueue(queue, [x1, y1 - 1]); + if(canvas_ff_fillable(colorBase, colorFill, x1, y1 - 1, thr)) { //Check top pixel + ds_queue_enqueue(qx, x1); + ds_queue_enqueue(qy, y1 - 1); + } } if(y1 < surface_h - 1) { - if(_corner && x1 > 0 && canvas_ff_fillable(colorBase, colorFill, x1 - 1, y1 + 1, thr)) //Check bottom left pixel - ds_queue_enqueue(queue, [x1 - 1, y1 + 1]); + if(_corner && x1 > 0 && canvas_ff_fillable(colorBase, colorFill, x1 - 1, y1 + 1, thr)) { //Check bottom left pixel + ds_queue_enqueue(qx, x1 - 1); + ds_queue_enqueue(qy, y1 + 1); + } - if(canvas_ff_fillable(colorBase, colorFill, x1, y1 + 1, thr)) //Check bottom pixel - ds_queue_enqueue(queue, [x1, y1 + 1]); + if(canvas_ff_fillable(colorBase, colorFill, x1, y1 + 1, thr)) { //Check bottom pixel + ds_queue_enqueue(qx, x1); + ds_queue_enqueue(qy, y1 + 1); + } } if(_corner && x1 < surface_w - 1) { - if(y1 > 0 && canvas_ff_fillable(colorBase, colorFill, x1 + 1, y1 - 1, thr)) //Check top right pixel - ds_queue_enqueue(queue, [x1 + 1, y1 - 1]); + if(y1 > 0 && canvas_ff_fillable(colorBase, colorFill, x1 + 1, y1 - 1, thr)) { //Check top right pixel + ds_queue_enqueue(qx, x1 + 1); + ds_queue_enqueue(qy, y1 - 1); + } - if(y1 < surface_h - 1 && canvas_ff_fillable(colorBase, colorFill, x1 + 1, y1 + 1, thr)) //Check bottom right pixel - ds_queue_enqueue(queue, [x1 + 1, y1 + 1]); + if(y1 < surface_h - 1 && canvas_ff_fillable(colorBase, colorFill, x1 + 1, y1 + 1, thr)) { //Check bottom right pixel + ds_queue_enqueue(qx, x1 + 1); + ds_queue_enqueue(qy, y1 + 1); + } } x1++; } } + + ds_queue_destroy(qx); + ds_queue_destroy(qy); draw_set_alpha(1); buffer_delete(_ff_buff); @@ -100,7 +119,7 @@ function canvas_flood_fill_all(_surf, _x, _y, _thres) { #region for (var j = 0; j < _ff_w; j++) { var c = buffer_read(_ff_buff, buffer_u32); - var d = color_diff(colorBase, c, true, true); + var d = color_diff_alpha(colorBase, c); if(d > _thres) continue; draw_point(j, i); diff --git a/scripts/canvas_magic_selection_functions/canvas_magic_selection_functions.gml b/scripts/canvas_magic_selection_functions/canvas_magic_selection_functions.gml index 532a83c3d..314030af8 100644 --- a/scripts/canvas_magic_selection_functions/canvas_magic_selection_functions.gml +++ b/scripts/canvas_magic_selection_functions/canvas_magic_selection_functions.gml @@ -1,13 +1,13 @@ function canvas_ms_fillable(colorBase, colorFill, _x, _y, _thres) { #region var c = _ff_getPixel(_x, _y); - var d = color_diff(colorBase, c, true, true); + var d = color_diff_alpha(colorBase, c); return d <= _thres; } #endregion function canvas_magic_selection_scanline(_surf, _x, _y, _thres, _corner = false) { #region - var colorBase = surface_getpixel_ext(_surf, _x, _y); + var colorBase = int64(surface_getpixel_ext(_surf, _x, _y)); var colorFill = colorBase; var x1, y1, x_start; @@ -19,8 +19,10 @@ function canvas_magic_selection_scanline(_surf, _x, _y, _thres, _corner = false) _ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4); buffer_get_surface(_ff_buff, _surf, 0); - var queue = ds_queue_create(); - ds_queue_enqueue(queue, [_x, _y]); + var qx = ds_queue_create(); + var qy = ds_queue_create(); + ds_queue_enqueue(qx, _x); + ds_queue_enqueue(qy, _y); var sel_x0 = surface_w; var sel_y0 = surface_h; @@ -30,10 +32,10 @@ function canvas_magic_selection_scanline(_surf, _x, _y, _thres, _corner = false) var _arr = array_create(surface_w * surface_h, 0); draw_set_color(c_white); - while(!ds_queue_empty(queue)) { - var pos = ds_queue_dequeue(queue); - x1 = pos[0]; - y1 = pos[1]; + while(!ds_queue_empty(qx)) { + + x1 = ds_queue_dequeue(qx); + y1 = ds_queue_dequeue(qy); if(_arr[y1 * surface_w + x1] == 1) continue; //Color in queue is already filled @@ -60,34 +62,48 @@ function canvas_magic_selection_scanline(_surf, _x, _y, _thres, _corner = false) //print($"> Filling {x1}, {y1}: {canvas_get_color_buffer(x1, y1)}"); if(y1 > 0) { - if(_corner && x1 > 0 && canvas_ms_fillable(colorBase, colorFill, x1 - 1, y1 - 1, thr)) //Check top left pixel - ds_queue_enqueue(queue, [x1 - 1, y1 - 1]); + if(_corner && x1 > 0 && canvas_ms_fillable(colorBase, colorFill, x1 - 1, y1 - 1, thr)) { //Check top left pixel + ds_queue_enqueue(qx, x1 - 1); + ds_queue_enqueue(qy, y1 - 1); + } - if(canvas_ms_fillable(colorBase, colorFill, x1, y1 - 1, thr)) //Check top pixel - ds_queue_enqueue(queue, [x1, y1 - 1]); + if(canvas_ms_fillable(colorBase, colorFill, x1, y1 - 1, thr)) { //Check top pixel + ds_queue_enqueue(qx, x1); + ds_queue_enqueue(qy, y1 - 1); + } } if(y1 < surface_h - 1) { - if(_corner && x1 > 0 && canvas_ms_fillable(colorBase, colorFill, x1 - 1, y1 + 1, thr)) //Check bottom left pixel - ds_queue_enqueue(queue, [x1 - 1, y1 + 1]); + if(_corner && x1 > 0 && canvas_ms_fillable(colorBase, colorFill, x1 - 1, y1 + 1, thr)) { //Check bottom left pixel + ds_queue_enqueue(qx, x1 - 1); + ds_queue_enqueue(qy, y1 + 1); + } - if(canvas_ms_fillable(colorBase, colorFill, x1, y1 + 1, thr)) //Check bottom pixel - ds_queue_enqueue(queue, [x1, y1 + 1]); + if(canvas_ms_fillable(colorBase, colorFill, x1, y1 + 1, thr)) { //Check bottom pixel + ds_queue_enqueue(qx, x1); + ds_queue_enqueue(qy, y1 + 1); + } } if(_corner && x1 < surface_w - 1) { - if(y1 > 0 && canvas_ms_fillable(colorBase, colorFill, x1 + 1, y1 - 1, thr)) //Check top right pixel - ds_queue_enqueue(queue, [x1 + 1, y1 - 1]); + if(y1 > 0 && canvas_ms_fillable(colorBase, colorFill, x1 + 1, y1 - 1, thr)) { //Check top right pixel + ds_queue_enqueue(qx, x1 + 1); + ds_queue_enqueue(qy, y1 - 1); + } - if(y1 < surface_h - 1 && canvas_ms_fillable(colorBase, colorFill, x1 + 1, y1 + 1, thr)) //Check bottom right pixel - ds_queue_enqueue(queue, [x1 + 1, y1 + 1]); + if(y1 < surface_h - 1 && canvas_ms_fillable(colorBase, colorFill, x1 + 1, y1 + 1, thr)) { //Check bottom right pixel + ds_queue_enqueue(qx, x1 + 1); + ds_queue_enqueue(qy, y1 + 1); + } } x1++; } } - ds_queue_destroy(queue); + ds_queue_destroy(qx); + ds_queue_destroy(qy); + buffer_delete(_ff_buff); return [ sel_x0, sel_y0, sel_x1, sel_y1 ]; @@ -115,7 +131,7 @@ function canvas_magic_selection_all(_surf, _x, _y, _thres) { #region for (var j = 0; j < _ff_w; j++) { var c = buffer_read(_ff_buff, buffer_u32); - var d = color_diff(colorBase, c, true, true); + var d = color_diff_alpha(colorBase, c); if(d > _thres) continue; draw_point(j, i); diff --git a/scripts/canvas_tool_fill/canvas_tool_fill.gml b/scripts/canvas_tool_fill/canvas_tool_fill.gml index fef2c15e4..d60419917 100644 --- a/scripts/canvas_tool_fill/canvas_tool_fill.gml +++ b/scripts/canvas_tool_fill/canvas_tool_fill.gml @@ -21,9 +21,9 @@ function canvas_tool_fill(toolAttr) : canvas_tool() constructor { surface_set_target(_canvas_surface); switch(_fill_type) { - case 0 : canvas_flood_fill_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, false); break; - case 1 : canvas_flood_fill_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, true); break; - case 2 : canvas_flood_fill_all( _canvas_surface, mouse_cur_x, mouse_cur_y, _thr); break; + case 0 : + case 1 : canvas_flood_fill_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, _fill_type); break; + case 2 : canvas_flood_fill_all( _canvas_surface, mouse_cur_x, mouse_cur_y, _thr); break; } surface_reset_target(); diff --git a/scripts/color_function/color_function.gml b/scripts/color_function/color_function.gml index f5e34bc2a..e895888a3 100644 --- a/scripts/color_function/color_function.gml +++ b/scripts/color_function/color_function.gml @@ -153,19 +153,32 @@ } #endregion #endregion -function color_diff(c1, c2, fast = false, alpha = false) { #region - var _c1_r = _color_get_red(c1); - var _c1_g = _color_get_green(c1); - var _c1_b = _color_get_blue(c1); - var _c1_a = _color_get_alpha(c1); +function color_diff_fast(c1, c2) { #region + INLINE - var _c2_r = _color_get_red(c2); - var _c2_g = _color_get_green(c2); - var _c2_b = _color_get_blue(c2); - var _c2_a = _color_get_alpha(c2); + return (abs(_color_get_red(c1) - _color_get_red(c2)) + + abs(_color_get_green(c1) - _color_get_green(c2)) + + abs(_color_get_blue(c1) - _color_get_blue(c2)) + ) / 3; +} #endregion + +function color_diff_alpha(c1, c2) { #region + INLINE - if(fast) return (abs(_c1_r - _c2_r) + abs(_c1_g - _c2_g) + abs(_c1_b - _c2_b)) / 3; - return sqrt(sqr(_c1_r - _c2_r) + sqr(_c1_g - _c2_g) + sqr(_c1_b - _c2_b)); + return sqrt(sqr(_color_get_red(c1) - _color_get_red(c2)) + + sqr(_color_get_green(c1) - _color_get_green(c2)) + + sqr(_color_get_blue(c1) - _color_get_blue(c2)) + + sqr(_color_get_alpha(c1) - _color_get_alpha(c2)) + ); +} #endregion + +function color_diff(c1, c2) { #region + INLINE + + return sqrt(sqr(_color_get_red(c1) - _color_get_red(c2)) + + sqr(_color_get_green(c1) - _color_get_green(c2)) + + sqr(_color_get_blue(c1) - _color_get_blue(c2)) + ); } #endregion #region merge diff --git a/scripts/node_de_corner/node_de_corner.gml b/scripts/node_de_corner/node_de_corner.gml index ed93c5af0..5dccb14b2 100644 --- a/scripts/node_de_corner/node_de_corner.gml +++ b/scripts/node_de_corner/node_de_corner.gml @@ -21,11 +21,14 @@ function Node_De_Corner(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) __init_mask_modifier(5); // inputs 7, 8, + inputs[| 9] = nodeValue("Include", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0b11) + .setDisplay(VALUE_DISPLAY.toggle, { data: [ "Inner", "Side" ] }); + outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); input_display_list = [ 1, ["Surfaces", true], 0, 5, 6, 7, 8, - ["Effect", false], 4, 2, 3, + ["Effect", false], 4, 9, 2, 3, ] attribute_surface_depth(); @@ -41,6 +44,7 @@ function Node_De_Corner(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) var _tol = _data[2]; var _itr = _data[3]; var _str = _data[4]; + var _inn = _data[9]; var _sw = surface_get_width_safe(surf); var _sh = surface_get_height_safe(surf); @@ -57,6 +61,8 @@ function Node_De_Corner(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) shader_set_f("dimension", _sw, _sh); shader_set_f("tolerance", _tol); shader_set_i("strict", _str); + shader_set_i("inner", bool(_inn & 0b01)); + shader_set_i("side", bool(_inn & 0b10)); draw_surface_safe(temp_surface[!_bg]); surface_reset_shader(); diff --git a/shaders/sh_de_corner/sh_de_corner.fsh b/shaders/sh_de_corner/sh_de_corner.fsh index de3f5eca9..7ff18e342 100644 --- a/shaders/sh_de_corner/sh_de_corner.fsh +++ b/shaders/sh_de_corner/sh_de_corner.fsh @@ -1,22 +1,33 @@ -// -// Simple passthrough fragment shader -// varying vec2 v_vTexcoord; varying vec4 v_vColour; uniform vec2 dimension; uniform float tolerance; uniform int strict; +uniform int inner; +uniform int side; float d(in vec4 c1, in vec4 c2) { return length(c1.rgb * c1.a - c2.rgb * c2.a) / sqrt(3.); } -bool s(in vec4 c1, in vec4 c2) { return d(c1, c2) <= tolerance; } + +vec4 a4; +bool s(in vec4 c2) { return d(a4, c2) <= tolerance; } +bool s(in bool b, in vec4 c2) { return b || d(a4, c2) <= tolerance; } + +bool s(in vec4 c1, in vec4 c2) { return d(c1, c2) <= tolerance; } +bool s(in bool b, in vec4 c1, in vec4 c2) { return b || d(c1, c2) <= tolerance; } + +bool ns(in vec4 c2) { return d(a4, c2) > tolerance; } +bool ns(in bool b, in vec4 c2) { return b || d(a4, c2) > tolerance; } + +bool ns(in vec4 c1, in vec4 c2) { return d(c1, c2) > tolerance; } +bool ns(in bool b, in vec4 c1, in vec4 c2) { return b || d(c1, c2) > tolerance; } float bright(in vec4 c) { return dot(c.rgb, vec3(0.2126, 0.7152, 0.0722)) * c.a; } #region select closet color - vec4 sel2(in vec4 c, in vec4 c0, in vec4 c1) { - float d0 = d(c, c0); - float d1 = d(c, c1); + vec4 sel2(in vec4 c0, in vec4 c1) { + float d0 = d(a4, c0); + float d1 = d(a4, c1); float mn = min(d0, d1); @@ -24,10 +35,10 @@ float bright(in vec4 c) { return dot(c.rgb, vec3(0.2126, 0.7152, 0.0722)) * c.a; return c1; } - vec4 sel3(in vec4 c, in vec4 c0, in vec4 c1, in vec4 c2) { - float d0 = d(c, c0); - float d1 = d(c, c1); - float d2 = d(c, c2); + vec4 sel3(in vec4 c0, in vec4 c1, in vec4 c2) { + float d0 = d(a4, c0); + float d1 = d(a4, c1); + float d2 = d(a4, c2); float mn = min(min(d0, d1), d2); @@ -36,11 +47,11 @@ float bright(in vec4 c) { return dot(c.rgb, vec3(0.2126, 0.7152, 0.0722)) * c.a; return c2; } - vec4 sel4(in vec4 c, in vec4 c0, in vec4 c1, in vec4 c2, in vec4 c3) { - float d0 = d(c, c0); - float d1 = d(c, c1); - float d2 = d(c, c2); - float d3 = d(c, c3); + vec4 sel4(in vec4 c0, in vec4 c1, in vec4 c2, in vec4 c3) { + float d0 = d(a4, c0); + float d1 = d(a4, c1); + float d2 = d(a4, c2); + float d3 = d(a4, c3); float mn = min(min(d0, d1), min(d2, d3)); @@ -63,7 +74,7 @@ void main() { // 3 4 5 // 6 7 8 - vec4 a4 = texture2D( gm_BaseTexture, v_vTexcoord ); + a4 = texture2D( gm_BaseTexture, v_vTexcoord ); vec2 tx = 1. / dimension; gl_FragColor = a4; @@ -80,62 +91,65 @@ void main() { vec4 a7 = sample( v_vTexcoord + vec2( 0., tx.y) ); vec4 a8 = sample( v_vTexcoord + vec2( tx.x, tx.y) ); + bool n = inner == 0; + bool d = side == 0; + if(strict == 0) { - if(s(a4, a0) && s(a4, a1) && s(a4, a3) && !s(a4, a2) && !s(a4, a5) && !s(a4, a6) && !s(a4, a7) && !s(a4, a8)) { // A A 2 - // A A 5 - // 6 7 8 - gl_FragColor = sel3(a4, sel2(a4, a2, a6), sel2(a4, a5, a7), a8); + if(s(n, a0) && s(a1) && s(a3) && ns(d, a2) && ns(d, a5) && ns(d, a6) && ns(d, a7) && ns(a8)) { // A A 2 + // A A 5 + // 6 7 8 + gl_FragColor = n? sel3(a5, a7, a8) : sel3(sel2(a2, a6), sel2(a5, a7), a8); return; } - if(s(a4, a1) && s(a4, a2) && s(a4, a5) && !s(a4, a0) && !s(a4, a3) && !s(a4, a6) && !s(a4, a7) && !s(a4, a8)) { // 0 A A - // 3 A A - // 6 7 8 - gl_FragColor = sel3(a4, sel2(a4, a0, a8), sel2(a4, a3, a7), a6); + if(s(a1) && s(n, a2) && s(a5) && ns(d, a0) && ns(d, a3) && ns(a6) && ns(d, a7) && ns(d, a8)) { // 0 A A + // 3 A A + // 6 7 8 + gl_FragColor = n? sel3(a3, a6, a7) : sel3(sel2(a0, a8), sel2(a3, a7), a6); return; } - if(s(a4, a3) && s(a4, a6) && s(a4, a7) && !s(a4, a0) && !s(a4, a1) && !s(a4, a2) && !s(a4, a5) && !s(a4, a8)) { // 0 1 2 - // A A 5 - // A A 8 - gl_FragColor = sel3(a4, sel2(a4, a0, a8), sel2(a4, a1, a5), a2); + if(s(a3) && s(n, a6) && s(a7) && ns(d, a0) && ns(d, a1) && ns(a2) && ns(d, a5) && ns(d, a8)) { // 0 1 2 + // A A 5 + // A A 8 + gl_FragColor = n? sel3(a1, a2, a5) : sel3(sel2(a0, a8), sel2(a1, a5), a2); return; } - if(s(a4, a5) && s(a4, a7) && s(a4, a8) && !s(a4, a0) && !s(a4, a1) && !s(a4, a2) && !s(a4, a3) && !s(a4, a6)) { // 0 1 2 - // 3 A A - // 6 A A - gl_FragColor = sel3(a4, sel2(a4, a2, a6), sel2(a4, a1, a3), a0); + if(s(a5) && s(a7) && s(n, a8) && ns(a0) && ns(d, a1) && ns(d, a2) && ns(d, a3) && ns(d, a6)) { // 0 1 2 + // 3 A A + // 6 A A + gl_FragColor = n? sel3(a0, a1, a3) : sel3(sel2(a2, a6), sel2(a1, a3), a0); return; } } else if(strict == 1) { - if(s(a5, a7) && s(a4, a1) && s(a4, a3) && s(a4, a0) && !s(a4, a2) && !s(a4, a5) && !s(a4, a6) && !s(a4, a7)) { // B B C - // B B A - // C A 8 - gl_FragColor = sel3(a4, sel2(a4, a2, a6), sel2(a4, a5, a7), a8); + if(s(a5, a7) && s(a1) && s(a3) && s(n, a0) && ns(d, a2) && ns(d, a5) && ns(d, a6) && ns(d, a7)) { // B B C + // B B A + // C A 8 + gl_FragColor = n? sel3(a5, a7, a8) : sel3(sel2(a2, a6), sel2(a5, a7), a8); return; } - if(s(a3, a7) && s(a4, a1) && s(a4, a2) && s(a4, a5) && !s(a4, a0) && !s(a4, a3) && !s(a4, a7) && !s(a4, a8)) { // C B B - // A B B - // 6 A C - gl_FragColor = sel3(a4, sel2(a4, a0, a8), sel2(a4, a3, a7), a6); + if(s(a3, a7) && s(a1) && s(n, a2) && s(a5) && ns(d, a0) && ns(d, a3) && ns(d, a7) && ns(d, a8)) { // C B B + // A B B + // 6 A C + gl_FragColor = n? sel3(a3, a6, a7) : sel3(sel2(a0, a8), sel2(a3, a7), a6); return; } - if(s(a5, a1) && s(a4, a3) && s(a4, a6) && s(a4, a7) && !s(a4, a0) && !s(a4, a1) && !s(a4, a5) && !s(a4, a8)) { // C A 2 - // B B A - // B B C - gl_FragColor = sel3(a4, sel2(a4, a0, a8), sel2(a4, a1, a5), a2); + if(s(a5, a1) && s(a3) && s(n, a6) && s(a7) && ns(d, a0) && ns(d, a1) && ns(d, a5) && ns(d, a8)) { // C A 2 + // B B A + // B B C + gl_FragColor = n? sel3(a1, a2, a5) : sel3(sel2(a0, a8), sel2(a1, a5), a2); return; } - if(s(a3, a1) && s(a4, a5) && s(a4, a8) && s(a4, a7) && !s(a4, a2) && !s(a4, a1) && !s(a4, a3) && !s(a4, a6)) { // 0 A C - // A B B - // C B B - gl_FragColor = sel3(a4, sel2(a4, a2, a6), sel2(a4, a1, a3), a0); + if(s(a3, a1) && s(a5) && s(n, a8) && s(a7) && ns(d, a2) && ns(d, a1) && ns(d, a3) && ns(d, a6)) { // 0 A C + // A B B + // C B B + gl_FragColor = n? sel3(a0, a1, a3) : sel3(sel2(a2, a6), sel2(a1, a3), a0); return; } }