Files
2026-02-21 16:45:37 +08:00

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;
}
}
}