From 0b974d2f2cde1d5f52d2a16a213c82b09ce3c648 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Fri, 1 Jul 2016 02:07:34 -0500 Subject: [PATCH 1/3] Draw Straight Lines --- addons/maptools/ACE_Settings.hpp | 7 + addons/maptools/XEH_PREP.hpp | 1 + addons/maptools/XEH_postInitClient.sqf | 5 + .../functions/fnc_drawLinesOnRoamer.sqf | 143 ++++++++++++++++++ .../functions/fnc_handleMouseButton.sqf | 45 ++++++ .../functions/fnc_isInsideMapTool.sqf | 5 - .../functions/fnc_updateMapToolMarkers.sqf | 6 +- addons/maptools/script_component.hpp | 7 + addons/maptools/stringtable.xml | 8 +- 9 files changed, 217 insertions(+), 10 deletions(-) create mode 100644 addons/maptools/functions/fnc_drawLinesOnRoamer.sqf 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..914c7d74110 100644 --- a/addons/maptools/XEH_postInitClient.sqf +++ b/addons/maptools/XEH_postInitClient.sqf @@ -32,3 +32,8 @@ GVAR(mapTool_isRotating) = false; [false] call FUNC(openMapGps); }; }] 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..64afc788b09 --- /dev/null +++ b/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf @@ -0,0 +1,143 @@ +/* + * 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) + params ["_a", "_b", "_p"]; + _n = _b vectorDiff _a; + _pa = _a vectorDiff _p; + _c = _n vectorMultiply ((_pa vectorDotProduct _n) / (_n vectorDotProduct _n)); + _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) = ["top", _currentMousePos, _currentMousePos]; + } else { + if ((GVAR(freeDrawingData) select 0) == "top") 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) = ["top", _currentMousePos, _currentMousePos]; + } else { + if ((GVAR(freeDrawingData) select 0) == "top") 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 d5f5b0f2d71..201677d035e 100644 --- a/addons/maptools/script_component.hpp +++ b/addons/maptools/script_component.hpp @@ -16,3 +16,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 e15135dcfd3..1315252565e 100644 --- a/addons/maptools/stringtable.xml +++ b/addons/maptools/stringtable.xml @@ -143,5 +143,11 @@ Touche modificatrice permettant la rotation des outils de naviguation Клавиша-модификатор, позволяющая поворачивать инструменты карты + + Draw straight lines with maptools + + + Draw on the edge of maptools to draw straight lines. Note: Must hover at midpoint to delete. + - \ No newline at end of file + From 68cc3a81e6fde12b7f4317f2fa99f34f089d540a Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Fri, 30 Sep 2016 15:41:44 -0500 Subject: [PATCH 2/3] Fix roamer sides, handle closing map mid-draw --- addons/maptools/XEH_postInitClient.sqf | 3 +++ addons/maptools/functions/fnc_drawLinesOnRoamer.sqf | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/addons/maptools/XEH_postInitClient.sqf b/addons/maptools/XEH_postInitClient.sqf index 914c7d74110..ddde7063cc9 100644 --- a/addons/maptools/XEH_postInitClient.sqf +++ b/addons/maptools/XEH_postInitClient.sqf @@ -30,6 +30,9 @@ 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; diff --git a/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf b/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf index 64afc788b09..12ad58c4fc7 100644 --- a/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf +++ b/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf @@ -97,9 +97,9 @@ switch (true) do { 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) = ["top", _currentMousePos, _currentMousePos]; + GVAR(freeDrawingData) = ["right", _currentMousePos, _currentMousePos]; } else { - if ((GVAR(freeDrawingData) select 0) == "top") then { // We are already drawing on this line, find best spot + 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]; }; @@ -115,9 +115,9 @@ switch (true) do { 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) = ["top", _currentMousePos, _currentMousePos]; + GVAR(freeDrawingData) = ["bottom", _currentMousePos, _currentMousePos]; } else { - if ((GVAR(freeDrawingData) select 0) == "top") then { // We are already drawing on this line, find best spot + 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]; }; From 29de16de21913b0024f70390579b6307f21eeeb2 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Sat, 1 Oct 2016 20:11:50 -0500 Subject: [PATCH 3/3] Add missing privates / formula notes --- addons/maptools/functions/fnc_drawLinesOnRoamer.sqf | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf b/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf index 12ad58c4fc7..6a900c335b7 100644 --- a/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf +++ b/addons/maptools/functions/fnc_drawLinesOnRoamer.sqf @@ -44,11 +44,12 @@ _roamerPosY + (-sin GVAR(mapTool_angle)) * DIST_LEFT_TO_CENTER_PERC * _roamerWid 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"]; - _n = _b vectorDiff _a; - _pa = _a vectorDiff _p; - _c = _n vectorMultiply ((_pa vectorDotProduct _n) / (_n vectorDotProduct _n)); - _d = _pa vectorDiff _c; + 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); };