/// <summary>
        /// Gets the underlying pointer for the native anchor.
        /// </summary>
        /// <param name="anchor">
        /// The native anchor to obtain the pointer for.
        /// </param>
        /// <param name="cancellationToken">
        /// A <see cref="CancellationToken"/> that can be used to cancel the operation.
        /// </param>
        /// <returns>
        /// A Task that yields the pointer.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        /// Thrown if <paramref name="anchor"/> is <see langword = "null" />.
        /// </exception>
        /// <exception cref="PlatformNotSupportedException">
        /// Thrown if the current platform is not supported by the SDK.
        /// </exception>
        /// <exception cref="InvalidOperationException">
        /// Thrown if a pointer could not be obtained from the native anchor.
        /// </exception>
        /// <exception cref="OperationCanceledException">
        /// The operation was canceled.
        /// </exception>
        /// <remarks>
        /// This method is async because ARKit cannot provide an anchor
        /// pointer until at least one frame has been processed. If a pointer
        /// is not returned on the first request, this operation will wait for
        /// one to be created.
        /// </remarks>

        static public IntPtr GetPointer(this NativeAnchor anchor)
        {
            // Validate
            if (anchor == null)
            {
                throw new ArgumentNullException(nameof(anchor));
            }

            // Placeholder
            IntPtr ptr = IntPtr.Zero;

#if UNITY_ANDROID || UNITY_IOS
            ptr = anchor.WorldAnchorHandle;
#elif WINDOWS_UWP || UNITY_WSA
            ptr = anchor.GetNativeSpatialAnchorPtr();
#else
            throw new PlatformNotSupportedException("Unable to retrieve the native anchor pointer. The platform is not supported.");
#endif

#if UNITY_EDITOR
#pragma warning disable CS0162 // Conditional compile statements prevent reaching this code in the unity editor
#endif
            // Warn if the anchor didn't give us a valid value
            if (ptr == IntPtr.Zero)
            {
                throw new InvalidOperationException("Couldn't obtain a native anchor pointer");
            }

            // Return the pointer
            return(ptr);

#if UNITY_EDITOR
#pragma warning restore CS0162
#endif
        }
Beispiel #2
0
        /// <summary>
        /// Stores the specified cloud version of the anchor and creates or updates the native anchor
        /// to match.
        /// </summary>
        /// <param name="cloudAnchor">
        /// The cloud version of the anchor.
        /// </param>
        /// <remarks>
        /// When this method completes, <see cref="CloudAnchor"/> will point to the anchor specified
        /// by <paramref name="cloudAnchor"/> and <see cref="NativeAnchor"/> will return a new or updated
        /// native anchor with the same information.
        /// </remarks>
        public void CloudToNative(CloudSpatialAnchor cloudAnchor)
        {
            // Validate
            if (cloudAnchor == null)
            {
                throw new ArgumentNullException(nameof(cloudAnchor));
            }

            // Apply and store updated native anchor
            nativeAnchor = gameObject.ApplyCloudAnchor(cloudAnchor);
        }
Beispiel #3
0
        /// <summary>
        /// Sets the pose of the attached <see cref="GameObject"/>, modifying
        /// native anchors if necessary.
        /// </summary>
        /// <param name="gameObject">
        /// The <see cref="GameObject"/> to set the pose on.
        /// </param>
        /// <param name="position">
        /// The new position to set.
        /// </param>
        /// <param name="rotation">
        /// The new rotation to set.
        /// </param>
        public void SetPose(Vector3 position, Quaternion rotation)
        {
            // Changing the position resets both native and cloud anchors
            cloudAnchor  = null;
            nativeAnchor = null;

            // Use extension method to update position and native anchor
            gameObject.SetPose(position, rotation);

            // Get the native anchor back (if there was one)
            nativeAnchor = gameObject.FindNativeAnchor();
        }
        /// <summary>
        /// Applies the specified cloud anchor to the GameObject by
        /// creating or updating the native anchor.
        /// to match.
        /// </summary>
        /// <param name="gameObject">
        /// The <see cref="GameObject"/> where the cloud anchor should be
        /// applied.
        /// </param>
        /// <param name="cloudAnchor">
        /// The cloud anchor to apply.
        /// </param>
        /// <returns>
        /// The <see cref="NativeAnchor"/> created or updated during the
        /// operation.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        /// Thrown if <paramref name="gameObject"/> or <paramref name="cloudAnchor"/>
        /// are <see langword = "null" />.
        /// </exception>
        /// <exception cref="PlatformNotSupportedException">
        /// Thrown if the current platform is not supported by the SDK.
        /// </exception>
        static public NativeAnchor ApplyCloudAnchor(this GameObject gameObject, CloudSpatialAnchor cloudAnchor)
        {
            // Validate
            if (gameObject == null)
            {
                throw new ArgumentNullException(nameof(gameObject));
            }
            if (cloudAnchor == null)
            {
                throw new ArgumentNullException(nameof(cloudAnchor));
            }

            // Placeholder
            NativeAnchor nativeAnchor = null;

            #if WINDOWS_UWP || UNITY_WSA
            // On UWP we can just update the pointer on any existing WorldAnchor.
            // Doing so will also automatically update the objects pose.

            // Find or create the world anchor
            nativeAnchor = gameObject.FindOrCreateNativeAnchor();

            // Update the World Anchor to use the cloud-based native anchor
            nativeAnchor.SetNativeSpatialAnchorPtr(cloudAnchor.LocalAnchor);
            #elif UNITY_IOS || UNITY_ANDROID
            // On iOS and Android we need to remove any existing native anchor,
            // move the object to the new pose, and then re-apply the native anchor.

            // Delete any existing native anchor
            gameObject.DeleteNativeAnchor();

            // Get the pose from the cloud anchor
            Pose pose = cloudAnchor.GetPose();

            // Move the GameObject to match the new pose
            gameObject.transform.position = pose.position;
            gameObject.transform.rotation = pose.rotation;

            // Add the native anchor back on
            nativeAnchor = gameObject.CreateNativeAnchor();
            #else
            throw new PlatformNotSupportedException("Unable to apply the cloud anchor. The platform is not supported.");
#endif
#if UNITY_EDITOR
#pragma warning disable CS0162 // Conditional compile statements prevent reaching this code in the unity editor
#endif
            // Return the created or updated anchor
            return(nativeAnchor);

#if UNITY_EDITOR
#pragma warning restore CS0162
#endif
        }
