{{announcement.body}}
{{announcement.title}}

Migrating to MRTK2: IInputClickHandler and SetGlobalListener Are Gone

DZone 's Guide to

Migrating to MRTK2: IInputClickHandler and SetGlobalListener Are Gone

How do we tap now?

· IoT Zone ·
Free Resource

Making something 'clickable' (or actually more 'air tappable') was pretty easy with the Mixed Reality Toolkit 1. You just added the IInputClickHandler interface like this:

using HoloToolkit.Unity.InputModule;
using UnityEngine;

public class ClickableThingy: MonoBehaviour, IInputClickHandler
{
    public void OnInputClicked(InputClickedEventData eventData)
    {
        // Do something
    }
}


You dragged this behavior on top of any game object you want to act on being air tapped and OnInputClicked was being activated as soon as you air tapped. But IInputClickHandler no longer exists in MRTK2. How does that work now?

Tap – Just Another Interface

To support the air tap in MRTK2, it's simply a matter of switching out one interface for another:

using Microsoft.MixedReality.Toolkit.Input;
using UnityEngine;

public class ClickableThingy : MonoBehaviour, IMixedRealityInputHandler
{
    public void OnInputUp(InputEventData eventData)
    {
        //Do something else
    }

    public void OnInputDown(InputEventData eventData)
    {
        //Do something
    }
}


I don't have HoloLens 2, but if you put whatever was in OnInputClicked in OnInputDown, it's being executed on a HoloLens 1 when you do an air tap and the object is selected by the gaze cursor... So, I guess that's a safe bet if you want to make something that runs on both HoloLens 1 and 2.

‘Global Tap’ – Add a Base Class

In the MRTK 1 days, when you wanted to do a ‘global tap,’ you could simply add a SetGlobalListener behavior to the game object that contained your IInputClickHandler implementing behavior:

Adding this object meant that any airtap would be routed to this IImputClicked object — even without the gaze cursor touching the game it, or touching anything at all, for what matters. This could be very useful in situations where you, for instance, were placing objects on the spatial map and some gesture is needed to stop the movement. Or, for example, some general confirmation gesture in a situation where some kind of UI was not feasible because it would get in the way. But the SetGlobalListener behavior is gone as well, so how do you get that behavior now?

Well, basically, you make your ClickableThingy not only implement IMixedRealityInputHandler, but also be a child class of BaseInputHandler.

using Microsoft.MixedReality.Toolkit.Input;
using UnityEngine;

public class ClickableThingyGlobal : BaseInputHandler, IMixedRealityInputHandler
{
    public void OnInputUp(InputEventData eventData)
    {
        // Do something else
    }

    public void OnInputDown(InputEventData eventData)
    {
        // Do something
    }
}


This has a property isFocusRequired that you can set to false in the editor:

And then, your ClickableThingy will get every tap. Smart people will notice it makes sense to always make a child class of BaseInputHandler as the IsFocusRequired property is default true – so the default behavior ClickableThingyGlobal is to act exactly the same as ClickableThingy, but you can configure its behavior in the editor, which makes your behavior applicable to more situations. Whatever you can make configurable saves code. So, I'd always go for a BaseInputHandler for anything that handles a tap.

Proof of the Pudding

This is exactly what the demo project shows: a cube that responds to a tap — regardless of whether there is a gaze or hand cursor on it — and a sphere that only responds to a tap when there is a hand or gaze cursor on it. Both use the ClickableThingyGlobal: the cube has the IsFocusRequired check box unselected, on the sphere, it is selected. To this end, I have adapted the ClickableThingyGlobal to actually do something usable:

using Microsoft.MixedReality.Toolkit.Input;
using UnityEngine;

public class ClickableThingyGlobal : BaseInputHandler, IMixedRealityInputHandler
{
    public void OnInputUp(InputEventData eventData)
    {
        GetComponent<MeshRenderer>().material.color = Color.white;
    }

    public void OnInputDown(InputEventData eventData)
    {
        GetComponent<MeshRenderer>().material.color = Color.red;
    }
}


Or, at least something visible, which is to change the color of the elements from white to red on tap (and back again).

In an HoloLens 1 it looks like this.


The cube will always flash red, the sphere only when there is some cursor pointing to it. In the HoloLens 2 emulator it looks like this:


The fun thing now is that you can act on both InputUp and InputDown, which I use to revert the color setting. To mimic the behavior of the old OnInputClicked, adding code in OnInputDown and leaving OnInputUp is sufficient, I feel.

Conclusion

Yet, another part of moved cheese, although not dramatically so. The demo code is very limited, but it can still be found here. I hope me documenting finding my way around Mixed Reality Toolkit 2 helps you. If you have questions about specific pieces of your HoloLens cheese having been moved and you can't find them, feel free to ask me. In any case, I intend to write lots more of these posts.

Topics:
iot ,hololens ,hololens 2 ,mrtk2 ,unity ,windows mixed reality ,mixed reality ,mr ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}