diff --git a/Engines/FlatRedBallXNA/FlatRedBall/FlatRedBallShared.projitems b/Engines/FlatRedBallXNA/FlatRedBall/FlatRedBallShared.projitems
index 90a59f718..70f0785c7 100644
--- a/Engines/FlatRedBallXNA/FlatRedBall/FlatRedBallShared.projitems
+++ b/Engines/FlatRedBallXNA/FlatRedBall/FlatRedBallShared.projitems
@@ -303,6 +303,7 @@
+
diff --git a/Engines/FlatRedBallXNA/FlatRedBall/Utilities/TaskHelper.cs b/Engines/FlatRedBallXNA/FlatRedBall/Utilities/TaskHelper.cs
new file mode 100644
index 000000000..83da504e0
--- /dev/null
+++ b/Engines/FlatRedBallXNA/FlatRedBall/Utilities/TaskHelper.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace FlatRedBall.Utilities
+{
+ public static class TaskHelper
+ {
+ public static async Task InSequence(params Func[] tasks)
+ {
+ foreach(var task in tasks)
+ {
+ await task();
+ }
+ }
+
+ public static async Task InSequence(params Task[] tasks)
+ {
+ foreach(var task in tasks)
+ {
+ await task;
+ }
+ }
+ }
+}
diff --git a/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/PlayerJoinView.cs b/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/PlayerJoinView.cs
index f50ec901e..917f11856 100644
--- a/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/PlayerJoinView.cs
+++ b/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/PlayerJoinView.cs
@@ -60,7 +60,19 @@ public ReadOnlyCollection PlayerJoinViewItems
public bool IsSubscribedToGamepadEvents { get; private set; }
- public JoinStyle JoinStyle { get; set; } = JoinStyle.AnyConnectedInput;
+ JoinStyle joinStyle = JoinStyle.AnyConnectedInput;
+ public JoinStyle JoinStyle
+ {
+ get => joinStyle;
+ set
+ {
+ joinStyle = value;
+ for (int i = 0; i < PlayerJoinViewItems.Count; i++)
+ {
+ UpdateConnectedJoinedStateForIndex(i, true);
+ }
+ }
+ }
#endregion
@@ -197,35 +209,64 @@ private void UpdateConnectedJoinedStateForIndex(int index, bool force)
{
var item = PlayerJoinViewItemsInternal[index];
- var isConnected = index <= InputManager.Xbox360GamePads.Length &&
- InputManager.Xbox360GamePads[index].IsConnected;
+ var isConnected = false;
- if(isConnected)
+ if(JoinStyle == JoinStyle.ExplicitlyAssignedInput)
{
- var gamepad = InputManager.Xbox360GamePads[index];
- item.InputDevice = gamepad;
+ isConnected = item.InputDevice != null;
+
+ if(item.InputDevice is Xbox360GamePad gamepad)
+ {
+ isConnected = gamepad.IsConnected;
#if !UWP && !XNA4_OLD && !FNA
- item.ControllerDisplayName = gamepad.Capabilities.DisplayName;
+
+ item.ControllerDisplayName = gamepad.Capabilities.DisplayName;
#endif
- item.ConnectedJoinedState = ConnectedJoinedState.Connected;
- item.GamepadLayout = gamepad.GamepadLayout;
- }
- else if(item.IsUsingKeyboardAsBackup)
- {
- item.ConnectedJoinedState = ConnectedJoinedState.Connected;
- item.InputDevice = InputManager.Keyboard;
- item.ControllerDisplayName = KeyboardName; // should it be something else? Localized? Need to think about this...
+ item.GamepadLayout = gamepad.GamepadLayout;
+
+ }
+ else if(item.InputDevice is FlatRedBall.Input.Keyboard)
+ {
+ isConnected = true;
+ item.ControllerDisplayName = KeyboardName;
+ item.GamepadLayout = GamepadLayout.Keyboard;
+ }
- item.GamepadLayout = GamepadLayout.Keyboard;
}
else
{
- item.ConnectedJoinedState = ConnectedJoinedState.NotConnected;
- item.InputDevice = null;
- item.GamepadLayout = GamepadLayout.Unknown;
+ isConnected = index <= InputManager.Xbox360GamePads.Length &&
+ InputManager.Xbox360GamePads[index].IsConnected;
+
+ if(isConnected)
+ {
+ var gamepad = InputManager.Xbox360GamePads[index];
+ item.InputDevice = gamepad;
+ #if !UWP && !XNA4_OLD && !FNA
+ item.ControllerDisplayName = gamepad.Capabilities.DisplayName;
+ #endif
+ item.ConnectedJoinedState = ConnectedJoinedState.Connected;
+ item.GamepadLayout = gamepad.GamepadLayout;
+ }
+ else if(item.IsUsingKeyboardAsBackup)
+ {
+ item.ConnectedJoinedState = ConnectedJoinedState.Connected;
+ item.InputDevice = InputManager.Keyboard;
+ item.ControllerDisplayName = KeyboardName; // should it be something else? Localized? Need to think about this...
+
+ item.GamepadLayout = GamepadLayout.Keyboard;
+ }
+ else
+ {
+ item.ConnectedJoinedState = ConnectedJoinedState.NotConnected;
+ item.InputDevice = null;
+ item.GamepadLayout = GamepadLayout.Unknown;
+ }
}
+
+
if (force)
{
item.ForceUpdateState();
diff --git a/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/PlayerJoinViewItem.cs b/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/PlayerJoinViewItem.cs
index 251f38d8b..8e5a7a297 100644
--- a/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/PlayerJoinViewItem.cs
+++ b/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/PlayerJoinViewItem.cs
@@ -134,7 +134,17 @@ protected override void UpdateState()
{
if(InputDevice != null)
{
- ControllerDisplayName = PlayerJoinView.KeyboardName;
+ if(InputDevice is Keyboard)
+ {
+ ControllerDisplayName = PlayerJoinView.KeyboardName;
+ }
+ else if(InputDevice is Xbox360GamePad gamepad)
+ {
+#if !UWP && !XNA4_OLD && !FNA
+
+ ControllerDisplayName = gamepad.Capabilities.DisplayName;
+#endif
+ }
}
else if(this.ConnectedJoinedState == ConnectedJoinedState.NotConnected && IsUsingKeyboardAsBackup)
{
diff --git a/FRBDK/Glue/GumPlugin/GumPlugin/CodeGeneration/SpriteCodeGenerator.cs b/FRBDK/Glue/GumPlugin/GumPlugin/CodeGeneration/SpriteCodeGenerator.cs
index a44478c63..afe9d1219 100644
--- a/FRBDK/Glue/GumPlugin/GumPlugin/CodeGeneration/SpriteCodeGenerator.cs
+++ b/FRBDK/Glue/GumPlugin/GumPlugin/CodeGeneration/SpriteCodeGenerator.cs
@@ -96,6 +96,10 @@ private static void GeneratePlayAnimationsAsync(ICodeBlock classBodyBlock)
foreachBlock.Line("sprite.TimeIntoAnimation = 0;");
foreachBlock.Line("sprite.CurrentFrameIndex = 0;");
foreachBlock.Line("sprite.UpdateToCurrentAnimationFrame();");
+
+ foreachBlock.If("sprite.CurrentChain == null")
+ .Line("throw new System.InvalidOperationException($\"Could not find the animation {animation}\");");
+
foreachBlock.Line("// subtract second difference to prevent it from looping once if it happens to fall mid-frame");
foreachBlock.Line("// Due to frame order, we need to delay one frame less, and multiply by 1.1 to fix possible accuracy issues");
foreachBlock.Line("await FlatRedBall.TimeManager.DelaySeconds(sprite.CurrentChain.TotalLength - FlatRedBall.TimeManager.SecondDifference * 1.1f);");