Files
aibis-dream/Assets/Scripts/MiniGame/Peipei/Eye/EyeTarget.cs
T

450 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<SpriteRenderer>();
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<SpriteRenderer>();
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;
}
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<EyeTargetVisual>();
}
if (unifiedVisual == null)
{
unifiedVisual = gameObject.AddComponent<EyeTargetVisual>();
}
unifiedVisual.Configure(spriteRenderer, imageSpriteRender);
unifiedVisual.ApplyTuning(visualSettings);
}
private void DisableLegacyChildRenderers()
{
foreach (var childRenderer in GetComponentsInChildren<SpriteRenderer>(true))
{
if (childRenderer.gameObject == gameObject)
{
continue;
}
if (imageSpriteRender != null && childRenderer == imageSpriteRender)
{
continue;
}
childRenderer.enabled = false;
}
}
/// <summary>
/// 禁用同组下旧版 overlay(如 posterNoColor / computernocolor),避免盖住 unified 效果。
/// </summary>
private void EnsureWrongColorOverlay()
{
if (wrongColorSpriteRenderer == null && transform.parent != null)
{
string errorName = $"{gameObject.name}Error";
foreach (var renderer in transform.parent.GetComponentsInChildren<SpriteRenderer>(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<SpriteRenderer>(true))
{
if (renderer.gameObject == gameObject)
{
continue;
}
if (renderer.GetComponent<EyeTarget>() != null)
{
continue;
}
if (renderer.GetComponentInParent<EyeTarget>() != null)
{
continue;
}
if (IsWrongColorOverlayRenderer(renderer))
{
continue;
}
renderer.enabled = false;
}
}
}