diff --git a/addons/maptools/ACE_Settings.hpp b/addons/maptools/ACE_Settings.hpp index 0da43b64cad..cb2d98e1ced 100644 --- a/addons/maptools/ACE_Settings.hpp +++ b/addons/maptools/ACE_Settings.hpp @@ -7,4 +7,11 @@ class ACE_Settings { description = CSTRING(rotateModifierKey_description); values[] = {"$STR_A3_OPTIONS_DISABLED", "ALT", "CTRL", "SHIFT"}; }; + class GVAR(drawStaightLines) { + value = 1; + typeName = "BOOL"; + isClientSettable = 1; + displayName = CSTRING(drawStaightLines_displayName); + description = CSTRING(drawStaightLines_description); + }; }; diff --git a/addons/maptools/XEH_PREP.hpp b/addons/maptools/XEH_PREP.hpp index 1670c595935..eac6947431a 100644 --- a/addons/maptools/XEH_PREP.hpp +++ b/addons/maptools/XEH_PREP.hpp @@ -1,6 +1,7 @@ PREP(calculateMapScale); PREP(canUseMapGPS); PREP(canUseMapTools); +PREP(drawLinesOnRoamer); PREP(handleMouseButton); PREP(handleMouseMove); PREP(isInsideMapTool); diff --git a/addons/maptools/XEH_postInitClient.sqf b/addons/maptools/XEH_postInitClient.sqf index 8569f0eb9fa..ddde7063cc9 100644 --- a/addons/maptools/XEH_postInitClient.sqf +++ b/addons/maptools/XEH_postInitClient.sqf @@ -30,5 +30,13 @@ GVAR(mapTool_isRotating) = false; } else { // Hide GPS [false] call FUNC(openMapGps); + + // Handle closing map in middle of line drawing (it's never created) + GVAR(freedrawing) = false; }; }] call CBA_fnc_addPlayerEventHandler; + + +GVAR(freeDrawingData) = []; +GVAR(freedrawing) = false; + diff --git a/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf b/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf new file mode 100644 index 00000000000..6a900c335b7 --- /dev/null +++ b/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf @@ -0,0 +1,144 @@ +/* + * Author: PabstMirror + * Prevents the cursor from entering the roamer when drawing lines and records the positions + * + * Arguments: + * 0: The Map + * 1: Roamer Width + * + * Return Value: + * Nothing + * + * Example: + * [map, 300] call ace_maptools_fnc_drawLinesOnRoamer + * + * Public: No + */ +#include "script_component.hpp" + +if (!GVAR(drawStaightLines)) exitWith {}; + +params ["_theMap", "_roamerWidth"]; +GVAR(mapTool_pos) params ["_roamerPosX", "_roamerPosY"]; + +private _posCenter = [_roamerPosX, _roamerPosY, 0]; + +private _posTopRight = [ +_roamerPosX + (cos GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (sin GVAR(mapTool_angle)) * DIST_TOP_TO_CENTER_PERC * _roamerWidth, +_roamerPosY + (-sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (cos GVAR(mapTool_angle)) * DIST_TOP_TO_CENTER_PERC * _roamerWidth, +0]; + +private _posTopLeft = [ +_roamerPosX + (-cos GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (sin GVAR(mapTool_angle)) * DIST_TOP_TO_CENTER_PERC * _roamerWidth, +_roamerPosY + (sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (cos GVAR(mapTool_angle)) * DIST_TOP_TO_CENTER_PERC * _roamerWidth, +0]; + +private _posBottomLeft = [ +_roamerPosX + (-cos GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (sin GVAR(mapTool_angle)) * DIST_BOTTOM_TO_CENTER_PERC * _roamerWidth, +_roamerPosY + (sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (cos GVAR(mapTool_angle)) * DIST_BOTTOM_TO_CENTER_PERC * _roamerWidth, +0]; + +private _posBottomRight = [ +_roamerPosX + (cos GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (sin GVAR(mapTool_angle)) * DIST_BOTTOM_TO_CENTER_PERC * _roamerWidth, +_roamerPosY + (-sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWidth + (cos GVAR(mapTool_angle)) * DIST_BOTTOM_TO_CENTER_PERC * _roamerWidth, +0]; + +private _fnc_Distance = { // Get distance point _p is from a line made from _a to _b (uses 3d array commands, but z should be 0) + // Ref: https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Vector_formulation + params ["_a", "_b", "_p"]; + private _n = _b vectorDiff _a; + private _pa = _a vectorDiff _p; + private _c = _n vectorMultiply ((_pa vectorDotProduct _n) / (_n vectorDotProduct _n)); + private _d = _pa vectorDiff _c; + sqrt (_d vectorDotProduct _d); +}; + +private _currentMousePos = _theMap ctrlMapScreenToWorld getMousePosition; +_currentMousePos set [2, 0]; + +// Break the roamer rectangle into 4 triangle, one for each side +switch (true) do { + case (_currentMousePos inPolygon [_posCenter, _posTopLeft, _posBottomLeft]): { // Left + private _distanceToRoamerLine = ([_posTopLeft, _posBottomLeft, _currentMousePos] call _fnc_Distance); + _currentMousePos = _currentMousePos vectorAdd ([_distanceToRoamerLine, (GVAR(mapTool_angle) - 90) ,0] call CBA_fnc_polar2vect); + if (GVAR(freeDrawingData) isEqualTo []) then { // We start drawing on the line + GVAR(freeDrawingData) = ["left", _currentMousePos, _currentMousePos]; + } else { + if ((GVAR(freeDrawingData) select 0) == "left") then { // We are already drawing on this line, find best spot + if ((_currentMousePos distance2d _posTopLeft) < ((GVAR(freeDrawingData) select 1) distance2d _posTopLeft)) then { + GVAR(freeDrawingData) set [1, _currentMousePos]; + }; + if ((_currentMousePos distance2d _posBottomLeft) < ((GVAR(freeDrawingData) select 2) distance2d _posBottomLeft)) then { + GVAR(freeDrawingData) set [2, _currentMousePos]; + }; + }; + }; + private _screenPosOfCorrectedPos = _theMap ctrlMapWorldToScreen _currentMousePos; + setMousePosition _screenPosOfCorrectedPos; + }; + case (_currentMousePos inPolygon [_posCenter, _posTopLeft, _posTopRight]): { // Top + private _distanceToRoamerLine = ([_posTopLeft, _posTopRight, _currentMousePos] call _fnc_Distance); + _currentMousePos = _currentMousePos vectorAdd ([_distanceToRoamerLine, (GVAR(mapTool_angle) + 0) ,0] call CBA_fnc_polar2vect); + if (GVAR(freeDrawingData) isEqualTo []) then { // We start drawing on the line + GVAR(freeDrawingData) = ["top", _currentMousePos, _currentMousePos]; + } else { + if ((GVAR(freeDrawingData) select 0) == "top") then { // We are already drawing on this line, find best spot + if ((_currentMousePos distance2d _posTopLeft) < ((GVAR(freeDrawingData) select 1) distance2d _posTopLeft)) then { + GVAR(freeDrawingData) set [1, _currentMousePos]; + }; + if ((_currentMousePos distance2d _posTopRight) < ((GVAR(freeDrawingData) select 2) distance2d _posTopRight)) then { + GVAR(freeDrawingData) set [2, _currentMousePos]; + }; + }; + }; + private _screenPosOfCorrectedPos = _theMap ctrlMapWorldToScreen _currentMousePos; + setMousePosition _screenPosOfCorrectedPos; + }; + case (_currentMousePos inPolygon [_posCenter, _posTopRight, _posBottomRight]): { // Right + private _distanceToRoamerLine = ([_posTopRight, _posBottomRight, _currentMousePos] call _fnc_Distance); + _currentMousePos = _currentMousePos vectorAdd ([_distanceToRoamerLine, (GVAR(mapTool_angle) + 90) ,0] call CBA_fnc_polar2vect); + if (GVAR(freeDrawingData) isEqualTo []) then { // We start drawing on the line + GVAR(freeDrawingData) = ["right", _currentMousePos, _currentMousePos]; + } else { + if ((GVAR(freeDrawingData) select 0) == "right") then { // We are already drawing on this line, find best spot + if ((_currentMousePos distance2d _posTopRight) < ((GVAR(freeDrawingData) select 1) distance2d _posTopRight)) then { + GVAR(freeDrawingData) set [1, _currentMousePos]; + }; + if ((_currentMousePos distance2d _posBottomRight) < ((GVAR(freeDrawingData) select 2) distance2d _posBottomRight)) then { + GVAR(freeDrawingData) set [2, _currentMousePos]; + }; + }; + }; + private _screenPosOfCorrectedPos = _theMap ctrlMapWorldToScreen _currentMousePos; + setMousePosition _screenPosOfCorrectedPos; + }; + case (_currentMousePos inPolygon [_posCenter, _posBottomLeft, _posBottomRight]): { // Bottom + private _distanceToRoamerLine = ([_posBottomLeft, _posBottomRight, _currentMousePos] call _fnc_Distance); + _currentMousePos = _currentMousePos vectorAdd ([_distanceToRoamerLine, (GVAR(mapTool_angle) + 180) ,0] call CBA_fnc_polar2vect); + if (GVAR(freeDrawingData) isEqualTo []) then { // We start drawing on the line + GVAR(freeDrawingData) = ["bottom", _currentMousePos, _currentMousePos]; + } else { + if ((GVAR(freeDrawingData) select 0) == "bottom") then { // We are already drawing on this line, find best spot + if ((_currentMousePos distance2d _posBottomLeft) < ((GVAR(freeDrawingData) select 1) distance2d _posBottomLeft)) then { + GVAR(freeDrawingData) set [1, _currentMousePos]; + }; + if ((_currentMousePos distance2d _posBottomRight) < ((GVAR(freeDrawingData) select 2) distance2d _posBottomRight)) then { + GVAR(freeDrawingData) set [2, _currentMousePos]; + }; + }; + }; + private _screenPosOfCorrectedPos = _theMap ctrlMapWorldToScreen _currentMousePos; + setMousePosition _screenPosOfCorrectedPos; + }; +}; + +#ifdef DEBUG_MODE_FULL +_theMap drawIcon ['iconStaticMG',[1,0,0,1],_posTopRight,24,24,getDir player,'1,1',1,0.03,'TahomaB','right']; +_theMap drawIcon ['iconStaticMG',[1,0,0,1],_posTopLeft,24,24,getDir player,'-1,1',1,0.03,'TahomaB','right']; +_theMap drawIcon ['iconStaticMG',[1,0,0,1],_posBottomLeft,24,24,getDir player,'-1,-1',1,0.03,'TahomaB','right']; +_theMap drawIcon ['iconStaticMG',[1,0,0,1],_posBottomRight,24,24,getDir player,'1,-1',1,0.03,'TahomaB','right']; +if !(GVAR(freeDrawingData) isEqualTo []) then { + _theMap drawIcon ['iconStaticMG',[0,0,1,1],GVAR(freeDrawingData) select 1,24,24,getDir player,'1,-1',1,0.03,'TahomaB','right']; + _theMap drawIcon ['iconStaticMG',[0,0,1,1],GVAR(freeDrawingData) select 2,24,24,getDir player,'1,-1',1,0.03,'TahomaB','right']; +}; +#endif diff --git a/addons/maptools/functions/fnc_handleMouseButton.sqf b/addons/maptools/functions/fnc_handleMouseButton.sqf index bf30a32ce18..7750ef09655 100644 --- a/addons/maptools/functions/fnc_handleMouseButton.sqf +++ b/addons/maptools/functions/fnc_handleMouseButton.sqf @@ -15,6 +15,51 @@ params ["_dir", "_params"]; _params params ["_control", "_button", "_screenPosX", "_screenPosY", "_shiftKey", "_ctrlKey", "_altKey"]; TRACE_2("params",_dir,_params); +// Using line drawing +if ((_button == 0) && {GVAR(freedrawing) || _ctrlKey}) exitWith { + if (GVAR(freedrawing) && {_dir == 0}) then { + GVAR(freedrawing) = false; + GVAR(drawPosEnd) = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY]; + TRACE_1("Ending Line",GVAR(freedrawing),GVAR(drawPosEnd)); + [{ + if (allMapMarkers isEqualTo []) exitWith {}; + private _markerName = allMapMarkers select (count allMapMarkers - 1); + private _markerPos = getMarkerPos _markerName; + private _distanceCheck = _markerPos distance2d GVAR(drawPosStart); + + TRACE_3("Line Drawn",_markerName,_markerPos,_distanceCheck); + + if (_distanceCheck > 1) exitWith {WARNING("Wrong Marker!");}; + if ((count GVAR(freeDrawingData)) != 3) exitWith {TRACE_1("never touched roamer",GVAR(freeDrawingData));}; + + GVAR(freeDrawingData) params ["", "_startStraightPos", "_endStraightPos"]; + _startStraightPos set [2, 0]; + _endStraightPos set [2, 0]; + + // Convert marker to rectangle and change it's pos/size/dir + _markerName setMarkerShape "RECTANGLE"; + + private _difPos = _endStraightPos vectorDiff _startStraightPos; + private _mag = vectorMagnitude _difPos; + _markerName setMarkerPos (_startStraightPos vectorAdd (_difPos vectorMultiply 0.5)); + _markerName setMarkerSize [10, _mag / 2]; + _markerName setMarkerDir (_difPos call CBA_fnc_vectDir); + + }, []] call CBA_fnc_execNextFrame; + } else { + if (_ctrlKey && {_dir == 1}) then { + GVAR(freeDrawingData) = []; + GVAR(freedrawing) = true; + GVAR(drawPosStart) = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY]; + TRACE_2("Starting Line",GVAR(freedrawing),GVAR(drawPosStart)); + } else { + GVAR(freedrawing) = false; + TRACE_1("weird - reseting",GVAR(freedrawing)); + }; + }; + false +}; + private _handled = false; // If it's not a left button event, exit diff --git a/addons/maptools/functions/fnc_isInsideMapTool.sqf b/addons/maptools/functions/fnc_isInsideMapTool.sqf index 1bcb35f86a6..216a2a675ab 100644 --- a/addons/maptools/functions/fnc_isInsideMapTool.sqf +++ b/addons/maptools/functions/fnc_isInsideMapTool.sqf @@ -11,11 +11,6 @@ */ #include "script_component.hpp" -#define TEXTURE_WIDTH_IN_M 6205 -#define DIST_BOTTOM_TO_CENTER_PERC -0.33 -#define DIST_TOP_TO_CENTER_PERC 0.65 -#define DIST_LEFT_TO_CENTER_PERC 0.30 - if (GVAR(mapTool_Shown) == 0) exitWith {false}; private _textureWidth = [TEXTURE_WIDTH_IN_M, TEXTURE_WIDTH_IN_M / 2] select (GVAR(mapTool_Shown) - 1); diff --git a/addons/maptools/functions/fnc_updateMapToolMarkers.sqf b/addons/maptools/functions/fnc_updateMapToolMarkers.sqf index 47688cdb91b..864ef33844f 100644 --- a/addons/maptools/functions/fnc_updateMapToolMarkers.sqf +++ b/addons/maptools/functions/fnc_updateMapToolMarkers.sqf @@ -12,10 +12,6 @@ */ #include "script_component.hpp" -#define TEXTURE_WIDTH_IN_M 6205 -#define CENTER_OFFSET_Y_PERC 0.1606 -#define CONSTANT_SCALE 0.2 - params ["_theMap"]; if ((GVAR(mapTool_Shown) == 0) || {!("ACE_MapTools" in items ACE_player)}) exitWith {}; @@ -30,6 +26,8 @@ if (GVAR(mapTool_Shown) == 1) then { _textureWidth = TEXTURE_WIDTH_IN_M / 2; }; +if (GVAR(freedrawing)) then {[_theMap, _textureWidth] call FUNC(drawLinesOnRoamer);}; + // Update scale of both parts getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"]; private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale)); diff --git a/addons/maptools/script_component.hpp b/addons/maptools/script_component.hpp index 8f2e7e39b98..4710caa7a3b 100644 --- a/addons/maptools/script_component.hpp +++ b/addons/maptools/script_component.hpp @@ -15,3 +15,10 @@ #endif #include "\z\ace\addons\main\script_macros.hpp" + +#define TEXTURE_WIDTH_IN_M 6205 +#define CENTER_OFFSET_Y_PERC 0.1606 +#define CONSTANT_SCALE 0.2 +#define DIST_BOTTOM_TO_CENTER_PERC -0.33 +#define DIST_TOP_TO_CENTER_PERC 0.65 +#define DIST_LEFT_TO_CENTER_PERC 0.30 diff --git a/addons/maptools/stringtable.xml b/addons/maptools/stringtable.xml index 4fe6db6e1af..59ab5db0d07 100644 --- a/addons/maptools/stringtable.xml +++ b/addons/maptools/stringtable.xml @@ -158,5 +158,11 @@ マップ ツールを回転させるキーを編集できます。 Modyfikator pozwalający na obracanie narzędzi nawigacyjnych + + Draw straight lines with maptools + + + Draw on the edge of maptools to draw straight lines. Note: Must hover at midpoint to delete. +