Created
November 2, 2017 13:10
-
-
Save mihakrajnc/c7f46ba9a136c1dab1ee36c5cd7dfc47 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Assets.Mapbox.Unity.MeshGeneration.Modifiers.MeshModifiers; | |
using Mapbox.Unity; | |
using Mapbox.Unity.Map; | |
using Mapbox.Unity.MeshGeneration.Components; | |
using Mapbox.Unity.MeshGeneration.Data; | |
using Mapbox.Unity.MeshGeneration.Enums; | |
using Mapbox.Unity.MeshGeneration.Interfaces; | |
using Mapbox.Unity.MeshGeneration.Modifiers; | |
using Pathfinding; | |
using UnityEngine; | |
using Random = UnityEngine.Random; | |
namespace Core.MB | |
{ | |
[CreateAssetMenu(menuName = "Mapbox/Modifiers/Custom/Color Filtered Prefab Modifier")] | |
public class ColorFilteredPrefabModifier : GameObjectModifier | |
{ | |
[SerializeField] private GameObject[] _prefabs; | |
[SerializeField] private int _density = 10; | |
[SerializeField] private Color[] colorFilters; | |
[SerializeField] private float tolerance = 0.02f; | |
[SerializeField] private float scale = 1; | |
[SerializeField] private LayerMask mask; | |
public override void Run(FeatureBehaviour fb, UnityTile tile) | |
{ | |
switch (tile.RasterDataState) | |
{ | |
case TilePropertyState.Loaded: | |
UpdatePrefabs(fb, tile); | |
break; | |
case TilePropertyState.Loading: | |
case TilePropertyState.None: | |
tile.OnRasterDataChanged += rTile => UpdatePrefabs(fb, tile); | |
break; | |
} | |
} | |
private void UpdatePrefabs(FeatureBehaviour fb, UnityTile tile) | |
{ | |
//FIXME: This is shit. Should remove OnRasterDataChanged callback instead. | |
if (!fb) return; | |
List<List<Vector3>> subset = fb.Data.Points; | |
Data flatData = EarcutLibrary.Flatten(subset); | |
List<int> result = EarcutLibrary.Earcut(flatData.Vertices, flatData.Holes, flatData.Dim); | |
for (int m = 0; m < result.Count - 3; m += 3) | |
{ | |
Vector2 vert1Pos = new Vector2(flatData.Vertices[2 * result[m]], | |
flatData.Vertices[2 * result[m] + 1]); | |
Vector2 vert2Pos = new Vector2(flatData.Vertices[2 * result[m + 1]], | |
flatData.Vertices[2 * result[m + 1] + 1]); | |
Vector2 vert3Pos = new Vector2(flatData.Vertices[2 * result[m + 2]], | |
flatData.Vertices[2 * result[m + 2] + 1]); | |
float area = Utils.TriangleArea(vert1Pos, vert2Pos, vert3Pos); | |
int numberOfPoints = Math.Max(1, (int) (_density * area / 3000)); | |
for (int i = 0; i < numberOfPoints; i++) | |
{ | |
Vector2 randomPoint = | |
Utils.RandomPointInTriangle(vert1Pos, vert2Pos, vert3Pos) * | |
tile.Map.WorldRelativeScale; | |
float height = tile.QueryHeightData( | |
(float) ((randomPoint.x + tile.Rect.Size.x / 2) / | |
tile.Rect.Size.x), | |
(float) ((randomPoint.y + tile.Rect.Size.y / 2) / | |
tile.Rect.Size.y)) * tile.Map.WorldRelativeScale; | |
Vector3 worldPos = new Vector3(randomPoint.x, height, randomPoint.y) + fb.transform.position; | |
RaycastHit hit; | |
if (Physics.Raycast(worldPos + Vector3.up * 50f, Vector3.down, out hit, 100, mask)) | |
{ | |
worldPos = hit.point; | |
Material material = hit.transform.GetComponent<Renderer>().material; | |
Texture texture = material.mainTexture; | |
Texture2D tex = texture as Texture2D; | |
if (tex != null) | |
{ | |
Vector2 pixelUv = hit.textureCoord; | |
pixelUv.x *= tex.width; | |
pixelUv.y *= tex.height; | |
Color color = tex.GetPixel((int) pixelUv.x, (int) pixelUv.y); | |
if (ColorMatches(color)) | |
{ | |
GameObject go = Instantiate(_prefabs[Random.Range(0, _prefabs.Length)], worldPos, | |
Quaternion.identity); | |
go.transform.localScale = Vector3.one * scale; | |
go.transform.parent = fb.transform; | |
} | |
} | |
} | |
} | |
} | |
} | |
private bool ColorMatches(Color color) | |
{ | |
return colorFilters == null || colorFilters.Length == 0 || colorFilters.Any(colorFilter => | |
Math.Abs(colorFilter.r - color.r) < tolerance && | |
Math.Abs(colorFilter.g - color.g) < tolerance && | |
Math.Abs(colorFilter.b - color.b) < tolerance); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment