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(); } } }