Categories
AR / VR HoloLens Windows

HoloLens: Adding Fallback Input Handlers for Positioning Out-of-Sight Objects

The TapToPlace  script of the HoloToolkit is a great and simple way to place and anchor holograms in the real world. However, it can be problematic if the hologram is placed out of reach / view from a previous session in another room and you can not tap the hologram to place it closer to you once again.

A good solution is to create another “reset” gesture that triggers object placement even if you don’t directly tap the hologram. An easy way to achieve this is the tap-and-hold gesture, which is one of the standard events the Input Manager of the HoloToolkit can send.

To handle interaction events that don’t target a particular hologram, the current HoloToolkit uses Fallback Input Handlers. However, this functionality isn’t very well documented anywhere. This guide explains how to write a custom fallback input handler.

Handling Fallback Input Events

For the general setup: first, ensure that your Unity HoloLens project includes the InputManager  Prefab from the HoloToolkit. Next, add the standard TapToPlace  script of the HoloToolkit to the game object you want to place in the world.

Now, add the following script HoldAnywhereHandler  to your scene, for example also into the Managers game objects hierarchy where you have placed the InputManager  prefab.

using HoloToolkit.Unity.InputModule;
using HoloToolkit.Unity.SpatialMapping;
using UnityEngine;

public class HoldAnywhereHandler : MonoBehaviour, IHoldHandler
{
    /// <summary>
    /// Game object to send a fallback hold event to, using a custom "AnywhereHoldCompleted" event.
    /// </summary>
    public GameObject SendEventToObject;

    // Use this for initialization
    void Start()
    {
        Debug.Log(gameObject.name + " : Registering as fallback input handler.");
        // Register using the singleton input manager instance of the HoloToolkit 
        InputManager.Instance.PushFallbackInputHandler(gameObject);
    }

    public void OnHoldCompleted(HoldEventData eventData)
    {
        Debug.Log(gameObject.name + " : Received fallback OnHoldCompleted event. " + Time.time);
        if (SendEventToObject != null && SendEventToObject.GetComponent<TapToPlace>() != null)
        {
            // Send custom event to the registered game object
            var receivingObject = SendEventToObject.GetComponent<TapToPlace>();
            if (!receivingObject.IsBeingPlaced)
            {
                receivingObject.OnInputClicked(null);
            }
            //SendEventToObject.SendMessage("AnywhereHoldCompleted", null);
        }
    }

    public void OnHoldStarted(HoldEventData eventData)
    {
        // Implementation not needed, but method required from interface
    }

    public void OnHoldCanceled(HoldEventData eventData)
    {
        // Implementation not needed, but method required from interface
    }
}

The script will register itself as the fallback input handler for any hold events that the user performs while not looking at a hologram. Accessing the input manager instance of the HoloToolkit works using the singleton pattern.

In this case, we are only interested in the event when the hold gesture has been completed: OnHoldCompleted . Whenever we get this, we simulate the click event for the pre-configured target object. We do not need to send any event parameters, as the standard TapToPlace  script does not use the parameters. In order to not accidentally ending the placement, we only send the click event if the hologram is not already being placed.

Script Configuration

The only final step is to assign the target hologram that we want to place. To do this, drag the placeable game object (that has the TapToPlace  script assigned) to the configuration section of the new HoldAnyhwereHandler  script.

As a result, you can tap and hold anywhere in the world to start placement of the hologram. You don’t need to hit the object anymore with your tap gesture as required by the default TapToPlace  script of the HoloToolkit.