using System; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; using UnityEngine.XR.Interaction.Toolkit.Interactors; // Presenter°¡ InteractionView¸¦ Á¦¾îÇϱâ À§ÇÑ ÀÎÅÍÆäÀ̽º public interface IInteractionView { event Action OnRobotGrabbed; // VR ÄÁÆ®·Ñ·¯°¡ ·Îº¿À» Àâ¾Ò´Ù ³ùÀ» ¶§ ¹ß»ý event Action OnRobotReleased; // VR ÄÁÆ®·Ñ·¯°¡ ƯÁ¤ Æ÷ÀÎÆ®¸¦ Ŭ¸¯ÇßÀ» ¶§ ¹ß»ý event Action OnPointClicked; // VR ÄÁÆ®·Ñ·¯°¡ Æ÷ÀÎÆ®¸¦ Àâ°í µå·¡±× ½ÃÀÛ/Áß/³¡ ÇßÀ» ¶§ ¹ß»ý event Action OnPointDragStart; event Action OnPointDragUpdate; // (Æ÷ÀÎÆ® À妽º, »õ ¿ùµå ÁÂÇ¥) event Action OnPointDragEnd; // Presenter°¡ È£ÃâÇÒ ÇÔ¼öµé void ShowGhostRobot(RobotData pose); void HideGhostRobot(); void ShowDragArrow(Vector3 position); void HideDragArrow(); } public class InteractionView : MonoBehaviour, IInteractionView { public event Action OnRobotGrabbed; public event Action OnRobotReleased; public event Action OnPointClicked; public event Action OnPointDragStart; public event Action OnPointDragUpdate; public event Action OnPointDragEnd; private XRBaseInteractor interactor; private bool isInitialized = false; private bool isGrabbingPoint = false; private int currentGrabbedPointIndex = -1; public bool isGrabbingRobot = false; void Start() { // Ray Interactor¿Í Direct Interactor ¸ðµÎ ó¸®ÇÒ ¼ö ÀÖµµ·Ï XRBaseInteractor·Î ¹ÞÀ½ interactor = GetComponent(); if (interactor == null) { Debug.LogError("InteractionView requires an XRBaseInteractor (Ray or Direct) on the same GameObject.", this); return; } } // --- ½Ç½Ã°£ ½ºÆ®¸®¹ÖÀ» À§ÇÑ Update --- void Update() { if (isInitialized) { if (isGrabbingPoint) { Vector3 currentControllerPosition = interactor.attachTransform.position; OnPointDragUpdate?.Invoke(currentGrabbedPointIndex, currentControllerPosition); } else if(isGrabbingRobot) { Vector3 currentHandleTransform = interactor.attachTransform.position; Quaternion currentControllerRotation = interactor.attachTransform.rotation; OnRobotGrabbed?.Invoke(currentHandleTransform, currentControllerRotation); } } else { if (interactor == null) { interactor = GetComponentInChildren(true); } if (interactor != null && interactor.gameObject.activeInHierarchy) { InitializeInteraction(); } } } private void InitializeInteraction() { // XRI À̺¥Æ® ±¸µ¶ interactor.selectEntered.AddListener(HandleGrabStart); interactor.selectExited.AddListener(HandleGrabEnd); // 'Ŭ¸¯'À» °¨ÁöÇÏ·Á¸é interactor.activated À̺¥Æ®¸¦ ±¸µ¶ÇØ¾ß ÇÔ isInitialized = true; AppManager.Instance.RegisterView(this); Debug.Log("InteractionView ÃʱâÈ­ ¿Ï·á. Interactor À̺¥Æ® ±¸µ¶ ½ÃÀÛ."); } private void OnDestroy() { if (interactor != null) { interactor.selectEntered.RemoveListener(HandleGrabStart); interactor.selectExited.RemoveListener(HandleGrabEnd); } } // --- XRI À̺¥Æ® Çڵ鷯 --- // "Àâ±â" ¹öưÀ» ´­·¶À» ¶§ private void HandleGrabStart(SelectEnterEventArgs args) { // ÀâÀº ´ë»ó ¿ÀºêÁ§Æ® GameObject grabbedGO = args.interactableObject.transform.gameObject; //// ÀâÀº °ÍÀÌ "Æ÷ÀÎÆ®"ÀÎÁö È®ÀÎ (RobotPoint ½ºÅ©¸³Æ® Ž»ö) //RobotPoint point = grabbedGO.GetComponent(); //if (point != null) //{ // isGrabbingPoint = true; // currentGrabbedPointIndex = point.pointIndex; // // Presenter¿¡°Ô "µå·¡±× ½ÃÀÛ" À̺¥Æ® Àü¼Û // OnPointDragStart?.Invoke(currentGrabbedPointIndex); //} // ÀâÀº °ÍÀÌ "·Îº¿"ÀÎÁö È®ÀÎ if (grabbedGO.CompareTag("RobotArm")) { isGrabbingRobot = true; } } // "Àâ±â" ¹öưÀ» ¶ÃÀ» ¶§ private void HandleGrabEnd(SelectExitEventArgs args) { // "Æ÷ÀÎÆ®"¸¦ ³õ°í ÀÖ´Â ÁßÀ̾ú´Ù¸é if (isGrabbingPoint) { // Presenter¿¡°Ô "µå·¡±× ³¡" À̺¥Æ® Àü¼Û (ÆË¾÷ Æ®¸®°Å¿ë) OnPointDragEnd?.Invoke(currentGrabbedPointIndex); } // "·Îº¿"À» ³õ°í ÀÖ´Â ÁßÀ̾ú´Ù¸é else if (isGrabbingRobot) { // Presenter¿¡°Ô "·Îº¿ ³õ±â" À̺¥Æ® Àü¼Û (ÆË¾÷ Æ®¸®°Å¿ë) RobotData currentPose = GetCurrentRobotPoseFromController(); OnRobotReleased?.Invoke(currentPose); } // »óÅ ÃʱâÈ­ isGrabbingPoint = false; currentGrabbedPointIndex = -1; } private RobotData GetCurrentRobotPoseFromController() { // ÀÌ View´Â PresenterÀÇ º¯È¯ ·ÎÁ÷(ConvertVrToRobotPose)À» ¾Ë ¼ö ¾øÀ¸¹Ç·Î, // ÇöÀç ÄÁÆ®·Ñ·¯ À§Ä¡/ȸÀüÀ» ±â¹ÝÀ¸·Î '°¡Â¥' RobotData¸¦ ¸¸µê // Presenter°¡ ÀÌ µ¥ÀÌÅ͸¦ ¹Þ¾Æ ¾îÂ÷ÇÇ ´Ù½Ã º¯È¯(¶Ç´Â ¹«½Ã)ÇØ¾ß ÇÔ return new RobotData(); // Àӽà µ¥ÀÌÅÍ } // --- Presenter°¡ È£ÃâÇÒ ÇÔ¼öµé --- public void ShowGhostRobot(RobotData pose) { /* ¹ÝÅõ¸í ·Îº¿2 Ȱ¼ºÈ­ ¹× À§Ä¡ ¼³Á¤ */ } public void HideGhostRobot() { /* ¹ÝÅõ¸í ·Îº¿2 ºñȰ¼ºÈ­ */ } public void ShowDragArrow(Vector3 position) { /* µå·¡±×¿ë È­»ìÇ¥ UI Ȱ¼ºÈ­ ¹× À§Ä¡ ¼³Á¤ */ } public void HideDragArrow() { /* µå·¡±×¿ë È­»ìÇ¥ UI ºñȰ¼ºÈ­ */ } }