diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs index ef1261628..55da596fa 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionList.cs @@ -13,6 +13,7 @@ namespace Artemis.Core public class DataModelConditionList : DataModelConditionPart { private bool _disposed; + private bool _reinitializing; /// /// Creates a new instance of the class @@ -83,6 +84,7 @@ namespace Artemis.Core ListPath?.Dispose(); ListPath = path != null ? new DataModelPath(path) : null; + SubscribeToListPath(); // Remove the old root group that was tied to the old data model while (Children.Any()) @@ -143,6 +145,10 @@ namespace Artemis.Core internal override void Save() { + // Don't save an invalid state + if (ListPath != null && !ListPath.IsValid) + return; + // Target list ListPath?.Save(); Entity.ListPath = ListPath?.Entity; @@ -164,6 +170,9 @@ namespace Artemis.Core internal void Initialize() { + while (Children.Any()) + RemoveChild(Children[0]); + if (Entity.ListPath == null) return; @@ -175,6 +184,7 @@ namespace Artemis.Core return; ListPath = listPath; + SubscribeToListPath(); if (ListPath.IsValid) { ListType = listType.GetGenericArguments()[0]; @@ -187,7 +197,7 @@ namespace Artemis.Core } // There should only be one child and it should be a group - if (Entity.Children.SingleOrDefault() is DataModelConditionGroupEntity rootGroup) + if (Entity.Children.FirstOrDefault() is DataModelConditionGroupEntity rootGroup) { AddChild(new DataModelConditionGroup(this, rootGroup)); } @@ -197,6 +207,39 @@ namespace Artemis.Core AddChild(new DataModelConditionGroup(this)); } } + + private void SubscribeToListPath() + { + if (ListPath == null) return; + ListPath.PathValidated += ListPathOnPathValidated; + ListPath.PathInvalidated += ListPathOnPathInvalidated; + } + + #region Event handlers + + private void ListPathOnPathValidated(object? sender, EventArgs e) + { + if (_reinitializing) + return; + + _reinitializing = true; + ListPath?.Dispose(); + Initialize(); + _reinitializing = false; + } + + private void ListPathOnPathInvalidated(object? sender, EventArgs e) + { + if (_reinitializing) + return; + + _reinitializing = true; + ListPath?.Dispose(); + Initialize(); + _reinitializing = false; + } + + #endregion } /// diff --git a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionPredicate.cs b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionPredicate.cs index c37ebf1c1..d7b107c74 100644 --- a/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionPredicate.cs +++ b/src/Artemis.Core/Models/Profile/Conditions/DataModelConditionPredicate.cs @@ -205,6 +205,10 @@ namespace Artemis.Core internal override void Save() { + // Don't save an invalid state + if (LeftPath != null && !LeftPath.IsValid || RightPath != null && !RightPath.IsValid) + return; + Entity.PredicateType = (int) PredicateType; LeftPath?.Save(); diff --git a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs index 78cc14677..1126b8efd 100644 --- a/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs +++ b/src/Artemis.Core/Models/Profile/DataModel/DataModelPath.cs @@ -14,9 +14,9 @@ namespace Artemis.Core /// public class DataModelPath : IStorageModel, IDisposable { - private bool _disposed; private readonly LinkedList _segments; private Expression>? _accessorLambda; + private bool _disposed; /// /// Creates a new instance of the class pointing directly to the target @@ -59,7 +59,7 @@ namespace Artemis.Core /// The path to base the new instance on public DataModelPath(DataModelPath dataModelPath) { - if (dataModelPath == null) + if (dataModelPath == null) throw new ArgumentNullException(nameof(dataModelPath)); Target = dataModelPath.Target; @@ -188,6 +188,8 @@ namespace Artemis.Core _accessorLambda = null; Accessor = null; + + OnPathInvalidated(); } internal void Initialize() @@ -239,6 +241,9 @@ namespace Artemis.Core ), parameter ); + + if (IsValid) + OnPathValidated(); } private void SubscribeToDataModelStore() @@ -307,5 +312,29 @@ namespace Artemis.Core } #endregion + + #region Events + + /// + /// Occurs whenever the path becomes invalid + /// + public event EventHandler PathInvalidated; + + /// + /// Occurs whenever the path becomes valid + /// + public event EventHandler PathValidated; + + protected virtual void OnPathValidated() + { + PathValidated?.Invoke(this, EventArgs.Empty); + } + + protected virtual void OnPathInvalidated() + { + PathInvalidated?.Invoke(this, EventArgs.Empty); + } + + #endregion } } \ No newline at end of file diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index 8e5e54dab..824649181 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -166,8 +166,8 @@ namespace Artemis.Core.Services _frameStopWatch.Restart(); lock (_dataModelExpansions) { - // Update all active modules - foreach (BaseDataModelExpansion dataModelExpansion in _dataModelExpansions) + // Update all active modules, check Enabled status because it may go false before before the _dataModelExpansions list is updated + foreach (BaseDataModelExpansion dataModelExpansion in _dataModelExpansions.Where(e => e.Enabled)) dataModelExpansion.Update(args.DeltaTime); } diff --git a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupView.xaml b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupView.xaml index 5a0512ba4..56350154b 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupView.xaml +++ b/src/Artemis.UI/Screens/ProfileEditor/Conditions/DataModelConditionGroupView.xaml @@ -146,7 +146,7 @@ - +