Pixel-Composer/scripts/node_processor/node_processor.gml

260 lines
8.0 KiB
Plaintext
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
}
2023-03-02 07:59:14 +01:00
#macro PROCESSOR_OVERLAY_CHECK if(array_length(current_data) != ds_list_size(inputs)) return;
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_data = [];
2023-08-17 16:56:54 +02:00
all_inputs = [];
2023-01-01 02:06:02 +01:00
process_amount = 0;
2023-02-28 09:43:01 +01:00
process_length = [];
2023-07-08 20:29:23 +02:00
dimension_index = 0;
2022-01-13 05:24:03 +01:00
2022-11-18 03:20:31 +01:00
icon = THEME.node_processor;
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
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
2023-03-05 07:16:44 +01:00
static getSingleValue = function(_index, _arr = 0, output = false) {
var _l = output? outputs : inputs;
var _n = _l[| _index];
2022-12-27 13:30:02 +01:00
var _in = _n.getValue();
2022-12-27 04:00:50 +01:00
2023-02-28 09:43:01 +01:00
if(!_n.isArray()) return _in;
2023-06-13 14:42:06 +02:00
switch(attributes.array_process) {
2023-02-28 09:43:01 +01:00
case ARRAY_PROCESS.loop : _index = safe_mod(_arr, array_length(_in)); break;
case ARRAY_PROCESS.hold : _index = min(_arr, array_length(_in) - 1); break;
case ARRAY_PROCESS.expand : _index = floor(_arr / process_length[_index][1]) % process_length[_index][0]; break;
2023-03-05 07:16:44 +01:00
case ARRAY_PROCESS.expand_inv : _index = floor(_arr / process_length[ds_list_size(_l) - 1 - _index][1]) % process_length[_index][0]; break;
2023-02-28 09:43:01 +01:00
}
return array_safe_get(_in, _index);
2022-12-27 13:30:02 +01:00
}
static getDimension = function(arr = 0) {
if(dimension_index == -1) return [1, 1];
var _in = getSingleValue(dimension_index, arr);
2023-01-01 02:06:02 +01:00
if(inputs[| dimension_index].type == VALUE_TYPE.surface && is_surface(_in)) {
2022-12-27 13:30:02 +01:00
var ww = surface_get_width(_in);
var hh = surface_get_height(_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];
}
static preProcess = function(outIndex) {
2023-08-19 12:42:50 +02:00
var _out = outputs[| outIndex].getValue();
all_inputs = array_create(ds_list_size(inputs));
2022-12-18 03:20:38 +01:00
2023-08-17 16:56:54 +02:00
if(process_amount == 0) { #region render single data
2023-01-01 02:06:02 +01:00
if(outputs[| outIndex].type == VALUE_TYPE.d3object) //passing 3D vertex call
return _out;
2023-02-14 02:51:14 +01:00
if(is_array(_out) && outputs[| outIndex].type == VALUE_TYPE.surface) { //free surface if needed
for(var i = 1; i < array_length(_out); i++)
2022-12-27 04:00:50 +01:00
if(is_surface(_out[i])) surface_free(_out[i]);
}
2023-03-19 09:17:39 +01:00
if(outputs[| outIndex].type == VALUE_TYPE.surface && dimension_index > -1) { //resize surface
2022-12-27 13:30:02 +01:00
var surf = inputs_data[dimension_index];
var _sw = 1, _sh = 1;
2023-02-14 02:51:14 +01:00
if(inputs[| dimension_index].type == VALUE_TYPE.surface) {
if(is_surface(surf)) {
_sw = surface_get_width(surf);
_sh = surface_get_height(surf);
} else
return noone;
2022-12-27 13:30:02 +01:00
} else if(is_array(surf)) {
2023-03-07 14:29:47 +01:00
_sw = array_safe_get(surf, 0, 1);
_sh = array_safe_get(surf, 1, 1);
2022-12-27 13:30:02 +01:00
}
2023-03-19 09:17:39 +01:00
_out = surface_verify(_out, _sw, _sh, attrDepth());
2022-12-27 04:00:50 +01:00
}
current_data = inputs_data;
2023-02-14 02:51:14 +01:00
if(active_index > -1 && !inputs_data[active_index]) { // skip
if(inputs[| 0].type == VALUE_TYPE.surface)
return surface_clone(inputs_data[0], _out);
else
return inputs_data[0]
}
2023-08-19 12:42:50 +02:00
all_inputs = inputs_data;
2023-08-17 16:56:54 +02:00
var data = processData(_out, inputs_data, outIndex, 0); /// Process data
2023-03-21 03:01:53 +01:00
return data;
2023-08-17 16:56:54 +02:00
} #endregion
2023-01-01 02:06:02 +01:00
2023-08-17 16:56:54 +02:00
if(outputs[| outIndex].type == VALUE_TYPE.d3object) { #region passing 3D vertex call
2023-01-01 02:06:02 +01:00
if(is_array(_out)) _out = _out[0];
return array_create(process_amount, _out);
2023-08-17 16:56:54 +02:00
} #endregion
2022-12-27 04:00:50 +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);
2022-12-27 04:00:50 +01:00
2023-08-17 16:56:54 +02:00
var _data = array_create(ds_list_size(inputs));
for(var i = 0; i < ds_list_size(inputs); i++)
all_inputs[i] = array_create(process_amount);
#endregion
2022-12-27 04:00:50 +01:00
for(var l = 0; l < process_amount; l++) {
2023-08-17 16:56:54 +02:00
for(var i = 0; i < ds_list_size(inputs); i++) { #region input preparation
2022-12-27 04:00:50 +01:00
var _in = inputs_data[i];
2022-01-13 05:24:03 +01:00
2022-12-27 04:00:50 +01:00
if(!inputs[| i].isArray(_in)) {
_data[i] = inputs_data[i];
continue;
2022-01-13 05:24:03 +01:00
}
2022-12-27 04:00:50 +01:00
if(array_length(_in) == 0) {
_data[i] = 0;
continue;
2022-01-13 05:24:03 +01:00
}
2022-12-27 04:00:50 +01:00
var _index = 0;
2023-06-13 14:42:06 +02:00
switch(attributes.array_process) {
2023-02-28 09:43:01 +01:00
case ARRAY_PROCESS.loop : _index = safe_mod(l, array_length(_in)); break;
case ARRAY_PROCESS.hold : _index = min(l, array_length(_in) - 1); break;
case ARRAY_PROCESS.expand : _index = floor(l / process_length[i][1]) % process_length[i][0]; break;
case ARRAY_PROCESS.expand_inv : _index = floor(l / process_length[ds_list_size(inputs) - 1 - i][1]) % process_length[i][0]; break;
2022-11-22 14:25:39 +01:00
}
2023-08-17 16:56:54 +02:00
2022-12-27 04:00:50 +01:00
_data[i] = _in[_index];
2023-08-17 16:56:54 +02:00
all_inputs[i][l] = _data[i];
} #endregion
2022-12-27 04:00:50 +01:00
2023-08-17 16:56:54 +02:00
if(outputs[| outIndex].type == VALUE_TYPE.surface && dimension_index > -1) { #region output surface verification
2022-12-27 13:30:02 +01:00
var surf = _data[dimension_index];
var _sw = 1, _sh = 1;
2023-02-14 02:51:14 +01:00
if(inputs[| dimension_index].type == VALUE_TYPE.surface) {
if(is_surface(surf)) {
_sw = surface_get_width(surf);
_sh = surface_get_height(surf);
} else
return noone;
2022-12-27 13:30:02 +01:00
} else if(is_array(surf)) {
_sw = surf[0];
_sh = surf[1];
}
2023-03-19 09:17:39 +01:00
_out[l] = surface_verify(_out[l], _sw, _sh, attrDepth());
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
if(inputs[| 0].type == VALUE_TYPE.surface)
_out[l] = surface_clone(_data[0], _out[l]);
else
_out[l] = _data[0];
2023-03-21 03:01:53 +01:00
} else {
2023-08-17 16:56:54 +02:00
_out[l] = processData(_out[l], _data, outIndex, l); /// Process data
2023-03-21 03:01:53 +01:00
}
2022-01-13 05:24:03 +01:00
}
2022-12-27 04:00:50 +01:00
return _out;
2022-01-13 05:24:03 +01:00
}
2023-08-17 16:56:54 +02:00
static update = function(frame = PROJECT.animator.current_frame) { #region
2023-02-28 09:43:01 +01:00
process_amount = 0;
inputs_data = array_create(ds_list_size(inputs));
process_length = array_create(ds_list_size(inputs));
2022-01-13 05:24:03 +01:00
2022-12-27 04:00:50 +01:00
for(var i = 0; i < ds_list_size(inputs); i++) { //pre-collect current input data
2023-02-28 09:43:01 +01:00
var val = inputs[| i].getValue();
var amo = inputs[| i].arrayLength(val);
2022-12-27 04:00:50 +01:00
2023-02-28 09:43:01 +01:00
inputs_data[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;
case ARRAY_PROCESS.expand :
case ARRAY_PROCESS.expand_inv :
if(amo && process_amount == 0)
process_amount = 1;
process_amount *= max(1, amo);
break;
}
process_length[i] = [max(1, amo), process_amount];
}
var amoMax = process_amount;
2023-07-25 20:12:40 +02:00
for( var i = 0, n = array_length(process_length); i < n; i++ ) {
2023-02-28 09:43:01 +01:00
amoMax /= process_length[i][0];
process_length[i][1] = amoMax;
2022-12-27 04:00:50 +01:00
}
2022-01-13 05:24:03 +01:00
2023-05-28 20:00:51 +02:00
var val;
2023-05-03 21:42:17 +02:00
for(var i = 0; i < ds_list_size(outputs); i++) {
2023-05-28 20:00:51 +02:00
if(outputs[| i].process_array) {
val = preProcess(i);
if(val == undefined) continue;
} else
2023-08-17 16:56:54 +02:00
val = processData(noone, noone, i);
2023-05-03 21:42:17 +02:00
outputs[| i].setValue(val);
}
2023-08-17 16:56:54 +02:00
} #endregion
2023-02-28 09:43:01 +01:00
2023-08-17 16:56:54 +02:00
static processSerialize = function(_map) { #region
2023-06-13 14:42:06 +02:00
_map.array_process = attributes.array_process;
2023-08-17 16:56:54 +02:00
} #endregion
2023-02-28 09:43:01 +01:00
2023-08-17 16:56:54 +02:00
static processDeserialize = function() { #region
2023-06-13 14:42:06 +02:00
attributes.array_process = struct_try_get(load_map, "array_process", ARRAY_PROCESS.loop);
2023-08-17 16:56:54 +02:00
} #endregion
2023-07-08 20:29:23 +02:00
///////////////////// CACHE /////////////////////
2023-08-17 16:56:54 +02:00
static cacheCurrentFrameIndex = function(_frame, index) { #region
2023-07-08 20:29:23 +02:00
cacheArrayCheck();
if(PROJECT.animator.current_frame < 0) return;
if(PROJECT.animator.current_frame >= array_length(cached_output)) return;
var prev = cached_output[PROJECT.animator.current_frame];
surface_array_free(array_safe_get(prev, index));
cached_output[PROJECT.animator.current_frame][index] = surface_array_clone(_frame);
array_safe_set(cache_result, PROJECT.animator.current_frame, true);
return cached_output[PROJECT.animator.current_frame];
2023-08-17 16:56:54 +02:00
} #endregion
2023-07-08 20:29:23 +02:00
2023-08-17 16:56:54 +02:00
static getCacheFrameIndex = function(frame = PROJECT.animator.current_frame, index = 0) { #region
2023-07-08 20:29:23 +02:00
if(frame < 0) return false;
if(!cacheExist(frame)) return noone;
var surf = array_safe_get(cached_output, frame);
return array_safe_get(surf, index);
2023-08-17 16:56:54 +02:00
} #endregion
2022-01-13 05:24:03 +01:00
}