From bfdb3541aaeccf5f3632b451c115b0c0a52979e2 Mon Sep 17 00:00:00 2001 From: Victor Chelaru Date: Tue, 27 Feb 2024 07:58:23 -0700 Subject: [PATCH] Fixed behavior assignment. Improved handling of existing children in the input device selector stack. --- .../Controls/Games/InputDeviceSelector.cs | 44 ++++++++++++++++++- .../DataGeneration/BehaviorGenerator.cs | 9 +++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/InputDeviceSelector.cs b/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/InputDeviceSelector.cs index 7612ca1d2..4b8b28728 100644 --- a/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/InputDeviceSelector.cs +++ b/Engines/Forms/FlatRedBall.Forms/FlatRedBall.Forms.Shared/Controls/Games/InputDeviceSelector.cs @@ -1,14 +1,18 @@ +using FlatRedBall.Forms.Managers; using FlatRedBall.Input; using Gum.Wireframe; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.Linq; namespace FlatRedBall.Forms.Controls.Games { public class InputDeviceSelector : FrameworkElement { + #region Fields/Properties + GraphicalUiElement InputDeviceContainerInstance; public List AllConnectedInputDevices { get; private set; } @@ -29,6 +33,8 @@ public int MaxPlayers List InputDeviceSelectionItemsInternal = new List(); + #endregion + #region Initialize public InputDeviceSelector() : base() @@ -59,6 +65,12 @@ private void DoCommonInitialization() protected override void ReactToVisualChanged() { InputDeviceContainerInstance = this.Visual.GetGraphicalUiElementByName("InputDeviceContainerInstance"); + // If using the built-in instantiation from the runtime, + // the Form association is made before variables are assigned. + // This means that InputDeviceContainerInstance.Children may not + // yet be populated, and will be populated after - when the "initial state" + // is set. Therefore, to handle this case there is also an if-check in Activity + // to make sure there isn't a mismatch. InputDeviceContainerInstance.Children.Clear(); if (!hasAssignedMaxPlayers) @@ -71,9 +83,18 @@ protected override void ReactToVisualChanged() UpdateInputDeviceSelectionItemsCount(); } + FrameworkElementManager.Self.AddFrameworkElement(this); + Visual.RemovedFromGuiManager += HandleRemovedFromGuiManager; + + base.ReactToVisualChanged(); } + private void HandleRemovedFromGuiManager(object sender, EventArgs e) + { + FrameworkElementManager.Self.RemoveFrameworkElement(this); + } + #endregion #region Update in response to changes @@ -128,15 +149,32 @@ private void UpdateInputDeviceSelectionItemsCount() InputDeviceSelectionItemsInternal.Remove(lastItem); InputDeviceContainerInstance.Children.Remove(lastItem.Visual); } + // This can happen if an item is directly added to children (such as loaded from .gumx) + while(InputDeviceContainerInstance.Children.Count > InputDeviceSelectionItemsInternal.Count) + { + for(int i = 0; i < InputDeviceContainerInstance.Children.Count; i++) + { + GraphicalUiElement child = (GraphicalUiElement)InputDeviceContainerInstance.Children[i]; + if(!InputDeviceSelectionItemsInternal.Any(item => item.Visual == child)) + { + InputDeviceContainerInstance.Children.Remove(child); + } + } + } } #endregion List devicesUnjoinedThisFrame = new List(); - public override void Activity() { + // See ReactToVisualChanged for why this is necessary + if(InputDeviceSelectionItemsInternal.Count != MaxPlayers || + InputDeviceContainerInstance.Children.Count != MaxPlayers) + { + UpdateInputDeviceSelectionItemsCount(); + } devicesUnjoinedThisFrame.Clear(); bool DidUnjoin(IInputDevice inputDevice) => @@ -196,6 +234,8 @@ private void HandleJoin(IInputDevice inputDevice) } } + #region ObservableArray Class + public class ObservableArrayIndexChangeArgs { public int Index { get; private set; } @@ -234,4 +274,6 @@ void OnIndexChanged(T oldItem, int index) CollectionChanged?.Invoke(this, new ObservableArrayIndexChangeArgs(index)); } } + + #endregion } \ No newline at end of file diff --git a/FRBDK/Glue/GumPlugin/GumPlugin/DataGeneration/BehaviorGenerator.cs b/FRBDK/Glue/GumPlugin/GumPlugin/DataGeneration/BehaviorGenerator.cs index 00f761bcd..a81dbd93a 100644 --- a/FRBDK/Glue/GumPlugin/GumPlugin/DataGeneration/BehaviorGenerator.cs +++ b/FRBDK/Glue/GumPlugin/GumPlugin/DataGeneration/BehaviorGenerator.cs @@ -14,6 +14,11 @@ public class FormsControlInfo public string BehaviorName; public string ControlName; + public override string ToString() + { + return $"{BehaviorName} -> {ControlName}"; + } + static FormsControlInfo() { List tempList = new List(); @@ -29,8 +34,8 @@ static FormsControlInfo() Add("DialogBoxBehavior", "FlatRedBall.Forms.Controls.Games.DialogBox"); - Add("InputDeviceSelector", "FlatRedBall.Forms.Controls.Games.InputDeviceSelector"); - Add("InputDeviceSelectionItem", "FlatRedBall.Forms.Controls.Games.InputDeviceSelectionItem"); + Add("InputDeviceSelectorBehavior", "FlatRedBall.Forms.Controls.Games.InputDeviceSelector"); + Add("InputDeviceSelectionItemBehavior", "FlatRedBall.Forms.Controls.Games.InputDeviceSelectionItem"); Add("LabelBehavior", "Label");