167 lines
3.1 KiB
C#
167 lines
3.1 KiB
C#
using UnityEngine;
|
|
|
|
namespace S_SnapTools
|
|
{
|
|
public class S_SnapToWorld : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
private LayerMask m_snapToLayers = 1;
|
|
|
|
[SerializeField]
|
|
private Vector3 m_snapDirection = Vector3.down;
|
|
|
|
[SerializeField]
|
|
private int m_snapFrameRate = 5;
|
|
|
|
[SerializeField]
|
|
private bool m_isRotationSnap = true;
|
|
|
|
[SerializeField]
|
|
private float m_maxSnapDistanceAgainstDirection = 1000f;
|
|
|
|
private int m_snapCounter = -1;
|
|
|
|
public LayerMask SnapToLayers
|
|
{
|
|
get
|
|
{
|
|
return m_snapToLayers;
|
|
}
|
|
set
|
|
{
|
|
m_snapToLayers = value;
|
|
}
|
|
}
|
|
|
|
public Vector3 SnapDirection
|
|
{
|
|
get
|
|
{
|
|
return m_snapDirection;
|
|
}
|
|
set
|
|
{
|
|
m_snapDirection = value;
|
|
}
|
|
}
|
|
|
|
public int SnapFrameRate
|
|
{
|
|
get
|
|
{
|
|
return m_snapFrameRate;
|
|
}
|
|
set
|
|
{
|
|
m_snapFrameRate = value;
|
|
}
|
|
}
|
|
|
|
public bool IsRotationSnap
|
|
{
|
|
get
|
|
{
|
|
return m_isRotationSnap;
|
|
}
|
|
set
|
|
{
|
|
m_isRotationSnap = value;
|
|
}
|
|
}
|
|
|
|
public float MaxSnapDistanceAgainstDirection
|
|
{
|
|
get
|
|
{
|
|
return m_maxSnapDistanceAgainstDirection;
|
|
}
|
|
set
|
|
{
|
|
m_maxSnapDistanceAgainstDirection = value;
|
|
}
|
|
}
|
|
|
|
public void DoSnap()
|
|
{
|
|
Vector3 origin = base.transform.position - m_snapDirection * m_maxSnapDistanceAgainstDirection;
|
|
RaycastHit hitInfo;
|
|
if (((1 << base.gameObject.layer) & m_snapToLayers.value) != 0)
|
|
{
|
|
RaycastHit[] array = Physics.RaycastAll(origin, m_snapDirection, float.PositiveInfinity, m_snapToLayers.value);
|
|
RaycastHit? raycastHit = null;
|
|
float num = float.PositiveInfinity;
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
if (!array[i].transform.IsChildOf(base.transform) && num > array[i].distance)
|
|
{
|
|
num = array[i].distance;
|
|
raycastHit = array[i];
|
|
}
|
|
}
|
|
if (raycastHit.HasValue)
|
|
{
|
|
SnapToHit(raycastHit.Value);
|
|
}
|
|
}
|
|
else if (Physics.Raycast(origin, m_snapDirection, out hitInfo, float.PositiveInfinity, m_snapToLayers.value))
|
|
{
|
|
SnapToHit(hitInfo);
|
|
}
|
|
}
|
|
|
|
private void SnapToHit(RaycastHit p_hit)
|
|
{
|
|
base.transform.position = p_hit.point;
|
|
if (!m_isRotationSnap)
|
|
{
|
|
return;
|
|
}
|
|
Vector3 forward = base.transform.forward;
|
|
base.transform.up = p_hit.normal;
|
|
forward -= base.transform.up * Vector3.Dot(base.transform.up, forward);
|
|
forward.Normalize();
|
|
if (Vector3.Dot(Vector3.Cross(base.transform.forward, forward), p_hit.normal) > 0f)
|
|
{
|
|
float num = 0f - Vector3.Angle(base.transform.forward, forward);
|
|
if (!float.IsNaN(num))
|
|
{
|
|
base.transform.Rotate(Vector3.down, num);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float num2 = 0f - Vector3.Angle(base.transform.forward, forward);
|
|
if (!float.IsNaN(num2))
|
|
{
|
|
base.transform.Rotate(Vector3.up, num2);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (m_snapFrameRate != -1)
|
|
{
|
|
if (m_snapCounter <= 0)
|
|
{
|
|
m_snapCounter = m_snapFrameRate;
|
|
DoSnap();
|
|
}
|
|
else
|
|
{
|
|
m_snapCounter--;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void MoveToLayer(Transform p_root, int p_layer)
|
|
{
|
|
p_root.gameObject.layer = p_layer;
|
|
foreach (Transform item in p_root)
|
|
{
|
|
MoveToLayer(item, p_layer);
|
|
}
|
|
}
|
|
}
|
|
}
|