using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Assets.AnnotationPass; using Assets.Common; using Assets.GridGenerator; using Assets.PointDistribution; using Assets.Utils; using UnityEngine; using UnityEngine.Serialization; using Random = System.Random; namespace Assets { [Serializable] public class GraphGeneratorDebug { public bool enabled = true; public bool displayPoints = true; public bool displayBoundary = true; public bool displayVertices = true; public bool displayNeighbours = false; public bool displayLabels = false; public bool displayEdges = true; public bool displayLocations = true; public bool displayLocationCells = true; public bool displayLocationEdges = true; public bool displayLocationPoints = true; [NonSerialized] public float generationTime = 0.0f; } [Serializable] public class LocationType { public string name; public Color color; public float height = 0.0f; } [ExecuteInEditMode] public class LandmassGenerator : MonoBehaviour { [NonSerialized] public Map Map; [NonSerialized] public Thread GenerationThread; public GraphGeneratorDebug debug; public Vector2 size = new Vector2(); public List types = new List(); [Range(2.0f, 64.0f)] public float radius = 8; public int seed = Environment.TickCount; public Graph SitesGraph => Map?.Sites; public Graph BoundariesGraph => Map?.Boundaries; public Graph LocationGraph => Map?.Metadata.GetProperty>(LocationPass.MapLocationsProperty); public void Generate() { GenerationThread?.Abort(); GenerationThread = new Thread(() => { var generator = CreateMapGenerator(); var result = generator.Generate(size.x, size.y); lock (GetType()) { Map = result; } }); GenerationThread.Start(); } public void OnDisable() { GenerationThread?.Abort(); } private MapGenerator CreateMapGenerator() { var generator = new MapGenerator(new VoronoiGridGenerator(seed, new PoissonDiskSampler(radius) { Generator = new Random(seed) })); generator.AddAnnotationPass(new LocationPass(types.Prepend(new LocationType { name = "Ocean", height = -1 }).Select(t => new Location { Type = t }), new Random(seed))); return generator; } public void Reset() { GenerationThread?.Abort(); } void OnDrawGizmos() { if (!debug.enabled || Map == null) return; if (debug.displayBoundary) { Gizmos.color = Color.gray; Gizmos.DrawLine(new Vector3(0, 0, 0), new Vector3(size.x, 0, 0)); Gizmos.DrawLine(new Vector3(0, 0, 0), new Vector3(0, 0, size.y)); Gizmos.DrawLine(new Vector3(size.x, 0, size.y), new Vector3(size.x, 0, 0)); Gizmos.DrawLine(new Vector3(size.x, 0, size.y), new Vector3(0, 0, size.y)); } if (debug.displayPoints) { Gizmos.color = Color.white; DebugUtils.DisplayGraphVertices(Map.Sites, s => s.Center, displayLabels: debug.displayLabels); } if (debug.displayNeighbours) { Gizmos.color = Color.yellow; DebugUtils.DisplayGraphEdges(Map.Sites, s => s.Center); } if (debug.displayVertices) { Gizmos.color = Color.blue; DebugUtils.DisplayGraphVertices(Map.Boundaries, displayLabels: debug.displayLabels); } if (debug.displayEdges) { Gizmos.color = Color.white; DebugUtils.DisplayGraphEdges(Map.Boundaries); } Gizmos.color = Color.blue; if (!Map.Metadata.HasProperty(LocationPass.MapLocationsProperty)) return; var locations = Map.Metadata.GetProperty>(LocationPass.MapLocationsProperty); if (debug.displayLocationCells) { var cells = Map.Sites.Vertices .Where(s => s.Metadata.HasProperty(LocationPass.SiteLocationProperty)) .Where(s => s.Metadata.GetProperty(LocationPass.SiteLocationProperty).Type.name != "Ocean"); foreach (var site in cells) { var location = site.Metadata.GetProperty(LocationPass.SiteLocationProperty); Gizmos.color = location.Type.color; Gizmos.DrawSphere(site.Center.ToVector3(), 2); } } // // if (debug.displayLocations && _locationGraph != null) // { // DisplayGraphEdges(_locationGraph.Morph(a => a.Item1)); // } // // if (debug.displayLocationPoints) // { // foreach (var location in _locations.Skip(1)) // { // Gizmos.color = location.Type.color; // foreach (var point in location.BoundaryPoints) // { // var v = VoronoiGenerator.Voronoi.Vertices[point].ToVector3(); // Gizmos.DrawSphere(v, 1); // if (debug.displayLabels) Handles.Label(v + Vector3.right, $"{point} at {v.x:F2}, {v.y:f2}"); // } // } // } // if (debug.displayLocationEdges) { foreach (var location in Map.Metadata.GetProperty>(LocationPass.MapLocationsProperty).Vertices) { Gizmos.color = location.Type.color; foreach (var (a, b) in location.BoundaryEdges) { Gizmos.DrawLine(BoundariesGraph[a].ToVector3(), BoundariesGraph[b].ToVector3()); } } } } } }