diff --git a/Chroma/EnvironmentEnhancement/GeometryFactory.cs b/Chroma/EnvironmentEnhancement/GeometryFactory.cs index c39891c7..04fec1bb 100644 --- a/Chroma/EnvironmentEnhancement/GeometryFactory.cs +++ b/Chroma/EnvironmentEnhancement/GeometryFactory.cs @@ -77,12 +77,7 @@ internal GameObject Create(CustomData customData) bool collision = customData.Get(_v2 ? V2_COLLISION : COLLISION) ?? false; object materialData = customData.GetRequired(_v2 ? V2_MATERIAL : MATERIAL); - MaterialsManager.MaterialInfo materialInfo = materialData switch - { - string name => _materialsManager.MaterialInfos[name], - CustomData data => _materialsManager.CreateMaterialInfo(data), - _ => throw new InvalidOperationException($"Could not read [{MATERIAL}].") - }; + MaterialsManager.MaterialInfo materialInfo = _materialsManager.GetMaterial(materialData); ShaderType shaderType = materialInfo.ShaderType; PrimitiveType primitiveType = geometryType switch diff --git a/Chroma/EnvironmentEnhancement/MaterialsManager.cs b/Chroma/EnvironmentEnhancement/MaterialsManager.cs index 232ce967..51bdd8fb 100644 --- a/Chroma/EnvironmentEnhancement/MaterialsManager.cs +++ b/Chroma/EnvironmentEnhancement/MaterialsManager.cs @@ -5,6 +5,7 @@ using Heck.Animation; using IPA.Utilities; using JetBrains.Annotations; +using Newtonsoft.Json; using UnityEngine; using Zenject; using static Chroma.ChromaController; @@ -54,6 +55,8 @@ private MaterialsManager( internal Dictionary MaterialInfos { get; } = new(); + internal Dictionary ReuseMaterials { get; } = new(); // grrr mappers + public void Dispose() { foreach (Material createdMaterial in _createdMaterials) @@ -92,6 +95,30 @@ internal MaterialInfo CreateMaterialInfo(CustomData customData) return materialInfo; } + + internal MaterialInfo GetMaterial(object materialData) + { + if (materialData is string name) + { + return MaterialInfos[name]; + } + + if (materialData is not CustomData data) + { + throw new InvalidOperationException($"Could not read [{MATERIAL}]."); + } + + string json = JsonConvert.SerializeObject(data); + if (ReuseMaterials.TryGetValue(json, out MaterialInfo m)) + { + return m; + } + + MaterialInfo materialInfo = CreateMaterialInfo(data); + ReuseMaterials[json] = materialInfo; + return materialInfo; + } + private static Material InstantiateSharedMaterial(ShaderType shaderType) { return new Material(Shader.Find(shaderType switch