using System.Collections; using TMPro; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UI; public class WaterHoseBehaviour : MonoBehaviour, IListener { [SerializeField] private GameObject pump = null; [SerializeField] [Min(0f)] private float waterDrainSpeed = 1f; [SerializeField] [Min(0f)] private float waterPumpingSpeed = 1f; [SerializeField] private Gradient waterLevelTextColor = null; [Space] [SerializeField] private CanvasGroup waterLevelCanvasGroup = null; [SerializeField] private TextMeshProUGUI waterLevelText = null; [SerializeField] private Image waterLevelBarImage = null; [Space] [SerializeField] private TextMeshProUGUI secondaryWaterLevelText = null; [SerializeField] private Image secondaryWaterLevelBarImage = null; private ParticleSystem[] pSystems; private VRControlMode vrControlMode; public bool IsActive { get; private set; } = false; private float waterLevel = 1f; private float localWaterLevelShowSpeed = 0.2f; private Coroutine localWaterLevelShowFunc = null; private void Start() { pSystems = GetComponentsInChildren<ParticleSystem>(); vrControlMode = (VRControlMode)PlayerPrefs.GetInt("VRControlMode", 1); OnEvent(EVENT_TYPE.ON_VR_CONTROLMODE_SWITCHED, this, vrControlMode); EventManager.Instance.AddListener(EVENT_TYPE.ON_FIRE_WON, this); EventManager.Instance.AddListener(EVENT_TYPE.ON_VR_CONTROLMODE_SWITCHED, this); } private void UpdateWaterLevelUI() { if (waterLevelText) { waterLevelText.text = string.Format("{0}%", (int)(waterLevel * 100)); waterLevelText.color = waterLevelTextColor.Evaluate(waterLevel); } if (waterLevelBarImage) waterLevelBarImage.fillAmount = waterLevel; if (secondaryWaterLevelText) { secondaryWaterLevelText.text = string.Format("{0}%", (int)(waterLevel * 100)); secondaryWaterLevelText.color = waterLevelTextColor.Evaluate(waterLevel); } if (secondaryWaterLevelBarImage) secondaryWaterLevelBarImage.fillAmount = waterLevel; } public void OnWaterHose(InputAction.CallbackContext ctx) { if (ctx.performed) { StartWaterHose(); } else if (ctx.canceled) { StopWaterHose(); } } public void StartWaterHose() { if (waterLevel > 0f) { for (int i = 0; i < pSystems.Length; i++) { pSystems[i].Play(); } IsActive = true; if (vrControlMode == VRControlMode.Advanced && gameObject.activeSelf) StartCoroutine(DrainWater()); } } public void StopWaterHose() { IsActive = false; for (int i = 0; i < pSystems.Length; i++) { pSystems[i].Stop(); } } public void OnEvent<T>(EVENT_TYPE eventType, Component Sender, T param = default) { switch (eventType) { case EVENT_TYPE.ON_VR_CONTROLMODE_SWITCHED: vrControlMode = (VRControlMode)(dynamic)param; if (vrControlMode == VRControlMode.Basic) { StopAllCoroutines(); StartCoroutine(ChangeWaterLevelOpacity(0f)); pump.SetActive(false); waterLevel = 1f; } else if (vrControlMode == VRControlMode.Advanced) { StopAllCoroutines(); StartCoroutine(ChangeWaterLevelOpacity(1f)); pump.SetActive(true); UpdateWaterLevelUI(); } break; case EVENT_TYPE.ON_FIRE_WON: gameObject.SetActive(false); break; } } public void ShowWaterLevel() { if (vrControlMode == VRControlMode.Advanced) { if (localWaterLevelShowFunc != null) StopCoroutine(localWaterLevelShowFunc); localWaterLevelShowFunc = StartCoroutine(ChangeWaterLevelOpacity(1f)); } } public void HideWaterLevel() { if (vrControlMode == VRControlMode.Advanced) { if (localWaterLevelShowFunc != null) StopCoroutine(localWaterLevelShowFunc); localWaterLevelShowFunc = StartCoroutine(ChangeWaterLevelOpacity(0f)); } } private IEnumerator ChangeWaterLevelOpacity(float targetValue) { float startValue = waterLevelCanvasGroup.alpha; float t = 0f; while(t < localWaterLevelShowSpeed) { t += Time.deltaTime; waterLevelCanvasGroup.alpha = Mathf.Lerp(startValue, targetValue, t / localWaterLevelShowSpeed); yield return null; } waterLevelCanvasGroup.alpha = targetValue; localWaterLevelShowFunc = null; } private IEnumerator DrainWater() { while(IsActive && waterLevel > 0f) { waterLevel = Mathf.Clamp01(waterLevel - Time.fixedDeltaTime * waterDrainSpeed); UpdateWaterLevelUI(); if (waterLevel == 0f) { StopWaterHose(); } yield return null; } } public void PumpWater(float value) { if (waterLevel < 1f) { waterLevel = Mathf.Clamp01(waterLevel + value * waterPumpingSpeed); UpdateWaterLevelUI(); } } }