From 85a77150c9ea0be2567433e8854a7a67673ccda4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Badano?= Date: Sat, 28 Feb 2015 17:48:46 -0300 Subject: [PATCH] - Add cursored self interaction menu (for using inside vehicles) - Renamed the base menu "SelfActions" to "ACE_SelfActions" - Limit the amount of objects the player is shown interactions with. This are the 3 nearest objects which have active action points visible on screen. - Cull action points that are not visible, to far away, etc before checking if they are active. --- addons/interact_menu/CursorMenus.hpp | 47 +++++++++++ addons/interact_menu/config.cpp | 2 + .../functions/fnc_compileMenu.sqf | 2 +- .../functions/fnc_compileMenuSelfAction.sqf | 4 +- .../interact_menu/functions/fnc_keyDown.sqf | 4 + .../functions/fnc_keyDownSelfAction.sqf | 18 ++++- .../functions/fnc_keyUpSelfAction.sqf | 4 + addons/interact_menu/functions/fnc_render.sqf | 80 ++++++++++++------- .../functions/fnc_renderIcon.sqf | 5 +- .../functions/fnc_renderMenu.sqf | 32 +++++--- addons/interaction/CfgVehicles.hpp | 22 ++--- 11 files changed, 163 insertions(+), 57 deletions(-) create mode 100644 addons/interact_menu/CursorMenus.hpp diff --git a/addons/interact_menu/CursorMenus.hpp b/addons/interact_menu/CursorMenus.hpp new file mode 100644 index 0000000000..d13813b92e --- /dev/null +++ b/addons/interact_menu/CursorMenus.hpp @@ -0,0 +1,47 @@ +class GVAR(cursorMenu) { + idd = 91919; + movingEnable = false; + onLoad = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(dlgCursorMenu)),_this select 0)]; uiNamespace setVariable [ARR_2(QUOTE(QGVAR(cursorMenuOpened)),true)]); + onUnload = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(cursorMenuOpened)),false)]); + objects[] = {}; + /*class controlsBackground { + class Background { + idc = 91920; + moving = 0; + font = "TahomaB"; + text = ""; + sizeEx = 0; + lineSpacing = 0; + access = 0; + type = 0; + style = 0; + size = 1; + colorBackground[] = {0, 0, 0, 0.5}; + colorText[] = {0, 0, 0, 0}; + x = "safezoneX"; + y = "safezoneY"; + w = "safezoneW"; + h = "safezoneH"; + }; + };*/ + class controls { + class Canvas { + idc = 91921; + moving = 0; + font = "TahomaB"; + text = ""; + sizeEx = 0; + lineSpacing = 0; + access = 0; + type = 0; + style = 0; + size = 1; + colorBackground[] = {0, 0, 0, 0}; + colorText[] = {0, 0, 0, 0}; + x = "safezoneX"; + y = "safezoneY"; + w = "safezoneW"; + h = "safezoneH"; + }; + }; +}; diff --git a/addons/interact_menu/config.cpp b/addons/interact_menu/config.cpp index 784c6529d6..528d272d6c 100644 --- a/addons/interact_menu/config.cpp +++ b/addons/interact_menu/config.cpp @@ -13,3 +13,5 @@ class CfgPatches { }; #include "CfgEventHandlers.hpp" + +#include "CursorMenus.hpp" diff --git a/addons/interact_menu/functions/fnc_compileMenu.sqf b/addons/interact_menu/functions/fnc_compileMenu.sqf index c6e9ec3a8f..cd9f8f51c7 100644 --- a/addons/interact_menu/functions/fnc_compileMenu.sqf +++ b/addons/interact_menu/functions/fnc_compileMenu.sqf @@ -89,7 +89,7 @@ missionNamespace setVariable [_actionsVarName, [_actionsCfg, []] call _recurseFn 1, [], uid, - ["MainActions","TeamManagement","MyAction"] + ["ACE_MainActions","TeamManagement","MyAction"] ] ] */ diff --git a/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf b/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf index f6bf1a0707..d4096d123f 100644 --- a/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf +++ b/addons/interact_menu/functions/fnc_compileMenuSelfAction.sqf @@ -81,9 +81,9 @@ _actions = [[ { true }, { true }, 10, - [_actionsCfg, ["SelfActions"]] call _recurseFnc, + [_actionsCfg, ["ACE_SelfActions"]] call _recurseFnc, GVAR(uidCounter), - ["SelfActions"] + ["ACE_SelfActions"] ] ]; GVAR(uidCounter) = GVAR(uidCounter) + 1; diff --git a/addons/interact_menu/functions/fnc_keyDown.sqf b/addons/interact_menu/functions/fnc_keyDown.sqf index 5d37019858..4a0592b5b8 100644 --- a/addons/interact_menu/functions/fnc_keyDown.sqf +++ b/addons/interact_menu/functions/fnc_keyDown.sqf @@ -13,6 +13,10 @@ #include "script_component.hpp" if(!GVAR(keyDown)) then { + + // Only interact with others if on foot + if (vehicle ACE_player != ACE_player) exitWith {}; + GVAR(keyDown) = true; GVAR(keyDownTime) = diag_tickTime; }; diff --git a/addons/interact_menu/functions/fnc_keyDownSelfAction.sqf b/addons/interact_menu/functions/fnc_keyDownSelfAction.sqf index be46dd132c..e91b5c6063 100644 --- a/addons/interact_menu/functions/fnc_keyDownSelfAction.sqf +++ b/addons/interact_menu/functions/fnc_keyDownSelfAction.sqf @@ -17,6 +17,22 @@ if(!GVAR(keyDownSelfAction)) then { GVAR(keyDown) = false; GVAR(keyDownTime) = diag_tickTime; - GVAR(selfMenuOffset) = [sin getDir ACE_player, cos getDir ACE_player, 0] vectorMultiply 2; + GVAR(useCursorMenu) = (vehicle ACE_player != ACE_player) || visibleMap; + + if (GVAR(useCursorMenu)) then { + closeDialog 0; + createDialog QGVAR(cursorMenu); + // The dialog sets: + // uiNamespace getVariable QGVAR(dlgCursorMenu); + // uiNamespace getVariable QGVAR(cursorMenuOpened); + ctrlEnable [91921, true]; + ((finddisplay 91919) displayctrl 91921) ctrlAddEventHandler ["MouseMoving", { + GVAR(cursorPos) = [_this select 1, _this select 2, 0]; + }]; + setMousePosition [0.5, 0.5]; + + }; + GVAR(selfMenuOffset) = (positionCameraToWorld [0, 0, 2]) vectorDiff (positionCameraToWorld [0, 0, 0]); + //systemChat format ["GVAR(selfMenuOffset) %1",GVAR(selfMenuOffset)]; }; true diff --git a/addons/interact_menu/functions/fnc_keyUpSelfAction.sqf b/addons/interact_menu/functions/fnc_keyUpSelfAction.sqf index e95c381eb3..1842587984 100644 --- a/addons/interact_menu/functions/fnc_keyUpSelfAction.sqf +++ b/addons/interact_menu/functions/fnc_keyUpSelfAction.sqf @@ -12,6 +12,10 @@ */ #include "script_component.hpp" +if (uiNamespace getVariable [QGVAR(cursorMenuOpened),false]) then { + closeDialog 0; +}; + GVAR(keyDownSelfAction) = false; if(GVAR(actionSelected)) then { this = GVAR(selectedTarget); diff --git a/addons/interact_menu/functions/fnc_render.sqf b/addons/interact_menu/functions/fnc_render.sqf index 03efb07112..c4cb9ad32f 100644 --- a/addons/interact_menu/functions/fnc_render.sqf +++ b/addons/interact_menu/functions/fnc_render.sqf @@ -17,45 +17,59 @@ _foundTarget = false; _cursorPos1 = positionCameraToWorld [0, 0, 0]; _cursorPos2 = positionCameraToWorld [0, 0, 2]; +GVAR(selfMenuScale) = (((worldToScreen (positionCameraToWorld [1,0,2])) select 0) - + ((worldToScreen (positionCameraToWorld [0,0,2])) select 0)) / 0.6; +//systemChat format ["selfMenuScale: %1", GVAR(selfMenuScale)]; GVAR(currentOptions) = []; private ["_actionsVarName","_classActions","_objectActions","_target","_player","_actionItem","_active"]; +_player = ACE_player; if (GVAR(keyDown)) then { [] call FUNC(updateVecLineMap); // Render all nearby interaction menus + #define MAXINTERACTOBJECTS 3 + private ["_numInteractObjects","_numInteractions"]; + _numInteractObjects = 0; + _nearestObjects = nearestObjects [(getPos ACE_player), ["All"], 15]; { _target = _x; - _player = ACE_player; - // Iterate through object actions, find base level actions and render them if appropiate - _actionsVarName = format [QGVAR(Act_%1), typeOf _target]; - GVAR(objectActions) = _target getVariable [QGVAR(actions), []]; - { - _actionItem = _x; - // Only render them directly if they are base level actions - if (count (_actionItem select 8) == 1) then { - _active = [_target, ACE_player] call (_actionItem select 4); + _numInteractions = 0; + // Prevent interacting with yourself or your own vehicle + if (_target != ACE_player && {_target != vehicle ACE_player}) then { - if (_active) then { - [_target, _actionItem, 0, [180, 360]] call FUNC(renderMenu); + // Iterate through object actions, find base level actions and render them if appropiate + _actionsVarName = format [QGVAR(Act_%1), typeOf _target]; + GVAR(objectActions) = _target getVariable [QGVAR(actions), []]; + { + _actionItem = _x; + // Only render them directly if they are base level actions + if (count (_actionItem select 8) == 1) then { + // Try to render the menu + if ([_target, _actionItem, false, [180, 360]] call FUNC(renderMenu)) then { + _numInteractions = _numInteractions + 1; + }; }; + } forEach GVAR(objectActions); + + // Iterate through base level class actions and render them if appropiate + _classActions = missionNamespace getVariable [_actionsVarName, []]; + { + _actionItem = _x; + // Try to render the menu + if ([_target, _actionItem, false, [180, 360]] call FUNC(renderMenu)) then { + _numInteractions = _numInteractions + 1; + }; + } forEach _classActions; + + // Limit the amount of objects the player can interact with + if (_numInteractions > 0) then { + _numInteractObjects = _numInteractObjects + 1; }; - } forEach GVAR(objectActions); - - // Iterate through base level class actions and render them if appropiate - _classActions = missionNamespace getVariable [_actionsVarName, []]; - { - _actionItem = _x; - _active = [_target, ACE_player] call (_actionItem select 4); - - if (_active) then { - [_target, _actionItem, 0, [180, 360]] call FUNC(renderMenu); - }; - } forEach _classActions; - - + }; + if (_numInteractObjects >= MAXINTERACTOBJECTS) exitWith {}; } forEach _nearestObjects; @@ -66,11 +80,11 @@ if (GVAR(keyDown)) then { // Render only the self action menu _target = vehicle ACE_player; - _player = ACE_player; // Iterate through object actions, find base level actions and render them if appropiate _actionsVarName = format [QGVAR(SelfAct_%1), typeOf _target]; GVAR(objectActions) = _target getVariable [QGVAR(selfActions), []]; + /* { _actionItem = _x; // Only render them directly if they are base level actions @@ -82,6 +96,7 @@ if (GVAR(keyDown)) then { }; }; } forEach GVAR(objectActions); + */ // Iterate through base level class actions and render them if appropiate _actionsVarName = format [QGVAR(SelfAct_%1), typeOf _target]; @@ -91,8 +106,9 @@ if (GVAR(keyDown)) then { _active = [_target, ACE_player] call (_actionItem select 4); if (_active) then { - _pos = (ACE_player modelToWorld (ACE_player selectionPosition "spine3")) vectorAdd GVAR(selfMenuOffset) vectorAdd [0,0,0.25]; - [ACE_player, _actionItem, 0, [180, 360], _pos] call FUNC(renderMenu); + //_pos = (ACE_player modelToWorld (ACE_player selectionPosition "spine3")) vectorAdd GVAR(selfMenuOffset) vectorAdd [0,0,0.25]; + _pos = _cursorPos1 vectorAdd GVAR(selfMenuOffset); + [_target, _actionItem, true, [180, 360], _pos] call FUNC(renderMenu); }; } forEach _classActions; }; @@ -100,9 +116,13 @@ if (GVAR(keyDown)) then { if(GVAR(keyDown) || GVAR(keyDownSelfAction)) then { - drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selected_ca.paa", [1,0,0,1], _cursorPos2, 1, 1, 0, "", 0.5, 0.025, "TahomaB"]; + // Draw the red selector only when there's no cursor + if !(uiNamespace getVariable [QGVAR(cursorMenuOpened),false]) then { + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selected_ca.paa", [1,0,0,1], _cursorPos2, 1, 1, 0, "", 0.5, 0.025, "TahomaB"]; + }; + + _cursorScreenPos = [worldToScreen _cursorPos2, GVAR(cursorPos)] select (uiNamespace getVariable [QGVAR(cursorMenuOpened),false]); - _cursorScreenPos = worldToScreen _cursorPos2; _closestDistance = 1000000; _closestSelection = -1; { diff --git a/addons/interact_menu/functions/fnc_renderIcon.sqf b/addons/interact_menu/functions/fnc_renderIcon.sqf index 0d1ce1fd43..d3f94a2d86 100644 --- a/addons/interact_menu/functions/fnc_renderIcon.sqf +++ b/addons/interact_menu/functions/fnc_renderIcon.sqf @@ -31,13 +31,16 @@ _sPos = worldToScreen _pos; if(count _sPos > 0) then { if(GVAR(iconCount) > (count GVAR(iconCtrls))-1) then { - GVAR(iconCtrls) pushBack ((findDisplay 46) ctrlCreate ["RscStructuredText", 54021+GVAR(iconCount)]); + _displayNum = [46,91919] select (uiNamespace getVariable [QGVAR(cursorMenuOpened),false]); + //systemChat format ["Displaynum: %1", _displayNum]; + GVAR(iconCtrls) pushBack ((findDisplay _displayNum) ctrlCreate ["RscStructuredText", 54021+GVAR(iconCount)]); }; _ctrl = GVAR(iconCtrls) select GVAR(iconCount); GVAR(iconCount) = GVAR(iconCount) + 1; if(_icon == "") then { _icon = DEFAULT_ICON; }; + //systemChat format ["Ctrl: %1, %2,%3", _text,_sPos select 0, _sPos select 1]; _text = format ["
%4", _icon, _color, _color, _text]; _ctrl ctrlSetStructuredText (parseText _text); _ctrl ctrlSetPosition [(_sPos select 0)-(0.2*SafeZoneW), (_sPos select 1)-(0.0095*SafeZoneW), 0.4*SafeZoneW, 0.035*SafeZoneW]; diff --git a/addons/interact_menu/functions/fnc_renderMenu.sqf b/addons/interact_menu/functions/fnc_renderMenu.sqf index c7af6e8839..f90b084a29 100644 --- a/addons/interact_menu/functions/fnc_renderMenu.sqf +++ b/addons/interact_menu/functions/fnc_renderMenu.sqf @@ -5,20 +5,20 @@ * Argument: * 0: Object * 1: Action data - * 2: ? + * 2: Was the condition already checked? * 3: Angle range available for rendering * 4: 3D position (Optional) * * Return value: - * None + * Was the menu rendered * * Public: No */ #include "script_component.hpp" -private ["_distance", "_uid", "_pos", "_cursorScreenPos", "_path", "_menuDepth", "_opacity", "_currentRenderDepth", "_radialOffset", "_active", "_x", "_offset", "_newPos", "_forEachIndex"]; +private ["_distance", "_uid", "_pos", "_cameraPos", "_path", "_menuDepth", "_opacity", "_currentRenderDepth", "_radialOffset", "_active", "_x", "_offset", "_newPos", "_forEachIndex"]; -EXPLODE_4_PVT(_this,_object,_actionData,_dummy,_angles); +EXPLODE_4_PVT(_this,_object,_actionData,_wasConditionChecked,_angles); EXPLODE_2_PVT(_angles,_centerAngle,_maxAngleSpan); _uid = _actionData select 7; @@ -35,12 +35,20 @@ if((count _this) > 4) then { }; }; -_cursorScreenPos = (positionCameraToWorld [0, 0, 0]); -// Exit if the action is too far away -if(_cursorScreenPos distance _pos >= _distance) exitWith {}; +// For non-self actions, exit if the action is too far away +_cameraPos = positionCameraToWorld [0, 0, 0]; +if (GVAR(keyDown) && {_cameraPos distance _pos >= _distance}) exitWith {false}; // Exit if the action is behind you -if(_cursorScreenPos select 2 < 0) exitWith {}; +_sPos = worldToScreen _pos; +if(count _sPos == 0) exitWith {false}; + +// Exit if the action is off screen +if ((_sPos select 0) < safeZoneXAbs || (_sPos select 0) > safeZoneXAbs + safeZoneWAbs) exitWith {false}; +if ((_sPos select 1) < safeZoneY || (_sPos select 1) > safeZoneY + safeZoneH) exitWith {false}; + +// If the condition was not checked, check it and exit if needed +if (!_wasConditionChecked && {!([_target, ACE_player] call (_actionItem select 4))}) exitWith {false}; _menuDepth = (count GVAR(menuDepthPath)) - 1; @@ -72,7 +80,7 @@ if(_menuDepth > 0 && !_menuInSelectedPath) then { GVAR(currentOptions) pushBack [_this, _pos, _path]; // Exit without rendering children if it isn't -if !(_menuInSelectedPath) exitWith {}; +if !(_menuInSelectedPath) exitWith {true}; // Collect all active children actions private "_activeChildren"; @@ -126,12 +134,12 @@ _angle = _centerAngle - _angleSpan / 2; _player = ACE_player; _offset = [GVAR(vecLineMap), _angle] call FUNC(rotateVectLine); - _mod = 0.15 max (0.15 * (_cursorScreenPos distance _pos)); + _mod = (0.15 max (0.15 * (_cameraPos distance _pos))) / GVAR(selfMenuScale); _newPos = _pos vectorAdd (_offset vectorMultiply _mod); // drawLine3D [_pos, _newPos, [1,0,0,0.5]]; - [_object, _x, _forEachIndex, [_angle, 140], _newPos] call FUNC(renderMenu); + [_object, _x, true, [_angle, 140], _newPos] call FUNC(renderMenu); if (_angleSpan == 360) then { _angle = _angle + _angleSpan / (count _activeChildren); @@ -139,3 +147,5 @@ _angle = _centerAngle - _angleSpan / 2; _angle = _angle + _angleSpan / (((count _activeChildren)-1) max 1); }; } forEach _activeChildren; + +true diff --git a/addons/interaction/CfgVehicles.hpp b/addons/interaction/CfgVehicles.hpp index 801e564384..10fde54769 100644 --- a/addons/interaction/CfgVehicles.hpp +++ b/addons/interaction/CfgVehicles.hpp @@ -32,7 +32,7 @@ class CfgVehicles { class ACE_Actions { class ACE_MainActions { displayName = "$STR_ACE_Interaction_MainAction"; - distance = 4; + distance = 5; condition = QUOTE(true); statement = ""; icon = "\a3\ui_f\data\IGUI\Cfg\Actions\eject_ca.paa"; @@ -40,7 +40,7 @@ class CfgVehicles { class ACE_TeamManagement { displayName = "$STR_ACE_Interaction_TeamManagement"; - distance = 4; + distance = 5; condition = QUOTE(alive _target && {!isPlayer _target} && {_target in units group _player} && {GVAR(EnableTeamManagement)}); statement = ""; showDisabled = 0; @@ -51,7 +51,7 @@ class CfgVehicles { class ACE_JoinTeamRed { displayName = "$STR_ACE_Interaction_JoinTeamRed"; - distance = 4; + distance = 5; condition = QUOTE(alive _target && {!isPlayer _target} && {_target in units group _player}); statement = QUOTE([ARR_2(_target,'RED')] call DFUNC(joinTeam)); showDisabled = 1; @@ -62,7 +62,7 @@ class CfgVehicles { }; class ACE_JoinTeamGreen { displayName = "$STR_ACE_Interaction_JoinTeamGreen"; - distance = 4; + distance = 5; condition = QUOTE(alive _target && {!isPlayer _target} && {_target in units group _player}); statement = QUOTE([ARR_2(_target,'GREEN')] call DFUNC(joinTeam)); showDisabled = 1; @@ -73,7 +73,7 @@ class CfgVehicles { }; class ACE_JoinTeamBlue { displayName = "$STR_ACE_Interaction_JoinTeamBlue"; - distance = 4; + distance = 5; condition = QUOTE(alive _target && {!isPlayer _target} && {_target in units group _player}); statement = QUOTE([ARR_2(_target,'BLUE')] call DFUNC(joinTeam)); showDisabled = 1; @@ -84,7 +84,7 @@ class CfgVehicles { }; class ACE_JoinTeamYellow { displayName = "$STR_ACE_Interaction_JoinTeamYellow"; - distance = 4; + distance = 5; condition = QUOTE(alive _target && {!isPlayer _target} && {_target in units group _player}); statement = QUOTE([ARR_2(_target,'YELLOW')] call DFUNC(joinTeam)); showDisabled = 1; @@ -96,7 +96,7 @@ class CfgVehicles { class ACE_LeaveTeam { displayName = "$STR_ACE_Interaction_LeaveTeam"; - distance = 4; + distance = 5; condition = QUOTE(alive _target && {!isPlayer _target} && {_target in units group _player} && {assignedTeam _player != 'MAIN'}); statement = QUOTE([ARR_2(_target,'MAIN')] call DFUNC(joinTeam)); showDisabled = 1; @@ -109,7 +109,7 @@ class CfgVehicles { class ACE_JoinGroup { displayName = "$STR_ACE_Interaction_JoinGroup"; - distance = 4; + distance = 5; condition = QUOTE(side group _player == side group _target && {group _player != group _target}); statement = QUOTE([_player] joinSilent group _target;); showDisabled = 0; @@ -121,7 +121,7 @@ class CfgVehicles { class ACE_GetDown { displayName = "$STR_ACE_Interaction_GetDown"; - distance = 4; + distance = 5; condition = QUOTE([_target] call DFUNC(canInteractWith)); statement = QUOTE([_target] call DFUNC(getDown)); showDisabled = 0; @@ -129,7 +129,7 @@ class CfgVehicles { }; class ACE_SendAway { displayName = "$STR_ACE_Interaction_SendAway"; - distance = 4; + distance = 5; condition = QUOTE([_target] call DFUNC(canInteractWith)); statement = QUOTE([_target] call DFUNC(sendAway)); showDisabled = 0; @@ -137,7 +137,7 @@ class CfgVehicles { }; class ACE_Pardon { displayName = "$STR_ACE_Interaction_Pardon"; - distance = 4; + distance = 5; condition = QUOTE(rating _target < -2000 && {alive _target} && {side group _player == side group _target}); statement = QUOTE([ARR_3(_target,'{_this addRating -rating _this}',_target)] call DEFUNC(common,execRemoteFnc)); showDisabled = 0;