Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ActionMenuInteractionDisplay.c
Go to the documentation of this file.
2{
3 [Attribute("{C80DEB58AA948E59}UI/layouts/HUD/InteractionSystem/ActionMenuElement.layout", UIWidgets.ResourceNamePicker, params: "layout")]
4 ResourceName m_sElementLayout;
5
6 [Attribute("{1D3B10902C8F8FEA}UI/layouts/HUD/InteractionSystem/ActionMenuSnackBar.layout", UIWidgets.ResourceNamePicker, params: "layout")]
7 ResourceName m_sSnackBarLayout;
8
9 [Attribute(UIColors.GetColorAttribute(GUIColors.ENABLED), UIWidgets.ColorPicker)]
10 protected ref Color m_EnabledColor;
11
12 [Attribute(UIColors.GetColorAttribute(GUIColors.DISABLED), UIWidgets.ColorPicker)]
13 protected ref Color m_DisabledColor;
14
15 [Attribute(UIColors.GetColorAttribute(GUIColors.DEFAULT_GLOW), UIWidgets.ColorPicker)]
17
18 [Attribute(UIColors.GetColorAttribute(UIColors.CONTRAST_COLOR), UIWidgets.ColorPicker)]
19 protected ref Color m_PerformingColor;
20
21 [Attribute("0", UIWidgets.CheckBox, "Fixed placement")]
22 protected bool m_bFixedPlacement;
23
24 [Attribute("25.0", UIWidgets.Slider, params: "0 100 0.1")]
25 protected float m_fScrollAnimationSpeed;
26
27 [Attribute("0.1", UIWidgets.Slider, params: "0 10 0.05")]
28 protected float m_fAutoExpandTime;
29
30 [Attribute("0.00", UIWidgets.Slider, "Action list element fade-in expand delay (in seconds).", params: "0 1 0.001")]
31 protected float m_fFadeInOffset;
32
33 [Attribute("0.6", UIWidgets.Slider, params: "0.3 10 0.2")]
35
36 // Non-selected element atributes
37 [Attribute("40", UIWidgets.Slider, params: "0.05 50 0.05")]
38 protected float m_fHeightElement;
39
40 // Transition speed in seconds between the icon and the button
41 [Attribute("0.3", UIWidgets.Slider, params: "0.3 10 0.2")]
42 protected float m_fButtonFadeInSpeed;
43
44 [Attribute("", desc: "each ID must be unique")]
45 protected ref array<ref SCR_NearbyContextColorsComponentInteract> m_aNearbyWidgetColors;
46
49
50 protected ref array<ref SCR_ActionMenuElementComponent> m_aActionMenuElements = {};
51 protected ref array<ref SCR_ActionMenuElementComponent> m_aActiveActionMenuElements = {};
52
54
57
58 // Data containing info from interaction handler
60
61 protected bool m_bIsSingleEntryMenu;
62
63 protected int m_iCurrentScroll;
65
66 protected float m_fExpandTimer; // Timer for auto-expand feature
67 protected float m_fExpandedTimer; // Time elapsed from menu expand, used for sequential fade in of elements
68 protected float m_fSnackBarAppearTimer; // Time for Snack bar to appear
69 protected float m_fSnackBarOpacityTimer; // Time for Snack bar to change opacity
70
72
74
75 protected bool m_bForceUpdate;
76 protected bool m_bForceResetScroll
77 protected bool m_bProgressReachedMax;
78 protected bool m_bIsActionEnabled;
79
80 protected int m_iContextCount;
82
85
86 protected float m_fTotalHeightElements;
87
88 protected const float ANCHOR_X = 0.48;
89 protected const float ANCHOR_Y = 0.94;
90
91 protected const float SAFEZONE_PADDING = 15.0;
92
93 protected const float WIDGET_DEFAULT_OPACITY = 1.0;
94 protected const float WIDGET_HIDDEN_OPACITY = 0.75;
95
96 protected const vector SCREEN_POS_MIN = "0.15 0.15 0";
97 protected const vector SCREEN_POS_MAX = "0.85 0.85 0";
98
99 protected const string SETTING_HINT_ACTION = "m_bShowInteractionHint";
100
101 //------------------------------------------------------------------------------------------------
103 protected void Create()
104 {
105 if (!m_wRoot)
106 {
107 Print("ActionsMenuDisplay is missing root layout!", LogLevel.ERROR);
108 return;
109 }
110
112 {
113 FrameSlot.SetAnchorMin(m_wRoot, 0, 0);
114 FrameSlot.SetAnchorMax(m_wRoot, 0, 0);
115 FrameSlot.SetAlignment(m_wRoot, 0, 0);
116 }
117 else
118 {
119 FrameSlot.SetAnchorMin(m_wRoot, ANCHOR_X, ANCHOR_Y);
120 FrameSlot.SetAnchorMax(m_wRoot, ANCHOR_X, ANCHOR_Y);
121 FrameSlot.SetAlignment(m_wRoot, 0, 0);
122 }
123
124 m_Widgets.Init(m_wRoot);
125
126 if (!m_Widgets.m_wActionMenu)
127 {
128 Debug.Error2("SCR_ActionMenuInteractionDisplay", "m_wActionMenu is NULL");
129 return;
130 }
131
133 {
135 foreach (SCR_NearbyContextColorsComponentInteract colorset : m_aNearbyWidgetColors)
136 {
137 if (!m_mCachedActionColors.Contains(colorset.m_eId))
138 m_mCachedActionColors.Insert(colorset.m_eId, colorset);
139 }
140 }
141
142 m_Widgets.m_wOutlineOverlay.SetVisible(false);
143 m_Widgets.m_wOutlineProgress.SetMaskProgress(0);
144 m_Widgets.m_wOutlineProgressGlow.SetMaskProgress(0);
145 m_Widgets.m_IconOverlayComponent.SetColorsData(m_mCachedActionColors);
146
147 Widget snackBarWidget = m_wRoot.GetWorkspace().CreateWidgets(m_sSnackBarLayout);
148
149 m_SnackBar = SCR_SnackBarController.Cast(snackBarWidget.FindHandler(SCR_SnackBarController));
150
152
153 // Initialize action menu state and data
154 Collapse();
155 }
156
157 //------------------------------------------------------------------------------------------------
158 protected void Destroy()
159 {
161 m_aActionMenuElements.Clear();
162
163 if (m_SnackBar)
164 m_SnackBar.SetVisibility(false);
165 }
166
167 //------------------------------------------------------------------------------------------------
168 protected bool Update(ActionsTuple actionsData, BaseUserAction selectedAction, UserActionContext currentContext, float fTimeSlice)
169 {
170 if (!currentContext && m_PrevContext)
171 {
172 m_PrevAction = null;
173 m_PrevContext = null;
174 return false;
175 }
176
177 // Detect context change (different set of actions)
178 if (currentContext != m_PrevContext)
179 {
180 m_PrevContext = currentContext;
181 m_bForceResetScroll = true;
182 m_bForceUpdate = true;
183
184 Collapse();
185 } // Detect if we changed action
186 else if (m_PrevAction != selectedAction)
187 {
188 m_bForceUpdate = true;
189 }
190
191 int actionsCount = actionsData.param1.Count();
192 if (!actionsData.param1 || actionsCount < 1)
193 return false;
194
195 UpdateAnimateActions(actionsData, selectedAction, currentContext, actionsCount < 2, fTimeSlice);
196
197 if (m_bForceUpdate)
198 return UpdateDisplayActions(actionsData, selectedAction, currentContext, actionsCount);
199
200 return true;
201 }
202
203 //------------------------------------------------------------------------------------------------
204 protected bool UpdateAnimateActions(ActionsTuple actionsData, BaseUserAction selectedAction, UserActionContext currentContext, bool isSingleAction, float fTimeSlice)
205 {
206 if (isSingleAction)
207 {
208 Collapse();
209 }
210 else
211 {
212 RunExpandTimer(fTimeSlice);
213 RunExpandedTimer(fTimeSlice);
214 }
215
216 m_iCurrentScroll = -1;
217 bool scrollingDown;
218 foreach (int i, BaseUserAction currAction : actionsData.param1)
219 {
220 if (currAction == m_PrevAction)
221 scrollingDown = true;
222
223 if (currAction == selectedAction)
224 {
226 break;
227 }
228 }
229
230 // Set and animate scroll
231 SetScroll(m_iCurrentScroll, fTimeSlice);
232 SetPaggingEffect(m_iCurrentScroll, scrollingDown);
233
235 m_fTimeSpentAdditionalInfo += fTimeSlice;
236
238 {
241 {
243
244 if (selectedAction.GetCannotPerformReason() != string.Empty)
245 {
246 m_SnackBar.SetText(selectedAction.GetCannotPerformReason());
247 m_SnackBar.AnimateShow();
248 }
249 }
250 else
251 {
252 bool shouldShowInteractionHint = true;
253
254 //check if the hint is enabled in settings
256 if (hudManager)
257 {
258 BaseContainer interfaceSettings = GetGame().GetGameUserSettings().GetModule(hudManager.GetInterfaceSettingsClass());
259 if (interfaceSettings)
260 interfaceSettings.Get(SETTING_HINT_ACTION, shouldShowInteractionHint);
261 }
262
263 //check setting value here
264 AnimateWidget.Opacity(m_Widgets.m_wIcon, !shouldShowInteractionHint, GetButtonFadeInSpeed(), true);
265 AnimateWidget.Opacity(m_Widgets.m_wIconGlow, !shouldShowInteractionHint, GetButtonFadeInSpeed(), true);
266 AnimateWidget.Opacity(m_Widgets.m_wInputButtonDisplayRoot, shouldShowInteractionHint, GetButtonFadeInSpeed(), true);
267 }
268 }
269
270 return true;
271 }
272
273 //------------------------------------------------------------------------------------------------
274 protected bool UpdateDisplayActions(ActionsTuple actionsData, BaseUserAction selectedAction, UserActionContext currentContext, int actionsCount)
275 {
276 m_bForceUpdate = false;
277
279 if (!playerEntity)
280 return true;
281
282 int iActiveWidgetsCount = m_aActionMenuElements.Count();
283 int iActionsDelta = iActiveWidgetsCount - actionsCount;
284 int iAbsDelta = Math.AbsInt(iActionsDelta);
285
286 // Toggle selection / adjustment widgets
287 bool isInProgress = selectedAction && selectedAction.IsInProgress();
288 m_bIsActionEnabled = selectedAction.CanBePerformed(playerEntity);
289
290 if (!isInProgress || !m_bIsActionEnabled)
291 {
294 AnimateWidget.StopAllAnimations(m_Widgets.m_wInputButtonDisplayRoot);
295
297 m_Widgets.m_wIcon.SetVisible(true);
298 m_Widgets.m_wIcon.SetOpacity(1.0);
299 m_Widgets.m_wIconGlow.SetVisible(true);
300 m_Widgets.m_wIconGlow.SetOpacity(1.0);
301 m_Widgets.m_wInputButtonDisplayRoot.SetVisible(false);
302 m_Widgets.m_wInputButtonDisplayRoot.SetOpacity(0.0);
303 }
304
305 // Add or remove widgets
306 if (iActionsDelta < 0)
307 {
308 // Elements missing
309 SCR_ActionMenuElementComponent actionMenuElement;
310 Widget elementWidget;
311 WorkspaceWidget rootWorkspace = m_wRoot.GetWorkspace();
312 for (int i = 0; i < iAbsDelta; i++)
313 {
314 elementWidget = rootWorkspace.CreateWidgets(m_sElementLayout, m_Widgets.m_wActionMenu);
315 if (!elementWidget)
316 continue;
317
318 LayoutSlot.SetHorizontalAlign(elementWidget, LayoutHorizontalAlign.Left);
319
320 actionMenuElement = SCR_ActionMenuElementComponent.Cast(elementWidget.FindHandler(SCR_ActionMenuElementComponent));
321 if (actionMenuElement)
322 m_aActionMenuElements.Insert(actionMenuElement);
323 }
324 }
325 else if (iActionsDelta > 0)
326 {
327 // Elements over
328 SCR_ActionMenuElementComponent actionMenuElement;
329 for (int i = iActiveWidgetsCount-1; i >= iActiveWidgetsCount-iAbsDelta; i--)
330 {
331 actionMenuElement = m_aActionMenuElements[i];
332 actionMenuElement.SetVisible(false);
333 }
334 }
335
336 if (m_iCurrentScroll < 0)
337 return false;
338
339 // Expand menu if we have more than 1 action
340 if (actionsCount > 1)
341 Expand();
342
344
345 // Set widget data
346 SCR_ActionUIInfo actionInfo;
347 SCR_ActionMenuElementComponent actionMenuElement;
348 foreach (int i, BaseUserAction currAction : actionsData.param1)
349 {
350 actionMenuElement = m_aActionMenuElements[i];
351
352 // Setup menu element
353 actionInfo = SCR_ActionUIInfo.Cast(currAction.GetUIInfo());
354 bool isActionDisabled = currAction.CanBePerformed(playerEntity);
355 bool succeeded = actionMenuElement.Set(currAction, currAction == selectedAction, isActionDisabled, actionInfo);
356
357 if (!actionMenuElement.GetIconComponent().HasColorData())
359
360 actionMenuElement.GetIconComponent().UpdateColors(currAction, true);
361 actionMenuElement.UpdateColors();
362
363 if (!succeeded)
364 {
365 actionMenuElement.SetVisible(false);
366 continue;
367 }
368
369 // Set element visibility based on menu state
370 if ((i == 0 || !m_bIsSingleEntryMenu) && (m_fExpandedTimer >= i * m_fFadeInOffset))
371 {
372 actionMenuElement.SetVisible(true);
373 m_aActiveActionMenuElements.Insert(actionMenuElement);
374 }
375 else
376 actionMenuElement.SetVisible(false);
377 }
378
380 if (m_bForceResetScroll)
381 {
382 m_bForceResetScroll = false;
383 SetScroll(0);
384 }
385
386 // Update visibility of the HOLD icons
387 if (selectedAction.GetActionDuration() != 0)
388 {
389 if (!isInProgress)
390 {
391 m_Widgets.m_wOutlineOverlay.SetVisible(true);
392
393 float duration = Math.AbsFloat(selectedAction.GetActionDuration());
394
395 m_Widgets.m_ButtonOverlayComponent.SetHoldAction(true, duration);
396 }
397 else
398 {
399 m_Widgets.m_ButtonOverlayComponent.ForceSetHoldAction(true);
400 }
401 }
402 else
403 {
404 m_Widgets.m_wOutlineOverlay.SetVisible(false);
405 m_Widgets.m_ButtonOverlayComponent.SetHoldAction(false);
406 }
407
408
409 if (!isInProgress)
410 {
411 actionInfo = SCR_ActionUIInfo.Cast(selectedAction.GetUIInfo());
412 m_Widgets.m_IconOverlayComponent.OnAssigned(actionInfo, selectedAction);
413
414 if (!m_Widgets.m_IconOverlayComponent.HasColorData())
415 m_Widgets.m_IconOverlayComponent.SetColorsData(m_mCachedActionColors);
416
417 m_Widgets.m_IconOverlayComponent.UpdateColors(selectedAction, true);
418 m_Widgets.m_wKeyBG.SetColor(m_Widgets.m_ButtonOverlayComponent.m_ActionDefault);
419 }
420
421 // Setups Snack Bar based on if the selected action can be performed
423 {
424 m_Widgets.m_wOutlineBackground.SetColor(m_EnabledColor);
425 m_Widgets.m_wOutlineBackgroundGlow.SetVisible(true);
426
428
429 if (!isInProgress)
430 {
431 m_Widgets.m_wIcon.SetColor(m_EnabledColor);
432 m_Widgets.m_wIconGlow.SetColor(m_DisabledColorGlow);
433 }
434
435 m_SnackBar.AnimateHide();
436 }
437 else
438 {
439 m_Widgets.m_wOutlineBackground.SetColor(m_DisabledColor);
440 m_Widgets.m_wOutlineBackgroundGlow.SetVisible(false);
441
443
444 m_Widgets.m_wIcon.LoadImageFromSet(0, UIConstants.ICONS_IMAGE_SET, UIConstants.ICON_INTERACT_DISABLED);
445 m_Widgets.m_wIconGlow.LoadImageFromSet(0, UIConstants.ICONS_GLOW_IMAGE_SET, UIConstants.ICON_INTERACT_DISABLED);
446 m_Widgets.m_wIcon.SetColor(m_DisabledColor);
447 m_Widgets.m_wIconGlow.SetColor(m_DisabledColorGlow);
448 }
449
450 m_PrevAction = selectedAction;
451
452 return true;
453 }
454
455 //------------------------------------------------------------------------------------------------
458 protected void SetPaggingEffect(int currentAction, bool scrollingDown)
459 {
460 if (currentAction < 0)
461 return;
462
464 int count = m_aActionMenuElements.Count();
465
466 // If the current action is not the first action, itterate through every action before the current one first.
467 for (int i = currentAction, index; i >= 0; i--)
468 {
469 if (i >= count)
470 continue;
471
472 element = m_aActionMenuElements[i];
473
474 float fVerticalPos = currentAction - i;
475 float timer = m_fCurrentScrollAnimation - currentAction;
476
477 if (scrollingDown)
478 fVerticalPos = fVerticalPos - Math.AbsFloat(timer);
479 else
480 fVerticalPos = fVerticalPos - (1.0 - timer);
481
482 element.SetOpacity(Math.AbsFloat(fVerticalPos));
483 index++;
484 }
485
486 // Itterate through all actions below (after) the current one and apply the correct padding.
487 for (int i = currentAction + 1, index; i < count; i++)
488 {
489 float fVerticalPos = (i - currentAction);
490 float timer = m_fCurrentScrollAnimation - currentAction;
491
492 if (scrollingDown)
493 fVerticalPos = fVerticalPos - Math.AbsFloat(timer);
494 else
495 fVerticalPos = fVerticalPos - (1.0 - timer);
496
497 element = m_aActionMenuElements[i];
498 element.SetOpacity(Math.AbsFloat(fVerticalPos));
499 index++;
500 }
501 }
502
503 //------------------------------------------------------------------------------------------------
504 protected bool GetSafeZone(vector worldPosition, vector screenPosition, vector min01, vector max01, out vector clampedPosition)
505 {
506 WorkspaceWidget workspace = m_Widgets.m_wActionMenu.GetWorkspace();
507 int screenw = workspace.DPIUnscale(workspace.GetWidth());
508 int screenh = workspace.DPIUnscale(workspace.GetHeight());
509
510 vector min = {
511 screenw * min01[0] + SAFEZONE_PADDING,
512 screenh * min01[1] + SAFEZONE_PADDING,
513 0.0
514 };
515
516 float menuw, menuh;
517 m_Widgets.m_wActionMenu.GetScreenSize(menuw, menuh);
518 menuw = workspace.DPIUnscale(menuw);
519 menuh = workspace.DPIUnscale(menuh);
520
521 // Maxs are offset by the menu width, so the menu never overflows
522 vector max = {
523 screenw * max01[0] - menuw - SAFEZONE_PADDING,
524 screenh * max01[1] - menuh + SAFEZONE_PADDING,
525 0.0
526 };
527
528 bool clamped = false;
529 clampedPosition = screenPosition;
530
531 // Bold assumption that can be done is that if this display is shown,
532 // the main camera is used for collecting the actions
533 CameraManager cameraManager = GetGame().GetCameraManager();
534 if (cameraManager)
535 {
536 CameraBase currentCamera = cameraManager.CurrentCamera();
537 if (currentCamera)
538 {
539 vector camTM[4];
540 currentCamera.GetWorldCameraTransform(camTM);
541 vector toActionDir = (worldPosition - camTM[3]).Normalized();
542 float d = vector.Dot(toActionDir, camTM[2]);
543 const float threshold = 0.5;
544 const float invThreshold = 1.0 / 0.5;
545 // Action is "behind view"
546 if (d < threshold)
547 {
548 float stickiness = 1.0;
549 // Use this to blend towards "full backwards" smoothly
550 if (d > 0.0)
551 stickiness = Math.Clamp(1.0 - (d * invThreshold), 0.0, 1.0);
552
553 clampedPosition[1] = Math.Lerp(clampedPosition[1], max[1], stickiness);
554 clamped = true;
555 }
556 }
557 }
558
559 for (int i = 0; i < 2; ++i)
560 {
561 if (clampedPosition[i] < min[i])
562 {
563 clampedPosition[i] = min[i];
564 clamped = true;
565 }
566 else if (clampedPosition[i] > max[i])
567 {
568 clampedPosition[i] = max[i];
569 clamped = true;
570 }
571 }
572
573 return clamped;
574 }
575
576 //------------------------------------------------------------------------------------------------
579 protected void SetPosition(vector worldPosition)
580 {
582 {
583 vector vScreenPosition = GetGame().GetWorkspace().ProjWorldToScreen(worldPosition, GetGame().GetWorld());
584 vector vClampedPosition;
585 GetSafeZone(worldPosition, vScreenPosition, SCREEN_POS_MIN, SCREEN_POS_MAX, vClampedPosition);
586
587 FrameSlot.SetPos(m_wRoot, vClampedPosition[0], vClampedPosition[1]);
588
589 // If action menu is drawn over picture in picture, fade out its opacity
590 // so it is not as intrusive and so it promotes the idea of it being "behind" the sights
591 SCR_2DPIPSightsComponent pipSights = ArmaReforgerScripted.GetCurrentPIPSights();
592 bool isPointInPIP = pipSights && pipSights.IsScreenPositionInSights(vClampedPosition);
593
594 float alpha = WIDGET_DEFAULT_OPACITY;
595 if (isPointInPIP)
596 alpha = WIDGET_HIDDEN_OPACITY;
597
598 m_wRoot.SetOpacity(alpha);
599 }
600 }
601
602 //------------------------------------------------------------------------------------------------
606 protected void SetScroll(int currentScroll, float timeSlice = 0)
607 {
608 if (!m_Widgets.m_wActionMenu || currentScroll < 0)
609 return;
610
611 // Reset action list to initial position
612 if (timeSlice == 0)
613 {
615 FrameSlot.SetPosY(m_Widgets.m_wActionMenu, m_fTotalHeightElements);
616
617 return;
618 }
619
620 // Scroll the action list towards the target position (currentScroll)
621 if (Math.AbsFloat(m_fCurrentScrollAnimation - currentScroll) > 0.001)
622 {
623 m_fCurrentScrollAnimation = Math.Lerp(m_fCurrentScrollAnimation, currentScroll, Math.Clamp(m_fScrollAnimationSpeed * timeSlice, 0.0, 1.0));
624
626 FrameSlot.SetPosY(m_Widgets.m_wActionMenu, fVerticalPos);
627 }
628 }
629
630 //------------------------------------------------------------------------------------------------
633 protected void RunExpandTimer(float fTimeSlice)
634 {
636 {
637 m_fExpandTimer = 0.0;
638 return;
639 }
640
641 // Expansion of additional actions
642 m_fExpandTimer += fTimeSlice;
643
645 Expand();
646 }
647
648 //------------------------------------------------------------------------------------------------
651 protected void RunExpandedTimer(float fTimeSlice)
652 {
654 {
655 m_fExpandedTimer = 0.0;
656 return;
657 }
658
659 // Expansion of additional actions
660 m_fExpandedTimer += fTimeSlice;
661 }
662
663 //------------------------------------------------------------------------------------------------
665 protected void Expand()
666 {
667 m_bIsSingleEntryMenu = false;
668 }
669
670 //------------------------------------------------------------------------------------------------
672 protected void Collapse()
673 {
675
676 SetScroll(0);
677 }
678
679 //------------------------------------------------------------------------------------------------
680 protected float GetButtonFadeInSpeed()
681 {
682 return 1 / m_fButtonFadeInSpeed;
683 }
684
685 #ifndef DISABLE_INTERACTIONS
686 //------------------------------------------------------------------------------------------------
688 override void OnActionStart(IEntity pUser, BaseUserAction pPerformedAction)
689 {
690 m_Widgets.m_wOutlineProgress.SetMaskProgress(0);
691 m_Widgets.m_wOutlineProgressGlow.SetMaskProgress(0);
692
693 m_Widgets.m_ButtonOverlayComponent.OnButtonHold(1);
694 }
695
696 //------------------------------------------------------------------------------------------------
698 override void OnActionProgress(IEntity pUser, BaseUserAction pPerformedAction, float fProgress, float fDuration)
699 {
700 //~ Continues action
701 if (fProgress > 0.0 && fDuration > 0.0)
702 {
704 m_Widgets.m_wOutlineProgress.SetMaskProgress(fProgress / fDuration);
705 m_Widgets.m_wOutlineProgressGlow.SetMaskProgress(fProgress / fDuration);
706 m_Widgets.m_wKeyBG.SetColor(m_Widgets.m_ButtonOverlayComponent.m_ActionHovered);
707
708 //~ Hackfix to track continuous actions looping back
709 if (!m_bForceUpdate && m_bProgressReachedMax && fProgress < fDuration)
710 m_bForceUpdate = true;
711
712 m_bProgressReachedMax = fProgress >= fDuration;
713 }
714 }
715
716 //------------------------------------------------------------------------------------------------
718 override void OnActionFinish(IEntity pUser, BaseUserAction pFinishedAction, ActionFinishReason eFinishReason)
719 {
720 m_Widgets.m_wOutlineProgress.SetMaskProgress(0);
721 m_Widgets.m_wOutlineProgressGlow.SetMaskProgress(0);
722 m_Widgets.m_ButtonOverlayComponent.OnButtonHold(0);
723 m_Widgets.m_wKeyBG.SetColor(m_Widgets.m_ButtonOverlayComponent.m_ActionDefault);
724
725 if (eFinishReason == ActionFinishReason.FINISHED)
726 m_bForceUpdate = true;
727 }
728
729 //------------------------------------------------------------------------------------------------
730 override void DisplayUpdate(IEntity owner, float timeSlice)
731 {
732 // Need data to update
733 if (!m_LastData || !m_LastData.pSelectedAction)
734 {
735 if (m_bShown)
736 Show(false, UIConstants.FADE_RATE_FAST);
737
738 return;
739 }
740
741 // Update ui
742 bool succeeded = Update(m_LastData.pActionsData, m_LastData.pSelectedAction, m_LastData.pCurrentContext, timeSlice);
743
744 // Toggle visibility
745 if (!succeeded)
746 {
747 if (m_bShown)
748 Show(false, UIConstants.FADE_RATE_FAST);
749
750 return;
751 }
752
753 if (!m_bShown)
754 Show(true, UIConstants.FADE_RATE_DEFAULT);
755
756 // Update current widget context position
757 UserActionContext lastContext = m_LastData.pCurrentContext;
758 if (lastContext)
759 {
760 vector position = lastContext.GetOrigin(); // Context's world position
761 if (lastContext.ShouldDisplayAtReferencePoint())
762 {
764 position = m_InteractionHandlerComponent.UpdateLastReferencePoint(timeSlice);//GetGame().GetWorld().GetTimestamp()); // Interaction reference point
765 }
767 }
768 }
769
770 //------------------------------------------------------------------------------------------------
771 override void DisplayStartDraw(IEntity owner)
772 {
773 super.DisplayStartDraw(owner);
774 Create();
775
777
778 Show(false, UIConstants.FADE_RATE_FAST);
779 }
780
781 //------------------------------------------------------------------------------------------------
782 override void DisplayStopDraw(IEntity owner)
783 {
784 Destroy();
785 m_LastData = null;
786 }
787
788 //------------------------------------------------------------------------------------------------
790 override void ShowDisplay()
791 {
792 super.ShowDisplay();
793
794 Show(true, UIConstants.FADE_RATE_DEFAULT);
795
796 }
797
798 //------------------------------------------------------------------------------------------------
800 override void HideDisplay()
801 {
802 if (m_SnackBar)
803 m_SnackBar.AnimateHide();
804
805 m_LastData = null;
806 m_PrevAction = null;
807 m_PrevContext = null;
808
809 if (m_Widgets)
810 {
811 m_Widgets.m_wOutlineProgress.SetMaskProgress(0);
812 m_Widgets.m_wOutlineProgressGlow.SetMaskProgress(0);
813 m_Widgets.m_ButtonOverlayComponent.OnButtonHold(0);
814 m_Widgets.m_wKeyBG.SetColor(m_Widgets.m_ButtonOverlayComponent.m_ActionDefault);
815 }
816
817 Show(false, UIConstants.FADE_RATE_FAST);
818
819 super.HideDisplay();
820 }
821
822 //------------------------------------------------------------------------------------------------
825 {
827
829 }
830
831 //------------------------------------------------------------------------------------------------
834 {
835 if (!data || !data.pActionsData)
836 return;
837
838 bool isEmpty;
839 int count = data.pActionsData.param1.Count();
840 if (m_iContextCount != count)
841 {
842 m_iContextCount = count;
844 m_bForceResetScroll = true;
845 isEmpty = true;
846 }
847 else if (count > 0 && data.pActionsData.param1.IsIndexValid(m_iCurrentScroll))
848 {
849 //~ Hackfix: if the player sprint, the action is disabled
851 if (playerEntity && data.pActionsData.param1[m_iCurrentScroll])
852 {
853 bool canPerfom = data.pActionsData.param1[m_iCurrentScroll].CanBePerformed(playerEntity);
854 if (m_bIsActionEnabled != canPerfom)
855 m_bForceUpdate = true;
856 }
857 }
858
859 //~ Hackfix: We compare the old action names and try to find anything different
860 foreach(int i, BaseUserAction currAction: data.pActionsData.param1)
861 {
862 string actionName = currAction.GetActionName();
863 if (!isEmpty && actionName == m_aCurrentContextNames[i])
864 continue;
865
866 m_bForceUpdate = true;
867 if (!isEmpty)
868 m_aCurrentContextNames.InsertAt(actionName, i);
869 else
870 m_aCurrentContextNames.Insert(actionName);
871 }
872 }
873
874 //------------------------------------------------------------------------------------------------
877 {
878 m_bForceUpdate = true;
879 }
880
881 //------------------------------------------------------------------------------------------------
882 // destructor
887 #endif
888}
ArmaReforgerScripted GetGame()
Definition game.c:1398
ActionFinishReason
Reason for why an action ended. Used in SCR_BaseInteractionDisplay and derived classes.
vector position
SCR_DestructionSynchronizationComponentClass ScriptComponentClass int index
Get all prefabs that have the spawner data
Widget m_wRoot
bool m_bShown
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
static WidgetAnimationOpacity Opacity(Widget widget, float targetValue, float speed, bool toggleVisibility=false)
static void StopAllAnimations(Widget w)
proto external bool IsInProgress()
Returns true while continuous or timed action is being used.
proto external float GetActionDuration()
Returns the duration of this action in seconds.
proto external string GetActionName()
proto external bool CanBePerformed(IEntity user)
Can this action be performed by the user?
string GetCannotPerformReason()
proto external UIInfo GetUIInfo()
Returns the UIInfo set for this user action or null if none.
Definition Color.c:13
Definition Debug.c:13
proto external Managed FindComponent(typename typeName)
Definition Math.c:13
SCR_NearbyContextWidgetComponentInteract GetIconComponent()
bool Set(notnull BaseUserAction userAction, bool isSelected, bool isAvailable, SCR_ActionUIInfo actionUIInfo)
void Create()
Creates and initializes root widget to be slotted with actions.
bool Update(ActionsTuple actionsData, BaseUserAction selectedAction, UserActionContext currentContext, float fTimeSlice)
ref array< ref SCR_ActionMenuElementComponent > m_aActiveActionMenuElements
InteractionHandlerComponent m_InteractionHandlerComponent
override void OnActionProgress(IEntity pUser, BaseUserAction pPerformedAction, float fProgress, float fDuration)
Called when action is being performed.
void SetScroll(int currentScroll, float timeSlice=0)
ref array< ref SCR_ActionMenuElementComponent > m_aActionMenuElements
override void OnActionStart(IEntity pUser, BaseUserAction pPerformedAction)
Called when action starts being performed.
bool UpdateDisplayActions(ActionsTuple actionsData, BaseUserAction selectedAction, UserActionContext currentContext, int actionsCount)
void SetPaggingEffect(int currentAction, bool scrollingDown)
override void DisplayUpdate(IEntity owner, float timeSlice)
ref array< ref SCR_NearbyContextColorsComponentInteract > m_aNearbyWidgetColors
override void HideDisplay()
Called when display was open and is supposed to hide. Called after last ShowActionsDisplay call.
override void SetDisplayData(ActionDisplayData data)
Data provided by the interaction handler.
ref map< SCR_ENearbyInteractionContextColors, ref SCR_NearbyContextColorsComponentInteract > m_mCachedActionColors
Holds all the different cached id with the enum as key.
void ForceUpdateUI()
Allows for external functions to request a UI update.
bool UpdateAnimateActions(ActionsTuple actionsData, BaseUserAction selectedAction, UserActionContext currentContext, bool isSingleAction, float fTimeSlice)
override void ShowDisplay()
Called when display was hidden and is supposed to be shown. Called before first ShowActionsDisplay ca...
bool GetSafeZone(vector worldPosition, vector screenPosition, vector min01, vector max01, out vector clampedPosition)
override void OnActionFinish(IEntity pUser, BaseUserAction pFinishedAction, ActionFinishReason eFinishReason)
Called when an action is finished.
void CompareNewDateWithOld(ActionDisplayData data)
Hackfix: We are trying to find clues if we need to update the UI based on the acton data.
Base class for displaying interactions in the UI.
static SCR_HUDManagerComponent GetHUDManager()
void SetColorsData(map< SCR_ENearbyInteractionContextColors, ref SCR_NearbyContextColorsComponentInteract > cachedActionColors)
void UpdateColors(UserActionContext ctx, SCR_ENearbyInteractionContextColors nearbyColorState=UIConstants.NEARBY_INTERACTION_DEFAULT_STATE)
static IEntity GetLocalControlledEntity()
Definition Types.c:486
override void Show()
Definition gameLib.c:262
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
Definition LogLevel.c:14
SCR_FieldOfViewSettings Attribute
array< string > TStringArray
Definition Types.c:385
LayoutHorizontalAlign