Skip to content

Commit

Permalink
Introduce teleport validation data provider (#727)
Browse files Browse the repository at this point in the history
* Add base setup for MixedRealityTeleportValidationDataProvider

* Define IMixedRealityTeleportValidationDataProvider

* Refactor TeleportValidationResult

* Implement profile and inspector

* Implement data provider

* Register teleport system data providers properly

* Fix profile changes not saved

* Remove teleport mode

* Update submodules
  • Loading branch information
FejZa committed Dec 20, 2020
1 parent fcc4048 commit f708e4e
Show file tree
Hide file tree
Showing 18 changed files with 298 additions and 100 deletions.
8 changes: 8 additions & 0 deletions Editor/Profiles/TeleportSystem.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@
using UnityEditor;
using XRTK.Definitions.TeleportSystem;
using XRTK.Services;
using XRTK.Services.Teleportation;

namespace XRTK.Editor.Profiles
namespace XRTK.Editor.Profiles.TeleportSystem
{
[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));
}

Expand All @@ -29,17 +26,7 @@ public override void OnInspectorGUI()
serializedObject.Update();
EditorGUI.BeginChangeCheck();

EditorGUILayout.PropertyField(teleportMode);

var activeTeleportMode = (TeleportMode)teleportMode.intValue;
switch (activeTeleportMode)
{
case TeleportMode.Provider:
EditorGUI.indentLevel++;
EditorGUILayout.PropertyField(teleportProvider);
EditorGUI.indentLevel--;
break;
}
EditorGUILayout.PropertyField(teleportProvider);

serializedObject.ApplyModifiedProperties();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using UnityEditor;
using XRTK.Definitions.TeleportSystem;

