eye-therapy-2 / Assets / Scripts / Builder / BuildingBehaviourAlt.cs
BuildingBehaviourAlt.cs
Raw
using System.Collections;
using UnityEngine;

public class BuildingBehaviourAlt : MonoBehaviour, IListener
{
    public Transform building;
    [SerializeField] Transform destination = null;
    [SerializeField] private Color wrongColor = new Color(1, 0, 0, 0.1f);
    [SerializeField] [ColorUsage(true, true)] private Color wrongOutglowColor = new Color(1, 0, 0, 0.1f);
    [SerializeField] private AnimationCurve colorChangeCurve = null;
    [SerializeField] [Min(0.1f)] private float wrongPosAnimTime = 0.5f;
    [SerializeField] [VectorRange(0f, 1f, 0f, 1f, true)] private Vector2[] visibilityLR = null;

    private bool buildDone = false;
    private Color mainColor;
    private Color outglowColor;
    private Material[] destinationMaterials;
    private Material[] buildingMaterials;
    private bool wrongCoroutineRunning = false;
    private Vector3 finalPosition;
    private Vector3 currentEulerAngles;

    void Start()
    {
        building.GetComponent<Renderer>().enabled = false;
        destination.GetComponent<Renderer>().enabled = true;

        Bounds b = building.GetComponent<Renderer>().bounds;
        destination.localScale = building.localScale * 1.01f;

        buildingMaterials = building.GetComponent<Renderer>().materials;
        for (int i = 0; i < buildingMaterials.Length; i++)
        {
            buildingMaterials[i].SetInt("_HighlightOn", 0);
        }
        destinationMaterials = destination.GetComponent<Renderer>().materials;
        mainColor = destinationMaterials[0].GetColor("_MainColor");
        outglowColor = destinationMaterials[0].GetColor("_OutGlowColor");
        currentEulerAngles = building.eulerAngles;

        EventManager.Instance.AddListener(EVENT_TYPE.ON_BUILDING_EYE_CHANGED, this);
        EventManager.Instance.AddListener(EVENT_TYPE.ON_BUILDING_DEST_EYE_CHANGED, this);
    }

    public void Init(Vector3? buildingPosition = null)
    {
        if (buildingPosition != null) building.position = buildingPosition.Value;
        for (int i = 0; i < buildingMaterials.Length; i++)
        {
            buildingMaterials[i].SetInt("_HighlightOn", 1);
        }
        building.GetComponent<Renderer>().enabled = true;
        building.GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
        finalPosition = destination.position;
    }

    public void CheckDistance(float distance)
    {
        if (Mathf.Abs(building.position.x - destination.position.x) <= distance && Mathf.Abs(building.position.z - destination.position.z) <= 0.05f)
        {
            EventManager.Instance.PostNotification<Object>(EVENT_TYPE.ON_BUILDING_BUILT, this);
            StopAllCoroutines();
            StartCoroutine(FinalizeBuild());
        }
        else
        {
            StartCoroutine(WrongPosColorAnim());
        }
    }

    public void Rotate()
    {
        currentEulerAngles += new Vector3(0, 90, 0);
        building.eulerAngles = currentEulerAngles;
        destination.eulerAngles = currentEulerAngles;
    }

    public void SetDestination(Vector3 pos)
    {
        destination.position = pos;
    }

    IEnumerator WrongPosColorAnim()
    {
        if (wrongCoroutineRunning) yield break;
        wrongCoroutineRunning = true;
        float t = 0f;
        while (t <= wrongPosAnimTime)
        {
            t += Time.deltaTime;
            float percent = Mathf.Clamp01(t / wrongPosAnimTime);
            float curvePercent = colorChangeCurve.Evaluate(percent);
            for (int i = 0; i < destinationMaterials.Length; i++)
            {
                destinationMaterials[i].SetColor("_MainColor", Color.LerpUnclamped(mainColor, wrongColor, curvePercent));
                destinationMaterials[i].SetColor("_OutGlowColor", Color.LerpUnclamped(outglowColor, wrongOutglowColor, curvePercent));
            }
            yield return null;
        }
        for (int i = 0; i < destinationMaterials.Length; i++)
        {
            destinationMaterials[i].SetColor("_MainColor", mainColor);
            destinationMaterials[i].SetColor("_OutGlowColor", outglowColor);
        }
        wrongCoroutineRunning = false;
    }

    IEnumerator FinalizeBuild()
    {
        buildDone = true;
        for (int i = 0; i < buildingMaterials.Length; i++)
        {
            buildingMaterials[i].SetInt("_HighlightOn", 0);
        }
        
        float t = 0f;
        Vector3 startPosition = building.position;
        float glow = destinationMaterials[0].GetFloat("_OutGlowSize");
        float buildingAlphaLeft = buildingMaterials[0].GetFloat("_AlphaLeftEye");
        float buildingAlphaRight = buildingMaterials[0].GetFloat("_AlphaRightEye");
        float destinationAlphaLeft = destinationMaterials[0].GetFloat("_AlphaLeftEye");
        float destinationAlphaRight = destinationMaterials[0].GetFloat("_AlphaRightEye");
        while (t <= 1f)
        {
            t += Time.deltaTime;
            building.position = Vector3.Lerp(startPosition, finalPosition, t);
            for (int i = 0; i < destinationMaterials.Length; i++)
            {
                destinationMaterials[i].SetFloat("_AlphaLeftEye", Mathf.Lerp(destinationAlphaLeft, 1f, t));
                destinationMaterials[i].SetFloat("_AlphaRightEye", Mathf.Lerp(destinationAlphaRight, 1f, t));
                destinationMaterials[i].SetColor("_MainColor", Color.Lerp(mainColor, Color.clear, t));
                destinationMaterials[i].SetFloat("_OutGlowSize", Mathf.Lerp(glow, 20f, t));
            }
            for (int i = 0; i < buildingMaterials.Length; i++)
            {
                buildingMaterials[i].SetFloat("_AlphaLeftEye", Mathf.Lerp(buildingAlphaLeft, 1f, t));
                buildingMaterials[i].SetFloat("_AlphaRightEye", Mathf.Lerp(buildingAlphaRight, 1f, t));
            }
            yield return null;
        }
        destination.GetComponent<Renderer>().enabled = false;
        building.GetComponent<Renderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;
    }

    public void OnEvent<T>(EVENT_TYPE eventType, Component Sender, T param = default)
    {
        switch (eventType)
        {
            case EVENT_TYPE.ON_BUILDING_EYE_CHANGED:
                if (!buildDone && (dynamic)param <= visibilityLR.Length)
                {
                    int idx = (dynamic)param;
                    for (int i = 0; i < buildingMaterials.Length; i++)
                    {
                        buildingMaterials[i].SetFloat("_AlphaLeftEye", visibilityLR[idx][0]);
                        buildingMaterials[i].SetFloat("_AlphaRightEye", visibilityLR[idx][1]);
                    }
                }
                break;
            case EVENT_TYPE.ON_BUILDING_DEST_EYE_CHANGED:
                if (!buildDone && (dynamic)param <= visibilityLR.Length)
                {
                    int idx = (dynamic)param;
                    for (int i = 0; i < destinationMaterials.Length; i++)
                    {
                        destinationMaterials[i].SetFloat("_AlphaLeftEye", visibilityLR[idx][0]);
                        destinationMaterials[i].SetFloat("_AlphaRightEye", visibilityLR[idx][1]);
                    }
                }
                break;
        }
    }
}