GazeProject/Assets/EYE ADVANCED/Scripts/EyeUnlockSequence.cs
2025-05-15 15:19:18 +02:00

321 lines
8.5 KiB
C#

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<EyeInteractable>();
meshRenderer = GetComponent<MeshRenderer>();
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<EyeInteractable>();
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);
}
}