inz-00/Assets/Scripts/LandmassGenerator.cs

191 lines
6.4 KiB
C#

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<LocationType> types = new List<LocationType>();
[Range(2.0f, 64.0f)]
public float radius = 8;
public int seed = Environment.TickCount;
public Graph<MapSite> SitesGraph => Map?.Sites;
public Graph<Point> BoundariesGraph => Map?.Boundaries;
public Graph<Location> LocationGraph => Map?.Metadata.GetProperty<Graph<Location>>(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<Graph<Location>>(LocationPass.MapLocationsProperty);
if (debug.displayLocationCells)
{
var cells = Map.Sites.Vertices
.Where(s => s.Metadata.HasProperty(LocationPass.SiteLocationProperty))
.Where(s => s.Metadata.GetProperty<Location>(LocationPass.SiteLocationProperty).Type.name != "Ocean");
foreach (var site in cells)
{
var location = site.Metadata.GetProperty<Location>(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<Graph<Location>>(LocationPass.MapLocationsProperty).Vertices)
{
Gizmos.color = location.Type.color;
foreach (var (a, b) in location.BoundaryEdges)
{
Gizmos.DrawLine(BoundariesGraph[a].ToVector3(), BoundariesGraph[b].ToVector3());
}
}
}
}
}
}