using System.Collections.Generic;
using UnityEngine;
namespace MS_Outline
{
///
/// Marks an object for highlighting with the FullOutline system.
/// Add this component to any object that should be highlightable.
///
[DisallowMultipleComponent]
public class GlowOutlineTarget : MonoBehaviour
{
private static HashSet activeTargets = new HashSet();
[Header("Glow Settings")]
[Tooltip("The color of the glow effect")]
[SerializeField] private Color glowColor = Color.yellow;
[Tooltip("Intensity multiplier for the glow. Values > 1 create HDR emission that blooms.")]
[Range(0f, 20f)]
[SerializeField] private float glowIntensity = 1.5f;
[Header("State")]
[Tooltip("Whether the glow is currently active")]
[SerializeField] private bool isGlowing = true;
[Header("Exclusions")]
[Tooltip("Child GameObjects to exclude from the outline (e.g., particle systems, VFX)")]
[SerializeField] private List excludedObjects = new List();
private Renderer[] renderers;
///
/// Get all currently glowing targets
///
public static IReadOnlyCollection ActiveTargets => activeTargets;
///
/// The color of the glow effect
///
public Color GlowColor
{
get => glowColor;
set => glowColor = value;
}
///
/// Intensity multiplier for the glow. Values > 1 create HDR emission.
///
public float GlowIntensity
{
get => glowIntensity;
set => glowIntensity = Mathf.Clamp(value, 0f, 20f);
}
///
/// Whether this object is currently glowing
///
public bool IsGlowing => isGlowing;
///
/// Get all renderers on this object
///
public Renderer[] Renderers => renderers;
private void Awake()
{
CacheRenderers();
}
///
/// Cache renderers, filtering out any excluded objects
///
private void CacheRenderers()
{
var allRenderers = GetComponentsInChildren();
if (excludedObjects == null || excludedObjects.Count == 0)
{
renderers = allRenderers;
return;
}
var filteredList = new List();
foreach (var renderer in allRenderers)
{
bool isExcluded = false;
foreach (var excluded in excludedObjects)
{
if (excluded != null &&
(renderer.gameObject == excluded || renderer.transform.IsChildOf(excluded.transform)))
{
isExcluded = true;
break;
}
}
if (!isExcluded)
filteredList.Add(renderer);
}
renderers = filteredList.ToArray();
}
private void OnEnable()
{
// If we were glowing before being disabled, re-register
if (isGlowing)
{
activeTargets.Add(this);
}
}
private void OnDisable()
{
// Always remove from active targets when disabled
activeTargets.Remove(this);
}
private void OnDestroy()
{
activeTargets.Remove(this);
}
#if UNITY_EDITOR
private void OnValidate()
{
// Handle inspector changes during play mode
if (Application.isPlaying && isActiveAndEnabled)
{
// Re-cache renderers in case exclusions changed
CacheRenderers();
if (isGlowing)
activeTargets.Add(this);
else
activeTargets.Remove(this);
}
}
#endif
///
/// Enable the glow effect on this object
///
public void EnableGlow()
{
if (!isGlowing)
{
isGlowing = true;
activeTargets.Add(this);
#if UNITY_EDITOR
Debug.Log($"[FullOutline] EnableGlow on {gameObject.name}. Active targets: {activeTargets.Count}");
#endif
}
}
///
/// Enable the glow effect with a specific color
///
public void EnableGlow(Color color)
{
glowColor = color;
EnableGlow();
}
///
/// Enable the glow effect with a specific color and intensity
///
public void EnableGlow(Color color, float intensity)
{
glowColor = color;
glowIntensity = Mathf.Clamp(intensity, 0f, 20f);
EnableGlow();
}
///
/// Disable the glow effect on this object
///
public void DisableGlow()
{
if (isGlowing)
{
isGlowing = false;
activeTargets.Remove(this);
}
}
///
/// Toggle the glow effect
///
public void ToggleGlow()
{
if (isGlowing)
DisableGlow();
else
EnableGlow();
}
}
}