215 lines
9.1 KiB
C#
215 lines
9.1 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Cinemachine;
|
|
using UniRx;
|
|
using UnityEngine;
|
|
using static Unity.Mathematics.math;
|
|
using Unity.Mathematics;
|
|
using Random = UnityEngine.Random;
|
|
|
|
public class SectorRenderer : MonoBehaviour
|
|
{
|
|
public Transform FogCameraParent;
|
|
public GameSettings Settings;
|
|
public Transform SectorRoot;
|
|
public Transform SectorBrushes;
|
|
public MeshRenderer SectorBoundaryBrush;
|
|
public MeshRenderer MinimapGravityQuad;
|
|
public CinemachineVirtualCamera[] SceneCameras;
|
|
public Camera[] FogCameras;
|
|
public Camera[] MinimapCameras;
|
|
public Material FogMaterial;
|
|
public float FogFarFadeFraction = .125f;
|
|
public float FarPlaneDistanceMultiplier = 2;
|
|
public InstancedMesh[] AsteroidMeshes;
|
|
|
|
// public Mesh[] AsteroidMeshes;
|
|
// public Material AsteroidMaterial;
|
|
|
|
[Header("Prefabs")]
|
|
public PlanetObject Planet;
|
|
public GasGiantObject GasGiant;
|
|
public SunObject Sun;
|
|
|
|
[Header("Icons")]
|
|
public Texture2D PlanetoidIcon;
|
|
public Texture2D PlanetIcon;
|
|
|
|
private Dictionary<Guid, PlanetObject> _planets = new Dictionary<Guid, PlanetObject>();
|
|
private Dictionary<Guid, InstancedMesh[]> _beltMeshes = new Dictionary<Guid, InstancedMesh[]>();
|
|
private Zone _zone;
|
|
private float _viewDistance;
|
|
private float _maxDepth;
|
|
|
|
public float Time { get; set; }
|
|
|
|
public float ViewDistance
|
|
{
|
|
set
|
|
{
|
|
_viewDistance = value;
|
|
foreach (var camera in FogCameras)
|
|
camera.orthographicSize = value;
|
|
foreach(var camera in SceneCameras)
|
|
camera.m_Lens.FarClipPlane = value * FarPlaneDistanceMultiplier;
|
|
FogMaterial.SetFloat("_DepthCeiling", value);
|
|
FogMaterial.SetFloat("_DepthBlend", FogFarFadeFraction * value);
|
|
}
|
|
}
|
|
|
|
public float MinimapDistance
|
|
{
|
|
set
|
|
{
|
|
foreach(var camera in MinimapCameras)
|
|
camera.orthographicSize = value;
|
|
MinimapGravityQuad.transform.localScale = value * 2 * Vector3.one;
|
|
foreach (var planet in _planets.Values)
|
|
planet.Icon.transform.localScale = Settings.IconSize / 256 * value * Vector3.one;
|
|
}
|
|
}
|
|
|
|
void Start()
|
|
{
|
|
ViewDistance = Settings.DefaultViewDistance;
|
|
MinimapDistance = Settings.MinimapZoomLevels[Settings.DefaultMinimapZoom];
|
|
}
|
|
|
|
public void LoadZone(Zone zone)
|
|
{
|
|
_maxDepth = 0;
|
|
_zone = zone;
|
|
SectorBrushes.localScale = zone.Data.Radius * 2 * Vector3.one;
|
|
ClearZone();
|
|
foreach(var p in zone.Planets.Values)
|
|
LoadPlanet(p);
|
|
}
|
|
|
|
public void ClearZone()
|
|
{
|
|
if (_planets.Count > 0)
|
|
{
|
|
foreach (var planet in _planets.Values)
|
|
{
|
|
DestroyImmediate(planet.gameObject);
|
|
}
|
|
_planets.Clear();
|
|
_beltMeshes.Clear();
|
|
}
|
|
}
|
|
|
|
void LoadPlanet(BodyData planetData)
|
|
{
|
|
if (planetData is AsteroidBeltData beltData)
|
|
{
|
|
var meshes = AsteroidMeshes.ToList();
|
|
while(meshes.Count > Settings.AsteroidMeshCount)
|
|
meshes.RemoveAt(Random.Range(0,meshes.Count));
|
|
_beltMeshes[planetData.ID] = meshes.ToArray();
|
|
}
|
|
else
|
|
{
|
|
PlanetObject planet;
|
|
if (planetData is GasGiantData gasGiantData)
|
|
{
|
|
if (planetData is SunData sunData)
|
|
{
|
|
planet = Instantiate(Sun, SectorRoot);
|
|
var sun = (SunObject) planet;
|
|
sunData.LightColor.Subscribe(c => sun.Light.color = c);
|
|
sunData.Mass.Subscribe(m => sun.Light.range = Settings.PlanetSettings.LightRadius.Evaluate(m));
|
|
sunData.FogTintColor.Subscribe(c => sun.FogTint.material.SetColor("_Color", c));
|
|
sunData.Mass.Subscribe(m => sun.FogTint.transform.localScale = Settings.PlanetSettings.FogTintRadius.Evaluate(m) * Vector3.one);
|
|
}
|
|
else planet = Instantiate(GasGiant, SectorRoot);
|
|
|
|
var gas = (GasGiantObject) planet;
|
|
var gasGiant = _zone.PlanetInstances[planetData.ID] as GasGiant;
|
|
gasGiantData.Colors.Subscribe(c => gas.Body.material.SetTexture("_ColorRamp", c.ToGradient(!(planetData is SunData)).ToTexture()));
|
|
gasGiantData.AlbedoRotationSpeed.Subscribe(f => gas.SunMaterial.AlbedoRotationSpeed = f);
|
|
gasGiantData.FirstOffsetRotationSpeed.Subscribe(f => gas.SunMaterial.FirstOffsetRotationSpeed = f);
|
|
gasGiantData.SecondOffsetRotationSpeed.Subscribe(f => gas.SunMaterial.SecondOffsetRotationSpeed = f);
|
|
gasGiantData.FirstOffsetDomainRotationSpeed.Subscribe(f => gas.SunMaterial.FirstOffsetDomainRotationSpeed = f);
|
|
gasGiantData.SecondOffsetDomainRotationSpeed.Subscribe(f => gas.SunMaterial.SecondOffsetDomainRotationSpeed = f);
|
|
gasGiant.GravityWavesRadius.Subscribe(f => gas.GravityWaves.transform.localScale = f * Vector3.one);
|
|
gasGiant.GravityWavesDepth.Subscribe(f => gas.GravityWaves.material.SetFloat("_Depth", f));
|
|
planetData.Mass.Subscribe(f => gas.GravityWaves.material.SetFloat("_Frequency", Settings.PlanetSettings.WaveFrequency.Evaluate(f)));
|
|
//gas.WaveScroll.Speed = Properties.GravitySettings.WaveSpeed.Evaluate(f);
|
|
}
|
|
else
|
|
{
|
|
planet = Instantiate(Planet, SectorRoot);
|
|
//planet.Icon.material.mainTexture = planetData.Mass > Context.GlobalData.PlanetMass ? PlanetIcon : PlanetoidIcon;
|
|
}
|
|
|
|
var planetInstance = _zone.PlanetInstances[planetData.ID];
|
|
planetInstance.BodyRadius.Subscribe(f => planet.Body.transform.localScale = f * Vector3.one);
|
|
planetInstance.GravityWellRadius.Subscribe(f => planet.GravityWell.transform.localScale = f * Vector3.one);
|
|
planetInstance.GravityWellDepth.Subscribe(f =>
|
|
{
|
|
if (f > _maxDepth) _maxDepth = f;
|
|
planet.GravityWell.material.SetFloat("_Depth", f);
|
|
});
|
|
|
|
_planets.Add(planetData.ID, planet);
|
|
}
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
foreach(var belt in _zone.AsteroidBelts)
|
|
{
|
|
var meshes = _beltMeshes[belt.Key];
|
|
for (int i = 0; i < meshes.Length; i++)
|
|
{
|
|
var matrices = belt.Value.Transforms
|
|
.Skip((int) (((float)i / meshes.Length) * belt.Value.Transforms.Length))
|
|
.Take((int) (1f / meshes.Length * belt.Value.Transforms.Length))
|
|
.Select((v, x) => Matrix4x4.TRS(
|
|
new Vector3(v.x, _zone.GetHeight(v.xy), v.y),
|
|
Quaternion.Euler(cos(v.z + (float) i / meshes.Length) * 100, sin(v.z + (float) i / meshes.Length) * 100, (float)x/belt.Value.Transforms.Length * 360),
|
|
Vector3.one * v.w))
|
|
.ToArray();
|
|
Graphics.DrawMeshInstanced(meshes[i].Mesh, 0, meshes[i].Material, matrices);
|
|
}
|
|
}
|
|
|
|
foreach (var planet in _planets)
|
|
{
|
|
var planetInstance = _zone.PlanetInstances[planet.Key];
|
|
var p = _zone.GetOrbitPosition(planetInstance.BodyData.Orbit);
|
|
planet.Value.transform.position = new Vector3(p.x, _zone.GetHeight(p) + planetInstance.BodyRadius.Value * 2, p.y);
|
|
if(planet.Value is GasGiantObject gasGiantObject)
|
|
{
|
|
gasGiantObject.GravityWaves.material.SetFloat("_Phase", Time * Settings.PlanetSettings.WaveSpeed.Evaluate(planetInstance.BodyData.Mass.Value));
|
|
if(!(planet.Value is SunObject))
|
|
{
|
|
var toParent = normalize(_zone.GetOrbitPosition(_zone.Orbits[planetInstance.BodyData.Orbit].Data.Parent) - p);
|
|
gasGiantObject.SunMaterial.LightingDirection = new Vector3(toParent.x, 0, toParent.y);
|
|
}
|
|
}
|
|
}
|
|
|
|
var fogPos = FogCameraParent.position;
|
|
SectorBoundaryBrush.material.SetFloat("_Power", Settings.PlanetSettings.ZoneDepthExponent);
|
|
SectorBoundaryBrush.material.SetFloat("_Depth", Settings.PlanetSettings.ZoneDepth + Settings.PlanetSettings.ZoneBoundaryFog);
|
|
var startDepth = Zone.PowerPulse(Settings.MinimapZoneGravityRange, Settings.PlanetSettings.ZoneDepthExponent) * Settings.PlanetSettings.ZoneDepth;
|
|
var depthRange = Settings.PlanetSettings.ZoneDepth - startDepth + _maxDepth;
|
|
MinimapGravityQuad.material.SetFloat("_StartDepth", startDepth);
|
|
MinimapGravityQuad.material.SetFloat("_DepthRange", depthRange);
|
|
FogMaterial.SetFloat("_GridOffset", Settings.PlanetSettings.ZoneBoundaryFog);
|
|
FogMaterial.SetVector("_GridTransform", new Vector4(fogPos.x,fogPos.z,_viewDistance*2));
|
|
var gravPos = MinimapGravityQuad.transform.position;
|
|
gravPos.y = -Settings.PlanetSettings.ZoneDepth - _maxDepth;
|
|
MinimapGravityQuad.transform.position = gravPos;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class InstancedMesh
|
|
{
|
|
public Mesh Mesh;
|
|
public Material Material;
|
|
}
|