17     [
Attribute(
desc:
"Class must be SCR_ScriptedWidgetTooltipPresets", 
params:
"conf class=SCR_ScriptedWidgetTooltipPresets")]
 
   18     protected ResourceName m_sPresetsConfig;
 
   21     protected string m_sPresetTag;
 
   23     protected ref SCR_ScriptedWidgetTooltipPreset m_Preset;
 
   24     protected WorkspaceWidget m_wWorkspace;
 
   25     protected Widget m_wTooltipProxy;
 
   26     protected Widget m_wHoverWidget;
 
   28     protected float m_fTargetPosition[2];
 
   31     protected RichTextWidget m_wMessage;
 
   34     protected const string WIDGET_MESSAGE = 
"Message";
 
   36     private const float DISTANCE_THRESHOLD = 0.001;
 
   39     protected static Widget m_wTooltipContent;
 
   40     protected static WidgetAnimationPosition m_PositionAnimation;
 
   53     override static Widget CreateTooltipWidget()
 
   55         return GetGame().GetWorkspace().CreateWidgets(
"{39445BE1E35BEA33}UI/layouts/Menus/Tooltips/TooltipBaseProxy.layout");
 
   59     override void Show(WorkspaceWidget pWorkspace, Widget pToolTipWidget, 
float desiredPosX, 
float desiredPosY)
 
   61         ForceHideCurrentTooltip();
 
   63         m_CurrentTooltip = 
this;
 
   67         BaseContainer container = rsc.GetResource().ToBaseContainer();
 
   87         if(m_OnTooltipShowInit)
 
   91         FrameSlot.SetAnchorMin(pToolTipWidget, 0, 0);
 
   92         FrameSlot.SetAnchorMax(pToolTipWidget, 0, 0);
 
   95         FrameSlot.SetSizeToContent(pToolTipWidget, 
m_Preset.m_bSizeToContent);
 
   97         Widget debugBorder = pToolTipWidget.FindAnyWidget(
"DebugBorder");
 
  101             showDebug = 
m_Preset.m_bShowDebugBorder;
 
  105             debugBorder.SetVisible(showDebug);
 
  112         InitContentPosition();
 
  115         UpdatePosition(
true, 
false, 
true);
 
  134             m_OnTooltipShow.Invoke(
this, m_wTooltipContent, m_wHoverWidget, m_Preset, 
m_Preset.m_sTag);
 
  137         GetGame().GetCallqueue().CallLater(Update, 
m_Preset.m_fUpdateFrequency, 
true);
 
  140         super.Show(pWorkspace, pToolTipWidget, desiredPosX, desiredPosY);
 
  144     override void Hide(WorkspaceWidget pWorkspace, Widget pToolTipWidget)
 
  148         super.Hide(pWorkspace, pToolTipWidget);
 
  153     protected void Update()
 
  168     protected void OnHide()
 
  173             m_OnTooltipHide.Invoke(
this, m_wTooltipProxy, m_wHoverWidget, m_Preset, 
m_Preset.m_sTag);
 
  189     protected void Clear()
 
  191         GetGame().GetCallqueue().Remove(Update);
 
  197         if (m_PositionAnimation)
 
  198             m_PositionAnimation.Stop();
 
  200         if (m_wTooltipContent)
 
  206     protected void InitContentPosition()
 
  208         SCR_TooltipPositionPreset positionPreset = 
