From 50df691493ff87b89d5971ff74619d71f68ccd83 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 10 Jul 2023 19:36:16 +0200 Subject: [PATCH] Added n frame delay --- addons/common/fnc_execNextFrame.sqf | 17 ++++++++--- addons/common/init_perFrameHandler.sqf | 40 ++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/addons/common/fnc_execNextFrame.sqf b/addons/common/fnc_execNextFrame.sqf index c81cc92b9f..e3248e91fb 100644 --- a/addons/common/fnc_execNextFrame.sqf +++ b/addons/common/fnc_execNextFrame.sqf @@ -3,11 +3,12 @@ Function: CBA_fnc_execNextFrame Description: - Executes a code once in non sched environment on the next frame. + Executes a code once in non sched environment delayed by n frames. Parameters: _function - The function to run. - _args - Parameters passed to the function executing. This will be the same array every execution. [optional] + _args - Parameters passed to the function executing. This will be the same array every execution. (optional, default: []) + _frames - The number of frames the execution will be delayed by. (optional, default: 1) Returns: Nothing @@ -21,9 +22,17 @@ Author: esteldunedain and PabstMirror, donated from ACE3 ---------------------------------------------------------------------------- */ -params [["_function", {}, [{}]], ["_args", []]]; +params [["_function", {}, [{}]], ["_args", []], ["_frames", 1, [0]]]; -if (diag_frameno != GVAR(nextFrameNo)) then { +// Do not allow negative or 0 frame delays +_frames = _frames max 1; + +if (_frames > 1) exitWith { + GVAR(nextFrameNBuffer) pushBack [diag_frameNo + _frames, _args, _function]; + GVAR(nextFrameNBufferIsSorted) = false; +}; + +if (diag_frameNo != GVAR(nextFrameNo)) then { GVAR(nextFrameBufferA) pushBack [_args, _function]; } else { GVAR(nextFrameBufferB) pushBack [_args, _function]; diff --git a/addons/common/init_perFrameHandler.sqf b/addons/common/init_perFrameHandler.sqf index 795211f423..141640cea2 100644 --- a/addons/common/init_perFrameHandler.sqf +++ b/addons/common/init_perFrameHandler.sqf @@ -9,7 +9,9 @@ GVAR(lastTickTime) = diag_tickTime; GVAR(waitAndExecArray) = []; GVAR(waitAndExecArrayIsSorted) = false; -GVAR(nextFrameNo) = diag_frameno + 1; +GVAR(nextFrameNBuffer) = []; +GVAR(nextFrameNBufferAIsSorted) = false; +GVAR(nextFrameNo) = diag_frameNo + 1; GVAR(nextFrameBufferA) = []; GVAR(nextFrameBufferB) = []; GVAR(waitUntilAndExecArray) = []; @@ -22,9 +24,9 @@ GVAR(waitUntilAndExecArray) = []; // frame number does not match expected; can happen between pre and postInit, save-game load and on closing map // need to manually set nextFrameNo, so new items get added to buffer B and are not executed this frame - if (diag_frameno != GVAR(nextFrameNo)) then { - TRACE_2("frame mismatch",diag_frameno,GVAR(nextFrameNo)); - GVAR(nextFrameNo) = diag_frameno; + if (diag_frameNo != GVAR(nextFrameNo)) then { + TRACE_2("frame mismatch",diag_frameNo,GVAR(nextFrameNo)); + GVAR(nextFrameNo) = diag_frameNo; }; // Execute per frame handlers @@ -44,7 +46,9 @@ GVAR(waitUntilAndExecArray) = []; GVAR(waitAndExecArray) sort true; GVAR(waitAndExecArrayIsSorted) = true; }; + private _delete = false; + { if (_x select 0 > CBA_missionTime) exitWith {}; @@ -54,20 +58,45 @@ GVAR(waitUntilAndExecArray) = []; GVAR(waitAndExecArray) set [_forEachIndex, objNull]; _delete = true; } forEach GVAR(waitAndExecArray); + if (_delete) then { GVAR(waitAndExecArray) = GVAR(waitAndExecArray) - [objNull]; _delete = false; }; + // Execute the exec next n frame functions + if (!GVAR(nextFrameNBufferIsSorted)) then { + GVAR(nextFrameNBuffer) sort true; + GVAR(nextFrameNBufferIsSorted) = true; + }; + + { + if (_x select 0 > GVAR(nextFrameNo)) exitWith {}; + + (_x select 1) call (_x select 2); + + // Mark the element for deletion so it's not executed ever again + GVAR(nextFrameNBuffer) set [_forEachIndex, objNull]; + _delete = true; + } forEach GVAR(nextFrameNBuffer); + + if (_delete) then { + GVAR(nextFrameNBuffer) = GVAR(nextFrameNBuffer) - [objNull]; + _delete = false; + }; + + // Execute the exec next frame functions { (_x select 0) call (_x select 1); } forEach GVAR(nextFrameBufferA); + // Swap double-buffer: GVAR(nextFrameBufferA) = GVAR(nextFrameBufferB); GVAR(nextFrameBufferB) = []; - GVAR(nextFrameNo) = diag_frameno + 1; + + GVAR(nextFrameNo) = diag_frameNo + 1; // Execute the waitUntilAndExec functions: @@ -81,6 +110,7 @@ GVAR(waitUntilAndExecArray) = []; _delete = true; }; } forEach GVAR(waitUntilAndExecArray); + if (_delete) then { GVAR(waitUntilAndExecArray) = GVAR(waitUntilAndExecArray) - [objNull]; };