using System; using AibisDream; using AibisDream.Kit; using AibisDream.Utility; using DG.Tweening; using UnityEngine; public class EyeTarget : MonoBehaviour { private static readonly int AlphaId = Shader.PropertyToID("_Alpha"); public Transform targetTransform; [Header("Optional overlay sprite for UF imagination")] [SerializeField] private SpriteRenderer imageSpriteRender; [Header("Wrong-color overlay (e.g. plantError); auto-resolved from sibling if unset")] [SerializeField] private SpriteRenderer wrongColorSpriteRenderer; [SerializeField] private Shader unifiedSpriteShader; [SerializeField] private EyeTargetVisual unifiedVisual; [Header("Indicator RGB (imagined color for debug overlay)")] public Color _color; public Color GetIndicatorColor() { return new Color( RoundIndicatorChannel(_color.r), RoundIndicatorChannel(_color.g), RoundIndicatorChannel(_color.b), _color.a); } private static float RoundIndicatorChannel(float value) { return Mathf.Round(value * 10f) / 10f; } private EyeVisualSettings visualSettings = new(); private Material wrongColorMaterial; private void Awake() { var spriteRenderer = GetComponent(); if (spriteRenderer == null) { Debug.LogError($"[EyeTarget] {name} 缺少 SpriteRenderer。", this); return; } EnsureWrongColorOverlay(); EnsureUnifiedVisual(spriteRenderer); DisableLegacyChildRenderers(); DisableLegacySiblingRenderers(); } public void BindVisualSettings(EyeVisualSettings settings) { visualSettings = settings ?? new EyeVisualSettings(); RefreshMaterialTuning(); } public void RefreshMaterialTuning() { EnsureVisualReady(); unifiedVisual?.ApplyTuning(visualSettings); } public void ApplyIdlePreviewState() { EnsureVisualReady(); Init(); } public void KillVisualTweens() { unifiedVisual?.KillActiveTweens(); wrongColorMaterial?.DOKill(); } private void EnsureVisualReady() { var spriteRenderer = GetComponent(); if (spriteRenderer == null) { return; } if (unifiedVisual == null || !unifiedVisual.IsReady) { EnsureUnifiedVisual(spriteRenderer); } } public void Init() { unifiedVisual?.ClearTransientEffects(visualSettings); SetToMinColorReveal(); SetToMaxBlur(); SetToNoWrongColor(); SetNoImage(); } public void ImageIn(float duration) { unifiedVisual?.TweenImageAlpha(1f, duration); } public void ImageOut(float duration) { unifiedVisual?.TweenImageAlpha(0f, duration); } public void SetNoImage() { unifiedVisual?.SetImageAlpha(0f); } public void SetToMinColorReveal() { unifiedVisual?.SetColorReveal(visualSettings.colorRevealMin); } public void SetToMaxColorReveal() { unifiedVisual?.SetColorReveal(visualSettings.colorRevealMax); } public bool IsAtFocusedColorState(EyeVisualSettings settings = null) { EyeVisualSettings tuning = settings ?? visualSettings; return unifiedVisual != null && unifiedVisual.IsAtColorReveal(tuning.colorRevealMax); } public bool IsAtUnfocusedColorState(EyeVisualSettings settings = null) { EyeVisualSettings tuning = settings ?? visualSettings; return unifiedVisual != null && unifiedVisual.IsAtColorReveal(tuning.colorRevealMin); } public void SetToMaxBlur() { unifiedVisual?.SetBlur(visualSettings.idleBlurAmount); } public void SetToMinBlur() { unifiedVisual?.SetBlur(visualSettings.focusedBlurAmount); } public void SetToNoWrongColor() { unifiedVisual?.SetWrongColor(0f); SetWrongColorOverlayAlpha(0f); } public void SetToWrongColor() { unifiedVisual?.SetWrongColor(1f); SetWrongColorOverlayAlpha(1f); } public void FadeOut(float duration) { unifiedVisual?.KillActiveTweens(); unifiedVisual?.PlayColorSweepTransition(visualSettings, duration, colorIn: false); } public void ColorIn(float duration) { unifiedVisual?.KillActiveTweens(); unifiedVisual?.PlayColorSweepTransition(visualSettings, duration, colorIn: true); } public void WrongColorIn(float duration) { unifiedVisual?.TweenWrongColor(1f, duration)?.SetEase(Ease.InOutSine); TweenWrongColorOverlay(1f, duration); } public void WrongColorOut(float duration) { unifiedVisual?.TweenWrongColor(0f, duration)?.SetEase(Ease.InOutSine); TweenWrongColorOverlay(0f, duration); } public void BlurIn(float duration) { var tween = unifiedVisual?.TweenBlur(visualSettings.idleBlurAmount, duration); tween?.SetEase(Ease.InOutSine); } public void BlurOut(float duration) { unifiedVisual?.TweenBlurFocusSettle(visualSettings, duration); } public void ColorBack() { SetToMaxColorReveal(); SetToNoWrongColor(); SetToMinBlur(); } public void ColorLost() { SetToMinColorReveal(); SetToMaxBlur(); } public bool TryGetUnifiedVisual(out EyeTargetVisual visual) { visual = unifiedVisual; return visual != null && visual.IsReady; } public void SetSaturation(float saturation) { unifiedVisual?.SetSaturation(saturation); } public Tween TweenSaturation(float saturation, float duration) { return unifiedVisual != null ? unifiedVisual.TweenSaturation(saturation, duration) : null; } public DG.Tweening.Sequence StartUnifiedGlitch(float duration = 1f) { return unifiedVisual != null ? unifiedVisual.StartGlitch(duration) : null; } public void StopUnifiedGlitch(float duration) { unifiedVisual?.StopGlitch(duration); } public Tween TweenRoundWave(float value, float duration) { return unifiedVisual != null ? unifiedVisual.TweenRoundWave(value, duration) : null; } public void SetUfWeights(float ascii, float dream, float memory) { unifiedVisual?.SetUfWeights(ascii, dream, memory); } public Tween TweenUfWeights(float ascii, float dream, float memory, float duration) { return unifiedVisual != null ? unifiedVisual.TweenUfWeights(ascii, dream, memory, duration) : null; } private void EnsureUnifiedVisual(SpriteRenderer spriteRenderer) { Shader shader = unifiedSpriteShader != null ? unifiedSpriteShader : Shader.Find("AIBIS/EyeUnifiedSprite"); if (shader == null) { Debug.LogError($"[EyeTarget] 找不到 AIBIS/EyeUnifiedSprite shader:{name}", this); return; } if (!shader.isSupported) { Debug.LogError($"[EyeTarget] AIBIS/EyeUnifiedSprite 在当前平台不受支持:{name}", this); return; } Material currentMaterial = Application.isPlaying ? spriteRenderer.material : spriteRenderer.sharedMaterial; bool usesUnifiedShader = currentMaterial != null && currentMaterial.shader != null && currentMaterial.shader.name == shader.name; if (currentMaterial == null || !usesUnifiedShader || !currentMaterial.HasProperty("_BlurAmount")) { Texture mainTex = currentMaterial != null && currentMaterial.HasProperty("_MainTex") ? currentMaterial.GetTexture("_MainTex") : null; var runtimeMaterial = new Material(shader) { name = $"{gameObject.name}_EyeUnified_Runtime" }; if (mainTex != null) { runtimeMaterial.SetTexture("_MainTex", mainTex); } if (Application.isPlaying) { spriteRenderer.material = runtimeMaterial; } else { spriteRenderer.sharedMaterial = runtimeMaterial; } } if (unifiedVisual == null) { unifiedVisual = GetComponent(); } if (unifiedVisual == null) { unifiedVisual = gameObject.AddComponent(); } unifiedVisual.Configure(spriteRenderer, imageSpriteRender); unifiedVisual.ApplyTuning(visualSettings); } private void DisableLegacyChildRenderers() { foreach (var childRenderer in GetComponentsInChildren(true)) { if (childRenderer.gameObject == gameObject) { continue; } if (imageSpriteRender != null && childRenderer == imageSpriteRender) { continue; } childRenderer.enabled = false; } } /// /// 禁用同组下旧版 overlay(如 posterNoColor / computernocolor),避免盖住 unified 效果。 /// private void EnsureWrongColorOverlay() { if (wrongColorSpriteRenderer == null && transform.parent != null) { string errorName = $"{gameObject.name}Error"; foreach (var renderer in transform.parent.GetComponentsInChildren(true)) { if (string.Equals(renderer.gameObject.name, errorName, StringComparison.OrdinalIgnoreCase)) { wrongColorSpriteRenderer = renderer; break; } } } if (wrongColorSpriteRenderer == null) { return; } wrongColorMaterial = Application.isPlaying ? wrongColorSpriteRenderer.material : wrongColorSpriteRenderer.sharedMaterial; wrongColorSpriteRenderer.enabled = true; SetWrongColorOverlayAlpha(0f); } private void SetWrongColorOverlayAlpha(float alpha) { if (wrongColorSpriteRenderer == null) { return; } alpha = Mathf.Clamp01(alpha); if (alpha > 0f) { wrongColorSpriteRenderer.gameObject.SetActive(true); wrongColorSpriteRenderer.enabled = true; } if (wrongColorMaterial != null && wrongColorMaterial.HasProperty(AlphaId)) { wrongColorMaterial.SetFloat(AlphaId, alpha); } if (alpha <= 0f) { wrongColorSpriteRenderer.gameObject.SetActive(false); } } private void TweenWrongColorOverlay(float alpha, float duration) { if (wrongColorSpriteRenderer == null || wrongColorMaterial == null || !wrongColorMaterial.HasProperty(AlphaId)) { return; } if (alpha > 0f) { wrongColorSpriteRenderer.gameObject.SetActive(true); wrongColorSpriteRenderer.enabled = true; } wrongColorMaterial.DOKill(); wrongColorMaterial .DOFloat(alpha, AlphaId, duration) .SetEase(Ease.InOutSine) .OnComplete(() => { if (alpha <= 0f && wrongColorSpriteRenderer != null) { wrongColorSpriteRenderer.gameObject.SetActive(false); } }); } private static bool IsWrongColorOverlayRenderer(SpriteRenderer renderer) { return renderer != null && renderer.gameObject.name.EndsWith("Error", StringComparison.OrdinalIgnoreCase); } private void DisableLegacySiblingRenderers() { Transform groupRoot = transform.parent; if (groupRoot == null) { return; } foreach (var renderer in groupRoot.GetComponentsInChildren(true)) { if (renderer.gameObject == gameObject) { continue; } if (renderer.GetComponent() != null) { continue; } if (renderer.GetComponentInParent() != null) { continue; } if (IsWrongColorOverlayRenderer(renderer)) { continue; } renderer.enabled = false; } } }