using NewHorizons.Builder.Body.Geometry; using NewHorizons.External.Modules; using NewHorizons.Utility; using NewHorizons.Utility.Files; using OWML.Common; using System.Collections.Generic; using UnityEngine; namespace NewHorizons.Builder.Body { public static class ProcGenBuilder { private static Material _material; private static Shader _planetShader; private static Dictionary _materialCache = new(); public static void ClearCache() { foreach (var material in _materialCache.Values) { Object.Destroy(material); } _materialCache.Clear(); } private static Material MakeMaterial() { var material = new Material(_planetShader); var keyword = "BASE_TILE"; var prefix = "_BaseTile"; material.SetFloat(prefix, 1); material.EnableKeyword(keyword); material.SetTexture("_BlendMap", ImageUtilities.MakeSolidColorTexture(1, 1, Color.white)); return material; } public static GameObject Make(IModBehaviour mod, GameObject planetGO, Sector sector, ProcGenModule module) { if (_planetShader == null) _planetShader = AssetBundleUtilities.NHAssetBundle.LoadAsset("Assets/Shaders/SphereTextureWrapperTriplanar.shader"); if (_material == null) _material = MakeMaterial(); var icosphere = new GameObject("Icosphere"); icosphere.SetActive(false); icosphere.transform.parent = sector?.transform ?? planetGO.transform; icosphere.transform.rotation = Quaternion.Euler(90, 0, 0); icosphere.transform.position = planetGO.transform.position; Mesh mesh = Icosphere.Build(4, module.scale, module.scale * 1.2f); icosphere.AddComponent().mesh = mesh; var cubeSphereMR = icosphere.AddComponent(); if (!_materialCache.TryGetValue(module, out var material)) { material = new Material(_material); material.name = planetGO.name; if (module.material == ProcGenModule.Material.Default) { if (!string.IsNullOrEmpty(module.texturePath)) { material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(mod, module.texturePath, wrap: true)); } else { material.mainTexture = ImageUtilities.MakeSolidColorTexture(1, 1, module.color?.ToColor() ?? Color.white); } } else { switch (module.material) { case ProcGenModule.Material.Ice: material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(Main.Instance, "Assets/textures/Ice.png", wrap: true)); break; case ProcGenModule.Material.Quantum: material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(Main.Instance, "Assets/textures/Quantum.png", wrap: true)); break; case ProcGenModule.Material.Rock: material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(Main.Instance, "Assets/textures/Rocks.png", wrap: true)); break; default: break; } material.SetFloat($"_BaseTileScale", 5 / module.scale); if (module.color != null) { material.color = module.color.ToColor(); } } material.SetFloat("_Smoothness", 0.1f); material.SetFloat("_Metallic", 0.1f); _materialCache[module] = material; } cubeSphereMR.sharedMaterial = material; var cubeSphereMC = icosphere.AddComponent(); cubeSphereMC.sharedMesh = mesh; icosphere.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(90, 0, 0)); var cubeSphereSC = icosphere.AddComponent(); cubeSphereSC.radius = module.scale; var superGroup = planetGO.GetComponent(); if (superGroup != null) icosphere.AddComponent()._superGroup = superGroup; icosphere.SetActive(true); return icosphere; } } }