diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index cb6ee3990..c9319d4da 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -253,9 +253,6 @@ Code - - - @@ -278,8 +275,11 @@ - - + + + + + @@ -324,6 +324,7 @@ True True + True @@ -519,6 +520,7 @@ + diff --git a/Artemis/Artemis/Components/Abstract/LayerComponent.cs b/Artemis/Artemis/Components/Abstract/LayerComponent.cs deleted file mode 100644 index c2b224c61..000000000 --- a/Artemis/Artemis/Components/Abstract/LayerComponent.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using Artemis.Models; -using Artemis.Models.Interfaces; - -namespace Artemis.Components.Abstract -{ - public abstract class LayerComponent - { - public string Name { get; set; } - public List ConditionModels { get; set; } - - public bool ConditionsMet(IGameDataModel dataModel) - { - return ConditionModels.All(cm => cm.ConditionMet(dataModel)); - } - - public abstract void Draw(Graphics g); - } -} \ No newline at end of file diff --git a/Artemis/Artemis/Components/Layer.cs b/Artemis/Artemis/Components/Layer.cs deleted file mode 100644 index a1beb3b86..000000000 --- a/Artemis/Artemis/Components/Layer.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Drawing; -using Artemis.Components.Abstract; - -namespace Artemis.Components -{ - public class Layer : LayerComponent - { - public override void Draw(Graphics g) - { - // Read properties and draw accordingly - } - } -} \ No newline at end of file diff --git a/Artemis/Artemis/Components/LayerComposite.cs b/Artemis/Artemis/Components/LayerComposite.cs deleted file mode 100644 index 775a707c5..000000000 --- a/Artemis/Artemis/Components/LayerComposite.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; -using System.Drawing; -using Artemis.Components.Abstract; - -namespace Artemis.Components -{ - public class LayerComposite : LayerComponent - { - public List LayerComponents { get; set; } - - public override void Draw(Graphics g) - { - foreach (var layerComponent in LayerComponents) - layerComponent.Draw(g); - } - } -} \ No newline at end of file diff --git a/Artemis/Artemis/DAL/ProfileProvider.cs b/Artemis/Artemis/DAL/ProfileProvider.cs index 3c847ce8b..f696beeda 100644 --- a/Artemis/Artemis/DAL/ProfileProvider.cs +++ b/Artemis/Artemis/DAL/ProfileProvider.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.IO; using System.Linq; using Artemis.Models; +using Artemis.Models.Profiles; using Newtonsoft.Json; namespace Artemis.DAL diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs index 8446f1eb3..be9ce538f 100644 --- a/Artemis/Artemis/Managers/MainManager.cs +++ b/Artemis/Artemis/Managers/MainManager.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.Linq; using System.Threading; -using System.Windows.Forms; using Artemis.Events; using Artemis.Models; using Artemis.Services; diff --git a/Artemis/Artemis/Models/LayerConditionModel.cs b/Artemis/Artemis/Models/Profiles/LayerConditionModel.cs similarity index 56% rename from Artemis/Artemis/Models/LayerConditionModel.cs rename to Artemis/Artemis/Models/Profiles/LayerConditionModel.cs index 3a2896cd2..8a48cdbaa 100644 --- a/Artemis/Artemis/Models/LayerConditionModel.cs +++ b/Artemis/Artemis/Models/Profiles/LayerConditionModel.cs @@ -1,7 +1,8 @@ using System.Collections.Generic; using System.Linq.Dynamic; +using Artemis.Models.Interfaces; -namespace Artemis.Models +namespace Artemis.Models.Profiles { public class LayerConditionModel { @@ -9,11 +10,11 @@ namespace Artemis.Models public string Value { get; set; } public string Operator { get; set; } - public bool ConditionMet(object subject) + public bool ConditionMet(IGameDataModel subject) { // Put the subject in a list, allowing Dynamic Linq to be used. - var subjectList = new List {subject}; - var res = subjectList.Where($"s => s.{Field} {Operator} {Value}").Any(); + var subjectList = new List {(T) subject}; + var res = subjectList.Where($"{Field} {Operator} {Value}").Any(); return res; } } diff --git a/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs new file mode 100644 index 000000000..cb41291b0 --- /dev/null +++ b/Artemis/Artemis/Models/Profiles/LayerDynamicPropertiesModel.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Drawing; +using System.Linq.Dynamic; +using System.Reflection; +using Artemis.Models.Interfaces; + +namespace Artemis.Models.Profiles +{ + public class LayerDynamicPropertiesModel + { + public string LayerProperty { get; set; } + public string GameProperty { get; set; } + public string RequiredOperator { get; set; } + public string RequiredValue { get; set; } + public LayerPopertyType LayerPopertyType { get; set; } + + /// + /// Only used when LayerPropertyType is PercentageOf or PercentageOfProperty + /// + public string PercentageSource { get; set; } + + /// + /// Only used when LayerPropertyType is Color + /// + public List LayerColors { get; set; } + + internal void ApplyProperty(IGameDataModel dataModel, LayerPropertiesModel userProps, + LayerPropertiesModel props) + { + var dataList = new List {(T) dataModel}; + + // Attempt to set the property + var layerProp = props.GetType().GetProperty(LayerProperty); + var layerUserProp = userProps.GetType().GetProperty(LayerProperty); + + if (LayerPopertyType == LayerPopertyType.PercentageOf) + SetPercentageOf(props, userProps, dataModel, int.Parse(PercentageSource)); + if (LayerPopertyType == LayerPopertyType.PercentageOfProperty) + SetPercentageOfProperty(props, userProps, dataModel); + if (LayerPopertyType == LayerPopertyType.Color) + { + if (dataList.Where($"{GameProperty} {RequiredOperator} {RequiredValue}").Any()) + SetColor(layerProp, dataModel); + } + } + + private void SetPercentageOf(LayerPropertiesModel props, LayerPropertiesModel userProps, + IGameDataModel dataModel, int percentageSource) + { + // Property that will be set + var layerProp = props.GetType().GetProperty(LayerProperty); + // Property to use as a 100% + var userProp = userProps.GetType().GetProperty(LayerProperty); + // Value to use as a source + var source = dataModel.GetType().GetProperty(GameProperty)?.GetValue(dataModel, null); + if (layerProp == null || userProp == null || source == null) + return; + + var percentage = double.Parse(source.ToString())/percentageSource; + layerProp.SetValue(props, (int) (percentage*(int) userProp.GetValue(userProps, null))); + } + + private void SetPercentageOfProperty(LayerPropertiesModel props, LayerPropertiesModel userProps, + IGameDataModel dataModel) + { + var value = dataModel.GetType().GetProperty(PercentageSource)?.GetValue(dataModel, null); + if (value != null) + SetPercentageOf(props, userProps, dataModel, (int) value); + } + + private void SetColor(PropertyInfo layerProp, IGameDataModel dataModel) + { + if (layerProp == null) + return; + if (layerProp.PropertyType == typeof (List)) + layerProp.SetValue(dataModel, LayerColors, null); + } + } + + public enum LayerPopertyType + { + PercentageOf, + PercentageOfProperty, + Color + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Models/Profiles/LayerModel.cs b/Artemis/Artemis/Models/Profiles/LayerModel.cs new file mode 100644 index 000000000..df4fd4186 --- /dev/null +++ b/Artemis/Artemis/Models/Profiles/LayerModel.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Artemis.Models.Interfaces; +using Artemis.Properties; +using Newtonsoft.Json; +using Color = System.Drawing.Color; +using Pen = System.Drawing.Pen; + +namespace Artemis.Models.Profiles +{ + public class LayerModel + { + public LayerModel(string name, LayerType layerType) + { + Name = name; + LayerType = layerType; + LayerUserProperties = new LayerPropertiesModel(); + LayerCalculatedProperties = new LayerPropertiesModel(); + + Children = new List(); + LayerConditions = new List(); + LayerProperties = new List(); + } + + public string Name { get; set; } + public LayerType LayerType { get; set; } + public LayerPropertiesModel LayerUserProperties { get; set; } + + [JsonIgnore] + public LayerPropertiesModel LayerCalculatedProperties { get; } + + public List Children { get; set; } + public List LayerConditions { get; set; } + public List LayerProperties { get; set; } + public ImageSource LayerImage => GetPreviewImage(); + + private BitmapImage GetPreviewImage() + { + var bitmap = new Bitmap(18, 18); + using (var g = Graphics.FromImage(bitmap)) + { + g.SmoothingMode = SmoothingMode.AntiAlias; + if (LayerType == LayerType.Ellipse) + { + g.FillEllipse(new SolidBrush(LayerUserProperties.Colors.FirstOrDefault()), 0, 0, 18, 18); + g.DrawEllipse(new Pen(Color.Black, 1), 0, 0, 17, 17); + } + else if (LayerType == LayerType.Rectangle) + { + g.FillRectangle(new SolidBrush(LayerUserProperties.Colors.FirstOrDefault()), 0, 0, 18, 18); + g.DrawRectangle(new Pen(Color.Black, 1), 0, 0, 17, 17); + } + else + { + bitmap = Resources.folder; + } + } + + using (var memory = new MemoryStream()) + { + bitmap.Save(memory, ImageFormat.Png); + memory.Position = 0; + + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.StreamSource = memory; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + + return bitmapImage; + } + } + + public bool ConditionsMet(IGameDataModel dataModel) + { + return LayerConditions.All(cm => cm.ConditionMet(dataModel)); + } + + public void Draw(IGameDataModel dataModel, Graphics g) + { + if (!ConditionsMet(dataModel)) + return; + + Update(dataModel); + switch (LayerType) + { + case LayerType.Folder: + DrawChildren(dataModel, g); + break; + case LayerType.Rectangle: + DrawRectangle(g); + break; + case LayerType.Ellipse: + DrawEllipse(g); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + private void Update(IGameDataModel dataModel) + { + foreach (var dynamicProperty in LayerProperties) + dynamicProperty.ApplyProperty(dataModel, LayerUserProperties, LayerCalculatedProperties); + } + + private void DrawChildren(IGameDataModel dataModel, Graphics g) + { + foreach (var layerModel in Children) + layerModel.Draw(dataModel, g); + } + + private void DrawRectangle(Graphics g) + { + } + + private void DrawEllipse(Graphics g) + { + } + } + + public enum LayerType + { + Folder, + Rectangle, + Ellipse + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Models/Profiles/LayerPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/LayerPropertiesModel.cs new file mode 100644 index 000000000..20e02df5f --- /dev/null +++ b/Artemis/Artemis/Models/Profiles/LayerPropertiesModel.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace Artemis.Models.Profiles +{ + public class LayerPropertiesModel + { + public int X { get; set; } + public int Y { get; set; } + public int Width { get; set; } + public int Height { get; set; } + public int Opacity { get; set; } + public bool ContainedBrush { get; set; } + public LinearGradientMode GradientMode { get; set; } + public bool Rotate { get; set; } + public double RotateSpeed { get; set; } + public List Colors { get; set; } + + public LayerPropertiesModel() + { + Colors = new List(); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Models/ProfileModel.cs b/Artemis/Artemis/Models/Profiles/ProfileModel.cs similarity index 68% rename from Artemis/Artemis/Models/ProfileModel.cs rename to Artemis/Artemis/Models/Profiles/ProfileModel.cs index 769013786..86d4d409c 100644 --- a/Artemis/Artemis/Models/ProfileModel.cs +++ b/Artemis/Artemis/Models/Profiles/ProfileModel.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; -using Artemis.Components; -namespace Artemis.Models +namespace Artemis.Models.Profiles { public class ProfileModel { @@ -16,7 +15,7 @@ namespace Artemis.Models public string KeyboardName { get; set; } public string GameName { get; set; } - public LayerComposite Layers { get; set; } + public List Layers { get; set; } protected bool Equals(ProfileModel other) { @@ -27,7 +26,7 @@ namespace Artemis.Models { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; + if (obj.GetType() != GetType()) return false; return Equals((ProfileModel) obj); } @@ -35,9 +34,9 @@ namespace Artemis.Models { unchecked { - var hashCode = (Name != null ? Name.GetHashCode() : 0); - hashCode = (hashCode*397) ^ (KeyboardName != null ? KeyboardName.GetHashCode() : 0); - hashCode = (hashCode*397) ^ (GameName != null ? GameName.GetHashCode() : 0); + var hashCode = Name?.GetHashCode() ?? 0; + hashCode = (hashCode*397) ^ (KeyboardName?.GetHashCode() ?? 0); + hashCode = (hashCode*397) ^ (GameName?.GetHashCode() ?? 0); return hashCode; } } diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueDataModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueDataModel.cs new file mode 100644 index 000000000..63b8522f5 --- /dev/null +++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueDataModel.cs @@ -0,0 +1,9 @@ +using Artemis.Models.Interfaces; + +namespace Artemis.Modules.Games.RocketLeague +{ + internal class RocketLeagueDataModel : IGameDataModel + { + public int Boost { get; set; } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Properties/Resources.Designer.cs b/Artemis/Artemis/Properties/Resources.Designer.cs index 353d73f90..2cca27e55 100644 --- a/Artemis/Artemis/Properties/Resources.Designer.cs +++ b/Artemis/Artemis/Properties/Resources.Designer.cs @@ -61,14 +61,14 @@ namespace Artemis.Properties { } /// - /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-16"?> - ///<!-- Used by Artemis to get the active Sign --> - ///<UserConfig> - /// <Group id="Artemis" displayName="Artemis"> - /// <VisibleVars> - /// <Var id="ActiveSign" displayName="ActiveSign" displayType="SLIDER:0:1:1000000"/> - /// </VisibleVars> - /// </Group> + /// Looks up a localized string similar to <?xml version="1.0" encoding="UTF-16"?> + ///<!-- Used by Artemis to get the active Sign --> + ///<UserConfig> + /// <Group id="Artemis" displayName="Artemis"> + /// <VisibleVars> + /// <Var id="ActiveSign" displayName="ActiveSign" displayType="SLIDER:0:1:1000000"/> + /// </VisibleVars> + /// </Group> ///</UserConfig>. /// internal static string artemisXml { @@ -88,23 +88,23 @@ namespace Artemis.Properties { } /// - /// Looks up a localized string similar to "Artemis" - ///{ - /// "uri" "http://localhost:{{port}}/csgo_game_event" - /// "timeout" "5.0" - /// "buffer" "0.1" - /// "throttle" "0.1" - /// "heartbeat" "30.0" - /// "data" - /// { - /// "provider" "1" - /// "map" "1" - /// "round" "1" - /// "player_id" "1" - /// "player_state" "1" - /// "player_weapons" "1" - /// "player_match_stats" "1" - /// } + /// Looks up a localized string similar to "Artemis" + ///{ + /// "uri" "http://localhost:{{port}}/csgo_game_event" + /// "timeout" "5.0" + /// "buffer" "0.1" + /// "throttle" "0.1" + /// "heartbeat" "30.0" + /// "data" + /// { + /// "provider" "1" + /// "map" "1" + /// "round" "1" + /// "player_id" "1" + /// "player_state" "1" + /// "player_weapons" "1" + /// "player_match_stats" "1" + /// } ///}. /// internal static string csgoGamestateConfiguration { @@ -116,7 +116,7 @@ namespace Artemis.Properties { /// /// Looks up a localized string similar to "Artemis" ///{ - /// "uri" "http://localhost:4000/" + /// "uri" "http://localhost:{{port}}/" /// "timeout" "5.0" /// "buffer" "0.1" /// "throttle" "0.1" @@ -138,6 +138,16 @@ namespace Artemis.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap folder { + get { + object obj = ResourceManager.GetObject("folder", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Byte[]. /// diff --git a/Artemis/Artemis/Properties/Resources.resx b/Artemis/Artemis/Properties/Resources.resx index 5e03ad8fc..bf8569e4d 100644 --- a/Artemis/Artemis/Properties/Resources.resx +++ b/Artemis/Artemis/Properties/Resources.resx @@ -142,4 +142,7 @@ ..\resources\witcher3\playerwitcher.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + ..\Resources\folder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Artemis/Artemis/Resources/folder.png b/Artemis/Artemis/Resources/folder.png new file mode 100644 index 000000000..c818db4fa Binary files /dev/null and b/Artemis/Artemis/Resources/folder.png differ diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs index 51dda4530..2fb888568 100644 --- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs @@ -1,9 +1,16 @@ -using System.Linq; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Linq; using System.Windows.Media; using Artemis.DAL; using Artemis.Managers; using Artemis.Models; +using Artemis.Models.Profiles; +using Artemis.Modules.Games.RocketLeague; +using Artemis.Modules.Games.TheDivision; using Caliburn.Micro; +using Color = System.Drawing.Color; namespace Artemis.ViewModels { @@ -65,8 +72,7 @@ namespace Artemis.ViewModels } var profile = new ProfileModel(name, _mainManager.KeyboardManager.ActiveKeyboard.Name, _gameModel.Name); - var test = ProfileProvider.GetAll(); - if (test.Contains(profile)) + if (ProfileProvider.GetAll().Contains(profile)) { var overwrite = await @@ -76,6 +82,44 @@ namespace Artemis.ViewModels return; } + // Test + profile.Layers = new List(); + var layerFolder = new LayerModel("[VM TEST] Folder 1", LayerType.Folder); + + var layer1 = new LayerModel("[VM TEST] Rectangle 1", LayerType.Rectangle); + layer1.LayerConditions.Add(new LayerConditionModel {Field = "Boost", Operator = ">", Value = "0"}); + layer1.LayerProperties.Add(new LayerDynamicPropertiesModel + { + LayerProperty = "Width", + LayerPopertyType = LayerPopertyType.PercentageOf, + GameProperty = "Boost", + PercentageSource = "100" + }); + layer1.LayerUserProperties = new LayerPropertiesModel + { + Colors = new List {Color.Red, Color.OrangeRed}, + ContainedBrush = true, + GradientMode = LinearGradientMode.Vertical, + Width = 21, + Height = 7, + Opacity = 100, + Rotate = true, + RotateSpeed = 1, + X = 0, + Y = 0 + }; + layerFolder.Children.Add(layer1); + layerFolder.Children.Add(new LayerModel("[VM TEST] Ellipse 1", LayerType.Ellipse)); + + var testData = new RocketLeagueDataModel {Boost = 20}; + var bitmap = _mainManager.KeyboardManager.ActiveKeyboard.KeyboardBitmap(4); + using (var g = Graphics.FromImage(bitmap)) + { + layerFolder.Draw(testData, g); + } + // End test + + profile.Layers.Add(layerFolder); ProfileProvider.AddOrUpdate(profile); LoadProfiles(); diff --git a/Artemis/Artemis/Views/ProfileEditorView.xaml b/Artemis/Artemis/Views/ProfileEditorView.xaml index 440d24e28..99f90af1e 100644 --- a/Artemis/Artemis/Views/ProfileEditorView.xaml +++ b/Artemis/Artemis/Views/ProfileEditorView.xaml @@ -20,7 +20,7 @@