当前位置:   article > 正文

Unity-TouchScripts中使用TUIO的记录和简单的代码分析_unitytouchscript插件tuio

unitytouchscript插件tuio

端午三天假,刚过完端午就被老板拉过去加班去了,端午三天假加了两天班,好了不吐槽了。记录一下Unity通过TouchScript插件中TUIO协议的使用以及代码的简单分析。

先说一下项目的大致情况,对方通过TUIO协议发送Blob格式的消息,发送的Blob消息中的面积(Area)是一个识别的重要信息,但TouchScript中返回的是Pointer类,但这个类中并没有我需要的消息。后来分析了一下代码的流向最终拿到了需要的信息。

TuioInput.cs

首先分析一下Tuio的输入,先看一下Unity函数:

  1. /// <inheritdoc />
  2. protected override void OnEnable()
  3. {
  4. base.OnEnable();
  5. screenWidth = Screen.width;
  6. screenHeight = Screen.height;
  7. cursorProcessor = new CursorProcessor();
  8. cursorProcessor.CursorAdded += OnCursorAdded;
  9. cursorProcessor.CursorUpdated += OnCursorUpdated;
  10. cursorProcessor.CursorRemoved += OnCursorRemoved;
  11. blobProcessor = new BlobProcessor();
  12. blobProcessor.BlobAdded += OnBlobAdded;
  13. blobProcessor.BlobUpdated += OnBlobUpdated;
  14. blobProcessor.BlobRemoved += OnBlobRemoved;
  15. objectProcessor = new ObjectProcessor();
  16. objectProcessor.ObjectAdded += OnObjectAdded;
  17. objectProcessor.ObjectUpdated += OnObjectUpdated;
  18. objectProcessor.ObjectRemoved += OnObjectRemoved;
  19. connect();
  20. }
  21. /// <inheritdoc />
  22. protected override void OnDisable()
  23. {
  24. disconnect();
  25. base.OnDisable();
  26. }

在OnEnable函数中,首先记录了一下屏幕的宽高,其次new了三个处理类,分别处理鼠标、Blob和物体的,并且分别注册了处理类的回调,当添加时、当更新时、当移除时,最后调用了connect连接函数。按下F12追踪一下connect函数;

  1. private void connect()
  2. {
  3. if (!Application.isPlaying) return;
  4. if (server != null) disconnect();
  5. server = new TuioServer(TuioPort);
  6. server.Connect();
  7. updateInputs();
  8. }

可以看到此处新建一个TuioServer类,并调用器自身的Connect函数,最后调用updateInputs函数。按下F12看一下TuioServer;

  1. namespace TUIOsharp
  2. {
  3. public class TuioServer
  4. {
  5. public TuioServer();
  6. public TuioServer(int port);
  7. public int Port { get; }
  8. public event EventHandler<ExceptionEventArgs> ErrorOccured;
  9. public void AddDataProcessor(IDataProcessor processor);
  10. public void Connect();
  11. public void Disconnect();
  12. public void RemoveAllDataProcessors();
  13. public void RemoveDataProcessor(IDataProcessor processor);
  14. }
  15. }

这里可以看到TuioServer类中有一个添加处理器的函数AddDataProcessor和移除处理器的函数RemoveDataProcessor,这个下边会说到。我们再看一下updateInputs函数;

  1. private void updateInputs()
  2. {
  3. if (server == null) return;
  4. if ((supportedInputs & InputType.Cursors) != 0) server.AddDataProcessor(cursorProcessor);
  5. else server.RemoveDataProcessor(cursorProcessor);
  6. if ((supportedInputs & InputType.Blobs) != 0) server.AddDataProcessor(blobProcessor);
  7. else server.RemoveDataProcessor(blobProcessor);
  8. if ((supportedInputs & InputType.Objects) != 0) server.AddDataProcessor(objectProcessor);
  9. else server.RemoveDataProcessor(objectProcessor);
  10. }

