1

I'm trying to implement multitouch drag in unirx for unity. I use the Buffer(count, skip) overload to get last to events for each finger and calculate the distance.

I now would like the clear the Buffer when a finger is lifted, otherwise the old value that is still in the buffer will create a large delta.

 private IObservable<TwoFingerDragEventData> CalculateDelta(IObservable<PointerEventData> dragEvent, int pointerId) {

    return dragEvent
      .Where(data => data.pointerId == pointerId)
      .Select(data => data.position)
      .Buffer(2, 1)
      .Select((IList<Vector2> list) => new TwoFingerDragEventData(
        Vector2.Distance(list[0], list[1]),
        list[1] - list[0]
      ))
    ;
  }
  • You need three instructions in the method. 1) var results = dragEvent ( and the rest of your query) 2) Clear buffer 3) return results; – jdweng Aug 19 '19 at 10:55
  • @jdweng The question is how do I clear that buffer? The buffer is internal to Observable and does not offer such functionality as far as I know. – Matthias Tylkowski Aug 19 '19 at 11:25
  • Isn't it dragEvent.data? No it is not internal to Observable. It is passed to the Event when it is registered and is always the same object. – jdweng Aug 19 '19 at 12:09
  • You're better off using `Switch()` operator for resting observables. You first build up a `IObservable>` and `.Switch()` turns it into an `IObservable` whereby only the latest inner values from the most recent outer observable is then produced. – Enigmativity Aug 19 '19 at 12:32
  • @Enigmativity yes that is how I did it, see answer below. @jdweng dragEvent is an `IObservable´ – Matthias Tylkowski Aug 19 '19 at 14:48

1 Answers1

0

I solved it now by wrapping the whole thing into another observable.

I use a BehaviourSubject<bool> isDragActiveSource which is set to true on drag start event and set to false on drag stop event.

isDragActiveSource
  .AsObservable()
  .Where(isActive => isActive == true)
  .SelectMany((bool _) => {
    IObservable<TwoFingerDragEventData> firstTouch = CalculateDelta(onDrag, 0);
    IObservable<TwoFingerDragEventData> secondTouch = CalculateDelta(onDrag, 1);

    return firstTouch.Zip(
      secondTouch,
      (TwoFingerDragEventData left, TwoFingerDragEventData right) => TwoFingerDragEventData.Avg(left, right
    ).TakeUntil(isDragActive.Where(isActive => isActive == false));
  })

When the BehaviourSubject emits false firstTouch and secondTouch Observables are completed (takeUntil) and when it becomes true again they are re-created.