Author Topic: What's the best way to integrate NGUI support into another input framework?  (Read 10397 times)

valyard

  • Guest
Hi.

I am the author of TouchScript framework for Unity3d (https://www.assetstore.unity3d.com/#/content/7394) which handles multi-touch input and gesture recognition from various devices. From time to time I get asked to integrate NGUI support into it.

Someone already hacked their way into it and posted the code here:
https://github.com/InteractiveLab/TouchScript/issues/6

But I would like to ask NGUI developers what would be the best way to do this without nasty hacks?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
NGUI's UICamera has a public static delegate: "onCustomInput". You can make it point to your own class where you can process custom events if you like.

UICamera also has a "genericEventHandler" that receives a copy of all events, whether they were handled or not -- which is useful if you had to determine gestures.

The idea would be instead of handling touch events yourself and then hacking states in NGUI, to tie into NGUI's event handling instead.

N3uRo

  • Guest
I'm considering of using TouchScript with NGUI but that code seems a bit hacky because it duplicates UICamera code and you have to be on each NGUI version checking if something has changed in UICamera script.

Aren, could you make a "ProcessTouches" method that receives list of touches that is a custom class of you? (Unity Input class can't be altered, neither Unity Touch class so it can't be hacked)

I know you have "MouseOrTouch" but it lacks of "touchID" so it has to be a new class or change that class.

That way it could be cleaner to process all touches and more extendable.

ProcessTouches(List<NGUICustomTouchClass> touches);

And then in your UICamera script you only have to change this:

  1. for (int i = 0; i < Input.touchCount; ++i)
  2. {
  3.  Touch touch = Input.GetTouch(i);

To:

  1. foreach(NGUICustomTouchClass touch as touches)
  2. {
  3.  

bdominguez

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 38
    • View Profile
I'm considering of using TouchScript with NGUI but that code seems a bit hacky because it duplicates UICamera code and you have to be on each NGUI version checking if something has changed in UICamera script.

Aren, could you make a "ProcessTouches" method that receives list of touches that is a custom class of you? (Unity Input class can't be altered, neither Unity Touch class so it can't be hacked)

I know you have "MouseOrTouch" but it lacks of "touchID" so it has to be a new class or change that class.

That way it could be cleaner to process all touches and more extendable.

ProcessTouches(List<NGUICustomTouchClass> touches);

And then in your UICamera script you only have to change this:

  1. for (int i = 0; i < Input.touchCount; ++i)
  2. {
  3.  Touch touch = Input.GetTouch(i);

To:

  1. foreach(NGUICustomTouchClass touch as touches)
  2. {
  3.  

+1

It could be great!

bdominguez

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 38
    • View Profile
Any news Aren?

Thanks!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
I'm not quite clear on this whole thing. Why do any of this when you can just set the custom touch event callback and do whatever logic you need inside, including any custom stuff you want? I'm not seeing any benefit of adding extra complexity here when you can already accomplish all of this via that callback.

bdominguez

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 38
    • View Profile
I'm not quite clear on this whole thing. Why do any of this when you can just set the custom touch event callback and do whatever logic you need inside, including any custom stuff you want? I'm not seeing any benefit of adding extra complexity here when you can already accomplish all of this via that callback.

Because we have to duplicate your UICamera "ProcessTouches" method code and check in each version if something has changed.

For TouchScript it's the same code exactly, the only thing that changed is the "Touch" type. In your case it's Unity "Touch" and in our case is TouchScript "ITouch" interface.

https://github.com/InteractiveLab/TouchScript/blob/b81e7e84cb61f3de8b69126637fc7317bb7ca840/TouchScript/ITouch.cs

That's why I suggested this:

http://www.tasharen.com/forum/index.php?topic=4984.msg42619#msg42619

So we have a more elegante way of accomplishing this.
« Last Edit: May 09, 2014, 05:39:04 AM by bdominguez »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
I picked up a touch screen and noticed that multi-touch doesn't work natively in Unity apps, but the TouchScript plugin does. Now I have a better understanding of what this thread was all about, and I wrote a script that makes NGUI work with TouchScript's touch events -- a bridge between two plugins, if you will. With the latest Pro version of NGUI, import the appropriate TouchScript unitypackage then simply attach this script to any game object. I wrote it for Win7/Win8, and simply attaching this script is enough to get multi-touch to work.
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. // Download the appropriate TouchScript 6.10 package here:
  6. // https://github.com/TouchScript/TouchScript/releases/tag/6.10
  7. // Thanks for znerolnoht for pointing out the updated specific link
  8.  
  9. using TouchScript;
  10. using TouchScript.InputSources;
  11.  
  12. /// <summary>
  13. /// Bridge script between TouchScript and NGUI. Simply attach this script to any game object.
  14. /// </summary>
  15.  
  16. public class TouchScriptNGUI : MonoBehaviour
  17. {
  18.         static public TouchScriptNGUI instance;
  19.  
  20.         /// <summary>
  21.         /// Whether the multi-touch should be enabled or not.
  22.         /// </summary>
  23.  
  24.         static public bool isEnabled
  25.         {
  26.                 get
  27.                 {
  28.                         if (instance != null) return instance.enabled;
  29.                         return PlayerPrefs.GetInt("Multitouch", 1) == 1;
  30.                 }
  31.                 set
  32.                 {
  33.                         PlayerPrefs.SetInt("Multitouch", value ? 1 : 0);
  34.                         if (instance != null) instance.enabled = value;
  35.                 }
  36.         }
  37.  
  38.         [System.NonSerialized] bool mActive = false;
  39.         [System.NonSerialized] BetterList<UICamera.Touch> mTouches = new BetterList<UICamera.Touch>();
  40.  
  41.         void Awake ()
  42.         {
  43.                 if (instance == null)
  44.                 {
  45.                         enabled = isEnabled;
  46.                         instance = this;
  47.                 }
  48.                 else Destroy(gameObject);
  49.         }
  50.  
  51.         void OnDestroy () { if (instance == this) instance = null; }
  52.  
  53.         void OnEnable ()
  54.         {
  55.                 string operatingSystem = SystemInfo.operatingSystem;
  56.  
  57.                 if (operatingSystem.StartsWith("Windows 7"))
  58.                 {
  59.                         mActive = true;
  60.                         NGUITools.AddMissingComponent<TouchManager>(gameObject);
  61.                         NGUITools.AddMissingComponent<Win7TouchInput>(gameObject);
  62. #if UNITY_EDITOR
  63.                         Debug.Log("Windows 7 multi-touch active", this);
  64. #endif
  65.                 }
  66.                 else if (operatingSystem.StartsWith("Windows "))
  67.                 {
  68.                         mActive = true;
  69.                         NGUITools.AddMissingComponent<TouchManager>(gameObject);
  70.                         NGUITools.AddMissingComponent<Win8TouchInput>(gameObject);
  71. #if UNITY_EDITOR
  72.                         Debug.Log("Windows multi-touch active", this);
  73. #endif
  74.                 }
  75.  
  76.                 if (mActive)
  77.                 {
  78.                         UICamera.GetInputTouchCount = OnGetTouchCount;
  79.                         UICamera.GetInputTouch = OnGetTouch;
  80.  
  81.                         ITouchManager instance = TouchManager.Instance;
  82.                         instance.TouchesBegan += OnTouchBegan;
  83.                         instance.TouchesEnded += OnTouchEnded;
  84.                         instance.TouchesMoved += OnTouchMove;
  85.                         instance.TouchesCancelled += OnTouchCancel;
  86.                 }
  87.                 else enabled = false;
  88.         }
  89.  
  90.         void OnDisable ()
  91.         {
  92.                 if (mActive)
  93.                 {
  94.                         mActive = false;
  95.                         UICamera.GetInputTouchCount = null;
  96.                         UICamera.GetInputTouch = null;
  97.                         ITouchManager instance = TouchManager.Instance;
  98.  
  99.                         if (instance != null)
  100.                         {
  101.                                 instance.TouchesBegan -= OnTouchBegan;
  102.                                 instance.TouchesEnded -= OnTouchEnded;
  103.                                 instance.TouchesMoved -= OnTouchMove;
  104.                                 instance.TouchesCancelled -= OnTouchCancel;
  105.                         }
  106.                         mTouches.Clear();
  107.                 }
  108.         }
  109.  
  110.         int OnGetTouchCount () { return mTouches.size; }
  111.         UICamera.Touch OnGetTouch (int index) { return mTouches[index]; }
  112.  
  113.         void OnTouchBegan (object sender, TouchEventArgs e)
  114.         {
  115.                 foreach (ITouch touch in e.Touches)
  116.                 {
  117.                         if (touch.Tags.HasTag(Tags.INPUT_MOUSE)) continue;
  118.  
  119.                         mTouches.Add(new UICamera.Touch()
  120.                         {
  121.                                 phase = TouchPhase.Began,
  122.                                 fingerId = touch.Id,
  123.                                 position = touch.Position,
  124.                                 tapCount = 1
  125.                         });
  126.                 }
  127.         }
  128.  
  129.         void OnTouchEnded (object sender, TouchEventArgs e)
  130.         {
  131.                 foreach (ITouch touch in e.Touches)
  132.                 {
  133.                         if (touch.Tags.HasTag(Tags.INPUT_MOUSE)) continue;
  134.  
  135.                         for (int index = 0; index < mTouches.size; ++index)
  136.                         {
  137.                                 UICamera.Touch t = mTouches[index];
  138.  
  139.                                 if (t.fingerId == touch.Id)
  140.                                 {
  141.                                         t.phase = TouchPhase.Ended;
  142.                                         t.position = touch.Position;
  143.                                         break;
  144.                                 }
  145.                         }
  146.                 }
  147.         }
  148.  
  149.         void OnTouchMove (object sender, TouchEventArgs e)
  150.         {
  151.                 foreach (ITouch touch in e.Touches)
  152.                 {
  153.                         if (touch.Tags.HasTag(Tags.INPUT_MOUSE)) continue;
  154.  
  155.                         for (int index = 0; index < mTouches.size; ++index)
  156.                         {
  157.                                 UICamera.Touch t = mTouches[index];
  158.  
  159.                                 if (t.fingerId == touch.Id)
  160.                                 {
  161.                                         t.position = touch.Position;
  162.                                         break;
  163.                                 }
  164.                         }
  165.                 }
  166.         }
  167.  
  168.         void OnTouchCancel (object sender, TouchEventArgs e) { OnTouchEnded(sender, e); }
  169.  
  170.         void LateUpdate ()
  171.         {
  172.                 int index = 0;
  173.  
  174.                 while (index < mTouches.size)
  175.                 {
  176.                         UICamera.Touch touch = mTouches[index];
  177.  
  178.                         if (touch.phase == TouchPhase.Ended)
  179.                         {
  180.                                 mTouches.RemoveAt(index);
  181.                         }
  182.                         else
  183.                         {
  184.                                 touch.phase = TouchPhase.Moved;
  185.                                 ++index;
  186.                         }
  187.                 }
  188.         }
  189. }
  190.  
« Last Edit: March 27, 2016, 02:48:37 AM by ArenMook »

StabbAmonte

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 1
  • Posts: 7
    • View Profile
ArenMook, I copied that script line for line and there are several compile errors:

Assets/Scripts/Game/Input/TouchScriptNGUI.cs(19,25): error CS0426: The nested type `Touch' does not exist in the type `UICamera'
Assets/Scripts/Game/Input/TouchScriptNGUI.cs(58,22): error CS0117: `UICamera' does not contain a definition for `GetInputTouch'
Assets/Scripts/Game/Input/TouchScriptNGUI.cs(58,48): error CS0426: The nested type `GetTouchCallback' does not exist in the type `UICamera'

This seems odd considering that this post is only about 10 days old.

I tried to change UICamera.Touch to UICamera.MouseOrTouch but that did not help, I think there is a deep issue I may be missing.

I recently updated to the latest version of nGUI (from 3.7.6 to 3.7.9 as of this post) and got the same errors.

Any help is appreciated.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
You'll need the Pro version of NGUI as these changes are a part of 3.8.0. If you don't have Pro, just wait until it's out on the Asset Store.

MS80

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 1
    • View Profile
Re: What's the best way to integrate NGUI support into another input framework?
« Reply #10 on: February 11, 2015, 11:35:44 AM »
I picked up a touch screen and noticed that multi-touch doesn't work natively in Unity apps, but the TouchScript plugin does. Now I have a better understanding of what this thread was all about, and I wrote a script that makes NGUI work with TouchScript's touch events

Are you kidding us Aren?  ;D
Thanks for the script and new NGUI version 3.8. It just works great! FINALLY !!!!  :o