Overhaul and improve spectator unit tree UX

The old method of refreshing the tree on each update would reset all expanded/collapsed nodes. Now the code will cull any units/groups/sides no longer spectatable from the list and cache the ones that are still valid. The cached data is then used to populate the list with new units.

Add coloured unit icons beside units in the list for quick user reference of side and type.

Store group netIDs in respective nodes for possible use in code.
This commit is contained in:
SilentSpike 2015-08-07 00:05:21 +01:00
parent bcb21b782e
commit 4c9b6e94cf
2 changed files with 55 additions and 34 deletions

View File

@ -158,9 +158,9 @@ class GVAR(interface) {
class unitTree: RscTree { class unitTree: RscTree {
idc = IDC_UNIT; idc = IDC_UNIT;
x = safeZoneX; x = safeZoneX;
y = safeZoneY + TOOL_H * 2; y = safeZoneY + TOOL_H * 6;
w = TOOL_W * 2; w = TOOL_W * 2;
h = safeZoneH - TOOL_H * 6; h = safeZoneH - TOOL_H * 13;
sizeEx = H_PART(0.8); sizeEx = H_PART(0.8);
borderSize = 1; borderSize = 1;
colorBorder[] = {COL_FORE}; colorBorder[] = {COL_FORE};

View File

@ -367,17 +367,43 @@ switch (toLower _mode) do {
}; };
case "onunitsupdate": { case "onunitsupdate": {
_args params ["_tree"]; _args params ["_tree"];
private ["_curSelData","_cachedGrps","_cachedSides","_grp","_side","_sNode","_gNode","_uNode"]; private ["_cachedUnits","_cachedGrps","_cachedSides","_s","_g","_grp","_u","_unit","_side"];
// Cache current selection // Cache existing group and side nodes and cull removed data
_curSelData = _tree tvData (tvCurSel _tree); _cachedUnits = [];
// Clear the tree
tvClear _tree;
// Update the tree from the unit list
_cachedGrps = []; _cachedGrps = [];
_cachedSides = []; _cachedSides = [];
for "_s" from 0 to ((_tree tvCount []) - 1) do {
for "_g" from 0 to ((_tree tvCount [_s]) - 1) do {
_grp = groupFromNetID (_tree tvData [_s,_g]);
if (_grp in GVAR(groupList)) then {
_cachedGrps pushBack _grp;
_cachedGrps pushBack _g;
for "_u" from 0 to ((_tree tvCount [_s,_g])) do {
_unit = objectFromNetId (_tree tvData [_s,_g,_u]);
if (_unit in GVAR(unitList)) then {
_cachedUnits pushBack _unit;
} else {
_tree tvDelete [_s,_g,_u];
};
};
} else {
_tree tvDelete [_s,_g];
};
};
if ((_tree tvCount [_s]) > 0) then {
_cachedSides pushBack (_tree tvText [_s]);
_cachedSides pushBack _s;
} else {
_tree tvDelete [_s];
};
};
// Update the tree from the unit list
{ {
_grp = group _x; _grp = group _x;
_side = [side _grp] call BIS_fnc_sideName; _side = [side _grp] call BIS_fnc_sideName;
@ -385,47 +411,42 @@ switch (toLower _mode) do {
// Use correct side node // Use correct side node
if !(_side in _cachedSides) then { if !(_side in _cachedSides) then {
// Add side node // Add side node
_sNode = _tree tvAdd [[], _side]; _s = _tree tvAdd [[], _side];
_tree tvExpand [_s];
_cachedSides pushBack _side; _cachedSides pushBack _side;
_cachedSides pushBack _sNode; _cachedSides pushBack _s;
} else { } else {
// If side already processed, use existing node // If side already processed, use existing node
_sNode = _cachedSides select ((_cachedSides find _side) + 1); _s = _cachedSides select ((_cachedSides find _side) + 1);
}; };
// Use correct group node // Use correct group node
if !(_grp in _cachedGrps) then { if !(_grp in _cachedGrps) then {
// Add group node // Add group node
_gNode = _tree tvAdd [[_sNode], groupID _grp]; _g = _tree tvAdd [[_s], groupID _grp];
_tree tvSetData [[_s,_g], netID _grp];
_cachedGrps pushBack _grp; _cachedGrps pushBack _grp;
_cachedGrps pushBack _gNode; _cachedGrps pushBack _g;
} else { } else {
// If group already processed, use existing node // If group already processed, use existing node
_gNode = _cachedGrps select ((_cachedGrps find _grp) + 1); _g = _cachedGrps select ((_cachedGrps find _grp) + 1);
}; };
_uNode = _tree tvAdd [[_sNode,_gNode], GETVAR(_x,GVAR(uName),"")]; _u = _tree tvAdd [[_s,_g], GETVAR(_x,GVAR(uName),"")];
_tree tvSetData [[_sNode,_gNode,_uNode], netID _x]; _tree tvSetData [[_s,_g,_u], netID _x];
_tree tvSetPicture [[_s,_g,_u], GETVAR(_x,GVAR(uIcon),"")];
_tree tvSetPictureColor [[_s,_g,_u], GETVAR(_grp,GVAR(gColor),[ARR_4(1,1,1,1)])];
// Preserve the previous selection _tree tvSort [[_s,_g],false];
if (_curSelData == (_tree tvData [_sNode,_gNode,_uNode])) then { } forEach (GVAR(unitList) - _cachedUnits);
_tree tvSetCurSel [_sNode,_gNode,_uNode];
};
_tree tvSort [[_sNode,_gNode],false];
_tree tvExpand [_sNode,_gNode];
} forEach GVAR(unitList);
{
if (typeName _x == "SCALAR") then {
_tree tvSort [[_x],false];
_tree tvExpand [_x];
};
} forEach _cachedSides;
_tree tvSort [[],false]; _tree tvSort [[],false];
if ((_tree tvCount []) <= 0) then {
_tree tvAdd [[], localize LSTRING(units_none)];
};
}; };
// Map events // Map events
case "onmapclick": { case "onmapclick": {
@ -439,7 +460,7 @@ switch (toLower _mode) do {
[nil,nil,nil, _newPos] call FUNC(setCameraAttributes); [nil,nil,nil, _newPos] call FUNC(setCameraAttributes);
}; };
}; };
// Break from interface for eexternal events // Break from interface for external events
case "escape": { case "escape": {
_args params ["_display"]; _args params ["_display"];
private "_dlg"; private "_dlg";