mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Viewports (#8480)
* Viewports * Support mem-points * Update CfgVehicles.hpp * Add some docs * Cleanup Debugging * Update addons/viewports/dev/debugPoints.sqf Co-authored-by: Dystopian <sddex@ya.ru> * Update addons/viewports/dev/debugPoints.sqf Co-authored-by: Dystopian <sddex@ya.ru> * Update addons/viewports/functions/fnc_eachFrame.sqf Co-authored-by: Filip Maciejewski <veteran29@users.noreply.github.com> * configProperties / 3den macro * Update viewports-framework.md * Update viewports-framework.md * Add compats for rhs btrs * Update addons/viewports/dev/debugPoints.sqf Co-authored-by: Drofseh <Drofseh@users.noreply.github.com> Co-authored-by: Dystopian <sddex@ya.ru> Co-authored-by: Filip Maciejewski <veteran29@users.noreply.github.com> Co-authored-by: Drofseh <Drofseh@users.noreply.github.com>
This commit is contained in:
parent
699e286db7
commit
a4258f3587
1
addons/viewports/$PBOPREFIX$
Normal file
1
addons/viewports/$PBOPREFIX$
Normal file
@ -0,0 +1 @@
|
||||
z\ace\addons\viewports
|
15
addons/viewports/CfgEventHandlers.hpp
Normal file
15
addons/viewports/CfgEventHandlers.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
class Extended_PreStart_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_SCRIPT(XEH_preStart));
|
||||
};
|
||||
};
|
||||
class Extended_PreInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_SCRIPT(XEH_preInit));
|
||||
};
|
||||
};
|
||||
class Extended_PostInit_EventHandlers {
|
||||
class ADDON {
|
||||
init = QUOTE(call COMPILE_SCRIPT(XEH_postInit));
|
||||
};
|
||||
};
|
22
addons/viewports/CfgVehicles.hpp
Normal file
22
addons/viewports/CfgVehicles.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
class CfgVehicles {
|
||||
class B_MBT_01_base_F;
|
||||
class B_MBT_01_cannon_F: B_MBT_01_base_F { // Merkava
|
||||
class ace_viewports {
|
||||
class SLD_backLeftUpper {
|
||||
type = "screen";
|
||||
camLocation[] = {0,0,0.05};
|
||||
maxDistance = 5;
|
||||
camAttach[] = {0,0};
|
||||
screenLocation[] = {-0.925,-3.43459,-1.07};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
};
|
||||
};
|
||||
class B_MBT_01_TUSK_F: B_MBT_01_cannon_F { // Merkava TUSK (slightly different model-space because different p3d model)
|
||||
class ace_viewports: ace_viewports {
|
||||
class SLD_backLeftUpper: SLD_backLeftUpper {
|
||||
screenLocation[] = {-0.925,-4.65511,-1.07};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
4
addons/viewports/README.md
Normal file
4
addons/viewports/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
ace_viewports
|
||||
==========
|
||||
|
||||
Allows crew to look through periscopes
|
8
addons/viewports/XEH_PREP.hpp
Normal file
8
addons/viewports/XEH_PREP.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
LOG("prep");
|
||||
|
||||
PREP(eachFrame);
|
||||
PREP(enterVehicle);
|
||||
PREP(getSeatInfo);
|
||||
PREP(getViewports);
|
||||
PREP(viewCleanup);
|
||||
PREP(viewCreate);
|
9
addons/viewports/XEH_postInit.sqf
Normal file
9
addons/viewports/XEH_postInit.sqf
Normal file
@ -0,0 +1,9 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
if (!hasInterface) exitWith {};
|
||||
|
||||
GVAR(pfeh) = -1;
|
||||
["CBA_settingsInitialized", {
|
||||
TRACE_1("CBA_settingsInitialized",GVAR(enabled));
|
||||
["vehicle", LINKFUNC(enterVehicle), true] call CBA_fnc_addPlayerEventHandler;
|
||||
}] call CBA_fnc_addEventHandler;
|
15
addons/viewports/XEH_preInit.sqf
Normal file
15
addons/viewports/XEH_preInit.sqf
Normal file
@ -0,0 +1,15 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
ADDON = false;
|
||||
|
||||
PREP_RECOMPILE_START;
|
||||
#include "XEH_PREP.hpp"
|
||||
PREP_RECOMPILE_END;
|
||||
|
||||
#include "initSettings.sqf"
|
||||
|
||||
#ifdef POINT_CONFIG_DEBUG
|
||||
call compileScript [QPATHTOF(dev\debugPoints.sqf)];
|
||||
#endif
|
||||
|
||||
ADDON = true;
|
3
addons/viewports/XEH_preStart.sqf
Normal file
3
addons/viewports/XEH_preStart.sqf
Normal file
@ -0,0 +1,3 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
#include "XEH_PREP.hpp"
|
19
addons/viewports/config.cpp
Normal file
19
addons/viewports/config.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
class CfgPatches {
|
||||
class ADDON {
|
||||
name = COMPONENT_NAME;
|
||||
units[] = {};
|
||||
weapons[] = {};
|
||||
requiredVersion = REQUIRED_VERSION;
|
||||
requiredAddons[] = {"ace_common"};
|
||||
author = ECSTRING(common,ACETeam);
|
||||
authors[] = {"PabstMirror"};
|
||||
url = ECSTRING(main,URL);
|
||||
VERSION_CONFIG;
|
||||
};
|
||||
};
|
||||
|
||||
#include "CfgEventHandlers.hpp"
|
||||
#include "CfgVehicles.hpp"
|
||||
#include "gui.hpp"
|
BIN
addons/viewports/data/optic_window_ca.paa
Normal file
BIN
addons/viewports/data/optic_window_ca.paa
Normal file
Binary file not shown.
173
addons/viewports/dev/debugPoints.sqf
Normal file
173
addons/viewports/dev/debugPoints.sqf
Normal file
@ -0,0 +1,173 @@
|
||||
#include "\z\ace\addons\viewports\script_component.hpp"
|
||||
/*
|
||||
[] call compileScript ["\z\ace\addons\viewports\dev\debugPoints.sqf"];
|
||||
|
||||
This is mostly just for placing the mem points in threeden
|
||||
left-click to place and adjust current point
|
||||
alt+left-click to place next point
|
||||
alt+right-click to output
|
||||
shift+right-click to reset
|
||||
|
||||
// Tweak:
|
||||
z = (vehicle player) getVariable "ace_viewports_viewports";
|
||||
p = z # 0 # 4; z # 0 set [4, p vectorAdd [0,0.1,0]];
|
||||
|
||||
// Place by view:
|
||||
v = (positionCameraToWorld [0,0,0.4]);
|
||||
m = (vehicle player) worldToModel v;
|
||||
z = (vehicle player) getVariable "ace_viewports_viewports";
|
||||
z # 0 set [4, m];
|
||||
*/
|
||||
|
||||
#define IDD_3DEN 313
|
||||
|
||||
[] spawn {
|
||||
INFO_2("Pre-Init [is3den %1][3den display: %2]", is3den, !isNull findDisplay IDD_3DEN);
|
||||
if (!is3den) exitWith {};
|
||||
|
||||
GVAR(3denIndex) = 0;
|
||||
GVAR(3denViewports) = [];
|
||||
|
||||
disableSerialization;
|
||||
private _3den = findDisplay IDD_3DEN;
|
||||
if (_3den getVariable [QGVAR(setup), false]) exitWith {};
|
||||
_3den setVariable [QGVAR(setup), true];
|
||||
|
||||
_3den displayAddEventHandler ["MouseButtonDown", {
|
||||
params ["", "_button", "_mouseX", "_mouseY", "_shift", "_ctrl", "_alt"];
|
||||
|
||||
if (_shift && _button == 1) exitWith {
|
||||
systemChat "Reset/Reload";
|
||||
if ((supportInfo "u:diag_mergeConfigFile") isNotEqualTo []) then {
|
||||
call compile 'diag_mergeConfigFile ["P:\z\ace\addons\viewports\config.cpp"]';
|
||||
};
|
||||
{ _x setVariable [QGVAR(viewports), nil] } forEach vehicles;
|
||||
GVAR(3denIndex) = 0;
|
||||
GVAR(3denViewports) = [];
|
||||
true
|
||||
};
|
||||
|
||||
if (_alt) then {
|
||||
if (count GVAR(3denViewports) > GVAR(3denIndex)) then {
|
||||
systemChat "Advance to next index";
|
||||
GVAR(3denIndex) = GVAR(3denIndex) + 1;
|
||||
};
|
||||
};
|
||||
if (_alt && _button == 1) exitWith {
|
||||
private _vehicle = (get3DENSelected "object") param [0, objNull];
|
||||
private _config = configOf _vehicle;
|
||||
private _model = getText (_config >> "model");
|
||||
while {true} do {
|
||||
private _parent = inheritsFrom _config;
|
||||
if ((getText (_parent >> "model")) != _model) exitWith {};
|
||||
_config = _parent;
|
||||
};
|
||||
|
||||
private _out = [];
|
||||
_out pushBack format [" class %1: %2 {", configName _config, configName inheritsFrom _config];
|
||||
_out pushBack format [" class ace_viewports {"];
|
||||
{
|
||||
_x params ["_name", "", "_camLocation", "_camAttach"];
|
||||
_out pushBack format [' class %1 {', _name];
|
||||
_out pushBack format [' camLocation[] = {%1, %2, %3};', _camLocation # 0, _camLocation # 1, _camLocation # 2];
|
||||
_out pushBack format [' camAttach = %1;', _camAttach];
|
||||
// _out pushBack format [' type = "%1";', _type];
|
||||
// _out pushBack format [' screenLocation[] = {};'];
|
||||
// _out pushBack format [' maxDistance = 99;'];
|
||||
// _out pushBack format [' compartments[]={};'];
|
||||
// _out pushBack format [' roles[]={};'];
|
||||
_out pushBack format [' };'];
|
||||
} forEach GVAR(3denViewports);
|
||||
|
||||
_out pushBack format [' };'];
|
||||
_out pushBack format [' };'];
|
||||
|
||||
// Some inherited configs might use a different model which uses a different offset - yuck
|
||||
private _inherited = '((configName _x) isKindOf (configName _config)) && {_model != getText (_x >> "model")}' configClasses (configFile >> "CfgVehicles");
|
||||
_out pushBack format ["// Watch out for %1", _inherited apply {configName _x}];
|
||||
|
||||
copyToClipboard (_out joinString endl);
|
||||
systemChat format ["copied %1 lines", count _out];
|
||||
};
|
||||
if (_button == 0) exitWith {
|
||||
private _vehicle = (get3DENSelected "object") param [0, objNull];
|
||||
if (isNull _vehicle) exitWith {};
|
||||
|
||||
private _start = AGLToASL positionCameraToWorld [0,0,0];
|
||||
private _end = AGLToASL screenToWorld [_mouseX, _mouseY];
|
||||
private _intersections = lineIntersectsSurfaces [_start, _end];
|
||||
private _pointASL = _intersections # 0 # 0;
|
||||
if (isNil "_pointASL") exitWith {};
|
||||
_pointASL = _pointASL vectorAdd [0,0,0.09]; // Add a little bit up because it always sinks into the model
|
||||
private _pointMS = _vehicle worldToModel ASLtoAGL _pointASL;
|
||||
|
||||
private _name = format ["view_%1",GVAR(3denIndex)];
|
||||
// [_name, _type, _camLocation, _camAttach, _screenLocation, _maxDistance, _compartments, _roles]
|
||||
GVAR(3denViewports) set [GVAR(3denIndex), [_name, "", _pointMS, 0, _pointMS, 99, [], []]];
|
||||
true
|
||||
};
|
||||
}];
|
||||
};
|
||||
|
||||
// this runs in both threeden and in-game
|
||||
addMissionEventHandler ["Draw3D", {
|
||||
private _vehicle = vehicle player;
|
||||
private _viewports = _vehicle getVariable [QGVAR(viewports), []];
|
||||
|
||||
if (is3den) then {
|
||||
_vehicle = (get3DENSelected "object") param [0, objNull];
|
||||
if (isNull _vehicle) exitWith {};
|
||||
_viewports = [_vehicle] call FUNC(getViewports);
|
||||
if (GVAR(3denViewports) isNotEqualTo []) then {
|
||||
_viewports = GVAR(3denViewports);
|
||||
};
|
||||
};
|
||||
if (isNull _vehicle) exitWith {};
|
||||
|
||||
|
||||
drawIcon3D ["#(argb,8,8,3)color(1,1,1,1)", [1,1,0,1], _vehicle modelToWorldVisual [0,0,0], 0.1, 0.1, 0, "", 1, 0.02, "TahomaB"];
|
||||
if (alive player) then { // not using ace_player so this works in 3den
|
||||
drawIcon3D ["#(argb,8,8,3)color(1,1,1,1)", [0,1,0,1], aslToAGL eyepos player, 0.1, 0.1, 0, "eye", 1, 0.02, "TahomaB"];
|
||||
drawIcon3D ["#(argb,8,8,3)color(1,1,1,1)", [0,1,0,1], player modelToWorldVisual (player selectionPosition "pilot"), 0.1, 0.1, 0, "pilot", 1, 0.02, "TahomaB"];
|
||||
};
|
||||
// {
|
||||
// private _pos = _vehicle modelToWorldVisual (_vehicle selectionPosition [_x, "Memory"]);
|
||||
// drawIcon3D ["#(argb,8,8,3)color(1,1,1,1)", [0,0,1,0.2], _pos, 0.05, 0.05, 0, _x, 1, 0.02, "TahomaB"];
|
||||
// } forEach (_vehicle selectionNames "Memory");
|
||||
|
||||
|
||||
{
|
||||
_x params ["_name", "_type", "_camLocation", "_camAttach", "_screenLocation", "_maxDistance", "_compartments", "_roles"];
|
||||
|
||||
if (_camLocation isEqualType "") then {
|
||||
_camLocation = _vehicle selectionPosition [_camLocation, "Memory"];
|
||||
};
|
||||
|
||||
private _screenAGL = _vehicle modelToWorldVisual _screenLocation;
|
||||
drawIcon3D ["#(argb,8,8,3)color(0,0,1,1)", [1,0.5,1,1], _screenAGL, 0.05, 0.05, 0, format ["%1:%2",_forEachIndex,_compartments], 1, 0.03, "TahomaB"];
|
||||
|
||||
private _camAGL = if (_camAttach isEqualType 0) then {
|
||||
_vehicle modelToWorldVisual _camLocation
|
||||
} else {
|
||||
private _turretConfig = [_vehicle, _camAttach] call CBA_fnc_getTurret;
|
||||
private _memoryPointGunnerOptics = getText(_turretConfig >> "memoryPointGunnerOptics");
|
||||
_vehicle modelToWorldVisual (_camLocation vectorAdd (_vehicle selectionPosition _memoryPointGunnerOptics))
|
||||
};
|
||||
drawIcon3D ["#(argb,8,8,3)color(1,0,0,1)", [0.5,1,1,1], _camAGL, 0.1, 0.1, 0, format ["%1:%2",_forEachIndex,_name], 1, 0.03, "TahomaB"];
|
||||
|
||||
if (_camAttach isEqualType 0) then {
|
||||
private _camAGL = _vehicle modelToWorldVisual _camLocation;
|
||||
drawIcon3D ["#(argb,8,8,3)color(1,0,0,1)", [1,1,1,1], _camAGL, 0.1, 0.1, 0, _name, 1, 0.05, "TahomaB"];
|
||||
private _target = _vehicle modelToWorldVisual (_camLocation vectorAdd ([1, _camAttach, 0] call CBA_fnc_polar2vect));
|
||||
drawLine3D [_camAGL, _target, [0,1,0,1]];
|
||||
private _target = _vehicle modelToWorldVisual (_camLocation vectorAdd ([1, _camAttach, 1] call CBA_fnc_polar2vect));
|
||||
drawLine3D [_camAGL, _target, [0,1,0,1]];
|
||||
private _target = _vehicle modelToWorldVisual (_camLocation vectorAdd ([1, _camAttach, -1] call CBA_fnc_polar2vect));
|
||||
drawLine3D [_camAGL, _target, [0,1,0,1]];
|
||||
private _target = _vehicle modelToWorldVisual (_camLocation vectorAdd ([0.2, _camAttach+90, 0] call CBA_fnc_polar2vect));
|
||||
drawLine3D [_camAGL, _target, [1,0,1,1]];
|
||||
private _target = _vehicle modelToWorldVisual (_camLocation vectorAdd ([0.2, _camAttach-90, 0] call CBA_fnc_polar2vect));
|
||||
drawLine3D [_camAGL, _target, [1,0,1.2,1]];
|
||||
};
|
||||
} forEach _viewports;
|
||||
}];
|
77
addons/viewports/functions/fnc_eachFrame.sqf
Normal file
77
addons/viewports/functions/fnc_eachFrame.sqf
Normal file
@ -0,0 +1,77 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Runs each frame while inside of a vehicle with viewports
|
||||
*
|
||||
* Arguments:
|
||||
* 0: PFEH Args <ARRAY>
|
||||
* 0: Player <OBJECT>
|
||||
* 1: Vehicle <OBJECT>
|
||||
* 2: Viewport configuration <ARRAY>
|
||||
* 3: Viewport index shown (-1 for none) <NUMBER>
|
||||
* 4: Last visionmode <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_viewports_fnc_eachFrame
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_args", "_pfID"];
|
||||
_args params ["_player", "_vehicle", "_viewports", "_shownIndex", "_lastVisionMode"];
|
||||
|
||||
private _newIndex = -1;
|
||||
if (cba_events_control) then {
|
||||
if (cameraView != "INTERNAL") exitWith {};
|
||||
if (isTurnedOut _player) exitWith {};
|
||||
if (!([_player, _vehicle, []] call EFUNC(common,canInteractWith))) exitWith {};
|
||||
|
||||
BEGIN_COUNTER(newIndex);
|
||||
if ((_shownIndex > -1) && {currentVisionMode _player != _lastVisionMode}) then {
|
||||
// Vision Mode Changed - Force stop cam and restart
|
||||
call FUNC(viewCleanup);
|
||||
_shownIndex = -1;
|
||||
};
|
||||
|
||||
([_player] call FUNC(getSeatInfo)) params ["_role", "", "", "_comparment"];
|
||||
|
||||
private _newIndexAngle = 45; // Controls the max angle
|
||||
private _eyesPosASL = AGLtoASL (positionCameraToWorld [0, 0, 0]);
|
||||
private _eyesDir = (AGLtoASL (positionCameraToWorld [0, 0, 1])) vectorDiff _eyesPosASL;
|
||||
{
|
||||
_x params ["", "", "_camLocation", "", "_screenLocation", "_maxDistance", "_compartments", "_roles"];
|
||||
|
||||
private _viewASL = AGLtoASL (_vehicle modelToWorldVisual _screenLocation);
|
||||
private _viewDiff = _viewASL vectorDiff _eyesPosASL;
|
||||
private _viewAngle = acos (_viewDiff vectorCos _eyesDir);
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
systemChat format ["%1: %2 @ %3",_forEachIndex,round _viewAngle, vectorMagnitude _viewDiff];
|
||||
#endif
|
||||
if (
|
||||
(_viewAngle < _newIndexAngle)
|
||||
&& {(_compartments isEqualTo []) || {(toLower _comparment) in _compartments}}
|
||||
&& {(_roles isEqualTo []) || {(toLower _role) in _roles}}
|
||||
&& {(vectorMagnitude _viewDiff) < _maxDistance}
|
||||
) then {
|
||||
_newIndex = _forEachIndex;
|
||||
_newIndexAngle = _viewAngle;
|
||||
};
|
||||
} forEach _viewports;
|
||||
END_COUNTER(newIndex);
|
||||
};
|
||||
|
||||
if (_shownIndex == _newIndex) exitWith {}; // No-change - fast exit
|
||||
|
||||
if (_shownIndex > -1) then {
|
||||
call FUNC(viewCleanup);
|
||||
};
|
||||
|
||||
if (_newIndex > -1) then {
|
||||
[_vehicle, _viewports # _newIndex, currentVisionMode _player] call FUNC(viewCreate);
|
||||
_args set [4, currentVisionMode _player];
|
||||
};
|
||||
|
||||
_args set [3, _newIndex];
|
36
addons/viewports/functions/fnc_enterVehicle.sqf
Normal file
36
addons/viewports/functions/fnc_enterVehicle.sqf
Normal file
@ -0,0 +1,36 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Handle playerEH for new changing vehicle, check if it has any viewports and start PFEH
|
||||
*
|
||||
* Arguments:
|
||||
* 0: player <OBJECT>
|
||||
* 1: vehicle <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [player, vehicle player] call ace_viewports_fnc_enterVehicle
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_player", "_vehicle"];
|
||||
TRACE_2("enterVehicle",_player,_vehicle);
|
||||
|
||||
if (GVAR(pfeh) != -1) then {
|
||||
TRACE_1("cleaning up",GVAR(pfeh));
|
||||
[GVAR(pfeh)] call CBA_fnc_removePerFrameHandler;
|
||||
GVAR(pfeh) = -1;
|
||||
call FUNC(viewCleanup);
|
||||
};
|
||||
|
||||
if (!GVAR(enabled)) exitWith {};
|
||||
if (_player == _vehicle) exitWith {};
|
||||
|
||||
private _viewports = [_vehicle] call FUNC(getViewports);
|
||||
if (_viewports isEqualTo []) exitWith {};
|
||||
|
||||
GVAR(pfeh) = [LINKFUNC(eachFrame), 0, [_player, _vehicle, _viewports, -1, -1]] call CBA_fnc_addPerFrameHandler;
|
||||
TRACE_3("start pfeh",GVAR(pfeh),typeOf _vehicle,count _viewports);
|
46
addons/viewports/functions/fnc_getSeatInfo.sqf
Normal file
46
addons/viewports/functions/fnc_getSeatInfo.sqf
Normal file
@ -0,0 +1,46 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: Dystopian, PabstMirror
|
||||
* Adapted from quickmount's addFreeSeatsActions
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Unit <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* ARRAY
|
||||
*
|
||||
* Example:
|
||||
* [player] call ace_viewports_fnc_getSeatInfo
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_unit"];
|
||||
|
||||
private _vehicle = vehicle _unit;
|
||||
if (_vehicle == _unit) exitWith { [] };
|
||||
private _vehicleConfig = configOf _vehicle;
|
||||
|
||||
private _fullCrew = fullCrew [_vehicle, "", false];
|
||||
(_fullCrew select (_fullCrew findIf {_unit == _x select 0})) params ["", "_role", "_cargoIndex", "_turretPath"];
|
||||
|
||||
private _compartment = switch (_role) do {
|
||||
case "driver": {
|
||||
(_vehicleConfig >> "driverCompartments") call BIS_fnc_getCfgData
|
||||
};
|
||||
case "cargo": {
|
||||
// note: cargoNumber is different from the cargoIndex from fullCrew...
|
||||
private _cargoNumber = fullCrew [_vehicle, "cargo", true] findIf {_unit == _x select 0};
|
||||
private _cargoCompartments = getArray (_vehicleConfig >> "cargoCompartments");
|
||||
private _cargoCompartmentsLast = count _cargoCompartments - 1;
|
||||
_cargoCompartments select (_cargoNumber min _cargoCompartmentsLast)
|
||||
};
|
||||
default {
|
||||
private _turretConfig = [_vehicleConfig, _turretPath] call CBA_fnc_getTurret;
|
||||
(_turretConfig >> "gunnerCompartments") call BIS_fnc_getCfgData
|
||||
};
|
||||
};
|
||||
|
||||
if (!(_compartment isEqualType "")) then { _compartment = format ["Compartment%1",_compartment] };
|
||||
|
||||
[_role, _cargoIndex, _turretPath, _compartment]
|
74
addons/viewports/functions/fnc_getViewports.sqf
Normal file
74
addons/viewports/functions/fnc_getViewports.sqf
Normal file
@ -0,0 +1,74 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Gets viewports for a vehicle from config. Caches results to a setVar on the vic.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: vehicle <OBJECT>
|
||||
*
|
||||
* Return Value:
|
||||
* ARRAY
|
||||
*
|
||||
* Example:
|
||||
* [vehicle player] call ace_viewports_fnc_getViewports
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle"];
|
||||
|
||||
private _viewports = _vehicle getVariable [QGVAR(viewports), nil];
|
||||
|
||||
if (isNil "_viewports") then {
|
||||
_viewports = (configProperties [(configOf _vehicle) >> "ace_viewports", "isClass _x", true]) apply {
|
||||
// name [STRING] is just used for debug
|
||||
private _name = configName _x;
|
||||
// type [STRING] - Optional
|
||||
private _type = getText (_x >> "type");
|
||||
// camLocation [ARRAY or STRING] - Required
|
||||
private _camLocation = if (isArray (_x >> "camLocation")) then {
|
||||
getArray (_x >> "camLocation") // modelOffset
|
||||
} else {
|
||||
getText (_x >> "camLocation") // memPoint
|
||||
};
|
||||
// camAttach [ARRAY or NUMBER] - Required
|
||||
private _camAttach = if (isArray (_x >> "camAttach")) then {
|
||||
getArray (_x >> "camAttach") // turret
|
||||
} else {
|
||||
getNumber (_x >> "camAttach") // angle
|
||||
};
|
||||
// screenLocation [ARRAY or STRING] - Optional (will be converted to ARRAY here!)
|
||||
private _screenLocation = if (isArray (_x >> "screenLocation")) then {
|
||||
getArray (_x >> "screenLocation") // modelOffset
|
||||
} else {
|
||||
getText (_x >> "screenLocation") // memPoint
|
||||
};
|
||||
if (_screenLocation isEqualType "") then {
|
||||
// screens should be on the hull (IE non-animated) so we can do all the mem-point calculations here
|
||||
if (_screenLocation == "") exitWith { // use generic periscope drop height from cam
|
||||
private _camLocArray = if (_camLocation isEqualType []) then {
|
||||
_camLocation
|
||||
} else {
|
||||
_vehicle selectionPosition [_camLocation, "Memory"];
|
||||
};
|
||||
_screenLocation =_camLocArray vectorAdd [0,0,-0.175]
|
||||
};
|
||||
_screenLocation = _vehicle selectionPosition [_screenLocation, "Memory"];
|
||||
};
|
||||
// maxDistance [NUMBER] - Optional
|
||||
private _maxDistance = getNumber (_x >> "maxDistance");
|
||||
if (_maxDistance == 0) then {
|
||||
_maxDistance = 0.8;
|
||||
};
|
||||
// compartments [ARRAY] - Optional
|
||||
private _compartments = (getArray (_x >> "compartments")) apply {toLower _x};
|
||||
// roles [ARRAY] - Optional
|
||||
private _roles = (getArray (_x >> "roles")) apply {toLower _x};
|
||||
|
||||
[_name, _type, _camLocation, _camAttach, _screenLocation, _maxDistance, _compartments, _roles]
|
||||
};
|
||||
TRACE_3("getViewports",_vehicle,typeOf _vehicle,count _viewports);
|
||||
_vehicle setVariable [QGVAR(viewports), _viewports];
|
||||
};
|
||||
|
||||
_viewports
|
28
addons/viewports/functions/fnc_viewCleanup.sqf
Normal file
28
addons/viewports/functions/fnc_viewCleanup.sqf
Normal file
@ -0,0 +1,28 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Cleans up existing viewport display and camera
|
||||
*
|
||||
* Arguments:
|
||||
* None
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_viewports_fnc_viewCleanup
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
TRACE_1("camCleanup",_this);
|
||||
|
||||
if (!isNull (missionNamespace getVariable [QGVAR(camera), objNull])) then {
|
||||
GVAR(camera) cameraEffect ["terminate", "back", QGVAR(pip0)];
|
||||
camDestroy GVAR(camera);
|
||||
};
|
||||
|
||||
private _display = uiNamespace getVariable [QGVAR(display), displayNull];
|
||||
if (!isNull _display) then {
|
||||
QGVAR(display) cutText ["", "PLAIN"];
|
||||
};
|
129
addons/viewports/functions/fnc_viewCreate.sqf
Normal file
129
addons/viewports/functions/fnc_viewCreate.sqf
Normal file
@ -0,0 +1,129 @@
|
||||
#include "script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Creates a viewport display and camera
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Vehicle <OBJECT>
|
||||
* 1: Viewport <ARRAY>
|
||||
* 2: Player's vision mode <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [...] call ace_viewports_fnc_viewCreate
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_vehicle", "_viewport", "_visionMode"];
|
||||
_viewport params ["_name", "_type", "_camLocation", "_camAttach"];
|
||||
TRACE_5("camCreate",_vehicle,_name,_type,_camLocation,_camAttach);
|
||||
|
||||
private _usingGoggles = _visionMode > 0;
|
||||
|
||||
if (_camLocation isEqualType "") then {
|
||||
_camLocation = _vehicle selectionPosition [_camLocation, "Memory"];
|
||||
if (_camLocation isEqualTo [0,0,0]) then { WARNING_2("probably bad cam location %1:%2",typeOf _vehicle,_viewport); }
|
||||
};
|
||||
|
||||
// Create Cam and attach it to vic
|
||||
GVAR(camera) = "camera" camCreate getPos _vehicle;
|
||||
if (_camAttach isEqualType 0) then {
|
||||
// number - Static attach and set const direction
|
||||
GVAR(camera) attachTo [_vehicle, _camLocation];
|
||||
GVAR(camera) setDir _camAttach; // could do pitch as well, but probably not needed
|
||||
} else {
|
||||
// array - Turret path, get gunner optic mem and bone-attach to it
|
||||
private _turretConfig = [_vehicle, _camAttach] call CBA_fnc_getTurret;
|
||||
private _memoryPointGunnerOptics = getText(_turretConfig >> "memoryPointGunnerOptics");
|
||||
GVAR(camera) attachTo [_vehicle, _camLocation, _memoryPointGunnerOptics, true];
|
||||
};
|
||||
|
||||
// Setup r2texture
|
||||
GVAR(camera) cameraEffect ["INTERNAL", "BACK", QGVAR(pip0)];
|
||||
private _renderTexture = format ["#(argb,512,512,1)r2t(%1,1)", QGVAR(pip0)];
|
||||
|
||||
// Create blank display
|
||||
QGVAR(display) cutRsc [QGVAR(display), "PLAIN", 0, false];
|
||||
private _display = uiNamespace getVariable [QGVAR(display), displayNull];
|
||||
|
||||
|
||||
// R2T aspect ratio parameter has no effect - it will match main video AR
|
||||
// better to have ui elements squashed than to squash the R2T
|
||||
private _screenAR = getResolution select 4;
|
||||
private _camEffect = [0];
|
||||
private _camFov = 0.75;
|
||||
|
||||
|
||||
switch (true) do {
|
||||
case (_type == "screen"): {
|
||||
// Generic "Squad Leader's Display" monitor showing turret cam
|
||||
private _desiredAR = 1.25;
|
||||
private _stretch = (_desiredAR / _screenAR) max 0.8 min 1.25; // define max stretch factor of pip texture (don't stretch more or less than this)
|
||||
|
||||
private _viewHeight = 0.3 * safeZoneH;
|
||||
private _viewWidth = _stretch * _viewHeight * _screenAR / 1.3333333333333;
|
||||
|
||||
private _ctrlRender = _display ctrlCreate ["RscPicture", -1];
|
||||
_ctrlRender ctrlSetText _renderTexture;
|
||||
_ctrlRender ctrlSetPosition [safezoneX + 0.5 * safezoneW - 0.5 * _viewWidth, safezoneY + 0.5 * safeZoneH - 0.5 * _viewHeight, _viewWidth, _viewHeight];
|
||||
_ctrlRender ctrlCommit 0;
|
||||
|
||||
private _ctrlOverlay = _display ctrlCreate ["RscPicture", -1];
|
||||
_ctrlOverlay ctrlSetText "\a3\weapons_f\reticle\data\optika_tv_ca.paa";
|
||||
_ctrlOverlay ctrlSetPosition [safezoneX + 0.5 * safezoneW - 0.5 * _viewWidth, safezoneY + 0.5 * safeZoneH - 0.5 * _viewHeight, _viewWidth, _viewHeight];
|
||||
_ctrlOverlay ctrlCommit 0;
|
||||
|
||||
if (_usingGoggles) then {
|
||||
// Screen will be out of focus, too bright and not in IR; should be almost impossible to see anything useful
|
||||
_camEffect = [3,1,1,0.1,0,[0,0,0,0],[1,1,1,0],[1,1,1,1]];
|
||||
|
||||
private _ctrlNVG = _display ctrlCreate ["RscPicture", -1];
|
||||
_ctrlNVG ctrlSetText "#(argb,8,8,3)color(1,1,0.6,0.9)";
|
||||
_ctrlNVG ctrlSetPosition [safezoneX + 0.5 * safezoneW - 0.5 * _viewWidth, safezoneY + 0.5 * safeZoneH - 0.5 * _viewHeight, _viewWidth, _viewHeight];
|
||||
_ctrlNVG ctrlCommit 0;
|
||||
} else {
|
||||
_camEffect = [0]; // 2.08's currentVisionMode change could allow matching real turret's vision mode
|
||||
};
|
||||
_camFov = 0.25;
|
||||
};
|
||||
default {
|
||||
// Generic periscope viewport
|
||||
private _desiredAR = 3;
|
||||
private _stretch = (_desiredAR / _screenAR) max 0.8 min 1.25; // define max stretch factor of pip texture
|
||||
private _viewHeight = 0.3 * safeZoneH;
|
||||
|
||||
if (_usingGoggles) then {
|
||||
_camEffect = [_visionMode]; // pass-thru
|
||||
// _camEffect = [3, true, 0.747773,0.791092,0,[0,0,0,0],[1.3,1.2,0,0.9],[6,1,1,0]];
|
||||
// Some periscope glass is IR Laser Safe (~1064nm) which is close to same wavelength as NVGs
|
||||
// And cannot apply nvg and ace_nightvision effects to pip at same time, so just make it small and shitty...
|
||||
_viewHeight = 0.45 * _viewHeight;
|
||||
};
|
||||
private _viewWidth = _stretch * _viewHeight * _screenAR / 1.3333333333333;
|
||||
|
||||
private _ctrlRender = _display ctrlCreate ["RscPicture", -1];
|
||||
_ctrlRender ctrlSetText _renderTexture;
|
||||
_ctrlRender ctrlSetPosition [safezoneX + 0.5 * safezoneW - 0.5 * _viewWidth, safezoneY + 0.5 * safeZoneH - 0.5 * _viewHeight, _viewWidth, _viewHeight];
|
||||
_ctrlRender ctrlCommit 0;
|
||||
|
||||
if (_usingGoggles) then {
|
||||
// Roughly try to color match ace_nvg, and make it semi-opaque
|
||||
private _ctrlNVG = _display ctrlCreate ["RscPicture", -1];
|
||||
_ctrlNVG ctrlSetText "#(argb,8,8,3)color(0.25,0.2,0.05,0.75)";
|
||||
_ctrlNVG ctrlSetPosition [safezoneX + 0.5 * safezoneW - 0.5 * _viewWidth, safezoneY + 0.5 * safeZoneH - 0.5 * _viewHeight, _viewWidth, _viewHeight];
|
||||
_ctrlNVG ctrlCommit 0;
|
||||
};
|
||||
|
||||
private _ctrlOverlay = _display ctrlCreate ["RscPicture", -1];
|
||||
_ctrlOverlay ctrlSetText QPATHTOF(data\optic_window_ca.paa);
|
||||
_ctrlOverlay ctrlSetPosition [safezoneX + 0.5 * safezoneW - 0.5 * _viewWidth, safezoneY + 0.5 * safeZoneH - 0.5 * _viewHeight, _viewWidth, _viewHeight];
|
||||
_ctrlOverlay ctrlCommit 0;
|
||||
};
|
||||
};
|
||||
|
||||
GVAR(camera) camSetFov _camFov;
|
||||
QGVAR(pip0) setPiPEffect _camEffect;
|
||||
GVAR(camera) camCommit 0;
|
1
addons/viewports/functions/script_component.hpp
Normal file
1
addons/viewports/functions/script_component.hpp
Normal file
@ -0,0 +1 @@
|
||||
#include "\z\ace\addons\viewports\script_component.hpp"
|
11
addons/viewports/gui.hpp
Normal file
11
addons/viewports/gui.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
class RscTitles {
|
||||
class GVAR(display) {
|
||||
idd = -1;
|
||||
onLoad = QUOTE( with uiNameSpace do { GVAR(display) = _this select 0 }; );
|
||||
movingEnable = 0;
|
||||
duration = 9999999;
|
||||
fadeIn = 0;
|
||||
fadeOut = 0;
|
||||
class controls {};
|
||||
};
|
||||
};
|
9
addons/viewports/initSettings.sqf
Normal file
9
addons/viewports/initSettings.sqf
Normal file
@ -0,0 +1,9 @@
|
||||
[
|
||||
QGVAR(enabled), "CHECKBOX",
|
||||
[LELSTRING(common,Enabled), LLSTRING(setting_enabled_description)],
|
||||
[ELSTRING(common,ACEKeybindCategoryVehicles), LSTRING(addon_displayname)],
|
||||
true,
|
||||
true,
|
||||
{},
|
||||
false // Doesn't need full mission restart, but you have to exit and re-enter vic
|
||||
] call CBA_fnc_addSetting;
|
18
addons/viewports/script_component.hpp
Normal file
18
addons/viewports/script_component.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#define COMPONENT viewports
|
||||
#define COMPONENT_BEAUTIFIED Viewports
|
||||
#include "\z\ace\addons\main\script_mod.hpp"
|
||||
|
||||
// #define DEBUG_MODE_FULL
|
||||
// #define DISABLE_COMPILE_CACHE
|
||||
// #define ENABLE_PERFORMANCE_COUNTERS
|
||||
// #define POINT_CONFIG_DEBUG
|
||||
|
||||
#ifdef DEBUG_ENABLED_VIEWPORTS
|
||||
#define DEBUG_MODE_FULL
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_SETTINGS_VIEWPORTS
|
||||
#define DEBUG_SETTINGS DEBUG_SETTINGS_VIEWPORTS
|
||||
#endif
|
||||
|
||||
#include "\z\ace\addons\main\script_macros.hpp"
|
11
addons/viewports/stringtable.xml
Normal file
11
addons/viewports/stringtable.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project name="ACE">
|
||||
<Package name="Viewports">
|
||||
<Key ID="STR_ACE_Viewports_addon_displayname">
|
||||
<English>Viewports</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Viewports_setting_enabled_description">
|
||||
<English>Allows crew to look through periscopes</English>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
24
docs/wiki/feature/viewports.md
Normal file
24
docs/wiki/feature/viewports.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
layout: wiki
|
||||
title: Viewports
|
||||
description: Allows crew to look through periscopes.
|
||||
group: feature
|
||||
category: interaction
|
||||
parent: wiki
|
||||
mod: ace
|
||||
version:
|
||||
major: 3
|
||||
minor: x
|
||||
patch: y
|
||||
---
|
||||
|
||||
## 1. Overview
|
||||
Allows crew to look through periscopes.
|
||||
|
||||
## 2. Usage
|
||||
- Hold <kbd>Ctrl</kbd>
|
||||
- Look at a supported periscope or display monitor
|
||||
|
||||
## 3. Dependencies
|
||||
|
||||
{% include dependencies_list.md component="viewports" %}
|
56
docs/wiki/framework/viewports-framework.md
Normal file
56
docs/wiki/framework/viewports-framework.md
Normal file
@ -0,0 +1,56 @@
|
||||
---
|
||||
layout: wiki
|
||||
title: Viewports Framework
|
||||
description: How to configure a vehicle for viewports
|
||||
group: framework
|
||||
order: 5
|
||||
parent: wiki
|
||||
mod: ace
|
||||
version:
|
||||
major: 3
|
||||
minor: x
|
||||
patch: y
|
||||
---
|
||||
|
||||
## 1. Config Values
|
||||
|
||||
Reference [ace_viewports_fnc_getViewports](https://github.com/acemod/ACE3/blob/master/addons/viewports/functions/fnc_getViewports.sqf)
|
||||
|
||||
```cpp
|
||||
class myVehicle {
|
||||
class ace_viewports {
|
||||
class Template {
|
||||
// type [STRING] - Optional
|
||||
type = "";
|
||||
// camLocation [ARRAY or STRING] - Required
|
||||
camLocation = "memoryPointP1";
|
||||
camLocation[] = {1,2,3}; // model offset
|
||||
// camAttach [ARRAY or NUMBER] - Required
|
||||
camAttach[] = {0,0}; // Turret path
|
||||
camAttach = 55; // Direction in degrees
|
||||
// screenLocation [ARRAY or STRING] - Optional
|
||||
screenLocation = "memoryPointP1x";
|
||||
screenLocation[] = {1,2,3};
|
||||
// maxDistance [NUMBER] - Optional
|
||||
maxDistance = 0.75;
|
||||
// compartments [ARRAY] - Optional
|
||||
compartments[]={"Compartment1"};
|
||||
// roles [ARRAY] - Optional
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class periscope_0 {
|
||||
camLocation[] = {0.987915, -0.324707, -0.0673385};
|
||||
camAttach = 70;
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class commandersView {
|
||||
screenLocation[] = {0.729126,-0.191597,-0.573349};
|
||||
maxDistance = 5;
|
||||
type = "screen";
|
||||
camLocation[] = {0,0,0.05};
|
||||
camAttach[] = {0,0};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
@ -226,11 +226,103 @@ class CfgVehicles {
|
||||
};
|
||||
class rhs_btr70_vmf: rhs_btr_base {
|
||||
EGVAR(refuel,fuelCapacity) = 350;
|
||||
class ace_viewports {
|
||||
class view_0 {
|
||||
camLocation[] = {0.478394, -0.575, -0.145};
|
||||
camAttach = 90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_1 {
|
||||
camLocation[] = {-1.38184, -0.575, -0.145};
|
||||
camAttach = -90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
class rhs_btr70_msv: rhs_btr70_vmf {};
|
||||
class rhs_btr80_msv: rhs_btr70_msv {
|
||||
EGVAR(refuel,fuelCapacity) = 300;
|
||||
class ace_viewports {
|
||||
class view_0 {
|
||||
camLocation[] = {0.534424, -0.336914, 0.636819};
|
||||
camAttach = 45;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_1 {
|
||||
camLocation[] = {0.760254, -0.459473, 0.526328};
|
||||
camAttach = 90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_2 {
|
||||
camLocation[] = {0.770508, -1.21924, 0.526954};
|
||||
camAttach = 90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_3 {
|
||||
camLocation[] = {-1.13, -1.2085, 0.490339};
|
||||
camAttach = -90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_4 {
|
||||
camLocation[] = {-1.14124, -0.416992, 0.460611};
|
||||
camAttach = -90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_5 {
|
||||
camLocation[] = {-0.932983, -0.326172, 0.647666};
|
||||
camAttach = -45;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
};
|
||||
};
|
||||
class rhs_btr80a_msv: rhs_btr80_msv {
|
||||
class ace_viewports {
|
||||
class view_0 {
|
||||
camLocation[] = {0.589844, -0.314941, 0.449678};
|
||||
camAttach = 45;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_1 {
|
||||
camLocation[] = {0.809082, -0.442871, 0.276865};
|
||||
camAttach = 90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_2 {
|
||||
camLocation[] = {0.819092, -1.24414, 0.27857};
|
||||
camAttach = 90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_3 {
|
||||
camLocation[] = {-1.1012, -1.22461, 0.341089};
|
||||
camAttach = -90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_4 {
|
||||
camLocation[] = {-1.11597, -0.458984, 0.307256};
|
||||
camAttach = -90;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
class view_5 {
|
||||
camLocation[] = {-0.869995, -0.304688, 0.461181};
|
||||
camAttach = -45;
|
||||
compartments[]={"Compartment1"};
|
||||
roles[]={"cargo"};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
class rhs_2s3tank_base: Tank_F {
|
||||
|
Loading…
Reference in New Issue
Block a user