Partial rendering for animation.

This commit is contained in:
MakhamDev 2023-10-02 15:45:30 +07:00
parent 387105fb53
commit abffaecb0d
23 changed files with 96 additions and 68 deletions

View file

@ -40,7 +40,9 @@
TOOLTIP = "";
DRAGGING = noone;
KEYBOARD_STRING = "";
RENDER_QUEUE = new Queue();
RENDER_ORDER = [];
globalvar AUTO_SAVE_TIMER;
AUTO_SAVE_TIMER = 0;
@ -78,7 +80,7 @@
});
addHotkey("", "Render all", vk_f5, MOD_KEY.none, function() {
UPDATE |= RENDER_TYPE.full;
RENDER_ALL_REORDER
});
addHotkey("", "Close file", "Q", MOD_KEY.ctrl, function() { PANEL_GRAPH.close(); });

View file

@ -80,6 +80,9 @@ _HOVERING_ELEMENT = noone;
//physics_pause_enable(true);
DEF_SURFACE_RESET();
if(UPDATE_RENDER_ORDER) ResetAllNodesRender();
UPDATE_RENDER_ORDER = false;
if(PROJECT.active) {
var _k = ds_map_find_first(PROJECT.nodeMap);
var _a = ds_map_size(PROJECT.nodeMap);
@ -91,7 +94,11 @@ _HOVERING_ELEMENT = noone;
if(PROJECT.animator.is_playing || PROJECT.animator.rendering) {
if(PROJECT.animator.frame_progress) {
__addon_preAnim();
Render();
if(PROJECT.animator.current_frame == 0)
ResetAllNodesRender();
Render(true);
__addon_postAnim();
}
PROJECT.animator.frame_progress = false;

View file

@ -403,7 +403,7 @@ function __Node_3D_Extrude(_x, _y, _group = noone) : Node_Processor(_x, _y, _gro
mesh_generating = false;
mesh_genetated = true;
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
outputs[| 3].setValue(vertexObjects);
}
}

View file

@ -47,7 +47,7 @@
frame_progress = true;
if(resetTime)
time_since_last_frame = 0;
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
} else
frame_progress = false;
}

View file

