mixedreality/com.microsoft.mixedreality..../SDK/Features/UX/Scripts/Pointers/DefaultPrimaryPointerSelect...

164 lines
5.7 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Collections.Generic;
using Unity.Profiling;
namespace Microsoft.MixedReality.Toolkit.Input
{
/// <summary>
/// Default primary pointer selector. The primary pointer is chosen among all interaction enabled ones using the following rules in order:
/// 1. Currently pressed pointer that has been pressed for the longest
/// 2. Pointer that was released most recently
/// 3. Pointer that became interaction enabled most recently
/// </summary>
public class DefaultPrimaryPointerSelector : IMixedRealityPrimaryPointerSelector, IMixedRealityPointerHandler
{
private readonly Dictionary<IMixedRealityPointer, PointerInfo> pointerInfos = new Dictionary<IMixedRealityPointer, PointerInfo>();
public void Initialize()
{
CoreServices.InputSystem?.RegisterHandler<IMixedRealityPointerHandler>(this);
}
public void Destroy()
{
CoreServices.InputSystem?.UnregisterHandler<IMixedRealityPointerHandler>(this);
}
#region IMixedRealityPrimaryPointerSelector
public void RegisterPointer(IMixedRealityPointer pointer)
{
var pointerInfo = new PointerInfo(pointer);
pointerInfos.Add(pointer, pointerInfo);
}
public void UnregisterPointer(IMixedRealityPointer pointer)
{
pointerInfos.Remove(pointer);
}
private static readonly ProfilerMarker UpdatePerfMarker = new ProfilerMarker("[MRTK] DefaultPrimaryPointerSelector.Update");
virtual public IMixedRealityPointer Update()
{
using (UpdatePerfMarker.Auto())
{
IMixedRealityPointer primaryPointer = null;
PointerInfo primaryInfo = null;
foreach (var keyValue in pointerInfos)
{
var pointer = keyValue.Key;
var info = keyValue.Value;
info.Update(pointer);
if (info.IsInteractionEnabled &&
(primaryInfo == null ||
(info.IsPressed && (!primaryInfo.IsPressed || info.PressedTimestamp < primaryInfo.PressedTimestamp)) ||
(!primaryInfo.IsPressed && info.ReleasedTimestamp > primaryInfo.ReleasedTimestamp)))
{
primaryPointer = pointer;
primaryInfo = info;
}
}
return primaryPointer;
}
}
#endregion IMixedRealityPrimaryPointerSelector
#region IMixedRealityPointerHandler
private static readonly ProfilerMarker OnPointerDownPerfMarker = new ProfilerMarker("[MRTK] DefaultPrimaryPointerSelector.OnPointerDown");
void IMixedRealityPointerHandler.OnPointerDown(MixedRealityPointerEventData eventData)
{
using (OnPointerDownPerfMarker.Auto())
{
PointerInfo info = null;
if (pointerInfos.TryGetValue(eventData.Pointer, out info))
{
info.IsPressed = true;
}
}
}
private static readonly ProfilerMarker OnPointerUpPerfMarker = new ProfilerMarker("[MRTK] DefaultPrimaryPointerSelector.OnPointerUp");
void IMixedRealityPointerHandler.OnPointerUp(MixedRealityPointerEventData eventData)
{
using (OnPointerUpPerfMarker.Auto())
{
PointerInfo info = null;
if (pointerInfos.TryGetValue(eventData.Pointer, out info))
{
info.IsPressed = false;
}
}
}
void IMixedRealityPointerHandler.OnPointerDragged(MixedRealityPointerEventData eventData) { }
void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData) { }
#endregion IMixedRealityPointerHandler
private class PointerInfo
{
private bool isInteractionEnabled;
public bool IsInteractionEnabled
{
get { return isInteractionEnabled; }
private set
{
if (value && !isInteractionEnabled)
{
// We count becoming interaction enabled as a pointer released event
ReleasedTimestamp = System.Diagnostics.Stopwatch.GetTimestamp();
}
isInteractionEnabled = value;
}
}
// Last time the pointer was released
public long ReleasedTimestamp { get; private set; }
private bool isPressed;
public bool IsPressed
{
get { return isPressed; }
set
{
if (value && !isPressed)
{
PressedTimestamp = System.Diagnostics.Stopwatch.GetTimestamp();
}
else if (!value && isPressed)
{
ReleasedTimestamp = System.Diagnostics.Stopwatch.GetTimestamp();
}
isPressed = value;
}
}
// Last time the pointer was pressed
public long PressedTimestamp { get; private set; }
public PointerInfo(IMixedRealityPointer pointer)
{
IsInteractionEnabled = pointer.IsInteractionEnabled;
}
public void Update(IMixedRealityPointer pointer)
{
IsInteractionEnabled = pointer.IsInteractionEnabled;
}
}
}
}