237 lines
5.1 KiB
C#
237 lines
5.1 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
namespace Moonlit.FootstepPro
|
|
{
|
|
[AddComponentMenu("FootprintSystem/Foot")]
|
|
public class Foot : MonoBehaviour
|
|
{
|
|
private class FootState
|
|
{
|
|
public bool Over;
|
|
|
|
public bool Under;
|
|
}
|
|
|
|
[SerializeField]
|
|
[Header("Foot type")]
|
|
private FootstepDataType _Type;
|
|
|
|
[SerializeField]
|
|
[Header("Settings")]
|
|
private float _TriggerHeight;
|
|
|
|
[SerializeField]
|
|
private List<IStepDetector> _Detectors;
|
|
|
|
[Header("Controller")]
|
|
public IFootstepController Controller;
|
|
|
|
public Vector3 EulerRotation;
|
|
|
|
private FootState _FootState = new FootState();
|
|
|
|
[SerializeField]
|
|
private List<FootTrigger> _Triggers = new List<FootTrigger>();
|
|
|
|
private List<IStepDetector> _OrDetectors = new List<IStepDetector>();
|
|
|
|
private List<IStepDetector> _AndDetectors = new List<IStepDetector>();
|
|
|
|
public FootstepDataType Type
|
|
{
|
|
get
|
|
{
|
|
return _Type;
|
|
}
|
|
set
|
|
{
|
|
_Type = value;
|
|
}
|
|
}
|
|
|
|
public List<FootTrigger> Triggers
|
|
{
|
|
get
|
|
{
|
|
return _Triggers;
|
|
}
|
|
}
|
|
|
|
public float TriggerHeight
|
|
{
|
|
get
|
|
{
|
|
return _TriggerHeight;
|
|
}
|
|
set
|
|
{
|
|
_TriggerHeight = value;
|
|
}
|
|
}
|
|
|
|
public List<IStepDetector> Detectors
|
|
{
|
|
get
|
|
{
|
|
return _Detectors;
|
|
}
|
|
}
|
|
|
|
private void Awake()
|
|
{
|
|
ValidateTriggers();
|
|
_FootState.Under = true;
|
|
_FootState.Over = false;
|
|
_Detectors = GetComponents<IStepDetector>().ToList();
|
|
_OrDetectors = _Detectors.Where((IStepDetector x) => x.Type == IStepDetector.CombineType.Optional).ToList();
|
|
_AndDetectors = _Detectors.Where((IStepDetector x) => x.Type == IStepDetector.CombineType.Required).ToList();
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!(Controller == null))
|
|
{
|
|
if (CheckStep() && _FootState.Over)
|
|
{
|
|
_FootState.Over = false;
|
|
Place();
|
|
}
|
|
if (!IsTriggered())
|
|
{
|
|
_FootState.Over = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Reset()
|
|
{
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
if (!(Controller == null))
|
|
{
|
|
Vector3 up = Controller.Up;
|
|
Vector3 triggerPlanePosition = GetTriggerPlanePosition();
|
|
Gizmos.matrix = Matrix4x4.TRS(triggerPlanePosition, Controller.transform.rotation, Vector3.one);
|
|
Gizmos.color = new Color(1f, 1f, 1f, 0.1f + ((!_FootState.Over) ? 0.5f : 0f)) * Color.magenta;
|
|
Gizmos.DrawCube(new Vector3(0f, 0f, 0f), new Vector3(0.3f, 0.001f, 0.3f));
|
|
}
|
|
}
|
|
|
|
public void Place()
|
|
{
|
|
if (Controller == null)
|
|
{
|
|
return;
|
|
}
|
|
FootInfo footInfo = new FootInfo();
|
|
footInfo.Position = base.transform.position;
|
|
footInfo.Rotation = base.transform.rotation;
|
|
footInfo.Data = Type;
|
|
List<RaycastHit> list = Physics.RaycastAll(base.transform.position + Controller.Up, -Controller.Up).ToList();
|
|
if (list.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
List<RaycastHit> list2 = list.Where(delegate(RaycastHit x)
|
|
{
|
|
Surface component = x.collider.GetComponent<Surface>();
|
|
return component != null && component.Type != null;
|
|
}).ToList();
|
|
if (list2.Count != 0)
|
|
{
|
|
RaycastHit[] array = list2.OrderBy((RaycastHit x) => x.distance).ToArray();
|
|
Controller.Callback(array[0], footInfo);
|
|
}
|
|
}
|
|
|
|
public void ResetRotation(Vector3 euler)
|
|
{
|
|
EulerRotation = euler;
|
|
base.transform.rotation = Quaternion.Euler(EulerRotation);
|
|
foreach (FootTrigger trigger in _Triggers)
|
|
{
|
|
trigger.transform.rotation = Quaternion.identity;
|
|
}
|
|
}
|
|
|
|
public void ValidateTriggers()
|
|
{
|
|
_Triggers.Where((FootTrigger x) => x == null).ToList().ForEach(delegate(FootTrigger x)
|
|
{
|
|
_Triggers.Remove(x);
|
|
});
|
|
}
|
|
|
|
private bool CheckStep()
|
|
{
|
|
bool flag = IsTriggered();
|
|
foreach (IStepDetector orDetector in _OrDetectors)
|
|
{
|
|
if (orDetector.enabled)
|
|
{
|
|
flag |= orDetector.Detect(this);
|
|
}
|
|
}
|
|
foreach (IStepDetector andDetector in _AndDetectors)
|
|
{
|
|
if (andDetector.enabled)
|
|
{
|
|
flag &= andDetector.Detect(this);
|
|
}
|
|
}
|
|
foreach (IStepDetector detector in _Detectors)
|
|
{
|
|
detector.Callback(flag);
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
private bool IsTriggered()
|
|
{
|
|
foreach (FootTrigger trigger in _Triggers)
|
|
{
|
|
Vector3 normalized = (trigger.transform.position - GetTriggerPlanePosition()).normalized;
|
|
float num = Vector3.Dot(normalized, -Controller.Up.normalized);
|
|
if (num < 0f)
|
|
{
|
|
trigger.IsTriggered = true;
|
|
}
|
|
else
|
|
{
|
|
trigger.IsTriggered = false;
|
|
}
|
|
}
|
|
foreach (FootTrigger trigger2 in _Triggers)
|
|
{
|
|
if (!trigger2.IsTriggered)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private Vector3 GetTriggerPlanePosition()
|
|
{
|
|
if (Controller == null)
|
|
{
|
|
return Vector3.zero;
|
|
}
|
|
return CalculateTriggerPosition(base.transform.position, -Controller.Up, Controller.transform.position, 0f - _TriggerHeight);
|
|
}
|
|
|
|
private Vector3 CalculateTriggerPosition(Vector3 footPosition, Vector3 bodyNormal, Vector3 bodyPosition, float triggerDistance)
|
|
{
|
|
Vector3 vector = footPosition + bodyNormal;
|
|
Vector3 lhs = bodyPosition - footPosition;
|
|
Vector3 vector2 = vector - footPosition;
|
|
Vector3 vector3 = footPosition + Vector3.Dot(lhs, vector2) / Vector3.Dot(vector2, vector2) * vector2;
|
|
return vector3 + bodyNormal * triggerDistance;
|
|
}
|
|
}
|
|
}
|