using System.Collections; using UnityEngine; public class EyeUnlockSequence : MonoBehaviour { [SerializeField] private GameObject[] segmentSequence; [SerializeField] private float[] timeWindows; [Header("Initial Focus Requirement")] [SerializeField] private float initialFocusTime = 1f; [SerializeField] private GameObject focusIndicator; [Header("Visual Feedback")] [SerializeField] private Material completedMaterial; [SerializeField] private Material defaultMaterial; [SerializeField] private Material focusingMaterial; [SerializeField] private Material greenMaterial; [SerializeField] private Material redMaterial; [Header("Color State")] [SerializeField] private bool isGreen = false; [Header("Light Activation")] [SerializeField] private Light pointLightToActivate; [SerializeField] private bool startLightEnabled = false; [Header("Reset Parameters")] [SerializeField] private float resetHoldDuration = 1f; [SerializeField] private float resetCooldownTime = 1f; [Header("Manager Reference")] [SerializeField] private SequenceManagerLightTurnOn sequenceManager; private int currentStep = -1; private Coroutine sequenceCoroutine; private Coroutine focusCoroutine; private EyeInteractable eyeInteractable; private MeshRenderer meshRenderer; private bool isSequenceCompleted = false; private Material originalMaterial; private float hoverStartTime; private bool isResettingSequence = false; private float lastHoverEndTime; private bool isFocusTimeMet = false; private bool isCurrentlyFocusing = false; private float currentFocusTime = 0f; private void Start() { eyeInteractable = GetComponent(); meshRenderer = GetComponent(); if (meshRenderer != null) { originalMaterial = meshRenderer.material; UpdateMaterialBasedOnState(); // Respect starting green/red state } DeactivateAllSegments(); if (pointLightToActivate != null) pointLightToActivate.enabled = startLightEnabled; if (focusIndicator != null) focusIndicator.SetActive(false); } private void Update() { if (eyeInteractable != null) { if (eyeInteractable.IsHovered) { if (!isFocusTimeMet && !isCurrentlyFocusing) { StartFocusTimer(); } if (isFocusTimeMet) { if (currentStep == -1 && !isSequenceCompleted) { Debug.Log("▶ Starting sequence..."); currentStep = 0; StartNextSegment(); } if (isSequenceCompleted) { HandleSequenceReset(); } } } else { if (isCurrentlyFocusing) { CancelFocusTimer(); } if (isResettingSequence) { isResettingSequence = false; Debug.Log("Reset attempt cancelled."); } hoverStartTime = 0f; } } } private void StartFocusTimer() { isCurrentlyFocusing = true; currentFocusTime = 0f; if (focusIndicator != null) focusIndicator.SetActive(true); if (meshRenderer != null && focusingMaterial != null) meshRenderer.material = focusingMaterial; if (focusCoroutine != null) StopCoroutine(focusCoroutine); focusCoroutine = StartCoroutine(FocusTimerCoroutine()); } private IEnumerator FocusTimerCoroutine() { while (currentFocusTime < initialFocusTime) { if (!eyeInteractable.IsHovered) { CancelFocusTimer(); yield break; } currentFocusTime += Time.deltaTime; yield return null; } isFocusTimeMet = true; isCurrentlyFocusing = false; if (focusIndicator != null) focusIndicator.SetActive(false); UpdateMaterialBasedOnState(); focusCoroutine = null; } private void CancelFocusTimer() { isCurrentlyFocusing = false; currentFocusTime = 0f; if (focusCoroutine != null) { StopCoroutine(focusCoroutine); focusCoroutine = null; } if (focusIndicator != null) focusIndicator.SetActive(false); UpdateMaterialBasedOnState(); } private void HandleSequenceReset() { if (Time.time - lastHoverEndTime < resetCooldownTime) return; if (!isResettingSequence) { hoverStartTime = Time.time; isResettingSequence = true; } if (Time.time - hoverStartTime >= resetHoldDuration) { ResetSequenceCompletely(); currentStep = 0; StartNextSegment(); isResettingSequence = false; } } private void StartNextSegment() { if (isSequenceCompleted) return; if (currentStep >= segmentSequence.Length) { HandleSequenceCompleted(); return; } GameObject segment = segmentSequence[currentStep]; float timeout = (timeWindows.Length > currentStep) ? timeWindows[currentStep] : 3f; segment.SetActive(true); // show this segment if (sequenceCoroutine != null) StopCoroutine(sequenceCoroutine); sequenceCoroutine = StartCoroutine(HandleSegmentWithTimeout(segment, timeout)); } private IEnumerator HandleSegmentWithTimeout(GameObject segment, float timeLimit) { if (isSequenceCompleted) yield break; EyeInteractable segmentInteractable = segment.GetComponent(); if (segmentInteractable == null) { Debug.LogWarning($"{segment.name} missing EyeInteractable."); yield break; } float timer = 0f; bool success = false; while (timer < timeLimit) { if (segmentInteractable.IsHovered) { success = true; break; } timer += Time.deltaTime; yield return null; } // ✅ We do NOT deactivate the segment here anymore! // This allows previous segments to remain visible. if (success) { currentStep++; StartNextSegment(); } else { ResetSequence(); } } private void HandleSequenceCompleted() { isSequenceCompleted = true; lastHoverEndTime = Time.time; if (sequenceCoroutine != null) StopCoroutine(sequenceCoroutine); DeactivateAllSegments(); // optional — if you want to hide them after success // Toggle state and notify manager IsGreen = !IsGreen; if (sequenceManager != null) sequenceManager.NotifyCompleted(this.gameObject); isFocusTimeMet = false; } public void UpdateMaterialBasedOnState() { if (meshRenderer == null) return; if (isGreen && greenMaterial != null) meshRenderer.material = greenMaterial; else if (!isGreen && redMaterial != null) meshRenderer.material = redMaterial; else if (defaultMaterial != null) meshRenderer.material = defaultMaterial; else meshRenderer.material = originalMaterial; } public bool IsGreen { get => isGreen; set { isGreen = value; UpdateMaterialBasedOnState(); } } public void SetMaterials(Material green, Material red) { if (green != null) greenMaterial = green; if (red != null) redMaterial = red; } private void ResetSequence() { if (isSequenceCompleted) return; DeactivateAllSegments(); currentStep = -1; isFocusTimeMet = false; } private void ResetSequenceCompletely() { isSequenceCompleted = false; ResetSequence(); } private void DeactivateAllSegments() { foreach (var segment in segmentSequence) if (segment != null) segment.SetActive(false); } }