using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Amanotes.Core
{
partial class Widget2D // Size2D
{
[SerializeField] protected internal Size2D _size = new Size2D();
public Vector2 size
{
get => _size;
set
{
if (_size == value) return;
_size.SetSize(value);
Refresh();
}
}
public Vector2 pivot
{
get => _size.pivot;
set => _size.pivot = value;
}
/// When true, widget height maps to local Z (e.g. flat XZ tiles).
public bool scrollAxisIsZ => _size.useZ;
public float width
{
get => ((Vector2)_size).x;
set
{
var v = size;
if (Mathf.Approximately(v.x, value)) return;
v.x = value;
_size.SetSize(v);
Refresh();
}
}
public float height
{
get => ((Vector2)_size).y;
set
{
var v = size;
if (Mathf.Approximately(v.y, value)) return;
v.y = value;
_size.SetSize(v);
Refresh();
}
}
#if UNITY_EDITOR
private void OnDrawGizmosSelected()
{
_size.DrawGizmoSelected(transform);
DrawComputedRectGizmos();
}
private void OnDrawGizmos() => _size.DrawGizmo(transform);
#endif
}
partial class Widget2D // Legacy (kept for serialization compat)
{
[HideInInspector] [SerializeField] private List targets;
protected void RefreshComponentsOnly()
{
ComputeAllRects();
ApplyTargets2();
}
}
partial class Widget2D // Listeners
{
[HideInInspector] [SerializeField] private List listeners = new List();
// Runtime-only rectId bindings for listeners (not serialized — set from code)
[System.NonSerialized] private Dictionary _listenerRectBindings;
private void NotifyListeners()
{
if (this == null || listeners == null) return;
for (var i = listeners.Count - 1; i >= 0; i--)
{
var lsn = listeners[i];
if (lsn == null) continue;
if (!(lsn is ISizeListener handler)) continue;
// Check if listener has a rect binding
if (_listenerRectBindings != null && _listenerRectBindings.TryGetValue(lsn, out var rectId)
&& !string.IsNullOrEmpty(rectId))
{
handler.OnResize(GetRectSize(rectId));
}
else
{
handler.OnResize(_size);
}
}
}
internal bool AddListener(Component c)
{
if (c == null) return false;
if (listeners.Contains(c)) return true;
if (!(c is ISizeListener)) return false;
listeners.Add(c);
return true;
}
///
/// Add a listener bound to a specific derived rect ID.
/// The listener's OnResize will receive the derived rect's size instead of raw widget size.
///
internal bool AddListener(Component c, string rectId)
{
if (!AddListener(c)) return false;
if (!string.IsNullOrEmpty(rectId))
{
_listenerRectBindings ??= new Dictionary(4);
_listenerRectBindings[c] = rectId;
}
return true;
}
internal bool RemoveListener(Component c)
{
if (c == null || listeners == null) return false;
_listenerRectBindings?.Remove(c);
return listeners.Remove(c);
}
internal bool ContainsListener(Component c)
{
return listeners != null && listeners.Contains(c);
}
#if UNITY_EDITOR
internal void Scan4Listeners(GameObject go)
{
var monos = go.GetComponents();
for (var i = 0; i < monos.Length; i++)
{
AddListener(monos[i]);
}
}
#endif
}
public partial class Widget2D : MonoBehaviour
{
#if UNITY_EDITOR
private void OnValidate()
{
if (PrefabUtility.IsPartOfPrefabAsset(gameObject)) return;
#pragma warning disable UDR0005
EditorApplication.delayCall += Refresh;
#pragma warning restore UDR0005
}
#endif
public virtual void Refresh()
{
ComputeAllRects();
ApplyTargets2();
NotifyListeners();
}
}
}