A game framework written with osu! in mind.
at master 4.3 kB view raw
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence. 2// See the LICENCE file in the repository root for full licence text. 3 4using System.Collections.Generic; 5using System.Collections.Immutable; 6using osu.Framework.Input.StateChanges.Events; 7using osu.Framework.Input.States; 8 9namespace osu.Framework.Input.StateChanges 10{ 11 /// <summary> 12 /// An abstract base class of an <see cref="IInput"/> which denotes a list of button state changes (pressed or released). 13 /// </summary> 14 /// <typeparam name="TButton">The type of button.</typeparam> 15 public abstract class ButtonInput<TButton> : IInput 16 where TButton : struct 17 { 18 public ImmutableArray<ButtonInputEntry<TButton>> Entries; 19 20 protected ButtonInput(IEnumerable<ButtonInputEntry<TButton>> entries) 21 { 22 Entries = entries.ToImmutableArray(); 23 } 24 25 /// <summary> 26 /// Creates a <see cref="ButtonInput{TButton}"/> with a single <typeparamref name="TButton"/> state. 27 /// </summary> 28 /// <param name="button">The <typeparamref name="TButton"/> to add.</param> 29 /// <param name="isPressed">The state of <paramref name="button"/>.</param> 30 protected ButtonInput(TButton button, bool isPressed) 31 { 32 Entries = ImmutableArray.Create(new ButtonInputEntry<TButton>(button, isPressed)); 33 } 34 35 /// <summary> 36 /// Creates a <see cref="ButtonInput{TButton}"/> from the difference of two <see cref="ButtonStates{TButton}"/>. 37 /// </summary> 38 /// <remarks> 39 /// Buttons that are pressed in <paramref name="previous"/> and not pressed in <paramref name="current"/> will be listed as <see cref="ButtonStateChangeKind.Released"/>. 40 /// Buttons that are not pressed in <paramref name="previous"/> and pressed in <paramref name="current"/> will be listed as <see cref="ButtonStateChangeKind.Pressed"/>. 41 /// </remarks> 42 /// <param name="current">The newer <see cref="ButtonStates{TButton}"/>.</param> 43 /// <param name="previous">The older <see cref="ButtonStates{TButton}"/>.</param> 44 protected ButtonInput(ButtonStates<TButton> current, ButtonStates<TButton> previous) 45 { 46 var difference = (current ?? new ButtonStates<TButton>()).EnumerateDifference(previous ?? new ButtonStates<TButton>()); 47 48 var builder = ImmutableArray.CreateBuilder<ButtonInputEntry<TButton>>(difference.Released.Length + difference.Pressed.Length); 49 50 foreach (var button in difference.Released) 51 builder.Add(new ButtonInputEntry<TButton>(button, false)); 52 foreach (var button in difference.Pressed) 53 builder.Add(new ButtonInputEntry<TButton>(button, true)); 54 55 Entries = builder.MoveToImmutable(); 56 } 57 58 /// <summary> 59 /// Retrieves the <see cref="ButtonStates{TButton}"/> from an <see cref="InputState"/>. 60 /// </summary> 61 protected abstract ButtonStates<TButton> GetButtonStates(InputState state); 62 63 /// <summary> 64 /// Create a <typeparamref name="TButton"/> state change event. 65 /// </summary> 66 /// <param name="state">The <see cref="InputState"/> which changed.</param> 67 /// <param name="button">The <typeparamref name="TButton"/> that changed.</param> 68 /// <param name="kind">The type of change that occurred on <paramref name="button"/>.</param> 69 protected virtual ButtonStateChangeEvent<TButton> CreateEvent(InputState state, TButton button, ButtonStateChangeKind kind) => new ButtonStateChangeEvent<TButton>(state, this, button, kind); 70 71 public virtual void Apply(InputState state, IInputStateChangeHandler handler) 72 { 73 if (Entries.Length == 0) 74 return; 75 76 var buttonStates = GetButtonStates(state); 77 78 foreach (var entry in Entries) 79 { 80 if (buttonStates.SetPressed(entry.Button, entry.IsPressed)) 81 { 82 var buttonStateChange = CreateEvent(state, entry.Button, entry.IsPressed ? ButtonStateChangeKind.Pressed : ButtonStateChangeKind.Released); 83 handler.HandleInputStateChange(buttonStateChange); 84 } 85 } 86 } 87 } 88}