using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; [CreateAssetMenu(fileName = "VisualStyle", menuName = "UniQuake/Visual Style", order = 1)] public class VisualStyle : ScriptableObject { [SerializeField] protected Material entityMaterial; [SerializeField] protected Material worldMaterial; // TODO: split into wall, liquid, sky, etc [SerializeField] protected Material liquidMaterial; [SerializeField] protected bool pointSampling; [SerializeField] protected bool affineTexturing; [SerializeField] protected LiquidProperties liquidProperties = new LiquidProperties(); [SerializeField] protected ParticleSystems particles = new ParticleSystems(); public ParticleSystems Particles => particles; public virtual void Activate() { if (pointSampling) Shader.EnableKeyword("_POINT_SAMPLING"); else Shader.DisableKeyword("_POINT_SAMPLING"); } public virtual Material CreateEntityMaterial(bool aliasModel) { var material = new Material(entityMaterial); if (aliasModel && affineTexturing) material.EnableKeyword("_AFFINE_ON"); else material.DisableKeyword("_AFFINE_ON"); return material; } public virtual Material CreateWorldMaterial(QSurfaceFlags surfaceFlags) { Material material; if (surfaceFlags.HasFlag(QSurfaceFlags.DrawTurbulence) && liquidMaterial != null) { float alpha = 1f; if (surfaceFlags.HasFlag(QSurfaceFlags.DrawWater)) alpha = liquidProperties.waterAlpha; else if (surfaceFlags.HasFlag(QSurfaceFlags.DrawSlime)) alpha = liquidProperties.slimeAlpha; else if (surfaceFlags.HasFlag(QSurfaceFlags.DrawLava)) alpha = liquidProperties.lavaAlpha; else if (surfaceFlags.HasFlag(QSurfaceFlags.DrawTeleporter)) alpha = liquidProperties.teleAlpha; material = new Material(liquidMaterial); material.SetColor("_BaseColor", new Color(1, 1, 1, alpha)); } else { material = new Material(worldMaterial); } if (surfaceFlags.HasFlag(QSurfaceFlags.DrawFence)) { material.EnableKeyword("_ALPHATEST_ON"); } return material; } public virtual void SetupEntityRenderer(MeshRenderer meshRenderer) { meshRenderer.shadowCastingMode = ShadowCastingMode.Off; meshRenderer.receiveShadows = false; meshRenderer.lightProbeUsage = LightProbeUsage.Off; meshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off; } public virtual void SetupEntityRenderer(SkinnedMeshRenderer skinnedMeshRenderer) { skinnedMeshRenderer.shadowCastingMode = ShadowCastingMode.Off; skinnedMeshRenderer.receiveShadows = false; skinnedMeshRenderer.lightProbeUsage = LightProbeUsage.Off; skinnedMeshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off; } public virtual void SetupWorldRenderer(MeshRenderer meshRenderer) { meshRenderer.shadowCastingMode = ShadowCastingMode.Off; meshRenderer.receiveShadows = false; meshRenderer.lightProbeUsage = LightProbeUsage.Off; meshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off; } public virtual void SetEntityTextures(Material material, Texture2D mainTexture, Texture2D fullBright) { material.mainTexture = mainTexture; material.SetTexture("_EmissionMap", fullBright); material.SetColor("_EmissionColor", Color.white); if (fullBright != null) material.EnableKeyword("_EMISSION"); else material.DisableKeyword("_EMISSION"); } public virtual void SetWorldTextures(Material material, Texture2D mainTexture, Texture2D fullBright, Texture2D lightmap) { material.mainTexture = mainTexture; material.SetTexture("_EmissionMap", fullBright); material.SetColor("_EmissionColor", Color.white); if (fullBright != null) material.EnableKeyword("_EMISSION"); else material.DisableKeyword("_EMISSION"); material.SetTexture("_LightMap", lightmap); if (lightmap != null) material.EnableKeyword("_QLIGHTMAP_ON"); else material.DisableKeyword("_QLIGHTMAP_ON"); } } [System.Serializable] public class LiquidProperties { [Range(0, 1)] public float waterAlpha = 0.85f, slimeAlpha = 0.9f, lavaAlpha = 0.95f, teleAlpha = 1.0f; } [System.Serializable] public class ParticleSystems { [SerializeField] protected ParticleSystem explosion; public virtual void CreateExplosion(Vector3 position, Layers layer) { if (explosion == null) return; var go = Object.Instantiate(explosion.gameObject); go.transform.position = position; SetLayer(go, layer); } protected static void SetLayer(GameObject go, Layers layer) { go.layer = (int)layer; int childCount = go.transform.childCount; for (int i = 0; i < childCount; ++i) { go.transform.GetChild(i).gameObject.layer = (int)layer; } } }