Files
beyond/Assets/Scripts/Characters/CharacterVisibilityController.cs

384 lines
12 KiB
C#

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<GameObject> gameObjectsToExclideFromChange;
private List<Renderer> renderersToExcludeFromChange = new List<Renderer>();
[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<Material> 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<Renderer>().ToList();
if (gameObjectsToExclideFromChange.Count > 0)
{
gameObjectsToExclideFromChange.ForEach(gameObject => renderersToExcludeFromChange.AddRange(gameObject.GetComponentsInChildren<Renderer>().ToList()));
renderers.RemoveAll(item => renderersToExcludeFromChange.Contains(item));
}
m_materials = new List<Material>();
foreach (var r in renderers)
{
foreach (var m in r.materials)
m_materials.Add(m);
}
var rdr = GetComponent<Renderer>();
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);
}
}
}