canvas recover

This commit is contained in:
Tanasart 2024-04-14 12:58:38 +07:00
parent 3174d74402
commit 7ff380dd2b
47 changed files with 4940 additions and 143 deletions

View file

@ -1,4 +1,4 @@
// 2024-04-14 10:09:02
// 2024-04-14 12:48:00
function canvas_brush() constructor {
brush_sizing = false;
brush_sizing_s = 0;

View file

@ -1,4 +1,4 @@
// 2024-04-14 10:09:00
// 2024-04-14 10:09:02
function canvas_brush() constructor {
brush_sizing = false;
brush_sizing_s = 0;

View file

@ -1,4 +1,4 @@
// 2024-04-14 10:20:09
// 2024-04-14 12:48:07
function canvas_tool() constructor {
node = noone;

View file

@ -0,0 +1,31 @@
// 2024-04-14 10:20:09
function canvas_tool() constructor {
node = noone;
rightTools = [];
override = false;
relative = false;
relative_position = [ 0, 0 ];
drawing_surface = noone;
_canvas_surface = noone;
apply_draw_surface = noone;
brush_resizable = false;
mouse_holding = false;
subtool = 0;
function init() {}
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function drawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
}

View file

@ -0,0 +1,93 @@
// 2024-04-14 12:48:17
function canvas_tool_shader() : canvas_tool() constructor {
mask = false;
override = true;
mouse_init = false;
mask_boundary_init = [ 0, 0, 1, 1 ];
mask_boundary = [ 0, 0, 1, 1 ];
preview_surface = [ noone, noone ];
function init() { mouse_init = true; }
function onInit(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function stepEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function stepMaskEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
if(mouse_press(mb_right)) {
PANEL_PREVIEW.tool_current = noone;
return;
}
var _dim = node.attributes.dimension;
var _sel = node.tool_selection;
preview_surface[0] = surface_verify(preview_surface[0], _dim[0], _dim[1]);
preview_surface[1] = surface_verify(preview_surface[1], _dim[0], _dim[1]);
if(mouse_init) {
mask = key_mod_press(SHIFT);
mask_boundary_init = [ _sel.selection_position[0], _sel.selection_position[1], _sel.selection_size[0], _sel.selection_size[1] ];
mask_boundary = [ _sel.selection_position[0], _sel.selection_position[1], _sel.selection_size[0], _sel.selection_size[1] ];
if(mask) _sel.apply();
onInit(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
mouse_init = false;
return;
}
var _surf = mask? _sel.selection_mask : _sel.selection_surface;
var _pos = _sel.selection_position;
surface_set_shader(preview_surface[0], noone);
draw_surface(_surf, _pos[0], _pos[1]);
surface_reset_shader();
if(mask) {
stepMaskEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
if(mouse_release(mb_left)) {
var _newSurf = surface_create(mask_boundary[2], mask_boundary[3]);
surface_set_shader(_newSurf, noone);
draw_surface(preview_surface[1], -mask_boundary[0], -mask_boundary[1]);
surface_reset_shader();
_sel.createNewSelection(_newSurf, mask_boundary[0], mask_boundary[1], mask_boundary[2], mask_boundary[3]);
PANEL_PREVIEW.tool_current = noone;
MOUSE_BLOCK = true;
}
} else {
stepEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
draw_surface_ext(preview_surface[1], _x, _y, _s, _s, 0, c_white, 1);
if(mouse_release(mb_left)) {
var _newSurf = surface_create(_dim[0], _dim[1]);
surface_set_shader(_newSurf, noone);
draw_surface(preview_surface[1], 0, 0);
surface_reset_shader();
surface_free(_sel.selection_surface);
_sel.selection_surface = _newSurf;
_sel.selection_position = [ 0, 0 ];
_sel.apply();
surface_free(_surf);
PANEL_PREVIEW.tool_current = noone;
MOUSE_BLOCK = true;
}
}
}
function drawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
if(!mask) return;
draw_surface_ext_safe(preview_surface[1], _x, _y, _s, _s);
}
}

View file

@ -1,4 +1,4 @@
// 2024-04-14 10:04:07
// 2024-04-14 12:50:50
function canvas_tool_brush(brush, eraser = false) : canvas_tool() constructor {
self.brush = brush;
isEraser = eraser;

View file

@ -1,4 +1,4 @@
// 2024-04-14 10:03:44
// 2024-04-14 10:04:07
function canvas_tool_brush(brush, eraser = false) : canvas_tool() constructor {
self.brush = brush;
isEraser = eraser;
@ -14,7 +14,6 @@ function canvas_tool_brush(brush, eraser = false) : canvas_tool() constructor {
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
print(brush.brush_surface);
mouse_cur_x = round((_mx - _x) / _s - 0.5);
mouse_cur_y = round((_my - _y) / _s - 0.5);

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:22:33
// 2024-04-14 12:48:46
function canvas_tool_node(canvas, node) : canvas_tool() constructor {
self.canvas = canvas;

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:22:32
// 2024-04-14 12:22:33
function canvas_tool_node(canvas, node) : canvas_tool() constructor {
self.canvas = canvas;

View file

@ -0,0 +1,73 @@
// 2024-04-14 12:51:21
function canvas_tool_outline() : canvas_tool_shader() constructor {
mouse_sx = 0;
function init() { mouse_init = true; }
function onInit(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
mouse_sx = _mx;
}
function stepEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
var _dim = node.attributes.dimension;
var _thck = abs(round((_mx - mouse_sx) / _s));
var _side = _mx > mouse_sx;
surface_set_shader(preview_surface[1], sh_outline);
shader_set_f("dimension", _dim);
shader_set_f("borderSize", _thck, _thck);
shader_set_f("borderStart", 0, 0);
shader_set_i("side", _side);
shader_set_color("borderColor", node.tool_attribute.color);
draw_surface(preview_surface[0], 0, 0);
surface_reset_shader();
}
function stepMaskEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
var _dim = node.attributes.dimension;
var _thck = abs(round((_mx - mouse_sx) / _s));
var _side = _mx > mouse_sx;
if(_side) {
surface_set_shader(preview_surface[1], sh_outline);
shader_set_f("dimension", _dim);
shader_set_f("borderSize", _thck, _thck);
shader_set_f("borderStart", 0, 0);
shader_set_i("side", _side);
shader_set_color("borderColor", c_white);
draw_surface(preview_surface[0], 0, 0);
surface_reset_shader();
mask_boundary[0] = mask_boundary_init[0] - _thck;
mask_boundary[1] = mask_boundary_init[1] - _thck;
mask_boundary[2] = mask_boundary_init[2] + _thck * 2;
mask_boundary[3] = mask_boundary_init[3] + _thck * 2;
} else {
surface_set_shader(preview_surface[1], sh_erode);
shader_set_f("dimension", _dim);
shader_set_f("size", _thck, _thck);
shader_set_i("border", 0);
shader_set_i("alpha", 1);
draw_surface(preview_surface[0], 0, 0);
surface_reset_shader();
mask_boundary[0] = mask_boundary_init[0] + _thck;
mask_boundary[1] = mask_boundary_init[1] + _thck;
mask_boundary[2] = mask_boundary_init[2] - _thck * 2;
mask_boundary[3] = mask_boundary_init[3] - _thck * 2;
}
}
}

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:31:10
// 2024-04-14 12:48:56
function canvas_tool_resize() : canvas_tool() constructor {
override = true;

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:30:55
// 2024-04-14 12:31:10
function canvas_tool_resize() : canvas_tool() constructor {
override = true;

View file

@ -1,4 +1,4 @@
// 2024-04-14 11:51:21
// 2024-04-14 12:51:12
function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
self.selector = selector;

View file

@ -1,4 +1,4 @@
// 2024-04-14 11:51:18
// 2024-04-14 12:51:08
function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
self.selector = selector;

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:16:19
// 2024-04-14 12:49:02
function canvas_tool_selection_brush(selector, brush) : canvas_tool_selection(selector) constructor {
self.brush = brush;

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:16:16
// 2024-04-14 12:16:19
function canvas_tool_selection_brush(selector, brush) : canvas_tool_selection(selector) constructor {
self.brush = brush;

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:16:16
// 2024-04-14 12:49:10
function canvas_tool_selection_freeform(selector, brush) : canvas_tool_selection(selector) constructor {
self.brush = brush;

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:14:09
// 2024-04-14 12:16:16
function canvas_tool_selection_freeform(selector, brush) : canvas_tool_selection(selector) constructor {
self.brush = brush;
@ -87,7 +87,7 @@ function canvas_tool_selection_freeform(selector, brush) : canvas_tool_selection
}
}
function onDrawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:16:16
// 2024-04-14 12:49:17
function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection(selector) constructor {
self.tool_attribute = toolAttr;

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:14:14
// 2024-04-14 12:16:16
function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection(selector) constructor {
self.tool_attribute = toolAttr;
@ -58,7 +58,7 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
}
}
function onDrawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:16:16
// 2024-04-14 12:49:25
function canvas_tool_selection_shape(selector, shape) : canvas_tool_selection(selector) constructor {
self.shape = shape;

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:15:58
// 2024-04-14 12:45:07
function canvas_tool_selection_shape(selector, shape) : canvas_tool_selection(selector) constructor {
self.shape = shape;
@ -52,7 +52,4 @@ function canvas_tool_selection_shape(selector, shape) : canvas_tool_selection(se
}
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:32:26
// 2024-04-14 12:58:03
function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Canvas";
color = COLORS.node_blend_canvas;
@ -819,7 +819,6 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
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);

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:27:33
// 2024-04-14 12:57:15
function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Canvas";
color = COLORS.node_blend_canvas;
@ -819,7 +819,6 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
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);

View file

@ -0,0 +1,102 @@
// 2024-04-14 12:51:01
function NodeTool(name, spr, context = instanceof(other)) constructor {
ctx = context;
self.name = name;
self.spr = spr;
subtools = is_array(spr)? array_length(spr) : 0;
selecting = 0;
settings = [];
attribute = {};
toolObject = noone;
toolFn = noone;
toolFnParam = {};
static checkHotkey = function() {
INLINE
return getToolHotkey(ctx, name);
}
static setToolObject = function(toolObject) { self.toolObject = toolObject; return self; }
static setToolFn = function(toolFn) { self.toolFn = toolFn; return self; }
static getName = function(index = 0) { return is_array(name)? array_safe_get_fast(name, index, "") : name; }
static getToolObject = function() { return is_array(toolObject)? toolObject[selecting] : toolObject; }
static getDisplayName = function(index = 0) {
var _key = checkHotkey();
var _nme = getName(index);
if(_key != "") _nme += $" ({_key})";
return _nme;
}
static setSetting = function(sets) { array_push(settings, sets); return self; }
static addSetting = function(name, type, onEdit, keyAttr, val) {
var w;
switch(type) {
case VALUE_TYPE.float :
w = new textBox(TEXTBOX_INPUT.number, onEdit);
w.font = f_p3;
break;
case VALUE_TYPE.boolean :
w = new checkBox(onEdit);
break;
}
array_push(settings, [ name, w, keyAttr, attribute ]);
attribute[$ keyAttr] = val;
return self;
}
static toggle = function(index = 0) {
if(toolFn != noone) {
if(subtools == 0) toolFn(ctx);
else toolFn[index](ctx);
return;
}
if(subtools == 0) {
PANEL_PREVIEW.tool_current = PANEL_PREVIEW.tool_current == self? noone : self;
} else {
if(PANEL_PREVIEW.tool_current == self && index == selecting) {
PANEL_PREVIEW.tool_current = noone;
selecting = 0;
} else {
PANEL_PREVIEW.tool_current = self;
selecting = index;
}
}
if(PANEL_PREVIEW.tool_current == self)
onToggle();
var _obj = getToolObject();
if(_obj) _obj.init();
}
static toggleKeyboard = function() {
if(subtools == 0) {
PANEL_PREVIEW.tool_current = PANEL_PREVIEW.tool_current == self? noone : self;
} else if(PANEL_PREVIEW.tool_current != self) {
PANEL_PREVIEW.tool_current = self;
selecting = 0;
} else if(selecting == subtools - 1) {
PANEL_PREVIEW.tool_current = noone;
selecting = 0;
} else
selecting++;
if(PANEL_PREVIEW.tool_current == self)
onToggle();
}
static onToggle = function() {}
}

View file

@ -1,4 +1,4 @@
// 2024-04-14 12:24:14
// 2024-04-14 12:50:09
#region funtion calls
function __fnInit_Inspector() {
__registerFunction("inspector_copy_prop", panel_inspector_copy_prop);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,692 @@
// 2024-04-14 12:50:42
#region ==================================== DRAW ====================================
function draw_surface_safe(surface, _x = 0, _y = 0) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.draw(_x, _y);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface(surface, _x, _y);
__channel_pos(surface);
} #endregion
function draw_surface_stretched_safe(surface, _x, _y, _w, _h) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.drawStretch(_x, _y, _w, _h);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface_stretched(surface, _x, _y, _w, _h);
__channel_pos(surface);
} #endregion
function draw_surface_ext_safe(surface, _x = 0, _y = 0, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.draw(_x, _y, _xs, _ys, _rot, _col, _alpha);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface_ext(surface, _x, _y, _xs, _ys, _rot, _col, _alpha);
__channel_pos(surface);
} #endregion
function draw_surface_tiled_safe(surface, _x, _y) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.drawTile(_x, _y);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface_tiled(surface, _x, _y);
__channel_pos(surface);
} #endregion
function draw_surface_tiled_ext_safe(surface, _x, _y, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.drawTile(_x, _y, _xs, _ys, _col, _alpha);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
var back = surface_get_target();
var bdim = surface_get_dimension(back);
shader_set(sh_draw_tile);
shader_set_f("backDimension", bdim);
shader_set_f("foreDimension", surface_get_dimension(surface));
shader_set_f("position" , [ _x, _y ]);
shader_set_f("scale" , [ _xs, _ys ]);
shader_set_f("rotation" , _rot);
draw_surface_stretched_ext(surface, 0, 0, bdim[0], bdim[1], _col, _alpha);
shader_reset();
} #endregion
function draw_surface_part_ext_safe(surface, _l, _t, _w, _h, _x, _y, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.drawPart(_l, _t, _w, _h, _x, _y, _xs, _ys, _rot, _col, _alpha);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface_part_ext(surface, _l, _t, _w, _h, _x, _y, _xs, _ys, _col, _alpha);
__channel_pos(surface);
} #endregion
#endregion ==================================== DRAW ====================================
#region ==================================== CHECK ===================================
function is_surface(s) { #region
INLINE
if(is_instanceof(s, dynaSurf) || is_instanceof(s, SurfaceAtlas)) return true;
if(is_numeric(s) && s > 0 && surface_exists(s)) return true;
return false;
} #endregion
function surface_verify(surf, w, h, format = surface_rgba8unorm) { #region
INLINE
if(!is_surface(surf)) return surface_create_valid(w, h, format);
return surface_size_to(surf, w, h, format, true);
} #endregion
function surface_valid(surf, w, h, format = surface_rgba8unorm) { #region
INLINE
if(!is_surface(surf)) return false;
var _sw = surface_get_width(surf);
var _sh = surface_get_height(surf);
var _f = surface_get_format(surf);
return _sw == w && _sh == h && _f == format;
} #endregion
#endregion ==================================== CHECK ====================================
#region ==================================== GET =====================================
function surface_get_width_safe(s, crop = true) { #region
INLINE
if(is_struct(s)) {
if(is_instanceof(s, dynaSurf)) return s.getWidth();
else if(is_instanceof(s, SurfaceAtlas)) return crop? surface_get_width(s.getSurface()) : s.oriSurf_w;
else return 1;
}
return surface_get_width(s);
} #endregion
function surface_get_height_safe(s, crop = true) { #region
INLINE
if(is_struct(s)) {
if(is_instanceof(s, dynaSurf)) return s.getHeight();
else if(is_instanceof(s, SurfaceAtlas)) return crop? surface_get_height(s.getSurface()) : s.oriSurf_h;
else return 1;
}
return surface_get_height(s);
} #endregion
function surface_get_format_safe(s, crop = true) { #region
INLINE
if(is_struct(s)) {
if(is_instanceof(s, dynaSurf)) return s.getFormat();
else if(is_instanceof(s, SurfaceAtlas)) return surface_get_format(s.getSurface());
else return surface_rgba8unorm;
}
return surface_get_format(s);
} #endregion
function surface_get_dimension(s) { #region
INLINE
if(!is_surface(s)) return [ 1, 1 ];
return [ surface_get_width_safe(s), surface_get_height_safe(s) ];
} #endregion
function surface_get_pixel(surface, _x, _y) { #region
INLINE
if(!is_surface(surface)) return;
var f = surface_get_format(surface);
var fx = floor(_x);
var fy = floor(_y);
var rx = frac(_x);
var ry = frac(_y);
var px = surface_getpixel(surface, fx, fy);
if(rx == 0 && ry == 0) {
if(is_numeric(px)) return px;
return make_color_rgb(px[0] * 256, px[1] * 256, px[2] * 256);
}
var p1 = surface_getpixel(surface, fx + 1, fy + 0);
var p2 = surface_getpixel(surface, fx + 0, fy + 1);
var p3 = surface_getpixel(surface, fx + 1, fy + 1);
return merge_color(
merge_color(px, p1, rx),
merge_color(p2, p3, rx),
ry);
} #endregion
function surface_get_pixel_ext(surface, _x, _y) { #region
INLINE
if(!is_surface(surface)) return 0;
var px = surface_getpixel_ext(surface, _x, _y);
if(is_numeric(px)) return int64(px);
return round(px[0] * (255 * power(256, 0))) + round(px[1] * (255 * power(256, 1))) + round(px[2] * (255 * power(256, 2))) + round(px[3] * (255 * power(256, 3)));
} #endregion
#endregion ==================================== GET ====================================
#region =================================== CREATE ===================================
function surface_create_empty(w, h, format = surface_rgba8unorm) { #region
INLINE
var s = surface_create(w, h, format);
surface_clear(s);
return s;
} #endregion
function surface_create_size(surface, format = surface_rgba8unorm) { #region
INLINE
return surface_create_valid(surface_get_width_safe(surface), surface_get_height_safe(surface), format);
} #endregion
function surface_create_valid(w, h, format = surface_rgba8unorm) { #region
INLINE
return surface_create_empty(surface_valid_size(w), surface_valid_size(h), format);
} #endregion
function surface_create_from_buffer(w, h, buff, format = surface_rgba8unorm) { #region
INLINE
if(buff < 0) return;
var s = surface_create_valid(surface_valid_size(w), surface_valid_size(h), format);
buffer_set_surface(buff, s, 0);
return s;
} #endregion
function surface_from_buffer(buff) { #region
static header_length = 24;
if(!buffer_exists(buff)) return noone;
if(buffer_get_size(buff) < header_length) return noone;
buffer_seek(buff, buffer_seek_start, 0);
var text = "";
repeat(4) text += chr(buffer_read(buff, buffer_u8));
if(text != "PXCS") return noone;
var w = buffer_read(buff, buffer_u16);
var h = buffer_read(buff, buffer_u16);
var format = buffer_read(buff, buffer_u8);
if(w < 1 || h < 1) return noone;
var s = surface_create(w, h, format);
buffer_set_surface(buff, s, header_length);
return s;
} #endregion
function surface_create_from_sprite(spr) { #region
if(!sprite_exists(spr)) return noone;
if(sprite_get_number(spr) == 1)
return surface_create_from_sprite_ext(spr, 0);
var s = [];
for( var i = 0; i < sprite_get_number(spr); i++ ) {
array_push(s, surface_create_from_sprite_ext(spr, i));
}
return s;
} #endregion
function surface_create_from_sprite_ext(spr, ind, format = surface_rgba8unorm) { #region
if(!sprite_exists(spr)) return noone;
var sw = sprite_get_width(spr);
var sh = sprite_get_height(spr);
var s = surface_create_valid(sw, sh, format);
surface_set_target(s);
BLEND_OVERRIDE;
DRAW_CLEAR
draw_sprite(spr, ind, sprite_get_xoffset(spr), sprite_get_yoffset(spr));
BLEND_NORMAL
surface_reset_target();
return s;
} #endregion
function surface_size_lim(surface, width, height) { #region
var sw = surface_get_width_safe(surface);
var sh = surface_get_height_safe(surface);
if(sw <= width && sh <= height) return surface;
var ss = min(width / sw, height / sh);
var s = surface_create(max(1, sw * ss), max(1, sh * ss));
surface_set_target(s);
DRAW_CLEAR
draw_surface_ext_safe(surface, 0, 0, ss, ss, 0, c_white, 1);
surface_reset_target();
return s;
} #endregion
function surface_size_to(surface, width, height, format = noone, skipCheck = false) { #region
INLINE
if(!skipCheck && !is_surface(surface)) return surface;
if(!is_numeric(width) || !is_numeric(height)) return surface;
if(width < 1 && height < 1) return surface;
if(format != noone && format != surface_get_format(surface)) {
surface_free(surface);
return surface_create(width, height, format);
}
width = surface_valid_size(width);
height = surface_valid_size(height);
var ww = surface_get_width(surface);
var hh = surface_get_height(surface);
if(ww == width && hh == height) return surface;
surface_resize(surface, width, height);
//surface_clear(surface);
return surface;
} #endregion
function surface_clear(surface) { #region
INLINE
if(!is_surface(surface)) return;
surface_set_target(surface);
DRAW_CLEAR
surface_reset_target();
} #endregion
function surface_copy_from(dst, src, format = noone) { #region
INLINE
surface_set_target(dst);
DRAW_CLEAR
BLEND_OVERRIDE;
draw_surface_safe(src, 0, 0);
BLEND_NORMAL
surface_reset_target();
} #endregion
function surface_clone(surface, destination = noone, format = noone) { #region
INLINE
if(is_struct(surface) && is_instanceof(surface, dynaSurf))
return surface.clone();
if(!is_surface(surface)) return noone;
destination = surface_verify(destination, surface_get_width_safe(surface), surface_get_height_safe(surface), format == noone? surface_get_format(surface) : format);
surface_set_target(destination);
DRAW_CLEAR
BLEND_OVERRIDE;
draw_surface_safe(surface, 0, 0);
BLEND_NORMAL
surface_reset_target();
return destination;
} #endregion
#endregion ==================================== CREATE ====================================
#region =================================== MODIFY ===================================
function surface_stretch(surf, _w, _h) { #region
INLINE
if(!is_surface(surf)) return noone;
_w = surface_valid_size(_w);
_h = surface_valid_size(_h);
var _surf = surface_create(_w, _h);
surface_set_target(_surf);
DRAW_CLEAR
draw_surface_stretched(surf, 0, 0, _w, _h);
surface_reset_target();
surface_free(surf);
return _surf;
} #endregion
function surface_mirror(surf, _h, _v) { #region
INLINE
if(!is_surface(surf)) return noone;
var _surf = surface_create_size(surf);
surface_set_target(_surf);
DRAW_CLEAR
var x0 = _h * surface_get_width_safe(_surf);
var y0 = _v * surface_get_height_safe(_surf);
draw_surface_ext_safe(surf, x0, y0, _h * 2 - 1, _v * 2 - 1, 0, c_white, 1);
surface_reset_target();
surface_free(surf);
return _surf;
} #endregion
function surface_project_posterize(surf) { #region
INLINE
if(!PROJECT.attributes.palette_fix) return surf;
if(!is_surface(surf)) return surf;
var _surf = surface_create(surface_get_width(surf), surface_get_height(surf));
surface_set_shader(_surf, sh_posterize_palette);
shader_set_f("palette", PROJECT.palettes);
shader_set_i("keys", array_length(PROJECT.attributes.palette));
shader_set_i("alpha", 1);
draw_surface(surf, 0, 0);
surface_reset_shader();
surface_free(surf);
return _surf;
} #endregion
#endregion ==================================== MODIFY ====================================
#region =================================== OTHERS ===================================
function surface_copy_size(dest, source, format = noone) { #region
INLINE
if(!is_surface(dest)) return;
if(!is_surface(source)) return;
surface_size_to(dest, surface_get_width_safe(source), surface_get_height_safe(source), format);
surface_set_target(dest);
DRAW_CLEAR
surface_reset_target();
surface_copy_from(dest, source);
} #endregion
function surface_valid_size(s) { #region
INLINE
if(!is_numeric(s)) return 1;
if(is_infinity(s)) return 1;
return clamp(round(s), 1, 8196);
} #endregion
function surface_array_free(arr) { #region
INLINE
if(!is_array(arr)) {
if(is_surface(arr)) surface_free(arr);
return;
}
for( var i = 0, n = array_length(arr); i < n; i++ )
surface_array_free(arr[i]);
} #endregion
function surface_array_clone(arr) { #region
if(!is_array(arr)) {
if(is_surface(arr))
return surface_clone(arr);
else
return arr;
}
var _arr = [];
for( var i = 0, n = array_length(arr); i < n; i++ )
_arr[i] = surface_array_clone(arr[i]);
return _arr;
} #endregion
function surface_array_serialize(arr) { #region
INLINE
var _arr = __surface_array_serialize(arr);
return json_stringify(_arr);
} #endregion
function __surface_array_serialize(arr) { #region
if(!is_array(arr)) {
if(is_surface(arr)) {
var buff = buffer_create(surface_get_width_safe(arr) * surface_get_height_safe(arr) * 4, buffer_fixed, 1);
buffer_get_surface(buff, arr, 0);
var comp = buffer_compress(buff, 0, buffer_get_size(buff));
var enc = buffer_base64_encode(comp, 0, buffer_get_size(comp));
buffer_delete(buff);
return { width: surface_get_width_safe(arr), height: surface_get_height_safe(arr), buffer: enc };
} else
return arr;
}
var _arr = [];
for( var i = 0, n = array_length(arr); i < n; i++ )
_arr[i] = __surface_array_serialize(arr[i]);
return _arr;
} #endregion
function surface_array_deserialize(arr, index = -1) { #region
INLINE
var _arr = json_try_parse(arr);
return index == -1? __surface_array_deserialize(_arr) : __surface_array_deserialize(_arr[index]);
} #endregion
function __surface_array_deserialize(arr) { #region
if(!is_array(arr)) {
if(!is_struct(arr) || !struct_has(arr, "buffer"))
return noone;
var buff = buffer_base64_decode(arr.buffer);
buff = buffer_decompress(buff);
return surface_create_from_buffer(arr.width, arr.height, buff);
}
var _arr = [];
for( var i = 0, n = array_length(arr); i < n; i++ )
_arr[i] = __surface_array_deserialize(arr[i]);
return _arr;
} #endregion
function surface_encode(surface, stringify = true) { #region
if(!is_surface(surface)) return "";
var buff = buffer_create(surface_get_width_safe(surface) * surface_get_height_safe(surface) * 4, buffer_fixed, 1);
buffer_get_surface(buff, surface, 0);
var comp = buffer_compress(buff, 0, buffer_get_size(buff));
var enc = buffer_base64_encode(comp, 0, buffer_get_size(comp));
var str = { width: surface_get_width_safe(surface), height: surface_get_height_safe(surface), buffer: enc };
buffer_delete(buff);
return stringify? json_stringify(str) : str;
} #endregion
function surface_decode(struct) { #region
var buff = buffer_base64_decode(struct.buffer);
var buff = buffer_decompress(buff);
return surface_create_from_buffer(struct.width, struct.height, buff);
} #endregion
function surface_format_get_bytes(format) { #region
switch(format) {
case surface_rgba4unorm : return 4 * 0.5; break;
case surface_rgba8unorm : return 4 * 1; break;
case surface_rgba16float : return 4 * 2; break;
case surface_rgba32float : return 4 * 4; break;
case surface_r8unorm : return 1 * 1; break;
case surface_r16float : return 1 * 2; break;
case surface_r32float : return 1 * 3; break;
}
return 1;
} #endregion
function surface_get_size(surface) { #region
INLINE
var sw = surface_get_width_safe(surface);
var sh = surface_get_height_safe(surface);
var sz = sw * sh * surface_format_get_bytes(surface_get_format(surface));
return sz;
} #endregion
function surface_texture(surface) { #region
INLINE
if(!is_surface(surface)) return -1;
return surface_get_texture(surface);
} #endregion
#macro surface_free surface_free_safe
#macro __surface_free surface_free
function surface_free_safe(surface) { #region
INLINE
if(!is_surface(surface)) return;
__surface_free(surface);
} #endregion
function surface_save_safe(surface, path) { #region
if(!is_surface(surface)) return;
if(is_instanceof(surface, SurfaceAtlas)) surface = surface.surface.get();
else if(is_instanceof(surface, SurfaceAtlasFast)) surface = surface.surface;
else if(is_instanceof(surface, dynaSurf)) surface = array_safe_get(surface.surfaces, 0);
if(!surface_exists(surface)) return;
var f = surface_get_format(surface);
if(f == surface_rgba8unorm) {
surface_save(surface, path);
return;
}
var w = surface_get_width_safe(surface);
var h = surface_get_height_safe(surface);
var s = surface_create(w, h, surface_rgba8unorm);
switch(f) {
case surface_rgba4unorm :
case surface_rgba8unorm :
case surface_rgba16float :
case surface_rgba32float :
surface_set_shader(s, sh_draw_normal);
draw_surface(surface, 0, 0);
surface_reset_shader();
surface_save(s, path);
return;
case surface_r8unorm : s = surface_create(w, h, surface_rgba8unorm); break;
case surface_r16float : s = surface_create(w, h, surface_rgba16float); break;
case surface_r32float : s = surface_create(w, h, surface_rgba32float); break;
default: return;
}
surface_set_shader(s, sh_draw_single_channel);
draw_surface(surface, 0, 0);
surface_reset_shader();
surface_save(s, path);
surface_free(s);
return;
} #endregion
function surface_cvt_8unorm(target, surface) { #region
if(!is_surface(surface)) return target;
target = surface_verify(target, surface_get_width_safe(surface), surface_get_height_safe(surface));
var _typ = surface_get_format(surface);
switch(_typ) {
case surface_rgba4unorm :
case surface_rgba8unorm :
case surface_rgba16float :
case surface_rgba32float :
surface_set_shader(target, sh_draw_normal);
break;
case surface_r8unorm :
case surface_r16float :
case surface_r32float :
surface_set_shader(target, sh_draw_single_channel);
break;
}
draw_surface(surface, 0, 0);
surface_reset_shader();
return target;
} #endregion
#endregion =================================== OTHERS ===================================

View file

@ -0,0 +1,692 @@
// 2024-04-14 12:39:09
#region ==================================== DRAW ====================================
function draw_surface_safe(surface, _x = 0, _y = 0) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.draw(_x, _y);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface(surface, _x, _y);
__channel_pos(surface);
} #endregion
function draw_surface_stretched_safe(surface, _x, _y, _w, _h) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.drawStretch(_x, _y, _w, _h);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface_stretched(surface, _x, _y, _w, _h);
__channel_pos(surface);
} #endregion
function draw_surface_ext_safe(surface, _x = 0, _y = 0, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.draw(_x, _y, _xs, _ys, _rot, _col, _alpha);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface_ext(surface, _x, _y, _xs, _ys, _rot, _col, _alpha);
__channel_pos(surface);
} #endregion
function draw_surface_tiled_safe(surface, _x, _y) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.drawTile(_x, _y);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface_tiled(surface, _x, _y);
__channel_pos(surface);
} #endregion
function draw_surface_tiled_ext_safe(surface, _x, _y, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.drawTile(_x, _y, _xs, _ys, _col, _alpha);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
var back = surface_get_target();
var bdim = surface_get_dimension(back);
shader_set(sh_draw_tile);
shader_set_f("backDimension", bdim);
shader_set_f("foreDimension", surface_get_dimension(surface));
shader_set_f("position" , [ _x, _y ]);
shader_set_f("scale" , [ _xs, _ys ]);
shader_set_f("rotation" , _rot);
draw_surface_stretched_ext(surface, 0, 0, bdim[0], bdim[1], _col, _alpha);
shader_reset();
} #endregion
function draw_surface_part_ext_safe(surface, _l, _t, _w, _h, _x, _y, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
INLINE
if(is_struct(surface)) {
if(is_instanceof(surface, dynaSurf)) {
surface.drawPart(_l, _t, _w, _h, _x, _y, _xs, _ys, _rot, _col, _alpha);
return;
} else if(is_instanceof(surface, SurfaceAtlas))
surface = surface.getSurface();
}
if(!surface_exists(surface)) return;
__channel_pre(surface);
draw_surface_part_ext(surface, _l, _t, _w, _h, _x, _y, _xs, _ys, _col, _alpha);
__channel_pos(surface);
} #endregion
#endregion ==================================== DRAW ====================================
#region ==================================== CHECK ===================================
function is_surface(s) { #region
INLINE
if(is_instanceof(s, dynaSurf) || is_instanceof(s, SurfaceAtlas)) return true;
if(is_numeric(s) && s > 0 && surface_exists(s)) return true;
return false;
} #endregion
function surface_verify(surf, w, h, format = surface_rgba8unorm) { #region
INLINE
if(!is_surface(surf)) return surface_create_valid(w, h, format);
return surface_size_to(surf, w, h, format, true);
} #endregion
function surface_valid(surf, w, h, format = surface_rgba8unorm) { #region
INLINE
if(!is_surface(surf)) return false;
var _sw = surface_get_width(surf);
var _sh = surface_get_height(surf);
var _f = surface_get_format(surf);
return _sw == w && _sh == h && _f == format;
} #endregion
#endregion ==================================== CHECK ====================================
#region ==================================== GET =====================================
function surface_get_width_safe(s, crop = true) { #region
INLINE
if(is_struct(s)) {
if(is_instanceof(s, dynaSurf)) return s.getWidth();
else if(is_instanceof(s, SurfaceAtlas)) return crop? surface_get_width(s.getSurface()) : s.oriSurf_w;
else return 1;
}
return surface_get_width(s);
} #endregion
function surface_get_height_safe(s, crop = true) { #region
INLINE
if(is_struct(s)) {
if(is_instanceof(s, dynaSurf)) return s.getHeight();
else if(is_instanceof(s, SurfaceAtlas)) return crop? surface_get_height(s.getSurface()) : s.oriSurf_h;
else return 1;
}
return surface_get_height(s);
} #endregion
function surface_get_format_safe(s, crop = true) { #region
INLINE
if(is_struct(s)) {
if(is_instanceof(s, dynaSurf)) return s.getFormat();
else if(is_instanceof(s, SurfaceAtlas)) return surface_get_format(s.getSurface());
else return surface_rgba8unorm;
}
return surface_get_format(s);
} #endregion
function surface_get_dimension(s) { #region
INLINE
if(!is_surface(s)) return [ 1, 1 ];
return [ surface_get_width_safe(s), surface_get_height_safe(s) ];
} #endregion
function surface_get_pixel(surface, _x, _y) { #region
INLINE
if(!is_surface(surface)) return;
var f = surface_get_format(surface);
var fx = floor(_x);
var fy = floor(_y);
var rx = frac(_x);
var ry = frac(_y);
var px = surface_getpixel(surface, fx, fy);
if(rx == 0 && ry == 0) {
if(is_numeric(px)) return px;
return make_color_rgb(px[0] * 256, px[1] * 256, px[2] * 256);
}
var p1 = surface_getpixel(surface, fx + 1, fy + 0);
var p2 = surface_getpixel(surface, fx + 0, fy + 1);
var p3 = surface_getpixel(surface, fx + 1, fy + 1);
return merge_color(
merge_color(px, p1, rx),
merge_color(p2, p3, rx),
ry);
} #endregion
function surface_get_pixel_ext(surface, _x, _y) { #region
INLINE
if(!is_surface(surface)) return 0;
var px = surface_getpixel_ext(surface, _x, _y);
if(is_numeric(px)) return int64(px);
return round(px[0] * (255 * power(256, 0))) + round(px[1] * (255 * power(256, 1))) + round(px[2] * (255 * power(256, 2))) + round(px[3] * (255 * power(256, 3)));
} #endregion
#endregion ==================================== GET ====================================
#region =================================== CREATE ===================================
function surface_create_empty(w, h, format = surface_rgba8unorm) { #region
INLINE
var s = surface_create(w, h, format);
surface_clear(s);
return s;
} #endregion
function surface_create_size(surface, format = surface_rgba8unorm) { #region
INLINE
return surface_create_valid(surface_get_width_safe(surface), surface_get_height_safe(surface), format);
} #endregion
function surface_create_valid(w, h, format = surface_rgba8unorm) { #region
INLINE
return surface_create_empty(surface_valid_size(w), surface_valid_size(h), format);
} #endregion
function surface_create_from_buffer(w, h, buff, format = surface_rgba8unorm) { #region
INLINE
if(buff < 0) return;
var s = surface_create_valid(surface_valid_size(w), surface_valid_size(h), format);
buffer_set_surface(buff, s, 0);
return s;
} #endregion
function surface_from_buffer(buff) { #region
static header_length = 24;
if(!buffer_exists(buff)) return noone;
if(buffer_get_size(buff) < header_length) return noone;
buffer_seek(buff, buffer_seek_start, 0);
var text = "";
repeat(4) text += chr(buffer_read(buff, buffer_u8));
if(text != "PXCS") return noone;
var w = buffer_read(buff, buffer_u16);
var h = buffer_read(buff, buffer_u16);
var format = buffer_read(buff, buffer_u8);
if(w < 1 || h < 1) return noone;
var s = surface_create(w, h, format);
buffer_set_surface(buff, s, header_length);
return s;
} #endregion
function surface_create_from_sprite(spr) { #region
if(!sprite_exists(spr)) return noone;
if(sprite_get_number(spr) == 1)
return surface_create_from_sprite_ext(spr, 0);
var s = [];
for( var i = 0; i < sprite_get_number(spr); i++ ) {
array_push(s, surface_create_from_sprite_ext(spr, i));
}
return s;
} #endregion
function surface_create_from_sprite_ext(spr, ind, format = surface_rgba8unorm) { #region
if(!sprite_exists(spr)) return noone;
var sw = sprite_get_width(spr);
var sh = sprite_get_height(spr);
var s = surface_create_valid(sw, sh, format);
surface_set_target(s);
BLEND_OVERRIDE;
DRAW_CLEAR
draw_sprite(spr, ind, sprite_get_xoffset(spr), sprite_get_yoffset(spr));
BLEND_NORMAL
surface_reset_target();
return s;
} #endregion
function surface_size_lim(surface, width, height) { #region
var sw = surface_get_width_safe(surface);
var sh = surface_get_height_safe(surface);
if(sw <= width && sh <= height) return surface;
var ss = min(width / sw, height / sh);
var s = surface_create(max(1, sw * ss), max(1, sh * ss));
surface_set_target(s);
DRAW_CLEAR
draw_surface_ext_safe(surface, 0, 0, ss, ss, 0, c_white, 1);
surface_reset_target();
return s;
} #endregion
function surface_size_to(surface, width, height, format = noone, skipCheck = false) { #region
INLINE
if(!skipCheck && !is_surface(surface)) return surface;
if(!is_numeric(width) || !is_numeric(height)) return surface;
if(width < 1 && height < 1) return surface;
if(format != noone && format != surface_get_format(surface)) {
surface_free(surface);
return surface_create(width, height, format);
}
width = surface_valid_size(width);
height = surface_valid_size(height);
var ww = surface_get_width(surface);
var hh = surface_get_height(surface);
if(ww == width && hh == height) return surface;
surface_resize(surface, width, height);
//surface_clear(surface);
return surface;
} #endregion
function surface_clear(surface) { #region
INLINE
if(!is_surface(surface)) return;
surface_set_target(surface);
DRAW_CLEAR
surface_reset_target();
} #endregion
function surface_copy_from(dst, src, format = noone) { #region
INLINE
surface_set_target(dst);
DRAW_CLEAR
BLEND_OVERRIDE;
draw_surface_safe(src, 0, 0);
BLEND_NORMAL
surface_reset_target();
} #endregion
function surface_clone(surface, destination = noone, format = noone) { #region
INLINE
if(is_struct(surface) && is_instanceof(surface, dynaSurf))
return surface.clone();
if(!is_surface(surface)) return noone;
destination = surface_verify(destination, surface_get_width_safe(surface), surface_get_height_safe(surface), format == noone? surface_get_format(surface) : format);
surface_set_target(destination);
DRAW_CLEAR
BLEND_OVERRIDE;
draw_surface_safe(surface, 0, 0);
BLEND_NORMAL
surface_reset_target();
return destination;
} #endregion
#endregion ==================================== CREATE ====================================
#region =================================== MODIFY ===================================
function surface_stretch(surf, _w, _h) { #region
INLINE
if(!is_surface(surf)) return noone;
_w = surface_valid_size(_w);
_h = surface_valid_size(_h);
var _surf = surface_create(_w, _h);
surface_set_target(_surf);
DRAW_CLEAR
draw_surface_stretched(surf, 0, 0, _w, _h);
surface_reset_target();
surface_free(surf);
return _surf;
} #endregion
function surface_mirror(surf, _h, _v) { #region
INLINE
if(!is_surface(surf)) return noone;
var _surf = surface_create_size(surf);
surface_set_target(_surf);
DRAW_CLEAR
var x0 = _h * surface_get_width_safe(_surf);
var y0 = _v * surface_get_height_safe(_surf);
draw_surface_ext_safe(surf, x0, y0, _h * 2 - 1, _v * 2 - 1, 0, c_white, 1);
surface_reset_target();
surface_free(surf);
return _surf;
} #endregion
function surface_project_posterize(surf) { #region
INLINE
if(!PROJECT.attributes.palette_fix) return surf;
if(!is_surface(surf)) return surf;
var _surf = surface_create(surface_get_width(surf), surface_get_height(surf));
surface_set_shader(_surf, sh_posterize_palette);
shader_set_f("palette", PROJECT.palettes);
shader_set_i("keys", array_length(PROJECT.attributes.palette));
shader_set_i("alpha", 1);
draw_surface(surf, 0, 0);
surface_reset_shader();
surface_free(surf);
return _surf;
} #endregion
#endregion ==================================== MODIFY ====================================
#region =================================== OTHERS ===================================
function surface_copy_size(dest, source, format = noone) { #region
INLINE
if(!is_surface(dest)) return;
if(!is_surface(source)) return;
surface_size_to(dest, surface_get_width_safe(source), surface_get_height_safe(source), format);
surface_set_target(dest);
DRAW_CLEAR
surface_reset_target();
surface_copy_from(dest, source);
} #endregion
function surface_valid_size(s) { #region
INLINE
if(!is_numeric(s)) return 1;
if(is_infinity(s)) return 1;
return clamp(round(s), 1, 8196);
} #endregion
function surface_array_free(arr) { #region
INLINE
if(!is_array(arr)) {
if(is_surface(arr)) surface_free(arr);
return;
}
for( var i = 0, n = array_length(arr); i < n; i++ )
surface_array_free(arr[i]);
} #endregion
function surface_array_clone(arr) { #region
if(!is_array(arr)) {
if(is_surface(arr))
return surface_clone(arr);
else
return arr;
}
var _arr = [];
for( var i = 0, n = array_length(arr); i < n; i++ )
_arr[i] = surface_array_clone(arr[i]);
return _arr;
} #endregion
function surface_array_serialize(arr) { #region
INLINE
var _arr = __surface_array_serialize(arr);
return json_stringify(_arr);
} #endregion
function __surface_array_serialize(arr) { #region
if(!is_array(arr)) {
if(is_surface(arr)) {
var buff = buffer_create(surface_get_width_safe(arr) * surface_get_height_safe(arr) * 4, buffer_fixed, 1);
buffer_get_surface(buff, arr, 0);
var comp = buffer_compress(buff, 0, buffer_get_size(buff));
var enc = buffer_base64_encode(comp, 0, buffer_get_size(comp));
buffer_delete(buff);
return { width: surface_get_width_safe(arr), height: surface_get_height_safe(arr), buffer: enc };
} else
return arr;
}
var _arr = [];
for( var i = 0, n = array_length(arr); i < n; i++ )
_arr[i] = __surface_array_serialize(arr[i]);
return _arr;
} #endregion
function surface_array_deserialize(arr, index = -1) { #region
INLINE
var _arr = json_try_parse(arr);
return index == -1? __surface_array_deserialize(_arr) : __surface_array_deserialize(_arr[index]);
} #endregion
function __surface_array_deserialize(arr) { #region
if(!is_array(arr)) {
if(!is_struct(arr) || !struct_has(arr, "buffer"))
return noone;
var buff = buffer_base64_decode(arr.buffer);
buff = buffer_decompress(buff);
return surface_create_from_buffer(arr.width, arr.height, buff);
}
var _arr = [];
for( var i = 0, n = array_length(arr); i < n; i++ )
_arr[i] = __surface_array_deserialize(arr[i]);
return _arr;
} #endregion
function surface_encode(surface, stringify = true) { #region
if(!is_surface(surface)) return "";
var buff = buffer_create(surface_get_width_safe(surface) * surface_get_height_safe(surface) * 4, buffer_fixed, 1);
buffer_get_surface(buff, surface, 0);
var comp = buffer_compress(buff, 0, buffer_get_size(buff));
var enc = buffer_base64_encode(comp, 0, buffer_get_size(comp));
var str = { width: surface_get_width_safe(surface), height: surface_get_height_safe(surface), buffer: enc };
buffer_delete(buff);
return stringify? json_stringify(str) : str;
} #endregion
function surface_decode(struct) { #region
var buff = buffer_base64_decode(struct.buffer);
var buff = buffer_decompress(buff);
return surface_create_from_buffer(struct.width, struct.height, buff);
} #endregion
function surface_format_get_bytes(format) { #region
switch(format) {
case surface_rgba4unorm : return 4 * 0.5; break;
case surface_rgba8unorm : return 4 * 1; break;
case surface_rgba16float : return 4 * 2; break;
case surface_rgba32float : return 4 * 4; break;
case surface_r8unorm : return 1 * 1; break;
case surface_r16float : return 1 * 2; break;
case surface_r32float : return 1 * 3; break;
}
return 1;
} #endregion
function surface_get_size(surface) { #region
INLINE
var sw = surface_get_width_safe(surface);
var sh = surface_get_height_safe(surface);
var sz = sw * sh * surface_format_get_bytes(surface_get_format(surface));
return sz;
} #endregion
function surface_texture(surface) { #region
INLINE
if(!is_surface(surface)) return -1;
return surface_get_texture(surface);
} #endregion
#macro surface_free surface_free_safe
#macro __surface_free surface_free
function surface_free_safe(surface) { #region
INLINE
if(!is_surface(surface)) return;
__surface_free(surface);
} #endregion
function surface_save_safe(surface, path) { #region
if(!is_surface(surface)) return;
if(is_instanceof(surface, SurfaceAtlas)) surface = surface.surface.get();
else if(is_instanceof(surface, SurfaceAtlasFast)) surface = surface.surface;
else if(is_instanceof(surface, dynaSurf)) surface = array_safe_get(surface.surfaces, 0);
if(!surface_exists(surface)) return;
var f = surface_get_format(surface);
if(f == surface_rgba8unorm) {
surface_save(surface, path);
return;
}
var w = surface_get_width_safe(surface);
var h = surface_get_height_safe(surface);
var s = surface_create(w, h, surface_rgba8unorm);
switch(f) {
case surface_rgba4unorm :
case surface_rgba8unorm :
case surface_rgba16float :
case surface_rgba32float :
surface_set_shader(s, sh_draw_normal);
draw_surface(surface, 0, 0);
surface_reset_shader();
surface_save(s, path);
return;
case surface_r8unorm : s = surface_create(w, h, surface_rgba8unorm); break;
case surface_r16float : s = surface_create(w, h, surface_rgba16float); break;
case surface_r32float : s = surface_create(w, h, surface_rgba32float); break;
default: return;
}
surface_set_shader(s, sh_draw_single_channel);
draw_surface(surface, 0, 0);
surface_reset_shader();
surface_save(s, path);
surface_free(s);
return;
} #endregion
function surface_cvt_8unorm(target, surface) { #region
if(!is_surface(surface)) return target;
target = surface_verify(target, surface_get_width_safe(surface), surface_get_height_safe(surface));
var _typ = surface_get_format(surface);
switch(_typ) {
case surface_rgba4unorm :
case surface_rgba8unorm :
case surface_rgba16float :
case surface_rgba32float :
surface_set_shader(target, sh_draw_normal);
break;
case surface_r8unorm :
case surface_r16float :
case surface_r32float :
surface_set_shader(target, sh_draw_single_channel);
break;
}
draw_surface(surface, 0, 0);
surface_reset_shader();
return target;
} #endregion
#endregion =================================== OTHERS ===================================

View file

@ -357,6 +357,7 @@
{"name":"canvas_tool_extrude","order":1,"path":"scripts/canvas_tool_extrude/canvas_tool_extrude.yy",},
{"name":"canvas_tool_fill","order":4,"path":"scripts/canvas_tool_fill/canvas_tool_fill.yy",},
{"name":"canvas_tool_inset","order":2,"path":"scripts/canvas_tool_inset/canvas_tool_inset.yy",},
{"name":"canvas_tool_node","order":12,"path":"scripts/canvas_tool_node/canvas_tool_node.yy",},
{"name":"canvas_tool_outline","order":3,"path":"scripts/canvas_tool_outline/canvas_tool_outline.yy",},
{"name":"canvas_tool_resize","order":11,"path":"scripts/canvas_tool_resize/canvas_tool_resize.yy",},
{"name":"canvas_tool_selection_freeform","order":8,"path":"scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.yy",},
@ -1126,7 +1127,7 @@
{"name":"safe_operation","order":6,"path":"scripts/safe_operation/safe_operation.yy",},
{"name":"sample_projects","order":6,"path":"scripts/sample_projects/sample_projects.yy",},
{"name":"save_function","order":1,"path":"scripts/save_function/save_function.yy",},
{"name":"canvas_tool_node","order":12,"path":"scripts/canvas_tool_node/canvas_tool_node.yy",},
{"name":"canvas_tool_selection_brush","order":13,"path":"scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.yy",},
{"name":"scrollBox","order":2,"path":"scripts/scrollBox/scrollBox.yy",},
{"name":"scrollPane","order":3,"path":"scripts/scrollPane/scrollPane.yy",},
{"name":"shell_functions","order":20,"path":"scripts/shell_functions/shell_functions.yy",},

View file

@ -718,6 +718,7 @@
{"id":{"name":"canvas_tool_extrude","path":"scripts/canvas_tool_extrude/canvas_tool_extrude.yy",},},
{"id":{"name":"canvas_tool_fill","path":"scripts/canvas_tool_fill/canvas_tool_fill.yy",},},
{"id":{"name":"canvas_tool_inset","path":"scripts/canvas_tool_inset/canvas_tool_inset.yy",},},
{"id":{"name":"canvas_tool_node","path":"scripts/canvas_tool_node/canvas_tool_node.yy",},},
{"id":{"name":"canvas_tool_outline","path":"scripts/canvas_tool_outline/canvas_tool_outline.yy",},},
{"id":{"name":"canvas_tool_resize","path":"scripts/canvas_tool_resize/canvas_tool_resize.yy",},},
{"id":{"name":"canvas_tool_selection_freeform","path":"scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.yy",},},
@ -1607,7 +1608,7 @@
{"id":{"name":"safe_operation","path":"scripts/safe_operation/safe_operation.yy",},},
{"id":{"name":"sample_projects","path":"scripts/sample_projects/sample_projects.yy",},},
{"id":{"name":"save_function","path":"scripts/save_function/save_function.yy",},},
{"id":{"name":"canvas_tool_node","path":"scripts/canvas_tool_node/canvas_tool_node.yy",},},
{"id":{"name":"canvas_tool_selection_brush","path":"scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.yy",},},
{"id":{"name":"scrollBox","path":"scripts/scrollBox/scrollBox.yy",},},
{"id":{"name":"scrollPane","path":"scripts/scrollPane/scrollPane.yy",},},
{"id":{"name":"shader_functions","path":"scripts/shader_functions/shader_functions.yy",},},

View file

@ -6,6 +6,7 @@ function canvas_brush() constructor {
brush_sizing_dx = 0;
brush_sizing_dy = 0;
brush_use_surface = false;
brush_surface = noone;
brush_size = 1;
brush_dist_min = 1;
@ -38,6 +39,13 @@ function canvas_brush() constructor {
brush_dist_min = max(1, _brushDist[0]);
brush_dist_max = max(1, _brushDist[1]);
if(brush_use_surface) {
if(!is_surface(brush_surface)) {
brush_surface = noone;
brush_use_surface = false;
}
} else
brush_surface = is_surface(_brushSurf)? _brushSurf : noone;
if(!_brushRotD)

View file

@ -1,6 +1,7 @@
function canvas_tool() constructor {
node = noone;
rightTools = [];
override = false;
relative = false;
@ -17,20 +18,13 @@ function canvas_tool() constructor {
function init() {}
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
}
function drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
}
function drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
}
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function drawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
}

View file

@ -1,8 +1,12 @@
function canvas_tool_shader() : canvas_tool() constructor {
mask = false;
override = true;
mouse_init = false;
mask_boundary_init = [ 0, 0, 1, 1 ];
mask_boundary = [ 0, 0, 1, 1 ];
preview_surface = [ noone, noone ];
function init() { mouse_init = true; }
@ -10,36 +14,58 @@ function canvas_tool_shader() : canvas_tool() constructor {
function onInit(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function stepEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function stepMaskEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
if(mouse_press(mb_right)) {
PANEL_PREVIEW.tool_current = noone;
return;
}
var _dim = node.attributes.dimension;
var _sel = node.tool_selection;
var _surf = _sel.selection_surface;
var _pos = _sel.selection_position;
preview_surface[0] = surface_verify(preview_surface[0], _dim[0], _dim[1]);
preview_surface[1] = surface_verify(preview_surface[1], _dim[0], _dim[1]);
if(mouse_init) {
mask = key_mod_press(SHIFT);
mask_boundary_init = [ _sel.selection_position[0], _sel.selection_position[1], _sel.selection_size[0], _sel.selection_size[1] ];
mask_boundary = [ _sel.selection_position[0], _sel.selection_position[1], _sel.selection_size[0], _sel.selection_size[1] ];
if(mask) _sel.apply();
onInit(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
mouse_init = false;
return;
}
var _surf = mask? _sel.selection_mask : _sel.selection_surface;
var _pos = _sel.selection_position;
surface_set_shader(preview_surface[0], noone);
draw_surface(_surf, _pos[0], _pos[1]);
surface_reset_shader();
stepEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
if(mask) {
stepMaskEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
if(mouse_release(mb_left)) {
var _newSurf = surface_create(mask_boundary[2], mask_boundary[3]);
surface_set_shader(_newSurf, noone);
draw_surface(preview_surface[1], -mask_boundary[0], -mask_boundary[1]);
surface_reset_shader();
_sel.createNewSelection(_newSurf, mask_boundary[0], mask_boundary[1], mask_boundary[2], mask_boundary[3]);
PANEL_PREVIEW.tool_current = noone;
MOUSE_BLOCK = true;
}
} else {
stepEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
draw_surface_ext(preview_surface[1], _x, _y, _s, _s, 0, c_white, 1);
if(mouse_press(mb_right)) {
PANEL_PREVIEW.tool_current = noone;
} else if(mouse_release(mb_left)) {
if(mouse_release(mb_left)) {
var _newSurf = surface_create(_dim[0], _dim[1]);
surface_set_shader(_newSurf, noone);
draw_surface(preview_surface[1], 0, 0);
@ -56,5 +82,11 @@ function canvas_tool_shader() : canvas_tool() constructor {
MOUSE_BLOCK = true;
}
}
}
function drawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
if(!mask) return;
draw_surface_ext_safe(preview_surface[1], _x, _y, _s, _s);
}
}

View file

@ -6,7 +6,7 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
applySelection = canvas.tool_selection.is_selected;
destiSurface = applySelection? canvas.tool_selection.selection_surface : canvas._canvas_surface;
destiSurface = applySelection? canvas.tool_selection.selection_surface : canvas.getCanvasSurface();
if(!is_surface(destiSurface)) {
canvas.nodeTool = noone;
return;
@ -22,9 +22,10 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
surface_reset_shader();
static destroy = function() {
noti_warning("Selected node has no surface output.");
if(applySelection) canvas.tool_selection.apply();
canvas.nodeTool = noone;
if(nodeObject != noone)
nodeObject.cleanUp();
surface_free(targetSurface);
surface_free(maskedSurface);
@ -32,7 +33,7 @@ function canvas_tool_node(canvas, node) : canvas_tool() constructor {
nodeObject = node.build(0, 0);
if(nodeObject == noone) {
if(nodeObject == noone || !is_instanceof(nodeObject, Node)) {
destroy();
return;
}

View file

@ -26,4 +26,47 @@ function canvas_tool_outline() : canvas_tool_shader() constructor {
surface_reset_shader();
}
function stepMaskEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
var _dim = node.attributes.dimension;
var _thck = abs(round((_mx - mouse_sx) / _s));
var _side = _mx > mouse_sx;
if(_side) {
surface_set_shader(preview_surface[1], sh_outline);
shader_set_f("dimension", _dim);
shader_set_f("borderSize", _thck, _thck);
shader_set_f("borderStart", 0, 0);
shader_set_i("side", _side);
shader_set_color("borderColor", c_white);
draw_surface(preview_surface[0], 0, 0);
surface_reset_shader();
mask_boundary[0] = mask_boundary_init[0] - _thck;
mask_boundary[1] = mask_boundary_init[1] - _thck;
mask_boundary[2] = mask_boundary_init[2] + _thck * 2;
mask_boundary[3] = mask_boundary_init[3] + _thck * 2;
} else {
surface_set_shader(preview_surface[1], sh_erode);
shader_set_f("dimension", _dim);
shader_set_f("size", _thck, _thck);
shader_set_i("border", 0);
shader_set_i("alpha", 1);
draw_surface(preview_surface[0], 0, 0);
surface_reset_shader();
mask_boundary[0] = mask_boundary_init[0] + _thck;
mask_boundary[1] = mask_boundary_init[1] + _thck;
mask_boundary[2] = mask_boundary_init[2] - _thck * 2;
mask_boundary[3] = mask_boundary_init[3] - _thck * 2;
}
}
}

View file

@ -33,7 +33,7 @@ function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
else
createNewSelection(_mask, sel_x0, sel_y0, sel_w, sel_h);
}
} #endregion
function modifySelection(_mask, sel_x0, sel_y0, sel_w, sel_h, _add) { #region
if(sel_w == 1 && sel_h == 1) return;
@ -218,7 +218,7 @@ function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
var sel_w = surface_get_width_safe(selection_surface);
var sel_h = surface_get_height_safe(selection_surface);
if(point_in_rectangle(mouse_cur_x, mouse_cur_y, pos_x, pos_y, pos_x + sel_w, pos_y + sel_h)) {
if(point_in_rectangle(mouse_cur_x, mouse_cur_y, pos_x, pos_y, pos_x + sel_w, pos_y + sel_h) && surface_get_pixel_ext(selection_mask, mouse_cur_x, mouse_cur_y)) {
is_select_drag = true;
selection_sx = pos_x;
selection_sy = pos_y;
@ -244,15 +244,25 @@ function canvas_tool_selection(selector = noone) : canvas_tool() constructor {
else if(is_surface(selection_surface)) { apply(); }
} #endregion
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
if(is_selected)
draw_surface_safe(selection_surface, selection_position[0], selection_position[1]);
function onDrawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {}
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);
function drawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
var sel_x0, sel_y0;
if(is_selecting) {
sel_x0 = min(selection_sx, mouse_cur_x);
sel_y0 = min(selection_sy, mouse_cur_y);
} else {
sel_x0 = selection_position[0];
sel_y0 = selection_position[1];
}
var _dx = _x + sel_x0 * _s;
var _dy = _y + sel_y0 * _s;
draw_surface_ext_safe(selection_mask, _dx, _dy, _s, _s);
onDrawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
} #endregion
function drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region

View file

@ -0,0 +1,91 @@
function canvas_tool_selection_brush(selector, brush) : canvas_tool_selection(selector) constructor {
self.brush = brush;
brush_resizable = true;
mouse_cur_x = 0;
mouse_cur_y = 0;
mouse_pre_x = 0;
mouse_pre_y = 0;
mouse_pre_draw_x = undefined;
mouse_pre_draw_y = undefined;
sel_x0 = 0;
sel_y0 = 0;
sel_x1 = 0;
sel_y1 = 0;
function step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
attributes = node.attributes;
var _dim = attributes.dimension;
mouse_cur_x = round((_mx - _x) / _s - 0.5);
mouse_cur_y = round((_my - _y) / _s - 0.5);
if(!selector.is_select_drag && mouse_press(mb_left, active)) {
selection_mask = surface_verify(selection_mask, _dim[0], _dim[1]);
surface_set_shader(selection_mask, noone);
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y, true);
surface_reset_shader();
is_selecting = true;
mouse_pre_draw_x = mouse_cur_x;
mouse_pre_draw_y = mouse_cur_y;
sel_x0 = mouse_cur_x - brush.brush_size;
sel_y0 = mouse_cur_y - brush.brush_size;
sel_x1 = mouse_cur_x + brush.brush_size;
sel_y1 = mouse_cur_y + brush.brush_size;
}
if(is_selecting) {
var _move = mouse_pre_draw_x != mouse_cur_x || mouse_pre_draw_y != mouse_cur_y;
var _1stp = brush.brush_dist_min == brush.brush_dist_max && brush.brush_dist_min == 1;
if(_move || !_1stp) {
surface_set_target(selection_mask);
BLEND_ADD
if(_1stp) canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y, true);
canvas_draw_line_size(brush, mouse_pre_draw_x, mouse_pre_draw_y, mouse_cur_x, mouse_cur_y, true);
BLEND_NORMAL
surface_reset_target();
}
mouse_pre_draw_x = mouse_cur_x;
mouse_pre_draw_y = mouse_cur_y;
sel_x0 = min(sel_x0, mouse_cur_x - brush.brush_size);
sel_y0 = min(sel_y0, mouse_cur_y - brush.brush_size);
sel_x1 = max(sel_x1, mouse_cur_x + brush.brush_size);
sel_y1 = max(sel_y1, mouse_cur_y + brush.brush_size);
if(mouse_release(mb_left)) {
var _sel_w = sel_x1 - sel_x0;
var _sel_h = sel_y1 - sel_y0;
var _sel = surface_create(_sel_w, _sel_h);
surface_set_shader(_sel);
draw_surface(selection_mask, -sel_x0, -sel_y0);
surface_reset_shader();
is_selecting = false;
selector.createSelection(_sel, sel_x0, sel_y0, _sel_w, _sel_h);
surface_free_safe(selection_mask);
}
}
BLEND_NORMAL;
mouse_pre_x = mouse_cur_x;
mouse_pre_y = mouse_cur_y;
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -0,0 +1,13 @@
{
"$GMScript":"",
"%Name":"canvas_tool_selection_brush",
"isCompatibility":false,
"isDnD":false,
"name":"canvas_tool_selection_brush",
"parent":{
"name":"tools",
"path":"folders/nodes/data/canvas/tools.yy",
},
"resourceType":"GMScript",
"resourceVersion":"2.0",
}

View file

@ -86,4 +86,7 @@ function canvas_tool_selection_freeform(selector, brush) : canvas_tool_selection
}
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -57,4 +57,7 @@ function canvas_tool_selection_magic(selector, toolAttr) : canvas_tool_selection
}
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -51,4 +51,7 @@ function canvas_tool_selection_shape(selector, shape) : canvas_tool_selection(se
}
}
function drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
canvas_draw_point_size(brush, mouse_cur_x, mouse_cur_y);
}
}

View file

@ -179,10 +179,11 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
prev_surface = surface_create_empty(1, 1);
preview_draw_surface = surface_create_empty(1, 1);
_preview_draw_surface = surface_create_empty(1, 1);
preview_draw_mask = surface_create_empty(1, 1);
draw_stack = ds_list_create();
brush = new canvas_brush();
#endregion
#region ++++ tools ++++
@ -195,7 +196,13 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
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.mirror = [ false, false ];
tool_mirror_edit = new checkBoxGroup( THEME.canvas_mirror, function(ind, val) { tool_attribute.mirror[ind] = val; });
tool_settings = [ [ "", tool_channel_edit, "channel", tool_attribute ],
[ "", tool_drawLayer_edit, "drawLayer", tool_attribute ],
[ "", tool_mirror_edit, "mirror", tool_attribute ],
];
tool_attribute.size = 1;
tool_size_edit = new textBox(TEXTBOX_INPUT.number, function(val) { tool_attribute.size = max(1, round(val)); }).setSlidable(0.1, true, [ 1, 999999 ])
@ -216,7 +223,7 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
tool_fil8 = [ "Diagonal", tool_fil8_edit, "fill8", tool_attribute ];
tools = [
new NodeTool( "Selection", [ THEME.canvas_tools_selection_rectangle, THEME.canvas_tools_selection_circle, THEME.canvas_tools_freeform_selection ]),
new NodeTool( "Selection", [ THEME.canvas_tools_selection_rectangle, THEME.canvas_tools_selection_circle, THEME.canvas_tools_freeform_selection, THEME.canvas_tools_selection_brush ]),
new NodeTool( "Magic Selection", THEME.canvas_tools_magic_selection )
.setSetting(tool_thrs)
@ -255,6 +262,7 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
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);
tool_sel_brush = new canvas_tool_selection_brush(tool_selection, brush);
#endregion
@ -264,15 +272,31 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
__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); });
__action_add_node = method(self, function(ctx) { dialogCall(o_dialog_add_node, mouse_mx + 8, mouse_my + 8, { context: ctx }); });
__action_make_brush = method(self, function() {
if(brush.brush_use_surface) {
brush.brush_surface = noone;
brush.brush_use_surface = false;
return;
}
var _surf = tool_selection.selection_surface;
var _bsurf = surface_create(surface_get_width(_surf) + 2, surface_get_height(_surf) + 2);
surface_set_target(_bsurf);
DRAW_CLEAR
draw_surface(_surf, 1, 1);
surface_reset_target();
brush.brush_use_surface = true;
brush.brush_surface = _bsurf;
tool_selection.apply();
PANEL_PREVIEW.tool_current = tools[2];
});
nodeTool = noone;
nodeToolPreview = new NodeTool( "Apply Node", THEME.canvas_resize, self ).setToolFn( __action_add_node );
nodeToolPreview = new NodeTool( "Apply Node", THEME.canvas_tools_node, self ).setToolFn( __action_add_node );
rightTools_general = [
nodeToolPreview,
-1,
new NodeTool( "Resize Canvas", THEME.canvas_resize ).setToolObject( new canvas_tool_resize() ),
new NodeTool( [ "Rotate 90 CW", "Rotate 90 CCW" ],
@ -285,13 +309,26 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
];
rightTools_selection = [
-1,
new NodeTool( "Make/Reset Brush", THEME.canvas_tools_pencil ).setToolFn( __action_make_brush ),
-1,
new NodeTool( "Outline", THEME.canvas_tools_outline ).setToolObject( new canvas_tool_outline() ),
new NodeTool( [ "Extrude", "Inset" ],
[ THEME.canvas_tools_extrude, THEME.canvas_tools_inset ] )
.setToolObject( [ new canvas_tool_extrude(), new canvas_tool_inset() ] ),
];
rightTools_brush = [
-1,
new NodeTool( "Make/Reset Brush", THEME.canvas_tools_pencil ).setToolFn( __action_make_brush ),
];
rightTools = rightTools_general;
tool_brush.rightTools = rightTools_brush;
tool_eraser.rightTools = rightTools_brush;
tool_rectangle.rightTools = rightTools_brush;
tool_ellipse.rightTools = rightTools_brush;
#endregion
function setToolColor(color) { tool_attribute.color = color; }
@ -474,16 +511,31 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
function apply_draw_surface() { #region
var _can = getCanvasSurface();
var _drw = drawing_surface;
var _dim = attributes.dimension;
var _tmp;
storeAction();
if(tool_selection.is_selected) {
var _tmp = surface_create(surface_get_width(tool_selection.selection_mask), surface_get_height(tool_selection.selection_mask));
var _spx = tool_selection.selection_position[0];
var _spy = tool_selection.selection_position[1];
var _spw = tool_selection.selection_size[0];
var _sph = tool_selection.selection_size[1];
surface_set_target(_tmp);
DRAW_CLEAR
draw_surface(drawing_surface, -tool_selection.selection_position[0], -tool_selection.selection_position[1]);
draw_surface(drawing_surface, -_spx, -_spy);
BLEND_ALPHA
if(tool_attribute.mirror[0]) draw_surface_ext_safe(drawing_surface, _spx * 2 + _spw - _spx, -_spy, -1, 1);
if(tool_attribute.mirror[1]) draw_surface_ext_safe(drawing_surface, -_spx, _spy * 2 + _sph - _spy, 1, -1);
if(tool_attribute.mirror[0] && tool_attribute.mirror[1]) draw_surface_ext_safe(drawing_surface, _spx * 2 + _spw - _spx, _spy * 2 + _sph - _spy, -1, -1);
BLEND_NORMAL
BLEND_MULTIPLY
draw_surface(tool_selection.selection_mask, 0, 0);
@ -491,7 +543,24 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
surface_reset_target();
_can = tool_selection.selection_surface;
_drw = _tmp;
} else {
var _tmp = surface_create(_dim[0], _dim[1]);
surface_set_target(_tmp);
DRAW_CLEAR
BLEND_OVERRIDE
draw_surface(drawing_surface, 0, 0);
BLEND_ALPHA
if(tool_attribute.mirror[0]) draw_surface_ext_safe(drawing_surface, _dim[0], 0, -1, 1);
if(tool_attribute.mirror[1]) draw_surface_ext_safe(drawing_surface, 0, _dim[1], 1, -1);
if(tool_attribute.mirror[0] && tool_attribute.mirror[1]) draw_surface_ext_safe(drawing_surface, _dim[0], _dim[1], -1, -1);
BLEND_NORMAL
surface_reset_target();
}
var _sw = surface_get_width(_can);
@ -504,10 +573,11 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
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_f("mirror", tool_attribute.mirror);
shader_set_color("pickColor", tool_attribute.pickColor);
shader_set_surface("back", _can);
shader_set_surface("fore", _drw);
shader_set_surface("fore", _tmp);
draw_sprite_stretched(s_fx_pixel, 0, 0, 0, _sw, _sh);
surface_reset_shader();
@ -515,8 +585,9 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
surface_free(_can);
surface_clear(drawing_surface);
if(tool_selection.is_selected) {
surface_free(_tmp);
if(tool_selection.is_selected) {
tool_selection.selection_surface = _drawnSurface;
} else {
setCanvasSurface(_drawnSurface);
@ -552,6 +623,14 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
DRAW_CLEAR
draw_surface_safe(drawing_surface);
surface_reset_target();
var __s = surface_get_target();
var _sw = surface_get_width(__s);
var _sh = surface_get_height(__s);
prev_surface = surface_verify(prev_surface, _dim[0], _dim[1]);
preview_draw_surface = surface_verify(preview_draw_surface, _dim[0], _dim[1]);
preview_draw_mask = surface_verify(preview_draw_mask, _sw, _sh);
#endregion
#region tool
@ -561,10 +640,7 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
rightTools = [];
array_append(rightTools, rightTools_general);
if(tool_selection.is_selected) {
array_push(rightTools, -1);
array_append(rightTools, rightTools_selection);
}
if(tool_selection.is_selected) array_append(rightTools, rightTools_selection);
if(nodeTool != noone)
_tool = nodeTool;
@ -593,6 +669,7 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
case 0 : _tool = tool_sel_rectangle; break;
case 1 : _tool = tool_sel_ellipse; break;
case 2 : _tool = tool_sel_freeform; break;
case 3 : _tool = tool_sel_brush; break;
}
break;
@ -601,7 +678,10 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
}
if(_tool) _tool.subtool = _currTool.selecting;
if(_tool) {
_tool.subtool = _currTool.selecting;
array_append(rightTools, _tool.rightTools);
}
tool_selection.node = self;
tool_selection.drawing_surface = drawing_surface;
@ -611,14 +691,34 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
if(is_instanceof(_tool, canvas_tool_selection) && tool_selection.is_selected) tool_selection.step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
}
#endregion
if(_tool && _tool.override) {
_tool.node = self;
_tool.step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
_tool.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
surface_set_shader(preview_draw_surface, noone);
_tool.drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
surface_reset_shader();
draw_surface_ext_safe(preview_draw_surface, _x, _y, _s);
surface_set_target(preview_draw_mask);
DRAW_CLEAR
_tool.drawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
surface_reset_target();
shader_set(sh_brush_outline);
shader_set_f("dimension", _sw, _sh);
draw_surface_ext_safe(preview_draw_mask);
shader_reset();
_tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
return;
}
#endregion
draw_set_color(tool_attribute.color);
if(_tool) { #region tool step
@ -657,18 +757,29 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
#region preview
var _alp = _color_get_alpha(tool_attribute.color);
var __s = surface_get_target();
prev_surface = surface_verify(prev_surface, _dim[0], _dim[1]);
preview_draw_surface = surface_verify(preview_draw_surface, _dim[0], _dim[1]);
_preview_draw_surface = surface_verify(_preview_draw_surface, surface_get_width_safe(__s), surface_get_height_safe(__s));
if(tool_selection.is_selected) tool_selection.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
if(_tool) _tool.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
surface_set_shader(preview_draw_surface, noone,, BLEND.alpha);
if(tool_selection.is_selected) tool_selection.drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
draw_surface_safe(_drawing_surface, 0, 0);
if(tool_selection.is_selected) {
var _spx = tool_selection.selection_position[0];
var _spy = tool_selection.selection_position[1];
var _spw = tool_selection.selection_size[0];
var _sph = tool_selection.selection_size[1];
if(tool_attribute.mirror[0]) draw_surface_ext_safe(_drawing_surface, _spx * 2 + _spw, 0, -1, 1);
if(tool_attribute.mirror[1]) draw_surface_ext_safe(_drawing_surface, 0, _spy * 2 + _sph, 1, -1);
if(tool_attribute.mirror[0] && tool_attribute.mirror[1]) draw_surface_ext_safe(_drawing_surface, _spx * 2 + _spw, _spy * 2 + _sph, -1, -1);
} else {
if(tool_attribute.mirror[0]) draw_surface_ext_safe(_drawing_surface, _dim[0], 0, -1, 1);
if(tool_attribute.mirror[1]) draw_surface_ext_safe(_drawing_surface, 0, _dim[1], 1, -1);
if(tool_attribute.mirror[0] && tool_attribute.mirror[1]) draw_surface_ext_safe(_drawing_surface, _dim[0], _dim[1], -1, -1);
}
draw_set_color(tool_attribute.color);
if(brush.brush_sizing)
canvas_draw_point_size(brush, brush.brush_sizing_dx, brush.brush_sizing_dy);
@ -677,24 +788,21 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
surface_reset_shader();
if(_tool) {
_tool.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
if(!is_instanceof(_tool, canvas_tool_selection) && (active || _tool.mouse_holding))
draw_surface_ext_safe(preview_draw_surface, _x, _y, _s, _s, 0, isUsingTool("Eraser")? c_red : c_white, isUsingTool("Eraser")? 0.2 : _alp);
surface_set_target(_preview_draw_surface);
surface_set_target(preview_draw_mask);
DRAW_CLEAR
draw_surface_ext_safe(preview_draw_surface, _x, _y, _s, _s, 0, c_white, 1);
if(tool_selection.is_selected) tool_selection.drawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
if(_tool) _tool.drawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
surface_reset_target();
shader_set(sh_brush_outline);
shader_set_f("dimension", surface_get_width(_preview_draw_surface), surface_get_height(_preview_draw_surface));
draw_surface_ext_safe(_preview_draw_surface, 0, 0, 1, 1, 0, c_white, 1);
shader_set_f("dimension", _sw, _sh);
draw_surface_ext_safe(preview_draw_mask, 0, 0, 1, 1, 0, c_white, 1);
shader_reset();
_tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
}
if(_tool) _tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
#endregion
var _x0 = _x;
@ -710,7 +818,6 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
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);
@ -793,7 +900,7 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
}
} #endregion
static getPreviewValues = function() { return output_surface; }
static getPreviewValues = function() { return nodeTool == noone || nodeTool.applySelection? output_surface : noone; }
static doSerialize = function(_map) { #region
surface_store_buffers();

View file

@ -805,7 +805,7 @@ function Panel_Inspector() : PanelContent() constructor {
var _hh = ui(40);
_y += _hh;
if(is_instanceof(inspecting, Node_Canvas) && inspecting.nodeTool != noone)
if(is_instanceof(inspecting, Node_Canvas) && inspecting.nodeTool != noone && is_instanceof(inspecting.nodeTool.nodeObject, Node))
return drawNodeProperties(_y, _m, inspecting.nodeTool.nodeObject);
if(inspectGroup >= 0)

View file

@ -1464,11 +1464,11 @@ function Panel_Preview() : PanelContent() constructor {
var settings = array_merge(_tool.getToolSettings(), tool_current.settings);
tool_x = lerp_float(tool_x, tool_x_to, 5);
var tolx = tool_x + ui(16);
var tolx = tool_x + ui(8);
var toly = ui(8);
var tolw = ui(48);
var tolh = toolbar_height - ui(20);
var tol_max_w = ui(32);
var tol_max_w = ui(16);
for( var i = 0, n = array_length(settings); i < n; i++ ) {
var sett = settings[i];
@ -1477,10 +1477,17 @@ function Panel_Preview() : PanelContent() constructor {
var key = sett[2];
var atr = sett[3];
if(i == 0 && nme != "") {
tolx += ui(8);
tol_max_w += ui(8);
}
draw_set_text(f_p2, fa_left, fa_center, COLORS._main_text_sub);
if(nme != "") {
draw_text(tolx, toolbar_height / 2 - ui(2), nme);
tolx += string_width(nme) + ui(8);
tol_max_w += string_width(nme) + ui(8);
}
wdg.setFocusHover(pFOCUS, pHOVER);
@ -1501,8 +1508,13 @@ function Panel_Preview() : PanelContent() constructor {
wdg.drawParam(params);
tolx += tolw + ui(16);
tol_max_w += tolw + ui(16);
if(nme != "") {
tolx += ui(8);
tol_max_w += ui(8);
}
tolx += tolw + ui(8) + (nme != "") * ui(8);
tol_max_w += tolw + ui(8) + (nme != "") * ui(8);
}
tol_max_w = max(0, tol_max_w - w);

View file

@ -34,7 +34,7 @@
__channel_pos(surface);
} #endregion
function draw_surface_ext_safe(surface, _x, _y, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
function draw_surface_ext_safe(surface, _x = 0, _y = 0, _xs = 1, _ys = 1, _rot = 0, _col = c_white, _alpha = 1) { #region
INLINE
if(is_struct(surface)) {