namespace ChivaXR.VR
{
using System.Collections.Generic;
using UnityEngine;
using Sirenix.OdinInspector;
using System.Linq;
using System;
public struct CVR_SimulationEventArgs
{
public IVR_Interactable interactable_Base;
}
public enum ToolAxis
{
x,
y,
z
}
public delegate void CVRInteractableSimulationEventHandler(object sender, CVR_SimulationEventArgs e);
[RequireComponent(typeof(IVR_Interactable))]
///
/// 工具模拟基类
///
public class CVR_SimulationTool : SerializedMonoBehaviour
{
private IVR_Interactable interactable;
public IVR_Interactable Interactable
{
get
{
if (interactable == null)
{
interactable = this.GetComponent();
}
return interactable;
}
}
private bool useSimulationPoint = false;
private bool simulationPointCreatInHandChild = true;
public bool UseSimulationPoint { get => useSimulationPoint; set => useSimulationPoint = value; }
///
/// 辅助模拟点是否创建在手部子级下
///
public bool SimulationPointCreatInHandChild { get => simulationPointCreatInHandChild; set => simulationPointCreatInHandChild = value; }
///
/// 模拟点生成位置
///
public Transform simulationPointPlace;
[HideInInspector]
public CVR_SimulationPoint simulationPoint;
[HideInInspector]
public Transform recordGrabPointInHand;
[HideInInspector]
public GameObject currentGrabHand;
[Header("工具模拟动画")]
[TypeFilter("GetFilteredTypeList")]
public CVR_SimulationAniBase SimulationAniDriverData;
public IEnumerable GetFilteredTypeList()
{
var q = typeof(CVR_SimulationAniBase).Assembly.GetTypes()
.Where(x => !x.IsAbstract)
.Where(x => !x.IsGenericTypeDefinition)
.Where(x => typeof(CVR_SimulationAniBase).IsAssignableFrom(x));
return q;
}
[HideInInspector]
public CVRInteractableSimulationEventHandler ExitSimulationMode;
private List childMeshRenderers;
protected virtual void Start()
{
Init();
if (simulationPointPlace != null)
{
UseSimulationPoint = true;
}
}
private void Update()
{
if (interactable.CVR_IsGrabbed() && currentGrabHand != null && interactable.CVR_IsUsing())
{
UpdataSimulationAniDates();
}
}
protected virtual void Init()
{
interactable = this.gameObject.GetComponent();
interactable.CVR_InteractableObjectGrabbed += StartGrab;
interactable.CVR_InteractableObjectUsed += StartUsing;
interactable.CVR_InteractableObjectPreUnGrabbed += PreStopGrab;
interactable.CVR_InteractableObjectUnused += StopUsed;
if (SimulationAniDriverData != null)
SimulationAniDriverData.Init(this);
}
protected virtual void StartGrab(object sender, CVR_InteractableObjectEventArgs e)
{
if (SimulationAniDriverData != null)
{
SimulationAniDriverData.CVR_Grab();
}
currentGrabHand = e.interactingObject;
}
protected virtual void PreStopGrab(object sender, CVR_InteractableObjectEventArgs e)
{
if (SimulationAniDriverData != null)
{
SimulationAniDriverData.CVR_UnGrab();
}
currentGrabHand = null;
}
protected virtual void StartUsing(object sender, CVR_InteractableObjectEventArgs e)
{
TriggerUsing();
if (!UseSimulationPoint) return;
CreatSimulationPoint();
}
protected virtual void StopUsed(object sender, CVR_InteractableObjectEventArgs e)
{
TriggerUnUsed();
if (!UseSimulationPoint) return;
CloseSimulationPoint();
}
///
/// 创建模拟操作点
///
public void CreatSimulationPoint()
{
if (simulationPoint != null) return;
if (recordGrabPointInHand == null)
{
recordGrabPointInHand = new GameObject(interactable.GetToolType().ToString()).transform;
}
recordGrabPointInHand.transform.parent = this.transform.parent;
recordGrabPointInHand.transform.localPosition = this.transform.localPosition;
recordGrabPointInHand.transform.localRotation = this.transform.localRotation;
simulationPoint = CVR_ToolManager.Instance.CreatSimulationPoint(interactable.GetToolType());
simulationPoint.transform.position = simulationPointPlace.transform.position;
simulationPoint.transform.rotation = simulationPointPlace.transform.rotation;
this.transform.parent = simulationPoint.transform;
this.transform.localPosition = simulationPointPlace.InverseTransformPoint(this.transform.position);
this.transform.localRotation = Quaternion.identity;
if (SimulationPointCreatInHandChild)
{
simulationPoint.transform.parent = recordGrabPointInHand.transform;
}
simulationPoint.BindInteractable(this.interactable);
if (SimulationAniDriverData != null)
{
SimulationAniDriverData.CVR_CreatSimulationPoint(simulationPoint);
}
}
///
/// 关闭操作模拟点
///
private void CloseSimulationPoint()
{
if (!this.gameObject.activeSelf) this.gameObject.SetActive(true);
this.transform.SetParent(recordGrabPointInHand.transform.parent);
this.transform.localPosition = recordGrabPointInHand.transform.localPosition;
this.transform.localRotation = recordGrabPointInHand.transform.localRotation;
OnCloseSimulation(new CVR_SimulationEventArgs { interactable_Base = this.interactable });
CVR_ToolManager.Instance.ClearSimulationPoint(interactable.GetToolType(), simulationPoint);
simulationPoint = null;
}
///
///关闭模拟控制
///
///
public void OnCloseSimulation(CVR_SimulationEventArgs e)
{
if (ExitSimulationMode != null)
{
ExitSimulationMode(this, e);
}
}
private void UpdataSimulationAniDates()
{
if (SimulationAniDriverData == null) return;
//Trigger按键XValue值
SimulationAniDriverData.CVR_TriggerXAxis_Value(interactable.CVR_GetControllerAxis(CVR_ButtonTypes.Trigger).x);
if (UseSimulationPoint)
{
if (simulationPoint == null) CreatSimulationPoint();
SimulationAniDriverData.CVR_UsingSimulationPointUpdate(simulationPoint);
}
}
private void TriggerUsing()
{
if (SimulationAniDriverData != null)
{
SimulationAniDriverData.CVR_TriggerUsing();
}
}
private void TriggerUnUsed()
{
if (SimulationAniDriverData != null)
{
SimulationAniDriverData.CVR_TriggerUnUsed();
SimulationAniDriverData.CVR_TriggerXAxis_Value(0);
}
}
}
}