From b7423ad6d6946248a18c8295ce58ec1d1f5d11b9 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Sun, 5 Jun 2016 22:13:46 +0200 Subject: [PATCH] Performance improvements, especially on large profiles --- Artemis/Artemis/Models/Profiles/LayerModel.cs | 43 +++--- .../Artemis/Models/Profiles/ProfileModel.cs | 10 +- .../Properties/DynamicPropertiesModel.cs | 12 +- .../Properties/FolderPropertiesModel.cs | 4 +- .../Properties/HeadsetPropertiesModel.cs | 6 +- .../Properties/KeyboardPropertiesModel.cs | 32 +++- .../Properties/LayerPropertiesModel.cs | 29 +++- .../Properties/MousePropertiesModel.cs | 6 +- .../Games/CounterStrike/CounterStrikeModel.cs | 2 +- .../Modules/Games/Overwatch/OverwatchModel.cs | 4 +- .../Games/Overwatch/OverwatchViewModel.cs | 3 +- .../Games/TheDivision/TheDivisionModel.cs | 144 +++--------------- .../Games/TheDivision/TheDivisionView.xaml | 2 +- Artemis/Artemis/Utilities/GeneralHelpers.cs | 19 --- .../Utilities/Layers/AnimationUpdater.cs | 24 ++- Artemis/Artemis/Utilities/Layers/Drawer.cs | 82 +++++----- .../Utilities/LogitechDll/DllManager.cs | 32 ++-- .../Utilities/LogitechDll/PipeServer.cs | 2 - .../LayerDynamicPropertiesViewModel.cs | 4 +- .../Profiles/ProfileEditorViewModel.cs | 1 + .../ViewModels/Profiles/ProfileViewModel.cs | 13 +- .../Properties/HeadsetPropertiesViewModel.cs | 2 +- .../Properties/KeyboardPropertiesViewModel.cs | 29 ++-- .../Properties/MousePropertiesViewModel.cs | 2 +- 24 files changed, 208 insertions(+), 299 deletions(-) diff --git a/Artemis/Artemis/Models/Profiles/LayerModel.cs b/Artemis/Artemis/Models/Profiles/LayerModel.cs index 62c9691ed..b0de10d36 100644 --- a/Artemis/Artemis/Models/Profiles/LayerModel.cs +++ b/Artemis/Artemis/Models/Profiles/LayerModel.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows.Media; @@ -51,8 +50,7 @@ namespace Artemis.Models.Profiles return; // Preview simply shows the properties as they are. When not previewing they are applied - LayerPropertiesModel appliedProperties; - Properties.Brush.Freeze(); + AppliedProperties appliedProperties; if (!preview) { if (!ConditionsMet(dataModel)) @@ -60,13 +58,12 @@ namespace Artemis.Models.Profiles appliedProperties = Properties.GetAppliedProperties(dataModel); } else - appliedProperties = GeneralHelpers.Clone(Properties); + appliedProperties = Properties.GetAppliedProperties(dataModel, true); // Update animations on layer types that support them if (LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif) { - AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties, - (KeyboardPropertiesModel) appliedProperties, updateAnimations); + AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties, updateAnimations); } switch (LayerType) @@ -77,10 +74,10 @@ namespace Artemis.Models.Profiles layerModel.Draw(dataModel, c, preview, updateAnimations); break; case LayerType.Keyboard: - Drawer.Draw(c, (KeyboardPropertiesModel) Properties, (KeyboardPropertiesModel) appliedProperties); + Drawer.Draw(c, (KeyboardPropertiesModel) Properties, appliedProperties); break; case LayerType.KeyboardGif: - GifImage = Drawer.DrawGif(c, (KeyboardPropertiesModel) appliedProperties, GifImage); + GifImage = Drawer.DrawGif(c, (KeyboardPropertiesModel)Properties, appliedProperties, GifImage); break; } } @@ -93,23 +90,17 @@ namespace Artemis.Models.Profiles return null; // Preview simply shows the properties as they are. When not previewing they are applied - LayerPropertiesModel appliedProperties; + AppliedProperties appliedProperties; if (!preview) { if (!ConditionsMet(dataModel)) - return null; // Don't return the brush when not previewing and the conditions arent met + return null; // Return null when not previewing and the conditions arent met appliedProperties = Properties.GetAppliedProperties(dataModel); } else - appliedProperties = GeneralHelpers.Clone(Properties); + appliedProperties = Properties.GetAppliedProperties(dataModel, true); // TODO: Mouse/headset animations - // Update animations on layer types that support them - //if (LayerType != LayerType.Folder && updateAnimations) - //{ - // AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel)Properties, - // (KeyboardPropertiesModel)appliedProperties); - //} if (LayerType != LayerType.Folder) return appliedProperties.Brush; @@ -165,18 +156,24 @@ namespace Artemis.Models.Profiles /// public bool MustDraw() { + // If any of the parents are disabled, this layer must not be drawn + var parent = Parent; + while (parent != null) + { + if (!parent.Enabled) + return false; + parent = parent.Parent; + } return Enabled && (LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif); } - public IEnumerable GetAllLayers(bool ignoreEnabled) + public IEnumerable GetLayers() { var layers = new List(); foreach (var layerModel in Children) { - if (ignoreEnabled && !layerModel.Enabled) - continue; layers.Add(layerModel); - layers.AddRange(layerModel.Children); + layers.AddRange(layerModel.GetLayers()); } return layers; @@ -236,7 +233,7 @@ namespace Artemis.Models.Profiles Profile.Layers.Add(source); } } - + #region IChildItem Members LayerModel IChildItem.Parent diff --git a/Artemis/Artemis/Models/Profiles/ProfileModel.cs b/Artemis/Artemis/Models/Profiles/ProfileModel.cs index 7cb675238..69b0e48c1 100644 --- a/Artemis/Artemis/Models/Profiles/ProfileModel.cs +++ b/Artemis/Artemis/Models/Profiles/ProfileModel.cs @@ -104,17 +104,13 @@ namespace Artemis.Models.Profiles /// /// Gives all the layers and their children in a flat list /// - public List GetLayers(bool ignoreEnabled = true) + public List GetLayers() { var layers = new List(); foreach (var layerModel in Layers) { - if (ignoreEnabled && !layerModel.Enabled) - { - continue; - } layers.Add(layerModel); - layers.AddRange(layerModel.GetAllLayers(ignoreEnabled)); + layers.AddRange(layerModel.GetLayers()); } return layers; @@ -126,7 +122,7 @@ namespace Artemis.Models.Profiles /// public void FixBoundaries(Rect keyboardRectangle) { - foreach (var layer in GetLayers(false)) + foreach (var layer in GetLayers()) { if (layer.LayerType != LayerType.Keyboard && layer.LayerType != LayerType.KeyboardGif) continue; diff --git a/Artemis/Artemis/Models/Profiles/Properties/DynamicPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/Properties/DynamicPropertiesModel.cs index c54452f6c..7b1552f95 100644 --- a/Artemis/Artemis/Models/Profiles/Properties/DynamicPropertiesModel.cs +++ b/Artemis/Artemis/Models/Profiles/Properties/DynamicPropertiesModel.cs @@ -37,7 +37,7 @@ namespace Artemis.Models.Profiles.Properties /// public LayerPropertyOptions LayerPropertyOptions { get; set; } - internal void ApplyProperty(IGameDataModel dataModel, KeyboardPropertiesModel properties) + internal void ApplyProperty(IGameDataModel dataModel, AppliedProperties properties) { if (LayerPropertyType == LayerPropertyType.PercentageOf) ApplyPercentageOf(dataModel, properties, PercentageSource); @@ -45,7 +45,7 @@ namespace Artemis.Models.Profiles.Properties ApplyPercentageOfProperty(dataModel, properties); } - private void ApplyPercentageOf(IGameDataModel dataModel, KeyboardPropertiesModel properties, double src) + private void ApplyPercentageOf(IGameDataModel dataModel, AppliedProperties properties, double src) { if (GameProperty == null) return; @@ -61,7 +61,7 @@ namespace Artemis.Models.Profiles.Properties ApplyOpacity(properties, percentage); } - private void ApplyWidth(KeyboardPropertiesModel properties, double percentage) + private void ApplyWidth(AppliedProperties properties, double percentage) { var newWidth = percentage * properties.Width; var difference = properties.Width - newWidth; @@ -72,7 +72,7 @@ namespace Artemis.Models.Profiles.Properties properties.X = properties.X + difference; } - private void ApplyHeight(KeyboardPropertiesModel properties, double percentage) + private void ApplyHeight(AppliedProperties properties, double percentage) { var newHeight = percentage*properties.Height; var difference = properties.Height - newHeight; @@ -82,7 +82,7 @@ namespace Artemis.Models.Profiles.Properties properties.Y = properties.Y + difference; } - private void ApplyOpacity(KeyboardPropertiesModel properties, double percentage) + private void ApplyOpacity(AppliedProperties properties, double percentage) { properties.Opacity = percentage*properties.Opacity; if (properties.Opacity < 0.0) @@ -95,7 +95,7 @@ namespace Artemis.Models.Profiles.Properties properties.Opacity = 1.0 - properties.Opacity; } - private void ApplyPercentageOfProperty(IGameDataModel dataModel, KeyboardPropertiesModel properties) + private void ApplyPercentageOfProperty(IGameDataModel dataModel, AppliedProperties properties) { var value = dataModel.GetPropValue(PercentageProperty); ApplyPercentageOf(dataModel, properties, value); diff --git a/Artemis/Artemis/Models/Profiles/Properties/FolderPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/Properties/FolderPropertiesModel.cs index 65bcc8603..c86b29c3c 100644 --- a/Artemis/Artemis/Models/Profiles/Properties/FolderPropertiesModel.cs +++ b/Artemis/Artemis/Models/Profiles/Properties/FolderPropertiesModel.cs @@ -5,9 +5,9 @@ namespace Artemis.Models.Profiles.Properties { public class FolderPropertiesModel : LayerPropertiesModel { - public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel) + public override AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false) { - return GeneralHelpers.Clone(this); + return new AppliedProperties(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Models/Profiles/Properties/HeadsetPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/Properties/HeadsetPropertiesModel.cs index 79093aa2f..c58877d3c 100644 --- a/Artemis/Artemis/Models/Profiles/Properties/HeadsetPropertiesModel.cs +++ b/Artemis/Artemis/Models/Profiles/Properties/HeadsetPropertiesModel.cs @@ -1,14 +1,12 @@ using Artemis.Models.Interfaces; -using Artemis.Utilities; namespace Artemis.Models.Profiles.Properties { public class HeadsetPropertiesModel : LayerPropertiesModel { - public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel) + public override AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false) { - // TODO: Apply any properties, if applicable to headsets in the first place. - return GeneralHelpers.Clone(this); + return new AppliedProperties(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Models/Profiles/Properties/KeyboardPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/Properties/KeyboardPropertiesModel.cs index 3f02b5950..540b78f80 100644 --- a/Artemis/Artemis/Models/Profiles/Properties/KeyboardPropertiesModel.cs +++ b/Artemis/Artemis/Models/Profiles/Properties/KeyboardPropertiesModel.cs @@ -1,6 +1,8 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.ComponentModel; using System.Windows; +using System.Windows.Media; using System.Xml.Serialization; using Artemis.Models.Interfaces; using Artemis.Utilities; @@ -33,15 +35,31 @@ namespace Artemis.Models.Profiles.Properties return new Rect(X*scale, Y*scale, Width*scale, Height*scale); } - public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel) + public override AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false) { - var properties = GeneralHelpers.Clone(this); + var applied = new AppliedProperties + { + X = X, + Y = Y, + Width = Width, + Height = Height, + Opacity = Opacity, + Brush = Brush.CloneCurrentValue() + }; - foreach (var dynamicProperty in properties.DynamicProperties) - dynamicProperty.ApplyProperty(dataModel, properties); - properties.Brush.Opacity = Opacity; + if (ignoreDynamic) + return applied; - return properties; + foreach (var dynamicProperty in DynamicProperties) + dynamicProperty.ApplyProperty(dataModel, applied); + + if (Math.Abs(applied.Opacity - 1) > 0.001) + { + applied.Brush = Brush.CloneCurrentValue(); + applied.Brush.Opacity = applied.Opacity; + } + + return applied; } } diff --git a/Artemis/Artemis/Models/Profiles/Properties/LayerPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/Properties/LayerPropertiesModel.cs index 98dc73151..bd96243b7 100644 --- a/Artemis/Artemis/Models/Profiles/Properties/LayerPropertiesModel.cs +++ b/Artemis/Artemis/Models/Profiles/Properties/LayerPropertiesModel.cs @@ -23,8 +23,6 @@ namespace Artemis.Models.Profiles.Properties Conditions = new List(); } - public abstract LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel); - public List Conditions { get; set; } public Brush Brush @@ -32,10 +30,35 @@ namespace Artemis.Models.Profiles.Properties get { return _brush; } set { - var cloned = value.Dispatcher.Invoke(() => GeneralHelpers.CloneAlt(value)); + if (value == null) + { + _brush = null; + return; + } + + if (value.IsFrozen) + { + _brush = value; + return; + } + + // Clone the brush off of the UI thread and freeze it + var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue); cloned.Freeze(); _brush = cloned; } } + + public abstract AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false); + } + + public struct AppliedProperties + { + public double X { get; set; } + public double Y { get; set; } + public double Width { get; set; } + public double Height { get; set; } + public double Opacity { get; set; } + public Brush Brush { get; set; } } } \ No newline at end of file diff --git a/Artemis/Artemis/Models/Profiles/Properties/MousePropertiesModel.cs b/Artemis/Artemis/Models/Profiles/Properties/MousePropertiesModel.cs index a64df1c3b..95c63af21 100644 --- a/Artemis/Artemis/Models/Profiles/Properties/MousePropertiesModel.cs +++ b/Artemis/Artemis/Models/Profiles/Properties/MousePropertiesModel.cs @@ -1,14 +1,12 @@ using Artemis.Models.Interfaces; -using Artemis.Utilities; namespace Artemis.Models.Profiles.Properties { public class MousePropertiesModel : LayerPropertiesModel { - public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel) + public override AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false) { - // TODO: Apply any properties, if applicable to mice in the first place. - return GeneralHelpers.Clone(this); + return new AppliedProperties(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs index 2358c7052..03a7af263 100644 --- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs +++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs @@ -84,7 +84,7 @@ namespace Artemis.Modules.Games.CounterStrike } catch (Exception ex) { - Logger.Error(ex, "Failed to deserialize CS:GO JSON"); + Logger?.Error(ex, "Failed to deserialize CS:GO JSON"); throw; } diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs index ac03eb17c..0a3e5bb45 100644 --- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs +++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs @@ -141,7 +141,7 @@ namespace Artemis.Modules.Games.Overwatch { if (Profile == null || GameDataModel == null) return null; - + return null; return Profile.GenerateBrush(GameDataModel, LayerType.Mouse, false, true); } @@ -149,7 +149,7 @@ namespace Artemis.Modules.Games.Overwatch { if (Profile == null || GameDataModel == null) return null; - + return null; return Profile.GenerateBrush(GameDataModel, LayerType.Headset, false, true); } } diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchViewModel.cs b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchViewModel.cs index c1765707e..494e60558 100644 --- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchViewModel.cs +++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchViewModel.cs @@ -78,9 +78,8 @@ namespace Artemis.Modules.Games.Overwatch } catch (Exception e) { - Logger.Error(e, "Couldn't place Overwatch DLL, Overwatch support won't work."); + Logger?.Error(e, "Couldn't place Overwatch DLL, Overwatch support won't work."); } - } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs index 9e788568e..a72bbd02c 100644 --- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.Drawing; -using System.Drawing.Drawing2D; +using System.Threading; +using System.Threading.Tasks; using Artemis.Managers; using Artemis.Models; using Artemis.Models.Profiles; -using Artemis.Modules.Effects.TypeWave; using Artemis.Utilities; -using Artemis.Utilities.Keyboard; using Artemis.Utilities.LogitechDll; using Brush = System.Windows.Media.Brush; @@ -14,16 +13,11 @@ namespace Artemis.Modules.Games.TheDivision { public class TheDivisionModel : GameModel { - private Wave _ammoWave; - private KeyboardRectangle _hpRect; - private KeyboardRectangle _p2; - private KeyboardRectangle _p3; - private KeyboardRectangle _p4; private StickyValue _stickyAmmo; private StickyValue _stickyHp; - private int _trans; - public TheDivisionModel(MainManager mainManager, TheDivisionSettings settings) : base(mainManager, settings, new TheDivisionDataModel()) + public TheDivisionModel(MainManager mainManager, TheDivisionSettings settings) + : base(mainManager, settings, new TheDivisionDataModel()) { Name = "TheDivision"; ProcessName = "TheDivision"; @@ -37,7 +31,13 @@ namespace Artemis.Modules.Games.TheDivision public override void Dispose() { Initialized = false; - DllManager.RestoreDll(); + + // Delay restoring the DLL to allow The Division to release it + Task.Factory.StartNew(() => + { + Thread.Sleep(2000); + DllManager.RestoreDll(); + }); _stickyAmmo.Dispose(); _stickyHp.Dispose(); @@ -47,45 +47,6 @@ namespace Artemis.Modules.Games.TheDivision { Initialized = false; - _ammoWave = new Wave(new Point(30, 14), 0, Color.Transparent); - _hpRect = new KeyboardRectangle(MainManager.DeviceManager.ActiveKeyboard, 3*Scale, 0*Scale, - new List(), - LinearGradientMode.Horizontal) - { - Height = 7*Scale, - Width = 21*Scale, - Rotate = true, - ContainedBrush = false - }; - - _p2 = new KeyboardRectangle(MainManager.DeviceManager.ActiveKeyboard, 0*Scale, 1*Scale, - new List(), - LinearGradientMode.Horizontal) - { - Height = 2*Scale, - Width = 3*Scale, - Rotate = true, - ContainedBrush = false - }; - _p3 = new KeyboardRectangle(MainManager.DeviceManager.ActiveKeyboard, 0*Scale, 3*Scale, - new List(), - LinearGradientMode.Horizontal) - { - Height = 2*Scale, - Width = 3*Scale, - Rotate = true, - ContainedBrush = false - }; - _p4 = new KeyboardRectangle(MainManager.DeviceManager.ActiveKeyboard, 0*Scale, 5*Scale, - new List(), - LinearGradientMode.Horizontal) - { - Height = 2*Scale, - Width = 3*Scale, - Rotate = true, - ContainedBrush = false - }; - _stickyAmmo = new StickyValue(200); _stickyHp = new StickyValue(200); @@ -113,7 +74,7 @@ namespace Artemis.Modules.Games.TheDivision // Parses Division key data to game data private void InterpertrateDivisionKey(IReadOnlyList parts) { - var gameDataModel = (TheDivisionDataModel)GameDataModel; + var gameDataModel = (TheDivisionDataModel) GameDataModel; var keyCode = parts[1]; var rPer = parts[2]; var gPer = parts[3]; @@ -133,10 +94,12 @@ namespace Artemis.Modules.Games.TheDivision newState = PlayerState.Offline; if (playerId == 1) - gameDataModel.PartyMember1 = newState; + gameDataModel.LowHp = (newState == PlayerState.Hit); else if (playerId == 2) - gameDataModel.PartyMember2 = newState; + gameDataModel.PartyMember1 = newState; else if (playerId == 3) + gameDataModel.PartyMember2 = newState; + else if (playerId == 4) gameDataModel.PartyMember3 = newState; } // R blinks white when low on ammo @@ -165,81 +128,16 @@ namespace Artemis.Modules.Games.TheDivision public override void Update() { - var gameDataModel = (TheDivisionDataModel)GameDataModel; - if (gameDataModel.LowAmmo) - { - _ammoWave.Size++; - if (_ammoWave.Size > 30) - { - _ammoWave.Size = 0; - _trans = 255; - } - } - else - _ammoWave.Size = 0; - - _hpRect.Colors = gameDataModel.LowHp - ? new List {Color.Red, Color.Orange} - : new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)}; - - if (gameDataModel.PartyMember1 == PlayerState.Offline) - _p2.Colors = new List {Color.Gray, Color.White}; - else if (gameDataModel.PartyMember1 == PlayerState.Online) - _p2.Colors = new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)}; - else - _p2.Colors = new List {Color.Red, Color.Orange}; - - if (gameDataModel.PartyMember2 == PlayerState.Offline) - _p3.Colors = new List {Color.Gray, Color.White}; - else if (gameDataModel.PartyMember2 == PlayerState.Online) - _p3.Colors = new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)}; - else - _p3.Colors = new List {Color.Red, Color.Orange}; - - if (gameDataModel.PartyMember3 == PlayerState.Offline) - _p4.Colors = new List {Color.Gray, Color.White}; - else if (gameDataModel.PartyMember3 == PlayerState.Online) - _p4.Colors = new List {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)}; - else - _p4.Colors = new List {Color.Red, Color.Orange}; + // DataModel updating is done whenever a pipe message is received } public override Bitmap GenerateBitmap() { - var bitmap = MainManager.DeviceManager.ActiveKeyboard.KeyboardBitmap(Scale); - using (var g = Graphics.FromImage(bitmap)) - { - g.Clear(Color.Transparent); - _hpRect.Draw(g); - _p2.Draw(g); - _p3.Draw(g); - _p4.Draw(g); - // Very, very PH - if (_ammoWave.Size != 0) - { - var path = new GraphicsPath(); - path.AddEllipse(_ammoWave.Point.X - _ammoWave.Size/2, _ammoWave.Point.Y - _ammoWave.Size/2, - _ammoWave.Size, _ammoWave.Size); + if (Profile == null || GameDataModel == null) + return null; - if (_ammoWave.Size > 15) - _trans = _trans - 16; - if (_trans < 1) - _trans = 255; - var pthGrBrush = new PathGradientBrush(path) - { - SurroundColors = new[] {_ammoWave.Color}, - CenterColor = Color.FromArgb(_trans, 255, 0, 0) - }; - - g.FillPath(pthGrBrush, path); - pthGrBrush.FocusScales = new PointF(0.3f, 0.8f); - - g.FillPath(pthGrBrush, path); - g.DrawEllipse(new Pen(pthGrBrush, 1), _ammoWave.Point.X - _ammoWave.Size/2, - _ammoWave.Point.Y - _ammoWave.Size/2, _ammoWave.Size, _ammoWave.Size); - } - } - return bitmap; + var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(Scale); + return Profile.GenerateBitmap(keyboardRect, GameDataModel, false, true); } public override Brush GenerateMouseBrush() diff --git a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml index 8dc3797be..cd3c3aaf6 100644 --- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionView.xaml @@ -25,7 +25,7 @@ diff --git a/Artemis/Artemis/Utilities/GeneralHelpers.cs b/Artemis/Artemis/Utilities/GeneralHelpers.cs index 927bb3dd7..8d24c9616 100644 --- a/Artemis/Artemis/Utilities/GeneralHelpers.cs +++ b/Artemis/Artemis/Utilities/GeneralHelpers.cs @@ -62,25 +62,6 @@ namespace Artemis.Utilities } } - /// - /// Perform a deep Copy of the object. - /// - /// The type of object being copied. - /// The object instance to copy. - /// The copied object. - public static T CloneAlt(T source) - { - // Don't serialize a null object, simply return the default for that object - if (ReferenceEquals(source, null)) - return default(T); - - var xaml = XamlWriter.Save(source); - var xamlString = new StringReader(xaml); - var xmlTextReader = new XmlTextReader(xamlString); - var deepCopyObject = (T)XamlReader.Load(xmlTextReader); - return deepCopyObject; - } - public static string Serialize(T source) { // Don't serialize a null object, simply return the default for that object diff --git a/Artemis/Artemis/Utilities/Layers/AnimationUpdater.cs b/Artemis/Artemis/Utilities/Layers/AnimationUpdater.cs index 672c2bb9f..f6eb8d6f5 100644 --- a/Artemis/Artemis/Utilities/Layers/AnimationUpdater.cs +++ b/Artemis/Artemis/Utilities/Layers/AnimationUpdater.cs @@ -4,44 +4,40 @@ namespace Artemis.Utilities.Layers { public static class AnimationUpdater { - public static void UpdateAnimation(KeyboardPropertiesModel properties, KeyboardPropertiesModel appliedProperties, bool updateAnimations) + public static void UpdateAnimation(KeyboardPropertiesModel properties, bool updateAnimations) { const int scale = 4; - var animateProperties = properties.Contain ? appliedProperties : properties; - appliedProperties.AnimationProgress = properties.AnimationProgress; - var progress = appliedProperties.AnimationProgress; + var progress = properties.AnimationProgress; - switch (animateProperties.Animation) + switch (properties.Animation) { case LayerAnimation.SlideRight: case LayerAnimation.SlideLeft: - if (progress + 1 >= animateProperties.Width*scale) + if (progress + 1 >= properties.Width*scale) progress = 0; - progress = progress + animateProperties.AnimationSpeed * 2; + progress = progress + properties.AnimationSpeed * 2; break; case LayerAnimation.SlideDown: case LayerAnimation.SlideUp: - if (progress + 1 >= animateProperties.Height*scale) + if (progress + 1 >= properties.Height*scale) progress = 0; - progress = progress + animateProperties.AnimationSpeed * 2; + progress = progress + properties.AnimationSpeed * 2; break; case LayerAnimation.Pulse: if (progress > 2) progress = 0; - progress = progress + animateProperties.AnimationSpeed/2; + progress = progress + properties.AnimationSpeed/2; break; case LayerAnimation.Grow: if (progress > 10) progress = 0; - progress = progress + animateProperties.AnimationSpeed / 2.5; + progress = progress + properties.AnimationSpeed / 2.5; break; default: - progress = progress + animateProperties.AnimationSpeed*2; + progress = progress + properties.AnimationSpeed*2; break; } - appliedProperties.AnimationProgress = progress; - // If not previewing, store the animation progress in the actual model for the next frame if (updateAnimations) properties.AnimationProgress = progress; diff --git a/Artemis/Artemis/Utilities/Layers/Drawer.cs b/Artemis/Artemis/Utilities/Layers/Drawer.cs index 206db6d15..ecf3f74bf 100644 --- a/Artemis/Artemis/Utilities/Layers/Drawer.cs +++ b/Artemis/Artemis/Utilities/Layers/Drawer.cs @@ -14,7 +14,7 @@ namespace Artemis.Utilities.Layers { public static class Drawer { - public static void Draw(DrawingContext c, KeyboardPropertiesModel props, KeyboardPropertiesModel applied) + public static void Draw(DrawingContext c, KeyboardPropertiesModel props, AppliedProperties applied) { if (applied.Brush == null) return; @@ -28,56 +28,52 @@ namespace Artemis.Utilities.Layers var s1 = new Rect(); var s2 = new Rect(); - if (applied.Animation == LayerAnimation.SlideRight) + if (props.Animation == LayerAnimation.SlideRight) { - s1 = new Rect(new Point(rect.X + applied.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height)); - s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + 1, rect.Height)); + s1 = new Rect(new Point(rect.X + props.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height)); + s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + 0.05, rect.Height)); } - if (applied.Animation == LayerAnimation.SlideLeft) + if (props.Animation == LayerAnimation.SlideLeft) { - s1 = new Rect(new Point(rect.X - applied.AnimationProgress, rect.Y), - new Size(rect.Width + 1, rect.Height)); + s1 = new Rect(new Point(rect.X - props.AnimationProgress, rect.Y), + new Size(rect.Width + 0.05, rect.Height)); s2 = new Rect(new Point(s1.X + rect.Width, rect.Y), new Size(rect.Width, rect.Height)); } - if (applied.Animation == LayerAnimation.SlideDown) + if (props.Animation == LayerAnimation.SlideDown) { - s1 = new Rect(new Point(rect.X, rect.Y + applied.AnimationProgress), new Size(rect.Width, rect.Height)); + s1 = new Rect(new Point(rect.X, rect.Y + props.AnimationProgress), new Size(rect.Width, rect.Height)); s2 = new Rect(new Point(s1.X, s1.Y - rect.Height), new Size(rect.Width, rect.Height)); } - if (applied.Animation == LayerAnimation.SlideUp) + if (props.Animation == LayerAnimation.SlideUp) { - s1 = new Rect(new Point(rect.X, rect.Y - applied.AnimationProgress), new Size(rect.Width, rect.Height)); + s1 = new Rect(new Point(rect.X, rect.Y - props.AnimationProgress), new Size(rect.Width, rect.Height)); s2 = new Rect(new Point(s1.X, s1.Y + rect.Height), new Size(rect.Width, rect.Height)); } var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale); - DrawRectangle(c, applied, clip, rect, s1, s2); + DrawRectangle(c, props, applied, clip, rect, s1, s2); } - private static void DrawRectangle(DrawingContext c, KeyboardPropertiesModel properties, Rect clip, - Rect rectangle, - Rect slide1, Rect slide2) + private static void DrawRectangle(DrawingContext c, KeyboardPropertiesModel props, AppliedProperties applied, + Rect clip, Rect rectangle, Rect slide1, Rect slide2) { - var brush = properties.Brush.CloneCurrentValue(); - brush.Opacity = properties.Opacity; - // Apply the pulse animation - if (properties.Animation == LayerAnimation.Pulse) - brush.Opacity = (Math.Sin(properties.AnimationProgress*Math.PI) + 1)*(properties.Opacity/2); + if (props.Animation == LayerAnimation.Pulse) + applied.Brush.Opacity = (Math.Sin(props.AnimationProgress*Math.PI) + 1)*(props.Opacity/2); else - brush.Opacity = properties.Opacity; + applied.Brush.Opacity = props.Opacity; - if (properties.Animation == LayerAnimation.Grow) + if (props.Animation == LayerAnimation.Grow) { // Take an offset of 4 to allow layers to slightly leave their bounds - var progress = (6.0 - properties.AnimationProgress)*10.0; + var progress = (6.0 - props.AnimationProgress)*10.0; if (progress < 0) { - brush.Opacity = 1 + (0.025*progress); - if (brush.Opacity < 0) - brush.Opacity = 0; - if (brush.Opacity > 1) - brush.Opacity = 1; + applied.Brush.Opacity = 1 + 0.025*progress; + if (applied.Brush.Opacity < 0) + applied.Brush.Opacity = 0; + if (applied.Brush.Opacity > 1) + applied.Brush.Opacity = 1; } rectangle.Inflate(-rectangle.Width/100.0*progress, -rectangle.Height/100.0*progress); clip.Inflate(-clip.Width/100.0*progress, -clip.Height/100.0*progress); @@ -85,41 +81,41 @@ namespace Artemis.Utilities.Layers c.PushClip(new RectangleGeometry(clip)); // Most animation types can be drawn regularly - if (properties.Animation == LayerAnimation.None || - properties.Animation == LayerAnimation.Grow || - properties.Animation == LayerAnimation.Pulse) + if (props.Animation == LayerAnimation.None || + props.Animation == LayerAnimation.Grow || + props.Animation == LayerAnimation.Pulse) { - c.DrawRectangle(brush, null, rectangle); + c.DrawRectangle(applied.Brush, null, rectangle); } // Sliding animations however, require offsetting two rects else { c.PushClip(new RectangleGeometry(clip)); - c.DrawRectangle(brush, null, slide1); - c.DrawRectangle(brush, null, slide2); + c.DrawRectangle(applied.Brush, null, slide1); + c.DrawRectangle(applied.Brush, null, slide2); c.Pop(); } c.Pop(); } - public static GifImage DrawGif(DrawingContext c, KeyboardPropertiesModel properties, GifImage gifImage, - bool update = true) + public static GifImage DrawGif(DrawingContext c, KeyboardPropertiesModel props, AppliedProperties applied, + GifImage gifImage, bool update = true) { - if (string.IsNullOrEmpty(properties.GifFile)) + if (string.IsNullOrEmpty(props.GifFile)) return null; - if (!File.Exists(properties.GifFile)) + if (!File.Exists(props.GifFile)) return null; const int scale = 4; // Only reconstruct GifImage if the underlying source has changed if (gifImage == null) - gifImage = new GifImage(properties.GifFile); - if (gifImage.Source != properties.GifFile) - gifImage = new GifImage(properties.GifFile); + gifImage = new GifImage(props.GifFile); + if (gifImage.Source != props.GifFile) + gifImage = new GifImage(props.GifFile); - var gifRect = new Rect(properties.X*scale, properties.Y*scale, properties.Width*scale, - properties.Height*scale); + var gifRect = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, + applied.Height*scale); var draw = update ? gifImage.GetNextFrame() : gifImage.GetFrame(0); c.DrawImage(ImageUtilities.BitmapToBitmapImage(new Bitmap(draw)), gifRect); diff --git a/Artemis/Artemis/Utilities/LogitechDll/DllManager.cs b/Artemis/Artemis/Utilities/LogitechDll/DllManager.cs index 88b594a49..e50367380 100644 --- a/Artemis/Artemis/Utilities/LogitechDll/DllManager.cs +++ b/Artemis/Artemis/Utilities/LogitechDll/DllManager.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using Artemis.Properties; using Microsoft.Win32; @@ -13,16 +14,24 @@ namespace Artemis.Utilities.LogitechDll if (!File.Exists(LogitechPath + @"\LogitechLed.dll") || !File.Exists(LogitechPath + @"\artemis.txt")) return false; - // Get rid of our own DLL - File.Delete(LogitechPath + @"\LogitechLed.dll"); + try + { + // Get rid of our own DLL + File.Delete(LogitechPath + @"\LogitechLed.dll"); - // Restore the backup - if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak")) - File.Copy(LogitechPath + @"\LogitechLed.dll.bak", LogitechPath + @"\LogitechLed.dll"); + // Restore the backup + if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak")) + File.Copy(LogitechPath + @"\LogitechLed.dll.bak", LogitechPath + @"\LogitechLed.dll"); - File.Delete(LogitechPath + @"\artemis.txt"); + File.Delete(LogitechPath + @"\artemis.txt"); - return true; + return true; + } + catch (Exception) + { + return false; + } + } public static void PlaceDll() @@ -35,8 +44,11 @@ namespace Artemis.Utilities.LogitechDll // Backup the existing DLL if (File.Exists(LogitechPath + @"\LogitechLed.dll")) - File.Move(LogitechPath + @"\LogitechLed.dll", - LogitechPath + @"\LogitechLed.dll.bak"); + { + if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak")) + File.Delete(LogitechPath + @"\LogitechLed.dll.bak"); + File.Move(LogitechPath + @"\LogitechLed.dll", LogitechPath + @"\LogitechLed.dll.bak"); + } // Copy our own DLL in place File.WriteAllBytes(LogitechPath + @"\LogitechLED.dll", diff --git a/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs b/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs index 66bd751ee..3958c5040 100644 --- a/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs +++ b/Artemis/Artemis/Utilities/LogitechDll/PipeServer.cs @@ -63,7 +63,6 @@ namespace Artemis.Utilities.LogitechDll private void HandleMessage(byte[] buffer) { var request = Encoding.ASCII.GetString(buffer); - Debug.WriteLine(request); PipeMessage?.Invoke(request); } @@ -106,7 +105,6 @@ namespace Artemis.Utilities.LogitechDll // Convert byte buffer to string var stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length); - Debug.WriteLine(stringData + Environment.NewLine); // Pass message back to calling form PipeMessage?.Invoke(stringData); diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs index dcdb69303..9505f2ef4 100644 --- a/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs @@ -3,6 +3,7 @@ using System.Linq; using Artemis.Models.Profiles.Properties; using Artemis.Utilities; using Caliburn.Micro; +using Castle.Core.Internal; namespace Artemis.ViewModels.Profiles { @@ -211,7 +212,8 @@ namespace Artemis.ViewModels.Profiles if (original != null) keyboardProperties.DynamicProperties.Remove(original); - keyboardProperties.DynamicProperties.Add(Proposed); + if (!Proposed.GameProperty.IsNullOrEmpty()) + keyboardProperties.DynamicProperties.Add(Proposed); } } } \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs index df91cae0a..8067335f8 100644 --- a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs @@ -172,6 +172,7 @@ namespace Artemis.ViewModels.Profiles source.Order = -1; target.Children.Add(source); target.FixOrder(); + target.Expanded = true; } else { diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs index 615b4974c..2f0061d2e 100644 --- a/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs @@ -5,7 +5,6 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; -using System.Windows.Threading; using Artemis.Events; using Artemis.Managers; using Artemis.Models.Profiles; @@ -91,7 +90,7 @@ namespace Artemis.ViewModels.Profiles if (_blurProgress > 2) _blurProgress = 0; _blurProgress = _blurProgress + 0.025; - BlurRadius = (Math.Sin(_blurProgress * Math.PI) + 1) * 10 + 10; + BlurRadius = (Math.Sin(_blurProgress*Math.PI) + 1)*10 + 10; if (SelectedProfile == null || _deviceManager.ActiveKeyboard == null) { @@ -112,10 +111,8 @@ namespace Artemis.ViewModels.Profiles // Draw the layers var drawLayers = SelectedProfile.Layers .OrderByDescending(l => l.Order) - .Where(l => l.Enabled && - (l.LayerType == LayerType.Keyboard || - l.LayerType == LayerType.KeyboardGif || - l.LayerType == LayerType.Folder)); + .Where(l => l.MustDraw() || (l.Enabled && l.LayerType == LayerType.Folder)) + .ToList(); foreach (var layer in drawLayers) layer.Draw(null, drawingContext, true, false); @@ -124,12 +121,12 @@ namespace Artemis.ViewModels.Profiles if (accentColor == null) return; - var pen = new Pen(new SolidColorBrush((Color)accentColor), 0.4); + var pen = new Pen(new SolidColorBrush((Color) accentColor), 0.4); // Draw the selection outline and resize indicator if (SelectedLayer != null && SelectedLayer.MustDraw()) { - var layerRect = ((KeyboardPropertiesModel)SelectedLayer.Properties).GetRect(); + var layerRect = ((KeyboardPropertiesModel) SelectedLayer.Properties).GetRect(); // Deflate the rect so that the border is drawn on the inside layerRect.Inflate(-0.2, -0.2); diff --git a/Artemis/Artemis/ViewModels/Profiles/Properties/HeadsetPropertiesViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/Properties/HeadsetPropertiesViewModel.cs index 4c2af9cee..2868cb19b 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Properties/HeadsetPropertiesViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/Properties/HeadsetPropertiesViewModel.cs @@ -14,7 +14,7 @@ namespace Artemis.ViewModels.Profiles.Properties : base(gameDataModel) { ProposedProperties = GeneralHelpers.Clone(properties); - Brush = GeneralHelpers.CloneAlt(ProposedProperties.Brush); + Brush = ProposedProperties.Brush.CloneCurrentValue(); } public Brush Brush diff --git a/Artemis/Artemis/ViewModels/Profiles/Properties/KeyboardPropertiesViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/Properties/KeyboardPropertiesViewModel.cs index c2c521f71..e03338fba 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Properties/KeyboardPropertiesViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/Properties/KeyboardPropertiesViewModel.cs @@ -9,16 +9,16 @@ namespace Artemis.ViewModels.Profiles.Properties { public class KeyboardPropertiesViewModel : LayerPropertiesViewModel { + private Brush _brush; private bool _isGif; private KeyboardPropertiesModel _proposedProperties; - private Brush _brush; public KeyboardPropertiesViewModel(IGameDataModel gameDataModel, LayerPropertiesModel properties) : base(gameDataModel) { var keyboardProperties = (KeyboardPropertiesModel) properties; ProposedProperties = GeneralHelpers.Clone(keyboardProperties); - Brush = GeneralHelpers.CloneAlt(ProposedProperties.Brush); + Brush = ProposedProperties.Brush.CloneCurrentValue(); DataModelProps = new BindableCollection(); DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap(gameDataModel)); @@ -51,6 +51,17 @@ namespace Artemis.ViewModels.Profiles.Properties } } + public Brush Brush + { + get { return _brush; } + set + { + if (Equals(value, _brush)) return; + _brush = value; + NotifyOfPropertyChange(() => Brush); + } + } + public bool ShowGif => IsGif; public bool ShowBrush => !IsGif; @@ -65,7 +76,7 @@ namespace Artemis.ViewModels.Profiles.Properties public void BrowseGif() { - var dialog = new OpenFileDialog { Filter = "Animated image file (*.gif)|*.gif" }; + var dialog = new OpenFileDialog {Filter = "Animated image file (*.gif)|*.gif"}; var result = dialog.ShowDialog(); if (result != DialogResult.OK) return; @@ -76,7 +87,6 @@ namespace Artemis.ViewModels.Profiles.Properties public override LayerPropertiesModel GetAppliedProperties() { - HeightProperties.Apply(ProposedProperties); WidthProperties.Apply(ProposedProperties); OpacityProperties.Apply(ProposedProperties); @@ -85,16 +95,5 @@ namespace Artemis.ViewModels.Profiles.Properties properties.Brush = Brush; return properties; } - - public Brush Brush - { - get { return _brush; } - set - { - if (Equals(value, _brush)) return; - _brush = value; - NotifyOfPropertyChange(() => Brush); - } - } } } \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/Profiles/Properties/MousePropertiesViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/Properties/MousePropertiesViewModel.cs index 6fc200580..2dc66c7f0 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Properties/MousePropertiesViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/Properties/MousePropertiesViewModel.cs @@ -15,7 +15,7 @@ namespace Artemis.ViewModels.Profiles.Properties : base(gameDataModel) { ProposedProperties = GeneralHelpers.Clone(properties); - Brush = GeneralHelpers.CloneAlt(ProposedProperties.Brush); + Brush = ProposedProperties.Brush.CloneCurrentValue(); } public Brush Brush