Iteration 4 over Assets/Scripts (no component/file splits, no Unity assets touched): Dedup: - Route inline cursor-release, material guards, Ctrl-held and undo/redo input through existing InputUtil / SetMatFloat helpers - Add ungated InputUtil.KeyPressedThisFrame; GameplayKeyPressed builds on it - Unify FindDeep/FindDeepChild into GeometryUtil.FindDeep Dead code / stale docs: - Remove unused code-gen bake path (HsvColorPicker.Build, PaintHud factory) - Drop unreferenced symbols (SubPhaseChanged event, LocalPhaseDuration, IsLocalSceneMain, MouseSensitivity.Changed, IsPaused, InSession, NetworkControlled, PreviousPose, JointCount, voxel-count accessors) - Fix incorrect PlayerRole / PaintHud / Pick / PlayerPose docs Perf / robustness (behaviour-neutral): - ConcealmentMeter.Evaluate: reuse vertex/topology buffers, two-pointer crossing count - BuildMeshCaches: alloc-free vertex copy, cached topology/UVs - Guard all PlayerPaintSync LogSync sites behind logSync - Cache LocalViewerIsHunter / controller / CanShoot / TypingGuard lookups; dedup LocalIsHunter with MatchHud - Change-guard RefreshEmissionColor and HeroCutout.Disarm - Cache scene/countdown string comparisons per frame - Grow NonAlloc buffers and log-once on saturation Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
133 lines
4.6 KiB
C#
133 lines
4.6 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
/// <summary>
|
|
/// Compact runtime HSV colour picker: a saturation/value square, a hue bar and a live swatch. The
|
|
/// square is a pure-hue base with two static gradient overlays on top (white-out -> saturation,
|
|
/// black-out -> value), so only the base tint changes per hue - no per-frame texture rebuilds. Hue is
|
|
/// never lost while dragging the square (the square only edits S/V, the bar only edits H). Alpha is
|
|
/// edited separately by a standalone slider in the HUD, not by this picker; <see cref="SetColor"/>
|
|
/// still stores the incoming alpha so <see cref="Value"/> round-trips it.
|
|
///
|
|
/// The child structure (stable names) comes from the baked HUD prefab. <see cref="Rebind"/>
|
|
/// (re)assigns the runtime gradient sprites (which a prefab cannot store) and (re)hooks the drag
|
|
/// relays. A leftover alpha bar from a pre-split prefab is hidden by <see cref="Rebind"/>, so no
|
|
/// re-bake is required.
|
|
/// </summary>
|
|
public class HsvColorPicker : MonoBehaviour
|
|
{
|
|
/// <summary>Raised with the new colour (RGB; alpha is preserved, not edited here) when the user moves
|
|
/// the square or hue bar.</summary>
|
|
public event Action<Color> Changed;
|
|
|
|
private float _h, _s, _v, _a = 1f;
|
|
|
|
private Image _hueBase; // pure-hue background of the SV square
|
|
private RectTransform _svHandle;
|
|
private RectTransform _hueHandle;
|
|
private Image _swatch;
|
|
|
|
/// <summary>Current colour (HSV -> RGB, with the preserved alpha).</summary>
|
|
public Color Value
|
|
{
|
|
get
|
|
{
|
|
Color c = Color.HSVToRGB(_h, _s, _v);
|
|
c.a = _a;
|
|
return c;
|
|
}
|
|
}
|
|
|
|
/// <summary>Shows <paramref name="c"/> without raising <see cref="Changed"/> (external set).</summary>
|
|
public void SetColor(Color c)
|
|
{
|
|
Color.RGBToHSV(c, out _h, out _s, out _v);
|
|
_a = c.a;
|
|
Refresh();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Re-finds the child widgets, (re)assigns the runtime gradient sprites and (re)hooks the drag
|
|
/// relays. Idempotent (unsubscribe-then-subscribe), so it is safe whether the structure was just
|
|
/// built in code or instantiated from a prefab. Call before <see cref="SetColor"/>.
|
|
/// </summary>
|
|
public void Rebind()
|
|
{
|
|
var sv = transform.Find("SV");
|
|
if (sv)
|
|
{
|
|
_hueBase = sv.GetComponent<Image>();
|
|
|
|
var sat = sv.Find("SatOverlay");
|
|
if (sat && sat.TryGetComponent(out Image satImg)) satImg.sprite = PaintHud.SaturationSprite();
|
|
var val = sv.Find("ValOverlay");
|
|
if (val && val.TryGetComponent(out Image valImg)) valImg.sprite = PaintHud.ValueSprite();
|
|
|
|
_svHandle = sv.Find("Handle") as RectTransform;
|
|
|
|
Rehook(sv, OnSvPicked);
|
|
}
|
|
|
|
var hue = transform.Find("Hue") as RectTransform;
|
|
if (hue)
|
|
{
|
|
if (hue.TryGetComponent(out Image hueImg)) hueImg.sprite = PaintHud.HueSprite();
|
|
_hueHandle = hue.Find("Handle") as RectTransform;
|
|
|
|
Rehook(hue, OnHuePicked);
|
|
}
|
|
|
|
// Alpha now lives on a standalone slider (PaintHud), not in the picker. Hide any alpha bar a
|
|
// pre-split prefab still carries so it does not show as a dead, non-functional strip.
|
|
var leftoverAlpha = transform.Find("Alpha");
|
|
if (leftoverAlpha) leftoverAlpha.gameObject.SetActive(false);
|
|
|
|
var swatch = transform.Find("Swatch");
|
|
if (swatch) _swatch = swatch.GetComponent<Image>();
|
|
|
|
Refresh();
|
|
}
|
|
|
|
// Idempotently hooks the handler to the surface's drag relay (unsubscribe-then-subscribe).
|
|
private static void Rehook(Component surface, Action<Vector2> handler)
|
|
{
|
|
if (surface.TryGetComponent(out UiPointerSurface pointer))
|
|
{
|
|
pointer.Picked -= handler;
|
|
pointer.Picked += handler;
|
|
}
|
|
}
|
|
|
|
private void OnSvPicked(Vector2 p)
|
|
{
|
|
_s = p.x;
|
|
_v = p.y;
|
|
Refresh();
|
|
Changed?.Invoke(Value);
|
|
}
|
|
|
|
private void OnHuePicked(Vector2 p)
|
|
{
|
|
_h = p.x;
|
|
Refresh();
|
|
Changed?.Invoke(Value);
|
|
}
|
|
|
|
private void Refresh()
|
|
{
|
|
if (_hueBase) _hueBase.color = Color.HSVToRGB(_h, 1f, 1f);
|
|
if (_svHandle)
|
|
{
|
|
_svHandle.anchorMin = _svHandle.anchorMax = new Vector2(_s, _v);
|
|
_svHandle.anchoredPosition = Vector2.zero;
|
|
}
|
|
if (_hueHandle)
|
|
{
|
|
_hueHandle.anchorMin = _hueHandle.anchorMax = new Vector2(_h, 0.5f);
|
|
_hueHandle.anchoredPosition = Vector2.zero;
|
|
}
|
|
if (_swatch) _swatch.color = Color.HSVToRGB(_h, _s, _v);
|
|
}
|
|
}
|