riversong code showcase
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
public class RuntimeTooltipUIController : UIControllerSystem<RuntimeTooltipUIView>, IDisposable
|
||||
{
|
||||
private VisualElement _currentSource;
|
||||
|
||||
public RuntimeTooltipUIController(IServiceLocator serviceLocator) : base(serviceLocator)
|
||||
{
|
||||
}
|
||||
|
||||
protected override RuntimeTooltipUIView View => UIRoot.GetView<RuntimeTooltipUIView>();
|
||||
|
||||
public override async UniTask InitializeAsync()
|
||||
{
|
||||
await base.InitializeAsync();
|
||||
|
||||
View.Show(false);
|
||||
|
||||
UIRoot.RootVisualElement.RegisterCallback<PointerEnterEvent>(OnPointerEnter, TrickleDown.TrickleDown);
|
||||
UIRoot.RootVisualElement.RegisterCallback<PointerLeaveEvent>(OnPointerLeave, TrickleDown.TrickleDown);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
UIRoot.RootVisualElement.UnregisterCallback<PointerEnterEvent>(OnPointerEnter, TrickleDown.TrickleDown);
|
||||
UIRoot.RootVisualElement.UnregisterCallback<PointerLeaveEvent>(OnPointerLeave, TrickleDown.TrickleDown);
|
||||
}
|
||||
|
||||
private void OnPointerEnter(PointerEnterEvent evt)
|
||||
{
|
||||
if (evt.target is not VisualElement element) return;
|
||||
|
||||
var source = element.GetFirstAncestorOrSelf(static candidate => !string.IsNullOrEmpty(candidate.tooltip));
|
||||
if (source == null || ReferenceEquals(source, _currentSource)) return;
|
||||
|
||||
_currentSource = source;
|
||||
|
||||
View.Show(true);
|
||||
View.AnchorTooltip(source, source.tooltip);
|
||||
}
|
||||
|
||||
private void OnPointerLeave(PointerLeaveEvent evt)
|
||||
{
|
||||
if (!ReferenceEquals(evt.target, _currentSource)) return;
|
||||
|
||||
_currentSource = null;
|
||||
View.Show(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace DanieleMarotta.RiversongCodeShowcase
|
||||
{
|
||||
[UIView("runtime-tooltip")]
|
||||
public class RuntimeTooltipUIView : UIView
|
||||
{
|
||||
private Label _content;
|
||||
|
||||
public override UniTask InitializeAsync(UIService uiService, VisualElement rootElement)
|
||||
{
|
||||
base.InitializeAsync(uiService, rootElement);
|
||||
|
||||
_content = rootElement.Q<Label>(className: "runtime-tooltip__content");
|
||||
|
||||
RootElement.SetPickingModeRecursive(PickingMode.Ignore);
|
||||
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
|
||||
public void AnchorTooltip(VisualElement anchor, string text)
|
||||
{
|
||||
_content.text = text;
|
||||
|
||||
var placeAbove = anchor.worldBound.center.y > Screen.height * 0.2f;
|
||||
|
||||
RootElement.EnableInClassList("runtime-tooltip--above", placeAbove);
|
||||
RootElement.EnableInClassList("runtime-tooltip--below", !placeAbove);
|
||||
|
||||
RootElement.schedule.Execute(() => ClampToScreen(anchor.worldBound, placeAbove));
|
||||
}
|
||||
|
||||
private void ClampToScreen(Rect anchor, bool placeAbove)
|
||||
{
|
||||
var width = RootElement.resolvedStyle.width;
|
||||
var height = RootElement.resolvedStyle.height;
|
||||
if (width <= 0 || height <= 0) return;
|
||||
|
||||
var left = Mathf.Clamp(anchor.center.x - width / 2, 0, Mathf.Max(0, Screen.width - width));
|
||||
|
||||
const float verticalGap = 32;
|
||||
var top = placeAbove ? anchor.yMin - verticalGap - height : anchor.yMax + verticalGap;
|
||||
top = Mathf.Clamp(top, 0, Mathf.Max(0, Screen.height - height));
|
||||
|
||||
RootElement.style.left = left + width / 2;
|
||||
RootElement.style.top = placeAbove ? top + height : top;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user