Pixel-Composer/scripts/node_canvas/node_canvas.gml

839 lines
28 KiB
Plaintext
Raw Normal View History

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 )
2024-03-24 04:58:08 +01:00
.setDisplay(VALUE_DISPLAY.slider, { range: [1, 32, 0.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.)
.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
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.)
.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 )
.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 );
inputs[| 14] = nodeValue("Use background dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true );
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;
2024-03-31 05:36:11 +02:00
draw_sprite_stretched(THEME.button_def, 0, _x, _y, _w, _h);
2023-10-04 09:49:31 +02:00
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
2024-04-11 15:43:03 +02:00
temp_surface = array_create(1);
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
];
#region ++++ data ++++
attributes.frames = 1;
attribute_surface_depth();
2023-03-19 09:17:39 +01:00
attributes.dimension = [ 1, 1 ];
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
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
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
2024-04-12 11:45:21 +02:00
draw_stack = ds_list_create();
brush = new canvas_brush();
2024-03-02 10:08:44 +01:00
#endregion
#region ++++ tools ++++
tool_attribute.color = cola(c_white);
tool_attribute.channel = [ true, true, true, true ];
tool_channel_edit = new checkBoxGroup(THEME.tools_canvas_channel, function(ind, val) { tool_attribute.channel[ind] = val; });
2024-04-13 07:32:04 +02:00
tool_attribute.drawLayer = 0;
tool_attribute.pickColor = c_white;
tool_drawLayer_edit = new buttonGroup( [ THEME.canvas_draw_layer, THEME.canvas_draw_layer, THEME.canvas_draw_layer ], function(val) { tool_attribute.drawLayer = val; });
tool_settings = [ [ "Channel", tool_channel_edit, "channel", tool_attribute ], [ "Draw", tool_drawLayer_edit, "drawLayer", 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));
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 ];
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);
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 ];
tools = [
2024-04-11 15:43:03 +02:00
new NodeTool( "Selection", [ THEME.canvas_tools_selection_rectangle, THEME.canvas_tools_selection_circle, THEME.canvas_tools_freeform_selection ]),
2024-04-12 11:45:21 +02:00
new NodeTool( "Magic Selection", THEME.canvas_tools_magic_selection )
.setSetting(tool_thrs)
.setSetting(tool_fil8),
new NodeTool( "Pencil", THEME.canvas_tools_pencil)
2024-04-12 11:45:21 +02:00
.setSetting(tool_size),
new NodeTool( "Eraser", THEME.canvas_tools_eraser)
2024-04-12 11:45:21 +02:00
.setSetting(tool_size),
new NodeTool( "Rectangle", [ THEME.canvas_tools_rect, THEME.canvas_tools_rect_fill ])
2024-04-12 11:45:21 +02:00
.setSetting(tool_size),
new NodeTool( "Ellipse", [ THEME.canvas_tools_ellip, THEME.canvas_tools_ellip_fill ])
2024-04-12 11:45:21 +02:00
.setSetting(tool_size),
2024-04-12 11:45:21 +02:00
new NodeTool( "Freeform", THEME.canvas_tools_freeform)
.setSetting(tool_size),
2024-04-11 15:43:03 +02:00
new NodeTool( "Fill", THEME.canvas_tools_bucket)
2024-04-12 11:45:21 +02:00
.setSetting(tool_thrs)
.setSetting(tool_fil8),
2024-04-11 15:43:03 +02:00
];
2024-04-12 11:45:21 +02:00
tool_selection = new canvas_tool_selection();
2024-04-11 15:43:03 +02:00
2024-04-12 11:45:21 +02:00
tool_brush = new canvas_tool_brush(brush, false);
tool_eraser = new canvas_tool_brush(brush, true);
tool_rectangle = new canvas_tool_shape(brush, CANVAS_TOOL_SHAPE.rectangle);
tool_ellipse = new canvas_tool_shape(brush, CANVAS_TOOL_SHAPE.ellipse);
tool_fill = new canvas_tool_fill(tool_attribute);
tool_freeform = new canvas_tool_draw_freeform(brush);
tool_sel_rectangle = new canvas_tool_selection_shape(tool_selection, CANVAS_TOOL_SHAPE.rectangle);
tool_sel_ellipse = new canvas_tool_selection_shape(tool_selection, CANVAS_TOOL_SHAPE.ellipse);
tool_sel_freeform = new canvas_tool_selection_freeform(tool_selection, brush);
tool_sel_magic = new canvas_tool_selection_magic(tool_selection, tool_attribute);
2024-04-13 07:32:04 +02:00
#endregion
2024-04-13 14:14:42 +02:00
#region ++++ right tools ++++
2024-04-13 07:32:04 +02:00
__action_rotate_90_cw = method(self, function() { if(tool_selection.is_selected) tool_selection.rotate90cw() else canvas_action_rotate(-90); });
__action_rotate_90_ccw = method(self, function() { if(tool_selection.is_selected) tool_selection.rotate90ccw() else canvas_action_rotate( 90); });
__action_flip_h = method(self, function() { if(tool_selection.is_selected) tool_selection.flipH() else canvas_action_flip(1); });
__action_flip_v = method(self, function() { if(tool_selection.is_selected) tool_selection.flipV() else canvas_action_flip(0); });
2024-04-13 14:14:42 +02:00
__action_add_node = method(self, function(ctx) { dialogCall(o_dialog_add_node, mouse_mx + 8, mouse_my + 8, { context: ctx }); });
nodeTool = noone;
nodeToolPreview = new NodeTool( "Apply Node", THEME.canvas_resize, self ).setToolFn( __action_add_node );
2024-04-13 07:32:04 +02:00
rightTools_general = [
2024-04-13 14:14:42 +02:00
nodeToolPreview,
-1,
2024-04-13 07:32:04 +02:00
new NodeTool( "Resize Canvas", THEME.canvas_resize ).setToolObject( new canvas_tool_resize() ),
new NodeTool( [ "Rotate 90 CW", "Rotate 90 CCW" ],
[ THEME.canvas_rotate_cw, THEME.canvas_rotate_ccw ] )
.setToolFn( [ __action_rotate_90_cw, __action_rotate_90_ccw ] ),
new NodeTool( [ "Flip H", "Flip V" ],
[ THEME.canvas_flip_h, THEME.canvas_flip_v ] )
.setToolFn( [ __action_flip_h, __action_flip_v ] ),
];
rightTools_selection = [
new NodeTool( "Outline", THEME.canvas_tools_outline ).setToolObject( new canvas_tool_outline() ),
2024-04-13 14:14:42 +02:00
new NodeTool( [ "Extrude", "Inset" ],
[ THEME.canvas_tools_extrude, THEME.canvas_tools_inset ] )
.setToolObject( [ new canvas_tool_extrude(), new canvas_tool_inset() ] ),
2024-04-13 07:32:04 +02:00
];
rightTools = rightTools_general;
2024-04-11 15:43:03 +02:00
#endregion
function setToolColor(color) { tool_attribute.color = color; }
2024-04-12 11:45:21 +02:00
function getToolColor() { return tool_attribute.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);
yy += _cw + ui(8);
hh += _cw + ui(8);
2024-01-16 11:00:39 +01:00
var _sel = noone;
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 ];
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);
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
2024-04-11 15:43:03 +02:00
var fr = attributes.frames;
var _dim = attributes.dimension;
2023-10-04 09:49:31 +02:00
if(array_length(canvas_surface) < fr) {
for( var i = array_length(canvas_surface); i < fr; i++ ) {
2024-04-11 15:43:03 +02:00
canvas_surface[i] = surface_create(_dim[0], _dim[1]);
surface_set_target(canvas_surface[i]);
DRAW_CLEAR
surface_reset_target();
2023-10-04 09:49:31 +02:00
}
} 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-03-31 05:36:11 +02:00
function getCanvasSurface(index = preview_index) { INLINE return array_safe_get_fast(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
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-04-12 11:45:21 +02:00
if(!is_surface(_canvas_surface)) { // recover surface from bufffer in case of VRAM refresh
2024-02-25 11:02:10 +01:00
setCanvasSurface(surface_create_from_buffer(_dim[0], _dim[1], canvas_buffer[index]), index);
2024-04-12 11:45:21 +02:00
2024-02-25 11:02:10 +01:00
} else if(surface_get_width_safe(_canvas_surface) != _dim[0] || surface_get_height_safe(_canvas_surface) != _dim[1]) { // resize surface
2024-03-31 05:36:11 +02:00
var _cbuff = array_safe_get_fast(canvas_buffer, index);
2024-01-20 05:06:56 +01:00
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);
2024-04-13 07:32:04 +02:00
var _newCanvas = surface_create(_dim[0], _dim[1]);
surface_set_target(_newCanvas);
DRAW_CLEAR
draw_surface(_canvas_surface, 0, 0);
surface_reset_target();
setCanvasSurface(_newCanvas, index);
surface_free(_canvas_surface);
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
2024-04-13 07:32:04 +02:00
function tool_pick_color(_x, _y) { #region
if(tool_selection.is_selected)
tool_attribute.pickColor = surface_get_pixel(tool_selection.selection_surface, _x - tool_selection.selection_position[0], _y - tool_selection.selection_position[1]);
else
tool_attribute.pickColor = surface_get_pixel(getCanvasSurface(), _x, _y);
} #endregion
2023-10-04 09:49:31 +02:00
function apply_draw_surface() { #region
2024-04-12 11:45:21 +02:00
var _can = getCanvasSurface();
var _drw = drawing_surface;
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
2024-04-12 11:45:21 +02:00
if(tool_selection.is_selected) {
var _tmp = surface_create(surface_get_width(tool_selection.selection_mask), surface_get_height(tool_selection.selection_mask));
surface_set_target(_tmp);
DRAW_CLEAR
draw_surface(drawing_surface, -tool_selection.selection_position[0], -tool_selection.selection_position[1]);
BLEND_MULTIPLY
draw_surface(tool_selection.selection_mask, 0, 0);
BLEND_NORMAL
surface_reset_target();
_can = tool_selection.selection_surface;
_drw = _tmp;
}
2024-04-13 07:32:04 +02:00
var _sw = surface_get_width(_can);
var _sh = surface_get_height(_can);
var _drawnSurface = surface_create(_sw, _sh);
surface_set_shader(_drawnSurface, sh_canvas_apply_draw);
shader_set_i("drawLayer", tool_attribute.drawLayer);
shader_set_i("eraser", isUsingTool("Eraser"));
shader_set_f("channels", tool_attribute.channel);
shader_set_f("alpha", _color_get_alpha(tool_attribute.color));
shader_set_color("pickColor", tool_attribute.pickColor);
2024-04-13 07:32:04 +02:00
shader_set_surface("back", _can);
shader_set_surface("fore", _drw);
2022-01-13 05:24:03 +01:00
2024-04-13 07:32:04 +02:00
draw_sprite_stretched(s_fx_pixel, 0, 0, 0, _sw, _sh);
surface_reset_shader();
2024-04-11 15:43:03 +02:00
2024-04-13 07:32:04 +02:00
surface_free(_can);
2024-04-12 11:45:21 +02:00
surface_clear(drawing_surface);
2024-04-11 15:43:03 +02:00
2024-04-13 07:32:04 +02:00
if(tool_selection.is_selected) {
surface_free(_tmp);
tool_selection.selection_surface = _drawnSurface;
} else {
setCanvasSurface(_drawnSurface);
surface_store_buffer();
}
2024-04-11 15:43:03 +02:00
} #endregion
2024-03-14 14:35:19 +01:00
static drawOverlay = function(hover, 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
2024-04-12 11:45:21 +02:00
COLORS_GLOBAL_GET = getToolColor;
COLORS_GLOBAL_SET = setToolColor;
2024-04-12 11:45:21 +02:00
brush.node = self;
brush.step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
2024-01-16 11:00:39 +01:00
2024-04-13 14:14:42 +02:00
if(!tool_selection.is_selected && active && key_mod_press(ALT)) { #region color selector
var dialog = instance_create(0, 0, o_dialog_color_picker);
2024-04-12 11:45:21 +02:00
dialog.onApply = setToolColor;
dialog.def_c = tool_attribute.color;
} #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
2024-04-13 07:32:04 +02:00
#region surfaces
var _dim = attributes.dimension;
_drawing_surface = surface_verify(_drawing_surface, _dim[0], _dim[1]);
drawing_surface = surface_verify( drawing_surface, _dim[0], _dim[1], attrDepth());
surface_set_target(_drawing_surface);
DRAW_CLEAR
draw_surface_safe(drawing_surface);
surface_reset_target();
2023-08-16 20:16:31 +02:00
#endregion
2024-04-12 11:45:21 +02:00
#region tool
var _currTool = PANEL_PREVIEW.tool_current;
2024-04-13 07:32:04 +02:00
var _tool = noone;
rightTools = [];
array_append(rightTools, rightTools_general);
if(tool_selection.is_selected) {
array_push(rightTools, -1);
array_append(rightTools, rightTools_selection);
}
2024-04-11 15:43:03 +02:00
2024-04-13 14:14:42 +02:00
if(nodeTool != noone)
_tool = nodeTool;
else if(_currTool != noone) {
2024-04-13 07:32:04 +02:00
_tool = _currTool.getToolObject();
2024-04-12 11:45:21 +02:00
switch(_currTool.getName()) {
case "Pencil" : _tool = tool_brush; break;
case "Eraser" : _tool = tool_eraser; break;
case "Fill" : _tool = tool_fill; break;
case "Freeform" : _tool = tool_freeform; break;
2023-07-15 20:01:29 +02:00
2024-04-12 11:45:21 +02:00
case "Rectangle" :
_tool = tool_rectangle;
_tool.fill = _currTool.selecting == 1;
break;
2024-04-11 15:43:03 +02:00
2024-04-12 11:45:21 +02:00
case "Ellipse" :
_tool = tool_ellipse;
_tool.fill = _currTool.selecting == 1;
break;
2024-04-11 15:43:03 +02:00
2024-04-12 11:45:21 +02:00
case "Selection" :
switch(_currTool.selecting) {
case 0 : _tool = tool_sel_rectangle; break;
case 1 : _tool = tool_sel_ellipse; break;
case 2 : _tool = tool_sel_freeform; break;
2024-04-11 15:43:03 +02:00
}
2023-07-15 20:01:29 +02:00
2024-04-12 11:45:21 +02:00
break;
2023-07-15 20:01:29 +02:00
2024-04-13 07:32:04 +02:00
case "Magic Selection" : _tool = tool_sel_magic; break;
2023-03-11 01:40:17 +01:00
2023-03-02 07:59:14 +01:00
}
2024-04-13 07:32:04 +02:00
if(_tool) _tool.subtool = _currTool.selecting;
tool_selection.node = self;
tool_selection.drawing_surface = drawing_surface;
tool_selection._canvas_surface = _canvas_surface;
tool_selection.apply_draw_surface = apply_draw_surface;
if(is_instanceof(_tool, canvas_tool_selection) && tool_selection.is_selected) tool_selection.step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
2023-03-11 01:40:17 +01:00
}
2024-04-13 14:14:42 +02:00
2024-04-12 11:45:21 +02:00
#endregion
2024-04-13 07:32:04 +02:00
if(_tool && _tool.override) {
_tool.node = self;
_tool.step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
return;
}
2024-04-12 11:45:21 +02:00
draw_set_color(tool_attribute.color);
if(_tool) { #region tool step
2022-01-13 05:24:03 +01:00
2024-04-12 11:45:21 +02:00
_tool.drawing_surface = drawing_surface;
_tool._canvas_surface = _canvas_surface;
2023-10-04 09:49:31 +02:00
2024-04-12 11:45:21 +02:00
_tool.apply_draw_surface = apply_draw_surface;
_tool.brush = brush;
2024-04-11 15:43:03 +02:00
2024-04-12 11:45:21 +02:00
_tool.node = self;
2024-04-11 15:43:03 +02:00
2024-04-12 11:45:21 +02:00
if(_tool.relative && tool_selection.is_selected) {
_tool._canvas_surface = tool_selection.selection_surface;
var _px = tool_selection.selection_position[0];
var _py = tool_selection.selection_position[1];
var _rx = _x + _px * _s;
var _ry = _y + _py * _s;
2022-01-13 05:24:03 +01:00
2024-04-12 11:45:21 +02:00
_tool.step(hover, active, _rx, _ry, _s, _mx, _my, _snx, _sny);
} else
_tool.step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
2023-03-11 01:40:17 +01:00
2024-04-12 11:45:21 +02:00
if(_tool.brush_resizable) {
if(hover && key_mod_press(CTRL)) {
if(mouse_wheel_down()) tool_attribute.size = max( 1, tool_attribute.size - 1);
if(mouse_wheel_up()) tool_attribute.size = min(64, tool_attribute.size + 1);
2023-07-14 20:34:35 +02:00
}
2024-04-11 15:43:03 +02:00
2024-04-12 11:45:21 +02:00
brush.sizing(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
}
2024-04-11 15:43:03 +02:00
} #endregion
2023-03-11 01:40:17 +01:00
draw_set_alpha(1);
2023-07-14 20:34:35 +02:00
2023-02-14 05:32:32 +01:00
#region preview
2024-04-12 11:45:21 +02:00
var _alp = _color_get_alpha(tool_attribute.color);
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
2024-04-12 11:45:21 +02:00
if(tool_selection.is_selected) tool_selection.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
2023-07-14 20:34:35 +02:00
surface_set_shader(preview_draw_surface, noone,, BLEND.alpha);
2024-04-12 11:45:21 +02:00
if(tool_selection.is_selected) tool_selection.drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
2023-08-16 20:16:31 +02:00
draw_surface_safe(_drawing_surface, 0, 0);
2023-07-14 20:34:35 +02:00
2024-04-12 11:45:21 +02:00
draw_set_color(tool_attribute.color);
if(brush.brush_sizing)
canvas_draw_point_size(brush, brush.brush_sizing_dx, brush.brush_sizing_dy);
else if(_tool)
_tool.drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
2023-07-14 20:34:35 +02:00
surface_reset_shader();
2023-03-11 01:40:17 +01:00
2024-04-12 11:45:21 +02:00
if(_tool) {
_tool.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
2024-04-11 15:43:03 +02:00
2024-04-13 07:32:04 +02:00
if(!is_instanceof(_tool, canvas_tool_selection) && (active || _tool.mouse_holding))
2023-07-15 20:01:29 +02:00
draw_surface_ext_safe(preview_draw_surface, _x, _y, _s, _s, 0, isUsingTool("Eraser")? c_red : c_white, isUsingTool("Eraser")? 0.2 : _alp);
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);
2024-04-11 15:43:03 +02:00
shader_set_f("dimension", surface_get_width(_preview_draw_surface), surface_get_height(_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();
2024-04-11 15:43:03 +02:00
2024-04-12 11:45:21 +02:00
_tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
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);
2024-04-12 11:45:21 +02:00
draw_set_alpha(1);
2023-07-14 20:34:35 +02:00
previewing = 1;
2024-04-12 11:45:21 +02:00
if((_tool == noone || !_tool.mouse_holding) && key_press(ord("V"), MOD_KEY.ctrl)) { #region
var _str = json_try_parse(clipboard_get_text(), noone);
print(clipboard_get_text())
if(is_struct(_str) && struct_has(_str, "buffer")) {
var _surf = surface_decode(_str);
if(is_surface(_surf)) {
tool_selection.selection_surface = _surf;
tool_selection.is_selected = true;
tool_selection.selection_position = [ 0, 0 ];
}
}
} #endregion
} #endregion
2023-02-14 05:32:32 +01:00
2023-10-04 11:28:13 +02:00
static step = function() { #region
var fram = attributes.frames;
var brush = getInputData(6);
var anim = getInputData(12);
var anims = getInputData(13);
2023-10-04 11:28:13 +02:00
inputs[| 12].setVisible(fram > 1);
inputs[| 13].setVisible(fram > 1 && anim);
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;
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
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);
var _bgDim = getInputData(14);
2023-07-14 20:34:35 +02:00
var cDep = attrDepth();
if(_bgDim && is_surface(_bg)) _dim = [ surface_get_width_safe(_bg), surface_get_height_safe(_bg) ];
attributes.dimension = _dim;
apply_surfaces();
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);
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
}
} #endregion
2022-01-13 05:24:03 +01:00
2023-10-04 11:28:13 +02:00
static getPreviewValues = function() { return output_surface; }
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;
} #endregion
2022-01-13 05:24:03 +01:00
static doApplyDeserialize = function() { #region
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();
} #endregion
2023-02-23 07:02:19 +01:00
static onCleanUp = function() { #region
2023-10-04 09:49:31 +02:00
surface_array_free(canvas_surface);
} #endregion
2022-01-13 05:24:03 +01:00
}