VFX fixes, group cache

This commit is contained in:
MakhamDev 2023-10-27 20:42:17 +07:00
parent 211615b8ab
commit b7918574b9
14 changed files with 224 additions and 103 deletions

View file

@ -1520,6 +1520,7 @@
{"name":"sh_draw_r16","order":10,"path":"shaders/sh_draw_r16/sh_draw_r16.yy",}, {"name":"sh_draw_r16","order":10,"path":"shaders/sh_draw_r16/sh_draw_r16.yy",},
{"name":"sh_channel_S","order":5,"path":"shaders/sh_channel_S/sh_channel_S.yy",}, {"name":"sh_channel_S","order":5,"path":"shaders/sh_channel_S/sh_channel_S.yy",},
{"name":"string_scale","order":4,"path":"scripts/string_scale/string_scale.yy",}, {"name":"string_scale","order":4,"path":"scripts/string_scale/string_scale.yy",},
{"name":"node_struct_set","order":3,"path":"scripts/node_struct_set/node_struct_set.yy",},
{"name":"s_node_cache","order":27,"path":"sprites/s_node_cache/s_node_cache.yy",}, {"name":"s_node_cache","order":27,"path":"sprites/s_node_cache/s_node_cache.yy",},
{"name":"node_repeat","order":9,"path":"scripts/node_repeat/node_repeat.yy",}, {"name":"node_repeat","order":9,"path":"scripts/node_repeat/node_repeat.yy",},
{"name":"draw_arc","order":22,"path":"scripts/draw_arc/draw_arc.yy",}, {"name":"draw_arc","order":22,"path":"scripts/draw_arc/draw_arc.yy",},

View file

@ -2257,6 +2257,7 @@
{"id":{"name":"sh_draw_r16","path":"shaders/sh_draw_r16/sh_draw_r16.yy",},}, {"id":{"name":"sh_draw_r16","path":"shaders/sh_draw_r16/sh_draw_r16.yy",},},
{"id":{"name":"sh_channel_S","path":"shaders/sh_channel_S/sh_channel_S.yy",},}, {"id":{"name":"sh_channel_S","path":"shaders/sh_channel_S/sh_channel_S.yy",},},
{"id":{"name":"string_scale","path":"scripts/string_scale/string_scale.yy",},}, {"id":{"name":"string_scale","path":"scripts/string_scale/string_scale.yy",},},
{"id":{"name":"node_struct_set","path":"scripts/node_struct_set/node_struct_set.yy",},},
{"id":{"name":"s_node_cache","path":"sprites/s_node_cache/s_node_cache.yy",},}, {"id":{"name":"s_node_cache","path":"sprites/s_node_cache/s_node_cache.yy",},},
{"id":{"name":"node_logic_operate","path":"scripts/node_logic_operate/node_logic_operate.yy",},}, {"id":{"name":"node_logic_operate","path":"scripts/node_logic_operate/node_logic_operate.yy",},},
{"id":{"name":"node_repeat","path":"scripts/node_repeat/node_repeat.yy",},}, {"id":{"name":"node_repeat","path":"scripts/node_repeat/node_repeat.yy",},},

View file

@ -16,16 +16,4 @@ function Node_Fluid(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
_to.node.updateForward(frame); _to.node.updateForward(frame);
} }
} }
static cachedPropagate = function() {
setRenderStatus(true);
for( var i = 0, n = ds_list_size(inputs); i < n; i++ ) {
var _input = inputs[| i];
if(_input.isLeaf()) continue;
if(!is_instanceof(_input.value_from.node, Node_Fluid)) continue;
_input.value_from.node.cachedPropagate();
}
}
} }

View file

