144 lines
4.0 KiB
C#
144 lines
4.0 KiB
C#
using UnityEditor;
|
|
using UnityEngine;
|
|
|
|
namespace TTT
|
|
{
|
|
|
|
public class RandomObjectMap : ScriptableWizard
|
|
{
|
|
|
|
|
|
public Texture2D SpawnMap;
|
|
public GameObject SpawnObject;
|
|
public int MaxNumber = 16;
|
|
public int Spacing = 1;
|
|
public float AboveGround = 0.0f;
|
|
public LayerMask UseLayer = 1;
|
|
public bool alignToSurface = false;
|
|
|
|
float Offset = 10.0f;
|
|
int MaxAttempts = 100;
|
|
|
|
|
|
[MenuItem("Window/Terrain Tools/Random Object Map",false,102)]
|
|
static void CreateWindow() {
|
|
ScriptableWizard.DisplayWizard("Random Object Map", typeof(RandomObjectMap), "Distribute objects");
|
|
}
|
|
|
|
void OnWizardUpdate() {
|
|
|
|
if(Terrain.activeTerrain==null)
|
|
{
|
|
errorString = "No active terrain in the scene";
|
|
return;
|
|
}else{
|
|
errorString = "";
|
|
}
|
|
|
|
|
|
helpString = "Choose a grayscale Overlay map\nand a game object to place.";
|
|
|
|
if (SpawnMap != null) {
|
|
if (SpawnMap.format != TextureFormat.ARGB32 && SpawnMap.format != TextureFormat.RGB24) {
|
|
EditorUtility.DisplayDialog("Wrong format", "SpawnMap must be in RGBA 32 bit or RGB 24 bit format", "Cancel");
|
|
return;
|
|
}
|
|
|
|
int w = SpawnMap.width;
|
|
if (SpawnMap.height != w) {
|
|
EditorUtility.DisplayDialog("Wrong size", "SpawnMap width and height must be the same", "Cancel");
|
|
return;
|
|
}
|
|
if (Mathf.ClosestPowerOfTwo(w) != w) {
|
|
EditorUtility.DisplayDialog("Wrong size", "SpawnMap width and height must be a power of two", "Cancel");
|
|
return;
|
|
}
|
|
|
|
|
|
if (w!=Terrain.activeTerrain.terrainData.alphamapResolution) {
|
|
EditorUtility.DisplayDialog("Wrong size", "SpawnMap must have same size ("+w+") as existing splatmap ("+Terrain.activeTerrain.terrainData.alphamapResolution+")", "Cancel");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
void OnWizardCreate()
|
|
{
|
|
|
|
|
|
if (Terrain.activeTerrain==null) {
|
|
//EditorUtility.DisplayDialog("Error", "You must have an active terrain in the scene", "Cancel");
|
|
Debug.LogError("You must have an active terrain in the scene first");
|
|
return;
|
|
}
|
|
|
|
|
|
Vector3 size = Terrain.activeTerrain.terrainData.size;
|
|
Vector3 NewPosition = new Vector3();
|
|
int placed = 0;
|
|
|
|
// make "folder" for objects
|
|
GameObject folderGO = new GameObject("RandomObjects");
|
|
|
|
for (int i=0; i<MaxNumber; i++)
|
|
{
|
|
EditorUtility.DisplayProgressBar("Placing objects", "calculating...", Mathf.InverseLerp(0.0f, (float)MaxNumber, (float)i));
|
|
|
|
|
|
for (int j=0; j<MaxAttempts; j++)
|
|
{
|
|
// calculate new random position
|
|
NewPosition = Terrain.activeTerrain.transform.position;
|
|
float w = Random.Range(0.0f, size.x);
|
|
float h = Random.Range(0.0f, size.z);
|
|
NewPosition.x += w;
|
|
NewPosition.y += size.y + Offset; // make sure we are above the terrain
|
|
NewPosition.z += h;
|
|
|
|
// check against spawnmap
|
|
int xmap = Mathf.RoundToInt((float)SpawnMap.width * w/size.x);
|
|
int ymap = Mathf.RoundToInt((float)SpawnMap.height * h/size.z);
|
|
float value = SpawnMap.GetPixel(xmap, ymap).grayscale;
|
|
|
|
if (value>0.0f && Random.Range(0.0f, 1.0f)<value)
|
|
{
|
|
// verify that position is above terrain/something
|
|
RaycastHit hit;
|
|
if (Physics.Raycast(NewPosition, -Vector3.up, out hit, Mathf.Infinity, UseLayer))
|
|
{
|
|
float distanceToGround = hit.distance;
|
|
NewPosition.y -= (distanceToGround-AboveGround);
|
|
|
|
// instantiate object
|
|
GameObject clone = Instantiate(SpawnObject, NewPosition, Quaternion.identity) as GameObject;
|
|
if (alignToSurface) clone.transform.rotation = Quaternion.LookRotation(clone.transform.forward, hit.normal);
|
|
clone.transform.parent = folderGO.transform;
|
|
placed++;
|
|
j=MaxAttempts;
|
|
|
|
// clear out space
|
|
if (Spacing>0)
|
|
{
|
|
for (int xx=Mathf.Max(0,xmap-Spacing); xx<=Mathf.Min(SpawnMap.width,xmap+Spacing); xx++)
|
|
{
|
|
for (int yy=Mathf.Max(0,ymap-Spacing); yy<=Mathf.Min(SpawnMap.height,ymap+Spacing); yy++)
|
|
{
|
|
SpawnMap.SetPixel(xx, yy, Color.black);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
EditorUtility.ClearProgressBar();
|
|
Debug.Log("placed "+placed+" objects");
|
|
|
|
|
|
}
|
|
}
|
|
|
|
} |