Arma Reforger Explorer 1.7.0.54
Arma Reforger Code Explorer by Zeroy - Thanks to MisterOutofTime
Loading...
Searching...
No Matches
SCR_ScriptedWidgetTooltip.c
Go to the documentation of this file.
1/*
2Parent class of Scripted Widgets Tooltips.
3These tooltips are set on widgets themselves, in the Behaviour section.
4In order to keep things orderly with the huge amount of tooltips required, and for ease of access, they can be defined in .conf files.
5Create a .conf file from SCR_ScriptedWidgetTooltipPresets to define a group of tooltips, add members, and give each preset a unique tag.
6In the Behaviour section of the widget you want to have a tooltip, pick this class, reference the .conf file and use the appropriate tag.
7Don't forget to set Ignore Cursor to false or the tooltip won't trigger!
8*/
12typedef ScriptInvokerBase<ScriptInvokerTooltipMethod> ScriptInvokerTooltip;
13
14//------------------------------------------------------------------------------------------------
16{
17 [Attribute(desc:"Class must be SCR_ScriptedWidgetTooltipPresets", params:"conf class=SCR_ScriptedWidgetTooltipPresets")]
19
20 [Attribute(desc:"tag to find the preset in the .conf")]
21 protected string m_sPresetTag;
22
23 protected ref SCR_ScriptedWidgetTooltipPreset m_Preset;
27
28 protected float m_fTargetPosition[2];
29
30 // Const
31 private const float DISTANCE_THRESHOLD = 0.001;
32 private const int DELAYED_INIT_WAIT_FRAMES = 2;
34 // Static
37
38 //---- REFACTOR NOTE START: This code will need to be refactored as current implementation is not conforming to the standards ----
39 // Static invokers on tooltips means a lot of different components in a menu will need to listen and react to these events even though none of them but one at a time will care about the triggered tooltip. Different instances of the same component might fight to update the tooltip with their data (like in a list or menu tabs). There is also the fact that these tooltips are set on the widgets in the layouts, meaning they can get lost in huge hierarchies.
40
41 // Invokers
42 // Reliance on static invokers is a bit of a bandaid solution but there is no other way for other scripts to access the tooltip class
43 // If possible, only bind on hover/focus gained and make sure to unbind on lost.
44 protected static ref ScriptInvokerTooltip m_OnTooltipShowInit; // Called before creating the content widget
45 protected static ref ScriptInvokerTooltip m_OnTooltipShow; // Called after creating the content widget
46 protected static ref ScriptInvokerTooltip m_OnTooltipHide; // Called after removing the content widget
47
48 //---- REFACTOR NOTE END ----
49
50 protected const string DEBUG_BORDER_NAME = "DebugBorder";
51
53 //------------------------------------------------------------------------------------------------
55 override static Widget CreateTooltipWidget()
56 {
57 return GetGame().GetWorkspace().CreateWidgets("{39445BE1E35BEA33}UI/layouts/Menus/Tooltips/TooltipBaseProxy.layout");
58 }
59
60 //------------------------------------------------------------------------------------------------
61 override void Show(WorkspaceWidget pWorkspace, Widget pToolTipWidget, float desiredPosX, float desiredPosY)
62 {
64
65 m_CurrentTooltip = this;
66
67 // Create presets
68 Resource rsc = BaseContainerTools.LoadContainer(m_sPresetsConfig);
69 BaseContainer container = rsc.GetResource().ToBaseContainer();
70 SCR_ScriptedWidgetTooltipPresets presets = SCR_ScriptedWidgetTooltipPresets.Cast(BaseContainerTools.CreateInstanceFromContainer(container));
71
72 if (!presets)
73 {
75 return;
76 }
77
78 // Find preset
79 m_Preset = presets.FindPreset(m_sPresetTag);
80
81 if (!m_Preset)
82 {
84 return;
85 }
86
87 // Setup
88 m_wWorkspace = pWorkspace;
89 m_wTooltipProxy = pToolTipWidget;
90
91 if (GetGame().GetInputManager().GetLastUsedInputDevice() == EInputDeviceType.MOUSE)
92 m_wHoverWidget = WidgetManager.GetWidgetUnderCursor();
93 else
94 m_wHoverWidget = pWorkspace.GetFocusedWidget();
95
97 m_OnTooltipShowInit.Invoke(this);
98
99 // Proxy initialization
100 FrameSlot.SetAnchorMin(pToolTipWidget, 0, 0);
101 FrameSlot.SetAnchorMax(pToolTipWidget, 0, 0);
102
103 FrameSlot.SetSize(pToolTipWidget, m_Preset.m_vSize[0], m_Preset.m_vSize[1]);
104 FrameSlot.SetSizeToContent(pToolTipWidget, m_Preset.m_bSizeToContent);
105
106 // TODO: debug visualization of paddings vs tooltip whole area
107 Widget debugBorder = pToolTipWidget.FindAnyWidget(DEBUG_BORDER_NAME);
108
109 #ifdef WORKBENCH
110 bool showDebug = m_Preset.m_bShowDebugBorder;
111 #else
112 const bool showDebug = false;
113 #endif
114
115 if (debugBorder)
116 debugBorder.SetVisible(showDebug);
117
118 // Content creation
119 if (!m_Preset.m_Content)
120 {
121 Print(string.Format("SCR_ScriptedWidgetTooltip - Show() - Missing content class! Tag: %1 | Conf: %2", GetTag(), m_sPresetsConfig), LogLevel.ERROR);
122 return;
123 }
124
125 if (!m_Preset.m_Content.Init(m_wWorkspace, GetContentWrapper()))
126 {
127 ForceHidden();
128 return;
129 }
130
131 // Determine and cache the correct content position inside the proxy
133
134 // Wait for the new screen to have a screen presence, as on controller the tooltip gets triggered as soon as Enfusions flags the widget as focused, even if the hierarchy has not finished initializing yet
135 DelayedPositionInit(DELAYED_INIT_WAIT_FRAMES);
136
137 // Fade in
138 if (m_Preset.m_fFadeInSpeed > 0)
139 {
140 m_wTooltipProxy.SetOpacity(0);
141 AnimateWidget.Opacity(m_wTooltipProxy, 1, m_Preset.m_fFadeInSpeed);
142 }
143
144 //! Forced hiding events
148
149 // Invoker
150 if (m_OnTooltipShow)
151 m_OnTooltipShow.Invoke(this);
152
153 // Tick - Used to update the tooltip's position
154 GetGame().GetCallqueue().CallLater(Update, m_Preset.m_fUpdateFrequency, true);
155
156 // Super
157 super.Show(pWorkspace, pToolTipWidget, desiredPosX, desiredPosY);
158 }
159
160 //------------------------------------------------------------------------------------------------
161 override void Hide(WorkspaceWidget pWorkspace, Widget pToolTipWidget)
162 {
163 OnHide();
164
165 super.Hide(pWorkspace, pToolTipWidget);
166 }
167
168 //! ---- PROTECTED ----
169 //------------------------------------------------------------------------------------------------
170 protected void DelayedPositionInit(int totalFrames)
171 {
172 if (totalFrames <= 0)
173 {
174 // Cache desired position and instantly place the tooltip there
175 UpdatePosition(true, false, true);
176
177 return;
178 }
179
180 totalFrames--;
181 GetGame().GetCallqueue().Call(DelayedPositionInit, totalFrames);
182 }
184 //------------------------------------------------------------------------------------------------
185 protected void Update()
186 {
187 if (!m_wWorkspace || !m_wTooltipProxy || !m_wHoverWidget || !m_Preset || !m_Preset.GetContentRoot())
188 {
189 Clear();
190 return;
191 }
193 UpdatePosition(m_Preset.m_bFollowCursor && GetGame().GetInputManager().GetLastUsedInputDevice() == EInputDeviceType.MOUSE);
194
195 if (!m_wTooltipProxy.IsVisible())
196 OnHide();
197 }
199 //------------------------------------------------------------------------------------------------
200 protected void OnHide()
201 {
202 Clear();
203
204 if (m_OnTooltipHide)
205 m_OnTooltipHide.Invoke(this);
206 }
207
208 //------------------------------------------------------------------------------------------------
209 protected void OnMenuChange(ChimeraMenuBase menu)
210 {
211 ForceHidden();
212 }
213
214 //------------------------------------------------------------------------------------------------
215 protected void OnTabChange(SCR_TabViewComponent tabView, Widget widget)
216 {
217 ForceHidden();
218 }
219
220 //------------------------------------------------------------------------------------------------
221 protected void Clear()
222 {
223 GetGame().GetCallqueue().Remove(Update);
224
228
230 m_PositionAnimation.Stop();
231
232 if (m_Preset.m_Content)
233 m_Preset.m_Content.Clear();
234 }
235
236 // Align the content to the correct side of the proxy
237 //------------------------------------------------------------------------------------------------
238 protected void InitContentPosition()
239 {
240 SCR_TooltipPositionPreset positionPreset = m_Preset.GetInputPositionSettings();
241 if (!positionPreset)
242 return;
243
244 Widget contentRoot = m_Preset.GetContentRoot();
245 if (!contentRoot)
246 return;
247
248 float targetX = positionPreset.GetContentAlignmentHorizontal();
249 float targetY = positionPreset.GetContentAlignmentVertical();
250
251 FrameSlot.SetAlignment(contentRoot, targetX, targetY);
252 FrameSlot.SetAnchorMin(contentRoot, targetX, targetY);
253 FrameSlot.SetAnchorMax(contentRoot, targetX, targetY);
254 }
255
257 //------------------------------------------------------------------------------------------------
258 void UpdatePosition(bool followTarget = true, bool animate = true, bool force = false)
259 {
260 vector tooltipSize = m_Preset.GetTooltipSize(m_wTooltipProxy);
261 bool rendered = tooltipSize[0] != 0 && tooltipSize[1] != 0;
262
263 vector goalPosition, goalAlignment, goalAlpha;
264
265 bool shouldUpdate = m_Preset.GetGoalPosition(m_Preset.GetContentRoot(), m_wHoverWidget, goalPosition, goalAlignment, goalAlpha, (!rendered || force));
266 if (!shouldUpdate)
267 return;
268
269 // When the content layout is created, its size is 0.
270 // If the proxy is SizeToContent and the tooltip is stationary, we need to slide it in position as soon as we have access to its actual size.
271 if (followTarget || !rendered)
272 m_fTargetPosition = {goalPosition[0], goalPosition[1]};
273
274 // -- Proxy --
275 // Move the Tooltip
276 vector tooltipPos = FrameSlot.GetPos(m_wTooltipProxy);
277
278 // Alignment
279 FrameSlot.SetAlignment(m_wTooltipProxy, goalAlignment[0], goalAlignment[1]);
280
281 // Position
282 if (!animate)
283 FrameSlot.SetPos(m_wTooltipProxy, goalPosition[0], goalPosition[1]);
284
285 else if (vector.DistanceSq(Vector(tooltipPos[0], tooltipPos[1], 0), Vector(m_fTargetPosition[0], m_fTargetPosition[1], 0)) >= DISTANCE_THRESHOLD)
286 m_PositionAnimation = AnimateWidget.Position(m_wTooltipProxy, m_fTargetPosition, m_Preset.m_fInterpolationSpeed);
287
288 // -- Content --
289 // Move the content to the correct edge of the proxy
290 Widget contentRoot = m_Preset.GetContentRoot();
291 if (!contentRoot)
292 return;
293
294 FrameSlot.SetAlignment(contentRoot, goalAlignment[0], goalAlignment[1]);
295 FrameSlot.SetAnchorMin(contentRoot, goalAlignment[0], goalAlignment[1]);
296 FrameSlot.SetAnchorMax(contentRoot, goalAlignment[0], goalAlignment[1]);
298
299 //------------------------------------------------------------------------------------------------
301 {
302 if (!m_wTooltipProxy)
303 return;
304
305 m_wTooltipProxy.SetVisible(false);
306 OnHide();
307 }
308
309//---- REFACTOR NOTE START: This code will need to be refactored as current implementation is not conforming to the standards ----
310// Tooltips rely on hardcoded string tags, far from ideal. This method is also somewhat weird, as it performs extra checks based on the optional parameters. It could probably be written better. it is necessary because we must use static invokers to notify classes that a tooltip has appeared: ideally, Widgets should have build in events for their tooltips, that ScriptedWidetComponent would expose to script
311
312 //------------------------------------------------------------------------------------------------
313 // Check if the tooltip has the right parameters. The most important one is the tag, since it differentiates tooltips
314 bool IsValid(string tag, Widget hoverWidget = null, ResourceName presets = string.Empty)
315 {
317 return false;
318
319 bool valid = tag == GetTag();
320
321 if (hoverWidget)
322 valid = valid && hoverWidget == m_wHoverWidget;
323
324 if (!presets.IsEmpty())
325 valid = valid && presets == m_sPresetsConfig;
326
327 return valid;
329
330//---- REFACTOR NOTE END ----
331
332 //------------------------------------------------------------------------------------------------
333 string GetTag()
334 {
335 return m_Preset.m_sTag;
336 }
337
338 //------------------------------------------------------------------------------------------------
340 {
341 return m_Preset.GetContent();
342 }
343
344 //------------------------------------------------------------------------------------------------
346 {
347 return m_Preset.GetContentRoot();
349
350 //------------------------------------------------------------------------------------------------
351 // Note: on the frame of creation, the proxy will still be invisible, causing this to return false
353 {
354 return m_wTooltipProxy && m_Preset && m_wTooltipProxy.IsVisible();
355 }
356
357 //------------------------------------------------------------------------------------------------
359 {
360 return m_wHoverWidget;
361 }
362
363 //------------------------------------------------------------------------------------------------
366 {
367 return m_wTooltipProxy;
368 }
369
370 //------------------------------------------------------------------------------------------------
372 {
373 if (!m_CurrentTooltip)
374 return false;
375
376 m_CurrentTooltip.ForceHidden();
377 return true;
378 }
379
380 //------------------------------------------------------------------------------------------------
385
386 //------------------------------------------------------------------------------------------------
394
395 //------------------------------------------------------------------------------------------------
403
404 //------------------------------------------------------------------------------------------------
412}
413
414//------------------------------------------------------------------------------------------------
415// --- Configuration classes ---
416//------------------------------------------------------------------------------------------------
419class SCR_ScriptedWidgetTooltipPreset
420{
421 [Attribute("", UIWidgets.Auto, "Custom tag, used for finding this preset at run time.")]
422 string m_sTag;
423
424 [Attribute(desc: "Content handling class")]
426
427 [Attribute()]
428 protected ref SCR_TooltipPositionPreset m_MousePositionSettings;
429
430 [Attribute()]
431 protected ref SCR_TooltipPositionPreset m_GamepadPositionSettings;
432
433 [Attribute("1", UIWidgets.CheckBox, "Defines if the tooltip should animate to follow mouse cursor or remain at initial position")]
434 bool m_bFollowCursor;
435
436//---- REFACTOR NOTE START: This code will need to be refactored as current implementation is not conforming to the standards ----
437// Given that we have objects for position settings, this should probably be in SCR_TooltipPositionPreset and allow different fixed positions based on device
438
439 [Attribute(desc: "Fixed Absolute screen position")]
440 protected vector m_vFixedPosition;
441
442//---- REFACTOR NOTE END ----
443
444 [Attribute("0", UIWidgets.CheckBox, desc: "Should the proxy adapt to the content: the proxy is used to check for overflowing and contains the actual Content layout. Giving it a fixed size will prevent slide in effect for overflowing tooltips. This will NOT influence the look of the content layout, as long as it fits inside the proxy and it's not set to stretch")]
445 bool m_bSizeToContent;
446
447//---- REFACTOR NOTE START: This code will need to be refactored as current implementation is not conforming to the standards ----
448// This is needed for overflowing tooltips, as it allows to create a safe zone and avoid the tooltip flickering in on the frame it's actual size is initialized. It feels like a hacky workaround, there's probably a better way to tackle the issue (like starting with 0 opacity and fading in the next frame, perhaps?)
449
450 [Attribute(desc: "Fixed proxy layout size. The proxy is used to check for overflowing and contains the actual Content layout. This will NOT influence the look of the comntent layout, as long as it fits inside the proxy and it's not set to stretch")]
451 vector m_vSize;
452
453//---- REFACTOR NOTE END ----
454
455 [Attribute(UIConstants.FADE_RATE_FAST.ToString(), desc: "FadeIn speed. Set to 0 to skip the animation")]
456 float m_fFadeInSpeed;
457
458 [Attribute(UIConstants.FADE_RATE_SUPER_FAST.ToString(), desc: "Movement speed")]
459 float m_fInterpolationSpeed;
460
461 [Attribute("40", desc: "Queued update delay in ms")]
462 float m_fUpdateFrequency;
463
464 [Attribute("0", UIWidgets.CheckBox)]
465 bool m_bShowDebugBorder;
466
467 //------------------------------------------------------------------------------------------------
469 {
470 return m_Content;
471 }
472
473 //------------------------------------------------------------------------------------------------
475 {
476 if (!m_Content)
477 return null;
478
479 return m_Content.GetContentRoot();
480 }
481
482 //------------------------------------------------------------------------------------------------
485 bool GetGoalPosition(Widget tooltipContent, Widget hoverWidget, out vector goalPosition, out vector goalAlignment, out vector goalAlpha, bool force = false)
486 {
487 vector tooltipSize = GetTooltipSize(tooltipContent);
488 SCR_TooltipPositionPreset positionSettings = GetInputPositionSettings();
489
490 if (!positionSettings || (positionSettings.m_eAnchor != SCR_ETooltipAnchor.CURSOR && !force))
491 return false;
492
493 positionSettings.GetGoalPosition(tooltipSize, hoverWidget, m_vFixedPosition, goalPosition, goalAlignment, goalAlpha);
494 return true;
495 }
496
497 //------------------------------------------------------------------------------------------------
498 vector GetTooltipSize(Widget tooltip)
499 {
500 vector size;
501 WorkspaceWidget workspace = GetGame().GetWorkspace();
502
503 // Tooltip size - SCALED
504 float xTooltipSize = workspace.DPIScale(m_vSize[0]);
505 float yTooltipSize = workspace.DPIScale(m_vSize[1]);
506 if (m_bSizeToContent && tooltip)
507 tooltip.GetScreenSize(xTooltipSize, yTooltipSize);
508
509 size[0] = xTooltipSize;
510 size[1] = yTooltipSize;
511 return size;
512 }
513
514 //------------------------------------------------------------------------------------------------
515 SCR_TooltipPositionPreset GetInputPositionSettings()
516 {
517 bool isUsingMouse = GetGame().GetInputManager().GetLastUsedInputDevice() == EInputDeviceType.MOUSE;
518 if (isUsingMouse)
519 return m_MousePositionSettings;
520 else
521 return m_GamepadPositionSettings;
522 }
523}
524
525//------------------------------------------------------------------------------------------------
527[BaseContainerProps(configRoot : true)]
529{
530 [Attribute()]
531 ref array<ref SCR_ScriptedWidgetTooltipPreset> m_aPresets;
532
533 //------------------------------------------------------------------------------------------------
535 SCR_ScriptedWidgetTooltipPreset FindPreset(string tag)
536 {
537 foreach (SCR_ScriptedWidgetTooltipPreset preset : m_aPresets)
538 {
539 if (preset.m_sTag == tag)
540 return preset;
541 }
542
543 return null;
544 }
545}
546
547//------------------------------------------------------------------------------------------------
548[BaseContainerProps(configRoot : true)]
549class SCR_TooltipPositionPreset
551 [Attribute("0", UIWidgets.ComboBox, "Where to position the Tooltip", "", ParamEnumArray.FromEnum(SCR_ETooltipAnchor))]
552 SCR_ETooltipAnchor m_eAnchor;
553
554 [Attribute("0", UIWidgets.ComboBox, "Horizontal Alignment", "", ParamEnumArray.FromEnum(SCR_ETooltipAlignmentHorizontal))]
555 SCR_ETooltipAlignmentHorizontal m_eHorizontalAlignment;
556
557 [Attribute("0", UIWidgets.ComboBox, "Vertical Alignment", "", ParamEnumArray.FromEnum(SCR_ETooltipAlignmentVertical))]
558 SCR_ETooltipAlignmentVertical m_eVerticalAlignment;
559
560 [Attribute("8 20 0", desc: "Tooltip offset from cursor or desired position")]
562
563 [Attribute("0", UIWidgets.ComboBox, "How to deal with overflow", "", ParamEnumArray.FromEnum(SCR_ETooltipOverflowHandling))]
564 SCR_ETooltipOverflowHandling m_eOverflowHandling;
565
566 const float ALIGNMENT_CENTER = 0.5;
567 const float ALIGNMENT_LEFT_TOP = 0;
568 const float ALIGNMENT_RIGHT_DOWN = 1;
569
570 //------------------------------------------------------------------------------------------------
572 void GetGoalPosition(vector tooltipSize, Widget hoverWidget, vector absolutePosition, out vector goalPosition, out vector goalAlignment, out vector goalAlpha)
573 {
574 float xHover, yHover;
575 float xHoverSize, yHoverSize;
576
577 if (hoverWidget)
578 {
579 // Hover widget position - SCALED
580 hoverWidget.GetScreenPos(xHover, yHover);
581
582 // Hover widget size - SCALED
583 hoverWidget.GetScreenSize(xHoverSize, yHoverSize);
584 }
585
586 // Cursor position - SCALED
587 int xCursor, yCursor;
588 WidgetManager.GetMousePos(xCursor, yCursor);
589
590 // Workspace size - SCALED
591 WorkspaceWidget workspace = GetGame().GetWorkspace();
592 float xWorkspaceSize, yWorkspaceSize;
593 workspace.GetScreenSize(xWorkspaceSize, yWorkspaceSize);
594
595 // Calculations setup
596 float xOffset = m_vOffset[0];
597 float yOffset = m_vOffset[1];
598
599 float xGoal, yGoal;
600 float xAlignment, yAlignment;
601 float xTargetSize, yTargetSize;
602
603 switch (m_eAnchor)
604 {
605 case SCR_ETooltipAnchor.CURSOR:
606 xGoal = xCursor;
607 yGoal = yCursor;
608 break;
609
610 case SCR_ETooltipAnchor.HOVERED_WIDGET:
611 xGoal = xHover;
612 yGoal = yHover;
613 xTargetSize = xHoverSize;
614 yTargetSize = yHoverSize;
615 break;
616
617 case SCR_ETooltipAnchor.ABSOLUTE:
618 xGoal = absolutePosition[0];
619 yGoal = absolutePosition[1];
620 break;
621 }
622
623 CalculateGoalPosition(m_eHorizontalAlignment, xTargetSize, tooltipSize[0], xWorkspaceSize, xGoal, xOffset, xAlignment);
624 CalculateGoalPosition(m_eVerticalAlignment, yTargetSize, tooltipSize[1], yWorkspaceSize, yGoal, yOffset, yAlignment);
625
626 // Set the alpha - SCALED - for anchors related to workspace size, as an alternative to screen position
627 if (xWorkspaceSize == 0)
628 xWorkspaceSize = 1;
629
630 if (yWorkspaceSize == 0)
631 yWorkspaceSize = 1;
632
633 goalAlpha[0] = (xGoal + workspace.DPIScale(xOffset)) / xWorkspaceSize;
634 goalAlpha[1] = (yGoal + workspace.DPIScale(yOffset)) / yWorkspaceSize;
635
636 // Set the goals - UNSCALED
637 goalPosition[0] = workspace.DPIUnscale(xGoal + workspace.DPIScale(xOffset));
638 goalPosition[1] = workspace.DPIUnscale(yGoal + workspace.DPIScale(yOffset));
639
640 // Set the desired Alignment
641 goalAlignment[0] = xAlignment;
642 goalAlignment[1] = yAlignment;
643 }
644
645 //------------------------------------------------------------------------------------------------
646 protected void CalculateGoalPosition(int alignmentCase, float targetSize, float tooltipSize, float maxAreaSize, inout float desiredPos, inout float offset, inout float alignment)
647 {
648 switch (alignmentCase)
649 {
650 case 0:
651 break;
652
653 case 1:
654 desiredPos = desiredPos + (targetSize * ALIGNMENT_CENTER);
655 alignment = ALIGNMENT_CENTER;
656 break;
657
658 case 2:
659 desiredPos = desiredPos + targetSize;
660 alignment = ALIGNMENT_RIGHT_DOWN;
661 break;
662
663 case 3:
664 alignment = ALIGNMENT_RIGHT_DOWN;
665 break;
666
667 case 4:
668 desiredPos = desiredPos + targetSize;
669 break;
670 }
671
672 CheckOverflow(tooltipSize, maxAreaSize, desiredPos, offset, alignment);
673 }
674
675 //------------------------------------------------------------------------------------------------
678 bool CheckOverflow(float tooltipSize, float maxAreaSize, inout float desiredPos, inout float offset, inout float alignment)
679 {
680 SCR_ETooltipOverflowType overflowType;
681
682 // Extending to the right of the position
683 if (alignment < ALIGNMENT_CENTER && desiredPos + offset + tooltipSize > maxAreaSize)
684 {
685 overflowType = SCR_ETooltipOverflowType.RIGHT;
686 }
687
688 // Extending to the left of the position
689 else if (alignment > ALIGNMENT_CENTER && desiredPos + offset - tooltipSize < 0)
690 {
691 overflowType = SCR_ETooltipOverflowType.LEFT;
692 }
693
694 // Center
695 else
696 {
697 if (desiredPos + offset + (tooltipSize * ALIGNMENT_CENTER) > maxAreaSize)
698 overflowType = SCR_ETooltipOverflowType.CENTER_RIGHT;
699
700 else if (desiredPos + offset - (tooltipSize * ALIGNMENT_CENTER) < 0)
701 overflowType = SCR_ETooltipOverflowType.CENTER_LEFT;
702 }
703
704 if (overflowType == SCR_ETooltipOverflowType.NONE)
705 return false;
706
707 // TODO: "ignore" option for debugging
708 // TODO: there seems to be an issue with overflow calculations on tooltips spawned when mouse is very close to screen edges, causing the tooltip to think it's overflowing while still far from the edge
709 // -- Handle overflow --
710 // Invert
711 if (m_eOverflowHandling == SCR_ETooltipOverflowHandling.INVERT)
712 {
713 if (alignment == ALIGNMENT_CENTER)
714 desiredPos = Math.Clamp(desiredPos, offset + (tooltipSize * ALIGNMENT_CENTER), maxAreaSize - (offset + (tooltipSize * ALIGNMENT_CENTER)));
715
716 alignment = 1 - alignment;
717 }
718
719 // Stop
720 else
721 {
722 switch (overflowType)
723 {
724 case SCR_ETooltipOverflowType.LEFT: desiredPos = tooltipSize + offset; break;
725 case SCR_ETooltipOverflowType.RIGHT: desiredPos = maxAreaSize - tooltipSize - offset; break;
726 case SCR_ETooltipOverflowType.CENTER_LEFT: desiredPos = (tooltipSize * ALIGNMENT_CENTER) + offset; break;
727 case SCR_ETooltipOverflowType.CENTER_RIGHT: desiredPos = maxAreaSize - (tooltipSize * ALIGNMENT_CENTER) - offset; break;
728 }
729 }
730
731 return true;
732 }
733
734 //------------------------------------------------------------------------------------------------
735 float GetContentAlignmentHorizontal()
736 {
737 switch (m_eHorizontalAlignment)
738 {
739 case SCR_ETooltipAlignmentHorizontal.LEFT: return ALIGNMENT_LEFT_TOP;
740 case SCR_ETooltipAlignmentHorizontal.RIGHT: return ALIGNMENT_RIGHT_DOWN;
741 case SCR_ETooltipAlignmentHorizontal.CENTER: return ALIGNMENT_CENTER;
742 case SCR_ETooltipAlignmentHorizontal.SIDE_LEFT: return ALIGNMENT_LEFT_TOP;
743 case SCR_ETooltipAlignmentHorizontal.SIDE_RIGHT: return ALIGNMENT_RIGHT_DOWN;
744 }
745
746 return ALIGNMENT_LEFT_TOP;
747 }
748
749 //------------------------------------------------------------------------------------------------
750 float GetContentAlignmentVertical()
751 {
752 switch (m_eVerticalAlignment)
753 {
754 case SCR_ETooltipAlignmentVertical.TOP: return ALIGNMENT_LEFT_TOP;
755 case SCR_ETooltipAlignmentVertical.ABOVE: return ALIGNMENT_RIGHT_DOWN;
756 case SCR_ETooltipAlignmentVertical.BELOW: return ALIGNMENT_LEFT_TOP;
757 case SCR_ETooltipAlignmentVertical.BOTTOM: return ALIGNMENT_RIGHT_DOWN;
758 case SCR_ETooltipAlignmentVertical.CENTER: return ALIGNMENT_CENTER;
759 }
760
761 return ALIGNMENT_LEFT_TOP;
762 }
763}
764
765//------------------------------------------------------------------------------------------------
766/*
767LEFT:
768 __
769 |__|_____
770 | |
771 |________|
772
773
774CENTER:
775 __
776 __|__|__
777 | |
778 |________|
779
780
781RIGHT:
782 __
783 _____|__|
784 | |
785 |________|
786
787
788SIDE_LEFT:
789 __ ________
790 |__| |
791 |________|
792
793
794SIDE_RIGHT:
795 ________ __
796 | |__|
797 |________|
798*/
807
808//------------------------------------------------------------------------------------------------
809/*
810TOP:
811 ________
812 | |__| |
813 |________|
814
815
816CENTER:
817 ________
818 | __ |
819 |________|
820
821
822BOTTOM:
823 ________
824 | __ |
825 |__|__|__|
826
827
828ABOVE:
829 __
830 __|__|__
831 | |
832 |________|
833
834
835BELOW:
836 ________
837 | |
838 |________|
839 |__|
840*/
841enum SCR_ETooltipAlignmentVertical
842{
844 CENTER,
847 BELOW
848}
849
850//------------------------------------------------------------------------------------------------
851enum SCR_ETooltipAnchor
852{
855 ABSOLUTE
856}
857
858//------------------------------------------------------------------------------------------------
859enum SCR_ETooltipOverflowHandling
860{
862 STOP
863}
864
865//------------------------------------------------------------------------------------------------
866enum SCR_ETooltipOverflowType
867{
869 LEFT,
870 RIGHT,
872 CENTER_RIGHT
873}
ArmaReforgerScripted GetGame()
Definition game.c:1398
int size
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
InputManager GetInputManager()
void UpdatePosition()
Update light position.
vector m_vOffset
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
enum SCR_ETooltipAlignmentHorizontal ABOVE
func ScriptInvokerTooltipMethod
Widget GetContentRoot()
enum SCR_ETooltipAlignmentHorizontal INVERT
void OnTabChange(SCR_TabViewComponent tabView, Widget widget)
ref SCR_ScriptedWidgetTooltipPreset m_Preset
void OnMenuChange(ChimeraMenuBase menu)
SCR_ScriptedWidgetTooltip ScriptedWidgetTooltip SCR_BaseContainerCustomTitleField("m_sTag")
ResourceName m_sPresetsConfig
SCR_ETooltipAlignmentHorizontal
Widget m_wTooltipProxy
ScriptInvokerBase< ScriptInvokerTooltipMethod > ScriptInvokerTooltip
Widget m_wHoverWidget
SCR_ScriptedWidgetTooltipContentBase GetContent()
enum SCR_ETooltipAlignmentHorizontal HOVERED_WIDGET
enum SCR_ETooltipAlignmentHorizontal CENTER_LEFT
float m_fTargetPosition[2]
static WidgetAnimationOpacity Opacity(Widget widget, float targetValue, float speed, bool toggleVisibility=false)
static WidgetAnimationPosition Position(Widget widget, float position[2], float speed)
Constant variables used in various menus.
Object holding reference to resource. In destructor release the resource.
Definition Resource.c:25
static ScriptInvokerTabView GetOnTabChange()
static ScriptInvokerMenu GetOnMenuClose()
static ScriptInvokerMenu GetOnMenuOpen()
override void Hide(WorkspaceWidget pWorkspace, Widget pToolTipWidget)
static ScriptInvokerTooltip GetOnTooltipHide()
static override Widget CreateTooltipWidget()
-— OVERRIDES -—
static ref ScriptInvokerTooltip m_OnTooltipShowInit
static ScriptInvokerTooltip GetOnTooltipShowInit()
override void Show(WorkspaceWidget pWorkspace, Widget pToolTipWidget, float desiredPosX, float desiredPosY)
bool IsValid(string tag, Widget hoverWidget=null, ResourceName presets=string.Empty)
static ref ScriptInvokerTooltip m_OnTooltipShow
static ref ScriptInvokerTooltip m_OnTooltipHide
static ScriptInvokerTooltip GetOnTooltipShow()
void UpdatePosition(bool followTarget=true, bool animate=true, bool force=false)
-— PUBLIC -—
void OnTabChange(SCR_TabViewComponent tabView, Widget widget)
ref SCR_ScriptedWidgetTooltipPreset m_Preset
void DelayedPositionInit(int totalFrames)
-— PROTECTED -—
void OnMenuChange(ChimeraMenuBase menu)
static SCR_ScriptedWidgetTooltip GetCurrentTooltip()
static WidgetAnimationPosition m_PositionAnimation
SCR_ScriptedWidgetTooltipContentBase GetContent()
Widget GetContentWrapper()
Override to change in which widget the content layout gets placed.
static SCR_ScriptedWidgetTooltip m_CurrentTooltip
Class for a .conf file with multiple Tooltip presets.
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
@ NONE
When Shape is created and not initialized yet.
Definition ShapeType.c:15
@ CENTER
Text will be centered.
SCR_FieldOfViewSettings Attribute
@ LEFT
navigation
@ RIGHT
proto native vector Vector(float x, float y, float z)
@ STOP
class WidgetType BOTTOM
class WidgetType TOP