可以看到再updateInputs函数内部,把再OnEnable函数中新建的三个处理类添加进TuioServer中。好的,我们再看一下TuioInput注册三个处理类的回调函数(由于对方是发送Blob消息的,这里只看一下Blob的回调函数,其他类似);

  1. private void OnBlobAdded(object sender, TuioBlobEventArgs e)
  2. {
  3. var entity = e.Blob;
  4. lock (this)
  5. {
  6. var x = entity.X * screenWidth;
  7. var y = (1 - entity.Y) * screenHeight;
  8. var touch = internalAddObject(new Vector2(x, y));
  9. updateBlobProperties(touch, entity);
  10. blobToInternalId.Add(entity, touch);
  11. }
  12. }

首先看一下参数TuioBlobEventArgs;

  1. namespace TUIOsharp.DataProcessors
  2. {
  3. public class TuioBlobEventArgs : EventArgs
  4. {
  5. public TuioBlob Blob;
  6. public TuioBlobEventArgs(TuioBlob blob);
  7. }
  8. }

在追踪一下TuioBlob类;

  1. namespace TUIOsharp.Entities
  2. {
  3. public class TuioBlob : TuioEntity
  4. {
  5. public TuioBlob(int id);
  6. public TuioBlob(int id, float x, float y, float angle, float width, float height, float area, float velocityX, float velocityY, float rotationVelocity, float acceleration, float rotationAcceleration);
  7. public float Angle { get; }
  8. public float Width { get; }
  9. public float Height { get; }
  10. public float Area { get; }
  11. public float RotationVelocity { get; }
  12. public float RotationAcceleration { get; }
  13. public void Update(float x, float y, float angle, float width, float height, float area, float velocityX, float velocityY, float rotationVelocity, float acceleration, float rotationAcceleration);
  14. }
  15. }

好的,在这个类中可以看到有很多信息,坐标、角度、宽度、高度等一些列信息,我需要的面积也在其中,下一步就是怎么取出数据了,由于没怎么用过TUIO,也没研究过TouchScript关于这块的内容走了很多岔子,这就不提了。关于这个类的一些参考可以看一下TUIO官网的说明,链接在这:http://www.tuio.org/?specification

接着看OnBlobAdded函数,在函数内部可以看到x值乘以了缓存的屏幕宽度、y值乘以了缓存的屏幕高度,可以断定传过来的xy是归一化后的数字(即介于0-1之间),同时y轴翻转;紧接着调用internalAddObject函数,并传参xy,看一下internalAddObject函数;

  1. private ObjectPointer internalAddObject(Vector2 position)
  2. {
  3. var pointer = objectPool.Get();
  4. pointer.Position = remapCoordinates(position);
  5. pointer.Buttons |= Pointer.PointerButtonState.FirstButtonDown | Pointer.PointerButtonState.FirstButtonPressed;
  6. addPointer(pointer);
  7. pressPointer(pointer);
  8. return pointer;
  9. }

在这里更新了一下位置,随后调用addPointer和pressPointer两个函数,这里看一下addPointer函数;

  1. /// <summary>
  2. /// Adds the pointer to the system.
  3. /// </summary>
  4. /// <param name="pointer">The pointer to add.</param>
  5. protected virtual void addPointer(Pointer pointer)
  6. {
  7. manager.INTERNAL_AddPointer(pointer);
  8. }

这里的函数实际调用了父类InputSource的函数,TuioInput类继承InputSource类,函数内部又调用了manager.INTERNAL_AddPointer函数,这里的manager是TouchManagerInstance类,一个比较核心的类。看一下INTERNAL_AddPointer函数;

  1. internal void INTERNAL_AddPointer(Pointer pointer)
  2. {
  3. lock (pointerLock)
  4. {
  5. pointer.INTERNAL_Init(nextPointerId);
  6. pointersAdded.Add(pointer);
  7. #if TOUCHSCRIPT_DEBUG
  8. pLogger.Log(pointer, PointerEvent.IdAllocated);
  9. #endif
  10. nextPointerId++;
  11. }
  12. }