namespace XRTK.Editor.Profiles.TeleportSystem
{
[CustomEditor(typeof(MixedRealityTeleportValidationDataProviderProfile))]
public class MixedRealityTeleportValidationDataProviderProfileInspector : BaseMixedRealityProfileInspector
{
private SerializedProperty validLayers;
private SerializedProperty invalidLayers;
private SerializedProperty upDirectionThreshold;
private SerializedProperty maxDistance;

protected override void OnEnable()
{
base.OnEnable();

validLayers = serializedObject.FindProperty(nameof(validLayers));
invalidLayers = serializedObject.FindProperty(nameof(invalidLayers));
upDirectionThreshold = serializedObject.FindProperty(nameof(upDirectionThreshold));
maxDistance = serializedObject.FindProperty(nameof(maxDistance));
}

public override void OnInspectorGUI()
{
RenderHeader("This profile defines the set of rules to validate against when deciding whether a teleport target location is valid or not.");

serializedObject.Update();

EditorGUILayout.PropertyField(validLayers);
EditorGUILayout.PropertyField(invalidLayers);
EditorGUILayout.PropertyField(upDirectionThreshold);
EditorGUILayout.PropertyField(maxDistance);

serializedObject.ApplyModifiedProperties();
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 0 additions & 16 deletions Runtime/Definitions/Physics/TeleportSurfaceResult.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,6 @@ namespace XRTK.Definitions.TeleportSystem
[CreateAssetMenu(menuName = "Mixed Reality Toolkit/Teleport System Profile", fileName = "MixedRealityTeleportSystemProfile", order = (int)CreateProfileMenuItemIndices.Input)]
public class MixedRealityTeleportSystemProfile : BaseMixedRealityServiceProfile<IMixedRealityTeleportDataProvider>
{
[SerializeField]
[Tooltip("The teleportation mode to use.")]
private TeleportMode teleportMode = TeleportMode.Default;

/// <summary>
/// The teleportation mode to use.
/// </summary>
public TeleportMode TeleportMode
{
get => teleportMode;
internal set => teleportMode = value;
}

[SerializeField]
[Tooltip("The concrete teleport provider to use for teleportation.")]
[Implements(typeof(IMixedRealityTeleportProvider), TypeGrouping.ByNamespaceFlat)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using UnityEngine;
using XRTK.Definitions.Utilities;
using XRTK.Services.Teleportation;

namespace XRTK.Definitions.TeleportSystem
{
/// <summary>
/// Configuration profile for the <see cref="MixedRealityTeleportValidationDataProvider"/>.
/// </summary>
[CreateAssetMenu(menuName = "Mixed Reality Toolkit/Teleport System/Teleport Validation Data Provider Profile", fileName = "MixedRealityTeleportValidationDataProviderProfile", order = (int)CreateProfileMenuItemIndices.Input)]
public class MixedRealityTeleportValidationDataProviderProfile : BaseMixedRealityProfile
{
[SerializeField]
[Tooltip("Layers that are considered 'valid' for teleportation.")]
private LayerMask validLayers = UnityEngine.Physics.DefaultRaycastLayers;

/// <summary>
/// Layers that are considered 'valid' for teleportation.
/// </summary>
public LayerMask ValidLayers
{
get => validLayers;
internal set => validLayers = value;
}

[SerializeField]
[Tooltip("Layers that are considered 'invalid' for teleportation.")]
private LayerMask invalidLayers = UnityEngine.Physics.IgnoreRaycastLayer;

/// <summary>
/// Layers that are considered 'invalid' for teleportation.
/// </summary>
public LayerMask InvalidLayers
{
get => invalidLayers;
internal set => invalidLayers = value;
}

[SerializeField]
[Range(0f, 1f)]
[Tooltip("The up direction threshold to use when determining if a surface is 'flat' enough to teleport to.")]
private float upDirectionThreshold = 0.2f;

/// <summary>
/// The up direction threshold to use when determining if a surface is 'flat' enough to teleport to.
/// </summary>
public float UpDirectionThreshold
{
get => upDirectionThreshold;
internal set => upDirectionThreshold = value;
}

[SerializeField]
[Min(.1f)]
[Tooltip("The maximum distance from the player a teleport location can be away.")]
private float maxDistance = 10f;

/// <summary>
/// The maximum distance from the player a teleport location can be away.
/// </summary>
public float MaxDistance
{
get => maxDistance;
internal set => maxDistance = value;
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) XRTK. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using UnityEngine;
using XRTK.Interfaces.InputSystem;
using XRTK.Services.Teleportation;

namespace XRTK.Interfaces.TeleportSystem
{
/// <summary>
/// Interface to define teleportation validation data providers.
/// </summary>
public interface IMixedRealityTeleportValidationDataProvider : IMixedRealityTeleportDataProvider
{
/// <summary>
/// Validates a <see cref="IPointerResult"/> and returns whether the <see cref="RaycastHit"/>
/// qualifies for teleporation.
/// </summary>
/// <param name="pointerResult">The <see cref="IPointerResult"/> to validate.</param>
/// <param name="teleportHotSpot"><see cref="IMixedRealityTeleportHotSpot"/> found at the target position, if any.</param>
/// <returns>The <see cref="TeleportValidationResult"/> for <paramref name="pointerResult"/>.</returns>
TeleportValidationResult IsValid(IPointerResult pointerResult, IMixedRealityTeleportHotSpot teleportHotSpot = null);
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion Runtime/Services/MixedRealityToolkit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,12 @@ private void InitializeServiceLocator()

if (ActiveProfile.IsTeleportSystemEnabled)
{
if (!TryCreateAndRegisterService<IMixedRealityTeleportSystem>(ActiveProfile.TeleportSystemSystemType, out _, ActiveProfile.TeleportSystemProfile) || TeleportSystem == null)
if (TryCreateAndRegisterService<IMixedRealityTeleportSystem>(ActiveProfile.TeleportSystemSystemType, out var service, ActiveProfile.TeleportSystemProfile) || TeleportSystem == null)
{
TryRegisterDataProviderConfigurations(ActiveProfile.TeleportSystemProfile.RegisteredServiceConfigurations, service);

}
else
{
Debug.LogError("Failed to start the Teleport System!");
}
Expand Down
52 changes: 21 additions & 31 deletions Runtime/Services/TeleportSystem/MixedRealityTeleportSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,10 @@ public class MixedRealityTeleportSystem : BaseEventSystem, IMixedRealityTeleport
public MixedRealityTeleportSystem(MixedRealityTeleportSystemProfile profile)
: base(profile)
{
teleportMode = profile.TeleportMode;
if (teleportMode == TeleportMode.Provider)
{
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?.Type == null ? null : teleportProvider = profile.TeleportProvider;
}

private readonly SystemType teleportProvider;
private readonly TeleportMode teleportMode;

private TeleportEventData teleportEventData;
private bool isTeleporting = false;

Expand All @@ -60,25 +48,27 @@ public override void Initialize()
teleportEventData = new TeleportEventData(EventSystem.current);
}

switch (teleportMode)
if (teleportProvider == null)
{
case TeleportMode.Default:
var component = CameraCache.Main.GetComponent<IMixedRealityTeleportProvider>() as Component;
if (!component.IsNull())
// No provier selected, we'll be using default teleport.
// Make sure to remove any leftover provider attached to the camera.
var component = CameraCache.Main.GetComponent<IMixedRealityTeleportProvider>() as Component;
if (!component.IsNull())
{
if (Application.isPlaying)
{
Object.Destroy(component);
}
else
{
if (Application.isPlaying)
{
Object.Destroy(component);
}
else
{
Object.DestroyImmediate(component);
}
Object.DestroyImmediate(component);
}
break;
case TeleportMode.Provider:
CameraCache.Main.gameObject.EnsureComponent(teleportProvider.Type);
break;
}
}
else
{
// A provider is set, make sure it's attached to the camera.
CameraCache.Main.gameObject.EnsureComponent(teleportProvider.Type);
}
}

Expand Down Expand Up @@ -178,7 +168,7 @@ public void RaiseTeleportStarted(IMixedRealityPointer pointer, IMixedRealityTele

// In default teleportation mode we do not expect any provider
// to handle teleportation, instead we simply perform an instant teleport.
if (teleportMode == TeleportMode.Default)
if (teleportProvider == null)
{
PerformDefaultTeleport(teleportEventData);
}
Expand Down Expand Up @@ -237,7 +227,7 @@ private void PerformDefaultTeleport(TeleportEventData eventData)
CameraCache.Main.transform;
var teleportTransform = cameraTransform.parent;
Debug.Assert(teleportTransform != null,
$"{nameof(TeleportMode.Default)} requires that the camera be parented under another object!");
$"{nameof(MixedRealityTeleportSystem)} without a provider set requires that the camera be parented under another object! Assign a teleport provider in the system profile or fix the camera setup.");

var targetRotation = Vector3.zero;
var targetPosition = eventData.Pointer.Result.EndPoint;
Expand Down

0 comments on commit f708e4e

Please sign in to comment.