Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visibility - Add during placement only mode and max distance setting #686

Merged
merged 3 commits into from
Dec 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 35 additions & 17 deletions addons/common/functions/fnc_getPosFromScreen.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
/*
* Author: mharis001
* Returns a world position based on the given screen position.
* Will attempt to find a flat position on an intersecting surface if enabled.
* Can attempt to find a flat position on an intersecting surface if enabled.
*
* Arguments:
* 0: Screen Position <ARRAY> (default: getMousePosition)
* 1: Check Intersections <BOOL> (default: true)
* 1: Check Intersections <BOOL|NUMBER> (default: true)
* - 0, false: Do not check for intersections, return position on terrain.
* - 1, true: Check for intersections with surfaces.
* - 2: Check for intersections and attempt to find a flat surface.
*
* Return Value:
* Position ASL <ARRAY>
Expand All @@ -19,26 +22,41 @@

#define MAX_RESULTS 5

params [["_screenPos", getMousePosition, [[]], 2], ["_checkIntersections", true, [true]]];
params [["_screenPos", getMousePosition, [[]], 2], ["_checkIntersections", true, [true, 0]]];

if (_checkIntersections isEqualType true) then {
_checkIntersections = parseNumber _checkIntersections;
};

if (visibleMap) then {
private _ctrlMap = findDisplay IDD_RSCDISPLAYCURATOR displayCtrl IDC_RSCDISPLAYCURATOR_MAINMAP;
private _pos2D = _ctrlMap ctrlMapScreenToWorld _screenPos;

AGLtoASL (_pos2D + [0])
AGLToASL (_ctrlMap posScreenToWorld _screenPos)
} else {
private _position = AGLtoASL screenToWorld _screenPos;
private _position = AGLToASL screenToWorld _screenPos;

if (_checkIntersections) then {
{
_x params ["_intersectPos", "_surfaceNormal"];
switch (_checkIntersections) do {
case 0: {
_position
};
case 1: {
lineIntersectsSurfaces [getPosASL curatorCamera, _position] param [0, []] param [0, _position]
};
case 2: {
{
_x params ["_intersectPos", "_surfaceNormal"];

// Use the intersection position if the surface is relatively flat
if (_surfaceNormal vectorDotProduct [0, 0, 1] > 0.5) exitWith {
_position = _intersectPos;
};
} forEach lineIntersectsSurfaces [getPosASL curatorCamera, _position, objNull, objNull, true, MAX_RESULTS, "VIEW", "FIRE", false];
};
// Always keep the first intersection as a fallback
if (_forEachIndex == 0) then {
_position = _intersectPos;
};

// Use the intersection position if the surface is relatively flat
if (_surfaceNormal vectorDotProduct [0, 0, 1] > 0.5) exitWith {
_position = _intersectPos;
};
} forEach lineIntersectsSurfaces [getPosASL curatorCamera, _position, objNull, objNull, true, MAX_RESULTS, "VIEW", "FIRE", false];

_position
_position
};
};
};
8 changes: 4 additions & 4 deletions addons/common/functions/fnc_selectPosition.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private _mouseEH = [_display, "MouseButtonDown", {

if (_button != 0) exitWith {};

private _position = [] call FUNC(getPosFromScreen);
private _position = [nil, 2] call FUNC(getPosFromScreen);
_thisArgs params ["_objects", "_function", "_args"];

[true, _objects, _position, _args, _shift, _ctrl, _alt] call _function;
Expand All @@ -94,7 +94,7 @@ private _keyboardEH = [_display, "KeyDown", {

if (_key != DIK_ESCAPE) exitWith {false};

private _position = [] call FUNC(getPosFromScreen);
private _position = [nil, 2] call FUNC(getPosFromScreen);
_thisArgs params ["_objects", "_function", "_args"];

[false, _objects, _position, _args, _shift, _ctrl, _alt] call _function;
Expand All @@ -108,7 +108,7 @@ private _drawEH = [_ctrlMap, "Draw", {
params ["_ctrlMap"];
_thisArgs params ["_objects", "_args", "_visuals", "_modifierFunction"];

private _position = [] call FUNC(getPosFromScreen);
private _position = [nil, 2] call FUNC(getPosFromScreen);
[_objects, _position, _args, _visuals] call _modifierFunction;
_visuals params ["_text", "_icon", "_angle", "_color"];

Expand Down Expand Up @@ -155,7 +155,7 @@ private _drawEH = [_ctrlMap, "Draw", {
// No 3D drawing needed if the map is visible
if (visibleMap) exitWith {};

private _position = [] call FUNC(getPosFromScreen);
private _position = [nil, 2] call FUNC(getPosFromScreen);
[_objects, _position, _args, _visuals] call _modifierFunction;
_visuals params ["_text", "_icon", "_angle", "_color"];

Expand Down
2 changes: 1 addition & 1 deletion addons/context_menu/script_component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

// _contextPosASL and _selectedObjects, _selectedGroups .., kept for BWC
#define SETUP_ACTION_VARS \
private _position = [GVAR(mousePos)] call EFUNC(common,getPosFromScreen); \
private _position = [GVAR(mousePos), 2] call EFUNC(common,getPosFromScreen); \
private _hoveredEntity = GVAR(hovered); \
+GVAR(selected) params ["_objects", "_groups", "_waypoints", "_markers"]; \
private _contextPosASL = _position; \
Expand Down
2 changes: 1 addition & 1 deletion addons/visibility/XEH_postInit.sqf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "script_component.hpp"

["zen_curatorDisplayLoaded", {
if (GVAR(enabled)) then {
if (GVAR(enabled) != INDICATOR_DISABLED) then {
call FUNC(start);
};
}] call CBA_fnc_addEventHandler;
Expand Down
57 changes: 30 additions & 27 deletions addons/visibility/functions/fnc_draw.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,49 @@
* Public: No
*/

