Overhaul spectator icon handling and rendering

- Optimize and improve 3D icon drawing
- Combine 2D and 3D PFHs into 1
- Render group icons outside of 200m, unit icons within
- Store list of groups on units update to cut down on what needs to be done each frame
- Change map control type to 100 to remove all default unit icons
- Improve colour caching, group colours don't change, unit colours do
- Remove icon setting, toggling should be at users discretion
This commit is contained in:
SilentSpike 2015-08-06 13:42:31 +01:00
parent 92ef0bfe99
commit bcb21b782e
10 changed files with 90 additions and 86 deletions

View File

@ -19,8 +19,4 @@ class ACE_Settings {
value = 0; value = 0;
values[] = {CSTRING(modes_all), CSTRING(visions_nv), CSTRING(visions_ti), "$STR_Special_None"}; values[] = {CSTRING(modes_all), CSTRING(visions_nv), CSTRING(visions_ti), "$STR_Special_None"};
}; };
class GVAR(unitIcons) {
typeName = "BOOL";
value = 1;
};
}; };

View File

@ -176,12 +176,13 @@ class GVAR(interface) {
}; };
class mapOverlay: RscMapControl { class mapOverlay: RscMapControl {
idc = IDC_MAP; idc = IDC_MAP;
type = 100;
x = safeZoneX; x = safeZoneX;
y = safeZoneY; y = safeZoneY;
w = safeZoneW; w = safeZoneW;
h = safeZoneH; h = safeZoneH;
onMouseButtonDown = QUOTE([ARR_2('onMapClick',_this)] call FUNC(handleInterface)); onMouseButtonDown = QUOTE([ARR_2('onMapClick',_this)] call FUNC(handleInterface));
onDraw = QUOTE([ARR_2('onDraw',_this)] call FUNC(handleInterface)); onDraw = QUOTE(_this call FUNC(handleMap));
}; };
class helpSplash: RscControlsGroupNoScrollbars { class helpSplash: RscControlsGroupNoScrollbars {
idc = IDC_HELP; idc = IDC_HELP;

View File

@ -8,6 +8,7 @@ PREP(handleCamera);
PREP(handleCompass); PREP(handleCompass);
PREP(handleIcons); PREP(handleIcons);
PREP(handleInterface); PREP(handleInterface);
PREP(handleMap);
PREP(handleMouse); PREP(handleMouse);
PREP(handleToolbar); PREP(handleToolbar);
PREP(handleUnits); PREP(handleUnits);
@ -51,5 +52,6 @@ GVAR(showUnit) = true;
GVAR(unitList) = []; GVAR(unitList) = [];
GVAR(unitBlacklist) = []; GVAR(unitBlacklist) = [];
GVAR(unitWhitelist) = []; GVAR(unitWhitelist) = [];
GVAR(groupList) = [];
ADDON = true; ADDON = true;

View File

@ -19,15 +19,20 @@
params ["_unit"]; params ["_unit"];
private ["_color","_icon","_name"]; private ["_color","_icon","_name"];
// Group info only needs to be cached once (groups can't change)
if (isNil { GETVAR((group _unit),GVAR(gColor),nil) }) then {
_color = [side group _unit] call BIS_fnc_sideColor; _color = [side group _unit] call BIS_fnc_sideColor;
SETVAR((group _unit),GVAR(gColor),_color);
};
// Unit info should be updated each time
_icon = getText (configFile >> "CfgVehicles" >> typeOf _unit >> "Icon"); _icon = getText (configFile >> "CfgVehicles" >> typeOf _unit >> "Icon");
_name = [_unit,false] call EFUNC(common,getName); _name = [_unit,false] call EFUNC(common,getName);
// Handle CfgVehicleIcons // Handle CfgVehicleIcons
if isText (configFile >> "CfgVehicleIcons" >> _icon) then { if (isText (configFile >> "CfgVehicleIcons" >> _icon)) then {
_icon = getText (configFile >> "CfgVehicleIcons" >> _icon); _icon = getText (configFile >> "CfgVehicleIcons" >> _icon);
}; };
SETVAR(_unit,GVAR(uColor),_color);
SETVAR(_unit,GVAR(uIcon),_icon); SETVAR(_unit,GVAR(uIcon),_icon);
SETVAR(_unit,GVAR(uName),_name); SETVAR(_unit,GVAR(uName),_name);

View File

@ -1,5 +1,5 @@
/* /*
* Author: SilentSpike * Author: Head, SilentSpike
* Handles rendering the spectator 3D unit icons * Handles rendering the spectator 3D unit icons
* *
* Arguments: * Arguments:
@ -17,41 +17,30 @@
#include "script_component.hpp" #include "script_component.hpp"
// Kill PFH when not in free cam (or display is closed)
if (isNil QGVAR(iconHandler)) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; };
if !(GVAR(showIcons)) exitWith {}; if !(GVAR(showIcons)) exitWith {};
private ["_refPoint","_drawVehicles","_leader","_color","_txt","_unit"];
private ["_cachedVehicles","_unit","_cameraPos","_cameraDir","_lambda","_uPos","_cmd","_txt"]; // Draw groups unless leader is within distance
_cachedVehicles = []; _refPoint = [GVAR(camera),GVAR(camUnit)] select (GVAR(camMode) > 0);
_drawVehicles = [];
{ {
_unit = vehicle _x; _leader = leader _x;
if ((_leader distanceSqr _refPoint) > 40000) then {
_color = GETVAR(_x,GVAR(gColor),[ARR_4(0,0,0,0)]);
_txt = groupID _x;
// Only try each vehicle once drawIcon3D ["\A3\ui_f\data\map\markers\nato\b_inf.paa", _color, _leader modelToWorldVisual [0,0,30], 1, 1, 0, _txt, 2, 0.02];
if !(_unit in _cachedVehicles) then { } else {
_cachedVehicles pushBack _unit; _drawVehicles append (units _x);
};
false
} count GVAR(groupList);
// Within 200m // Draw units for groups within distance
if ((GVAR(camera) distanceSqr _unit) < 40000) then { {
_cameraPos = (positionCameraToWorld [0, 0, 0]) call EFUNC(common,positionToASL); _color = GETVAR((group _x),GVAR(gColor),[ARR_4(0,0,0,0)]);
_cameraDir = ((positionCameraToWorld [0, 0, 1]) call EFUNC(common,positionToASL)) vectorDiff _cameraPos; _txt = ["", GETVAR(_x,GVAR(uName),"")] select (isPlayer _x);
// Quick oclussion test (taken from interact_menu) drawIcon3D ["\A3\ui_f\data\map\markers\military\dot_CA.paa", _color, _x modelToWorldVisual [0,0,3], 0.7, 0.7, 0, _txt, 1, 0.02];
_lambda = ((getPosASL _x) vectorDiff _cameraPos) vectorDotProduct _cameraDir; false
if (_lambda > -1) then { } count (_drawVehicles arrayIntersect GVAR(unitList));
_uPos = worldToScreen (visiblePosition _unit);
// Only draw if onscreen
if ((_uPos select 0 > safeZoneXAbs) && (_uPos select 0 < safeZoneXAbs + safeZoneWAbs)) then {
if ((_uPos select 1 > safeZoneY) && (_uPos select 1 < safeZoneY + safeZoneH)) then {
// Use commander's info if available
_cmd = [_x, effectiveCommander _unit] select ((effectiveCommander _unit) in GVAR(unitList));
_txt = ["", GETVAR(_cmd,GVAR(uName),"")] select (isPlayer _cmd);
drawIcon3D ["\A3\ui_f\data\map\markers\military\dot_CA.paa", GETVAR(_cmd,GVAR(uColor),[ARR_4(0,0,0,0)]), _unit modelToWorldVisual [0,0,3], 0.7, 0.7, 0, _txt, 1, 0.02];
};
};
};
};
};
} forEach GVAR(unitList);

View File

@ -114,6 +114,9 @@ switch (toLower _mode) do {
// Keep unit list and tree up to date // Keep unit list and tree up to date
[FUNC(handleUnits), 21, _display] call CBA_fnc_addPerFrameHandler; [FUNC(handleUnits), 21, _display] call CBA_fnc_addPerFrameHandler;
// Handle unit icons on map and 3D
GVAR(iconHandler) = addMissionEventHandler ["Draw3D",FUNC(handleIcons)];
// Populate the help splash // Populate the help splash
private "_help"; private "_help";
_help = (_display displayCtrl IDC_HELP) controlsGroupCtrl IDC_HELP_LIST; _help = (_display displayCtrl IDC_HELP) controlsGroupCtrl IDC_HELP_LIST;
@ -187,6 +190,7 @@ switch (toLower _mode) do {
// Kill GUI PFHs // Kill GUI PFHs
GVAR(camHandler) = nil; GVAR(camHandler) = nil;
GVAR(compHandler) = nil; GVAR(compHandler) = nil;
removeMissionEventHandler ["Draw3D",GVAR(iconHandler)];
GVAR(iconHandler) = nil; GVAR(iconHandler) = nil;
GVAR(toolHandler) = nil; GVAR(toolHandler) = nil;
}; };
@ -435,34 +439,6 @@ switch (toLower _mode) do {
[nil,nil,nil, _newPos] call FUNC(setCameraAttributes); [nil,nil,nil, _newPos] call FUNC(setCameraAttributes);
}; };
}; };
case "ondraw": {
_args params ["_map"];
if (GVAR(camMode) == 0) then {
_map drawIcon ["\A3\UI_F\Data\GUI\Rsc\RscDisplayMissionEditor\iconcamera_ca.paa",[0,0,0,1],GVAR(camera),24,24,GVAR(camPan)];
};
if !(GVAR(showIcons)) exitWith {};
private ["_cachedVehicles","_unit","_color","_icon"];
_cachedVehicles = [];
{
_unit = vehicle _x;
if !(_unit in _cachedVehicles) then {
_cachedVehicles pushBack _unit;
// Use previously cached info where possible
if (isNil { GETVAR(_unit,GVAR(uIcon),nil) }) then {
[_unit] call FUNC(cacheUnitInfo);
};
_color = GETVAR(_unit,GVAR(uColor),[ARR_4(0,0,0,0)]);
_icon = GETVAR(_unit,GVAR(uIcon),"");
_map drawIcon [_icon, _color, _unit, 24, 24, getDir _unit];
};
} forEach GVAR(unitList);
};
// Break from interface for eexternal events // Break from interface for eexternal events
case "escape": { case "escape": {
_args params ["_display"]; _args params ["_display"];

View File

@ -0,0 +1,46 @@
/*
* Author: Head, SilentSpike
* Handles rendering the spectator map icons
*
* Arguments:
* 0: Parameters <ANY>
* 1: PFH handle <NUMBER>
*
* Return Value:
* None <NIL>
*
* Example:
* [ace_spectator_fnc_handleIcons, 0] call CBA_fnc_addPerFrameHandler;
*
* Public: No
*/
#include "script_component.hpp"
params ["_map"];
private ["_cachedVehicles","_unit","_color","_icon"];
if (GVAR(camMode) == 0) then {
_map drawIcon ["\A3\UI_F\Data\GUI\Rsc\RscDisplayMissionEditor\iconcamera_ca.paa",[0,0,0,1],GVAR(camera),20,20,GVAR(camPan)];
};
_cachedVehicles = [];
{
_unit = vehicle _x;
if !(_unit in _cachedVehicles) then {
_cachedVehicles pushBack _unit;
// Use previously cached info where possible
if (GETVAR(_unit,GVAR(uIcon),"") == "") then {
[_unit] call FUNC(cacheUnitInfo);
};
// Function has caching built in
_color = [side effectiveCommander _unit] call BIS_fnc_sideColor;
_icon = GETVAR(_unit,GVAR(uIcon),"");
_map drawIcon [_icon, _color, _unit, 19, 19, getDir _unit];
};
false
} count GVAR(unitList);

View File

@ -79,11 +79,6 @@ if (_newMode == 0) then { // Free
// Handle camera movement // Handle camera movement
if (isNil QGVAR(camHandler)) then { GVAR(camHandler) = [FUNC(handleCamera), 0] call CBA_fnc_addPerFrameHandler; }; if (isNil QGVAR(camHandler)) then { GVAR(camHandler) = [FUNC(handleCamera), 0] call CBA_fnc_addPerFrameHandler; };
// Handle unit icons
if (GVAR(unitIcons)) then {
if (isNil QGVAR(iconHandler)) then { GVAR(iconHandler) = [FUNC(handleIcons), 0] call CBA_fnc_addPerFrameHandler; };
};
} else { } else {
// When null unit is given choose random // When null unit is given choose random
if (isNull _newUnit) then { if (isNull _newUnit) then {
@ -111,7 +106,6 @@ if (_newMode == 0) then { // Free
// Terminate camera view // Terminate camera view
GVAR(camera) cameraEffect ["terminate", "back"]; GVAR(camera) cameraEffect ["terminate", "back"];
GVAR(camHandler) = nil; GVAR(camHandler) = nil;
GVAR(iconHandler) = nil;
cameraEffectEnableHUD true; cameraEffectEnableHUD true;
}; };

View File

@ -33,7 +33,7 @@ if !(_newUnits isEqualTo []) exitWith {
}; };
}; };
private ["_sides","_cond","_filteredUnits","_color","_icon"]; private ["_sides","_cond","_filteredUnits","_filteredGroups"];
// Unit setting filter // Unit setting filter
_newUnits = [[],allPlayers,playableUnits,allUnits] select GVAR(filterUnits); _newUnits = [[],allPlayers,playableUnits,allUnits] select GVAR(filterUnits);
@ -63,10 +63,13 @@ _filteredUnits = [];
_filteredUnits append GVAR(unitWhitelist); _filteredUnits append GVAR(unitWhitelist);
// Cache icons and colour for drawing // Cache icons and colour for drawing
_filteredGroups = [];
{ {
// Intentionally re-applied to units in case their status changes // Intentionally re-applied to units in case their status changes
[_x] call FUNC(cacheUnitInfo); [_x] call FUNC(cacheUnitInfo);
_filteredGroups pushBack (group _x);
} forEach _filteredUnits; } forEach _filteredUnits;
// Replace previous list entirely (removes any no longer valid) // Replace previous lists entirely (removes any no longer valid)
GVAR(unitList) = _filteredUnits arrayIntersect _filteredUnits; GVAR(unitList) = _filteredUnits arrayIntersect _filteredUnits;
GVAR(groupList) = _filteredGroups arrayIntersect _filteredGroups;

View File

@ -100,14 +100,6 @@
<English>Thermal imaging</English> <English>Thermal imaging</English>
<Polish>Termowizja</Polish> <Polish>Termowizja</Polish>
</Key> </Key>
<Key ID="STR_ACE_Spectator_icons_DisplayName">
<English>Unit icons</English>
<Polish>Ikony jednostek</Polish>
</Key>
<Key ID="STR_ACE_Spectator_icons_Description">
<English>Render icons above spectatable units.</English>
<Polish>Renderuj ikony nad głowami jednostek, które można obserwować.</Polish>
</Key>
<!-- Interface strings --> <!-- Interface strings -->
<Key ID="STR_ACE_Spectator_HelpTitle"> <Key ID="STR_ACE_Spectator_HelpTitle">
<English>Spectator Controls</English> <English>Spectator Controls</English>