fill modes

This commit is contained in:
Tanasart 2024-04-18 15:04:08 +07:00
parent e5f73db0ed
commit 1daa21a32e
24 changed files with 729 additions and 74 deletions

View file

@ -1,15 +1,17 @@
// 2024-04-18 12:09:27
// 2024-04-18 15:00:52
function buttonGroup(_data, _onClick) : widget() constructor {
data = _data;
onClick = _onClick;
size = array_length(data);
display_button = false;
buttonSpr = [ THEME.button_left, THEME.button_middle, THEME.button_right ];
fColor = COLORS._main_text;
current_selecting = 0;
tooltips = [];
current_selecting = 0;
for(var i = 0; i < array_length(data); i++)
buttons[i] = button(-1);

View file

@ -1,4 +1,4 @@
// 2024-04-18 08:59:10
// 2024-04-18 15:00:45
function buttonGroup(_data, _onClick) : widget() constructor {
data = _data;
onClick = _onClick;
@ -7,9 +7,11 @@ function buttonGroup(_data, _onClick) : widget() constructor {
buttonSpr = [ THEME.button_left, THEME.button_middle, THEME.button_right ];
fColor = COLORS._main_text;
current_selecting = 0;
size = array_length(data);
tooltips = [];
current_selecting = 0;
for(var i = 0; i < array_length(data); i++)
buttons[i] = button(-1);

View file

@ -0,0 +1,119 @@
// 2024-04-18 14:54:43
function _ff_getPixel(_x, _y) { return buffer_read_at(_ff_buff, (_y * _ff_w + _x) * 4, buffer_u32); }
function canvas_ff_fillable(colorBase, colorFill, _x, _y, _thres) { #region
var c = _ff_getPixel(_x, _y);
var d = color_diff(colorBase, c, true, true);
return d <= _thres && c != colorFill;
} #endregion
function canvas_flood_fill_scanline(_surf, _x, _y, _thres, _corner = false) { #region
var colorFill = tool_attribute.color;
var colorBase = surface_getpixel_ext(_surf, _x, _y);
if(colorFill == colorBase) return; //Clicking on the same color as the fill color
var _c = tool_attribute.color;
draw_set_color(_c);
_ff_w = surface_get_width(_surf);
_ff_h = surface_get_height(_surf);
_ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4);
buffer_get_surface(_ff_buff, _surf, 0);
var x1, y1, x_start;
var spanAbove, spanBelow;
var thr = _thres * _thres;
var queue = ds_queue_create();
ds_queue_enqueue(queue, [_x, _y]);
while(!ds_queue_empty(queue)) {
var pos = ds_queue_dequeue(queue);
x1 = pos[0];
y1 = pos[1];
if(_ff_getPixel(x1, y1) == colorFill) continue; //Color in queue is already filled
while(x1 > 0 && canvas_ff_fillable(colorBase, colorFill, x1 - 1, y1, thr)) //Move to the leftmost connected pixel in the same row.
x1--;
x_start = x1;
spanAbove = false;
spanBelow = false;
while(x1 < surface_w && canvas_ff_fillable(colorBase, colorFill, x1, y1, thr)) {
draw_point(x1, y1);
buffer_seek(_ff_buff, buffer_seek_start, (y1 * _ff_w + x1) * 4)
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(canvas_ff_fillable(colorBase, colorFill, x1, y1 - 1, thr)) //Check top pixel
ds_queue_enqueue(queue, [x1, 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(canvas_ff_fillable(colorBase, colorFill, x1, y1 + 1, thr)) //Check bottom pixel
ds_queue_enqueue(queue, [x1, 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 < 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]);
}
x1++;
}
}
draw_set_alpha(1);
buffer_delete(_ff_buff);
} #endregion
function canvas_flood_fill_all(_surf, _x, _y, _thres) { #region
var colorBase = surface_getpixel_ext(_surf, _x, _y);
var colorFill = colorBase;
var thr = _thres * _thres;
var _ff_w = surface_get_width(_surf);
var _ff_h = surface_get_height(_surf);
var _ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4);
buffer_get_surface(_ff_buff, _surf, 0);
buffer_seek(_ff_buff, buffer_seek_start, 0);
var sel_x0 = surface_w;
var sel_y0 = surface_h;
var sel_x1 = 0;
var sel_y1 = 0;
for (var i = 0; i < _ff_h; i++)
for (var j = 0; j < _ff_w; j++) {
var c = buffer_read(_ff_buff, buffer_u32);
var d = color_diff(colorBase, c, true, true);
if(d > _thres) continue;
draw_point(j, i);
sel_x0 = min(sel_x0, j);
sel_y0 = min(sel_y0, i);
sel_x1 = max(sel_x1, j);
sel_y1 = max(sel_y1, i);
}
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion

View file

@ -0,0 +1,119 @@
// 2024-04-18 14:54:42
function _ff_getPixel(_x, _y) { return buffer_read_at(_ff_buff, (_y * _ff_w + _x) * 4, buffer_u32); }
function canvas_ff_fillable(colorBase, colorFill, _x, _y, _thres) { #region
var c = _ff_getPixel(_x, _y);
var d = color_diff(colorBase, c, true, true);
return d <= _thres && c != colorFill;
} #endregion
function canvas_flood_fill_scanline(_surf, _x, _y, _thres, _corner = false) { #region
var colorFill = tool_attribute.color;
var colorBase = surface_getpixel_ext(_surf, _x, _y);
if(colorFill == colorBase) return; //Clicking on the same color as the fill color
var _c = tool_attribute.color;
draw_set_color(_c);
_ff_w = surface_get_width(_surf);
_ff_h = surface_get_height(_surf);
_ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4);
buffer_get_surface(_ff_buff, _surf, 0);
var x1, y1, x_start;
var spanAbove, spanBelow;
var thr = _thres * _thres;
var queue = ds_queue_create();
ds_queue_enqueue(queue, [_x, _y]);
while(!ds_queue_empty(queue)) {
var pos = ds_queue_dequeue(queue);
x1 = pos[0];
y1 = pos[1];
if(_ff_getPixel(x1, y1) == colorFill) continue; //Color in queue is already filled
while(x1 > 0 && canvas_ff_fillable(colorBase, colorFill, x1 - 1, y1, thr)) //Move to the leftmost connected pixel in the same row.
x1--;
x_start = x1;
spanAbove = false;
spanBelow = false;
while(x1 < surface_w && canvas_ff_fillable(colorBase, colorFill, x1, y1, thr)) {
draw_point(x1, y1);
buffer_seek(_ff_buff, buffer_seek_start, (y1 * _ff_w + x1) * 4)
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(canvas_ff_fillable(colorBase, colorFill, x1, y1 - 1, thr)) //Check top pixel
ds_queue_enqueue(queue, [x1, 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(canvas_ff_fillable(colorBase, colorFill, x1, y1 + 1, thr)) //Check bottom pixel
ds_queue_enqueue(queue, [x1, 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 < 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]);
}
x1++;
}
}
draw_set_alpha(1);
buffer_delete(_ff_buff);
} #endregion
function canvas_flood_fill_all(_surf, _x, _y, _thres) { #region
var colorBase = surface_getpixel_ext(_surf, _x, _y);
var colorFill = colorBase;
var thr = _thres * _thres;
var _ff_w = surface_get_width(_surf);
var _ff_h = surface_get_height(_surf);
var _ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4);
buffer_get_surface(_ff_buff, _surf, 0);
buffer_seek(_ff_buff, buffer_seek_start, 0);
var sel_x0 = surface_w;
var sel_y0 = surface_h;
var sel_x1 = 0;
var sel_y1 = 0;
for (var i = 0; i < _ff_h; i++)
for (var j = 0; j < _ff_w; j++) {
var c = buffer_read(_ff_buff, buffer_u32);
var d = color_diff(colorBase, c, true, true);
if(d > _thres) continue;
draw_point(j, i);
sel_x0 = min(sel_x0, j);
sel_y0 = min(sel_y0, i);
sel_x1 = max(sel_x1, j);
sel_y1 = max(sel_y1, i);
}
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion

View file

@ -0,0 +1,134 @@
// 2024-04-18 14:49:34
function canvas_ms_fillable(colorBase, colorFill, _x, _y, _thres) { #region
var c = _ff_getPixel(_x, _y);
var d = color_diff(colorBase, c, true, true);
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 colorFill = colorBase;
var x1, y1, x_start;
var spanAbove, spanBelow;
var thr = _thres * _thres;
_ff_w = surface_get_width(_surf);
_ff_h = surface_get_height(_surf);
_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 sel_x0 = surface_w;
var sel_y0 = surface_h;
var sel_x1 = 0;
var sel_y1 = 0;
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];
if(_arr[y1 * surface_w + x1] == 1) continue; //Color in queue is already filled
while(x1 > 0 && canvas_ms_fillable(colorBase, colorFill, x1 - 1, y1, thr)) //Move to the leftmost connected pixel in the same row.
x1--;
x_start = x1;
spanAbove = false;
spanBelow = false;
//print($"Searching {x1}, {y1} | {canvas_ms_fillable(colorBase, colorFill, x1, y1, thr)}");
while(x1 < surface_w && canvas_ms_fillable(colorBase, colorFill, x1, y1, thr)) {
draw_point(x1, y1);
if(_arr[y1 * surface_w + x1] == 1) continue;
_arr[y1 * surface_w + x1] = 1;
sel_x0 = min(sel_x0, x1);
sel_y0 = min(sel_y0, y1);
sel_x1 = max(sel_x1, x1);
sel_y1 = max(sel_y1, y1);
//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(canvas_ms_fillable(colorBase, colorFill, x1, y1 - 1, thr)) //Check top pixel
ds_queue_enqueue(queue, [x1, 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(canvas_ms_fillable(colorBase, colorFill, x1, y1 + 1, thr)) //Check bottom pixel
ds_queue_enqueue(queue, [x1, 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 < 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]);
}
x1++;
}
}
ds_queue_destroy(queue);
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion
function canvas_magic_selection_all(_surf, _x, _y, _thres) { #region
var colorBase = surface_getpixel_ext(_surf, _x, _y);
var colorFill = colorBase;
var thr = _thres * _thres;
var _ff_w = surface_get_width(_surf);
var _ff_h = surface_get_height(_surf);
var _ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4);
buffer_get_surface(_ff_buff, _surf, 0);
buffer_seek(_ff_buff, buffer_seek_start, 0);
var sel_x0 = surface_w;
var sel_y0 = surface_h;
var sel_x1 = 0;
var sel_y1 = 0;
for (var i = 0; i < _ff_h; i++)
for (var j = 0; j < _ff_w; j++) {
var c = buffer_read(_ff_buff, buffer_u32);
var d = color_diff(colorBase, c, true, true);
if(d > _thres) continue;
draw_point(j, i);
sel_x0 = min(sel_x0, j);
sel_y0 = min(sel_y0, i);
sel_x1 = max(sel_x1, j);
sel_y1 = max(sel_y1, i);
}
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion

View file

@ -0,0 +1,134 @@
// 2024-04-18 14:49:32
function canvas_ms_fillable(colorBase, colorFill, _x, _y, _thres) { #region
var c = _ff_getPixel(_x, _y);
var d = color_diff(colorBase, c, true, true);
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 colorFill = colorBase;
var x1, y1, x_start;
var spanAbove, spanBelow;
var thr = _thres * _thres;
_ff_w = surface_get_width(_surf);
_ff_h = surface_get_height(_surf);
_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 sel_x0 = surface_w;
var sel_y0 = surface_h;
var sel_x1 = 0;
var sel_y1 = 0;
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];
if(_arr[y1 * surface_w + x1] == 1) continue; //Color in queue is already filled
while(x1 > 0 && canvas_ms_fillable(colorBase, colorFill, x1 - 1, y1, thr)) //Move to the leftmost connected pixel in the same row.
x1--;
x_start = x1;
spanAbove = false;
spanBelow = false;
//print($"Searching {x1}, {y1} | {canvas_ms_fillable(colorBase, colorFill, x1, y1, thr)}");
while(x1 < surface_w && canvas_ms_fillable(colorBase, colorFill, x1, y1, thr)) {
draw_point(x1, y1);
if(_arr[y1 * surface_w + x1] == 1) continue;
_arr[y1 * surface_w + x1] = 1;
sel_x0 = min(sel_x0, x1);
sel_y0 = min(sel_y0, y1);
sel_x1 = max(sel_x1, x1);
sel_y1 = max(sel_y1, y1);
//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(canvas_ms_fillable(colorBase, colorFill, x1, y1 - 1, thr)) //Check top pixel
ds_queue_enqueue(queue, [x1, 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(canvas_ms_fillable(colorBase, colorFill, x1, y1 + 1, thr)) //Check bottom pixel
ds_queue_enqueue(queue, [x1, 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 < 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]);
}
x1++;
}
}
ds_queue_destroy(queue);
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion
function canvas_magic_selection_all(_surf, _x, _y, _thres) { #region
var colorBase = surface_getpixel_ext(_surf, _x, _y);
var colorFill = colorBase;
var thr = _thres * _thres;
var _ff_w = surface_get_width(_surf);
var _ff_h = surface_get_height(_surf);
var _ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4);
buffer_get_surface(_ff_buff, _surf, 0);
buffer_seek(_ff_buff, buffer_seek_start, 0);
var sel_x0 = surface_w;
var sel_y0 = surface_h;
var sel_x1 = 0;
var sel_y1 = 0;
for (var i = 0; i < _ff_h; i++)
for (var j = 0; j < _ff_w; j++) {
var c = buffer_read(_ff_buff, buffer_u32);
var d = color_diff(colorBase, c, true, true);
if(d > _thres) continue;
draw_point(j, i);
sel_x0 = min(sel_x0, j);
sel_y0 = min(sel_y0, i);
sel_x1 = max(sel_x1, j);
sel_y1 = max(sel_y1, i);
}
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion

View file

@ -0,0 +1,39 @@
// 2024-04-18 14:54:47
function canvas_tool_fill(toolAttr) : canvas_tool() constructor {
self.tool_attribute = toolAttr;
relative = true;
mouse_cur_x = 0;
mouse_cur_y = 0;
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
var _thr = tool_attribute.thres;
var _fill_type = tool_attribute.fillType;
mouse_cur_x = round((_mx - _x) / _s - 0.5);
mouse_cur_y = round((_my - _y) / _s - 0.5);
surface_w = surface_get_width(_canvas_surface);
surface_h = surface_get_height(_canvas_surface);
if(mouse_press(mb_left, active) && point_in_rectangle(mouse_cur_x, mouse_cur_y, 0, 0, surface_w - 1, surface_h - 1)) {
node.storeAction();
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;
}
surface_reset_target();
node.surface_store_buffer();
}
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
}
}

View file

@ -0,0 +1,39 @@
// 2024-04-18 14:54:46
function canvas_tool_fill(toolAttr) : canvas_tool() constructor {
self.tool_attribute = toolAttr;
relative = true;
mouse_cur_x = 0;
mouse_cur_y = 0;
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
var _thr = tool_attribute.thres;
var _fill_type = tool_attribute.fillType;
mouse_cur_x = round((_mx - _x) / _s - 0.5);
mouse_cur_y = round((_my - _y) / _s - 0.5);
surface_w = surface_get_width(_canvas_surface);
surface_h = surface_get_height(_canvas_surface);
if(mouse_press(mb_left, active) && point_in_rectangle(mouse_cur_x, mouse_cur_y, 0, 0, surface_w - 1, surface_h - 1)) {
node.storeAction();
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;
}
surface_reset_target();
node.surface_store_buffer();
}
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
}
}