在这里调用了Pointer类自身的INTERNAL_Init函数,这里就不看了,INTERNAL_Init函数内部更新了一下Id并 记录了一下位置,;在调用Pointer类自身的INTERNAL_Init函数后,将其添加至pointersAdded这个list中,并自动更新下一个Id,关于pointersAdded这里先不深究,等一下再说;接着看一下pressPointer函数;

  1. /// <summary>
  2. /// Mark the pointer as touching the surface.
  3. /// </summary>
  4. /// <param name="pointer">The pointer.</param>
  5. protected virtual void pressPointer(Pointer pointer)
  6. {
  7. if (pointer == null) return;
  8. manager.INTERNAL_PressPointer(pointer.Id);
  9. }

和上边相同调用了manager的函数,看一下INTERNAL_PressPointer函数;

  1. internal void INTERNAL_PressPointer(int id)
  2. {
  3. lock (pointerLock)
  4. {
  5. Pointer pointer;
  6. if (!idToPointer.TryGetValue(id, out pointer))
  7. {
  8. // This pointer was added this frame
  9. if (!wasPointerAddedThisFrame(id, out pointer))
  10. {
  11. // No pointer with such id
  12. #if TOUCHSCRIPT_DEBUG
  13. if (DebugMode)
  14. Debug.LogWarning("TouchScript > Pointer with id [" + id +
  15. "] is requested to PRESS but no pointer with such id found.");
  16. #endif
  17. return;
  18. }
  19. }
  20. #if TOUCHSCRIPT_DEBUG
  21. if (!pointersPressed.Add(id))
  22. if (DebugMode)
  23. Debug.LogWarning("TouchScript > Pointer with id [" + id +
  24. "] is requested to PRESS more than once this frame.");
  25. #else
  26. pointersPressed.Add(id);
  27. #endif
  28. }
  29. }

在这里可以看到函数首先会从idToPointer这个字典中尝试获取Pointer,由于取反,当字典中存在时将会执行

pointersPressed.Add(id);

这条语句,将id添加至pointersPressed中;当字典不存在时,会调用wasPointerAddedThisFrame进行一次判断(应该是判断是否是新添加的Pointer),同样取反,true->return,false->添加至pointersPressed。wasPointerAddedThisFrame函数内部如下:

  1. private bool wasPointerAddedThisFrame(int id, out Pointer pointer)
  2. {
  3. pointer = null;
  4. foreach (var p in pointersAdded)
  5. {
  6. if (p.Id == id)
  7. {
  8. pointer = p;
  9. return true;
  10. }
  11. }
  12. return false;
  13. }

通过foreach进行判断,有意思的是遍历是pointersAdded,上边分析INTERNAL_AddPointer函数时,最终的Pointer被添加的就是pointersAdded。

好的,经过上边一串有点长的函数调用分析,终于把OnBlobAdded函数内部中的internalAddObject函数分析完毕,请滚动一下鼠标重新看一下OnBlobAdded函数,接下来要继续分析下边的执行语句;调用updateBlobProperties函数,并把一些数据添加到blobToInternalId字典中;

  1. private void updateBlobProperties(ObjectPointer obj, TuioBlob target)
  2. {
  3. obj.Width = target.Width;
  4. obj.Height = target.Height;
  5. obj.Angle = target.Angle;
  6. }

updateBlobProperties函数内部更新了一些属性,如上代码所见,我们是不是可以把Area(面积)更新一下???这样我们就可以拿到自己想要的数据了,事实证明这样是可以的,我最终也是这样解决的,理论上这篇博客已经给出了开始问题的解决方案,只需要订阅TouchManager的相应事件即可,比如TouchManager.Instance.PointersAdded、TouchManager.Instance.PointersUpdated、TouchManager.Instance.PointersRemoved……在回调时把相应的Pointer转换为ObjectPointer即可拿到area(ObjectPointer时是Pointer的子类)。但最终我继续分析了其他代码,把Pointer在TouchScript内部流通给搞明白了。所以,我们继续分析;

