diff --git a/src/Artemis.Core/Plugins/Abstract/LayerBrushProvider.cs b/src/Artemis.Core/Plugins/Abstract/LayerBrushProvider.cs
index 5a87c0e1d..f44945385 100644
--- a/src/Artemis.Core/Plugins/Abstract/LayerBrushProvider.cs
+++ b/src/Artemis.Core/Plugins/Abstract/LayerBrushProvider.cs
@@ -22,12 +22,12 @@ namespace Artemis.Core.Plugins.Abstract
}
///
- /// A read-only collection of all layer brushes added with
+ /// A read-only collection of all layer brushes added with
///
public ReadOnlyCollection LayerBrushDescriptors => _layerBrushDescriptors.AsReadOnly();
///
- /// Adds a layer brush descriptor for a given layer brush, so that it appears in the UI.
+ /// Registers a layer brush descriptor for a given layer brush, so that it appears in the UI.
/// Note: You do not need to manually remove these on disable
///
/// The type of the layer brush you wish to register
@@ -37,7 +37,7 @@ namespace Artemis.Core.Plugins.Abstract
/// The Material icon to display in the UI, a full reference can be found
/// here
///
- protected void AddLayerBrushDescriptor(string displayName, string description, string icon) where T : BaseLayerBrush
+ protected void RegisterLayerBrushDescriptor(string displayName, string description, string icon) where T : BaseLayerBrush
{
if (!Enabled)
throw new ArtemisPluginException(PluginInfo, "Can only add a layer brush descriptor when the plugin is enabled");
diff --git a/src/Artemis.UI.Shared/Controls/ColorPicker.xaml b/src/Artemis.UI.Shared/Controls/ColorPicker.xaml
index 250f1c1f7..07968179f 100644
--- a/src/Artemis.UI.Shared/Controls/ColorPicker.xaml
+++ b/src/Artemis.UI.Shared/Controls/ColorPicker.xaml
@@ -65,8 +65,6 @@
-
-
[ValueConversion(typeof(Color), typeof(string))]
- internal class ColorToSolidColorConverter : IValueConverter
+ public class ColorToSolidColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
diff --git a/src/Artemis.UI.Shared/Converters/ColorToStringConverter.cs b/src/Artemis.UI.Shared/Converters/ColorToStringConverter.cs
index e01ac78a3..6e431160b 100644
--- a/src/Artemis.UI.Shared/Converters/ColorToStringConverter.cs
+++ b/src/Artemis.UI.Shared/Converters/ColorToStringConverter.cs
@@ -10,7 +10,7 @@ namespace Artemis.UI.Shared.Converters
/// Converts into .
///
[ValueConversion(typeof(Color), typeof(string))]
- internal class ColorToStringConverter : IValueConverter
+ public class ColorToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
diff --git a/src/Artemis.UI.Shared/Converters/SKColorToStringConverter.cs b/src/Artemis.UI.Shared/Converters/SKColorToStringConverter.cs
new file mode 100644
index 000000000..8bd81154b
--- /dev/null
+++ b/src/Artemis.UI.Shared/Converters/SKColorToStringConverter.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Globalization;
+using System.Windows.Data;
+using System.Windows.Media;
+using SkiaSharp;
+
+namespace Artemis.UI.Shared.Converters
+{
+ ///
+ ///
+ /// Converts into .
+ ///
+ [ValueConversion(typeof(Color), typeof(string))]
+ public class SKColorToStringConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return value?.ToString();
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (string.IsNullOrWhiteSpace((string) value))
+ return SKColor.Empty;
+
+ return SKColor.TryParse((string)value, out var color) ? color : SKColor.Empty;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs
new file mode 100644
index 000000000..0f91099df
--- /dev/null
+++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelDisplayViewModel.cs
@@ -0,0 +1,39 @@
+using Stylet;
+
+namespace Artemis.UI.Shared.DataModelVisualization
+{
+ public abstract class DataModelDisplayViewModel : DataModelDisplayViewModel
+ {
+ private T _displayValue;
+
+ public T DisplayValue
+ {
+ get => _displayValue;
+ set
+ {
+ if (!SetAndNotify(ref _displayValue, value)) return;
+ OnDisplayValueUpdated();
+ }
+ }
+
+ protected virtual void OnDisplayValueUpdated()
+ {
+ }
+
+ internal override void UpdateValue(object model)
+ {
+ DisplayValue = model is T value ? value : default;
+ }
+ }
+
+ ///
+ /// For internal use only, implement instead.
+ ///
+ public abstract class DataModelDisplayViewModel : PropertyChangedBase
+ {
+ ///
+ /// Prevents this type being implemented directly, implement instead.
+ ///
+ internal abstract void UpdateValue(object model);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
new file mode 100644
index 000000000..7bc781608
--- /dev/null
+++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelInputViewModel.cs
@@ -0,0 +1,28 @@
+using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
+using Stylet;
+
+namespace Artemis.UI.Shared.DataModelVisualization
+{
+ public abstract class DataModelInputViewModel : DataModelInputViewModel
+ {
+ protected DataModelInputViewModel(DataModelPropertyAttribute description)
+ {
+ Description = description;
+ }
+
+ public DataModelPropertyAttribute Description { get; }
+ internal override object InternalGuard { get; } = null;
+ }
+
+ ///
+ /// For internal use only, implement instead.
+ ///
+ public abstract class DataModelInputViewModel : PropertyChangedBase
+ {
+ ///
+ /// Prevents this type being implemented directly, implement instead.
+ ///
+ // ReSharper disable once UnusedMember.Global
+ internal abstract object InternalGuard { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/DataModelVisualizationRegistration.cs b/src/Artemis.UI.Shared/DataModelVisualization/DataModelVisualizationRegistration.cs
new file mode 100644
index 000000000..6aa9c65f1
--- /dev/null
+++ b/src/Artemis.UI.Shared/DataModelVisualization/DataModelVisualizationRegistration.cs
@@ -0,0 +1,53 @@
+using System;
+using Artemis.Core;
+using Artemis.Core.Plugins.Models;
+using Artemis.UI.Shared.Services;
+
+namespace Artemis.UI.Shared.DataModelVisualization
+{
+ public class DataModelVisualizationRegistration
+ {
+ private readonly IDataModelVisualizationService _dataModelVisualizationService;
+
+ public DataModelVisualizationRegistration(IDataModelVisualizationService dataModelVisualizationService,
+ RegistrationType registrationType,
+ PluginInfo pluginInfo,
+ Type supportedType,
+ Type viewModelType)
+ {
+ _dataModelVisualizationService = dataModelVisualizationService;
+ RegistrationType = registrationType;
+ PluginInfo = pluginInfo;
+ SupportedType = supportedType;
+ ViewModelType = viewModelType;
+
+ if (PluginInfo != Constants.CorePluginInfo)
+ PluginInfo.Instance.PluginDisabled += InstanceOnPluginDisabled;
+ }
+
+ public RegistrationType RegistrationType { get; }
+ public PluginInfo PluginInfo { get; }
+ public Type SupportedType { get; }
+ public Type ViewModelType { get; }
+
+ internal void Unsubscribe()
+ {
+ if (PluginInfo != Constants.CorePluginInfo)
+ PluginInfo.Instance.PluginDisabled -= InstanceOnPluginDisabled;
+ }
+
+ private void InstanceOnPluginDisabled(object sender, EventArgs e)
+ {
+ if (RegistrationType == RegistrationType.Input)
+ _dataModelVisualizationService.RemoveDataModelInput(this);
+ else if (RegistrationType == RegistrationType.Display)
+ _dataModelVisualizationService.RemoveDataModelDisplay(this);
+ }
+ }
+
+ public enum RegistrationType
+ {
+ Display,
+ Input
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/DataModelVisualization/DataModelListViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
similarity index 78%
rename from src/Artemis.UI/DataModelVisualization/DataModelListViewModel.cs
rename to src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
index 885d4ce21..e61194c73 100644
--- a/src/Artemis.UI/DataModelVisualization/DataModelListViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs
@@ -3,18 +3,22 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
+using Artemis.UI.Shared.Services;
using Stylet;
-namespace Artemis.UI.DataModelVisualization
+namespace Artemis.UI.Shared.DataModelVisualization.Shared
{
public class DataModelListViewModel : DataModelVisualizationViewModel
{
+ private readonly IDataModelVisualizationService _dataModelVisualizationService;
private BindableCollection _children;
- private IList _list;
private string _count;
+ private IList _list;
- public DataModelListViewModel(PropertyInfo propertyInfo, DataModelPropertyAttribute propertyDescription, DataModelVisualizationViewModel parent)
+ internal DataModelListViewModel(PropertyInfo propertyInfo, DataModelPropertyAttribute propertyDescription, DataModelVisualizationViewModel parent,
+ IDataModelVisualizationService dataModelVisualizationService)
{
+ _dataModelVisualizationService = dataModelVisualizationService;
PropertyInfo = propertyInfo;
Parent = parent;
PropertyDescription = propertyDescription;
@@ -53,7 +57,7 @@ namespace Artemis.UI.DataModelVisualization
DataModelVisualizationViewModel child;
if (Children.Count <= index)
{
- child = CreateChild(item);
+ child = CreateChild(_dataModelVisualizationService, item);
Children.Add(child);
}
else
diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertyViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertyViewModel.cs
new file mode 100644
index 000000000..cac4d9424
--- /dev/null
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelPropertyViewModel.cs
@@ -0,0 +1,59 @@
+using System.Reflection;
+using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
+
+namespace Artemis.UI.Shared.DataModelVisualization.Shared
+{
+ public class DataModelPropertyViewModel : DataModelVisualizationViewModel
+ {
+ private DataModelDisplayViewModel _displayViewModel;
+ private bool _showNull;
+ private bool _showToString;
+ private bool _showViewModel;
+
+ internal DataModelPropertyViewModel(PropertyInfo propertyInfo, DataModelPropertyAttribute propertyDescription, DataModelVisualizationViewModel parent)
+ {
+ PropertyInfo = propertyInfo;
+ Parent = parent;
+ PropertyDescription = propertyDescription;
+ }
+
+ public DataModelDisplayViewModel DisplayViewModel
+ {
+ get => _displayViewModel;
+ set => SetAndNotify(ref _displayViewModel, value);
+ }
+
+ public bool ShowToString
+ {
+ get => _showToString;
+ set => SetAndNotify(ref _showToString, value);
+ }
+
+ public bool ShowNull
+ {
+ get => _showNull;
+ set => SetAndNotify(ref _showNull, value);
+ }
+
+ public bool ShowViewModel
+ {
+ get => _showViewModel;
+ set => SetAndNotify(ref _showViewModel, value);
+ }
+
+ public override void Update()
+ {
+ if (PropertyInfo != null && Parent?.Model != null)
+ {
+ Model = PropertyInfo.GetValue(Parent.Model);
+ DisplayViewModel?.UpdateValue(Model);
+ }
+
+ ShowToString = Model != null && DisplayViewModel == null;
+ ShowNull = Model == null;
+ ShowViewModel = Model != null && DisplayViewModel != null;
+
+ UpdateListStatus();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/DataModelVisualization/DataModelViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelViewModel.cs
similarity index 70%
rename from src/Artemis.UI/DataModelVisualization/DataModelViewModel.cs
rename to src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelViewModel.cs
index 44868fa40..e93913225 100644
--- a/src/Artemis.UI/DataModelVisualization/DataModelViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelViewModel.cs
@@ -1,21 +1,25 @@
using System.Reflection;
using Artemis.Core.Extensions;
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
+using Artemis.UI.Shared.Services;
using Stylet;
-namespace Artemis.UI.DataModelVisualization
+namespace Artemis.UI.Shared.DataModelVisualization.Shared
{
public class DataModelViewModel : DataModelVisualizationViewModel
{
+ private readonly IDataModelVisualizationService _dataModelVisualizationService;
private BindableCollection _children;
- public DataModelViewModel()
+ internal DataModelViewModel()
{
Children = new BindableCollection();
}
- public DataModelViewModel(PropertyInfo propertyInfo, object model, DataModelPropertyAttribute propertyDescription, DataModelVisualizationViewModel parent)
+ internal DataModelViewModel(PropertyInfo propertyInfo, object model, DataModelPropertyAttribute propertyDescription, DataModelVisualizationViewModel parent,
+ IDataModelVisualizationService dataModelVisualizationService)
{
+ _dataModelVisualizationService = dataModelVisualizationService;
PropertyInfo = propertyInfo;
Model = model;
PropertyDescription = propertyDescription;
@@ -36,7 +40,7 @@ namespace Artemis.UI.DataModelVisualization
Children.Clear();
foreach (var propertyInfo in Model.GetType().GetProperties())
{
- var child = CreateChild(propertyInfo);
+ var child = CreateChild(_dataModelVisualizationService, propertyInfo);
if (child != null)
Children.Add(child);
}
diff --git a/src/Artemis.UI/DataModelVisualization/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
similarity index 75%
rename from src/Artemis.UI/DataModelVisualization/DataModelVisualizationViewModel.cs
rename to src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
index 791b1ca79..1bb7f96b8 100644
--- a/src/Artemis.UI/DataModelVisualization/DataModelVisualizationViewModel.cs
+++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs
@@ -3,20 +3,25 @@ using System.Collections;
using System.Reflection;
using Artemis.Core.Extensions;
using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
+using Artemis.UI.Shared.Services;
using Humanizer;
using Stylet;
-namespace Artemis.UI.DataModelVisualization
+namespace Artemis.UI.Shared.DataModelVisualization.Shared
{
public abstract class DataModelVisualizationViewModel : PropertyChangedBase
{
+ private bool _isListProperty;
+ private string _listDescription;
+ private object _model;
+ private DataModelVisualizationViewModel _parent;
private DataModelPropertyAttribute _propertyDescription;
private PropertyInfo _propertyInfo;
private Type _propertyType;
- private DataModelVisualizationViewModel _parent;
- private object _model;
- private bool _isListProperty;
- private string _listDescription;
+
+ internal DataModelVisualizationViewModel()
+ {
+ }
public DataModelPropertyAttribute PropertyDescription
{
@@ -62,7 +67,7 @@ namespace Artemis.UI.DataModelVisualization
public abstract void Update();
- protected DataModelVisualizationViewModel CreateChild(PropertyInfo propertyInfo)
+ protected DataModelVisualizationViewModel CreateChild(IDataModelVisualizationService dataModelVisualizationService, PropertyInfo propertyInfo)
{
// Skip properties decorated with DataModelIgnore
if (Attribute.IsDefined(propertyInfo, typeof(DataModelIgnoreAttribute)))
@@ -73,11 +78,15 @@ namespace Artemis.UI.DataModelVisualization
if (dataModelPropertyAttribute == null)
dataModelPropertyAttribute = new DataModelPropertyAttribute {Name = propertyInfo.Name.Humanize()};
+ // If a display VM was found, prefer to use that in any case
+ var typeViewModel = dataModelVisualizationService.GetDataModelDisplayViewModel(propertyInfo.PropertyType);
+ if (typeViewModel != null)
+ return new DataModelPropertyViewModel(propertyInfo, dataModelPropertyAttribute, this) {DisplayViewModel = typeViewModel};
// For primitives, create a property view model, it may be null that is fine
if (propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType == typeof(string))
return new DataModelPropertyViewModel(propertyInfo, dataModelPropertyAttribute, this);
if (typeof(IList).IsAssignableFrom(propertyInfo.PropertyType))
- return new DataModelListViewModel(propertyInfo, dataModelPropertyAttribute, this);
+ return new DataModelListViewModel(propertyInfo, dataModelPropertyAttribute, this, dataModelVisualizationService);
// For other value types create a child view model if the value type is not null
if (propertyInfo.PropertyType.IsClass || propertyInfo.PropertyType.IsStruct())
{
@@ -85,22 +94,26 @@ namespace Artemis.UI.DataModelVisualization
if (value == null)
return null;
- return new DataModelViewModel(propertyInfo, value, dataModelPropertyAttribute, this);
+ return new DataModelViewModel(propertyInfo, value, dataModelPropertyAttribute, this, dataModelVisualizationService);
}
return null;
}
- protected DataModelVisualizationViewModel CreateChild(object value)
+ protected DataModelVisualizationViewModel CreateChild(IDataModelVisualizationService dataModelVisualizationService, object value)
{
var dataModelPropertyAttribute = new DataModelPropertyAttribute {Name = "Unknown property"};
+ // If a display VM was found, prefer to use that in any case
+ var typeViewModel = dataModelVisualizationService.GetDataModelDisplayViewModel(value.GetType());
+ if (typeViewModel != null)
+ return new DataModelPropertyViewModel(null, dataModelPropertyAttribute, this) {Model = value, DisplayViewModel = typeViewModel};
// For primitives, create a property view model, it may be null that is fine
if (value.GetType().IsPrimitive || value is string)
return new DataModelPropertyViewModel(null, dataModelPropertyAttribute, this) {Model = value};
// For other value types create a child view model if the value type is not null
if (value.GetType().IsClass || value.GetType().IsStruct())
- return new DataModelViewModel(null, value, dataModelPropertyAttribute, this);
+ return new DataModelViewModel(null, value, dataModelPropertyAttribute, this, dataModelVisualizationService);
return null;
}
diff --git a/src/Artemis.UI.Shared/PropertyInput/PropertyInputRegistration.cs b/src/Artemis.UI.Shared/PropertyInput/PropertyInputRegistration.cs
index 2d00f3074..425c4e827 100644
--- a/src/Artemis.UI.Shared/PropertyInput/PropertyInputRegistration.cs
+++ b/src/Artemis.UI.Shared/PropertyInput/PropertyInputRegistration.cs
@@ -30,15 +30,10 @@ namespace Artemis.UI.Shared.PropertyInput
PluginInfo.Instance.PluginDisabled -= InstanceOnPluginDisabled;
}
- internal void Remove()
- {
- // It'll call Unsubscribe for us
- _profileEditorService.RemovePropertyInput(this);
- }
-
private void InstanceOnPluginDisabled(object sender, EventArgs e)
{
- Remove();
+ // Profile editor service will call Unsubscribe
+ _profileEditorService.RemovePropertyInput(this);
}
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs b/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs
index ab1856305..b2f59f322 100644
--- a/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs
+++ b/src/Artemis.UI.Shared/PropertyInput/PropertyInputViewModel.cs
@@ -5,10 +5,10 @@ using Stylet;
namespace Artemis.UI.Shared.PropertyInput
{
- public abstract class PropertyInputViewModel : ValidatingModelBase, IDisposable
+ public abstract class PropertyInputViewModel : PropertyInputViewModel
{
- private T _inputValue;
private bool _inputDragging;
+ private T _inputValue;
protected PropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService)
{
@@ -30,6 +30,7 @@ namespace Artemis.UI.Shared.PropertyInput
public LayerProperty LayerProperty { get; }
public IProfileEditorService ProfileEditorService { get; }
+ internal override object InternalGuard { get; } = null;
public bool InputDragging
{
@@ -47,12 +48,15 @@ namespace Artemis.UI.Shared.PropertyInput
}
}
- public virtual void Dispose()
+ public override void Dispose()
{
LayerProperty.Updated -= LayerPropertyOnUpdated;
LayerProperty.BaseValueChanged -= LayerPropertyOnUpdated;
+ Dispose(true);
+ GC.SuppressFinalize(this);
}
+
protected virtual void OnInputValueApplied()
{
}
@@ -97,7 +101,6 @@ namespace Artemis.UI.Shared.PropertyInput
Validate();
}
-
#region Event handlers
public void InputDragStarted(object sender, EventArgs e)
@@ -122,4 +125,33 @@ namespace Artemis.UI.Shared.PropertyInput
#endregion
}
+
+ ///
+ /// For internal use only, implement instead.
+ ///
+ public abstract class PropertyInputViewModel : ValidatingModelBase, IDisposable
+ {
+ protected PropertyInputViewModel()
+ {
+ }
+
+ protected PropertyInputViewModel(IModelValidator validator) : base(validator)
+ {
+ }
+
+ ///
+ /// Prevents this type being implemented directly, implement instead.
+ ///
+ // ReSharper disable once UnusedMember.Global
+ internal abstract object InternalGuard { get; }
+
+ public abstract void Dispose();
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs b/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs
new file mode 100644
index 000000000..4810900e5
--- /dev/null
+++ b/src/Artemis.UI.Shared/Services/DataModelVisualizationService.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Artemis.Core.Plugins.Abstract;
+using Artemis.Core.Plugins.Exceptions;
+using Artemis.Core.Plugins.Models;
+using Artemis.Core.Services.Interfaces;
+using Artemis.UI.Shared.DataModelVisualization;
+using Artemis.UI.Shared.DataModelVisualization.Shared;
+using Artemis.UI.Shared.Services.Interfaces;
+using Ninject;
+
+namespace Artemis.UI.Shared.Services
+{
+ public class DataModelVisualizationService : IDataModelVisualizationService
+ {
+ private readonly IDataModelService _dataModelService;
+ private readonly IKernel _kernel;
+ private readonly List _registeredDataModelDisplays;
+ private readonly List _registeredDataModelEditors;
+
+ public DataModelVisualizationService(IDataModelService dataModelService, IKernel kernel)
+ {
+ _dataModelService = dataModelService;
+ _kernel = kernel;
+ _registeredDataModelEditors = new List();
+ _registeredDataModelDisplays = new List();
+ }
+
+ public DataModelViewModel GetMainDataModelVisualization()
+ {
+ var viewModel = new DataModelViewModel();
+ foreach (var dataModelExpansion in _dataModelService.DataModelExpansions)
+ viewModel.Children.Add(new DataModelViewModel(null, dataModelExpansion, dataModelExpansion.DataModelDescription, viewModel, this));
+
+ return viewModel;
+ }
+
+ public DataModelViewModel GetPluginDataModelVisualization(Plugin plugin)
+ {
+ var dataModel = _dataModelService.GetPluginDataModel(plugin);
+ if (dataModel == null)
+ return null;
+
+ var viewModel = new DataModelViewModel();
+ viewModel.Children.Add(new DataModelViewModel(null, dataModel, dataModel.DataModelDescription, viewModel, this));
+ return viewModel;
+ }
+
+ public DataModelVisualizationRegistration RegisterDataModelInput(PluginInfo pluginInfo) where T : DataModelInputViewModel
+ {
+ var viewModelType = typeof(T);
+ lock (_registeredDataModelEditors)
+ {
+ var supportedType = viewModelType.BaseType.GetGenericArguments()[0];
+ var existing = _registeredDataModelEditors.FirstOrDefault(r => r.SupportedType == supportedType);
+ if (existing != null)
+ {
+ if (existing.PluginInfo != pluginInfo)
+ throw new ArtemisPluginException($"Cannot register property editor for type {supportedType.Name} because an editor was already registered by {pluginInfo.Name}");
+ return existing;
+ }
+
+ _kernel.Bind(viewModelType).ToSelf();
+ var registration = new DataModelVisualizationRegistration(this, RegistrationType.Input, pluginInfo, supportedType, viewModelType);
+ _registeredDataModelEditors.Add(registration);
+ return registration;
+ }
+ }
+
+ public DataModelVisualizationRegistration RegisterDataModelDisplay(PluginInfo pluginInfo) where T : DataModelDisplayViewModel
+ {
+ var viewModelType = typeof(T);
+ lock (_registeredDataModelDisplays)
+ {
+ var supportedType = viewModelType.BaseType.GetGenericArguments()[0];
+ var existing = _registeredDataModelDisplays.FirstOrDefault(r => r.SupportedType == supportedType);
+ if (existing != null)
+ {
+ if (existing.PluginInfo != pluginInfo)
+ throw new ArtemisPluginException($"Cannot register property editor for type {supportedType.Name} because an editor was already registered by {pluginInfo.Name}");
+ return existing;
+ }
+
+ _kernel.Bind(viewModelType).ToSelf();
+ var registration = new DataModelVisualizationRegistration(this, RegistrationType.Display, pluginInfo, supportedType, viewModelType);
+ _registeredDataModelDisplays.Add(registration);
+ return registration;
+ }
+ }
+
+ public void RemoveDataModelInput(DataModelVisualizationRegistration registration)
+ {
+ lock (_registeredDataModelEditors)
+ {
+ if (_registeredDataModelEditors.Contains(registration))
+ {
+ registration.Unsubscribe();
+ _registeredDataModelEditors.Remove(registration);
+
+ _kernel.Unbind(registration.ViewModelType);
+ }
+ }
+ }
+
+ public void RemoveDataModelDisplay(DataModelVisualizationRegistration registration)
+ {
+ lock (_registeredDataModelDisplays)
+ {
+ if (_registeredDataModelDisplays.Contains(registration))
+ {
+ registration.Unsubscribe();
+ _registeredDataModelDisplays.Remove(registration);
+
+ _kernel.Unbind(registration.ViewModelType);
+ }
+ }
+ }
+
+ public DataModelDisplayViewModel GetDataModelDisplayViewModel(Type propertyType)
+ {
+ lock (_registeredDataModelDisplays)
+ {
+ var match = _registeredDataModelDisplays.FirstOrDefault(d => d.SupportedType == propertyType);
+ if (match != null)
+ return (DataModelDisplayViewModel) _kernel.Get(match.ViewModelType);
+ return null;
+ }
+ }
+ }
+
+ public interface IDataModelVisualizationService : IArtemisSharedUIService
+ {
+ DataModelViewModel GetMainDataModelVisualization();
+ DataModelViewModel GetPluginDataModelVisualization(Plugin plugin);
+
+ DataModelVisualizationRegistration RegisterDataModelInput(PluginInfo pluginInfo) where T : DataModelInputViewModel;
+ DataModelVisualizationRegistration RegisterDataModelDisplay(PluginInfo pluginInfo) where T : DataModelDisplayViewModel;
+ void RemoveDataModelInput(DataModelVisualizationRegistration registration);
+ void RemoveDataModelDisplay(DataModelVisualizationRegistration registration);
+
+ DataModelDisplayViewModel GetDataModelDisplayViewModel(Type propertyType);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
index 2623b8c32..bc40f25fe 100644
--- a/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/Interfaces/IProfileEditorService.cs
@@ -63,7 +63,15 @@ namespace Artemis.UI.Shared.Services.Interfaces
///
event EventHandler ProfilePreviewUpdated;
- PropertyInputRegistration RegisterPropertyInput(PluginInfo pluginInfo, Type viewModelType);
+ ///
+ /// Registers a new property input view model used in the profile editor for the generic type defined in
+ ///
+ /// Note: Registration will remove itself on plugin disable so you don't have to
+ ///
+ ///
+ ///
+ PropertyInputRegistration RegisterPropertyInput(PluginInfo pluginInfo) where T : PropertyInputViewModel;
+
void RemovePropertyInput(PropertyInputRegistration registration);
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
index ccfcdbe91..f48cd18ef 100644
--- a/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
+++ b/src/Artemis.UI.Shared/Services/ProfileEditorService.cs
@@ -103,6 +103,7 @@ namespace Artemis.UI.Shared.Services
foreach (var baseLayerEffect in folder.LayerEffects)
baseLayerEffect.Update(delta.TotalSeconds);
}
+
foreach (var layer in SelectedProfile.GetAllLayers())
{
layer.OverrideProgress(CurrentTime);
@@ -153,12 +154,9 @@ namespace Artemis.UI.Shared.Services
UpdateProfilePreview();
}
- public PropertyInputRegistration RegisterPropertyInput(PluginInfo pluginInfo, Type viewModelType)
+ public PropertyInputRegistration RegisterPropertyInput(PluginInfo pluginInfo) where T : PropertyInputViewModel
{
- // Bit ugly to do a name comparison but I don't know a nicer way right now
- if (viewModelType.BaseType == null || viewModelType.BaseType.Name != typeof(PropertyInputViewModel<>).Name)
- throw new ArtemisPluginException($"{nameof(viewModelType)} base type must be of type PropertyInputViewModel");
-
+ var viewModelType = typeof(T);
lock (_registeredPropertyEditors)
{
var supportedType = viewModelType.BaseType.GetGenericArguments()[0];
diff --git a/src/Artemis.UI/DataModelVisualization/DataModelPropertyViewModel.cs b/src/Artemis.UI/DataModelVisualization/DataModelPropertyViewModel.cs
deleted file mode 100644
index 49ab9f955..000000000
--- a/src/Artemis.UI/DataModelVisualization/DataModelPropertyViewModel.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using System.Reflection;
-using Artemis.Core.Plugins.Abstract.DataModels.Attributes;
-
-namespace Artemis.UI.DataModelVisualization
-{
- public class DataModelPropertyViewModel : DataModelVisualizationViewModel
- {
- public DataModelPropertyViewModel(PropertyInfo propertyInfo, DataModelPropertyAttribute propertyDescription, DataModelVisualizationViewModel parent)
- {
- PropertyInfo = propertyInfo;
- Parent = parent;
- PropertyDescription = propertyDescription;
- }
-
- public override void Update()
- {
- if (PropertyInfo != null && Parent?.Model != null)
- Model = PropertyInfo.GetValue(Parent.Model);
-
- UpdateListStatus();
- }
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.UI/DataModelVisualization/SKColorDataModelDisplayView.xaml b/src/Artemis.UI/DataModelVisualization/SKColorDataModelDisplayView.xaml
new file mode 100644
index 000000000..2e55a49de
--- /dev/null
+++ b/src/Artemis.UI/DataModelVisualization/SKColorDataModelDisplayView.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/DataModelVisualization/SKColorDataModelDisplayViewModel.cs b/src/Artemis.UI/DataModelVisualization/SKColorDataModelDisplayViewModel.cs
new file mode 100644
index 000000000..cd1eff507
--- /dev/null
+++ b/src/Artemis.UI/DataModelVisualization/SKColorDataModelDisplayViewModel.cs
@@ -0,0 +1,9 @@
+using Artemis.UI.Shared.DataModelVisualization;
+using SkiaSharp;
+
+namespace Artemis.UI.DataModelVisualization
+{
+ public class SKColorDataModelDisplayViewModel : DataModelDisplayViewModel
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/PropertyInput/SKPointPropertyInputViewModel.cs b/src/Artemis.UI/PropertyInput/SKPointPropertyInputViewModel.cs
index 911445cf9..437b790ec 100644
--- a/src/Artemis.UI/PropertyInput/SKPointPropertyInputViewModel.cs
+++ b/src/Artemis.UI/PropertyInput/SKPointPropertyInputViewModel.cs
@@ -4,7 +4,6 @@ using Artemis.Core.Models.Profile.LayerProperties;
using Artemis.UI.Shared.PropertyInput;
using Artemis.UI.Shared.Services.Interfaces;
using FluentValidation;
-// using PropertyChanged;
using SkiaSharp;
using Stylet;
@@ -17,15 +16,12 @@ namespace Artemis.UI.PropertyInput
{
}
- // Since SKPoint is immutable we need to create properties that replace the SKPoint entirely
- // [DependsOn(nameof(InputValue))]
public float X
{
get => InputValue.X;
set => InputValue = new SKPoint(value, Y);
}
- // [DependsOn(nameof(InputValue))]
public float Y
{
get => InputValue.Y;
diff --git a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugView.xaml b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugView.xaml
index ef97ae43f..f26191f39 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugView.xaml
+++ b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugView.xaml
@@ -4,11 +4,11 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Artemis.UI.Screens.Settings.Debug.Tabs"
- xmlns:dataModel="clr-namespace:Artemis.UI.DataModelVisualization"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:converters="clr-namespace:Artemis.UI.Converters"
xmlns:wpf="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:plugins="clr-namespace:Artemis.Core.Plugins.Abstract;assembly=Artemis.Core"
+ xmlns:dataModel="clr-namespace:Artemis.UI.Shared.DataModelVisualization.Shared;assembly=Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" d:DataContext="{d:DesignInstance local:DataModelDebugViewModel}">
@@ -101,6 +101,8 @@
+
+
[]
@@ -112,17 +114,24 @@
Text="{Binding ListDescription}"
ToolTip="{Binding PropertyDescription.Description}"
Visibility="{Binding IsListProperty, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
+
+
+ Visibility="{Binding ShowToString, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
+ Visibility="{Binding ShowNull, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
+
+
diff --git a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
index f4f867571..0a3918226 100644
--- a/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
+++ b/src/Artemis.UI/Screens/Settings/Debug/Tabs/DataModelDebugViewModel.cs
@@ -3,8 +3,9 @@ using System.Linq;
using System.Timers;
using Artemis.Core.Events;
using Artemis.Core.Services.Interfaces;
-using Artemis.UI.DataModelVisualization;
using Artemis.UI.Services;
+using Artemis.UI.Shared.DataModelVisualization.Shared;
+using Artemis.UI.Shared.Services;
using Stylet;
namespace Artemis.UI.Screens.Settings.Debug.Tabs
diff --git a/src/Artemis.UI/Services/DataModelVisualizationService.cs b/src/Artemis.UI/Services/DataModelVisualizationService.cs
deleted file mode 100644
index 8e7e2a54d..000000000
--- a/src/Artemis.UI/Services/DataModelVisualizationService.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-using Artemis.Core.Plugins.Abstract;
-using Artemis.Core.Services.Interfaces;
-using Artemis.UI.DataModelVisualization;
-using Artemis.UI.Services.Interfaces;
-
-namespace Artemis.UI.Services
-{
- public class DataModelVisualizationService : IDataModelVisualizationService
- {
- private readonly IDataModelService _dataModelService;
-
- public DataModelVisualizationService(IDataModelService dataModelService)
- {
- _dataModelService = dataModelService;
- }
-
- public DataModelViewModel GetMainDataModelVisualization()
- {
- var viewModel = new DataModelViewModel();
- foreach (var dataModelExpansion in _dataModelService.DataModelExpansions)
- viewModel.Children.Add(new DataModelViewModel(null, dataModelExpansion, dataModelExpansion.DataModelDescription, viewModel));
-
- return viewModel;
- }
-
- public DataModelViewModel GetPluginDataModelVisualization(Plugin plugin)
- {
- var dataModel = _dataModelService.GetPluginDataModel(plugin);
- if (dataModel == null)
- return null;
-
- var viewModel = new DataModelViewModel();
- viewModel.Children.Add(new DataModelViewModel(null, dataModel, dataModel.DataModelDescription, viewModel));
- return viewModel;
- }
- }
-
- public interface IDataModelVisualizationService : IArtemisUIService
- {
- DataModelViewModel GetMainDataModelVisualization();
- DataModelViewModel GetPluginDataModelVisualization(Plugin plugin);
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.UI/Services/DebugService.cs b/src/Artemis.UI/Services/DebugService.cs
index 21e143692..54f02c062 100644
--- a/src/Artemis.UI/Services/DebugService.cs
+++ b/src/Artemis.UI/Services/DebugService.cs
@@ -1,6 +1,10 @@
-using System.Windows;
+using System;
+using System.Windows;
+using Artemis.Core;
+using Artemis.UI.DataModelVisualization;
using Artemis.UI.Screens.Settings.Debug;
using Artemis.UI.Services.Interfaces;
+using Artemis.UI.Shared.Services;
using MaterialDesignExtensions.Controls;
using Ninject;
using Stylet;
@@ -11,12 +15,21 @@ namespace Artemis.UI.Services
{
private readonly IKernel _kernel;
private readonly IWindowManager _windowManager;
+ private readonly IDataModelVisualizationService _dataModelVisualizationService;
private DebugViewModel _debugViewModel;
- public DebugService(IKernel kernel, IWindowManager windowManager)
+ public DebugService(IKernel kernel, IWindowManager windowManager, IDataModelVisualizationService dataModelVisualizationService)
{
_kernel = kernel;
_windowManager = windowManager;
+ _dataModelVisualizationService = dataModelVisualizationService;
+
+ RegisterBuiltInDataModelDisplays();
+ }
+
+ private void RegisterBuiltInDataModelDisplays()
+ {
+ _dataModelVisualizationService.RegisterDataModelDisplay(Constants.CorePluginInfo);
}
public void ShowDebugger()
diff --git a/src/Artemis.UI/Services/LayerEditorService.cs b/src/Artemis.UI/Services/LayerEditorService.cs
index c9dc4c7d3..f17726205 100644
--- a/src/Artemis.UI/Services/LayerEditorService.cs
+++ b/src/Artemis.UI/Services/LayerEditorService.cs
@@ -141,13 +141,13 @@ namespace Artemis.UI.Services
private void RegisterBuiltInPropertyEditors()
{
- _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(BrushPropertyInputViewModel));
- _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(ColorGradientPropertyInputViewModel));
- _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(FloatPropertyInputViewModel));
- _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(IntPropertyInputViewModel));
- _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKColorPropertyInputViewModel));
- _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKPointPropertyInputViewModel));
- _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo, typeof(SKSizePropertyInputViewModel));
+ _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo);
+ _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo);
+ _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo);
+ _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo);
+ _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo);
+ _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo);
+ _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo);
}
}
}
\ No newline at end of file
diff --git a/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrushProvider.cs b/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrushProvider.cs
index 814843b31..a7a18eb7f 100644
--- a/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrushProvider.cs
+++ b/src/Plugins/Artemis.Plugins.LayerBrushes.Color/ColorBrushProvider.cs
@@ -6,7 +6,7 @@ namespace Artemis.Plugins.LayerBrushes.Color
{
public override void EnablePlugin()
{
- AddLayerBrushDescriptor("Color", "A brush supporting solid colors and multiple types of gradients", "Brush");
+ RegisterLayerBrushDescriptor("Color", "A brush supporting solid colors and multiple types of gradients", "Brush");
}
public override void DisablePlugin()
diff --git a/src/Plugins/Artemis.Plugins.LayerBrushes.ColorRgbNet/RgbNetColorBrushProvider.cs b/src/Plugins/Artemis.Plugins.LayerBrushes.ColorRgbNet/RgbNetColorBrushProvider.cs
index fe71aae4d..2c511a8e5 100644
--- a/src/Plugins/Artemis.Plugins.LayerBrushes.ColorRgbNet/RgbNetColorBrushProvider.cs
+++ b/src/Plugins/Artemis.Plugins.LayerBrushes.ColorRgbNet/RgbNetColorBrushProvider.cs
@@ -15,8 +15,8 @@ namespace Artemis.Plugins.LayerBrushes.ColorRgbNet
public override void EnablePlugin()
{
- _profileEditorService.RegisterPropertyInput(PluginInfo, typeof(StringPropertyInputViewModel));
- AddLayerBrushDescriptor("RGB.NET Color", "A RGB.NET based color", "Brush");
+ _profileEditorService.RegisterPropertyInput(PluginInfo);
+ RegisterLayerBrushDescriptor("RGB.NET Color", "A RGB.NET based color", "Brush");
}
public override void DisablePlugin()
diff --git a/src/Plugins/Artemis.Plugins.LayerBrushes.Noise/NoiseBrushProvider.cs b/src/Plugins/Artemis.Plugins.LayerBrushes.Noise/NoiseBrushProvider.cs
index ba643df02..9bc4017f9 100644
--- a/src/Plugins/Artemis.Plugins.LayerBrushes.Noise/NoiseBrushProvider.cs
+++ b/src/Plugins/Artemis.Plugins.LayerBrushes.Noise/NoiseBrushProvider.cs
@@ -6,7 +6,7 @@ namespace Artemis.Plugins.LayerBrushes.Noise
{
public override void EnablePlugin()
{
- AddLayerBrushDescriptor("Noise", "A brush of that shows an animated random noise", "ScatterPlot");
+ RegisterLayerBrushDescriptor("Noise", "A brush of that shows an animated random noise", "ScatterPlot");
}
public override void DisablePlugin()
diff --git a/src/Plugins/Artemis.Plugins.Modules.General/GeneralDataModel.cs b/src/Plugins/Artemis.Plugins.Modules.General/GeneralDataModel.cs
index 4e53c6a3b..a5a397bf3 100644
--- a/src/Plugins/Artemis.Plugins.Modules.General/GeneralDataModel.cs
+++ b/src/Plugins/Artemis.Plugins.Modules.General/GeneralDataModel.cs
@@ -20,6 +20,8 @@ namespace Artemis.Plugins.Modules.General
[DataModelProperty(Name = "A test boolean", Description = "This is a test boolean that's not of any use outside testing!")]
public bool TestBoolean { get; set; }
+ public SKColor TestColor { get; set; } = new SKColor(221, 21, 152);
+
[DataModelProperty(Name = "Player info", Description = "[TEST] Contains information about the player")]
public PlayerInfo PlayerInfo { get; set; }