function Node_Warp(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { name = "Warp"; newInput(0, nodeValue_Surface("Surface in", self)); newInput(1, nodeValue_Vec2("Top left", self, [ 0, 0 ] )) .setUnitRef(function(index) { return getDimension(index); }); newInput(2, nodeValue_Vec2("Top right", self, [ DEF_SURF_W, 0 ] )) .setUnitRef(function(index) { return getDimension(index); }); newInput(3, nodeValue_Vec2("Bottom left", self, [ 0, DEF_SURF_H ] )) .setUnitRef(function(index) { return getDimension(index); }); newInput(4, nodeValue_Vec2("Bottom right", self, DEF_SURF )) .setUnitRef(function(index) { return getDimension(index); }); newInput(5, nodeValue_Bool("Active", self, true)); active_index = 5; newInput(6, nodeValue_Bool("Use custom dimension", self, false)); newInput(7, nodeValue_Dimension(self)); newInput(8, nodeValue_Bool("Tile", self, false)); newOutput(0, nodeValue_Output("Surface out", self, VALUE_TYPE.surface, noone)); input_display_list = [ 5, ["Surfaces", false], 0, 6, 7, 8, ["Wrap", false], 1, 2, 3, 4 ] attribute_surface_depth(); attribute_interpolation(); drag_side = -1; drag_mx = 0; drag_my = 0; drag_s = [[0, 0], [0, 0]]; attributes.initalset = LOADING || APPENDING; warp_surface = array_create(2); static onValueFromUpdate = function(index) { if(index == 0 && attributes.initalset == false) { var _surf = getInputData(0); if(!is_surface(_surf)) return; var _sw = surface_get_width_safe(_surf); var _sh = surface_get_height_safe(_surf); inputs[1].setValue([ 0, 0 ]); inputs[2].setValue([ _sw, 0 ]); inputs[3].setValue([ 0, _sh ]); inputs[4].setValue([ _sw, _sh ]); attributes.initalset = true; } } if(!LOADING && !APPENDING) run_in(1, function() { onValueFromUpdate(0); }) static step = function() { var _useDim = getInputData(6); inputs[7].setVisible(_useDim); dimension_index = _useDim? 7 : 0; } static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny, params) { PROCESSOR_OVERLAY_CHECK var _surf = outputs[0].getValue(); if(is_array(_surf)) { if(array_length(_surf) == 0) return; _surf = _surf[preview_index]; } var _ss = current_data[0]; if(!is_surface(_ss)) return; var tl = array_clone(current_data[1]); var tr = array_clone(current_data[2]); var bl = array_clone(current_data[3]); var br = array_clone(current_data[4]); tl[0] = _x + tl[0] * _s; tr[0] = _x + tr[0] * _s; bl[0] = _x + bl[0] * _s; br[0] = _x + br[0] * _s; tl[1] = _y + tl[1] * _s; tr[1] = _y + tr[1] * _s; bl[1] = _y + bl[1] * _s; br[1] = _y + br[1] * _s; #region preview var sw = surface_get_width(_surf) * _s; var sh = surface_get_height(_surf) * _s; warp_surface[0] = surface_verify(warp_surface[0], params.w, params.h); warp_surface[1] = surface_verify(warp_surface[1], sw, sh); surface_set_target(warp_surface[1]); draw_clear(c_black); draw_set_color(c_dkgrey); for(var i = 0; i <= 1; i += 0.125) { draw_line_width(0, i * sh, sw, i * sh, 2); draw_line_width(i * sw, 0, i * sw, sh, 2); } surface_reset_target(); warpSurface( warp_surface[0], warp_surface[1], params.w, params.h, tl, tr, bl, br, true ); // BLEND_ADD // draw_surface_safe(warp_surface[0]); // BLEND_NORMAL #endregion draw_set_color(COLORS._main_accent); draw_line(tl[0], tl[1], tr[0], tr[1]); draw_line(tl[0], tl[1], bl[0], bl[1]); draw_line(br[0], br[1], tr[0], tr[1]); draw_line(br[0], br[1], bl[0], bl[1]); var _hactive = active; if(point_in_circle(_mx, _my, tl[0], tl[1], 12)) _hactive = false; if(point_in_circle(_mx, _my, tr[0], tr[1], 12)) _hactive = false; if(point_in_circle(_mx, _my, bl[0], bl[1], 12)) _hactive = false; if(point_in_circle(_mx, _my, br[0], br[1], 12)) _hactive = false; var dx = 0; var dy = 0; if(drag_side > -1) { dx = (_mx - drag_mx) / _s; dy = (_my - drag_my) / _s; if(mouse_release(mb_left)) { drag_side = -1; UNDO_HOLDING = false; } } #region edit draw_set_color(COLORS.node_overlay_gizmo_inactive); if(drag_side == 0) { draw_line_width(tl[0], tl[1], tr[0], tr[1], 3); var _tlx = value_snap(drag_s[0][0] + dx, _snx); var _tly = value_snap(drag_s[0][1] + dy, _sny); var _trx = value_snap(drag_s[1][0] + dx, _snx); var _try = value_snap(drag_s[1][1] + dy, _sny); var _up1 = inputs[1].setValue([ _tlx, _tly ]); var _up2 = inputs[2].setValue([ _trx, _try ]); if(_up1 || _up2) UNDO_HOLDING = true; } else if(drag_side == 1) { draw_line_width(tl[0], tl[1], bl[0], bl[1], 3); var _tlx = value_snap(drag_s[0][0] + dx, _snx); var _tly = value_snap(drag_s[0][1] + dy, _sny); var _blx = value_snap(drag_s[1][0] + dx, _snx); var _bly = value_snap(drag_s[1][1] + dy, _sny); var _up1 = inputs[1].setValue([ _tlx, _tly ]); var _up3 = inputs[3].setValue([ _blx, _bly ]); if(_up1 || _up3) UNDO_HOLDING = true; } else if(drag_side == 2) { draw_line_width(br[0], br[1], tr[0], tr[1], 3); var _brx = value_snap(drag_s[0][0] + dx, _snx); var _bry = value_snap(drag_s[0][1] + dy, _sny); var _trx = value_snap(drag_s[1][0] + dx, _snx); var _try = value_snap(drag_s[1][1] + dy, _sny); var _up4 = inputs[4].setValue([ _brx, _bry ]); var _up2 = inputs[2].setValue([ _trx, _try ]); if(_up4 || _up2) UNDO_HOLDING = true; } else if(drag_side == 3) { draw_line_width(br[0], br[1], bl[0], bl[1], 3); var _brx = value_snap(drag_s[0][0] + dx, _snx); var _bry = value_snap(drag_s[0][1] + dy, _sny); var _blx = value_snap(drag_s[1][0] + dx, _snx); var _bly = value_snap(drag_s[1][1] + dy, _sny); var _up4 = inputs[4].setValue([ _brx, _bry ]); var _up3 = inputs[3].setValue([ _blx, _bly ]); if(_up4 || _up3) UNDO_HOLDING = true; } else if(_hactive) { draw_set_color(COLORS._main_accent); if(distance_to_line_infinite(_mx, _my, tl[0], tl[1], tr[0], tr[1]) < 12) { draw_line_width(tl[0], tl[1], tr[0], tr[1], 3); if(mouse_press(mb_left)) { drag_side = 0; drag_mx = _mx; drag_my = _my; drag_s = [ current_data[1], current_data[2] ]; } } else if(distance_to_line_infinite(_mx, _my, tl[0], tl[1], bl[0], bl[1]) < 12) { draw_line_width(tl[0], tl[1], bl[0], bl[1], 3); if(mouse_press(mb_left)) { drag_side = 1; drag_mx = _mx; drag_my = _my; drag_s = [ current_data[1], current_data[3] ]; } } else if(distance_to_line_infinite(_mx, _my, br[0], br[1], tr[0], tr[1]) < 12) { draw_line_width(br[0], br[1], tr[0], tr[1], 3); if(mouse_press(mb_left)) { drag_side = 2; drag_mx = _mx; drag_my = _my; drag_s = [ current_data[4], current_data[2] ]; } } else if(distance_to_line_infinite(_mx, _my, br[0], br[1], bl[0], bl[1]) < 12) { draw_line_width(br[0], br[1], bl[0], bl[1], 3); if(mouse_press(mb_left)) { drag_side = 3; drag_mx = _mx; drag_my = _my; drag_s = [ current_data[4], current_data[3] ]; } } } var _hov = false; var hv = inputs[1].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active = !hv; _hov |= hv; var hv = inputs[2].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active = !hv; _hov |= hv; var hv = inputs[3].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active = !hv; _hov |= hv; var hv = inputs[4].drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny); active = !hv; _hov |= hv; return _hov; #endregion } static warpSurface = function(surf, warp, sw, sh, tl, tr, bl, br, tile = false) { var teq = round(tl[1]) == round(tr[1]); var beq = round(bl[1]) == round(br[1]); var leq = round(tl[0]) == round(bl[0]); var req = round(tr[0]) == round(br[0]); var _wdim = surface_get_dimension(warp); if(teq && beq && leq && req) { // rectangle surface_set_shader(surf) shader_set_interpolation(warp); // if(filt) gpu_set_tex_filter(true); if(tile) draw_surface_tiled_ext(warp, tl[0], tl[1], (tr[0] - tl[0]) / _wdim[0], (bl[1] - tl[1]) / _wdim[1], c_white, 1); else draw_surface_stretched_safe(warp, tl[0], tl[1], tr[0] - tl[0], bl[1] - tl[1]); // if(filt) gpu_set_tex_filter(false); surface_reset_shader(); } else { surface_set_shader(surf, sh_warp_4points); shader_set_interpolation(warp); shader_set_f("dimension", surface_get_dimension(warp)); shader_set_f("p0", br[0] / sw, br[1] / sh); shader_set_f("p1", tr[0] / sw, tr[1] / sh); shader_set_f("p2", tl[0] / sw, tl[1] / sh); shader_set_f("p3", bl[0] / sw, bl[1] / sh); shader_set_i("tile", tile); // if(filt) gpu_set_tex_filter(true); draw_surface_stretched(warp, 0, 0, sw, sh); // if(filt) gpu_set_tex_filter(false); surface_reset_shader(); } } static processData = function(_outSurf, _data, _output_index, _array_index) { var tl = _data[1]; var tr = _data[2]; var bl = _data[3]; var br = _data[4]; var tile = _data[8]; var _useDim = _data[6]; var _dim = _data[7]; if(!is_surface(_data[0])) return _outSurf; var sw = _useDim? _dim[0] : surface_get_width_safe(_data[0]); var sh = _useDim? _dim[1] : surface_get_height_safe(_data[0]); warpSurface(_outSurf, _data[0], sw, sh, tl, tr, bl, br, tile); return _outSurf; } }