369 lines
6.4 KiB
C#
369 lines
6.4 KiB
C#
using UnityEngine;
|
|
|
|
namespace S_SnapTools
|
|
{
|
|
public class S_SnapToGrid : MonoBehaviour
|
|
{
|
|
public enum ESnapCondition
|
|
{
|
|
ON_UPDATE = 0,
|
|
WHEN_STILL = 1
|
|
}
|
|
|
|
[SerializeField]
|
|
private float m_epsilon = 0.001f;
|
|
|
|
[SerializeField]
|
|
private float m_maxVelocity_StillMode = 0.001f;
|
|
|
|
[SerializeField]
|
|
private float m_maxEulerVelocity_StillMode = 0.01f;
|
|
|
|
[SerializeField]
|
|
private float m_stillTimeBeforSnap_StillMode = 0.2f;
|
|
|
|
[SerializeField]
|
|
private Vector3 m_gridOffset = Vector3.zero;
|
|
|
|
[SerializeField]
|
|
private Vector3 m_gridCellSize = Vector3.one * 10f;
|
|
|
|
[SerializeField]
|
|
private Vector3 m_rotationOffset = Vector3.zero;
|
|
|
|
[SerializeField]
|
|
private Vector3 m_rotationStepSize = Vector3.one * 22.5f;
|
|
|
|
[SerializeField]
|
|
private ESnapCondition m_snapCondition;
|
|
|
|
[SerializeField]
|
|
private bool m_isInstantSnap;
|
|
|
|
[SerializeField]
|
|
private bool m_isSnapAxisX = true;
|
|
|
|
[SerializeField]
|
|
private bool m_isSnapAxisY = true;
|
|
|
|
[SerializeField]
|
|
private bool m_isSnapAxisZ = true;
|
|
|
|
[SerializeField]
|
|
private bool m_isSnapAxisXRotation = true;
|
|
|
|
[SerializeField]
|
|
private bool m_isSnapAxisYRotation = true;
|
|
|
|
[SerializeField]
|
|
private bool m_isSnapAxisZRotation = true;
|
|
|
|
private float m_stillTimePos;
|
|
|
|
private float m_stillTimeRot;
|
|
|
|
private Vector3 m_lastPosition = Vector3.zero;
|
|
|
|
private Vector3 m_lastEuler = Vector3.zero;
|
|
|
|
public float Epsilon
|
|
{
|
|
get
|
|
{
|
|
return m_epsilon;
|
|
}
|
|
set
|
|
{
|
|
m_epsilon = value;
|
|
}
|
|
}
|
|
|
|
public float MaxVelocity_StillMode
|
|
{
|
|
get
|
|
{
|
|
return m_maxVelocity_StillMode;
|
|
}
|
|
set
|
|
{
|
|
m_maxVelocity_StillMode = value;
|
|
}
|
|
}
|
|
|
|
public float MaxEulerVelocity_StillMode
|
|
{
|
|
get
|
|
{
|
|
return m_maxEulerVelocity_StillMode;
|
|
}
|
|
set
|
|
{
|
|
m_maxEulerVelocity_StillMode = value;
|
|
}
|
|
}
|
|
|
|
public float StillTimeBeforSnap_StillMode
|
|
{
|
|
get
|
|
{
|
|
return m_stillTimeBeforSnap_StillMode;
|
|
}
|
|
set
|
|
{
|
|
m_stillTimeBeforSnap_StillMode = value;
|
|
}
|
|
}
|
|
|
|
public Vector3 GridOffset
|
|
{
|
|
get
|
|
{
|
|
return m_gridOffset;
|
|
}
|
|
set
|
|
{
|
|
m_gridOffset = value;
|
|
}
|
|
}
|
|
|
|
public Vector3 GridCellSize
|
|
{
|
|
get
|
|
{
|
|
return m_gridCellSize;
|
|
}
|
|
set
|
|
{
|
|
m_gridCellSize = value;
|
|
}
|
|
}
|
|
|
|
public Vector3 RotationOffset
|
|
{
|
|
get
|
|
{
|
|
return m_rotationOffset;
|
|
}
|
|
set
|
|
{
|
|
m_rotationOffset = value;
|
|
}
|
|
}
|
|
|
|
public Vector3 RotationStepSize
|
|
{
|
|
get
|
|
{
|
|
return m_rotationStepSize;
|
|
}
|
|
set
|
|
{
|
|
m_rotationStepSize = value;
|
|
}
|
|
}
|
|
|
|
public ESnapCondition SnapCondition
|
|
{
|
|
get
|
|
{
|
|
return m_snapCondition;
|
|
}
|
|
set
|
|
{
|
|
m_snapCondition = value;
|
|
}
|
|
}
|
|
|
|
public bool IsInstantSnap
|
|
{
|
|
get
|
|
{
|
|
return m_isInstantSnap;
|
|
}
|
|
set
|
|
{
|
|
m_isInstantSnap = value;
|
|
}
|
|
}
|
|
|
|
public bool IsSnapAxisX
|
|
{
|
|
get
|
|
{
|
|
return m_isSnapAxisX;
|
|
}
|
|
set
|
|
{
|
|
m_isSnapAxisX = value;
|
|
}
|
|
}
|
|
|
|
public bool IsSnapAxisY
|
|
{
|
|
get
|
|
{
|
|
return m_isSnapAxisY;
|
|
}
|
|
set
|
|
{
|
|
m_isSnapAxisY = value;
|
|
}
|
|
}
|
|
|
|
public bool IsSnapAxisZ
|
|
{
|
|
get
|
|
{
|
|
return m_isSnapAxisZ;
|
|
}
|
|
set
|
|
{
|
|
m_isSnapAxisZ = value;
|
|
}
|
|
}
|
|
|
|
public bool IsSnapAxisXRotation
|
|
{
|
|
get
|
|
{
|
|
return m_isSnapAxisXRotation;
|
|
}
|
|
set
|
|
{
|
|
m_isSnapAxisXRotation = value;
|
|
}
|
|
}
|
|
|
|
public bool IsSnapAxisYRotation
|
|
{
|
|
get
|
|
{
|
|
return m_isSnapAxisYRotation;
|
|
}
|
|
set
|
|
{
|
|
m_isSnapAxisYRotation = value;
|
|
}
|
|
}
|
|
|
|
public bool IsSnapAxisZRotation
|
|
{
|
|
get
|
|
{
|
|
return m_isSnapAxisZRotation;
|
|
}
|
|
set
|
|
{
|
|
m_isSnapAxisZRotation = value;
|
|
}
|
|
}
|
|
|
|
public void DoSnap()
|
|
{
|
|
DoSnapPosition();
|
|
DoSnapRotation();
|
|
}
|
|
|
|
public void DoSnapPosition()
|
|
{
|
|
Vector3 o_snapTarget;
|
|
if (GetSnapTarget(base.transform.position, m_gridOffset, m_gridCellSize, m_isSnapAxisX, m_isSnapAxisY, m_isSnapAxisZ, out o_snapTarget))
|
|
{
|
|
if (m_isInstantSnap)
|
|
{
|
|
base.transform.position = o_snapTarget;
|
|
}
|
|
else
|
|
{
|
|
base.transform.position = Vector3.Lerp(base.transform.position, o_snapTarget, 0.5f);
|
|
}
|
|
m_lastPosition = base.transform.position;
|
|
}
|
|
}
|
|
|
|
public void DoSnapRotation()
|
|
{
|
|
Vector3 o_snapTarget;
|
|
if (GetSnapTarget(base.transform.localEulerAngles, m_rotationOffset, m_rotationStepSize, m_isSnapAxisXRotation, m_isSnapAxisYRotation, m_isSnapAxisZRotation, out o_snapTarget))
|
|
{
|
|
if (m_isInstantSnap)
|
|
{
|
|
base.transform.localEulerAngles = o_snapTarget;
|
|
}
|
|
else
|
|
{
|
|
base.transform.localEulerAngles = Vector3.Slerp(base.transform.localEulerAngles, o_snapTarget, 0.5f);
|
|
}
|
|
m_lastEuler = base.transform.localEulerAngles;
|
|
}
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
if (m_gridCellSize.x == 0f || m_gridCellSize.y == 0f || m_gridCellSize.z == 0f)
|
|
{
|
|
m_gridCellSize += Vector3.one * 0.1f;
|
|
Debug.LogError("S_SnapToGrid: Start: All components of the GridCellSize vector must be unequal 0!");
|
|
}
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (m_snapCondition == ESnapCondition.ON_UPDATE)
|
|
{
|
|
DoSnap();
|
|
return;
|
|
}
|
|
if (IsStill(base.transform.position, m_maxVelocity_StillMode, ref m_lastPosition, ref m_stillTimePos))
|
|
{
|
|
DoSnapPosition();
|
|
}
|
|
if (IsStill(base.transform.localEulerAngles, m_maxEulerVelocity_StillMode, ref m_lastEuler, ref m_stillTimeRot))
|
|
{
|
|
DoSnapRotation();
|
|
}
|
|
}
|
|
|
|
private bool IsStill(Vector3 p_currentValue, float p_maxV, ref Vector3 r_lastValue, ref float r_stillTime)
|
|
{
|
|
if ((r_lastValue - p_currentValue).magnitude / Time.deltaTime < p_maxV)
|
|
{
|
|
r_stillTime += Time.deltaTime;
|
|
}
|
|
else
|
|
{
|
|
r_stillTime = 0f;
|
|
}
|
|
r_lastValue = p_currentValue;
|
|
return r_stillTime >= m_stillTimeBeforSnap_StillMode;
|
|
}
|
|
|
|
private bool GetSnapTarget(Vector3 p_value, Vector3 p_offset, Vector3 p_stepSize, bool p_isSnapAxisX, bool p_isSnapAxisY, bool p_isSnapAxisZ, out Vector3 o_snapTarget)
|
|
{
|
|
Vector3 vector = p_value - p_offset;
|
|
float num = vector.x / p_stepSize.x;
|
|
float num2 = vector.y / p_stepSize.y;
|
|
float num3 = vector.z / p_stepSize.z;
|
|
if ((p_isSnapAxisX && num - Mathf.Floor(num) > m_epsilon) || (p_isSnapAxisY && num2 - Mathf.Floor(num2) > m_epsilon) || (p_isSnapAxisZ && num3 - Mathf.Floor(num3) > m_epsilon))
|
|
{
|
|
if (p_isSnapAxisX)
|
|
{
|
|
num = Mathf.Round(num);
|
|
}
|
|
if (p_isSnapAxisY)
|
|
{
|
|
num2 = Mathf.Round(num2);
|
|
}
|
|
if (p_isSnapAxisZ)
|
|
{
|
|
num3 = Mathf.Round(num3);
|
|
}
|
|
o_snapTarget = p_offset + Vector3.Scale(new Vector3(num, num2, num3), p_stepSize);
|
|
return true;
|
|
}
|
|
o_snapTarget = p_value;
|
|
return false;
|
|
}
|
|
}
|
|
}
|