forked from Shardstone/trail-into-darkness
added documentation, fixed some bugs
This commit is contained in:
@@ -5,6 +5,10 @@ using UnityEngine.InputSystem;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Jovian.PopupSystem.UI {
|
||||
/// <summary>
|
||||
/// MonoBehaviour reference holder for a popup view. Manages the grow-only element cache,
|
||||
/// screen positioning, and visibility. One instance per registered <see cref="PopupCategory"/>.
|
||||
/// </summary>
|
||||
public class PopupReference : MonoBehaviour {
|
||||
[SerializeField] RectTransform content;
|
||||
[SerializeField] CanvasGroup canvasGroup;
|
||||
@@ -52,6 +56,7 @@ namespace Jovian.PopupSystem.UI {
|
||||
public RectTransform Content => content;
|
||||
public bool IsVisible => isVisible;
|
||||
|
||||
/// <summary>Constrains the popup's horizontal size to the given maximum width in pixels.</summary>
|
||||
public void SetMaxWidth(float maxPopupWidth) {
|
||||
maxWidth = maxPopupWidth;
|
||||
if(maxWidth > 0f) {
|
||||
@@ -62,6 +67,7 @@ namespace Jovian.PopupSystem.UI {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Shows or hides the popup GameObject. Resets alpha to 0 when hiding.</summary>
|
||||
public void SetVisible(bool visible) {
|
||||
isVisible = visible;
|
||||
gameObject.SetActive(visible);
|
||||
@@ -70,6 +76,7 @@ namespace Jovian.PopupSystem.UI {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Deactivates all cached content elements and marks layout as dirty.</summary>
|
||||
public void ClearContent() {
|
||||
DeactivateRange(headerCache, ref headerIndex);
|
||||
DeactivateRange(textCache, ref textIndex);
|
||||
@@ -91,14 +98,17 @@ namespace Jovian.PopupSystem.UI {
|
||||
|
||||
// --- Element access (grow-only) ---
|
||||
|
||||
/// <summary>Returns the next available header element from the cache, or creates one.</summary>
|
||||
public TMP_Text GetHeader() {
|
||||
return GetOrCreate(headerCache, headerPrefab, ref headerIndex);
|
||||
}
|
||||
|
||||
/// <summary>Returns the next available text element from the cache, or creates one.</summary>
|
||||
public TMP_Text GetText() {
|
||||
return GetOrCreate(textCache, textPrefab, ref textIndex);
|
||||
}
|
||||
|
||||
/// <summary>Returns the next available stat row (label + value pair) from the cache, or creates one.</summary>
|
||||
public (TMP_Text label, TMP_Text value) GetStat() {
|
||||
if(statIndex < statCache.Count) {
|
||||
var existing = statCache[statIndex];
|
||||
@@ -118,10 +128,12 @@ namespace Jovian.PopupSystem.UI {
|
||||
return (entry.label, entry.value);
|
||||
}
|
||||
|
||||
/// <summary>Returns the next available image element from the cache, or creates one.</summary>
|
||||
public Image GetImage() {
|
||||
return GetOrCreate(imageCache, imagePrefab, ref imageIndex);
|
||||
}
|
||||
|
||||
/// <summary>Returns the next available separator element from the cache, or creates one.</summary>
|
||||
public Image GetSeparator() {
|
||||
return GetOrCreate(separatorCache, separatorPrefab, ref separatorIndex);
|
||||
}
|
||||
@@ -145,6 +157,7 @@ namespace Jovian.PopupSystem.UI {
|
||||
|
||||
// --- Positioning ---
|
||||
|
||||
/// <summary>Configures the popup to anchor to a target element on the specified side.</summary>
|
||||
public void SetAnchorMode(RectTransform target, AnchorSide side, float edgePadding) {
|
||||
positionMode = PopupPositionMode.AnchorToElement;
|
||||
anchorTarget = target;
|
||||
@@ -152,12 +165,14 @@ namespace Jovian.PopupSystem.UI {
|
||||
screenEdgePadding = edgePadding;
|
||||
}
|
||||
|
||||
/// <summary>Configures the popup to follow the mouse cursor with the given offset.</summary>
|
||||
public void SetFollowMouseMode(Vector2 offset, float edgePadding) {
|
||||
positionMode = PopupPositionMode.FollowMouse;
|
||||
followOffset = offset;
|
||||
screenEdgePadding = edgePadding;
|
||||
}
|
||||
|
||||
/// <summary>Positions the popup at a fixed screen coordinate with edge clamping.</summary>
|
||||
public void SetFixedPosition(Vector2 screenPos, float edgePadding) {
|
||||
positionMode = PopupPositionMode.AnchorToElement;
|
||||
anchorTarget = null;
|
||||
@@ -165,6 +180,7 @@ namespace Jovian.PopupSystem.UI {
|
||||
PositionAtScreenPoint(screenPos);
|
||||
}
|
||||
|
||||
/// <summary>Updates the popup position based on the current mode (follow mouse or anchored).</summary>
|
||||
public void UpdatePosition() {
|
||||
if(positionMode == PopupPositionMode.FollowMouse) {
|
||||
PositionAtScreenPoint(Mouse.current.position.ReadValue() + followOffset);
|
||||
|
||||
@@ -1,54 +1,48 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace Jovian.PopupSystem.UI {
|
||||
/// <summary>
|
||||
/// Reference holder MonoBehaviour for popup triggers. Attach to any UI element with a
|
||||
/// Graphic component (Image, TMP_Text, etc.) that has Raycast Target enabled.
|
||||
/// Configure category, anchor side, and position mode in the Inspector.
|
||||
/// Forwards pointer events to the bound <see cref="PopupTriggerView"/>.
|
||||
/// </summary>
|
||||
public class PopupTrigger : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {
|
||||
[SerializeField] PopupCategory category;
|
||||
[SerializeField] AnchorSide anchorSide = AnchorSide.Below;
|
||||
[SerializeField] PopupPositionMode positionMode = PopupPositionMode.AnchorToElement;
|
||||
|
||||
IPopupSystem popupSystem;
|
||||
Action<PopupContentBuilder> contentCallback;
|
||||
bool initialized;
|
||||
PopupTriggerView handler;
|
||||
|
||||
/// <summary>The popup category this trigger belongs to.</summary>
|
||||
public PopupCategory Category => category;
|
||||
|
||||
public void Initialize(IPopupSystem popupSystem, Action<PopupContentBuilder> contentCallback) {
|
||||
this.popupSystem = popupSystem;
|
||||
this.contentCallback = contentCallback;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public void Initialize(IPopupSystem popupSystem, PopupCategory category, Action<PopupContentBuilder> contentCallback) {
|
||||
this.popupSystem = popupSystem;
|
||||
this.category = category;
|
||||
this.contentCallback = contentCallback;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
public void UpdateContent(Action<PopupContentBuilder> contentCallback) {
|
||||
this.contentCallback = contentCallback;
|
||||
/// <summary>Which side of this element the popup anchors to.</summary>
|
||||
public AnchorSide AnchorSide => anchorSide;
|
||||
|
||||
/// <summary>Whether the popup anchors to this element or follows the mouse.</summary>
|
||||
public PopupPositionMode PositionMode => positionMode;
|
||||
|
||||
/// <summary>The bound behavior handler. Null until <see cref="Bind"/> is called.</summary>
|
||||
public PopupTriggerView Handler => handler;
|
||||
|
||||
/// <summary>
|
||||
/// Binds a <see cref="PopupTriggerView"/> to this trigger. Called automatically
|
||||
/// by <see cref="IPopupSystem.ScanTriggers"/> or <see cref="IPopupSystem.InitializeTriggersInChildren"/>.
|
||||
/// </summary>
|
||||
public void Bind(PopupTriggerView view) {
|
||||
handler = view;
|
||||
}
|
||||
|
||||
/// <summary>Forwards pointer enter to the bound handler.</summary>
|
||||
public void OnPointerEnter(PointerEventData eventData) {
|
||||
if(!initialized || popupSystem == null || contentCallback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(positionMode == PopupPositionMode.AnchorToElement) {
|
||||
popupSystem.Show(category, contentCallback, (RectTransform)transform, anchorSide);
|
||||
}
|
||||
else {
|
||||
popupSystem.Show(category, contentCallback);
|
||||
}
|
||||
handler?.OnPointerEnter(this);
|
||||
}
|
||||
|
||||
/// <summary>Forwards pointer exit to the bound handler.</summary>
|
||||
public void OnPointerExit(PointerEventData eventData) {
|
||||
if(!initialized || popupSystem == null) {
|
||||
return;
|
||||
}
|
||||
popupSystem.Hide(category);
|
||||
handler?.OnPointerExit(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user