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