Beispiel #1
0
        /// <summary>
        /// Remove an active user.
        /// </summary>
        /// <param name="user">An active user.</param>
        /// <exception cref="ArgumentNullException"><paramref name="user"/> is <c>null</c>.</exception>
        /// <remarks>
        /// Removing a user also unassigns all currently assigned devices from the user. On completion of this
        /// method, <see cref="devices"/> of <paramref name="user"/> will be empty.
        /// </remarks>
        public static void Remove(IInputUser user)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var index = FindUserIndex(user);

            if (index == -1)
            {
                return;
            }

            // Remove devices.
            var userData = s_AllUserData[index];

            if (userData.deviceCount > 0)
            {
                ArrayHelpers.EraseSliceWithCapacity(ref s_AllDevices, ref s_AllDeviceCount, userData.deviceStartIndex,
                                                    userData.deviceCount);
            }

            // Remove.
            var userCount = s_AllUserCount;

            ArrayHelpers.EraseAtWithCapacity(ref s_AllUsers, ref userCount, index);
            ArrayHelpers.EraseAtWithCapacity(ref s_AllUserData, ref s_AllUserCount, index);

            // Send notification.
            Notify(user, InputUserChange.Removed);
        }
Beispiel #2
0
 private static void Notify(IInputUser user, InputUserChange change)
 {
     for (var i = 0; i < s_OnChange.length; ++i)
     {
         s_OnChange[i](user, change);
     }
 }
Beispiel #3
0
        public static void AssignInputDevices <TDevices>(this IInputUser user, TDevices devices)
            where TDevices : IEnumerable <InputDevice> // Parameter so that compiler can know enumerable type instead of having to go through the interface.
        {
            if (devices == null)
            {
                throw new ArgumentNullException("devices");
            }

            var userIndex = FindUserIndex(user);

            if (userIndex == -1)
            {
                throw new InvalidOperationException(string.Format("User '{0}' has not been added to the system", user));
            }

            var wasAdded = false;

            foreach (var device in devices)
            {
                if (device == null)
                {
                    continue;
                }
                wasAdded |= AssignDeviceInternal(userIndex, device);
            }

            if (wasAdded)
            {
                Notify(user, InputUserChange.DevicesChanged);
            }
        }
Beispiel #4
0
    /// <summary>
    /// Called when an action is triggered from a device that isn't assigned to any user.
    /// </summary>
    /// <param name="user"></param>
    /// <param name="action"></param>
    /// <param name="control"></param>
    /// <remarks>
    /// In single-player mode, we concurrently enable all our bindings from all available control schemes.
    /// This means that the actions will bind to whatever devices are available. However, we only assign
    /// the devices actively used with the current control scheme to the user. This means that we always know
    /// how the player is currently controlling the game.
    ///
    /// When the player uses a binding that isn't part of the current control scheme, this method will
    /// be called. In here we automatically switch control schemes by looking at which control scheme is
    /// suited to the unassigned device.
    ///
    /// Note that the logic here also covers the case where there are multiple devices meant to be used
    /// with the same control scheme. For example, there may be two gamepads and the player is free to
    /// switch from one or the other. In that case, while we will stay on the Gamepad control scheme,
    /// we will still unassign the previously used gamepad from the player and assign the newly used one.
    /// </remarks>
    private void OnUnassignedDeviceUsed(IInputUser user, InputAction action, InputControl control)
    {
        // We only support control scheme switching in single player.
        if (!m_SinglePlayer)
        {
            return;
        }

        // All our IInputUsers are expected to be DemoPlayerControllers.
        var player = user as DemoPlayerController;

        if (player == null)
        {
            return;
        }

        ////REVIEW: should we just look at the binding that triggered and go by the binding group it is in?

        // Select a control scheme based on the device that was used.
        var device        = control.device;
        var controlScheme = player.SelectControlSchemeBasedOnDevice(device);

        // Give the device to the user and then switch control schemes.
        // If the control scheme requires additional devices, we select them automatically using
        // AndAssignMissingDevices().
        user.ClearAssignedInputDevices();
        user.AssignInputDevice(device);
        user.AssignControlScheme(controlScheme)
        .AndAssignMissingDevices();
    }
