2023-02-28 09:43:01 +01:00
|
|
|
function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
|
2022-01-13 05:24:03 +01:00
|
|
|
name = "Canvas";
|
2022-11-18 03:20:31 +01:00
|
|
|
color = COLORS.node_blend_canvas;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-21 12:40:20 +02:00
|
|
|
inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF )
|
2022-01-13 05:24:03 +01:00
|
|
|
.setDisplay(VALUE_DISPLAY.vector);
|
|
|
|
|
2023-07-18 17:51:40 +02:00
|
|
|
inputs[| 1] = nodeValue("Color", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, c_white );
|
2023-07-14 20:34:35 +02:00
|
|
|
inputs[| 2] = nodeValue("Brush size", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1 )
|
2023-10-02 08:57:44 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.slider, { range: [1, 32, 1] });
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
inputs[| 3] = nodeValue("Fill threshold", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0.)
|
2023-10-02 08:57:44 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.slider);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
inputs[| 4] = nodeValue("Fill type", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0)
|
2022-01-19 03:05:13 +01:00
|
|
|
.setDisplay(VALUE_DISPLAY.enum_scroll, ["4 connect", "8 connect", "Entire canvas"]);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
inputs[| 5] = nodeValue("Draw preview overlay", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
inputs[| 6] = nodeValue("Brush", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone)
|
2023-07-14 20:34:35 +02:00
|
|
|
.setVisible(true, false);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
inputs[| 7] = nodeValue("Surface amount", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
inputs[| 8] = nodeValue("Background", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, -1);
|
|
|
|
|
|
|
|
inputs[| 9] = nodeValue("Background alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1.)
|
2023-10-02 08:57:44 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.slider);
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-07-21 12:40:20 +02:00
|
|
|
inputs[| 10] = nodeValue("Render background", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true);
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-06-24 22:12:35 +02:00
|
|
|
inputs[| 11] = nodeValue("Alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1 )
|
2023-10-02 08:57:44 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.slider);
|
2023-06-24 22:12:35 +02:00
|
|
|
|
2023-10-04 11:28:13 +02:00
|
|
|
inputs[| 12] = nodeValue("Frames animation", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false );
|
|
|
|
|
|
|
|
inputs[| 13] = nodeValue("Animation speed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1 );
|
|
|
|
|
2023-10-30 14:21:34 +01:00
|
|
|
inputs[| 14] = nodeValue("Use background dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true );
|
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
inputs[| 15] = nodeValue("Brush distance", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ] )
|
|
|
|
.setDisplay(VALUE_DISPLAY.range, { linked : true });
|
|
|
|
|
|
|
|
inputs[| 16] = nodeValue("Rotate brush by direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false );
|
|
|
|
|
|
|
|
inputs[| 17] = nodeValue("Random direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0, 0, 0, 0 ] )
|
|
|
|
.setDisplay(VALUE_DISPLAY.rotation_random);
|
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
frame_renderer_x = 0;
|
|
|
|
frame_renderer_x_to = 0;
|
|
|
|
frame_renderer_x_max = 0;
|
|
|
|
|
|
|
|
frame_renderer_content = surface_create(1, 1);
|
|
|
|
frame_renderer = new Inspector_Custom_Renderer(function(_x, _y, _w, _m, _hover, _focus) { #region
|
|
|
|
var _h = 64;
|
|
|
|
_y += 8;
|
|
|
|
|
|
|
|
var _cnt_hover = false;
|
|
|
|
|
|
|
|
draw_sprite_stretched(THEME.button, 0, _x, _y, _w, _h);
|
|
|
|
|
|
|
|
if(_hover && frame_renderer.parent != noone && point_in_rectangle(_m[0], _m[1], _x, _y, _x + _w, _y + _h)) {
|
|
|
|
frame_renderer.parent.scroll_lock = true;
|
|
|
|
_cnt_hover = _hover;
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ww = _w - 4 - 40;
|
|
|
|
var _hh = _h - 4 - 4;
|
|
|
|
|
|
|
|
var _x0 = _x + 4;
|
|
|
|
var _y0 = _y + 4;
|
|
|
|
var _x1 = _x0 + _ww;
|
|
|
|
var _y1 = _y0 + _hh;
|
|
|
|
|
|
|
|
draw_sprite_stretched(THEME.ui_panel_bg, 1, _x0, _y0, _ww, _hh);
|
|
|
|
|
|
|
|
frame_renderer_x_max = 0;
|
|
|
|
frame_renderer_content = surface_verify(frame_renderer_content, _ww, _hh);
|
|
|
|
surface_set_shader(frame_renderer_content);
|
|
|
|
var _msx = _m[0] - _x0;
|
|
|
|
var _msy = _m[1] - _y0;
|
|
|
|
|
|
|
|
var _fr_h = _hh - 8;
|
|
|
|
var _fr_w = _fr_h;
|
|
|
|
|
|
|
|
var _fr_x = 8 - frame_renderer_x;
|
|
|
|
var _fr_y = 4;
|
|
|
|
|
2023-10-04 11:28:13 +02:00
|
|
|
var surfs = output_surface;
|
2023-10-04 09:49:31 +02:00
|
|
|
var _del = noone;
|
|
|
|
|
2023-10-04 11:28:13 +02:00
|
|
|
for( var i = 0, n = attributes.frames; i < n; i++ ) {
|
2023-10-04 09:49:31 +02:00
|
|
|
var _surf = surfs[i];
|
|
|
|
|
|
|
|
if(!is_surface(_surf)) continue;
|
|
|
|
|
|
|
|
var _sw = surface_get_width(_surf);
|
|
|
|
var _sh = surface_get_height(_surf);
|
|
|
|
|
|
|
|
var _ss = min(_fr_w / _sw, _fr_h / _sh);
|
|
|
|
var _sx = _fr_x;
|
|
|
|
var _sy = _fr_y + _fr_h / 2 - _sh * _ss / 2;
|
|
|
|
|
2023-10-04 11:28:13 +02:00
|
|
|
draw_surface_ext(_surf, _sx, _sy, _ss, _ss, 0, c_white, 0.75);
|
2023-10-04 09:49:31 +02:00
|
|
|
|
|
|
|
draw_set_color(i == preview_index? COLORS._main_accent : COLORS.panel_toolbar_outline);
|
|
|
|
draw_rectangle(_sx, _sy, _sx + _sw * _ss, _sy + _sh * _ss, true);
|
|
|
|
|
|
|
|
var _del_x = _sx + _sw * _ss - 8;
|
|
|
|
var _del_y = _sy + 8;
|
|
|
|
var _del_a = 0;
|
|
|
|
|
|
|
|
if(_hover) {
|
|
|
|
if(point_in_circle(_msx, _msy, _del_x, _del_y, 8)) {
|
|
|
|
_del_a = 1;
|
|
|
|
|
|
|
|
if(mouse_press(mb_left, _focus))
|
|
|
|
_del = i;
|
|
|
|
} else if(point_in_rectangle(_msx, _msy, _sx, _sy, _sx + _sw * _ss, _sy + _sh * _ss)) {
|
|
|
|
if(mouse_press(mb_left, _focus)) preview_index = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
draw_sprite(THEME.close_16, _del_a, _del_x, _del_y);
|
|
|
|
|
|
|
|
_fr_x += _sw * _ss + 8;
|
|
|
|
frame_renderer_x_max += _sw * _ss + 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(_del > noone) removeFrame(_del);
|
|
|
|
surface_reset_shader();
|
|
|
|
draw_surface(frame_renderer_content, _x0, _y0);
|
|
|
|
|
|
|
|
frame_renderer_x_max = max(0, frame_renderer_x_max - 200);
|
|
|
|
frame_renderer_x = lerp_float(frame_renderer_x, frame_renderer_x_to, 3);
|
|
|
|
|
|
|
|
if(_cnt_hover) {
|
|
|
|
if(mouse_wheel_down()) frame_renderer_x_to = clamp(frame_renderer_x_to + 80, 0, frame_renderer_x_max);
|
|
|
|
if(mouse_wheel_up()) frame_renderer_x_to = clamp(frame_renderer_x_to - 80, 0, frame_renderer_x_max);
|
|
|
|
}
|
|
|
|
|
|
|
|
var _bs = 32;
|
|
|
|
var _bx = _x1 + ui(20) - _bs / 2;
|
|
|
|
var _by = _y + _h / 2 - _bs / 2;
|
|
|
|
|
|
|
|
if(buttonInstant(THEME.button_hide, _bx, _by, _bs, _bs, _m, _focus, _hover,, THEME.add,, COLORS._main_value_positive) == 2) {
|
|
|
|
attributes.frames++;
|
|
|
|
refreshFrames();
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 8 + _h;
|
|
|
|
}); #endregion
|
|
|
|
|
2022-01-13 05:24:03 +01:00
|
|
|
input_display_list = [
|
2024-01-16 14:08:57 +01:00
|
|
|
["Output", false], 0, frame_renderer, 12, 13,
|
|
|
|
["Brush", true], 6, 15, 17, 16,
|
2024-01-08 08:10:50 +01:00
|
|
|
["Background", true, 10], 8, 14, 9,
|
2022-01-13 05:24:03 +01:00
|
|
|
];
|
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
#region ++++ data ++++
|
|
|
|
attributes.frames = 1;
|
|
|
|
attribute_surface_depth();
|
2023-03-19 09:17:39 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
attributes.dimension = [ 1, 1 ];
|
2023-10-30 14:21:34 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
output_surface = [ surface_create_empty(1, 1) ];
|
|
|
|
canvas_surface = [ surface_create_empty(1, 1) ];
|
|
|
|
canvas_buffer = [ buffer_create(1 * 1 * 4, buffer_fixed, 2) ];
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
drawing_surface = surface_create_empty(1, 1);
|
|
|
|
_drawing_surface = surface_create_empty(1, 1);
|
|
|
|
surface_w = 1;
|
|
|
|
surface_h = 1;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
prev_surface = surface_create_empty(1, 1);
|
|
|
|
preview_draw_surface = surface_create_empty(1, 1);
|
|
|
|
_preview_draw_surface = surface_create_empty(1, 1);
|
2023-07-14 20:34:35 +02:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
is_selecting = false;
|
|
|
|
is_selected = false;
|
|
|
|
is_select_drag = false;
|
|
|
|
selection_surface = surface_create_empty(1, 1);
|
|
|
|
selection_mask = surface_create_empty(1, 1);
|
|
|
|
selection_position = [ 0, 0 ];
|
|
|
|
selection_sx = 0;
|
|
|
|
selection_sy = 0;
|
|
|
|
selection_mx = 0;
|
|
|
|
selection_my = 0;
|
2023-07-15 20:01:29 +02:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
mouse_cur_x = 0;
|
|
|
|
mouse_cur_y = 0;
|
|
|
|
mouse_pre_x = 0;
|
|
|
|
mouse_pre_y = 0;
|
2023-11-06 13:19:59 +01:00
|
|
|
mouse_pre_draw_x = undefined;
|
|
|
|
mouse_pre_draw_y = undefined;
|
|
|
|
mouse_pre_dir_x = undefined;
|
|
|
|
mouse_pre_dir_y = undefined;
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
mouse_holding = false;
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_sizing = false;
|
|
|
|
brush_sizing_s = 0;
|
|
|
|
brush_sizing_mx = 0;
|
|
|
|
brush_sizing_my = 0;
|
|
|
|
brush_sizing_dx = 0;
|
|
|
|
brush_sizing_dy = 0;
|
|
|
|
|
|
|
|
brush_surface = noone;
|
|
|
|
brush_size = 1;
|
|
|
|
brush_dist_min = 1;
|
|
|
|
brush_dist_max = 1;
|
|
|
|
brush_direction = 0;
|
|
|
|
brush_rand_dir = [ 0, 0, 0, 0, 0 ];
|
|
|
|
brush_seed = irandom_range(100000, 999999);
|
|
|
|
brush_next_dist = 0;
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2024-03-02 10:08:44 +01:00
|
|
|
draw_stack = ds_list_create();
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region ++++ tools ++++
|
2024-01-16 09:56:20 +01:00
|
|
|
tool_attribute.color = cola(c_white);
|
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
tool_attribute.channel = [ true, true, true, true ];
|
2024-01-16 09:56:20 +01:00
|
|
|
tool_channel_edit = new checkBoxGroup(THEME.tools_canvas_channel, function(ind, val) { tool_attribute.channel[ind] = val; });
|
|
|
|
tool_settings = [ [ "Channel", tool_channel_edit, "channel", tool_attribute ] ];
|
|
|
|
|
|
|
|
tool_attribute.size = 1;
|
2024-03-02 10:08:44 +01:00
|
|
|
tool_size_edit = new textBox(TEXTBOX_INPUT.number, function(val) { tool_attribute.size = max(1, round(val)); }).setSlidable(0.1, true, [ 1, 999999 ])
|
|
|
|
.setFont(f_p3)
|
|
|
|
.setSideButton(button(function() { dialogPanelCall(new Panel_Node_Canvas_Pressure(self), mouse_mx, mouse_my, { anchor: ANCHOR.top | ANCHOR.left }) })
|
|
|
|
.setIcon(THEME.pen_pressure, 0, COLORS._main_icon));
|
2024-01-16 09:56:20 +01:00
|
|
|
tool_size = [ "Size", tool_size_edit, "size", tool_attribute ];
|
|
|
|
|
2024-03-02 10:08:44 +01:00
|
|
|
tool_attribute.pressure = false;
|
|
|
|
tool_attribute.pressure_size = [ 1, 1 ];
|
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
tool_attribute.thres = 0;
|
2024-03-02 10:08:44 +01:00
|
|
|
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);
|
2024-01-16 09:56:20 +01:00
|
|
|
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 ];
|
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
tools = [
|
|
|
|
new NodeTool( "Selection", [ THEME.canvas_tools_selection_rectangle, THEME.canvas_tools_selection_circle ]),
|
2024-01-16 09:56:20 +01:00
|
|
|
|
|
|
|
new NodeTool( "Pencil", THEME.canvas_tools_pencil)
|
|
|
|
.setSetting(tool_size),
|
|
|
|
|
|
|
|
new NodeTool( "Eraser", THEME.canvas_tools_eraser)
|
|
|
|
.setSetting(tool_size),
|
|
|
|
|
|
|
|
new NodeTool( "Rectangle", [ THEME.canvas_tools_rect, THEME.canvas_tools_rect_fill ])
|
|
|
|
.setSetting(tool_size),
|
|
|
|
|
|
|
|
new NodeTool( "Ellipse", [ THEME.canvas_tools_ellip, THEME.canvas_tools_ellip_fill ])
|
|
|
|
.setSetting(tool_size),
|
|
|
|
|
|
|
|
new NodeTool( "Fill", THEME.canvas_tools_bucket)
|
|
|
|
.setSetting(tool_thrs)
|
|
|
|
.setSetting(tool_fil8),
|
2023-11-01 14:13:23 +01:00
|
|
|
];
|
|
|
|
#endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
function setToolColor(color) { tool_attribute.color = color; }
|
|
|
|
|
|
|
|
static drawTools = function(_mx, _my, xx, yy, tool_size, hover, focus) { #region
|
|
|
|
var _sx0 = xx - tool_size / 2;
|
|
|
|
var _sx1 = xx + tool_size / 2;
|
|
|
|
var hh = ui(8);
|
|
|
|
|
|
|
|
yy += ui(4);
|
|
|
|
draw_set_color(COLORS._main_icon_dark);
|
|
|
|
draw_line_round(_sx0 + ui(8), yy, _sx1 - ui(8), yy, 2);
|
|
|
|
yy += ui(4);
|
|
|
|
|
|
|
|
var _cx = _sx0 + ui(8);
|
|
|
|
var _cw = tool_size - ui(16);
|
|
|
|
var _ch = ui(12);
|
|
|
|
var _pd = ui(5);
|
|
|
|
|
|
|
|
yy += ui(8);
|
|
|
|
hh += ui(8);
|
|
|
|
drawColor(tool_attribute.color, _cx, yy, _cw, _cw);
|
|
|
|
draw_sprite_stretched_ext(THEME.palette_selecting, 0, _cx - _pd, yy - _pd, _cw + _pd * 2, _cw + _pd * 2, c_white, 1);
|
|
|
|
|
2024-01-28 09:53:41 +01:00
|
|
|
if(point_in_rectangle(_mx, _my, _cx, yy, _cx + _cw, yy + _ch) && mouse_press(mb_left, focus))
|
|
|
|
colorSelectorCall(tool_attribute.color, setToolColor);
|
2024-01-16 09:56:20 +01:00
|
|
|
|
|
|
|
yy += _cw + ui(8);
|
|
|
|
hh += _cw + ui(8);
|
|
|
|
|
2024-01-16 11:00:39 +01:00
|
|
|
var _sel = noone;
|
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
for( var i = 0, n = array_length(DEF_PALETTE); i < n; i++ ) {
|
|
|
|
var _c = DEF_PALETTE[i];
|
|
|
|
|
|
|
|
var ii = 0;
|
|
|
|
if(i == 0) ii = 4;
|
|
|
|
if(i == n - 1) ii = 5;
|
|
|
|
|
|
|
|
draw_sprite_stretched_ext(THEME.palette_mask, ii, _cx, yy, _cw, _ch, _c, 1);
|
|
|
|
|
2024-01-16 11:00:39 +01:00
|
|
|
if(_c == tool_attribute.color)
|
|
|
|
_sel = [ _cx, yy ];
|
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
if(hover && point_in_rectangle(_mx, _my, _cx, yy, _cx + _cw, yy + _ch)) {
|
|
|
|
if(mouse_click(mb_left, focus))
|
|
|
|
tool_attribute.color = _c;
|
|
|
|
}
|
|
|
|
|
|
|
|
yy += _ch;
|
|
|
|
hh += _ch;
|
|
|
|
}
|
|
|
|
|
2024-01-16 11:00:39 +01:00
|
|
|
if(_sel != noone)
|
|
|
|
draw_sprite_stretched_ext(THEME.palette_selecting, 0, _sel[0] - _pd, _sel[1] - _pd, _cw + _pd * 2, _ch + _pd * 2, c_white, 1);
|
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
return hh + ui(4);
|
|
|
|
} #endregion
|
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
function removeFrame(index = 0) { #region
|
|
|
|
if(attributes.frames <= 1) return;
|
|
|
|
|
2023-10-18 14:58:55 +02:00
|
|
|
if(preview_index == attributes.frames)
|
|
|
|
preview_index--;
|
2023-10-04 09:49:31 +02:00
|
|
|
attributes.frames--;
|
|
|
|
|
|
|
|
array_delete(canvas_surface, index, 1);
|
|
|
|
array_delete(canvas_buffer, index, 1);
|
|
|
|
update();
|
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function refreshFrames() { #region
|
|
|
|
var fr = attributes.frames;
|
|
|
|
|
|
|
|
if(array_length(canvas_surface) < fr) {
|
|
|
|
for( var i = array_length(canvas_surface); i < fr; i++ ) {
|
|
|
|
canvas_surface[i] = surface_create_empty(1, 1);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
array_resize(canvas_surface, fr);
|
|
|
|
|
|
|
|
if(array_length(canvas_buffer) < fr) {
|
|
|
|
for( var i = array_length(canvas_buffer); i < fr; i++ ) {
|
|
|
|
canvas_buffer[i] = buffer_create(1 * 1 * 4, buffer_fixed, 2);
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
array_resize(canvas_buffer, fr);
|
|
|
|
} #endregion
|
|
|
|
|
2024-02-25 11:02:10 +01:00
|
|
|
function getCanvasSurface(index = preview_index) { INLINE return array_safe_get(canvas_surface, index); }
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2024-02-25 11:02:10 +01:00
|
|
|
function setCanvasSurface(surface, index = preview_index) { INLINE canvas_surface[index] = surface; }
|
2023-10-04 09:49:31 +02:00
|
|
|
|
|
|
|
function storeAction() { #region
|
2023-08-16 20:16:31 +02:00
|
|
|
var action = recordAction(ACTION_TYPE.custom, function(data) {
|
|
|
|
is_selected = false;
|
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
var _canvas = surface_clone(getCanvasSurface(data.index));
|
2023-08-16 20:16:31 +02:00
|
|
|
|
|
|
|
if(is_surface(data.surface))
|
2023-10-04 09:49:31 +02:00
|
|
|
setCanvasSurface(surface_clone(data.surface), data.index);
|
|
|
|
surface_store_buffer(data.index);
|
2023-08-16 20:16:31 +02:00
|
|
|
surface_free(data.surface);
|
|
|
|
|
2023-12-18 04:40:21 +01:00
|
|
|
data.surface = _canvas;
|
|
|
|
data.index = preview_index;
|
2023-10-04 09:49:31 +02:00
|
|
|
}, { surface: surface_clone(getCanvasSurface()), tooltip: "Modify canvas", index: preview_index });
|
2023-06-24 22:12:35 +02:00
|
|
|
|
2023-08-16 20:16:31 +02:00
|
|
|
action.clear_action = function(data) { surface_free_safe(data.surface); };
|
2023-10-04 09:49:31 +02:00
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function apply_surfaces() { #region
|
|
|
|
for( var i = 0; i < attributes.frames; i++ )
|
|
|
|
apply_surface(i);
|
|
|
|
} #endregion
|
2023-08-16 20:16:31 +02:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
function apply_surface(index = preview_index) { #region
|
2023-10-30 14:21:34 +01:00
|
|
|
var _dim = attributes.dimension;
|
2023-08-16 20:16:31 +02:00
|
|
|
var cDep = attrDepth();
|
2023-03-13 10:45:56 +01:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
var _canvas_surface = getCanvasSurface(index);
|
2024-03-02 10:08:44 +01:00
|
|
|
//print($"Applying surface {index} - {_canvas_surface} [{is_surface(_canvas_surface)}]");
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2024-02-25 11:02:10 +01:00
|
|
|
if(!is_surface(_canvas_surface)) { // recover surface
|
|
|
|
//print($"recovering surface from buffer {random(1)}");
|
|
|
|
|
|
|
|
setCanvasSurface(surface_create_from_buffer(_dim[0], _dim[1], canvas_buffer[index]), index);
|
|
|
|
} else if(surface_get_width_safe(_canvas_surface) != _dim[0] || surface_get_height_safe(_canvas_surface) != _dim[1]) { // resize surface
|
2024-01-20 05:06:56 +01:00
|
|
|
var _cbuff = array_safe_get(canvas_buffer, index);
|
|
|
|
if(buffer_exists(_cbuff)) buffer_delete(_cbuff);
|
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
canvas_buffer[index] = buffer_create(_dim[0] * _dim[1] * 4, buffer_fixed, 4);
|
|
|
|
setCanvasSurface(surface_size_to(_canvas_surface, _dim[0], _dim[1]), index);
|
2023-08-16 20:16:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
drawing_surface = surface_verify(drawing_surface, _dim[0], _dim[1], cDep);
|
|
|
|
surface_clear(drawing_surface);
|
2023-10-04 09:49:31 +02:00
|
|
|
} #endregion
|
|
|
|
|
|
|
|
function surface_store_buffers(index = preview_index) { #region
|
|
|
|
for( var i = 0; i < attributes.frames; i++ )
|
|
|
|
surface_store_buffer(i);
|
|
|
|
} #endregion
|
2023-03-11 01:40:17 +01:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
function surface_store_buffer(index = preview_index) { #region
|
2023-10-18 14:58:55 +02:00
|
|
|
if(index >= attributes.frames) return;
|
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
buffer_delete(canvas_buffer[index]);
|
2023-07-14 20:34:35 +02:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
var _canvas_surface = getCanvasSurface(index);
|
|
|
|
|
|
|
|
surface_w = surface_get_width_safe(_canvas_surface);
|
|
|
|
surface_h = surface_get_height_safe(_canvas_surface);
|
|
|
|
canvas_buffer[index] = buffer_create(surface_w * surface_h * 4, buffer_fixed, 4);
|
|
|
|
buffer_get_surface(canvas_buffer[index], _canvas_surface, 0);
|
2023-07-14 20:34:35 +02:00
|
|
|
|
|
|
|
triggerRender();
|
2023-10-04 09:49:31 +02:00
|
|
|
apply_surface(index);
|
|
|
|
} #endregion
|
2023-07-14 20:34:35 +02:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
function apply_draw_surface() { #region
|
2024-01-16 09:56:20 +01:00
|
|
|
var _alp = _color_get_alpha(tool_attribute.color);
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-08-16 20:16:31 +02:00
|
|
|
storeAction();
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
surface_set_target(getCanvasSurface());
|
2023-11-01 14:13:23 +01:00
|
|
|
BLEND_ALPHA
|
|
|
|
if(isUsingTool("Eraser")) {
|
|
|
|
gpu_set_blendmode(bm_subtract);
|
|
|
|
if(tool_attribute.channel[3])
|
|
|
|
gpu_set_colorwriteenable(false, false, false, true);
|
|
|
|
}
|
2023-08-16 20:16:31 +02:00
|
|
|
draw_surface_ext_safe(drawing_surface, 0, 0, 1, 1, 0, c_white, _alp);
|
2023-11-01 14:13:23 +01:00
|
|
|
|
|
|
|
gpu_set_colorwriteenable(tool_attribute.channel[0], tool_attribute.channel[1], tool_attribute.channel[2], tool_attribute.channel[3]);
|
2023-08-16 20:16:31 +02:00
|
|
|
surface_reset_target();
|
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_clear(drawing_surface);
|
2023-08-16 20:16:31 +02:00
|
|
|
BLEND_NORMAL;
|
|
|
|
|
|
|
|
surface_store_buffer();
|
2023-10-04 09:49:31 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
function draw_point_size(_x, _y, _draw = false) { #region
|
|
|
|
if(brush_surface == noone) {
|
|
|
|
if(brush_size <= 1)
|
2022-01-13 05:24:03 +01:00
|
|
|
draw_point(_x, _y);
|
2023-11-01 14:13:23 +01:00
|
|
|
else if(brush_size == 2) {
|
2022-01-13 05:24:03 +01:00
|
|
|
draw_point(_x, _y);
|
|
|
|
draw_point(_x + 1, _y);
|
|
|
|
draw_point(_x, _y + 1);
|
|
|
|
draw_point(_x + 1, _y + 1);
|
2023-11-01 14:13:23 +01:00
|
|
|
} else if(brush_size == 3) {
|
2022-01-13 05:24:03 +01:00
|
|
|
draw_point(_x, _y);
|
|
|
|
draw_point(_x - 1, _y);
|
|
|
|
draw_point(_x, _y - 1);
|
|
|
|
draw_point(_x + 1, _y);
|
|
|
|
draw_point(_x, _y + 1);
|
|
|
|
} else
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_circle_prec(_x, _y, brush_size / 2, 0);
|
2022-09-21 06:09:40 +02:00
|
|
|
} else {
|
2023-11-01 14:13:23 +01:00
|
|
|
var _sw = surface_get_width_safe(brush_surface);
|
|
|
|
var _sh = surface_get_height_safe(brush_surface);
|
|
|
|
var _r = brush_direction + angle_random_eval(brush_rand_dir, brush_seed);
|
|
|
|
var _p = point_rotate(-_sw / 2, -_sh / 2, 0, 0, _r);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_surface_ext_safe(brush_surface, _x + _p[0], _y + _p[1], 1, 1, _r, draw_get_color(), draw_get_alpha());
|
|
|
|
|
|
|
|
if(_draw) brush_seed = irandom_range(100000, 999999);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
2023-07-14 20:34:35 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
function draw_line_size(_x0, _y0, _x1, _y1, _draw = false) { #region
|
2023-10-11 05:17:49 +02:00
|
|
|
|
2024-01-20 05:06:56 +01:00
|
|
|
if(brush_size == 1 && brush_surface == noone) {
|
|
|
|
if(_x1 > _x0) _x0--;
|
|
|
|
if(_y1 > _y0) _y0--;
|
|
|
|
if(_y1 < _y0) _y1--;
|
|
|
|
if(_x1 < _x0) _x1--;
|
|
|
|
|
2022-01-13 05:24:03 +01:00
|
|
|
draw_line(_x0, _y0, _x1, _y1);
|
2024-01-20 05:06:56 +01:00
|
|
|
} else {
|
2023-07-14 20:34:35 +02:00
|
|
|
var diss = point_distance(_x0, _y0, _x1, _y1);
|
2022-01-13 05:24:03 +01:00
|
|
|
var dirr = point_direction(_x0, _y0, _x1, _y1);
|
|
|
|
var st_x = lengthdir_x(1, dirr);
|
|
|
|
var st_y = lengthdir_y(1, dirr);
|
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
var _i = _draw? brush_next_dist : 0;
|
|
|
|
var _dst = diss;
|
|
|
|
|
|
|
|
if(_i < diss) {
|
|
|
|
while(_i < diss) {
|
|
|
|
var _px = _x0 + st_x * _i;
|
|
|
|
var _py = _y0 + st_y * _i;
|
2024-01-20 05:06:56 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(_px, _py, _draw);
|
2024-01-20 05:06:56 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_next_dist = random_range(brush_dist_min, brush_dist_max);
|
|
|
|
_i += brush_next_dist;
|
|
|
|
_dst -= brush_next_dist;
|
|
|
|
}
|
2023-07-14 20:34:35 +02:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_next_dist -= _dst;
|
|
|
|
} else
|
|
|
|
brush_next_dist -= diss;
|
|
|
|
|
|
|
|
if(brush_dist_min == brush_dist_max && brush_dist_min == 1)
|
|
|
|
draw_point_size(_x1, _y1, _draw);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
2023-07-14 20:34:35 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
function draw_rect_size(_x0, _y0, _x1, _y1, _fill) { #region
|
2022-01-13 05:24:03 +01:00
|
|
|
if(_x0 == _x1 && _y0 == _y1) {
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(_x0, _y0);
|
2022-01-13 05:24:03 +01:00
|
|
|
return;
|
|
|
|
} else if(_x0 == _x1) {
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(_x0, _y0);
|
|
|
|
draw_point_size(_x1, _y1);
|
|
|
|
draw_line_size(_x0, _y0, _x0, _y1);
|
2022-01-13 05:24:03 +01:00
|
|
|
return;
|
|
|
|
} else if(_y0 == _y1) {
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(_x0, _y0);
|
|
|
|
draw_point_size(_x1, _y1);
|
|
|
|
draw_line_size(_x0, _y0, _x1, _y0);
|
2022-01-13 05:24:03 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var _min_x = min(_x0, _x1);
|
|
|
|
var _max_x = max(_x0, _x1);
|
|
|
|
var _min_y = min(_y0, _y1);
|
|
|
|
var _may_y = max(_y0, _y1);
|
|
|
|
|
|
|
|
if(_fill) {
|
|
|
|
draw_rectangle(_min_x, _min_y, _max_x, _may_y, 0);
|
2023-11-01 14:13:23 +01:00
|
|
|
} else if(brush_size == 1 && brush_surface == noone)
|
2022-01-13 05:24:03 +01:00
|
|
|
draw_rectangle(_min_x + 1, _min_y + 1, _max_x - 1, _may_y - 1, 1);
|
|
|
|
else {
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_line_size(_min_x, _min_y, _max_x, _min_y);
|
|
|
|
draw_line_size(_min_x, _min_y, _min_x, _may_y);
|
|
|
|
draw_line_size(_max_x, _may_y, _max_x, _min_y);
|
|
|
|
draw_line_size(_max_x, _may_y, _min_x, _may_y);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
2023-07-14 20:34:35 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
function draw_ellp_size(_x0, _y0, _x1, _y1, _fill) { #region
|
2022-01-13 05:24:03 +01:00
|
|
|
if(_x0 == _x1 && _y0 == _y1) {
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(_x0, _y0);
|
2022-01-13 05:24:03 +01:00
|
|
|
return;
|
|
|
|
} else if(_x0 == _x1) {
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(_x0, _y0);
|
|
|
|
draw_point_size(_x1, _y1);
|
|
|
|
draw_line_size(_x0, _y0, _x0, _y1);
|
2022-01-13 05:24:03 +01:00
|
|
|
return;
|
|
|
|
} else if(_y0 == _y1) {
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(_x0, _y0);
|
|
|
|
draw_point_size(_x1, _y1);
|
|
|
|
draw_line_size(_x0, _y0, _x1, _y0);
|
2022-01-13 05:24:03 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-08-30 07:36:37 +02:00
|
|
|
var _min_x = min(_x0, _x1) - 1;
|
2022-01-13 05:24:03 +01:00
|
|
|
var _max_x = max(_x0, _x1);
|
2022-08-30 07:36:37 +02:00
|
|
|
var _min_y = min(_y0, _y1) - 1;
|
|
|
|
var _max_y = max(_y0, _y1);
|
|
|
|
|
2022-01-13 05:24:03 +01:00
|
|
|
if(_fill) {
|
2022-08-30 07:36:37 +02:00
|
|
|
draw_ellipse(_min_x, _min_y, _max_x, _max_y, 0);
|
|
|
|
} else {
|
2022-01-13 05:24:03 +01:00
|
|
|
var samp = 64;
|
2022-09-21 06:09:40 +02:00
|
|
|
var cx = (_min_x + _max_x) / 2;
|
|
|
|
var cy = (_min_y + _max_y) / 2;
|
2022-01-13 05:24:03 +01:00
|
|
|
var rx = abs(_x0 - _x1) / 2;
|
|
|
|
var ry = abs(_y0 - _y1) / 2;
|
|
|
|
|
|
|
|
var ox, oy, nx, ny;
|
|
|
|
for( var i = 0; i <= samp; i++ ) {
|
|
|
|
nx = cx + lengthdir_x(rx, 360 / samp * i);
|
|
|
|
ny = cy + lengthdir_y(ry, 360 / samp * i);
|
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
if(i) draw_line_size(ox, oy, nx, ny);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
ox = nx;
|
|
|
|
oy = ny;
|
|
|
|
}
|
|
|
|
}
|
2023-07-14 20:34:35 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
function get_color_buffer(_x, _y) { #region
|
2023-10-04 09:49:31 +02:00
|
|
|
var _cbuffer = canvas_buffer[preview_index];
|
2023-02-14 05:32:32 +01:00
|
|
|
var pos = (surface_w * _y + _x) * 4;
|
2023-10-04 09:49:31 +02:00
|
|
|
if(pos >= buffer_get_size(_cbuffer)) {
|
|
|
|
print("Error buffer overflow " + string(pos) + "/" + string(buffer_get_size(_cbuffer)));
|
2023-02-14 05:32:32 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
buffer_seek(_cbuffer, buffer_seek_start, pos);
|
|
|
|
var c = buffer_read(_cbuffer, buffer_u32);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
return c;
|
2023-07-14 20:34:35 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
function ff_fillable(colorBase, colorFill, _x, _y, _thres) { #region
|
2023-10-11 05:17:49 +02:00
|
|
|
var d = color_diff(colorBase, get_color_buffer(_x, _y), true, true);
|
2023-02-14 05:32:32 +01:00
|
|
|
return d <= _thres && d != colorFill;
|
2023-07-14 20:34:35 +02:00
|
|
|
} #endregion
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
function flood_fill_scanline(_x, _y, _surf, _thres, _corner = false) { #region
|
2023-02-14 05:32:32 +01:00
|
|
|
var colorFill = draw_get_color() + (255 << 24);
|
|
|
|
var colorBase = get_color_buffer(_x, _y);
|
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
if(colorFill == colorBase) return; //Clicking on the same color as the fill color
|
|
|
|
|
|
|
|
var _alp = _color_get_alpha(tool_attribute.color);
|
|
|
|
draw_set_alpha(_alp);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
|
|
|
var x1, y1, x_start;
|
|
|
|
var spanAbove, spanBelow;
|
2023-03-02 07:59:14 +01:00
|
|
|
var thr = _thres * _thres;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
var queue = ds_queue_create();
|
|
|
|
ds_queue_enqueue(queue, [_x, _y]);
|
|
|
|
|
|
|
|
while(!ds_queue_empty(queue)) {
|
|
|
|
var pos = ds_queue_dequeue(queue);
|
2022-01-13 05:24:03 +01:00
|
|
|
x1 = pos[0];
|
|
|
|
y1 = pos[1];
|
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
var colorCurr = get_color_buffer(x1, y1);
|
2024-01-16 09:56:20 +01:00
|
|
|
//print($"Searching {x1}, {y1}: {colorCurr}");
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
if(colorCurr == colorFill) continue; //Color in queue is already filled
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
while(x1 > 0 && ff_fillable(colorBase, colorFill, x1 - 1, y1, thr)) //Move to the leftmost connected pixel in the same row.
|
2022-01-13 05:24:03 +01:00
|
|
|
x1--;
|
|
|
|
x_start = x1;
|
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
spanAbove = false;
|
|
|
|
spanBelow = false;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
while(x1 < surface_w && ff_fillable(colorBase, colorFill, x1, y1, thr)) {
|
2022-01-13 05:24:03 +01:00
|
|
|
draw_point(x1, y1);
|
2023-03-11 01:40:17 +01:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
var _cbuffer = canvas_buffer[preview_index];
|
|
|
|
buffer_seek(_cbuffer, buffer_seek_start, (surface_w * y1 + x1) * 4);
|
|
|
|
buffer_write(_cbuffer, buffer_u32, colorFill);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
//print($"> Filling {x1}, {y1}: {get_color_buffer(x1, y1)}");
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2022-01-13 05:24:03 +01:00
|
|
|
if(y1 > 0) {
|
2024-01-16 09:56:20 +01:00
|
|
|
if(_corner && x1 > 0 && ff_fillable(colorBase, colorFill, x1 - 1, y1 - 1, thr)) //Check top left pixel
|
|
|
|
ds_queue_enqueue(queue, [x1 - 1, y1 - 1]);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
if(ff_fillable(colorBase, colorFill, x1, y1 - 1, thr)) //Check top pixel
|
2023-02-14 05:32:32 +01:00
|
|
|
ds_queue_enqueue(queue, [x1, y1 - 1]);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
if(y1 < surface_h - 1) {
|
2024-01-16 09:56:20 +01:00
|
|
|
if(_corner && x1 > 0 && ff_fillable(colorBase, colorFill, x1 - 1, y1 + 1, thr)) //Check bottom left pixel
|
|
|
|
ds_queue_enqueue(queue, [x1 - 1, y1 + 1]);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
if(ff_fillable(colorBase, colorFill, x1, y1 + 1, thr)) //Check bottom pixel
|
2023-02-14 05:32:32 +01:00
|
|
|
ds_queue_enqueue(queue, [x1, y1 + 1]);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
2024-01-16 09:56:20 +01:00
|
|
|
if(_corner && x1 < surface_w - 1) {
|
|
|
|
if(y1 > 0 && 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 && ff_fillable(colorBase, colorFill, x1 + 1, y1 + 1, thr)) //Check bottom right pixel
|
2023-02-14 05:32:32 +01:00
|
|
|
ds_queue_enqueue(queue, [x1 + 1, y1 + 1]);
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
2024-01-16 09:56:20 +01:00
|
|
|
|
|
|
|
x1++;
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
2024-01-16 09:56:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
draw_set_alpha(1);
|
2023-07-14 20:34:35 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
function canvas_fill(_x, _y, _surf, _thres) { #region
|
2024-01-16 09:56:20 +01:00
|
|
|
var _alp = _color_get_alpha(tool_attribute.color);
|
2023-06-24 22:12:35 +02:00
|
|
|
|
2023-09-08 21:37:36 +02:00
|
|
|
var w = surface_get_width_safe(_surf);
|
|
|
|
var h = surface_get_height_safe(_surf);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
var _c1 = get_color_buffer(_x, _y);
|
2023-03-02 07:59:14 +01:00
|
|
|
var thr = _thres * _thres;
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-06-24 22:12:35 +02:00
|
|
|
draw_set_alpha(_alp);
|
2022-01-13 05:24:03 +01:00
|
|
|
for( var i = 0; i < w; i++ ) {
|
|
|
|
for( var j = 0; j < h; j++ ) {
|
|
|
|
if(i == _x && j == _y) {
|
|
|
|
draw_point(i, j);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
var _c2 = get_color_buffer(i, j);
|
2023-03-02 07:59:14 +01:00
|
|
|
if(color_diff(_c1, _c2, true) <= thr)
|
2022-01-13 05:24:03 +01:00
|
|
|
draw_point(i, j);
|
|
|
|
}
|
2023-03-11 01:40:17 +01:00
|
|
|
}
|
|
|
|
draw_set_alpha(1);
|
2023-07-14 20:34:35 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-10-04 07:21:45 +02:00
|
|
|
static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
|
2024-01-16 11:00:39 +01:00
|
|
|
if(instance_exists(o_dialog_color_picker)) return;
|
2023-12-05 04:28:49 +01:00
|
|
|
|
2023-03-02 07:59:14 +01:00
|
|
|
mouse_cur_x = round((_mx - _x) / _s - 0.5);
|
|
|
|
mouse_cur_y = round((_my - _y) / _s - 0.5);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-10-30 14:21:34 +01:00
|
|
|
var _dim = attributes.dimension;
|
2024-01-16 09:56:20 +01:00
|
|
|
var _col = tool_attribute.color;
|
|
|
|
var _siz = tool_attribute.size;
|
|
|
|
var _thr = tool_attribute.thres;
|
|
|
|
var _fill_type = tool_attribute.fill8;
|
|
|
|
|
2023-10-02 08:57:44 +02:00
|
|
|
var _prev = getInputData(5);
|
2023-11-01 14:13:23 +01:00
|
|
|
var _brushSurf = getInputData(6);
|
|
|
|
var _brushDist = getInputData(15);
|
|
|
|
var _brushRotD = getInputData(16);
|
|
|
|
var _brushRotR = getInputData(17);
|
|
|
|
|
2024-03-02 10:08:44 +01:00
|
|
|
if(PEN_USE && tool_attribute.pressure)
|
|
|
|
brush_size = round(lerp(tool_attribute.pressure_size[0], tool_attribute.pressure_size[1], power(PEN_PRESSURE / 1024, 2)));
|
|
|
|
else
|
|
|
|
brush_size = _siz;
|
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_dist_min = max(1, _brushDist[0]);
|
|
|
|
brush_dist_max = max(1, _brushDist[1]);
|
|
|
|
brush_surface = is_surface(_brushSurf)? _brushSurf : noone;
|
|
|
|
if(!_brushRotD)
|
|
|
|
brush_direction = 0;
|
2023-11-06 13:19:59 +01:00
|
|
|
else if(mouse_pre_dir_x == undefined) {
|
|
|
|
mouse_pre_dir_x = _mx;
|
|
|
|
mouse_pre_dir_y = _my;
|
|
|
|
} else if(point_distance(mouse_pre_dir_x, mouse_pre_dir_y, _mx, _my) > _s) {
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_direction = point_direction(mouse_pre_dir_x, mouse_pre_dir_y, _mx, _my);
|
|
|
|
mouse_pre_dir_x = _mx;
|
|
|
|
mouse_pre_dir_y = _my;
|
|
|
|
}
|
2023-11-06 13:19:59 +01:00
|
|
|
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_rand_dir = _brushRotR;
|
2024-01-16 11:00:39 +01:00
|
|
|
|
|
|
|
#region color selector
|
|
|
|
if(active && key_mod_press(ALT)) {
|
|
|
|
var dialog = instance_create(0, 0, o_dialog_color_picker);
|
|
|
|
dialog.onApply = setToolColor;
|
|
|
|
dialog.def_c = _col;
|
|
|
|
}
|
|
|
|
#endregion
|
2023-08-16 20:16:31 +02:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
var _canvas_surface = getCanvasSurface();
|
|
|
|
|
2024-02-25 11:02:10 +01:00
|
|
|
if(!surface_exists(_canvas_surface)) return;
|
2023-10-04 09:49:31 +02:00
|
|
|
|
|
|
|
var _surf_w = surface_get_width_safe(_canvas_surface);
|
|
|
|
var _surf_h = surface_get_height_safe(_canvas_surface);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-08-16 20:16:31 +02:00
|
|
|
#region drawing surface review
|
|
|
|
_drawing_surface = surface_verify(_drawing_surface, _surf_w, _surf_h);
|
|
|
|
surface_set_target(_drawing_surface);
|
|
|
|
DRAW_CLEAR
|
|
|
|
draw_surface_safe(drawing_surface);
|
|
|
|
surface_reset_target();
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
if(!isUsingTool("Selection") && is_surface(selection_surface)) { #region
|
2023-07-15 20:01:29 +02:00
|
|
|
var pos_x = selection_position[0];
|
|
|
|
var pos_y = selection_position[1];
|
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
surface_set_target(_canvas_surface);
|
2023-07-15 20:01:29 +02:00
|
|
|
BLEND_ALPHA
|
2023-09-08 21:09:09 +02:00
|
|
|
draw_surface_safe(selection_surface, pos_x, pos_y);
|
2023-07-15 20:01:29 +02:00
|
|
|
BLEND_NORMAL
|
|
|
|
surface_reset_target();
|
|
|
|
|
|
|
|
surface_store_buffer();
|
|
|
|
surface_free(selection_surface);
|
2023-08-16 20:16:31 +02:00
|
|
|
} #endregion
|
2023-07-15 20:01:29 +02:00
|
|
|
|
2022-01-13 05:24:03 +01:00
|
|
|
draw_set_color(_col);
|
|
|
|
|
2023-07-15 20:01:29 +02:00
|
|
|
if(!isUsingTool("Selection"))
|
|
|
|
gpu_set_colorwriteenable(tool_attribute.channel[0], tool_attribute.channel[1], tool_attribute.channel[2], tool_attribute.channel[3]);
|
|
|
|
|
2023-08-16 20:16:31 +02:00
|
|
|
if(isUsingTool("Selection")) { #region
|
2023-07-15 20:01:29 +02:00
|
|
|
if(is_selected) {
|
|
|
|
if(!is_surface(selection_surface)) {
|
|
|
|
is_selected = false;
|
|
|
|
} else {
|
|
|
|
if(is_select_drag) {
|
|
|
|
var px = selection_sx + (mouse_cur_x - selection_mx);
|
|
|
|
var py = selection_sy + (mouse_cur_y - selection_my);
|
|
|
|
|
|
|
|
selection_position[0] = px;
|
|
|
|
selection_position[1] = py;
|
|
|
|
|
|
|
|
if(mouse_release(mb_left))
|
|
|
|
is_select_drag = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(mouse_press(mb_left, active)) {
|
|
|
|
var pos_x = selection_position[0];
|
|
|
|
var pos_y = selection_position[1];
|
2023-09-08 21:37:36 +02:00
|
|
|
var sel_w = surface_get_width_safe(selection_surface);
|
|
|
|
var sel_h = surface_get_height_safe(selection_surface);
|
2023-07-15 20:01:29 +02:00
|
|
|
|
|
|
|
if(point_in_rectangle(mouse_cur_x, mouse_cur_y, pos_x, pos_y, pos_x + sel_w, pos_y + sel_h)) {
|
|
|
|
is_select_drag = true;
|
|
|
|
selection_sx = pos_x;
|
|
|
|
selection_sy = pos_y;
|
|
|
|
selection_mx = mouse_cur_x;
|
|
|
|
selection_my = mouse_cur_y;
|
|
|
|
} else {
|
|
|
|
is_selected = false;
|
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
surface_set_target(_canvas_surface);
|
2023-07-15 20:01:29 +02:00
|
|
|
BLEND_ALPHA
|
2023-09-08 21:09:09 +02:00
|
|
|
draw_surface_safe(selection_surface, pos_x, pos_y);
|
2023-07-15 20:01:29 +02:00
|
|
|
BLEND_NORMAL
|
|
|
|
surface_reset_target();
|
|
|
|
|
|
|
|
surface_store_buffer();
|
|
|
|
surface_free(selection_surface);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!is_selected) {
|
|
|
|
if(is_selecting) {
|
|
|
|
var sel_x0 = min(selection_sx, mouse_cur_x);
|
|
|
|
var sel_y0 = min(selection_sy, mouse_cur_y);
|
|
|
|
var sel_x1 = max(selection_sx, mouse_cur_x);
|
|
|
|
var sel_y1 = max(selection_sy, mouse_cur_y);
|
|
|
|
|
|
|
|
var sel_w = sel_x1 - sel_x0 + 1;
|
|
|
|
var sel_h = sel_y1 - sel_y0 + 1;
|
|
|
|
|
|
|
|
selection_mask = surface_verify(selection_mask, sel_w, sel_h);
|
|
|
|
surface_set_target(selection_mask);
|
|
|
|
DRAW_CLEAR
|
|
|
|
draw_set_color(c_white);
|
|
|
|
if(isUsingTool("Selection", 0))
|
|
|
|
draw_rectangle(0, 0, sel_w, sel_h, false);
|
|
|
|
else if(isUsingTool("Selection", 1))
|
|
|
|
draw_ellipse(0, 0, sel_w - 1, sel_h - 1, false);
|
|
|
|
surface_reset_target();
|
|
|
|
|
|
|
|
if(mouse_release(mb_left)) {
|
|
|
|
is_selecting = false;
|
|
|
|
|
|
|
|
if(sel_x0 != sel_x1 && sel_y0 != sel_y1) {
|
|
|
|
is_selected = true;
|
|
|
|
|
|
|
|
selection_surface = surface_create(sel_w, sel_h);
|
|
|
|
|
|
|
|
surface_set_target(selection_surface);
|
|
|
|
DRAW_CLEAR
|
2023-10-04 09:49:31 +02:00
|
|
|
draw_surface_safe(_canvas_surface, -sel_x0, -sel_y0);
|
2023-07-15 20:01:29 +02:00
|
|
|
|
|
|
|
BLEND_MULTIPLY
|
2023-09-08 21:09:09 +02:00
|
|
|
draw_surface_safe(selection_mask, 0, 0);
|
2023-07-15 20:01:29 +02:00
|
|
|
BLEND_NORMAL
|
|
|
|
surface_reset_target();
|
2023-08-16 20:16:31 +02:00
|
|
|
|
|
|
|
storeAction();
|
2023-10-04 09:49:31 +02:00
|
|
|
surface_set_target(_canvas_surface);
|
2023-07-15 20:01:29 +02:00
|
|
|
gpu_set_blendmode(bm_subtract);
|
2023-09-08 21:09:09 +02:00
|
|
|
draw_surface_safe(selection_surface, sel_x0, sel_y0);
|
2023-07-15 20:01:29 +02:00
|
|
|
gpu_set_blendmode(bm_normal);
|
|
|
|
surface_reset_target();
|
|
|
|
|
|
|
|
surface_store_buffer();
|
|
|
|
|
|
|
|
selection_position = [ sel_x0, sel_y0 ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(mouse_press(mb_left, active)) {
|
|
|
|
is_selecting = true;
|
|
|
|
selection_sx = mouse_cur_x;
|
|
|
|
selection_sy = mouse_cur_y;
|
|
|
|
|
|
|
|
surface_free_safe(selection_mask);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-16 20:16:31 +02:00
|
|
|
#endregion
|
|
|
|
} else if(isUsingTool("Pencil") || isUsingTool("Eraser")) { #region
|
2023-11-06 13:19:59 +01:00
|
|
|
if(mouse_pre_draw_x != undefined && mouse_pre_draw_y != undefined && key_mod_press(SHIFT) && key_mod_press(CTRL)) {
|
2023-03-11 01:40:17 +01:00
|
|
|
var aa = point_direction(mouse_pre_draw_x, mouse_pre_draw_y, mouse_cur_x, mouse_cur_y);
|
|
|
|
var dd = point_distance(mouse_pre_draw_x, mouse_pre_draw_y, mouse_cur_x, mouse_cur_y);
|
|
|
|
var _a = round(aa / 45) * 45;
|
|
|
|
dd = dd * cos(degtorad(_a - aa));
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-03-11 01:40:17 +01:00
|
|
|
mouse_cur_x = mouse_pre_draw_x + lengthdir_x(dd, _a);
|
|
|
|
mouse_cur_y = mouse_pre_draw_y + lengthdir_y(dd, _a);
|
|
|
|
}
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-03-11 01:40:17 +01:00
|
|
|
if(mouse_press(mb_left, active)) {
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_next_dist = 0;
|
2023-03-19 09:17:39 +01:00
|
|
|
drawing_surface = surface_verify(drawing_surface, _dim[0], _dim[1], attrDepth());
|
2023-07-14 20:34:35 +02:00
|
|
|
|
|
|
|
surface_set_shader(drawing_surface, noone);
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(mouse_cur_x, mouse_cur_y, true);
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_reset_shader();
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-03-11 01:40:17 +01:00
|
|
|
mouse_holding = true;
|
2024-02-25 11:02:10 +01:00
|
|
|
if(mouse_pre_draw_x != undefined && mouse_pre_draw_y != undefined && key_mod_press(SHIFT)) { ///////////////// shift line
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_set_shader(drawing_surface, noone, true, BLEND.alpha);
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_next_dist = 0;
|
|
|
|
draw_line_size(mouse_pre_draw_x, mouse_pre_draw_y, mouse_cur_x, mouse_cur_y, true);
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_reset_shader();
|
2023-03-11 01:40:17 +01:00
|
|
|
mouse_holding = false;
|
|
|
|
|
|
|
|
apply_draw_surface();
|
2023-03-02 07:59:14 +01:00
|
|
|
}
|
2023-03-11 01:40:17 +01:00
|
|
|
|
|
|
|
mouse_pre_draw_x = mouse_cur_x;
|
|
|
|
mouse_pre_draw_y = mouse_cur_y;
|
|
|
|
}
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2024-02-25 11:02:10 +01:00
|
|
|
if(mouse_holding) {
|
2023-11-01 14:13:23 +01:00
|
|
|
var _move = mouse_pre_draw_x != mouse_cur_x || mouse_pre_draw_y != mouse_cur_y;
|
|
|
|
var _1stp = brush_dist_min == brush_dist_max && brush_dist_min == 1;
|
|
|
|
|
|
|
|
if(_move || !_1stp) {
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_set_shader(drawing_surface, noone, false, BLEND.alpha);
|
2023-11-01 14:13:23 +01:00
|
|
|
if(_1stp) draw_point_size(mouse_cur_x, mouse_cur_y, true);
|
|
|
|
draw_line_size(mouse_pre_draw_x, mouse_pre_draw_y, mouse_cur_x, mouse_cur_y, true);
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_reset_shader();
|
2023-03-02 07:59:14 +01:00
|
|
|
}
|
2023-03-11 01:40:17 +01:00
|
|
|
|
|
|
|
mouse_pre_draw_x = mouse_cur_x;
|
|
|
|
mouse_pre_draw_y = mouse_cur_y;
|
2023-11-01 14:13:23 +01:00
|
|
|
|
2024-02-25 11:02:10 +01:00
|
|
|
if(mouse_release(mb_left)) {
|
|
|
|
mouse_holding = false;
|
|
|
|
apply_draw_surface();
|
|
|
|
}
|
2023-03-11 01:40:17 +01:00
|
|
|
}
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-03-11 01:40:17 +01:00
|
|
|
BLEND_NORMAL;
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-03-11 01:40:17 +01:00
|
|
|
mouse_pre_x = mouse_cur_x;
|
|
|
|
mouse_pre_y = mouse_cur_y;
|
2023-10-04 09:49:31 +02:00
|
|
|
|
|
|
|
if(brush_sizing) {
|
|
|
|
var s = brush_sizing_s + (_mx - brush_sizing_mx) / 16;
|
|
|
|
s = max(1, s);
|
2024-01-20 05:06:56 +01:00
|
|
|
tool_attribute.size = s;
|
2023-10-04 09:49:31 +02:00
|
|
|
|
|
|
|
if(mouse_release(mb_right))
|
|
|
|
brush_sizing = false;
|
2023-11-01 14:13:23 +01:00
|
|
|
} else if(mouse_press(mb_right, active) && key_mod_press(SHIFT) && brush_surface == noone) {
|
2023-10-04 09:49:31 +02:00
|
|
|
brush_sizing = true;
|
|
|
|
brush_sizing_s = _siz;
|
|
|
|
brush_sizing_mx = _mx;
|
|
|
|
brush_sizing_my = _my;
|
|
|
|
|
|
|
|
brush_sizing_dx = mouse_cur_x;
|
|
|
|
brush_sizing_dy = mouse_cur_y;
|
|
|
|
}
|
2023-08-16 20:16:31 +02:00
|
|
|
#endregion
|
|
|
|
} else if(isUsingTool("Rectangle") || isUsingTool("Ellipse")) { #region
|
2023-03-11 01:40:17 +01:00
|
|
|
if(mouse_holding && key_mod_press(SHIFT)) {
|
|
|
|
var ww = mouse_cur_x - mouse_pre_x;
|
|
|
|
var hh = mouse_cur_y - mouse_pre_y;
|
|
|
|
var ss = max(abs(ww), abs(hh));
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-03-11 01:40:17 +01:00
|
|
|
mouse_cur_x = mouse_pre_x + ss * sign(ww);
|
|
|
|
mouse_cur_y = mouse_pre_y + ss * sign(hh);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(mouse_press(mb_left, active)) {
|
2022-01-13 05:24:03 +01:00
|
|
|
mouse_pre_x = mouse_cur_x;
|
|
|
|
mouse_pre_y = mouse_cur_y;
|
|
|
|
|
2023-03-11 01:40:17 +01:00
|
|
|
mouse_holding = true;
|
|
|
|
}
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
if(mouse_holding) {
|
|
|
|
drawing_surface = surface_verify(drawing_surface, _dim[0], _dim[1], attrDepth());
|
|
|
|
|
|
|
|
surface_set_shader(drawing_surface, noone);
|
2023-07-15 20:01:29 +02:00
|
|
|
if(isUsingTool("Rectangle"))
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_rect_size(mouse_pre_x, mouse_pre_y, mouse_cur_x, mouse_cur_y, isUsingTool("Rectangle", 1));
|
2023-07-15 20:01:29 +02:00
|
|
|
else if(isUsingTool("Ellipse"))
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_ellp_size(mouse_pre_x, mouse_pre_y, mouse_cur_x, mouse_cur_y, isUsingTool("Ellipse", 1));
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_reset_shader();
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
if(mouse_release(mb_left)) {
|
|
|
|
apply_draw_surface();
|
|
|
|
mouse_holding = false;
|
|
|
|
}
|
2023-03-11 01:40:17 +01:00
|
|
|
}
|
2023-10-04 11:28:13 +02:00
|
|
|
|
|
|
|
if(brush_sizing) {
|
|
|
|
var s = brush_sizing_s + (_mx - brush_sizing_mx) / 16;
|
|
|
|
s = max(1, s);
|
|
|
|
inputs[| 2].setValue(s);
|
|
|
|
|
|
|
|
if(mouse_release(mb_right))
|
|
|
|
brush_sizing = false;
|
2023-11-01 14:13:23 +01:00
|
|
|
} else if(mouse_press(mb_right, active) && key_mod_press(SHIFT) && brush_surface == noone) {
|
2023-10-04 11:28:13 +02:00
|
|
|
brush_sizing = true;
|
2023-11-01 14:13:23 +01:00
|
|
|
brush_sizing_s = brush_size;
|
2023-10-04 11:28:13 +02:00
|
|
|
brush_sizing_mx = _mx;
|
|
|
|
brush_sizing_my = _my;
|
|
|
|
|
|
|
|
brush_sizing_dx = mouse_cur_x;
|
|
|
|
brush_sizing_dy = mouse_cur_y;
|
|
|
|
}
|
2023-08-16 20:16:31 +02:00
|
|
|
#endregion
|
|
|
|
} else if(isUsingTool("Fill") || (DRAGGING && DRAGGING.type == "Color")) { #region
|
2023-10-04 09:49:31 +02:00
|
|
|
var fill = DRAGGING? mouse_release(mb_left, active) : mouse_press(mb_left, active);
|
2023-08-16 20:16:31 +02:00
|
|
|
|
|
|
|
if(fill && point_in_rectangle(mouse_cur_x, mouse_cur_y, 0, 0, _surf_w - 1, _surf_h - 1)) {
|
|
|
|
storeAction();
|
2023-10-04 09:49:31 +02:00
|
|
|
surface_set_target(_canvas_surface);
|
2023-08-16 20:16:31 +02:00
|
|
|
if(DRAGGING) draw_set_color(DRAGGING.data);
|
|
|
|
switch(_fill_type) {
|
|
|
|
case 0 :
|
2023-10-04 09:49:31 +02:00
|
|
|
flood_fill_scanline(mouse_cur_x, mouse_cur_y, _canvas_surface, _thr, false);
|
2023-08-16 20:16:31 +02:00
|
|
|
break;
|
|
|
|
case 1 :
|
2023-10-04 09:49:31 +02:00
|
|
|
flood_fill_scanline(mouse_cur_x, mouse_cur_y, _canvas_surface, _thr, true);
|
2023-08-16 20:16:31 +02:00
|
|
|
break;
|
|
|
|
case 2 :
|
2023-10-04 09:49:31 +02:00
|
|
|
canvas_fill(mouse_cur_x, mouse_cur_y, _canvas_surface, _thr);
|
2023-08-16 20:16:31 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
surface_store_buffer();
|
|
|
|
surface_reset_target();
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
2023-08-16 20:16:31 +02:00
|
|
|
#endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
|
2023-03-11 01:40:17 +01:00
|
|
|
draw_set_alpha(1);
|
|
|
|
gpu_set_colorwriteenable(true, true, true, true);
|
2023-07-14 20:34:35 +02:00
|
|
|
|
2023-02-14 05:32:32 +01:00
|
|
|
#region preview
|
2023-10-02 08:57:44 +02:00
|
|
|
var _bg = getInputData(8);
|
|
|
|
var _bga = getInputData(9);
|
|
|
|
var _bgr = getInputData(10);
|
2024-01-16 09:56:20 +01:00
|
|
|
var _alp = _color_get_alpha(_col);
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
var __s = surface_get_target();
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-07-18 17:51:40 +02:00
|
|
|
prev_surface = surface_verify(prev_surface, _dim[0], _dim[1]);
|
2023-07-14 20:34:35 +02:00
|
|
|
preview_draw_surface = surface_verify(preview_draw_surface, _dim[0], _dim[1]);
|
2023-09-08 21:37:36 +02:00
|
|
|
_preview_draw_surface = surface_verify(_preview_draw_surface, surface_get_width_safe(__s), surface_get_height_safe(__s));
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_set_shader(preview_draw_surface, noone,, BLEND.alpha);
|
2023-08-16 20:16:31 +02:00
|
|
|
draw_surface_safe(_drawing_surface, 0, 0);
|
2023-07-14 20:34:35 +02:00
|
|
|
|
|
|
|
draw_set_color(_col);
|
2023-07-15 20:01:29 +02:00
|
|
|
if(isUsingTool("Selection")) {
|
|
|
|
if(is_selected)
|
2023-09-08 21:09:09 +02:00
|
|
|
draw_surface_safe(selection_surface, selection_position[0], selection_position[1]);
|
2023-07-15 20:01:29 +02:00
|
|
|
else if(is_selecting) {
|
|
|
|
var sel_x0 = min(selection_sx, mouse_cur_x);
|
|
|
|
var sel_y0 = min(selection_sy, mouse_cur_y);
|
|
|
|
draw_surface_safe(selection_mask, sel_x0, sel_y0);
|
|
|
|
}
|
|
|
|
} else if(isUsingTool("Pencil") || isUsingTool("Eraser")) {
|
2023-10-11 05:17:49 +02:00
|
|
|
if(isUsingTool("Eraser")) draw_set_color(c_white);
|
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
if(brush_sizing) {
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(brush_sizing_dx, brush_sizing_dy);
|
2023-10-11 05:17:49 +02:00
|
|
|
} else {
|
2023-11-06 13:19:59 +01:00
|
|
|
if(mouse_pre_draw_x != undefined && mouse_pre_draw_y != undefined && key_mod_press(SHIFT))
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_line_size(mouse_pre_draw_x, mouse_pre_draw_y, mouse_cur_x, mouse_cur_y);
|
2023-10-11 05:17:49 +02:00
|
|
|
else
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(mouse_cur_x, mouse_cur_y);
|
2023-10-11 05:17:49 +02:00
|
|
|
}
|
2023-07-15 20:01:29 +02:00
|
|
|
} else if(isUsingTool("Rectangle")) {
|
2023-10-04 11:28:13 +02:00
|
|
|
if(brush_sizing)
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(brush_sizing_dx, brush_sizing_dy);
|
2023-10-04 11:28:13 +02:00
|
|
|
else if(mouse_holding)
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_rect_size(mouse_pre_x, mouse_pre_y, mouse_cur_x, mouse_cur_y, isUsingTool("Rectangle", 1));
|
2023-07-25 20:12:40 +02:00
|
|
|
else
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(mouse_cur_x, mouse_cur_y);
|
2023-07-15 20:01:29 +02:00
|
|
|
} else if(isUsingTool("Ellipse")) {
|
2023-10-04 11:28:13 +02:00
|
|
|
if(brush_sizing)
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(brush_sizing_dx, brush_sizing_dy);
|
2023-10-04 11:28:13 +02:00
|
|
|
else if(mouse_holding)
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_ellp_size(mouse_pre_x, mouse_pre_y, mouse_cur_x, mouse_cur_y, isUsingTool("Ellipse", 1));
|
2023-07-25 20:12:40 +02:00
|
|
|
else
|
2023-11-01 14:13:23 +01:00
|
|
|
draw_point_size(mouse_cur_x, mouse_cur_y);
|
2023-07-14 20:34:35 +02:00
|
|
|
}
|
|
|
|
surface_reset_shader();
|
2023-03-11 01:40:17 +01:00
|
|
|
|
2024-01-16 11:00:39 +01:00
|
|
|
if((active || mouse_holding) && isUsingTool()) {
|
2023-07-15 20:01:29 +02:00
|
|
|
if(isUsingTool("Selection")) {
|
|
|
|
if(is_selected) {
|
|
|
|
var pos_x = _x + selection_position[0] * _s;
|
|
|
|
var pos_y = _y + selection_position[1] * _s;
|
2023-09-08 21:37:36 +02:00
|
|
|
var sel_w = surface_get_width_safe(selection_surface) * _s;
|
|
|
|
var sel_h = surface_get_height_safe(selection_surface) * _s;
|
2023-07-15 20:01:29 +02:00
|
|
|
|
|
|
|
draw_set_color(c_white);
|
|
|
|
draw_rectangle_dashed(pos_x, pos_y, pos_x + sel_w, pos_y + sel_h, true, 4);
|
|
|
|
|
2023-09-08 21:09:09 +02:00
|
|
|
draw_surface_ext_safe(selection_surface, pos_x, pos_y, _s, _s, 0, c_white, 1);
|
2023-07-15 20:01:29 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
gpu_set_colorwriteenable(tool_attribute.channel[0], tool_attribute.channel[1], tool_attribute.channel[2], tool_attribute.channel[3]);
|
|
|
|
draw_surface_ext_safe(preview_draw_surface, _x, _y, _s, _s, 0, isUsingTool("Eraser")? c_red : c_white, isUsingTool("Eraser")? 0.2 : _alp);
|
|
|
|
gpu_set_colorwriteenable(true, true, true, true);
|
|
|
|
}
|
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_set_target(_preview_draw_surface);
|
|
|
|
DRAW_CLEAR
|
2023-09-08 21:09:09 +02:00
|
|
|
draw_surface_ext_safe(preview_draw_surface, _x, _y, _s, _s, 0, c_white, 1);
|
2023-07-14 20:34:35 +02:00
|
|
|
surface_reset_target();
|
2022-09-21 06:09:40 +02:00
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
shader_set(sh_brush_outline);
|
2023-09-08 21:37:36 +02:00
|
|
|
shader_set_f("dimension", surface_get_width_safe(_preview_draw_surface), surface_get_height_safe(_preview_draw_surface));
|
2023-09-08 21:09:09 +02:00
|
|
|
draw_surface_ext_safe(_preview_draw_surface, 0, 0, 1, 1, 0, c_white, 1);
|
2023-07-14 20:34:35 +02:00
|
|
|
shader_reset();
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
2023-07-14 20:34:35 +02:00
|
|
|
var _x0 = _x;
|
|
|
|
var _y0 = _y;
|
|
|
|
var _x1 = _x0 + _dim[0] * _s;
|
|
|
|
var _y1 = _y0 + _dim[1] * _s;
|
|
|
|
|
|
|
|
draw_set_color(COLORS.panel_preview_surface_outline);
|
|
|
|
draw_rectangle(_x0, _y0, _x1 - 1, _y1 - 1, true);
|
|
|
|
|
|
|
|
previewing = 1;
|
2024-01-16 09:56:20 +01:00
|
|
|
draw_set_alpha(1);
|
2023-10-04 07:21:45 +02:00
|
|
|
} #endregion
|
2023-02-14 05:32:32 +01:00
|
|
|
|
2023-10-04 11:28:13 +02:00
|
|
|
static step = function() { #region
|
2023-10-05 06:29:20 +02:00
|
|
|
var fram = attributes.frames;
|
2023-11-01 14:13:23 +01:00
|
|
|
var brush = getInputData(6);
|
2023-10-05 06:29:20 +02:00
|
|
|
var anim = getInputData(12);
|
2023-11-01 14:13:23 +01:00
|
|
|
var anims = getInputData(13);
|
2023-10-04 11:28:13 +02:00
|
|
|
|
|
|
|
inputs[| 12].setVisible(fram > 1);
|
|
|
|
inputs[| 13].setVisible(fram > 1 && anim);
|
2023-11-01 14:13:23 +01:00
|
|
|
inputs[| 15].setVisible(is_surface(brush));
|
|
|
|
inputs[| 16].setVisible(is_surface(brush));
|
2023-10-04 11:28:13 +02:00
|
|
|
|
|
|
|
update_on_frame = fram > 1 && anim;
|
2023-10-05 06:29:20 +02:00
|
|
|
|
|
|
|
if(update_on_frame)
|
2023-10-09 16:07:33 +02:00
|
|
|
preview_index = safe_mod(CURRENT_FRAME * anims, fram);
|
2023-10-04 11:28:13 +02:00
|
|
|
} #endregion
|
|
|
|
|
2023-10-09 16:07:33 +02:00
|
|
|
static update = function(frame = CURRENT_FRAME) { #region
|
2023-10-02 08:57:44 +02:00
|
|
|
var _dim = getInputData(0);
|
|
|
|
var _bg = getInputData(8);
|
|
|
|
var _bga = getInputData(9);
|
|
|
|
var _bgr = getInputData(10);
|
2023-10-04 11:28:13 +02:00
|
|
|
var _anim = getInputData(12);
|
|
|
|
var _anims = getInputData(13);
|
2023-10-30 14:21:34 +01:00
|
|
|
var _bgDim = getInputData(14);
|
2023-07-14 20:34:35 +02:00
|
|
|
|
|
|
|
var cDep = attrDepth();
|
|
|
|
|
2023-10-30 14:21:34 +01:00
|
|
|
if(_bgDim && is_surface(_bg)) _dim = [ surface_get_width_safe(_bg), surface_get_height_safe(_bg) ];
|
|
|
|
attributes.dimension = _dim;
|
2023-11-01 14:13:23 +01:00
|
|
|
apply_surfaces();
|
2023-10-30 14:21:34 +01:00
|
|
|
|
2023-10-09 07:36:20 +02:00
|
|
|
var _frames = attributes.frames;
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2023-10-09 07:36:20 +02:00
|
|
|
if(!is_array(output_surface)) output_surface = array_create(_frames);
|
|
|
|
else if(array_length(output_surface) != _frames)
|
|
|
|
array_resize(output_surface, _frames);
|
|
|
|
|
|
|
|
if(_frames == 1) {
|
2023-10-04 09:49:31 +02:00
|
|
|
var _canvas_surface = getCanvasSurface(0);
|
2023-11-01 14:13:23 +01:00
|
|
|
output_surface[0] = surface_verify(output_surface[0], _dim[0], _dim[1], cDep);
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2023-10-09 07:36:20 +02:00
|
|
|
surface_set_shader(output_surface[0], noone,, BLEND.alpha);
|
2023-10-04 09:49:31 +02:00
|
|
|
if(_bgr && is_surface(_bg))
|
|
|
|
draw_surface_stretched_ext(_bg, 0, 0, _dim[0], _dim[1], c_white, _bga);
|
|
|
|
draw_surface_safe(_canvas_surface, 0, 0);
|
|
|
|
surface_reset_shader();
|
2023-10-04 11:28:13 +02:00
|
|
|
|
2023-10-09 07:36:20 +02:00
|
|
|
outputs[| 0].setValue(output_surface[0]);
|
2023-10-04 09:49:31 +02:00
|
|
|
} else {
|
2023-10-09 07:36:20 +02:00
|
|
|
for( var i = 0; i < _frames; i++ ) {
|
2023-10-04 09:49:31 +02:00
|
|
|
var _canvas_surface = getCanvasSurface(i);
|
2023-10-04 11:28:13 +02:00
|
|
|
output_surface[i] = surface_verify(output_surface[i], _dim[0], _dim[1], cDep);
|
2023-10-04 09:49:31 +02:00
|
|
|
|
2023-10-04 11:28:13 +02:00
|
|
|
surface_set_shader(output_surface[i], noone,, BLEND.alpha);
|
2023-10-04 09:49:31 +02:00
|
|
|
if(_bgr && is_surface(_bg))
|
|
|
|
draw_surface_stretched_ext(_bg, 0, 0, _dim[0], _dim[1], c_white, _bga);
|
|
|
|
draw_surface_safe(_canvas_surface, 0, 0);
|
|
|
|
surface_reset_shader();
|
|
|
|
}
|
2023-10-04 11:28:13 +02:00
|
|
|
|
|
|
|
if(_anim) {
|
2023-10-09 16:07:33 +02:00
|
|
|
var _fr_index = safe_mod(CURRENT_FRAME * _anims, _frames);
|
2023-10-04 11:28:13 +02:00
|
|
|
outputs[| 0].setValue(output_surface[_fr_index]);
|
|
|
|
} else
|
|
|
|
outputs[| 0].setValue(output_surface);
|
2023-10-04 09:49:31 +02:00
|
|
|
}
|
2023-10-04 07:21:45 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-10-04 11:28:13 +02:00
|
|
|
static getPreviewValues = function() { return output_surface; }
|
|
|
|
|
2023-10-04 07:21:45 +02:00
|
|
|
static doSerialize = function(_map) { #region
|
2023-10-04 09:49:31 +02:00
|
|
|
surface_store_buffers();
|
|
|
|
var _buff = array_create(attributes.frames);
|
|
|
|
|
|
|
|
for( var i = 0; i < attributes.frames; i++ ) {
|
|
|
|
var comp = buffer_compress(canvas_buffer[i], 0, buffer_get_size(canvas_buffer[i]));
|
|
|
|
_buff[i] = buffer_base64_encode(comp, 0, buffer_get_size(comp));
|
|
|
|
}
|
2023-03-13 10:45:56 +01:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
_map.surfaces = _buff;
|
2023-10-04 07:21:45 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
|
2023-10-04 07:21:45 +02:00
|
|
|
static doApplyDeserialize = function() { #region
|
2023-10-30 14:21:34 +01:00
|
|
|
var _dim = struct_has(attributes, "dimension")? attributes.dimension : getInputData(0);
|
2023-03-13 10:45:56 +01:00
|
|
|
|
2023-10-04 09:49:31 +02:00
|
|
|
if(!struct_has(load_map, "surfaces")) {
|
|
|
|
if(struct_has(load_map, "surface")) {
|
|
|
|
var buff = buffer_base64_decode(load_map.surface);
|
|
|
|
|
|
|
|
canvas_buffer[0] = buffer_decompress(buff);
|
|
|
|
canvas_surface[0] = surface_create_from_buffer(_dim[0], _dim[1], canvas_buffer[0]);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
canvas_buffer = array_create(array_length(load_map.surfaces));
|
|
|
|
canvas_surface = array_create(array_length(load_map.surfaces));
|
|
|
|
|
|
|
|
for( var i = 0, n = array_length(load_map.surfaces); i < n; i++ ) {
|
|
|
|
var buff = buffer_base64_decode(load_map.surfaces[i]);
|
|
|
|
|
|
|
|
canvas_buffer[i] = buffer_decompress(buff);
|
|
|
|
canvas_surface[i] = surface_create_from_buffer(_dim[0], _dim[1], canvas_buffer[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
apply_surfaces();
|
2023-10-04 07:21:45 +02:00
|
|
|
} #endregion
|
2023-02-23 07:02:19 +01:00
|
|
|
|
2023-10-04 07:21:45 +02:00
|
|
|
static onCleanUp = function() { #region
|
2023-10-04 09:49:31 +02:00
|
|
|
surface_array_free(canvas_surface);
|
2023-10-04 07:21:45 +02:00
|
|
|
} #endregion
|
2022-01-13 05:24:03 +01:00
|
|
|
}
|