OnBlobUpdated函数:

  1. private void OnBlobUpdated(object sender, TuioBlobEventArgs e)
  2. {
  3. var entity = e.Blob;
  4. lock (this)
  5. {
  6. ObjectPointer touch;
  7. if (!blobToInternalId.TryGetValue(entity, out touch)) return;
  8. var x = entity.X * screenWidth;
  9. var y = (1 - entity.Y) * screenHeight;
  10. touch.Position = remapCoordinates(new Vector2(x, y));
  11. updateBlobProperties(touch, entity);
  12. updatePointer(touch);
  13. }
  14. }

在这里会首先对blobToInternalId字典尝试获取ObjectPointer(在OnBlobAdded函数最后把OnBlobAdded添加到了blobToInternalId字典中),如果获取成功,会计算位置,并通过remapCoordinates最终调用函数把位置重新映射一下(这里就补贴其他代码了,如果有兴趣请自行查看,下同),调用updateBlobProperties(上边分析过了)更新属性,最终调用updatePointer函数,updatePointer函数内部调用manager.INTERNAL_UpdatePointer函数,该函数如下:

  1. internal void INTERNAL_UpdatePointer(int id)
  2. {
  3. lock (pointerLock)
  4. {
  5. Pointer pointer;
  6. if (!idToPointer.TryGetValue(id, out pointer))
  7. {
  8. // This pointer was added this frame
  9. if (!wasPointerAddedThisFrame(id, out pointer))
  10. {
  11. // No pointer with such id
  12. #if TOUCHSCRIPT_DEBUG
  13. if (DebugMode) Debug.LogWarning("TouchScript > Pointer with id [" + id + "] is requested to MOVE to but no pointer with such id found.");
  14. #endif
  15. return;
  16. }
  17. }
  18. pointersUpdated.Add(id);
  19. }
  20. }

和INTERNAL_PressPointer函数类似,只不过最后添加的是pointersUpdated而不是pointersPressed。

OnBlobRemoved函数:

  1. private void OnBlobRemoved(object sender, TuioBlobEventArgs e)
  2. {
  3. var entity = e.Blob;
  4. lock (this)
  5. {
  6. ObjectPointer touch;
  7. if (!blobToInternalId.TryGetValue(entity, out touch)) return;
  8. blobToInternalId.Remove(entity);
  9. releasePointer(touch);
  10. removePointer(touch);
  11. }
  12. }

同样的先在blobToInternalId中尝试获取ObjectPointer,如果获取成功,则从blobToInternalId移除,且调用releasePointer函数和removePointer,这两个函数最终调用了TouchManagerInstance的INTERNAL_ReleasePointer函数和INTERNAL_RemovePointer函数;其内部实现如下:

  1. /// <inheritdoc />
  2. internal void INTERNAL_ReleasePointer(int id)
  3. {
  4. lock (pointerLock)
  5. {
  6. Pointer pointer;
  7. if (!idToPointer.TryGetValue(id, out pointer))
  8. {
  9. // This pointer was added this frame
  10. if (!wasPointerAddedThisFrame(id, out pointer))
  11. {
  12. // No pointer with such id
  13. #if TOUCHSCRIPT_DEBUG
  14. if (DebugMode)
  15. Debug.LogWarning("TouchScript > Pointer with id [" + id +
  16. "] is requested to END but no pointer with such id found.");
  17. #endif
  18. return;
  19. }
  20. }
  21. #if TOUCHSCRIPT_DEBUG
  22. if (!pointersReleased.Add(id))
  23. if (DebugMode)
  24. Debug.LogWarning("TouchScript > Pointer with id [" + id +
  25. "] is requested to END more than once this frame.");
  26. #else
  27. pointersReleased.Add(id);
  28. #endif
  29. }
  30. }
  31. /// <inheritdoc />
  32. internal void INTERNAL_RemovePointer(int id)
  33. {
  34. lock (pointerLock)
  35. {
  36. Pointer pointer;
  37. if (!idToPointer.TryGetValue(id, out pointer))
  38. {
  39. // This pointer was added this frame
  40. if (!wasPointerAddedThisFrame(id, out pointer))
  41. {
  42. // No pointer with such id
  43. #if TOUCHSCRIPT_DEBUG
  44. if (DebugMode)
  45. Debug.LogWarning("TouchScript > Pointer with id [" + id +
  46. "] is requested to REMOVE but no pointer with such id found.");
  47. #endif
  48. return;
  49. }
  50. }
  51. #if TOUCHSCRIPT_DEBUG
  52. if (!pointersRemoved.Add(pointer.Id))
  53. if (DebugMode)
  54. Debug.LogWarning("TouchScript > Pointer with id [" + id +
  55. "] is requested to REMOVE more than once this frame.");
  56. #else
  57. pointersRemoved.Add(pointer.Id);
  58. #endif
  59. }
  60. }

