Pixel-Composer/scripts/node_crop/node_crop.gml
2024-09-04 08:57:11 +07:00

409 lines
13 KiB
Plaintext

function Node_Crop(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Crop";
preview_alpha = 0.5;
newInput(0, nodeValue_Surface("Surface in", self));
newInput(1, nodeValue_Padding("Crop", self, [ 0, 0, 0, 0 ]))
.setUnitRef(function(index) { return getDimension(index); });
newInput(2, nodeValue_Bool("Active", self, true));
active_index = 2;
newInput(3, nodeValue_Enum_Scroll("Aspect Ratio", self, 0, [ "None", "Manual", "1:1", "3:2", "4:3", "16:9" ]));
newInput(4, nodeValue_Vec2("Ratio", self, [ 1, 1 ]));
newInput(5, nodeValue_Vec2("Center", self, [ .5, .5 ]))
.setUnitRef(function(index) { return getDimension(index); }, VALUE_UNIT.reference);
newInput(6, nodeValue_Float("Width", self, 8 ));
newInput(7, nodeValue_Enum_Scroll("Fit Mode", self, 0, [ "Manual", "Width", "Height", "Minimum" ]));
newOutput(0, nodeValue_Output("Surface out", self, VALUE_TYPE.surface, noone));
input_display_list = [ 2,
["Surface", true], 0,
["Crop", false], 3, 4, 1, 7, 5, 6,
]
attribute_surface_depth();
tool_drag = new NodeTool("Draw crop area", THEME.crop_tool, "Node_Crop");
tool_fitw = new NodeTool("Fit Width", THEME.crop_fit_width)
.setToolFn(function() {
var _dim = getDimension(preview_index);
var _asp = current_data[3];
var _rat = current_data[4];
var _cen = current_data[5];
var _ratio = getRatio(_asp, _rat);
inputs[5].setValue([ _dim[0] / 2, _cen[1] ]);
inputs[6].setValue(_dim[0]);
});
tool_fith = new NodeTool("Fit Height", THEME.crop_fit_height)
.setToolFn(function() {
var _dim = getDimension(preview_index);
var _asp = current_data[3];
var _rat = current_data[4];
var _cen = current_data[5];
var _ratio = getRatio(_asp, _rat);
inputs[5].setValue([ _cen[0], _dim[1] / 2 ]);
inputs[6].setValue(_dim[1] * _ratio);
});
tools = [ tool_drag ];
drag_side = noone;
drag_mx = 0;
drag_my = 0;
drag_sv = 0;
static getPreviewValues = function() { return getInputData(0); }
static getRatio = function(_asp, _rat) {
switch(_asp) {
case 1 : return _rat[0] / _rat[1]; break;
case 2 : return 1 / 1; break;
case 3 : return 3 / 2; break;
case 4 : return 4 / 3; break;
case 5 : return 16 / 9; break;
}
return 1;
}
static step = function() {
var _asp = getInputData(3);
var _fit = getInputData(7);
inputs[1].setVisible(_asp == 0);
inputs[4].setVisible(_asp == 1);
inputs[5].setVisible(_asp > 0 && _fit == 0);
inputs[6].setVisible(_asp > 0 && _fit == 0);
}
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny, params) {
PROCESSOR_OVERLAY_CHECK
var _inSurf = current_data[0];
var _spRaw = current_data[1];
var _asp = current_data[3];
var _fit = current_data[7];
var _splice;
if(_asp == 0) {
tools = [ tool_drag ];
for( var i = 0, n = array_length(_spRaw); i < n; i++ )
_splice[i] = round(_spRaw[i]);
var dim = [ surface_get_width_safe(_inSurf), surface_get_height_safe(_inSurf) ];
var sp_r = _x + (dim[0] - _splice[0]) * _s;
var sp_l = _x + _splice[2] * _s;
var sp_t = _y + _splice[1] * _s;
var sp_b = _y + (dim[1] - _splice[3]) * _s;
var _out = getSingleValue(0,, true);
draw_surface_ext_safe(_out, sp_l, sp_t, _s, _s);
if(isUsingTool(0)) {
if(drag_side) {
var _mx0 = min(_mx, drag_mx);
var _mx1 = max(_mx, drag_mx);
var _my0 = min(_my, drag_my);
var _my1 = max(_my, drag_my);
_mx0 = value_snap(round((_mx0 - _x) / _s), _snx);
_mx1 = value_snap(round((_mx1 - _x) / _s), _snx);
_my0 = value_snap(round((_my0 - _y) / _s), _sny);
_my1 = value_snap(round((_my1 - _y) / _s), _sny);
if(inputs[1].setValue([dim[0] - _mx1, _my0, _mx0, dim[1] - _my1]))
UNDO_HOLDING = true;
draw_set_color(COLORS._main_accent);
draw_set_alpha(0.50);
draw_line(_x + _mx0 * _s, 0, _x + _mx0 * _s, params.h);
draw_line(0, _y + _my0 * _s, params.w, _y + _my0 * _s);
draw_line(_x + _mx1 * _s, 0, _x + _mx1 * _s, params.h);
draw_line(0, _y + _my1 * _s, params.w, _y + _my1 * _s);
draw_set_alpha(1);
if(mouse_release(mb_left, active)) {
drag_side = noone;
UNDO_HOLDING = false;
}
} else {
var _mxs = _x + value_snap(round((_mx - _x) / _s), _snx) * _s;
var _mys = _y + value_snap(round((_my - _y) / _s), _sny) * _s;
draw_set_color(COLORS._main_accent);
draw_set_alpha(0.50);
draw_line(_mxs, 0, _mxs, params.h);
draw_line(0, _mys, params.w, _mys);
draw_set_alpha(1);
if(mouse_press(mb_left, active)) {
drag_side = 1;
drag_mx = _mx;
drag_my = _my;
}
}
draw_set_color(COLORS._main_accent);
draw_line_width(sp_r, sp_t - 1, sp_r, sp_b + 1, 2);
draw_line_width(sp_l, sp_t - 1, sp_l, sp_b + 1, 2);
draw_line_width(sp_l - 1, sp_t, sp_r + 1, sp_t, 2);
draw_line_width(sp_l - 1, sp_b, sp_r + 1, sp_b, 2);
return;
}
draw_set_color(COLORS._main_accent);
draw_set_alpha(0.50);
draw_line(sp_r, 0, sp_r, params.h);
draw_line(sp_l, 0, sp_l, params.h);
draw_line(0, sp_t, params.w, sp_t);
draw_line(0, sp_b, params.w, sp_b);
draw_set_alpha(1);
draw_line_width(sp_r, sp_t - 1, sp_r, sp_b + 1, 2);
draw_line_width(sp_l, sp_t - 1, sp_l, sp_b + 1, 2);
draw_line_width(sp_l - 1, sp_t, sp_r + 1, sp_t, 2);
draw_line_width(sp_l - 1, sp_b, sp_r + 1, sp_b, 2);
var _hov = noone;
if(drag_side != noone) {
var vv;
if(drag_side < 4) {
if(drag_side == 0) vv = value_snap(drag_sv - (_mx - drag_mx) / _s, _snx);
else if(drag_side == 1) vv = value_snap(drag_sv + (_my - drag_my) / _s, _sny);
else if(drag_side == 2) vv = value_snap(drag_sv + (_mx - drag_mx) / _s, _snx);
else if(drag_side == 3) vv = value_snap(drag_sv - (_my - drag_my) / _s, _sny);
_splice[drag_side] = vv;
} else if(drag_side < 8) {
if(drag_side == 4) {
_splice[2] = value_snap(drag_sv[2] + (_mx - drag_mx) / _s, _snx);
_splice[1] = value_snap(drag_sv[1] + (_my - drag_my) / _s, _sny);
} else if(drag_side == 5) {
_splice[0] = value_snap(drag_sv[0] - (_mx - drag_mx) / _s, _snx);
_splice[1] = value_snap(drag_sv[1] + (_my - drag_my) / _s, _sny);
} else if(drag_side == 6) {
_splice[2] = value_snap(drag_sv[2] + (_mx - drag_mx) / _s, _snx);
_splice[3] = value_snap(drag_sv[3] - (_my - drag_my) / _s, _sny);
} else if(drag_side == 7) {
_splice[0] = value_snap(drag_sv[0] - (_mx - drag_mx) / _s, _snx);
_splice[3] = value_snap(drag_sv[3] - (_my - drag_my) / _s, _sny);
}
} else if(drag_side == 8) {
_splice[0] = value_snap(drag_sv[0] - (_mx - drag_mx) / _s, _snx);
_splice[1] = value_snap(drag_sv[1] + (_my - drag_my) / _s, _sny);
_splice[2] = value_snap(drag_sv[2] + (_mx - drag_mx) / _s, _snx);
_splice[3] = value_snap(drag_sv[3] - (_my - drag_my) / _s, _sny);
}
if(inputs[1].setValue(_splice))
UNDO_HOLDING = true;
if(mouse_release(mb_left, active)) {
drag_side = noone;
UNDO_HOLDING = false;
}
}
draw_set_color(merge_color(c_white, COLORS._main_accent, 0.5));
if(hover) {
if(drag_side == 4 || point_in_circle(_mx, _my, sp_l, sp_t, 12)) {
draw_line_width(sp_l, 0, sp_l, params.h, 4);
draw_line_width(0, sp_t, params.w, sp_t, 4);
draw_sprite_colored(THEME.anchor_selector, 1, sp_l, sp_t);
_hov = 4;
} else if(drag_side == 5 || point_in_circle(_mx, _my, sp_r, sp_t, 12)) {
draw_line_width(sp_r, 0, sp_r, params.h, 4);
draw_line_width(0, sp_t, params.w, sp_t, 4);
draw_sprite_colored(THEME.anchor_selector, 1, sp_r, sp_t);
_hov = 5;
} else if(drag_side == 6 || point_in_circle(_mx, _my, sp_l, sp_b, 12)) {
draw_line_width(sp_l, 0, sp_l, params.h, 4);
draw_line_width(0, sp_b, params.w, sp_b, 4);
draw_sprite_colored(THEME.anchor_selector, 1, sp_l, sp_b);
_hov = 6;
} else if(drag_side == 7 || point_in_circle(_mx, _my, sp_r, sp_b, 12)) {
draw_line_width(sp_r, 0, sp_r, params.h, 4);
draw_line_width(0, sp_b, params.w, sp_b, 4);
draw_sprite_colored(THEME.anchor_selector, 1, sp_r, sp_b);
_hov = 7;
} else if(drag_side == 0 || distance_to_line(_mx, _my, sp_r, 0, sp_r, params.h) < 12) {
draw_line_width(sp_r, 0, sp_r, params.h, 4);
_hov = 0;
} else if(drag_side == 1 || distance_to_line(_mx, _my, 0, sp_t, params.w, sp_t) < 12) {
draw_line_width(0, sp_t, params.w, sp_t, 4);
_hov = 1;
} else if(drag_side == 2 || distance_to_line(_mx, _my, sp_l, 0, sp_l, params.h) < 12) {
draw_line_width(sp_l, 0, sp_l, params.h, 4);
_hov = 2;
} else if(drag_side == 3 || distance_to_line(_mx, _my, 0, sp_b, params.w, sp_b) < 12) {
draw_line_width(0, sp_b, params.w, sp_b, 4);
_hov = 3;
} else if(drag_side == 8 || point_in_rectangle(_mx, _my, sp_l, sp_t, sp_r, sp_b)) {
draw_line_width(sp_r, sp_t - 1, sp_r, sp_b + 1, 4);
draw_line_width(sp_l, sp_t - 1, sp_l, sp_b + 1, 4);
draw_line_width(sp_l - 1, sp_t, sp_r + 1, sp_t, 4);
draw_line_width(sp_l - 1, sp_b, sp_r + 1, sp_b, 4);
_hov = 8;
}
}
if(_hov != 4) draw_sprite_colored(THEME.anchor_selector, 0, sp_l, sp_t);
if(_hov != 5) draw_sprite_colored(THEME.anchor_selector, 0, sp_r, sp_t);
if(_hov != 6) draw_sprite_colored(THEME.anchor_selector, 0, sp_l, sp_b);
if(_hov != 7) draw_sprite_colored(THEME.anchor_selector, 0, sp_r, sp_b);
if(drag_side == noone && _hov != noone) {
if(mouse_press(mb_left, active)) {
drag_side = _hov;
drag_mx = _mx;
drag_my = _my;
drag_sv = _hov < 4? _splice[_hov] : _splice;
}
}
} else if(_fit == 0) {
tools = [ tool_fitw, tool_fith ];
var _rat = current_data[4];
var _cent = current_data[5];
var _width = abs(current_data[6]);
var _ratio = getRatio(_asp, _rat);
var _height = ceil(_width / _ratio);
var _x0 = round(_cent[0] - _width / 2);
var _y0 = round(_cent[1] - _height / 2);
var _px0 = _x + _x0 * _s;
var _py0 = _y + _y0 * _s;
var _px1 = _px0 + _width * _s;
var _py1 = _py0 + _height * _s;
var _out = getSingleValue(0,, true);
draw_surface_ext_safe(_out, _px0, _py0, _s, _s);
draw_set_color(COLORS._main_accent);
draw_rectangle(_px0, _py0, _px1, _py1, true);
var _px = _x + _cent[0] * _s;
var _py = _y + _cent[1] * _s;
var a = inputs[5].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active &= !a;
var a = inputs[6].drawOverlay(hover, active, _px, _py, _s / 2, _mx, _my, _snx, _sny); active &= !a;
} else {
var _idim = surface_get_dimension(_inSurf);
var _out = getSingleValue(0,, true);
var _odim = surface_get_dimension(_out);
var _x0 = _idim[0] / 2 - _odim[0] / 2;
var _y0 = _idim[1] / 2 - _odim[1] / 2;
var _px0 = _x + _x0 * _s;
var _py0 = _y + _y0 * _s;
var _px1 = _px0 + _odim[0] * _s;
var _py1 = _py0 + _odim[1] * _s;
draw_surface_ext_safe(_out, _px0, _py0, _s, _s);
draw_set_color(COLORS._main_accent);
draw_rectangle(_px0, _py0, _px1, _py1, true);
}
}
static onValueUpdate = function(index) {
if(index != 3) return;
var _dim = getDimension(0);
var _asp = inputs[3].getValue();
var _rat = inputs[4].getValue();
var _ratio = getRatio(_asp, _rat);
inputs[5].setValue([ _dim[0] / 2, _dim[1] / 2 ]);
inputs[6].setValue(min(_dim[0], _dim[1] * _ratio));
}
static processData = function(_outSurf, _data, _output_index, _array_index) {
var _inSurf = _data[0];
var _crop = _data[1];
var _asp = _data[3];
var _rat = _data[4];
var _cent = _data[5];
var _width = abs(_data[6]);
var _fit = _data[7];
var _sdim = surface_get_dimension(_inSurf);
if(_asp == 0) {
var _dim = [ _sdim[0] - _crop[0] - _crop[2],
_sdim[1] - _crop[1] - _crop[3] ];
_outSurf = surface_verify(_outSurf, _dim[0], _dim[1]);
surface_set_shader(_outSurf, noone);
draw_surface_safe(_inSurf, -_crop[2], -_crop[1]);
surface_reset_shader();
} else if(_fit == 0) {
var _ratio = getRatio(_asp, _rat);
var _height = ceil(_width / _ratio);
var _x0 = round(_cent[0] - _width / 2);
var _y0 = round(_cent[1] - _height / 2);
_outSurf = surface_verify(_outSurf, _width, _height);
surface_set_shader(_outSurf, noone);
draw_surface_safe(_inSurf, -_x0, -_y0);
surface_reset_shader();
} else {
var _ratio = getRatio(_asp, _rat);
var _w = 1, _h = 1, _x0, _y0;
if(_fit == 1) {
_w = _sdim[0];
_h = _w * _ratio;
} else if(_fit == 2) {
_h = _sdim[1];
_w = _h / _ratio;
} else if(_fit == 3) {
_w = min(_sdim[0], _sdim[1] * _ratio);
_h = _w * _ratio;
}
var _x0 = round(_sdim[0] / 2 - _w / 2);
var _y0 = round(_sdim[1] / 2 - _h / 2);
_outSurf = surface_verify(_outSurf, _w, _h);
surface_set_shader(_outSurf, noone);
draw_surface_safe(_inSurf, -_x0, -_y0);
surface_reset_shader();
}
return _outSurf;
}
}