From d043a471b32c4e057fd273b8e0e2221631e33ad5 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Thu, 16 Jul 2015 11:15:33 +0100 Subject: [PATCH] Improving unit list handling --- addons/spectator/ACE_Settings.hpp | 4 +- addons/spectator/XEH_preInit.sqf | 5 ++ .../functions/fnc_handleInterface.sqf | 12 +-- addons/spectator/functions/fnc_handleTree.sqf | 87 +++++++++++++++++++ .../functions/fnc_moduleSpectator.sqf | 2 +- .../spectator/functions/fnc_updateUnits.sqf | 72 ++++++++++----- 6 files changed, 152 insertions(+), 30 deletions(-) create mode 100644 addons/spectator/functions/fnc_handleTree.sqf diff --git a/addons/spectator/ACE_Settings.hpp b/addons/spectator/ACE_Settings.hpp index 88f4ebfad6..46cb4b5a89 100644 --- a/addons/spectator/ACE_Settings.hpp +++ b/addons/spectator/ACE_Settings.hpp @@ -7,7 +7,7 @@ class ACE_Settings { value = 0; typeName = "BOOL"; }; - class GVAR(AI) { + class GVAR(allowAI) { value = 0; typeName = "BOOL"; }; @@ -23,4 +23,4 @@ class ACE_Settings { value = 0; typeName = "BOOL"; }; -}; \ No newline at end of file +}; diff --git a/addons/spectator/XEH_preInit.sqf b/addons/spectator/XEH_preInit.sqf index 52aa5db1e0..9e71c9bdc5 100644 --- a/addons/spectator/XEH_preInit.sqf +++ b/addons/spectator/XEH_preInit.sqf @@ -7,9 +7,14 @@ PREP(handleInterface); PREP(handleKilled); PREP(handleMouse); PREP(handleRespawn); +PREP(handleTree); PREP(moduleSpectator); PREP(setSpectator); PREP(updateUnits); PREP(updateView); +GVAR(unitList) = []; +GVAR(unitBlacklist) = []; +GVAR(unitWhitelist) = []; + ADDON = true; diff --git a/addons/spectator/functions/fnc_handleInterface.sqf b/addons/spectator/functions/fnc_handleInterface.sqf index 3a16c68692..d06c9cca14 100644 --- a/addons/spectator/functions/fnc_handleInterface.sqf +++ b/addons/spectator/functions/fnc_handleInterface.sqf @@ -43,7 +43,7 @@ switch (toLower _mode) do { GVAR(camDolly) = [false,false,false,false]; GVAR(camFocus) = [-1,-1]; GVAR(camFOV) = 0.7; - GVAR(camSpeed) = 0.8; + GVAR(camSpeed) = 0.1; GVAR(camTilt) = -60; GVAR(camZoom) = 3; GVAR(gunCam) = false; @@ -54,7 +54,6 @@ switch (toLower _mode) do { GVAR(mouseDelta) = [0.5,0.5]; GVAR(mousePos) = [0.5,0.5]; GVAR(mousePosOld) = [0.5,0.5]; - GVAR(unitList) = []; // Initalize the camera view GVAR(camera) = "Camera" camCreate GVAR(camPos); @@ -68,6 +67,9 @@ switch (toLower _mode) do { // Handle camera movement [FUNC(handleCamera), 0] call CBA_fnc_addPerFrameHandler; + // Populate the unit list + [allUnits] call FUNC(updateUnits); + // Create the dialog createDialog QGVAR(overlay); @@ -109,7 +111,6 @@ switch (toLower _mode) do { GVAR(mouseDelta) = nil; GVAR(mousePos) = nil; GVAR(mousePosOld) = nil; - GVAR(unitList) = nil; // Reset nametag settings if (["ace_nametags"] call EFUNC(common,isModLoaded)) then { @@ -134,10 +135,11 @@ switch (toLower _mode) do { // Set text values (_display displayCtrl IDC_FOCUS) ctrlSetText str(GVAR(camFocus)); (_display displayCtrl IDC_FOV) ctrlSetText str(GVAR(camFOV)); + (_display displayCtrl IDC_SPEED) ctrlSetText format ["%1 m/s",GVAR(camSpeed)]; (_display displayCtrl IDC_VIEW) ctrlSetText (["FREE","FIRST","THIRD"] select GVAR(camMode)); - // Populate unit tree - call FUNC(updateUnits); + // Keep unit tree up to date + call FUNC(handleTree); // Hacky way to enable keybindings //_display displayAddEventHandler ["KeyUp", {[_this,'keyup'] call CBA_events_fnc_keyHandler}]; diff --git a/addons/spectator/functions/fnc_handleTree.sqf b/addons/spectator/functions/fnc_handleTree.sqf new file mode 100644 index 0000000000..593b1a5cb1 --- /dev/null +++ b/addons/spectator/functions/fnc_handleTree.sqf @@ -0,0 +1,87 @@ +/* + * Author: SilentSpike + * Tracks the units in the unit tree and updates it according to their status + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * [] call ace_spectator_fnc_handleTree; + * + * Public: No + */ + +#include "script_component.hpp" + +// Remove any existing PFH +if !(isNil QGVAR(treePFH)) then { + [GVAR(treePFH)] call CBA_fnc_removePerFrameHandler; + GVAR(treePFH) = nil; +}; + +// Fetch tree +disableSerialization; +_display = GETUVAR(GVAR(display),displayNull); +_ctrl = _display displayCtrl IDC_TREE; + +// Clear the tree +_ctrl tvDelete []; + +// Update the tree +_cachedGrps = []; +{ + _grp = group _x; + _node = 0; + // If group already exists, find existing node + if !(_grp in _cachedGrps) then { + _side = [west,east,resistance,civilian,sideLogic] find (side _grp); + _node = _ctrl tvCount []; + + _ctrl tvAdd [[], groupID _grp]; + _ctrl tvSetValue [[_node], _side]; + + _cachedGrps pushBack _grp; + } else { + _node = _cachedGrps find _grp; + }; + + _index = _ctrl tvCount [_node]; + + _ctrl tvAdd [[_node], name _x]; + _ctrl tvSetData [[_node,_index], netID _x]; + + _ctrl tvSort [[_node],false]; +} forEach GVAR(unitList); + +// Sort group nodes by side +_ctrl tvSortByValue [[],false]; + +// Keep tree up to date +GVAR(treePFH) = [{ + // Kill PFH when display is closed + if (isNull (GETUVAR(GVAR(display),displayNull))) exitWith { + [_this select 1] call CBA_fnc_removePerFrameHandler; + GVAR(treePFH) = nil; + }; + + disableSerialization; + _display = GETUVAR(GVAR(display),displayNull); + _ctrl = _display displayCtrl IDC_TREE; + + _nodes = (_ctrl tvCount []) - 1; + for "_n" from 0 to _nodes do { + _units = (_ctrl tvCount [_n]) - 1; + for "_i" from 0 to _units do { + _netID = _ctrl tvData [_n,_i]; + _unit = objectFromNetId _netID; + + if (isNull _unit || !alive _unit) then { + _ctrl tvDelete [_n,_i]; + GVAR(unitList) = GVAR(unitList) - [_unit]; + }; + }; + }; +}, 5] call CBA_fnc_addPerFrameHandler; diff --git a/addons/spectator/functions/fnc_moduleSpectator.sqf b/addons/spectator/functions/fnc_moduleSpectator.sqf index 8fe49d66f2..7a85f40fcb 100644 --- a/addons/spectator/functions/fnc_moduleSpectator.sqf +++ b/addons/spectator/functions/fnc_moduleSpectator.sqf @@ -21,7 +21,7 @@ if !(_activated) exitWith {}; [_logic, QGVAR(enabled), "SpectatorEnabled"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(limitSide), "SpectatorPlayerSide"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(AI), "SpectatorAI"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(allowAI), "SpectatorAI"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(tracking), "SpectatorTracking"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(modulePos), "SpectatorPos"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(endMission), "SpectatorEnd"] call EFUNC(common,readSettingFromModule); diff --git a/addons/spectator/functions/fnc_updateUnits.sqf b/addons/spectator/functions/fnc_updateUnits.sqf index f2feeb948f..50d0811e58 100644 --- a/addons/spectator/functions/fnc_updateUnits.sqf +++ b/addons/spectator/functions/fnc_updateUnits.sqf @@ -1,29 +1,57 @@ +/* + * Author: SilentSpike + * Updates the list of units available to spectate via addition/subtraction + * + * Arguments: + * 0: Units to add to the list + * 1: Add or remove units + * 2: Permanent change (force add/remove) + * + * Return Value: + * None + * + * Example: + * [allUnits,true] call ace_spectator_fnc_updateUnits + * + * Public: Yes + */ + #include "script_component.hpp" -// Remove dead and null units -GVAR(unitList) - [objNull]; -GVAR(unitList) - allDead; +_newUnits = _this select 0; +_append = if (count _this > 1) then {_this select 1} else {true}; +_permanent = if (count _this > 2) then {_this select 2} else {false}; -// Fetch new units for list -{ - if ( - (simulationEnabled _x) && - {(side _x) in [west,east,resistance,civilian] } && - //{!isObjectHidden _unit} && // (currently dev branch only) - {!(_x getVariable [QGVAR(isSpectator), false])} // Who watches the watchmen? - ) then { - GVAR(unitList) pushBack _x; +if (_permanent) then { + if (_append) then { + GVAR(unitBlacklist) = GVAR(unitBlacklist) - _newUnits; + GVAR(unitWhitelist) append _newUnits; + } else { + GVAR(unitWhitelist) = GVAR(unitWhitelist) - _newUnits; + GVAR(unitBlacklist) append _newUnits; }; -} forEach (allUnits - GVAR(unitList)); + _newUnits = []; +}; -disableSerialization; -_display = GETUVAR(GVAR(display),displayNull); -_ctrl = _display displayCtrl IDC_TREE; +if (_append) then { + _newUnits = _newUnits - GVAR(unitList); -// Clear the tree -_ctrl tvCollapse []; + // Append only valid units to the list + { + if ( + (_x isKindOf "CAManBase") && + {(side _x) in [west,east,resistance,civilian]} && + {(isPlayer _x) || GVAR(allowAI)} && // AI restriction + {(simulationEnabled _x)} && //!isObjectHidden _unit} && // (currently dev branch only) + {!(_x getVariable [QGVAR(isSpectator), false])} // Who watches the watchmen? + ) then { + GVAR(unitList) pushBack _x; + }; + } forEach _newUnits; +} else { + GVAR(unitList) = GVAR(unitList) - _newUnits; +}; -// Update the tree -{ - // _ctrl tvAdd [[,_forEachIndex], name _x]; -} forEach GVAR(unitList); +// Apply whitelist and blacklist +GVAR(unitList) append GVAR(unitWhitelist); +GVAR(unitList) = GVAR(unitList) - GVAR(unitBlacklist);