Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_MapCursorModule.c
Go to the documentation of this file.
1 //------------------------------------------------------------------------------------------------
4 {
5  static bool isGamepad; // is using gamepad
6  bool isFixedMode = true; // determines whether cursor is fixed to the screen center
7 
8  static int x, y; // by default, all screen position are DPI Unscaled, when scaled, these will return a range from 0 to window resolution in pixels
9  static int startPos[2]; // state start pos pan
10  static int startPosMultiSel[2]; // state start pos multi select
11  int lastX, lastY; // last pos of x & y
12  EMapCursorEdgePos edgeFlags; // cursor screen edge flags
13 
14  static WorkspaceWidget m_WorkspaceWidget;
15 
16  //------------------------------------------------------------------------------------------------
18  static int Scale(int pos)
19  {
20  if (!m_WorkspaceWidget)
21  m_WorkspaceWidget = GetGame().GetWorkspace();
22 
23  return m_WorkspaceWidget.DPIScale(pos);
24  }
25 
26  //------------------------------------------------------------------------------------------------
27  void ~SCR_MapCursorInfo()
28  {
29  x = 0;
30  y = 0;
31  startPos = {0, 0};
32  startPosMultiSel = {0, 0};
33  }
34 };
35 
36 //------------------------------------------------------------------------------------------------
40 {
41  [Attribute(defvalue: "1.5", uiwidget: UIWidgets.EditBox, desc: "Panning: multiplier of keyboard panning speed", params: "0.1 10")]
42  float m_fPanKBMMultiplier;
43 
44  [Attribute(defvalue: "1.5", uiwidget: UIWidgets.EditBox, desc: "Panning: multiplier of thubmstick panning speed", params: "0.1 10")]
45  float m_fPanStickMultiplier;
46 
47  [Attribute(defvalue: "1", uiwidget: UIWidgets.CheckBox, desc: "Enables panning by moving cursor to the screen edges")]
48  bool m_bEnableCursorEdgePan;
49 
50  [Attribute(defvalue: "1", uiwidget: UIWidgets.CheckBox, desc: "Center KBM cursor on map open")]
51  bool m_bIsCursorCenteredOnOpen;
52 
53  [Attribute(defvalue: "0.1", uiwidget: UIWidgets.EditBox, desc: "Time it takes to perform zooming of a single step", params: "0.01 10")]
54  float m_fZoomAnimTime;
55 
56  [Attribute(defvalue: "2", uiwidget: UIWidgets.EditBox, desc: "Each zoom step is increased/decreased by the currentZoom/thisVariable, lower number means faster steps", params: "0.1 10")]
57  float m_fZoomStrength;
58 
59  [Attribute(defvalue: "100", uiwidget: UIWidgets.EditBox, desc: "This is multiplier of average frame time resulting in a rotation degree value", params: "100 1000")]
60  int m_iRotateSpeedMouse;
61 
62  [Attribute(defvalue: "1", uiwidget: UIWidgets.CheckBox, desc: "Enables custom map crosshair visuals")]
63  bool m_bEnableMapCrosshairVisuals;
64 
65  [Attribute(defvalue: "0", uiwidget: UIWidgets.CheckBox, desc: "Enables crosshair grid coordinate display")]
66  bool m_bEnableCrosshairCoords;
67 
68  [Attribute("0 0 0 1", UIWidgets.ColorPicker, desc: "Cursor grid/guide lines color")]
69  ref Color m_GuidelineColor;
70 
71  [Attribute("", UIWidgets.Object, "Cursor state configuration")]
72  protected ref array<ref SCR_CursorVisualState> m_aCursorStatesConfig;
73 
74  protected ref map<EMapCursorState, SCR_CursorVisualState> m_aCursorStatesMap = new map<EMapCursorState, SCR_CursorVisualState>; // used to quickly fetch a desired cursor state from config
75 
76  //static
77  protected static bool m_bRecentlyTraced; // recently performed widget trace
78  protected static ref array<Widget> s_aTracedWidgets = {};
79 
80  // const
81  const int CURSOR_CAPTURE_OFFSET = 10; // hardcoded(code) screen edges in pixels for cursor capture
82  const int GUILDING_LINE_WIDTH = 16;
83  const float PAN_DEFAULT_COUNTDOWN = 0.1;
84  const float SINGLE_SELECTION_RANGE = 50.0; // range in world pos
85  const float CIRCLE_SELECTION_RANGE = 500.0; // range in world pos
86  const float FREE_CURSOR_RESET = 3.0; // seconds, time before free cursor resets to locked mode on controller
87 
88  const EMapCursorState CUSTOM_CURSOR_LOCKED = EMapCursorState.CS_DISABLE;
89  const EMapCursorState STATE_PAN_RESTRICTED = EMapCursorState.CS_DRAG | EMapCursorState.CS_MODIFIER | EMapCursorState.CS_DRAW | EMapCursorState.CS_CONTEXTUAL_MENU | EMapCursorState.CS_DIALOG;
90  const EMapCursorState STATE_ZOOM_RESTRICTED = EMapCursorState.CS_DRAG | EMapCursorState.CS_MODIFIER | EMapCursorState.CS_DRAW | EMapCursorState.CS_CONTEXTUAL_MENU;
91  const EMapCursorState STATE_HOVER_RESTRICTED = EMapCursorState.CS_PAN | EMapCursorState.CS_ZOOM | EMapCursorState.CS_MULTI_SELECTION
92  | EMapCursorState.CS_DRAG | EMapCursorState.CS_DRAW | EMapCursorState.CS_CONTEXTUAL_MENU;
93  const EMapCursorState STATE_SELECT_RESTRICTED = EMapCursorState.CS_MULTI_SELECTION | EMapCursorState.CS_CONTEXTUAL_MENU | EMapCursorState.CS_DRAG | EMapCursorState.CS_DRAW;
94  const EMapCursorState STATE_MULTISELECT_RESTRICTED = EMapCursorState.CS_DRAG | EMapCursorState.CS_DRAW | EMapCursorState.CS_CONTEXTUAL_MENU | EMapCursorState.CS_MODIFIER;
95  const EMapCursorState STATE_DRAG_RESTRICTED = EMapCursorState.CS_CONTEXTUAL_MENU | EMapCursorState.CS_MULTI_SELECTION | EMapCursorState.CS_ROTATE | EMapCursorState.CS_DRAW;
96  const EMapCursorState STATE_ROTATE_RESTRICTED = EMapCursorState.CS_PAN | EMapCursorState.CS_ZOOM | EMapCursorState.CS_CONTEXTUAL_MENU;
97  const EMapCursorState STATE_DRAW_RESTRICTED = EMapCursorState.CS_PAN | EMapCursorState.CS_ZOOM | EMapCursorState.CS_CONTEXTUAL_MENU;
98  const EMapCursorState STATE_SUBMENU_RESTRICTED = EMapCursorState.CS_CONTEXTUAL_MENU | EMapCursorState.CS_DIALOG;
99  const EMapCursorState STATE_CTXMENU_RESTRICTED = EMapCursorState.CS_DRAG | EMapCursorState.CS_DRAW | EMapCursorState.CS_ROTATE;
100  const EMapCursorState STATE_RESET_RESTRICTED = EMapCursorState.CS_DRAG | EMapCursorState.CS_DRAW | EMapCursorState.CS_ROTATE;
101 
102  // timers
103  protected float m_fPanCountdown; // used to stop panning cursor state and refresh start position for next drag panning
104  protected float m_fModifActionDelay; // delay between modifier action activation
105  protected float m_fZoomHoldTime; // zoom hold time for adjusting speed of zoom
106  protected float m_fHoverTime; // hover activation
107  protected float m_fFreeCursorTime; // free cursor deactivation
108  protected float m_fSelectHoldTime; // determines activation of multiselect, which is not using input filters so it doesnt create initial click pos delay
109 
110  // enums
111  EMapCursorSelectType m_eMultiSelType; // multiselect type
112  protected EMapCursorState m_CursorState = EMapCursorState.CS_DEFAULT; // keeps current cursor state
113 
114  protected bool m_bIsInit; // is module initiated
115  protected bool m_bIsDisabled; // temporary module disable
116  protected bool m_bIsDraggingAvailable;
117  protected bool m_bIsSelectionAvailable;
118  protected bool m_bIsModifierActive;
119  protected int m_iRotationDirVal;
120  protected float m_fZoomMultiplierWheel = 1;
121  protected InputManager m_InputManager;
122  protected ref SCR_MapCursorInfo m_CursorInfo;
123  protected ref SCR_CursorCustom m_CustomCursor;
124  protected CanvasWidget m_MapWidget;
125  protected SCR_MapSelectionModule m_SelectionModule;
126 
127  // positioning & sizing
128  protected Widget m_wCrossGrid; // cross grid root
129  protected ImageWidget m_wCrossLTop; // top left fill image, width and heigth determined by the cursor pos
130  protected ImageWidget m_wCrossRTop; // top right fill image, width by (screen reso - cursor pos), height determined by cursos pos
131  protected ImageWidget m_wCrossLBot; // bot left fill image, width set by top left fill, height by (screen reso - cursor pos)
132  protected ImageWidget m_wGLLeft; // guiding line sizing
133  protected ImageWidget m_wGLTop; // guiding line sizing
134  protected Widget m_wCrossMCenter; // used for centering
135 
136  // Rest of guide lines for coloring
137  protected ImageWidget m_wGLRight;
138  protected ImageWidget m_wGLBot;
139  protected ImageWidget m_wGLFadeTop;
140  protected ImageWidget m_wGLFadeLeft;
141  protected ImageWidget m_wGLFadeRight;
142  protected ImageWidget m_wGLFadeBot;
143  protected TextWidget m_wCoordText;
144 
145  //------------------------------------------------------------------------------------------------
146  // GETTERS / SETTERS
147  //------------------------------------------------------------------------------------------------
149  SCR_MapCursorInfo GetCursorInfo() { return m_CursorInfo; }
150 
151  //------------------------------------------------------------------------------------------------
153  EMapCursorState GetCursorState() { return m_CursorState; }
154 
155  //------------------------------------------------------------------------------------------------
157  static array<Widget> GetMapWidgetsUnderCursor()
158  {
159  if (!SCR_MapEntity.GetMapInstance().IsOpen())
160  {
161  s_aTracedWidgets.Clear();
162  return s_aTracedWidgets;
163  }
164 
165  if (!m_bRecentlyTraced)
166  TraceMapWidgets();
167 
168  return s_aTracedWidgets;
169  }
170 
171  //------------------------------------------------------------------------------------------------
174  protected void SetCursorState(EMapCursorState state)
175  {
176  if (!m_bIsInit) // some map components may call this when the module already disabled map cursor
177  return;
178 
179  m_CursorState |= state;
180  SetCursorType(m_CursorState);
181  }
182 
183  //------------------------------------------------------------------------------------------------
186  protected void UnsetCursorState(EMapCursorState state)
187  {
188  m_CursorState &= ~state;
189  SetCursorType(m_CursorState);
190  }
191 
192  //------------------------------------------------------------------------------------------------
194  protected void SetCursorType(EMapCursorState type)
195  {
196  if (!m_bEnableMapCrosshairVisuals)
197  return;
198 
199  SCR_CursorVisualState cursorState = GetCursorStateCfg();
200 
201  if (type == EMapCursorState.CS_DISABLE || m_bIsDisabled)
202  m_CustomCursor.SetCursorVisual(null);
203  else
204  m_CustomCursor.SetCursorVisual(cursorState);
205 
206  SetCrosshairGridVisible(!cursorState.m_DisableCursorLines);
207  }
208 
209  //------------------------------------------------------------------------------------------------
211  protected void SetCrosshairGridVisible(bool state)
212  {
213  if (!m_wCrossGrid || !m_bEnableMapCrosshairVisuals)
214  return;
215 
216  m_wCrossGrid.SetVisible(state);
217  }
218 
219  //------------------------------------------------------------------------------------------------
221  protected void OnInputDeviceIsGamepad(bool isGamepad)
222  {
223  m_CursorInfo.isGamepad = isGamepad;
224  if (m_CursorInfo.isGamepad)
225  ForceCenterCursor();
226  else if (m_fFreeCursorTime != 0) // if scheme switched during fade
227  m_CustomCursor.SetOpacity(1);
228  }
229 
230  //------------------------------------------------------------------------------------------------
232  void SetWheelZoomMultiplier(float value)
233  {
234  m_fZoomMultiplierWheel = value;
235  }
236 
237  //------------------------------------------------------------------------------------------------
240  void ForceCenterCursor()
241  {
242  float screenX, screenY;
243  m_MapWidget.GetScreenSize(screenX, screenY);
244 
245  m_InputManager.SetCursorPosition(screenX/2, screenY/2);
246  m_CursorInfo.x = screenX/2;
247  m_CursorInfo.y = screenY/2;
248 
249  if (!m_CursorInfo.isFixedMode)
250  m_fFreeCursorTime = FREE_CURSOR_RESET;
251  }
252 
253  //------------------------------------------------------------------------------------------------
254  // CURSOR STATE HANDLERS
255  //------------------------------------------------------------------------------------------------
257  protected void HandleMove()
258  {
259  //begin move
260  if (m_CursorInfo.lastX != m_CursorInfo.x || m_CursorInfo.lastY != m_CursorInfo.y)
261  {
262  if ( ~m_CursorState & EMapCursorState.CS_MOVE )
263  {
264  SetCursorState(EMapCursorState.CS_MOVE);
265  }
266  }
267  //end move
268  else if (m_CursorState & EMapCursorState.CS_MOVE)
269  UnsetCursorState(EMapCursorState.CS_MOVE);
270  }
271 
272  //------------------------------------------------------------------------------------------------
274  protected void HandlePan(float timeSlice)
275  {
276  // pan disabled
277  if (m_CursorState & STATE_PAN_RESTRICTED)
278  {
279  if (m_CursorState & EMapCursorState.CS_PAN)
280  m_fPanCountdown = 0;
281  else
282  return;
283  }
284 
285  // Start panning if cursor is on the screen edges
286  if ( m_CursorInfo.edgeFlags > 0 && (m_CursorState & EMapCursorState.CS_PAN) == 0 ) // dont allow edge panning while panning using another method
287  {
288  if (m_fPanCountdown == 0)
289  m_fPanCountdown = PAN_DEFAULT_COUNTDOWN;
290 
291  float frameTime = System.GetFrameTimeS();
292  int px = (int)(frameTime * 1000) * m_fPanKBMMultiplier;
293 
294  if (m_CursorInfo.edgeFlags & EMapCursorEdgePos.LEFT)
295  m_MapEntity.Pan(EMapPanMode.HORIZONTAL, px);
296  else if (m_CursorInfo.edgeFlags & EMapCursorEdgePos.RIGHT)
297  m_MapEntity.Pan(EMapPanMode.HORIZONTAL, -px);
298 
299  if (m_CursorInfo.edgeFlags & EMapCursorEdgePos.TOP)
300  m_MapEntity.Pan(EMapPanMode.VERTICAL, px);
301  else if (m_CursorInfo.edgeFlags & EMapCursorEdgePos.BOTTOM)
302  m_MapEntity.Pan(EMapPanMode.VERTICAL, -px);
303  }
304 
305  // stop pan state
306  if (m_fPanCountdown <= 0)
307  {
308  if (m_CursorState & EMapCursorState.CS_PAN)
309  {
310  UnsetCursorState(EMapCursorState.CS_PAN);
311  m_CursorInfo.startPos = {0, 0};
312  }
313 
314  return;
315  }
316  // begin pan state
317  if ( ~m_CursorState & EMapCursorState.CS_PAN )
318  SetCursorState(EMapCursorState.CS_PAN);
319 
320  m_fPanCountdown -= timeSlice;
321  }
322 
323  //------------------------------------------------------------------------------------------------
325  protected void HandleZoom()
326  {
327  // stop zoom state
328  if (!m_MapEntity.IsZooming())
329  {
330  if (m_CursorState & EMapCursorState.CS_ZOOM)
331  {
332  UnsetCursorState(EMapCursorState.CS_ZOOM);
333  }
334 
335  return;
336  }
337 
339  if (m_CursorState & STATE_ZOOM_RESTRICTED)
340  return;
341 
342  // begin zoom state
343  if ( ~m_CursorState & EMapCursorState.CS_ZOOM )
344  {
345  SetCursorState(EMapCursorState.CS_ZOOM);
346  }
347  }
348 
349  //------------------------------------------------------------------------------------------------
351  protected void HandleHover(float timeSlice)
352  {
353  // begin hover
354  if (m_CursorState == EMapCursorState.CS_DEFAULT)
355  {
356  m_fHoverTime += timeSlice;
357 
358  if (m_fHoverTime >= 0.25)
359  {
360  float worldX, worldY;
361  m_MapEntity.ScreenToWorldNoFlip(m_CursorInfo.Scale(m_CursorInfo.x), m_CursorInfo.Scale(m_CursorInfo.y), worldX, worldY);
362  vector curPos = Vector(worldX, 0, worldY);
363 
364  MapItem closeItem = m_MapEntity.GetClose(curPos, SINGLE_SELECTION_RANGE / m_MapEntity.GetCurrentZoom());
365  if (closeItem)
366  {
367  SetCursorState(EMapCursorState.CS_HOVER);
368  m_MapEntity.HoverItem(closeItem);
369  }
370 
371  return;
372  }
373  }
374  // end hover
375  else if (m_CursorState & EMapCursorState.CS_HOVER)
376  {
377  float worldX, worldY;
378  m_MapEntity.ScreenToWorldNoFlip(m_CursorInfo.Scale(m_CursorInfo.x), m_CursorInfo.Scale(m_CursorInfo.y), worldX, worldY);
379  vector curPos = Vector(worldX, 0, worldY);
380  MapItem closeItem = m_MapEntity.GetClose(curPos, SINGLE_SELECTION_RANGE / m_MapEntity.GetCurrentZoom());
381 
382  if ( (m_CursorState & STATE_HOVER_RESTRICTED)
383  || !closeItem
384  || (closeItem && closeItem != m_MapEntity.GetHoveredItem())
385  )
386  {
387  m_MapEntity.ClearHover();
388  m_fHoverTime = 0;
389  UnsetCursorState(EMapCursorState.CS_HOVER);
390  }
391  }
392  }
393 
394  //------------------------------------------------------------------------------------------------
396  protected void HandleSelect()
397  {
399  if (m_CursorState & STATE_SELECT_RESTRICTED)
400  return;
401 
402  vector vScreenPos = Vector(m_CursorInfo.Scale(m_CursorInfo.x), 0, m_CursorInfo.Scale(m_CursorInfo.y));
403  m_MapEntity.InvokeOnSelect(vScreenPos);
404 
405  // start select
406  if ( ~m_CursorState & EMapCursorState.CS_SELECT )
407  {
408  SetCursorState(EMapCursorState.CS_SELECT);
409 
410  float worldX, worldY;
411  m_MapEntity.ScreenToWorldNoFlip(m_CursorInfo.Scale(m_CursorInfo.x), m_CursorInfo.Scale(m_CursorInfo.y), worldX, worldY);
412  vector curPos = Vector(worldX, 0, worldY);
413 
414  MapItem selected = m_MapEntity.GetClose(curPos, SINGLE_SELECTION_RANGE / m_MapEntity.GetCurrentZoom() );
415  autoptr array<MapItem> selectedItems = new array<MapItem>;
416  m_MapEntity.GetSelected(selectedItems);
417 
418  // only select if different item or multiple selected
419  if (selected && (selectedItems.Count() != 1 || selectedItems[0] != selected) )
420  {
421  m_MapEntity.ClearSelection();
422  m_MapEntity.SelectItem(selected);
423  }
424  else
425  m_MapEntity.ClearSelection();
426 
427  }
428 
429  // Selection state end instantly after a click
430  UnsetCursorState(EMapCursorState.CS_SELECT);
431  }
432 
433  //------------------------------------------------------------------------------------------------
435  protected void HandleMultiSelect(bool activate)
436  {
437  // multiselect state end or disabled
438  if ( (m_CursorState & STATE_MULTISELECT_RESTRICTED) != 0 || !activate)
439  {
440  // never started
441  if ( ~m_CursorState & EMapCursorState.CS_MULTI_SELECTION )
442  return;
443 
444  // select items
445  m_MapEntity.ClearSelection();
446  autoptr array<MapItem> selectedItems = new array<MapItem>;
447  GetCursorSelection(selectedItems);
448  int count = selectedItems.Count();
449 
450  for ( int i = 0; i < count; i++ )
451  {
452  m_MapEntity.SelectItem(selectedItems[i]);
453  }
454 
455  // multiselect end
456  UnsetCursorState(EMapCursorState.CS_MULTI_SELECTION);
457  m_CursorInfo.startPosMultiSel = {0, 0};
458  }
459  else if (activate)
460  {
461  // multiselect begin
462  if ( ~m_CursorState & EMapCursorState.CS_MULTI_SELECTION )
463  SetCursorState(EMapCursorState.CS_MULTI_SELECTION);
464 
465  // highlight for items within selection
466  m_MapEntity.ResetHighlighted();
467  autoptr array<MapItem> selectedItems = new array<MapItem>;
468  GetCursorSelection(selectedItems);
469  int count = selectedItems.Count();
470 
471  for ( int i = 0; i < count; i++ )
472  {
473  selectedItems[i].SetHighlighted(true);
474  }
475  }
476  }
477 
478  //------------------------------------------------------------------------------------------------
481  protected void HandleDrag(bool startDrag)
482  {
483  // begin drag
484  if (startDrag)
485  {
486  // disable drag state
487  if (m_CursorState & STATE_DRAG_RESTRICTED)
488  return;
489 
490  if ( ~m_CursorState & EMapCursorState.CS_DRAG )
491  {
492  if (SCR_MapToolInteractionUI.StartDrag())
493  {
494  SetCursorState(EMapCursorState.CS_DRAG);
495  }
496  }
497  }
498  // end drag
499  else
500  {
501  if (m_CursorState & EMapCursorState.CS_DRAG)
502  {
503  UnsetCursorState(EMapCursorState.CS_DRAG);
504  SCR_MapToolInteractionUI.EndDrag();
505  }
506  }
507  }
508 
509  //------------------------------------------------------------------------------------------------
511  protected void HandleRotateTool(bool startRotate)
512  {
513  if (m_CursorState & STATE_ROTATE_RESTRICTED)
514  return;
515 
516  if (startRotate)
517  {
518  if ( ~m_CursorState & EMapCursorState.CS_ROTATE )
519  {
520  if (m_CursorState & EMapCursorState.CS_DRAG)
521  HandleDrag(false);
522 
523  if (SCR_MapToolInteractionUI.StartRotate())
524  SetCursorState(EMapCursorState.CS_ROTATE);
525  }
526  }
527  else
528  {
529  if (m_CursorState & EMapCursorState.CS_ROTATE)
530  {
531  UnsetCursorState(EMapCursorState.CS_ROTATE);
532  SCR_MapToolInteractionUI.EndRotate();
533  }
534  }
535  }
536 
537  //------------------------------------------------------------------------------------------------
539  bool HandleDraw(bool active)
540  {
541  // begin draw state
542  if (active && (m_CursorState & STATE_DRAW_RESTRICTED) == 0)
543  {
544  if ( ~m_CursorState & EMapCursorState.CS_DRAW )
545  {
546  SetCursorState(EMapCursorState.CS_DRAW);
547  return true;
548  }
549  }
550  // end draw state
551  else if (m_CursorState & EMapCursorState.CS_DRAW)
552  {
553  UnsetCursorState(EMapCursorState.CS_DRAW);
554  }
555 
556  return false;
557  }
558 
559  //------------------------------------------------------------------------------------------------
561  bool HandleSubMenu(bool active)
562  {
563  // begin sub menu state
564  if (active && (m_CursorState & STATE_SUBMENU_RESTRICTED) == 0)
565  {
566  if (~m_CursorState & EMapCursorState.CS_SUB_MENU)
567  {
568  SetCursorState(EMapCursorState.CS_SUB_MENU);
569  return true;
570  }
571  }
572  // end sub menu state
573  else if (m_CursorState & EMapCursorState.CS_SUB_MENU)
574  {
575  UnsetCursorState(EMapCursorState.CS_SUB_MENU);
576  }
577 
578  return false;
579  }
580 
581  //------------------------------------------------------------------------------------------------
583  bool HandleDialog(bool active)
584  {
585  if (active)
586  {
587  if (~m_CursorState & EMapCursorState.CS_DIALOG)
588  {
589  if (m_CursorInfo.isGamepad)
590  ForceCenterCursor();
591 
592  SetCursorState(EMapCursorState.CS_DIALOG);
593 
594  return true;
595  }
596  }
597  else if (m_CursorState & EMapCursorState.CS_DIALOG)
598  {
599  UnsetCursorState(EMapCursorState.CS_DIALOG);
600 
601  if (m_CursorInfo.isGamepad)
602  ForceCenterCursor();
603  }
604 
605  return false;
606  }
607 
608  //------------------------------------------------------------------------------------------------
609  void ToggleFastTravelDestinationSelection(bool enable)
610  {
611  if (enable)
612  SetCursorState(EMapCursorState.CS_ASSIGN_WP);
613  else
614  UnsetCursorState(EMapCursorState.CS_ASSIGN_WP);
615  }
616 
617  //------------------------------------------------------------------------------------------------
621  bool HandleContextualMenu(bool doClose = false)
622  {
624  if ((m_CursorState & STATE_CTXMENU_RESTRICTED) != 0 && !doClose)
625  return false;
626 
627  SCR_MapRadialUI radialMenu = SCR_MapRadialUI.Cast(m_MapEntity.GetMapUIComponent(SCR_MapRadialUI));
628  if (!radialMenu)
629  return false;
630 
631  if (doClose) // close
632  {
633  if (m_CursorState & EMapCursorState.CS_CONTEXTUAL_MENU)
634  {
635  UnsetCursorState(EMapCursorState.CS_CONTEXTUAL_MENU);
636 
637  return false;
638  }
639  }
640  else if (~m_CursorState & EMapCursorState.CS_CONTEXTUAL_MENU) // open
641  {
642  SetCursorState(EMapCursorState.CS_CONTEXTUAL_MENU);
643 
644  return true;
645  }
646 
647  return false;
648  }
649 
650  //------------------------------------------------------------------------------------------------
651  // SUPPORT METHODS
652  //------------------------------------------------------------------------------------------------
655  protected void GetCursorSelection(out array<MapItem> mapItems)
656  {
658  float startWorldX, startWorldY, worldX, worldY;
659  m_MapEntity.ScreenToWorldNoFlip(m_CursorInfo.Scale(m_CursorInfo.startPosMultiSel[0]), m_CursorInfo.Scale(m_CursorInfo.startPosMultiSel[1]), startWorldX, startWorldY);
660  m_MapEntity.ScreenToWorldNoFlip(m_CursorInfo.Scale(m_CursorInfo.x), m_CursorInfo.Scale(m_CursorInfo.y), worldX, worldY);
661  vector startPos = Vector(startWorldX, 0, startWorldY);
662  vector curPos = Vector(worldX, 0, worldY);
663 
665  if (m_eMultiSelType == EMapCursorSelectType.RECTANGLE)
666  m_MapEntity.GetInsideRect(mapItems, startPos, curPos);
667  else if (m_eMultiSelType == EMapCursorSelectType.CIRCLE)
668  {
669  float circleRadius = m_SelectionModule.GetSelCircleSize() / 2; // size is in pixels while we want radius
670  m_MapEntity.GetInsideCircle(mapItems, curPos, circleRadius / m_MapEntity.GetCurrentZoom());
671  }
672  }
673 
674  //------------------------------------------------------------------------------------------------
678  protected void GetCursorPosition(out int x, out int y)
679  {
680  WorkspaceWidget workspace = GetGame().GetWorkspace();
681 
682  if (!m_MapWidget)
683  m_MapWidget = m_MapEntity.GetMapWidget();
684 
685  float screenX, screenY, offX, offY;
686  m_MapWidget.GetScreenSize(screenX, screenY);
687  m_MapWidget.GetScreenPos(offX, offY);
688 
689  WidgetManager.GetMousePos(x, y);
690 
691  // gamepad cursor
692  if (m_CursorInfo.isGamepad)
693  {
694  // free mode
695  if (!m_CursorInfo.isFixedMode)
696  {
697  if (m_CursorState & STATE_RESET_RESTRICTED)
698  m_fFreeCursorTime = 0;
699  else
700  m_fFreeCursorTime += System.GetFrameTimeS();
701 
702  if (m_fFreeCursorTime > FREE_CURSOR_RESET - 1.0)
703  {
704  float alpha = Math.InverseLerp(FREE_CURSOR_RESET, FREE_CURSOR_RESET - 1.0, m_fFreeCursorTime);
705  m_CustomCursor.SetOpacity(alpha);
706  }
707 
708  if (m_fFreeCursorTime >= FREE_CURSOR_RESET)
709  {
710  m_CursorInfo.isFixedMode = true;
711  m_fFreeCursorTime = 0;
712  m_CustomCursor.SetOpacity(1);
713 
714  ForceCenterCursor();
715  WidgetManager.GetMousePos(x, y);
716  }
717  }
718  }
719 
720  // If the widget is not fullscreen, cursor position needs to be offset to match it
721  x -= offX;
722  y -= offY;
723 
724  // Screen edge pan
725  EMapEntityMode mode = m_MapEntity.GetMapConfig().MapEntityMode;
726  if (m_bEnableCursorEdgePan)
727  TestEdgePan(x, y, screenX, screenY);
728 
729  // unscale the result
730  x = workspace.DPIUnscale(x);
731  y = workspace.DPIUnscale(y);
732  }
733 
734  //------------------------------------------------------------------------------------------------
740  protected void TestEdgePan(inout float x, inout float y, int screenX, int screenY)
741  {
742  float windowWidth, windowHeight;
743  m_MapWidget.GetScreenSize(windowWidth, windowHeight);
744 
745  if (x == 0) // hack so the game doesnt autoscroll to top left when cursor is in default pos (f.e. during window unfocus)
746  return;
747 
748  if (x <= CURSOR_CAPTURE_OFFSET)
749  m_CursorInfo.edgeFlags |= EMapCursorEdgePos.LEFT;
750  else
751  m_CursorInfo.edgeFlags &= ~EMapCursorEdgePos.LEFT;
752 
753  if (y <= CURSOR_CAPTURE_OFFSET)
754  m_CursorInfo.edgeFlags |= EMapCursorEdgePos.TOP;
755  else
756  m_CursorInfo.edgeFlags &= ~EMapCursorEdgePos.TOP;
757 
758  if (x >= (int)windowWidth - CURSOR_CAPTURE_OFFSET - 1)
759  m_CursorInfo.edgeFlags |= EMapCursorEdgePos.RIGHT;
760  else
761  m_CursorInfo.edgeFlags &= ~EMapCursorEdgePos.RIGHT;
762 
763  if (y >= (int)windowHeight - CURSOR_CAPTURE_OFFSET - 1)
764  m_CursorInfo.edgeFlags |= EMapCursorEdgePos.BOTTOM;
765  else
766  m_CursorInfo.edgeFlags &= ~EMapCursorEdgePos.BOTTOM;
767  }
768 
769  //------------------------------------------------------------------------------------------------
770  // INPUTS
771  //------------------------------------------------------------------------------------------------
773  protected void OnInputPanDrag( float value, EActionTrigger reason )
774  {
775  // pan disabled
776  if (m_CursorState & STATE_PAN_RESTRICTED)
777  return;
778 
779  m_fPanCountdown = PAN_DEFAULT_COUNTDOWN;
780  m_MapEntity.Pan(EMapPanMode.DRAG);
781  }
782 
783  //------------------------------------------------------------------------------------------------
785  protected void OnInputPanH( float value, EActionTrigger reason )
786  {
787  CalculatePan(value, EMapPanMode.HORIZONTAL, m_fPanKBMMultiplier); // value determines direction for digital inputs
788  }
789 
790  //------------------------------------------------------------------------------------------------
792  protected void OnInputPanV( float value, EActionTrigger reason )
793  {
794  CalculatePan(value, EMapPanMode.VERTICAL, m_fPanKBMMultiplier); // value determines direction for digital inputs
795  }
796 
797  //------------------------------------------------------------------------------------------------
799  protected void OnInputPanHGamepad( float value, EActionTrigger reason )
800  {
801  if (value == 0)
802  return;
803 
804  CalculatePan(1, EMapPanMode.HORIZONTAL, value * m_fPanStickMultiplier);
805  }
806 
807  //------------------------------------------------------------------------------------------------
809  protected void OnInputPanVGamepad( float value, EActionTrigger reason )
810  {
811  if (value == 0)
812  return;
813 
814  CalculatePan(1, EMapPanMode.VERTICAL, value * m_fPanStickMultiplier);
815  }
816 
817  //------------------------------------------------------------------------------------------------
822  protected void CalculatePan(float direction, EMapPanMode panMode, float multiPlier)
823  {
824  if (m_CursorState & STATE_PAN_RESTRICTED)
825  return;
826 
827  m_fPanCountdown = PAN_DEFAULT_COUNTDOWN;
828  int px = (System.GetFrameTimeS() * 1000); // speed of pan based on time elapsed to avoid slowdown during lower fps
829 
830  if ((int)direction == 1)
831  px = px * multiPlier;
832  else if ((int)direction == 2)
833  px = -px * multiPlier;
834 
835  m_MapEntity.Pan(panMode, px);
836  }
837 
838  //------------------------------------------------------------------------------------------------
840  protected void OnInputGamepadCursorH( float value, EActionTrigger reason )
841  {
842  if (!m_CursorInfo.isGamepad)
843  return;
844 
845  if (value != 0)
846  {
847  m_fFreeCursorTime = 0;
848  m_CustomCursor.SetOpacity(1);
849  m_CursorInfo.isFixedMode = false;
850  }
851  }
852 
853  //------------------------------------------------------------------------------------------------
855  protected void OnInputGamepadCursorV( float value, EActionTrigger reason )
856  {
857  if (!m_CursorInfo.isGamepad)
858  return;
859 
860  if (value != 0)
861  {
862  m_fFreeCursorTime = 0;
863  m_CustomCursor.SetOpacity(1);
864  m_CursorInfo.isFixedMode = false;
865  }
866  }
867 
868  //------------------------------------------------------------------------------------------------
870  protected void OnInputZoom( float value, EActionTrigger reason )
871  {
873  if (m_CursorState & STATE_ZOOM_RESTRICTED)
874  return;
875 
876  m_fZoomHoldTime += System.GetFrameTimeS();
877  if ( (m_CursorState & EMapCursorState.CS_ZOOM) && m_fZoomHoldTime < 0.05) // if pressed, call once every 0.05 second
878  return;
879 
880  float zoomPPU = m_MapEntity.GetCurrentZoom();
881  if (value == 1)
882  m_MapEntity.ZoomSmooth(zoomPPU + zoomPPU/m_fZoomStrength, m_fZoomAnimTime, false);
883  else
884  m_MapEntity.ZoomSmooth(zoomPPU - zoomPPU/m_fZoomStrength, m_fZoomAnimTime, false);
885 
886  m_fZoomHoldTime = 0;
887  }
888 
889  //------------------------------------------------------------------------------------------------
891  protected void OnInputZoomWheelUp( float value, EActionTrigger reason )
892  {
894  if (m_CursorState & STATE_ZOOM_RESTRICTED)
895  return;
896 
897  float targetPPU = m_MapEntity.GetTargetZoomPPU();
898  value = value * m_fZoomMultiplierWheel;
899  m_MapEntity.ZoomSmooth(targetPPU + targetPPU * (value * 0.001), m_fZoomAnimTime, false); // the const here is adjusting the value to match the input with zoom range
900  }
901 
902  //------------------------------------------------------------------------------------------------
904  protected void OnInputZoomWheelDown( float value, EActionTrigger reason )
905  {
907  if (m_CursorState & STATE_ZOOM_RESTRICTED)
908  return;
909 
910  float targetPPU = m_MapEntity.GetTargetZoomPPU();
911  value = value * m_fZoomMultiplierWheel;
912  m_MapEntity.ZoomSmooth(targetPPU - targetPPU/2 * (value * 0.001), m_fZoomAnimTime, false); // the const here is adjusting the value to match the input with zoom range
913  }
914 
915  //------------------------------------------------------------------------------------------------
917  protected void OnInputDrag( float value, EActionTrigger reason )
918  {
919  if (!m_bIsDraggingAvailable)
920  return;
921 
922  if (m_CursorState & EMapCursorState.CS_MODIFIER)
923  return;
924 
925  if (reason == EActionTrigger.DOWN)
926  HandleDrag(true);
927  else
928  HandleDrag(false);
929  }
930 
931  //------------------------------------------------------------------------------------------------
933  protected void OnInputDragToggle( float value, EActionTrigger reason )
934  {
935  if (!m_bIsDraggingAvailable)
936  return;
937 
938  if (m_CursorState & EMapCursorState.CS_MODIFIER)
939  return;
940 
941  if (~m_CursorState & EMapCursorState.CS_DRAG)
942  HandleDrag(true);
943  else
944  HandleDrag(false);
945  }
946 
947  //------------------------------------------------------------------------------------------------
949  protected void OnInputModifier( float value, EActionTrigger reason )
950  {
951  if (reason == EActionTrigger.DOWN)
952  {
953  SetCursorState(EMapCursorState.CS_MODIFIER);
954  if (!SCR_MapToolInteractionUI.s_bIsRotating)
955  HandleRotateTool(true);
956  }
957  else
958  {
959  UnsetCursorState(EMapCursorState.CS_MODIFIER);
960  if (SCR_MapToolInteractionUI.s_bIsRotating)
961  HandleRotateTool(false);
962  }
963  }
964 
965  //------------------------------------------------------------------------------------------------
967  protected void OnInputModifClick( float value, EActionTrigger reason )
968  {
969  SCR_MapToolInteractionUI.ActivateAction();
970  }
971 
972  //------------------------------------------------------------------------------------------------
974  protected void OnInputMultiSel( float value, EActionTrigger reason )
975  {
976  if (reason == EActionTrigger.PRESSED)
977  {
978  if (m_fSelectHoldTime == 0) // first call
979  m_CursorInfo.startPosMultiSel = {m_CursorInfo.x, m_CursorInfo.y};
980 
981  m_fSelectHoldTime += System.GetFrameTimeS();
982  if (m_fSelectHoldTime < 0.2)
983  return;
984 
985  HandleMultiSelect(true);
986  m_eMultiSelType = EMapCursorSelectType.RECTANGLE;
987 
988  }
989  else
990  {
991  HandleMultiSelect(false);
992  m_fSelectHoldTime = 0;
993  }
994  }
995 
996  //------------------------------------------------------------------------------------------------
998  protected void OnInputMultiSelGamepad( float value, EActionTrigger reason )
999  {
1000  if (reason == EActionTrigger.PRESSED)
1001  {
1002  m_CursorInfo.startPosMultiSel = {m_CursorInfo.x, m_CursorInfo.y};
1003  HandleMultiSelect(true);
1004  m_eMultiSelType = EMapCursorSelectType.CIRCLE;
1005  }
1006  else
1007  HandleMultiSelect(false);
1008 
1009  }
1010 
1011  //------------------------------------------------------------------------------------------------
1013  protected void OnPauseMenuOpened()
1014  {
1015  m_bIsDisabled = true;
1016  m_CursorState = EMapCursorState.CS_DEFAULT;
1017  SetCursorType(EMapCursorState.CS_DISABLE);
1018  }
1019 
1020  //------------------------------------------------------------------------------------------------
1022  protected void OnPauseMenuClosed()
1023  {
1024  m_bIsDisabled = false;
1025  SetCursorType(m_CursorState);
1026  }
1027 
1028  //------------------------------------------------------------------------------------------------
1031  protected SCR_CursorVisualState GetCursorStateCfg()
1032  {
1033  EMapCursorState state = EMapCursorState.CS_LAST;
1034  EMapCursorState stateMin = EMapCursorState.CS_DEFAULT;
1036  while (state != stateMin)
1037  {
1038  if (m_CursorState & state)
1039  {
1040  cfg = m_aCursorStatesMap.Get(state);
1041  if (cfg)
1042  return cfg;
1043  }
1044 
1045  state = state >> 1;
1046  }
1047 
1048  return m_aCursorStatesMap.Get(EMapCursorState.CS_DEFAULT);
1049  }
1050 
1051  //------------------------------------------------------------------------------------------------
1053  protected void UpdateCrosshairUI()
1054  {
1055  float sizeX, sizeY, cursorX, cursorY;
1056  m_wCrossMCenter.GetScreenSize(sizeX, sizeY);
1057 
1058  cursorX = m_CursorInfo.x;
1059  cursorY = m_CursorInfo.y;
1060 
1061  // calculate and set new size of top & left fill imageWidgets
1062  WorkspaceWidget workspace = GetGame().GetWorkspace();
1063  cursorX = cursorX - workspace.DPIUnscale(sizeX)/2;
1064  cursorY = cursorY - workspace.DPIUnscale(sizeY)/2;
1065 
1066  m_CustomCursor.Update(m_CursorInfo.x, m_CursorInfo.y);
1067 
1068  m_MapWidget.GetScreenSize(sizeX, sizeY);
1069 
1070  m_wCrossLTop.SetSize(cursorX, cursorY);
1071  m_wCrossRTop.SetSize(workspace.DPIUnscale(sizeX) - cursorX, cursorY);
1072  m_wCrossLBot.SetSize(0, workspace.DPIUnscale(sizeY) - cursorY);
1073  m_wGLTop.SetSize(GUILDING_LINE_WIDTH, cursorY);
1074  m_wGLLeft.SetSize(cursorX, GUILDING_LINE_WIDTH);
1075 
1076  if (m_bEnableCrosshairCoords)
1077  {
1078  float wX, wY;
1079  m_MapEntity.ScreenToWorld(m_CursorInfo.Scale(m_CursorInfo.x), m_CursorInfo.Scale(m_CursorInfo.y), wX, wY);
1080  m_wCoordText.SetText(Math.Round(wX).ToString() + ", " + Math.Round(wY).ToString());
1081  }
1082 
1083  }
1084 
1085  //------------------------------------------------------------------------------------------------
1087  protected static void TraceMapWidgets()
1088  {
1089  WidgetManager.TraceWidgets(SCR_MapCursorInfo.Scale(SCR_MapCursorInfo.x), SCR_MapCursorInfo.Scale(SCR_MapCursorInfo.y), SCR_MapEntity.GetMapInstance().GetMapMenuRoot(), s_aTracedWidgets);
1090  m_bRecentlyTraced = true;
1091  }
1092 
1093  //------------------------------------------------------------------------------------------------
1095  protected void InitWidgets(Widget root)
1096  {
1097  m_MapWidget = m_MapEntity.GetMapWidget();
1098 
1099  m_wCrossGrid = root.FindAnyWidget("CursorCrosshair");
1100  if (m_bEnableMapCrosshairVisuals)
1101  {
1102  SetCrosshairGridVisible(true);
1103  // positioning widgets
1104  m_wCrossMCenter = m_wCrossGrid.FindAnyWidget("CrossMCenter");
1105  m_wCrossRTop = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("CrossRTop"));
1106  m_wCrossLTop = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("CrossLTop"));
1107  m_wCrossLBot = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("CrossLBot"));
1108  m_wGLTop = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("GLTop"));
1109  m_wGLLeft = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("GLLeft"));
1110  // guidelines
1111  m_wGLFadeLeft = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("GLFadeLeft"));
1112  m_wGLRight = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("GLRight"));
1113  m_wGLFadeRight = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("GLFadeRight"));
1114  m_wGLBot = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("GLBot"));
1115  m_wGLFadeBot = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("GLFadeBot"));
1116  m_wGLFadeTop = ImageWidget.Cast(m_wCrossGrid.FindAnyWidget("GLFadeTop"));
1117  m_wCoordText = TextWidget.Cast(m_wCrossGrid.FindAnyWidget("CoordText"));
1118 
1119  // TODO configuration
1120  // Colors
1121  m_wGLTop.SetColor(m_GuidelineColor);
1122  m_wGLLeft.SetColor(m_GuidelineColor);
1123  m_wGLRight.SetColor(m_GuidelineColor);
1124  m_wGLBot.SetColor(m_GuidelineColor);
1125  m_wGLFadeTop.SetColor(m_GuidelineColor);
1126  m_wGLFadeLeft.SetColor(m_GuidelineColor);
1127  m_wGLFadeRight.SetColor(m_GuidelineColor);
1128  m_wGLFadeBot.SetColor(m_GuidelineColor);
1129  m_wCoordText.SetColor(m_GuidelineColor);
1130 
1131  m_wCoordText.SetOpacity(0); // text
1132 
1133  if (m_bEnableCrosshairCoords)
1134  m_wCoordText.SetOpacity(1);
1135  }
1136  else
1137  {
1138  SetCrosshairGridVisible(false);
1139  }
1140 
1141  // cursor
1142  if (!m_CustomCursor)
1143  m_CustomCursor = new SCR_CursorCustom();
1144  }
1145 
1146  //------------------------------------------------------------------------------------------------
1148  protected void InitInputs()
1149  {
1150  m_InputManager = g_Game.GetInputManager();
1151 
1152  // controller detection
1153  OnInputDeviceIsGamepad(!GetGame().GetInputManager().IsUsingMouseAndKeyboard());
1154  GetGame().OnInputDeviceIsGamepadInvoker().Insert(OnInputDeviceIsGamepad);
1155 
1156  // pause menu
1157  PauseMenuUI.m_OnPauseMenuOpened.Insert(OnPauseMenuOpened);
1158  PauseMenuUI.m_OnPauseMenuClosed.Insert(OnPauseMenuClosed);
1159 
1160  m_InputManager.AddActionListener("MapPanDrag", EActionTrigger.PRESSED, OnInputPanDrag);
1161  m_InputManager.AddActionListener("MapPanH", EActionTrigger.PRESSED, OnInputPanH);
1162  m_InputManager.AddActionListener("MapPanV", EActionTrigger.PRESSED, OnInputPanV);
1163  m_InputManager.AddActionListener("MapPanHGamepad", EActionTrigger.VALUE, OnInputPanHGamepad); // requires trigger by value since thumbstick val ranges from -1 to 1
1164  m_InputManager.AddActionListener("MapPanVGamepad", EActionTrigger.VALUE, OnInputPanVGamepad);
1165  m_InputManager.AddActionListener("MapGamepadCursorX", EActionTrigger.VALUE, OnInputGamepadCursorH);
1166  m_InputManager.AddActionListener("MapGamepadCursorY", EActionTrigger.VALUE, OnInputGamepadCursorV);
1167  m_InputManager.AddActionListener("MapZoom", EActionTrigger.PRESSED, OnInputZoom);
1168  m_InputManager.AddActionListener("MapWheelUp", EActionTrigger.PRESSED, OnInputZoomWheelUp);
1169  m_InputManager.AddActionListener("MapWheelDown", EActionTrigger.PRESSED, OnInputZoomWheelDown);
1170  m_InputManager.AddActionListener("MapSelect", EActionTrigger.UP, HandleSelect);
1171 
1172  // multi selection
1173  m_SelectionModule = SCR_MapSelectionModule.Cast(m_MapEntity.GetMapModule(SCR_MapSelectionModule));
1174  if ( m_SelectionModule )
1175  {
1176  m_InputManager.AddActionListener("MapMultiSelect", EActionTrigger.PRESSED, OnInputMultiSel);
1177  m_InputManager.AddActionListener("MapMultiSelect", EActionTrigger.UP, OnInputMultiSel);
1178  m_InputManager.AddActionListener("MapMultiSelectGamepad", EActionTrigger.PRESSED, OnInputMultiSelGamepad);
1179  m_InputManager.AddActionListener("MapMultiSelectGamepad", EActionTrigger.UP, OnInputMultiSelGamepad);
1180  }
1181 
1182  // tool interaction UI
1183  if ( SCR_MapToolInteractionUI.Cast(m_MapEntity.GetMapUIComponent(SCR_MapToolInteractionUI)) )
1184  {
1185  m_bIsDraggingAvailable = true;
1186 
1187  m_InputManager.AddActionListener("MapModifierKey", EActionTrigger.DOWN, OnInputModifier);
1188  m_InputManager.AddActionListener("MapModifierKey", EActionTrigger.UP, OnInputModifier);
1189  m_InputManager.AddActionListener("MapModifClick", EActionTrigger.DOWN, OnInputModifClick);
1190  m_InputManager.AddActionListener("MapDrag", EActionTrigger.DOWN, OnInputDrag);
1191  m_InputManager.AddActionListener("MapDrag", EActionTrigger.UP, OnInputDrag);
1192  m_InputManager.AddActionListener("MapDragGamepad", EActionTrigger.DOWN, OnInputDragToggle);
1193  }
1194  else
1195  m_bIsDraggingAvailable = false;
1196 
1197  }
1198 
1199  //------------------------------------------------------------------------------------------------
1201  protected void CleanupInputs()
1202  {
1203  if (!m_InputManager)
1204  m_InputManager = g_Game.GetInputManager();
1205 
1206  // controller detection
1207  GetGame().OnInputDeviceIsGamepadInvoker().Remove(OnInputDeviceIsGamepad);
1208 
1209  // pause menu
1210  PauseMenuUI.m_OnPauseMenuOpened.Remove(OnPauseMenuOpened);
1211  PauseMenuUI.m_OnPauseMenuClosed.Remove(OnPauseMenuClosed);
1212 
1213  m_InputManager.RemoveActionListener("MapPanDrag", EActionTrigger.PRESSED, OnInputPanDrag);
1214  m_InputManager.RemoveActionListener("MapPanH", EActionTrigger.PRESSED, OnInputPanH);
1215  m_InputManager.RemoveActionListener("MapPanV", EActionTrigger.PRESSED, OnInputPanV);
1216  m_InputManager.RemoveActionListener("MapPanHGamepad", EActionTrigger.VALUE, OnInputPanHGamepad);
1217  m_InputManager.RemoveActionListener("MapPanVGamepad", EActionTrigger.VALUE, OnInputPanVGamepad);
1218  m_InputManager.RemoveActionListener("MapGamepadCursorX", EActionTrigger.VALUE, OnInputGamepadCursorH);
1219  m_InputManager.RemoveActionListener("MapGamepadCursorY", EActionTrigger.VALUE, OnInputGamepadCursorV);
1220  m_InputManager.RemoveActionListener("MapZoom", EActionTrigger.PRESSED, OnInputZoom);
1221  m_InputManager.RemoveActionListener("MapWheelUp", EActionTrigger.PRESSED, OnInputZoomWheelUp);
1222  m_InputManager.RemoveActionListener("MapWheelDown", EActionTrigger.PRESSED, OnInputZoomWheelDown);
1223  m_InputManager.RemoveActionListener("MapSelect", EActionTrigger.UP, HandleSelect);
1224 
1225  m_InputManager.RemoveActionListener("MapModifierKey", EActionTrigger.DOWN, OnInputModifier);
1226  m_InputManager.RemoveActionListener("MapModifierKey", EActionTrigger.UP, OnInputModifier);
1227  m_InputManager.RemoveActionListener("MapModifClick", EActionTrigger.DOWN, OnInputModifClick);
1228  m_InputManager.RemoveActionListener("MapDrag", EActionTrigger.DOWN, OnInputDrag);
1229  m_InputManager.RemoveActionListener("MapDrag", EActionTrigger.UP, OnInputDrag);
1230  m_InputManager.RemoveActionListener("MapDragGamepad", EActionTrigger.DOWN, OnInputDragToggle);
1231 
1232  m_InputManager.RemoveActionListener("MapMultiSelect", EActionTrigger.PRESSED, OnInputMultiSel);
1233  m_InputManager.RemoveActionListener("MapMultiSelect", EActionTrigger.UP, OnInputMultiSel);
1234  m_InputManager.RemoveActionListener("MapMultiSelectGamepad", EActionTrigger.PRESSED, OnInputMultiSelGamepad);
1235  m_InputManager.RemoveActionListener("MapMultiSelectGamepad", EActionTrigger.UP, OnInputMultiSelGamepad);
1236  }
1237 
1238  //------------------------------------------------------------------------------------------------
1239  // OVERRIDES
1240  //------------------------------------------------------------------------------------------------
1241  override void OnMapOpen(MapConfiguration config)
1242  {
1243  if (!m_CursorInfo)
1245 
1246  m_bIsDisabled = false;
1247  InitWidgets(config.RootWidgetRef);
1248  InitInputs();
1249  m_bIsInit = true;
1250 
1251  SetCursorType(m_CursorState);
1252 
1253  if (m_bIsCursorCenteredOnOpen || m_CursorInfo.isGamepad)
1254  ForceCenterCursor();
1255  }
1256 
1257  //------------------------------------------------------------------------------------------------
1258  override void OnMapClose(MapConfiguration config)
1259  {
1260  m_CursorState = EMapCursorState.CS_DEFAULT;
1261  SetCursorType(EMapCursorState.CS_DISABLE);
1262  CleanupInputs();
1263 
1264  m_bIsInit = false;
1265  }
1266 
1267  //------------------------------------------------------------------------------------------------
1268  override void Update(float timeSlice)
1269  {
1270  if (m_bIsDisabled)
1271  return;
1272 
1273  m_bRecentlyTraced = false;
1274 
1275  // update last pos
1276  m_CursorInfo.lastX = m_CursorInfo.x;
1277  m_CursorInfo.lastY = m_CursorInfo.y;
1278 
1279  // update current pos
1280  GetCursorPosition(m_CursorInfo.x, m_CursorInfo.y);
1281 
1282  // frame handlers
1283  HandleMove();
1284  HandleHover(timeSlice);
1285  HandlePan(timeSlice);
1286  HandleZoom();
1287 
1288  // crosshair grid lines
1289  if (m_bEnableMapCrosshairVisuals && (m_CursorState & CUSTOM_CURSOR_LOCKED) == 0)
1290  UpdateCrosshairUI();
1291  }
1292 
1293  //------------------------------------------------------------------------------------------------
1294  void SCR_MapCursorModule()
1295  {
1296  foreach (SCR_CursorVisualState cursorState : m_aCursorStatesConfig)
1297  {
1298  EMapCursorState stateEnum = cursorState.m_eCursorState;
1299  if (stateEnum)
1300  m_aCursorStatesMap.Insert(stateEnum, cursorState);
1301  }
1302  }
1303 };
1304 
1305 //------------------------------------------------------------------------------------------------
1309 {
1310  [Attribute("1", UIWidgets.ComboBox, "Configure selected cursor state", "", ParamEnumArray.FromEnum(EMapCursorState))]
1311  int m_eCursorState;
1312 
1313  [Attribute("{E75FB4134580A496}UI/Textures/Cursor/cursors.imageset", UIWidgets.ResourceNamePicker, desc: "Imageset selection", params: "imageset")]
1314  ResourceName m_sCursorIconsImageset;
1315 
1316  [Attribute("default", UIWidgets.EditBox, desc: "imageset quad")]
1317  string m_sImageQuad;
1318 
1319  [Attribute("", UIWidgets.EditBox, desc: "imageset quad when controller is active instead of KBM \nIf this is not defined, attibute from above is used for both cases")]
1320  string m_sImageQuadController;
1321 
1322  [Attribute("0", UIWidgets.Slider, desc: "Padding from top, in pixels", "-32 32 1")]
1323  float m_fPaddingTop;
1324 
1325  [Attribute("0", UIWidgets.Slider, desc: "Padding from left, in pixels", "-32 32 1")]
1326  float m_fPaddingLeft;
1327 
1328  [Attribute("0.76 0.38 0.08 1", UIWidgets.ColorPicker, desc: "Cursor color")]
1329  ref Color m_Color;
1330 
1331  [Attribute(desc: "Cursor lines are disabled in this state if otherwise active")]
1332  bool m_DisableCursorLines;
1333 };
1334 
1335 //------------------------------------------------------------------------------------------------
1337 class SCR_CursorStateTitle: BaseContainerCustomTitle
1338 {
1339  //------------------------------------------------------------------------------------------------
1340  override bool _WB_GetCustomTitle(BaseContainer source, out string title)
1341  {
1342  int type;
1343  source.Get("m_eCursorState", type);
1344  title = typename.EnumToString(EMapCursorState, type);
1345 
1346  return true;
1347  }
1348 };
SCR_CursorStateTitle
Custom names for cursor visual states.
Definition: SCR_MapCursorModule.c:1337
direction
vector direction
Definition: SCR_DestructibleTreeV2.c:31
m_MapEntity
protected SCR_MapEntity m_MapEntity
Definition: SCR_MapGadgetComponent.c:14
EMapCursorState
EMapCursorState
Map cursor state.
Definition: SCR_MapConstants.c:39
m_InputManager
protected InputManager m_InputManager
Definition: SCR_BaseManualCameraComponent.c:15
EMapCursorEdgePos
EMapCursorEdgePos
Flags for when cursor is placed on screen edges.
Definition: SCR_MapConstants.c:62
EMapPanMode
EMapPanMode
Panning modes.
Definition: SCR_MapConstants.c:19
SCR_MapRadialUI
2D map radial menu UI
Definition: SCR_MapRadialUI.c:13
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
PauseMenuUI
Definition: SCR_PauseMenuUI.c:2
SCR_MapSelectionModule
Definition: SCR_MapSelectionModule.c:3
SCR_CursorVisualState
Cursor visual state config.
Definition: SCR_MapCursorModule.c:1308
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
SCR_MapCursorModule
Map cursor behavior and mode setup.
Definition: SCR_MapCursorModule.c:39
SCR_CursorCustom
Scripted map cursor visualization for cases where the gamecode provided one is not sufficient.
Definition: SCR_CursorCustom.c:3
Attribute
typedef Attribute
Post-process effect of scripted camera.
MapItem
Definition: MapItem.c:12
EMapCursorSelectType
EMapCursorSelectType
Map cursor multiselection type.
Definition: SCR_MapConstants.c:72
SCR_MapEntity
Map entity.
Definition: SCR_MapEntity.c:20
m_CursorInfo
protected SCR_MapCursorInfo m_CursorInfo
Definition: SCR_MapToolInteractionUI.c:38
SCR_MapModuleBase
Map module base class.
Definition: SCR_MapModuleBase.c:4
m_bIsDisabled
protected bool m_bIsDisabled
Definition: SCR_VONController.c:38
GetInputManager
protected InputManager GetInputManager()
Definition: SCR_BaseManualCameraComponent.c:65
type
EDamageType type
Definition: SCR_DestructibleTreeV2.c:32
SCR_MapCursorInfo
Cursor data.
Definition: SCR_MapCursorModule.c:3
params
Configs ServerBrowser KickDialogs params
Definition: SCR_NotificationSenderComponent.c:24
EMapEntityMode
EMapEntityMode
Mode of the map.
Definition: SCR_MapConstants.c:28
int
SCR_PossessingManagerComponentClass int
BaseContainerProps
SCR_AIGoalReaction_Follow BaseContainerProps
Handles insects that are supposed to be spawned around selected prefabs defined in prefab names array...
Definition: SCR_AIGoalReaction.c:468