From 8e9b2b61dca179f0457117f89b3ddf3dd34ece8c Mon Sep 17 00:00:00 2001 From: Tanasart Date: Sun, 19 Nov 2023 19:33:42 +0700 Subject: [PATCH] - [Loop] Loop now use subgraph update for better static performance. --- scripts/__node_iterator/__node_iterator.gml | 18 +++++++- scripts/globals/globals.gml | 3 +- scripts/node_feedback/node_feedback.gml | 14 +++--- scripts/node_iterate/node_iterate.gml | 17 ++----- .../node_iterate_each/node_iterate_each.gml | 29 ++++-------- .../node_iterate_filter.gml | 31 ++++--------- .../node_iterate_sort/node_iterate_sort.gml | 10 +++- scripts/render_data/render_data.gml | 46 ++++++++----------- 8 files changed, 73 insertions(+), 95 deletions(-) diff --git a/scripts/__node_iterator/__node_iterator.gml b/scripts/__node_iterator/__node_iterator.gml index c4c4504b8..ef75e0491 100644 --- a/scripts/__node_iterator/__node_iterator.gml +++ b/scripts/__node_iterator/__node_iterator.gml @@ -5,7 +5,23 @@ enum ITERATION_STATUS { } function Node_Iterator(_x, _y, _group = noone) : Node_Collection(_x, _y, _group) constructor { - willRestart = false; //in the next getNextNode, reset all child nodes, use in loop. + color = COLORS.node_blend_loop; + icon = THEME.loop; + + willRestart = false; //in the next getNextNode, reset all child nodes, use in loop. + managedRenderOrder = true; + reset_all_child = true; + combine_render_time = false; + loop_start_time = 0; + + iterated = 0; + + 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 initLoop = function() { #region resetRender(); diff --git a/scripts/globals/globals.gml b/scripts/globals/globals.gml index 25859c4a7..e027abf0c 100644 --- a/scripts/globals/globals.gml +++ b/scripts/globals/globals.gml @@ -1,6 +1,6 @@ #region save globalvar LOADING, APPENDING, CLONING; - globalvar CONNECTION_CONFLICT, ALWAYS_FULL; + globalvar CONNECTION_CONFLICT; globalvar MESSAGE; LOADING = false; @@ -11,7 +11,6 @@ CONNECTION_CONFLICT = ds_queue_create(); randomize(); - ALWAYS_FULL = false; #endregion #region main diff --git a/scripts/node_feedback/node_feedback.gml b/scripts/node_feedback/node_feedback.gml index 43ec5881e..6785a32f4 100644 --- a/scripts/node_feedback/node_feedback.gml +++ b/scripts/node_feedback/node_feedback.gml @@ -3,19 +3,19 @@ function Node_Feedback(_x, _y, _group = noone) : Node_Collection(_x, _y, _group) color = COLORS.node_blend_feedback; icon = THEME.feedback; - update_on_frame = true; - reset_all_child = true; + update_on_frame = true; + reset_all_child = true; - if(!LOADING && !APPENDING && !CLONING) { + if(!LOADING && !APPENDING && !CLONING) { #region var input = nodeBuild("Node_Feedback_Input", -256, -32, self); var output = nodeBuild("Node_Feedback_Output", 256, -32, self); input.inputs[| 2].setValue(4); output.inputs[| 0].setFrom(input.outputs[| 0]); output.inputs[| 1].setFrom(input.outputs[| 1]); - } + } #endregion - static getNextNodes = function() { + static getNextNodes = function() { #region var allReady = true; for(var i = custom_input_index; i < ds_list_size(inputs); i++) { var _in = inputs[| i].from; @@ -27,7 +27,5 @@ function Node_Feedback(_x, _y, _group = noone) : Node_Collection(_x, _y, _group) if(!allReady) return []; return __nodeLeafList(getNodeList()); - } - - PATCH_STATIC + } #endregion } \ No newline at end of file diff --git a/scripts/node_iterate/node_iterate.gml b/scripts/node_iterate/node_iterate.gml index c9ea60232..e8f459b9d 100644 --- a/scripts/node_iterate/node_iterate.gml +++ b/scripts/node_iterate/node_iterate.gml @@ -1,29 +1,18 @@ function Node_Iterate(_x, _y, _group = noone) : Node_Iterator(_x, _y, _group) constructor { - name = "Loop"; - color = COLORS.node_blend_loop; - icon = THEME.loop; - - reset_all_child = true; - combine_render_time = false; - managedRenderOrder = true; - iterated = 0; + name = "Loop"; inputs[| 0] = nodeValue("Repeat", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 1 ) .uncache(); custom_input_index = ds_list_size(inputs); - loop_start_time = 0; - ALWAYS_FULL = true; - if(!LOADING && !APPENDING && !CLONING) { + if(!LOADING && !APPENDING && !CLONING) { #region var input = nodeBuild("Node_Iterator_Input", -256, -32, self); var output = nodeBuild("Node_Iterator_Output", 256, -32, self); input.inputs[| 2].setValue(4); output.inputs[| 1].setFrom(input.outputs[| 1]); - } + } #endregion static getIterationCount = function() { return getInputData(0); } - - PATCH_STATIC } \ No newline at end of file diff --git a/scripts/node_iterate_each/node_iterate_each.gml b/scripts/node_iterate_each/node_iterate_each.gml index deb6af16a..5f91a9ad3 100644 --- a/scripts/node_iterate_each/node_iterate_each.gml +++ b/scripts/node_iterate_each/node_iterate_each.gml @@ -1,12 +1,5 @@ function Node_Iterate_Each(_x, _y, _group = noone) : Node_Iterator(_x, _y, _group) constructor { - name = "Loop Array"; - color = COLORS.node_blend_loop; - icon = THEME.loop; - - reset_all_child = true; - combine_render_time = false; - managedRenderOrder = true; - iterated = 0; + name = "Loop Array"; inputs[| 0] = nodeValue("Array", self, JUNCTION_CONNECT.input, VALUE_TYPE.any, [] ) .setVisible(true, true); @@ -15,22 +8,20 @@ function Node_Iterate_Each(_x, _y, _group = noone) : Node_Iterator(_x, _y, _grou custom_input_index = ds_list_size(inputs); custom_output_index = ds_list_size(inputs); - loop_start_time = 0; - ALWAYS_FULL = true; - if(!LOADING && !APPENDING && !CLONING) { + if(!LOADING && !APPENDING && !CLONING) { #region var input = nodeBuild("Node_Iterator_Each_Input", -256, -32, self); var output = nodeBuild("Node_Iterator_Each_Output", 256, -32, self); output.inputs[| 0].setFrom(input.outputs[| 0]); - } + } #endregion - static onStep = function() { + static onStep = function() { #region var type = inputs[| 0].isLeaf()? VALUE_TYPE.any : inputs[| 0].value_from.type; inputs[| 0].setType(type); - } + } #endregion - static doInitLoop = function() { + static doInitLoop = function() { #region var arrIn = getInputData(0); var arrOut = outputs[| 0].getValue(); @@ -38,15 +29,13 @@ function Node_Iterate_Each(_x, _y, _group = noone) : Node_Iterator(_x, _y, _grou surface_array_free(arrOut); outputs[| 0].setValue([]) } - } + } #endregion - static getIterationCount = function() { + static getIterationCount = function() { #region var arrIn = getInputData(0); var maxIter = is_array(arrIn)? array_length(arrIn) : 0; if(!is_real(maxIter)) maxIter = 1; return maxIter; - } - - PATCH_STATIC + } #endregion } \ No newline at end of file diff --git a/scripts/node_iterate_filter/node_iterate_filter.gml b/scripts/node_iterate_filter/node_iterate_filter.gml index 2ccef32a0..3b72a7fd3 100644 --- a/scripts/node_iterate_filter/node_iterate_filter.gml +++ b/scripts/node_iterate_filter/node_iterate_filter.gml @@ -1,14 +1,5 @@ -//Make an iterator_* parent??? - function Node_Iterate_Filter(_x, _y, _group = noone) : Node_Iterator(_x, _y, _group) constructor { - name = "Filter Array"; - color = COLORS.node_blend_loop; - icon = THEME.loop; - - reset_all_child = true; - combine_render_time = false; - managedRenderOrder = true; - iterated = 0; + name = "Filter Array"; inputs[| 0] = nodeValue("Array", self, JUNCTION_CONNECT.input, VALUE_TYPE.any, [] ) .setVisible(true, true); @@ -17,36 +8,32 @@ function Node_Iterate_Filter(_x, _y, _group = noone) : Node_Iterator(_x, _y, _gr custom_input_index = ds_list_size(inputs); custom_output_index = ds_list_size(inputs); - loop_start_time = 0; - ALWAYS_FULL = true; - if(!LOADING && !APPENDING && !CLONING) { + if(!LOADING && !APPENDING && !CLONING) { #region var input = nodeBuild("Node_Iterator_Filter_Input", -256, -32, self); var output = nodeBuild("Node_Iterator_Filter_Output", 256, -32, self); output.inputs[| 0].setFrom(input.outputs[| 0]); - } + } #endregion - static onStep = function() { + static onStep = function() { #region var type = inputs[| 0].isLeaf()? VALUE_TYPE.any : inputs[| 0].value_from.type; inputs[| 0].setType(type); - } + } #endregion - static doInitLoop = function() { + static doInitLoop = function() { #region var arrIn = getInputData(0); var arrOut = outputs[| 0].getValue(); surface_array_free(arrOut); outputs[| 0].setValue([]) - } + } #endregion - static getIterationCount = function() { + static getIterationCount = function() { #region var arrIn = getInputData(0); var maxIter = is_array(arrIn)? array_length(arrIn) : 0; if(!is_real(maxIter)) maxIter = 1; return maxIter; - } - - PATCH_STATIC + } #endregion } \ No newline at end of file diff --git a/scripts/node_iterate_sort/node_iterate_sort.gml b/scripts/node_iterate_sort/node_iterate_sort.gml index 711575b6f..33c4c0d16 100644 --- a/scripts/node_iterate_sort/node_iterate_sort.gml +++ b/scripts/node_iterate_sort/node_iterate_sort.gml @@ -1,5 +1,5 @@ function Node_Iterate_Sort(_x, _y, _group = noone) : Node_Collection(_x, _y, _group) constructor { - name = "Sort Array"; + name = "Sort Array"; color = COLORS.node_blend_loop; icon = THEME.loop; @@ -17,7 +17,6 @@ function Node_Iterate_Sort(_x, _y, _group = noone) : Node_Collection(_x, _y, _gr custom_input_index = ds_list_size(inputs); custom_output_index = ds_list_size(inputs); loop_start_time = 0; - ALWAYS_FULL = true; inputNodes = [ noone, noone ]; outputNode = noone; @@ -33,6 +32,13 @@ function Node_Iterate_Sort(_x, _y, _group = noone) : Node_Collection(_x, _y, _gr var output = nodeBuild("Node_Iterator_Sort_Output", 256, -32, self); } #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() { return getNextNodesExternal(); } static onStep = function() { #region diff --git a/scripts/render_data/render_data.gml b/scripts/render_data/render_data.gml index 2b54e8d77..8f996131c 100644 --- a/scripts/render_data/render_data.gml +++ b/scripts/render_data/render_data.gml @@ -44,15 +44,6 @@ function __nodeLeafList(_list) { #region return nodes; } #endregion -function __nodeManualManaged(_node) { #region - var gr = _node.group; - while(gr != noone) { - if(gr.managedRenderOrder) return true; - gr = gr.group; - } - return false; -} #endregion - function ResetAllNodesRender() { #region LOG_IF(global.FLAG.render == 1, $"XXXXXXXXXXXXXXXXXXXX RESETTING ALL NODES [frame {CURRENT_FRAME}] XXXXXXXXXXXXXXXXXXXX"); @@ -128,7 +119,7 @@ function __sortGraph(_list, _nodeList) { #region ds_list_add(_list, _node); _node.topoSorted = true; - if(is_instanceof(_node, Node_Collection)) + if(is_instanceof(_node, Node_Collection) && !_node.managedRenderOrder) __sortGraph(_list, _node.nodes); } else { ds_stack_push(_st, _node); @@ -138,6 +129,22 @@ function __sortGraph(_list, _nodeList) { #region } } #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(array_exists(global.group_io, instanceof(_node))) { 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 non-renderActive [{_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.rendered && !_node.isActiveDynamic()) { LOG_IF(global.FLAG.render == 1, $"Skip rendered static [{_node.internalName}]"); 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}] =============================="); @@ -151,7 +158,7 @@ function Render(partial = false, runAction = false) { #region var rendering = noone; var error = 0; - var reset_all = !partial || ALWAYS_FULL; + var reset_all = !partial; if(reset_all) { var _key = ds_map_find_first(PROJECT.nodeMap); @@ -174,23 +181,10 @@ function Render(partial = false, runAction = false) { #region for( var i = 0, n = ds_list_size(PROJECT.nodeTopo); i < n; i++ ) { var _node = PROJECT.nodeTopo[| i]; - - if(is_undefined(_node)) { LOG_IF(global.FLAG.render == 1, $"Skip undefiend [{_node}]"); continue; } - if(!is_instanceof(_node, Node)) { LOG_IF(global.FLAG.render == 1, $"Skip non-node [{_node}]"); continue; } _node.render_time = 0; - if(array_exists(global.group_io, instanceof(_node))) { - LOG_IF(global.FLAG.render == 1, $"Skip group IO [{_node.internalName}]"); continue; } - - if(!_node.active) { LOG_IF(global.FLAG.render == 1, $"Skip inactive [{_node.internalName}]"); continue; } - if(!_node.isRenderActive()) { LOG_IF(global.FLAG.render == 1, $"Skip non-renderActive [{_node.internalName}]"); continue; } - if(!_node.attributes.update_graph) { LOG_IF(global.FLAG.render == 1, $"Skip non-auto update [{_node.internalName}]"); continue; } - if(__nodeManualManaged(_node)) { LOG_IF(global.FLAG.render == 1, $"Skip in-loop [{_node.internalName}]"); continue; } - - if(_node.passiveDynamic) { - _node.forwardPassiveDynamic(); LOG_IF(global.FLAG.render == 1, $"Skip passive dynamic [{_node.internalName}]"); continue; } - - if(_node.rendered && !_node.isActiveDynamic()) { LOG_IF(global.FLAG.render == 1, $"Skip rendered static [{_node.internalName}]"); continue; } + if(!__nodeIsRenderLeaf(_node)) + continue; LOG_IF(global.FLAG.render == 1, $" Found leaf [{_node.internalName}]"); RENDER_QUEUE.enqueue(_node);