Beispiel #5
0
 /// <summary>
 /// Get the sequence number of the user.
 /// </summary>
 /// <remarks>
 /// It can be useful to establish a sorting of players locally such that it is
 /// known who is the first player, who is the second, and so on. This property
 /// gives the positioning of the user within the globally established sequence.
 ///
 /// Note that the index of a user may change as users are added and removed.
 /// </remarks>
 public static int GetUserIndex(this IInputUser user)
 {
     if (user == null)
     {
         throw new ArgumentNullException("user");
     }
     return(FindUserIndex(user));
 }
        /// <inheritdoc />
        public async Task <TUserFull> GetUserFullAsync(IInputUser inputUser, CancellationToken cancellationToken = default(CancellationToken))
        {
            var request = new RequestGetFullUser
            {
                Id = inputUser
            };

            return((TUserFull)await RequestSender.SendRequestAsync(request, cancellationToken).ConfigureAwait(false));
        }
        /// <inheritdoc />
        public async Task <TLink> DeleteContactAsync(IInputUser user, CancellationToken cancellationToken = default(CancellationToken))
        {
            ClientSettings.EnsureUserAuthorized();

            var req = new RequestDeleteContact
            {
                Id = user
            };

            return((TLink)await RequestSender.SendRequestAsync(req, cancellationToken).ConfigureAwait(false));
        }
Beispiel #8
0
 private static int FindUserIndex(IInputUser user)
 {
     for (var i = 0; i < s_AllUserCount; ++i)
     {
         if (s_AllUsers[i] == user)
         {
             return(i);
         }
     }
     return(-1);
 }
Beispiel #9
0
        /// <summary>
        /// Deletes a user from a chat and sends a service message on it.
        /// </summary>
        /// <param name="chatId">Chat's identifier</param>
        /// <param name="user">User ID to be deleted</param>
        /// <returns>
        /// Returns a <see cref="IUpdates"/> object containing a service message sent during the action.
        /// </returns>
        public async Task <IUpdates> DeleteChatUser(int chatId, IInputUser user)
        {
            EnsureUserAuthorized();

            var request = new RequestDeleteChatUser
            {
                ChatId = chatId,
                UserId = user
            };

            return(await SenderService.SendRequestAsync(request).ConfigureAwait(false));
        }
        /// <inheritdoc />
        public async Task <IUpdates> DeleteChatUser(int chatId, IInputUser user, CancellationToken cancellationToken = default(CancellationToken))
        {
            ClientSettings.EnsureUserAuthorized();

            var request = new RequestDeleteChatUser
            {
                ChatId = chatId,
                UserId = user
            };

            return(await RequestSender.SendRequestAsync(request, cancellationToken).ConfigureAwait(false));
        }
        /// <inheritdoc />
        public async Task <IPhotos> GetUserPhotosAsync(IInputUser user, int offset = 0, int limit = 200, long maxId = 0, CancellationToken cancellationToken = default(CancellationToken))
        {
            var request = new RequestGetUserPhotos
            {
                UserId = user,
                MaxId  = maxId,
                Limit  = limit,
                Offset = offset
            };

            return(await RequestSender.SendRequestAsync(request, cancellationToken).ConfigureAwait(false));
        }
Beispiel #12
0
        /// <summary>
        /// Adds a user to a chat and sends a service message on it.
        /// </summary>
        /// <param name="chatId">Chat's identifier</param>
        /// <param name="user">User ID to be added</param>
        /// <param name="limit">Number of last messages to be forwarded</param>
        /// <returns>
        /// Returns a <see cref="IUpdates"/> object contains info on one message with auxiliary data and data on the current state of updates.
        /// </returns>
        public async Task <IUpdates> AddChatUserAsync(int chatId, IInputUser user, int limit)
        {
            EnsureUserAuthorized();

            var request = new RequestAddChatUser
            {
                ChatId   = chatId,
                UserId   = user,
                FwdLimit = limit
            };

            return(await SenderService.SendRequestAsync(request).ConfigureAwait(false));
        }