Beispiel #5
0
        /// <summary>
        /// Creates or updates the <see cref="CloudSpatialAnchor"/> returned by
        /// <see cref="CloudAnchor"/> to reflect the same data as the native anchor.
        /// </summary>
        /// <param name="useExisting">
        /// <c>true</c> to reuse any existing cloud anchor; <c>false</c> to
        /// always create a new one.
        /// </param>
        /// <returns>
        /// A <see cref="Task"/> that represents the operation.
        /// </returns>
        /// <remarks>
        /// <para>
        /// If no native anchor exists on the game object it will be created.
        /// </para>
        /// </remarks>
        public void NativeToCloud(bool useExisting)
        {
            // Make sure there's a native anchor
            if (nativeAnchor == null)
            {
                nativeAnchor = gameObject.FindOrCreateNativeAnchor();
            }

            // If there is no cloud anchor, create it
            if ((!useExisting) || (cloudAnchor == null))
            {
                cloudAnchor = nativeAnchor.ToCloud();
            }
        }
        /// <summary>
        /// Removes and destroys any native anchor applied to the object.
        /// </summary>
        /// <param name="gameObject">
        /// The <see cref="GameObject"/> where the anchor should be removed.
        /// </param>
        /// <exception cref="System.ArgumentNullException">
        /// Thrown if <paramref name="gameObject"/> is <see langword = "null" />.
        /// </exception>
        static public void DeleteNativeAnchor(this GameObject gameObject)
        {
            // Validate
            if (gameObject == null)
            {
                throw new ArgumentNullException(nameof(gameObject));
            }

            // Try to find the native anchor
            NativeAnchor nativeAnchor = FindNativeAnchor(gameObject);

            // If found destroy (which will also remove it)
            if (nativeAnchor != null)
            {
                GameObject.DestroyImmediate(nativeAnchor);
            }
        }
        /// <summary>
        /// Creates or updates the <see cref="CloudSpatialAnchor"/> returned by
        /// <see cref="CloudAnchor"/> to reflect the same data as the native anchor.
        /// </summary>
        /// <param name="anchor">
        /// The native anchor to convert to a cloud anchor.
        /// </param>
        /// <returns>
        /// A Task that yields the <see cref="CloudSpatialAnchor"/>.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        /// Thrown if <paramref name="anchor"/> is <see langword = "null" />.
        /// </exception>
        /// <remarks>
        /// This method is async because ARKit needs to process at least one
        /// frame before any requested anchor is fully created. This method
        /// will return only after any underlying native processes are
        /// complete.
        /// </remarks>
        static public CloudSpatialAnchor ToCloud(this NativeAnchor anchor)
        {
            // Validate
            if (anchor == null)
            {
                throw new ArgumentNullException(nameof(anchor));
            }

            // Get the native pointer
            IntPtr ptr = anchor.GetPointer();

            // Create the cloud version
            CloudSpatialAnchor cloudAnchor = new CloudSpatialAnchor();

            // Set the local pointer
            cloudAnchor.LocalAnchor = ptr;

            // Done!
            return(cloudAnchor);
        }
        /// <summary>
        /// Returns any existing anchor if found; otherwise, creates and returns
        /// a new anchor.
        /// </summary>
        /// <param name="gameObject">
        /// The <see cref="GameObject"/> to search for or add the anchor.
        /// </param>
        /// <returns>
        /// The existing or newly created native anchor.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">
        /// Thrown if <paramref name="gameObject"/> is <see langword = "null" />.
        /// </exception>
        static public NativeAnchor FindOrCreateNativeAnchor(this GameObject gameObject)
        {
            // Validate
            if (gameObject == null)
            {
                throw new ArgumentNullException(nameof(gameObject));
            }

            // Try to find an existing anchor
            NativeAnchor anchor = FindNativeAnchor(gameObject);

            // If not found, create
            if (anchor == null)
            {
                anchor = CreateNativeAnchor(gameObject);
            }

            // Return the anchor
            return(anchor);
        }
Beispiel #9
0
 protected virtual void Awake()
 {
     // If there's already a native anchor, go ahead and reference it
     nativeAnchor = gameObject.FindNativeAnchor();
 }