@ -130,7 +130,8 @@ function __APPEND_MAP(_map, context = PANEL_GRAPH.getCurrentContext()) {
APPENDING = false;
PANEL_ANIMATION.updatePropertyList();
UPDATE |= RENDER_TYPE.full;
RENDER_ALL_REORDER
if(struct_has(_map, "metadata")) {
var meta = _map.metadata;

View file

@ -119,7 +119,6 @@
HOTKEY_CONTEXT[| 0] = "";
globalvar CURSOR, TOOLTIP, DRAGGING, DIALOG_DEPTH_HOVER;
globalvar UPDATE, RENDER_QUEUE;
#endregion
#region inputs

View file

@ -236,7 +236,7 @@ function __LOAD_PATH(path, readonly = false, safe_mode = false, override = false
log_warning("LOAD, connect", exception_print(e));
}
Render();
RENDER_ALL_REORDER
LOADING = false;
PROJECT.modified = false;

View file

@ -408,13 +408,16 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
static focusStep = function() {}
static inspectorStep = function() {}
static getInputData = function(index, def = 0) { return array_safe_get(inputs_data, index, def); }
static getInputData = function(index, def = 0) { #region
gml_pragma("forceinline");
return array_safe_get(inputs_data, index, def);
} #endregion
static getInputs = function() { #region
inputs_data = array_create(ds_list_size(inputs));
inputs_data = array_create(ds_list_size(inputs), undefined);
for(var i = 0; i < ds_list_size(inputs); i++)
inputs_data[i] = inputs[| i].getValue();
inputs_data[i] = inputs[| i].getValue(,,, true);
} #endregion
static doUpdate = function() { #region
@ -425,24 +428,17 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
LOG_BLOCK_START();
LOG_IF(global.FLAG.render, $">>>>>>>>>> DoUpdate called from {internalName} <<<<<<<<<<");
var t = get_timer();
var _hash = input_hash;
getInputs();
input_hash = md5_string_unicode(json_stringify(inputs_data));
input_hash = md5_string_unicode(string(inputs_data));
anim_last_step = isAnimated() || _hash != input_hash;
if(name == "Shape") print($"{isAnimated()} - {_hash != input_hash}");
try {
var t = get_timer();
if(!is_instanceof(self, Node_Collection))
setRenderStatus(true);
if(anim_last_step)
update(); ///Update only if input hash differs from previous.
if(!is_instanceof(self, Node_Collection))
render_time = get_timer() - t;
if(anim_last_step) update(); ///Update only if input hash differs from previous.
} catch(exception) {
var sCurr = surface_get_target();
while(surface_get_target() != sBase)
@ -451,6 +447,9 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
log_warning("RENDER", exception_print(exception), self);
}
if(!is_instanceof(self, Node_Collection))
render_time = get_timer() - t;
if(!use_cache && PROJECT.onion_skin) {
for( var i = 0; i < ds_list_size(outputs); i++ ) {
if(outputs[| i].type != VALUE_TYPE.surface) continue;
@ -1078,7 +1077,8 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
outputs[| i].destroy();
onDestroy();
UPDATE |= RENDER_TYPE.full;
RENDER_ALL_REORDER
} #endregion
static restore = function() { #region
@ -1513,8 +1513,7 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
static attributeDeserialize = function(attr) { #region
struct_override(attributes, attr);
}
#endregion
} #endregion
static postDeserialize = function() {}
static processDeserialize = function() {}
@ -1631,4 +1630,6 @@ function Node(_x, _y, _group = PANEL_GRAPH.getCurrentContext()) : __Node_Base(_x
return surface_rgba8unorm;
return surface_get_format(_s);
} #endregion
static toString = function() { return $"PixelComposerNode: {node_id}[{internalName}] {input_hash}"; }
}

View file

@ -44,7 +44,7 @@ function Node_DynaSurf(_x, _y, _group = noone) : Node_Collection(_x, _y, _group)
_surH.inputs[| 0].setFrom(_input.outputs[| 0]);
_outH.inputs[| 0].setFrom(_surH.outputs[| 0]);
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
} #endregion
static setRenderStatus = function(result) { #region

View file

@ -570,7 +570,7 @@ function Node_Export(_x, _y, _group = noone) : Node(_x, _y, _group) constructor
insp2UpdateIcon = [ THEME.play_all, 0, COLORS._main_value_positive ];
static onInspector1Update = function() { #region
if(isInLoop()) UPDATE |= RENDER_TYPE.full;
if(isInLoop()) RENDER_ALL
else doInspectorAction();
} #endregion

View file

@ -17,7 +17,7 @@ function Node_Feedback(_x, _y, _group = noone) : Node_Collection(_x, _y, _group)
static doStepBegin = function() {
if(!PROJECT.animator.frame_progress) return;
setRenderStatus(false);
UPDATE |= RENDER_TYPE.full; //force full render
RENDER_ALL //force full render
}
static getNextNodes = function() {

View file

@ -21,7 +21,7 @@ function Node_Fluid_Group(_x, _y, _group = noone) : Node_Collection(_x, _y, _gro
RETURN_ON_REST
setRenderStatus(false);
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
}
PATCH_STATIC

View file

@ -20,7 +20,7 @@ function variable_editor(nodeVal) constructor {
if(string_pos(" ", value.name))
noti_warning("Global variable name can't have space.");
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
});
vb_range = new vectorBox(2, function(index, val) {
@ -39,7 +39,7 @@ function variable_editor(nodeVal) constructor {
disp_index = 0;
refreshInput();
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
} );
sc_type.update_hover = false;
@ -47,7 +47,7 @@ function variable_editor(nodeVal) constructor {
disp_index = val;
refreshInput();
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
} );
sc_disp.update_hover = false;
@ -190,7 +190,7 @@ function Node_Global(_x = 0, _y = 0) : __Node_Base(_x, _y) constructor {
anim_priority = -999;
static valueUpdate = function(index) {
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
}
static createValue = function() {

View file

@ -290,7 +290,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
if(mouse_release(mb_left)) {
transform_type = 0;
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
UNDO_HOLDING = false;
}
} else if(drag_point > -1) {
@ -550,7 +550,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
if(mouse_release(mb_left)) {
drag_point = -1;
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
UNDO_HOLDING = false;
}
}
@ -812,7 +812,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
drag_point_sx = (_mx - _x) / _s;
drag_point_sy = (_my - _y) / _s;
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
}
#endregion
}

View file

@ -15,7 +15,7 @@ function Node_Pixel_Builder(_x, _y, _group = noone) : Node_Collection(_x, _y, _g
if(!LOADING && !APPENDING && !CLONING) {
var input = nodeBuild("Node_PB_Layer", -256, -32, self);
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
}
static getNextNodes = function() {

View file

@ -21,7 +21,7 @@ function Node_Strand_Group(_x, _y, _group = noone) : Node_Collection(_x, _y, _gr
RETURN_ON_REST
setRenderStatus(false);
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
}
PATCH_STATIC

View file

@ -102,7 +102,7 @@ function Node_Tunnel_In(_x, _y, _group = noone) : Node(_x, _y, _group) construct
k = ds_map_find_next(TUNNELS_IN_MAP, k);
}
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
}
static step = function() {

View file

@ -60,7 +60,7 @@ function Node_Tunnel_Out(_x, _y, _group = noone) : Node(_x, _y, _group) construc
TUNNELS_OUT[? node_id] = _key;
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
}
static step = function() {

View file

@ -1283,7 +1283,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
global.cache_call++;
if(useCache && use_cache) {
var cache_hit = cache_value[0];
cache_hit &= (!is_anim && value_from == noone) || cache_value[1] == _time;
cache_hit &= !isAnimated() || cache_value[1] == _time;
cache_hit &= cache_value[2] != undefined;
cache_hit &= cache_value[3] == applyUnit;
cache_hit &= connect_type == JUNCTION_CONNECT.input;
@ -1592,8 +1592,8 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
if(_update) node.valueUpdate(self.index);
node.clearCacheForward();
if(fullUpdate) UPDATE |= RENDER_TYPE.full;
else UPDATE |= RENDER_TYPE.partial;
if(fullUpdate) RENDER_ALL
else RENDER_PARTIAL
if(!LOADING) PROJECT.modified = true;
}
@ -1702,6 +1702,7 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
PROJECT.modified = true;
}
UPDATE_RENDER_ORDER = true;
return true;
} #endregion
@ -1716,6 +1717,8 @@ function NodeValue(_name, _node, _connect, _type, _value, _tooltip = "") constru
node.clearCacheForward();
PROJECT.modified = true;
UPDATE_RENDER_ORDER = true;
return false;
} #endregion