这两个函数内部极为相似,不同的是最后是添加的不是同一个HashSet。

TouchManagerInstance.cs

先看一下几个比较眼熟的字段:

  1. private List<Pointer> pointers = new List<Pointer>(30);
  2. private HashSet<Pointer> pressedPointers = new HashSet<Pointer>();
  3. private Dictionary<int, Pointer> idToPointer = new Dictionary<int, Pointer>(30);
  4. // Upcoming changes
  5. private List<Pointer> pointersAdded = new List<Pointer>(10);
  6. private HashSet<int> pointersUpdated = new HashSet<int>();
  7. private HashSet<int> pointersPressed = new HashSet<int>();
  8. private HashSet<int> pointersReleased = new HashSet<int>();
  9. private HashSet<int> pointersRemoved = new HashSet<int>();
  10. private HashSet<int> pointersCancelled = new HashSet<int>();

我们看一下它的Update函数:

  1. private void Update()
  2. {
  3. sendFrameStartedToPointers();
  4. updateInputs();
  5. updatePointers();
  6. }

这里只看一下updatePointers函数:

  1. private void updatePointers()
  2. {
  3. IsInsidePointerFrame = true;
  4. if (frameStartedInvoker != null) frameStartedInvoker.InvokeHandleExceptions(this, EventArgs.Empty);
  5. // need to copy buffers since they might get updated during execution
  6. List<Pointer> addedList = null;
  7. List<int> updatedList = null;
  8. List<int> pressedList = null;
  9. List<int> releasedList = null;
  10. List<int> removedList = null;
  11. List<int> cancelledList = null;
  12. lock (pointerLock)
  13. {
  14. if (pointersAdded.Count > 0)
  15. {
  16. addedList = pointerListPool.Get();
  17. addedList.AddRange(pointersAdded);
  18. pointersAdded.Clear();
  19. }
  20. if (pointersUpdated.Count > 0)
  21. {
  22. updatedList = intListPool.Get();
  23. updatedList.AddRange(pointersUpdated);
  24. pointersUpdated.Clear();
  25. }
  26. if (pointersPressed.Count > 0)
  27. {
  28. pressedList = intListPool.Get();
  29. pressedList.AddRange(pointersPressed);
  30. pointersPressed.Clear();
  31. }
  32. if (pointersReleased.Count > 0)
  33. {
  34. releasedList = intListPool.Get();
  35. releasedList.AddRange(pointersReleased);
  36. pointersReleased.Clear();
  37. }
  38. if (pointersRemoved.Count > 0)
  39. {
  40. removedList = intListPool.Get();
  41. removedList.AddRange(pointersRemoved);
  42. pointersRemoved.Clear();
  43. }
  44. if (pointersCancelled.Count > 0)
  45. {
  46. cancelledList = intListPool.Get();
  47. cancelledList.AddRange(pointersCancelled);
  48. pointersCancelled.Clear();
  49. }
  50. }
  51. var count = pointers.Count;
  52. for (var i = 0; i < count; i++)
  53. {
  54. pointers[i].INTERNAL_UpdatePosition();
  55. }
  56. if (addedList != null)
  57. {
  58. updateAdded(addedList);
  59. pointerListPool.Release(addedList);
  60. }
  61. if (updatedList != null)
  62. {
  63. updateUpdated(updatedList);
  64. intListPool.Release(updatedList);
  65. }
  66. if (pressedList != null)
  67. {
  68. updatePressed(pressedList);
  69. intListPool.Release(pressedList);
  70. }
  71. if (releasedList != null)
  72. {
  73. updateReleased(releasedList);
  74. intListPool.Release(releasedList);
  75. }
  76. if (removedList != null)
  77. {
  78. updateRemoved(removedList);
  79. intListPool.Release(removedList);
  80. }
  81. if (cancelledList != null)
  82. {
  83. updateCancelled(cancelledList);
  84. intListPool.Release(cancelledList);
  85. }
  86. if (frameFinishedInvoker != null) frameFinishedInvoker.InvokeHandleExceptions(this, EventArgs.Empty);
  87. IsInsidePointerFrame = false;
  88. }

