This commit is contained in:
Tanasart 2024-04-27 10:10:20 +07:00
parent 65af445712
commit 3b4fc55d72
23 changed files with 1818 additions and 48 deletions

View file

@ -1,4 +1,4 @@
// 2024-04-21 14:35:38
// 2024-04-27 08:27:13
#event properties (no comments/etc. here are saved)
parent_index = _p_dialog;
uses_physics = false;
@ -189,8 +189,10 @@ if !target exit;
var by = dialog_y + ui(18);
if(buttonInstant(THEME.button_hide, bx, by, bw, bh, mouse_ui, sFOCUS, sHOVER, __txt("Add") + "...", THEME.add,, COLORS._main_value_positive) == 2) {
var path = get_open_filenames_compat("image|*.png;*.jpg", "");
key_release();
if(path != "") {
var paths = paths_to_array(path);
var arr = target.getInputData(0);

View file

@ -1,4 +1,4 @@
// 2024-04-21 14:35:31
// 2024-04-27 08:27:13
#event properties (no comments/etc. here are saved)
parent_index = _p_dialog;
uses_physics = false;
@ -189,8 +189,10 @@ if !target exit;
var by = dialog_y + ui(18);
if(buttonInstant(THEME.button_hide, bx, by, bw, bh, mouse_ui, sFOCUS, sHOVER, __txt("Add") + "...", THEME.add,, COLORS._main_value_positive) == 2) {
var path = get_open_filenames_compat("image|*.png;*.jpg", "");
key_release();
if(path != "") {
var paths = paths_to_array(path);
var arr = target.getInputData(0);

View file

@ -1,4 +1,4 @@
// 2024-04-25 15:00:56
// 2024-04-27 09:25:48
#region save
globalvar LOADING, CLONING, CLONING_GROUP;
globalvar CONNECTION_CONFLICT, LOADING_VERSION;

View file

@ -1,4 +1,4 @@
// 2024-04-18 12:08:21
// 2024-04-27 09:05:38
#region save
globalvar LOADING, CLONING, CLONING_GROUP;
globalvar CONNECTION_CONFLICT, LOADING_VERSION;
@ -39,8 +39,8 @@
LATEST_VERSION = 11600;
VERSION = 11700;
SAVE_VERSION = 11690;
VERSION_STRING = "1.17.rc3";
BUILD_NUMBER = 11700;
VERSION_STRING = "1.17.rc4";
BUILD_NUMBER = 11704;
globalvar HOTKEYS, HOTKEY_CONTEXT;
HOTKEYS = ds_map_create();
@ -200,7 +200,7 @@
#region debug
global.FLAG = {};
global.FLAG.render = 0;
global.FLAG.render = 1;
global.FLAG.renderTime = false;
global.FLAG.keyframe_override = true;
global.FLAG.wav_import = true;

View file

@ -0,0 +1,64 @@
// 2024-04-27 10:05:49
function Node_Atlas_Get(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Atlas Get";
previewable = true;
inputs[| 0] = nodeValue("Atlas", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone)
.setVisible(true, true);
outputs[| 0] = nodeValue("Surface", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, [])
.setArrayDepth(1);
outputs[| 1] = nodeValue("Position", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [])
.setDisplay(VALUE_DISPLAY.vector)
.setArrayDepth(1);
outputs[| 2] = nodeValue("Rotation", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [])
.setArrayDepth(1);
outputs[| 3] = nodeValue("Scale", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [])
.setDisplay(VALUE_DISPLAY.vector)
.setArrayDepth(1);
outputs[| 4] = nodeValue("Blend", self, JUNCTION_CONNECT.output, VALUE_TYPE.color, [])
.setArrayDepth(1);
outputs[| 5] = nodeValue("Alpha", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [])
.setArrayDepth(1);
static update = function(frame = CURRENT_FRAME) {
var atl = getInputData(0);
if(atl == noone) return;
if(!is_array(atl)) atl = [ atl ];
if(array_empty(atl)) return;
var n = array_length(atl);
var surf = array_create(n);
var posi = array_create(n);
var rota = array_create(n);
var scal = array_create(n);
var blns = array_create(n);
var alph = array_create(n);
for( var i = 0; i < n; i++ ) {
var _at = atl[i];
if(!is_instanceof(_at, SurfaceAtlas)) continue;
surf[i] = _at.getSurface();
posi[i] = [ _at.x, _at.y ];
rota[i] = _at.rotation;
scal[i] = [ _at.sx, _at.sy ];
blns[i] = _at.blend;
alph[i] = _at.alpha;
}
outputs[| 0].setValue(surf);
outputs[| 1].setValue(posi);
outputs[| 2].setValue(rota);
outputs[| 3].setValue(scal);
outputs[| 4].setValue(blns);
outputs[| 5].setValue(alph);
}
}

View file

@ -0,0 +1,64 @@
// 2024-04-27 10:03:11
function Node_Atlas_Get(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Atlas Get";
previewable = true;
inputs[| 0] = nodeValue("Atlas", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone)
.setVisible(true, true);
outputs[| 0] = nodeValue("Surface", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, [])
.setArrayDepth(1);
outputs[| 1] = nodeValue("Position", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [ 0, 0 ])
.setDisplay(VALUE_DISPLAY.vector)
.setArrayDepth(1);
outputs[| 2] = nodeValue("Rotation", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [])
.setArrayDepth(1);
outputs[| 3] = nodeValue("Scale", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [ 0, 0 ])
.setDisplay(VALUE_DISPLAY.vector)
.setArrayDepth(1);
outputs[| 4] = nodeValue("Blend", self, JUNCTION_CONNECT.output, VALUE_TYPE.color, [])
.setArrayDepth(1);
outputs[| 5] = nodeValue("Alpha", self, JUNCTION_CONNECT.output, VALUE_TYPE.float, [])
.setArrayDepth(1);
static update = function(frame = CURRENT_FRAME) {
var atl = getInputData(0);
if(atl == noone) return;
if(!is_array(atl)) atl = [ atl ];
if(array_empty(atl)) return;
var n = array_length(atl);
var surf = array_create(n);
var posi = array_create(n);
var rota = array_create(n);
var scal = array_create(n);
var blns = array_create(n);
var alph = array_create(n);
for( var i = 0; i < n; i++ ) {
var _at = atl[i];
if(!is_instanceof(_at, SurfaceAtlas)) continue;
surf[i] = _at.getSurface();
posi[i] = [ _at.x, _at.y ];
rota[i] = _at.rotation;
scal[i] = [ _at.sx, _at.sy ];
blns[i] = _at.blend;
alph[i] = _at.alpha;
}
outputs[| 0].setValue(surf);
outputs[| 1].setValue(posi);
outputs[| 2].setValue(rota);
outputs[| 3].setValue(scal);
outputs[| 4].setValue(blns);
outputs[| 5].setValue(alph);
}
}

View file

@ -0,0 +1,81 @@
// 2024-04-27 10:02:58
function Node_Atlas_Set(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Atlas Set";
previewable = true;
inputs[| 0] = nodeValue("Atlas", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone)
.setVisible(true, true);
inputs[| 1] = nodeValue("Surface", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, [])
.setArrayDepth(1);
inputs[| 2] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ])
.setDisplay(VALUE_DISPLAY.vector)
.setArrayDepth(1);
inputs[| 3] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setArrayDepth(1);
inputs[| 4] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ])
.setDisplay(VALUE_DISPLAY.vector)
.setArrayDepth(1);
inputs[| 5] = nodeValue("Blend", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, [])
.setArrayDepth(1);
inputs[| 6] = nodeValue("Alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setArrayDepth(1);
outputs[| 0] = nodeValue("Atlas", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
static update = function(frame = CURRENT_FRAME) {
var atl = getInputData(0);
if(atl == noone) return;
if(!is_array(atl)) atl = [ atl ];
if(array_empty(atl)) return;
var surf = getInputData(1);
var posi = getInputData(2);
var rota = getInputData(3);
var scal = getInputData(4);
var blns = getInputData(5);
var alph = getInputData(6);
var use = array_create(7);
for( var i = 1; i < 7; i++ ) use[i] = inputs[| i].value_from != noone;
var n = array_length(atl);
var natl = array_create(n);
for( var i = 0; i < n; i++ ) {
var _at = atl[i];
if(!is_instanceof(_at, SurfaceAtlas)) continue;
natl[i] = _at.clone();
if(use[1]) natl[i].setSurface(array_safe_get_fast(surf, i));
if(use[2]) {
var pos = array_safe_get_fast(posi, i);
natl[i].x = array_safe_get_fast(pos, 0);
natl[i].y = array_safe_get_fast(pos, 1);
}
if(use[3]) natl[i].rotation = array_safe_get_fast(rota, i);
if(use[4]) {
var sca = array_safe_get_fast(scal, i);
natl[i].sx = array_safe_get_fast(sca, 0, 1);
natl[i].sy = array_safe_get_fast(sca, 1, 1);
}
if(use[5]) natl[i].blend = array_safe_get_fast(blns, i);
if(use[6]) natl[i].alpha = array_safe_get_fast(alph, i);
}
outputs[| 0].setValue(natl);
}
}

View file

@ -0,0 +1,81 @@
// 2024-04-27 10:00:54
function Node_Atlas_Set(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Atlas Set";
previewable = true;
inputs[| 0] = nodeValue("Atlas", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone)
.setVisible(true, true);
inputs[| 1] = nodeValue("Surface", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, [])
.setArrayDepth(1);
inputs[| 2] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setDisplay(VALUE_DISPLAY.vector, 2)
.setArrayDepth(1);
inputs[| 3] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setArrayDepth(1);
inputs[| 4] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setDisplay(VALUE_DISPLAY.vector, 2)
.setArrayDepth(1);
inputs[| 5] = nodeValue("Blend", self, JUNCTION_CONNECT.input, VALUE_TYPE.color, [])
.setArrayDepth(1);
inputs[| 6] = nodeValue("Alpha", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setArrayDepth(1);
outputs[| 0] = nodeValue("Atlas", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone);
static update = function(frame = CURRENT_FRAME) {
var atl = getInputData(0);
if(atl == noone) return;
if(!is_array(atl)) atl = [ atl ];
if(array_empty(atl)) return;
var surf = getInputData(1);
var posi = getInputData(2);
var rota = getInputData(3);
var scal = getInputData(4);
var blns = getInputData(5);
var alph = getInputData(6);
var use = array_create(7);
for( var i = 1; i < 7; i++ ) use[i] = inputs[| i].value_from != noone;
var n = array_length(atl);
var natl = array_create(n);
for( var i = 0; i < n; i++ ) {
var _at = atl[i];
if(!is_instanceof(_at, SurfaceAtlas)) continue;
natl[i] = _at.clone();
if(use[1]) natl[i].setSurface(array_safe_get_fast(surf, i));
if(use[2]) {
var pos = array_safe_get_fast(posi, i);
natl[i].x = array_safe_get_fast(pos, 0);
natl[i].y = array_safe_get_fast(pos, 1);
}
if(use[3]) natl[i].rotation = array_safe_get_fast(rota, i);
if(use[4]) {
var sca = array_safe_get_fast(scal, i);
natl[i].sx = array_safe_get_fast(sca, 0, 1);
natl[i].sy = array_safe_get_fast(sca, 1, 1);
}
if(use[5]) natl[i].blend = array_safe_get_fast(blns, i);
if(use[6]) natl[i].alpha = array_safe_get_fast(alph, i);
}
outputs[| 0].setValue(natl);
}
}

View file

@ -0,0 +1,168 @@
// 2024-04-27 09:43:53
function Node_Iterate_Sort_Inline(_x, _y, _group = noone) : Node_Collection_Inline(_x, _y, _group) constructor {
name = "Sort Array";
color = COLORS.node_blend_loop;
is_root = false;
topoList = ds_list_create();
input_node = noone;
output_node = noone;
toSort = true;
input_node_type = Node_Iterator_Sort_Inline_Input;
output_node_type = Node_Iterator_Sort_Inline_Output;
iterated = 0;
if(!LOADING && !APPENDING) { #region
var input = nodeBuild("Node_Iterator_Sort_Inline_Input", x, y);
var output = nodeBuild("Node_Iterator_Sort_Inline_Output", x + 256, y);
addNode(input);
addNode(output);
input_node = input;
output_node = output;
input_node.loop = self;
output_node.loop = self;
if(CLONING && is_instanceof(CLONING_GROUP, Node_Iterate_Sort_Inline)) {
APPEND_MAP[? CLONING_GROUP.input_node.node_id] = input;
APPEND_MAP[? CLONING_GROUP.output_node.node_id] = output;
ds_list_add(APPEND_LIST, input, output);
}
} #endregion
static isActiveDynamic = function(frame = CURRENT_FRAME) { #region
for( var i = 0, n = ds_list_size(nodes); i < n; i++ )
if(nodes[| i].isActiveDynamic(frame)) return true;
return false;
} #endregion
static getNextNodes = function() { #region
return output_node.getNextNodes();
} #endregion
static refreshMember = function() { #region
ds_list_clear(nodes);
for( var i = 0, n = array_length(attributes.members); i < n; i++ ) {
if(!ds_map_exists(PROJECT.nodeMap, attributes.members[i])) {
print($"Node not found {attributes.members[i]}");
continue;
}
var _node = PROJECT.nodeMap[? attributes.members[i]];
_node.inline_context = self;
ds_list_add(nodes, _node);
if(is_instanceof(_node, Node_Iterator_Sort_Inline_Input)) {
input_node = _node;
input_node.loop = self;
}
if(is_instanceof(_node, Node_Iterator_Sort_Inline_Output)) {
output_node = _node;
output_node.loop = self;
}
}
if(input_node == noone || output_node == noone) {
if(input_node) input_node.destroy();
if(output_node) output_node.destroy();
destroy();
}
} #endregion
static update = function(frame = CURRENT_FRAME) { #region
if(input_node == noone || output_node == noone) {
if(input_node) input_node.destroy();
if(output_node) output_node.destroy();
destroy();
return;
}
if(IS_FIRST_FRAME) toSort = true;
if(toSort) NodeListSort(topoList, nodes);
toSort = false;
input_node.startSort = true;
//sortArray();
} #endregion
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static swap = function(arr, a, b) { #region
var temp = arr[a];
arr[@ a] = arr[b];
arr[@ b] = temp;
} #endregion
static compareValue = function(val1, val2) { #region
input_node.outputs[| 0].setValue(val1,,, false);
input_node.outputs[| 1].setValue(val2,,, false);
resetRender(true);
RenderList(topoList);
var res = output_node.inputs[| 0].getValue();
//print($"Comparing value {val1}, {val2} > [{res}]");
return res;
} #endregion
static partition = function(arr, low, high) { #region
var pv = arr[high];
var i = low - 1;
for(var j = low; j < high; j++) {
if(compareValue(arr[j], pv)) continue;
i++;
swap(arr, i, j);
}
swap(arr, i + 1, high);
return i + 1;
} #endregion
static quickSort = function(arr, low, high) { #region
if(low >= high) return;
var p = partition(arr, low, high);
quickSort(arr, low, p - 1);
quickSort(arr, p + 1, high);
} #endregion
static sortArray = function() { #region
iterated = 0;
loop_start_time = get_timer();
var _frj = input_node.inputs[| 0].value_from;
var type = _frj == noone? VALUE_TYPE.any : _frj.type;
input_node.inputs[| 0].setType(type);
input_node.outputs[| 0].setType(type);
input_node.outputs[| 1].setType(type);
output_node.outputs[| 0].setType(type);
if(input_node.inputs[| 0].value_from == noone) return;
//print($"=============== STARTING SORT with {ds_list_size(topoList)}/{ds_list_size(nodes)} nodes ===============")
var arrIn = input_node.inputs[| 0].getValue();
var arrOut = output_node.outputs[| 0].getValue();
arrOut = array_clone(arrIn);
quickSort(arrOut, 0, array_length(arrOut) - 1);
output_node.outputs[| 0].setValue(arrOut);
} #endregion
}

View file

@ -0,0 +1,168 @@
// 2024-04-27 09:43:35
function Node_Iterate_Sort_Inline(_x, _y, _group = noone) : Node_Collection_Inline(_x, _y, _group) constructor {
name = "Sort Array";
color = COLORS.node_blend_loop;
is_root = false;
topoList = ds_list_create();
input_node = noone;
output_node = noone;
toSort = true;
input_node_type = Node_Iterator_Sort_Inline_Input;
output_node_type = Node_Iterator_Sort_Inline_Output;
iterated = 0;
if(!LOADING && !APPENDING) { #region
var input = nodeBuild("Node_Iterator_Sort_Inline_Input", x, y);
var output = nodeBuild("Node_Iterator_Sort_Inline_Output", x + 256, y);
addNode(input);
addNode(output);
input_node = input;
output_node = output;
input_node.loop = self;
output_node.loop = self;
if(CLONING && is_instanceof(CLONING_GROUP, Node_Iterate_Sort_Inline)) {
APPEND_MAP[? CLONING_GROUP.input_node.node_id] = input;
APPEND_MAP[? CLONING_GROUP.output_node.node_id] = output;
ds_list_add(APPEND_LIST, input, output);
}
} #endregion
static isActiveDynamic = function(frame = CURRENT_FRAME) { #region
for( var i = 0, n = ds_list_size(nodes); i < n; i++ )
if(nodes[| i].isActiveDynamic(frame)) return true;
return false;
} #endregion
static getNextNodes = function() { #region
return output_node.getNextNodes();
} #endregion
static refreshMember = function() { #region
ds_list_clear(nodes);
for( var i = 0, n = array_length(attributes.members); i < n; i++ ) {
if(!ds_map_exists(PROJECT.nodeMap, attributes.members[i])) {
print($"Node not found {attributes.members[i]}");
continue;
}
var _node = PROJECT.nodeMap[? attributes.members[i]];
_node.inline_context = self;
ds_list_add(nodes, _node);
if(is_instanceof(_node, Node_Iterator_Sort_Inline_Input)) {
input_node = _node;
input_node.loop = self;
}
if(is_instanceof(_node, Node_Iterator_Sort_Inline_Output)) {
output_node = _node;
output_node.loop = self;
}
}
if(input_node == noone || output_node == noone) {
if(input_node) input_node.destroy();
if(output_node) output_node.destroy();
destroy();
}
} #endregion
static update = function(frame = CURRENT_FRAME) { #region
if(input_node == noone || output_node == noone) {
if(input_node) input_node.destroy();
if(output_node) output_node.destroy();
destroy();
return;
}
if(IS_FIRST_FRAME) toSort = true;
if(toSort) NodeListSort(topoList, nodes);
toSort = false;
input_node.startSort = true;
//sortArray();
} #endregion
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static swap = function(arr, a, b) { #region
var temp = arr[a];
arr[@ a] = arr[b];
arr[@ b] = temp;
} #endregion
static compareValue = function(val1, val2) { #region
input_node.outputs[| 0].setValue(val1,,, false);
input_node.outputs[| 1].setValue(val2,,, false);
resetRender(true);
RenderList(topoList);
var res = output_node.inputs[| 0].getValue();
//print($"Comparing value {val1}, {val2} > [{res}]");
return res;
} #endregion
static partition = function(arr, low, high) { #region
var pv = arr[high];
var i = low - 1;
for(var j = low; j < high; j++) {
if(compareValue(arr[j], pv)) continue;
i++;
swap(arr, i, j);
}
swap(arr, i + 1, high);
return i + 1;
} #endregion
static quickSort = function(arr, low, high) { #region
if(low >= high) return;
var p = partition(arr, low, high);
quickSort(arr, low, p - 1);
quickSort(arr, p + 1, high);
} #endregion
static sortArray = function() { #region
iterated = 0;
loop_start_time = get_timer();
var _frj = input_node.inputs[| 0].value_from;
var type = _frj == noone? VALUE_TYPE.any : _frj.type;
input_node.inputs[| 0].setType(type);
input_node.outputs[| 0].setType(type);
input_node.outputs[| 1].setType(type);
output_node.outputs[| 0].setType(type);
if(input_node.inputs[| 0].value_from == noone) return;
//print($"=============== STARTING SORT with {ds_list_size(topoList)}/{ds_list_size(nodes)} nodes ===============")
var arrIn = input_node.inputs[| 0].getValue();
var arrOut = output_node.outputs[| 0].getValue();
arrOut = array_clone(arrIn);
quickSort(arrOut, 0, array_length(arrOut) - 1);
output_node.outputs[| 0].setValue(arrOut);
} #endregion
}

View file

@ -0,0 +1,30 @@
// 2024-04-27 09:34:58
function Node_Iterator_Sort_Inline_Input(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Sort Input";
color = COLORS.node_blend_loop;
loop = noone;
clonable = false;
inline_parent_object = "Node_Iterate_Sort_Inline";
manual_ungroupable = false;
inputs[| 0] = nodeValue("Array in", self, JUNCTION_CONNECT.input, VALUE_TYPE.any, [] )
.setVisible(true, true);
outputs[| 0] = nodeValue("Value 1", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0 );
outputs[| 1] = nodeValue("Value 2", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0 );
startSort = false;
static onGetPreviousNodes = function(arr) {
array_push(arr, loop);
}
static update = function() {
if(startSort) {
startSort = false;
loop.sortArray();
}
}
}

View file

@ -0,0 +1,28 @@
// 2024-04-27 09:18:20
function Node_Iterator_Sort_Inline_Input(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
name = "Sort Input";
color = COLORS.node_blend_loop;
loop = noone;
clonable = false;
inline_parent_object = "Node_Iterate_Sort_Inline";
manual_ungroupable = false;
inputs[| 0] = nodeValue("Array in", self, JUNCTION_CONNECT.input, VALUE_TYPE.any, [] )
.setVisible(true, true);
outputs[| 0] = nodeValue("Value 1", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0 );
outputs[| 1] = nodeValue("Value 2", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0 );
startSort = false;
static onGetPreviousNodes = function(arr) {
array_push(arr, loop);
}
static update = function() {
if(startSort) loop.sortArray();
startSort = false;
}
}

View file

@ -0,0 +1,340 @@
// 2024-04-27 09:33:31
enum RENDER_TYPE {
none = 0,
partial = 1,
full = 2
}
#region globalvar
globalvar UPDATE, RENDER_QUEUE, RENDER_ORDER, UPDATE_RENDER_ORDER, LIVE_UPDATE;
LIVE_UPDATE = false;
UPDATE_RENDER_ORDER = false;
#macro RENDER_ALL_REORDER UPDATE_RENDER_ORDER = true; UPDATE |= RENDER_TYPE.full;
#macro RENDER_ALL UPDATE |= RENDER_TYPE.full;
#macro RENDER_PARTIAL UPDATE |= RENDER_TYPE.partial;
#endregion
function __nodeLeafList(_list) { #region
var nodes = [];
var nodeNames = [];
for( var i = 0, n = ds_list_size(_list); i < n; i++ ) {
var _node = _list[| i];
if(!_node.active) { LOG_LINE_IF(global.FLAG.render == 1, $"Reject {_node.internalName} [inactive]"); continue; }
if(!_node.isLeafList(_list)) { LOG_LINE_IF(global.FLAG.render == 1, $"Reject {_node.internalName} [not leaf]"); continue; }
if(!_node.isRenderable()) { LOG_LINE_IF(global.FLAG.render == 1, $"Reject {_node.internalName} [not renderable]"); continue; }
array_push(nodes, _node);
array_push(nodeNames, _node.internalName);
}
LOG_LINE_IF(global.FLAG.render == 1, $"Push node {nodeNames} to queue");
return nodes;
} #endregion
function ResetAllNodesRender() { #region
LOG_IF(global.FLAG.render == 1, $"XXXXXXXXXXXXXXXXXXXX RESETTING ALL NODES [frame {CURRENT_FRAME}] XXXXXXXXXXXXXXXXXXXX");
var _key = ds_map_find_first(PROJECT.nodeMap);
var amo = ds_map_size(PROJECT.nodeMap);
repeat(amo) {
var _node = PROJECT.nodeMap[? _key];
_node.setRenderStatus(false);
for( var i = 0, n = ds_list_size(_node.inputs); i < n; i++ )
_node.inputs[| i].resetCache();
_key = ds_map_find_next(PROJECT.nodeMap, _key);
}
} #endregion
function NodeTopoSort() { #region
//print($"======================= RESET TOPO =======================")
var _key = ds_map_find_first(PROJECT.nodeMap);
var amo = ds_map_size(PROJECT.nodeMap);
var _t = get_timer();
repeat(amo) {
var _node = PROJECT.nodeMap[? _key];
_node.clearTopoSorted();
_key = ds_map_find_next(PROJECT.nodeMap, _key);
}
ds_list_clear(PROJECT.nodeTopo);
__topoSort(PROJECT.nodeTopo, PROJECT.nodes);
LOG_IF(global.FLAG.render == 1, $"+++++++ Topo Sort Completed: {ds_list_size(PROJECT.nodeTopo)} nodes sorted in {(get_timer() - _t) / 1000} ms +++++++");
} #endregion
function NodeListSort(_list, _nodeList) { #region
for( var i = 0, n = ds_list_size(_nodeList); i < n; i++ )
_nodeList[| i].clearTopoSorted();
// print($"===================== NODE LIST SORT =====================")
ds_list_clear(_list);
__topoSort(_list, _nodeList);
} #endregion
function __sortNode(_list, _node) { #region
if(_node.topoSorted) return;
var _parents = [];
var _prev = _node.getPreviousNodes();
for( var i = 0, n = array_length(_prev); i < n; i++ ) {
var _in = _prev[i];
if(_in == noone || _in.topoSorted) continue;
array_push(_parents, _in);
}
// print($" > Checking {_node.name}: {array_length(_parents)}");
if(is_instanceof(_node, Node_Collection) && !_node.managedRenderOrder)
__topoSort(_list, _node.nodes);
for( var i = 0, n = array_length(_parents); i < n; i++ )
__sortNode(_list, _parents[i]);
if(!_node.topoSorted) {
ds_list_add(_list, _node);
_node.topoSorted = true;
// print($" > Adding > {_node.name}");
}
} #endregion
function __topoSort(_list, _nodeList) { #region
var _root = [];
var _leftOver = [];
for( var i = 0, n = ds_list_size(_nodeList); i < n; i++ ) {
var _node = _nodeList[| i];
var _isRoot = true;
if(is_instanceof(_node, Node_Collection_Inline) && !_node.is_root) {
array_push(_leftOver, _node);
continue;
}
for( var j = 0, m = ds_list_size(_node.outputs); j < m; j++ ) {
var _to = _node.outputs[| j].getJunctionTo();
for( var k = 0, p = array_length(_to); k < p; k++ ) {
if(ds_list_exist(_nodeList, _to[k].node)) {
_isRoot = false;
break;
}
}
if(!_isRoot) break;
}
if(_isRoot) array_push(_root, _node);
}
// print($"Root: {_root}");
for( var i = 0, n = array_length(_root); i < n; i++ )
__sortNode(_list, _root[i]);
for( var i = 0, n = array_length(_leftOver); i < n; i++ ) {
if(!_leftOver[i].topoSorted)
ds_list_insert(_list, 0, _leftOver[i]);
}
} #endregion
function __nodeIsRenderLeaf(_node) { #region
if(is_undefined(_node)) { LOG_IF(global.FLAG.render == 1, $"Skip undefiend [{_node}]"); return false; }
if(!is_instanceof(_node, Node)) { LOG_IF(global.FLAG.render == 1, $"Skip non-node [{_node}]"); return false; }
if(_node.is_group_io) { LOG_IF(global.FLAG.render == 1, $"Skip group IO [{_node.internalName}]"); return false; }
if(!_node.active) { LOG_IF(global.FLAG.render == 1, $"Skip inactive [{_node.internalName}]"); return false; }
if(!_node.isRenderActive()) { LOG_IF(global.FLAG.render == 1, $"Skip render inactive [{_node.internalName}]"); return false; }
if(!_node.attributes.update_graph) { LOG_IF(global.FLAG.render == 1, $"Skip non-auto update [{_node.internalName}]"); return false; }
if(_node.passiveDynamic) { _node.forwardPassiveDynamic(); LOG_IF(global.FLAG.render == 1, $"Skip passive dynamic [{_node.internalName}]"); return false; }
if(!_node.isActiveDynamic()) { LOG_IF(global.FLAG.render == 1, $"Skip rendered static [{_node.internalName}]"); return false; }
if(_node.inline_context != noone && _node.inline_context.managedRenderOrder) return false;
return true;
} #endregion
function Render(partial = false, runAction = false) { #region
LOG_BLOCK_START();
LOG_IF(global.FLAG.render, $"============================== RENDER START [{partial? "PARTIAL" : "FULL"}] [frame {CURRENT_FRAME}] ==============================");
try {
var t = get_timer();
var t1 = get_timer();
var _render_time = 0;
var _leaf_time = 0;
var rendering = noone;
var error = 0;
var reset_all = !partial;
if(reset_all) {
LOG_IF(global.FLAG.render == 1, $"xxxxxxxxxx Resetting {ds_list_size(PROJECT.nodeTopo)} nodes xxxxxxxxxx");
var _key = ds_map_find_first(PROJECT.nodeMap);
var amo = ds_map_size(PROJECT.nodeMap);
repeat(amo) {
var _node = PROJECT.nodeMap[? _key];
_node.setRenderStatus(false);
_key = ds_map_find_next(PROJECT.nodeMap, _key);
}
}
// get leaf node
LOG_IF(global.FLAG.render == 1, $"----- Finding leaf from {ds_list_size(PROJECT.nodeTopo)} nodes -----");
RENDER_QUEUE.clear();
for( var i = 0, n = ds_list_size(PROJECT.nodeTopo); i < n; i++ ) {
var _node = PROJECT.nodeTopo[| i];
_node.passiveDynamic = false;
}
for( var i = 0, n = ds_list_size(PROJECT.nodeTopo); i < n; i++ ) {
var _node = PROJECT.nodeTopo[| i];
_node.render_time = 0;
if(!__nodeIsRenderLeaf(_node))
continue;
LOG_IF(global.FLAG.render == 1, $" Found leaf [{_node.internalName}]");
RENDER_QUEUE.enqueue(_node);
_node.forwardPassiveDynamic();
}
_leaf_time = get_timer() - t;
LOG_IF(global.FLAG.render >= 1, $"Get leaf complete: found {RENDER_QUEUE.size()} leaves in {(get_timer() - t) / 1000} ms."); t = get_timer();
LOG_IF(global.FLAG.render == 1, "================== Start rendering ==================");
// render forward
while(!RENDER_QUEUE.empty()) {
LOG_BLOCK_START();
LOG_IF(global.FLAG.render == 1, $"➤➤➤➤➤➤ CURRENT RENDER QUEUE {RENDER_QUEUE} [{RENDER_QUEUE.size()}] ");
rendering = RENDER_QUEUE.dequeue();
var renderable = rendering.isRenderable();
LOG_IF(global.FLAG.render == 1, $"Rendering {rendering.internalName} ({rendering.display_name}) : {renderable? "Update" : "Pass"} ({rendering.rendered})");
if(renderable) {
var _render_pt = get_timer();
rendering.doUpdate();
_render_time += get_timer() - _render_pt;
var nextNodes = rendering.getNextNodes();
for( var i = 0, n = array_length(nextNodes); i < n; i++ ) {
if(nextNodes[i].isRenderable())
RENDER_QUEUE.enqueue(nextNodes[i]);
}
if(runAction && rendering.hasInspector1Update())
rendering.inspector1Update();
} else if(rendering.force_requeue)
RENDER_QUEUE.enqueue(rendering);
LOG_BLOCK_END();
}
_render_time /= 1000;
LOG_IF(global.FLAG.renderTime || global.FLAG.render >= 1, $"=== RENDER FRAME {CURRENT_FRAME} COMPLETE IN {(get_timer() - t1) / 1000} ms ===\n");
LOG_IF(global.FLAG.render > 1, $"=== RENDER SUMMARY STA ===");
LOG_IF(global.FLAG.render > 1, $" total time: {(get_timer() - t1) / 1000} ms");
LOG_IF(global.FLAG.render > 1, $" leaf: {_leaf_time / 1000} ms");
LOG_IF(global.FLAG.render > 1, $" render loop: {(get_timer() - t) / 1000} ms");
LOG_IF(global.FLAG.render > 1, $" render only: {_render_time} ms");
LOG_IF(global.FLAG.render > 1, $"=== RENDER SUMMARY END ===");
} catch(e) {
noti_warning(exception_print(e));
}
LOG_END();
} #endregion
function __renderListReset(list) { #region
for( var i = 0; i < ds_list_size(list); i++ ) {
list[| i].setRenderStatus(false);
if(struct_has(list[| i], "nodes"))
__renderListReset(list[| i].nodes);
}
} #endregion
function RenderList(list) { #region
LOG_BLOCK_START();
LOG_IF(global.FLAG.render == 1, $"=============== RENDER LIST START [{ds_list_size(list)}] ===============");
var queue = ds_queue_create();
try {
var rendering = noone;
var error = 0;
var t = current_time;
__renderListReset(list);
// get leaf node
for( var i = 0, n = ds_list_size(list); i < n; i++ ) {
var _node = list[| i];
_node.passiveDynamic = false;
}
for( var i = 0, n = ds_list_size(list); i < n; i++ ) {
var _node = list[| i];
if(!__nodeIsRenderLeaf(_node))
continue;
LOG_IF(global.FLAG.render == 1, $"Found leaf {_node.internalName}");
ds_queue_enqueue(queue, _node);
_node.forwardPassiveDynamic();
LOG_BLOCK_END();
}
LOG_IF(global.FLAG.render == 1, "Get leaf complete: found " + string(ds_queue_size(queue)) + " leaves.");
LOG_IF(global.FLAG.render == 1, "=== Start rendering ===");
// render forward
while(!ds_queue_empty(queue)) {
LOG_BLOCK_START();
rendering = ds_queue_dequeue(queue)
var renderable = rendering.isRenderable();
LOG_IF(global.FLAG.render == 1, $"Rendering {rendering.internalName} ({rendering.display_name}) : {renderable? "Update" : "Pass"}");
if(renderable) {
rendering.doUpdate();
var nextNodes = rendering.getNextNodes();
for( var i = 0, n = array_length(nextNodes); i < n; i++ ) {
var _node = nextNodes[i];
if(ds_list_exist(list, _node) && _node.isRenderable())
ds_queue_enqueue(queue, _node);
}
}
LOG_BLOCK_END();
}
} catch(e) {
noti_warning(exception_print(e));
}
LOG_IF(global.FLAG.render == 1, "=== RENDER COMPLETE ===\n");
LOG_END();
ds_queue_destroy(queue);
} #endregion

View file

@ -0,0 +1,340 @@
// 2024-04-27 09:32:10
enum RENDER_TYPE {
none = 0,
partial = 1,
full = 2
}
#region globalvar
globalvar UPDATE, RENDER_QUEUE, RENDER_ORDER, UPDATE_RENDER_ORDER, LIVE_UPDATE;
LIVE_UPDATE = false;
UPDATE_RENDER_ORDER = false;
#macro RENDER_ALL_REORDER UPDATE_RENDER_ORDER = true; UPDATE |= RENDER_TYPE.full;
#macro RENDER_ALL UPDATE |= RENDER_TYPE.full;
#macro RENDER_PARTIAL UPDATE |= RENDER_TYPE.partial;
#endregion
function __nodeLeafList(_list) { #region
var nodes = [];
var nodeNames = [];
for( var i = 0, n = ds_list_size(_list); i < n; i++ ) {
var _node = _list[| i];
if(!_node.active) { LOG_LINE_IF(global.FLAG.render == 1, $"Reject {_node.internalName} [inactive]"); continue; }
if(!_node.isLeafList(_list)) { LOG_LINE_IF(global.FLAG.render == 1, $"Reject {_node.internalName} [not leaf]"); continue; }
if(!_node.isRenderable()) { LOG_LINE_IF(global.FLAG.render == 1, $"Reject {_node.internalName} [not renderable]"); continue; }
array_push(nodes, _node);
array_push(nodeNames, _node.internalName);
}
LOG_LINE_IF(global.FLAG.render == 1, $"Push node {nodeNames} to queue");
return nodes;
} #endregion
function ResetAllNodesRender() { #region
LOG_IF(global.FLAG.render == 1, $"XXXXXXXXXXXXXXXXXXXX RESETTING ALL NODES [frame {CURRENT_FRAME}] XXXXXXXXXXXXXXXXXXXX");
var _key = ds_map_find_first(PROJECT.nodeMap);
var amo = ds_map_size(PROJECT.nodeMap);
repeat(amo) {
var _node = PROJECT.nodeMap[? _key];
_node.setRenderStatus(false);
for( var i = 0, n = ds_list_size(_node.inputs); i < n; i++ )
_node.inputs[| i].resetCache();
_key = ds_map_find_next(PROJECT.nodeMap, _key);
}
} #endregion
function NodeTopoSort() { #region
//print($"======================= RESET TOPO =======================")
var _key = ds_map_find_first(PROJECT.nodeMap);
var amo = ds_map_size(PROJECT.nodeMap);
var _t = get_timer();
repeat(amo) {
var _node = PROJECT.nodeMap[? _key];
_node.clearTopoSorted();
_key = ds_map_find_next(PROJECT.nodeMap, _key);
}
ds_list_clear(PROJECT.nodeTopo);
__topoSort(PROJECT.nodeTopo, PROJECT.nodes);
LOG_IF(global.FLAG.render == 1, $"+++++++ Topo Sort Completed: {ds_list_size(PROJECT.nodeTopo)} nodes sorted in {(get_timer() - _t) / 1000} ms +++++++");
} #endregion
function NodeListSort(_list, _nodeList) { #region
for( var i = 0, n = ds_list_size(_nodeList); i < n; i++ )
_nodeList[| i].clearTopoSorted();
print($"===================== NODE LIST SORT =====================")
ds_list_clear(_list);
__topoSort(_list, _nodeList);
} #endregion
function __sortNode(_list, _node) { #region
if(_node.topoSorted) return;
var _parents = [];
var _prev = _node.getPreviousNodes();
for( var i = 0, n = array_length(_prev); i < n; i++ ) {
var _in = _prev[i];
if(_in == noone || _in.topoSorted) continue;
array_push(_parents, _in);
}
print($" > Checking {_node.name}: {array_length(_parents)}");
if(is_instanceof(_node, Node_Collection) && !_node.managedRenderOrder)
__topoSort(_list, _node.nodes);
for( var i = 0, n = array_length(_parents); i < n; i++ )
__sortNode(_list, _parents[i]);
if(!_node.topoSorted) {
ds_list_add(_list, _node);
_node.topoSorted = true;
print($" > Adding > {_node.name}");
}
} #endregion
function __topoSort(_list, _nodeList) { #region
var _root = [];
var _leftOver = [];
for( var i = 0, n = ds_list_size(_nodeList); i < n; i++ ) {
var _node = _nodeList[| i];
var _isRoot = true;
if(is_instanceof(_node, Node_Collection_Inline) && !_node.is_root) {
array_push(_leftOver, _node);
continue;
}
for( var j = 0, m = ds_list_size(_node.outputs); j < m; j++ ) {
var _to = _node.outputs[| j].getJunctionTo();
for( var k = 0, p = array_length(_to); k < p; k++ ) {
if(ds_list_exist(_nodeList, _to[k].node)) {
_isRoot = false;
break;
}
}
if(!_isRoot) break;
}
if(_isRoot) array_push(_root, _node);
}
print($"Root: {_root}");
for( var i = 0, n = array_length(_root); i < n; i++ )
__sortNode(_list, _root[i]);
for( var i = 0, n = array_length(_leftOver); i < n; i++ ) {
if(!_leftOver[i].topoSorted)
ds_list_insert(_list, 0, _leftOver[i]);
}
} #endregion
function __nodeIsRenderLeaf(_node) { #region
if(is_undefined(_node)) { LOG_IF(global.FLAG.render == 1, $"Skip undefiend [{_node}]"); return false; }
if(!is_instanceof(_node, Node)) { LOG_IF(global.FLAG.render == 1, $"Skip non-node [{_node}]"); return false; }
if(_node.is_group_io) { LOG_IF(global.FLAG.render == 1, $"Skip group IO [{_node.internalName}]"); return false; }
if(!_node.active) { LOG_IF(global.FLAG.render == 1, $"Skip inactive [{_node.internalName}]"); return false; }
if(!_node.isRenderActive()) { LOG_IF(global.FLAG.render == 1, $"Skip render inactive [{_node.internalName}]"); return false; }
if(!_node.attributes.update_graph) { LOG_IF(global.FLAG.render == 1, $"Skip non-auto update [{_node.internalName}]"); return false; }
if(_node.passiveDynamic) { _node.forwardPassiveDynamic(); LOG_IF(global.FLAG.render == 1, $"Skip passive dynamic [{_node.internalName}]"); return false; }
if(!_node.isActiveDynamic()) { LOG_IF(global.FLAG.render == 1, $"Skip rendered static [{_node.internalName}]"); return false; }
if(_node.inline_context != noone && _node.inline_context.managedRenderOrder) return false;
return true;
} #endregion
function Render(partial = false, runAction = false) { #region
LOG_BLOCK_START();
LOG_IF(global.FLAG.render, $"============================== RENDER START [{partial? "PARTIAL" : "FULL"}] [frame {CURRENT_FRAME}] ==============================");
try {
var t = get_timer();
var t1 = get_timer();
var _render_time = 0;
var _leaf_time = 0;
var rendering = noone;
var error = 0;
var reset_all = !partial;
if(reset_all) {
LOG_IF(global.FLAG.render == 1, $"xxxxxxxxxx Resetting {ds_list_size(PROJECT.nodeTopo)} nodes xxxxxxxxxx");
var _key = ds_map_find_first(PROJECT.nodeMap);
var amo = ds_map_size(PROJECT.nodeMap);
repeat(amo) {
var _node = PROJECT.nodeMap[? _key];
_node.setRenderStatus(false);
_key = ds_map_find_next(PROJECT.nodeMap, _key);
}
}
// get leaf node
LOG_IF(global.FLAG.render == 1, $"----- Finding leaf from {ds_list_size(PROJECT.nodeTopo)} nodes -----");
RENDER_QUEUE.clear();
for( var i = 0, n = ds_list_size(PROJECT.nodeTopo); i < n; i++ ) {
var _node = PROJECT.nodeTopo[| i];
_node.passiveDynamic = false;
}
for( var i = 0, n = ds_list_size(PROJECT.nodeTopo); i < n; i++ ) {
var _node = PROJECT.nodeTopo[| i];
_node.render_time = 0;
if(!__nodeIsRenderLeaf(_node))
continue;
LOG_IF(global.FLAG.render == 1, $" Found leaf [{_node.internalName}]");
RENDER_QUEUE.enqueue(_node);
_node.forwardPassiveDynamic();
}
_leaf_time = get_timer() - t;
LOG_IF(global.FLAG.render >= 1, $"Get leaf complete: found {RENDER_QUEUE.size()} leaves in {(get_timer() - t) / 1000} ms."); t = get_timer();
LOG_IF(global.FLAG.render == 1, "================== Start rendering ==================");
// render forward
while(!RENDER_QUEUE.empty()) {
LOG_BLOCK_START();
LOG_IF(global.FLAG.render == 1, $"➤➤➤➤➤➤ CURRENT RENDER QUEUE {RENDER_QUEUE} [{RENDER_QUEUE.size()}] ");
rendering = RENDER_QUEUE.dequeue();
var renderable = rendering.isRenderable();
LOG_IF(global.FLAG.render == 1, $"Rendering {rendering.internalName} ({rendering.display_name}) : {renderable? "Update" : "Pass"} ({rendering.rendered})");
if(renderable) {
var _render_pt = get_timer();
rendering.doUpdate();
_render_time += get_timer() - _render_pt;
var nextNodes = rendering.getNextNodes();
for( var i = 0, n = array_length(nextNodes); i < n; i++ ) {
if(nextNodes[i].isRenderable())
RENDER_QUEUE.enqueue(nextNodes[i]);
}
if(runAction && rendering.hasInspector1Update())
rendering.inspector1Update();
} else if(rendering.force_requeue)
RENDER_QUEUE.enqueue(rendering);
LOG_BLOCK_END();
}
_render_time /= 1000;
LOG_IF(global.FLAG.renderTime || global.FLAG.render >= 1, $"=== RENDER FRAME {CURRENT_FRAME} COMPLETE IN {(get_timer() - t1) / 1000} ms ===\n");
LOG_IF(global.FLAG.render > 1, $"=== RENDER SUMMARY STA ===");
LOG_IF(global.FLAG.render > 1, $" total time: {(get_timer() - t1) / 1000} ms");
LOG_IF(global.FLAG.render > 1, $" leaf: {_leaf_time / 1000} ms");
LOG_IF(global.FLAG.render > 1, $" render loop: {(get_timer() - t) / 1000} ms");
LOG_IF(global.FLAG.render > 1, $" render only: {_render_time} ms");
LOG_IF(global.FLAG.render > 1, $"=== RENDER SUMMARY END ===");
} catch(e) {
noti_warning(exception_print(e));
}
LOG_END();
} #endregion
function __renderListReset(list) { #region
for( var i = 0; i < ds_list_size(list); i++ ) {
list[| i].setRenderStatus(false);
if(struct_has(list[| i], "nodes"))
__renderListReset(list[| i].nodes);
}
} #endregion
function RenderList(list) { #region
LOG_BLOCK_START();
LOG_IF(global.FLAG.render == 1, $"=============== RENDER LIST START [{ds_list_size(list)}] ===============");
var queue = ds_queue_create();
try {
var rendering = noone;
var error = 0;
var t = current_time;
__renderListReset(list);
// get leaf node
for( var i = 0, n = ds_list_size(list); i < n; i++ ) {
var _node = list[| i];
_node.passiveDynamic = false;
}
for( var i = 0, n = ds_list_size(list); i < n; i++ ) {
var _node = list[| i];
if(!__nodeIsRenderLeaf(_node))
continue;
LOG_IF(global.FLAG.render == 1, $"Found leaf {_node.internalName}");
ds_queue_enqueue(queue, _node);
_node.forwardPassiveDynamic();
LOG_BLOCK_END();
}
LOG_IF(global.FLAG.render == 1, "Get leaf complete: found " + string(ds_queue_size(queue)) + " leaves.");
LOG_IF(global.FLAG.render == 1, "=== Start rendering ===");
// render forward
while(!ds_queue_empty(queue)) {
LOG_BLOCK_START();
rendering = ds_queue_dequeue(queue)
var renderable = rendering.isRenderable();
LOG_IF(global.FLAG.render == 1, $"Rendering {rendering.internalName} ({rendering.display_name}) : {renderable? "Update" : "Pass"}");
if(renderable) {
rendering.doUpdate();
var nextNodes = rendering.getNextNodes();
for( var i = 0, n = array_length(nextNodes); i < n; i++ ) {
var _node = nextNodes[i];
if(ds_list_exist(list, _node) && _node.isRenderable())
ds_queue_enqueue(queue, _node);
}
}
LOG_BLOCK_END();
}
} catch(e) {
noti_warning(exception_print(e));
}
LOG_IF(global.FLAG.render == 1, "=== RENDER COMPLETE ===\n");
LOG_END();
ds_queue_destroy(queue);
} #endregion

View file

@ -0,0 +1,186 @@
// 2024-04-27 10:08:09
enum DIMENSION {
width,
height
}
function vectorBox(_size, _onModify, _unit = noone) : widget() constructor {
size = _size;
onModify = _onModify;
unit = _unit;
linkable = true;
per_line = false;
current_value = [];
linked = false;
side_button = noone;
link_inactive_color = noone;
tooltip = new tooltipSelector("Axis", [ __txt("Independent"), __txt("Linked") ]);
onModifyIndex = function(index, val) {
var v = toNumber(val);
if(linked) {
var modi = false;
for( var i = 0; i < size; i++ ) {
tb[i]._input_text = v;
if(is_callable(onModify))
modi |= onModify(i, v);
}
return modi;
}
if(is_callable(onModify))
return onModify(index, v);
return noone;
}
axis = [ "x", "y", "z", "w" ];
onModifySingle[0] = function(val) { return onModifyIndex(0, val); }
onModifySingle[1] = function(val) { return onModifyIndex(1, val); }
onModifySingle[2] = function(val) { return onModifyIndex(2, val); }
onModifySingle[3] = function(val) { return onModifyIndex(3, val); }
for(var i = 0; i < 4; i++) {
tb[i] = new textBox(TEXTBOX_INPUT.number, onModifySingle[i]);
tb[i].slidable = true;
}
static apply = function() { #region
for( var i = 0; i < size; i++ ) {
tb[i].apply();
current_value[i] = toNumber(tb[i]._input_text);
}
} #endregion
static setLinkInactiveColor = function(color) { #region
link_inactive_color = color;
return self;
} #endregion
static setSlideSpeed = function(speed) { #region
for(var i = 0; i < size; i++)
tb[i].setSlidable(speed);
return self;
} #endregion
static setInteract = function(interactable) { #region
self.interactable = interactable;
if(side_button)
side_button.interactable = interactable;
for( var i = 0; i < size; i++ )
tb[i].interactable = interactable;
} #endregion
static register = function(parent = noone) { #region
for( var i = 0; i < size; i++ )
tb[i].register(parent);
if(side_button != noone)
side_button.register(parent);
if(unit != noone && unit.reference != noone)
unit.triggerButton.register(parent);
} #endregion
static isHovering = function() { #region
for( var i = 0, n = array_length(tb); i < n; i++ ) if(tb[i].isHovering()) return true;
return false;
} #endregion
static drawParam = function(params) { #region
setParam(params);
for(var i = 0; i < 4; i++) tb[i].setParam(params);
return draw(params.x, params.y, params.w, params.h, params.data, params.display_data, params.m);
} #endregion
static draw = function(_x, _y, _w, _h, _data, _display_data, _m) { #region
x = _x;
y = _y;
w = _w;
h = per_line? (_h + ui(4)) * size - ui(4) : _h;
if(struct_has(_display_data, "linked")) linked = _display_data.linked;
if(struct_has(_display_data, "side_button")) side_button = _display_data.side_button;
tooltip.index = linked;
if(!is_array(_data)) return _h;
if(array_empty(_data)) return _h;
if(is_array(_data[0])) return _h;
current_value = _data;
var sz = min(size, array_length(_data));
var _bs = min(_h, ui(32));
if((_w - _bs) / sz > ui(48)) {
if(side_button) {
side_button.setFocusHover(active, hover);
side_button.draw(_x + _w - _bs, _y + _h / 2 - _bs / 2, _bs, _bs, _m, THEME.button_hide);
_w -= _bs + ui(4);
}
if(unit != noone && unit.reference != noone) {
unit.triggerButton.setFocusHover(iactive, ihover);
unit.draw(_x + _w - _bs, _y + _h / 2 - _bs / 2, _bs, _bs, _m);
_w -= _bs + ui(4);
}
if(linkable) {
var _icon_blend = linked? COLORS._main_accent : (link_inactive_color == noone? COLORS._main_icon : link_inactive_color);
var bx = _x;
var by = _y + _h / 2 - _bs / 2;
if(buttonInstant(THEME.button_hide, bx, by, _bs, _bs, _m, active, hover, tooltip, THEME.value_link, linked, _icon_blend) == 2) {
linked = !linked;
_display_data.linked = linked;
if(linked) {
onModify(0, _data[0]);
onModify(1, _data[0]);
}
}
_x += _bs + ui(4);
_w -= _bs + ui(4);
}
}
var ww = per_line? _w : _w / sz;
if(!per_line) {
draw_sprite_stretched_ext(THEME.textbox, 3, _x, _y, _w, _h, c_white, 1);
draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y, _w, _h, c_white, 0.5 + 0.5 * interactable);
}
for(var i = 0; i < sz; i++) {
var bx = per_line? _x : _x + ww * i;
var by = per_line? _y + (_h + ui(4)) * i : _y;
tb[i].setFocusHover(active, hover);
tb[i].hide = !per_line;
tb[i].label = axis[i];
tb[i].draw(bx, by, ww, _h, _data[i], _m);
}
resetFocus();
return h;
} #endregion
static clone = function() { #region
var cln = new vectorBox(size, onModify, unit);
cln.linkable = linkable;
cln.per_line = per_line;
return cln;
} #endregion
}

View file

@ -0,0 +1,186 @@
// 2024-04-27 10:07:59
enum DIMENSION {
width,
height
}
function vectorBox(_size, _onModify, _unit = noone) : widget() constructor {
size = _size;
onModify = _onModify;
unit = _unit;
linkable = true;
per_line = false;
current_value = [];
linked = false;
side_button = noone;
link_inactive_color = noone;
tooltip = new tooltipSelector("Axis", [ __txt("Independent"), __txt("Linked") ]);
onModifyIndex = function(index, val) {
var v = toNumber(val);
if(linked) {
var modi = false;
for( var i = 0; i < size; i++ ) {
tb[i]._input_text = v;
if(is_callable(onModify))
modi |= onModify(i, v);
}
return modi;
}
if(is_callable(onModify))
return onModify(index, v);
return noone;
}
axis = [ "x", "y", "z", "w" ];
onModifySingle[0] = function(val) { return onModifyIndex(0, val); }
onModifySingle[1] = function(val) { return onModifyIndex(1, val); }
onModifySingle[2] = function(val) { return onModifyIndex(2, val); }
onModifySingle[3] = function(val) { return onModifyIndex(3, val); }
for(var i = 0; i < 4; i++) {
tb[i] = new textBox(TEXTBOX_INPUT.number, onModifySingle[i]);
tb[i].slidable = true;
}
static apply = function() { #region
for( var i = 0; i < size; i++ ) {
tb[i].apply();
current_value[i] = toNumber(tb[i]._input_text);
}
} #endregion
static setLinkInactiveColor = function(color) { #region
link_inactive_color = color;
return self;
} #endregion
static setSlideSpeed = function(speed) { #region
for(var i = 0; i < size; i++)
tb[i].setSlidable(speed);
return self;
} #endregion
static setInteract = function(interactable) { #region
self.interactable = interactable;
if(side_button)
side_button.interactable = interactable;
for( var i = 0; i < size; i++ )
tb[i].interactable = interactable;
} #endregion
static register = function(parent = noone) { #region
for( var i = 0; i < size; i++ )
tb[i].register(parent);
if(side_button != noone)
side_button.register(parent);
if(unit != noone && unit.reference != noone)
unit.triggerButton.register(parent);
} #endregion
static isHovering = function() { #region
for( var i = 0, n = array_length(tb); i < n; i++ ) if(tb[i].isHovering()) return true;
return false;
} #endregion
static drawParam = function(params) { #region
setParam(params);
for(var i = 0; i < 4; i++) tb[i].setParam(params);
return draw(params.x, params.y, params.w, params.h, params.data, params.display_data, params.m);
} #endregion
static draw = function(_x, _y, _w, _h, _data, _display_data, _m) { #region
x = _x;
y = _y;
w = _w;
h = per_line? (_h + ui(4)) * size - ui(4) : _h;
if(struct_has(_display_data, "linked")) linked = _display_data.linked;
if(struct_has(_display_data, "side_button")) side_button = _display_data.side_button;
tooltip.index = linked;
if(!is_array(_data)) return _h;
if(array_empty(_data)) return _h;
if(is_array(_data[0])) return _h;
current_value = _data;
var sz = min(size, array_length(_data));
var _bs = min(_h, ui(32));
if((_w - _bs) / sz > ui(48)) {
if(side_button) {
side_button.setFocusHover(active, hover);
side_button.draw(_x + _w - _bs, _y + _h / 2 - _bs / 2, _bs, _bs, _m, THEME.button_hide);
_w -= _bs + ui(4);
}
if(unit != noone && unit.reference != noone) {
unit.triggerButton.setFocusHover(iactive, ihover);
unit.draw(_x + _w - _bs, _y + _h / 2 - _bs / 2, _bs, _bs, _m);
_w -= _bs + ui(4);
}
if(linkable) {
var _icon_blend = linked? COLORS._main_accent : (link_inactive_color == noone? COLORS._main_icon : link_inactive_color);
var bx = _x;
var by = _y + _h / 2 - _bs / 2;
if(buttonInstant(THEME.button_hide, bx, by, _bs, _bs, _m, active, hover, tooltip, THEME.value_link, linked, _icon_blend) == 2) {
linked = !linked;
_display_data.linked = linked;
if(linked) {
onModify(0, _data[0]);
onModify(1, _data[0]);
}
}
_x += _bs + ui(4);
_w -= _bs + ui(4);
}
}
var ww = per_line? _w : _w / sz;
if(!per_line) {
draw_sprite_stretched_ext(THEME.textbox, 3, _x, _y, _w, _h, c_white, 1);
draw_sprite_stretched_ext(THEME.textbox, 0, _x, _y, _w, _h, c_white, 0.5 + 0.5 * interactable);
}
for(var i = 0; i < sz; i++) {
var bx = per_line? _x : _x + ww * i;
var by = per_line? _y + (_h + ui(4)) * i : _y;
tb[i].setFocusHover(active, hover);
tb[i].hide = !per_line;
tb[i].label = axis[i];
tb[i].draw(bx, by, ww, _h, _data[i], _m);
}
resetFocus();
return h;
} #endregion
static clone = function() { #region
var cln = new vectorBox(size, onModify, unit);
cln.linkable = linkable;
cln.per_line = per_line;
return cln;
} #endregion
}

View file

@ -29,8 +29,10 @@ if !target exit;
var by = dialog_y + ui(18);
if(buttonInstant(THEME.button_hide, bx, by, bw, bh, mouse_ui, sFOCUS, sHOVER, __txt("Add") + "...", THEME.add,, COLORS._main_value_positive) == 2) {
var path = get_open_filenames_compat("image|*.png;*.jpg", "");
key_release();
if(path != "") {
var paths = paths_to_array(path);
var arr = target.getInputData(0);

View file

@ -29,25 +29,28 @@ function Node_Atlas_Get(_x, _y, _group = noone) : Node(_x, _y, _group) construct
var atl = getInputData(0);
if(atl == noone) return;
if(is_array(atl) && array_length(atl) == 0) return;
if(!is_array(atl))
atl = [ atl ];
if(!is_array(atl)) atl = [ atl ];
if(array_empty(atl)) return;
var surf = [];
var posi = [];
var rota = [];
var scal = [];
var blns = [];
var alph = [];
var n = array_length(atl);
var surf = array_create(n);
var posi = array_create(n);
var rota = array_create(n);
var scal = array_create(n);
var blns = array_create(n);
var alph = array_create(n);
for( var i = 0, n = array_length(atl); i < n; i++ ) {
surf[i] = atl[i].getSurface();
posi[i] = atl[i].position;
rota[i] = atl[i].rotation;
scal[i] = atl[i].scale;
blns[i] = atl[i].blend;
alph[i] = atl[i].alpha;
for( var i = 0; i < n; i++ ) {
var _at = atl[i];
if(!is_instanceof(_at, SurfaceAtlas)) continue;
surf[i] = _at.getSurface();
posi[i] = [ _at.x, _at.y ];
rota[i] = _at.rotation;
scal[i] = [ _at.sx, _at.sy ];
blns[i] = _at.blend;
alph[i] = _at.alpha;
}
outputs[| 0].setValue(surf);

View file

@ -8,14 +8,14 @@ function Node_Atlas_Set(_x, _y, _group = noone) : Node(_x, _y, _group) construct
inputs[| 1] = nodeValue("Surface", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, [])
.setArrayDepth(1);
inputs[| 2] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
inputs[| 2] = nodeValue("Position", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ])
.setDisplay(VALUE_DISPLAY.vector)
.setArrayDepth(1);
inputs[| 3] = nodeValue("Rotation", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
.setArrayDepth(1);
inputs[| 4] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [])
inputs[| 4] = nodeValue("Scale", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 0 ])
.setDisplay(VALUE_DISPLAY.vector)
.setArrayDepth(1);
@ -31,10 +31,9 @@ function Node_Atlas_Set(_x, _y, _group = noone) : Node(_x, _y, _group) construct
var atl = getInputData(0);
if(atl == noone) return;
if(is_array(atl) && array_length(atl) == 0) return;
if(!is_array(atl))
atl = [ atl ];
if(!is_array(atl)) atl = [ atl ];
if(array_empty(atl)) return;
var surf = getInputData(1);
var posi = getInputData(2);
@ -43,13 +42,17 @@ function Node_Atlas_Set(_x, _y, _group = noone) : Node(_x, _y, _group) construct
var blns = getInputData(5);
var alph = getInputData(6);
var use = [ 0 ];
var use = array_create(7);
for( var i = 1; i < 7; i++ ) use[i] = inputs[| i].value_from != noone;
var natl = [];
var n = array_length(atl);
var natl = array_create(n);
for( var i = 0, n = array_length(atl); i < n; i++ ) {
natl[i] = atl[i].clone();
for( var i = 0; i < n; i++ ) {
var _at = atl[i];
if(!is_instanceof(_at, SurfaceAtlas)) continue;
natl[i] = _at.clone();
if(use[1]) natl[i].setSurface(array_safe_get_fast(surf, i));

View file

@ -8,6 +8,8 @@ function Node_Iterate_Sort_Inline(_x, _y, _group = noone) : Node_Collection_Inli
input_node = noone;
output_node = noone;
toSort = true;
input_node_type = Node_Iterator_Sort_Inline_Input;
output_node_type = Node_Iterator_Sort_Inline_Output;
iterated = 0;
@ -83,11 +85,16 @@ function Node_Iterate_Sort_Inline(_x, _y, _group = noone) : Node_Collection_Inli
return;
}
if(IS_FIRST_FRAME) NodeListSort(topoList, nodes);
if(IS_FIRST_FRAME) toSort = true;
if(toSort) NodeListSort(topoList, nodes);
toSort = false;
sortArray();
input_node.startSort = true;
//sortArray();
} #endregion
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static swap = function(arr, a, b) { #region
var temp = arr[a];
arr[@ a] = arr[b];
@ -103,6 +110,7 @@ function Node_Iterate_Sort_Inline(_x, _y, _group = noone) : Node_Collection_Inli
var res = output_node.inputs[| 0].getValue();
//print($"Comparing value {val1}, {val2} > [{res}]");
return res;
} #endregion
@ -145,6 +153,8 @@ function Node_Iterate_Sort_Inline(_x, _y, _group = noone) : Node_Collection_Inli
if(input_node.inputs[| 0].value_from == noone) return;
//print($"=============== STARTING SORT with {ds_list_size(topoList)}/{ds_list_size(nodes)} nodes ===============")
var arrIn = input_node.inputs[| 0].getValue();
var arrOut = output_node.outputs[| 0].getValue();

View file

@ -14,8 +14,16 @@ function Node_Iterator_Sort_Inline_Input(_x, _y, _group = noone) : Node(_x, _y,
outputs[| 1] = nodeValue("Value 2", self, JUNCTION_CONNECT.output, VALUE_TYPE.any, 0 );
startSort = false;
static onGetPreviousNodes = function(arr) {
array_push(arr, loop);
}
static update = function() {
if(startSort) {
startSort = false;
loop.sortArray();
}
}
}

View file

@ -70,8 +70,10 @@ function NodeTopoSort() { #region
} #endregion
function NodeListSort(_list, _nodeList) { #region
for( var i = 0, n = ds_list_size(_list); i < n; i++ )
_list[| i].clearTopoSorted();
for( var i = 0, n = ds_list_size(_nodeList); i < n; i++ )
_nodeList[| i].clearTopoSorted();
// print($"===================== NODE LIST SORT =====================")
ds_list_clear(_list);
__topoSort(_list, _nodeList);
@ -107,12 +109,12 @@ function __sortNode(_list, _node) { #region
} #endregion
function __topoSort(_list, _nodeList) { #region
var _leaf = [];
var _root = [];
var _leftOver = [];
for( var i = 0, n = ds_list_size(_nodeList); i < n; i++ ) {
var _node = _nodeList[| i];
var _isLeaf = true;
var _isRoot = true;
if(is_instanceof(_node, Node_Collection_Inline) && !_node.is_root) {
array_push(_leftOver, _node);
@ -124,19 +126,21 @@ function __topoSort(_list, _nodeList) { #region
for( var k = 0, p = array_length(_to); k < p; k++ ) {
if(ds_list_exist(_nodeList, _to[k].node)) {
_isLeaf = false;
_isRoot = false;
break;
}
}
if(!_isLeaf) break;
if(!_isRoot) break;
}
if(_isLeaf) array_push(_leaf, _node);
if(_isRoot) array_push(_root, _node);
}
for( var i = 0, n = array_length(_leaf); i < n; i++ )
__sortNode(_list, _leaf[i]);
// print($"Root: {_root}");
for( var i = 0, n = array_length(_root); i < n; i++ )
__sortNode(_list, _root[i]);
for( var i = 0, n = array_length(_leftOver); i < n; i++ ) {
if(!_leftOver[i].topoSorted)

View file

@ -109,9 +109,9 @@ function vectorBox(_size, _onModify, _unit = noone) : widget() constructor {
if(struct_has(_display_data, "side_button")) side_button = _display_data.side_button;
tooltip.index = linked;
if(!is_array(_data)) return 0;
if(array_empty(_data)) return 0;
if(is_array(_data[0])) return 0;
if(!is_array(_data)) return _h;
if(array_empty(_data)) return _h;
if(is_array(_data[0])) return _h;
current_value = _data;