VR4Medical/ICI/Library/PackageCache/com.unity.xr.interaction.toolkit@42ef3600567b/Runtime/AR/Interactables/ARTranslationInteractable.deprecated.cs
2025-07-29 13:45:50 +03:00

228 lines
9.0 KiB
C#

//-----------------------------------------------------------------------
// <copyright file="TranslationManipulator.cs" company="Google">
//
// Copyright 2018 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// </copyright>
//-----------------------------------------------------------------------
// Modifications copyright © 2020 Unity Technologies ApS
using System;
using Unity.XR.CoreUtils;
#if !AR_FOUNDATION_PRESENT && !PACKAGE_DOCS_GENERATION
// Stub class definition used to fool version defines that this MonoScript exists (fixed in 19.3)
namespace UnityEngine.XR.Interaction.Toolkit.AR
{
/// <summary>
/// Manipulates the position of an object via a drag gesture.
/// If not selected, the object will be selected when the drag gesture starts.
/// </summary>
[Obsolete("ARTranslationInteractable has been replaced by the ARTransformer. Use the ARTransformer instead.")]
public class ARTranslationInteractable { }
}
#else
namespace UnityEngine.XR.Interaction.Toolkit.AR
{
/// <summary>
/// Manipulates the position of an object via a drag gesture.
/// If not selected, the object will be selected when the drag gesture starts.
/// </summary>
[AddComponentMenu("XR/AR Translation Interactable", 22)]
[RequireComponent(typeof(ARSelectionInteractable))]
[HelpURL(XRHelpURLConstants.k_ARTranslationInteractable)]
[Obsolete("ARTranslationInteractable has been replaced by the ARTransformer. Use the ARTransformer instead.")]
public class ARTranslationInteractable : ARBaseGestureInteractable
{
[SerializeField]
[Tooltip("Controls whether Unity constrains the object vertically, horizontally, or free to move in all axes.")]
GestureTransformationUtility.GestureTranslationMode m_ObjectGestureTranslationMode;
/// <summary>
/// Controls whether the object will be constrained vertically, horizontally, or free to move in all axis.
/// </summary>
public GestureTransformationUtility.GestureTranslationMode objectGestureTranslationMode
{
get => m_ObjectGestureTranslationMode;
set => m_ObjectGestureTranslationMode = value;
}
[SerializeField]
[Tooltip("The maximum translation distance of this object.")]
float m_MaxTranslationDistance = 10f;
/// <summary>
/// The maximum translation distance of this object.
/// </summary>
public float maxTranslationDistance
{
get => m_MaxTranslationDistance;
set => m_MaxTranslationDistance = value;
}
[SerializeField]
[Tooltip("The LayerMask that Unity uses during an additional ray cast when a user touch does not hit any AR trackable planes.")]
LayerMask m_FallbackLayerMask;
/// <summary>
/// The <see cref="LayerMask"/> that Unity uses during an additional ray cast
/// when a user touch does not hit any AR trackable planes.
/// </summary>
public LayerMask fallbackLayerMask
{
get => m_FallbackLayerMask;
set => m_FallbackLayerMask = value;
}
const float k_PositionSpeed = 12f;
const float k_DiffThreshold = 0.0001f;
bool m_IsActive;
Vector3 m_DesiredLocalPosition;
float m_GroundingPlaneHeight;
Vector3 m_DesiredAnchorPosition;
Quaternion m_DesiredRotation;
GestureTransformationUtility.Placement m_LastPlacement;
/// <inheritdoc />
public override void ProcessInteractable(XRInteractionUpdateOrder.UpdatePhase updatePhase)
{
base.ProcessInteractable(updatePhase);
if (updatePhase == XRInteractionUpdateOrder.UpdatePhase.Dynamic)
UpdatePosition();
}
/// <inheritdoc />
protected override bool CanStartManipulationForGesture(DragGesture gesture)
{
// If the gesture isn't targeting this item, don't start manipulating.
return gesture.targetObject != null && gesture.targetObject == gameObject && transform.parent != null;
}
/// <inheritdoc />
protected override void OnStartManipulation(DragGesture gesture)
{
m_GroundingPlaneHeight = transform.parent.position.y;
}
/// <inheritdoc />
protected override void OnContinueManipulation(DragGesture gesture)
{
if (transform.parent == null)
{
Debug.LogError("Translation Interactable needs a parent object.", this);
return;
}
m_IsActive = true;
var desiredPlacement = xrOrigin != null
? GestureTransformationUtility.GetBestPlacementPosition(
transform.parent.position, gesture.position, m_GroundingPlaneHeight, 0.03f,
maxTranslationDistance, objectGestureTranslationMode, xrOrigin, fallbackLayerMask: m_FallbackLayerMask)
#pragma warning disable 618 // Calling deprecated method to help with backwards compatibility.
: GestureTransformationUtility.GetBestPlacementPosition(
transform.parent.position, gesture.position, m_GroundingPlaneHeight, 0.03f,
maxTranslationDistance, objectGestureTranslationMode, arSessionOrigin, fallbackLayerMask: m_FallbackLayerMask);
#pragma warning restore 618
if (desiredPlacement.hasHoveringPosition && desiredPlacement.hasPlacementPosition)
{
// If desired position is lower than current position, don't drop it until it's finished.
m_DesiredLocalPosition = transform.parent.InverseTransformPoint(desiredPlacement.hoveringPosition);
m_DesiredAnchorPosition = desiredPlacement.placementPosition;
m_GroundingPlaneHeight = desiredPlacement.updatedGroundingPlaneHeight;
// Rotate if the plane direction has changed.
if (((desiredPlacement.placementRotation * Vector3.up) - transform.up).magnitude > k_DiffThreshold)
m_DesiredRotation = desiredPlacement.placementRotation;
else
m_DesiredRotation = transform.rotation;
if (desiredPlacement.hasPlane)
m_LastPlacement = desiredPlacement;
}
}
/// <inheritdoc />
protected override void OnEndManipulation(DragGesture gesture)
{
if (!m_LastPlacement.hasPlacementPosition)
return;
var oldAnchor = transform.parent.gameObject;
var desiredPose = new Pose(m_DesiredAnchorPosition, m_LastPlacement.placementRotation);
var desiredLocalPosition = transform.parent.InverseTransformPoint(desiredPose.position);
if (desiredLocalPosition.magnitude > maxTranslationDistance)
desiredLocalPosition = desiredLocalPosition.normalized * maxTranslationDistance;
desiredPose.position = transform.parent.TransformPoint(desiredLocalPosition);
var anchor = new GameObject("PlacementAnchor").transform;
anchor.SetWorldPose(new Pose(m_LastPlacement.placementPosition, m_LastPlacement.placementRotation));
transform.parent = anchor;
Destroy(oldAnchor);
m_DesiredLocalPosition = Vector3.zero;
// Rotate if the plane direction has changed.
if (((desiredPose.rotation * Vector3.up) - transform.up).magnitude > k_DiffThreshold)
m_DesiredRotation = desiredPose.rotation;
else
m_DesiredRotation = transform.rotation;
// Make sure position is updated one last time.
m_IsActive = true;
}
void UpdatePosition()
{
if (!m_IsActive)
return;
// Lerp position.
var oldLocalPosition = transform.localPosition;
var newLocalPosition = Vector3.Lerp(
oldLocalPosition, m_DesiredLocalPosition, Time.deltaTime * k_PositionSpeed);
var diffLength = (m_DesiredLocalPosition - newLocalPosition).magnitude;
if (diffLength < k_DiffThreshold)
{
newLocalPosition = m_DesiredLocalPosition;
m_IsActive = false;
}
transform.localPosition = newLocalPosition;
// Lerp rotation.
var oldRotation = transform.rotation;
var newRotation =
Quaternion.Lerp(oldRotation, m_DesiredRotation, Time.deltaTime * k_PositionSpeed);
transform.rotation = newRotation;
}
}
}
#endif