Pixel-Composer/scripts/node_processor/node_processor.gml

451 lines
13 KiB
Text
Raw Normal View History

2022-01-13 05:24:03 +01:00
enum ARRAY_PROCESS {
loop,
2023-02-28 09:43:01 +01:00
hold,
expand,
expand_inv,
2022-01-13 05:24:03 +01:00
}
2024-08-08 06:57:51 +02:00
#macro PROCESSOR_OVERLAY_CHECK if(array_length(current_data) != array_length(inputs)) return 0;
2023-03-02 07:59:14 +01:00
2023-02-28 09:43:01 +01:00
function Node_Processor(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
2023-06-13 14:42:06 +02:00
attributes.array_process = ARRAY_PROCESS.loop;
2022-12-27 13:30:02 +01:00
current_data = [];
inputs_is_array = [];
inputs_index = [];
2023-01-01 02:06:02 +01:00
dimension_index = 0;
2023-01-01 02:06:02 +01:00
process_amount = 0;
2023-02-28 09:43:01 +01:00
process_length = [];
process_running = [];
2023-10-06 11:51:11 +02:00
2023-10-10 07:12:42 +02:00
manage_atlas = true;
atlas_index = 0;
2022-01-13 05:24:03 +01:00
batch_output = true; //Run processData once with all outputs as array.
2024-06-06 09:54:13 +02:00
icon = THEME.node_processor_icon;
2022-01-13 05:24:03 +01:00
2023-03-19 09:17:39 +01:00
array_push(attributeEditors, "Array processor");
2023-07-14 20:34:35 +02:00
array_push(attributeEditors, [ "Array process type", function() { return attributes.array_process; },
2023-04-11 20:29:20 +02:00
new scrollBox([ "Loop", "Hold", "Expand", "Expand inverse" ],
function(val) {
2023-06-13 14:42:06 +02:00
attributes.array_process = val;
2023-04-11 20:29:20 +02:00
triggerRender();
}, false) ]);
2023-03-19 09:17:39 +01:00
2024-03-31 05:36:11 +02:00
static getInputData = function(index, def = 0) { INLINE return array_safe_get_fast(inputs_data, index, def); }
2023-08-24 11:59:05 +02:00
2023-10-03 11:27:36 +02:00
static processData_prebatch = function() {}
static processData_postbatch = function() {}
2023-08-17 16:56:54 +02:00
static processData = function(_outSurf, _data, _output_index, _array_index = 0) { return _outSurf; }
2022-01-13 05:24:03 +01:00
2024-06-28 11:54:13 +02:00
static getSingleValue = function(_index, _arr = preview_index, output = false) {
var _l = output? outputs : inputs;
if(_index < 0 || _index >= array_length(_l)) return 0;
2024-08-08 06:57:51 +02:00
var _n = _l[_index];
var _in = output? _n.getValue() : getInputData(_index);
2023-11-30 10:55:37 +01:00
if(!_n.isArray(_in)) return _in;
if(!is_array(_in)) return 0;
2023-02-28 09:43:01 +01:00
var _aIndex = _arr;
2023-11-23 02:32:26 +01:00
2023-06-13 14:42:06 +02:00
switch(attributes.array_process) {
case ARRAY_PROCESS.loop : _aIndex = safe_mod(_arr, process_length[_index]); break;
case ARRAY_PROCESS.hold : _aIndex = min(_arr, process_length[_index] - 1 ); break;
case ARRAY_PROCESS.expand : _aIndex = floor(_arr / process_running[_index]) % process_length[_index]; break;
case ARRAY_PROCESS.expand_inv : _aIndex = floor(_arr / process_running[array_length(_l) - 1 - _index]) % process_length[_index]; break;
2023-02-28 09:43:01 +01:00
}
2023-11-25 08:54:35 +01:00
2024-03-31 05:36:11 +02:00
return array_safe_get_fast(_in, _aIndex);
2024-06-28 11:54:13 +02:00
}
2022-12-27 13:30:02 +01:00
2024-06-28 11:54:13 +02:00
static getDimension = function(arr = 0) {
2024-04-11 05:51:13 +02:00
if(dimension_index == -1) return [ 1, 1 ];
2022-12-27 13:30:02 +01:00
var _ip = array_safe_get(inputs, dimension_index, noone);
if(_ip == noone) return [ 1, 1 ];
2022-12-27 13:30:02 +01:00
var _in = getSingleValue(dimension_index, arr);
if(_ip.type == VALUE_TYPE.surface && is_surface(_in)) {
2023-09-08 21:37:36 +02:00
var ww = surface_get_width_safe(_in);
var hh = surface_get_height_safe(_in);
2022-12-27 04:00:50 +01:00
return [ww, hh];
2022-01-13 05:24:03 +01:00
}
2022-12-27 13:30:02 +01:00
if(is_array(_in) && array_length(_in) == 2)
return _in;
2022-12-27 04:00:50 +01:00
return [1, 1];
2024-06-28 11:54:13 +02:00
}
2022-12-27 04:00:50 +01:00
2024-06-28 11:54:13 +02:00
static processDataArray = function(outIndex) {
2024-08-08 06:57:51 +02:00
var _output = outputs[outIndex];
var _out = _output.getValue();
2023-10-06 11:51:11 +02:00
var _atlas = false;
var _pAtl = noone;
2024-08-08 06:57:51 +02:00
var _data = [];
2024-11-15 09:39:23 +01:00
var _dep = attrDepth();
2022-12-18 03:20:38 +01:00
2024-08-07 11:48:39 +02:00
if(process_amount == 1) { // render single data
if(_output.type == VALUE_TYPE.d3object) //passing 3D vertex call
2023-01-01 02:06:02 +01:00
return _out;
2024-08-08 06:57:51 +02:00
_data = array_map(inputs, function(_in, i) /*=>*/ {return inputs_data[i]});
2023-10-06 11:51:11 +02:00
if(_output.type == VALUE_TYPE.surface) { // Surface preparation
if(manage_atlas) {
_pAtl = _data[atlas_index];
_atlas = is_instanceof(_pAtl, SurfaceAtlas);
if(_atlas) _data[atlas_index] = _pAtl.getSurface();
}
if(dimension_index > -1) {
var surf = _data[dimension_index];
2023-09-26 14:35:25 +02:00
var _sw = 1, _sh = 1;
2024-08-08 06:57:51 +02:00
if(inputs[dimension_index].type == VALUE_TYPE.surface) {
2023-09-26 14:35:25 +02:00
if(is_surface(surf)) {
_sw = surface_get_width_safe(surf);
_sh = surface_get_height_safe(surf);
} else
return noone;
2024-11-15 09:39:23 +01:00
2023-09-26 14:35:25 +02:00
} else if(is_array(surf)) {
2024-03-31 05:36:11 +02:00
_sw = array_safe_get_fast(surf, 0, 1);
_sh = array_safe_get_fast(surf, 1, 1);
2023-09-26 14:35:25 +02:00
}
if(is_instanceof(_out, SurfaceAtlas)) {
if(manage_atlas) {
surface_free_safe(_out.getSurface())
2024-11-15 09:39:23 +01:00
_out = surface_verify(_out.getSurface(), _sw, _sh, _dep);
}
2023-10-06 11:51:11 +02:00
} else
2024-11-15 09:39:23 +01:00
_out = surface_verify(_out, _sw, _sh, _dep);
2022-12-27 13:30:02 +01:00
}
2022-12-27 04:00:50 +01:00
}
2023-10-06 11:51:11 +02:00
current_data = _data;
2023-02-14 02:51:14 +01:00
2024-07-07 09:08:13 +02:00
if(active_index > -1 && !_data[active_index]) // skip
2024-08-08 06:57:51 +02:00
return inputs[0].type == VALUE_TYPE.surface? surface_clone(_data[0], _out) : _data[0];
2023-10-06 11:51:11 +02:00
var data = processData(_out, _data, outIndex, 0); // Process data
if(_output.type == VALUE_TYPE.surface) {
if(manage_atlas && _atlas && is_surface(data)) { // Convert back to atlas
var _atl = _pAtl.clone();
_atl.setSurface(data);
return _atl;
}
//data = surface_project_posterize(data);
2023-02-14 02:51:14 +01:00
}
2023-03-21 03:01:53 +01:00
return data;
2024-08-07 11:48:39 +02:00
}
2023-01-01 02:06:02 +01:00
2023-08-17 16:56:54 +02:00
#region ++++ array preparation ++++
if(!is_array(_out))
_out = array_create(process_amount);
else if(array_length(_out) != process_amount)
array_resize(_out, process_amount);
#endregion
2022-12-27 04:00:50 +01:00
for(var l = 0; l < process_amount; l++) {
2024-08-18 13:13:40 +02:00
for(var i = array_length(inputs) - 1; i >= 0; i--)
_data[i] = inputs_index[i][l] == -1? inputs_data[i] : inputs_data[i][inputs_index[i][l]];
2024-08-09 13:30:09 +02:00
2023-10-06 11:51:11 +02:00
if(_output.type == VALUE_TYPE.surface) { #region // Output surface verification
if(manage_atlas) {
_pAtl = _data[atlas_index];
_atlas = is_instanceof(_pAtl, SurfaceAtlas);
if(_atlas) _data[atlas_index] = _pAtl.getSurface();
2022-12-27 13:30:02 +01:00
}
2023-03-19 09:17:39 +01:00
2023-10-06 11:51:11 +02:00
if(dimension_index > -1) {
var surf = _data[dimension_index];
var _sw = 1, _sh = 1;
2024-08-08 06:57:51 +02:00
if(inputs[dimension_index].type == VALUE_TYPE.surface) {
2023-10-06 11:51:11 +02:00
if(is_surface(surf)) {
_sw = surface_get_width_safe(surf);
_sh = surface_get_height_safe(surf);
} else
return noone;
} else if(is_array(surf)) {
_sw = surf[0];
_sh = surf[1];
}
if(is_instanceof(_out[l], SurfaceAtlas)) {
if(manage_atlas) {
surface_free_safe(_out[l].surface.surface)
2024-11-15 09:39:23 +01:00
_out[l] = surface_verify(_out[l].getSurface(), _sw, _sh, _dep);
}
2023-10-06 11:51:11 +02:00
} else
2024-11-15 09:39:23 +01:00
_out[l] = surface_verify(_out[l], _sw, _sh, _dep);
2023-10-06 11:51:11 +02:00
}
2023-08-17 16:56:54 +02:00
} #endregion
2022-12-27 04:00:50 +01:00
2023-02-14 02:51:14 +01:00
if(l == 0 || l == preview_index)
2022-12-27 13:30:02 +01:00
current_data = _data;
2023-02-14 02:51:14 +01:00
if(active_index > -1 && !_data[active_index]) { // skip
2024-08-08 06:57:51 +02:00
if(!_atlas && inputs[0].type == VALUE_TYPE.surface)
2023-02-14 02:51:14 +01:00
_out[l] = surface_clone(_data[0], _out[l]);
else
_out[l] = _data[0];
2024-07-07 09:08:13 +02:00
2023-10-06 11:51:11 +02:00
} else {
_out[l] = processData(_out[l], _data, outIndex, l); // Process data
if(_output.type == VALUE_TYPE.surface) {
if(manage_atlas && _atlas && is_surface(_out[l])) { // Convert back to atlas
var _atl = _pAtl.clone();
_atl.setSurface(_out[l]);
_out[l] = _atl;
}
//data = surface_project_posterize(data);
2023-10-06 11:51:11 +02:00
}
}
2022-01-13 05:24:03 +01:00
}
2022-12-27 04:00:50 +01:00
return _out;
2024-06-28 11:54:13 +02:00
}
2022-01-13 05:24:03 +01:00
2024-06-28 11:54:13 +02:00
static processBatchOutput = function() {
2024-08-08 06:57:51 +02:00
var _is = array_length(inputs);
var _os = array_length(outputs);
var _dep = attrDepth();
var data;
var _out = array_create(_os);
2024-08-08 06:57:51 +02:00
for(var i = 0; i < _os; i++) _out[i] = outputs[i].getValue();
2024-07-07 09:08:13 +02:00
2024-08-08 06:57:51 +02:00
var _surfOut = outputs[0];
2024-07-07 09:08:13 +02:00
var _skip = active_index != -1 && !inputs_data[active_index];
if(process_amount == 1) {
2024-06-06 09:54:13 +02:00
current_data = inputs_data;
2024-07-07 09:08:13 +02:00
if(_skip) { // skip
2024-08-08 06:57:51 +02:00
var _skp = inputs[0].type == VALUE_TYPE.surface? surface_clone(inputs_data[0], _out[0]) : inputs_data[0];
2024-07-07 09:08:13 +02:00
_surfOut.setValue(_skp);
return;
}
if(dimension_index > -1) {
var _dim = getDimension();
2024-10-13 11:43:44 +02:00
for(var i = 0; i < _os; i++) {
2024-11-15 09:39:23 +01:00
if(outputs[i].type != VALUE_TYPE.surface) continue;
_out[i] = surface_verify(_out[i], _dim[0], _dim[1], _dep);
2024-10-13 11:43:44 +02:00
}
}
2024-06-06 09:54:13 +02:00
if(_os == 1) {
data = processData(_out[0], inputs_data, 0, 0);
2024-08-30 11:08:30 +02:00
if(data == noone) return;
2024-08-08 06:57:51 +02:00
outputs[0].setValue(data);
2024-06-06 09:54:13 +02:00
} else {
data = processData(_out, inputs_data, 0, 0);
2024-08-30 11:08:30 +02:00
if(data == noone) return;
2024-08-08 06:57:51 +02:00
for(var i = 0; i < _os; i++) outputs[i].setValue(data[i]);
}
2024-06-06 09:54:13 +02:00
return;
}
2024-06-06 09:54:13 +02:00
2024-07-07 09:08:13 +02:00
if(_skip) {
2024-06-06 09:54:13 +02:00
2024-08-08 06:57:51 +02:00
var _skp = inputs[0].type == VALUE_TYPE.surface? surface_array_clone(inputs_data[0]) : inputs_data[0];
2024-07-07 09:08:13 +02:00
_surfOut.setValue(_skp);
2024-06-06 09:54:13 +02:00
2024-07-07 09:08:13 +02:00
} else {
2024-06-06 09:54:13 +02:00
2024-07-07 09:08:13 +02:00
var _inputs = array_create(_is);
var _outputs = array_create(_os);
for( var l = 0; l < process_amount; l++ ) {
for(var i = 0; i < _is; i++)
_inputs[i] = inputs_index[i][l] == -1? inputs_data[i] : inputs_data[i][inputs_index[i][l]];
2024-07-07 09:08:13 +02:00
if(l == 0 || l == preview_index) current_data = _inputs;
2024-07-07 09:08:13 +02:00
var _outa = array_create(_os);
2024-11-15 09:39:23 +01:00
var _dim = getDimension(l);
2024-07-07 09:08:13 +02:00
for(var i = 0; i < _os; i++) {
_outa[i] = array_safe_get(_out[i], l);
2024-11-15 09:39:23 +01:00
if(dimension_index == -1) continue;
if(outputs[i].type != VALUE_TYPE.surface) continue;
_outa[i] = surface_verify(_outa[i], _dim[0], _dim[1], _dep);
2024-07-07 09:08:13 +02:00
}
if(_os == 1) {
data = processData(_outa[0], _inputs, 0, l);
_outputs[0][l] = data;
} else {
data = processData(_outa, _inputs, 0, l);
for(var i = 0; i < _os; i++) _outputs[i][l] = data[i];
}
}
2024-06-06 09:54:13 +02:00
2024-07-07 09:08:13 +02:00
for( var i = 0, n = _os; i < n; i++ )
2024-08-08 06:57:51 +02:00
outputs[i].setValue(_outputs[i]);
2024-07-07 09:08:13 +02:00
}
2024-06-06 09:54:13 +02:00
2024-06-28 11:54:13 +02:00
}
2024-06-28 11:54:13 +02:00
static processOutput = function() {
2024-08-08 06:57:51 +02:00
for(var i = 0; i < array_length(outputs); i++) {
var val = outputs[i].process_array? processDataArray(i) : processData(outputs[i].getValue(), noone, i);
2024-06-06 09:54:13 +02:00
if(val != undefined)
2024-08-08 06:57:51 +02:00
outputs[i].setValue(val);
}
2024-06-28 11:54:13 +02:00
}
2023-10-18 14:58:55 +02:00
static preGetInputs = function() {}
2024-06-28 11:54:13 +02:00
static getInputs = function() {
2023-10-18 14:58:55 +02:00
preGetInputs();
2024-08-18 13:13:40 +02:00
var _len = array_length(inputs);
process_amount = 1;
inputs_data = array_verify(inputs_data, _len);
inputs_is_array = array_verify(inputs_is_array, _len);
inputs_index = array_verify(inputs_index, _len);
process_length = array_verify(process_length, _len);
process_running = array_verify(process_running, _len);
2022-01-13 05:24:03 +01:00
2024-08-08 06:57:51 +02:00
array_foreach(inputs, function(_in, i) /*=>*/ {
2024-08-07 11:48:39 +02:00
var raw = _in.getValue();
2024-07-07 09:08:13 +02:00
var amo = _in.arrayLength(raw);
2023-11-26 13:16:38 +01:00
var val = raw;
2022-12-27 04:00:50 +01:00
2024-08-14 09:55:53 +02:00
_in.bypass_junc.setValue(val);
2024-07-07 09:08:13 +02:00
if(amo == 0) val = noone; //empty array
2023-11-26 13:16:38 +01:00
else if(amo == 1) val = raw[0]; //spread single array
inputs_is_array[i] = amo > 1;
2023-09-18 13:54:55 +02:00
amo = max(1, amo);
2024-08-06 12:39:22 +02:00
input_value_map[$ _in.internalName] = val;
inputs_data[i] = val; //setInputData(i, val);
2022-01-13 05:24:03 +01:00
2023-06-13 14:42:06 +02:00
switch(attributes.array_process) {
2023-02-28 09:43:01 +01:00
case ARRAY_PROCESS.loop :
case ARRAY_PROCESS.hold :
process_amount = max(process_amount, amo);
break;
2023-08-24 11:59:05 +02:00
2023-02-28 09:43:01 +01:00
case ARRAY_PROCESS.expand :
case ARRAY_PROCESS.expand_inv :
2023-09-18 13:54:55 +02:00
process_amount *= amo;
2023-02-28 09:43:01 +01:00
break;
}
process_length[i] = amo;
process_running[i] = process_amount;
2024-08-08 06:57:51 +02:00
});
2023-02-28 09:43:01 +01:00
var amoMax = process_amount;
for( var i = 0; i < _len; i++ ) {
amoMax /= process_length[i];
process_running[i] = amoMax;
inputs_index[i] = array_verify(inputs_index[i], process_amount);
2022-12-27 04:00:50 +01:00
}
2022-01-13 05:24:03 +01:00
for(var l = 0; l < process_amount; l++) // input preparation
for(var i = 0; i < _len; i++) {
inputs_index[i][l] = -1;
if(!inputs_is_array[i]) continue;
var _index = 0;
switch(attributes.array_process) {
case ARRAY_PROCESS.loop : _index = safe_mod(l, process_length[i]); break;
case ARRAY_PROCESS.hold : _index = min(l, process_length[i] - 1); break;
case ARRAY_PROCESS.expand : _index = floor(l / process_running[i]) % process_length[i]; break;
case ARRAY_PROCESS.expand_inv : _index = floor(l / process_running[array_length(inputs) - 1 - i]) % process_length[i]; break;
}
inputs_index[i][l] = _index;
}
2024-04-11 05:51:13 +02:00
// print($"{name}: {process_amount}");
2024-06-28 11:54:13 +02:00
}
2024-06-28 11:54:13 +02:00
static update = function(frame = CURRENT_FRAME) {
2023-10-03 11:27:36 +02:00
processData_prebatch();
2024-06-06 09:54:13 +02:00
if(batch_output) processBatchOutput();
else processOutput();
2024-06-06 09:54:13 +02:00
2023-10-03 11:27:36 +02:00
processData_postbatch();
postProcess();
2024-05-31 10:36:29 +02:00
postPostProcess();
2024-06-28 11:54:13 +02:00
}
2023-02-28 09:43:01 +01:00
static postProcess = function() {}
2024-05-31 10:36:29 +02:00
static postPostProcess = function() {}
2023-07-08 20:29:23 +02:00
///////////////////// CACHE /////////////////////
2024-11-12 03:39:57 +01:00
static cacheCurrentFrameIndex = function(_aindex, _surface) {
2023-07-08 20:29:23 +02:00
cacheArrayCheck();
2024-11-12 03:39:57 +01:00
var _frame = CURRENT_FRAME;
if(_frame < 0) return;
if(_frame >= array_length(cached_output)) return;
2023-07-08 20:29:23 +02:00
2024-11-12 03:39:57 +01:00
var _surfs = cached_output[_frame];
var _cache = array_safe_get_fast(_surfs, _aindex);
2023-07-08 20:29:23 +02:00
2024-11-12 03:39:57 +01:00
if(is_array(_surface)) {
surface_array_free(_cache);
_surfs[_aindex] = surface_array_clone(_surface);
} else if(surface_exists(_surface)) {
var _sw = surface_get_width(_surface);
var _sh = surface_get_height(_surface);
_cache = surface_verify(_cache, _sw, _sh);
surface_set_target(_cache);
DRAW_CLEAR BLEND_OVERRIDE
draw_surface(_surface, 0, 0);
surface_reset_target();
_surfs[_aindex] = _cache;
}
cached_output[_frame] = _surfs;
array_safe_set(cache_result, _frame, true);
2023-07-08 20:29:23 +02:00
2024-11-12 03:39:57 +01:00
return cached_output[_frame];
2024-06-28 11:54:13 +02:00
}
2023-07-08 20:29:23 +02:00
2024-11-12 03:39:57 +01:00
static getCacheFrameIndex = function(_aindex = 0, _frame = CURRENT_FRAME) {
if(_frame < 0) return false;
if(!cacheExist(_frame)) return noone;
2023-07-08 20:29:23 +02:00
2024-11-12 03:39:57 +01:00
var surf = array_safe_get_fast(cached_output, _frame);
return array_safe_get_fast(surf, _aindex, noone);
2024-06-28 11:54:13 +02:00
}
2022-01-13 05:24:03 +01:00
}