Beispiel #13
0
        /// <summary>Adds a user to a chat and sends a service message on it.</summary>
        /// <param name="chatId">Chat's identifier</param>
        /// <param name="user">User ID to be added</param>
        /// <param name="limit">Number of last messages to be forwarded</param>
        /// <returns>
        ///     Returns a <see cref="IUpdates" /> object contains info on one message with auxiliary data and data on the
        ///     current state of updates.
        /// </returns>
        public async Task <IUpdates> AddChatUserAsync(int chatId, IInputUser user, int limit, CancellationToken cancellationToken = default(CancellationToken))
        {
            AuthApiService.EnsureUserAuthorized();

            var request = new RequestAddChatUser
            {
                ChatId   = chatId,
                UserId   = user,
                FwdLimit = limit
            };

            return(await SenderService.SendRequestAsync(request, cancellationToken).ConfigureAwait(false));
        }
Beispiel #14
0
        /// <summary>
        /// Get the unique numeric ID of the user.
        /// </summary>
        /// <remarks>
        /// The ID of a user cannot be changed over its lifetime. Also, while the user
        /// is active, no other player can have the same ID.
        /// </remarks>
        public static ulong GetUserId(this IInputUser user)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var index = FindUserIndex(user);

            if (index == -1)
            {
                return(kInvalidId);
            }

            return(s_AllUserData[index].id);
        }
Beispiel #15
0
        /// <summary>
        /// Get the control scheme currently employed by the user.
        /// </summary>
        /// <remarks>
        ///
        /// Note that if bindings are enabled that are not part of the active control scheme,
        /// this property will automatically change value according to what bindings are being
        /// used.
        ///
        /// Any time the value of this property change (whether by <see cref="SetControlScheme"/>
        /// or by automatic switching), a notification is sent on <see cref="onChange"/> with
        /// <see cref="InputUserChange.ControlSchemeChanged"/>.
        /// </remarks>
        public static InputControlScheme?GetControlScheme(this IInputUser user)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var index = FindUserIndex(user);

            if (index == -1)
            {
                return(null);
            }

            return(s_AllUserData[index].controlScheme);
        }
Beispiel #16
0
        /// <summary>
        /// Get the list of <see cref="InputDevice">input devices</see> assigned to the user.
        /// </summary>
        /// <remarks>
        /// Devices do not necessarily need to be unique to a user. For example, two users may both
        /// be assigned the same keyboard in a split-screen game where one user uses the left side and
        /// another user uses the right side of the keyboard. Another example is a game where players
        /// take turns on the same machine.
        /// </remarks>
        public static ReadOnlyArray <InputDevice> GetAssignedInputDevices(this IInputUser user)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var index = FindUserIndex(user);

            if (index == -1)
            {
                return(new ReadOnlyArray <InputDevice>());
            }

            return(new ReadOnlyArray <InputDevice>(s_AllDevices, s_AllUserData[index].deviceStartIndex,
                                                   s_AllUserData[index].deviceCount));
        }
Beispiel #17
0
        /// <summary>
        /// Add a new user.
        /// </summary>
        /// <param name="userName">Optional <see cref="userName"/> to assign to the newly created user.</param>
        /// <returns>A newly created user.</returns>
        /// <remarks>
        /// Adding a user sends a notification with <see cref="InputUserChange.Added"/> through <see cref="onChange"/>.
        ///
        /// The user will start out with no devices and no actions assigned.
        ///
        /// The user is added to <see cref="all"/>.
        /// </remarks>
        public static void Add(IInputUser user, string userName = null)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var userData = new UserData
            {
                id       = ++s_LastUserId,
                userName = userName,
            };

            // Add to list.
            var userCount = s_AllUserCount;

            ArrayHelpers.AppendWithCapacity(ref s_AllUsers, ref userCount, user);
            ArrayHelpers.AppendWithCapacity(ref s_AllUserData, ref s_AllUserCount, userData);

            // Send notification.
            Notify(user, InputUserChange.Added);
        }
Beispiel #18
0
        public static void SetUserName(this IInputUser user, string userName)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var index = FindUserIndex(user);

            if (index == -1)
            {
                throw new InvalidOperationException(string.Format("User '{0}' has not been added to the system", user));
            }

            if (string.Compare(s_AllUserData[index].userName, userName) == 0)
            {
                return;
            }

            s_AllUserData[index].userName = userName;

            Notify(user, InputUserChange.NameChanged);
        }
