using System; using System.Collections.Generic; using ConformalDecals.Text; using ConformalDecals.Util; using TMPro; using UniLinq; using UnityEngine; namespace ConformalDecals { public static class DecalConfig { private static Texture2D _blankNormal; private static List _shaderBlacklist; private static Dictionary _fontList; private static int _decalLayer = 31; private static bool _selectableInFlight; private static string _fallbackFontName = "NotoSans-Regular SDF"; private struct LegacyShaderEntry { public string name; public string[] keywords; } private static readonly Dictionary LegacyShaderPairs = new Dictionary() { ["ConformalDecals/Feature/Bumped"] = new LegacyShaderEntry() { name = "ConformalDecals/Decal/Standard", keywords = new[] {"DECAL_BUMPMAP"} }, ["ConformalDecals/Paint/Diffuse"] = new LegacyShaderEntry() { name = "ConformalDecals/Decal/Standard", keywords = new string[] { } }, ["ConformalDecals/Paint/Specular"] = new LegacyShaderEntry() { name = "ConformalDecals/Decal/Standard", keywords = new[] {"DECAL_SPECMAP"} }, ["ConformalDecals/Paint/DiffuseSDF"] = new LegacyShaderEntry() { name = "ConformalDecals/Decal/Standard", keywords = new[] {"DECAL_SDF_ALPHA"} }, ["ConformalDecals/Paint/SpecularSDF"] = new LegacyShaderEntry() { name = "ConformalDecals/Decal/Standard", keywords = new[] {"DECAL_SDF_ALPHA", "DECAL_SPECMAP"} }, }; public static Texture2D BlankNormal => _blankNormal; public static int DecalLayer => _decalLayer; public static bool SelectableInFlight => _selectableInFlight; public static IEnumerable Fonts => _fontList.Values; public static TMP_FontAsset FallbackFont { get; private set; } public static bool IsBlacklisted(Shader shader) { return IsBlacklisted(shader.name); } public static bool IsBlacklisted(string shaderName) { return _shaderBlacklist.Contains(shaderName); } public static bool IsLegacy(string shaderName, out string newShader, out string[] keywords) { if (LegacyShaderPairs.TryGetValue(shaderName, out var entry)) { newShader = entry.name; keywords = entry.keywords; return true; } newShader = null; keywords = null; return false; } public static DecalFont GetFont(string name) { if (_fontList.TryGetValue(name, out var font)) { return font; } else { throw new KeyNotFoundException($"Font {name} not found"); } } private static void ParseConfig(ConfigNode node) { ParseUtil.ParseIntIndirect(ref _decalLayer, node, "decalLayer"); ParseUtil.ParseBoolIndirect(ref _selectableInFlight, node, "selectableInFlight"); foreach (var blacklist in node.GetNodes("SHADERBLACKLIST")) { foreach (var shaderName in blacklist.GetValuesList("shader")) { _shaderBlacklist.Add(shaderName); } } var allFonts = Resources.FindObjectsOfTypeAll(); ParseUtil.ParseStringIndirect(ref _fallbackFontName, node, "fallbackFont"); FallbackFont = allFonts.First(o => o.name == _fallbackFontName); if (FallbackFont == null) Logging.LogError($"could not find find fallback font asset named {_fallbackFontName}"); foreach (var fontNode in node.GetNodes("FONT")) { try { var name = ParseUtil.ParseString(fontNode, "name"); if (string.IsNullOrEmpty(name)) throw new FormatException(); var fontAsset = allFonts.First(o => o.name == name); if (fontAsset == null) throw new FormatException($"Could not find font asset named {name}"); if (!fontAsset.fallbackFontAssets.Contains(FallbackFont)) { fontAsset.fallbackFontAssets.Add(FallbackFont); } var font = new DecalFont(name, fontNode, fontAsset); _fontList.Add(font.Name, font); } catch (Exception e) { Logging.LogException($"Exception parsing font node:\n{fontNode.ToString()}\n", e); } } } private static Texture2D MakeBlankNormal() { Logging.Log("Generating neutral normal map texture"); var width = 2; var height = 2; var color = new Color32(255, 128, 128, 128); var colors = new[] {color, color, color, color}; var tex = new Texture2D(width, height, TextureFormat.RGBA32, false); for (var x = 0; x <= width; x++) { for (var y = 0; y < height; y++) { tex.SetPixels32(colors); } } tex.Apply(); return tex; } // ReSharper disable once UnusedMember.Global public static void ModuleManagerPostLoad() { _shaderBlacklist = new List(); _fontList = new Dictionary(); var configs = GameDatabase.Instance.GetConfigs("CONFORMALDECALS"); if (configs.Length > 0) { Logging.Log("loading config"); foreach (var config in configs) { ParseConfig(config.config); } } // setup physics for decals, ignore collision with everything Physics.IgnoreLayerCollision(_decalLayer, 1, true); // default Physics.IgnoreLayerCollision(_decalLayer, 17, true); // EVA Physics.IgnoreLayerCollision(_decalLayer, 19, true); // PhysicalObjects Physics.IgnoreLayerCollision(_decalLayer, 23, true); // AeroFXIgnore Physics.IgnoreLayerCollision(_decalLayer, 26, true); // wheelCollidersIgnore Physics.IgnoreLayerCollision(_decalLayer, 27, true); // wheelColliders _blankNormal = MakeBlankNormal(); } } }