using System; using System.Collections.Generic; using UnityEngine.InputSystem.LowLevel; namespace UnityEngine.InputSystem.Utilities { /// /// Extension methods for working with IObservable /// in the context of the Input System. /// public static class Observable { /// /// Filter a stream of observable values by a predicate. /// /// The stream of observable values. /// Filter to apply to the stream. Only values for which the predicate returns true /// are passed on to OnNext of the observer. /// Value type for the observable stream. /// is null -or- is null. /// A new observable that is filtered by the given predicate. /// /// /// /// InputSystem.onEvent /// .Where(e => e.HasButtonPress()) /// .Call(e => Debug.Log("Press")); /// /// /// /// /// public static IObservable Where(this IObservable source, Func predicate) { if (source == null) throw new ArgumentNullException(nameof(source)); if (predicate == null) throw new ArgumentNullException(nameof(predicate)); return new WhereObservable(source, predicate); } /// /// Transform each value in an observable stream of values into a value of a different type. /// /// The stream of observable values. /// Function to transform values in the stream. /// Type of source values to transform from. /// Type of target values to transform to. /// is null -or- is null. /// A new observable of values of the new result type. /// /// /// /// InputSystem.onEvent /// .Select(eventPtr => eventPtr.GetFirstButtonPressOrNull()) /// .Call(ctrl => /// { /// if (ctrl != null) /// Debug.Log(ctrl); /// }); /// /// /// /// /// public static IObservable Select(this IObservable source, Func filter) { if (source == null) throw new ArgumentNullException(nameof(source)); if (filter == null) throw new ArgumentNullException(nameof(filter)); return new SelectObservable(source, filter); } /// /// Transform each value in an observable stream of values such that one value is translated to zero or more values /// of a new type. /// /// The stream of observable values. /// Function to transform each value in the stream into zero or more new values. /// Type of source values to transform from. /// Type of target values to transform to. /// is null -or- is null. /// A new observable of values of the new result type. /// /// /// /// InputSystem.onEvent /// .SelectMany(eventPtr => eventPtr.GetAllButtonPresses()) /// .Call(ctrl => /// Debug.Log($"Button {ctrl} pressed")); /// /// /// /// /// public static IObservable SelectMany(this IObservable source, Func> filter) { if (source == null) throw new ArgumentNullException(nameof(source)); if (filter == null) throw new ArgumentNullException(nameof(filter)); return new SelectManyObservable(source, filter); } /// /// Take up to the first N values from the given observable stream of values. /// /// An observable source of values. /// The maximum number of values to take from the source. /// Types of values to read from the stream. /// is null. /// is negative. /// A stream of up to values. public static IObservable Take(this IObservable source, int count) { if (source == null) throw new ArgumentNullException(nameof(source)); if (count < 0) throw new ArgumentOutOfRangeException(nameof(count)); return new TakeNObservable(source, count); } /// /// From an observable stream of events, take only those that are for the given . /// /// An observable stream of events. /// Device to filter events for. /// is null. /// An observable stream of events for the given device. /// /// Each event has an associated with it. This is used to match /// against the of . /// /// /// /// InputSystem.onEvent /// .ForDevice(Mouse.current) /// .Call(e => Debug.Log($"Mouse event: {e}"); /// /// /// /// /// /// public static IObservable ForDevice(this IObservable source, InputDevice device) { if (source == null) throw new ArgumentNullException(nameof(source)); return new ForDeviceEventObservable(source, null, device); } /// /// From an observable stream of events, take only those that are for a device of the given type. /// /// An observable stream of events. /// Type of device (such as ) to filter for. /// is null. /// An observable stream of events for devices of type . /// /// /// /// InputSystem.onEvent /// .ForDevice<Gamepad>() /// .Where(e => e.HasButtonPress()) /// .CallOnce(e => PlayerInput.Instantiate(myPrefab, /// pairWithDevice: InputSystem.GetDeviceById(e.deviceId))); /// /// /// /// /// public static IObservable ForDevice(this IObservable source) where TDevice : InputDevice { if (source == null) throw new ArgumentNullException(nameof(source)); return new ForDeviceEventObservable(source, typeof(TDevice), null); } /// /// Call an action for the first value in the given stream of values and then automatically dispose /// the observer. /// /// An observable source of values. /// Action to call for the first value that arrives from the source. /// Type of values delivered by the source. /// is null -or- is null. /// A handle to the subscription. Call Dispose to unsubscribe at any time. /// /// /// /// InputSystem.onEvent /// .Where(e => e.type == DeviceConfigurationEvent.typeStatic) /// .CallOnce(_ => Debug.Log("Device configuration changed")); /// /// /// /// /// /// public static IDisposable CallOnce(this IObservable source, Action action) { if (source == null) throw new ArgumentNullException(nameof(source)); if (action == null) throw new ArgumentNullException(nameof(action)); IDisposable subscription = null; subscription = source.Take(1).Subscribe(new Observer(action, () => subscription?.Dispose())); return subscription; } /// /// Call the given callback for every value generated by the given observable stream of values. /// /// An observable stream of values. /// A callback to invoke for each value. /// /// is null -or- is null. /// A handle to the subscription. Call Dispose to unsubscribe at any time. /// /// /// /// InputSystem.onEvent /// .Where(e => e.type == DeviceConfigurationEvent.typeStatic) /// .Call(_ => Debug.Log("Device configuration changed")); /// /// /// /// /// /// public static IDisposable Call(this IObservable source, Action action) { if (source == null) throw new ArgumentNullException(nameof(source)); if (action == null) throw new ArgumentNullException(nameof(action)); return source.Subscribe(new Observer(action)); } } }