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]
))
;
}
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.