View file

@ -208,7 +208,7 @@ function Node_WAV_File_Read(_x, _y, _group = noone) : Node(_x, _y, _group) const
readSoundComplete();
checkPreview(true);
UPDATE |= RENDER_TYPE.full;
RENDER_ALL
}
insp2UpdateIcon[1] = attributes.play;

View file

@ -141,9 +141,7 @@ function Panel_Menu() : PanelContent() constructor {
]],
[ __txt("Rendering"), [
menuItem(__txtx("panel_menu_render_all_nodes", "Render all nodes"), function() {
for(var i = 0; i < ds_list_size(PROJECT.nodes); i++)
PROJECT.nodes[| i].triggerRender();
UPDATE |= RENDER_TYPE.full;
RENDER_ALL_REORDER
}, [ THEME.sequence_control, 1 ], ["", "Render all"]),
menuItem(__txtx("panel_menu_execute_exports", "Execute all export nodes"), function() {
var key = ds_map_find_first(PROJECT.nodeMap);

View file

@ -5,11 +5,18 @@ enum RENDER_TYPE {
}
#region globalvar
global.FLAG.render = false;
globalvar UPDATE, RENDER_QUEUE, RENDER_ORDER, UPDATE_RENDER_ORDER;
UPDATE_RENDER_ORDER = false;
global.FLAG.render = true;
global.group_inputs = [ "Node_Group_Input", "Node_Feedback_Input", "Node_Iterator_Input", "Node_Iterator_Each_Input" ];
#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) {
function __nodeLeafList(_list) { #region
var nodes = [];
var nodeNames = [];
@ -27,9 +34,9 @@ function __nodeLeafList(_list) {
LOG_LINE_IF(global.FLAG.render, $"Push node {nodeNames} to stack");
return nodes;
}
} #endregion
function __nodeIsLoop(_node) {
function __nodeIsLoop(_node) { #region
switch(instanceof(_node)) {
case "Node_Iterate" :
case "Node_Iterate_Each" :
@ -38,19 +45,30 @@ function __nodeIsLoop(_node) {
return true;
}
return false;
}
} #endregion
function __nodeInLoop(_node) {
function __nodeInLoop(_node) { #region
var gr = _node.group;
while(gr != noone) {
if(__nodeIsLoop(gr)) return true;
gr = gr.group;
}
return false;
}
} #endregion
function Render(partial = false, runAction = false) {
var t = current_time;
function ResetAllNodesRender() { #region
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);
}
} #endregion
function Render(partial = false, runAction = false) { #region
var t = get_timer();
LOG_BLOCK_START();
LOG_IF(global.FLAG.render, $"============================== RENDER START [frame {PROJECT.animator.current_frame}] ==============================");
@ -69,7 +87,7 @@ function Render(partial = false, runAction = false) {
_key = ds_map_find_next(PROJECT.nodeMap, _key);
}
}
// get leaf node
RENDER_QUEUE.clear();
var key = ds_map_find_first(PROJECT.nodeMap);
@ -122,8 +140,9 @@ function Render(partial = false, runAction = false) {
rendering.doUpdate();
var nextNodes = rendering.getNextNodes();
for( var i = 0, n = array_length(nextNodes); i < n; i++ )
for( var i = 0, n = array_length(nextNodes); i < n; i++ ) {
RENDER_QUEUE.enqueue(nextNodes[i]);
}
if(runAction && rendering.hasInspector1Update())
rendering.inspector1Update();
@ -135,20 +154,20 @@ function Render(partial = false, runAction = false) {
noti_warning(exception_print(e));
}
LOG_IF(global.FLAG.render, "=== RENDER COMPLETE IN {" + string(current_time - t) + "ms} ===\n");
LOG_IF(global.FLAG.render, $"=== RENDER COMPLETE IN {(get_timer() - t) / 1000} ms ===\n");
LOG_END();
}
} #endregion
function __renderListReset(list) {
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) {
function RenderList(list) { #region
LOG_BLOCK_START();
LOG_IF(global.FLAG.render, "=============== RENDER LIST START ===============");
var queue = ds_queue_create();
@ -212,9 +231,9 @@ function RenderList(list) {
LOG_END();
ds_queue_destroy(queue);
}
} #endregion
function RenderListAction(list, context = PANEL_GRAPH.getCurrentContext()) {
function RenderListAction(list, context = PANEL_GRAPH.getCurrentContext()) { #region
printIf(global.FLAG.render, "=== RENDER LIST ACTION START [frame " + string(PROJECT.animator.current_frame) + "] ===");
try {
@ -272,4 +291,4 @@ function RenderListAction(list, context = PANEL_GRAPH.getCurrentContext()) {
} catch(e) {
noti_warning(exception_print(e));
}
}
} #endregion

View file

@ -1,14 +1,12 @@
#macro struct_has variable_struct_exists
function struct_override(original, override, excludes = []) {
function struct_override(original, override) {
var args = variable_struct_get_names(override);
for( var i = 0, n = array_length(args); i < n; i++ ) {
var _key = args[i];
if(!struct_has(original, _key)) continue;
if(is_callable(original[$ _key])) continue;
if(array_exists(excludes, _key)) continue;
original[$ _key] = override[$ _key];
}