2025-10-30 09:31:05 +09:00
using System ;
using UnityEngine ;
2025-11-04 11:36:19 +09:00
using UnityEngine.XR.Interaction.Toolkit ;
using UnityEngine.XR.Interaction.Toolkit.Interactors ;
2025-10-30 09:31:05 +09:00
// Presenter<65> <72> InteractionView<65> <77> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ϱ <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> ̽<EFBFBD>
public interface IInteractionView
{
2025-11-04 11:36:19 +09:00
event Action < Vector3 , Quaternion > OnRobotGrabbed ;
2025-10-30 09:31:05 +09:00
// VR <20> <> Ʈ<EFBFBD> ѷ<EFBFBD> <D1B7> <EFBFBD> <20> κ<EFBFBD> <CEBA> <EFBFBD> <20> <> <EFBFBD> Ҵ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <EFBFBD>
event Action < RobotData > OnRobotReleased ;
// VR <20> <> Ʈ<EFBFBD> ѷ<EFBFBD> <D1B7> <EFBFBD> Ư<> <C6AF> <20> <> <EFBFBD> <EFBFBD> Ʈ<EFBFBD> <C6AE> Ŭ<> <C5AC> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <20> <EFBFBD>
event Action < int > OnPointClicked ;
// VR <20> <> Ʈ<EFBFBD> ѷ<EFBFBD> <D1B7> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> Ʈ<EFBFBD> <C6AE> <20> <> <EFBFBD> <EFBFBD> <20> 巡<EFBFBD> <E5B7A1> <20> <> <EFBFBD> <EFBFBD> /<2F> <> /<2F> <> <20> <> <EFBFBD> <EFBFBD> <20> <> <20> <EFBFBD>
event Action < int > OnPointDragStart ;
event Action < int , Vector3 > OnPointDragUpdate ; // (<28> <> <EFBFBD> <EFBFBD> Ʈ <20> ε<EFBFBD> <CEB5> <EFBFBD> , <20> <> <20> <> <EFBFBD> <EFBFBD> <20> <> ǥ)
event Action < int > OnPointDragEnd ;
// Presenter<65> <72> ȣ <> <C8A3> <EFBFBD> <EFBFBD> <20> Լ<EFBFBD> <D4BC> <EFBFBD>
void ShowGhostRobot ( RobotData pose ) ;
void HideGhostRobot ( ) ;
void ShowDragArrow ( Vector3 position ) ;
void HideDragArrow ( ) ;
}
public class InteractionView : MonoBehaviour , IInteractionView
{
2025-11-04 11:36:19 +09:00
public event Action < Vector3 , Quaternion > OnRobotGrabbed ;
2025-10-30 09:31:05 +09:00
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 ;
2025-11-04 11:36:19 +09:00
private XRBaseInteractor interactor ;
private bool isInitialized = false ;
private bool isGrabbingPoint = false ;
private int currentGrabbedPointIndex = - 1 ;
public bool isGrabbingRobot = false ;
void Start ( )
{
// Ray Interactor<6F> <72> Direct Interactor <20> <> <EFBFBD> <EFBFBD> ó<> <C3B3> <EFBFBD> <EFBFBD> <20> <> <20> ֵ<EFBFBD> <D6B5> <EFBFBD> XRBaseInteractor<6F> <72> <20> <> <EFBFBD> <EFBFBD>
interactor = GetComponent < NearFarInteractor > ( ) ;
if ( interactor = = null )
{
Debug . LogError ( "InteractionView requires an XRBaseInteractor (Ray or Direct) on the same GameObject." , this ) ;
return ;
}
}
// --- <20> ǽð<C7BD> <20> <> Ʈ<EFBFBD> <C6AE> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> Update ---
2025-10-30 09:31:05 +09:00
void Update ( )
{
2025-11-04 11:36:19 +09:00
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 ( ) ;
}
}
}
private void InitializeInteraction ( )
{
// XRI <20> ̺<EFBFBD> Ʈ <20> <> <EFBFBD> <EFBFBD>
interactor . selectEntered . AddListener ( HandleGrabStart ) ;
interactor . selectExited . AddListener ( HandleGrabEnd ) ;
// 'Ŭ<> <C5AC> '<27> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ϸ<EFBFBD> <CFB7> <EFBFBD> interactor.activated <20> ̺<EFBFBD> Ʈ<EFBFBD> <C6AE> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> ؾ<EFBFBD> <20> <>
isInitialized = true ;
AppManager . Instance . RegisterView ( this ) ;
Debug . Log ( "InteractionView <20> ʱ<EFBFBD> ȭ <20> Ϸ<EFBFBD> . Interactor <20> ̺<EFBFBD> Ʈ <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> ." ) ;
}
private void OnDestroy ( )
{
if ( interactor ! = null )
{
interactor . selectEntered . RemoveListener ( HandleGrabStart ) ;
interactor . selectExited . RemoveListener ( HandleGrabEnd ) ;
}
}
// --- XRI <20> ̺<EFBFBD> Ʈ <20> ڵ鷯 ---
// "<22> <> <EFBFBD> <EFBFBD> " <20> <> ư<EFBFBD> <C6B0> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <>
private void HandleGrabStart ( SelectEnterEventArgs args )
{
// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> Ʈ
GameObject grabbedGO = args . interactableObject . transform . gameObject ;
//// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> "<22> <> <EFBFBD> <EFBFBD> Ʈ"<22> <> <EFBFBD> <EFBFBD> Ȯ<> <C8AE> (RobotPoint <20> <> ũ<EFBFBD> <C5A9> Ʈ Ž<> <C5BD> )
//RobotPoint point = grabbedGO.GetComponent<RobotPoint>();
//if (point != null)
//{
// isGrabbingPoint = true;
// currentGrabbedPointIndex = point.pointIndex;
// // Presenter<65> <72> <EFBFBD> <EFBFBD> "<22> 巡<EFBFBD> <E5B7A1> <20> <> <EFBFBD> <EFBFBD> " <20> ̺<EFBFBD> Ʈ <20> <> <EFBFBD> <EFBFBD>
// OnPointDragStart?.Invoke(currentGrabbedPointIndex);
//}
// <20> <> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> "<22> κ<EFBFBD> "<22> <> <EFBFBD> <EFBFBD> Ȯ<> <C8AE>
if ( grabbedGO . CompareTag ( "RobotArm" ) )
{
isGrabbingRobot = true ;
}
}
// "<22> <> <EFBFBD> <EFBFBD> " <20> <> ư<EFBFBD> <C6B0> <20> <> <EFBFBD> <EFBFBD> <20> <>
private void HandleGrabEnd ( SelectExitEventArgs args )
{
// "<22> <> <EFBFBD> <EFBFBD> Ʈ"<22> <> <20> <> <EFBFBD> <EFBFBD> <20> ִ<EFBFBD> <20> <> <EFBFBD> ̾<EFBFBD> <CCBE> ٸ<EFBFBD>
if ( isGrabbingPoint )
{
// Presenter<65> <72> <EFBFBD> <EFBFBD> "<22> 巡<EFBFBD> <E5B7A1> <20> <> " <20> ̺<EFBFBD> Ʈ <20> <> <EFBFBD> <EFBFBD> (<28> ˾<EFBFBD> Ʈ<> <C6AE> <EFBFBD> ſ <EFBFBD> )
OnPointDragEnd ? . Invoke ( currentGrabbedPointIndex ) ;
}
// "<22> κ<EFBFBD> "<22> <> <20> <> <EFBFBD> <EFBFBD> <20> ִ<EFBFBD> <20> <> <EFBFBD> ̾<EFBFBD> <CCBE> ٸ<EFBFBD>
else if ( isGrabbingRobot )
{
// Presenter<65> <72> <EFBFBD> <EFBFBD> "<22> κ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> " <20> ̺<EFBFBD> Ʈ <20> <> <EFBFBD> <EFBFBD> (<28> ˾<EFBFBD> Ʈ<> <C6AE> <EFBFBD> ſ <EFBFBD> )
RobotData currentPose = GetCurrentRobotPoseFromController ( ) ;
OnRobotReleased ? . Invoke ( currentPose ) ;
}
// <20> <> <EFBFBD> <EFBFBD> <20> ʱ<EFBFBD> ȭ
isGrabbingPoint = false ;
currentGrabbedPointIndex = - 1 ;
}
private RobotData GetCurrentRobotPoseFromController ( )
{
// <20> <> View<65> <77> Presenter<65> <72> <20> <> ȯ <20> <> <EFBFBD> <EFBFBD> (ConvertVrToRobotPose)<29> <> <20> <> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> Ƿ<EFBFBD> ,
// <20> <> <EFBFBD> <EFBFBD> <20> <> Ʈ<EFBFBD> ѷ<EFBFBD> <20> <> ġ/ȸ<> <C8B8> <EFBFBD> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> '<27> <> ¥' RobotData<74> <61> <20> <> <EFBFBD> <EFBFBD>
// Presenter<65> <72> <20> <> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> <EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> ٽ<EFBFBD> <20> <> ȯ(<28> Ǵ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> )<29> ؾ<EFBFBD> <20> <>
return new RobotData ( ) ; // <20> ӽ<EFBFBD> <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD>
2025-10-30 09:31:05 +09:00
}
// --- Presenter<65> <72> ȣ <> <C8A3> <EFBFBD> <EFBFBD> <20> Լ<EFBFBD> <D4BC> <EFBFBD> ---
public void ShowGhostRobot ( RobotData pose ) { /* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> κ<EFBFBD> 2 Ȱ<> <C8B0> ȭ <20> <> <20> <> ġ <20> <> <EFBFBD> <EFBFBD> */ }
public void HideGhostRobot ( ) { /* <20> <> <EFBFBD> <EFBFBD> <EFBFBD> <EFBFBD> <20> κ<EFBFBD> 2 <20> <> Ȱ<EFBFBD> <C8B0> ȭ */ }
public void ShowDragArrow ( Vector3 position ) { /* <20> 巡<EFBFBD> <EFBFBD> ȭ<> <C8AD> ǥ UI Ȱ<> <C8B0> ȭ <20> <> <20> <> ġ <20> <> <EFBFBD> <EFBFBD> */ }
public void HideDragArrow ( ) { /* <20> 巡<EFBFBD> <EFBFBD> ȭ<> <C8AD> ǥ UI <20> <> Ȱ<EFBFBD> <C8B0> ȭ */ }
}