4 using System.Collections.Generic;
17 [RequireComponent(typeof(Collider))]
18 [RequireComponent(typeof(Interpolator))]
21 [Tooltip(
"Distance from camera to keep the object while placing it.")]
22 public float DefaultGazeDistance = 2.0f;
24 [Tooltip(
"Place parent on tap instead of current game object.")]
27 [Tooltip(
"Specify the parent game object to be moved on tap, if the immediate parent is not desired.")]
35 [Tooltip(
"Setting this to true will enable the user to move and place the object in the scene without needing to tap on the object. Useful when you want to place an object immediately.")]
38 [Tooltip(
"Setting this to true will allow this behavior to control the DrawMesh property on the spatial mapping.")]
39 public bool AllowMeshVisualizationControl =
true;
41 [Tooltip(
"Should the center of the Collider be used instead of the gameObjects world transform.")]
49 private const int IgnoreRaycastLayer = 2;
51 private Dictionary<GameObject, int> layerCache =
new Dictionary<GameObject, int>();
52 private Vector3 PlacementPosOffset;
58 ParentGameObjectToPlace = GetParentToPlace();
59 PlaceParentOnTap = ParentGameObjectToPlace != null;
62 interpolator = EnsureInterpolator();
74 private void OnEnable()
76 Bounds bounds = transform.GetColliderBounds();
77 PlacementPosOffset = transform.position - bounds.center;
84 private GameObject GetParentToPlace()
86 if (ParentGameObjectToPlace)
88 return ParentGameObjectToPlace;
91 return gameObject.transform.parent ? gameObject.transform.parent.gameObject : null;
99 var interpolatorHolder = PlaceParentOnTap ? ParentGameObjectToPlace : gameObject;
100 return interpolatorHolder.EnsureComponent<
Interpolator>();
105 if (!IsBeingPlaced) {
return; }
108 Vector3 placementPosition = GetPlacementPosition(cameraTransform.position, cameraTransform.forward, DefaultGazeDistance);
110 if (UseColliderCenter)
112 placementPosition += PlacementPosOffset;
120 if (PlaceParentOnTap)
122 placementPosition = ParentGameObjectToPlace.transform.position + (placementPosition - gameObject.transform.position);
129 interpolator.
SetTargetRotation(Quaternion.Euler(0, cameraTransform.localEulerAngles.y, 0));
135 IsBeingPlaced = !IsBeingPlaced;
140 private void HandlePlacement()
151 private void StartPlacing()
153 var layerCacheTarget = PlaceParentOnTap ? ParentGameObjectToPlace : gameObject;
154 layerCacheTarget.SetLayerRecursively(IgnoreRaycastLayer, out layerCache);
161 private void StopPlacing()
163 var layerCacheTarget = PlaceParentOnTap ? ParentGameObjectToPlace : gameObject;
164 layerCacheTarget.ApplyLayerCacheRecursively(layerCache);
171 private void AttachWorldAnchor()
180 private void RemoveWorldAnchor()
192 private void ToggleSpatialMesh()
204 private static Vector3 GetPlacementPosition(Vector3 headPosition, Vector3 gazeDirection,
float defaultGazeDistance)
207 if (SpatialMappingRaycast(headPosition, gazeDirection, out hitInfo))
209 return hitInfo.point;
211 return GetGazePlacementPosition(headPosition, gazeDirection, defaultGazeDistance);
221 private static bool SpatialMappingRaycast(Vector3 origin, Vector3 direction, out RaycastHit spatialMapHit)
228 spatialMapHit = hitInfo;
232 spatialMapHit =
new RaycastHit();
243 private static Vector3 GetGazePlacementPosition(Vector3 headPosition, Vector3 gazeDirection,
float defaultGazeDistance)
249 return headPosition + gazeDirection * defaultGazeDistance;