Files
HDRobotics/Assets/Scripts/View/InteractionView.cs

289 lines
8.1 KiB
C#
Raw Normal View History

2025-10-30 09:31:05 +09:00
using System;
using System.Collections;
2025-11-06 15:28:16 +09:00
using System.Threading;
using System.Threading.Tasks;
2025-10-30 09:31:05 +09:00
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
2025-11-06 15:28:16 +09:00
using UnityEngine.XR.Interaction.Toolkit.Interactables;
using UnityEngine.XR.Interaction.Toolkit.Interactors;
2025-10-30 09:31:05 +09:00
public interface IInteractionView
{
2025-11-06 15:28:16 +09:00
2025-10-30 09:31:05 +09:00
}
public class InteractionView : MonoBehaviour, IInteractionView
{
public event Action<Vector3, Quaternion> OnRobotGrabbed;
2025-10-30 09:31:05 +09:00
public event Action<RobotData> OnRobotReleased;
public event Action<int, Vector3> OnPointClicked;
2025-10-30 09:31:05 +09:00
public event Action<int> OnPointDragStart;
2025-11-06 15:28:16 +09:00
public event Action<int, Vector3, Quaternion> OnPointDragUpdate;
2025-10-30 09:31:05 +09:00
public event Action<int> OnPointDragEnd;
2025-11-06 15:28:16 +09:00
[SerializeField]private NearFarInteractor nearFarInteractor;
private XRBaseInteractor baseInteractor;
private IXRRayProvider rayProvider;
2025-11-06 20:14:27 +09:00
[SerializeField]
[Tooltip("<22><EFBFBD><E5B7A1> <20><> <20><>ġ<EFBFBD><C4A1> ǥ<><C7A5><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>κ<EFBFBD> <20><><EFBFBD><EFBFBD>")]
private GameObject ghostRobot;
[SerializeField]
[Tooltip("<22><EFBFBD>׿<EFBFBD> <20><><EFBFBD><20>̹<EFBFBD><CCB9><EFBFBD>")]
private GameObject dragArrow;
[SerializeField] private float clickTimeThreshold = 0.5f;
[SerializeField] private float dragMovementThreshold = 0.05f;
private Coroutine clickOrDragCoroutine = null;
private Vector3 startGrabPosition;
2025-11-06 20:14:27 +09:00
private bool isInitialized = false;
private bool isGrabbingPoint = false;
private int currentGrabbedPointIndex = -1;
Vector3 currentTargetPosition = Vector3.zero;
Quaternion currentTargetRotation = Quaternion.identity;
public bool isGrabbingRobot = false;
//void Start()
//{
// nearFarInteractor = GetComponentInChildren<NearFarInteractor>();
2025-11-06 15:28:16 +09:00
// if (nearFarInteractor == null)
// {
// Debug.LogError("InteractionView: 'nearFarInteractor'<27><> <20>Ҵ<EFBFBD><D2B4><EFBFBD><EFBFBD><EFBFBD> <20>ʾҽ<CABE><D2BD>ϴ<EFBFBD>", this);
// return;
// }
2025-11-06 15:28:16 +09:00
// baseInteractor = nearFarInteractor as XRBaseInteractor;
// rayProvider = nearFarInteractor as IXRRayProvider;
2025-11-06 15:28:16 +09:00
// if (baseInteractor == null)
// {
// Debug.LogError("NearFarInteractor<6F><72> XRBaseInteractor<6F><72> <20><>ȯ<EFBFBD><C8AF> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>.", this);
// return;
// }
2025-11-06 15:28:16 +09:00
// InitializeInteraction();
//}
2025-10-30 09:31:05 +09:00
void Update()
{
2025-11-06 15:28:16 +09:00
if (!isInitialized || rayProvider == null)
{
2025-11-06 15:28:16 +09:00
if (nearFarInteractor == null)
{
2025-11-06 15:28:16 +09:00
nearFarInteractor = GetComponentInChildren<NearFarInteractor>(true);
baseInteractor = nearFarInteractor as XRBaseInteractor;
rayProvider = nearFarInteractor as IXRRayProvider;
}
if (nearFarInteractor != null)
{
2025-11-06 15:28:16 +09:00
InitializeInteraction();
}
}
else
{
2025-11-06 15:28:16 +09:00
currentTargetPosition = rayProvider.rayEndPoint;
currentTargetRotation = baseInteractor.attachTransform.rotation;
if (isGrabbingRobot)
{
OnRobotGrabbed?.Invoke(currentTargetPosition, currentTargetRotation);
return;
}
2025-11-06 15:28:16 +09:00
if (isGrabbingPoint)
{
2025-11-06 15:28:16 +09:00
OnPointDragUpdate?.Invoke(currentGrabbedPointIndex, currentTargetPosition, currentTargetRotation);
}
else if (clickOrDragCoroutine != null)
{
float distance = Vector3.Distance(startGrabPosition, currentTargetPosition);
if (distance > dragMovementThreshold)
{
StartDragMode();
}
}
}
}
private void InitializeInteraction()
{
// XRI <20>̺<EFBFBD>Ʈ <20><><EFBFBD><EFBFBD>
2025-11-06 15:28:16 +09:00
baseInteractor.selectEntered.AddListener(HandleGrabStart);
baseInteractor.selectExited.AddListener(HandleGrabEnd);
isInitialized = true;
AppManager.Instance.RegisterView(this);
}
private void OnDestroy()
{
2025-11-06 15:28:16 +09:00
if (baseInteractor != null)
{
2025-11-06 15:28:16 +09:00
baseInteractor.selectEntered.RemoveListener(HandleGrabStart);
baseInteractor.selectExited.RemoveListener(HandleGrabEnd);
}
}
// --- XRI <20>̺<EFBFBD>Ʈ <20>ڵ鷯 ---
private void HandleGrabStart(SelectEnterEventArgs args)
{
GameObject grabbedGO = args.interactableObject.transform.gameObject;
2025-11-06 20:14:27 +09:00
RobotPoint point = grabbedGO.GetComponent<RobotPoint>();
if (point != null)
{
isGrabbingPoint = true;
isGrabbingRobot = false;
currentGrabbedPointIndex = point.pointIndex;
// Ÿ<≯<EFBFBD> <20><><EFBFBD><EFBFBD>
startGrabPosition = rayProvider.rayEndPoint;
if (clickOrDragCoroutine != null)
StopCoroutine(clickOrDragCoroutine);
clickOrDragCoroutine = StartCoroutine(ClickOrDragTimer());
//OnPointDragStart?.Invoke(currentGrabbedPointIndex);
2025-11-06 20:14:27 +09:00
}
else if (grabbedGO.CompareTag("RobotArm"))
{
2025-11-06 15:28:16 +09:00
isGrabbingPoint = false;
isGrabbingRobot = true;
2025-11-06 15:28:16 +09:00
currentGrabbedPointIndex = -1;
OnPointDragStart?.Invoke(currentGrabbedPointIndex);
}
}
private void HandleGrabEnd(SelectExitEventArgs args)
{
if (isGrabbingRobot)
2025-11-06 20:14:27 +09:00
{
OnRobotReleased?.Invoke(new RobotData());
2025-11-06 20:14:27 +09:00
}
else
2025-11-06 20:14:27 +09:00
{
if (clickOrDragCoroutine != null)
{
StopCoroutine(clickOrDragCoroutine);
clickOrDragCoroutine = null;
OnPointClicked?.Invoke(currentGrabbedPointIndex, currentTargetPosition);
}
else if (isGrabbingPoint)
{
OnPointDragEnd?.Invoke(currentGrabbedPointIndex);
}
2025-11-06 20:14:27 +09:00
}
// <20><><EFBFBD><EFBFBD> <20>ʱ<EFBFBD>ȭ
clickOrDragCoroutine = null;
isGrabbingPoint = false;
2025-11-06 15:28:16 +09:00
isGrabbingRobot = false;
currentGrabbedPointIndex = -1;
}
// Ŭ<><C5AC>/<2F><EFBFBD><E5B7A1> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> Ÿ<≯<EFBFBD> <20>ڷ<EFBFBD>ƾ
private IEnumerator ClickOrDragTimer()
{
yield return new WaitForSeconds(clickTimeThreshold);
if (clickOrDragCoroutine != null)
{
Debug.Log("<22>ð<EFBFBD> <20>ʰ<EFBFBD><CAB0><EFBFBD> <20><EFBFBD><E5B7A1> <20><><EFBFBD><EFBFBD> (OnPointDragStart)");
StartDragMode();
}
}
// Ÿ<≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD> <20><EFBFBD><E5B7A1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ
private void StartDragMode()
{
if (clickOrDragCoroutine != null)
{
StopCoroutine(clickOrDragCoroutine);
clickOrDragCoroutine = null;
}
isGrabbingPoint = true;
OnPointDragStart?.Invoke(currentGrabbedPointIndex);
}
2025-11-06 20:14:27 +09:00
// <20>κ<EFBFBD> <20><>ǥ<EFBFBD><C7A5>(mm)<29><> Unity <20><><EFBFBD><EFBFBD> <20><>ǥ<EFBFBD><C7A5>(m)<29><> <20><>ȯ
private Vector3 ConvertRobotDataToVector3(RobotData pose)
{
2025-11-06 20:14:27 +09:00
float x = Convert.ToSingle(pose.x / -1000.0);
float y = Convert.ToSingle(pose.z / 1000.0);
float z = Convert.ToSingle(pose.y / -1000.0);
return new Vector3(x, y, z);
2025-10-30 09:31:05 +09:00
}
2025-11-06 20:14:27 +09:00
// <20>κ<EFBFBD> <20><><EFBFBD>Ϸ<EFBFBD> <20><>(rx,ry,rz)<29><> Unity <20><><EFBFBD>ʹϾ<CDB4><CFBE><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ
private Quaternion ConvertRobotDataToQuaternion(RobotData pose)
{
return Quaternion.Euler(pose.rx, pose.ry, pose.rz);
2025-11-06 15:28:16 +09:00
}
2025-11-06 20:14:27 +09:00
// <20><><EFBFBD><EFBFBD>Ʈ <20>κ<EFBFBD><CEBA><EFBFBD> <20><>ġ/ȸ<><C8B8> <20><><EFBFBD><EFBFBD>
public void ShowGhostRobot()
{
if (ghostRobot == null)
{
Debug.LogWarning("Ghost Robot<6F><74> Inspector<6F><72> <20>Ҵ<EFBFBD><D2B4><EFBFBD><EFBFBD><EFBFBD> <20>ʾҽ<CABE><D2BD>ϴ<EFBFBD>.");
return;
}
ghostRobot.SetActive(true);
2025-11-06 15:28:16 +09:00
}
2025-11-06 20:14:27 +09:00
// <20><><EFBFBD><EFBFBD>Ʈ <20>κ<EFBFBD> <20><>Ȱ<EFBFBD><C8B0>ȭ
public void HideGhostRobot()
{
if (ghostRobot != null)
{
ghostRobot.SetActive(false);
}
2025-11-06 15:28:16 +09:00
}
2025-11-06 20:14:27 +09:00
// <20><EFBFBD><E5B7A1> ȭ<><C8AD>ǥ Ȱ<><C8B0>ȭ <20><> <20><>ġ <20><><EFBFBD><EFBFBD>
public void ShowDragArrow(Vector3 position)
{
if (dragArrow == null)
{
Debug.LogWarning("Drag Arrow<6F><77> Inspector<6F><72> <20>Ҵ<EFBFBD><D2B4><EFBFBD><EFBFBD><EFBFBD> <20>ʾҽ<CABE><D2BD>ϴ<EFBFBD>.");
return;
}
dragArrow.SetActive(true);
dragArrow.transform.position = position;
}
// <20><EFBFBD><E5B7A1> ȭ<><C8AD>ǥ <20><>Ȱ<EFBFBD><C8B0>ȭ
public void HideDragArrow()
{
if (dragArrow != null)
{
dragArrow.SetActive(false);
}
}
// <20><><EFBFBD><EFBFBD> <20><> <20><>ġ <20><>ȯ
public Vector3 GetCurrentRayPosition()
{
if (rayProvider != null)
{
return rayProvider.rayEndPoint;
}
if (baseInteractor != null)
{
return baseInteractor.attachTransform.position;
}
return transform.position;
2025-11-06 15:28:16 +09:00
}
2025-10-30 09:31:05 +09:00
}