Beispiel #19
0
        public static void AssignInputDevice(this IInputUser user, InputDevice device)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }
            if (device == null)
            {
                throw new ArgumentNullException("device");
            }

            var userIndex = FindUserIndex(user);

            if (userIndex == -1)
            {
                throw new InvalidOperationException(string.Format("User '{0}' has not been added to the system", user));
            }

            if (AssignDeviceInternal(userIndex, device))
            {
                Notify(user, InputUserChange.DevicesChanged);
            }
        }
Beispiel #20
0
        public static void SetControlScheme(this IInputUser user, string schemeName)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var index = FindUserIndex(user);

            if (index == -1)
            {
                throw new InvalidOperationException(string.Format("User '{0}' has not been added to the system", user));
            }

            if (string.IsNullOrEmpty(schemeName) && !s_AllUserData[index].controlScheme.HasValue)
            {
                return;
            }
            if (!string.IsNullOrEmpty(schemeName) && s_AllUserData[index].controlScheme.HasValue &&
                string.Compare(
                    s_AllUserData[index].controlScheme.Value.m_Name, schemeName,
                    StringComparison.InvariantCultureIgnoreCase) == 0)
            {
                return;
            }

            if (string.IsNullOrEmpty(schemeName))
            {
                s_AllUserData[index].controlScheme = null;
            }
            else
            {
                s_AllUserData[index].controlScheme = new InputControlScheme(schemeName);
            }

            Notify(user, InputUserChange.ControlSchemeChanged);
        }
Beispiel #21
0
        public static void SetControlScheme(this IInputUser user, InputControlScheme scheme)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var index = FindUserIndex(user);

            if (index == -1)
            {
                throw new InvalidOperationException(string.Format("User '{0}' has not been added to the system", user));
            }

            // Ignore if the control scheme is already set on the user.
            if (s_AllUserData[index].controlScheme.HasValue && s_AllUserData[index].controlScheme == scheme)
            {
                return;
            }

            s_AllUserData[index].controlScheme = scheme;

            Notify(user, InputUserChange.ControlSchemeChanged);
        }
Beispiel #22
0
        //do we really need a stack on this? is a single InputActionMap or even a list of InputActionMaps not enough?
        //what's the problem that the stack here is trying to solve?
        /// <summary>
        /// Get the <see cref="InputAction">input actions</see> that are currently active for the user.
        /// </summary>
        public static InputActionStack GetInputActions(this IInputUser user)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            var index = FindUserIndex(user);

            if (index == -1)
            {
                return(null);
            }

            var result = s_AllUserData[index].actionStack;

            if (result == null)
            {
                result = new InputActionStack();
                s_AllUserData[index].actionStack = result;
            }

            return(result);
        }
Beispiel #23
0
 private async Task<IUser> GetUser(IInputUser user, TelegramClient client)
 {
     return (await GetUsers(new List<IInputUser> { user }, client)).First();
 }
Beispiel #24
0
 public static void ResetHaptics(this IInputUser user)
 {
     ////TODO
 }
Beispiel #25
0
 public static void SetUserHandle(this IInputUser user, InputUserHandle?handle)
 {
     throw new NotImplementedException();
 }
Beispiel #26
0
 public static void ResetHaptics(this IInputUser user)
 {
     throw new NotImplementedException();
 }
Beispiel #27
0
 public static void PauseHaptics(this IInputUser user)
 {
     ////TODO
 }
