// Copyright (C) 2023 Nicholas Maltbie
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
// associated documentation files (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge, publish, distribute,
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
using System;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
namespace nickmaltbie.OpenKCC.Utils.ColliderCast
{
///
/// Enum to translate capsule direction to numeric value.
///
public enum CapsuleDirection
{
X = 0,
Y = 1,
Z = 2,
}
///
/// List of primitive collider types.
///
public enum ColliderType
{
Box,
Sphere,
Capsule,
Point,
}
///
/// Generic collider configuration.
///
[Serializable]
public class ColliderConfiguration : PropertyAttribute
{
///
/// Type of collider for this configuration.
///
public ColliderType type = ColliderType.Box;
///
/// Center of box collider.
///
public Vector3 boxCenter = Vector3.zero;
///
/// Size of the box collider.
///
public Vector3 boxSize = Vector3.one;
///
/// Center of sphere collider.
///
public Vector3 sphereCenter = Vector3.zero;
///
/// Radius of the sphere collider.
///
public float sphereRadius = 0.5f;
///
/// Center of capsule collider
///
public Vector3 capsuleCenter = Vector3.zero;
///
/// Radius of the capsule collider.
///
public float capsuleRadius = 0.5f;
///
/// Height of the capsule collider.
///
public float capsuleHeight = 2.0f;
///
/// Direction fo the capsule collider.
///
public CapsuleDirection capsuleDirection = CapsuleDirection.Y;
///
/// Center of point collider.
///
public Vector3 pointCenter = Vector3.zero;
///
/// Gets or sets the radius fo the collider (applies to Sphere or Capsule).
///
public float Radius
{
get
{
switch (type)
{
case ColliderType.Sphere:
return sphereRadius;
case ColliderType.Capsule:
return capsuleRadius;
default:
return 0;
}
}
set
{
switch (type)
{
case ColliderType.Sphere:
sphereRadius = value;
break;
case ColliderType.Capsule:
capsuleRadius = value;
break;
}
}
}
///
/// Gets or sets the center of the collider (applies to Box, Sphere, or Capsule).
///
public Vector3 Center
{
get
{
switch (type)
{
case ColliderType.Sphere:
return sphereCenter;
case ColliderType.Capsule:
return capsuleCenter;
case ColliderType.Box:
return boxCenter;
default:
case ColliderType.Point:
return pointCenter;
}
}
set
{
switch (type)
{
case ColliderType.Sphere:
sphereCenter = value;
break;
case ColliderType.Capsule:
capsuleCenter = value; ;
break;
case ColliderType.Box:
boxCenter = value;
break;
default:
case ColliderType.Point:
pointCenter = value;
break;
}
}
}
///
/// Gets or sets the size of the collider (applies to Box).
///
public Vector3 Size
{
get => boxSize;
set => boxSize = value;
}
///
/// Gets or sets the height of the collider (applies to Capsule).
///
public float Height
{
get => capsuleHeight;
set => capsuleHeight = value;
}
///
/// Gets or Sets Direction of capsule collider.
///
public CapsuleDirection CapsuleDirection
{
get => capsuleDirection;
set => capsuleDirection = value;
}
///
/// Constructs an instance of Collider configuration.
///
/// Type of collider to create.
/// Center of the collider in 3D space.
/// Size of the collider (only applies to Box)
/// Radius fo the collider (applies to Sphere or Capsule).
/// Height of the collider (applies to Capsule).
/// Direction of capsule collider.
public ColliderConfiguration(
ColliderType type = ColliderType.Box,
Vector3? center = null,
Vector3? size = null,
float radius = 0.5f,
float height = 2.0f,
CapsuleDirection capsuleDirection = CapsuleDirection.Y)
{
this.type = type;
Center = center ?? Vector3.zero;
Size = size ?? Vector3.one;
Radius = radius;
Height = height;
CapsuleDirection = capsuleDirection;
}
///
/// Attaches a collider component to a given game object
/// based on this collider configuration.
///
/// Game object to attach collider to.
/// Should existing colliders on the object be cleaned up.
/// Collider attached to the given game object.
public Collider AttachCollider(GameObject go, bool cleanupCollider = true)
{
if (cleanupCollider)
{
foreach (Collider col in go.GetComponents())
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying)
{
GameObject.DestroyImmediate(col);
}
else
{
GameObject.Destroy(col);
}
#else
GameObject.Destroy(col);
#endif
}
}
switch (type)
{
case ColliderType.Box:
BoxCollider box = go.AddComponent();
box.size = Size;
box.center = Center;
return box;
case ColliderType.Sphere:
SphereCollider sphere = go.AddComponent();
sphere.center = Center;
sphere.radius = Radius;
return sphere;
case ColliderType.Capsule:
CapsuleCollider capsule = go.AddComponent();
capsule.center = Center;
capsule.radius = Radius;
capsule.height = Height;
capsule.direction = (int)CapsuleDirection;
return capsule;
}
return null;
}
}
}