if (call EFUNC(common,isInScreenshotMode)) exitWith {};
if (
call EFUNC(common,isInScreenshotMode)
|| {GVAR(enabled) == INDICATOR_PLACEMENT_ONLY && {!call EFUNC(common,isPlacementActive)}}
) exitWith {};

// The cursor position in the world
private _pos = AGLtoASL screenToWorld getMousePosition;
private _intersections = lineIntersectsSurfaces [getPosASL curatorCamera, _pos];
if (_intersections isNotEqualTo []) then {
_pos = _intersections select 0 select 0;
};

// Check 1.5 above the cursor to prevent a small object on the terrain blocking the view
// Get the cursor's position in the world
// Check 1.5 m above the position to check for small terrain objects blocking the view
// Converting to AGL here to avoid repeated conversions in the loop
private _pos = [] call EFUNC(common,getPosFromScreen);
private _posHigh = _pos vectorAdd [0, 0, 1.5];
private _draw = false;
private _posAGL = ASLToAGL _pos;

private _visible = false;

{
// Check if the cursor's position is in the player's view (filter the local player and virtual units)
if (_x != player && {side _x != sideLogic} && {((_x getRelDir _posHigh) + 90) mod 360 < 180}) then {
if (
_x != player
&& {side _x != sideLogic}
&& {_x distance _posAGL <= GVAR(maxDistance)}
&& {
private _dir = _x getRelDir _pos;
_dir <= 90 || {_dir >= 270}
}
) then {
private _eyePos = eyePos _x;
if (lineIntersectsSurfaces [_eyePos, _pos, _x, objNull] isEqualTo [] || {lineIntersectsSurfaces [_eyePos, _posHigh, _x, objNull] isEqualTo []}) then {

if (
lineIntersectsSurfaces [_eyePos, _pos, _x] isEqualTo []
|| {lineIntersectsSurfaces [_eyePos, _posHigh, _x] isEqualTo []}
) then {
// Check visibility through smoke
private _visibility = [objNull, "VIEW"] checkVisibility [_eyePos, _posHigh];

// Draw a line from each player that can see the cursor
drawLine3D [ASLToAGL _eyePos, ASLToAGL _pos, [1, 0, 0, _visibility]];
drawLine3D [ASLToAGL _eyePos, _posAGL, [1, 0, 0, _visibility]];

_draw = true;
_visible = true;
};
};
} forEach allPlayers;

// Write visible under the cursor if any player can see the position
if (_draw) then {
drawIcon3D [
"",
[1, 0, 0, 1],
ASLToAGL _pos,
1, 1.3, 0,
LLSTRING(Visible),
2,
0.04,
"PuristaMedium",
"center"
];
// Write visible under the cursor if a player can see the position
if (_visible) then {
drawIcon3D ["", [1, 0, 0, 1], _posAGL, 1, 1.3, 0, LLSTRING(Visible), 2, 0.04, "PuristaMedium", "center"];
};
29 changes: 25 additions & 4 deletions addons/visibility/initSettings.sqf
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
[
QGVAR(enabled),
"CHECKBOX",
"LIST",
[LSTRING(Enabled), LSTRING(Enabled_Description)],
ELSTRING(main,DisplayName),
false,
[ELSTRING(main,DisplayName), LSTRING(DisplayName)],
[
[
INDICATOR_DISABLED,
INDICATOR_ENABLED,
INDICATOR_PLACEMENT_ONLY
],
[
ELSTRING(common,Disabled),
ELSTRING(common,Enabled),
[LSTRING(DuringPlacementOnly), LSTRING(DuringPlacementOnly_Description)]
],
0
],
false,
{
params ["_value"];

if (isNull findDisplay IDD_RSCDISPLAYCURATOR) exitWith {};

if (_value) then {
if (_value != INDICATOR_DISABLED) then {
call FUNC(start);
} else {
call FUNC(stop);
};
}
] call CBA_fnc_addSetting;

[
QGVAR(maxDistance),
"SLIDER",
[LSTRING(MaxDistance), LSTRING(MaxDistance_Description)],
[ELSTRING(main,DisplayName), LSTRING(DisplayName)],
[100, 5000, 5000, -1],
false
] call CBA_fnc_addSetting;
4 changes: 4 additions & 0 deletions addons/visibility/script_component.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@
#include "\x\zen\addons\main\script_macros.hpp"

#include "\x\zen\addons\common\defineResinclDesign.inc"

#define INDICATOR_DISABLED 0
#define INDICATOR_ENABLED 1
#define INDICATOR_PLACEMENT_ONLY 2
24 changes: 22 additions & 2 deletions addons/visibility/stringtable.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project name="ZEN">
<Package name="Visibility">
<Key ID="STR_ZEN_Visibility_Enabled">
<Key ID="STR_ZEN_Visibility_DisplayName">
<English>Visibility Indicator</English>
<French>Indicateur de visibilité</French>
<German>Sichtbarkeitsindikator</German>
Expand All @@ -11,8 +11,12 @@
<Chinese>能见度指标</Chinese>
<Italian>Indicatore di visibilità</Italian>
</Key>
<Key ID="STR_ZEN_Visibility_Enabled">
<English>Enable Visibility Indicator</English>
<German>Aktiviere den Sichtbarkeitsindikator</German>
</Key>
<Key ID="STR_ZEN_Visibility_Enabled_Description">
<English>Indicates when a player can see the Zeus' cursor.</English>
<English>Enables showing an indicator when a player can see the Zeus cursor position.</English>
<French>Indique quand un joueur peut voir le curseur de Zeus.</French>
<German>Zeigt an, wann ein Spieler den Zeuszeiger sehen könnte.</German>
<Polish>Wskazuje czy kursor Zeusa jest widoczny dla gracza.</Polish>
Expand All @@ -21,6 +25,22 @@
<Chinese>顯示玩家何時能看到宙斯的光標。</Chinese>
<Italian>Indica quando un giocatore può vedere il cursore 'Zeus'</Italian>
</Key>
<Key ID="STR_ZEN_Visibility_DuringPlacementOnly">
<English>During Placement Only</English>
<German>Nur während dem Platzieren</German>
</Key>
<Key ID="STR_ZEN_Visibility_DuringPlacementOnly_Description">
<English>Only show the indicator while placing objects.</English>
<German>Zeigt den Indikator nur an während dem Platzieren</German>
</Key>
<Key ID="STR_ZEN_Visibility_MaxDistance">
<English>Max Check Distance</English>
<German>Maximale Distanz</German>
</Key>
<Key ID="STR_ZEN_Visibility_MaxDistance_Description">
<English>Controls the maximum distance from the cursor's position that players are considered for visibility checks.</English>
<German>Die Maximale Distanz zwischen dem Mauszeiger and den Spielern, bei der die Sichtbarkeit überprüft wird.</German>
</Key>
<Key ID="STR_ZEN_Visibility_Visible">
<English>VISIBLE</English>
<French>VISIBLE</French>
Expand Down