首先看一下pointersAdded,在这里把pointersAdded装进addedList中;

  1. if (pointersAdded.Count > 0)
  2. {
  3. addedList = pointerListPool.Get();
  4. addedList.AddRange(pointersAdded);
  5. pointersAdded.Clear();
  6. }

最后调用updateAdded函数:

  1. if (addedList != null)
  2. {
  3. updateAdded(addedList);
  4. pointerListPool.Release(addedList);
  5. }

看一下updateAdded函数:

  1. private void updateAdded(List<Pointer> pointers)
  2. {
  3. samplerUpdateAdded.Begin();
  4. var addedCount = pointers.Count;
  5. var list = pointerListPool.Get();
  6. for (var i = 0; i < addedCount; i++)
  7. {
  8. var pointer = pointers[i];
  9. list.Add(pointer);
  10. this.pointers.Add(pointer);
  11. idToPointer.Add(pointer.Id, pointer);
  12. #if TOUCHSCRIPT_DEBUG
  13. pLogger.Log(pointer, PointerEvent.Added);
  14. #endif
  15. tmpPointer = pointer;
  16. layerManager.ForEach(_layerAddPointer);
  17. tmpPointer = null;
  18. #if TOUCHSCRIPT_DEBUG
  19. if (DebugMode) addDebugFigureForPointer(pointer);
  20. #endif
  21. }
  22. if (pointersAddedInvoker != null)
  23. pointersAddedInvoker.InvokeHandleExceptions(this, PointerEventArgs.GetCachedEventArgs(list));
  24. pointerListPool.Release(list);
  25. samplerUpdateAdded.End();
  26. }

可以看到最终这些Pointer被添加进idToPointer和pointers中,在函数最后几行进行了回调,完成了一次触摸点从接收到回调的一个完整流程。

在看一下pointersUpdated:

  1. if (pointersUpdated.Count > 0)
  2. {
  3. updatedList = intListPool.Get();
  4. updatedList.AddRange(pointersUpdated);
  5. pointersUpdated.Clear();
  6. }

被添加进updatedList中,接着往下看:

  1. if (updatedList != null)
  2. {
  3. updateUpdated(updatedList);
  4. intListPool.Release(updatedList);
  5. }

