2024-07-17 09:02:36 +02:00
|
|
|
function Node_Path_Scatter(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor {
|
2024-06-17 13:12:33 +02:00
|
|
|
name = "Scatter Path";
|
|
|
|
setDimension(96, 48);
|
|
|
|
|
2024-08-18 09:13:41 +02:00
|
|
|
newInput(0, nodeValue_PathNode("Base Path", self, noone))
|
2024-06-17 13:12:33 +02:00
|
|
|
.setVisible(true, true);
|
|
|
|
|
2024-08-18 09:13:41 +02:00
|
|
|
newInput(1, nodeValue_PathNode("Scatter Path", self, noone))
|
2024-06-17 13:12:33 +02:00
|
|
|
.setVisible(true, true);
|
|
|
|
|
2024-08-18 06:16:20 +02:00
|
|
|
newInput(2, nodeValue_Slider_Range("Range", self, [ 0, 1 ]));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-08-18 06:16:20 +02:00
|
|
|
newInput(3, nodeValue_Int("Amount", self, 4));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-08-18 06:16:20 +02:00
|
|
|
newInput(4, nodeValue_Slider_Range("Scale", self, [ 0.5, 1 ]));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-08-18 09:13:41 +02:00
|
|
|
newInput(5, nodeValue_Float("Seed", self, seed_random(6)))
|
2024-08-08 06:57:51 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY._default, { side_button : button(function() { randomize(); inputs[5].setValue(seed_random(6)); }).setIcon(THEME.icon_random, 0, COLORS._main_icon) });
|
2024-06-17 13:12:33 +02:00
|
|
|
|
[Blend, Composite] Add blends modes: color burn. linear burn, color dodge, linear dodge, soft light, hard light, vivid light, linear light, pin light, exclusion, divide.
2024-10-05 09:27:38 +02:00
|
|
|
newInput(6, nodeValue_Curve("Scale over Length", self, CURVE_DEF_11));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-08-18 06:16:20 +02:00
|
|
|
newInput(7, nodeValue_Rotation_Random("Rotation", self, [ 0, 45, 135, 0, 0 ] ));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-08-18 06:16:20 +02:00
|
|
|
newInput(8, nodeValue_Enum_Scroll("Distribution", self, 0 , [ "Uniform", "Random" ]));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
[Blend, Composite] Add blends modes: color burn. linear burn, color dodge, linear dodge, soft light, hard light, vivid light, linear light, pin light, exclusion, divide.
2024-10-05 09:27:38 +02:00
|
|
|
newInput(9, nodeValue_Curve("Trim over Length", self, CURVE_DEF_11));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-08-18 09:13:41 +02:00
|
|
|
newInput(10, nodeValue_Float("Range", self, 1))
|
2024-06-17 13:12:33 +02:00
|
|
|
.setDisplay(VALUE_DISPLAY.slider);
|
|
|
|
|
2024-08-18 06:16:20 +02:00
|
|
|
newInput(11, nodeValue_Bool("Flip if Negative", self, false ));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-08-18 06:16:20 +02:00
|
|
|
newInput(12, nodeValue_Enum_Scroll("Origin", self, 0 , [ "Individual", "First", "Zero" ]));
|
2024-06-19 05:41:07 +02:00
|
|
|
|
2024-09-04 03:57:11 +02:00
|
|
|
newOutput(0, nodeValue_Output("Path", self, VALUE_TYPE.pathnode, self));
|
2024-06-17 13:12:33 +02:00
|
|
|
|
|
|
|
input_display_list = [ 5,
|
|
|
|
["Paths", false], 0, 1, 10, 9,
|
|
|
|
["Scatter", false], 8, 3,
|
2024-06-19 05:41:07 +02:00
|
|
|
["Position", false], 12, 2,
|
2024-06-17 13:12:33 +02:00
|
|
|
["Rotation", false], 7, 11,
|
|
|
|
["Scale", false], 4, 6,
|
|
|
|
];
|
|
|
|
|
2024-06-22 04:19:30 +02:00
|
|
|
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) {
|
2024-07-17 09:02:36 +02:00
|
|
|
var _path = getSingleValue(0);
|
2024-06-17 13:12:33 +02:00
|
|
|
if(_path && struct_has(_path, "drawOverlay")) _path.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
|
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
var _path = getSingleValue(1);
|
2024-06-17 13:12:33 +02:00
|
|
|
if(_path && struct_has(_path, "drawOverlay")) _path.drawOverlay(hover, active, _x, _y, _s, _mx, _my, _snx, _sny);
|
|
|
|
|
2024-06-22 04:19:30 +02:00
|
|
|
}
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
function Path_Scatter() constructor {
|
|
|
|
line_amount = 0;
|
|
|
|
paths = [];
|
|
|
|
segment_counts = [];
|
|
|
|
line_lengths = [];
|
|
|
|
accu_lengths = [];
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
__temp_p = [ 0, 0 ];
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
static getLineCount = function() { return line_amount; }
|
|
|
|
static getSegmentCount = function(ind = 0) { return array_safe_get_fast(segment_counts, ind); }
|
|
|
|
static getLength = function(ind = 0) { return array_safe_get_fast(line_lengths, ind); }
|
|
|
|
static getAccuLength = function(ind = 0) { return array_safe_get_fast(accu_lengths, ind); }
|
|
|
|
static getPointRatio = function(_rat, ind = 0, out = undefined) {
|
|
|
|
if(out == undefined) out = new __vec2(); else { out.x = 0; out.y = 0; }
|
|
|
|
|
|
|
|
var _path = array_safe_get_fast(paths, ind, 0);
|
|
|
|
if(_path == 0) return out;
|
|
|
|
|
|
|
|
var _pathObj = _path.path;
|
|
|
|
if(!is_struct(_pathObj) || !struct_has(_pathObj, "getPointRatio"))
|
|
|
|
return out;
|
|
|
|
|
|
|
|
var _ind = _path.index;
|
|
|
|
var _ori = _path.ori;
|
|
|
|
var _pos = _path.pos;
|
|
|
|
var _rot = _path.rot;
|
|
|
|
var _rotW = _path.rotW;
|
|
|
|
var _sca = _path.sca;
|
|
|
|
var _trm = _path.trim;
|
|
|
|
var _flip = _path.flip;
|
|
|
|
|
|
|
|
_rat *= _trm;
|
|
|
|
|
|
|
|
out = _pathObj.getPointRatio(_rat, _ind, out);
|
|
|
|
|
|
|
|
var _px = out.x - _ori[0];
|
|
|
|
var _py = out.y - _ori[1];
|
|
|
|
|
|
|
|
if(_flip && angle_difference(_rotW, 90) < 0)
|
|
|
|
_px = -_px;
|
|
|
|
|
|
|
|
__temp_p = point_rotate(_px, _py, 0, 0, _rot, __temp_p);
|
|
|
|
|
|
|
|
out.x = _pos[0] + __temp_p[0] * _sca;
|
|
|
|
out.y = _pos[1] + __temp_p[1] * _sca;
|
|
|
|
|
2024-06-17 13:12:33 +02:00
|
|
|
return out;
|
2024-07-17 09:02:36 +02:00
|
|
|
}
|
|
|
|
static getPointDistance = function(_dist, ind = 0, out = undefined) { return getPointRatio(_dist / getLength(ind), ind, out); }
|
|
|
|
static getBoundary = function(ind = 0) {
|
|
|
|
var _path = getInputData(0);
|
|
|
|
return struct_has(_path, "getBoundary")? _path.getBoundary(ind) : new BoundingBox( 0, 0, 1, 1 );
|
|
|
|
}
|
2024-06-22 04:19:30 +02:00
|
|
|
}
|
2024-06-19 05:41:07 +02:00
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static processData = function(_outSurf, _data, _output_index, _array_index) {
|
|
|
|
|
|
|
|
var path_base = _data[ 0];
|
|
|
|
var path_scat = _data[ 1];
|
|
|
|
var _range = _data[ 2];
|
|
|
|
var _repeat = _data[ 3];
|
|
|
|
var _scale = _data[ 4];
|
|
|
|
var _seed = _data[ 5];
|
|
|
|
var _sca_wid = _data[ 6];
|
|
|
|
var _rotation = _data[ 7];
|
|
|
|
var _distrib = _data[ 8];
|
|
|
|
var _trim = _data[ 9];
|
|
|
|
var _trim_rng = _data[10];
|
|
|
|
var _flip = _data[11];
|
|
|
|
var _resetOri = _data[12];
|
|
|
|
|
|
|
|
var _scattered = new Path_Scatter();
|
|
|
|
if(path_base == noone) return _scattered;
|
|
|
|
if(path_scat == noone) return _scattered;
|
2024-06-17 13:12:33 +02:00
|
|
|
var p = new __vec2();
|
|
|
|
|
|
|
|
random_set_seed(_seed);
|
|
|
|
|
2024-06-19 05:41:07 +02:00
|
|
|
var _line_amounts = path_scat.getLineCount();
|
|
|
|
var _ind = 0;
|
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
_scattered.line_amount = _repeat * _line_amounts;
|
|
|
|
_scattered.paths = array_create(_scattered.line_amount);
|
|
|
|
_scattered.segment_counts = array_create(_scattered.line_amount);
|
|
|
|
_scattered.line_lengths = array_create(_scattered.line_amount);
|
|
|
|
_scattered.accu_lengths = array_create(_scattered.line_amount);
|
2024-06-19 05:41:07 +02:00
|
|
|
|
|
|
|
var ori, pos;
|
|
|
|
var _prog_raw, _prog;
|
|
|
|
var _dir, _sca, _rot, _rotW, _trm;
|
2024-07-17 09:02:36 +02:00
|
|
|
var x0, y0, x1, y1;
|
2024-06-19 05:41:07 +02:00
|
|
|
|
|
|
|
for (var i = 0; i < _repeat; i++) {
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-06-19 05:41:07 +02:00
|
|
|
_prog_raw = _distrib? random_range(0, 1) : (i / max(1, _repeat - 1)) * 0.9999;
|
|
|
|
_prog = lerp(_range[0], _range[1], _prog_raw);
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-06-19 05:41:07 +02:00
|
|
|
_sca = random_range(_scale[0], _scale[1]);
|
|
|
|
_sca *= eval_curve_x(_sca_wid, _prog_raw);
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-06-19 05:41:07 +02:00
|
|
|
_rot = angle_random_eval(_rotation);
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-06-19 05:41:07 +02:00
|
|
|
_trm = _trim_rng;
|
|
|
|
_trm *= eval_curve_x(_trim, _prog_raw);
|
2024-06-22 05:12:08 +02:00
|
|
|
|
2024-06-19 05:41:07 +02:00
|
|
|
for (var k = 0; k < _line_amounts; k++) {
|
|
|
|
|
|
|
|
switch(_resetOri) {
|
|
|
|
case 0 :
|
|
|
|
p = path_scat.getPointRatio(0, k, p);
|
|
|
|
ori = [ p.x, p.y ];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1 :
|
|
|
|
p = path_scat.getPointRatio(0, 0, p);
|
|
|
|
ori = [ p.x, p.y ];
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2 :
|
|
|
|
ori = [ 0, 0 ];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = path_base.getPointRatio(_prog, k, p);
|
|
|
|
pos = [ p.x, p.y ];
|
|
|
|
|
|
|
|
p = path_base.getPointRatio(clamp(_prog - 0.001, 0., 0.9999), k, p);
|
|
|
|
x0 = p.x;
|
|
|
|
y0 = p.y;
|
|
|
|
|
|
|
|
p = path_base.getPointRatio(clamp(_prog + 0.001, 0., 0.9999), k, p);
|
|
|
|
x1 = p.x;
|
|
|
|
y1 = p.y;
|
|
|
|
|
|
|
|
_dir = point_direction(x0, y0, x1, y1);
|
|
|
|
_dir += _rot;
|
2024-06-22 05:12:08 +02:00
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
_scattered.paths[_ind] = {
|
2024-06-19 05:41:07 +02:00
|
|
|
path : path_scat,
|
|
|
|
index : k,
|
|
|
|
ori : ori,
|
|
|
|
pos : pos,
|
|
|
|
rot : _dir,
|
|
|
|
rotW : _rot,
|
|
|
|
sca : _sca,
|
|
|
|
trim : max(0, _trm),
|
|
|
|
flip : _flip,
|
|
|
|
}
|
|
|
|
|
|
|
|
var _segment_counts = array_clone(path_scat.getSegmentCount(k));
|
|
|
|
var _line_lengths = array_clone(path_scat.getLength(k));
|
|
|
|
var _accu_lengths = array_clone(path_scat.getAccuLength(k));
|
|
|
|
|
|
|
|
_line_lengths *= _sca;
|
|
|
|
|
|
|
|
for (var j = 0, m = array_length(_accu_lengths); j < m; j++)
|
|
|
|
_accu_lengths[j] *= _sca;
|
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
_scattered.segment_counts[_ind] = _segment_counts;
|
|
|
|
_scattered.line_lengths[_ind] = _line_lengths;
|
|
|
|
_scattered.accu_lengths[_ind] = _accu_lengths;
|
2024-06-19 05:41:07 +02:00
|
|
|
|
|
|
|
_ind++;
|
2024-06-17 13:12:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-17 09:02:36 +02:00
|
|
|
return _scattered;
|
2024-06-22 04:19:30 +02:00
|
|
|
}
|
2024-06-17 13:12:33 +02:00
|
|
|
|
2024-06-22 04:19:30 +02:00
|
|
|
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) {
|
2024-06-17 13:12:33 +02:00
|
|
|
var bbox = drawGetBbox(xx, yy, _s);
|
2024-06-22 04:19:30 +02:00
|
|
|
draw_sprite_bbox_uniform(s_node_path_scatter, 0, bbox);
|
|
|
|
}
|
2024-06-17 13:12:33 +02:00
|
|
|
}
|