Beispiel #28
0
    public void Users_CanDetectWhenUnassignedDeviceIsUsed()
    {
        var gamepad1 = InputSystem.AddDevice <Gamepad>();
        var gamepad2 = InputSystem.AddDevice <Gamepad>();
        var gamepad3 = InputSystem.AddDevice <Gamepad>();

        var asset = ScriptableObject.CreateInstance <InputActionAsset>();
        var map   = new InputActionMap("map");

        asset.AddActionMap(map);

        var actionAssignedToUser = map.AddAction("action", binding: "<Gamepad>/buttonSouth");

        actionAssignedToUser.Enable();

        var actionNotAssignedToUser = new InputAction(binding: "<Gamepad>/buttonNorth");

        actionNotAssignedToUser.Enable();

        var user = new TestUser();

        InputUser.Add(user);

        // Noise.
        InputUser.Add(new TestUser());
        InputUser.all[1].AssignInputDevice(gamepad3);

        IInputUser   receivedUser    = null;
        InputAction  receivedAction  = null;
        InputControl receivedControl = null;

        InputUser.onUnassignedDeviceUsed +=
            (u, a, c) =>
        {
            Assert.That(receivedUser, Is.Null);
            receivedUser    = u;
            receivedAction  = a;
            receivedControl = c;
        };

        user.AssignInputActions(asset);
        user.AssignInputDevice(gamepad1);

        // No callback if using gamepad1.
        InputSystem.QueueStateEvent(gamepad1, new GamepadState().WithButton(GamepadButton.South));
        InputSystem.Update();

        Assert.That(receivedUser, Is.Null);
        Assert.That(receivedAction, Is.Null);
        Assert.That(receivedControl, Is.Null);

        // Callback when using gamepad2.
        InputSystem.QueueStateEvent(gamepad2, new GamepadState().WithButton(GamepadButton.South));
        InputSystem.Update();

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedAction, Is.SameAs(actionAssignedToUser));
        Assert.That(receivedControl, Is.SameAs(gamepad2.buttonSouth));

        receivedUser    = null;
        receivedControl = null;
        receivedAction  = null;

        // No callback when triggering action not assigned to user.
        InputSystem.QueueStateEvent(gamepad1, new GamepadState().WithButton(GamepadButton.North));
        InputSystem.Update();

        Assert.That(receivedUser, Is.Null);
        Assert.That(receivedAction, Is.Null);
        Assert.That(receivedControl, Is.Null);
    }
Beispiel #29
0
    public void Users_CanBeMonitoredForChanges()
    {
        InputUser.Add(new TestUser()); // Noise.
        InputUser.Add(new TestUser()); // Noise.
        var user = new TestUser();

        IInputUser      receivedUser   = null;
        InputUserChange?receivedChange = null;

        InputUser.onChange +=
            (usr, change) =>
        {
            Assert.That(receivedChange == null);
            receivedUser   = usr;
            receivedChange = change;
        };

        // Added.
        InputUser.Add(user);

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedChange, Is.EqualTo(InputUserChange.Added));

        receivedUser   = null;
        receivedChange = null;

        // NameChanged.
        user.SetUserName("NewName");

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedChange, Is.EqualTo(InputUserChange.NameChanged));

        receivedUser   = null;
        receivedChange = null;

        // HandleChanged.
        user.SetUserHandle(new InputUserHandle("test", 1));

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedChange, Is.EqualTo(InputUserChange.HandleChanged));

        receivedUser   = null;
        receivedChange = null;

        // Same name, no notification.
        user.SetUserName("NewName");

        Assert.That(receivedChange, Is.Null);

        // DevicesChanged.
        var device = InputSystem.AddDevice <Gamepad>();

        user.AssignInputDevice(device);

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedChange, Is.EqualTo(InputUserChange.DevicesChanged));

        receivedUser   = null;
        receivedChange = null;

        // Same device, no notification.
        user.AssignInputDevice(device);

        Assert.That(receivedChange, Is.Null);

        // DevicesChanges, removed.
        user.ClearAssignedInputDevices();

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedChange, Is.EqualTo(InputUserChange.DevicesChanged));

        receivedUser   = null;
        receivedChange = null;

        // ControlSchemeChanged.
        user.AssignControlScheme("gamepad");

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedChange, Is.EqualTo(InputUserChange.ControlSchemeChanged));

        receivedUser   = null;
        receivedChange = null;

        // Same control scheme, no notification.
        user.AssignControlScheme("gamepad");

        Assert.That(receivedChange, Is.Null);

        // Removed.
        InputUser.Remove(user);

        Assert.That(receivedUser, Is.SameAs(user));
        Assert.That(receivedChange, Is.EqualTo(InputUserChange.Removed));

        ////TODO: actions
        ////TODO: activate, passivate
    }