<feat> 로봇 동기화 (제어기 <-> 3d)
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.Interaction.Toolkit;
|
||||
using UnityEngine.XR.Interaction.Toolkit.Interactors;
|
||||
|
||||
// Presenter가 InteractionView를 제어하기 위한 인터페이스
|
||||
public interface IInteractionView
|
||||
{
|
||||
event Action<Vector3, Quaternion> OnRobotGrabbed;
|
||||
// VR 컨트롤러가 로봇을 잡았다 놨을 때 발생
|
||||
event Action<RobotData> OnRobotReleased;
|
||||
// VR 컨트롤러가 특정 포인트를 클릭했을 때 발생
|
||||
@@ -20,38 +23,139 @@ public interface IInteractionView
|
||||
void HideDragArrow();
|
||||
}
|
||||
|
||||
// (이 스크립트는 VR 컨트롤러 로직이 있는 곳에 붙어야 합니다)
|
||||
public class InteractionView : MonoBehaviour, IInteractionView
|
||||
{
|
||||
public event Action<Vector3, Quaternion> OnRobotGrabbed;
|
||||
public event Action<RobotData> OnRobotReleased;
|
||||
public event Action<int> OnPointClicked;
|
||||
public event Action<int> OnPointDragStart;
|
||||
public event Action<int, Vector3> OnPointDragUpdate;
|
||||
public event Action<int> 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<NearFarInteractor>();
|
||||
if (interactor == null)
|
||||
{
|
||||
Debug.LogError("InteractionView requires an XRBaseInteractor (Ray or Direct) on the same GameObject.", this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// --- 실시간 스트리밍을 위한 Update ---
|
||||
void Update()
|
||||
{
|
||||
// 컨트롤러로 로봇을 잡고있는지 감지
|
||||
// if (IsGrabbingRobot()) { ... }
|
||||
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<NearFarInteractor>(true);
|
||||
}
|
||||
if (interactor != null && interactor.gameObject.activeInHierarchy)
|
||||
{
|
||||
InitializeInteraction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 컨트롤러 그랩 버튼을 뗐을 때
|
||||
// if (OnGrabRelease())
|
||||
// {
|
||||
// RobotData currentPose = GetCurrentRobotPose();
|
||||
// OnRobotReleased?.Invoke(currentPose); // 2. "위치 확정?" 팝업 요청
|
||||
// }
|
||||
private void InitializeInteraction()
|
||||
{
|
||||
// XRI 이벤트 구독
|
||||
interactor.selectEntered.AddListener(HandleGrabStart);
|
||||
interactor.selectExited.AddListener(HandleGrabEnd);
|
||||
|
||||
// 컨트롤러로 포인트를 클릭했을 때
|
||||
// if (OnPointClick(out int clickedPointIndex))
|
||||
// {
|
||||
// OnPointClicked?.Invoke(clickedPointIndex); // 8. "이동/삭제?" 팝업 요청
|
||||
// }
|
||||
// '클릭'을 감지하려면 interactor.activated 이벤트를 구독해야 함
|
||||
|
||||
// 컨트롤러로 포인트를 꾹 누르기 시작(드래그 시작)
|
||||
// if (OnPointHold(out int draggedPointIndex))
|
||||
// {
|
||||
// OnPointDragStart?.Invoke(draggedPointIndex); // 5. 드래그 시작
|
||||
// }
|
||||
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<RobotPoint>();
|
||||
//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가 호출할 함수들 ---
|
||||
|
||||
Reference in New Issue
Block a user