View file

@ -1,4 +1,4 @@
// 2024-04-18 14:17:33
// 2024-04-18 14:19:06
function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
self.selector = selector;

View file

@ -1,4 +1,4 @@
// 2024-04-18 13:48:56
// 2024-04-18 14:17:33
function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
self.selector = selector;

View file

@ -1,4 +1,4 @@
// 2024-04-18 12:08:38
// 2024-04-18 14:51:58
function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection(selector) constructor {
self.tool_attribute = toolAttr;
@ -13,7 +13,7 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
if(is_selected) { onSelected(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); return; }
var _thr = tool_attribute.thres;
var _fill_type = tool_attribute.fill8;
var _fill_type = tool_attribute.fillType;
if(!selector.is_select_drag && mouse_press(mb_left, active)) {
selecting = true;
@ -34,8 +34,9 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
switch(_fill_type) {
case 0 : bb = canvas_magic_selection_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, false); break;
case 1 : bb = canvas_magic_selection_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, true); break;
}
case 2 : bb = canvas_magic_selection_all(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr); break;
}
surface_reset_target();
var sel_x0 = bb[0];
@ -66,6 +67,6 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
canvas_draw_point_brush(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -1,4 +1,4 @@
// 2024-04-18 09:15:40
// 2024-04-18 14:51:21
function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection(selector) constructor {
self.tool_attribute = toolAttr;
@ -13,7 +13,7 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
if(is_selected) { onSelected(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); return; }
var _thr = tool_attribute.thres;
var _fill_type = tool_attribute.fill8;
var _fill_type = tool_attribute.fillType;
if(!selector.is_select_drag && mouse_press(mb_left, active)) {
selecting = true;
@ -34,8 +34,9 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
switch(_fill_type) {
case 0 : bb = canvas_magic_selection_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, false); break;
case 1 : bb = canvas_magic_selection_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, true); break;
}
case 2 : bb = canvas_magic_selection_all(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr); break;
}
surface_reset_target();
var sel_x0 = bb[0];
@ -66,6 +67,6 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
canvas_draw_point_brush(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -1,4 +1,4 @@
// 2024-04-18 13:40:32
// 2024-04-18 15:00:59
function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Canvas";
color = COLORS.node_blend_canvas;
@ -237,13 +237,14 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
tool_attribute.pressure = false;
tool_attribute.pressure_size = [ 1, 1 ];
tool_attribute.thres = 0;
tool_thrs_edit = new textBox(TEXTBOX_INPUT.number, function(val) { tool_attribute.thres = clamp(val, 0, 1); }).setSlidable(0.01, false, [ 0, 1 ]).setFont(f_p3);
tool_thrs = [ "Threshold", tool_thrs_edit, "thres", tool_attribute ];
tool_attribute.thres = 0;
tool_thrs_edit = new textBox(TEXTBOX_INPUT.number, function(val) { tool_attribute.thres = clamp(val, 0, 1); }).setSlidable(0.01, false, [ 0, 1 ]).setFont(f_p3);
tool_thrs = [ "Threshold", tool_thrs_edit, "thres", tool_attribute ];
tool_attribute.fill8 = false;
tool_fil8_edit = new checkBox(function() { tool_attribute.fill8 = !tool_attribute.fill8; });
tool_fil8 = [ "Diagonal", tool_fil8_edit, "fill8", tool_attribute ];
tool_attribute.fillType = 0;
tool_fil8_edit = new buttonGroup( [ THEME.canvas_fill_type, THEME.canvas_fill_type, THEME.canvas_fill_type ], function(val) { tool_attribute.fillType = val; })
.setTooltips( [ "Edge", "Edge + Corner", "Entire image" ] );
tool_fil8 = [ "Fill", tool_fil8_edit, "fillType", tool_attribute ];
tool_attribute.button_apply = [ false, false ];
tool_curve_apply = button( function() { tool_curve_bez.apply(); } ).setIcon(THEME.toolbar_check, 0);

View file

@ -1,4 +1,4 @@
// 2024-04-18 13:40:30
// 2024-04-18 15:00:58
function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Canvas";
color = COLORS.node_blend_canvas;
@ -237,13 +237,14 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
tool_attribute.pressure = false;
tool_attribute.pressure_size = [ 1, 1 ];
tool_attribute.thres = 0;
tool_thrs_edit = new textBox(TEXTBOX_INPUT.number, function(val) { tool_attribute.thres = clamp(val, 0, 1); }).setSlidable(0.01, false, [ 0, 1 ]).setFont(f_p3);
tool_thrs = [ "Threshold", tool_thrs_edit, "thres", tool_attribute ];
tool_attribute.thres = 0;
tool_thrs_edit = new textBox(TEXTBOX_INPUT.number, function(val) { tool_attribute.thres = clamp(val, 0, 1); }).setSlidable(0.01, false, [ 0, 1 ]).setFont(f_p3);
tool_thrs = [ "Threshold", tool_thrs_edit, "thres", tool_attribute ];
tool_attribute.fill8 = false;
tool_fil8_edit = new checkBox(function() { tool_attribute.fill8 = !tool_attribute.fill8; });
tool_fil8 = [ "Diagonal", tool_fil8_edit, "fill8", tool_attribute ];
tool_attribute.fillType = 0;
tool_fil8_edit = new buttonGroup( [ THEME.canvas_fill_type, THEME.canvas_fill_type, THEME.canvas_fill_type ], function(val) { tool_attribute.fillType = val; })
.setTooltips( [ "Edge", "Edge + Corner", "Entire image" ] );
tool_fil8 = [ "Fill", tool_fil8_edit, "fillType", tool_attribute ];
tool_attribute.button_apply = [ false, false ];
tool_curve_apply = button( function() { tool_curve_bez.apply(); } ).setIcon(THEME.toolbar_check, 0);

View file

@ -1,4 +1,4 @@
// 2024-04-16 09:29:34
// 2024-04-18 15:03:27
#region funtion calls
function __fnInit_Preview() {
__registerFunction("preview_focus_content", panel_preview_focus_content);
@ -1506,8 +1506,10 @@ function Panel_Preview() : PanelContent() constructor {
tolw = ui(40);
if(wdg.side_button != noone) tolw += tolh + ui(8);
break;
case "buttonGroup":
case "checkBoxGroup" : tolw = tolh * wdg.size; break;
case "checkBox" : tolw = tolh; break;
case "scrollBox" : tolw = ui(96); break;
case "buttonClass" : tolw = wdg.text == ""? tolh : tolw; break;
@ -1519,8 +1521,8 @@ function Panel_Preview() : PanelContent() constructor {
wdg.drawParam(params);
tolx += tolw + ui(8) + (nme != "") * ui(8);
tol_max_w += tolw + ui(8) + (nme != "") * ui(8);
tolx += tolw + ui(8);
tol_max_w += tolw + ui(8);
}
tol_max_w = max(0, tol_max_w - w);

View file

@ -1,4 +1,4 @@
// 2024-04-16 09:29:29
// 2024-04-18 15:02:59
#region funtion calls
function __fnInit_Preview() {
__registerFunction("preview_focus_content", panel_preview_focus_content);
@ -102,7 +102,6 @@ function Panel_Preview() : PanelContent() constructor {
bg_color = COLORS.panel_bg_clear;
mouse_pos_string = "";
mouse_pos_icon = "";
#endregion
#region ---- tool ----
@ -1507,8 +1506,10 @@ function Panel_Preview() : PanelContent() constructor {
tolw = ui(40);
if(wdg.side_button != noone) tolw += tolh + ui(8);
break;
case "buttonGroup":
case "checkBoxGroup" : tolw = tolh * wdg.size; break;
case "checkBox" : tolw = tolh; break;
case "scrollBox" : tolw = ui(96); break;
case "buttonClass" : tolw = wdg.text == ""? tolh : tolw; break;
@ -1520,8 +1521,8 @@ function Panel_Preview() : PanelContent() constructor {
wdg.drawParam(params);
tolx += tolw + ui(8) + (nme != "") * ui(8);
tol_max_w += tolw + ui(8) + (nme != "") * ui(8);
tolx += tolw + ui(8);
tol_max_w += tolw + ui(8);
}
tol_max_w = max(0, tol_max_w - w);

Binary file not shown.

View file

@ -1,14 +1,16 @@
function buttonGroup(_data, _onClick) : widget() constructor {
data = _data;
onClick = _onClick;
size = array_length(data);
display_button = false;
buttonSpr = [ THEME.button_left, THEME.button_middle, THEME.button_right ];
fColor = COLORS._main_text;
current_selecting = 0;
tooltips = [];
current_selecting = 0;
for(var i = 0; i < array_length(data); i++)
buttons[i] = button(-1);

View file

@ -78,27 +78,41 @@ function canvas_flood_fill_scanline(_surf, _x, _y, _thres, _corner = false) { #r
buffer_delete(_ff_buff);
} #endregion
function canvas_fill(_x, _y, _surf, _thres) { #region
var _alp = _color_get_alpha(tool_attribute.color);
var w = surface_get_width_safe(_surf);
var h = surface_get_height_safe(_surf);
var _c1 = surface_getpixel_ext(_surf, _x, _y);
function canvas_flood_fill_all(_surf, _x, _y, _thres) { #region
var colorBase = surface_getpixel_ext(_surf, _x, _y);
var colorFill = colorBase;
var thr = _thres * _thres;
var _ff_w = surface_get_width(_surf);
var _ff_h = surface_get_height(_surf);
var _ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4);
buffer_get_surface(_ff_buff, _surf, 0);
buffer_seek(_ff_buff, buffer_seek_start, 0);
var sel_x0 = surface_w;
var sel_y0 = surface_h;
var sel_x1 = 0;
var sel_y1 = 0;
for (var i = 0; i < _ff_h; i++)
for (var j = 0; j < _ff_w; j++) {
draw_set_alpha(_alp);
for( var i = 0; i < w; i++ ) {
for( var j = 0; j < h; j++ ) {
if(i == _x && j == _y) {
draw_point(i, j);
continue;
}
var _c2 = surface_getpixel_ext(_surf, i, j);
if(color_diff(_c1, _c2, true) <= thr)
draw_point(i, j);
}
var c = buffer_read(_ff_buff, buffer_u32);
var d = color_diff(colorBase, c, true, true);
if(d > _thres) continue;
draw_point(j, i);
sel_x0 = min(sel_x0, j);
sel_y0 = min(sel_y0, i);
sel_x1 = max(sel_x1, j);
sel_y1 = max(sel_y1, i);
}
draw_set_alpha(1);
} #endregion
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion

View file

@ -90,5 +90,44 @@ function canvas_magic_selection_scanline(_surf, _x, _y, _thres, _corner = false)
ds_queue_destroy(queue);
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion
function canvas_magic_selection_all(_surf, _x, _y, _thres) { #region
var colorBase = surface_getpixel_ext(_surf, _x, _y);
var colorFill = colorBase;
var thr = _thres * _thres;
var _ff_w = surface_get_width(_surf);
var _ff_h = surface_get_height(_surf);
var _ff_buff = buffer_create(_ff_w * _ff_h * 4, buffer_fixed, 4);
buffer_get_surface(_ff_buff, _surf, 0);
buffer_seek(_ff_buff, buffer_seek_start, 0);
var sel_x0 = surface_w;
var sel_y0 = surface_h;
var sel_x1 = 0;
var sel_y1 = 0;
for (var i = 0; i < _ff_h; i++)
for (var j = 0; j < _ff_w; j++) {
var c = buffer_read(_ff_buff, buffer_u32);
var d = color_diff(colorBase, c, true, true);
if(d > _thres) continue;
draw_point(j, i);
sel_x0 = min(sel_x0, j);
sel_y0 = min(sel_y0, i);
sel_x1 = max(sel_x1, j);
sel_y1 = max(sel_y1, i);
}
buffer_delete(_ff_buff);
return [ sel_x0, sel_y0, sel_x1, sel_y1 ];
} #endregion

View file

@ -8,7 +8,7 @@ function canvas_tool_fill(toolAttr) : canvas_tool() constructor {
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
var _thr = tool_attribute.thres;
var _fill_type = tool_attribute.fill8;
var _fill_type = tool_attribute.fillType;
mouse_cur_x = round((_mx - _x) / _s - 0.5);
mouse_cur_y = round((_my - _y) / _s - 0.5);
@ -23,6 +23,7 @@ function canvas_tool_fill(toolAttr) : canvas_tool() constructor {
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;
}
surface_reset_target();

View file

@ -12,7 +12,7 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
if(is_selected) { onSelected(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); return; }
var _thr = tool_attribute.thres;
var _fill_type = tool_attribute.fill8;
var _fill_type = tool_attribute.fillType;
if(!selector.is_select_drag && mouse_press(mb_left, active)) {
selecting = true;
@ -33,8 +33,9 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
switch(_fill_type) {
case 0 : bb = canvas_magic_selection_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, false); break;
case 1 : bb = canvas_magic_selection_scanline(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr, true); break;
}
case 2 : bb = canvas_magic_selection_all(_canvas_surface, mouse_cur_x, mouse_cur_y, _thr); break;
}
surface_reset_target();
var sel_x0 = bb[0];

View file

@ -236,13 +236,14 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
tool_attribute.pressure = false;
tool_attribute.pressure_size = [ 1, 1 ];
tool_attribute.thres = 0;
tool_thrs_edit = new textBox(TEXTBOX_INPUT.number, function(val) { tool_attribute.thres = clamp(val, 0, 1); }).setSlidable(0.01, false, [ 0, 1 ]).setFont(f_p3);
tool_thrs = [ "Threshold", tool_thrs_edit, "thres", tool_attribute ];
tool_attribute.thres = 0;
tool_thrs_edit = new textBox(TEXTBOX_INPUT.number, function(val) { tool_attribute.thres = clamp(val, 0, 1); }).setSlidable(0.01, false, [ 0, 1 ]).setFont(f_p3);
tool_thrs = [ "Threshold", tool_thrs_edit, "thres", tool_attribute ];
tool_attribute.fill8 = false;
tool_fil8_edit = new checkBox(function() { tool_attribute.fill8 = !tool_attribute.fill8; });
tool_fil8 = [ "Diagonal", tool_fil8_edit, "fill8", tool_attribute ];
tool_attribute.fillType = 0;
tool_fil8_edit = new buttonGroup( [ THEME.canvas_fill_type, THEME.canvas_fill_type, THEME.canvas_fill_type ], function(val) { tool_attribute.fillType = val; })
.setTooltips( [ "Edge", "Edge + Corner", "Entire image" ] );
tool_fil8 = [ "Fill", tool_fil8_edit, "fillType", tool_attribute ];
tool_attribute.button_apply = [ false, false ];
tool_curve_apply = button( function() { tool_curve_bez.apply(); } ).setIcon(THEME.toolbar_check, 0);

View file

@ -1505,8 +1505,10 @@ function Panel_Preview() : PanelContent() constructor {
tolw = ui(40);
if(wdg.side_button != noone) tolw += tolh + ui(8);
break;
case "buttonGroup":
case "checkBoxGroup" : tolw = tolh * wdg.size; break;
case "checkBox" : tolw = tolh; break;
case "scrollBox" : tolw = ui(96); break;
case "buttonClass" : tolw = wdg.text == ""? tolh : tolw; break;
@ -1518,8 +1520,8 @@ function Panel_Preview() : PanelContent() constructor {
wdg.drawParam(params);
tolx += tolw + ui(8) + (nme != "") * ui(8);
tol_max_w += tolw + ui(8) + (nme != "") * ui(8);
tolx += tolw + ui(8);
tol_max_w += tolw + ui(8);
}
tol_max_w = max(0, tol_max_w - w);