2023-03-19 09:17:39 +01:00
|
|
|
function Node_Strand_Render(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
|
|
|
|
name = "Strand Render";
|
|
|
|
color = COLORS.node_blend_strand;
|
|
|
|
icon = THEME.strandSim;
|
|
|
|
use_cache = true;
|
|
|
|
|
|
|
|
inputs[| 0] = nodeValue("Dimension", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, def_surf_size2)
|
|
|
|
.setDisplay(VALUE_DISPLAY.vector);
|
|
|
|
|
|
|
|
inputs[| 1] = nodeValue("Strand", self, JUNCTION_CONNECT.input, VALUE_TYPE.strands, noone)
|
|
|
|
.setVisible(true, true);
|
|
|
|
|
|
|
|
inputs[| 2] = nodeValue("Thickness", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 1, 1 ])
|
|
|
|
.setDisplay(VALUE_DISPLAY.vector_range);
|
|
|
|
|
|
|
|
inputs[| 3] = nodeValue("Thickness over length", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11);
|
|
|
|
|
2023-05-28 20:00:51 +02:00
|
|
|
inputs[| 4] = nodeValue("Random color", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white));
|
2023-03-19 09:17:39 +01:00
|
|
|
|
2023-05-28 20:00:51 +02:00
|
|
|
inputs[| 5] = nodeValue("Color over length", self, JUNCTION_CONNECT.input, VALUE_TYPE.gradient, new gradientObject(c_white));
|
2023-03-19 09:17:39 +01:00
|
|
|
|
|
|
|
inputs[| 6] = nodeValue("Seed", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, irandom_range(10000, 99999));
|
|
|
|
|
|
|
|
inputs[| 7] = nodeValue("Child", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0, "Render extra strands between the real strands.");
|
|
|
|
|
|
|
|
outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
|
|
|
|
|
|
|
|
input_display_list = [ 6,
|
|
|
|
["Output", false], 0,
|
|
|
|
["Strand", false], 7, 1, 2, 3,
|
|
|
|
["Color", false], 4, 5,
|
|
|
|
];
|
|
|
|
|
|
|
|
insp2UpdateTooltip = "Clear cache";
|
|
|
|
insp2UpdateIcon = [ THEME.cache, 0, COLORS._main_icon ];
|
|
|
|
|
|
|
|
static onInspector2Update = function() { clearCache(); }
|
|
|
|
|
|
|
|
static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) {
|
|
|
|
var _str = inputs[| 1].getValue();
|
|
|
|
if(_str == noone) return;
|
|
|
|
if(!is_array(_str)) _str = [ _str ];
|
|
|
|
|
|
|
|
for( var i = 0; i < array_length(_str); i++ )
|
|
|
|
_str[i].draw(_x, _y, _s);
|
|
|
|
}
|
|
|
|
|
2023-07-06 19:49:16 +02:00
|
|
|
static update = function(frame = PROJECT.animator.current_frame) {
|
|
|
|
if(!PROJECT.animator.is_playing && recoverCache()) return;
|
2023-03-19 09:17:39 +01:00
|
|
|
|
|
|
|
var _dim = inputs[| 0].getValue();
|
|
|
|
var _str = inputs[| 1].getValue();
|
|
|
|
|
|
|
|
var _thk = inputs[| 2].getValue();
|
|
|
|
var _tln = inputs[| 3].getValue();
|
|
|
|
var _bld = inputs[| 4].getValue();
|
|
|
|
var _col = inputs[| 5].getValue();
|
|
|
|
var _sed = inputs[| 6].getValue();
|
|
|
|
var _chd = inputs[| 7].getValue();
|
|
|
|
|
|
|
|
var _surf = outputs[| 0].getValue();
|
|
|
|
_surf = surface_verify(_surf, _dim[0], _dim[1]);
|
|
|
|
outputs[| 0].setValue(_surf);
|
|
|
|
|
|
|
|
if(_str == noone) return;
|
|
|
|
if(!is_array(_str)) _str = [ _str ];
|
|
|
|
|
|
|
|
random_set_seed(_sed);
|
|
|
|
var _sedIndex = 0;
|
|
|
|
|
|
|
|
surface_set_target(_surf);
|
|
|
|
DRAW_CLEAR
|
|
|
|
var h0 = [], h1 = [];
|
|
|
|
|
|
|
|
for( var h = 0; h < array_length(_str); h++ ) {
|
|
|
|
var _strand = _str[h];
|
|
|
|
var hairs = _strand.hairs;
|
|
|
|
|
|
|
|
for( var i = 0; i < array_length(hairs); i++ ) {
|
|
|
|
var hair = hairs[i];
|
|
|
|
var os, ns, ot, nt;
|
|
|
|
|
|
|
|
var len = array_length(hair.points);
|
|
|
|
var bld = _bld.eval(random1D(_sed + _sedIndex)); _sedIndex++;
|
|
|
|
var clr = c_black;
|
|
|
|
|
|
|
|
for( var j = 0; j < len; j++ ) {
|
|
|
|
ns = hair.points[j];
|
|
|
|
nt = eval_curve_x(_tln, j / (len - 1));
|
|
|
|
nt *= random1D(_sed + _sedIndex, _thk[0], _thk[1]); _sedIndex++;
|
|
|
|
|
|
|
|
if(j) {
|
|
|
|
clr = _col.eval(j / (len - 1));
|
|
|
|
clr = colorMultiply(bld, clr);
|
|
|
|
draw_set_color(clr);
|
|
|
|
draw_line_width2(os.x, os.y, ns.x, ns.y, ot, nt, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
ot = nt;
|
|
|
|
os = ns;
|
|
|
|
|
|
|
|
h1[j] = [ nt, clr ];
|
|
|
|
}
|
|
|
|
|
|
|
|
if(_chd && (i > 0 || _strand.loop)) {
|
|
|
|
var hair0 = i == 0? hairs[array_length(hairs) - 1] : hairs[i - 1];
|
|
|
|
|
|
|
|
for( var j = 1; j < _chd + 1; j++ ) {
|
|
|
|
var lrp = j / (_chd + 1);
|
|
|
|
|
|
|
|
var ox, oy, nx, ny, ot, nt, oc, nc;
|
|
|
|
for( var k = 0; k < len; k++ ) {
|
|
|
|
var nx0 = hair0.points[k].x;
|
|
|
|
var ny0 = hair0.points[k].y;
|
|
|
|
|
|
|
|
var nx1 = hair.points[k].x;
|
|
|
|
var ny1 = hair.points[k].y;
|
|
|
|
|
|
|
|
nx = lerp(nx0, nx1, lrp);
|
|
|
|
ny = lerp(ny0, ny1, lrp);
|
|
|
|
|
|
|
|
if(k) {
|
|
|
|
ot = i == 0? h1[k][0] : h0[k][0];
|
|
|
|
nt = h1[k][0];
|
|
|
|
|
|
|
|
oc = i == 0? h1[k][1] : h0[k][1];
|
|
|
|
nc = h1[k][1];
|
|
|
|
|
|
|
|
draw_set_color(merge_color(oc, nc, lrp));
|
|
|
|
draw_line_width2(ox, oy, nx, ny, ot, nt, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
ox = nx;
|
|
|
|
oy = ny;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
h0 = array_clone(h1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
surface_reset_target();
|
|
|
|
cacheCurrentFrame(_surf);
|
|
|
|
}
|
|
|
|
}
|