Files

628 lines
18 KiB
C#

using UnityEngine;
using UnityEngine.Rendering.Universal;
using DG.Tweening;
using System.Collections;
using System.Collections.Generic;
namespace AibisDream.FixSystem
{
/// <summary>
/// CablePanel 灯光系统 - 管理呼吸灯、小灯和ECG波形
/// </summary>
public class CablePanelLight : MonoBehaviour
{
// 灯光系统常量
private const float SELF_CHECK_DELAY = 0.05f;
private const float SELF_CHECK_INTERVAL = 0.1f;
private const float ECG_WAVE_TOGGLE_DELAY = 0.1f;
private const float ECG_WAVE_FINAL_DELAY = 0.2f;
private const float BREATHING_LIGHT_START_DELAY = 0.5f;
private const float BREATHING_LIGHT_MAX_INTENSITY = 1f;
private const int SELF_CHECK_COUNT = 2;
#region 呼吸灯相关字段
[Header("呼吸灯设置")]
[SerializeField] private Light2D breathingLight;
[SerializeField] private float normalBreathingSpeed = 1f;
[SerializeField] private float warningBreathingSpeed = 1f;
[SerializeField] private float emergencyBreathingSpeed = 2f;
[SerializeField] private Color normalColor = Color.green;
[SerializeField] private Color warningColor = Color.yellow;
[SerializeField] private Color emergencyColor = Color.red;
[SerializeField] private RobotECGWave ecgWave;
private SpriteRenderer breathingLightSprite;
private Tween breathingTween;
#endregion
#region 小灯相关字段
[Header("小灯设置")]
[SerializeField] private List<Light2D> smallLights = new List<Light2D>();
[SerializeField] private float smallLightBlinkInterval = 0.5f;
[SerializeField] private Color smallLightDefaultColor = Color.yellow;
[SerializeField] private Color smallLightNormalColor = Color.green;
[SerializeField] private Color smallLightErrorColor = Color.red;
[SerializeField] private float operationBlinkDuration = 1f;
[SerializeField] private float operationBlinkInterval = 0.1f;
private List<SpriteRenderer> smallLightSprites = new List<SpriteRenderer>();
private SmallLightState smallLightState = SmallLightState.Default;
private SmallLightStatus smallLightStatus = SmallLightStatus.Normal;
#endregion
#region 系统状态字段
private bool isSystemStarting = false;
private Coroutine smallLightsBlinkCoroutine;
private bool isLightOn;
#endregion
#region 生命周期
private void OnEnable()
{
// 启动小灯闪烁协程
if (smallLightsBlinkCoroutine == null)
{
smallLightsBlinkCoroutine = StartCoroutine(SmallLightsBlinkRoutine());
}
}
private void OnDisable()
{
// 清理所有Tween
breathingTween?.Kill();
breathingTween = null;
// 停止协程
if (smallLightsBlinkCoroutine != null)
{
StopCoroutine(smallLightsBlinkCoroutine);
smallLightsBlinkCoroutine = null;
}
StopAllCoroutines();
}
#endregion
#region 初始化方法
/// <summary>
/// 初始化灯光系统
/// </summary>
public void Initialize(bool isLightOn)
{
this.isLightOn = isLightOn;
// 初始化SpriteRenderer引用
InitializeSpriteRenderers();
// 初始化系统状态
if (isLightOn)
{
InitializeSystemOn();
}
else
{
InitializeSystemOff();
}
SetSmallLightState(SmallLightState.Default);
}
/// <summary>
/// 初始化SpriteRenderer引用
/// </summary>
private void InitializeSpriteRenderers()
{
// 自动获取呼吸灯的SpriteRenderer
if (breathingLight != null)
{
breathingLightSprite = breathingLight.GetComponentInParent<SpriteRenderer>();
}
// 自动获取小灯的SpriteRenderer
smallLightSprites.Clear();
foreach (var light in smallLights)
{
if (light != null)
{
var spriteRenderer = light.GetComponentInParent<SpriteRenderer>();
smallLightSprites.Add(spriteRenderer);
}
}
}
/// <summary>
/// 系统开启时的初始化
/// </summary>
private void InitializeSystemOn()
{
SetBreathingLight(normalColor, BREATHING_LIGHT_MAX_INTENSITY);
InitializeSmallLights(smallLightDefaultColor, BREATHING_LIGHT_MAX_INTENSITY);
SetECGWaveActive(true);
}
/// <summary>
/// 系统关闭时的初始化
/// </summary>
private void InitializeSystemOff()
{
SetBreathingLight(normalColor, 0f, true);
TurnOffAllSmallLights();
SetECGWaveActive(false);
}
#endregion
#region 公共方法 - 系统控制
/// <summary>
/// 设置系统电源状态
/// </summary>
public void SetSystemPower(bool isOn)
{
if (!isOn)
{
TurnOffAllLights();
}
else
{
InitializeSystemOn();
}
}
/// <summary>
/// 启动系统
/// </summary>
public IEnumerator StartSystem()
{
if (isSystemStarting || isLightOn) yield break;
isSystemStarting = true;
yield return SystemStartSequence();
isSystemStarting = false;
}
#endregion
#region 公共方法 - 状态更新
/// <summary>
/// 更新呼吸灯
/// </summary>
public void UpdateBreathingLight(LightState state)
{
if (breathingLight == null) return;
var (color, breathingSpeed) = GetBreathingConfig(state);
SetBreathingLight(color, BREATHING_LIGHT_MAX_INTENSITY);
StartBreathingEffect(breathingSpeed);
}
/// <summary>
/// 更新ECG波形
/// </summary>
public void UpdateECGWave(LightState state)
{
if (ecgWave != null)
{
ecgWave.SetWaveType(GetWaveTypeByState(state));
}
}
#endregion
#region 公共方法 - 小灯控制
/// <summary>
/// 设置小灯状态
/// </summary>
public void SetSmallLightState(SmallLightState newState)
{
if (smallLightState != newState)
{
smallLightState = newState;
if (newState == SmallLightState.Default)
{
smallLightStatus = SmallLightStatus.Normal;
}
StartCoroutine(HandleSmallLightStateChange());
}
}
/// <summary>
/// 设置小灯状态状态
/// </summary>
public void SetSmallLightStatus(SmallLightStatus newStatus)
{
if (smallLightStatus != newStatus)
{
smallLightStatus = newStatus;
UpdateSmallLightsStatus();
}
}
#endregion
#region 公共方法 - 波形控制
/// <summary>
/// 获取当前波形类型
/// </summary>
public RobotECGWave.WaveType GetCurrentWaveType()
{
return ecgWave?.waveType ?? RobotECGWave.WaveType.RobotECG;
}
/// <summary>
/// 设置波形类型
/// </summary>
public void SetWaveType(RobotECGWave.WaveType waveType)
{
if (ecgWave != null)
{
ecgWave.SetWaveType(waveType);
}
}
#endregion
#region 系统启动序列
/// <summary>
/// 系统启动序列
/// </summary>
private IEnumerator SystemStartSequence()
{
// 1. ECG波形闪烁
yield return StartCoroutine(ECGWaveToggleSequence());
// 2. 小灯自检
yield return StartCoroutine(SmallLightsSelfCheck());
// 3. 启动呼吸灯
SetBreathingLight(normalColor, BREATHING_LIGHT_MAX_INTENSITY);
yield return new WaitForSeconds(BREATHING_LIGHT_START_DELAY);
// 4. 设置系统状态为开启
SetSystemPower(true);
}
/// <summary>
/// ECG波形闪烁序列
/// </summary>
private IEnumerator ECGWaveToggleSequence()
{
if (ecgWave == null) yield break;
ecgWave.gameObject.SetActive(true);
yield return new WaitForSeconds(ECG_WAVE_TOGGLE_DELAY);
ecgWave.gameObject.SetActive(false);
yield return new WaitForSeconds(ECG_WAVE_TOGGLE_DELAY);
ecgWave.gameObject.SetActive(true);
yield return new WaitForSeconds(ECG_WAVE_FINAL_DELAY);
}
/// <summary>
/// 小灯自检序列
/// </summary>
private IEnumerator SmallLightsSelfCheck()
{
// 关闭所有小灯
SetSmallLightsColorAndIntensity(Color.clear, 0f);
// 自检两次
for (int check = 0; check < SELF_CHECK_COUNT; check++)
{
// 从左到右点亮
for (int i = 0; i < smallLights.Count; i++)
{
if (smallLights[i] != null)
{
smallLights[i].color = smallLightDefaultColor;
smallLights[i].intensity = BREATHING_LIGHT_MAX_INTENSITY;
}
if (i < smallLightSprites.Count && smallLightSprites[i] != null)
{
smallLightSprites[i].color = smallLightDefaultColor;
}
yield return new WaitForSeconds(SELF_CHECK_DELAY);
}
// 关闭所有灯
SetSmallLightsColorAndIntensity(Color.clear, 0f);
yield return new WaitForSeconds(SELF_CHECK_INTERVAL);
}
// 恢复到默认状态(只有第一个灯闪烁)
ResetSmallLightsToDefault();
}
#endregion
#region 小灯相关方法
/// <summary>
/// 处理小灯状态变化
/// </summary>
private IEnumerator HandleSmallLightStateChange()
{
if (smallLightState == SmallLightState.Operation)
{
yield return StartCoroutine(OperationBlinkSequence());
SetSmallLightsToOperationState();
}
else
{
ResetSmallLightsToDefault();
}
}
/// <summary>
/// 运行状态闪烁序列
/// </summary>
private IEnumerator OperationBlinkSequence()
{
float endTime = Time.time + operationBlinkDuration;
while (Time.time < endTime)
{
foreach (var light in smallLights)
{
if (light != null)
{
light.intensity = Random.value > 0.5f ? BREATHING_LIGHT_MAX_INTENSITY : 0f;
}
}
yield return new WaitForSeconds(operationBlinkInterval);
}
}
/// <summary>
/// 设置小灯为运行状态
/// </summary>
private void SetSmallLightsToOperationState()
{
Color targetColor = GetSmallLightColorByStatus();
SetSmallLightsColorAndIntensity(targetColor, BREATHING_LIGHT_MAX_INTENSITY);
}
/// <summary>
/// 根据当前状态获取小灯颜色
/// </summary>
private Color GetSmallLightColorByStatus()
{
return smallLightStatus == SmallLightStatus.Normal ? smallLightNormalColor : smallLightErrorColor;
}
/// <summary>
/// 重置小灯为默认状态
/// </summary>
private void ResetSmallLightsToDefault()
{
SetSmallLightsColorAndIntensity(smallLightDefaultColor, 0f);
// 只有第一个灯闪烁
if (smallLights.Count > 0 && smallLights[0] != null)
{
smallLights[0].intensity = BREATHING_LIGHT_MAX_INTENSITY;
if (smallLightSprites.Count > 0 && smallLightSprites[0] != null)
{
smallLightSprites[0].color = smallLightDefaultColor;
}
}
}
/// <summary>
/// 更新小灯状态状态
/// </summary>
private void UpdateSmallLightsStatus()
{
Color targetColor = smallLightStatus == SmallLightStatus.Normal
? smallLightNormalColor
: smallLightErrorColor;
SetSmallLightsColorAndIntensity(targetColor, BREATHING_LIGHT_MAX_INTENSITY);
}
/// <summary>
/// 小灯闪烁协程
/// </summary>
private IEnumerator SmallLightsBlinkRoutine()
{
while (true)
{
if (!isLightOn)
{
TurnOffAllSmallLights();
}
else if (smallLightState == SmallLightState.Default)
{
ResetSmallLightsToDefault();
}
yield return new WaitForSeconds(smallLightBlinkInterval);
}
}
/// <summary>
/// 初始化小灯
/// </summary>
private void InitializeSmallLights(Color color, float intensity)
{
SetSmallLightsColorAndIntensity(color, intensity);
}
/// <summary>
/// 设置小灯颜色和强度
/// </summary>
private void SetSmallLightsColorAndIntensity(Color color, float intensity)
{
for (int i = 0; i < smallLights.Count; i++)
{
if (smallLights[i] != null)
{
smallLights[i].color = color;
smallLights[i].intensity = intensity;
}
if (i < smallLightSprites.Count && smallLightSprites[i] != null)
{
smallLightSprites[i].color = color;
}
}
}
/// <summary>
/// 关闭所有小灯
/// </summary>
private void TurnOffAllSmallLights()
{
SetSmallLightsColorAndIntensity(Color.clear, 0f);
}
#endregion
#region 呼吸灯相关方法
/// <summary>
/// 设置呼吸灯
/// </summary>
private void SetBreathingLight(Color color, float intensity, bool useTransparent = false)
{
if (breathingLight != null)
{
breathingLight.color = color;
breathingLight.intensity = intensity;
}
if (breathingLightSprite != null)
{
breathingLightSprite.color = useTransparent
? new Color(color.r, color.g, color.b, 0f)
: color;
}
}
/// <summary>
/// 启动呼吸效果
/// </summary>
private void StartBreathingEffect(float breathingSpeed)
{
breathingTween?.Kill();
float halfCycleDuration = 1f / Mathf.Max(0.01f, breathingSpeed);
breathingLight.intensity = 0f;
if (breathingLightSprite != null)
{
Color color = breathingLightSprite.color;
color.a = 0f;
breathingLightSprite.color = color;
}
breathingTween = DOTween.To(
() => breathingLight.intensity,
x =>
{
breathingLight.intensity = x;
if (breathingLightSprite != null)
{
Color color = breathingLightSprite.color;
color.a = x / BREATHING_LIGHT_MAX_INTENSITY;
breathingLightSprite.color = color;
}
},
BREATHING_LIGHT_MAX_INTENSITY,
halfCycleDuration
)
.SetLoops(-1, LoopType.Yoyo)
.SetEase(Ease.InOutSine);
}
/// <summary>
/// 获取呼吸灯配置
/// </summary>
private (Color color, float breathingSpeed) GetBreathingConfig(LightState state)
{
return state switch
{
LightState.Normal => (normalColor, normalBreathingSpeed),
LightState.Warning => (warningColor, warningBreathingSpeed),
LightState.Emergency => (emergencyColor, emergencyBreathingSpeed),
_ => (normalColor, normalBreathingSpeed)
};
}
#endregion
#region ECG波形相关方法
/// <summary>
/// 根据状态获取波形类型
/// </summary>
private RobotECGWave.WaveType GetWaveTypeByState(LightState state)
{
return state switch
{
LightState.Normal => RobotECGWave.WaveType.RobotECG,
LightState.Warning => RobotECGWave.WaveType.Warning,
LightState.Emergency => RobotECGWave.WaveType.Noise,
_ => RobotECGWave.WaveType.RobotECG
};
}
/// <summary>
/// 设置ECG波形激活状态
/// </summary>
private void SetECGWaveActive(bool active)
{
if (ecgWave != null)
{
ecgWave.gameObject.SetActive(active);
}
}
#endregion
#region 辅助方法
/// <summary>
/// 关闭所有灯光
/// </summary>
private void TurnOffAllLights()
{
breathingTween?.Kill();
breathingTween = null;
SetBreathingLight(normalColor, 0f, true);
TurnOffAllSmallLights();
SetECGWaveActive(false);
}
#endregion
}
/// <summary>
/// 小灯状态
/// </summary>
public enum SmallLightState
{
Default, // 默认状态
Operation // 运行状态
}
/// <summary>
/// 小灯状态状态
/// </summary>
public enum SmallLightStatus
{
Normal, // 正常
Error // 错误
}
}