using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; using OHM.UnityToolkit; using UnityEngine.Serialization; namespace Ambiance { public class AmbianceController : UniqueInstance { [SerializeField] public AmbiancesDef ambiancesDef; [SerializeField] [FormerlySerializedAs("skyMatRef")] private Material _skyMatRef; [SerializeField] [FormerlySerializedAs("dirLight")] private Light _dirLight; private Camera camera; public Dictionary debugColors = new Dictionary(); public int changeAmbianceSectionCount = 1; private AmbianceDef _forcedAmbiance; private bool currentlyOnFire; public UnityEvent OnAmbianceChange; public AmbianceDef CurrentAmbiance { get; private set; } public AmbianceDef CurrentAmbianceToUse { get; private set; } public int CurrentLevelIdx { get; private set; } public int CurrentAmbianceIdx { get; private set; } public int CurrentAmbianceRealIdx { get; private set; } public Material SkyMat { get; private set; } public Dictionary SpecialMats { get; private set; } public bool Flip { get; set; } public string _debugSkyColorKey { get; private set; } = "debug_sky_color"; public string GetFlippedId(string id) { return id + "_f"; } protected override void AwakeInstance() { SpecialMats = new Dictionary(); foreach (SpecialMatDef def in ambiancesDef.specialsMatRef) { var mat = new Material(def.materialRef); mat.name = mat.name + "_" + def.id; SpecialMats[def.id] = mat; if (!def.flippable) { continue; } var flipped = new Material(def.materialRef); string flippedId = GetFlippedId(def.id); flipped.name = flipped.name + "_" + flippedId; flipped.mainTextureScale = new Vector2(flipped.mainTextureScale.x, 0f - flipped.mainTextureScale.y); SpecialMats[flippedId] = flipped; } if (_skyMatRef != null) { SkyMat = new Material(_skyMatRef); RenderSettings.skybox = SkyMat; } } public void UpdateCameraAmbiance(Camera camera) { this.camera = camera; SetAmbiance(CurrentAmbiance, currentlyOnFire); } public void ForceAmbiance(AmbianceDef amb) { _forcedAmbiance = amb; SetLevelIdx(CurrentLevelIdx, currentlyOnFire, forceReload: true); } public void SetLevelIdx(int levelIdx, bool onFire, bool forceReload) { if (!forceReload && CurrentLevelIdx == levelIdx && currentlyOnFire == onFire) { return; } CurrentLevelIdx = levelIdx; currentlyOnFire = onFire; if (_forcedAmbiance != null) { SetAmbiance(_forcedAmbiance, onFire); return; } CurrentAmbianceIdx = levelIdx / changeAmbianceSectionCount; List ambiances = ambiancesDef.GetAmbiancesList(); CurrentAmbianceRealIdx = CurrentAmbianceIdx % ambiances.Count; SetAmbiance(ambiances[CurrentAmbianceRealIdx], onFire); } public void TryAmbiance(AmbianceDef ambianceDef, bool onFire) { SetAmbiance(ambianceDef, onFire); } public Material GetSpecialMat(string id, bool allowFlip = false) { if (SpecialMats == null) { return null; } if (Flip && allowFlip) { string flippedId = GetFlippedId(id); if (SpecialMats.ContainsKey(flippedId)) { return SpecialMats[flippedId]; } } if (SpecialMats.ContainsKey(id)) { return SpecialMats[id]; } return null; } private void SetAmbiance(AmbianceDef def, bool fire) { CurrentAmbiance = def; AmbianceDef toUse = (fire && def != null && def.fireAmbiance != null) ? def.fireAmbiance : def; CurrentAmbianceToUse = toUse; if (toUse == null) { return; } RenderSettings.fogColor = toUse.fogColor; ApplySpecialColor(toUse); if (SkyMat != null) { if (debugColors.ContainsKey(_debugSkyColorKey)) { Color debugColor = debugColors[_debugSkyColorKey]; SkyMat.SetColor("_SkyColor1", debugColor); SkyMat.SetColor("_SkyColor2", debugColor); SkyMat.SetColor("_SkyColor3", debugColor); } else { SkyMat.SetTexture("_MainTex", def.skyPano); } } FogDistance fog = (def.fogDistance != null) ? def.fogDistance : ambiancesDef.defaultFogDistance; RenderSettings.fogStartDistance = fog.start; RenderSettings.fogEndDistance = fog.end; OnAmbianceChange.Invoke(); } private void ApplySpecialColor(AmbianceDef def) { if (def == null || def.specialColors == null) { return; } foreach (SpecialColorDef sc in def.specialColors) { Material mat = GetSpecialMat(sc.id); if (mat != null) { ApplySpecialColorToMat(mat, sc); } else { Debug.LogErrorFormat( "Ambiance {0} is trying to set undefined special material {1}. Please check ambiance or def", def.name, sc.id); } Material flipped = GetSpecialMat(GetFlippedId(sc.id)); if (flipped != null) { ApplySpecialColorToMat(flipped, sc); } } } private void ApplySpecialColorToMat(Material specMat, SpecialColorDef sc) { if (debugColors.ContainsKey(sc.id)) { Color debugColor = debugColors[sc.id]; specMat.SetColor("_TintColor", debugColor); specMat.SetColor("_ColorAdd", debugColor); specMat.SetColor("_EmissionColor", debugColor); specMat.mainTexture = null; return; } specMat.color = sc.color; if (specMat.HasProperty("_TintColor")) { specMat.SetColor("_TintColor", sc.color); } if (specMat.HasProperty("_ColorAdd")) { specMat.SetColor("_ColorAdd", sc.colorAdd); } if (specMat.HasProperty("_EmissionColor")) { specMat.EnableKeyword("_EMISSION"); specMat.SetColor("_EmissionColor", sc.colorEmission); } if (specMat.HasProperty("_EmissionMap") && sc.textureEmission != null) { specMat.SetTexture("_EmissionMap", sc.textureEmission); } if (sc.texture != null) { specMat.mainTexture = sc.texture; return; } SpecialMatDef matDef = ambiancesDef.specialsMatRef.Find((SpecialMatDef d) => d.id == sc.id); if (matDef != null) { specMat.mainTexture = matDef.materialRef.mainTexture; } } } }