diff --git a/Artemis/Artemis/App.config b/Artemis/Artemis/App.config index 7f7bc23d9..7a342616a 100644 --- a/Artemis/Artemis/App.config +++ b/Artemis/Artemis/App.config @@ -2,24 +2,59 @@ - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 909e2e886..3a0358555 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -38,8 +38,8 @@ https://github.com/SpoinkyNL/Artemis/wiki/Frequently-Asked-Questions-%28FAQ%29 Artemis Artemis - 3 - 1.1.3.3 + 0 + 1.2.0.0 false true true @@ -275,6 +275,9 @@ + + + @@ -282,9 +285,9 @@ - + - + @@ -306,6 +309,11 @@ + + GenericPropertiesView.xaml + + + @@ -503,14 +511,14 @@ - + - - - - + + + + @@ -550,13 +558,13 @@ EventPropertiesView.xaml - + FolderPropertiesView.xaml - + HeadsetPropertiesView.xaml - + KeyboardPropertiesView.xaml @@ -568,7 +576,7 @@ LayerEditorView.xaml - + MousePropertiesView.xaml @@ -594,6 +602,8 @@ Code + + ResXFileCodeGenerator Designer @@ -707,6 +717,10 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + MSBuild:Compile Designer @@ -767,15 +781,15 @@ Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile @@ -791,7 +805,7 @@ MSBuild:Compile Designer - + Designer MSBuild:Compile diff --git a/Artemis/Artemis/ArtemisBootstrapper.cs b/Artemis/Artemis/ArtemisBootstrapper.cs index b4376a51d..9d1ea7ac2 100644 --- a/Artemis/Artemis/ArtemisBootstrapper.cs +++ b/Artemis/Artemis/ArtemisBootstrapper.cs @@ -117,7 +117,7 @@ namespace Artemis private void CheckDuplicateInstances() { bool aIsNewInstance; - Mutex = new Mutex(true, "ArtemisMutex2", out aIsNewInstance); + Mutex = new Mutex(true, "ArtemisMutex", out aIsNewInstance); if (aIsNewInstance) return; diff --git a/Artemis/Artemis/DAL/ProfileProvider.cs b/Artemis/Artemis/DAL/ProfileProvider.cs index 3babec07f..2e5aae995 100644 --- a/Artemis/Artemis/DAL/ProfileProvider.cs +++ b/Artemis/Artemis/DAL/ProfileProvider.cs @@ -58,15 +58,32 @@ namespace Artemis.DAL { if (prof == null) throw new ArgumentNullException(nameof(prof)); - if (!(prof.GameName?.Length > 1) || !(prof.KeyboardSlug?.Length > 1) || !(prof.Name?.Length > 1)) - throw new ArgumentException("Profile is invalid. Name, GameName and KeyboardSlug are required"); - var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}"; - if (!Directory.Exists(path)) - Directory.CreateDirectory(path); + lock (prof) + { + if (!(prof.GameName?.Length > 1) || !(prof.KeyboardSlug?.Length > 1) || !(prof.Name?.Length > 1)) + throw new ArgumentException("Profile is invalid. Name, GameName and KeyboardSlug are required"); - var json = JsonConvert.SerializeObject(prof, Formatting.Indented); - File.WriteAllText(path + $@"\{prof.Name}.json", json); + var path = ProfileFolder + $@"\{prof.KeyboardSlug}\{prof.GameName}"; + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + string json; + + // Should saving fail for whatever reason, catch the exception and log it + // But DON'T touch the profile file. + try + { + json = JsonConvert.SerializeObject(prof, Formatting.Indented); + } + catch (Exception e) + { + Logger.Error(e, "Couldn't save profile '{0}.json'", prof.Name); + return; + } + + File.WriteAllText(path + $@"\{prof.Name}.json", json); + } } private static List ReadProfiles() diff --git a/Artemis/Artemis/DeviceProviders/Corsair/CorsairHeadsets.cs b/Artemis/Artemis/DeviceProviders/Corsair/CorsairHeadsets.cs index 45152ab2c..6feb723f6 100644 --- a/Artemis/Artemis/DeviceProviders/Corsair/CorsairHeadsets.cs +++ b/Artemis/Artemis/DeviceProviders/Corsair/CorsairHeadsets.cs @@ -25,13 +25,16 @@ namespace Artemis.DeviceProviders.Corsair CueSDK.Initialize(); Logger.Debug("Attempted to enable Corsair headset. CanUse: {0}", CanUse); + + if (CanUse) + CueSDK.HeadsetSDK.UpdateMode = UpdateMode.Manual; + return CanUse; } public override void Disable() { - if (CueSDK.IsInitialized) - CueSDK.Reinitialize(); + throw new NotImplementedException("Can only disable a keyboard"); } public override void UpdateDevice(Bitmap bitmap) @@ -51,7 +54,7 @@ namespace Artemis.DeviceProviders.Corsair { var col = ledIndex == 0 ? bitmap.GetPixel(0, 0) - : bitmap.GetPixel((int)((ledIndex + 1) * step - 1), (int)((ledIndex + 1) * step - 1)); + : bitmap.GetPixel((int) ((ledIndex + 1)*step - 1), (int) ((ledIndex + 1)*step - 1)); corsairLed.Color = col; ledIndex++; diff --git a/Artemis/Artemis/DeviceProviders/Corsair/CorsairRGB.cs b/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboards.cs similarity index 97% rename from Artemis/Artemis/DeviceProviders/Corsair/CorsairRGB.cs rename to Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboards.cs index 6fd2fd58a..aa67d094c 100644 --- a/Artemis/Artemis/DeviceProviders/Corsair/CorsairRGB.cs +++ b/Artemis/Artemis/DeviceProviders/Corsair/CorsairKeyboards.cs @@ -11,12 +11,12 @@ using Point = System.Drawing.Point; namespace Artemis.DeviceProviders.Corsair { - public class CorsairRGB : KeyboardProvider + public class CorsairKeyboards : KeyboardProvider { private CorsairKeyboard _keyboard; private ImageBrush _keyboardBrush; - public CorsairRGB(ILogger logger) + public CorsairKeyboards(ILogger logger) { Logger = logger; Name = "Corsair RGB Keyboards"; @@ -68,6 +68,7 @@ namespace Artemis.DeviceProviders.Corsair } Logger.Debug("Corsair SDK reported device as: {0}", _keyboard.DeviceInfo.Model); Slug = "corsair-" + _keyboard.DeviceInfo.Model.Replace(' ', '-').ToLower(); + _keyboard.Brush = _keyboardBrush ?? (_keyboardBrush = new ImageBrush()); } diff --git a/Artemis/Artemis/DeviceProviders/Corsair/CorsairMice.cs b/Artemis/Artemis/DeviceProviders/Corsair/CorsairMice.cs index 8d3d1efc8..706d367e9 100644 --- a/Artemis/Artemis/DeviceProviders/Corsair/CorsairMice.cs +++ b/Artemis/Artemis/DeviceProviders/Corsair/CorsairMice.cs @@ -25,13 +25,16 @@ namespace Artemis.DeviceProviders.Corsair CueSDK.Initialize(); Logger.Debug("Attempted to enable Corsair mice. CanUse: {0}", CanUse); + + if (CanUse) + CueSDK.MouseSDK.UpdateMode = UpdateMode.Manual; + return CanUse; } public override void Disable() { - if (CueSDK.IsInitialized) - CueSDK.Reinitialize(); + throw new NotImplementedException("Can only disable a keyboard"); } public override void UpdateDevice(Bitmap bitmap) diff --git a/Artemis/Artemis/DeviceProviders/DeviceProvider.cs b/Artemis/Artemis/DeviceProviders/DeviceProvider.cs index f68bc3dbf..970fa50ad 100644 --- a/Artemis/Artemis/DeviceProviders/DeviceProvider.cs +++ b/Artemis/Artemis/DeviceProviders/DeviceProvider.cs @@ -45,6 +45,7 @@ namespace Artemis.DeviceProviders { Keyboard, Mouse, - Headset + Headset, + Generic } } \ No newline at end of file diff --git a/Artemis/Artemis/DeviceProviders/Logitech/G810.cs b/Artemis/Artemis/DeviceProviders/Logitech/G810.cs new file mode 100644 index 000000000..8c7b35fbb --- /dev/null +++ b/Artemis/Artemis/DeviceProviders/Logitech/G810.cs @@ -0,0 +1,21 @@ +using System.Windows; +using Artemis.Properties; + +namespace Artemis.DeviceProviders.Logitech +{ + internal class G810 : LogitechKeyboard + { + public G810() + { + Name = "Logitech G810 RGB"; + Slug = "logitech-g910"; // Shares slugs with the G910 because the layout is identical + CantEnableText = "Couldn't connect to your Logitech G810.\n" + + "Please check your cables and updating the Logitech Gaming Software\n" + + "A minimum version of 8.81.15 is required.\n\n" + + "If needed, you can select a different keyboard in Artemis under settings."; + Height = 6; + Width = 21; + PreviewSettings = new PreviewSettings(675, 185, new Thickness(0, 35, 0, 0), Resources.g810); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/DeviceProviders/Logitech/G910.cs b/Artemis/Artemis/DeviceProviders/Logitech/G910.cs new file mode 100644 index 000000000..6a335d180 --- /dev/null +++ b/Artemis/Artemis/DeviceProviders/Logitech/G910.cs @@ -0,0 +1,21 @@ +using System.Windows; +using Artemis.Properties; + +namespace Artemis.DeviceProviders.Logitech +{ + internal class G910 : LogitechKeyboard + { + public G910() + { + Name = "Logitech G910 RGB"; + Slug = "logitech-g910"; + CantEnableText = "Couldn't connect to your Logitech G910.\n" + + "Please check your cables and updating the Logitech Gaming Software\n" + + "A minimum version of 8.81.15 is required.\n\n" + + "If needed, you can select a different keyboard in Artemis under settings."; + Height = 6; + Width = 21; + PreviewSettings = new PreviewSettings(540, 154, new Thickness(25, -80, 0, 0), Resources.g910); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/DeviceProviders/Logitech/LogitechGeneric.cs b/Artemis/Artemis/DeviceProviders/Logitech/LogitechGeneric.cs new file mode 100644 index 000000000..fcf07d3f9 --- /dev/null +++ b/Artemis/Artemis/DeviceProviders/Logitech/LogitechGeneric.cs @@ -0,0 +1,58 @@ +using System; +using System.Drawing; +using Artemis.DeviceProviders.Logitech.Utilities; +using Ninject.Extensions.Logging; + +namespace Artemis.DeviceProviders.Logitech +{ + // TODO: Handle shutdown, maybe implement Disable() afterall? + public class LogitechGeneric : DeviceProvider + { + /// + /// A generic Logitech DeviceProvider. Because the Logitech SDK currently doesn't allow specific + /// device targeting (only very broad per-key-RGB and full RGB etc..) + /// + public LogitechGeneric(ILogger logger) + { + Logger = logger; + Type = DeviceType.Generic; + } + + public ILogger Logger { get; set; } + + public override void UpdateDevice(Bitmap bitmap) + { + if (!CanUse || bitmap == null) + return; + + using (bitmap) + { + var col = bitmap.GetPixel(bitmap.Width/2, bitmap.Height/2); + LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_RGB); + LogitechGSDK.LogiLedSetLighting((int) (col.R/2.55), (int) (col.G/2.55), (int) (col.B/2.55)); + } + } + + public override bool TryEnable() + { + var majorNum = 0; + var minorNum = 0; + var buildNum = 0; + + LogitechGSDK.LogiLedInit(); + LogitechGSDK.LogiLedGetSdkVersion(ref majorNum, ref minorNum, ref buildNum); + + // Turn it into one long number... + var version = int.Parse($"{majorNum}{minorNum}{buildNum}"); + CanUse = version >= 88115; + Logger.Debug("Attempted to enable Logitech generic device. CanUse: {0}", CanUse); + + return CanUse; + } + + public override void Disable() + { + throw new NotImplementedException("Can only disable a keyboard"); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/DeviceProviders/Logitech/Orion.cs b/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs similarity index 82% rename from Artemis/Artemis/DeviceProviders/Logitech/Orion.cs rename to Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs index 4d673194c..32d9cc77d 100644 --- a/Artemis/Artemis/DeviceProviders/Logitech/Orion.cs +++ b/Artemis/Artemis/DeviceProviders/Logitech/LogitechKeyboard.cs @@ -2,36 +2,21 @@ using System.Threading; using System.Windows; using Artemis.DeviceProviders.Logitech.Utilities; -using Artemis.Properties; using Artemis.Utilities; using Artemis.Utilities.LogitechDll; using Microsoft.Win32; namespace Artemis.DeviceProviders.Logitech { - internal class Orion : KeyboardProvider + public abstract class LogitechKeyboard : KeyboardProvider { - public Orion() - { - Name = "Logitech G910 RGB"; - Slug = "logitech-g910"; - CantEnableText = "Couldn't connect to your Logitech G910.\n" + - "Please check your cables and updating the Logitech Gaming Software\n" + - "A minimum version of 8.81.15 is required.\n\n" + - "If needed, you can select a different keyboard in Artemis under settings."; - Height = 6; - Width = 21; - PreviewSettings = new PreviewSettings(540, 154, new Thickness(25, -80, 0, 0), Resources.g910); - } - public override bool CanEnable() { //Check to see if VC++ 2012 x64 is installed. - if (Registry.LocalMachine.OpenSubKey( @"SOFTWARE\Classes\Installer\Dependencies\{ca67548a-5ebe-413a-b50c-4b9ceb6d66c6}") == null) { - CantEnableText = "Couldn't connect to your Logitech G910.\n" + + CantEnableText = "Couldn't connect to your Logitech keyboard.\n" + "The Visual C 2012 Redistributable could not be found, which is required.\n" + "Please download it by going to the following URL:\n\n" + "https://www.microsoft.com/download/confirmation.aspx?id=30679"; @@ -77,9 +62,9 @@ namespace Artemis.DeviceProviders.Logitech Thread.Sleep(200); LogitechGSDK.LogiLedSaveCurrentLighting(); - LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_PERKEY_RGB); // Disable keys we can't color + LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_PERKEY_RGB); LogitechGSDK.LogiLedSetLighting(0, 0, 0); } @@ -92,6 +77,7 @@ namespace Artemis.DeviceProviders.Logitech public override void DrawBitmap(Bitmap bitmap) { + LogitechGSDK.LogiLedSetTargetDevice(LogitechGSDK.LOGI_DEVICETYPE_PERKEY_RGB); LogitechGSDK.LogiLedSetLightingFromBitmap(OrionUtilities.BitmapToByteArray(bitmap)); } } diff --git a/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs b/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs index 242ce0396..3f1bd656a 100644 --- a/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs +++ b/Artemis/Artemis/DeviceProviders/Razer/BlackWidow.cs @@ -27,7 +27,7 @@ namespace Artemis.DeviceProviders.Razer { if (!Chroma.IsSdkAvailable()) return false; - + // Some people have Synapse installed, but not a Chroma keyboard, deal with this var blackWidowFound = Chroma.Instance.Query(Devices.Blackwidow).Connected; var blackWidowTeFound = Chroma.Instance.Query(Devices.BlackwidowTe).Connected; diff --git a/Artemis/Artemis/InjectionModules/ArtemisModules.cs b/Artemis/Artemis/InjectionModules/ArtemisModules.cs index 4aa41678d..9c23101b9 100644 --- a/Artemis/Artemis/InjectionModules/ArtemisModules.cs +++ b/Artemis/Artemis/InjectionModules/ArtemisModules.cs @@ -17,6 +17,7 @@ using Artemis.Profiles.Layers.Animations; using Artemis.Profiles.Layers.Conditions; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Types.Folder; +using Artemis.Profiles.Layers.Types.Generic; using Artemis.Profiles.Layers.Types.Headset; using Artemis.Profiles.Layers.Types.Keyboard; using Artemis.Profiles.Layers.Types.KeyboardGif; @@ -54,13 +55,16 @@ namespace Artemis.InjectionModules #region Devices // Keyboards - Bind().To().InSingletonScope(); - Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); Bind().To().InSingletonScope(); // Mice Bind().To().InSingletonScope(); // Headsets Bind().To().InSingletonScope(); + // Other + Bind().To().InSingletonScope(); #endregion @@ -83,6 +87,7 @@ namespace Artemis.InjectionModules Bind().To(); Bind().To(); Bind().To(); + Bind().To(); #endregion } diff --git a/Artemis/Artemis/Managers/DeviceManager.cs b/Artemis/Artemis/Managers/DeviceManager.cs index 474fe02f2..ad18d36ea 100644 --- a/Artemis/Artemis/Managers/DeviceManager.cs +++ b/Artemis/Artemis/Managers/DeviceManager.cs @@ -30,13 +30,14 @@ namespace Artemis.Managers .Cast().ToList(); MiceProviders = deviceProviders.Where(d => d.Type == DeviceType.Mouse).ToList(); HeadsetProviders = deviceProviders.Where(d => d.Type == DeviceType.Headset).ToList(); + GenericProviders = deviceProviders.Where(d => d.Type == DeviceType.Generic).ToList(); _logger.Info("Intialized DeviceManager with {0} device providers", deviceProviders.Count); } - public List HeadsetProviders { get; set; } - public List MiceProviders { get; set; } + public List HeadsetProviders { get; set; } + public List GenericProviders { get; set; } [Inject] public MetroDialogService DialogService { get; set; } @@ -133,6 +134,8 @@ namespace Artemis.Managers mouseProvider.TryEnableAsync(); foreach (var headsetProvider in HeadsetProviders) headsetProvider.TryEnableAsync(); + foreach (var genericProvider in GenericProviders) + genericProvider.TryEnableAsync(); } /// diff --git a/Artemis/Artemis/Managers/LoopManager.cs b/Artemis/Artemis/Managers/LoopManager.cs index 32abd3fba..56a357077 100644 --- a/Artemis/Artemis/Managers/LoopManager.cs +++ b/Artemis/Artemis/Managers/LoopManager.cs @@ -1,24 +1,25 @@ using System; using System.Drawing; using System.Linq; +using System.Threading; using System.Threading.Tasks; using System.Timers; -using Artemis.Events; +using Artemis.DeviceProviders; using Caliburn.Micro; using Ninject.Extensions.Logging; +using Timer = System.Timers.Timer; namespace Artemis.Managers { /// /// Manages the main programn loop /// - public class LoopManager : IDisposable, IHandle, IHandle + public class LoopManager : IDisposable { private readonly DeviceManager _deviceManager; private readonly EffectManager _effectManager; private readonly ILogger _logger; private readonly Timer _loopTimer; - private Bitmap _keyboardBitmap; public LoopManager(IEventAggregator events, ILogger logger, EffectManager effectManager, DeviceManager deviceManager) @@ -45,19 +46,6 @@ namespace Artemis.Managers { _loopTimer.Stop(); _loopTimer.Dispose(); - _keyboardBitmap?.Dispose(); - } - - public void Handle(ActiveEffectChanged message) - { - if (_deviceManager.ActiveKeyboard != null && _effectManager.ActiveEffect != null) - _keyboardBitmap = _deviceManager.ActiveKeyboard.KeyboardBitmap(_effectManager.ActiveEffect.KeyboardScale); - } - - public void Handle(ActiveKeyboardChanged message) - { - if (_deviceManager.ActiveKeyboard != null && _effectManager.ActiveEffect != null) - _keyboardBitmap = _deviceManager.ActiveKeyboard.KeyboardBitmap(_effectManager.ActiveEffect.KeyboardScale); } public Task StartAsync() @@ -74,6 +62,10 @@ namespace Artemis.Managers if (_deviceManager.ActiveKeyboard == null) _deviceManager.EnableLastKeyboard(); + + while (_deviceManager.ChangingKeyboard) + Thread.Sleep(200); + // If still null, no last keyboard, so stop. if (_deviceManager.ActiveKeyboard == null) { @@ -104,13 +96,11 @@ namespace Artemis.Managers Running = false; _deviceManager.ReleaseActiveKeyboard(); - _keyboardBitmap?.Dispose(); - _keyboardBitmap = null; } private void Render(object sender, ElapsedEventArgs e) { - if (!Running) + if (!Running || _deviceManager.ChangingKeyboard) return; // Stop if no active effect @@ -122,9 +112,6 @@ namespace Artemis.Managers } var renderEffect = _effectManager.ActiveEffect; - if (_deviceManager.ChangingKeyboard || _keyboardBitmap == null) - return; - // Stop if no active keyboard if (_deviceManager.ActiveKeyboard == null) { @@ -143,32 +130,69 @@ namespace Artemis.Managers if (renderEffect.Initialized) renderEffect.Update(); - // Get ActiveEffect's bitmap - Bitmap mouseBitmap = null; - Bitmap headsetBitmap = null; + // Get the devices that must be rendered to var mice = _deviceManager.MiceProviders.Where(m => m.CanUse).ToList(); var headsets = _deviceManager.HeadsetProviders.Where(m => m.CanUse).ToList(); + var generics = _deviceManager.GenericProviders.Where(m => m.CanUse).ToList(); - if (renderEffect.Initialized) - renderEffect.Render(_keyboardBitmap, out mouseBitmap, out headsetBitmap, mice.Any(), headsets.Any()); - - // Draw enabled overlays on top of the renderEffect - foreach (var overlayModel in _effectManager.EnabledOverlays) + // Setup the frame for this tick + using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard)) { - overlayModel.Update(); - overlayModel.RenderOverlay(_keyboardBitmap, ref mouseBitmap, ref headsetBitmap, mice.Any(), - headsets.Any()); + if (renderEffect.Initialized) + renderEffect.Render(frame, !mice.Any() && !headsets.Any() && !generics.Any()); + + // Draw enabled overlays on top of the renderEffect + foreach (var overlayModel in _effectManager.EnabledOverlays) + { + overlayModel.Update(); + overlayModel.RenderOverlay(frame, !mice.Any() && !headsets.Any() && !generics.Any()); + } + + // Update the keyboard + _deviceManager.ActiveKeyboard?.DrawBitmap(frame.KeyboardBitmap); + + // Update the other devices + foreach (var mouse in mice) + mouse.UpdateDevice(frame.MouseBitmap); + foreach (var headset in headsets) + headset.UpdateDevice(frame.HeadsetBitmap); + foreach (var generic in generics) + generic.UpdateDevice(frame.GenericBitmap); } - - // Update mice and headsets - foreach (var mouse in mice) - mouse.UpdateDevice(mouseBitmap); - foreach (var headset in headsets) - headset.UpdateDevice(headsetBitmap); - - // Update the keyboard - _deviceManager.ActiveKeyboard?.DrawBitmap(_keyboardBitmap); } } } + + public class RenderFrame : IDisposable + { + public RenderFrame(KeyboardProvider keyboard) + { + KeyboardBitmap = keyboard.KeyboardBitmap(4); + MouseBitmap = new Bitmap(40, 40); + HeadsetBitmap = new Bitmap(40, 40); + GenericBitmap = new Bitmap(40, 40); + + using (var g = Graphics.FromImage(KeyboardBitmap)) + g.Clear(Color.Black); + using (var g = Graphics.FromImage(MouseBitmap)) + g.Clear(Color.Black); + using (var g = Graphics.FromImage(HeadsetBitmap)) + g.Clear(Color.Black); + using (var g = Graphics.FromImage(GenericBitmap)) + g.Clear(Color.Black); + } + + public Bitmap KeyboardBitmap { get; set; } + public Bitmap MouseBitmap { get; set; } + public Bitmap HeadsetBitmap { get; set; } + public Bitmap GenericBitmap { get; set; } + + public void Dispose() + { + KeyboardBitmap.Dispose(); + MouseBitmap.Dispose(); + HeadsetBitmap.Dispose(); + GenericBitmap.Dispose(); + } + } } \ No newline at end of file diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs index 6d0df6330..1d2693896 100644 --- a/Artemis/Artemis/Managers/MainManager.cs +++ b/Artemis/Artemis/Managers/MainManager.cs @@ -122,9 +122,6 @@ namespace Artemis.Managers if (EffectManager.ActiveEffect != null) EffectManager.DisableInactiveGame(); - if (EffectManager.ActiveEffect is ProfilePreviewModel) - return; - // If the currently active effect is a no longer running game, get rid of it. var activeGame = EffectManager.ActiveEffect as GameModel; if (activeGame != null) diff --git a/Artemis/Artemis/Managers/ProfileManager.cs b/Artemis/Artemis/Managers/ProfileManager.cs index 433d91ac0..2c1861c66 100644 --- a/Artemis/Artemis/Managers/ProfileManager.cs +++ b/Artemis/Artemis/Managers/ProfileManager.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using System.Timers; +using Artemis.Models; using Artemis.Modules.Effects.ProfilePreview; using Artemis.Settings; using Artemis.ViewModels.Abstract; @@ -63,7 +64,7 @@ namespace Artemis.Managers } else { - if (_effectManager.ActiveEffect != ProfilePreviewModel) + if (_effectManager.ActiveEffect != ProfilePreviewModel && !(_effectManager.ActiveEffect is GameModel)) { _logger.Debug("Activate profile preview"); _effectManager.ChangeEffect(ProfilePreviewModel); diff --git a/Artemis/Artemis/Models/EffectModel.cs b/Artemis/Artemis/Models/EffectModel.cs index 18712d07f..3765b85c9 100644 --- a/Artemis/Artemis/Models/EffectModel.cs +++ b/Artemis/Artemis/Models/EffectModel.cs @@ -6,9 +6,8 @@ using System.Windows; using Artemis.Managers; using Artemis.Models.Interfaces; using Artemis.Profiles; +using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; -using Artemis.Profiles.Layers.Types.Headset; -using Artemis.Profiles.Layers.Types.Mouse; using Newtonsoft.Json; namespace Artemis.Models @@ -43,59 +42,61 @@ namespace Artemis.Models public abstract void Update(); // Called after every update - public virtual void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice, - bool renderHeadsets) + /// + /// Renders the currently active profile + /// + /// + /// + public virtual void Render(RenderFrame frame, bool keyboardOnly) { - mouse = null; - headset = null; - if (Profile == null || DataModel == null || MainManager.DeviceManager.ActiveKeyboard == null) return; - // Get all enabled layers who's conditions are met - var renderLayers = GetRenderLayers(renderMice, renderHeadsets); - - // Render the keyboard layer-by-layer - var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); - using (var g = Graphics.FromImage(keyboard)) + lock (DataModel) { - // Fill the bitmap's background with black to avoid trailing colors on some keyboards - g.Clear(Color.Black); - Profile.DrawLayers(g, renderLayers.Where(rl => rl.MustDraw()), DataModel, keyboardRect, false, true); - } + // Get all enabled layers who's conditions are met + var renderLayers = GetRenderLayers(keyboardOnly); - // Render the mouse layer-by-layer - var smallRect = new Rect(0, 0, 40, 40); - mouse = new Bitmap(40, 40); - using (var g = Graphics.FromImage(mouse)) - { - // Not all SDK's handle transparency - g.Clear(Color.Black); - Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType is MouseType), DataModel, smallRect, - false, true); - } + // Render the keyboard layer-by-layer + var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); + using (var g = Graphics.FromImage(frame.KeyboardBitmap)) + { + Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), + DataModel, keyboardRect, false, true); + } + // Render mice layer-by-layer + var devRec = new Rect(0, 0, 40, 40); + using (var g = Graphics.FromImage(frame.MouseBitmap)) + { + Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel, + devRec, false, true); + } + // Render headsets layer-by-layer + using (var g = Graphics.FromImage(frame.HeadsetBitmap)) + { + Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset), + DataModel, devRec, false, true); + } + // Render generic devices layer-by-layer + using (var g = Graphics.FromImage(frame.GenericBitmap)) + { + Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic), + DataModel, devRec, false, true); + } - // Render the headset layer-by-layer - headset = new Bitmap(40, 40); - using (var g = Graphics.FromImage(headset)) - { - // Not all SDK's handle transparency - g.Clear(Color.Black); - Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType is HeadsetType), DataModel, smallRect, - false, true); + // Trace debugging + if (DateTime.Now.AddSeconds(-2) <= LastTrace) + return; + LastTrace = DateTime.Now; + MainManager.Logger.Trace("Effect datamodel as JSON: \r\n{0}", + JsonConvert.SerializeObject(DataModel, Formatting.Indented)); + MainManager.Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count); + foreach (var renderLayer in renderLayers) + MainManager.Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, + renderLayer.LayerType); } - - // Trace debugging - if (DateTime.Now.AddSeconds(-2) <= LastTrace) - return; - LastTrace = DateTime.Now; - MainManager.Logger.Trace("Effect datamodel as JSON: \r\n{0}", - JsonConvert.SerializeObject(DataModel, Formatting.Indented)); - MainManager.Logger.Trace("Effect {0} has to render {1} layers", Name, renderLayers.Count); - foreach (var renderLayer in renderLayers) - MainManager.Logger.Trace("- Layer name: {0}, layer type: {1}", renderLayer.Name, renderLayer.LayerType); } - public abstract List GetRenderLayers(bool renderMice, bool renderHeadsets); + public abstract List GetRenderLayers(bool keyboardOnly); } } \ No newline at end of file diff --git a/Artemis/Artemis/Models/OverlayModel.cs b/Artemis/Artemis/Models/OverlayModel.cs index 8d4ac2335..9657577bb 100644 --- a/Artemis/Artemis/Models/OverlayModel.cs +++ b/Artemis/Artemis/Models/OverlayModel.cs @@ -1,5 +1,4 @@ -using System.Drawing; -using Artemis.Managers; +using Artemis.Managers; namespace Artemis.Models { @@ -28,7 +27,6 @@ namespace Artemis.Models } } - public abstract void RenderOverlay(Bitmap keyboard, ref Bitmap mouse, ref Bitmap headset, bool renderMice, - bool renderHeadsets); + public abstract void RenderOverlay(RenderFrame frame, bool keyboardOnly); } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualization.cs b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualization.cs index a3db59c01..677970011 100644 --- a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualization.cs +++ b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualization.cs @@ -1,28 +1,23 @@ -namespace Artemis.Modules.Effects.AudioVisualizer { - - +using System.ComponentModel; +using System.Configuration; + +namespace Artemis.Modules.Effects.AudioVisualizer +{ // This class allows you to handle specific events on the settings class: // The SettingChanging event is raised before a setting's value is changed. // The PropertyChanged event is raised after a setting's value is changed. // The SettingsLoaded event is raised after the setting values are loaded. // The SettingsSaving event is raised before the setting values are saved. - internal sealed partial class AudioVisualization { - - public AudioVisualization() { - // // To add event handlers for saving and changing settings, uncomment the lines below: - // - // this.SettingChanging += this.SettingChangingEventHandler; - // - // this.SettingsSaving += this.SettingsSavingEventHandler; - // - } - - private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + internal sealed partial class AudioVisualization + { + private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e) + { // Add code to handle the SettingChangingEvent event here. } - - private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + + private void SettingsSavingEventHandler(object sender, CancelEventArgs e) + { // Add code to handle the SettingsSaving event here. } } -} +} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs index aa103501f..9e2dacc18 100644 --- a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs +++ b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs @@ -182,24 +182,20 @@ namespace Artemis.Modules.Effects.AudioVisualizer } } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { return null; } - public override void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice, - bool renderHeadsets) + public override void Render(RenderFrame frame, bool keyboardOnly) { - mouse = null; - headset = null; - if (SpectrumData == null || SoundRectangles == null) return; // Lock the _spectrumData array while busy with it _generating = true; - using (var g = Graphics.FromImage(keyboard)) + using (var g = Graphics.FromImage(frame.KeyboardBitmap)) { foreach (var soundRectangle in SoundRectangles) soundRectangle.Draw(g); diff --git a/Artemis/Artemis/Modules/Effects/Bubbles/Bubbles.cs b/Artemis/Artemis/Modules/Effects/Bubbles/Bubbles.cs index bf183261a..fceb0c983 100644 --- a/Artemis/Artemis/Modules/Effects/Bubbles/Bubbles.cs +++ b/Artemis/Artemis/Modules/Effects/Bubbles/Bubbles.cs @@ -1,28 +1,23 @@ -namespace Artemis.Modules.Effects.Bubbles { - - +using System.ComponentModel; +using System.Configuration; + +namespace Artemis.Modules.Effects.Bubbles +{ // This class allows you to handle specific events on the settings class: // The SettingChanging event is raised before a setting's value is changed. // The PropertyChanged event is raised after a setting's value is changed. // The SettingsLoaded event is raised after the setting values are loaded. // The SettingsSaving event is raised before the setting values are saved. - internal sealed partial class Bubbles { - - public Bubbles() { - // // To add event handlers for saving and changing settings, uncomment the lines below: - // - // this.SettingChanging += this.SettingChangingEventHandler; - // - // this.SettingsSaving += this.SettingsSavingEventHandler; - // - } - - private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { + internal sealed partial class Bubbles + { + private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e) + { // Add code to handle the SettingChangingEvent event here. } - - private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { + + private void SettingsSavingEventHandler(object sender, CancelEventArgs e) + { // Add code to handle the SettingsSaving event here. } } -} +} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Effects/Bubbles/BubblesModel.cs b/Artemis/Artemis/Modules/Effects/Bubbles/BubblesModel.cs index 0ec3ecb48..45c2fe0b0 100644 --- a/Artemis/Artemis/Modules/Effects/Bubbles/BubblesModel.cs +++ b/Artemis/Artemis/Modules/Effects/Bubbles/BubblesModel.cs @@ -88,20 +88,16 @@ namespace Artemis.Modules.Effects.Bubbles } } - public override void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice, - bool renderHeadsets) + public override void Render(RenderFrame frame, bool keyboardOnly) { - mouse = null; - headset = null; - - using (var g = Graphics.FromImage(keyboard)) + using (var g = Graphics.FromImage(frame.KeyboardBitmap)) { foreach (var bubble in _bubbles) bubble.Draw(g); } } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { return null; } diff --git a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs index f66a8b7ad..6566a68fe 100644 --- a/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs +++ b/Artemis/Artemis/Modules/Effects/ProfilePreview/ProfilePreviewModel.cs @@ -5,9 +5,8 @@ using System.Windows; using Artemis.Managers; using Artemis.Models; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; -using Artemis.Profiles.Layers.Types.Headset; -using Artemis.Profiles.Layers.Types.Mouse; namespace Artemis.Modules.Effects.ProfilePreview { @@ -32,47 +31,50 @@ namespace Artemis.Modules.Effects.ProfilePreview { } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { - return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets, true); + return Profile.GetRenderLayers(DataModel, keyboardOnly, true); } - public override void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice, - bool renderHeadsets) + public override void Render(RenderFrame frame, bool keyboardOnly) { - mouse = null; - headset = null; - - if (Profile == null || DataModel == null) + if (Profile == null || DataModel == null || MainManager.DeviceManager.ActiveKeyboard == null) return; - // Get all enabled layers who's conditions are met - var renderLayers = GetRenderLayers(renderMice, renderHeadsets); - - // Render the keyboard layer-by-layer - var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); - using (var g = Graphics.FromImage(keyboard)) + lock (DataModel) { - // Fill the bitmap's background with black to avoid trailing colors on some keyboards - g.Clear(Color.Black); - Profile.DrawLayers(g, renderLayers.Where(rl => rl.MustDraw()), DataModel, keyboardRect, true, true); - } + // Get all enabled layers who's conditions are met + var renderLayers = GetRenderLayers(keyboardOnly); - // Render the mouse layer-by-layer - var smallRect = new Rect(0, 0, 40, 40); - mouse = new Bitmap(40, 40); - using (var g = Graphics.FromImage(mouse)) - { - Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType is MouseType), DataModel, smallRect, - true, true); - } - - // Render the headset layer-by-layer - headset = new Bitmap(40, 40); - using (var g = Graphics.FromImage(headset)) - { - Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType is HeadsetType), DataModel, smallRect, - true, true); + // Render the keyboard layer-by-layer + var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(KeyboardScale); + using (var g = Graphics.FromImage(frame.KeyboardBitmap)) + { + Profile.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Keyboard), + DataModel, + keyboardRect, true, true); + } + // Render mice layer-by-layer + var devRec = new Rect(0, 0, 40, 40); + using (var g = Graphics.FromImage(frame.MouseBitmap)) + { + Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mouse), DataModel, + devRec, true, true); + } + // Render headsets layer-by-layer + using (var g = Graphics.FromImage(frame.HeadsetBitmap)) + { + Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Headset), + DataModel, + devRec, true, true); + } + // Render generic devices layer-by-layer + using (var g = Graphics.FromImage(frame.GenericBitmap)) + { + Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic), + DataModel, + devRec, true, true); + } } } } diff --git a/Artemis/Artemis/Modules/Effects/TypeWave/TypeWaveModel.cs b/Artemis/Artemis/Modules/Effects/TypeWave/TypeWaveModel.cs index 8020ac68d..ff4eb66fa 100644 --- a/Artemis/Artemis/Modules/Effects/TypeWave/TypeWaveModel.cs +++ b/Artemis/Artemis/Modules/Effects/TypeWave/TypeWaveModel.cs @@ -3,7 +3,6 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Windows.Forms; -using Artemis.DeviceProviders.Corsair; using Artemis.DeviceProviders.Logitech.Utilities; using Artemis.Managers; using Artemis.Models; @@ -89,17 +88,13 @@ namespace Artemis.Modules.Effects.TypeWave } } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { return null; } - public override void Render(Bitmap keyboard, out Bitmap mouse, out Bitmap headset, bool renderMice, - bool renderHeadsets) + public override void Render(RenderFrame frame, bool keyboardOnly) { - mouse = null; - headset = null; - if (_waves.Count == 0) return; @@ -113,19 +108,13 @@ namespace Artemis.Modules.Effects.TypeWave path.AddEllipse(_waves[i].Point.X - _waves[i].Size/2, _waves[i].Point.Y - _waves[i].Size/2, _waves[i].Size, _waves[i].Size); - Color fillColor; - if (MainManager.DeviceManager.ActiveKeyboard is CorsairRGB) - fillColor = Color.Black; - else - fillColor = Color.Transparent; - var pthGrBrush = new PathGradientBrush(path) { SurroundColors = new[] {_waves[i].Color}, - CenterColor = fillColor + CenterColor = Color.Transparent }; - using (var g = Graphics.FromImage(keyboard)) + using (var g = Graphics.FromImage(frame.KeyboardBitmap)) { g.FillPath(pthGrBrush, path); pthGrBrush.FocusScales = new PointF(0.3f, 0.8f); diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs index 1e12eeddf..e8ae34117 100644 --- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs +++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileDataModel.cs @@ -24,7 +24,6 @@ namespace Artemis.Modules.Effects.WindowsProfile public int Hours12 { get; set; } public int Minutes { get; set; } public int Seconds { get; set; } - } public class CpuDataModel diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs index 1ce50203f..ce5b05eba 100644 --- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs +++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileModel.cs @@ -60,7 +60,6 @@ namespace Artemis.Modules.Effects.WindowsProfile } - public class WindowsProfileModel : EffectModel { private readonly ILogger _logger; @@ -101,6 +100,19 @@ namespace Artemis.Modules.Effects.WindowsProfile UpdateDay(dataModel); } + #region Current Time + + private void UpdateDay(WindowsProfileDataModel dataModel) + { + var now = DateTime.Now; + dataModel.CurrentTime.Hours24 = int.Parse(now.ToString("HH")); + dataModel.CurrentTime.Hours12 = int.Parse(now.ToString("hh")); + dataModel.CurrentTime.Minutes = int.Parse(now.ToString("mm")); + dataModel.CurrentTime.Seconds = int.Parse(now.ToString("ss")); + } + + #endregion + #region CPU private void SetupCpu() @@ -163,9 +175,9 @@ namespace Artemis.Modules.Effects.WindowsProfile dataModel.Performance.RAMUsage = (int) percentOccupied; } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { - return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets, false); + return Profile.GetRenderLayers(DataModel, keyboardOnly, false); } public static PerformanceCounter GetOverallPerformanceCounter() @@ -194,19 +206,6 @@ namespace Artemis.Modules.Effects.WindowsProfile #endregion - #region Current Time - private void UpdateDay(WindowsProfileDataModel dataModel) - { - - var now = DateTime.Now; - dataModel.CurrentTime.Hours24 = int.Parse(now.ToString("HH")); - dataModel.CurrentTime.Hours12 = int.Parse(now.ToString("hh")); - dataModel.CurrentTime.Minutes = int.Parse(now.ToString("mm")); - dataModel.CurrentTime.Seconds = int.Parse(now.ToString("ss")); - - } - #endregion - #region Spotify public void SetupSpotify() diff --git a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileViewModel.cs b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileViewModel.cs index 511490997..3bf68a2ce 100644 --- a/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileViewModel.cs +++ b/Artemis/Artemis/Modules/Effects/WindowsProfile/WindowsProfileViewModel.cs @@ -57,13 +57,13 @@ namespace Artemis.Modules.Effects.WindowsProfile protected override void OnActivate() { base.OnActivate(); - ProfileEditor.ProfileViewModel.Activate(); + ProfileEditor.Activate(); } protected override void OnDeactivate(bool close) { base.OnDeactivate(close); - ProfileEditor.ProfileViewModel.Deactivate(); + ProfileEditor.Deactivate(); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrike.settings b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrike.settings index cfa6c587e..2e32158e5 100644 --- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrike.settings +++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrike.settings @@ -1,5 +1,7 @@  - + + diff --git a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs index 567c79bca..8d34cba15 100644 --- a/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs +++ b/Artemis/Artemis/Modules/Games/CounterStrike/CounterStrikeModel.cs @@ -64,9 +64,9 @@ namespace Artemis.Modules.Games.CounterStrike } } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { - return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets); + return Profile.GetRenderLayers(DataModel, keyboardOnly); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2.settings b/Artemis/Artemis/Modules/Games/Dota2/Dota2.settings index c3dafb56c..c4c987d69 100644 --- a/Artemis/Artemis/Modules/Games/Dota2/Dota2.settings +++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2.settings @@ -1,5 +1,7 @@  - + + diff --git a/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs b/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs index 1c4fb8fb4..a3ab32b42 100644 --- a/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs +++ b/Artemis/Artemis/Modules/Games/Dota2/Dota2Model.cs @@ -64,9 +64,9 @@ namespace Artemis.Modules.Games.Dota2 DataModel = JsonConvert.DeserializeObject(jsonString); } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { - return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets); + return Profile.GetRenderLayers(DataModel, keyboardOnly); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs index fa92cebaf..3fa5f39fc 100644 --- a/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs +++ b/Artemis/Artemis/Modules/Games/Overwatch/OverwatchModel.cs @@ -115,8 +115,6 @@ namespace Artemis.Modules.Games.Overwatch return; _events.PublishOnUIThread(new RazerColorArrayChanged(colors)); - //MainManager.Logger.Trace("DataModel: \r\n{0}", - // JsonConvert.SerializeObject(gameDataModel, Formatting.Indented)); // Determine general game state ParseGameSate(gameDataModel, colors); @@ -222,9 +220,9 @@ namespace Artemis.Modules.Games.Overwatch gameDataModel.Ability2Ready = colors[2, 4].Equals(Color.FromRgb(4, 141, 144)); } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { - return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets); + return Profile.GetRenderLayers(DataModel, keyboardOnly); } } diff --git a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs index 8d5aa782b..9b7ad7f25 100644 --- a/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs +++ b/Artemis/Artemis/Modules/Games/RocketLeague/RocketLeagueModel.cs @@ -24,6 +24,23 @@ namespace Artemis.Modules.Games.RocketLeague Scale = 4; Enabled = Settings.Enabled; Initialized = false; + + // Generate a new offset when the game is updated + //var offset = new GamePointersCollection + //{ + // Game = "RocketLeague", + // GameVersion = "1.21", + // GameAddresses = new List + // { + // new GamePointer + // { + // Description = "Boost", + // BasePointer = new IntPtr(0x016AD528), + // Offsets = new[] {0x304, 0x8, 0x50, 0x720, 0x224} + // } + // } + //}; + //var res = JsonConvert.SerializeObject(offset, Formatting.Indented); } public int Scale { get; set; } @@ -57,15 +74,13 @@ namespace Artemis.Modules.Games.RocketLeague var offsets = _pointer.GameAddresses.First(ga => ga.Description == "Boost").ToString(); var boostAddress = _memory.GetAddress("\"RocketLeague.exe\"" + offsets); - var boostFloat = _memory.ReadFloat(boostAddress)*100/3; + var boostInt = (int) (_memory.ReadFloat(boostAddress)*100); + if (boostInt > 100) + boostInt = 100; + if (boostInt < 0) + boostInt = 0; - ((RocketLeagueDataModel) DataModel).Boost = (int) Math.Ceiling(boostFloat); - - // Take care of any reading errors resulting in an OutOfMemory on draw - if (((RocketLeagueDataModel) DataModel).Boost < 0) - ((RocketLeagueDataModel) DataModel).Boost = 0; - if (((RocketLeagueDataModel) DataModel).Boost > 100) - ((RocketLeagueDataModel) DataModel).Boost = 100; + ((RocketLeagueDataModel) DataModel).Boost = boostInt; if (DateTime.Now.AddSeconds(-2) <= LastTrace) return; @@ -74,12 +89,12 @@ namespace Artemis.Modules.Games.RocketLeague JsonConvert.SerializeObject(_pointer.GameAddresses, Formatting.Indented)); MainManager.Logger.Trace("RL specific offsets: {0}", offsets); MainManager.Logger.Trace("Boost address: {0}", boostAddress); - MainManager.Logger.Trace("Boost float: {0}", boostFloat); + MainManager.Logger.Trace("Boost int: {0}", boostInt); } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { - return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets); + return Profile.GetRenderLayers(DataModel, keyboardOnly); } } } \ 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 d7c683626..a817bd567 100644 --- a/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs +++ b/Artemis/Artemis/Modules/Games/TheDivision/TheDivisionModel.cs @@ -129,9 +129,9 @@ namespace Artemis.Modules.Games.TheDivision // DataModel updating is done whenever a pipe message is received } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { - return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets); + return Profile.GetRenderLayers(DataModel, keyboardOnly); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs index 3de8ee80f..5bd263f4d 100644 --- a/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs +++ b/Artemis/Artemis/Modules/Games/Witcher3/Witcher3Model.cs @@ -136,9 +136,9 @@ namespace Artemis.Modules.Games.Witcher3 } } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { - return Profile.GetRenderLayers(DataModel, renderMice, renderHeadsets); + return Profile.GetRenderLayers(DataModel, keyboardOnly); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Overlays/VolumeDisplay/VolumeDisplayModel.cs b/Artemis/Artemis/Modules/Overlays/VolumeDisplay/VolumeDisplayModel.cs index 435fa4d0a..d9121701b 100644 --- a/Artemis/Artemis/Modules/Overlays/VolumeDisplay/VolumeDisplayModel.cs +++ b/Artemis/Artemis/Modules/Overlays/VolumeDisplay/VolumeDisplayModel.cs @@ -63,7 +63,7 @@ namespace Artemis.Modules.Overlays.VolumeDisplay } } - public override List GetRenderLayers(bool renderMice, bool renderHeadsets) + public override List GetRenderLayers(bool keyboardOnly) { return null; } @@ -77,13 +77,12 @@ namespace Artemis.Modules.Overlays.VolumeDisplay VolumeDisplay.Transparancy = 255; } - public override void RenderOverlay(Bitmap keyboard, ref Bitmap mouse, ref Bitmap headset, bool renderMice, - bool renderHeadsets) + public override void RenderOverlay(RenderFrame frame, bool keyboardOnly) { if (MainManager.DeviceManager.ActiveKeyboard == null || VolumeDisplay == null || VolumeDisplay.Ttl < 1) return; - using (var g = Graphics.FromImage(keyboard)) + using (var g = Graphics.FromImage(frame.KeyboardBitmap)) { VolumeDisplay.Draw(g); } diff --git a/Artemis/Artemis/ViewModels/Profiles/Layers/LayerPropertiesViewModel.cs b/Artemis/Artemis/Profiles/Layers/Abstract/LayerPropertiesViewModel.cs similarity index 91% rename from Artemis/Artemis/ViewModels/Profiles/Layers/LayerPropertiesViewModel.cs rename to Artemis/Artemis/Profiles/Layers/Abstract/LayerPropertiesViewModel.cs index f633520b0..ef03980cd 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Layers/LayerPropertiesViewModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Abstract/LayerPropertiesViewModel.cs @@ -1,15 +1,14 @@ -using System.Drawing; +using System.Windows.Media; using Artemis.Models.Interfaces; using Artemis.Profiles.Layers.Models; using Caliburn.Micro; -using Brush = System.Windows.Media.Brush; -namespace Artemis.ViewModels.Profiles.Layers +namespace Artemis.Profiles.Layers.Abstract { public abstract class LayerPropertiesViewModel : PropertyChangedBase { - private LayerModel _layerModel; private Brush _brush; + private LayerModel _layerModel; protected LayerPropertiesViewModel(LayerModel layerModel, IDataModel dataModel) { diff --git a/Artemis/Artemis/Profiles/Layers/Animations/SlideDownAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/SlideDownAnimation.cs index e25af27df..74b56819c 100644 --- a/Artemis/Artemis/Profiles/Layers/Animations/SlideDownAnimation.cs +++ b/Artemis/Artemis/Profiles/Layers/Animations/SlideDownAnimation.cs @@ -33,7 +33,7 @@ namespace Artemis.Profiles.Layers.Animations : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); var s1 = new Rect(new Point(rect.X, rect.Y + props.AnimationProgress), new Size(rect.Width, rect.Height)); - var s2 = new Rect(new Point(s1.X, s1.Y - rect.Height), new Size(rect.Width, rect.Height)); + var s2 = new Rect(new Point(s1.X, s1.Y - rect.Height), new Size(rect.Width, rect.Height + .5)); var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale); diff --git a/Artemis/Artemis/Profiles/Layers/Animations/SlideLeftAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/SlideLeftAnimation.cs index ff277c1a9..f77fbcaf4 100644 --- a/Artemis/Artemis/Profiles/Layers/Animations/SlideLeftAnimation.cs +++ b/Artemis/Artemis/Profiles/Layers/Animations/SlideLeftAnimation.cs @@ -33,7 +33,7 @@ namespace Artemis.Profiles.Layers.Animations : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); var s1 = new Rect(new Point(rect.X - props.AnimationProgress, rect.Y), - new Size(rect.Width + 0.05, rect.Height)); + new Size(rect.Width + .5, rect.Height)); var s2 = new Rect(new Point(s1.X + rect.Width, rect.Y), new Size(rect.Width, rect.Height)); var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale); diff --git a/Artemis/Artemis/Profiles/Layers/Animations/SlideRightAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/SlideRightAnimation.cs index 88b02828b..89229b254 100644 --- a/Artemis/Artemis/Profiles/Layers/Animations/SlideRightAnimation.cs +++ b/Artemis/Artemis/Profiles/Layers/Animations/SlideRightAnimation.cs @@ -33,7 +33,7 @@ namespace Artemis.Profiles.Layers.Animations : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); var s1 = new Rect(new Point(rect.X + props.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height)); - var s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + 1, rect.Height)); + var s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + .5, rect.Height)); var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale); diff --git a/Artemis/Artemis/Profiles/Layers/Animations/SlideUpAnimation.cs b/Artemis/Artemis/Profiles/Layers/Animations/SlideUpAnimation.cs index 05c2f8b6c..fc5ab53c6 100644 --- a/Artemis/Artemis/Profiles/Layers/Animations/SlideUpAnimation.cs +++ b/Artemis/Artemis/Profiles/Layers/Animations/SlideUpAnimation.cs @@ -32,7 +32,8 @@ namespace Artemis.Profiles.Layers.Animations ? new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale) : new Rect(props.X*scale, props.Y*scale, props.Width*scale, props.Height*scale); - var s1 = new Rect(new Point(rect.X, rect.Y - props.AnimationProgress), new Size(rect.Width, rect.Height)); + var s1 = new Rect(new Point(rect.X, rect.Y - props.AnimationProgress), + new Size(rect.Width, rect.Height + .5)); var 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); diff --git a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerAnimation.cs b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerAnimation.cs index c0df0f6a4..1b311956b 100644 --- a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerAnimation.cs +++ b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerAnimation.cs @@ -1,10 +1,12 @@ using System.Windows.Media; using Artemis.Profiles.Layers.Models; +using Newtonsoft.Json; namespace Artemis.Profiles.Layers.Interfaces { public interface ILayerAnimation { + [JsonIgnore] string Name { get; } void Update(LayerModel layerModel, bool updateAnimations); void Draw(LayerPropertiesModel props, LayerPropertiesModel applied, DrawingContext c); diff --git a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerType.cs b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerType.cs index e83eb6382..4630d6680 100644 --- a/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerType.cs +++ b/Artemis/Artemis/Profiles/Layers/Interfaces/ILayerType.cs @@ -1,8 +1,9 @@ using System.Collections.Generic; using System.Windows.Media; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Models; -using Artemis.ViewModels.Profiles.Layers; +using Newtonsoft.Json; namespace Artemis.Profiles.Layers.Interfaces { @@ -11,12 +12,21 @@ namespace Artemis.Profiles.Layers.Interfaces /// /// Layer type name /// + [JsonIgnore] string Name { get; } /// - /// Gets whether this type must be drawn on the keyboard/the editor or not + /// Gets whether this type must be drawn in the editor or not. Setting this to true + /// enables moving and resizing the layer /// - bool MustDraw { get; } + [JsonIgnore] + bool ShowInEdtor { get; } + + /// + /// Gets for what kind of device this layer should be drawn. + /// + [JsonIgnore] + DrawType DrawType { get; } /// /// The the thumbnail for this layer type @@ -52,6 +62,16 @@ namespace Artemis.Profiles.Layers.Interfaces /// /// The datamodel to use in the new viewmodel /// The layer to use in the new viewmodel - LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel, List layerAnimations, IDataModel dataModel, LayerModel proposedLayer); + LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel, + List layerAnimations, IDataModel dataModel, LayerModel proposedLayer); + } + + public enum DrawType + { + None, + Keyboard, + Mouse, + Headset, + Generic } } \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs index 5c2cf057e..c026b17c9 100644 --- a/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Models/LayerModel.cs @@ -3,11 +3,10 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Media; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Animations; using Artemis.Profiles.Layers.Conditions; using Artemis.Profiles.Layers.Interfaces; -using Artemis.Profiles.Layers.Types.Headset; using Artemis.Profiles.Layers.Types.Keyboard; -using Artemis.Profiles.Layers.Types.Mouse; using Artemis.Utilities; using Artemis.Utilities.ParentChild; using Newtonsoft.Json; @@ -114,7 +113,7 @@ namespace Artemis.Profiles.Layers.Models return false; parent = parent.Parent; } - return Enabled && LayerType.MustDraw; + return Enabled && LayerType.ShowInEdtor; } /// @@ -146,6 +145,7 @@ namespace Artemis.Profiles.Layers.Models Order = -1, LayerType = new KeyboardType(), LayerCondition = new DataModelCondition(), + LayerAnimation = new NoneAnimation(), Properties = new KeyboardPropertiesModel { Brush = new SolidColorBrush(ColorHelpers.GetRandomRainbowMediaColor()), @@ -192,49 +192,31 @@ namespace Artemis.Profiles.Layers.Models } } - public void Replace(LayerModel layer) - { - layer.Order = Order; - layer.Parent = null; - layer.Profile = null; - - if (Parent != null) - { - Parent.Children.Add(layer); - Parent.Children.Remove(this); - } - else if (Profile != null) - { - Profile.Layers.Add(layer); - Profile.Layers.Remove(this); - } - } - /// /// Generates a flat list containing all layers that must be rendered on the keyboard, /// the first mouse layer to be rendered and the first headset layer to be rendered /// /// The game data model to base the conditions on /// Instance of said game data model - /// Whether or not to include mice in the list - /// Whether or not to include headsets in the list + /// Whether or not to ignore anything but keyboards /// /// A flat list containing all layers that must be rendered - public List GetRenderLayers(IDataModel dataModel, bool includeMice, bool includeHeadsets, - bool ignoreConditions = false) + public List GetRenderLayers(IDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false) { var layers = new List(); - foreach (var layerModel in Children.OrderByDescending(c => c.Order)) + foreach (var layerModel in Children.OrderByDescending(l => l.Order)) { - if (!layerModel.Enabled || !includeMice && layerModel.LayerType is MouseType || - !includeHeadsets && layerModel.LayerType is HeadsetType) + if (!layerModel.Enabled || keyboardOnly && layerModel.LayerType.DrawType != DrawType.Keyboard) continue; - if (!ignoreConditions && !layerModel.ConditionsMet(dataModel)) - continue; + if (!ignoreConditions) + { + if (!layerModel.ConditionsMet(dataModel)) + continue; + } layers.Add(layerModel); - layers.AddRange(layerModel.GetRenderLayers(dataModel, includeMice, includeHeadsets, ignoreConditions)); + layers.AddRange(layerModel.GetRenderLayers(dataModel, keyboardOnly, ignoreConditions)); } return layers; diff --git a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs index 6c80bc49f..fa6aee5a5 100644 --- a/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Models/LayerPropertiesModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Windows; using System.Windows.Media; using Artemis.Utilities.Converters; using Newtonsoft.Json; @@ -7,6 +8,8 @@ namespace Artemis.Profiles.Layers.Models { public abstract class LayerPropertiesModel { + private Brush _brush; + public LayerPropertiesModel(LayerPropertiesModel source = null) { if (source == null) @@ -25,8 +28,6 @@ namespace Artemis.Profiles.Layers.Models Brush = source.Brush; } - private Brush _brush; - public double X { get; set; } public double Y { get; set; } public double Width { get; set; } @@ -38,7 +39,6 @@ namespace Artemis.Profiles.Layers.Models public List DynamicProperties { get; set; } = new List(); [JsonIgnore] - public double AnimationProgress { get; set; } [JsonConverter(typeof(BrushJsonConverter))] @@ -65,5 +65,10 @@ namespace Artemis.Profiles.Layers.Models _brush = cloned; } } + + public Rect GetRect(int scale = 4) + { + return new Rect(X * scale, Y * scale, Width * scale, Height * scale); + } } } \ No newline at end of file diff --git a/Artemis/Artemis/Views/Profiles/Layers/FolderPropertiesView.xaml b/Artemis/Artemis/Profiles/Layers/Types/Folder/FolderPropertiesView.xaml similarity index 90% rename from Artemis/Artemis/Views/Profiles/Layers/FolderPropertiesView.xaml rename to Artemis/Artemis/Profiles/Layers/Types/Folder/FolderPropertiesView.xaml index d4493cfa5..a7648d670 100644 --- a/Artemis/Artemis/Views/Profiles/Layers/FolderPropertiesView.xaml +++ b/Artemis/Artemis/Profiles/Layers/Types/Folder/FolderPropertiesView.xaml @@ -1,4 +1,4 @@ - /// Interaction logic for FolderPropertiesView.xaml diff --git a/Artemis/Artemis/ViewModels/Profiles/Layers/FolderPropertiesViewModel.cs b/Artemis/Artemis/Profiles/Layers/Types/Folder/FolderPropertiesViewModel.cs similarity index 80% rename from Artemis/Artemis/ViewModels/Profiles/Layers/FolderPropertiesViewModel.cs rename to Artemis/Artemis/Profiles/Layers/Types/Folder/FolderPropertiesViewModel.cs index fd0ffaf50..de809f0e1 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Layers/FolderPropertiesViewModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Folder/FolderPropertiesViewModel.cs @@ -1,7 +1,8 @@ using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Models; -namespace Artemis.ViewModels.Profiles.Layers +namespace Artemis.Profiles.Layers.Types.Folder { public class FolderPropertiesViewModel : LayerPropertiesViewModel { diff --git a/Artemis/Artemis/Profiles/Layers/Types/Folder/FolderType.cs b/Artemis/Artemis/Profiles/Layers/Types/Folder/FolderType.cs index 08b24cb63..40bf854fb 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/Folder/FolderType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Folder/FolderType.cs @@ -2,18 +2,20 @@ using System.Windows; using System.Windows.Media; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; using Artemis.Properties; using Artemis.Utilities; -using Artemis.ViewModels.Profiles.Layers; namespace Artemis.Profiles.Layers.Types.Folder { public class FolderType : ILayerType { public string Name { get; } = "Folder"; - public bool MustDraw { get; } = false; + public bool ShowInEdtor { get; } = false; + // FolderType pretents to be a keyboard so it's children get drawn + public DrawType DrawType { get; } = DrawType.Keyboard; public ImageSource DrawThumbnail(LayerModel layer) { diff --git a/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesView.xaml b/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesView.xaml new file mode 100644 index 000000000..9747459ea --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesView.xaml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesView.xaml.cs b/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesView.xaml.cs new file mode 100644 index 000000000..55231c05a --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesView.xaml.cs @@ -0,0 +1,15 @@ +using System.Windows.Controls; + +namespace Artemis.Profiles.Layers.Types.Generic +{ + /// + /// Interaction logic for GenericPropertiesView.xaml + /// + public partial class GenericPropertiesView : UserControl + { + public GenericPropertiesView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesViewModel.cs b/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesViewModel.cs new file mode 100644 index 000000000..42dcc8d09 --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericPropertiesViewModel.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Linq; +using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; +using Artemis.Profiles.Layers.Interfaces; +using Artemis.Profiles.Layers.Models; +using Artemis.Utilities; +using Artemis.ViewModels.Profiles; +using Caliburn.Micro; + +namespace Artemis.Profiles.Layers.Types.Generic +{ + public class GenericPropertiesViewModel : LayerPropertiesViewModel + { + private ILayerAnimation _selectedLayerAnimation; + + public GenericPropertiesViewModel(LayerModel layerModel, IDataModel dataModel, + IEnumerable layerAnimations) : base(layerModel, dataModel) + { + LayerAnimations = new BindableCollection(layerAnimations); + OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", + new BindableCollection(GeneralHelpers.GenerateTypeMap(dataModel)), + layerModel.Properties); + + SelectedLayerAnimation = LayerAnimations.FirstOrDefault(l => l.Name == layerModel.LayerAnimation?.Name) ?? + LayerAnimations.First(l => l.Name == "None"); + } + + public BindableCollection LayerAnimations { get; set; } + public LayerDynamicPropertiesViewModel OpacityProperties { get; set; } + + public ILayerAnimation SelectedLayerAnimation + { + get { return _selectedLayerAnimation; } + set + { + if (Equals(value, _selectedLayerAnimation)) return; + _selectedLayerAnimation = value; + NotifyOfPropertyChange(() => SelectedLayerAnimation); + } + } + + public override void ApplyProperties() + { + OpacityProperties.Apply(LayerModel); + LayerModel.Properties.Brush = Brush; + LayerModel.LayerAnimation = SelectedLayerAnimation; + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericType.cs b/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericType.cs new file mode 100644 index 000000000..0155ce658 --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/Generic/GenericType.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Media; +using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; +using Artemis.Profiles.Layers.Animations; +using Artemis.Profiles.Layers.Interfaces; +using Artemis.Profiles.Layers.Models; +using Artemis.Properties; +using Artemis.Utilities; + +namespace Artemis.Profiles.Layers.Types.Generic +{ + public class GenericType : ILayerType + { + public string Name { get; } = "Generic (Logitech)"; + public bool ShowInEdtor { get; } = false; + public DrawType DrawType { get; } = DrawType.Generic; + + public ImageSource DrawThumbnail(LayerModel layer) + { + var thumbnailRect = new Rect(0, 0, 18, 18); + var visual = new DrawingVisual(); + using (var c = visual.RenderOpen()) + { + c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.generic), thumbnailRect); + } + + var image = new DrawingImage(visual.Drawing); + return image; + } + + public void Draw(LayerModel layer, DrawingContext c) + { + // If an animation is present, let it handle the drawing + if (layer.LayerAnimation != null && !(layer.LayerAnimation is NoneAnimation)) + { + layer.LayerAnimation.Draw(layer.Properties, layer.AppliedProperties, c); + return; + } + + // Otherwise draw the rectangle with its applied dimensions and brush + var rect = new Rect(layer.AppliedProperties.X*4, + layer.AppliedProperties.Y*4, + layer.AppliedProperties.Width*4, + layer.AppliedProperties.Height*4); + + c.PushClip(new RectangleGeometry(rect)); + c.DrawRectangle(layer.AppliedProperties.Brush, null, rect); + c.Pop(); + } + + public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false) + { + // Generic layers are always drawn 10*10 (which is 40*40 when scaled up) + layerModel.Properties.Width = 10; + layerModel.Properties.Height = 10; + layerModel.Properties.X = 0; + layerModel.Properties.Y = 0; + layerModel.Properties.Contain = true; + + layerModel.AppliedProperties = new SimplePropertiesModel(layerModel.Properties); + + if (isPreview || dataModel == null) + return; + + // If not previewing, apply dynamic properties according to datamodel + var props = (SimplePropertiesModel) layerModel.AppliedProperties; + foreach (var dynamicProperty in props.DynamicProperties) + dynamicProperty.ApplyProperty(dataModel, layerModel.AppliedProperties); + } + + public void SetupProperties(LayerModel layerModel) + { + if (layerModel.Properties is SimplePropertiesModel) + return; + + layerModel.Properties = new SimplePropertiesModel(layerModel.Properties); + + // Remove height and width dynamic properties since they are not applicable + layerModel.Properties.DynamicProperties.Remove( + layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Height")); + layerModel.Properties.DynamicProperties.Remove( + layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Width")); + } + + public LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel, + List layerAnimations, IDataModel dataModel, LayerModel proposedLayer) + { + if (layerPropertiesViewModel is GenericPropertiesViewModel) + return layerPropertiesViewModel; + return new GenericPropertiesViewModel(proposedLayer, dataModel, layerAnimations); + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesView.xaml b/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesView.xaml new file mode 100644 index 000000000..a9f29d4e0 --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesView.xaml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Artemis/Artemis/Views/Profiles/Layers/HeadsetPropertiesView.xaml.cs b/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesView.xaml.cs similarity index 86% rename from Artemis/Artemis/Views/Profiles/Layers/HeadsetPropertiesView.xaml.cs rename to Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesView.xaml.cs index 3a7aeb506..59a578bf3 100644 --- a/Artemis/Artemis/Views/Profiles/Layers/HeadsetPropertiesView.xaml.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesView.xaml.cs @@ -1,6 +1,6 @@ using System.Windows.Controls; -namespace Artemis.Views.Profiles.Layers +namespace Artemis.Profiles.Layers.Types.Headset { /// /// Interaction logic for HeadsetPropertiesView.xaml diff --git a/Artemis/Artemis/ViewModels/Profiles/Layers/HeadsetPropertiesViewModel.cs b/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesViewModel.cs similarity index 82% rename from Artemis/Artemis/ViewModels/Profiles/Layers/HeadsetPropertiesViewModel.cs rename to Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesViewModel.cs index 8c3eb2906..76ac3cae1 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Layers/HeadsetPropertiesViewModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetPropertiesViewModel.cs @@ -1,11 +1,14 @@ using System.Collections.Generic; +using System.Linq; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; using Artemis.Utilities; +using Artemis.ViewModels.Profiles; using Caliburn.Micro; -namespace Artemis.ViewModels.Profiles.Layers +namespace Artemis.Profiles.Layers.Types.Headset { public class HeadsetPropertiesViewModel : LayerPropertiesViewModel { @@ -18,6 +21,9 @@ namespace Artemis.ViewModels.Profiles.Layers OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", new BindableCollection(GeneralHelpers.GenerateTypeMap(dataModel)), layerModel.Properties); + + SelectedLayerAnimation = LayerAnimations.FirstOrDefault(l => l.Name == layerModel.LayerAnimation?.Name) ?? + LayerAnimations.First(l => l.Name == "None"); } public BindableCollection LayerAnimations { get; set; } diff --git a/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetType.cs b/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetType.cs index b50921b8b..0b5b6382e 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Headset/HeadsetType.cs @@ -1,21 +1,22 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Linq; using System.Windows; using System.Windows.Media; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Animations; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; using Artemis.Properties; using Artemis.Utilities; -using Artemis.ViewModels.Profiles.Layers; namespace Artemis.Profiles.Layers.Types.Headset { public class HeadsetType : ILayerType { public string Name { get; } = "Headset"; - public bool MustDraw { get; } = false; + public bool ShowInEdtor { get; } = false; + public DrawType DrawType { get; } = DrawType.Headset; public ImageSource DrawThumbnail(LayerModel layer) { @@ -38,10 +39,10 @@ namespace Artemis.Profiles.Layers.Types.Headset } // Otherwise draw the rectangle with its applied dimensions and brush - var rect = new Rect(layer.AppliedProperties.X * 4, - layer.AppliedProperties.Y * 4, - layer.AppliedProperties.Width * 4, - layer.AppliedProperties.Height * 4); + var rect = new Rect(layer.AppliedProperties.X*4, + layer.AppliedProperties.Y*4, + layer.AppliedProperties.Width*4, + layer.AppliedProperties.Height*4); c.PushClip(new RectangleGeometry(rect)); c.DrawRectangle(layer.AppliedProperties.Brush, null, rect); @@ -63,7 +64,7 @@ namespace Artemis.Profiles.Layers.Types.Headset return; // If not previewing, apply dynamic properties according to datamodel - var props = (SimplePropertiesModel)layerModel.AppliedProperties; + var props = (SimplePropertiesModel) layerModel.AppliedProperties; foreach (var dynamicProperty in props.DynamicProperties) dynamicProperty.ApplyProperty(dataModel, layerModel.AppliedProperties); } @@ -74,6 +75,12 @@ namespace Artemis.Profiles.Layers.Types.Headset return; layerModel.Properties = new SimplePropertiesModel(layerModel.Properties); + + // Remove height and width dynamic properties since they are not applicable + layerModel.Properties.DynamicProperties.Remove( + layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Height")); + layerModel.Properties.DynamicProperties.Remove( + layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Width")); } public LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel, diff --git a/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesModel.cs b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesModel.cs index 4ae12f40c..04a48b685 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesModel.cs @@ -1,5 +1,4 @@ -using System.Windows; -using Artemis.Profiles.Layers.Models; +using Artemis.Profiles.Layers.Models; namespace Artemis.Profiles.Layers.Types.Keyboard { @@ -10,10 +9,5 @@ namespace Artemis.Profiles.Layers.Types.Keyboard } public string GifFile { get; set; } - - public Rect GetRect(int scale = 4) - { - return new Rect(X*scale, Y*scale, Width*scale, Height*scale); - } } } \ No newline at end of file diff --git a/Artemis/Artemis/Views/Profiles/Layers/KeyboardPropertiesView.xaml b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesView.xaml similarity index 96% rename from Artemis/Artemis/Views/Profiles/Layers/KeyboardPropertiesView.xaml rename to Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesView.xaml index 4c0d85e02..9e582617b 100644 --- a/Artemis/Artemis/Views/Profiles/Layers/KeyboardPropertiesView.xaml +++ b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesView.xaml @@ -1,4 +1,4 @@ - - + - + diff --git a/Artemis/Artemis/Views/Profiles/Layers/KeyboardPropertiesView.xaml.cs b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesView.xaml.cs similarity index 86% rename from Artemis/Artemis/Views/Profiles/Layers/KeyboardPropertiesView.xaml.cs rename to Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesView.xaml.cs index c63f3beea..cbf3bc8d4 100644 --- a/Artemis/Artemis/Views/Profiles/Layers/KeyboardPropertiesView.xaml.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesView.xaml.cs @@ -1,6 +1,6 @@ using System.Windows.Controls; -namespace Artemis.Views.Profiles.Layers +namespace Artemis.Profiles.Layers.Types.Keyboard { /// /// Interaction logic for KeyboardPropertiesView.xaml diff --git a/Artemis/Artemis/ViewModels/Profiles/Layers/KeyboardPropertiesViewModel.cs b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesViewModel.cs similarity index 88% rename from Artemis/Artemis/ViewModels/Profiles/Layers/KeyboardPropertiesViewModel.cs rename to Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesViewModel.cs index 28a935a4d..69a1f08d0 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Layers/KeyboardPropertiesViewModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardPropertiesViewModel.cs @@ -2,13 +2,14 @@ using System.Linq; using System.Windows.Forms; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; -using Artemis.Profiles.Layers.Types.Keyboard; +using Artemis.Utilities; +using Artemis.ViewModels.Profiles; using Caliburn.Micro; -using static Artemis.Utilities.GeneralHelpers; -namespace Artemis.ViewModels.Profiles.Layers +namespace Artemis.Profiles.Layers.Types.Keyboard { public class KeyboardPropertiesViewModel : LayerPropertiesViewModel { @@ -20,7 +21,8 @@ namespace Artemis.ViewModels.Profiles.Layers { LayerAnimations = new BindableCollection(layerAnimations); - var dataModelProps = new BindableCollection(GenerateTypeMap(dataModel)); + var dataModelProps = + new BindableCollection(GeneralHelpers.GenerateTypeMap(dataModel)); HeightProperties = new LayerDynamicPropertiesViewModel("Height", dataModelProps, layerModel.Properties); WidthProperties = new LayerDynamicPropertiesViewModel("Width", dataModelProps, layerModel.Properties); OpacityProperties = new LayerDynamicPropertiesViewModel("Opacity", dataModelProps, layerModel.Properties); @@ -31,7 +33,7 @@ namespace Artemis.ViewModels.Profiles.Layers public bool ShowGif => IsGif; public bool ShowBrush => !IsGif; - public BindableCollection DataModelProps { get; set; } + public BindableCollection DataModelProps { get; set; } public BindableCollection LayerAnimations { get; set; } public LayerDynamicPropertiesViewModel HeightProperties { get; set; } public LayerDynamicPropertiesViewModel WidthProperties { get; set; } diff --git a/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardType.cs b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardType.cs index a9b3bdfcf..1b510d03d 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Keyboard/KeyboardType.cs @@ -2,19 +2,18 @@ using System.Windows; using System.Windows.Media; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Animations; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; -using Artemis.Utilities; -using Artemis.ViewModels.Profiles.Layers; - namespace Artemis.Profiles.Layers.Types.Keyboard { public class KeyboardType : ILayerType { public string Name { get; } = "Keyboard"; - public bool MustDraw { get; } = true; + public bool ShowInEdtor { get; } = true; + public DrawType DrawType { get; } = DrawType.Keyboard; public ImageSource DrawThumbnail(LayerModel layer) { diff --git a/Artemis/Artemis/Profiles/Layers/Types/KeyboardGif/KeyboardGifType.cs b/Artemis/Artemis/Profiles/Layers/Types/KeyboardGif/KeyboardGifType.cs index e4814e51a..c280b3adc 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/KeyboardGif/KeyboardGifType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/KeyboardGif/KeyboardGifType.cs @@ -4,20 +4,20 @@ using System.IO; using System.Windows; using System.Windows.Media; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Types.Keyboard; using Artemis.Properties; using Artemis.Utilities; -using Artemis.ViewModels.Profiles.Layers; - namespace Artemis.Profiles.Layers.Types.KeyboardGif { internal class KeyboardGifType : ILayerType { public string Name { get; } = "Keyboard - GIF"; - public bool MustDraw { get; } = true; + public bool ShowInEdtor { get; } = true; + public DrawType DrawType { get; } = DrawType.Keyboard; public ImageSource DrawThumbnail(LayerModel layer) { diff --git a/Artemis/Artemis/Views/Profiles/Layers/MousePropertiesView.xaml b/Artemis/Artemis/Profiles/Layers/Types/Mouse/MousePropertiesView.xaml similarity index 95% rename from Artemis/Artemis/Views/Profiles/Layers/MousePropertiesView.xaml rename to Artemis/Artemis/Profiles/Layers/Types/Mouse/MousePropertiesView.xaml index af960162a..55d238e0d 100644 --- a/Artemis/Artemis/Views/Profiles/Layers/MousePropertiesView.xaml +++ b/Artemis/Artemis/Profiles/Layers/Types/Mouse/MousePropertiesView.xaml @@ -1,4 +1,4 @@ - - + - + @@ -40,7 +41,7 @@ TickPlacement="None" TickFrequency="0.05" Value="{Binding Path=LayerModel.Properties.AnimationSpeed, Mode=TwoWay}" Minimum="0.05" Maximum="3" SmallChange="0" IsSnapToTickEnabled="True" Margin="10,12,10,2" Height="24" /> - + /// Interaction logic for MousePropertiesView.xaml diff --git a/Artemis/Artemis/ViewModels/Profiles/Layers/MousePropertiesViewModel.cs b/Artemis/Artemis/Profiles/Layers/Types/Mouse/MousePropertiesViewModel.cs similarity index 93% rename from Artemis/Artemis/ViewModels/Profiles/Layers/MousePropertiesViewModel.cs rename to Artemis/Artemis/Profiles/Layers/Types/Mouse/MousePropertiesViewModel.cs index 32ec88cce..aba7a1a1f 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Layers/MousePropertiesViewModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Mouse/MousePropertiesViewModel.cs @@ -1,12 +1,14 @@ using System.Collections.Generic; using System.Linq; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; using Artemis.Utilities; +using Artemis.ViewModels.Profiles; using Caliburn.Micro; -namespace Artemis.ViewModels.Profiles.Layers +namespace Artemis.Profiles.Layers.Types.Mouse { public class MousePropertiesViewModel : LayerPropertiesViewModel { diff --git a/Artemis/Artemis/Profiles/Layers/Types/Mouse/MouseType.cs b/Artemis/Artemis/Profiles/Layers/Types/Mouse/MouseType.cs index 1ad7d68ba..fdc0e7418 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/Mouse/MouseType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/Mouse/MouseType.cs @@ -1,29 +1,31 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Linq; using System.Windows; using System.Windows.Media; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Animations; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; using Artemis.Properties; using Artemis.Utilities; -using Artemis.ViewModels.Profiles.Layers; - namespace Artemis.Profiles.Layers.Types.Mouse { public class MouseType : ILayerType { public string Name { get; } = "Mouse"; - public bool MustDraw { get; } = false; + public bool ShowInEdtor { get; } = false; + public DrawType DrawType { get; } = DrawType.Mouse; public ImageSource DrawThumbnail(LayerModel layer) { var thumbnailRect = new Rect(0, 0, 18, 18); var visual = new DrawingVisual(); using (var c = visual.RenderOpen()) + { c.DrawImage(ImageUtilities.BitmapToBitmapImage(Resources.mouse), thumbnailRect); + } var image = new DrawingImage(visual.Drawing); return image; @@ -39,10 +41,10 @@ namespace Artemis.Profiles.Layers.Types.Mouse } // Otherwise draw the rectangle with its applied dimensions and brush - var rect = new Rect(layer.AppliedProperties.X * 4, - layer.AppliedProperties.Y * 4, - layer.AppliedProperties.Width * 4, - layer.AppliedProperties.Height * 4); + var rect = new Rect(layer.AppliedProperties.X*4, + layer.AppliedProperties.Y*4, + layer.AppliedProperties.Width*4, + layer.AppliedProperties.Height*4); c.PushClip(new RectangleGeometry(rect)); c.DrawRectangle(layer.AppliedProperties.Brush, null, rect); @@ -64,7 +66,7 @@ namespace Artemis.Profiles.Layers.Types.Mouse return; // If not previewing, apply dynamic properties according to datamodel - var props = (SimplePropertiesModel)layerModel.AppliedProperties; + var props = (SimplePropertiesModel) layerModel.AppliedProperties; foreach (var dynamicProperty in props.DynamicProperties) dynamicProperty.ApplyProperty(dataModel, layerModel.AppliedProperties); } @@ -75,6 +77,12 @@ namespace Artemis.Profiles.Layers.Types.Mouse return; layerModel.Properties = new SimplePropertiesModel(layerModel.Properties); + + // Remove height and width dynamic properties since they are not applicable + layerModel.Properties.DynamicProperties.Remove( + layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Height")); + layerModel.Properties.DynamicProperties.Remove( + layerModel.Properties.DynamicProperties.FirstOrDefault(d => d.LayerProperty == "Width")); } public LayerPropertiesViewModel SetupViewModel(LayerPropertiesViewModel layerPropertiesViewModel, diff --git a/Artemis/Artemis/Profiles/ProfileModel.cs b/Artemis/Artemis/Profiles/ProfileModel.cs index 66f2962d9..4b0e03630 100644 --- a/Artemis/Artemis/Profiles/ProfileModel.cs +++ b/Artemis/Artemis/Profiles/ProfileModel.cs @@ -1,13 +1,13 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows; using System.Windows.Media; +using Artemis.DeviceProviders; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; -using Artemis.Profiles.Layers.Types.Headset; -using Artemis.Profiles.Layers.Types.Keyboard; -using Artemis.Profiles.Layers.Types.Mouse; using Artemis.Utilities; using Artemis.Utilities.ParentChild; using Newtonsoft.Json; @@ -31,9 +31,10 @@ namespace Artemis.Profiles public bool IsDefault { get; set; } public string KeyboardSlug { get; set; } public string GameName { get; set; } + public int Width { get; set; } + public int Height { get; set; } [JsonIgnore] - public DrawingVisual DrawingVisual { get; set; } public void FixOrder() @@ -88,52 +89,30 @@ namespace Artemis.Profiles /// /// The game data model to base the conditions on /// Instance of said game data model - /// Whether or not to include mice in the list - /// Whether or not to include headsets in the list + /// Whether or not to ignore anything but keyboards /// /// A flat list containing all layers that must be rendered - public List GetRenderLayers(IDataModel dataModel, bool includeMice, bool includeHeadsets, - bool ignoreConditions = false) + public List GetRenderLayers(IDataModel dataModel, bool keyboardOnly, bool ignoreConditions = false) { var layers = new List(); foreach (var layerModel in Layers.OrderByDescending(l => l.Order)) { - if (!layerModel.Enabled || !includeMice && layerModel.LayerType is MouseType || - !includeHeadsets && layerModel.LayerType is HeadsetType) + if (!layerModel.Enabled || keyboardOnly && layerModel.LayerType.DrawType != DrawType.Keyboard) continue; - if (!ignoreConditions && !layerModel.ConditionsMet(dataModel)) - continue; + if (!ignoreConditions) + { + if (!layerModel.ConditionsMet(dataModel)) + continue; + } layers.Add(layerModel); - layers.AddRange(layerModel.GetRenderLayers(dataModel, includeMice, includeHeadsets, ignoreConditions)); + layers.AddRange(layerModel.GetRenderLayers(dataModel, keyboardOnly, ignoreConditions)); } return layers; } - /// - /// Looks at all the layers wthin the profile and makes sure they are within boundaries of the given rectangle - /// - /// - public void FixBoundaries(Rect keyboardRectangle) - { - foreach (var layer in GetLayers()) - { - if (!layer.LayerType.MustDraw) - continue; - - var props = (KeyboardPropertiesModel) layer.Properties; - var layerRect = new Rect(new Point(props.X, props.Y), new Size(props.Width, props.Height)); - if (keyboardRectangle.Contains(layerRect)) - continue; - - props.X = 0; - props.Y = 0; - layer.Properties = props; - } - } - /// /// Draw all the given layers on the given rect /// @@ -168,6 +147,47 @@ namespace Artemis.Profiles g.DrawImage(bmp, new PointF(0, 0)); } + /// + /// Looks at all the layers wthin the profile and makes sure they are within boundaries of the given rectangle + /// + /// + public void FixBoundaries(Rect keyboardRectangle) + { + foreach (var layer in GetLayers()) + { + if (!layer.LayerType.ShowInEdtor) + continue; + + var props = layer.Properties; + var layerRect = new Rect(new Point(props.X, props.Y), new Size(props.Width, props.Height)); + if (keyboardRectangle.Contains(layerRect)) + continue; + + props.X = 0; + props.Y = 0; + layer.Properties = props; + } + } + + /// + /// Resizes layers that are shown in the editor and match exactly the full keyboard widht and height + /// + /// The keyboard the profile was made for + /// The new keyboard to adjust the layers for + public void ResizeLayers(KeyboardProvider target) + { + foreach (var layer in GetLayers()) + { + if (!layer.LayerType.ShowInEdtor || + !(Math.Abs(layer.Properties.Width - Width) < 0.01) || + !(Math.Abs(layer.Properties.Height - Height) < 0.01)) + continue; + + layer.Properties.Width = target.Width; + layer.Properties.Height = target.Height; + } + } + #region Compare protected bool Equals(ProfileModel other) diff --git a/Artemis/Artemis/Properties/Resources.Designer.cs b/Artemis/Artemis/Properties/Resources.Designer.cs index e7e5363ad..a531595d2 100644 --- a/Artemis/Artemis/Properties/Resources.Designer.cs +++ b/Artemis/Artemis/Properties/Resources.Designer.cs @@ -158,6 +158,16 @@ namespace Artemis.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap g810 { + get { + object obj = ResourceManager.GetObject("g810", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -168,6 +178,16 @@ namespace Artemis.Properties { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap generic { + get { + object obj = ResourceManager.GetObject("generic", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/Artemis/Artemis/Properties/Resources.resx b/Artemis/Artemis/Properties/Resources.resx index 3db4fb76e..efe0589cc 100644 --- a/Artemis/Artemis/Properties/Resources.resx +++ b/Artemis/Artemis/Properties/Resources.resx @@ -181,4 +181,10 @@ ..\Resources\Witcher3\Witcher3Artemis.zip;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\Keyboards\g810.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\generic.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/Keyboards/default-profiles.zip b/Artemis/Artemis/Resources/Keyboards/default-profiles.zip index 93c402655..fc967a61f 100644 Binary files a/Artemis/Artemis/Resources/Keyboards/default-profiles.zip and b/Artemis/Artemis/Resources/Keyboards/default-profiles.zip differ diff --git a/Artemis/Artemis/Resources/Keyboards/g810.png b/Artemis/Artemis/Resources/Keyboards/g810.png new file mode 100644 index 000000000..a0c7195b7 Binary files /dev/null and b/Artemis/Artemis/Resources/Keyboards/g810.png differ diff --git a/Artemis/Artemis/Resources/generic.png b/Artemis/Artemis/Resources/generic.png new file mode 100644 index 000000000..c932ab815 Binary files /dev/null and b/Artemis/Artemis/Resources/generic.png differ diff --git a/Artemis/Artemis/Utilities/Converters/JsonConverters.cs b/Artemis/Artemis/Utilities/Converters/JsonConverters.cs index cfc95ae1f..49658f291 100644 --- a/Artemis/Artemis/Utilities/Converters/JsonConverters.cs +++ b/Artemis/Artemis/Utilities/Converters/JsonConverters.cs @@ -8,7 +8,7 @@ using Newtonsoft.Json.Linq; namespace Artemis.Utilities.Converters { /// - /// Stores a brush by temporarily serializing it to XAML because Json.NET has trouble + /// Stores a brush by temporarily serializing it to XAML because Json.NET has trouble /// saving it as JSON /// public class BrushJsonConverter : JsonConverter diff --git a/Artemis/Artemis/Utilities/Converters/ValueConverters.cs b/Artemis/Artemis/Utilities/Converters/ValueConverters.cs index 7af474bfb..b92116b6b 100644 --- a/Artemis/Artemis/Utilities/Converters/ValueConverters.cs +++ b/Artemis/Artemis/Utilities/Converters/ValueConverters.cs @@ -68,12 +68,12 @@ namespace Artemis.Utilities.Converters { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return value == null ? 0.0 : ((TimeSpan)value).TotalMilliseconds; + return value == null ? 0.0 : ((TimeSpan) value).TotalMilliseconds; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { - return value == null ? new TimeSpan() : TimeSpan.FromMilliseconds((double)value); + return value == null ? new TimeSpan() : TimeSpan.FromMilliseconds((double) value); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Utilities/GeneralHelpers.cs b/Artemis/Artemis/Utilities/GeneralHelpers.cs index 3eb2c5ac2..58fb17d1d 100644 --- a/Artemis/Artemis/Utilities/GeneralHelpers.cs +++ b/Artemis/Artemis/Utilities/GeneralHelpers.cs @@ -55,7 +55,7 @@ namespace Artemis.Utilities ObjectCreationHandling = ObjectCreationHandling.Replace, TypeNameHandling = TypeNameHandling.Auto }; - return (T)JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source), source.GetType(), + return (T) JsonConvert.DeserializeObject(JsonConvert.SerializeObject(source), source.GetType(), deserializeSettings); } diff --git a/Artemis/Artemis/Utilities/Updater.cs b/Artemis/Artemis/Utilities/Updater.cs index 945832c4b..587cc74c8 100644 --- a/Artemis/Artemis/Utilities/Updater.cs +++ b/Artemis/Artemis/Utilities/Updater.cs @@ -15,12 +15,12 @@ namespace Artemis.Utilities { public static class Updater { - public static int CurrentVersion = 113; + public static int CurrentVersion = 120; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public static async Task CheckForUpdate(MetroDialogService dialogService) { - Logger.Info("Checking for updates - Current version: 1.1.3"); + Logger.Info("Checking for updates - Current version: 1.2.0"); if (!General.Default.CheckForUpdates) return null; diff --git a/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs b/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs index 486a8b810..b3df40c87 100644 --- a/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs +++ b/Artemis/Artemis/ViewModels/Abstract/GameViewModel.cs @@ -108,13 +108,13 @@ namespace Artemis.ViewModels.Abstract protected override void OnActivate() { base.OnActivate(); - ProfileEditor.ProfileViewModel.Activate(); + ProfileEditor.Activate(); } protected override void OnDeactivate(bool close) { base.OnDeactivate(close); - ProfileEditor.ProfileViewModel.Deactivate(); + ProfileEditor.Deactivate(); } } diff --git a/Artemis/Artemis/ViewModels/Profiles/Events/EventPropertiesViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/Events/EventPropertiesViewModel.cs index 8b1af58c7..62b65afe7 100644 --- a/Artemis/Artemis/ViewModels/Profiles/Events/EventPropertiesViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/Events/EventPropertiesViewModel.cs @@ -3,7 +3,6 @@ using Artemis.Profiles.Layers.Models; using Artemis.Utilities; using Caliburn.Micro; - namespace Artemis.ViewModels.Profiles.Events { public class EventPropertiesViewModel : PropertyChangedBase diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs index db5f5c219..81f1b05ec 100644 --- a/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/LayerConditionViewModel.cs @@ -213,7 +213,7 @@ namespace Artemis.ViewModels.Profiles SelectedDataModelProp = DataModelProps.FirstOrDefault(m => m.Path == LayerConditionModel.Field); SelectedOperator = Operators.FirstOrDefault(o => o.Value == LayerConditionModel.Operator); LayerConditionModel.Type = SelectedDataModelProp.Type; - if (LayerConditionModel.Type == "Enum") + if (LayerConditionModel.Type == "Enum" || LayerConditionModel.Type == "Boolean") SelectedEnum = LayerConditionModel.Value; else UserValue = LayerConditionModel.Value; diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs index bd5061cbd..3bfc489be 100644 --- a/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/LayerDynamicPropertiesViewModel.cs @@ -5,7 +5,6 @@ using Artemis.Utilities; using Caliburn.Micro; using Castle.Core.Internal; - namespace Artemis.ViewModels.Profiles { public sealed class LayerDynamicPropertiesViewModel : PropertyChangedBase diff --git a/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs index f43f71a54..0dfea8c36 100644 --- a/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/LayerEditorViewModel.cs @@ -4,6 +4,7 @@ using System.ComponentModel; using System.IO; using System.Linq; using Artemis.Models.Interfaces; +using Artemis.Profiles.Layers.Abstract; using Artemis.Profiles.Layers.Interfaces; using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Types.Keyboard; @@ -11,9 +12,7 @@ using Artemis.Profiles.Layers.Types.KeyboardGif; using Artemis.Services; using Artemis.Utilities; using Artemis.ViewModels.Profiles.Events; -using Artemis.ViewModels.Profiles.Layers; using Caliburn.Micro; - using Newtonsoft.Json; using Ninject; @@ -35,20 +34,20 @@ namespace Artemis.ViewModels.Profiles _dataModel = dataModel; _layerAnimations = layerAnimations; + LayerTypes = new BindableCollection(layerTypes); + DataModelProps = new BindableCollection( + GeneralHelpers.GenerateTypeMap(dataModel)); + Layer = layer; ProposedLayer = GeneralHelpers.Clone(layer); if (Layer.Properties == null) Layer.SetupProperties(); - LayerTypes = new BindableCollection(layerTypes); - DataModelProps = new BindableCollection( - GeneralHelpers.GenerateTypeMap(dataModel)); LayerConditionVms = new BindableCollection( layer.Properties.Conditions.Select(c => new LayerConditionViewModel(this, c, DataModelProps))); PropertyChanged += PropertiesViewModelHandler; - PreSelect(); } @@ -166,8 +165,25 @@ namespace Artemis.ViewModels.Profiles public void Apply() { LayerPropertiesViewModel?.ApplyProperties(); - Layer = GeneralHelpers.Clone(ProposedLayer); - + var appliedLayer = GeneralHelpers.Clone(ProposedLayer); + + // Fix relations + if (Layer.Parent != null) + { + Layer.Parent.Children.Add(appliedLayer); + Layer.Parent.Children.Remove(Layer); + } + else + { + Layer.Profile.Layers.Add(appliedLayer); + Layer.Profile.Layers.Remove(Layer); + } + appliedLayer.Children.Clear(); + foreach (var layerModel in Layer.Children) + appliedLayer.Children.Add(layerModel); + + Layer = appliedLayer; + // TODO: EventPropVM must have layer too if (EventPropertiesViewModel != null) Layer.EventProperties = EventPropertiesViewModel.GetAppliedProperties(); @@ -201,8 +217,20 @@ namespace Artemis.ViewModels.Profiles foreach (var conditionViewModel in LayerConditionVms) ProposedLayer.Properties.Conditions.Add(conditionViewModel.LayerConditionModel); + // Ignore children on the comparison + var currentNoChildren = GeneralHelpers.Clone(Layer); + currentNoChildren.Children.Clear(); + // If not a keyboard, ignore size and position + if (ProposedLayer.LayerType.DrawType != DrawType.Keyboard) + { + ProposedLayer.Properties.Width = currentNoChildren.Properties.Width; + ProposedLayer.Properties.Height = currentNoChildren.Properties.Height; + ProposedLayer.Properties.X = currentNoChildren.Properties.X; + ProposedLayer.Properties.Y = currentNoChildren.Properties.Y; + ProposedLayer.Properties.Contain = currentNoChildren.Properties.Contain; + } - var current = JsonConvert.SerializeObject(Layer, Formatting.Indented); + var current = JsonConvert.SerializeObject(currentNoChildren, Formatting.Indented); var proposed = JsonConvert.SerializeObject(ProposedLayer, Formatting.Indented); if (current.Equals(proposed)) diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs index acda2190d..3e2929dd5 100644 --- a/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/ProfileEditorViewModel.cs @@ -1,8 +1,10 @@ -using System.ComponentModel; +using System; +using System.ComponentModel; using System.Dynamic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Timers; using System.Windows.Forms; using System.Windows.Input; using System.Windows.Media; @@ -21,12 +23,12 @@ using Artemis.Utilities; using Caliburn.Micro; using GongSolutions.Wpf.DragDrop; using MahApps.Metro.Controls.Dialogs; - using Ninject; using DragDropEffects = System.Windows.DragDropEffects; using IDropTarget = GongSolutions.Wpf.DragDrop.IDropTarget; using MouseEventArgs = System.Windows.Input.MouseEventArgs; using Screen = Caliburn.Micro.Screen; +using Timer = System.Timers.Timer; namespace Artemis.ViewModels.Profiles { @@ -35,9 +37,11 @@ namespace Artemis.ViewModels.Profiles private readonly EffectModel _gameModel; private readonly ILayerEditorVmFactory _layerEditorVmFactory; private readonly MainManager _mainManager; + private readonly Timer _saveTimer; private ImageSource _keyboardPreview; private BindableCollection _layers; private BindableCollection _profiles; + private bool _saving; private ProfileModel _selectedProfile; public ProfileEditorViewModel(IEventAggregator events, MainManager mainManager, EffectModel gameModel, @@ -56,8 +60,13 @@ namespace Artemis.ViewModels.Profiles events.Subscribe(this); - ProfileViewModel.PropertyChanged += PropertyChangeHandler; - PropertyChanged += PropertyChangeHandler; + + PropertyChanged += EditorStateHandler; + ProfileViewModel.PropertyChanged += LayerSelectedHandler; + + _saveTimer = new Timer(5000); + _saveTimer.Elapsed += ProfileSaveHandler; + LoadProfiles(); } @@ -201,38 +210,16 @@ namespace Artemis.ViewModels.Profiles LoadProfiles(); } - /// - /// Handles refreshing the layer preview - /// - /// - /// - private void PropertyChangeHandler(object sender, PropertyChangedEventArgs e) + public void Activate() { - if (e.PropertyName == "KeyboardPreview") - return; + ProfileViewModel.Activate(); + _saveTimer.Start(); + } - if (e.PropertyName == "SelectedLayer") - { - NotifyOfPropertyChange(() => LayerSelected); - return; - } - - if (SelectedProfile != null) - ProfileProvider.AddOrUpdate(SelectedProfile); - - if (e.PropertyName != "SelectedProfile") - return; - - // Update editor enabled state - NotifyOfPropertyChange(() => EditorEnabled); - // Update ProfileViewModel - ProfileViewModel.SelectedProfile = SelectedProfile; - // Update interface - Layers.Clear(); - if (SelectedProfile != null) - Layers.AddRange(SelectedProfile.Layers); - - NotifyOfPropertyChange(() => ProfileSelected); + public void Deactivate() + { + ProfileViewModel.Deactivate(); + _saveTimer.Stop(); } /// @@ -267,7 +254,8 @@ namespace Artemis.ViewModels.Profiles if (ProfileViewModel.SelectedLayer == null) return; - EditLayer(ProfileViewModel.SelectedLayer); + var selectedLayer = ProfileViewModel.SelectedLayer; + EditLayer(selectedLayer); } /// @@ -276,8 +264,12 @@ namespace Artemis.ViewModels.Profiles /// The layer to open the view for public void EditLayer(LayerModel layer) { + if (layer == null) + return; + IWindowManager manager = new WindowManager(); var editorVm = _layerEditorVmFactory.CreateLayerEditorVm(_gameModel.DataModel, layer); + dynamic settings = new ExpandoObject(); var icon = ImageUtilities.GenerateWindowIcon(); @@ -286,9 +278,9 @@ namespace Artemis.ViewModels.Profiles manager.ShowDialog(editorVm, null, settings); - // The layer editor VM may have created a new instance of the layer, reapply it to the list - layer.Replace(editorVm.Layer); - layer = editorVm.Layer; + //// The layer editor VM may have created a new instance of the layer, reapply it to the list + //layer.Replace(editorVm.Layer); + //layer = editorVm.Layer; // If the layer was a folder, but isn't anymore, assign it's children to it's parent. if (!(layer.LayerType is FolderType) && layer.Children.Any()) @@ -316,10 +308,10 @@ namespace Artemis.ViewModels.Profiles /// /// Adds a new layer to the profile and selects it /// - public void AddLayer() + public LayerModel AddLayer() { if (SelectedProfile == null) - return; + return null; // Create a new layer var layer = LayerModel.CreateLayer(); @@ -333,6 +325,20 @@ namespace Artemis.ViewModels.Profiles } UpdateLayerList(layer); + return layer; + } + + public LayerModel AddFolder() + { + var layer = AddLayer(); + if (layer == null) + return null; + + layer.Name = "New folder"; + layer.LayerType = new FolderType(); + layer.LayerType.SetupProperties(layer); + + return layer; } /// @@ -408,6 +414,8 @@ namespace Artemis.ViewModels.Profiles { var clone = GeneralHelpers.Clone(layer); layer.InsertAfter(clone); + foreach (var layerModel in layer.Children) + clone.Children.Add(GeneralHelpers.Clone(layerModel)); UpdateLayerList(clone); } @@ -487,6 +495,8 @@ namespace Artemis.ViewModels.Profiles { Name = name, KeyboardSlug = _mainManager.DeviceManager.ActiveKeyboard.Slug, + Width = _mainManager.DeviceManager.ActiveKeyboard.Width, + Height = _mainManager.DeviceManager.ActiveKeyboard.Height, GameName = _gameModel.Name }; @@ -613,7 +623,8 @@ namespace Artemis.ViewModels.Profiles } // Verify the keyboard - if (profile.KeyboardSlug != _mainManager.DeviceManager.ActiveKeyboard.Slug) + var deviceManager = _mainManager.DeviceManager; + if (profile.KeyboardSlug != deviceManager.ActiveKeyboard.Slug) { var adjustKeyboard = await DialogService.ShowQuestionMessageBox("Profile not inteded for this keyboard", $"Watch out, this profile wasn't ment for this keyboard, but for the {profile.KeyboardSlug}. " + @@ -622,9 +633,16 @@ namespace Artemis.ViewModels.Profiles if (!adjustKeyboard.Value) return; - profile.KeyboardSlug = _mainManager.DeviceManager.ActiveKeyboard.Slug; + // Resize layers that are on the full keyboard width + profile.ResizeLayers(deviceManager.ActiveKeyboard); + // Put layers back into the canvas if they fell outside it + profile.FixBoundaries(deviceManager.ActiveKeyboard.KeyboardRectangle(1)); + + // Setup profile metadata to match the new keyboard + profile.KeyboardSlug = deviceManager.ActiveKeyboard.Slug; + profile.Width = deviceManager.ActiveKeyboard.Width; + profile.Height = deviceManager.ActiveKeyboard.Height; profile.IsDefault = false; - profile.FixBoundaries(_mainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(1)); } // Verify the name @@ -656,5 +674,48 @@ namespace Artemis.ViewModels.Profiles ProfileProvider.ExportProfile(SelectedProfile, dialog.FileName); } + + private void EditorStateHandler(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName != "SelectedProfile") + return; + + // Update editor enabled state + NotifyOfPropertyChange(() => EditorEnabled); + // Update ProfileViewModel + ProfileViewModel.SelectedProfile = SelectedProfile; + // Update interface + Layers.Clear(); + + if (SelectedProfile != null) + Layers.AddRange(SelectedProfile.Layers); + + NotifyOfPropertyChange(() => ProfileSelected); + } + + private void LayerSelectedHandler(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName != "SelectedLayer") + return; + + NotifyOfPropertyChange(() => LayerSelected); + } + + private void ProfileSaveHandler(object sender, ElapsedEventArgs e) + { + if (_saving || SelectedProfile == null) + return; + + _saving = true; + try + { + ProfileProvider.AddOrUpdate(SelectedProfile); + } + catch (Exception) + { + // ignored + } + _saving = false; + } } } \ No newline at end of file diff --git a/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs b/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs index 4f7b0aede..aa567639c 100644 --- a/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs +++ b/Artemis/Artemis/ViewModels/Profiles/ProfileViewModel.cs @@ -110,11 +110,12 @@ namespace Artemis.ViewModels.Profiles drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(0, 0, 0, 0)), null, keyboardRect); // Draw the layers - var drawLayers = SelectedProfile.GetRenderLayers(new ProfilePreviewDataModel(), false, false, true); + var drawLayers = SelectedProfile.GetRenderLayers(new ProfilePreviewDataModel(), false, true); foreach (var layer in drawLayers) { layer.Update(null, true, false); - layer.Draw(null, drawingContext, true, false); + if (layer.LayerType.ShowInEdtor) + layer.Draw(null, drawingContext, true, false); } // Get the selection color @@ -127,7 +128,7 @@ namespace Artemis.ViewModels.Profiles // Draw the selection outline and resize indicator if (SelectedLayer != null && SelectedLayer.MustDraw()) { - var layerRect = ((KeyboardPropertiesModel) SelectedLayer.Properties).GetRect(); + var layerRect = SelectedLayer.Properties.GetRect(); // Deflate the rect so that the border is drawn on the inside layerRect.Inflate(-0.2, -0.2); @@ -200,9 +201,7 @@ namespace Artemis.ViewModels.Profiles var hoverLayer = SelectedProfile.GetLayers() .Where(l => l.MustDraw()) - .FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties) - .GetRect(1) - .Contains(x, y)); + .FirstOrDefault(l => l.Properties.GetRect(1).Contains(x, y)); SelectedLayer = hoverLayer; } @@ -222,8 +221,7 @@ namespace Artemis.ViewModels.Profiles var y = pos.Y/((double) keyboard.PreviewSettings.Height/keyboard.Height); var hoverLayer = SelectedProfile.GetLayers() .Where(l => l.MustDraw()) - .FirstOrDefault(l => ((KeyboardPropertiesModel) l.Properties) - .GetRect(1).Contains(x, y)); + .FirstOrDefault(l => l.Properties.GetRect(1).Contains(x, y)); HandleDragging(e, x, y, hoverLayer); @@ -233,11 +231,10 @@ namespace Artemis.ViewModels.Profiles return; } - // Turn the mouse pointer into a hand if hovering over an active layer if (hoverLayer == SelectedLayer) { - var rect = ((KeyboardPropertiesModel) hoverLayer.Properties).GetRect(1); + var rect = hoverLayer.Properties.GetRect(1); KeyboardPreviewCursor = Math.Sqrt(Math.Pow(x - rect.BottomRight.X, 2) + Math.Pow(y - rect.BottomRight.Y, 2)) < 0.6 ? Cursors.SizeNWSE @@ -276,16 +273,15 @@ namespace Artemis.ViewModels.Profiles return; } - if (SelectedLayer == null) + if (SelectedLayer == null || (SelectedLayer.LayerType != null && !SelectedLayer.LayerType.ShowInEdtor)) return; // Setup the dragging state on mouse press if (_draggingLayerOffset == null && hoverLayer != null && e.LeftButton == MouseButtonState.Pressed) { - var layerRect = ((KeyboardPropertiesModel) hoverLayer.Properties).GetRect(1); - var selectedProps = (KeyboardPropertiesModel) SelectedLayer.Properties; + var layerRect = hoverLayer.Properties.GetRect(1); - _draggingLayerOffset = new Point(x - selectedProps.X, y - selectedProps.Y); + _draggingLayerOffset = new Point(x - SelectedLayer.Properties.X, y - SelectedLayer.Properties.Y); _draggingLayer = hoverLayer; // Detect dragging if cursor is in the bottom right _resizing = Math.Sqrt(Math.Pow(x - layerRect.BottomRight.X, 2) + @@ -295,8 +291,7 @@ namespace Artemis.ViewModels.Profiles if (_draggingLayerOffset == null || _draggingLayer == null || (_draggingLayer != SelectedLayer)) return; - var draggingProps = (KeyboardPropertiesModel) _draggingLayer?.Properties; - + var draggingProps = _draggingLayer.Properties; // If no setup or reset was done, handle the actual dragging action if (_resizing) { diff --git a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml index 1ea2699c1..8a03e5159 100644 --- a/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml +++ b/Artemis/Artemis/Views/Flyouts/FlyoutSettingsView.xaml @@ -113,7 +113,7 @@ - +