Improve spectator drawing and selection (#5457)

* Optimise cursor object updates
* Restrict distance units can be selected from
* Fix potential for no icons to render in FPP
* Limit projectile drawing distance
* Optimise icon updates
* Fix group names not being drawn in vehicles
* Fix selection nameplate not drawing for vehicles
* Fix selection of non-spectatable entities
This commit is contained in:
SilentSpike 2017-08-30 11:40:12 +01:00 committed by GitHub
parent abc91f1564
commit 1ab7a886e7
3 changed files with 48 additions and 41 deletions

View File

@ -19,17 +19,21 @@
BEGIN_COUNTER(updateCursor); BEGIN_COUNTER(updateCursor);
private _camTarget = GVAR(camTarget); private _camTarget = GVAR(camTarget);
private _camTargetVeh = vehicle _camTarget;
private _cursorObject = objNull; private _cursorObject = objNull;
// This function doesn't work for units underwater, due to use of screenToWorld. Would be complicated to work around this. // This doesn't work for units underwater due to use of screenToWorld
private _intersections = [getMousePosition select 0, getMousePosition select 1, _camTarget, vehicle _camTarget] call BIS_fnc_getIntersectionsUnderCursor; // Would be hard to work around due to parallax
private _start = AGLToASL positionCameraToWorld [0,0,0];
private _end = AGLToASL screenToWorld getMousePosition;
if !(_intersections isEqualTo []) then { // Can only select units within name drawing distance
_cursorObject = (_intersections select 0) select 3; if ((_start distanceSqr _end) <= DISTANCE_NAMES_SQR) then {
}; private _intersections = lineIntersectsSurfaces [_start, _end, _camTarget, _camTargetVeh];
if !(_cursorObject isKindOf "Man") then { if !(_intersections isEqualTo []) then {
_cursorObject = effectiveCommander _cursorObject; _cursorObject = effectiveCommander ((_intersections select 0) select 3);
};
}; };
GVAR(cursorObject) = _cursorObject; GVAR(cursorObject) = _cursorObject;
@ -43,10 +47,11 @@ if !(GVAR(uiMapVisible)) then {
_x params ["_unit", "_type", "_icon"]; _x params ["_unit", "_type", "_icon"];
private _position = (_unit modelToWorldVisual (_unit selectionPosition "Head")) vectorAdd [0,0,HEIGHT_OFFSET]; private _position = (_unit modelToWorldVisual (_unit selectionPosition "Head")) vectorAdd [0,0,HEIGHT_OFFSET];
if (_type == 2 && { _unit distanceSqr GVAR(camera) < DISTANCE_NAMES_SQR } && {_unit in _camTarget || _unit in _cursorObject}) then { // Cursor object is always effectiveCommander so no need to check `in`
if (_type == 2 && {_unit in _camTargetVeh || _unit == _cursorObject}) then {
drawIcon3D [ drawIcon3D [
ICON_BACKGROUND_UNIT, ICON_BACKGROUND_UNIT,
[0, 0, 0, [0.4, 0.8] select (_unit in _camTarget)], [0, 0, 0, [0.4, 0.8] select (_unit in _camTargetVeh)],
_position, _position,
5, 5,
4, 4,

View File

@ -33,11 +33,13 @@ if (_button == 0) exitWith {
[objNull] call FUNC(setFocus); [objNull] call FUNC(setFocus);
}; };
} else { } else {
playSound "ReadoutClick"; if (GVAR(cursorObject) in ([] call FUNC(getTargetEntities))) then {
playSound "ReadoutClick";
// Focus will be at screen center // Focus will be at screen center
[GVAR(cursorObject)] call FUNC(setFocus); [GVAR(cursorObject)] call FUNC(setFocus);
setMousePosition [0.5, 0.5]; setMousePosition [0.5, 0.5];
};
}; };
}; };

View File

@ -19,17 +19,17 @@
private _iconsToDraw = []; private _iconsToDraw = [];
private _entitiesToDraw = []; private _entitiesToDraw = [];
// camToWorld is used instead of camera object to account for FPP
private _camPos = AGLToASL positionCameraToWorld [0,0,0];
{ {
private _vehicle = vehicle _x; private _vehicle = vehicle _x;
private _inVehicle = (_vehicle != _x); private _inVehicle = (_vehicle != _x);
private _distanceToCameraSqr = GVAR(camera) distanceSqr _x; private _distanceToCameraSqr = _camPos distanceSqr _x;
if (_distanceToCameraSqr <= DISTANCE_ICONS_SQR && { !_inVehicle || { _x == effectiveCommander _vehicle } }) then { if (_distanceToCameraSqr <= DISTANCE_ICONS_SQR && { !_inVehicle || { _x == effectiveCommander _vehicle } }) then {
private _group = group _x; private _group = group _x;
private _groupSide = side _group; private _isLeader = _x == leader _group;
private _groupName = groupId _group; private _groupColor = [side _group] call BIS_fnc_sideColor;
private _groupLeader = leader _group;
private _groupColor = [_groupSide] call BIS_fnc_sideColor;
// Calculate distance fade // Calculate distance fade
(_distanceToCameraSqr call { (_distanceToCameraSqr call {
@ -54,19 +54,19 @@ private _entitiesToDraw = [];
// Apply color fade // Apply color fade
_groupColor set [3, _fadeByDistance]; _groupColor set [3, _fadeByDistance];
private _name = ([_x] call EFUNC(common,getName)) select [0, NAME_MAX_CHARACTERS];
if !(isPlayer _x) then { _name = format ["%1: %2", localize "str_player_ai", _name]; };
if (_inVehicle) then {
private _crewCount = (({alive _x} count (crew _vehicle)) - 1);
if (_crewCount > 0) then {
_name = format ["%1 (+%2)", _name, _crewCount];
};
};
// Show unit name only if camera is near enough // Show unit name only if camera is near enough
if (_distanceToCameraSqr < DISTANCE_NAMES_SQR) then { if (_distanceToCameraSqr < DISTANCE_NAMES_SQR) then {
// Unit name private _name = ([_x] call EFUNC(common,getName)) select [0, NAME_MAX_CHARACTERS];
if !(isPlayer _x) then { _name = format ["%1: %2", localize "str_player_ai", _name]; };
if (_inVehicle) then {
private _crewCount = (({alive _x} count (crew _vehicle)) - 1);
if (_crewCount > 0) then {
_name = format ["%1 (+%2)", _name, _crewCount];
};
};
// Draw unit name for effective commander or all units on foot
_iconsToDraw pushBack [_x, 2, [ _iconsToDraw pushBack [_x, 2, [
"", "",
[1,1,1,1], [1,1,1,1],
@ -81,8 +81,8 @@ private _entitiesToDraw = [];
"center" "center"
]]; ]];
} else { } else {
if (_x == _groupLeader) then { // Draw group name for effective commander or leader on foot
// Group name if (_inVehicle || _isLeader) then {
_iconsToDraw pushBack [_x, 0, [ _iconsToDraw pushBack [_x, 0, [
"", "",
[1,1,1,_fadeByDistance], [1,1,1,_fadeByDistance],
@ -90,7 +90,7 @@ private _entitiesToDraw = [];
0, 0,
_heightByDistance, _heightByDistance,
0, 0,
_groupName, groupID _group,
2, 2,
_fontSizeByDistance, _fontSizeByDistance,
"PuristaMedium", "PuristaMedium",
@ -99,8 +99,8 @@ private _entitiesToDraw = [];
}; };
}; };
if (_x == _groupLeader || { _inVehicle && { _x == effectiveCommander _vehicle } }) then { // Draw group icon for effective commander or leader on foot
// Group icon if (_inVehicle || _isLeader) then {
_iconsToDraw pushBack [_x, 0, [ _iconsToDraw pushBack [_x, 0, [
[_group, true] call FUNC(getGroupIcon), [_group, true] call FUNC(getGroupIcon),
_groupColor, _groupColor,
@ -116,7 +116,7 @@ private _entitiesToDraw = [];
]]; ]];
}; };
// Draw unit icon // Draw unit icon for effective commander or all units on foot
_iconsToDraw pushBack [_x, 1, [ _iconsToDraw pushBack [_x, 1, [
[ICON_UNIT, ICON_REVIVE] select (NEEDS_REVIVE(_x)), [ICON_UNIT, ICON_REVIVE] select (NEEDS_REVIVE(_x)),
_groupColor, _groupColor,
@ -130,14 +130,14 @@ private _entitiesToDraw = [];
"PuristaMedium", "PuristaMedium",
"center" "center"
]]; ]];
};
// Track entities themselves for use with fired EH // Track entities themselves for use with fired EH
_entitiesToDraw pushBack _vehicle; _entitiesToDraw pushBack _vehicle;
// Add fired EH for drawing and icon highlighting // Add fired EH for drawing and icon highlighting
if (GETVAR(_vehicle,GVAR(firedEH),-1) == -1) then { if (GETVAR(_vehicle,GVAR(firedEH),-1) == -1) then {
SETVAR(_vehicle,GVAR(firedEH),_vehicle addEventHandler [ARR_2("Fired",{_this call FUNC(handleFired)})]); SETVAR(_vehicle,GVAR(firedEH),_vehicle addEventHandler [ARR_2("Fired",{_this call FUNC(handleFired)})]);
};
}; };
nil // Speed loop nil // Speed loop