From ee9b5ac6721d5321b45ad0186632eb290348fb56 Mon Sep 17 00:00:00 2001 From: Tanasart Date: Tue, 18 Jun 2024 10:18:50 +0700 Subject: [PATCH] - [Curve data] Add shfit and scale properties. --- scripts/color_function/color_function.gml | 39 +- scripts/curveBox/curveBox.gml | 153 +++++--- .../curve_bezier_function.gml | 115 ++++-- scripts/node_keyframe/node_keyframe.gml | 6 + scripts/node_line/node_line.gml | 359 +++++++++++------- scripts/node_path/node_path.gml | 51 ++- .../node_path_scatter/node_path_scatter.gml | 16 +- 7 files changed, 506 insertions(+), 233 deletions(-) diff --git a/scripts/color_function/color_function.gml b/scripts/color_function/color_function.gml index 0104c5b35..5a34a59e3 100644 --- a/scripts/color_function/color_function.gml +++ b/scripts/color_function/color_function.gml @@ -122,22 +122,41 @@ } #endregion function colorMultiply(c1, c2) { #region + INLINE + if(c1 * c2 == 0) return 0; if(c1 == c_white) return c2; if(c2 == c_white) return c1; - var r1 = _color_get_red(c1); - var g1 = _color_get_green(c1); - var b1 = _color_get_blue(c1); - var a1 = _color_get_alpha(c1); + var a1 = c1 >> 24 & 0xFF; + var r1 = c1 >> 16 & 0xFF; + var g1 = c1 >> 8 & 0xFF; + var b1 = c1 & 0xFF; - var r2 = _color_get_red(c2); - var g2 = _color_get_green(c2); - var b2 = _color_get_blue(c2); - var a2 = _color_get_alpha(c2); + var a2 = c2 >> 24 & 0xFF; + var r2 = c2 >> 16 & 0xFF; + var g2 = c2 >> 8 & 0xFF; + var b2 = c2 & 0xFF; + + var a = min(a1 * a2 / 255, 255); + var r = min(r1 * r2 / 255, 255); + var g = min(g1 * g2 / 255, 255); + var b = min(b1 * b2 / 255, 255); - if(is_real(c1)) return make_color_rgb((r1 * r2) * 255, (g1 * g2) * 255, (b1 * b2) * 255); - return make_color_rgba((r1 * r2) * 255, (g1 * g2) * 255, (b1 * b2) * 255, (a1 * a2) * 255); + return (a << 24) | (r << 16) | (g << 8) | b; + + // var r1 = _color_get_red(c1); + // var g1 = _color_get_green(c1); + // var b1 = _color_get_blue(c1); + // var a1 = _color_get_alpha(c1); + + // var r2 = _color_get_red(c2); + // var g2 = _color_get_green(c2); + // var b2 = _color_get_blue(c2); + // var a2 = _color_get_alpha(c2); + + // if(is_real(c1)) return make_color_rgb((r1 * r2) * 255, (g1 * g2) * 255, (b1 * b2) * 255); + // return make_color_rgba((r1 * r2) * 255, (g1 * g2) * 255, (b1 * b2) * 255, (a1 * a2) * 255); } #endregion function colorAdd(c1, c2) { #region diff --git a/scripts/curveBox/curveBox.gml b/scripts/curveBox/curveBox.gml index bd1f90829..c7211608f 100644 --- a/scripts/curveBox/curveBox.gml +++ b/scripts/curveBox/curveBox.gml @@ -1,11 +1,12 @@ function curveBox(_onModify) : widget() constructor { - onModify = _onModify; + onModify = _onModify; + curr_data = []; curve_surface = surface_create(1, 1); node_dragging = -1; node_drag_typ = -1; - h = 160; + h = 200; height_drag = false; height_my = 0; height_ss = 0; @@ -32,14 +33,41 @@ function curveBox(_onModify) : widget() constructor { cw = 0; ch = 0; + tb_shift = new textBox(TEXTBOX_INPUT.number, function(val) { var _data = array_clone(curr_data); _data[0] = val; onModify(_data); }).setSlidable(1 / 100); + tb_scale = new textBox(TEXTBOX_INPUT.number, function(val) { var _data = array_clone(curr_data); _data[1] = val; onModify(_data); }).setSlidable(1 / 100); + + tb_shift.label = "Shift"; + tb_scale.label = "Scale"; + static get_x = function(val) { return cw * (val - minx) / (maxx - minx); } static get_y = function(val) { return ch * (1 - (val - miny) / (maxy - miny)); } static register = function() {} + static setInteract = function(interactable = noone) { #region + self.interactable = interactable; + + tb_shift.setInteract(interactable); + tb_scale.setInteract(interactable); + } #endregion + + static register = function(parent = noone) { + tb_shift.register(parent); + tb_scale.register(parent); + } + + static isHovering = function() { #region + if(tb_shift.isHovering()) return true; + if(tb_scale.isHovering()) return true; + + return hovering; + } #endregion + static drawParam = function(params) { rx = params.rx; ry = params.ry; + tb_shift.setParam(params); + tb_scale.setParam(params); return draw(params.x, params.y, params.w, params.data, params.m); } @@ -49,30 +77,39 @@ function curveBox(_onModify) : widget() constructor { y = _y; w = _w; + if(!is_array(_data) || array_length(_data) == 0) return 0; + if(is_array(_data[0])) return 0; + var _h = h - ui(4); + var _amo = array_length(_data); + var _shf = _amo % 6; + var points = (_amo - _shf) / 6; + + var _shift = 0; + var _scale = 1; + var zoom_size = ui(12); var zoom_padd = zoom_size + ui(8); + var tbh = line_get_height(font) + ui(4); + cw = _w - zoom_padd; - ch = _h - zoom_padd; + ch = _h - zoom_padd - (tbh + ui(4)) * bool(_shf); - hovering = false; + hovering = false; + curr_data = _data; + if(_shf == 1) { _shift = _data[0]; } + else if(_shf == 2) { _shift = _data[0]; _scale = _data[1]; } - if(!is_array(_data) || array_length(_data) == 0) return 0; - if(is_array(_data[0])) return 0; - - var points = array_length(_data) / 6; - - #region display - display_pos_x = lerp(minx, maxx, (_m[0] - _x) / cw); - display_pos_y = lerp(miny, maxy, 1 - (_m[1] - _y) / ch); - display_sel = false; - #endregion + display_pos_x = lerp(minx, maxx, (_m[0] - _x) / cw); + display_pos_y = lerp(miny, maxy, 1 - (_m[1] - _y) / ch); + display_sel = false; curve_surface = surface_verify(curve_surface, cw, ch); if(node_dragging != -1) { #region editing + show_coord = true; _data = array_clone(_data); @@ -84,7 +121,7 @@ function curveBox(_onModify) : widget() constructor { var _my = 1 - (_m[1] - _y) / ch; _my = clamp(_my * (maxy - miny) + miny, 0, 1); - var node_point = (node_dragging - 2) / 6; + var node_point = (node_dragging - _shf - 2) / 6; if(node_point > 0 && node_point < points - 1) { if(key_mod_press(CTRL) || grid_snap) @@ -104,35 +141,7 @@ function curveBox(_onModify) : widget() constructor { display_pos_y = _data[node_dragging + 1]; display_sel = 1; - //sort by x - var _xindex = []; - var _pindex = []; - for( var i = 0; i < points; i++ ) { - var ind = i * 6; - var _x0 = _data[ind + 2]; - array_push(_xindex, _x0); - array_push(_pindex, _x0); - } - - array_sort(_xindex, true); - - if(node_point > 0 && node_point < points - 1) { - var sorted = []; - for( var i = 0; i < points; i++ ) { - var prog = _xindex[i]; - var ind = array_find(_pindex, prog); - - array_push(sorted, _data[ind * 6 + 0]); - array_push(sorted, _data[ind * 6 + 1]); - array_push(sorted, _data[ind * 6 + 2]); - array_push(sorted, _data[ind * 6 + 3]); - array_push(sorted, _data[ind * 6 + 4]); - array_push(sorted, _data[ind * 6 + 5]); - } - - if(onModify(sorted)) - UNDO_HOLDING = true; - } else if(onModify(_data)) + if(onModify(_data)) UNDO_HOLDING = true; } else { //control @@ -215,8 +224,15 @@ function curveBox(_onModify) : widget() constructor { draw_line(_px, 0, _px, ch); } + // print(""); + + if(_shf) { + draw_set_color(merge_color(COLORS._main_icon, COLORS._main_icon_dark, 0.5)); + draw_curve(0, 0, cw, ch, _data, minx, maxx, miny, maxy, _shift, _scale); + } + for( var i = 0; i < points; i++ ) { - var ind = i * 6; + var ind = _shf + i * 6; var _x0 = _data[ind + 2]; var _y0 = _data[ind + 3]; @@ -227,7 +243,9 @@ function curveBox(_onModify) : widget() constructor { var by0 = _y0 + _data[ind + 1] * _w_prev; var ax0 = _x0 + _data[ind + 4] * _w_next; var ay0 = _y0 + _data[ind + 5] * _w_next; - + + // print($"{_x0}, {_y0} | {_data[ind + 0]}, {_data[ind + 1]} | {_data[ind + 4]}, {_data[ind + 5]}"); + bx0 = get_x(bx0); by0 = get_y(by0); _x0 = get_x(_x0); @@ -285,7 +303,7 @@ function curveBox(_onModify) : widget() constructor { draw_set_color(COLORS._main_accent); draw_curve(0, 0, cw, ch, _data, minx, maxx, miny, maxy); - + surface_reset_target(); #endregion @@ -297,7 +315,7 @@ function curveBox(_onModify) : widget() constructor { var zminy = 0 - 1; var zmaxy = 1 + 1; - var byH = _h - zoom_padd; + var byH = ch; var bx = _x + w - bs; var by = _y; @@ -332,7 +350,7 @@ function curveBox(_onModify) : widget() constructor { var bxW = _w - zoom_padd; var bx = _x; - var by = _y + _h - bs; + var by = _y + _h - bs - (tbh + ui(4)) * bool(_shf); var zx0 = bx + bs / 2 + (bxW - bs) * (minx - zminx) / (zmaxx - zminx); var zx1 = bx + bs / 2 + (bxW - bs) * (maxx - zminx) / (zmaxx - zminx); @@ -394,7 +412,7 @@ function curveBox(_onModify) : widget() constructor { } var _bhx = _x + _w - bs; - var _bhy = _y + _h - bs; + var _bhy = _y + _h - bs - (tbh + ui(4)) * bool(_shf); var _hov = false; if(point_in_rectangle(_m[0], _m[1], _bhx, _bhy, _bhx + bs, _bhy + bs)) { @@ -409,7 +427,6 @@ function curveBox(_onModify) : widget() constructor { } draw_sprite_stretched_ext(THEME.menu_button_mask, 0, _bhx, _bhy, bs, bs, _hov? COLORS._main_icon : CDEF.main_dkgrey, 1); - // draw_sprite_ext(THEME.circle, 0, _bhx + bs / 2, _bhy + bs / 2, 1, 1, 0, COLORS._main_icon_light, 1); if(height_drag) { h = height_ss + _m[1] - height_my; @@ -426,29 +443,33 @@ function curveBox(_onModify) : widget() constructor { if(mouse_press(mb_left, active)) { if(node_hovering == -1) { - var _ind = point_insert * 6; + var _ind = _shf + point_insert * 6; var _px = (_m[0] - _x) / cw; var _py = 1 - (_m[1] - _y) / ch; - - array_insert(_data, _ind + 0, -0.1); + + array_insert(_data, _ind + 0, -1 / 3); array_insert(_data, _ind + 1, 0); array_insert(_data, _ind + 2, _px); array_insert(_data, _ind + 3, _py); - array_insert(_data, _ind + 4, 0.1); + array_insert(_data, _ind + 4, 1 / 3); array_insert(_data, _ind + 5, 0); + if(onModify(_data)) UNDO_HOLDING = true; node_dragging = _ind + 2; node_drag_typ = 0; + } else { node_dragging = node_hovering; node_drag_typ = node_hover_typ; + } + } else if(mouse_press(mb_right, active)) { - var node_point = (node_hovering - 2) / 6; + var node_point = (node_hovering - _shf - 2) / 6; if(node_hover_typ == 0 && node_point > 0 && node_point < points - 1) { - array_delete(_data, node_point * 6, 6); + array_delete(_data, _shf + node_point * 6, 6); if(onModify(_data)) UNDO_HOLDING = true; } @@ -496,6 +517,24 @@ function curveBox(_onModify) : widget() constructor { } show_coord = false; + + if(_shf) { + var tby = _y + h - tbh; + var tbw = _w / 2; + + tb_shift.setFocusHover(active, hover); + tb_scale.setFocusHover(active, hover); + + tb_shift.hide = true; + tb_scale.hide = true; + + draw_sprite_stretched_ext(THEME.textbox, 3, _x, tby, _w, tbh, c_white, 1); + draw_sprite_stretched_ext(THEME.textbox, 0, _x, tby, _w, tbh, c_white, 0.5 + 0.5 * interactable); + + tb_shift.draw(_x, tby, tbw, tbh, _data[0], _m); + tb_scale.draw(_x + tbw, tby, tbw, tbh, _data[1], _m); + } + resetFocus(); return h; diff --git a/scripts/curve_bezier_function/curve_bezier_function.gml b/scripts/curve_bezier_function/curve_bezier_function.gml index d05c0cb2e..9d7f58720 100644 --- a/scripts/curve_bezier_function/curve_bezier_function.gml +++ b/scripts/curve_bezier_function/curve_bezier_function.gml @@ -1,38 +1,78 @@ //curve format [-cx0, -cy0, x0, y0, +cx0, +cy0, -cx1, -cy1, x1, y1, +cx1, +cy1] //segment format [y0, +cx0, +cy0, -cx1, -cy1, y1] -#macro CURVE_DEF_00 [0, 0, 0, 0, 1/3, 0, /**/ -1/3, 0, 1, 0, 0, 0] -#macro CURVE_DEF_01 [0, 0, 0, 0, 1/3, 1/3, /**/ -1/3, -1/3, 1, 1, 0, 0] -#macro CURVE_DEF_10 [0, 0, 0, 1, 1/3, -1/3, /**/ -1/3, 1/3, 1, 0, 0, 0] -#macro CURVE_DEF_11 [0, 0, 0, 1, 1/3, 0, /**/ -1/3, 0, 1, 1, 0, 0] +#macro CURVE_DEF_00 [0, 1, /**/ 0, 0, 0, 0, 1/3, 0, /**/ -1/3, 0, 1, 0, 0, 0] +#macro CURVE_DEF_01 [0, 1, /**/ 0, 0, 0, 0, 1/3, 1/3, /**/ -1/3, -1/3, 1, 1, 0, 0] +#macro CURVE_DEF_10 [0, 1, /**/ 0, 0, 0, 1, 1/3, -1/3, /**/ -1/3, 1/3, 1, 0, 0, 0] +#macro CURVE_DEF_11 [0, 1, /**/ 0, 0, 0, 1, 1/3, 0, /**/ -1/3, 0, 1, 1, 0, 0] -function draw_curve(x0, y0, _w, _h, _bz, minx = 0, maxx = 1, miny = 0, maxy = 1) { #region - var segments = array_length(_bz) / 6 - 1; +function draw_curve(x0, y0, _w, _h, _bz, minx = 0, maxx = 1, miny = 0, maxy = 1, _shift = 0, _scale = 1) { #region + var _amo = array_length(_bz); + var _shf = _amo % 6; + + var segments = (_amo - _shf) / 6 - 1; var _ox, _oy; + var rngx = maxx - minx; + var rngy = maxy - miny; + for( var i = 0; i < segments; i++ ) { - var ind = i * 6; + var ind = _shf + i * 6; - var _x0 = _bz[ind + 2]; - var _y0 = _bz[ind + 3]; + var _x0 = _bz[ind + 2]; + var _y0 = _bz[ind + 3]; var ax0 = _x0 + _bz[ind + 4]; var ay0 = _y0 + _bz[ind + 5]; - var _x1 = _bz[ind + 6 + 2]; - var _y1 = _bz[ind + 6 + 3]; + var _x1 = _bz[ind + 6 + 2]; + var _y1 = _bz[ind + 6 + 3]; var bx1 = _x1 + _bz[ind + 6 + 0]; var by1 = _y1 + _bz[ind + 6 + 1]; - var smp = ceil((_x1 - _x0) / (maxx - minx) * 32); + var _xr = _x1 - _x0; + + var smp = ceil(_xr / rngx * 32); var bbz = [ _y0, ax0, ay0, bx1, by1, _y1 ]; - if(_x1 < minx) continue; + //if(_x1 < minx) continue; + + if(i == 0) { + var _rx = _x0 * _scale + _shift; + var _ry = _y0; + + _rx = ( _rx - minx ) / rngx; + _ry = ( _ry - miny ) / rngy; + + var _nx = x0 + _w * _rx; + var _ny = y0 + _h * (1 - _ry); + + draw_line(x0, _ny, _nx, _ny); + } + + if(i == segments - 1) { + var _rx = _x1 * _scale + _shift; + var _ry = _y1; + + _rx = ( _rx - minx ) / rngx; + _ry = ( _ry - miny ) / rngy; + + var _nx = x0 + _w * _rx; + var _ny = y0 + _h * (1 - _ry); + + draw_line(x0 + _w, _ny, _nx, _ny); + } for(var j = 0; j <= smp; j++) { var t = j / smp; var _r = eval_curve_segment_t_position(t, bbz); - var _rx = ((_x0 + _r[0] * (_x1 - _x0)) - minx) / (maxx - minx); - var _ry = (_r[1] - miny) / (maxy - miny); + + var _rx = _r[0] * _xr + _x0; + var _ry = _r[1]; + + _rx = _rx * _scale + _shift; + + _rx = ( _rx - minx ) / rngx; + _ry = ( _ry - miny ) / rngy; var _nx = x0 + _w * _rx; var _ny = y0 + _h * (1 - _ry); @@ -47,17 +87,23 @@ function draw_curve(x0, y0, _w, _h, _bz, minx = 0, maxx = 1, miny = 0, maxy = 1) } } #endregion -function eval_curve_segment_t_position(t, _bz) { #region +function eval_curve_segment_t_position(_t, _bz) { #region + var _t2 = _t * _t; + var _t3 = _t * _t * _t; + var _T = 1 - _t; + var _T2 = _T * _T; + var _T3 = _T * _T * _T; + return [ - power(1 - t, 3) * 0 - + 3 * power(1 - t, 2) * t * _bz[1] - + 3 * (1 - t) * power(t, 2) * _bz[3] - + power(t, 3) * 1, + _T3 * 0 + + 3 * _T2 * _t * _bz[1] + + 3 * _T * _t2 * _bz[3] + + _t3 * 1, - power(1 - t, 3) * _bz[0] - + 3 * power(1 - t, 2) * t * _bz[2] - + 3 * (1 - t) * power(t, 2) * _bz[4] - + power(t, 3) * _bz[5] + _T3 * _bz[0] + + 3 * _T2 * _t * _bz[2] + + 3 * _T * _t2 * _bz[4] + + _t3 * _bz[5] ]; } #endregion @@ -69,19 +115,30 @@ function eval_curve_segment_t(_bz, t) { #region } #endregion function eval_curve_x(_bz, _x, _tolr = 0.00001) { #region - static _CURVE_DEF_01 = [0, 0, 0, 0, 1/3, 1/3, /**/ -1/3, -1/3, 1, 1, 0, 0]; - static _CURVE_DEF_10 = [0, 0, 0, 1, 1/3, -1/3, /**/ -1/3, 1/3, 1, 0, 0, 0]; - static _CURVE_DEF_11 = [0, 0, 0, 1, 1/3, 0, /**/ -1/3, 0, 1, 1, 0, 0]; + static _CURVE_DEF_01 = [0, 1, /**/ 0, 0, 0, 0, 1/3, 1/3, /**/ -1/3, -1/3, 1, 1, 0, 0]; + static _CURVE_DEF_10 = [0, 1, /**/ 0, 0, 0, 1, 1/3, -1/3, /**/ -1/3, 1/3, 1, 0, 0, 0]; + static _CURVE_DEF_11 = [0, 1, /**/ 0, 0, 0, 1, 1/3, 0, /**/ -1/3, 0, 1, 1, 0, 0]; if(array_equals(_bz, _CURVE_DEF_11)) return 1; if(array_equals(_bz, _CURVE_DEF_01)) return _x; if(array_equals(_bz, _CURVE_DEF_10)) return 1 - _x; - var segments = array_length(_bz) / 6 - 1; + var _amo = array_length(_bz); + var _shf = _amo % 6; + var _shift = 0; + var _scale = 1; + + if(_shf) { + var _shift = _bz[0]; + var _scale = _bz[1]; + } + + var segments = (_amo - _shf) / 6 - 1; + _x = _x / _scale - _shift; _x = clamp(_x, 0, 1); for( var i = 0; i < segments; i++ ) { - var ind = i * 6; + var ind = _shf + i * 6; var _x0 = _bz[ind + 2]; var _y0 = _bz[ind + 3]; //var bx0 = _x0 + _bz[ind + 0]; diff --git a/scripts/node_keyframe/node_keyframe.gml b/scripts/node_keyframe/node_keyframe.gml index e0a416bce..8932305a2 100644 --- a/scripts/node_keyframe/node_keyframe.gml +++ b/scripts/node_keyframe/node_keyframe.gml @@ -701,10 +701,16 @@ function valueAnimator(_val, _prop, _sep_axis = false) constructor { if(is_array(value)) { for(var j = 0; j < array_length(value); j++) _val[j] = processValue(value[j]); + } else if(is_array(base)) { for(var j = 0; j < array_length(base); j++) _val[j] = processValue(value); } + + if(prop.type == VALUE_TYPE.curve && array_length(value) % 6 == 0) { + array_insert(_val, 0, 0); + array_insert(_val, 1, 1); + } } //print($"Deserialize {prop.node.name}:{prop.name} = {_val} "); diff --git a/scripts/node_line/node_line.gml b/scripts/node_line/node_line.gml index 035758c4f..bc482a8df 100644 --- a/scripts/node_line/node_line.gml +++ b/scripts/node_line/node_line.gml @@ -1,5 +1,6 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { name = "Line"; + batch_output = true; inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, DEF_SURF ) .setDisplay(VALUE_DISPLAY.vector); @@ -43,7 +44,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons inputs[| 15] = nodeValue("Span color over path", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Apply the full 'color over length' to the trimmed path."); - inputs[| 16] = nodeValue("Greyscale over width", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + inputs[| 16] = nodeValue("Width pass", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); inputs[| 17] = nodeValue("1px mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false, "Render pixel perfect 1px line."); @@ -79,6 +80,8 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); + outputs[| 1] = nodeValue("Width Pass", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); + lines = []; widthMap = ds_map_create(); @@ -133,7 +136,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons if(index == 11) ds_map_clear(widthMap); } #endregion - static processData = function(_outSurf, _data, _output_index, _array_index) { #region + static processData = function(_outData, _data, _output_index, _array_index) { #region #region data var _dim = _data[0]; var _bg = _data[1]; @@ -195,7 +198,8 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons random_set_seed(_sed); var _sedIndex = 0; - _outSurf = surface_verify(_outSurf, _dim[0], _dim[1], attrDepth()); + var _colorPass = surface_verify(_outData[0], _dim[0], _dim[1], attrDepth()); + var _widthPass = surface_verify(_outData[1], _dim[0], _dim[1], attrDepth()); var p = new __vec2(); var _ox, _nx, _nx1, _oy, _ny, _ny1; @@ -281,9 +285,9 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons // print($"_pp = {_pp}, total = {_total}"); p = _pat.getPointDistance(_pp, i, p); - if(struct_has(_pat, "getWeightDistance")) wght = _pat.getWeightDistance(_pp, i); + } else { _prog_next = min(_prog_curr + _stepLen, 1); //Move forward _stepLen or _total (if less) stop at 1 _pathPng = _ratInv? 1 - _prog_curr : _prog_curr; @@ -341,6 +345,7 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons array_resize(lines, _lineAmo); #endregion + } else { #region var x0, y0, x1, y1; var _0 = point_rectangle_overlap(_dim[0], _dim[1], (_ang + 180) % 360); @@ -385,143 +390,233 @@ function Node_Line(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons } #endregion #region draw + + surface_set_target(_colorPass); + if(_bg) draw_clear_alpha(0, 1); + else DRAW_CLEAR + + if(_useTex) { #region + var tex = surface_get_texture(_tex); + + shader_set(sh_draw_mapping); + shader_set_f("position", _texPos); + shader_set_f("rotation", degtorad(_texRot)); + shader_set_f("scale", _texSca); + + shader_set_interpolation(_tex); + } #endregion + + for( var i = 0, n = array_length(lines); i < n; i++ ) { + var points = lines[i]; + if(array_length(points) < 2) continue; + + var _caps = []; + + if(_useTex) draw_primitive_begin_texture(pr_trianglestrip, tex); + else draw_primitive_begin(pr_trianglestrip); + + random_set_seed(_sed + i); + var pxs = []; + var dat = array_safe_get_fast(_pathData, i, noone); + + var _col_base = dat == noone? _colb.eval(random(1)) : dat.color; + + for( var j = 0; j < array_length(points); j++ ) { + var p0 = points[j]; + var _nx = p0.x - 0.5 * _1px; + var _ny = p0.y - 0.5 * _1px; + var prog = p0.prog; + var prgc = p0.progCrop; + var _dir = j? point_direction(_ox, _oy, _nx, _ny) : 0; + + var widProg = value_snap_real(_widap? prog : prgc, 0.01); + + _nw = random_range(_wid[0], _wid[1]); + if(!ds_map_exists(widthMap, widProg)) + widthMap[? widProg] = eval_curve_x(_widc, widProg, 0.1); + _nw *= widthMap[? widProg]; + _nw *= p0.weight; + + _nc = colorMultiply(_col_base, _color.eval(_colP? prog : prgc)); + + if(_cap) { #region + if(j == 1) { + _d = _dir + 180; + _caps[0] = [ _oc, _ox, _oy, _ow / 2, _d - 90, _d ]; + _caps[1] = [ _oc, _ox, _oy, _ow / 2, _d, _d + 90 ]; + } + + if(j == array_length(points) - 1) { + _d = _dir; + _caps[2] = [ _nc, _nx, _ny, _nw / 2, _d - 90, _d ]; + _caps[3] = [ _nc, _nx, _ny, _nw / 2, _d, _d + 90 ]; + } + } #endregion + + if(_1px) { #region + if(j) { + var dst = point_distance(_ox, _oy, _nx, _ny); + if(dst <= 1 && i < array_length(points) - 1) continue; + draw_line_color(_ox, _oy, _nx, _ny, _oc, _nc); + } + + _ox = _nx; + _oy = _ny; + _oc = _nc; + #endregion + } else { #region + if(j) { + var _nd0 = _dir; + var _nd1 = _nd0; + + if(j < array_length(points) - 1) { + var p2 = points[j + 1]; + var _nnx = p2.x; + var _nny = p2.y; + + _nd1 = point_direction(_nx, _ny, _nnx, _nny); + _nd = _nd0 + angle_difference(_nd1, _nd0) / 2; + } else + _nd = _nd0; + + if(_useTex) { + var _len = array_length(points) - 1; + + var ox0 = _ox + lengthdir_x(_ow / 2, _od + 90); + var oy0 = _oy + lengthdir_y(_ow / 2, _od + 90); + var nx0 = _nx + lengthdir_x(_nw / 2, _nd + 90); + var ny0 = _ny + lengthdir_y(_nw / 2, _nd + 90); - surface_set_target(_outSurf); - if(_bg) draw_clear_alpha(0, 1); - else DRAW_CLEAR - - if(_useTex) { #region - var tex = surface_get_texture(_tex); - - shader_set(sh_draw_mapping); - shader_set_f("position", _texPos); - shader_set_f("rotation", degtorad(_texRot)); - shader_set_f("scale", _texSca); - - shader_set_interpolation(_tex); - } #endregion - - for( var i = 0, n = array_length(lines); i < n; i++ ) { - var points = lines[i]; - if(array_length(points) < 2) continue; - - var _caps = []; - - if(_useTex) draw_primitive_begin_texture(pr_trianglestrip, tex); - else draw_primitive_begin(pr_trianglestrip); - - random_set_seed(_sed + i); - var pxs = []; - var dat = array_safe_get_fast(_pathData, i, noone); - - var _col_base = dat == noone? _colb.eval(random(1)) : dat.color; - - for( var j = 0; j < array_length(points); j++ ) { - var p0 = points[j]; - var _nx = p0.x - 0.5 * _1px; - var _ny = p0.y - 0.5 * _1px; - var prog = p0.prog; - var prgc = p0.progCrop; - var _dir = j? point_direction(_ox, _oy, _nx, _ny) : 0; - - var widProg = value_snap_real(_widap? prog : prgc, 0.01); - - _nw = random_range(_wid[0], _wid[1]); - if(!ds_map_exists(widthMap, widProg)) - widthMap[? widProg] = eval_curve_x(_widc, widProg, 0.1); - _nw *= widthMap[? widProg]; - _nw *= p0.weight; - - _nc = colorMultiply(_col_base, _color.eval(_colP? prog : prgc)); - - if(_cap) { #region - if(j == 1) { - _d = _dir + 180; - _caps[0] = [ _oc, _ox, _oy, _ow / 2, _d - 90, _d ]; - _caps[1] = [ _oc, _ox, _oy, _ow / 2, _d, _d + 90 ]; - } + var ox1 = _ox + lengthdir_x(_ow / 2, _od + 90 + 180); + var oy1 = _oy + lengthdir_y(_ow / 2, _od + 90 + 180); + var nx1 = _nx + lengthdir_x(_nw / 2, _nd + 90 + 180); + var ny1 = _ny + lengthdir_y(_nw / 2, _nd + 90 + 180); + + draw_vertex_texture_color(ox0, oy0, 0, (j - 1) / _len, _oc, 1); + draw_vertex_texture_color(ox1, oy1, 1, (j - 1) / _len, _oc, 1); + draw_vertex_texture_color(nx0, ny0, 0, (j - 0) / _len, _nc, 1); + draw_vertex_texture_color(nx1, ny1, 1, (j - 0) / _len, _nc, 1); + + } else + draw_line_width2_angle(_ox, _oy, _nx, _ny, _ow, _nw, _od + 90, _nd + 90, _oc, _nc); + } else { + var p1 = points[j + 1]; + _nd = point_direction(_nx, _ny, p1.x, p1.y); + } - if(j == array_length(points) - 1) { - _d = _dir; - _caps[2] = [ _nc, _nx, _ny, _nw / 2, _d - 90, _d ]; - _caps[3] = [ _nc, _nx, _ny, _nw / 2, _d, _d + 90 ]; + _ox = _nx; + _oy = _ny; + _od = _nd; + _ow = _nw; + _oc = _nc; } - } #endregion - - if(_1px) { #region - if(j) { - var dst = point_distance(_ox, _oy, _nx, _ny); - if(dst <= 1 && i < array_length(points) - 1) continue; - draw_line_color(_ox, _oy, _nx, _ny, _oc, _nc); - } - - _ox = _nx; - _oy = _ny; - _oc = _nc; #endregion - } else { #region - if(j) { - var _nd0 = _dir; - var _nd1 = _nd0; - - if(j < array_length(points) - 1) { - var p2 = points[j + 1]; - var _nnx = p2.x; - var _nny = p2.y; - - _nd1 = point_direction(_nx, _ny, _nnx, _nny); - _nd = _nd0 + angle_difference(_nd1, _nd0) / 2; - } else - _nd = _nd0; - - if(_useTex) { - var _len = array_length(points) - 1; - - var ox0 = _ox + lengthdir_x(_ow / 2, _od + 90); - var oy0 = _oy + lengthdir_y(_ow / 2, _od + 90); - var nx0 = _nx + lengthdir_x(_nw / 2, _nd + 90); - var ny0 = _ny + lengthdir_y(_nw / 2, _nd + 90); - - var ox1 = _ox + lengthdir_x(_ow / 2, _od + 90 + 180); - var oy1 = _oy + lengthdir_y(_ow / 2, _od + 90 + 180); - var nx1 = _nx + lengthdir_x(_nw / 2, _nd + 90 + 180); - var ny1 = _ny + lengthdir_y(_nw / 2, _nd + 90 + 180); - - draw_vertex_texture_color(ox0, oy0, 0, (j - 1) / _len, _oc, 1); - draw_vertex_texture_color(ox1, oy1, 1, (j - 1) / _len, _oc, 1); - draw_vertex_texture_color(nx0, ny0, 0, (j - 0) / _len, _nc, 1); - draw_vertex_texture_color(nx1, ny1, 1, (j - 0) / _len, _nc, 1); - } else if(_colW) - draw_line_width2_angle_width(_ox, _oy, _nx, _ny, _ow, _nw, _od + 90, _nd + 90, merge_color(_oc, c_black, 0.5), merge_color(_nc, c_black, 0.5)); - else - draw_line_width2_angle(_ox, _oy, _nx, _ny, _ow, _nw, _od + 90, _nd + 90, _oc, _nc); - } else { - var p1 = points[j + 1]; - _nd = point_direction(_nx, _ny, p1.x, p1.y); - } - - _ox = _nx; - _oy = _ny; - _od = _nd; - _ow = _nw; - _oc = _nc; } - #endregion + + draw_primitive_end(); + + for( var j = 0, m = array_length(_caps); j < m; j++ ) { + var _cps = _caps[j]; + draw_set_color(_cps[0]); + draw_circle_angle(_cps[1], _cps[2], _cps[3], _cps[4], _cps[5], _capP); + } } - draw_primitive_end(); - - for( var j = 0, m = array_length(_caps); j < m; j++ ) { - var _cps = _caps[j]; - draw_set_color(_cps[0]); - draw_circle_angle(_cps[1], _cps[2], _cps[3], _cps[4], _cps[5], _capP); - } - } + if(_useTex) shader_reset(); + surface_reset_target(); - if(_useTex) shader_reset(); - surface_reset_target(); + if(_colW && !_1px) { + + surface_set_target(_widthPass); + if(_bg) draw_clear_alpha(0, 1); + else DRAW_CLEAR + + for( var i = 0, n = array_length(lines); i < n; i++ ) { + var points = lines[i]; + if(array_length(points) < 2) continue; + + var _caps = []; + + draw_primitive_begin(pr_trianglestrip); + + random_set_seed(_sed + i); + var pxs = []; + var dat = array_safe_get_fast(_pathData, i, noone); + + var _col_base = dat == noone? _colb.eval(random(1)) : dat.color; + + for( var j = 0; j < array_length(points); j++ ) { + var p0 = points[j]; + var _nx = p0.x - 0.5 * _1px; + var _ny = p0.y - 0.5 * _1px; + var prog = p0.prog; + var prgc = p0.progCrop; + var _dir = j? point_direction(_ox, _oy, _nx, _ny) : 0; + + var widProg = value_snap_real(_widap? prog : prgc, 0.01); + + _nw = random_range(_wid[0], _wid[1]); + if(!ds_map_exists(widthMap, widProg)) + widthMap[? widProg] = eval_curve_x(_widc, widProg, 0.1); + _nw *= widthMap[? widProg]; + _nw *= p0.weight; + + if(_cap) { #region + if(j == 1) { + _d = _dir + 180; + _caps[0] = [ c_grey, _ox, _oy, _ow / 2, _d - 90, _d ]; + _caps[1] = [ c_grey, _ox, _oy, _ow / 2, _d, _d + 90 ]; + } + + if(j == array_length(points) - 1) { + _d = _dir; + _caps[2] = [ c_grey, _nx, _ny, _nw / 2, _d - 90, _d ]; + _caps[3] = [ c_grey, _nx, _ny, _nw / 2, _d, _d + 90 ]; + } + } #endregion + + if(j) { + var _nd0 = _dir; + var _nd1 = _nd0; + + if(j < array_length(points) - 1) { + var p2 = points[j + 1]; + var _nnx = p2.x; + var _nny = p2.y; + + _nd1 = point_direction(_nx, _ny, _nnx, _nny); + _nd = _nd0 + angle_difference(_nd1, _nd0) / 2; + } else + _nd = _nd0; + + draw_line_width2_angle_width(_ox, _oy, _nx, _ny, _ow, _nw, _od + 90, _nd + 90, c_white, c_white); + } else { + var p1 = points[j + 1]; + _nd = point_direction(_nx, _ny, p1.x, p1.y); + } + + _ox = _nx; + _oy = _ny; + _od = _nd; + _ow = _nw; + + #endregion + } + + draw_primitive_end(); + + for( var j = 0, m = array_length(_caps); j < m; j++ ) { + var _cps = _caps[j]; + draw_set_color(_cps[0]); + draw_circle_angle(_cps[1], _cps[2], _cps[3], _cps[4], _cps[5], _capP); + } + } + + surface_reset_target(); + + } #endregion - return _outSurf; + return [ _colorPass, _widthPass ]; } #endregion } \ No newline at end of file diff --git a/scripts/node_path/node_path.gml b/scripts/node_path/node_path.gml index f6c853ea3..e4ff06270 100644 --- a/scripts/node_path/node_path.gml +++ b/scripts/node_path/node_path.gml @@ -41,7 +41,8 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { ["Anchors", false], ]; - output_display_list = [ 1, 0, 2 ]; + output_display_list = [ 1, 0, 2 ]; + path_preview_surface = noone; setDynamicInput(1, false); @@ -845,6 +846,50 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { lengthTotal += l; lengthAccs[i] = lengthTotal; } + + var minx = boundary.minx - 8, miny = boundary.miny - 8; + var maxx = boundary.maxx + 8, maxy = boundary.maxy + 8; + var rngx = maxx - minx, rngy = maxy - miny; + var prev_s = 128; + var _surf = surface_create(prev_s, prev_s); + + _surf = surface_verify(_surf, prev_s, prev_s); + surface_set_target(_surf); + DRAW_CLEAR + + var ox, oy, nx, ny; + draw_set_color(c_white); + for (var i = 0, n = array_length(segments); i < n; i++) { + var segment = segments[i]; + + for (var j = 0, m = array_length(segment); j < m; j += 2) { + nx = (segment[j + 0] - minx) / rngx * prev_s; + ny = (segment[j + 1] - miny) / rngy * prev_s; + + if(j) draw_line_round(ox, oy, nx, ny, 3); + + ox = nx; + oy = ny; + } + } + + draw_set_color(COLORS._main_accent); + for (var i = 0, n = array_length(anchors); i < n; i++) { + var _a0 = anchors[i]; + draw_circle((_a0[0] - minx) / rngx * prev_s, (_a0[1] - miny) / rngy * prev_s, 6, false); + } + surface_reset_target(); + + path_preview_surface = surface_verify(path_preview_surface, prev_s, prev_s); + surface_set_shader(path_preview_surface, sh_FXAA); + shader_set_f("dimension", prev_s, prev_s); + shader_set_f("cornerDis", 0.5); + shader_set_f("mixAmo", 1); + + draw_surface(_surf, 0, 0); + surface_reset_shader(); + + surface_free(_surf); } #endregion static getLineCount = function() { return 1; } @@ -985,6 +1030,8 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region var bbox = drawGetBbox(xx, yy, _s); - draw_sprite_fit(THEME.node_draw_path, 0, bbox.xc, bbox.yc, bbox.w, bbox.h); + gpu_set_tex_filter(true); + draw_surface_bbox(path_preview_surface, bbox); + gpu_set_tex_filter(false); } #endregion } \ No newline at end of file diff --git a/scripts/node_path_scatter/node_path_scatter.gml b/scripts/node_path_scatter/node_path_scatter.gml index bd5ad3be5..6075c20d9 100644 --- a/scripts/node_path_scatter/node_path_scatter.gml +++ b/scripts/node_path_scatter/node_path_scatter.gml @@ -1,5 +1,6 @@ function Node_Path_Scatter(_x, _y, _group = noone) : Node(_x, _y, _group) constructor { name = "Scatter Path"; + setDimension(96, 48); inputs[| 0] = nodeValue("Base Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone) @@ -182,9 +183,18 @@ function Node_Path_Scatter(_x, _y, _group = noone) : Node(_x, _y, _group) constr flip : _flip, } - segment_counts[i] = array_clone(path_scat.getSegmentCount(0)); - line_lengths[i] = array_clone(path_scat.getLength(0)); - accu_lengths[i] = array_clone(path_scat.getAccuLength(0)); + var _segment_counts = array_clone(path_scat.getSegmentCount(0)); + var _line_lengths = array_clone(path_scat.getLength(0)); + var _accu_lengths = array_clone(path_scat.getAccuLength(0)); + + _line_lengths *= _sca; + + for (var j = 0, m = array_length(_accu_lengths); j < m; j++) + _accu_lengths[j] *= _sca; + + segment_counts[i] = _segment_counts; + line_lengths[i] = _line_lengths; + accu_lengths[i] = _accu_lengths; } outputs[| 0].setValue(self);