@ -219,19 +219,38 @@ function array_shape(arr, first = true, isSurface = false) {
return (first? "" : " x ") + dim; return (first? "" : " x ") + dim;
} }
function array_spread(arr, _arr = []) { function array_depth(arr) {
if(!is_array(arr)) { gml_pragma("forceinline");
if(!is_array(arr)) return 0;
var d = 0;
var p = arr;
while(is_array(p) && !array_empty(p)) {
d++;
p = p[0];
}
return d;
}
function array_spread(arr, _arr = [], _minDepth = 0) {
gml_pragma("forceinline");
if(array_depth(arr) == _minDepth) {
array_push(_arr, arr); array_push(_arr, arr);
return _arr; return _arr;
} }
for( var i = 0, n = array_length(arr); i < n; i++ ) for( var i = 0, n = array_length(arr); i < n; i++ )
array_spread(arr[i], _arr); array_spread(arr[i], _arr, _minDepth);
return _arr; return _arr;
} }
function array_verify(arr, length) { function array_verify(arr, length) {
gml_pragma("forceinline");
if(!is_array(arr)) return array_create(length); if(!is_array(arr)) return array_create(length);
if(array_length(arr) == length) return arr; if(array_length(arr) == length) return arr;

View file

@ -73,9 +73,6 @@ function Node_VFX_Group(_x, _y, _group = noone) : Node_Collection(_x, _y, _group
allCached = true; allCached = true;
for( var i = 0, n = ds_list_size(nodes); i < n; i++ ) { for( var i = 0, n = ds_list_size(nodes); i < n; i++ ) {
var node = nodes[| i]; var node = nodes[| i];
if(!is_instanceof(node, Node_VFX_Renderer_Output) &&
!is_instanceof(node, Node_VFX_Renderer)) continue;
if(!node.recoverCache()) allCached = false; if(!node.recoverCache()) allCached = false;
} }

View file

@ -44,6 +44,9 @@ function Node_VFX_Variable(_x, _y, _group = noone) : Node(_x, _y, _group) constr
.setDisplay(VALUE_DISPLAY.vector) .setDisplay(VALUE_DISPLAY.vector)
.setVisible(false); .setVisible(false);
outputs[| 9] = nodeValue("Seed", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, 0 )
.setVisible(false);
static update = function(frame = CURRENT_FRAME) { static update = function(frame = CURRENT_FRAME) {
var parts = getInputData(0); var parts = getInputData(0);
if(!is_array(parts)) return; if(!is_array(parts)) return;
@ -64,7 +67,8 @@ function Node_VFX_Variable(_x, _y, _group = noone) : Node(_x, _y, _group) constr
if(outputs[| 5].visible) _val[5][i] = part.life; if(outputs[| 5].visible) _val[5][i] = part.life;
if(outputs[| 6].visible) _val[6][i] = part.life_total; if(outputs[| 6].visible) _val[6][i] = part.life_total;
if(outputs[| 7].visible) _val[7][i] = part.surf; if(outputs[| 7].visible) _val[7][i] = part.surf;
if(outputs[| 8].visible) _val[8][i] = [part.sx, part.sy]; if(outputs[| 8].visible) _val[8][i] = [part.speedx, part.speedy];
if(outputs[| 9].visible) _val[9][i] = part.seed;
} }
for( var i = 0; i < ds_list_size(outputs); i++ ) for( var i = 0; i < ds_list_size(outputs); i++ )

View file

@ -1387,6 +1387,18 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
arr[i]._clearCacheForward(); arr[i]._clearCacheForward();
} #endregion } #endregion
static cachedPropagate = function(_group = group) { #region
if(group != _group) return;
setRenderStatus(true);
for( var i = 0, n = ds_list_size(inputs); i < n; i++ ) {
var _input = inputs[| i];
if(_input.isLeaf()) continue;
_input.value_from.node.cachedPropagate(_group);
}
} #endregion
static clearInputCache = function() { #region static clearInputCache = function() { #region
for( var i = 0; i < ds_list_size(inputs); i++ ) { for( var i = 0; i < ds_list_size(inputs); i++ ) {
if(!is_instanceof(inputs[| i], NodeValue)) continue; if(!is_instanceof(inputs[| i], NodeValue)) continue;

View file

@ -63,8 +63,6 @@ function Node_Fluid_Group(_x, _y, _group = noone) : Node_Collection(_x, _y, _gro
static update = function() { static update = function() {
for( var i = 0, n = ds_list_size(nodes); i < n; i++ ) { for( var i = 0, n = ds_list_size(nodes); i < n; i++ ) {
var node = nodes[| i]; var node = nodes[| i];
if(!is_instanceof(node, Node_Fluid_Render)) continue;
if(node.cacheExist()) node.cachedPropagate(); if(node.cacheExist()) node.cachedPropagate();
} }

View file

@ -6,6 +6,9 @@ function Node_Path_Builder(_x, _y, _group = noone) : Node(_x, _y, _group) constr
length = 0; length = 0;
lengthAcc = []; lengthAcc = [];
lines = [];
connected = false;
inputs[| 0] = nodeValue("Point array", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, []) inputs[| 0] = nodeValue("Point array", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setVisible(true, true) .setVisible(true, true)
.setArrayDepth(2); .setArrayDepth(2);
@ -15,25 +18,22 @@ function Node_Path_Builder(_x, _y, _group = noone) : Node(_x, _y, _group) constr
outputs[| 0] = nodeValue("Path", self, JUNCTION_CONNECT.output, VALUE_TYPE.pathnode, self); outputs[| 0] = nodeValue("Path", self, JUNCTION_CONNECT.output, VALUE_TYPE.pathnode, self);
static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) { #region static drawOverlay = function(active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
var _lines = getInputData(0);
var _conn = getInputData(1);
draw_set_color(COLORS._main_accent); draw_set_color(COLORS._main_accent);
if(_conn) { if(connected) {
for( var i = 1, n = array_length(_lines); i < n; i++ ) { for( var i = 1, n = array_length(lines); i < n; i++ ) {
var p0 = _lines[i - 1]; var p0 = lines[i - 1];
var p1 = _lines[i - 0]; var p1 = lines[i - 0];
draw_line(_x + p0[0] * _s, _y + p0[1] * _s, draw_line(_x + p0[0] * _s, _y + p0[1] * _s,
_x + p1[0] * _s, _y + p1[1] * _s); _x + p1[0] * _s, _y + p1[1] * _s);
} }
} else { } else {
var len = floor(array_length(_lines) / 2) * 2; var len = floor(array_length(lines) / 2) * 2;
for( var i = 0; i < len; i += 2 ) { for( var i = 0; i < len; i += 2 ) {
var p0 = _lines[i + 0]; var p0 = lines[i + 0];
var p1 = _lines[i + 1]; var p1 = lines[i + 1];
draw_line(_x + p0[0] * _s, _y + p0[1] * _s, draw_line(_x + p0[0] * _s, _y + p0[1] * _s,
_x + p1[0] * _s, _y + p1[1] * _s); _x + p1[0] * _s, _y + p1[1] * _s);
@ -42,17 +42,11 @@ function Node_Path_Builder(_x, _y, _group = noone) : Node(_x, _y, _group) constr
} #endregion } #endregion
static getLineCount = function() { #region static getLineCount = function() { #region
var _lines = getInputData(0); return connected? 1 : floor(array_length(lines) / 2);
var _conn = getInputData(1);
return _conn? 1 : floor(array_length(_lines) / 2);
} #endregion } #endregion
static getSegmentCount = function() { #region static getSegmentCount = function() { #region
var _lines = getInputData(0); return connected? array_length(lines) - 1 : 1;
var _conn = getInputData(1);
return _conn? array_length(_lines) - 1 : 1;
} #endregion } #endregion
static getLength = function(index) { return is_array(length)? array_safe_get(length, index) : length; } static getLength = function(index) { return is_array(length)? array_safe_get(length, index) : length; }
@ -60,15 +54,13 @@ function Node_Path_Builder(_x, _y, _group = noone) : Node(_x, _y, _group) constr
static getAccuLength = function(index) { return array_safe_get(lengthAcc, index, []); } static getAccuLength = function(index) { return array_safe_get(lengthAcc, index, []); }
static getPointRatio = function(_rat, _ind = 0) { #region static getPointRatio = function(_rat, _ind = 0) { #region
var _lines = getInputData(0);
var _conn = getInputData(1);
var _p0, _p1; var _p0, _p1;
var _x, _y; var _x, _y;
if(_conn) { if(connected) {
var _st = _rat * (array_length(_lines) - 1); var _st = _rat * (array_length(lines) - 1);
_p0 = array_safe_get(_lines, floor(_st) + 0,, ARRAY_OVERFLOW._default); _p0 = array_safe_get(lines, floor(_st) + 0,, ARRAY_OVERFLOW._default);
_p1 = array_safe_get(_lines, floor(_st) + 1,, ARRAY_OVERFLOW._default); _p1 = array_safe_get(lines, floor(_st) + 1,, ARRAY_OVERFLOW._default);
if(!is_array(_p0)) return new __vec2(); if(!is_array(_p0)) return new __vec2();
if(!is_array(_p1)) return new __vec2(); if(!is_array(_p1)) return new __vec2();
@ -78,8 +70,8 @@ function Node_Path_Builder(_x, _y, _group = noone) : Node(_x, _y, _group) constr
return new __vec2( _x, _y ); return new __vec2( _x, _y );
} else { } else {
_p0 = array_safe_get(_lines, _ind * 2 + 0,, ARRAY_OVERFLOW._default); _p0 = array_safe_get(lines, _ind * 2 + 0,, ARRAY_OVERFLOW._default);
_p1 = array_safe_get(_lines, _ind * 2 + 1,, ARRAY_OVERFLOW._default); _p1 = array_safe_get(lines, _ind * 2 + 1,, ARRAY_OVERFLOW._default);
if(!is_array(_p0)) return new __vec2(); if(!is_array(_p0)) return new __vec2();
if(!is_array(_p1)) return new __vec2(); if(!is_array(_p1)) return new __vec2();
@ -92,32 +84,31 @@ function Node_Path_Builder(_x, _y, _group = noone) : Node(_x, _y, _group) constr
} #endregion } #endregion
static getPointDistance = function(_dist, ind = 0) { #region static getPointDistance = function(_dist, ind = 0) { #region
var _conn = getInputData(1); if(connected) return getPointRatio(_dist / length);
else return getPointRatio(_dist / length[ind], ind);
if(_conn) return getPointRatio(_dist / length);
else return getPointRatio(_dist / length[ind], ind);
} #endregion } #endregion
static getBoundary = function() { #region static getBoundary = function() { #region
var boundary = new BoundingBox(); var boundary = new BoundingBox();
var _lines = getInputData(0); var lines = getInputData(0);
for( var i = 0, n = array_length(_lines); i < n; i++ ) for( var i = 0, n = array_length(lines); i < n; i++ )
boundary.addPoint(_lines[i][0], _lines[i][1]); boundary.addPoint(lines[i][0], lines[i][1]);
return boundary; return boundary;
} #endregion } #endregion
static update = function() { #region static update = function() { #region
var _lines = getInputData(0); lines = [];
var _conn = getInputData(1); array_spread(getInputData(0), lines, 1);
connected = getInputData(1);
if(_conn) { if(connected) {
length = 0; length = 0;
lengthAcc = []; lengthAcc = [];
for( var i = 1, n = array_length(_lines); i < n; i++ ) { for( var i = 1, n = array_length(lines); i < n; i++ ) {
var p0 = _lines[i - 1]; var p0 = lines[i - 1];
var p1 = _lines[i - 0]; var p1 = lines[i - 0];
var dist = point_distance(p0[0], p0[1], p1[0], p1[1]); var dist = point_distance(p0[0], p0[1], p1[0], p1[1]);
@ -125,16 +116,29 @@ function Node_Path_Builder(_x, _y, _group = noone) : Node(_x, _y, _group) constr
array_push(lengthAcc, length); array_push(lengthAcc, length);
} }
} else { } else {
length = []; length = [];
lengthAcc = []; lengthAcc = [];
var len = floor(array_length(_lines) / 2) * 2; var len = floor(array_length(lines) / 2) * 2;
for( var i = 0; i < len; i += 2 ) { for( var i = 0; i < len; i += 2 ) {
var p0 = _lines[i + 0]; var p0 = lines[i + 0];
var p1 = _lines[i + 1]; var p1 = lines[i + 1];
var dist = point_distance(p0[0], p0[1], p1[0], p1[1]); var p0x = array_safe_get(p0, 0);
var p0y = array_safe_get(p0, 1);
var p1x = array_safe_get(p1, 0);
var p1y = array_safe_get(p1, 1);
p0x = is_real(p0x)? p0x : 0;
p0y = is_real(p0y)? p0y : 0;
p1x = is_real(p1x)? p1x : 0;
p1y = is_real(p1y)? p1y : 0;
lines[i + 0] = [ p0x, p0y ];
lines[i + 1] = [ p1x, p1y ];
var dist = point_distance(p0x, p0y, p1x, p1y);
array_push(length, dist); array_push(length, dist);
array_push(lengthAcc, [ dist ]); array_push(lengthAcc, [ dist ]);

View file

@ -606,6 +606,7 @@ function NodeObject(_name, _spr, _node, _create, tags = []) constructor { #regio
ds_list_add(values, "Struct"); ds_list_add(values, "Struct");
addNodeObject(values, "Struct", s_node_struct, "Node_Struct", [1, Node_Struct]); addNodeObject(values, "Struct", s_node_struct, "Node_Struct", [1, Node_Struct]);
addNodeObject(values, "Struct Get", s_node_struct_get, "Node_Struct_Get", [1, Node_Struct_Get]); addNodeObject(values, "Struct Get", s_node_struct_get, "Node_Struct_Get", [1, Node_Struct_Get]);
//addNodeObject(values, "Struct Set", s_node_struct_get, "Node_Struct_Set", [1, Node_Struct_Set]);
addNodeObject(values, "Parse JSON", s_node_json_parse, "Node_Struct_JSON_Parse", [1, Node_Struct_JSON_Parse]).setVersion(1145); addNodeObject(values, "Parse JSON", s_node_json_parse, "Node_Struct_JSON_Parse", [1, Node_Struct_JSON_Parse]).setVersion(1145);
ds_list_add(values, "Mesh"); ds_list_add(values, "Mesh");

View file

@ -11,54 +11,72 @@ function Node_Struct_Get(_x, _y, _group = noone) : Node(_x, _y, _group) construc
outputs[| 0] = nodeValue("Struct", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, {}); outputs[| 0] = nodeValue("Struct", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, {});
static update = function() { static getStructValue = function(str, keys) { #region
var _pnt = str, val = 0;
if(!is_struct(_pnt)) return [ VALUE_TYPE.any, val ];
for( var j = 0; j < array_length(keys); j++ ) {
var k = keys[j];
if(!variable_struct_exists(_pnt, k))
return [ VALUE_TYPE.float, 0 ];
val = variable_struct_get(_pnt, k);
if(j == array_length(keys) - 1) {
if(is_struct(val)) {
if(is_instanceof(val, Surface))
return [ VALUE_TYPE.surface, val.get() ];
else if(is_instanceof(val, Buffer))
return [ VALUE_TYPE.buffer, val.buffer ];
else
return [ VALUE_TYPE.struct, val ];
} else if(is_array(val) && array_length(val))
return [ is_string(val[0])? VALUE_TYPE.text : VALUE_TYPE.float, val ];
else
return [ is_string(val)? VALUE_TYPE.text : VALUE_TYPE.float, val ];
}
if(is_struct(val)) _pnt = val;
else break;
}
return [ VALUE_TYPE.any, val ];
} #endregion
static update = function() { #region
var str = getInputData(0); var str = getInputData(0);
var key = getInputData(1); var key = getInputData(1);
var keys = string_splice(key, "."); var keys = string_splice(key, ".");
var _str = str;
var out = outputs[| 0]; if(is_array(str)) {
var typ = VALUE_TYPE.any;
var val = array_create(array_length(str));
for( var i = 0, n = array_length(str); i < n; i++ ) {
var _str = str[i];
var _v = getStructValue(_str, keys);
typ = _v[0];
val[i] = _v[1];
}
outputs[| 0].setType(typ);
outputs[| 0].setValue(val);
} else {
var val = getStructValue(str, keys);
for( var j = 0; j < array_length(keys); j++ ) { outputs[| 0].setType(val[0]);
var k = keys[j]; outputs[| 0].setValue(val[1]);
if(!variable_struct_exists(_str, k)) {
out.setValue(0);
out.setType(VALUE_TYPE.float);
break;
}
var val = variable_struct_get(_str, k);
if(j == array_length(keys) - 1) {
if(is_struct(val)) {
if(is_instanceof(val, Surface)) {
out.setType(VALUE_TYPE.surface);
val = val.get();
} else if(is_instanceof(val, Buffer)) {
out.setType(VALUE_TYPE.buffer);
val = val.buffer;
} else
out.setType(VALUE_TYPE.struct);
} else if(is_array(val) && array_length(val))
out.setType(is_string(val[0])? VALUE_TYPE.text : VALUE_TYPE.float);
else
out.setType(is_string(val)? VALUE_TYPE.text : VALUE_TYPE.float);
out.setValue(val);
}
if(is_struct(val)) _str = val;
else break;
} }
} } #endregion
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) { #region
var bbox = drawGetBbox(xx, yy, _s); var bbox = drawGetBbox(xx, yy, _s);
var str = getInputData(1); var str = getInputData(1);
draw_set_text(f_h5, fa_center, fa_center, COLORS._main_text); draw_set_text(f_h5, fa_center, fa_center, COLORS._main_text);
var ss = string_scale(str, bbox.w, bbox.h); var ss = string_scale(str, bbox.w, bbox.h);
draw_text_transformed(bbox.xc, bbox.yc, str, ss, ss, 0); draw_text_transformed(bbox.xc, bbox.yc, str, ss, ss, 0);
} } #endregion
} }

View file

@ -0,0 +1,66 @@
function Node_Struct_Set(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Struct Set";
previewable = false;
w = 96;
inputs[| 0] = nodeValue("Struct", self, JUNCTION_CONNECT.input, VALUE_TYPE.struct, {})
.setVisible(true, true);
inputs[| 1] = nodeValue("Key", self, JUNCTION_CONNECT.input, VALUE_TYPE.text, "");
inputs[| 2] = nodeValue("Value", self, JUNCTION_CONNECT.input, VALUE_TYPE.any, 0);
outputs[| 0] = nodeValue("Struct", self, JUNCTION_CONNECT.output, VALUE_TYPE.struct, {});
static update = function() {
var str = getInputData(0);
var key = getInputData(1);
var val = getInputData(2);
var keys = string_splice(key, ".");
var _str = str;
var out = outputs[| 0];
for( var j = 0; j < array_length(keys); j++ ) {
var k = keys[j];
if(!variable_struct_exists(_str, k)) {
out.setType(VALUE_TYPE.float);
break;
}
var val = variable_struct_get(_str, k);
if(j == array_length(keys) - 1) {
if(is_struct(val)) {
if(is_instanceof(val, Surface)) {
out.setType(VALUE_TYPE.surface);
val = val.get();
} else if(is_instanceof(val, Buffer)) {
out.setType(VALUE_TYPE.buffer);
val = val.buffer;
} else
out.setType(VALUE_TYPE.struct);
} else if(is_array(val) && array_length(val))
out.setType(is_string(val[0])? VALUE_TYPE.text : VALUE_TYPE.float);
else
out.setType(is_string(val)? VALUE_TYPE.text : VALUE_TYPE.float);
out.setValue(val);
}
if(is_struct(val)) _str = val;
else break;
}
}
static onDrawNode = function(xx, yy, _mx, _my, _s, _hover, _focus) {
var bbox = drawGetBbox(xx, yy, _s);
var str = getInputData(1);
draw_set_text(f_h5, fa_center, fa_center, COLORS._main_text);
var ss = string_scale(str, bbox.w, bbox.h);
draw_text_transformed(bbox.xc, bbox.yc, str, ss, ss, 0);
}
}

View file

@ -0,0 +1,11 @@
{
"resourceType": "GMScript",
"resourceVersion": "1.0",
"name": "node_struct_set",
"isCompatibility": false,
"isDnD": false,
"parent": {
"name": "struct",
"path": "folders/nodes/data/value/struct.yy",
},
}

View file

@ -288,8 +288,9 @@ function value_type_directional(f, t) { #region
if(f == VALUE_TYPE.strands && t == VALUE_TYPE.pathnode ) return true; if(f == VALUE_TYPE.strands && t == VALUE_TYPE.pathnode ) return true;
if(f == VALUE_TYPE.color && t == VALUE_TYPE.struct ) return true; if(f == VALUE_TYPE.color && t == VALUE_TYPE.struct ) return true;
if(f == VALUE_TYPE.mesh && t == VALUE_TYPE.struct ) return true; if(f == VALUE_TYPE.mesh && t == VALUE_TYPE.struct ) return true;
if(f == VALUE_TYPE.particle && t == VALUE_TYPE.struct ) return true;
if(f == VALUE_TYPE.surface && t == VALUE_TYPE.d3Material ) return true; if(f == VALUE_TYPE.surface && t == VALUE_TYPE.d3Material ) return true;