<fix> 로봇좌표 TCP전달 수정
This commit is contained in:
@@ -1,26 +1,14 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.Interaction.Toolkit;
|
||||
using UnityEngine.XR.Interaction.Toolkit.Interactables;
|
||||
using UnityEngine.XR.Interaction.Toolkit.Interactors;
|
||||
|
||||
// Presenter가 InteractionView를 제어하기 위한 인터페이스
|
||||
public interface IInteractionView
|
||||
{
|
||||
event Action<Vector3, Quaternion> OnRobotGrabbed;
|
||||
// VR 컨트롤러가 로봇을 잡았다 놨을 때 발생
|
||||
event Action<RobotData> OnRobotReleased;
|
||||
// VR 컨트롤러가 특정 포인트를 클릭했을 때 발생
|
||||
event Action<int> OnPointClicked;
|
||||
// VR 컨트롤러가 포인트를 잡고 드래그 시작/중/끝 했을 때 발생
|
||||
event Action<int> OnPointDragStart;
|
||||
event Action<int, Vector3> OnPointDragUpdate; // (포인트 인덱스, 새 월드 좌표)
|
||||
event Action<int> OnPointDragEnd;
|
||||
|
||||
// Presenter가 호출할 함수들
|
||||
void ShowGhostRobot(RobotData pose);
|
||||
void HideGhostRobot();
|
||||
void ShowDragArrow(Vector3 position);
|
||||
void HideDragArrow();
|
||||
}
|
||||
|
||||
public class InteractionView : MonoBehaviour, IInteractionView
|
||||
@@ -29,10 +17,12 @@ public class InteractionView : MonoBehaviour, IInteractionView
|
||||
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, Vector3, Quaternion> OnPointDragUpdate;
|
||||
public event Action<int> OnPointDragEnd;
|
||||
|
||||
private XRBaseInteractor interactor;
|
||||
[SerializeField]private NearFarInteractor nearFarInteractor;
|
||||
private XRBaseInteractor baseInteractor;
|
||||
private IXRRayProvider rayProvider;
|
||||
|
||||
private bool isInitialized = false;
|
||||
private bool isGrabbingPoint = false;
|
||||
@@ -42,41 +32,57 @@ public class InteractionView : MonoBehaviour, IInteractionView
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Ray Interactor와 Direct Interactor 모두 처리할 수 있도록 XRBaseInteractor로 받음
|
||||
interactor = GetComponent<NearFarInteractor>();
|
||||
if (interactor == null)
|
||||
nearFarInteractor = GetComponent<NearFarInteractor>();
|
||||
|
||||
if (nearFarInteractor == null)
|
||||
{
|
||||
Debug.LogError("InteractionView requires an XRBaseInteractor (Ray or Direct) on the same GameObject.", this);
|
||||
Debug.LogError("InteractionView: 'nearFarInteractor'가 할당되지 않았습니다", this);
|
||||
return;
|
||||
}
|
||||
|
||||
baseInteractor = nearFarInteractor as XRBaseInteractor;
|
||||
rayProvider = nearFarInteractor as IXRRayProvider;
|
||||
|
||||
if (baseInteractor == null)
|
||||
{
|
||||
Debug.LogError("NearFarInteractor를 XRBaseInteractor로 변환할 수 없습니다.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeInteraction();
|
||||
}
|
||||
|
||||
// --- 실시간 스트리밍을 위한 Update ---
|
||||
void Update()
|
||||
{
|
||||
if (isInitialized)
|
||||
if (!isInitialized || rayProvider == null)
|
||||
{
|
||||
if (isGrabbingPoint)
|
||||
if (nearFarInteractor == null)
|
||||
{
|
||||
Vector3 currentControllerPosition = interactor.attachTransform.position;
|
||||
OnPointDragUpdate?.Invoke(currentGrabbedPointIndex, currentControllerPosition);
|
||||
nearFarInteractor = GetComponentInChildren<NearFarInteractor>(true);
|
||||
baseInteractor = nearFarInteractor as XRBaseInteractor;
|
||||
rayProvider = nearFarInteractor as IXRRayProvider;
|
||||
}
|
||||
else if(isGrabbingRobot)
|
||||
if (nearFarInteractor != null && nearFarInteractor.gameObject.activeInHierarchy)
|
||||
{
|
||||
Vector3 currentHandleTransform = interactor.attachTransform.position;
|
||||
Quaternion currentControllerRotation = interactor.attachTransform.rotation;
|
||||
OnRobotGrabbed?.Invoke(currentHandleTransform, currentControllerRotation);
|
||||
InitializeInteraction();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (interactor == null)
|
||||
Vector3 currentTargetPosition = Vector3.zero;
|
||||
Quaternion currentTargetRotation = Quaternion.identity;
|
||||
|
||||
currentTargetPosition = rayProvider.rayEndPoint;
|
||||
currentTargetRotation = baseInteractor.attachTransform.rotation;
|
||||
|
||||
|
||||
if (isGrabbingPoint)
|
||||
{
|
||||
interactor = GetComponentInChildren<NearFarInteractor>(true);
|
||||
OnPointDragUpdate?.Invoke(currentGrabbedPointIndex, currentTargetPosition, currentTargetRotation);
|
||||
}
|
||||
if (interactor != null && interactor.gameObject.activeInHierarchy)
|
||||
else if (isGrabbingRobot)
|
||||
{
|
||||
InitializeInteraction();
|
||||
OnRobotGrabbed?.Invoke(currentTargetPosition, currentTargetRotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,22 +90,23 @@ public class InteractionView : MonoBehaviour, IInteractionView
|
||||
private void InitializeInteraction()
|
||||
{
|
||||
// XRI 이벤트 구독
|
||||
interactor.selectEntered.AddListener(HandleGrabStart);
|
||||
interactor.selectExited.AddListener(HandleGrabEnd);
|
||||
|
||||
// '클릭'을 감지하려면 interactor.activated 이벤트를 구독해야 함
|
||||
baseInteractor.selectEntered.AddListener(HandleGrabStart);
|
||||
baseInteractor.selectExited.AddListener(HandleGrabEnd);
|
||||
//interactor.activated.AddListener(OnActivated);
|
||||
//interactor.deactivated.AddListener(OnDeactivated);
|
||||
|
||||
isInitialized = true;
|
||||
AppManager.Instance.RegisterView(this);
|
||||
Debug.Log("InteractionView 초기화 완료. Interactor 이벤트 구독 시작.");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (interactor != null)
|
||||
if (baseInteractor != null)
|
||||
{
|
||||
interactor.selectEntered.RemoveListener(HandleGrabStart);
|
||||
interactor.selectExited.RemoveListener(HandleGrabEnd);
|
||||
baseInteractor.selectEntered.RemoveListener(HandleGrabStart);
|
||||
baseInteractor.selectExited.RemoveListener(HandleGrabEnd);
|
||||
//interactor.activated.RemoveListener(OnActivated);
|
||||
//interactor.deactivated.RemoveListener(OnDeactivated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,48 +115,157 @@ public class InteractionView : MonoBehaviour, IInteractionView
|
||||
// "잡기" 버튼을 눌렀을 때
|
||||
private void HandleGrabStart(SelectEnterEventArgs args)
|
||||
{
|
||||
// 잡은 대상 오브젝트
|
||||
GameObject grabbedGO = args.interactableObject.transform.gameObject;
|
||||
|
||||
//// 잡은 것이 "포인트"인지 확인 (RobotPoint 스크립트 탐색)
|
||||
// 잡은 것이 "포인트"인지 확인
|
||||
//RobotPoint point = grabbedGO.GetComponent<RobotPoint>();
|
||||
//if (point != null)
|
||||
//{
|
||||
// isGrabbingPoint = true;
|
||||
// isGrabbingRobot = false;
|
||||
// currentGrabbedPointIndex = point.pointIndex;
|
||||
|
||||
// // Presenter에게 "드래그 시작" 이벤트 전송
|
||||
// // (Presenter의 HandlePointDragStart 호출)
|
||||
// OnPointDragStart?.Invoke(currentGrabbedPointIndex);
|
||||
//}
|
||||
// 잡은 것이 "로봇"인지 확인
|
||||
if (grabbedGO.CompareTag("RobotArm"))
|
||||
// 2. 잡은 것이 "로봇 핸들"인지 확인
|
||||
if (grabbedGO.CompareTag("RobotArm"))
|
||||
{
|
||||
isGrabbingPoint = false;
|
||||
isGrabbingRobot = true;
|
||||
|
||||
// (로봇 자체를 잡는 것은 -1 인덱스로 Presenter에게 알림)
|
||||
currentGrabbedPointIndex = -1;
|
||||
|
||||
// (로봇 잡기도 "PointDragStart" 이벤트로 통합하여 Presenter에 알림)
|
||||
OnPointDragStart?.Invoke(currentGrabbedPointIndex);
|
||||
}
|
||||
|
||||
//if (!enableSelectToDrag) return;
|
||||
//BeginDrag(args.interactorObject);
|
||||
}
|
||||
|
||||
// "잡기" 버튼을 뗐을 때
|
||||
private void HandleGrabEnd(SelectExitEventArgs args)
|
||||
{
|
||||
// "포인트"를 놓고 있는 중이었다면
|
||||
if (isGrabbingPoint)
|
||||
{
|
||||
// Presenter에게 "드래그 끝" 이벤트 전송 (팝업 트리거용)
|
||||
OnPointDragEnd?.Invoke(currentGrabbedPointIndex);
|
||||
}
|
||||
// "로봇"을 놓고 있는 중이었다면
|
||||
else if (isGrabbingRobot)
|
||||
{
|
||||
// Presenter에게 "로봇 놓기" 이벤트 전송 (팝업 트리거용)
|
||||
RobotData currentPose = GetCurrentRobotPoseFromController();
|
||||
OnRobotReleased?.Invoke(currentPose);
|
||||
}
|
||||
//if (!enableSelectToDrag) return;
|
||||
//EndDrag();
|
||||
//// "포인트"를 놓고 있는 중이었다면
|
||||
//if (isGrabbingPoint)
|
||||
//{
|
||||
// // Presenter에게 "드래그 끝" 이벤트 전송 (팝업 트리거용)
|
||||
// OnPointDragEnd?.Invoke(currentGrabbedPointIndex);
|
||||
//}
|
||||
//// "로봇"을 놓고 있는 중이었다면
|
||||
//else if (isGrabbingRobot)
|
||||
//{
|
||||
// // Presenter에게 "로봇 놓기" 이벤트 전송 (팝업 트리거용)
|
||||
// RobotData currentPose = GetCurrentRobotPoseFromController();
|
||||
// OnRobotReleased?.Invoke(currentPose);
|
||||
//}
|
||||
|
||||
// 상태 초기화
|
||||
isGrabbingPoint = false;
|
||||
isGrabbingRobot = false;
|
||||
currentGrabbedPointIndex = -1;
|
||||
}
|
||||
|
||||
// ---- Drag lifecycle ----
|
||||
//private void BeginDrag(IXRInteractor interactor)
|
||||
//{
|
||||
// currentInteractor = interactor;
|
||||
// isDragging = true;
|
||||
|
||||
// startPosition = transform.position;
|
||||
// //pathLine.enabled = true;
|
||||
|
||||
// uiController?.UpdateStatus("드래그 중...");
|
||||
// if (communicationScript != null) communicationScript.isMoving = false;
|
||||
|
||||
// // ← 드래그 루프 시작
|
||||
// StartDragMoveLoop();
|
||||
//}
|
||||
|
||||
//private void EndDrag()
|
||||
//{
|
||||
// if (!isDragging) return;
|
||||
// isDragging = false;
|
||||
// uiController?.UpdateStatus("완료!");
|
||||
// communicationScript.isMoving = false;
|
||||
// // ← 루프 중지
|
||||
// StopDragMoveLoop();
|
||||
|
||||
// currentInteractor = null;
|
||||
//}
|
||||
|
||||
//private void StopDragMoveLoop()
|
||||
//{
|
||||
// if (dragLoopCts != null)
|
||||
// {
|
||||
// dragLoopCts.Cancel();
|
||||
// dragLoopCts.Dispose();
|
||||
// dragLoopCts = null;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//private void StartDragMoveLoop()
|
||||
//{
|
||||
// StopDragMoveLoop(); // 중복 방지
|
||||
// dragLoopCts = new CancellationTokenSource();
|
||||
// _ = DragMoveLoopAsync(dragLoopCts.Token);
|
||||
//}
|
||||
|
||||
//private async Task DragMoveLoopAsync(CancellationToken token)
|
||||
//{
|
||||
// // 드래그 동안 100ms 주기로 전송
|
||||
// while (!token.IsCancellationRequested && isDragging)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// // 로봇이 아직 이동 중이 아니라면(대기 상태) 최신 dragPosition으로 지령 전송
|
||||
// if (communicationScript != null && !communicationScript.isMoving)
|
||||
// {
|
||||
// await MovingTask(); // 내부에서 StratMovement(dragPosition) 호출 및 isMoving 갱신 :contentReference[oaicite:4]{index=4}
|
||||
// }
|
||||
|
||||
// await Task.Delay(10, token); // 100ms 주기
|
||||
// }
|
||||
// catch (TaskCanceledException) { /* 정상 취소 */ }
|
||||
// }
|
||||
//}
|
||||
|
||||
//// ---- Per-frame ----
|
||||
//void Update()
|
||||
//{
|
||||
// if (isDragging && currentInteractor != null)
|
||||
// {
|
||||
// communicationScript.isMoving = false;
|
||||
// // 1) Ray Interactor: 현재 3D Raycast 히트 포인트가 있으면 그대로 사용
|
||||
// if (currentInteractor is XRRayInteractor ray &&
|
||||
// ray.TryGetCurrent3DRaycastHit(out RaycastHit hit))
|
||||
// {
|
||||
// dragPosition = hit.point;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // 2) Direct Interactor 또는 Ray 히트가 없을 때: 컨트롤러(또는 attachTransform) 위치 사용
|
||||
// var t = currentInteractor.transform;
|
||||
// var attach = currentInteractor.GetAttachTransform(null);
|
||||
// dragPosition = attach != null ? attach.position : t.position;
|
||||
// }
|
||||
|
||||
// uiController?.UpdateCoordinates(dragPosition); // 기존 UI 갱신 유지 :contentReference[oaicite:2]{index=2}
|
||||
// }
|
||||
//}
|
||||
|
||||
//private async Task MovingTask()
|
||||
//{
|
||||
// if (communicationScript == null) return;
|
||||
// bool ok = await communicationScript.StratMovement(dragPosition); // 기존 호출 그대로 사용 :contentReference[oaicite:3]{index=3}
|
||||
// if (ok) communicationScript.isMoving = true;
|
||||
//}
|
||||
|
||||
private RobotData GetCurrentRobotPoseFromController()
|
||||
{
|
||||
// 이 View는 Presenter의 변환 로직(ConvertVrToRobotPose)을 알 수 없으므로,
|
||||
@@ -159,8 +275,23 @@ public class InteractionView : MonoBehaviour, IInteractionView
|
||||
}
|
||||
|
||||
// --- Presenter가 호출할 함수들 ---
|
||||
public void ShowGhostRobot(RobotData pose) { /* 반투명 로봇2 활성화 및 위치 설정 */ }
|
||||
public void HideGhostRobot() { /* 반투명 로봇2 비활성화 */ }
|
||||
public void ShowDragArrow(Vector3 position) { /* 드래그용 화살표 UI 활성화 및 위치 설정 */ }
|
||||
public void HideDragArrow() { /* 드래그용 화살표 UI 비활성화 */ }
|
||||
public void ShowGhostRobot(RobotData pose)
|
||||
{
|
||||
/* 반투명 로봇2 활성화 및 위치 설정 */
|
||||
}
|
||||
|
||||
public void HideGhostRobot()
|
||||
{
|
||||
/* 반투명 로봇2 비활성화 */
|
||||
}
|
||||
|
||||
public void ShowDragArrow(Vector3 position)
|
||||
{
|
||||
/* 드래그용 화살표 UI 활성화 및 위치 설정 */
|
||||
}
|
||||
|
||||
public void HideDragArrow()
|
||||
{
|
||||
/* 드래그용 화살표 UI 비활성화 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public interface IProgramView
|
||||
public class ProgramView : MonoBehaviour, IProgramView
|
||||
{
|
||||
// --- UI 요소 참조 ---
|
||||
[SerializeField] private Button loadIconButton;
|
||||
//[SerializeField] private Button loadIconButton;
|
||||
[SerializeField] private Button loadProgramButton;
|
||||
//[SerializeField] private Button saveProgramButton;
|
||||
//[SerializeField] private Button addPointButton; // UI상 위치를 찍는 버튼
|
||||
@@ -68,13 +68,12 @@ public class ProgramView : MonoBehaviour, IProgramView
|
||||
|
||||
backspaceButton.onClick.AddListener(HandleBackspace);
|
||||
createProgramButton.onClick.AddListener(HandleCreateClick);
|
||||
loadIconButton.onClick.AddListener(HandleLoadIconClick);
|
||||
//loadIconButton.onClick.AddListener(HandleLoadIconClick);
|
||||
closeProgramListButton.onClick.AddListener(HideProgramList);
|
||||
|
||||
programSelectPanel.SetActive(true);
|
||||
programNewPanel.SetActive(true);
|
||||
programListPanel.SetActive(false);
|
||||
loadProgramButton.gameObject.SetActive(false);
|
||||
programIdText.text = string.Empty;
|
||||
}
|
||||
|
||||
@@ -97,11 +96,6 @@ public class ProgramView : MonoBehaviour, IProgramView
|
||||
OnCreateProgramClicked?.Invoke(inputId);
|
||||
}
|
||||
|
||||
private void HandleLoadIconClick()
|
||||
{
|
||||
loadProgramButton.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
// Presenter가 호출할 오류 메시지 표시 함수
|
||||
public void ShowMessage(string message)
|
||||
{
|
||||
@@ -112,21 +106,10 @@ public class ProgramView : MonoBehaviour, IProgramView
|
||||
{
|
||||
if (programId == null)
|
||||
{
|
||||
//currentProgramIdText.text = "No Program Loaded";
|
||||
//endpointListText.text = "";
|
||||
Debug.Log("No Program Loaded");
|
||||
return;
|
||||
}
|
||||
Debug.Log($"연결된 프로그램: {programId}.job");
|
||||
|
||||
//currentProgramIdText.text = "Current: " + program.programId;
|
||||
|
||||
//System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
//for (int i = 0; i < program.endpointPositions.Count; i++)
|
||||
//{
|
||||
// sb.AppendLine($"P{i + 1}: {program.endpointPositions[i].ToString("F2")}");
|
||||
//}
|
||||
//endpointListText.text = sb.ToString();
|
||||
}
|
||||
|
||||
public void ShowProgramList(List<string> programIds)
|
||||
|
||||
Reference in New Issue
Block a user