forked from cgvr/DeltaVR
		
	
		
			
				
	
	
		
			382 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			382 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using _PROJECT.NewHandPresence;
 | 
						|
using System.Collections;
 | 
						|
using System.Collections.Generic;
 | 
						|
using Unity.XR.CoreUtils;
 | 
						|
using UnityEditor;
 | 
						|
using UnityEngine;
 | 
						|
public enum ElevatorState
 | 
						|
{
 | 
						|
    Stationary,
 | 
						|
    OpeningDoors,
 | 
						|
    AwaitingPassengers,
 | 
						|
    ClosingDoors,
 | 
						|
    Moving
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
public class ElevatorBox : MonoBehaviour
 | 
						|
{
 | 
						|
    public List<ElevatorOuter> callers = new List<ElevatorOuter>();
 | 
						|
 | 
						|
    public GameObject leftDoor;
 | 
						|
    public Transform leftDoorOpenPos;
 | 
						|
    public Transform leftDoorClosedPos;
 | 
						|
 | 
						|
    public GameObject rightDoor;
 | 
						|
    public Transform rightDoorOpenPos;
 | 
						|
    public Transform rightDoorClosedPos;
 | 
						|
 | 
						|
    public float doorOpenTime = 4f;
 | 
						|
    public float doorCloseTime = 5.6f;
 | 
						|
    public float floorMoveTime = 5f;
 | 
						|
    public float doorStayOpenTime = 2f;
 | 
						|
 | 
						|
    [System.Serializable]
 | 
						|
    public struct FloorData
 | 
						|
    {
 | 
						|
        public int floorNumber;      // can be -1, 0, 1, 2 ...
 | 
						|
        public Transform floorPoint; // reference to the transform in scene
 | 
						|
    }
 | 
						|
 | 
						|
    // Unity can display arrays/lists of this struct in Inspector
 | 
						|
    public FloorData[] floors;
 | 
						|
 | 
						|
    // Runtime dictionary for quick lookup
 | 
						|
    private Dictionary<int, Transform> floorDict = new Dictionary<int, Transform>();
 | 
						|
    [System.Serializable]
 | 
						|
    public struct FloorNumbers
 | 
						|
    {
 | 
						|
        public int floorNumber;
 | 
						|
        public GameObject floorNumberSprite;
 | 
						|
    }
 | 
						|
 | 
						|
    public List<FloorNumbers> floorDisplayNumbers;
 | 
						|
 | 
						|
    public AudioSource audioSource;
 | 
						|
 | 
						|
    public AudioClip[] openDoorsClips;
 | 
						|
    public AudioClip[] closeDoorsClips;
 | 
						|
    public AudioClip[] moveElevatorClips;
 | 
						|
 | 
						|
    private int currentFloor = 2;
 | 
						|
    private int targetFloor = 2;
 | 
						|
 | 
						|
    private ElevatorState state = ElevatorState.Stationary;
 | 
						|
 | 
						|
    void Awake()
 | 
						|
    {
 | 
						|
 | 
						|
        foreach (var f in floors)
 | 
						|
        {
 | 
						|
            if (!floorDict.ContainsKey(f.floorNumber))
 | 
						|
                floorDict.Add(f.floorNumber, f.floorPoint);
 | 
						|
        }
 | 
						|
 | 
						|
        
 | 
						|
    }
 | 
						|
    private void Start()
 | 
						|
    {
 | 
						|
        updateDisplayFloorNumber(currentFloor);
 | 
						|
 | 
						|
        foreach (ElevatorOuter caller in callers)
 | 
						|
            caller.statusPlate.UpdateDisplayFloorNumber(currentFloor);
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    public IEnumerator callElevator(int floor)
 | 
						|
    {
 | 
						|
        //Debug.Log("Calling Elevator");
 | 
						|
        Debug.Log(state);
 | 
						|
        if (state == ElevatorState.Stationary || state == ElevatorState.ClosingDoors)
 | 
						|
        {
 | 
						|
            Debug.Log(floor);
 | 
						|
            
 | 
						|
            if (floor != currentFloor) 
 | 
						|
            {
 | 
						|
                //Debug.Log("Started moving lift");
 | 
						|
                yield return StartCoroutine(CloseDoors());
 | 
						|
                targetFloor = floor;
 | 
						|
                yield return StartCoroutine(MoveToFloor(targetFloor));
 | 
						|
            }
 | 
						|
            else
 | 
						|
 | 
						|
                StartCoroutine(OpenDoors());
 | 
						|
 | 
						|
            SetState(ElevatorState.AwaitingPassengers);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    public void interestExpired()
 | 
						|
    {
 | 
						|
       if (state == ElevatorState.AwaitingPassengers)
 | 
						|
        {
 | 
						|
            if (IsElevatorEmpty())
 | 
						|
            {
 | 
						|
                StartCoroutine(CloseAndStationary());
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    private bool IsElevatorEmpty()
 | 
						|
    {
 | 
						|
        return this.GetComponentInChildren<XROrigin>() == null;
 | 
						|
    }
 | 
						|
 | 
						|
    private void SetState(ElevatorState newstate)
 | 
						|
    {
 | 
						|
        Debug.Log("Setting new state of " + newstate);
 | 
						|
        this.state = newstate;
 | 
						|
    }
 | 
						|
    private void OnTriggerEnter(Collider other)
 | 
						|
    {
 | 
						|
        XROrigin enteredPlayerVR = other.GetComponent<XROrigin>();
 | 
						|
        KbmController enteredPlayerKbm = other.GetComponent<KbmController>();
 | 
						|
 | 
						|
        Debug.Log("Player Entered box");
 | 
						|
        if (enteredPlayerVR != null)
 | 
						|
        {
 | 
						|
            addChild(enteredPlayerVR);
 | 
						|
        }
 | 
						|
        else if (enteredPlayerKbm != null)
 | 
						|
        {
 | 
						|
            enteredPlayerKbm.transform.SetParent(this.transform);
 | 
						|
        }
 | 
						|
        else 
 | 
						|
            return;
 | 
						|
 | 
						|
 | 
						|
            switch (targetFloor)
 | 
						|
            {
 | 
						|
                case int f when f == floors[0].floorNumber:
 | 
						|
                    targetFloor = floors[1].floorNumber;
 | 
						|
                    break;
 | 
						|
 | 
						|
                case int f when f == floors[1].floorNumber:
 | 
						|
                    targetFloor = floors[0].floorNumber;
 | 
						|
                    break;
 | 
						|
 | 
						|
                default:
 | 
						|
                    break;
 | 
						|
            }
 | 
						|
 | 
						|
        StartCoroutine(LiftTransferSequence());        
 | 
						|
    }
 | 
						|
 | 
						|
    
 | 
						|
    private void OnTriggerExit(Collider other)
 | 
						|
    {
 | 
						|
 | 
						|
        // Was it a player, that exited?
 | 
						|
        XROrigin exitedPlayerVR = other.GetComponent<XROrigin>();
 | 
						|
        KbmController exitedPlayerKbm = other.GetComponent<KbmController>();
 | 
						|
        if (exitedPlayerVR != null)
 | 
						|
        {
 | 
						|
            removeChild(exitedPlayerVR);
 | 
						|
        }
 | 
						|
        else if (exitedPlayerKbm != null)
 | 
						|
        {
 | 
						|
            exitedPlayerKbm.transform.SetParent(null);
 | 
						|
        }
 | 
						|
        else
 | 
						|
            return;
 | 
						|
 | 
						|
        Debug.Log("Player exited box, state is: " +  this.state);
 | 
						|
 | 
						|
        if (this.state == ElevatorState.AwaitingPassengers)
 | 
						|
        {
 | 
						|
            if (IsElevatorEmpty())
 | 
						|
            {
 | 
						|
                //Debug.Log("Elevator is empty");
 | 
						|
                StartCoroutine(CloseAndStationary());
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    private ElevatorOuter findTargetCaller()
 | 
						|
    {
 | 
						|
        //Debug.Log("finding target caller");
 | 
						|
        foreach (ElevatorOuter caller in this.callers)
 | 
						|
                {
 | 
						|
                    //Debug.Log(caller.floor);
 | 
						|
                    //Debug.Log(targetFloor);
 | 
						|
                    if (caller.floor == targetFloor)
 | 
						|
                    {
 | 
						|
                        //Debug.Log("found caller");
 | 
						|
                        return caller;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
        return null;
 | 
						|
    }
 | 
						|
    private ElevatorOuter findCurrentCaller()
 | 
						|
    {
 | 
						|
        //Debug.Log("finding target caller");
 | 
						|
        foreach (ElevatorOuter caller in this.callers)
 | 
						|
        {
 | 
						|
            //Debug.Log(caller.floor);
 | 
						|
            //Debug.Log(targetFloor);
 | 
						|
            if (caller.floor == this.currentFloor)
 | 
						|
            {
 | 
						|
                //Debug.Log("found caller");
 | 
						|
                return caller;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        return null;
 | 
						|
    }
 | 
						|
    
 | 
						|
    private void SetCurrentFloor(int floor) { 
 | 
						|
        this.currentFloor = floor;
 | 
						|
 | 
						|
        updateDisplayFloorNumber(floor);
 | 
						|
 | 
						|
        foreach (ElevatorOuter caller in callers)
 | 
						|
            caller.statusPlate.UpdateDisplayFloorNumber(floor);
 | 
						|
    }
 | 
						|
 | 
						|
    private void updateDisplayFloorNumber(int newValue)
 | 
						|
    {
 | 
						|
        foreach (var f in floorDisplayNumbers)
 | 
						|
        {
 | 
						|
            if (f.floorNumber != newValue) 
 | 
						|
                f.floorNumberSprite.SetActive(false);
 | 
						|
            else
 | 
						|
                f.floorNumberSprite.SetActive(true);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    public void addChild(XROrigin player)
 | 
						|
    {
 | 
						|
        player.transform.SetParent(this.transform);
 | 
						|
    }
 | 
						|
    public void removeChild(XROrigin player)
 | 
						|
    {
 | 
						|
        player.transform.SetParent(null);
 | 
						|
    }
 | 
						|
 | 
						|
    private void playRandomAudioClipFrom(AudioClip[] list)
 | 
						|
    {
 | 
						|
        if (list.Length == 0) return;
 | 
						|
 | 
						|
        int index = Random.Range(0, list.Length);
 | 
						|
        audioSource.clip = list[index];
 | 
						|
        audioSource.Play();
 | 
						|
    }
 | 
						|
 | 
						|
    private IEnumerator LiftTransferSequence()
 | 
						|
        {
 | 
						|
            yield return StartCoroutine(CloseDoors());
 | 
						|
            yield return StartCoroutine(MoveToFloor(targetFloor));
 | 
						|
        }
 | 
						|
    public IEnumerator MoveToFloor(int floorNumber)
 | 
						|
    {
 | 
						|
        Debug.Log("Moving to floor " + floorNumber);
 | 
						|
        
 | 
						|
        if (floorDict.TryGetValue(floorNumber, out Transform target))
 | 
						|
        {
 | 
						|
            yield return StartCoroutine(MoveElevator(target.position));
 | 
						|
            SetCurrentFloor(targetFloor);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            Debug.LogWarning($"No floor defined for number {floorNumber}");
 | 
						|
        }
 | 
						|
 | 
						|
        yield return StartCoroutine(OpenDoors());
 | 
						|
    }
 | 
						|
    private IEnumerator CloseAndStationary()
 | 
						|
    {
 | 
						|
        Debug.Log("Close and set stationary");
 | 
						|
        // Wait for CloseDoors() to finish
 | 
						|
        yield return StartCoroutine(CloseDoors());
 | 
						|
 | 
						|
        // After doors have closed, set state
 | 
						|
        SetState(ElevatorState.Stationary);
 | 
						|
    }
 | 
						|
 | 
						|
    private IEnumerator CloseDoors()
 | 
						|
    {
 | 
						|
        //if (state == ElevatorState.AwaitingPassengers) {
 | 
						|
        //Debug.Log("Closing doors");
 | 
						|
 | 
						|
        if (Vector3.Distance(leftDoor.transform.position, leftDoorClosedPos.position) < 0.01f)
 | 
						|
            yield break;
 | 
						|
 | 
						|
        SetState(ElevatorState.ClosingDoors);
 | 
						|
        playRandomAudioClipFrom(closeDoorsClips);
 | 
						|
 | 
						|
        ElevatorOuter currentCaller = findCurrentCaller();
 | 
						|
            
 | 
						|
        if (currentCaller != null) currentCaller.CloseDoors();
 | 
						|
 | 
						|
        yield return StartCoroutine(MoveDoors(leftDoor, leftDoorClosedPos, rightDoor, rightDoorClosedPos, doorCloseTime));
 | 
						|
        //}
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    private IEnumerator OpenDoors()
 | 
						|
    {
 | 
						|
        if (state != ElevatorState.AwaitingPassengers) {
 | 
						|
            //Debug.Log("Opening doors");
 | 
						|
            SetState(ElevatorState.OpeningDoors);
 | 
						|
            playRandomAudioClipFrom(openDoorsClips);
 | 
						|
            ElevatorOuter targetCaller = findTargetCaller();
 | 
						|
            //Debug.Log("Target caller is: " + targetCaller);
 | 
						|
            if (targetCaller != null) 
 | 
						|
                targetCaller.OpenDoors();
 | 
						|
 | 
						|
            yield return StartCoroutine(MoveDoors(leftDoor, leftDoorOpenPos, rightDoor, rightDoorOpenPos, doorOpenTime));
 | 
						|
 | 
						|
            
 | 
						|
            SetState(ElevatorState.AwaitingPassengers);
 | 
						|
            yield return new WaitForSeconds(doorStayOpenTime); // wait for passengers
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    private IEnumerator MoveDoors(GameObject left, Transform targetLeft, GameObject right, Transform targetRight, float moveTime)
 | 
						|
    {
 | 
						|
        Debug.Log("Moving doors");
 | 
						|
        Vector3 startL = left.transform.position;
 | 
						|
        Vector3 startR = right.transform.position;
 | 
						|
        float t = 0;
 | 
						|
 | 
						|
        while (t < 1f)
 | 
						|
        {
 | 
						|
            t += Time.deltaTime / moveTime;
 | 
						|
            float easedT = Mathf.SmoothStep(0f, 1f, t); // ease in/out
 | 
						|
            left.transform.position = Vector3.Lerp(startL, targetLeft.position, easedT);
 | 
						|
            right.transform.position = Vector3.Lerp(startR, targetRight.position, easedT);
 | 
						|
            yield return null;
 | 
						|
        }
 | 
						|
        //Debug.Log("Inner Doors moved");
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    private IEnumerator MoveElevator(Vector3 targetPos)
 | 
						|
    {
 | 
						|
        if (targetFloor > currentFloor) 
 | 
						|
            foreach (ElevatorOuter caller in callers)       
 | 
						|
                caller.statusPlate.SetMoveState(ElevatorMoveState.Ascending);
 | 
						|
 | 
						|
        else
 | 
						|
            foreach (ElevatorOuter caller in callers)
 | 
						|
                caller.statusPlate.SetMoveState(ElevatorMoveState.Decending);
 | 
						|
 | 
						|
        Vector3 startPos = transform.position;
 | 
						|
        float t = 0;
 | 
						|
        
 | 
						|
        SetState(ElevatorState.Moving);
 | 
						|
        playRandomAudioClipFrom(moveElevatorClips);
 | 
						|
 | 
						|
        while (t < 1f)
 | 
						|
        {
 | 
						|
            t += Time.deltaTime / floorMoveTime;
 | 
						|
            float easedT = Mathf.SmoothStep(0f, 1f, t); // ease in/out
 | 
						|
            transform.position = Vector3.Lerp(startPos, targetPos, easedT);
 | 
						|
            yield return null;
 | 
						|
        }
 | 
						|
 | 
						|
        foreach (ElevatorOuter caller in callers)
 | 
						|
            caller.statusPlate.SetMoveState(ElevatorMoveState.NotMoving);
 | 
						|
    }
 | 
						|
}
 |