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