Last active
June 27, 2019 04:39
-
-
Save zalo/a88b6c188cbe504784374de656afe3c4 to your computer and use it in GitHub Desktop.
A simple Unity Wacom Multitouch Data Provider that uses the WacomMTDN.dll from the Wacom Feel Multitouch Samples (linked in the comments)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections.Concurrent; | |
using UnityEngine; | |
using WacomMTDN; | |
// Simple Wacom Multitouch Unity Integration built from the Wacom's DotNet Example: | |
// https://developer-docs.wacom.com/display/DevDocs/Feel+Multi-touch+Sample+Code+Downloads | |
// WacomMTDN.dll can be found at: https://drive.google.com/file/d/1fvoRfIev28fKMvTrfF9IBZkAaWow5UJ4/view?usp=sharing | |
public class WacomMultiTouchProvider : MonoBehaviour { | |
///<summary> How long since the last touch event to nullify fingers </summary> | |
private const float NO_TOUCH_TIMEOUT = 0.032f; | |
///<summary> How many historical samples per finger to keep </summary> | |
private const int HISTORY_LENGTH = 20; | |
///<summary> The container for the latest frame of multitouch data </summary> | |
[NonSerialized] | |
public WacomMTFingerCollection CurrentFrame; | |
///<summary> The container for the histories of multitouch data </summary> | |
[NonSerialized] | |
public Dictionary<int, List<WacomMTFinger>> fingerHistories = | |
new Dictionary<int, List<WacomMTFinger>>(); | |
[Tooltip("The status Returned from the Wacom Multitouch Driver")] | |
[SerializeField] | |
private string currentStatus; | |
[Header("Optional Gizmo Drawing")] | |
[Tooltip("A transform for a surface to draw touch gizmos")] | |
public Transform touchSurface; | |
///<summary> Gets data about connected Wacom Tablets </summary> | |
protected CWacomMTConfig mWacomMTConfig = new CWacomMTConfig(); | |
///<summary> Manages receiving data from a subscribed Wacom Tablet </summary> | |
protected CWacomMTWindowClient mWacomMTWindowClient; | |
private IntPtr mUserDataIntPtr = IntPtr.Zero; | |
private ConcurrentQueue<WacomMTFingerCollection> fingerUpdates = | |
new ConcurrentQueue<WacomMTFingerCollection>(); | |
private float noTouchTimer = 0f; | |
private List<int> IDsToKeep = new List<int>(10), | |
IDsToRemove = new List<int>(10); | |
private void Update() { | |
if (mWacomMTWindowClient != null && | |
mWacomMTWindowClient.IsRegisteredAsHitRectClient()) { | |
noTouchTimer += Time.unscaledDeltaTime; | |
WacomMTFingerCollection latestFrame; | |
while (fingerUpdates.TryDequeue(out latestFrame)) { | |
CurrentFrame = latestFrame; | |
//Manage Historical Data | |
IDsToKeep.Clear(); IDsToRemove.Clear(); | |
for (int i = 0; i < CurrentFrame.FingerCount; i++) { | |
var finger = CurrentFrame.GetFingerByIndex((uint)i); | |
if (!(finger.X == 0f && finger.Y == 0)){ | |
List<WacomMTFinger> fingerHistory; | |
if (!fingerHistories.TryGetValue(finger.FingerID, out fingerHistory)) { | |
fingerHistory = new List<WacomMTFinger>(HISTORY_LENGTH); | |
fingerHistories.Add(finger.FingerID, fingerHistory); | |
} | |
fingerHistory.Insert(0, finger); | |
while (fingerHistory.Count > HISTORY_LENGTH) { | |
fingerHistory.RemoveAt(fingerHistory.Count - 1); | |
} | |
IDsToKeep.Add(finger.FingerID); | |
} | |
} | |
foreach (KeyValuePair<int, List<WacomMTFinger>> finger in fingerHistories) { | |
if (!IDsToKeep.Contains(finger.Key)) { IDsToRemove.Add(finger.Key); } | |
} | |
foreach (int ID in IDsToRemove) { fingerHistories.Remove(ID); } | |
noTouchTimer = 0f; | |
} | |
// Nullify fingers if have not received any touch events for longer than | |
// NO_TOUCH_TIMEOUT | |
if (noTouchTimer > NO_TOUCH_TIMEOUT) { | |
CurrentFrame.FingerCount = 0; | |
fingerHistories.Clear(); | |
} | |
} | |
} | |
void OnDrawGizmos() { | |
for (int i = 0; i < CurrentFrame.FingerCount; i++) { | |
WacomMTFinger finger = CurrentFrame.GetFingerByIndex((uint)i); | |
Gizmos.color = Color.HSVToRGB((finger.FingerID * 0.309f) % 1f, 1f, 1f); | |
Gizmos.DrawSphere(FingerToGizmoPosition(finger), 0.02f); | |
List<WacomMTFinger> fingerHistory; | |
if(fingerHistories.TryGetValue(finger.FingerID, out fingerHistory) && | |
fingerHistory.Count > 1) { | |
for (int j = 1; j < fingerHistory.Count; j++) { | |
Gizmos.DrawLine(FingerToGizmoPosition(fingerHistory[j - 1]) + Vector3.up * 0.01f, | |
FingerToGizmoPosition(fingerHistory[j]) + Vector3.up * 0.01f); | |
} | |
} | |
} | |
} | |
Vector3 FingerToGizmoPosition(WacomMTFinger finger) { | |
Vector3 fingerPos = new Vector3(finger.X-0.5f, 0f, 0.5f - finger.Y); | |
return touchSurface.TransformPoint(fingerPos); | |
} | |
#region Boring Connection Management Stuff | |
void OnEnable() { | |
mWacomMTConfig.Init(); | |
try { | |
// Prepares some test userdata to send when client is registered. | |
currentStatus = "User data returned to client..."; | |
mUserDataIntPtr = CMemUtils.AllocateUnmanagedString(currentStatus); | |
if (mWacomMTConfig.DeviceIDList.data.Length > 0) { | |
//Subscribe to Finger Touch Events | |
mWacomMTWindowClient = new CWacomMTFingerClient( | |
WacomMTProcessingMode.WMTProcessingModeConsumer); | |
//Use this to capture messages within region of the tablet space | |
var callback = new WacomMTCallback(DoFingerDataUpdateCallback); | |
WacomMTHitRect fullScreenHitRect = new WacomMTHitRect( | |
0f, 0f, 1f, 1f);//Display.main.systemWidth, Display.main.systemHeight); | |
//Use the display resolution if it is a display tablet... | |
mWacomMTWindowClient.RegisterHitRectClient( | |
mWacomMTConfig.DeviceIDList.data[0], | |
fullScreenHitRect, | |
ref callback, | |
mUserDataIntPtr); | |
} | |
Debug.Log("Wacom Connection Opened Successfully; Device ID: " + | |
mWacomMTWindowClient.DeviceID); | |
} catch (Exception ex) { | |
Debug.LogError(ex.ToString()); | |
} | |
} | |
void OnDisable() { | |
try { | |
// Remove our client (if one created). | |
if (mWacomMTWindowClient != null && | |
mWacomMTWindowClient.IsRegisteredAsHitRectClient()) { | |
mWacomMTWindowClient.UnregisterHitRectClient(); | |
} | |
if (mWacomMTConfig != null) { | |
// Close the WacomMT connection. | |
mWacomMTConfig.Quit(); | |
mWacomMTConfig = null; | |
} | |
if (mUserDataIntPtr != IntPtr.Zero) { | |
CMemUtils.FreeUnmanagedString(mUserDataIntPtr); | |
mUserDataIntPtr = IntPtr.Zero; | |
} | |
Debug.Log("Wacom Multitouch Connection Shut Down Successfully!"); | |
} catch (Exception ex) { | |
Debug.LogError(ex.ToString()); | |
} | |
} | |
public UInt32 DoFingerDataUpdateCallback(IntPtr packet_I, IntPtr userData_I) { | |
try { | |
// Recover the finger collection sent back. | |
WacomMTFingerCollection fingerCollection = | |
CMemUtils.PtrToStructure<WacomMTFingerCollection>(packet_I); | |
fingerUpdates.Enqueue(fingerCollection); | |
// Recover the user data sent back. | |
currentStatus = CMemUtils.PtrToManagedString(userData_I); | |
} catch (Exception ex) { | |
Debug.LogError(ex.ToString()); | |
} | |
return 0; | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment