Arma Reforger Explorer  1.1.0.42
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
SCR_RadialMenu.c
Go to the documentation of this file.
1 //------------------------------------------------------------------------------------------------
7 [BaseContainerProps(configRoot: true)]
9 {
10  protected static SCR_RadialMenu m_GlobalRadialMenu;
11  protected static SCR_RadialMenu m_OpenedRadialMenu; // reference to any currently open radial menu inheriting from this class
12 
13  const float SIZE_LARGE = 580;
14  protected const float SIZE_SMALL = 400;
15 
16  protected vector m_vMenuCenterPos;
17 
18  protected float m_fEntriesAngleDistance;
19  protected float m_fEntryAngleOffset;
20 
21  protected float m_fPointingAngle;
22  protected bool m_bIsPointingToCenter;
23  protected float m_fDynamicMouseSelectionTreshold;
24 
25  protected bool m_bActivateContext;
26  protected bool m_bPreventSelectionContext;
27 
28  protected SCR_RadialMenuInputs m_RadialInputs;
29  protected SCR_RadialMenuControllerInputs m_RadialControllerInputs;
30 
31  protected string m_sActionHint;
32 
33  // Events
34  protected ref ScriptInvoker<SCR_RadialMenu, float> m_OnDisplaySizeChange;
35  protected ref ScriptInvoker<SCR_RadialMenu, string> m_OnSetActionHint;
36 
37  //------------------------------------------------------------------------------------------------
38  protected void InvokeOnDisplaySizeChange(float size)
39  {
40  if (m_OnDisplaySizeChange)
41  m_OnDisplaySizeChange.Invoke(this, size);
42  }
43 
44  //------------------------------------------------------------------------------------------------
45  ScriptInvoker GetOnDisplaySizeChange()
46  {
47  if (!m_OnDisplaySizeChange)
48  m_OnDisplaySizeChange = new ScriptInvoker();
49 
50  return m_OnDisplaySizeChange;
51  }
52 
53  //------------------------------------------------------------------------------------------------
54  protected void InvokeOnSetActionHint(string action)
55  {
56  if (m_OnSetActionHint)
57  m_OnSetActionHint.Invoke(this, action);
58  }
59 
60  //------------------------------------------------------------------------------------------------
61  ScriptInvoker GetOnSetActionHint()
62  {
63  if (!m_OnSetActionHint)
64  m_OnSetActionHint = new ScriptInvoker();
65 
66  return m_OnSetActionHint;
67  }
68 
69  //------------------------------------------------------------------------------------------------
70  // Getting global menu
71  //------------------------------------------------------------------------------------------------
72 
73 
74  //------------------------------------------------------------------------------------------------
76  static SCR_RadialMenu GlobalRadialMenu()
77  {
78  if (!m_GlobalRadialMenu)
79  {
80  PlayerController controller = GetGame().GetPlayerController();
81  if (!controller)
82  return null;
83 
84  SCR_RadialMenuGameModeComponent rm = SCR_RadialMenuGameModeComponent.Cast(controller.FindComponent(SCR_RadialMenuGameModeComponent));
85 
86  if (!rm)
87  {
88  #ifdef RADMENU_DEBUG
89  Print("[SCR_RadialMenuController] - Can't setup radial menu due to missing RM game mode!");
90  #endif
91  return null;
92  }
93 
94  m_GlobalRadialMenu = SCR_RadialMenu.Cast(rm.GetMenu());
95  }
96 
97  return m_GlobalRadialMenu;
98  }
99 
100  //------------------------------------------------------------------------------------------------
101  protected void OnMenuOpened(ChimeraMenuBase menu)
102  {
103  if (m_OpenedRadialMenu)
104  m_OpenedRadialMenu.Close();
105  }
106 
107  //------------------------------------------------------------------------------------------------
108  // Override
109  //------------------------------------------------------------------------------------------------
110 
111  //------------------------------------------------------------------------------------------------
112  protected override event void OnOpen()
113  {
114  super.OnOpen(owner);
115 
116  if (m_OpenedRadialMenu)
117  m_OpenedRadialMenu.Close();
118 
119  // Setup controls
120  m_Inputs.Init();
121  AddActionListeners();
122 
123  GetGame().GetCallqueue().Remove(ReleaseContext);
124  m_bActivateContext = true;
125 
126  m_OpenedRadialMenu = this;
127 
128  DeselectEntry();
129  }
130 
131  //------------------------------------------------------------------------------------------------
132  protected override event void OnClose()
133  {
134  super.OnClose(owner);
135  RemoveActionListeners();
136 
137  m_OpenedRadialMenu = null;
138 
139  // Allow to stop using context after split of a second to prevent unwanted input
140  if (m_RadialInputs)
141  GetGame().GetCallqueue().CallLater(ReleaseContext, m_RadialInputs.m_iContextDeactivationTime);
142  }
143 
144  //------------------------------------------------------------------------------------------------
145  protected void ReleaseContext()
146  {
147  m_bActivateContext = false;
148  }
149 
150  //------------------------------------------------------------------------------------------------
151  override void Update(float timeSlice)
152  {
153  if (System.IsConsoleApp())
154  return;
155 
156  // Context
157  if (m_bActivateContext && !m_bPreventSelectionContext)
158  GetGame().GetInputManager().ActivateContext(m_Inputs.m_sContext);
159 
160  // Controller inputs
161  if (m_bActivateContext && m_ControllerInputs)
162  GetGame().GetInputManager().ActivateContext(m_ControllerInputs.m_sControllerContext);
163 
164  OnUpdate(timeSlice);
165  }
166 
167  //------------------------------------------------------------------------------------------------
169  override protected void OnUpdate(float timeSlice)
170  {
171  if (!m_bOpened)
172  return;
173 
174  if (!m_bPreventSelectionContext)
175  SelectEntry();
176  }
177 
178  //------------------------------------------------------------------------------------------------
180  override void SetMenuDisplay(SCR_SelectionMenuDisplay display = null)
181  {
182  // By default find radial menu display from HUD manager
183  if (!display)
184  {
185  SCR_HUDManagerComponent hud = GetGame().GetHUDManager();
186 
187  if (hud)
188  {
189  display = SCR_SelectionMenuDisplay.Cast(hud.FindInfoDisplay(SCR_RadialMenuDisplay));
190  }
191  }
192 
193  super.SetMenuDisplay(display);
194 
195  // Setup cofiguration
196  if (m_RadialControllerInputs)
197  ChangeDisplaySize(m_RadialControllerInputs.m_bUseLargeSize, m_RadialControllerInputs.m_fCustomSize);
198  }
199 
200  //------------------------------------------------------------------------------------------------
202  override protected void SelectEntry()
203  {
205  int id = -1;
206 
207  entry = HandleSelection(id);
208 
209  if (!GetGame().GetInputManager().IsUsingMouseAndKeyboard())
210  {
211  if (m_bIsPointingToCenter && m_RadialControllerInputs.m_bDeselectInCenter)
212  {
213  // Call deselection after split of a second to prevent deselection happening during closing
214  if (GetGame().GetCallqueue().GetRemainingTime(DeselectEntry) == -1)
215  GetGame().GetCallqueue().CallLater(DeselectEntry, m_RadialInputs.m_iGamepadDeselectionDelay);
216 
217  return;
218  }
219  }
220 
221  GetGame().GetCallqueue().Remove(DeselectEntry);
222 
223  // Update selection
224  if (m_SelectedEntry != entry)
225  {
226  m_SelectedEntry = entry;
227  InvokeOnSelect(entry, id);
228 
229  PlaySound(m_sSelectionSound);
230 
231  // Setup input action
232  if (entry && !entry.GetInputAction().IsEmpty())
233  SetActionHint(entry.GetInputAction());
234  else
235  HideActionHint();
236  }
237  }
238 
239  //------------------------------------------------------------------------------------------------
240  override protected void InvokeOnUpdateEntries(array<ref SCR_SelectionMenuEntry> entries)
241  {
242  if (!m_aEntries.IsEmpty())
243  m_fEntriesAngleDistance = 360 / m_aEntries.Count();
244 
245  super.InvokeOnUpdateEntries(entries);
246  }
247 
248  //------------------------------------------------------------------------------------------------
249  override void SetController(IEntity owner, SCR_SelectionMenuControllerInputs controls)
250  {
251  super.SetController(owner, controls);
252 
253  m_RadialControllerInputs = SCR_RadialMenuControllerInputs.Cast(controls);
254  m_RadialInputs = SCR_RadialMenuInputs.Cast(m_Inputs);
255 
256  if (m_RadialControllerInputs && m_RadialInputs)
257  m_RadialInputs.SetUseRightStick(m_RadialControllerInputs.m_bUseRightStick);
258 
259  #ifdef RADMENU_DEBUG
260  // Set controller configuration from diag menu
261  DebugSetupControllerInputs(m_RadialControllerInputs);
262  DebugFillWithEntries();
263  #endif
264  }
265 
266  //------------------------------------------------------------------------------------------------
267  override protected void OnPerformInput()
268  {
269  super.OnPerformInput();
270 
271  if (!m_SelectedEntry)
272  {
273  if (m_ControllerInputs.m_bCloseOnPerform)
274  Close();
275  }
276  }
277 
278  //------------------------------------------------------------------------------------------------
280  override protected void AddActionListeners()
281  {
282  super.AddActionListeners();
283 
284  SCR_MenuHelper.GetOnMenuOpened().Insert(OnMenuOpened);
285 
286  // Quick actions 1-9
287  if (!m_RadialControllerInputs.m_bUseQuickActions)
288  return;
289 
290  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot1", EActionTrigger.DOWN, OnQuickAction1);
291  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot2", EActionTrigger.DOWN, OnQuickAction2);
292  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot3", EActionTrigger.DOWN, OnQuickAction3);
293  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot4", EActionTrigger.DOWN, OnQuickAction4);
294  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot5", EActionTrigger.DOWN, OnQuickAction5);
295  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot6", EActionTrigger.DOWN, OnQuickAction6);
296  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot7", EActionTrigger.DOWN, OnQuickAction7);
297  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot8", EActionTrigger.DOWN, OnQuickAction8);
298  GetGame().GetInputManager().AddActionListener("InventoryQuickSlot9", EActionTrigger.DOWN, OnQuickAction9);
299  }
300 
301  //------------------------------------------------------------------------------------------------
303  override protected void RemoveActionListeners()
304  {
305  super.RemoveActionListeners();
306 
307  SCR_MenuHelper.GetOnMenuOpened().Remove(OnMenuOpened);
308 
309  // Quick actions 1-9
310  if (!m_RadialControllerInputs.m_bUseQuickActions)
311  return;
312 
313  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot1", EActionTrigger.DOWN, OnQuickAction1);
314  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot2", EActionTrigger.DOWN, OnQuickAction2);
315  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot3", EActionTrigger.DOWN, OnQuickAction3);
316  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot4", EActionTrigger.DOWN, OnQuickAction4);
317  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot5", EActionTrigger.DOWN, OnQuickAction5);
318  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot6", EActionTrigger.DOWN, OnQuickAction6);
319  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot7", EActionTrigger.DOWN, OnQuickAction7);
320  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot8", EActionTrigger.DOWN, OnQuickAction8);
321  GetGame().GetInputManager().RemoveActionListener("InventoryQuickSlot9", EActionTrigger.DOWN, OnQuickAction9);
322  }
323 
324  //------------------------------------------------------------------------------------------------
325  protected void OnQuickAction1() { QuickActionUse(1); }
326  protected void OnQuickAction2() { QuickActionUse(2); }
327  protected void OnQuickAction3() { QuickActionUse(3); }
328  protected void OnQuickAction4() { QuickActionUse(4); }
329  protected void OnQuickAction5() { QuickActionUse(5); }
330  protected void OnQuickAction6() { QuickActionUse(6); }
331  protected void OnQuickAction7() { QuickActionUse(7); }
332  protected void OnQuickAction8() { QuickActionUse(8); }
333  protected void OnQuickAction9() { QuickActionUse(9); }
334 
335  //------------------------------------------------------------------------------------------------
336  protected void QuickActionUse(int id)
337  {
338  // - 1 because slot actions starts with 1, but entries with 0
339  id -= 1;
340 
341  if (!m_aEntries.IsIndexValid(id))
342  return;
343 
344  m_SelectedEntry = m_aEntries[id];
345  m_iSelectedEntryId = id;
346 
347  if (!SCR_SelectionMenuCategoryEntry.Cast(m_SelectedEntry))
348  InvokeOnSelect(m_SelectedEntry, id);
349 
350  m_bEntryPerformed = true;
351  PerformEntry(m_SelectedEntry);
352  }
353 
354  //------------------------------------------------------------------------------------------------
355  // Custom
356  //------------------------------------------------------------------------------------------------
357 
358  //------------------------------------------------------------------------------------------------
359  protected int GetSelectedElementIndex(float angle, int elementCount)
360  {
361  if (elementCount == 0)
362  return -1;
363 
364  float angleDeg = Math.Repeat(angle * Math.RAD2DEG, 360) - m_fEntryAngleOffset;
365  float overflow = m_fEntriesAngleDistance * 0.5;
366 
367  // compensate overflowing offset
368  if (angleDeg < 0)
369  {
370  angleDeg = Math.Repeat(angleDeg, 360);
371  }
372 
373  if (m_fEntriesAngleDistance == 0)
374  {
375  #ifdef RADMENU_DEBUG
376  DebugPrint("GetSelectedElementIndex", "No distance between entries!");
377  #endif
378  return -1;
379  }
380 
381  // Find entry index withing circle
382  int idx = Math.Round(angleDeg / m_fEntriesAngleDistance);
383 
384  if (idx < 0 || idx >= elementCount)
385  {
386  idx = -1;
387  }
388 
389  // Count with overflow
390  if (idx == -1)
391  {
392  if (angleDeg > (360 - overflow + m_fEntryAngleOffset))
393  return 0;
394  else
395  return -1;
396  }
397 
398  return idx;
399  }
400 
401  //------------------------------------------------------------------------------------------------
404  protected float AdjustDistanceWithResolution(float distance)
405  {
406  // Current
407  float curW, curH;
408  GetGame().GetWorkspace().GetScreenSize(curW, curH);
409 
410  if (curW == 0 || curH == 0)
411  return distance;
412 
413  // Reference 1920x1080
414  int refW, refH;
415  WidgetManager.GetReferenceScreenSize(refW, refH);
416 
417  float ratioX = curW / refW;
418  float ratioY = curH / refH;
419 
420  float ratioDist = vector.Distance(
421  Vector(m_vMenuCenterPos[0] / refW, m_vMenuCenterPos[1] / refH, 0),
422  Vector(curW / refW, curH / refH,
423  0));
424 
425  return distance / ratioDist;
426  }
427 
428  //------------------------------------------------------------------------------------------------
429  protected SCR_SelectionMenuEntry HandleSelection(out int id)
430  {
431  // Check m_Inputs
432  if (!m_RadialInputs || !m_RadialControllerInputs)
433  return null;
434 
435  float dist;
436  vector dir;
437 
438  // Handle used input
439  if (GetGame().GetInputManager().IsUsingMouseAndKeyboard())
440  {
441  // Mouse
442  int mouseX, mouseY;
443  WidgetManager.GetMousePos(mouseX, mouseY);
444  dir = Vector(mouseX, mouseY, 0);
445 
446  dist = vector.Distance(m_vMenuCenterPos, dir);
447  dist = AdjustDistanceWithResolution(dist);
448 
449  // Center the direction
450  dir[0] = mouseX - m_vMenuCenterPos[0];
451  dir[1] = (mouseY - m_vMenuCenterPos[1]) * -1;
452  dir.Normalize();
453 
454  // Deselect if in center
455  m_bIsPointingToCenter = (
456  m_RadialControllerInputs.m_bDeselectInCenter && dist < m_fDynamicMouseSelectionTreshold);
457 
458  if (m_bIsPointingToCenter)
459  return null;
460  }
461  else
462  {
463  // Gamepad
464  float x, y;
465  m_RadialInputs.GetRadialXYInput(x, y);
466 
467  dir[0] = x;
468  dir[1] = y;
469  dist = vector.Distance(vector.Zero, Vector(x, y, 0));
470 
471  // Deselect if in center
472  m_bIsPointingToCenter = (
473  m_RadialControllerInputs.m_bDeselectInCenter && dist < m_RadialInputs.m_fGamepadSelectionTreshhold);
474 
475  if (m_bIsPointingToCenter)
476  return null;
477  }
478 
479  // Selected pointed
480  float angle = Math.Atan2(dir[0], dir[1]);
481  id = GetSelectedElementIndex(angle, m_aEntries.Count());
482 
483  m_fPointingAngle = angle * Math.RAD2DEG;
484 
485  if (m_aEntries.IsIndexValid(id))
486  return m_aEntries[id];
487 
488  id = -1;
489  return null;
490  }
491 
492  //------------------------------------------------------------------------------------------------
493  protected void DeselectEntry()
494  {
495  m_SelectedEntry = null;
496  InvokeOnSelect(null, -1);
497  }
498 
499  //------------------------------------------------------------------------------------------------
501  protected void ReactQuickInput()
502  {
503  for (int i = 1; i < 9; i++)
504  {
505  if (GetGame().GetInputManager().GetActionTriggered("InventoryQuickSlot" + i))
506  {
507  // - 1 because slot actions starts with 1, but entries with 0
508  int id = i-1;
509 
510  if (!m_aEntries.IsIndexValid(id))
511  continue;
512 
513  m_SelectedEntry = m_aEntries[id];
514  m_iSelectedEntryId = id;
515 
516  if (!SCR_SelectionMenuCategoryEntry.Cast(m_SelectedEntry))
517  InvokeOnSelect(m_SelectedEntry, id);
518 
519  m_bEntryPerformed = true;
520  PerformEntry(m_SelectedEntry);
521  }
522  }
523  }
524 
525  //------------------------------------------------------------------------------------------------
529  void ChangeDisplaySize(bool useLarge = true, float customSize = -1)
530  {
531  float size = SIZE_LARGE;
532  if (!useLarge)
533  size = SIZE_SMALL;
534 
535  if (customSize > 0)
536  size = customSize;
537 
538  // Change seletion treshold
539  m_fDynamicMouseSelectionTreshold = m_RadialInputs.m_fMouseSelectionTreshold;
540 
541  if (m_RadialInputs.m_bDynamicMouseTreshold)
542  m_fDynamicMouseSelectionTreshold *= size / SIZE_LARGE; // Mutliply with large size based ratio
543 
544  // Invoke
545  InvokeOnDisplaySizeChange(size);
546  }
547 
548  //------------------------------------------------------------------------------------------------
550  void SetActionHint(string action)
551  {
552  m_sActionHint = action;
553  InvokeOnSetActionHint(m_sActionHint);
554  }
555 
556  //------------------------------------------------------------------------------------------------
557  //1 Invoke emtpy action to hide in radial menu display
558  void HideActionHint()
559  {
560  InvokeOnSetActionHint("");
561  }
562 
563  //------------------------------------------------------------------------------------------------
564  // Get set
565  //------------------------------------------------------------------------------------------------
566 
567  //------------------------------------------------------------------------------------------------
568  void SetMenuCenterPos(vector centerPos)
569  {
570  m_vMenuCenterPos = centerPos;
571  }
572 
573  //------------------------------------------------------------------------------------------------
574  float GetEntriesAngleDistance()
575  {
576  return m_fEntriesAngleDistance;
577  }
578 
579  //------------------------------------------------------------------------------------------------
580  float GetPointingAngle()
581  {
582  return m_fPointingAngle;
583  }
584 
585  //------------------------------------------------------------------------------------------------
586  bool IsPointingToCenter()
587  {
588  return m_bIsPointingToCenter;
589  }
590 
591  //------------------------------------------------------------------------------------------------
592  // Debug
593  //------------------------------------------------------------------------------------------------
594 
595  #ifdef RADMENU_DEBUG
596 
597  //------------------------------------------------------------------------------------------------
598  override protected void DebugPrint(string method, string msg)
599  {
600  Print(string.Format("[SCR_RadialMenu] - %1() - '%2'", method, msg));
601  }
602 
603  //------------------------------------------------------------------------------------------------
604  protected void DebugSetupDiagMenu()
605  {
606  string rmDiagName = "Radial menu (refactored)";
607 
608  DiagMenu.RegisterMenu(SCR_DebugMenuID.DEBUGUI_RADIALMENU_MENU, rmDiagName, "UI");
609 
610  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CONFIG_DEBUG, "", "Override config", rmDiagName);
611  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CLOSE_ON_RELEASE_OPEN, "", "Close on open", rmDiagName);
612  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_PERFORM_ON_CLOSE, "", "Perform on close", rmDiagName);
613  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CLOSE_ON_PERFORM, "", "Close on perform", rmDiagName);
614  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_DESELECT_IN_CENTER, "", "Delect in center", rmDiagName);
615  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_USE_LARGE_SIZE, "", "Large size", rmDiagName);
616 
617  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CUSTOM_SIZE_ENABLE, "", "Override size", rmDiagName);
618  DiagMenu.RegisterRange(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CUSTOM_SIZE, "", "Sustom size", rmDiagName, "100, 1000, 100, 1");
619 
620  DiagMenu.RegisterBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_ENTRY_COUNT_ENABLE, "", "Entries setup", rmDiagName);
621  DiagMenu.RegisterRange(SCR_DebugMenuID.DEBUGUI_RADIALMENU_ENTRY_COUNT, "", "Entries", rmDiagName, "2, 32, 2, 1");
622  }
623 
624  //------------------------------------------------------------------------------------------------
625  protected void DebugCleanup()
626  {
627  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CONFIG_DEBUG);
628  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CLOSE_ON_RELEASE_OPEN);
629  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_PERFORM_ON_CLOSE);
630  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CLOSE_ON_PERFORM);
631  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_DESELECT_IN_CENTER);
632  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_USE_LARGE_SIZE);
633  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CUSTOM_SIZE_ENABLE);
634  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CUSTOM_SIZE);
635  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_ENTRY_COUNT_ENABLE);
636  DiagMenu.Unregister(SCR_DebugMenuID.DEBUGUI_RADIALMENU_ENTRY_COUNT);
637  }
638 
639  //------------------------------------------------------------------------------------------------
641  protected void DebugSetupControllerInputs(out notnull SCR_RadialMenuControllerInputs inputs)
642  {
643  // Check if debug is enabled
644  if (!DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CONFIG_DEBUG))
645  return;
646 
647  inputs.m_bCloseOnReleaseOpen = DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CLOSE_ON_RELEASE_OPEN);
648  inputs.m_bPerformOnClose = DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_PERFORM_ON_CLOSE);
649  inputs.m_bCloseOnPerform = DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CLOSE_ON_PERFORM);
650  inputs.m_bDeselectInCenter = DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_DESELECT_IN_CENTER);
651  inputs.m_bUseLargeSize = DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_USE_LARGE_SIZE);
652 
653  if (DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CUSTOM_SIZE_ENABLE))
654  inputs.m_fCustomSize = DiagMenu.GetRangeValue(SCR_DebugMenuID.DEBUGUI_RADIALMENU_CUSTOM_SIZE);
655  else
656  inputs.m_fCustomSize = -1;
657  }
658 
659  //------------------------------------------------------------------------------------------------
660  protected void DebugFillWithEntries()
661  {
662  if (!DiagMenu.GetBool(SCR_DebugMenuID.DEBUGUI_RADIALMENU_ENTRY_COUNT_ENABLE))
663  return;
664 
665  m_aEntries.Clear();
666 
667  int count = DiagMenu.GetRangeValue(SCR_DebugMenuID.DEBUGUI_RADIALMENU_ENTRY_COUNT);
668  for (int i = 0; i < count; i++)
669  {
671  entry.SetName("Debug entry " + i);
672  entry.Enable(true);
673 
674  AddEntry(entry);
675  }
676  }
677 
678  #endif
679 
680  //------------------------------------------------------------------------------------------------
681  void SCR_RadialMenu()
682  {
683  #ifdef RADMENU_DEBUG
684  DebugSetupDiagMenu();
685  #endif
686  }
687 
688  //------------------------------------------------------------------------------------------------
689  void ~SCR_RadialMenu()
690  {
691  #ifdef RADMENU_DEBUG
692  DebugCleanup();
693  #endif
694  }
695 
696  //------------------------------------------------------------------------------------------------
697  void SetPreventSelectionContext(bool enable)
698  {
699  m_bPreventSelectionContext = enable;
700  }
701 
702  //------------------------------------------------------------------------------------------------
703  bool GetPreventSelectionContext()
704  {
705  return m_bPreventSelectionContext;
706  }
707 
708  //------------------------------------------------------------------------------------------------
709  bool GetUseQuickActions()
710  {
711  if (!m_RadialControllerInputs)
712  return false;
713 
714  return m_RadialControllerInputs.m_bUseQuickActions;
715  }
716 };
717 
718 //------------------------------------------------------------------------------------------------
722 [BaseContainerProps(configRoot: true)]
724 {
725  protected const string RADIAL_LEFT_CONTEXT = "RadialMenuLeftContext";
726  protected const string RADIAL_RIGHT_CONTEXT = "RadialMenuRightContext";
727  protected const string DEFAULT_RADIAL_LEFT_X = "RadialX";
728  protected const string DEFAULT_RADIAL_LEFT_Y = "RadialY";
729  protected const string DEFAULT_RADIAL_RIGHT_X = "RadialX2";
730  protected const string DEFAULT_RADIAL_RIGHT_Y = "RadialY2";
731 
732  [Attribute("100", desc: "How far from center needs to be to select entry. Use when controller m_bDeselectInCenter = true")]
733  float m_fMouseSelectionTreshold;
734 
735  [Attribute("250", UIWidgets.Slider, desc: "Delay in ms for how long should context be active - prevents character rotation and other unwanted input", "0 1000 1")]
736  int m_iContextDeactivationTime;
737 
738  [Attribute("1", desc: "Allow dynamically setup inner mouse selection treshold base on menu size from SIZE_LARGE")]
739  bool m_bDynamicMouseTreshold;
740 
741  [Attribute("0.5", "0 1 0.01", desc: "How far from center needs to be to select entry. Use when controller m_bDeselectInCenter = true")]
742  float m_fGamepadSelectionTreshhold;
743 
744  [Attribute("500", UIWidgets.Slider, desc: "How long in milisecond should selection stay when moving to center.", "0 1000 1")]
745  int m_iGamepadDeselectionDelay;
746 
747  protected bool m_bUseRightStick;
748 
749  //------------------------------------------------------------------------------------------------
752  override void Init()
753  {
754  SetUseRightStick(m_bUseRightStick);
755  }
756 
757  //------------------------------------------------------------------------------------------------
758  void GetRadialXYInput(out float x, out float y)
759  {
760  InputManager inputManager = GetGame().GetInputManager();
761  if (m_bUseRightStick)
762  {
763  inputManager.ActivateContext(RADIAL_RIGHT_CONTEXT, m_iGamepadDeselectionDelay);
764  x = inputManager.GetActionValue(DEFAULT_RADIAL_RIGHT_X);
765  y = inputManager.GetActionValue(DEFAULT_RADIAL_RIGHT_Y);
766  }
767  else
768  {
769  inputManager.ActivateContext(RADIAL_LEFT_CONTEXT, m_iGamepadDeselectionDelay);
770  x = inputManager.GetActionValue(DEFAULT_RADIAL_LEFT_X);
771  y = inputManager.GetActionValue(DEFAULT_RADIAL_LEFT_Y);
772  }
773  }
774 
775  //------------------------------------------------------------------------------------------------
776  void SetUseRightStick(bool use)
777  {
778  m_bUseRightStick = use;
779  }
780 };
781 
782 //------------------------------------------------------------------------------------------------
783 [BaseContainerProps(configRoot: true)]
785 {
786  const static int MAX_HINTS = 9;
787 
788  [Attribute("1", desc: "True = right thumbstick used for menu navigation, otherwise use left thumbstick")]
789  bool m_bUseRightStick;
790 
791  [Attribute("1", desc: "Select no entry if selection is pointing into menu center")]
792  bool m_bDeselectInCenter;
793 
794  [Attribute("1", desc: "Use large or small size for radial menu visuals")]
795  bool m_bUseLargeSize;
796 
797  [Attribute("-1", UIWidgets.Slider, desc: "Base radial menu size. Will ignore m_bUseLargeSize and use custom size instead of presets if it's more than 0", "-1 1000 1")]
798  float m_fCustomSize;
799 
800  [Attribute("0", UIWidgets.Slider, desc: "Display the crosshair in the center of the layout")]
801  bool m_bShowCrosshair;
802 
803  [Attribute("1", UIWidgets.Slider, desc: "Display inner circle backround if true")]
804  bool m_bShowInnerBackground;
805 
806  [Attribute("0", UIWidgets.Slider, desc: "Allows to use entries with quick 1-10 input")]
807  bool m_bUseQuickActions;
808 }
ChimeraMenuBase
Constant variables used in various menus.
Definition: ChimeraMenuBase.c:70
SCR_HUDManagerComponent
Definition: SCR_HUDManagerComponent.c:23
PlaySound
SCR_ParticleContactComponentClass ScriptComponentClass PlaySound(IEntity owner, SCR_ParticleContactComponentClass prefabData, Contact contact)
Definition: SCR_ParticleContactComponent.c:38
SCR_SelectionMenuCategoryEntry
Definition: SCR_SelectionMenuCategory.c:6
GetCallqueue
ScriptCallQueue GetCallqueue()
Definition: game.c:225
SCR_RadialMenuDisplay
Definition: SCR_RadialMenuDisplay.c:7
GetGame
ArmaReforgerScripted GetGame()
Definition: game.c:1424
desc
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
Definition: SCR_RespawnBriefingComponent.c:17
SCR_SelectionMenu
Definition: SCR_SelectionMenu.c:6
SCR_RadialMenuInputs
Definition: SCR_RadialMenu.c:723
m_aEntries
protected ref array< ref SCR_TextsTaskManagerEntry > m_aEntries
Definition: SCR_TextsTaskManagerComponent.c:3
Attribute
typedef Attribute
Post-process effect of scripted camera.
distance
float distance
Definition: SCR_DestructibleTreeV2.c:29
SCR_SelectionMenuInputs
Definition: SCR_SelectionMenu.c:771
SCR_MenuHelper
Definition: SCR_MenuHelper.c:15
AddEntry
Widget AddEntry(ResourceName entryPath, SCR_WorkshopItemActionDownload action)
Add new widget in category based based on category type.
Definition: SCR_DownloadManagerListComponent.c:69
GetInputManager
protected InputManager GetInputManager()
Definition: SCR_BaseManualCameraComponent.c:65
SCR_SelectionMenuControllerInputs
Definition: SCR_SelectionMenu.c:794
SCR_SelectionMenuDisplay
Definition: SCR_SelectionMenuDisplay.c:7
SCR_SelectionMenuEntry
Definition: SCR_SelectionMenuEntry.c:7
SCR_DebugMenuID
SCR_DebugMenuID
This enum contains all IDs for DiagMenu entries added in script.
Definition: DebugMenuID.c:3
SCR_RadialMenu
Definition: SCR_RadialMenu.c:8
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
SCR_RadialMenuControllerInputs
Definition: SCR_RadialMenu.c:784