diff --git a/#backups/scripts/__canvas_brush/__canvas_brush.gml.backup0 b/#backups/scripts/__canvas_brush/__canvas_brush.gml.backup0 index 9634571c6..e41e97e99 100644 --- a/#backups/scripts/__canvas_brush/__canvas_brush.gml.backup0 +++ b/#backups/scripts/__canvas_brush/__canvas_brush.gml.backup0 @@ -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; diff --git a/#backups/scripts/__canvas_brush/__canvas_brush.gml.backup1 b/#backups/scripts/__canvas_brush/__canvas_brush.gml.backup1 index f78a2ce8a..9634571c6 100644 --- a/#backups/scripts/__canvas_brush/__canvas_brush.gml.backup1 +++ b/#backups/scripts/__canvas_brush/__canvas_brush.gml.backup1 @@ -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; diff --git a/#backups/scripts/__canvas_tool/__canvas_tool.gml.backup0 b/#backups/scripts/__canvas_tool/__canvas_tool.gml.backup0 index 2b3ce6828..3d9d9401e 100644 --- a/#backups/scripts/__canvas_tool/__canvas_tool.gml.backup0 +++ b/#backups/scripts/__canvas_tool/__canvas_tool.gml.backup0 @@ -1,4 +1,4 @@ -// 2024-04-14 10:20:09 +// 2024-04-14 12:48:07 function canvas_tool() constructor { node = noone; diff --git a/#backups/scripts/__canvas_tool/__canvas_tool.gml.backup1 b/#backups/scripts/__canvas_tool/__canvas_tool.gml.backup1 new file mode 100644 index 000000000..2b3ce6828 --- /dev/null +++ b/#backups/scripts/__canvas_tool/__canvas_tool.gml.backup1 @@ -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) {} +} \ No newline at end of file diff --git a/#backups/scripts/__canvas_tool_shader/__canvas_tool_shader.gml.backup0 b/#backups/scripts/__canvas_tool_shader/__canvas_tool_shader.gml.backup0 new file mode 100644 index 000000000..2e4e8faf3 --- /dev/null +++ b/#backups/scripts/__canvas_tool_shader/__canvas_tool_shader.gml.backup0 @@ -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); + } +} \ No newline at end of file diff --git a/#backups/scripts/canvas_tool_brush/canvas_tool_brush.gml.backup0 b/#backups/scripts/canvas_tool_brush/canvas_tool_brush.gml.backup0 index eee79f1d7..232f0a334 100644 --- a/#backups/scripts/canvas_tool_brush/canvas_tool_brush.gml.backup0 +++ b/#backups/scripts/canvas_tool_brush/canvas_tool_brush.gml.backup0 @@ -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; diff --git a/#backups/scripts/canvas_tool_brush/canvas_tool_brush.gml.backup1 b/#backups/scripts/canvas_tool_brush/canvas_tool_brush.gml.backup1 index de8bc565f..eee79f1d7 100644 --- a/#backups/scripts/canvas_tool_brush/canvas_tool_brush.gml.backup1 +++ b/#backups/scripts/canvas_tool_brush/canvas_tool_brush.gml.backup1 @@ -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); diff --git a/#backups/scripts/canvas_tool_node/canvas_tool_node.gml.backup0 b/#backups/scripts/canvas_tool_node/canvas_tool_node.gml.backup0 index a28f04ae5..6d4cb6595 100644 --- a/#backups/scripts/canvas_tool_node/canvas_tool_node.gml.backup0 +++ b/#backups/scripts/canvas_tool_node/canvas_tool_node.gml.backup0 @@ -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; diff --git a/#backups/scripts/canvas_tool_node/canvas_tool_node.gml.backup1 b/#backups/scripts/canvas_tool_node/canvas_tool_node.gml.backup1 index 3a22c396d..a28f04ae5 100644 --- a/#backups/scripts/canvas_tool_node/canvas_tool_node.gml.backup1 +++ b/#backups/scripts/canvas_tool_node/canvas_tool_node.gml.backup1 @@ -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; diff --git a/#backups/scripts/canvas_tool_outline/canvas_tool_outline.gml.backup0 b/#backups/scripts/canvas_tool_outline/canvas_tool_outline.gml.backup0 new file mode 100644 index 000000000..735c753a5 --- /dev/null +++ b/#backups/scripts/canvas_tool_outline/canvas_tool_outline.gml.backup0 @@ -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; + + } + + } + +} \ No newline at end of file diff --git a/#backups/scripts/canvas_tool_resize/canvas_tool_resize.gml.backup0 b/#backups/scripts/canvas_tool_resize/canvas_tool_resize.gml.backup0 index 1e79e17a8..ad87c7285 100644 --- a/#backups/scripts/canvas_tool_resize/canvas_tool_resize.gml.backup0 +++ b/#backups/scripts/canvas_tool_resize/canvas_tool_resize.gml.backup0 @@ -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; diff --git a/#backups/scripts/canvas_tool_resize/canvas_tool_resize.gml.backup1 b/#backups/scripts/canvas_tool_resize/canvas_tool_resize.gml.backup1 index e4004976f..1e79e17a8 100644 --- a/#backups/scripts/canvas_tool_resize/canvas_tool_resize.gml.backup1 +++ b/#backups/scripts/canvas_tool_resize/canvas_tool_resize.gml.backup1 @@ -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; diff --git a/#backups/scripts/canvas_tool_selection/canvas_tool_selection.gml.backup0 b/#backups/scripts/canvas_tool_selection/canvas_tool_selection.gml.backup0 index a1b8585e4..5a6e70da0 100644 --- a/#backups/scripts/canvas_tool_selection/canvas_tool_selection.gml.backup0 +++ b/#backups/scripts/canvas_tool_selection/canvas_tool_selection.gml.backup0 @@ -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; diff --git a/#backups/scripts/canvas_tool_selection/canvas_tool_selection.gml.backup1 b/#backups/scripts/canvas_tool_selection/canvas_tool_selection.gml.backup1 index ce6f6c832..ee32f0512 100644 --- a/#backups/scripts/canvas_tool_selection/canvas_tool_selection.gml.backup1 +++ b/#backups/scripts/canvas_tool_selection/canvas_tool_selection.gml.backup1 @@ -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; diff --git a/#backups/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml.backup0 b/#backups/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml.backup0 index 8b6b98230..dd235abfe 100644 --- a/#backups/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml.backup0 +++ b/#backups/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml.backup0 @@ -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; diff --git a/#backups/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml.backup1 b/#backups/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml.backup1 index 96e3c76a6..8b6b98230 100644 --- a/#backups/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml.backup1 +++ b/#backups/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml.backup1 @@ -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; diff --git a/#backups/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml.backup0 b/#backups/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml.backup0 index d6650145d..cc0c87310 100644 --- a/#backups/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml.backup0 +++ b/#backups/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml.backup0 @@ -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; diff --git a/#backups/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml.backup1 b/#backups/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml.backup1 index 74d23c983..d6650145d 100644 --- a/#backups/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml.backup1 +++ b/#backups/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml.backup1 @@ -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); } } \ No newline at end of file diff --git a/#backups/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml.backup0 b/#backups/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml.backup0 index 8e389e2da..e61bca41c 100644 --- a/#backups/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml.backup0 +++ b/#backups/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml.backup0 @@ -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; diff --git a/#backups/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml.backup1 b/#backups/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml.backup1 index bc61105ce..8e389e2da 100644 --- a/#backups/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml.backup1 +++ b/#backups/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml.backup1 @@ -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); } } \ No newline at end of file diff --git a/#backups/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml.backup0 b/#backups/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml.backup0 index f76796816..988168534 100644 --- a/#backups/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml.backup0 +++ b/#backups/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml.backup0 @@ -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; diff --git a/#backups/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml.backup1 b/#backups/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml.backup1 index aae70b2f6..5508bfa36 100644 --- a/#backups/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml.backup1 +++ b/#backups/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml.backup1 @@ -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); - } } \ No newline at end of file diff --git a/#backups/scripts/node_canvas/node_canvas.gml.backup0 b/#backups/scripts/node_canvas/node_canvas.gml.backup0 index 4087dff77..c07b4e568 100644 --- a/#backups/scripts/node_canvas/node_canvas.gml.backup0 +++ b/#backups/scripts/node_canvas/node_canvas.gml.backup0 @@ -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,8 +819,7 @@ 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); diff --git a/#backups/scripts/node_canvas/node_canvas.gml.backup1 b/#backups/scripts/node_canvas/node_canvas.gml.backup1 index b19cf1708..1f296dc16 100644 --- a/#backups/scripts/node_canvas/node_canvas.gml.backup1 +++ b/#backups/scripts/node_canvas/node_canvas.gml.backup1 @@ -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,8 +819,7 @@ 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); diff --git a/#backups/scripts/node_tool/node_tool.gml.backup0 b/#backups/scripts/node_tool/node_tool.gml.backup0 new file mode 100644 index 000000000..da21b8561 --- /dev/null +++ b/#backups/scripts/node_tool/node_tool.gml.backup0 @@ -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() {} +} \ No newline at end of file diff --git a/#backups/scripts/panel_inspector/panel_inspector.gml.backup0 b/#backups/scripts/panel_inspector/panel_inspector.gml.backup0 index 308595b0f..93e0cb057 100644 --- a/#backups/scripts/panel_inspector/panel_inspector.gml.backup0 +++ b/#backups/scripts/panel_inspector/panel_inspector.gml.backup0 @@ -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); diff --git a/#backups/scripts/panel_inspector/panel_inspector.gml.backup1 b/#backups/scripts/panel_inspector/panel_inspector.gml.backup1 new file mode 100644 index 000000000..308595b0f --- /dev/null +++ b/#backups/scripts/panel_inspector/panel_inspector.gml.backup1 @@ -0,0 +1,1028 @@ +// 2024-04-14 12:24:14 +#region funtion calls + function __fnInit_Inspector() { + __registerFunction("inspector_copy_prop", panel_inspector_copy_prop); + __registerFunction("inspector_paste_prop", panel_inspector_paste_prop); + __registerFunction("inspector_toggle_animation", panel_inspector_toggle_animation); + + __registerFunction("inspector_color_pick", panel_inspector_color_pick); + } + + function panel_inspector_copy_prop() { CALL("inspector_copy_prop"); PANEL_INSPECTOR.propSelectCopy(); } + function panel_inspector_paste_prop() { CALL("inspector_paste_prop"); PANEL_INSPECTOR.propSelectPaste(); } + function panel_inspector_toggle_animation() { CALL("inspector_toggle_animation"); PANEL_INSPECTOR.anim_toggling = true; } + + function panel_inspector_color_pick() { CALL("inspector_color_pick"); if(!PREFERENCES.alt_picker) return; PANEL_INSPECTOR.color_picking = true; } +#endregion + +function Inspector_Custom_Renderer(drawFn, registerFn = noone) : widget() constructor { #region + h = 64; + self.draw = drawFn; + + if(registerFn != noone) register = registerFn; + else { + register = function(parent = noone) { + if(!interactable) return; + self.parent = parent; + } + } +} #endregion + +function Inspector_Sprite(spr) constructor { self.spr = spr; } + +function Inspector_Spacer(height, line = false) constructor { self.h = height; self.line = line; } + +function Panel_Inspector() : PanelContent() constructor { + #region ---- main ---- + title = __txt("Inspector"); + context_str = "Inspector"; + icon = THEME.panel_inspector_icon; + + w = ui(400); + h = ui(640); + min_w = ui(160); + + locked = false; + inspecting = noone; + inspectings = []; + inspectGroup = false; + top_bar_h = ui(100); + + static initSize = function() { + content_w = w - ui(32); + content_h = h - top_bar_h - ui(12); + } + initSize(); + + view_mode_tooltip = new tooltipSelector("View", [ "Compact", "Spacious" ]) + #endregion + + #region ---- properties ---- + prop_hover = noone; + prop_selecting = noone; + + prop_highlight = noone; + prop_highlight_time = 0; + + prop_dragging = noone; + prop_sel_drag_x = 0; + prop_sel_drag_y = 0; + + color_picking = false; + + picker_index = 0; + picker_change = false; + #endregion + + globalvar_viewer_init(); + drawWidgetInit(); + + #region ---- header labels ---- + tb_node_name = new textBox(TEXTBOX_INPUT.text, function(txt) { + if(inspecting) inspecting.setDisplayName(txt); + }) + + tb_prop_filter = new textBox(TEXTBOX_INPUT.text, function(txt) { filter_text = txt; }) + tb_prop_filter.no_empty = false; + tb_prop_filter.auto_update = true; + tb_prop_filter.font = f_p0; + tb_prop_filter.color = COLORS._main_text_sub; + tb_prop_filter.align = fa_center; + tb_prop_filter.hide = true; + filter_text = ""; + + prop_page_button = new buttonGroup([ "Properties", "Settings" ], function(val) { prop_page = val; }); + prop_page_button.buttonSpr = [ THEME.button_hide_left, THEME.button_hide_middle, THEME.button_hide_right ]; + prop_page_button.font = f_p1; + prop_page_button.fColor = COLORS._main_text_sub; + prop_page = 0; + #endregion + + #region ---- metadata ---- + current_meta = -1; + meta_tb[0] = new textArea(TEXTBOX_INPUT.text, function(str) { current_meta.description = str; }); + meta_tb[1] = new textArea(TEXTBOX_INPUT.text, function(str) { current_meta.author = str; }); + meta_tb[2] = new textArea(TEXTBOX_INPUT.text, function(str) { current_meta.contact = str; }); + meta_tb[3] = new textArea(TEXTBOX_INPUT.text, function(str) { current_meta.alias = str; }); + meta_tb[4] = new textArrayBox(noone, META_TAGS); + for( var i = 0, n = array_length(meta_tb); i < n; i++ ) + meta_tb[i].hide = true; + + meta_display = [ + [ __txt("Project Settings"), false ], + [ __txt("Metadata"), true ], + [ __txtx("panel_globalvar", "Global variables"), true, button(function() { panelAdd("Panel_Globalvar", true); }, THEME.node_goto).setIcon(THEME.node_goto, 0, COLORS._main_icon) ], + [ __txt("Group Properties"), true ], + ]; + #endregion + + #region ---- workshop ---- + workshop_uploading = false; + #endregion + + #region ++++ hotkeys ++++ + addHotkey("Inspector", "Copy property", "C", MOD_KEY.ctrl, panel_inspector_copy_prop); + addHotkey("Inspector", "Paste property", "V", MOD_KEY.ctrl, panel_inspector_paste_prop); + addHotkey("Inspector", "Toggle animation", "I", MOD_KEY.none, panel_inspector_toggle_animation); + + addHotkey("", "Color picker", "", MOD_KEY.alt, panel_inspector_color_pick); + #endregion + + #region ++++ menus ++++ + static nodeExpandAll = function(node) { + if(node.input_display_list == -1) return; + + var dlist = node.input_display_list; + for( var i = 0, n = array_length(dlist); i < n; i++ ) { + if(!is_array(dlist[i])) continue; + dlist[i][@ 1] = false; + } + } + + static nodeCollapseAll = function(node) { + if(node.input_display_list == -1) return; + + var dlist = node.input_display_list; + for( var i = 0, n = array_length(dlist); i < n; i++ ) { + if(!is_array(dlist[i])) continue; + dlist[i][@ 1] = true; + } + } + + group_menu = [ + menuItem(__txt("Expand all"), function() { + if(inspecting != noone) nodeExpandAll(inspecting); + for( var i = 0, n = array_length(inspectings); i < n; i++ ) + nodeExpandAll(inspectings[i]); + }), + menuItem(__txt("Collapse all"), function() { + if(inspecting != noone) nodeCollapseAll(inspecting); + for( var i = 0, n = array_length(inspectings); i < n; i++ ) + nodeCollapseAll(inspectings[i]); + }), + ] + + __dialog_junction = noone; + menu_junc_reset_value = menuItem(__txtx("panel_inspector_reset", "Reset value"), function() { __dialog_junction.resetValue(); }); + menu_junc_add_anim = menuItem(__txtx("panel_inspector_add", "Add animation"), function() { __dialog_junction.setAnim(true); }); + menu_junc_rem_anim = menuItem(__txtx("panel_inspector_remove", "Remove animation"), function() { __dialog_junction.setAnim(false); }); + menu_junc_combine_axis = menuItem(__txtx("panel_inspector_axis_combine", "Combine axis"), function() { __dialog_junction.sep_axis = false; }); + menu_junc_separate_axis = menuItem(__txtx("panel_inspector_axis_separate", "Separate axis"), function() { __dialog_junction.sep_axis = true; }); + menu_junc_expression_ena = menuItem(__txtx("panel_inspector_use_expression", "Use expression"), function() { __dialog_junction.expUse = true; }); + menu_junc_expression_dis = menuItem(__txtx("panel_inspector_disable_expression", "Disable expression"), function() { __dialog_junction.expUse = false; }); + menu_junc_extract = menuItem(__txtx("panel_inspector_extract_single", "Extract to node"), function() { __dialog_junction.extractNode(); }); + + menu_junc_copy = menuItem(__txt("Copy"), function() { clipboard_set_text(__dialog_junction.getShowString()); }, THEME.copy, ["Inspector", "Copy property"]); + menu_junc_paste = menuItem(__txt("Paste"), function() { __dialog_junction.setString(clipboard_get_text()); }, THEME.paste, ["Inspector", "Paste property"]); + + function setSelectingItemColor(color) { + if(__dialog_junction == noone) return; + + __dialog_junction.setColor(color); + + var _val_to = __dialog_junction.getJunctionTo(); + for( var i = 0, n = array_length(_val_to); i < n; i++ ) + _val_to[i].setColor(color); + } + + var _clrs = COLORS.labels; + var _item = array_create(array_length(_clrs)); + + for( var i = 0, n = array_length(_clrs); i < n; i++ ) { + _item[i] = [ + [ THEME.timeline_color, i > 0, _clrs[i] ], + function(_data) { + setSelectingItemColor(_data.color); + }, "", { color: i == 0? -1 : _clrs[i] } + ]; + } + + array_push(_item, [ + [ THEME.timeline_color, 2 ], + function(_data) { + colorSelectorCall(__dialog_junction? __dialog_junction.color : c_white, setSelectingItemColor); + } + ]); + + menu_junc_color = menuItemGroup(__txt("Color"), _item); + menu_junc_color.spacing = ui(24); + #endregion + + function setInspecting(inspecting) { #region + if(locked) return; + + self.inspecting = inspecting; + + if(inspecting != noone) + inspecting.onInspect(); + contentPane.scroll_y = 0; + contentPane.scroll_y_to = 0; + + picker_index = 0; + } #endregion + + function getInspecting() { #region + if(inspecting == noone) return noone; + return inspecting.active? inspecting : noone; + } #endregion + + function onFocusBegin() { PANEL_INSPECTOR = self; } + + function onResize() { #region + initSize(); + contentPane.resize(content_w, content_h); + } #endregion + + static drawMeta = function(_y, _m) { #region + var con_w = contentPane.surface_w - ui(4); + var _hover = pHOVER && contentPane.hover; + + var context = PANEL_GRAPH.getCurrentContext(); + var meta = context == noone? PROJECT.meta : context.metadata; + if(meta == noone) return 0; + current_meta = meta; + + var hh = ui(8); + var yy = _y + ui(8); + + var rx = x + ui(16); + var ry = y + top_bar_h; + + attribute_hovering = noone; + + for( var i = 0, n = array_length(meta_display); i < n; i++ ) { + if(i == 3) { + var context = PANEL_GRAPH.getCurrentContext(); + if(context == noone) continue; + } + + var _meta = meta_display[i]; + var _txt = array_safe_get_fast(_meta, 0); + var _b = array_safe_get_fast(_meta, 2, noone); + var _x1 = con_w - (_b != noone) * ui(30); + + if(_hover && point_in_rectangle(_m[0], _m[1], 0, yy, _x1, yy + ui(32))) { + draw_sprite_stretched_ext(THEME.group_label, 0, 0, yy, con_w, ui(32), COLORS.panel_inspector_group_hover, 1); + + if(mouse_press(mb_left, pFOCUS)) + meta_display[i][1] = !meta_display[i][1]; + } else + draw_sprite_stretched_ext(THEME.group_label, 0, 0, yy, con_w, ui(32), COLORS.panel_inspector_group_bg, 1); + + if(_b != noone) { + _b.setFocusHover(pFOCUS, _hover); + _b.draw(_x1, yy + ui(2), ui(28), ui(28), _m, THEME.button_hide_fill); + } + + draw_sprite_ui(THEME.arrow, meta_display[i][1]? 0 : 3, ui(16), yy + ui(32) / 2, 1, 1, 0, COLORS.panel_inspector_group_bg, 1); + + draw_set_text(f_p0, fa_left, fa_center, COLORS._main_text_inner); + draw_text_add(ui(32), yy + ui(32) / 2, _txt); + + yy += ui(32 + 8); + hh += ui(32 + 8); + + if(meta_display[i][1]) { + yy += ui(4); + hh += ui(4); + continue; + } + + switch(i) { + case 0 : + var _edt = PROJECT.attributeEditor; + for( var j = 0; j < array_length(_edt); j++ ) { + var title = _edt[j][0]; + var param = _edt[j][1]; + var editW = _edt[j][2]; + var drpFn = _edt[j][3]; + + var widx = ui(8); + var widy = yy; + + draw_set_text(f_p0, fa_left, fa_top, COLORS._main_text_inner); + draw_text_add(ui(16), yy, __txt(title)); + yy += line_get_height() + ui(6); + hh += line_get_height() + ui(6); + + editW.setFocusHover(pFOCUS, _hover); + if(pFOCUS) editW.register(contentPane); + + var wh = 0; + var _data = PROJECT.attributes[$ param]; + var _param = new widgetParam(ui(16), yy, w - ui(16 + 48), TEXTBOX_HEIGHT, _data, {}, _m, rx, ry); + + wh = editW.drawParam(_param); + + var jun = PANEL_GRAPH.value_dragging; + var widw = con_w - ui(16); + var widh = line_get_height() + ui(6) + wh + ui(4); + + if(jun != noone && _hover && point_in_rectangle(_m[0], _m[1], widx, widy, widx + widw, widy + widh)) { + draw_sprite_stretched_ext(THEME.ui_panel_active, 0, widx, widy, widw, widh, COLORS._main_value_positive, 1); + attribute_hovering = drpFn; + } + + yy += wh + ui(8); + hh += wh + ui(8); + } + break; + case 1 : + for( var j = 0; j < array_length(meta.displays); j++ ) { + var display = meta.displays[j]; + + draw_set_text(f_p0, fa_left, fa_top, COLORS._main_text_inner); + draw_text_add(ui(16), yy, __txt(display[0])); + yy += line_get_height() + ui(6); + hh += line_get_height() + ui(6); + + meta_tb[j].setFocusHover(pFOCUS, _hover); + if(pFOCUS) meta_tb[j].register(contentPane); + + var wh = 0; + var _dataFunc = display[1]; + var _data = _dataFunc(meta); + + switch(instanceof(meta_tb[j])) { + case "textArea" : + wh = meta_tb[j].draw(ui(16), yy, w - ui(16 + 48), display[2], _data, _m); + break; + case "textArrayBox" : + meta_tb[j].arraySet = current_meta.tags; + wh = meta_tb[j].draw(ui(16), yy, w - ui(16 + 48), display[2], _m, rx, ry); + break; + } + + yy += wh + ui(8); + hh += wh + ui(8); + } + break; + case 2 : + if(findPanel("Panel_Globalvar")) { + yy += ui(4); + hh += ui(4); + continue; + } + + var gvh = globalvar_viewer_draw(ui(16), yy, contentPane.surface_w - ui(24), _m, pFOCUS, _hover, contentPane, ui(16) + x, top_bar_h + y); + yy += gvh + ui(8); + hh += gvh + ui(8); + + var bh = ui(36); + var bx = ui(16); + var by = yy; + var bbw = contentPane.surface_w - ui(24); + + if(var_editing) { + var bw = bbw / 2 - ui(4); + + if(buttonInstant(THEME.button_hide, bx, by, bw, bh, _m, pFOCUS, _hover) == 2) + var_editing = !var_editing; + + var txt = __txt("Apply"); + var icon = THEME.accept; + var colr = COLORS._main_value_positive; + + draw_set_text(f_p0b, fa_left, fa_center, COLORS._main_icon) + var bxc = bx + bw / 2 - (string_width(txt) + ui(48)) / 2; + var byc = by + bh / 2; + draw_sprite_ui(icon, 0, bxc + ui(24), byc,,,, colr); + draw_text_add(bxc + ui(48), byc, txt); + + bx += bw + ui(4); + + if(buttonInstant(THEME.button_hide, bx, by, bw, bh, _m, pFOCUS, _hover) == 2) + PROJECT.globalNode.createValue(); + + var txt = __txt("Add"); + var icon = THEME.add; + + draw_set_text(f_p0b, fa_left, fa_center, COLORS._main_icon) + var bxc = bx + bw / 2 - (string_width(txt) + ui(48)) / 2; + var byc = by + bh / 2; + draw_sprite_ui(icon, 0, bxc + ui(24), byc,,,, colr); + draw_text_add(bxc + ui(48), byc, txt); + } else { + var bw = bbw; + + if(buttonInstant(THEME.button_hide, bx, by, bw, bh, _m, pFOCUS, _hover) == 2) + var_editing = !var_editing; + + var txt = __txt("Edit"); + var icon = THEME.gear; + var colr = COLORS._main_icon; + + draw_set_text(f_p0b, fa_left, fa_center, colr) + var bxc = bx + bw / 2 - (string_width(txt) + ui(48)) / 2; + var byc = by + bh / 2; + draw_sprite_ui(icon, 0, bxc + ui(24), byc,,,, colr); + draw_text_add(bxc + ui(48), byc, txt); + } + break; + case 3 : + var context = PANEL_GRAPH.getCurrentContext(); + var _h = drawNodeProperties(yy, _m, context); + + yy += _h; + hh += _h; + break; + } + + yy += ui(8); + hh += ui(8); + } + + return hh; + } #endregion + + static highlightProp = function(prop) { #region + prop_highlight = prop; + prop_highlight_time = 60; + } #endregion + + static drawNodeProperties = function(_y, _m, _inspecting = inspecting) { #region + var con_w = contentPane.surface_w - ui(4); + var _hover = pHOVER && contentPane.hover; + + _inspecting.inspecting = true; + prop_hover = noone; + var jun = noone; + var amoIn = _inspecting.input_display_list == -1? ds_list_size(_inspecting.inputs) : array_length(_inspecting.input_display_list); + var amoOut = ds_list_size(_inspecting.outputs); + var amo = inspectGroup == 0? amoIn + 1 + amoOut : amoIn; + var hh = 0; + + //tb_prop_filter.register(contentPane); + //tb_prop_filter.setFocusHover(pHOVER, pFOCUS); + //tb_prop_filter.draw(ui(32), _y + ui(4), con_w - ui(64), ui(28), filter_text, _m); + //draw_sprite_ui(THEME.search, 0, ui(32 + 16), _y + ui(4 + 14), 1, 1, 0, COLORS._main_icon, 1); + + var xc = con_w / 2; + + if(prop_page == 1) { #region attribute/settings editor + hh += ui(8); + var hg = ui(32); + var yy = _y + hh; + var wx1 = con_w - ui(8); + var ww = max(ui(180), con_w / 3); + var wx0 = wx1 - ww; + + for( var i = 0, n = array_length(_inspecting.attributeEditors); i < n; i++ ) { + var edt = _inspecting.attributeEditors[i]; + + if(is_string(edt)) { + var lby = yy + ui(12); + draw_set_alpha(0.5); + draw_set_text(f_p1, fa_center, fa_center, COLORS._main_text_sub); + draw_text_add(xc, lby, edt); + + var lbw = string_width(edt) / 2; + draw_set_color(COLORS._main_text_sub); + draw_line_round(xc + lbw + ui(16), lby, wx1, lby, 2); + draw_line_round(xc - lbw - ui(16), lby, ui(8), lby, 2); + draw_set_alpha(1.0); + + yy += ui(32); + hh += ui(32); + continue; + } + + var val = edt[1](); + edt[2].setFocusHover(pFOCUS, pHOVER); + + if(instanceof(edt[2]) == "buttonClass") { + edt[2].text = edt[0]; + edt[2].draw(ui(8), yy, con_w - ui(16), hg, _m); + + yy += hg + ui(8); + hh += hg + ui(8); + continue; + } + + draw_set_text(f_p0, fa_left, fa_center, COLORS._main_text); + draw_text_add(ui(8), yy + hg / 2, edt[0]); + + var _param = new widgetParam(wx0, yy, ww, hg, val, {}, _m, x + contentPane.x, y + contentPane.y); + _param.s = hg; + edt[2].drawParam(_param); + + yy += hg + ui(8); + hh += hg + ui(8); + } + return hh; + } #endregion + + var color_picker_selecting = noone; + var color_picker_index = 0; + var pickers = []; + var _colsp = false; + + for(var i = 0; i < amo; i++) { + var yy = hh + _y; + + if(i < amoIn) { #region inputs + if(_inspecting.input_display_list == -1) { + jun = _inspecting.inputs[| i]; + } else { + if(i >= array_length(_inspecting.input_display_list)) break; + var jun_disp = _inspecting.input_display_list[i]; + if(is_instanceof(jun_disp, Inspector_Spacer)) { // SPACER + var _hh = ui(jun_disp.h); + var _yy = yy + _hh / 2 - ui(2); + + if(jun_disp.line) { + draw_set_color(COLORS.panel_inspector_key_separator); + draw_line(ui(8), _yy, con_w - ui(8), _yy); + } + + hh += _hh; + continue; + + } else if(is_instanceof(jun_disp, Inspector_Sprite)) { // SPRITE + var _spr = jun_disp.spr; + var _sh = sprite_get_height(_spr); + + draw_sprite(_spr, 0, xc, yy); + + hh += _sh + ui(8); + continue; + + } else if(is_array(jun_disp)) { // LABEL + var pad = i && _colsp == false? ui(4) : 0 + _colsp = false; + yy += pad; + + var txt = __txt(jun_disp[0]); + var coll = jun_disp[1] && filter_text == ""; + var lbh = viewMode? ui(32) : ui(26); + var togl = array_safe_get_fast(jun_disp, 2, noone); + if(togl != noone) var toging = _inspecting.getInputData(togl); + + var lbx = (togl != noone) * ui(40); + var lbw = con_w - lbx; + var ltx = lbx + ui(32); + + if(_hover && point_in_rectangle(_m[0], _m[1], lbx, yy, con_w, yy + lbh)) { + draw_sprite_stretched_ext(THEME.group_label, 0, lbx, yy, lbw, lbh, COLORS.panel_inspector_group_hover, 1); + + if(mouse_press(mb_left, pFOCUS)) + jun_disp[@ 1] = !coll; + if(mouse_press(mb_right, pFOCUS)) + menuCall("inspector_group_menu",,, group_menu,, _inspecting); + } else + draw_sprite_stretched_ext(THEME.group_label, 0, lbx, yy, lbw, lbh, COLORS.panel_inspector_group_bg, 1); + + if(filter_text == "") + draw_sprite_ui(THEME.arrow, 0, lbx + ui(16), yy + lbh / 2, 1, 1, -90 + coll * 90, COLORS.panel_inspector_group_bg, 1); + + var cc, aa = 1; + + if(togl != noone) { + if(_hover && point_in_rectangle(_m[0], _m[1], 0, yy, ui(32), yy + lbh)) { + draw_sprite_stretched_ext(THEME.group_label, 0, 0, yy, ui(32), lbh, COLORS.panel_inspector_group_hover, 1); + + if(mouse_press(mb_left, pFOCUS)) + _inspecting.inputs[| togl].setValue(!toging); + } else + draw_sprite_stretched_ext(THEME.group_label, 0, 0, yy, ui(32), lbh, COLORS.panel_inspector_group_bg, 1); + + cc = toging? COLORS._main_accent : COLORS.panel_inspector_group_bg; + aa = 0.5 + toging * 0.5; + + draw_sprite_ui(THEME.inspector_checkbox, 0, ui(16), yy + lbh / 2, 1, 1, 0, cc, 1); + if(toging) + draw_sprite_ui(THEME.inspector_checkbox, 1, ui(16), yy + lbh / 2, 1, 1, 0, cc, 1); + } + + draw_set_alpha(aa); + draw_set_text(viewMode? f_p0 : f_p1, fa_left, fa_center, COLORS._main_text); + draw_text_add(ltx, yy + lbh / 2, txt); + draw_set_alpha(1); + + hh += lbh + ui(viewMode? 8 : 6) + pad; + + if(coll) { // skip + _colsp = true; + var j = i + 1; + var _len = array_length(_inspecting.input_display_list); + + while(j < _len) { + var j_jun = _inspecting.input_display_list[j]; + if(is_array(j_jun)) + break; + j++; + } + + i = j - 1; + } + + continue; + + } else if(is_struct(jun_disp) && instanceof(jun_disp) == "Inspector_Custom_Renderer") { + jun_disp.register(contentPane); + jun_disp.rx = ui(16) + x; + jun_disp.ry = top_bar_h + y; + + hh += jun_disp.draw(ui(6), yy, con_w - ui(12), _m, _hover, pFOCUS) + ui(8); + continue; + } + jun = _inspecting.inputs[| _inspecting.input_display_list[i]]; + } + #endregion + } else if(i == amoIn) { #region output label + hh += ui(8 + 32 + 8); + + draw_sprite_stretched_ext(THEME.group_label, 0, 0, yy + ui(8), con_w, ui(32), COLORS.panel_inspector_output_label, 0.8); + draw_set_text(f_p0b, fa_center, fa_center, COLORS._main_text_sub); + draw_text_add(xc, yy + ui(8 + 16), __txt("Outputs")); + continue; + #endregion + } else { #region outputs + var outInd = i - amoIn - 1; + jun = _inspecting.outputs[| outInd]; + #endregion + } + + if(!is_struct(jun)) continue; + if(instanceof(jun) != "NodeValue") continue; + + if(!jun.show_in_inspector || jun.type == VALUE_TYPE.object) continue; + if(filter_text != "") { + var pos = string_pos(filter_text, string_lower(jun.getName())); + if(pos == 0) continue; + } + + #region ++++ draw widget ++++ + var _font = viewMode == INSP_VIEW_MODE.spacious? f_p0 : f_p2; + + var lb_h = line_get_height(_font) + ui(8); + var lb_w = line_get_width(jun.getName(), _font) + ui(16); + var lb_x = ui(48) + (ui(24) * (jun.color != -1)); + var padd = ui(8); + + var _selY = yy; + + var widg = drawWidget(ui(16), yy, contentPane.surface_w - ui(24), _m, jun, false, pHOVER && contentPane.hover, pFOCUS, contentPane, ui(16) + x, top_bar_h + y); + var widH = widg[0]; + var mbRight = widg[1]; + + var lbHov = point_in_rectangle(_m[0], _m[1], lb_x, _selY + ui(2), lb_x + lb_w, _selY + lb_h - ui(4)); + if(lbHov) draw_sprite_stretched_ext(THEME.button_hide, 1, lb_x, _selY + ui(2), lb_w, lb_h - ui(6), COLORS._main_icon, 1); + + hh += lb_h + widH + padd; + + var _selY1 = yy + lb_h + widH + ui(2); + var _selH = _selY1 - _selY + (viewMode * ui(4)); + + if(jun == prop_highlight && prop_highlight_time) { + if(prop_highlight_time == 60) + contentPane.setScroll(_y - yy); + var aa = min(1, prop_highlight_time / 30); + draw_sprite_stretched_ext(THEME.ui_panel_active, 0, ui(4), yy, contentPane.surface_w - ui(4), _selH, COLORS._main_accent, aa); + } + + if(_hover && lbHov && prop_dragging == noone && mouse_press(mb_left, pFOCUS)) { + prop_dragging = jun; + + prop_sel_drag_x = mouse_mx; + prop_sel_drag_y = mouse_my; + } + #endregion + + if(jun.connect_type == JUNCTION_CONNECT.input && jun.type == VALUE_TYPE.color && jun.display_type == VALUE_DISPLAY._default) { #region color picker + pickers[color_picker_index] = jun; + color_picker_index++; + } #endregion + + if(_hover && point_in_rectangle(_m[0], _m[1], ui(4), _selY, contentPane.surface_w - ui(4), _selY + _selH)) { #region mouse in widget + _HOVERING_ELEMENT = jun; + + var hov = PANEL_GRAPH.value_dragging != noone || (NODE_DROPPER_TARGET != noone && NODE_DROPPER_TARGET != jun); + + if(hov) { + draw_sprite_stretched_ext(THEME.ui_panel_active, 0, ui(4), _selY, contentPane.surface_w - ui(8), _selH, COLORS._main_value_positive, 1); + if(mouse_press(mb_left, NODE_DROPPER_TARGET_CAN)) { + NODE_DROPPER_TARGET.expression += $"{jun.node.internalName}.{jun.connect_type == JUNCTION_CONNECT.input? "inputs" : "outputs"}.{jun.internalName}"; + NODE_DROPPER_TARGET.expressionUpdate(); + } + } else + draw_sprite_stretched_ext(THEME.prop_selecting, 0, ui(4), _selY, contentPane.surface_w - ui(8), _selH, COLORS._main_accent, 1); + + if(anim_toggling) { + jun.setAnim(!jun.is_anim); + anim_toggling = false; + } + + prop_hover = jun; + + if(mouse_press(mb_left, pFOCUS)) + prop_selecting = jun; + + if(mouse_press(mb_right, pFOCUS && mbRight)) { #region right click menu + var _menuItem = [ menu_junc_color, -1 ]; + + if(i < amoIn) { + array_push(_menuItem, menu_junc_reset_value, jun.is_anim? menu_junc_rem_anim : menu_junc_add_anim); + if(jun.sepable) array_push(_menuItem, jun.sep_axis? menu_junc_combine_axis : menu_junc_separate_axis); + array_push(_menuItem, -1); + } + + array_push(_menuItem, jun.expUse? menu_junc_expression_dis : menu_junc_expression_ena, -1, menu_junc_copy); + if(jun.connect_type == JUNCTION_CONNECT.input) + array_push(_menuItem, menu_junc_paste); + + if(jun.connect_type == JUNCTION_CONNECT.input && jun.extract_node != "") { + if(is_array(jun.extract_node)) { + var ext = menuItem(__txtx("panel_inspector_extract_multiple", "Extract to..."), function(_dat) { + var arr = []; + for(var i = 0; i < array_length(__dialog_junction.extract_node); i++) { + var _rec = __dialog_junction.extract_node[i]; + array_push(arr, menuItem(_rec, function(_dat) { __dialog_junction.extractNode(_dat.name); })); + } + + return submenuCall(_dat, arr); + }).setIsShelf(); + array_push(_menuItem, ext); + } else + array_push(_menuItem, menu_junc_extract); + } + + var dia = menuCall("inspector_value_menu",,, _menuItem,, jun); + __dialog_junction = jun; + } #endregion + } #endregion + } + + #region color picker + if(key_mod_press(ALT) && color_picker_index) { + pickers[picker_index].editWidget.onColorPick(); + } + + if(MESSAGE != noone && MESSAGE.type == "Color") { + var inp = array_safe_get_fast(pickers, picker_index, 0); + if(is_struct(inp)) { + inp.setValue(MESSAGE.data); + MESSAGE = noone; + } + } + + color_picking = false; + #endregion + + #region drag + if(prop_dragging) { + if(DRAGGING == noone && point_distance(prop_sel_drag_x, prop_sel_drag_y, mouse_mx, mouse_my) > 16) { + prop_dragging.dragValue(); + prop_dragging = noone; + } + + if(mouse_release(mb_left)) + prop_dragging = noone; + } + #endregion + + if(prop_highlight_time) { + prop_highlight_time--; + if(prop_highlight_time == 0) + prop_highlight = noone; + } + + return hh; + } #endregion + + contentPane = new scrollPane(content_w, content_h, function(_y, _m) { #region + var con_w = contentPane.surface_w - ui(4); + + draw_clear_alpha(COLORS.panel_bg_clear, 0); + + if(point_in_rectangle(_m[0], _m[1], 0, 0, con_w, content_h) && mouse_press(mb_left, pFOCUS)) + prop_selecting = noone; + + if(inspecting == noone) return drawMeta(_y, _m); + + prop_page_button.setFocusHover(pFOCUS, pHOVER); + prop_page_button.draw(ui(32), _y + ui(4), contentPane.w - ui(76), ui(28), prop_page, _m, x + contentPane.x, y + contentPane.y); + + var _hh = ui(40); + _y += _hh; + + 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) + return drawNodeProperties(_y, _m, inspecting); + + for( var i = 0, n = min(10, array_length(inspectings)); i < n; i++ ) { + if(i) { + _y += ui(8); + _hh += ui(8); + } + + if(n > 1) { + draw_sprite_stretched_ext(THEME.group_label, 0, 0, _y, con_w, ui(32), COLORS.panel_inspector_output_label, 0.9); + draw_set_text(f_p0b, fa_center, fa_center, COLORS._main_text_sub); + + var _tx = inspectings[i].getFullName(); + draw_text_add(con_w / 2, _y + ui(16), _tx); + + _y += ui(32 + 8); + _hh += ui(32 + 8); + } + + var _h = drawNodeProperties(_y, _m, inspectings[i]); + _y += _h; + _hh += _h; + } + + return _hh; + }); #endregion + + function propSelectCopy() { #region + if(!prop_selecting) return; + clipboard_set_text(prop_selecting.getShowString()); + } #endregion + + function propSelectPaste() { #region + if(!prop_selecting) return; + + prop_selecting.setString(clipboard_get_text()); + } #endregion + + function drawInspectingNode() { #region + tb_node_name.font = f_h5; + tb_node_name.hide = true; + tb_node_name.align = fa_center; + tb_node_name.format = TEXT_AREA_FORMAT.node_title; + tb_node_name.setFocusHover(pFOCUS, pHOVER); + + var txt = inspecting.renamed? inspecting.display_name : inspecting.name; + if(inspectGroup == 1) txt = $"[{array_length(PANEL_GRAPH.nodes_selecting)}] {txt}"; + else if(inspectGroup == -1) txt = $"[{array_length(PANEL_GRAPH.nodes_selecting)}] Multiple nodes"; + + tb_node_name.draw(ui(64), ui(14), w - ui(128), ui(32), txt, [mx, my]); + + if(inspectGroup >= 0) { + draw_set_text(f_p1, fa_center, fa_center, COLORS._main_text_sub); + draw_text_add(w / 2 + ui(8), ui(56), inspecting.name); + + draw_set_text(f_p3, fa_center, fa_center, COLORS._main_text_sub); + draw_set_alpha(0.65); + draw_text_add(w / 2, ui(76), inspecting.internalName); + draw_set_alpha(1); + } + + var bx = ui(8); + var by = ui(12); + + if(inspectGroup == 0) { + draw_set_font(f_p1); + var lx = w / 2 - string_width(inspecting.name) / 2 - ui(10); + var ly = ui(56 - 8); + if(buttonInstant(THEME.button_hide, lx, ly, ui(16), ui(16), [mx, my], pFOCUS, pHOVER, __txt("Lock"), THEME.lock_12, !locked, locked? COLORS._main_icon_light : COLORS._main_icon) == 2) + locked = !locked; + + if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), [mx, my], pFOCUS, pHOVER, __txt("Presets"), THEME.preset, 1) == 2) + dialogCall(o_dialog_preset, x + bx, y + by + ui(36), { "node": inspecting }); + } else { + draw_sprite_ui_uniform(THEME.preset, 1, bx + ui(32) / 2, by + ui(32) / 2, 1, COLORS._main_icon_dark); + } + + by += ui(36); + view_mode_tooltip.index = viewMode; + if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), [mx, my], pFOCUS, pHOVER, view_mode_tooltip, THEME.inspector_view, viewMode) == 2) { + viewMode = !viewMode; + PREFERENCES.inspector_view_default = viewMode; + } + + //////////////////////////////////////////////////////////////////// INSPECTOR ACTIONS //////////////////////////////////////////////////////////////////// + + var bx = w - ui(44); + var by = ui(12); + + if(inspecting.hasInspector1Update(true)) { + var icon = inspecting.insp1UpdateIcon; + var ac = inspecting.insp1UpdateActive; + var cc = ac? icon[2] : COLORS._main_icon_dark; + var tt = inspecting.insp1UpdateTooltip; + if(inspectGroup) tt += " [All]"; + + if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), [mx, my], pFOCUS && ac, pHOVER && ac, tt, icon[0], icon[1], cc) == 2) { + if(inspectGroup == 1) { + for( var i = 0, n = array_length(inspectings); i < n; i++ ) inspectings[i].inspector1Update(); + } else + inspecting.inspector1Update(); + } + } else + draw_sprite_ui(THEME.sequence_control, 1, bx + ui(16), by + ui(16),,,, COLORS._main_icon_dark); + + if(inspecting.hasInspector2Update()) { + by += ui(36); + var icon = inspecting.insp2UpdateIcon; + var ac = inspecting.insp2UpdateActive; + var cc = ac? icon[2] : COLORS._main_icon_dark; + var tt = inspecting.insp2UpdateTooltip; + if(inspectGroup) tt += " [All]"; + + if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), [mx, my], pFOCUS && ac, pHOVER && ac, tt, icon[0], icon[1], cc) = 2) { + if(inspectGroup) { + for( var i = 0, n = array_length(inspectings); i < n; i++ ) inspectings[i].inspector2Update(); + } else + inspecting.inspector2Update(); + } + } + } #endregion + + function drawContent(panel) { #region >>>>>>>>>>>>>>>>>>>> MAIN DRAW <<<<<<<<<<<<<<<<<<<< + draw_clear_alpha(COLORS.panel_bg_clear, 0); + + draw_sprite_stretched(THEME.ui_panel_bg, 1, ui(8), top_bar_h - ui(8), w - ui(16), h - top_bar_h); + + if(inspecting && !inspecting.active) + inspecting = noone; + + if(inspecting) { + var _ins = instanceof(inspecting); + var _nodes = PANEL_GRAPH.nodes_selecting; + + inspectGroup = array_length(_nodes) > 1; + inspectings = array_empty(_nodes)? [ inspecting ] : _nodes; + + for( var i = 0, n = array_length(_nodes); i < n; i++ ) + if(instanceof(_nodes[i]) != _ins) { inspectGroup = -1; break; } + + title = inspecting.renamed? inspecting.display_name : inspecting.name; + inspecting.inspectorStep(); + drawInspectingNode(); + } else { + title = __txt("Inspector"); + + var txt = "Untitled"; + var context = PANEL_GRAPH.getCurrentContext(); + + if(context == noone && file_exists_empty(PROJECT.path)) + txt = string_replace(filename_name(PROJECT.path), filename_ext(PROJECT.path), ""); + else if(context != noone) + txt = context.name; + + draw_set_text(f_h5, fa_center, fa_center, COLORS._main_text); + draw_text_add(w / 2, ui(30), txt); + + if(PROJECT.meta.steam == FILE_STEAM_TYPE.steamOpen) { + var _tw = string_width(txt) / 2; + draw_sprite_ui(THEME.steam, 0, w / 2 - _tw - ui(16), ui(32),,,, COLORS._main_icon); + } + + var bx = w - ui(44); + var by = ui(12); + + if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), [mx, my], pFOCUS, pHOVER, __txtx("panel_inspector_set_default", "Set Metadata as default"), THEME.save, 0, COLORS._main_icon) == 2) { + var path = DIRECTORY + "meta.json"; + json_save_struct(path, PROJECT.meta.serialize()); + } + + by += ui(36); + if(STEAM_ENABLED && !workshop_uploading) { + if(PROJECT.path == "") { + buttonInstant(noone, bx, by, ui(32), ui(32), [mx, my], pFOCUS, pHOVER, __txtx("panel_inspector_workshop_save", "Save file before upload"), THEME.workshop_upload, 0, COLORS._main_icon, 0.5); + } else { + if(PROJECT.meta.steam == FILE_STEAM_TYPE.local) { //project made locally + if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), [mx, my], pFOCUS, pHOVER, __txtx("panel_inspector_workshop_upload", "Upload to Steam Workshop"), THEME.workshop_upload, 0, COLORS._main_icon) == 2) { + var s = PANEL_PREVIEW.getNodePreviewSurface(); + if(is_surface(s)) { + PROJECT.meta.author_steam_id = STEAM_USER_ID; + PROJECT.meta.steam = FILE_STEAM_TYPE.steamUpload; + SAVE_AT(PROJECT, PROJECT.path); + + steam_ugc_create_project(); + workshop_uploading = true; + } else + noti_warning("Please send any node to preview panel to use as a thumbnail.") + } + } + + if(PROJECT.meta.steam && PROJECT.meta.author_steam_id == STEAM_USER_ID) { + if(PROJECT.meta.steam == FILE_STEAM_TYPE.steamUpload) { + buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), [mx, my], false, pHOVER, __txtx("panel_inspector_workshop_restart", "Open project from the workshop tab to update."), THEME.workshop_update, 0, COLORS._main_icon); + } else if(buttonInstant(THEME.button_hide, bx, by, ui(32), ui(32), [mx, my], pFOCUS, pHOVER, __txtx("panel_inspector_workshop_update", "Update Steam Workshop content"), THEME.workshop_update, 0, COLORS._main_icon) == 2) { + SAVE_AT(PROJECT, PROJECT.path); + steam_ugc_update_project(); + workshop_uploading = true; + } + } + } + } + + if(workshop_uploading) { + draw_sprite_ui(THEME.loading_s, 0, bx + ui(16), by + ui(16),,, current_time / 5, COLORS._main_icon); + if(STEAM_UGC_ITEM_UPLOADING == false) + workshop_uploading = false; + } + } + + contentPane.setFocusHover(pFOCUS, pHOVER); + contentPane.draw(ui(16), top_bar_h, mx - ui(16), my - top_bar_h); + + if(!locked && PANEL_GRAPH.getFocusingNode() && inspecting != PANEL_GRAPH.getFocusingNode()) + setInspecting(PANEL_GRAPH.getFocusingNode()); + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/panel_preview/panel_preview.gml.backup0 b/#backups/scripts/panel_preview/panel_preview.gml.backup0 new file mode 100644 index 000000000..f5a180b6f --- /dev/null +++ b/#backups/scripts/panel_preview/panel_preview.gml.backup0 @@ -0,0 +1,1770 @@ +// 2024-04-14 12:50:29 +#region funtion calls + function __fnInit_Preview() { + __registerFunction("preview_focus_content", panel_preview_focus_content); + __registerFunction("preview_save_current_frame", panel_preview_save_current_frame); + __registerFunction("preview_save_all_current_frame", panel_preview_save_all_current_frame); + __registerFunction("preview_preview_window", panel_preview_preview_window); + __registerFunction("preview_toggle_grid", panel_preview_toggle_grid); + + __registerFunction("preview_pan", panel_preview_pan); + __registerFunction("preview_zoom", panel_preview_zoom); + } + + function panel_preview_focus_content() { CALL("preview_focus_content"); PANEL_PREVIEW.fullView(); } + function panel_preview_save_current_frame() { CALL("preview_save_current_frame"); PANEL_PREVIEW.saveCurrentFrame(); } + function panel_preview_save_all_current_frame() { CALL("preview_save_all_current_frame"); PANEL_PREVIEW.saveAllCurrentFrames(); } + function panel_preview_preview_window() { CALL("preview_preview_window"); PANEL_PREVIEW.create_preview_window(PANEL_PREVIEW.getNodePreview()); } + function panel_preview_toggle_grid() { CALL("preview_toggle_grid"); PROJECT.previewGrid.show = !PROJECT.previewGrid.show; } + + function panel_preview_pan() { CALL("preview_pan"); PANEL_PREVIEW.canvas_dragging_key = true; } + function panel_preview_zoom() { CALL("preview_zoom"); PANEL_PREVIEW.canvas_zooming_key = true; } +#endregion + +function Panel_Preview() : PanelContent() constructor { + title = __txt("Preview"); + context_str = "Preview"; + icon = THEME.panel_preview_icon; + + last_focus = noone; + + #region ---- canvas control & sample ---- + function initSize() { + canvas_x = w / 2; + canvas_y = h / 2; + } + run_in(1, function() { initSize() }); + + canvas_x = 0; + canvas_y = 0; + canvas_s = ui(1); + canvas_w = ui(128); + canvas_h = ui(128); + canvas_a = 0; + + canvas_bg = -1; + + do_fullView = false; + + canvas_hover = true; + canvas_dragging_key = false; + canvas_dragging = false; + canvas_drag_key = 0; + canvas_drag_mx = 0; + canvas_drag_my = 0; + canvas_drag_sx = 0; + canvas_drag_sy = 0; + + canvas_zooming_key = false; + canvas_zooming = false; + canvas_zoom_mx = 0; + canvas_zoom_my = 0; + canvas_zoom_m = 0; + canvas_zoom_s = 0; + + sample_color = noone; + sample_x = noone; + sample_y = noone; + + #endregion + + #region ---- preview ---- + locked = false; + preview_node = [ noone, noone ]; + preview_surfaces = [ 0, 0 ]; + preview_surface = [ 0, 0 ]; + tile_surface = surface_create(1, 1); + + preview_x = 0; + preview_x_to = 0; + preview_x_max = 0; + preview_sequence = [ 0, 0 ]; + _preview_sequence = preview_sequence; + preview_rate = 10; + + right_menu_x = 0; + right_menu_y = 8; + mouse_on_preview = 0; + _mouse_on_preview = 0; + + resetViewOnDoubleClick = true; + + splitView = 0; + splitPosition = 0.5; + splitSelection = 0; + + splitViewDragging = false; + splitViewStart = 0; + splitViewMouse = 0; + + tileMode = 0; + + bg_color = COLORS.panel_bg_clear; + #endregion + + #region ---- tool ---- + tool_x = 0; + tool_x_to = 0; + tool_x_max = 0; + + tool_y = 0; + tool_y_to = 0; + tool_y_max = 0; + + tool_ry = 0; + tool_ry_to = 0; + tool_ry_max = 0; + + tool_current = noone; + + toolbar_width = ui(40); + toolbar_height = ui(40); + + tool_hovering = false; + tool_side_drawing = false; + overlay_hovering = false; + + sbChannel = new scrollBox([], function(index) { #region + var node = getNodePreview(); + if(node == noone) return; + + node.preview_channel = array_safe_get_fast(sbChannelIndex, index); + }); #endregion + sbChannelIndex = []; + sbChannel.font = f_p1; + sbChannel.align = fa_left; + #endregion + + #region ---- 3d ---- + d3_active = false; + _d3_active = false; + d3_active_transition = 0; + + d3_surface = noone; + d3_surface_normal = noone; + d3_surface_depth = noone; + d3_surface_outline = noone; + d3_surface_bg = noone; + d3_preview_channel = 0; + + d3_deferData = noone; + + global.SKY_SPHERE = new __3dUVSphere(0.5, 16, 8, true); + + #region camera + d3_view_camera = new __3dCamera(); + d3_camW = 1; + d3_camH = 1; + + d3_view_camera.setFocusAngle(135, 45, 4); + d3_camLerp = false; + + d3_camTarget = new __vec3(); + + d3_camPanning = false; + d3_camPan_mx = 0; + d3_camPan_my = 0; + + d3_zoom_speed = 0.2; + d3_pan_speed = 2; + #endregion + + #region scene + d3_scene = new __3dScene(d3_view_camera, "Preview panel"); + d3_scene.lightAmbient = $404040; + d3_scene.cull_mode = cull_counterclockwise; + d3_scene_preview = d3_scene; + + d3_scene_light_enabled = true; + + d3_scene_light0 = new __3dLightDirectional(); + d3_scene_light0.transform.position.set(-1, -2, 3); + d3_scene_light0.color = $FFFFFF; + d3_scene_light0.shadow_active = false; + d3_scene_light0.shadow_map_scale = 4; + + d3_scene_light1 = new __3dLightDirectional(); + d3_scene_light1.transform.position.set(1, 2, -3); + d3_scene_light1.color = $505050; + #endregion + + #region tool + d3_tool_snap = false; + d3_tool_snap_position = 1; + d3_tool_snap_rotation = 15; + #endregion + + #region shadow map + + #endregion + + #region view channel + d3ChannelNames = [ "Rendered", "Normal", "Depth" ]; + d3Channel = new scrollBox(d3ChannelNames, function(index) { d3_preview_channel = index; }); + d3Channel.align = fa_left; + #endregion + #endregion + + tb_framerate = new textBox(TEXTBOX_INPUT.number, function(val) { preview_rate = real(val); }); + + #region ++++ hotkey ++++ + addHotkey("Preview", "Focus content", "F", MOD_KEY.none, panel_preview_focus_content); + addHotkey("Preview", "Save current frame", "S", MOD_KEY.shift, panel_preview_save_current_frame); + addHotkey("Preview", "Save all current frame", -1, MOD_KEY.none, panel_preview_save_all_current_frame); + addHotkey("Preview", "Preview window", "P", MOD_KEY.ctrl, panel_preview_preview_window); + addHotkey("Preview", "Toggle grid", "G", MOD_KEY.ctrl, panel_preview_toggle_grid); + + addHotkey("Preview", "Pan", "", MOD_KEY.ctrl, panel_preview_pan); + addHotkey("Preview", "Zoom", "", MOD_KEY.alt | MOD_KEY.ctrl, panel_preview_zoom); + #endregion + + #region ++++ toolbars & actions ++++ + topbar_height = ui(32); + toolbar_height = ui(40); + toolbars = [ + [ + THEME.icon_reset_when_preview, + function() { return resetViewOnDoubleClick; }, + function() { return resetViewOnDoubleClick? __txtx("panel_preview_center_canvas_on_preview", "Center canvas on preview") : + __txtx("panel_preview_keep_canvas_on_preview", "Keep canvas on preview"); }, + function() { resetViewOnDoubleClick = !resetViewOnDoubleClick; } + ], + [ + THEME.icon_split_view, + function() { return splitView; }, + function() { + switch(splitView) { + case 0 : return __txtx("panel_preview_split_view_off", "Split view off"); + case 1 : return __txtx("panel_preview_horizontal_split_view", "Horizontal split view"); + case 2 : return __txtx("panel_preview_vertical_split_view", "Vertical split view"); + } + return __txtx("panel_preview_split_view", "Split view"); + }, + function() { splitView = (splitView + 1) % 3; } + ], + [ + THEME.icon_tile_view, + function() { var t = [3, 0, 1, 2]; return array_safe_get_fast(t, tileMode); }, + function() { + switch(tileMode) { + case 0 : return __txtx("panel_preview_tile_off", "Tile off"); + case 1 : return __txtx("panel_preview_tile_horizontal", "Tile horizontal"); + case 2 : return __txtx("panel_preview_tile_vertical", "Tile vertical"); + case 3 : return __txtx("panel_preview_tile_both", "Tile both"); + } + return __txtx("panel_preview_tile_mode", "Tile mode"); + }, + function(data) { + menuCall("preview_tile_menu", data.x + ui(28), data.y + ui(28), [ + menuItem(__txtx("panel_preview_tile_off", "Tile off"), function() { tileMode = 0; }), + menuItem(__txtx("panel_preview_tile_horizontal", "Tile horizontal"), function() { tileMode = 1; }), + menuItem(__txtx("panel_preview_tile_vertical", "Tile vertical"), function() { tileMode = 2; }), + menuItem(__txtx("panel_preview_tile_both", "Tile both"), function() { tileMode = 3; }), + ]); + } + ], + [ + THEME.icon_grid_setting, + function() { return 0; }, + function() { return __txtx("grid_title", "Grid setting") }, + function(param) { + var dia = dialogPanelCall(new Panel_Preview_Grid_Setting(), param.x, param.y, { anchor: ANCHOR.bottom | ANCHOR.left }); + } + ], + [ + THEME.onion_skin, + function() { return 0; }, + function() { return __txt("Onion Skin") }, + function(param) { + var dia = dialogPanelCall(new Panel_Preview_Onion_Setting(), param.x, param.y, { anchor: ANCHOR.bottom | ANCHOR.left }); + } + ], + ]; + + toolbars_3d = [ + [ + THEME.d3d_preview_settings, + function() { return 0; }, + function() { return __txt("3D Preview Settings") }, + function(param) { + var dia = dialogPanelCall(new Panel_Preview_3D_Setting(self), param.x, param.y, { anchor: ANCHOR.bottom | ANCHOR.left }); + } + ], + [ + THEME.d3d_snap_settings, + function() { return 0; }, + function() { return __txt("3D Snap Settings") }, + function(param) { + var dia = dialogPanelCall(new Panel_Preview_Snap_Setting(self), param.x, param.y, { anchor: ANCHOR.bottom | ANCHOR.left }); + } + ], + ]; + + tooltip_center = new tooltipHotkey(__txtx("panel_preview_center_canvas", "Center canvas"), "Preview", "Focus content"); + + actions = [ + [ + THEME.lock, + __txtx("panel_preview_lock_preview", "Lock previewing node"), + function() { locked = !locked; }, + function() { return !locked; }, + ], + [ + THEME.icon_preview_export, + __txtx("panel_preview_export_canvas", "Export canvas"), + function() { saveCurrentFrame(); }, + function() { return 0; }, + ], + [ + THEME.icon_center_canvas, + tooltip_center, + function() { fullView(); }, + function() { return 0; }, + ], + + ]; + #endregion + + function setNodePreview(node) { #region + if(locked) return; + + if(resetViewOnDoubleClick) + do_fullView = true; + + if(is_instanceof(node, Node) && node.getPreviewingNode != noone) + node = node.getPreviewingNode(); + + preview_node[splitView? splitSelection : 0] = node; + } #endregion + + function removeNodePreview(node) { #region + if(locked) return; + + if(preview_node[0] == node) preview_node[0] = noone; + if(preview_node[1] == node) preview_node[1] = noone; + } #endregion + + function resetNodePreview() { #region + preview_node = [ noone, noone ]; + locked = false; + } #endregion + + function getNodePreview() { return preview_node[splitView? splitSelection : 0]; } + function getNodePreviewSurface() { return preview_surfaces[splitView? splitSelection : 0]; } + function getNodePreviewSequence() { return preview_sequence[splitView? splitSelection : 0]; } + + function getPreviewData() { #region + preview_surfaces = [ noone, noone ]; + preview_sequence = [ noone, noone ]; + + for( var i = 0; i < 2; i++ ) { + var node = preview_node[i]; + + if(node == noone) continue; + if(!node.active) { + resetNodePreview(); + return; + } + + var value = node.getPreviewValues(); + + if(is_array(value)) { + preview_sequence[i] = value; + canvas_a = array_length(value); + } else { + preview_surfaces[i] = value; + canvas_a = 0; + } + + if(preview_sequence[i] != noone) { + if(array_length(preview_sequence[i]) == 0) return; + preview_surfaces[i] = preview_sequence[i][safe_mod(node.preview_index, array_length(preview_sequence[i]))]; + } + } + + var prevS = getNodePreviewSurface(); + + if(is_surface(prevS)) { + canvas_w = surface_get_width_safe(prevS); + canvas_h = surface_get_height_safe(prevS); + } + } #endregion + + function onFocusBegin() { PANEL_PREVIEW = self; } + + function dragCanvas() { #region + if(canvas_dragging) { + if(!MOUSE_WRAPPING) { + var dx = mx - canvas_drag_mx; + var dy = my - canvas_drag_my; + + canvas_x += dx; + canvas_y += dy; + } + + canvas_drag_mx = mx; + canvas_drag_my = my; + setMouseWrap(); + + if(mouse_release(canvas_drag_key)) + canvas_dragging = false; + } + + if(canvas_zooming) { + if(!MOUSE_WRAPPING) { + var dy = -(my - canvas_zoom_m) / 200; + + var _s = canvas_s; + canvas_s = clamp(canvas_s * (1 + dy), 0.10, 64); + + if(_s != canvas_s) { + var dx = (canvas_s - _s) * ((canvas_zoom_mx - canvas_x) / _s); + var dy = (canvas_s - _s) * ((canvas_zoom_my - canvas_y) / _s); + canvas_x -= dx; + canvas_y -= dy; + } + } + + canvas_zoom_m = my; + setMouseWrap(); + + if(mouse_release(canvas_drag_key)) + canvas_zooming = false; + } + + if(pHOVER && canvas_hover) { + var _doDragging = false; + var _doZooming = false; + + if(mouse_press(PREFERENCES.pan_mouse_key, pFOCUS)) { + _doDragging = true; + canvas_drag_key = PREFERENCES.pan_mouse_key; + } else if(mouse_press(mb_left, pFOCUS) && canvas_dragging_key) { + _doDragging = true; + canvas_drag_key = mb_left; + } else if(mouse_press(mb_left, pFOCUS) && canvas_zooming_key) { + _doZooming = true; + canvas_drag_key = mb_left; + } + + if(_doDragging) { + canvas_dragging = true; + canvas_drag_mx = mx; + canvas_drag_my = my; + canvas_drag_sx = canvas_x; + canvas_drag_sy = canvas_y; + } + + if(_doZooming) { + canvas_zooming = true; + canvas_zoom_mx = mx; + canvas_zoom_my = my; + canvas_zoom_m = my; + canvas_zoom_s = canvas_s; + } + + var _canvas_s = canvas_s; + var inc = 0.1; + if(canvas_s > 16) inc = 2; + else if(canvas_s > 8) inc = 1; + else if(canvas_s > 3) inc = 0.5; + else if(canvas_s > 1) inc = 0.25; + + if(mouse_wheel_down() && !key_mod_press_any()) canvas_s = max(round(canvas_s / inc) * inc - inc, 0.10); + if(mouse_wheel_up() && !key_mod_press_any()) canvas_s = min(round(canvas_s / inc) * inc + inc, 64); + + if(_canvas_s != canvas_s) { + var dx = (canvas_s - _canvas_s) * ((mx - canvas_x) / _canvas_s); + var dy = (canvas_s - _canvas_s) * ((my - canvas_y) / _canvas_s); + canvas_x -= dx; + canvas_y -= dy; + } + } + + canvas_dragging_key = false; + canvas_zooming_key = false; + canvas_hover = point_in_rectangle(mx, my, 0, toolbar_height, w, h - toolbar_height); + } #endregion + + function dragCanvas3D() { #region + if(d3_camPanning) { + if(!MOUSE_WRAPPING) { + var dx = mx - d3_camPan_mx; + var dy = my - d3_camPan_my; + + var px = d3_view_camera.focus_angle_x; + var py = d3_view_camera.focus_angle_y; + var ax = px + dx * 0.2 * d3_pan_speed; + var ay = py + dy * 0.1 * d3_pan_speed; + + //if(py < 90 && ay >= 90) ax -= 180; + //if(py > 90 && ay <= 90) ax += 180; + + //print($"{ax},\t{ay}"); + + d3_view_camera.focus_angle_x = ax; + d3_view_camera.focus_angle_y = ay; + } + + d3_camPan_mx = mx; + d3_camPan_my = my; + setMouseWrap(); + + if(mouse_release(canvas_drag_key)) + d3_camPanning = false; + } + + if(canvas_zooming) { + if(!MOUSE_WRAPPING) { + var dy = -(my - canvas_zoom_m) / 200; + d3_view_camera.focus_dist = clamp(d3_view_camera.focus_dist + dy, 1, 1000); + } + + canvas_zoom_m = my; + setMouseWrap(); + + if(mouse_release(canvas_drag_key)) + canvas_zooming = false; + } + + if(pHOVER && canvas_hover) { + var _doDragging = false; + var _doZooming = false; + + if(mouse_press(PREFERENCES.pan_mouse_key, pFOCUS)) { + _doDragging = true; + canvas_drag_key = PREFERENCES.pan_mouse_key; + } else if(mouse_press(mb_left, pFOCUS) && canvas_dragging_key) { + _doDragging = true; + canvas_drag_key = mb_left; + } else if(mouse_press(mb_left, pFOCUS) && canvas_zooming_key) { + _doZooming = true; + canvas_drag_key = mb_left; + } + + if(_doDragging) { + d3_camPanning = true; + d3_camPan_mx = mx; + d3_camPan_my = my; + } + + if(_doZooming) { + canvas_zooming = true; + canvas_zoom_m = my; + } + + if(mouse_wheel_up()) d3_view_camera.focus_dist = max( 1, d3_view_camera.focus_dist * (1 - d3_zoom_speed)); + if(mouse_wheel_down()) d3_view_camera.focus_dist = min(1000, d3_view_camera.focus_dist * (1 + d3_zoom_speed)); + } + + canvas_dragging_key = false; + canvas_zooming_key = false; + canvas_hover = point_in_rectangle(mx, my, 0, toolbar_height, w, h - toolbar_height); + } #endregion + + function fullView() { #region + var bbox = noone; + + var node = getNodePreview(); + if(node != noone) bbox = node.getPreviewBoundingBox(); + if(bbox == noone) bbox = BBOX().fromWH(0, 0, PROJECT.attributes.surface_dimension[0], PROJECT.attributes.surface_dimension[1]); + + var ss = min((w - 32 - tool_side_drawing * 40) / bbox.w, (h - 32 - toolbar_height * 2) / bbox.h); + canvas_s = ss; + canvas_x = w / 2 - bbox.w * canvas_s / 2 - bbox.x0 * canvas_s + (tool_side_drawing * 40 / 2); + canvas_y = h / 2 - bbox.h * canvas_s / 2 - bbox.y0 * canvas_s; + } #endregion + + function drawNodeChannel(_x, _y) { #region + var _node = getNodePreview(); + if(_node == noone) return; + if(ds_list_size(_node.outputs) < 2) return; + + var chName = []; + sbChannelIndex = []; + + var currName = _node.outputs[| _node.preview_channel].name; + draw_set_text(sbChannel.font, fa_center, fa_center); + var ww = 0; + var hh = TEXTBOX_HEIGHT - ui(2); + + for( var i = 0; i < ds_list_size(_node.outputs); i++ ) { + if(_node.outputs[| i].type != VALUE_TYPE.surface) continue; + + array_push(chName, _node.outputs[| i].name); + array_push(sbChannelIndex, i); + ww = max(ww, string_width(_node.outputs[| i].name) + ui(40)); + } + + sbChannel.data_list = chName; + sbChannel.setFocusHover(pFOCUS, pHOVER); + sbChannel.draw(_x - ww, _y - hh / 2, ww, hh, currName, [mx, my], x, y); + right_menu_y += ui(40); + } #endregion + + function drawNodeChannel3D(_x, _y) { #region + var _node = getNodePreview(); + if(_node == noone) return; + + var ww = ui(128); + var hh = toolbar_height - ui(12); + + d3Channel.setFocusHover(pFOCUS, pHOVER); + d3Channel.draw(_x - ww, _y - hh / 2, ww, hh, d3ChannelNames[d3_preview_channel], [mx, my], x, y); + right_menu_y += ui(40); + } #endregion + + function drawOnionSkin(node, psx, psy, ss) { #region + var _surf = preview_surfaces[0]; + var _rang = PROJECT.onion_skin.range; + + var _alph = PROJECT.onion_skin.alpha; + var _colr = PROJECT.onion_skin.color; + + var _step = PROJECT.onion_skin.step; + var _top = PROJECT.onion_skin.on_top; + + var fr = CURRENT_FRAME; + var st = min(_rang[0], _rang[1]); + var ed = max(_rang[0], _rang[1]); + + st = sign(st) * floor(abs(st) / _step) * _step; + ed = sign(ed) * floor(abs(ed) / _step) * _step; + + st += fr; + ed += fr; + + for( var i = st; i <= ed; i += _step ) { + var surf = node.getCacheFrame(i); + if(!is_surface(surf)) continue; + + var aa = power(_alph, abs((i - fr) / _step)); + var cc = c_white; + if(i < fr) cc = _colr[0]; + else if(i > fr) cc = _colr[1]; + + draw_surface_ext_safe(surf, psx, psy, ss, ss, 0, cc, aa); + } + + if(_top) draw_surface_ext_safe(_surf, psx, psy, ss, ss); + } #endregion + + function drawNodePreview() { #region + var ss = canvas_s; + var psx = 0, psy = 0; + var psw = 0, psh = 0; + var pswd = 0, pshd = 0; + var psx1 = 0, psy1 = 0; + + var ssx = 0, ssy = 0; + var ssw = 0, ssh = 0; + + if(is_surface(preview_surfaces[0])) { + psx = canvas_x + preview_node[0].preview_x * ss; + psy = canvas_y + preview_node[0].preview_y * ss; + + psw = surface_get_width_safe(preview_surfaces[0]); + psh = surface_get_height_safe(preview_surfaces[0]); + pswd = psw * ss; + pshd = psh * ss; + + psx1 = psx + pswd; + psy1 = psy + pshd; + } + + if(is_surface(preview_surfaces[1])) { + var ssx = canvas_x + preview_node[1].preview_x * ss; + var ssy = canvas_y + preview_node[1].preview_y * ss; + + var ssw = surface_get_width_safe(preview_surfaces[1]); + var ssh = surface_get_height_safe(preview_surfaces[1]); + } + + var _node = getNodePreview(); + if(_node) title = _node.renamed? _node.display_name : _node.name; + + #region >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Draw Surfaces <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + var _ps0 = is_surface(preview_surfaces[0]); + var _ps1 = is_surface(preview_surfaces[1]); + + if(_ps0) { + var _sw = surface_get_width_safe(preview_surfaces[0]); + var _sh = surface_get_height_safe(preview_surfaces[0]); + + preview_surface[0] = surface_verify(preview_surface[0], _sw, _sh); + + surface_set_shader(preview_surface[0], PROJECT.attributes.palette_fix? sh_posterize_palette : sh_sample); + shader_set_f("palette", PROJECT.palettes); + shader_set_i("keys", array_length(PROJECT.attributes.palette)); + shader_set_i("alpha", 1); + + draw_surface_safe(preview_surfaces[0]); + surface_reset_shader(); + } + + if(_ps1) { + var _sw = surface_get_width_safe(preview_surfaces[1]); + var _sh = surface_get_height_safe(preview_surfaces[1]); + + preview_surface[1] = surface_verify(preview_surface[1], _sw, _sh); + + surface_set_shader(preview_surface[1], PROJECT.attributes.palette_fix? sh_posterize_palette : sh_sample); + shader_set_f("palette", PROJECT.palettes); + shader_set_i("keys", array_length(PROJECT.attributes.palette)); + shader_set_i("alpha", 1); + + draw_surface_safe(preview_surfaces[1]); + surface_reset_shader(); + } + + switch(splitView) { + case 0 : + if(_ps0) { + preview_node[0].previewing = 1; + + switch(tileMode) { + case 0 : + if(PROJECT.onion_skin.enabled) drawOnionSkin(node, psx, psy, ss); + else draw_surface_ext(preview_surface[0], psx, psy, ss, ss, 0, c_white, preview_node[0].preview_alpha); + break; + + case 1 : + tile_surface = surface_verify(tile_surface, w, surface_get_height_safe(preview_surface[0]) * ss); + surface_set_target(tile_surface); + DRAW_CLEAR + draw_surface_tiled_ext_safe(preview_surface[0], psx, 0, ss, ss, 0, c_white, 1); + surface_reset_target(); + draw_surface_safe(tile_surface, 0, psy); + break; + + case 2 : + tile_surface = surface_verify(tile_surface, surface_get_width_safe(preview_surface[0]) * ss, h); + surface_set_target(tile_surface); + DRAW_CLEAR + draw_surface_tiled_ext_safe(preview_surface[0], 0, psy, ss, ss, 0, c_white, 1); + surface_reset_target(); + draw_surface_safe(tile_surface, psx, 0); + break; + + case 3 : + draw_surface_tiled_ext_safe(preview_surface[0], psx, psy, ss, ss, 0, c_white, 1); break; + } + } + break; + case 1 : + var sp = splitPosition * w; + + if(_ps0) { + preview_node[0].previewing = 2; + var maxX = min(sp, psx1); + var sW = min(psw, (maxX - psx) / ss); + + if(sW > 0) + draw_surface_part_ext_safe(preview_surface[0], 0, 0, sW, psh, psx, psy, ss, ss, 0, c_white, 1); + } + + if(_ps1) { + preview_node[1].previewing = 3; + var minX = max(ssx, sp); + var sX = (minX - ssx) / ss; + var spx = max(sp, ssx); + + if(sX >= 0 && sX < ssw) + draw_surface_part_ext_safe(preview_surface[1], sX, 0, ssw - sX, ssh, spx, ssy, ss, ss, 0, c_white, 1); + } + break; + case 2 : + var sp = splitPosition * h; + + if(_ps0) { + preview_node[0].previewing = 4; + var maxY = min(sp, psy1); + var sH = min(psh, (maxY - psy) / ss); + + if(sH > 0) + draw_surface_part_ext_safe(preview_surface[0], 0, 0, psw, sH, psx, psy, ss, ss, 0, c_white, 1); + } + + if(_ps1) { + preview_node[1].previewing = 5; + var minY = max(ssy, sp); + var sY = (minY - ssy) / ss; + var spy = max(sp, ssy); + + if(sY >= 0 && sY < ssh) + draw_surface_part_ext_safe(preview_surface[1], 0, sY, ssw, ssh - sY, ssx, spy, ss, ss, 0, c_white, 1); + } + break; + } + #endregion + + if(!instance_exists(o_dialog_menubox)) { #region color sample + sample_color = noone; + sample_x = noone; + sample_y = noone; + + if(mouse_on_preview && (mouse_press(mb_right) || key_mod_press(CTRL))) { + var _sx = sample_x; + var _sy = sample_y; + + sample_x = floor((mx - canvas_x) / canvas_s); + sample_y = floor((my - canvas_y) / canvas_s); + var surf = getNodePreviewSurface(); + sample_color = surface_get_pixel_ext(surf, sample_x, sample_y); + + //print($"{dec_to_hex(sample_color)}: {color_get_alpha(int64(sample_color))}"); + } + } #endregion + + if(is_surface(preview_surfaces[0])) { #region outline + if(PROJECT.previewGrid.show) { + var _gw = PROJECT.previewGrid.size[0] * canvas_s; + var _gh = PROJECT.previewGrid.size[1] * canvas_s; + + var gw = pswd / _gw; + var gh = pshd / _gh; + + var cx = canvas_x; + var cy = canvas_y; + + draw_set_color(PROJECT.previewGrid.color); + draw_set_alpha(PROJECT.previewGrid.opacity); + + for( var i = 1; i < gw; i++ ) { + var _xx = cx + i * _gw; + draw_line(_xx, cy, _xx, cy + pshd); + } + + for( var i = 1; i < gh; i++ ) { + var _yy = cy + i * _gh; + draw_line(cx, _yy, cx + pswd, _yy); + } + + draw_set_alpha(1); + } + + draw_set_color(COLORS.panel_preview_surface_outline); + draw_rectangle(psx, psy, psx + pswd - 1, psy + pshd - 1, true); + } #endregion + } #endregion + + function draw3D() { #region + var _prev_node = getNodePreview(); + if(_prev_node == noone) return; + if(!_prev_node.is_3D) return; + + _prev_node.previewing = 1; + + d3_scene_preview = struct_has(_prev_node, "scene")? _prev_node.scene : d3_scene; + d3_scene_preview.camera = d3_view_camera; + + #region view + var _pos, targ, _blend = 1; + + targ = d3_camTarget; + _pos = d3d_PolarToCart(targ.x, targ.y, targ.z, d3_view_camera.focus_angle_x, d3_view_camera.focus_angle_y, d3_view_camera.focus_dist); + + if(d3_active_transition == 1) { + var _up = new __vec3(0, 0, -1); + + d3_view_camera.position._lerp_float(_pos, 5, 0.1); + d3_view_camera.focus._lerp_float( targ, 5, 0.1); + d3_view_camera.up._lerp_float( _up, 5, 0.1); + + if(d3_view_camera.position.equal(_pos) && d3_view_camera.focus.equal(targ)) + d3_active_transition = 0; + } else if(d3_active_transition == -1) { + var _pos = new __vec3(0, 0, 8); + var targ = new __vec3(0, 0, 0); + var _up = new __vec3(0, 1, 0); + + d3_view_camera.position._lerp_float(_pos, 5, 0.1); + d3_view_camera.focus._lerp_float( targ, 5, 0.1); + d3_view_camera.up._lerp_float( _up, 5, 0.1); + + _blend = d3_view_camera.position.distance(_pos) / 2; + _blend = clamp(_blend, 0, 1); + + if(d3_view_camera.position.equal(_pos) && d3_view_camera.focus.equal(targ)) + d3_active_transition = 0; + } else { + d3_view_camera.position.set(_pos); + d3_view_camera.focus.set(targ); + } + + d3_view_camera.setViewSize(w, h); + d3_view_camera.setMatrix(); + #endregion + + #region background + surface_free_safe(d3_surface_bg); + + if(d3_scene_preview != d3_scene) + d3_surface_bg = d3_scene_preview.renderBackground(w, h); + #endregion + + #region shadow + if(d3_scene_preview == d3_scene) { + d3_scene_light0.shadow_map_scale = d3_view_camera.focus_dist * 2; + + var _prev_obj = _prev_node.getPreviewObject(); + if(_prev_obj != noone) { + d3_scene_light0.submitShadow(d3_scene_preview, _prev_obj); + _prev_obj.submitShadow(d3_scene_preview, _prev_obj); + } + } + #endregion + + d3_surface = surface_verify(d3_surface, w, h); + d3_surface_normal = surface_verify(d3_surface_normal, w, h); + d3_surface_depth = surface_verify(d3_surface_depth, w, h); + d3_surface_outline = surface_verify(d3_surface_outline, w, h); + + #region defer + var _prev_obj = _prev_node.getPreviewObject(); + d3_deferData = d3_scene_preview.deferPass(_prev_obj, w, h, d3_deferData); + #endregion + + #region grid + surface_set_target_ext(0, d3_surface); + surface_set_target_ext(1, d3_surface_normal); + surface_set_target_ext(2, d3_surface_depth); + + draw_clear_alpha(bg_color, 0); + + d3_view_camera.applyCamera(); + + gpu_set_ztestenable(true); + gpu_set_zwriteenable(false); + + if(OS != os_macosx) { + gpu_set_cullmode(cull_noculling); + + shader_set(sh_d3d_grid_view); + var _dist = round(d3_view_camera.focus.distance(d3_view_camera.position)); + var _tx = round(d3_view_camera.focus.x); + var _ty = round(d3_view_camera.focus.y); + + var _scale = _dist * 2; + while(_scale > 32) _scale /= 2; + + shader_set_f("axisBlend", _blend); + shader_set_f("scale", _scale); + shader_set_f("shift", _tx / _dist / 2, _ty / _dist / 2); + draw_sprite_stretched(s_fx_pixel, 0, _tx - _dist, _ty - _dist, _dist * 2, _dist * 2); + shader_reset(); + } + + gpu_set_zwriteenable(true); + #endregion + + #region draw + d3_scene_preview.reset(); + gpu_set_cullmode(cull_counterclockwise); + + var _prev_obj = _prev_node.getPreviewObjects(); + + if(d3_scene_preview == d3_scene) { + if(d3_scene_light_enabled) { + d3_scene_preview.addLightDirectional(d3_scene_light0); + d3_scene_preview.addLightDirectional(d3_scene_light1); + } + } + + for( var i = 0, n = array_length(_prev_obj); i < n; i++ ) { + var _prev = _prev_obj[i]; + if(_prev == noone) continue; + + _prev.submitShader(d3_scene_preview); + } + + d3_scene_preview.apply(d3_deferData); + + //print("========= Submit begin ========="); + for( var i = 0, n = array_length(_prev_obj); i < n; i++ ) { + var _prev = _prev_obj[i]; + if(_prev == noone) continue; + _prev.submitUI(d3_scene_preview); //////////////// SUBMIT //////////////// + } + //print("========= Submit end ========="); + + gpu_set_cullmode(cull_noculling); + surface_reset_target(); + + draw_clear(bg_color); + + switch(d3_preview_channel) { + case 0 : + if(d3_scene_preview.draw_background) + draw_surface_safe(d3_surface_bg); + + draw_surface_safe(d3_surface); + + BLEND_MULTIPLY + draw_surface_safe(d3_deferData.ssao); + BLEND_NORMAL + break; + case 1 : draw_surface_safe(d3_surface_normal); break; + case 2 : draw_surface_safe(d3_surface_depth); break; + } + #endregion + + #region outline + var inspect_node = PANEL_INSPECTOR.getInspecting(); + + if(inspect_node && inspect_node.is_3D) { + var _inspect_obj = inspect_node.getPreviewObjectOutline(); + + surface_set_target(d3_surface_outline); + draw_clear(c_black); + + d3_scene_preview.camera.applyCamera(); + + gpu_set_ztestenable(false); + for( var i = 0, n = array_length(_inspect_obj); i < n; i++ ) { + if(_inspect_obj[i] == noone) continue; + _inspect_obj[i].submitSel(d3_scene_preview); + } + surface_reset_target(); + + shader_set(sh_d3d_outline); + shader_set_dim("dimension", d3_surface_outline); + shader_set_color("outlineColor", COLORS._main_accent); + draw_surface(d3_surface_outline, 0, 0); + shader_reset(); + } + #endregion + + d3_scene_preview.camera.resetCamera(); + } #endregion + + function drawPreviewOverlay() { #region + right_menu_y = toolbar_height - ui(4); + toolbar_draw = false; + + var _node = getNodePreview(); + + #region status texts (top right) + if(right_menu_x == 0) right_menu_x = w - ui(8); + + if(PANEL_PREVIEW == self) { + draw_set_text(f_p0, fa_right, fa_top, COLORS._main_text_accent); + draw_text(right_menu_x, right_menu_y, __txt("Active")); + right_menu_y += string_height("l"); + } + + var txt = $"{__txt("fps")} {fps}"; + if(PREFERENCES.panel_preview_show_real_fps) + txt += $" / {FPS_REAL}"; + + draw_set_text(f_p0, fa_right, fa_top, fps >= PROJECT.animator.framerate? COLORS._main_text_sub : COLORS._main_value_negative); + draw_text(right_menu_x, right_menu_y, txt); + right_menu_y += string_height("l"); + + draw_set_text(f_p0, fa_right, fa_top, COLORS._main_text_sub); + draw_text(right_menu_x, right_menu_y, $"{__txt("Frame")} {CURRENT_FRAME + 1}/{TOTAL_FRAMES}"); + + right_menu_y += string_height("l"); + draw_text(right_menu_x, right_menu_y, $"x{canvas_s}"); + + if(pHOVER) { + right_menu_y += string_height("l"); + var mpx = floor((mx - canvas_x) / canvas_s); + var mpy = floor((my - canvas_y) / canvas_s); + draw_text(right_menu_x, right_menu_y, $"[{mpx}, {mpy}]"); + } + + if(_node == noone) return; + + right_menu_y += string_height("l"); + var txt = $"{canvas_w} x {canvas_h}px"; + if(canvas_a) txt = $"{canvas_a} x {txt}"; + draw_text(right_menu_x, right_menu_y, txt); + + right_menu_y += string_height("l"); + right_menu_x = w - ui(8); + #endregion + + var pseq = getNodePreviewSequence(); + if(pseq == noone) return; + + if(!array_equals(pseq, _preview_sequence)) { + _preview_sequence = pseq; + preview_x = 0; + preview_x_to = 0; + } + + var prev_size = ui(48); + preview_x = lerp_float(preview_x, preview_x_to, 4); + + if(pHOVER && my > h - toolbar_height - prev_size - ui(16) && my > toolbar_height) { + canvas_hover = false; + + if(mouse_wheel_down() && !key_mod_press_any()) preview_x_to = clamp(preview_x_to - prev_size * SCROLL_SPEED, - preview_x_max, 0); + if(mouse_wheel_up() && !key_mod_press_any()) preview_x_to = clamp(preview_x_to + prev_size * SCROLL_SPEED, - preview_x_max, 0); + } + + #region surface array + preview_x_max = 0; + + if(array_length(pseq) > 1) { + var _xx = tool_side_drawing * ui(40); + var xx = _xx + preview_x + ui(8); + var yy = h - toolbar_height - prev_size - ui(8); + + if(my > yy - 8) mouse_on_preview = 0; + var hoverable = pHOVER && point_in_rectangle(mx, my, _xx, ui(32), w, h - toolbar_height); + + for(var i = 0; i < array_length(pseq); i++) { + var prev = pseq[i]; + if(is_instanceof(prev, __d3dMaterial)) + prev = prev.surface; + if(!is_surface(prev)) continue; + + var prev_w = surface_get_width_safe(prev); + var prev_h = surface_get_height_safe(prev); + var ss = prev_size / max(prev_w, prev_h); + var prev_sw = prev_w * ss; + + draw_set_color(COLORS.panel_preview_surface_outline); + draw_rectangle(xx, yy, xx + prev_w * ss, yy + prev_h * ss, true); + + if(hoverable && point_in_rectangle(mx, my, xx, yy, xx + prev_sw, yy + prev_h * ss)) { + if(mouse_press(mb_left, pFOCUS)) { + _node.preview_index = i; + _node.onValueUpdate(0); + if(resetViewOnDoubleClick) + do_fullView = true; + } + draw_surface_ext_safe(prev, xx, yy, ss, ss, 0, c_white, 1); + } else { + draw_surface_ext_safe(prev, xx, yy, ss, ss, 0, c_white, 0.5); + } + + if(i == _node.preview_index) { + draw_set_color(COLORS._main_accent); + draw_rectangle(xx, yy, xx + prev_sw, yy + prev_h * ss, true); + } + + xx += prev_sw + ui(8); + preview_x_max += prev_sw + ui(8); + } + } + #endregion + + preview_x_max = max(preview_x_max - ui(100), 0); + + #region ++++ sequence control ++++ + //var by = h - toolbar_height - prev_size - ui(56); + //var bx = ui(10); + + //var b = buttonInstant(THEME.button_hide, bx, by, ui(40), ui(40), [mx, my], pFOCUS, pHOVER); + + //if(_node.preview_speed == 0) { + // if(b) { + // draw_sprite_ui_uniform(THEME.sequence_control, 1, bx + ui(20), by + ui(20), 1, COLORS._main_icon, 1); + // if(b == 2) _node.preview_speed = preview_rate / game_get_speed(gamespeed_fps); + // } + // draw_sprite_ui_uniform(THEME.sequence_control, 1, bx + ui(20), by + ui(20), 1, COLORS._main_icon, 0.5); + //} else { + // if(b) { + // draw_sprite_ui_uniform(THEME.sequence_control, 0, bx + ui(20), by + ui(20), 1, COLORS._main_accent, 1); + // if(b == 2) _node.preview_speed = 0; + // } + // draw_sprite_ui_uniform(THEME.sequence_control, 0, bx + ui(20), by + ui(20), 1, COLORS._main_accent, .75); + //} + #endregion + } #endregion + + function drawNodeTools(active, _node) { #region + var _mx = mx; + var _my = my; + var isHover = pHOVER && mouse_on_preview == 1; + var tool_size = ui(32); + + var cx = canvas_x + _node.preview_x * canvas_s; + var cy = canvas_y + _node.preview_y * canvas_s; + var _snx = 0, _sny = 0; + + tool_side_drawing = _node.tools != -1; + + if(_node.tools != -1 && point_in_rectangle(_mx, _my, 0, 0, toolbar_width, h)) { + isHover = false; + mouse_on_preview = 0; + } + + var overlayHover = tool_hovering == noone && !overlay_hovering; + overlayHover &= active && isHover; + overlayHover &= point_in_rectangle(mx, my, (_node.tools != -1) * toolbar_width, toolbar_height, w, h - toolbar_height); + overlayHover &= !key_mod_press(CTRL); + var params = { w, h, toolbar_height }; + + reset_global_getset(); + + if(_node.is_3D) { + if(key_mod_press(CTRL) || d3_tool_snap) { + _snx = d3_tool_snap_position; + _sny = d3_tool_snap_rotation; + } + + _node.drawOverlay3D(overlayHover, d3_scene, _mx, _my, _snx, _sny, params); + } else { + if(key_mod_press(CTRL)) { + _snx = PROJECT.previewGrid.show? PROJECT.previewGrid.size[0] : 1; + _sny = PROJECT.previewGrid.show? PROJECT.previewGrid.size[1] : 1; + } else if(PROJECT.previewGrid.snap) { + _snx = PROJECT.previewGrid.size[0]; + _sny = PROJECT.previewGrid.size[1]; + } + + _node.drawOverlay(isHover, overlayHover, cx, cy, canvas_s, _mx, _my, _snx, _sny, params); + } + + #region node overlay + overlay_hovering = false; + + if(_node.drawPreviewToolOverlay(pHOVER, pFOCUS, _mx, _my, { x, y, w, h, toolbar_height, + x0: _node.tools == -1? 0 : ui(40), + x1: w, + y0: toolbar_height - ui(8), + y1: h - toolbar_height + })) { + canvas_hover = false; + overlay_hovering = true; + } + #endregion + + var _tool = tool_hovering; + tool_hovering = noone; + + if(_node.tools == -1) { + tool_current = noone; + return; + } + + var aa = d3_active? 0.8 : 1; + draw_sprite_stretched_ext(THEME.tool_side, 1, 0, ui(32), toolbar_width, h - toolbar_height - ui(32), c_white, aa); + + tool_y_max = 0; + tool_y = lerp_float(tool_y, tool_y_to, 5); + var xx = ui(1) + toolbar_width / 2; + var yy = ui(34) + tool_size / 2 + tool_y; + var pd = 2; + var thov = pHOVER && point_in_rectangle(mx, my, 0, toolbar_height, toolbar_width, h - toolbar_height); + if(thov) canvas_hover = false; + + for(var i = 0; i < array_length(_node.tools); i++) { #region left tools + var tool = _node.tools[i]; + var _x0 = xx - tool_size / 2; + var _y0 = yy - tool_size / 2; + var _x1 = xx + tool_size / 2; + var _y1 = yy + tool_size / 2; + + if(tool == -1) { + draw_set_color(COLORS._main_icon_dark); + draw_line_round(xx + ui(8), _y0 + ui(3), xx - ui(9), _y0 + ui(3), 2); + + yy += ui(8); + tool_y_max += ui(8); + continue; + } + + if(thov && point_in_rectangle(_mx, _my, _x0, _y0 + 1, _x1, _y1 - 1)) + tool_hovering = tool; + + if(tool.subtools > 0 && _tool == tool) { #region subtools + var s_ww = tool_size * tool.subtools; + var s_hh = tool_size; + draw_sprite_stretched(THEME.menu_bg, 0, _x0 - pd, _y0 - pd, s_ww + pd * 2, s_hh + pd * 2); + + var stool = tool.spr; + + for( var j = 0; j < array_length(stool); j++ ) { + var _sxx = xx + j * tool_size; + var _syy = yy; + + var _sx0 = _sxx - tool_size / 2; + var _sy0 = _syy - tool_size / 2; + var _sx1 = _sxx + tool_size / 2; + var _sy1 = _syy + tool_size / 2; + + if(point_in_rectangle(_mx, _my, _sx0, _sy0 + 1, _sx1, _sy1 - 1)) { + TOOLTIP = tool.getDisplayName(j); + draw_sprite_stretched(THEME.button_hide, 1, _sx0 + pd, _sy0 + pd, tool_size - pd * 2, tool_size - pd * 2); + + if(mouse_press(mb_left, pFOCUS)) + tool.toggle(j); + } + + if(tool_current == tool && tool.selecting == j) { + draw_sprite_stretched_ext(THEME.button_hide, 2, _sx0 + pd, _sy0 + pd, tool_size - pd * 2, tool_size - pd * 2, COLORS.panel_preview_grid, 1); + draw_sprite_stretched_ext(THEME.button_hide, 3, _sx0 + pd, _sy0 + pd, tool_size - pd * 2, tool_size - pd * 2, COLORS._main_accent, 1); + } + + draw_sprite_colored(stool[j], 0, _sxx, _syy); + } + + if(point_in_rectangle(_mx, _my, _x0, _y0 + 1, _x0 + s_ww, _y1 - 1)) + tool_hovering = tool; + #endregion + } else { #region single tools + if(tool_hovering == tool) { + draw_sprite_stretched(THEME.button_hide, 1, _x0 + pd, _y0 + pd, tool_size - pd * 2, tool_size - pd * 2); + TOOLTIP = tool.getDisplayName(); + + if(mouse_press(mb_left, pFOCUS)) + tool.toggle(); + } + + if(pFOCUS && WIDGET_CURRENT == noone) { + var _key = tool.checkHotkey(); + + if(keyboard_check_pressed(ord(string(i + 1))) || (_key != "" && keyboard_check_pressed(ord(_key)))) + tool.toggleKeyboard(); + } + + if(tool_current == tool) { + draw_sprite_stretched_ext(THEME.button_hide, 2, _x0 + pd, _y0 + pd, tool_size - pd * 2, tool_size - pd * 2, COLORS.panel_preview_grid, 1); + draw_sprite_stretched_ext(THEME.button_hide, 3, _x0 + pd, _y0 + pd, tool_size - pd * 2, tool_size - pd * 2, COLORS._main_accent, 1); + } + + if(tool.subtools > 0) draw_sprite_colored(tool.spr[tool.selecting], 0, xx, yy); + else draw_sprite_colored(tool.spr, 0, xx, yy); + #endregion + } + + yy += tool_size; + tool_y_max += tool_size; + } #endregion + + var _h = _node.drawTools(_mx, _my, xx, yy - tool_size / 2, tool_size, thov, pFOCUS); + yy += _h; + tool_y_max += _h; + + tool_y_max = max(0, tool_y_max - h + toolbar_height * 2); + if(thov && !key_mod_press_any()) { + if(mouse_wheel_up()) tool_y_to = clamp(tool_y_to + ui(64) * SCROLL_SPEED, -tool_y_max, 0); + if(mouse_wheel_down()) tool_y_to = clamp(tool_y_to - ui(64) * SCROLL_SPEED, -tool_y_max, 0); + } + + if(_node.rightTools != -1) { + right_menu_x = w - toolbar_width - ui(8); + tool_ry_max = 0; + tool_ry = lerp_float(tool_ry, tool_ry_to, 5); + + var _tbx = w - toolbar_width; + var xx = _tbx + toolbar_width / 2; + var yy = ui(34) + tool_size / 2 + tool_ry; + + var _sw = -toolbar_width / sprite_get_width(THEME.tool_side); + var _sh = h - toolbar_height - ui(32) / sprite_get_height(THEME.tool_side); + + draw_sprite_ext(THEME.tool_side, 1, w + 1, ui(32), _sw, _sh, 0, c_white, aa); + + var thov = pHOVER && point_in_rectangle(mx, my, _tbx, toolbar_height, w, h - toolbar_height); + if(thov) canvas_hover = false; + + for(var i = 0; i < array_length(_node.rightTools); i++) { #region right tools + var tool = _node.rightTools[i]; + var _x0 = xx - tool_size / 2; + var _y0 = yy - tool_size / 2; + var _x1 = xx + tool_size / 2; + var _y1 = yy + tool_size / 2; + + if(tool == -1) { + draw_set_color(COLORS._main_icon_dark); + draw_line_round(xx + ui(8), _y0 + ui(3), xx - ui(9), _y0 + ui(3), 2); + + yy += ui(8); + tool_ry_max += ui(8); + continue; + } + + if(thov && point_in_rectangle(_mx, _my, _x0, _y0 + 1, _x1, _y1 - 1)) + tool_hovering = tool; + + if(tool.subtools > 0 && _tool == tool) { #region subtools + + var stool = tool.spr; + var s_ww = tool_size * tool.subtools; + var s_hh = tool_size; + var tx = _x0 - s_ww + tool_size; + draw_sprite_stretched(THEME.menu_bg, 0, tx - pd, _y0 - pd, s_ww + pd * 2, s_hh + pd * 2); + + var _am = array_length(stool); + + for( var j = 0; j < _am; j++ ) { + var _sind = _am - 1 - j; + var _sxx = tx + j * tool_size + tool_size / 2; + var _syy = yy; + + var _sx0 = _sxx - tool_size / 2; + var _sy0 = _syy - tool_size / 2; + var _sx1 = _sxx + tool_size / 2; + var _sy1 = _syy + tool_size / 2; + + draw_sprite_colored(stool[_sind], 0, _sxx, _syy); + + if(point_in_rectangle(_mx, _my, _sx0, _sy0 + 1, _sx1, _sy1 - 1)) { + TOOLTIP = tool.getDisplayName(_sind); + draw_sprite_stretched(THEME.button_hide, 1, _sx0 + pd, _sy0 + pd, tool_size - pd * 2, tool_size - pd * 2); + + if(mouse_press(mb_left, pFOCUS)) + tool.toggle(_sind); + } + + if(tool_current == tool && tool.selecting == _sind) { + draw_sprite_stretched_ext(THEME.button_hide, 2, _sx0 + pd, _sy0 + pd, tool_size - pd * 2, tool_size - pd * 2, COLORS.panel_preview_grid, 1); + draw_sprite_stretched_ext(THEME.button_hide, 3, _sx0 + pd, _sy0 + pd, tool_size - pd * 2, tool_size - pd * 2, COLORS._main_accent, 1); + } + } + + if(point_in_rectangle(_mx, _my, tx, _y0 + 1, tx + s_ww, _y1 - 1)) + tool_hovering = tool; + #endregion + } else { #region single tools + if(tool_hovering == tool) { + draw_sprite_stretched(THEME.button_hide, 1, _x0 + pd, _y0 + pd, tool_size - pd * 2, tool_size - pd * 2); + TOOLTIP = tool.getDisplayName(); + + if(mouse_press(mb_left, pFOCUS)) + tool.toggle(); + } + + if(tool_current == tool) { + draw_sprite_stretched_ext(THEME.button_hide, 2, _x0 + pd, _y0 + pd, tool_size - pd * 2, tool_size - pd * 2, COLORS.panel_preview_grid, 1); + draw_sprite_stretched_ext(THEME.button_hide, 3, _x0 + pd, _y0 + pd, tool_size - pd * 2, tool_size - pd * 2, COLORS._main_accent, 1); + } + + if(tool.subtools > 0) draw_sprite_colored(tool.spr[tool.selecting], 0, xx, yy); + else draw_sprite_colored(tool.spr, 0, xx, yy); + #endregion + } + + yy += tool_size; + tool_ry_max += tool_size; + } #endregion + + tool_ry_max = max(0, tool_ry_max - h + toolbar_height * 2); + if(thov && !key_mod_press_any()) { + if(mouse_wheel_up()) tool_ry_to = clamp(tool_ry_to + ui(64) * SCROLL_SPEED, -tool_ry_max, 0); + if(mouse_wheel_down()) tool_ry_to = clamp(tool_ry_to - ui(64) * SCROLL_SPEED, -tool_ry_max, 0); + } + } + } #endregion + + function drawToolBar(_tool) { #region + var ty = h - toolbar_height; + //draw_sprite_stretched_ext(THEME.toolbar_shadow, 0, 0, ty - 12 + 4, w, 12, c_white, 0.5); + + var aa = d3_active? 0.8 : 1; + draw_sprite_stretched_ext(THEME.toolbar, 1, 0, 0, w, topbar_height, c_white, aa); + draw_sprite_stretched_ext(THEME.toolbar, 0, 0, ty, w, toolbar_height, c_white, aa); + + if(_tool && tool_current != noone) { #region tool settings + var settings = array_merge(_tool.getToolSettings(), tool_current.settings); + + tool_x = lerp_float(tool_x, tool_x_to, 5); + 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(16); + + for( var i = 0, n = array_length(settings); i < n; i++ ) { + var sett = settings[i]; + var nme = sett[0]; + var wdg = sett[1]; + 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); + + switch(instanceof(wdg)) { + case "textBox" : + tolw = ui(40); + if(wdg.side_button != noone) tolw += tolh + ui(8); + break; + + case "checkBoxGroup" : tolw = tolh * wdg.size; break; + case "checkBox" : tolw = tolh; break; + case "scrollBox" : tolw = ui(96); break; + } + + var params = new widgetParam(tolx, toly, tolw, tolh, atr[$ key],, [ mx, my ]) + params.s = tolh; + params.font = f_p3; + + wdg.drawParam(params); + + 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); + if(point_in_rectangle(mx, my, 0, 0, w, toolbar_height) && !key_mod_press_any()) { + if(mouse_wheel_up()) tool_x_to = clamp(tool_x_to + ui(64) * SCROLL_SPEED, -tol_max_w, 0); + if(mouse_wheel_down()) tool_x_to = clamp(tool_x_to - ui(64) * SCROLL_SPEED, -tol_max_w, 0); + } + #endregion + } else { #region color sampler + var cx = ui(8); + var cy = ui(8); + var cw = ui(32); + var ch = topbar_height - ui(16); + + if(sample_color != noone) { + draw_set_color(sample_color); + draw_rectangle(cx, cy, cx + cw, cy + ch, false); + draw_set_alpha(1); + } + + draw_set_color(COLORS.panel_toolbar_outline); + draw_rectangle(cx, cy, cx + cw, cy + ch, true); + + if(sample_color != noone) { + var tx = cx + cw + ui(16); + var hx = color_get_hex(sample_color); + draw_set_text(f_p0, fa_left, fa_center, COLORS._main_text); + draw_text(tx, cy + ch / 2, hx); + + tx += string_width(hx) + ui(8); + draw_set_color(COLORS._main_text_sub); + draw_text(tx, cy + ch / 2, $"({color_get_alpha(sample_color)})"); + } + #endregion + } + + var tbx = toolbar_height / 2; + var tby = ty + toolbar_height / 2; + + var _toolbars = d3_active? toolbars_3d : toolbars; + + for( var i = 0, n = array_length(_toolbars); i < n; i++ ) { + var tb = _toolbars[i]; + var tbSpr = tb[0]; + var tbInd = tb[1](); + var tbTooltip = tb[2](); + var tbActive = tb[3]; + + var b = buttonInstant(THEME.button_hide, tbx - ui(14), tby - ui(14), ui(28), ui(28), [mx, my], pFOCUS, pHOVER, tbTooltip, tbSpr, tbInd); + if(b == 2) tbActive( { x: x + tbx - ui(14), y: y + tby - ui(14) } ); + + tbx += ui(32); + } + + tbx = w - toolbar_height / 2; + for( var i = 0, n = array_length(actions); i < n; i++ ) { + var tb = actions[i]; + var tbSpr = tb[0]; + var tbTooltip = tb[1]; + var tbIndex = tb[3](); + + var b = buttonInstant(THEME.button_hide, tbx - ui(14), tby - ui(14), ui(28), ui(28), [mx, my], pFOCUS, pHOVER, tbTooltip, tbSpr, tbIndex); + if(b == 2) tb[2](); + + tbx -= ui(32); + } + + draw_set_color(COLORS.panel_toolbar_separator); + draw_line_width(tbx + ui(12), tby - toolbar_height / 2 + ui(8), tbx + ui(12), tby + toolbar_height / 2 - ui(8), 2); + + if(d3_active) drawNodeChannel3D(tbx, tby); + else drawNodeChannel(tbx, tby); + } #endregion + + function drawSplitView() { #region + if(splitView == 0) return; + + draw_set_color(COLORS.panel_preview_split_line); + + if(splitViewDragging) { + if(splitView == 1) { + var cx = splitViewStart + (mx - splitViewMouse); + splitPosition = clamp(cx / w, .1, .9); + } else if(splitView == 2) { + var cy = splitViewStart + (my - splitViewMouse); + splitPosition = clamp(cy / h, .1, .9); + } + + if(mouse_release(mb_left)) + splitViewDragging = false; + } + + if(splitView == 1) { + var sx = w * splitPosition; + + if(mouse_on_preview && point_in_rectangle(mx, my, sx - ui(4), 0, sx + ui(4), h)) { + draw_line_width(sx, 0, sx, h, 2); + if(mouse_press(mb_left, pFOCUS)) { + splitViewDragging = true; + splitViewStart = sx; + splitViewMouse = mx; + } + } else + draw_line_width(sx, 0, sx, h, 1); + + draw_sprite_ui_uniform(THEME.icon_active_split, 0, splitSelection? sx + ui(16) : sx - ui(16), toolbar_height + ui(16),, COLORS._main_accent); + + if(mouse_on_preview && mouse_press(mb_left, pFOCUS)) { + if(point_in_rectangle(mx, my, 0, 0, sx, h)) + splitSelection = 0; + else if(point_in_rectangle(mx, my, sx, 0, w, h)) + splitSelection = 1; + } + } else { + var sy = h * splitPosition; + + if(mouse_on_preview && point_in_rectangle(mx, my, 0, sy - ui(4), w, sy + ui(4))) { + draw_line_width(0, sy, w, sy, 2); + if(mouse_press(mb_left, pFOCUS)) { + splitViewDragging = true; + splitViewStart = sy; + splitViewMouse = my; + } + } else + draw_line_width(0, sy, w, sy, 1); + draw_sprite_ui_uniform(THEME.icon_active_split, 0, ui(16), splitSelection? sy + ui(16) : sy - ui(16),, COLORS._main_accent); + + if(mouse_on_preview && mouse_press(mb_left, pFOCUS)) { + if(point_in_rectangle(mx, my, 0, 0, w, sy)) + splitSelection = 0; + else if(point_in_rectangle(mx, my, 0, sy, w, h)) + splitSelection = 1; + } + } + } #endregion + + function drawContent(panel) { #region >>>>>>>>>>>>>>>>>>>> MAIN DRAW <<<<<<<<<<<<<<<<<<<< + mouse_on_preview = pHOVER && point_in_rectangle(mx, my, 0, topbar_height, w, h - toolbar_height); + + var _prev_node = getNodePreview(); + + d3_active = _prev_node != noone && _prev_node.is_3D; + + draw_clear(bg_color); + if(canvas_bg == -1 && canvas_s >= 0.1) + draw_sprite_tiled_ext(s_transparent, 0, canvas_x, canvas_y, canvas_s, canvas_s, COLORS.panel_preview_transparent, 1); + else + draw_clear(canvas_bg); + draw_set_color(COLORS._main_icon_dark); + draw_line_width(canvas_x, 0, canvas_x, h, 1); + draw_line_width(0, canvas_y, w, canvas_y, 1); + + bg_color = lerp_color(bg_color, d3_active? COLORS.panel_3d_bg : COLORS.panel_bg_clear, 0.3); + title = __txt("Preview"); + + getPreviewData(); + + if(_prev_node) { + if(d3_active) { + dragCanvas3D(); + draw3D(); + } else { + dragCanvas(); + drawNodePreview(); + } + } else dragCanvas(); + + drawPreviewOverlay(); + + var inspect_node = PANEL_INSPECTOR.getInspecting(); + + var tool = noone; + if(inspect_node) { + tool = inspect_node.getTool(); + if(tool) drawNodeTools(pFOCUS, tool); + } else + tool_current = noone; + + if(do_fullView) { + do_fullView = false; + fullView(); + } + + if(mouse_on_preview && mouse_press(mb_right, pFOCUS) && !key_mod_press(SHIFT)) { + menuCall("preview_context_menu",,, [ + menuItem(__txtx("panel_graph_preview_window", "Send to preview window"), function() { create_preview_window(getNodePreview()); }, noone, ["Preview", "Preview window"]), + -1, + menuItem(__txtx("panel_preview_save", "Save current preview as") + "...", function() { saveCurrentFrame(); }), + menuItem(__txtx("panel_preview_save_all", "Save all current previews as") + "...", function() { saveAllCurrentFrames(); }), + -1, + menuItem(__txtx("panel_preview_copy_image", "Copy image"), function() { copyCurrentFrame(); }, THEME.copy), + menuItem(__txtx("panel_preview_copy_color", "Copy color") + " [" + string(sample_color) + "]", function() { clipboard_set_text(sample_color); }), + menuItem(__txtx("panel_preview_copy_hex", "Copy hex") + " [" + string(color_get_hex(sample_color)) + "]", function() { clipboard_set_text(color_get_hex(sample_color)); }), + ],, getNodePreview()); + } + + if(!d3_active) drawSplitView(); + drawToolBar(tool); + } #endregion + + static onFullScreen = function() { run_in(1, fullView); } + + function copyCurrentFrame() { #region + var prevS = getNodePreviewSurface(); + if(!is_surface(prevS)) return; + + var buff = buffer_create(surface_get_width_safe(prevS) * surface_get_height_safe(prevS) * 4, buffer_fixed, 1); + var s = surface_create(surface_get_width_safe(prevS), surface_get_height_safe(prevS)); + + surface_set_target(s); + shader_set(sh_BGR); + draw_surface(prevS, 0, 0); + shader_reset(); + surface_reset_target(); + + buffer_get_surface(buff, s, 0); + surface_free(s); + + clipboard_set_bitmap(buffer_get_address(buff), surface_get_width_safe(prevS), surface_get_height_safe(prevS)); + } #endregion + + function saveCurrentFrame() { #region + var prevS = getNodePreviewSurface(); + if(!is_surface(prevS)) return; + + var path = get_save_filename("image|*.png;*.jpg", "export"); + key_release(); + if(path == "") return; + if(filename_ext(path) != ".png") path += ".png"; + + surface_save_safe(prevS, path); + } #endregion + + function saveAllCurrentFrames() { #region + var path = get_save_filename("image|*.png;*.jpg", "export"); + key_release(); + if(path == "") return; + + var ext = ".png"; + var name = string_replace_all(path, ext, ""); + var ind = 0; + + var pseq = getNodePreviewSequence(); + for(var i = 0; i < array_length(pseq); i++) { + var prev = pseq[i]; + if(!is_surface(prev)) continue; + var _name = name + string(ind) + ext; + surface_save_safe(prev, _name); + ind++; + } + } #endregion +} \ No newline at end of file diff --git a/#backups/scripts/surface_functions/surface_functions.gml.backup0 b/#backups/scripts/surface_functions/surface_functions.gml.backup0 new file mode 100644 index 000000000..a8afe10c4 --- /dev/null +++ b/#backups/scripts/surface_functions/surface_functions.gml.backup0 @@ -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 =================================== \ No newline at end of file diff --git a/#backups/scripts/surface_functions/surface_functions.gml.backup1 b/#backups/scripts/surface_functions/surface_functions.gml.backup1 new file mode 100644 index 000000000..099262f0b --- /dev/null +++ b/#backups/scripts/surface_functions/surface_functions.gml.backup1 @@ -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 =================================== \ No newline at end of file diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index 383a8a5f3..95fee781d 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -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",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index ec9abb59a..bf1d7cd4f 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -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",},}, diff --git a/scripts/__canvas_brush/__canvas_brush.gml b/scripts/__canvas_brush/__canvas_brush.gml index 37a431b37..b4ea4c7d7 100644 --- a/scripts/__canvas_brush/__canvas_brush.gml +++ b/scripts/__canvas_brush/__canvas_brush.gml @@ -5,7 +5,8 @@ function canvas_brush() constructor { brush_sizing_my = 0; brush_sizing_dx = 0; brush_sizing_dy = 0; - + + brush_use_surface = false; brush_surface = noone; brush_size = 1; brush_dist_min = 1; @@ -38,7 +39,14 @@ function canvas_brush() constructor { brush_dist_min = max(1, _brushDist[0]); brush_dist_max = max(1, _brushDist[1]); - brush_surface = is_surface(_brushSurf)? _brushSurf : noone; + + 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) brush_direction = 0; diff --git a/scripts/__canvas_tool/__canvas_tool.gml b/scripts/__canvas_tool/__canvas_tool.gml index 8608b9e57..2ff77664c 100644 --- a/scripts/__canvas_tool/__canvas_tool.gml +++ b/scripts/__canvas_tool/__canvas_tool.gml @@ -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 step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {} - function drawPreview(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 drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {} - function drawPostOverlay(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) {} } \ No newline at end of file diff --git a/scripts/__canvas_tool_shader/__canvas_tool_shader.gml b/scripts/__canvas_tool_shader/__canvas_tool_shader.gml index daf7ae2e9..790e1bf81 100644 --- a/scripts/__canvas_tool_shader/__canvas_tool_shader.gml +++ b/scripts/__canvas_tool_shader/__canvas_tool_shader.gml @@ -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,51 +14,79 @@ 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); - - draw_surface_ext(preview_surface[1], _x, _y, _s, _s, 0, c_white, 1); - - if(mouse_press(mb_right)) { - PANEL_PREVIEW.tool_current = noone; + if(mask) { + stepMaskEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); - } else if(mouse_release(mb_left)) { + 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; + } - var _newSurf = surface_create(_dim[0], _dim[1]); - surface_set_shader(_newSurf, noone); - draw_surface(preview_surface[1], 0, 0); - surface_reset_shader(); + } 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); - surface_free(_sel.selection_surface); - _sel.selection_surface = _newSurf; - _sel.selection_position = [ 0, 0 ]; - _sel.apply(); + 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(_surf); + surface_free(_sel.selection_surface); + _sel.selection_surface = _newSurf; + _sel.selection_position = [ 0, 0 ]; + _sel.apply(); - PANEL_PREVIEW.tool_current = noone; - MOUSE_BLOCK = true; + 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); + } } \ No newline at end of file diff --git a/scripts/canvas_tool_node/canvas_tool_node.gml b/scripts/canvas_tool_node/canvas_tool_node.gml index 8c458dbf8..96b988bb8 100644 --- a/scripts/canvas_tool_node/canvas_tool_node.gml +++ b/scripts/canvas_tool_node/canvas_tool_node.gml @@ -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; } diff --git a/scripts/canvas_tool_outline/canvas_tool_outline.gml b/scripts/canvas_tool_outline/canvas_tool_outline.gml index 3d47ec28a..822c2761a 100644 --- a/scripts/canvas_tool_outline/canvas_tool_outline.gml +++ b/scripts/canvas_tool_outline/canvas_tool_outline.gml @@ -1,11 +1,11 @@ function canvas_tool_outline() : canvas_tool_shader() constructor { - mouse_sx = 0; + mouse_sx = 0; function init() { mouse_init = true; } function onInit(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { - mouse_sx = _mx; + mouse_sx = _mx; } function stepEffect(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { @@ -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; + + } + + } + } \ No newline at end of file diff --git a/scripts/canvas_tool_selection/canvas_tool_selection.gml b/scripts/canvas_tool_selection/canvas_tool_selection.gml index 8dcdc4343..5949e4b44 100644 --- a/scripts/canvas_tool_selection/canvas_tool_selection.gml +++ b/scripts/canvas_tool_selection/canvas_tool_selection.gml @@ -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]); - - 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 onDrawMask(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {} + + 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 diff --git a/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml b/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml new file mode 100644 index 000000000..ecc40f521 --- /dev/null +++ b/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.gml @@ -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); + } +} \ No newline at end of file diff --git a/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.yy b/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.yy new file mode 100644 index 000000000..a058919e4 --- /dev/null +++ b/scripts/canvas_tool_selection_brush/canvas_tool_selection_brush.yy @@ -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", +} \ No newline at end of file diff --git a/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml b/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml index 16bd8a712..3dcb6e8e0 100644 --- a/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml +++ b/scripts/canvas_tool_selection_freeform/canvas_tool_selection_freeform.gml @@ -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); + } } \ No newline at end of file diff --git a/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml b/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml index 493e82fd2..2b0dd9ee8 100644 --- a/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml +++ b/scripts/canvas_tool_selection_magic/canvas_tool_selection_magic.gml @@ -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); + } } \ No newline at end of file diff --git a/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml b/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml index e08fc9680..58cb9813f 100644 --- a/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml +++ b/scripts/canvas_tool_selection_shape/canvas_tool_selection_shape.gml @@ -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); + } } \ No newline at end of file diff --git a/scripts/node_canvas/node_canvas.gml b/scripts/node_canvas/node_canvas.gml index 4814f03c7..7817d54d0 100644 --- a/scripts/node_canvas/node_canvas.gml +++ b/scripts/node_canvas/node_canvas.gml @@ -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); + surface_free(_tmp); + if(tool_selection.is_selected) { - surface_free(_tmp); 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,13 +691,33 @@ 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; + } - if(_tool && _tool.override) { - _tool.node = self; - _tool.step(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); - return; - } + #endregion draw_set_color(tool_attribute.color); @@ -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); @@ -676,25 +787,22 @@ function Node_Canvas(_x, _y, _group = noone) : Node(_x, _y, _group) constructor _tool.drawPreview(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); surface_reset_shader(); + + 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_mask); + DRAW_CLEAR + 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", _sw, _sh); + draw_surface_ext_safe(preview_draw_mask, 0, 0, 1, 1, 0, c_white, 1); + shader_reset(); + + if(_tool) _tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); - 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); - DRAW_CLEAR - draw_surface_ext_safe(preview_draw_surface, _x, _y, _s, _s, 0, c_white, 1); - 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_reset(); - - _tool.drawPostOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); - } #endregion var _x0 = _x; @@ -710,8 +818,7 @@ 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(); diff --git a/scripts/panel_inspector/panel_inspector.gml b/scripts/panel_inspector/panel_inspector.gml index 6613b5ef5..d45892890 100644 --- a/scripts/panel_inspector/panel_inspector.gml +++ b/scripts/panel_inspector/panel_inspector.gml @@ -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) diff --git a/scripts/panel_preview/panel_preview.gml b/scripts/panel_preview/panel_preview.gml index 6cb2ac5ad..b29750f50 100644 --- a/scripts/panel_preview/panel_preview.gml +++ b/scripts/panel_preview/panel_preview.gml @@ -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); - draw_text(tolx, toolbar_height / 2 - ui(2), nme); - tolx += string_width(nme) + ui(8); - tol_max_w += string_width(nme) + ui(8); + 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); diff --git a/scripts/surface_functions/surface_functions.gml b/scripts/surface_functions/surface_functions.gml index 47476849e..adee13ef7 100644 --- a/scripts/surface_functions/surface_functions.gml +++ b/scripts/surface_functions/surface_functions.gml @@ -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)) {