ZeroVR/ZeroPacientVR/Assets/FImpossible Creations/Plugins - Level Design/PGG/Rules Logics/Utilities/Helpers/CollisionOffsetData.cs

177 lines
7.0 KiB
C#

using UnityEngine;
namespace FIMSpace.Generating.Rules.Helpers
{
public struct CollisionOffsetData
{
public SpawnData parent;
public Bounds bounds;
public Bounds boundsWithSpawnOff;
public Bounds prbounds;
public Vector3 positionOffset;
public Vector3 cellOffset;
public Vector3 scale;
public Quaternion rotation;
public string name;
public CollisionOffsetData(SpawnData spawn, Vector3? cellOffset = null)
{
parent = spawn;
if (spawn.Prefab == null )
{
Debug.LogError("[Interior Generator] Null Prefab in modificator: " + spawn.OwnerMod);
}
name = spawn.Prefab.name;
bounds = new Bounds(Vector3.zero, new Vector3(0.1f, 0.1f, 0.1f));
if ( spawn.PreviewMesh != null)
bounds = spawn.PreviewMesh.bounds;
Vector3 eul = spawn.RotationOffset + spawn.LocalRotationOffset;
rotation = Quaternion.Euler(eul);
Renderer filtr = spawn.Prefab.gameObject.GetComponentInChildren<Renderer>();
if (filtr)
{
spawn.Prefab.transform.position = Vector3.zero;
spawn.Prefab.transform.rotation = rotation;
bounds = filtr.bounds;
if (filtr.transform.parent != null)
bounds.center -= filtr.transform.TransformVector(filtr.transform.localPosition);
spawn.Prefab.transform.rotation = Quaternion.identity;
}
Collider col = spawn.Prefab.GetComponentInChildren<Collider>();
if ( col)
{
if (col.bounds.size.magnitude > bounds.size.magnitude)
{
bounds.size = col.bounds.size;
//UnityEngine.Debug.Log("newBounds");
}
}
positionOffset = spawn.Offset + Quaternion.Euler(spawn.RotationOffset) * spawn.DirectionalOffset;
scale = spawn.LocalScaleMul;
bounds.size = Vector3.Scale(bounds.size, spawn.Prefab.transform.localScale);
float angle = Quaternion.Angle(rotation, Quaternion.identity);
if (!filtr && !col)
{
if (angle > 45 && angle < 135) bounds.size = new Vector3(bounds.size.z, bounds.size.y, bounds.size.x);
if (angle < 315 && angle > 225) bounds.size = new Vector3(bounds.size.z, bounds.size.y, bounds.size.x);
}
if (cellOffset == null) this.cellOffset = Vector3.zero; else this.cellOffset = cellOffset.Value;
prbounds = PRBounds(bounds, scale, positionOffset - this.cellOffset);
boundsWithSpawnOff = new Bounds(bounds.center + spawn.GetFullOffset(true), bounds.size);
}
public static Bounds PRBounds(Bounds refB, Vector3 scale, Vector3 off)
{
return new Bounds(Vector3.Scale(refB.center, scale) + off, Vector3.Scale(refB.size, scale));
}
public bool OffsetOn(CollisionOffsetData other, ref SpawnData spawn, float amount, FieldCell cell, float sides, float limit = 2f)
{
if (other.prbounds.Intersects(prbounds))
{
//sides *= FGenerators.GetRandom(0f, 2f) > 1f ? -1f : 1f;
//sides = 1f;
#region Debugging
//Vector3 cOff = new Vector3(cell.FlatPos.x, 0, cell.FlatPos.y) * 2f;
//if (cell.FlatPos == new Vector2Int(0, 1))
//{
// Bounds offs = prbounds;
// offs.center += cOff;
// PlanHelper.DebugBounds3D(offs, Color.green * 0.7f);
// offs = other.prbounds;
// offs.center += cOff;
// PlanHelper.DebugBounds3D(offs, Color.red * 0.8f);
//}
#endregion
Vector3 toCenter = (-other.positionOffset).normalized;
float startRotY = toCenter == Vector3.zero ? 0f : Quaternion.LookRotation(toCenter).eulerAngles.y;
float toEdgeFactor = Mathf.Abs(other.prbounds.min.x) + Mathf.Abs(other.prbounds.max.x) + Mathf.Abs(other.prbounds.min.z) + Mathf.Abs(other.prbounds.max.z) + Mathf.Abs(other.prbounds.center.x) + Mathf.Abs(other.prbounds.center.z) + Mathf.Abs(other.positionOffset.x) + Mathf.Abs(other.positionOffset.z);
float distMul = 2f;
if (toEdgeFactor > 3f) distMul = Mathf.Lerp(distMul, 0.85f, toEdgeFactor - 3f);
Vector3 origin = Quaternion.Euler(0, startRotY + 89f * sides, 0f) * Vector3.forward * distMul;
origin.y = other.prbounds.center.y;
Vector3 castDir = -origin;
castDir.y = 0f;
castDir.Normalize();
if (toEdgeFactor >= 3f)
{
castDir = Vector3.Lerp(castDir, other.positionOffset.normalized, toEdgeFactor /2f - 2.5f);
origin = Vector3.Lerp(origin, -other.positionOffset, toEdgeFactor/2f - 2.5f);
//castDir = Vector3.Lerp(castDir, (origin - other.prbounds.ClosestPoint(origin)).normalized, toEdgeFactor - 3.5f);
}
origin += other.positionOffset;
#region Debugging
//if (cell.FlatPos == new Vector2Int(0, 1))
//{
// UnityEngine.Debug.Log("Edg " + toEdgeFactor + " " + other.name);
// Debug.DrawRay(origin + cOff, castDir, Color.white, 1.1f);
// Debug.DrawRay(origin + cOff, Vector3.up, Color.white * 0.7f, 1.1f);
// //UnityEngine.Debug.Log(" " + other.prbounds.min.x + " " + other.prbounds.max.x + " z " + " " + other.prbounds.min.z + " " + other.prbounds.max.z);
//}
#endregion
float distance;
Ray r = new Ray(origin, castDir);
if (other.prbounds.IntersectRay(r, out distance))
{
Vector3 hitPoint = r.origin + r.direction * distance;
#region Debugging
//if (cell.FlatPos == new Vector2Int(0, 1))
//{
// UnityEngine.Debug.Log("Intersect with " + other.name + " factor = " + toEdgeFactor);
// Debug.DrawRay(hitPoint + cOff, Vector3.down, Color.magenta, 1.1f);
//}
#endregion
Vector3 desiredPos = hitPoint - r.direction * amount * (prbounds.extents.x + prbounds.extents.z) / 2f;
if (Mathf.Abs(desiredPos.x) > limit || Mathf.Abs(desiredPos.z) > limit)
{
return false;
}
desiredPos.y = positionOffset.y;
spawn.DirectionalOffset = Vector3.zero;
spawn.Offset = desiredPos;
desiredPos.y = prbounds.center.y;
prbounds.center = desiredPos;
}
}
return true;
}
}
}