199 lines
7.4 KiB
C#
199 lines
7.4 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Sirenix.OdinInspector;
|
|
using Sirenix.Utilities;
|
|
using UnityEngine;
|
|
using VOID.Generic.Dict;
|
|
|
|
namespace VOID.Generic.World
|
|
{
|
|
public class ComplexArea : SerializedMonoBehaviour
|
|
{
|
|
[SerializeField] [ReadOnly] public List<Area> areas;
|
|
|
|
[ReadOnly] [BoxGroup("variant", false)]
|
|
public bool isVariant;
|
|
|
|
[ReadOnly] [HideIf(nameof(isVariant))] [BoxGroup("variant", false)]
|
|
public List<ComplexArea> variants = new();
|
|
|
|
[ReadOnly] [ShowIf(nameof(isVariant))] [BoxGroup("variant", false)]
|
|
public ComplexArea original;
|
|
|
|
#if UNITY_EDITOR
|
|
private GameObject GetGameObjectForAreas()
|
|
{
|
|
const string areasGameObjectName = "_areas";
|
|
var areasGameObject = gameObject.transform.Find(areasGameObjectName)?.gameObject;
|
|
if (areasGameObject) return areasGameObject;
|
|
areasGameObject = new GameObject(areasGameObjectName);
|
|
areasGameObject.transform.position = Vector3.zero;
|
|
areasGameObject.transform.parent = gameObject.transform;
|
|
areasGameObject.transform.SetAsFirstSibling();
|
|
return areasGameObject;
|
|
}
|
|
|
|
[Title("Generate")]
|
|
[Button]
|
|
private void GenerateAreas()
|
|
{
|
|
areas.ForEach(area => DestroyImmediate(area.gameObject));
|
|
areas.Clear();
|
|
GenerateMissingAreas();
|
|
}
|
|
|
|
[Button]
|
|
private void GenerateMissingAreas()
|
|
{
|
|
// Bounds thats contains everything in this ComplexArea Prefab
|
|
var complexAreaBounds = new Bounds();
|
|
GetComponentsInChildren<Collider>()
|
|
.ForEach(collider => complexAreaBounds.Encapsulate(collider.bounds));
|
|
GetComponentsInChildren<MeshRenderer>()
|
|
.ForEach(meshRenderer => complexAreaBounds.Encapsulate(meshRenderer.bounds));
|
|
|
|
// To calculate position index we need only width (x) and length (z)
|
|
var startIndex = new Vector2Int(
|
|
Mathf.RoundToInt(complexAreaBounds.min.x / Area.Size),
|
|
Mathf.RoundToInt(complexAreaBounds.min.z / Area.Size)
|
|
);
|
|
var endIndex = new Vector2Int(
|
|
Mathf.RoundToInt(complexAreaBounds.max.x / Area.Size),
|
|
Mathf.RoundToInt(complexAreaBounds.max.z / Area.Size)
|
|
);
|
|
|
|
var areasGameObject = GetGameObjectForAreas();
|
|
|
|
// Create areas for everything inside bounds
|
|
for (var x = startIndex.x; x <= endIndex.x; x++)
|
|
{
|
|
for (var y = startIndex.y; y <= endIndex.y; y++)
|
|
{
|
|
if (areas.Any(area => area.position.x == x && area.position.y == y)) continue;
|
|
|
|
var areaGameObject = new GameObject();
|
|
areaGameObject.AddComponent<Area>();
|
|
areaGameObject.transform.parent = areasGameObject.transform;
|
|
areaGameObject.transform.position = new Vector3(x * Area.Size, 0, y * Area.Size);
|
|
}
|
|
}
|
|
|
|
UpdateAll();
|
|
}
|
|
|
|
[Button]
|
|
private void GenerateVariants()
|
|
{
|
|
Editor.EditorWindow.World.ComplexAreaRotateVariantGenerator.GenerateRotatedVariants(this);
|
|
}
|
|
|
|
[Title("Update")]
|
|
[Button(ButtonSizes.Large)]
|
|
public void UpdateAll()
|
|
{
|
|
UpdateAreaList();
|
|
UpdatePositionIndexes();
|
|
UpdateNames();
|
|
UpdateConnections();
|
|
}
|
|
|
|
[ResponsiveButtonGroup("Update")]
|
|
[Button]
|
|
private void UpdateAreaList()
|
|
{
|
|
areas = gameObject.GetComponentsInChildren<Area>().ToList();
|
|
areas.ForEach(area => area.complexArea = this);
|
|
}
|
|
|
|
[ResponsiveButtonGroup("Update")]
|
|
[Button]
|
|
private void UpdatePositionIndexes()
|
|
{
|
|
areas.ForEach(area =>
|
|
{
|
|
var position = area.transform.position;
|
|
area.position.x = Mathf.RoundToInt(position.x / Area.Size);
|
|
area.position.y = Mathf.RoundToInt(position.z / Area.Size);
|
|
});
|
|
}
|
|
|
|
[ResponsiveButtonGroup("Update")]
|
|
[Button]
|
|
private void UpdateNames()
|
|
{
|
|
UpdatePositionIndexes();
|
|
areas.ForEach(area => area.name = $"{nameof(Area)} ({area.position.x},{area.position.y})");
|
|
}
|
|
|
|
[ResponsiveButtonGroup("Update")]
|
|
[Button]
|
|
private void UpdateConnections()
|
|
{
|
|
UpdatePositionIndexes();
|
|
areas.ForEach(area =>
|
|
{
|
|
var forwardArea = areas.Find(subArea => (area.position + Vector2Int.up).Equals(subArea.position));
|
|
var rightArea = areas.Find(subArea => (area.position + Vector2Int.right).Equals(subArea.position));
|
|
var backArea = areas.Find(subArea => (area.position + Vector2Int.down).Equals(subArea.position));
|
|
var leftArea = areas.Find(subArea => (area.position + Vector2Int.left).Equals(subArea.position));
|
|
|
|
area.forwardConnection.direction = Direction2D.Forward;
|
|
area.rightConnection.direction = Direction2D.Right;
|
|
area.backConnection.direction = Direction2D.Back;
|
|
area.leftConnection.direction = Direction2D.Left;
|
|
|
|
if (forwardArea)
|
|
area.forwardConnection.type = AreaConnectionType.Inner;
|
|
else if (area.forwardConnection.type == AreaConnectionType.Inner)
|
|
area.forwardConnection.type = AreaConnectionType.None;
|
|
|
|
if (rightArea)
|
|
area.rightConnection.type = AreaConnectionType.Inner;
|
|
else if (area.rightConnection.type == AreaConnectionType.Inner)
|
|
area.rightConnection.type = AreaConnectionType.None;
|
|
|
|
if (backArea)
|
|
area.backConnection.type = AreaConnectionType.Inner;
|
|
else if (area.backConnection.type == AreaConnectionType.Inner)
|
|
area.backConnection.type = AreaConnectionType.None;
|
|
|
|
if (leftArea)
|
|
area.leftConnection.type = AreaConnectionType.Inner;
|
|
else if (area.leftConnection.type == AreaConnectionType.Inner)
|
|
area.leftConnection.type = AreaConnectionType.None;
|
|
});
|
|
}
|
|
|
|
[Title("Auto-Fix")]
|
|
[Button(ButtonSizes.Large)]
|
|
public void AutoFixAll()
|
|
{
|
|
AutoFixAreaTransforms();
|
|
AutoFixAreaHierarchy();
|
|
}
|
|
|
|
[ResponsiveButtonGroup("AutoFix")]
|
|
[Button]
|
|
private void AutoFixAreaTransforms()
|
|
{
|
|
areas.ForEach(area =>
|
|
{
|
|
var position = area.transform.localPosition;
|
|
position.x = Mathf.RoundToInt(position.x / Area.Size) * (int)Area.Size;
|
|
position.y = Mathf.RoundToInt(position.y / Area.Size) * (int)Area.Size;
|
|
position.z = Mathf.RoundToInt(position.z / Area.Size) * (int)Area.Size;
|
|
area.transform.localPosition = position;
|
|
});
|
|
}
|
|
|
|
[ResponsiveButtonGroup("AutoFix")]
|
|
[Button]
|
|
private void AutoFixAreaHierarchy()
|
|
{
|
|
var areasGameObject = GetGameObjectForAreas();
|
|
GetComponentsInChildren<Area>()
|
|
.ForEach(area => area.gameObject.transform.parent = areasGameObject.transform);
|
|
}
|
|
#endif
|
|
}
|
|
} |