From fcc4048f2b07d5223509aaf3eb6065085c4bfc03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dino=20Fejzagi=C4=87?= Date: Sat, 19 Dec 2020 18:47:13 +0100 Subject: [PATCH] Teleport Mode for Teleport System (#726) * Add .vsconfig to gitignore * Introduce teleport mode * Clean up provider when switching back to default mode --- ...edRealityTeleportSystemProfileInspector.cs | 17 ++++- .../MixedRealityTeleportSystemProfile.cs | 16 +++- .../MixedRealityTeleportSystem.cs | 74 +++++++++++++++++-- .../Services/TeleportSystem/TeleportMode.cs | 23 ++++++ .../TeleportSystem/TeleportMode.cs.meta | 11 +++ 5 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 Runtime/Services/TeleportSystem/TeleportMode.cs create mode 100644 Runtime/Services/TeleportSystem/TeleportMode.cs.meta diff --git a/Editor/Profiles/MixedRealityTeleportSystemProfileInspector.cs b/Editor/Profiles/MixedRealityTeleportSystemProfileInspector.cs index 360aebc86..8c449907a 100644 --- a/Editor/Profiles/MixedRealityTeleportSystemProfileInspector.cs +++ b/Editor/Profiles/MixedRealityTeleportSystemProfileInspector.cs @@ -4,29 +4,42 @@ using UnityEditor; using XRTK.Definitions.TeleportSystem; using XRTK.Services; +using XRTK.Services.Teleportation; namespace XRTK.Editor.Profiles { [CustomEditor(typeof(MixedRealityTeleportSystemProfile))] public class MixedRealityTeleportSystemProfileInspector : MixedRealityServiceProfileInspector { + private SerializedProperty teleportMode; private SerializedProperty teleportProvider; protected override void OnEnable() { base.OnEnable(); + teleportMode = serializedObject.FindProperty(nameof(teleportMode)); teleportProvider = serializedObject.FindProperty(nameof(teleportProvider)); } public override void OnInspectorGUI() { - RenderHeader("The teleport system profile defines default behaviour for the teleport system."); + RenderHeader("The teleport system profile defines behaviour for the teleport system."); serializedObject.Update(); EditorGUI.BeginChangeCheck(); - EditorGUILayout.PropertyField(teleportProvider); + EditorGUILayout.PropertyField(teleportMode); + + var activeTeleportMode = (TeleportMode)teleportMode.intValue; + switch (activeTeleportMode) + { + case TeleportMode.Provider: + EditorGUI.indentLevel++; + EditorGUILayout.PropertyField(teleportProvider); + EditorGUI.indentLevel--; + break; + } serializedObject.ApplyModifiedProperties(); diff --git a/Runtime/Definitions/TeleportSystem/MixedRealityTeleportSystemProfile.cs b/Runtime/Definitions/TeleportSystem/MixedRealityTeleportSystemProfile.cs index 39e740686..ff92bd2bb 100644 --- a/Runtime/Definitions/TeleportSystem/MixedRealityTeleportSystemProfile.cs +++ b/Runtime/Definitions/TeleportSystem/MixedRealityTeleportSystemProfile.cs @@ -6,15 +6,29 @@ using XRTK.Definitions.Utilities; using XRTK.Interfaces.TeleportSystem; using XRTK.Interfaces.TeleportSystem.Handlers; +using XRTK.Services.Teleportation; namespace XRTK.Definitions.TeleportSystem { /// - /// Configuration profile for the . + /// Configuration profile for the . /// [CreateAssetMenu(menuName = "Mixed Reality Toolkit/Teleport System Profile", fileName = "MixedRealityTeleportSystemProfile", order = (int)CreateProfileMenuItemIndices.Input)] public class MixedRealityTeleportSystemProfile : BaseMixedRealityServiceProfile { + [SerializeField] + [Tooltip("The teleportation mode to use.")] + private TeleportMode teleportMode = TeleportMode.Default; + + /// + /// The teleportation mode to use. + /// + public TeleportMode TeleportMode + { + get => teleportMode; + internal set => teleportMode = value; + } + [SerializeField] [Tooltip("The concrete teleport provider to use for teleportation.")] [Implements(typeof(IMixedRealityTeleportProvider), TypeGrouping.ByNamespaceFlat)] diff --git a/Runtime/Services/TeleportSystem/MixedRealityTeleportSystem.cs b/Runtime/Services/TeleportSystem/MixedRealityTeleportSystem.cs index a586f8afa..507925ef4 100644 --- a/Runtime/Services/TeleportSystem/MixedRealityTeleportSystem.cs +++ b/Runtime/Services/TeleportSystem/MixedRealityTeleportSystem.cs @@ -29,15 +29,21 @@ public class MixedRealityTeleportSystem : BaseEventSystem, IMixedRealityTeleport public MixedRealityTeleportSystem(MixedRealityTeleportSystemProfile profile) : base(profile) { - if (profile.TeleportProvider?.Type == null) + teleportMode = profile.TeleportMode; + if (teleportMode == TeleportMode.Provider) { - throw new Exception($"The {nameof(MixedRealityTeleportSystemProfile)} is missing the required {teleportProvider}!"); - } + if (profile.TeleportProvider?.Type == null) + { + throw new Exception($"The {nameof(MixedRealityTeleportSystemProfile)} is configured for " + + $"{TeleportMode.Provider} but is missing the required {teleportProvider}!"); + } - teleportProvider = profile.TeleportProvider; + teleportProvider = profile.TeleportProvider; + } } private readonly SystemType teleportProvider; + private readonly TeleportMode teleportMode; private TeleportEventData teleportEventData; private bool isTeleporting = false; @@ -54,7 +60,26 @@ public override void Initialize() teleportEventData = new TeleportEventData(EventSystem.current); } - CameraCache.Main.gameObject.EnsureComponent(teleportProvider.Type); + switch (teleportMode) + { + case TeleportMode.Default: + var component = CameraCache.Main.GetComponent() as Component; + if (!component.IsNull()) + { + if (Application.isPlaying) + { + Object.Destroy(component); + } + else + { + Object.DestroyImmediate(component); + } + } + break; + case TeleportMode.Provider: + CameraCache.Main.gameObject.EnsureComponent(teleportProvider.Type); + break; + } } /// @@ -65,7 +90,6 @@ public override void Disable() if (!Application.isPlaying) { var component = CameraCache.Main.GetComponent() as Component; - if (!component.IsNull()) { Object.DestroyImmediate(component); @@ -151,6 +175,13 @@ public void RaiseTeleportStarted(IMixedRealityPointer pointer, IMixedRealityTele // Pass handler HandleEvent(teleportEventData, OnTeleportStartedHandler); + + // In default teleportation mode we do not expect any provider + // to handle teleportation, instead we simply perform an instant teleport. + if (teleportMode == TeleportMode.Default) + { + PerformDefaultTeleport(teleportEventData); + } } private static readonly ExecuteEvents.EventFunction OnTeleportCompletedHandler = @@ -198,5 +229,36 @@ public void RaiseTeleportCanceled(IMixedRealityPointer pointer, IMixedRealityTel } #endregion IMixedRealityTeleportSystem Implementation + + private void PerformDefaultTeleport(TeleportEventData eventData) + { + var cameraTransform = MixedRealityToolkit.CameraSystem != null ? + MixedRealityToolkit.CameraSystem.MainCameraRig.CameraTransform : + CameraCache.Main.transform; + var teleportTransform = cameraTransform.parent; + Debug.Assert(teleportTransform != null, + $"{nameof(TeleportMode.Default)} requires that the camera be parented under another object!"); + + var targetRotation = Vector3.zero; + var targetPosition = eventData.Pointer.Result.EndPoint; + targetRotation.y = eventData.Pointer.PointerOrientation; + + if (eventData.HotSpot != null) + { + targetPosition = eventData.HotSpot.Position; + if (eventData.HotSpot.OverrideTargetOrientation) + { + targetRotation.y = eventData.HotSpot.TargetOrientation; + } + } + + var height = targetPosition.y; + targetPosition -= cameraTransform.position - teleportTransform.position; + targetPosition.y = height; + teleportTransform.position = targetPosition; + teleportTransform.RotateAround(cameraTransform.position, Vector3.up, targetRotation.y - cameraTransform.eulerAngles.y); + + RaiseTeleportComplete(eventData.Pointer, eventData.HotSpot); + } } } diff --git a/Runtime/Services/TeleportSystem/TeleportMode.cs b/Runtime/Services/TeleportSystem/TeleportMode.cs new file mode 100644 index 000000000..ff4c6ec9c --- /dev/null +++ b/Runtime/Services/TeleportSystem/TeleportMode.cs @@ -0,0 +1,23 @@ +// Copyright (c) XRTK. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +namespace XRTK.Services.Teleportation +{ + /// + /// Supported teleport modes in the implementation. + /// + public enum TeleportMode + { + /// + /// will instantly teleport the player + /// to the selected location and does not require any additional setup. + /// + Default = 0, + /// + /// mode lets 's + /// handle teleportation. This mode requires + /// to be configured with a concrete implementation. + /// + Provider + } +} diff --git a/Runtime/Services/TeleportSystem/TeleportMode.cs.meta b/Runtime/Services/TeleportSystem/TeleportMode.cs.meta new file mode 100644 index 000000000..add585649 --- /dev/null +++ b/Runtime/Services/TeleportSystem/TeleportMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8d3a2f4a39c7024493058f95c033cda +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: