Skip to content

Commit

Permalink
Added a public Combinations collection and associated constructor to …
Browse files Browse the repository at this point in the history
…Keybind
  • Loading branch information
Ellpeck committed Jul 16, 2024
1 parent fa60b5e commit b2dd81e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Jump to version:
### MLEM
Additions
- **Added the ability for formatted (tokenized) strings to be drawn with custom rotation, origin and flipping**
- **Added a public Combinations collection and associated constructor to Keybind**
- Added a RectangleF.FromCorners overload that accepts points
- Added indexers and Count to SpriteAnimation and SpriteAnimationGroup

Expand Down
40 changes: 30 additions & 10 deletions MLEM/Input/Keybind.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;

Expand All @@ -20,27 +21,43 @@ public class Keybind : IComparable<Keybind>, IComparable {
private static readonly Combination[] EmptyCombinations = new Combination[0];
private static readonly GenericInput[] EmptyInputs = new GenericInput[0];

/// <summary>
/// A read-only collection containing all combinations that this keybind has.
/// This property is serializable using the <see cref="DataMemberAttribute"/>.
/// </summary>
[DataMember]
private Combination[] combinations = Keybind.EmptyCombinations;
public readonly IList<Combination> Combinations;

private readonly List<Combination> combinations = new List<Combination>();

/// <summary>
/// Creates a new keybind and adds the given key and modifiers using <see cref="Add(MLEM.Input.GenericInput,MLEM.Input.GenericInput[])"/>
/// </summary>
/// <param name="key">The key to be pressed.</param>
/// <param name="modifiers">The modifier keys that have to be held down.</param>
public Keybind(GenericInput key, params GenericInput[] modifiers) {
public Keybind(GenericInput key, params GenericInput[] modifiers) : this() {
this.Add(key, modifiers);
}

/// <inheritdoc cref="Keybind(GenericInput, GenericInput[])"/>
public Keybind(GenericInput key, ModifierKey modifier) {
public Keybind(GenericInput key, ModifierKey modifier) : this() {
this.Add(key, modifier);
}

/// <summary>
/// Creates a new keybind from the given set of <paramref name="combinations"/>. This constructor can be used when manually serializing and deserializing a keybind's <see cref="Combinations"/>.
/// </summary>
/// <param name="combinations">The combinations to add.</param>
public Keybind(IList<Combination> combinations) : this() {
this.combinations.AddRange(combinations);
}

/// <summary>
/// Creates a new keybind with no default combinations
/// </summary>
public Keybind() {}
public Keybind() {
this.Combinations = new ReadOnlyCollection<Combination>(this.combinations);
}

/// <summary>
/// Adds a new key combination to this keybind that can optionally be pressed for the keybind to trigger.
Expand All @@ -58,7 +75,7 @@ public Keybind Add(GenericInput key, params GenericInput[] modifiers) {
/// <param name="combination">The combination to add.</param>
/// <returns>This keybind, for chaining</returns>
public Keybind Add(Combination combination) {
this.combinations = this.combinations.Append(combination).ToArray();
this.combinations.Add(combination);
return this;
}

Expand Down Expand Up @@ -87,7 +104,7 @@ public Keybind Insert(int index, GenericInput key, params GenericInput[] modifie
/// <param name="combination">The combination to insert.</param>
/// <returns>This keybind, for chaining.</returns>
public Keybind Insert(int index, Combination combination) {
this.combinations = this.combinations.Take(index).Append(combination).Concat(this.combinations.Skip(index)).ToArray();
this.combinations.Insert(index, combination);
return this;
}

Expand All @@ -103,7 +120,7 @@ public Keybind Insert(int index, GenericInput key, ModifierKey modifier) {
/// </summary>
/// <returns>This keybind, for chaining</returns>
public Keybind Clear() {
this.combinations = Keybind.EmptyCombinations;
this.combinations.Clear();
return this;
}

Expand All @@ -113,7 +130,10 @@ public Keybind Clear() {
/// <param name="predicate">The predicate to match against</param>
/// <returns>This keybind, for chaining</returns>
public Keybind Remove(Func<Combination, int, bool> predicate) {
this.combinations = this.combinations.Where((c, i) => !predicate(c, i)).ToArray();
// we can't use RemoveAll here because it doesn't provide an index
var keep = this.combinations.Where((c, i) => !predicate(c, i)).ToArray();
this.combinations.Clear();
this.combinations.AddRange(keep);
return this;
}

Expand All @@ -124,7 +144,7 @@ public Keybind Remove(Func<Combination, int, bool> predicate) {
/// <param name="other">The keybind to copy from</param>
/// <returns>This keybind, for chaining</returns>
public Keybind CopyFrom(Keybind other) {
this.combinations = this.combinations.Concat(other.combinations).ToArray();
this.combinations.AddRange(other.combinations);
return this;
}

Expand Down Expand Up @@ -285,7 +305,7 @@ public IEnumerable<Combination> GetCombinations() {
/// <param name="combination">The combination, or default if this method returns false.</param>
/// <returns>Whether the combination could be successfully retrieved or the index was out of bounds of this keybind's combination collection.</returns>
public bool TryGetCombination(int index, out Combination combination) {
if (index >= 0 && index < this.combinations.Length) {
if (index >= 0 && index < this.combinations.Count) {
combination = this.combinations[index];
return true;
} else {
Expand Down

1 comment on commit b2dd81e

@Ellpeck
Copy link
Owner Author

@Ellpeck Ellpeck commented on b2dd81e Jul 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

realizing now that this impl kinda sucks bc of readonly list serialization. it should really be

  • just the combinations array being a public get, private set property
  • the constructor accepting an array that gets copied into the current combination using copyfrom
  • this way, the potentially breaking change would only be combinations now being uppercase
  • profit

Please sign in to comment.