最终调用了updateUpdated函数:

  1. private void updateUpdated(List<int> pointers)
  2. {
  3. samplerUpdateUpdated.Begin();
  4. var updatedCount = pointers.Count;
  5. var list = pointerListPool.Get();
  6. for (var i = 0; i < updatedCount; i++)
  7. {
  8. var id = pointers[i];
  9. Pointer pointer;
  10. if (!idToPointer.TryGetValue(id, out pointer))
  11. {
  12. #if TOUCHSCRIPT_DEBUG
  13. if (DebugMode)
  14. Debug.LogWarning("TouchScript > Id [" + id +
  15. "] was in UPDATED list but no pointer with such id found.");
  16. #endif
  17. continue;
  18. }
  19. list.Add(pointer);
  20. #if TOUCHSCRIPT_DEBUG
  21. pLogger.Log(pointer, PointerEvent.Updated);
  22. #endif
  23. var layer = pointer.GetPressData().Layer;
  24. if (layer != null) layer.INTERNAL_UpdatePointer(pointer);
  25. else
  26. {
  27. tmpPointer = pointer;
  28. layerManager.ForEach(_layerUpdatePointer);
  29. tmpPointer = null;
  30. }
  31. #if TOUCHSCRIPT_DEBUG
  32. if (DebugMode) addDebugFigureForPointer(pointer);
  33. #endif
  34. }
  35. if (pointersUpdatedInvoker != null)
  36. pointersUpdatedInvoker.InvokeHandleExceptions(this, PointerEventArgs.GetCachedEventArgs(list));
  37. pointerListPool.Release(list);
  38. samplerUpdateUpdated.End();
  39. }

这里和updateAdded函数类似,不过它是在idToPointer中尝试获取(idToPointer承载了大部分的工作),最后回调一次PointersUpdated。

最后分析的是pointersRemoved:

  1. if (pointersRemoved.Count > 0)
  2. {
  3. removedList = intListPool.Get();
  4. removedList.AddRange(pointersRemoved);
  5. pointersRemoved.Clear();
  6. }

添加至removedList:

  1. if (removedList != null)
  2. {
  3. updateRemoved(removedList);
  4. intListPool.Release(removedList);
  5. }

调用updateRemoved函数:

  1. private void updateRemoved(List<int> pointers)
  2. {
  3. samplerUpdateRemoved.Begin();
  4. var removedCount = pointers.Count;
  5. var list = pointerListPool.Get();
  6. for (var i = 0; i < removedCount; i++)
  7. {
  8. var id = pointers[i];
  9. Pointer pointer;
  10. if (!idToPointer.TryGetValue(id, out pointer))
  11. {
  12. #if TOUCHSCRIPT_DEBUG
  13. if (DebugMode) Debug.LogWarning("TouchScript > Id [" + id + "] was in REMOVED list but no pointer with such id found.");
  14. #endif
  15. continue;
  16. }
  17. idToPointer.Remove(id);
  18. this.pointers.Remove(pointer);
  19. pressedPointers.Remove(pointer);
  20. list.Add(pointer);
  21. #if TOUCHSCRIPT_DEBUG
  22. pLogger.Log(pointer, PointerEvent.Removed);
  23. #endif
  24. tmpPointer = pointer;
  25. layerManager.ForEach(_layerRemovePointer);
  26. tmpPointer = null;
  27. #if TOUCHSCRIPT_DEBUG
  28. if (DebugMode) removeDebugFigureForPointer(pointer);
  29. #endif
  30. }
  31. if (pointersRemovedInvoker != null)
  32. pointersRemovedInvoker.InvokeHandleExceptions(this, PointerEventArgs.GetCachedEventArgs(list));
  33. removedCount = list.Count;
  34. for (var i = 0; i < removedCount; i++)
  35. {
  36. var pointer = list[i];
  37. pointer.InputSource.INTERNAL_DiscardPointer(pointer);
  38. }
  39. pointerListPool.Release(list);
  40. samplerUpdateRemoved.End();
  41. }

同样在idToPointer中尝试获取,最后完成回调。

到这里这篇博客就基本结束了,也不总结什么了,想研究的自己去看代码琢磨琢磨就清楚了。最后说一下事件的大致调用顺序

add-press-update-released-remove

另外Cancell没找到。

就这样,本人水平有限,如果有错误,欢迎大佬指正,谢谢!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/114180
推荐阅读
相关标签
  

闽ICP备14008679号