using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Sirenix.OdinInspector; using UnityEngine; namespace Beyond { public class CharacterVisibilityController : MonoBehaviour { public enum State { NORMAL, GHOST, INVISIBLE, UNINITIALIZED }; [Serializable] public struct ShaderValues { public float alpha; public float invisibility; public float fresnelPower; [ColorUsageAttribute(true, true, 0f, 8f, 0.125f, 3f)] public Color fresnelColor; public ShaderValues(float alpha, float invisibility, float fresnelPower, Color c) { fresnelColor = c; this.alpha = alpha; this.invisibility = invisibility; this.fresnelPower = 4f; } public ShaderValues Lerp(ShaderValues val, float t) { ShaderValues res; res.alpha = Mathf.Lerp(alpha, val.alpha, t); res.invisibility = Mathf.Lerp(invisibility, val.invisibility, t); res.fresnelPower = Mathf.Lerp(fresnelPower, val.fresnelPower, t); res.fresnelColor = Color.Lerp(fresnelColor, val.fresnelColor, t); return res; } } public bDamageModifierController m_damageModifierContoller; private const string NormalDamageModifierName = "NormalDamage", GhostDamageModifierName = "GhostDamage"; private const int ghostDamagePercentage = 0, normalDamagePercentage = -100; public ShaderValues m_NormalShaderValue = new ShaderValues(1f, 0f, 4f, Color.black); public ShaderValues m_GhostShaderValue = new ShaderValues(0.5f, 0f, 4f, new Color(0f, 1.5f, 2f)); public ShaderValues m_InvisibleShaderValue = new ShaderValues(0.4f, 10f, 4f, new Color(0f, 0.15f, 0.2f)); public ShaderValues m_currentValues; public ShaderValues m_previousValues; public ShaderValues m_targetValues; public State m_currentState = State.UNINITIALIZED; private State m_targetState = State.NORMAL; public State m_startingState = State.NORMAL; public float m_transitionTime = 5f; private float m_timer = 0f; /* public float m_targetAlpha = 0.5f; [ColorUsageAttribute(true,true,0f,8f,0.125f,3f)] public Color m_targetFresnelColor = new Color(0f, 1f, 2f); public float m_targetFresnelPower = 4f; public float m_targetInvisibility = 0f; */ public List gameObjectsToExclideFromChange; private List renderersToExcludeFromChange = new List(); [OnValueChanged("SetAlpha")] public float m_alpha = 0f; [ColorUsageAttribute(true, true, 0f, 8f, 0.125f, 3f)] [OnValueChanged("SetFresnelColor")] public Color m_fresnelColor = new Color(0.5f, 0.5f, 2f); [OnValueChanged("SetFresnelPower")] public float m_fresnelPower = 4f; [OnValueChanged("SetCutoffThreshold")] public float m_dissolveTh = 0f; [OnValueChanged("SetInvisibility")] public float m_invisibility = 0f; private bool m_inTransition = false; private List m_materials; private Shader m_transparent; private Shader m_opaque; private int m_thresholID = Shader.PropertyToID("_Threshold"); private int m_baseColorID = Shader.PropertyToID("_BaseColor"); private int m_FresnelColorID = Shader.PropertyToID("_FresnelColor"); private int m_FresnelPowerID = Shader.PropertyToID("FresnelPower"); private int m_InvisibilityID = Shader.PropertyToID("_Invisibility"); private bool m_usesTransparent = false; private void InitMaterials() { if (m_materials != null && m_materials.Count > 0) return; var renderers = GetComponentsInChildren().ToList(); if (gameObjectsToExclideFromChange.Count > 0) { gameObjectsToExclideFromChange.ForEach(gameObject => renderersToExcludeFromChange.AddRange(gameObject.GetComponentsInChildren().ToList())); renderers.RemoveAll(item => renderersToExcludeFromChange.Contains(item)); } m_materials = new List(); foreach (var r in renderers) { foreach (var m in r.materials) m_materials.Add(m); } var rdr = GetComponent(); if (rdr) { foreach (var m in rdr.materials) m_materials.Add(m); } m_transparent = Shader.Find("Shader Graphs/BeyondLitTransparent"); //m_transparent if (m_transparent == null) { Debug.LogError("Transparent shader not found!"); } m_opaque = Shader.Find("Shader Graphs/BeyondLit"); if (m_opaque == null) { Debug.LogError("Opaque shader not found!"); } } private ShaderValues GetValuesForState(State s) { ShaderValues v = m_NormalShaderValue; switch (s) { case State.NORMAL: v = m_NormalShaderValue; break; case State.GHOST: v = m_GhostShaderValue; break; case State.INVISIBLE: v = m_InvisibleShaderValue; break; } return v; } private void SetValues(ShaderValues val) { foreach (var m in m_materials) { Color c = m.GetColor(m_baseColorID); c.a = val.alpha; m.SetColor(m_baseColorID, c); m.SetColor(m_FresnelColorID, val.fresnelColor); m.SetFloat(m_FresnelPowerID, val.fresnelPower); m.SetFloat(m_InvisibilityID, val.invisibility); } } private void SetAlpha() { #if UNITY_EDITOR InitMaterials(); #endif foreach (var m in m_materials) { Color c = m.GetColor(m_baseColorID); c.a = m_alpha; m.SetColor(m_baseColorID, c); } } private void SetFresnelColor() { #if UNITY_EDITOR InitMaterials(); #endif foreach (var m in m_materials) { m.SetColor(m_FresnelColorID, m_fresnelColor); } } private void SetFresnelPower() { #if UNITY_EDITOR InitMaterials(); #endif foreach (var m in m_materials) { m.SetFloat(m_FresnelPowerID, m_fresnelPower); } } private void SetCutoffThreshold() { #if UNITY_EDITOR InitMaterials(); #endif foreach (var m in m_materials) { m.SetFloat(m_thresholID, m_dissolveTh); } } private void SetInvisibility() { #if UNITY_EDITOR InitMaterials(); #endif foreach (var m in m_materials) { m.SetFloat(m_InvisibilityID, m_invisibility); } } [Button] public void SetNormalState() { SetState(State.NORMAL); } [Button] public void SetGhostState() { SetState(State.GHOST); } [Button] public void SetInvisibleState() { SetState(State.INVISIBLE); } [Button] public void SetTransparentShader() { if (m_usesTransparent) return; #if UNITY_EDITOR InitMaterials(); #endif foreach (var m in m_materials) { m.shader = m_transparent; } m_usesTransparent = true; } [Button] public void SetOpaqueShader() { if (!m_usesTransparent) return; #if UNITY_EDITOR InitMaterials(); #endif foreach (var m in m_materials) { m.shader = m_opaque; } m_usesTransparent = false; } public void SetState(State state) { if (state == m_currentState) { return; } if (m_currentState == State.UNINITIALIZED) { m_previousValues = m_currentValues = GetValuesForState(state); SetValues(m_currentValues); m_currentState = m_targetState = state; ManageStatesBehaviour(state); return; } //m_targetValues m_targetState = state; m_previousValues = m_targetValues; m_timer = 0f; m_targetValues = GetValuesForState(state); ManageStatesBehaviour(state); } private void ManageStatesBehaviour(State state) { switch (state) { case State.NORMAL: EnableAllDamage(); break; case State.GHOST: DisableAllDamageExceptGhost(); SetTransparentShader(); break; case State.INVISIBLE: SetTransparentShader(); break; } } private void EnableAllDamage() { if (!m_damageModifierContoller) { return; } m_damageModifierContoller.SetModifierPercentageDamage(NormalDamageModifierName, 0); m_damageModifierContoller.SetModifierPercentageDamage(GhostDamageModifierName, 0); } private void DisableAllDamageExceptGhost() { if (!m_damageModifierContoller) { return; } m_damageModifierContoller.SetModifierPercentageDamage(NormalDamageModifierName, normalDamagePercentage); m_damageModifierContoller.SetModifierPercentageDamage(GhostDamageModifierName, ghostDamagePercentage); } private void Update() { if (m_currentState != m_targetState) { if (m_timer > m_transitionTime) { m_currentState = m_targetState; m_currentValues = m_targetValues; switch (m_targetState) { case State.NORMAL: SetOpaqueShader(); break; case State.GHOST: break; case State.INVISIBLE: break; } } else { m_previousValues = GetValuesForState(m_currentState); m_currentValues = m_previousValues.Lerp(m_targetValues, m_timer / m_transitionTime); m_timer += Time.deltaTime; } SetValues(m_currentValues); } } private void Start() { m_currentState = State.UNINITIALIZED; InitMaterials(); SetState(m_startingState); } } }