diff --git a/src/Artemis.Core/DefaultTypes/Properties/BoolLayerProperty.cs b/src/Artemis.Core/DefaultTypes/Properties/BoolLayerProperty.cs new file mode 100644 index 000000000..c88ff368f --- /dev/null +++ b/src/Artemis.Core/DefaultTypes/Properties/BoolLayerProperty.cs @@ -0,0 +1,26 @@ +namespace Artemis.Core.DefaultTypes +{ + /// + public class BoolLayerProperty : LayerProperty + { + internal BoolLayerProperty() + { + KeyframesSupported = false; + DataBindingsSupported = false; + } + + /// + /// Implicitly converts an to a + /// + public static implicit operator bool(BoolLayerProperty p) + { + return p.CurrentValue; + } + + /// + protected override void UpdateCurrentValue(float keyframeProgress, float keyframeProgressEased) + { + throw new ArtemisCoreException("Boolean properties do not support keyframes."); + } + } +} \ No newline at end of file diff --git a/src/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs b/src/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs index ebb2c24cf..c18ee6513 100644 --- a/src/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs +++ b/src/Artemis.Plugins.DataModelExpansions.TestData/DataModels/PluginDataModel.cs @@ -21,6 +21,15 @@ namespace Artemis.Plugins.DataModelExpansions.TestData.DataModels // You can even have classes in your datamodel, just don't forget to instantiate them ;) [DataModelProperty(Name = "A class within the datamodel")] public PluginSubDataModel PluginSubDataModel { get; set; } + + public Team Team { get; set; } + public bool IsWinning { get; set; } + } + + public enum Team + { + Blue, + Orange } public class PluginSubDataModel diff --git a/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml.cs b/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml.cs index 325a14c24..491b2e820 100644 --- a/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml.cs +++ b/src/Artemis.UI.Shared/Controls/DraggableFloat.xaml.cs @@ -141,7 +141,7 @@ namespace Artemis.UI.Shared if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift)) stepSize = stepSize * 10; - var value = (float) UltimateRoundingFunction(startValue + stepSize * (x - startX), stepSize, 0.5m); + var value = (float) RoundToNearestOf(startValue + stepSize * (x - startX), stepSize); if (Min != null) value = Math.Max(value, Min.Value); if (Max != null) @@ -217,9 +217,15 @@ namespace Artemis.UI.Shared return float.TryParse(fullText, out _); } - private static decimal UltimateRoundingFunction(decimal amountToRound, decimal nearstOf, decimal fairness) + /// + /// Rounds the provided decimal to the nearest value of x with a given threshold + /// Source: https://stackoverflow.com/a/25922075/5015269 + /// + /// The value to round + /// The value to round down towards + private static decimal RoundToNearestOf(decimal input, decimal nearestOf) { - return Math.Floor(amountToRound / nearstOf + fairness) * nearstOf; + return Math.Floor(input / nearestOf + 0.5m) * nearestOf; } } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs index a49e17d00..691671043 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelListViewModel.cs @@ -106,7 +106,7 @@ namespace Artemis.UI.Shared if (typeViewModel != null) return new DataModelListPropertyViewModel(DataModel, this, PropertyInfo) {DisplayViewModel = typeViewModel}; // For primitives, create a property view model, it may be null that is fine - if (listType.IsPrimitive || listType == typeof(string)) + if (listType.IsPrimitive || listType.IsEnum || listType == typeof(string)) return new DataModelListPropertyViewModel(DataModel, this, PropertyInfo) {ListType = listType}; // For other value types create a child view model if (listType.IsClass || listType.IsStruct()) diff --git a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs index fd5993b27..a683e4d91 100644 --- a/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs +++ b/src/Artemis.UI.Shared/DataModelVisualization/Shared/DataModelVisualizationViewModel.cs @@ -169,11 +169,11 @@ namespace Artemis.UI.Shared IsMatchingFilteredTypes = false; return; } - + if (looseMatch) - IsMatchingFilteredTypes = filteredTypes.Any(t => t.IsCastableFrom(PropertyInfo.PropertyType)); + IsMatchingFilteredTypes = filteredTypes.Any(t => t.IsCastableFrom(PropertyInfo.PropertyType) || t == typeof(Enum) && PropertyInfo.PropertyType.IsEnum); else - IsMatchingFilteredTypes = filteredTypes.Any(t => t == PropertyInfo.PropertyType); + IsMatchingFilteredTypes = filteredTypes.Any(t => t == PropertyInfo.PropertyType || t == typeof(Enum) && PropertyInfo.PropertyType.IsEnum); } public DataModelVisualizationViewModel GetChildForCondition(DisplayConditionPredicate predicate, DisplayConditionSide side) @@ -241,7 +241,7 @@ namespace Artemis.UI.Shared if (typeViewModel != null) return new DataModelPropertyViewModel(DataModel, this, propertyInfo) {DisplayViewModel = typeViewModel, Depth = depth}; // For primitives, create a property view model, it may be null that is fine - if (propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType == typeof(string)) + if (propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType.IsEnum || propertyInfo.PropertyType == typeof(string)) return new DataModelPropertyViewModel(DataModel, this, propertyInfo) {Depth = depth}; if (typeof(IList).IsAssignableFrom(propertyInfo.PropertyType)) return new DataModelListViewModel(DataModel, this, propertyInfo) {Depth = depth}; diff --git a/src/Artemis.UI.Shared/Services/DataModelUIService.cs b/src/Artemis.UI.Shared/Services/DataModelUIService.cs index 84ac900a6..b8af900e1 100644 --- a/src/Artemis.UI.Shared/Services/DataModelUIService.cs +++ b/src/Artemis.UI.Shared/Services/DataModelUIService.cs @@ -179,6 +179,9 @@ namespace Artemis.UI.Shared.Services // Fall back on a VM that supports the type through conversion if (match == null) match = _registeredDataModelEditors.FirstOrDefault(d => d.CompatibleConversionTypes.Contains(propertyType)); + // Lastly try getting an enum VM if the provided type is an enum + if (match == null && propertyType.IsEnum) + match = _registeredDataModelEditors.FirstOrDefault(d => d.SupportedType == typeof(Enum)); if (match != null) { diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputView.xaml b/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputView.xaml new file mode 100644 index 000000000..957369e5e --- /dev/null +++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputView.xaml @@ -0,0 +1,21 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputViewModel.cs b/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputViewModel.cs new file mode 100644 index 000000000..d4f966351 --- /dev/null +++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/BoolDataModelInputViewModel.cs @@ -0,0 +1,12 @@ +using Artemis.Core.DataModelExpansions; +using Artemis.UI.Shared; + +namespace Artemis.UI.DefaultTypes.DataModel.Input +{ + public class BoolDataModelInputViewModel : DataModelInputViewModel + { + public BoolDataModelInputViewModel(DataModelPropertyAttribute targetDescription, bool initialValue) : base(targetDescription, initialValue) + { + } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputView.xaml b/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputView.xaml new file mode 100644 index 000000000..ed763cb5d --- /dev/null +++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputView.xaml @@ -0,0 +1,17 @@ + + + \ No newline at end of file diff --git a/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputViewModel.cs b/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputViewModel.cs new file mode 100644 index 000000000..ec374e67a --- /dev/null +++ b/src/Artemis.UI/DefaultTypes/DataModel/Input/EnumDataModelInputViewModel.cs @@ -0,0 +1,17 @@ +using System; +using Artemis.Core.DataModelExpansions; +using Artemis.UI.Shared; +using Stylet; + +namespace Artemis.UI.DefaultTypes.DataModel.Input +{ + public class EnumDataModelInputViewModel : DataModelInputViewModel + { + public EnumDataModelInputViewModel(DataModelPropertyAttribute targetDescription, Enum initialValue) : base(targetDescription, initialValue) + { + EnumValues = new BindableCollection(EnumUtilities.GetAllValuesAndDescriptions(initialValue.GetType())); + } + + public BindableCollection EnumValues { get; set; } + } +} \ No newline at end of file diff --git a/src/Artemis.UI/DefaultTypes/PropertyInput/BoolPropertyInputView.xaml b/src/Artemis.UI/DefaultTypes/PropertyInput/BoolPropertyInputView.xaml new file mode 100644 index 000000000..3f7941a5b --- /dev/null +++ b/src/Artemis.UI/DefaultTypes/PropertyInput/BoolPropertyInputView.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Artemis.UI/DefaultTypes/PropertyInput/BoolPropertyInputViewModel.cs b/src/Artemis.UI/DefaultTypes/PropertyInput/BoolPropertyInputViewModel.cs new file mode 100644 index 000000000..91be2ffea --- /dev/null +++ b/src/Artemis.UI/DefaultTypes/PropertyInput/BoolPropertyInputViewModel.cs @@ -0,0 +1,15 @@ +using Artemis.Core; +using Artemis.UI.Shared; +using Artemis.UI.Shared.Services; + +namespace Artemis.UI.PropertyInput +{ + public class BoolPropertyInputViewModel : PropertyInputViewModel + { + public BoolPropertyInputViewModel(LayerProperty layerProperty, IProfileEditorService profileEditorService) : base(layerProperty, profileEditorService) + { + } + + public bool IsEnabled => true; + } +} \ No newline at end of file diff --git a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/EditToolViewModel.cs b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/EditToolViewModel.cs index 1a25f5fba..4dc60454c 100644 --- a/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/EditToolViewModel.cs +++ b/src/Artemis.UI/Screens/ProfileEditor/Visualization/Tools/EditToolViewModel.cs @@ -34,7 +34,7 @@ namespace Artemis.UI.Screens.ProfileEditor.Visualization.Tools profileEditorService.SelectedProfileElementUpdated += (sender, args) => Update(); profileEditorService.ProfilePreviewUpdated += (sender, args) => Update(); } - + public SKPath ShapePath { get => _shapePath; diff --git a/src/Artemis.UI/Services/RegistrationService.cs b/src/Artemis.UI/Services/RegistrationService.cs index 7261cf312..738fae7ea 100644 --- a/src/Artemis.UI/Services/RegistrationService.cs +++ b/src/Artemis.UI/Services/RegistrationService.cs @@ -40,6 +40,8 @@ namespace Artemis.UI.Services _dataModelUIService.RegisterDataModelInput(Constants.CorePluginInfo, Constants.IntegralNumberTypes); _dataModelUIService.RegisterDataModelInput(Constants.CorePluginInfo, null); _dataModelUIService.RegisterDataModelInput(Constants.CorePluginInfo, null); + _dataModelUIService.RegisterDataModelInput(Constants.CorePluginInfo, null); + _dataModelUIService.RegisterDataModelInput(Constants.CorePluginInfo, null); _registeredBuiltInDataModelInputs = true; } @@ -57,6 +59,7 @@ namespace Artemis.UI.Services _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo); _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo); _profileEditorService.RegisterPropertyInput(typeof(EnumPropertyInputViewModel<>), Constants.CorePluginInfo); + _profileEditorService.RegisterPropertyInput(Constants.CorePluginInfo); _registeredBuiltInPropertyEditors = true; }