Pixel-Composer/scripts/node_liquefy/node_liquefy.gml
2024-10-13 16:43:44 +07:00

346 lines
No EOL
11 KiB
Text

enum LIQUEFY_TYPE {
push,
twirl,
pinch,
bloat,
}
function Node_Liquefy(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
name = "Liquefy";
newInput(0, nodeValue_Surface("Surface in", self));
newInput(1, nodeValue_Bool("Active", self, true));
active_index = 1;
newInput(2, nodeValue_Surface("Mask", self));
newInput(3, nodeValue_Float("Mix", self, 1))
.setDisplay(VALUE_DISPLAY.slider);
newInput(4, nodeValue_Toggle("Channel", self, 0b1111, { data: array_create(4, THEME.inspector_channel) }));
__init_mask_modifier(2); // inputs 5, 6,
newOutput(0, nodeValue_Output("Surface out", self, VALUE_TYPE.surface, noone));
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typeList = [
new scrollItem("Push", s_node_liquefy_type, 0),
new scrollItem("Twirl", s_node_liquefy_type, 1),
new scrollItem("Pinch", s_node_liquefy_type, 2),
new scrollItem("Bloat", s_node_liquefy_type, 3),
];
typeListStr = array_create_ext(array_length(typeList), function(i) /*=>*/ {return typeList[i].name});
static createNewInput = function() {
var _index = array_length(inputs);
dynamic_input_inspecting = getInputAmount();
newInput(_index + 0, nodeValue_Enum_Scroll("Type", self, 0, typeList));
newInput(_index + 1, nodeValue_Vec2("Position", self, [ 0, 0 ]))
.setUnitRef(function(index) /*=>*/ {return getDimension(index)}, VALUE_UNIT.reference);
newInput(_index + 2, nodeValue_Vec2("Position 2", self, [ 1, 0 ])) // push
.setUnitRef(function(index) /*=>*/ {return getDimension(index)}, VALUE_UNIT.reference);
newInput(_index + 3, nodeValue_Float("Radius", self, 8));
inputs[_index + 3].overlay_text_valign = fa_bottom;
newInput(_index + 4, nodeValue_Float("Intensity", self, 0.1))
.setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 4, 0.01] });
newInput(_index + 5, nodeValue_Float("Falloff", self, 0));
newInput(_index + 6, nodeValue_Curve("Falloff Curve", self, CURVE_DEF_10));
newInput(_index + 7, nodeValue_Float("Push", self, 0.1))
.setDisplay(VALUE_DISPLAY.slider, { range: [ 0, 4, 0.01] });
newInput(_index + 8, nodeValue_PathNode("Push path", self, noone))
newInput(_index + 9, nodeValue_Int("Push resolution", self, 16));
newInput(_index + 10, nodeValue_Float("Radius 2", self, 8));
inputs[_index + 10].overlay_text_valign = fa_bottom;
refreshDynamicDisplay();
return inputs[_index];
}
effect_renderer = new Inspector_Custom_Renderer(function(_x, _y, _w, _m, _hover, _focus) {
var bs = ui(24);
var bx = _x + ui(20);
var by = _y;
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover, "", THEME.add_16, 0, COLORS._main_value_positive) == 2) {
createNewInput();
triggerRender();
}
var amo = getInputAmount();
var lh = ui(28);
var _h = ui(12) + lh * amo;
var yy = _y + bs + ui(4);
var del_light = -1;
draw_sprite_stretched_ext(THEME.ui_panel_bg, 1, _x, yy, _w, _h, COLORS.node_composite_bg_blend, 1);
for(var i = 0; i < amo; i++) {
var _x0 = _x + ui(24);
var _x1 = _x + _w - ui(16);
var _yy = ui(6) + yy + i * lh + lh / 2;
var _ind = input_fix_len + i * data_length;
var _typ = current_data[_ind + 0];
var _col = COLORS._main_icon;
var tc = i == dynamic_input_inspecting? COLORS._main_text_accent : COLORS._main_icon;
var hov = _hover && point_in_rectangle(_m[0], _m[1], _x0, _yy - lh / 2, _x1, _yy + lh / 2 - 1);
if(hov && _m[0] < _x1 - ui(32)) {
tc = COLORS._main_text;
if(mouse_press(mb_left, _focus)) {
dynamic_input_inspecting = i;
refreshDynamicDisplay();
}
}
draw_sprite_ext(s_node_liquefy_type, _typ, _x0 + ui(8), _yy, 1, 1, 0, _col, .5 + .5 * (i == dynamic_input_inspecting));
draw_set_text(f_p2, fa_left, fa_center, tc);
draw_text_add(_x0 + ui(28), _yy, typeListStr[_typ]);
if(amo > 1) {
var bs = ui(24);
var bx = _x1 - bs;
var by = _yy - bs / 2;
if(buttonInstant(THEME.button_hide, bx, by, bs, bs, _m, _focus, _hover, "", THEME.minus_16, 0, hov? COLORS._main_value_negative : COLORS._main_icon) == 2)
del_light = i;
}
}
if(del_light > -1)
deleteDynamicInput(del_light);
return ui(32) + _h;
});
input_display_dynamic = [ 0,
["Regions", false], 1, 2, 8, 9, 3, 10, 5,
["Effect", false], 4, 7,
];
input_display_list = [ 1, 4,
["Surfaces", true], 0, 2, 3, 5, 6,
new Inspector_Spacer(8, true),
new Inspector_Spacer(2, false, false),
effect_renderer,
]
setDynamicInput(11, false);
if(!LOADING && !APPENDING) createNewInput();
attribute_surface_depth();
attribute_oversample();
attribute_interpolation();
temp_surface = [ 0, 0 ];
disp_path = [];
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
PROCESSOR_OVERLAY_CHECK
if(getInputAmount() == 0) return;
dynamic_input_inspecting = clamp(dynamic_input_inspecting, 0, getInputAmount() - 1);
var _ind = input_fix_len + dynamic_input_inspecting * data_length;
var _type = current_data[_ind + 0];
var _hov = false;
draw_set_circle_precision(64);
var pos = current_data[_ind + 1];
var rad = current_data[_ind + 3] * _s;
var px = _x + pos[0] * _s;
var py = _y + pos[1] * _s;
switch(_type) {
case LIQUEFY_TYPE.push :
var _path = current_data[_ind + 8];
var rad2 = current_data[_ind + 10] * _s;
if(_path == noone) {
var pos2 = current_data[_ind + 2];
var qx = _x + pos2[0] * _s;
var qy = _y + pos2[1] * _s;
draw_set_color(COLORS._main_accent);
draw_circle(px, py, rad, true);
draw_circle(qx, qy, rad2, true);
var hv = inputs[_ind + 2].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); _hov |= bool(hv); hover &= !hv;
var hv = inputs[_ind + 1].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); _hov |= bool(hv); hover &= !hv;
var hv = inputs[_ind + 10].drawOverlay(hover, active, qx, qy, _s, _mx, _my, _snx, _sny); _hov |= bool(hv); hover &= !hv;
} else if(!array_empty(disp_path)) {
var ox, oy, nx, ny;
ox = _x + disp_path[0] * _s;
oy = _y + disp_path[1] * _s;
px = ox;
py = oy;
draw_set_color(COLORS._main_accent);
draw_circle(px, py, rad, true);
for( var i = 2, n = array_length(disp_path); i < n; i += 2 ) {
nx = _x + disp_path[i + 0] * _s;
ny = _y + disp_path[i + 1] * _s;
draw_line(ox, oy, nx, ny);
ox = nx;
oy = ny;
}
draw_circle(ox, oy, rad2, true);
var hv = inputs[_ind + 10].drawOverlay(hover, active, ox, oy, _s, _mx, _my, _snx, _sny); _hov |= bool(hv); hover &= !hv;
}
break;
default:
var hv = inputs[_ind + 1].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); _hov |= bool(hv); hover &= !hv;
break;
}
var hv = inputs[_ind + 3].drawOverlay(hover, active, px, py, _s, _mx, _my, _snx, _sny); _hov |= bool(hv); hover &= !hv;
return _hov;
}
static step = function() {
__step_mask_modifier();
}
static applyLiquefy = function(_data, _i) {
var _ind = input_fix_len + _i * data_length;
var _surf = _data[0];
var _type = _data[_ind + 0];
var _pos1 = _data[_ind + 1];
var _pos2 = _data[_ind + 2];
var _rad = _data[_ind + 3];
var _int = _data[_ind + 4];
var _fall = _data[_ind + 5];
var _push = _data[_ind + 7];
var _path = _data[_ind + 8];
var _pthR = min(1024, _data[_ind + 9]);
var _rad2 = _data[_ind + 10];
var _shader = sh_liquefy_push;
switch(_type) {
case LIQUEFY_TYPE.push : _shader = sh_liquefy_push; break;
case LIQUEFY_TYPE.twirl : _shader = sh_liquefy_twirl; break;
case LIQUEFY_TYPE.pinch : _shader = sh_liquefy_pinch; break;
case LIQUEFY_TYPE.bloat : _shader = sh_liquefy_bloat; break;
}
surface_set_shader(temp_surface[0], _shader, true, BLEND.over);
shader_set_interpolation(_surf);
shader_set_dim("dimension", _surf);
shader_set_2("pos1", _pos1);
shader_set_2("pos2", _pos2);
shader_set_f("radius", _rad);
shader_set_f("radius2", _rad2);
shader_set_f("intensity", _int);
shader_set_f("falloff", _fall);
shader_set_f("pushIntens", _push);
if(_type == LIQUEFY_TYPE.push) {
var _usePath = _path != noone;
var _pthList = array_create(_pthR * 2);
var _p = new __vec2();
if(_usePath) {
for( var i = 0; i < _pthR; i++ ) {
_p = _path.getPointRatio(i / (_pthR - 1) ,0, _p);
_pthList[i * 2 + 0] = _p.x;
_pthList[i * 2 + 1] = _p.y;
}
if(_i == dynamic_input_inspecting)
disp_path = _pthList;
}
shader_set_i("usePath", _usePath);
shader_set_i("pathResolution", _pthR);
shader_set_f("pathList", _pthList);
}
draw_surface_safe(temp_surface[1]);
surface_reset_shader();
surface_set_shader(temp_surface[1], noone, true, BLEND.over);
draw_surface_safe(temp_surface[0]);
surface_reset_shader();
}
static processData = function(_outSurf, _data, _output_index, _array_index) {
var _amo = getInputAmount();
if(_amo == 0) return _outSurf;
var sam = struct_try_get(attributes, "oversample");
var _surf = _data[0];
if(!is_surface(_surf)) return _outSurf;
#region visibility
dynamic_input_inspecting = clamp(dynamic_input_inspecting, 0, _amo - 1);
var _ind = input_fix_len + dynamic_input_inspecting * data_length;
var _type = _data[_ind + 0];
inputs[_ind + 2].setVisible(_type == 0);
inputs[_ind + 7].setVisible(_type == 0);
inputs[_ind + 8].setVisible(_type == 0, _type == 0);
inputs[_ind + 9].setVisible(_type == 0);
inputs[_ind + 10].setVisible(_type == 0);
if(_type == LIQUEFY_TYPE.push) {
var _path = _data[_ind + 8];
var _usePath = _path != noone;
inputs[_ind + 1].setVisible(!_usePath);
inputs[_ind + 2].setVisible(!_usePath);
inputs[_ind + 9].setVisible( _usePath);
}
#endregion
var _dim = surface_get_dimension(_surf);
for( var i = 0, n = array_length(temp_surface); i < n; i++ )
temp_surface[i] = surface_verify(temp_surface[i], _dim[0], _dim[1]);
surface_set_shader(temp_surface[1], noone, true, BLEND.over);
draw_surface_safe(_surf);
surface_reset_shader();
for(var i = 0; i < _amo; i++)
applyLiquefy(_data, i);
surface_set_shader(_outSurf, noone, true, BLEND.over);
draw_surface_safe(temp_surface[1]);
surface_reset_shader();
__process_mask_modifier(_data);
_outSurf = mask_apply(_surf, _outSurf, _data[2], _data[3]);
_outSurf = channel_apply(_surf, _outSurf, _data[4]);
return _outSurf;
}
}