m_Preset.GetInputPositionSettings();
 
  212         float targetX = positionPreset.GetContentAlignmentHorizontal();
 
  213         float targetY = positionPreset.GetContentAlignmentVertical();
 
  217         FrameSlot.SetAnchorMax(m_wTooltipContent, targetX, targetY);
 
  221     protected void InitContents()
 
  224         SetMessage(
m_Preset.m_sMessageText);
 
  229     void UpdatePosition(
bool followTarget = 
true, 
bool animate = 
true, 
bool force = 
false)
 
  232         bool rendered = tooltipSize[0] != 0 && tooltipSize[1] != 0;
 
  234         vector goalPosition, goalAlignment, goalAlpha;
 
  242         if (followTarget || !rendered)
 
  247         vector tooltipPos = FrameSlot.GetPos(m_wTooltipProxy);
 
  250         FrameSlot.SetAlignment(m_wTooltipProxy, goalAlignment[0], goalAlignment[1]);
 
  254             FrameSlot.SetPos(m_wTooltipProxy, goalPosition[0], goalPosition[1]);
 
  256         else if (vector.DistanceSq(Vector(tooltipPos[0], tooltipPos[1], 0), Vector(m_fTargetPosition[0], m_fTargetPosition[1], 0)) >= DISTANCE_THRESHOLD)
 
  257             m_PositionAnimation = AnimateWidget.Position(m_wTooltipProxy, m_fTargetPosition, 
m_Preset.m_fInterpolationSpeed);
 
  261         if (!m_wTooltipContent)
 
  264         FrameSlot.SetAlignment(m_wTooltipContent, goalAlignment[0], goalAlignment[1]);
 
  265         FrameSlot.SetAnchorMin(m_wTooltipContent, goalAlignment[0], goalAlignment[1]);
 
  266         FrameSlot.SetAnchorMax(m_wTooltipContent, goalAlignment[0], goalAlignment[1]);
 
  270     bool SetMessage(
string message)
 
  282         return SetMessage(GetDefaultMessage());
 
  286     bool SetMessageColor(Color color)
 
  288         if (!m_wMessage || !color)
 
  305     string GetDefaultMessage()
 
  333     Widget GetContentWidget()
 
  339     Widget GetTooltipWidget()
 
  345     Widget GetHoverWidget()
 
  352     Widget GetContentWrapper()
 
  358     static bool ForceHideCurrentTooltip()
 
  360         if (!m_CurrentTooltip)
 
  363         m_CurrentTooltip.ForceHidden();
 
  370         return m_CurrentTooltip;
 
  376         if (!m_OnTooltipShowInit)
 
  379         return m_OnTooltipShowInit;
 
  385         if (!m_OnTooltipShow)
 
  388         return m_OnTooltipShow;
 
  394         if (!m_OnTooltipHide)
 
  397         return m_OnTooltipHide;
 
  406 class SCR_ScriptedWidgetTooltipPreset
 
  408     [
Attribute(
"", UIWidgets.Auto, 
"Custom tag, used for finding this preset at run time.")]
 
  411     [
Attribute(
"{197FC671D07413E9}UI/layouts/Menus/Tooltips/Tooltip_SimpleMessage.layout", UIWidgets.ResourceNamePicker, 
".layout for the content of the Tooltip", 
params: 
"layout")]
 
  412     ResourceName m_sContentLayout;
 
  415     ref SCR_TooltipPositionPreset m_MousePositionSettings;
 
  418     ref SCR_TooltipPositionPreset m_GamepadPositionSettings;
 
  420     [
Attribute(
"1", UIWidgets.CheckBox, 
"Defines if the tooltip should animate to follow mouse cursor or remain at initial position")]
 
  424     vector m_vFixedPosition;
 
  426     [
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 comntent layout, as long as it fits inside the proxy and it's not set to stretch")]
 
  427     bool m_bSizeToContent;
 
  429     [
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")]
 
  433     string m_sMessageText;
 
  439     float m_fInterpolationSpeed;
 
  442     float m_fUpdateFrequency;
 
  445     bool m_bShowDebugBorder;
 
  447     string m_sDefaultMessage;
 
  452         m_sDefaultMessage = m_sMessageText;
 
  458     bool GetGoalPosition(Widget tooltipContent, Widget hoverWidget, out vector goalPosition, out vector goalAlignment, out vector goalAlpha, 
bool force = 
false)
 
  460         vector tooltipSize = GetTooltipSize(tooltipContent);
 
  461         SCR_TooltipPositionPreset positionSettings = GetInputPositionSettings();
 
  463         if (positionSettings.m_eAnchor != SCR_ETooltipAnchor.CURSOR && !force)
 
  466         positionSettings.GetGoalPosition(tooltipSize, hoverWidget, m_vFixedPosition, goalPosition, goalAlignment, goalAlpha);
 
  471     vector GetTooltipSize(Widget tooltip)
 
  474         WorkspaceWidget workspace = 
GetGame().GetWorkspace();
 
  477         float xTooltipSize = workspace.DPIScale(m_vSize[0]);
 
  478         float yTooltipSize = workspace.DPIScale(m_vSize[1]);
 
  479         if (m_bSizeToContent && tooltip)
 
  480             tooltip.GetScreenSize(xTooltipSize, yTooltipSize);
 
  482         size[0] = xTooltipSize;
 
  483         size[1] = yTooltipSize;
 
  488     SCR_TooltipPositionPreset GetInputPositionSettings()
 
  490         bool isUsingMouse = 
GetGame().GetInputManager().GetLastUsedInputDevice() == EInputDeviceType.MOUSE;
 
  492             return m_MousePositionSettings;
 
  494             return m_GamepadPositionSettings;
 
  505     ref array<ref SCR_ScriptedWidgetTooltipPreset> m_aPresets;
 
  509     SCR_ScriptedWidgetTooltipPreset FindPreset(
string tag)
 
  511         foreach (SCR_ScriptedWidgetTooltipPreset preset : 
m_aPresets)
 
  513             if (preset.m_sTag == tag)
 
  525 class SCR_TooltipPositionPreset
 
  527     [
Attribute(
"0", UIWidgets.ComboBox, 
"Where to position the Tooltip", 
"", ParamEnumArray.FromEnum(SCR_ETooltipAnchor))]
 
  528     SCR_ETooltipAnchor m_eAnchor;
 
  533     [
Attribute(
"0", UIWidgets.ComboBox, 
"Vertical Alignment", 
"", ParamEnumArray.FromEnum(SCR_ETooltipAlignmentVertical))]
 
  536     [
Attribute(
"8 20 0", 
desc: 
"Tooltip offset from cursor or desired position")]
 
  539     [
Attribute(
"0", UIWidgets.ComboBox, 
"How to deal with overflow", 
"", ParamEnumArray.FromEnum(SCR_ETooltipOverflowHandling))]
 
  540     SCR_ETooltipOverflowHandling m_eOverflowHandling;
 
  542     const float ALIGNMENT_CENTER = 0.5;
 
  543     const float ALIGNMENT_LEFT_TOP = 0;
 
  544     const float ALIGNMENT_RIGHT_DOWN = 1;
 
  548     void GetGoalPosition(vector tooltipSize, Widget hoverWidget, vector absolutePosition, out vector goalPosition, out vector goalAlignment, out vector goalAlpha)
 
  550         float xHover, yHover;
 
  551         float xHoverSize, yHoverSize;
 
  556             hoverWidget.GetScreenPos(xHover, yHover);
 
  559             hoverWidget.GetScreenSize(xHoverSize, yHoverSize);
 
  563         int xCursor, yCursor;
 
  564         WidgetManager.GetMousePos(xCursor, yCursor);
 
  567         WorkspaceWidget workspace = 
GetGame().GetWorkspace();
 
  568         float xWorkspaceSize, yWorkspaceSize;
 
  569         workspace.GetScreenSize(xWorkspaceSize, yWorkspaceSize);
 
  576         float xAlignment, yAlignment;
 
  577         float xTargetSize, yTargetSize;
 
  581             case SCR_ETooltipAnchor.CURSOR:
 
  586             case SCR_ETooltipAnchor.HOVERED_WIDGET:
 
  589                 xTargetSize = xHoverSize;
 
  590                 yTargetSize = yHoverSize;
 
  593             case SCR_ETooltipAnchor.ABSOLUTE:
 
  594                 xGoal = absolutePosition[0];
 
  595                 yGoal = absolutePosition[1];
 
  599         CalculateGoalPosition(
m_eHorizontalAlignment, xTargetSize, tooltipSize[0], xWorkspaceSize, xGoal, xOffset, xAlignment);
 
  600         CalculateGoalPosition(
m_eVerticalAlignment, yTargetSize, tooltipSize[1], yWorkspaceSize, yGoal, yOffset, yAlignment);
 
  603         if (xWorkspaceSize == 0)
 
  606         if (yWorkspaceSize == 0)
 
  609         goalAlpha[0] = (xGoal + workspace.DPIScale(xOffset)) / xWorkspaceSize;
 
  610         goalAlpha[1] = (yGoal + workspace.DPIScale(yOffset)) / yWorkspaceSize;
 
  613         goalPosition[0] = workspace.DPIUnscale(xGoal + workspace.DPIScale(xOffset));
 
  614         goalPosition[1] = workspace.DPIUnscale(yGoal + workspace.DPIScale(yOffset));
 
  617         goalAlignment[0] = xAlignment;
 
  618         goalAlignment[1] = yAlignment;
 
  622     protected void CalculateGoalPosition(
int alignmentCase, 
float targetSize, 
float tooltipSize, 
float maxAreaSize, inout 
float desiredPos, inout 
float offset, inout 
float alignment)
 
  624         switch (alignmentCase)
 
  630                 desiredPos = desiredPos + (targetSize * ALIGNMENT_CENTER);
 
  631                 alignment = ALIGNMENT_CENTER;
 
  635                 desiredPos = desiredPos + targetSize;
 
  636                 alignment = ALIGNMENT_RIGHT_DOWN;
 
  640                 alignment = ALIGNMENT_RIGHT_DOWN;
 
  644                 desiredPos = desiredPos + targetSize;
 
  648         CheckOverflow(tooltipSize, maxAreaSize, desiredPos, offset, alignment);
 
  654     bool CheckOverflow(
float tooltipSize, 
float maxAreaSize, inout 
float desiredPos, inout 
float offset, inout 
float alignment)
 
  656         SCR_ETooltipOverflowType overflowType;
 
  659         if (alignment < ALIGNMENT_CENTER && desiredPos + offset + tooltipSize > maxAreaSize)
 
  661             overflowType = SCR_ETooltipOverflowType.RIGHT;
 
  665         else if (alignment > ALIGNMENT_CENTER && desiredPos + offset - tooltipSize < 0)
 
  667             overflowType = SCR_ETooltipOverflowType.LEFT;
 
  673             if (desiredPos + offset + (tooltipSize * ALIGNMENT_CENTER) > maxAreaSize)
 
  674                 overflowType = SCR_ETooltipOverflowType.CENTER_RIGHT;
 
  677             else if (desiredPos + offset - (tooltipSize * ALIGNMENT_CENTER) < 0)
 
  678                 overflowType = SCR_ETooltipOverflowType.CENTER_LEFT;
 
  681         if (overflowType == SCR_ETooltipOverflowType.NONE)
 
  686         if (m_eOverflowHandling == SCR_ETooltipOverflowHandling.INVERT)
 
  688             if (alignment == ALIGNMENT_CENTER)
 
  689                 desiredPos = Math.Clamp(desiredPos, offset + (tooltipSize * ALIGNMENT_CENTER), maxAreaSize - (offset + (tooltipSize * ALIGNMENT_CENTER)));
 
  691             alignment = 1 - alignment;
 
  697             switch (overflowType)
 
  699                 case SCR_ETooltipOverflowType.LEFT:         desiredPos = tooltipSize + offset;                                      
break;
 
  700                 case SCR_ETooltipOverflowType.RIGHT:        desiredPos = maxAreaSize - tooltipSize - offset;                        
break;
 
  701                 case SCR_ETooltipOverflowType.CENTER_LEFT:  desiredPos = (tooltipSize * ALIGNMENT_CENTER) + offset;                 
break;
 
  702                 case SCR_ETooltipOverflowType.CENTER_RIGHT: desiredPos = maxAreaSize - (tooltipSize * ALIGNMENT_CENTER) - offset;   
break;
 
  710     float GetContentAlignmentHorizontal()
 
  721         return ALIGNMENT_LEFT_TOP;
 
  725     float GetContentAlignmentVertical()
 
  729             case SCR_ETooltipAlignmentVertical.TOP:     
return ALIGNMENT_LEFT_TOP;
 
  730             case SCR_ETooltipAlignmentVertical.ABOVE:   
return ALIGNMENT_RIGHT_DOWN;
 
  731             case SCR_ETooltipAlignmentVertical.BELOW:   
return ALIGNMENT_LEFT_TOP;
 
  732             case SCR_ETooltipAlignmentVertical.BOTTOM:  
return ALIGNMENT_RIGHT_DOWN;
 
  733             case SCR_ETooltipAlignmentVertical.CENTER:  
return ALIGNMENT_CENTER;
 
  736         return ALIGNMENT_LEFT_TOP;
 
  817 enum SCR_ETooltipAlignmentVertical
 
  827 enum SCR_ETooltipAnchor
 
  835 enum SCR_ETooltipOverflowHandling
 
  842 enum SCR_ETooltipOverflowType