diff --git a/Artemis/Artemis/KeyboardProviders/Corsair/CorsairRGB.cs b/Artemis/Artemis/KeyboardProviders/Corsair/CorsairRGB.cs index af78cc0ec..ccd01ceb4 100644 --- a/Artemis/Artemis/KeyboardProviders/Corsair/CorsairRGB.cs +++ b/Artemis/Artemis/KeyboardProviders/Corsair/CorsairRGB.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Drawing; +using System.Drawing; using System.Threading; using System.Windows; using Artemis.Properties; @@ -9,7 +8,6 @@ using CUE.NET.Brushes; using CUE.NET.Devices.Generic.Enums; using CUE.NET.Devices.Keyboard; using CUE.NET.Exceptions; -using Point = System.Drawing.Point; namespace Artemis.KeyboardProviders.Corsair { diff --git a/Artemis/Artemis/KeyboardProviders/KeyboardProvider.cs b/Artemis/Artemis/KeyboardProviders/KeyboardProvider.cs index 71c0d028e..0e28f4ccb 100644 --- a/Artemis/Artemis/KeyboardProviders/KeyboardProvider.cs +++ b/Artemis/Artemis/KeyboardProviders/KeyboardProvider.cs @@ -1,12 +1,16 @@ -using System.Collections.Generic; -using System.Drawing; +using System.Drawing; using System.Windows; using Size = System.Windows.Size; namespace Artemis.KeyboardProviders { - public abstract class KeyboardProvider + public abstract class KeyboardProvider : DeviceProvider { + protected KeyboardProvider() + { + Type = DeviceType.Keyboard; + } + public string Name { get; set; } public int Height { get; set; } public int Width { get; set; } @@ -15,7 +19,8 @@ namespace Artemis.KeyboardProviders public PreviewSettings PreviewSettings { get; set; } public abstract bool CanEnable(); - public abstract void Enable(); // TODO: This should be done in a background thread with a callback mechanism as it causes UI lag + public abstract void Enable(); + // TODO: This should be done in a background thread with a callback mechanism as it causes UI lag public abstract void Disable(); public abstract void DrawBitmap(Bitmap bitmap); @@ -34,6 +39,18 @@ namespace Artemis.KeyboardProviders public Rect KeyboardRectangle(int scale) => new Rect(new Size(Width*scale, Height*scale)); } + public class DeviceProvider + { + public DeviceType Type { get; set; } + } + + public enum DeviceType + { + Keyboard, + Mouse, + Headset + } + public struct PreviewSettings { public int Width { get; set; } diff --git a/Artemis/Artemis/Managers/LoopManager.cs b/Artemis/Artemis/Managers/LoopManager.cs index 4cd90aafc..f0e892a64 100644 --- a/Artemis/Artemis/Managers/LoopManager.cs +++ b/Artemis/Artemis/Managers/LoopManager.cs @@ -1,11 +1,9 @@ using System; using System.Drawing; -using System.Threading; using System.Timers; using Artemis.Events; using Caliburn.Micro; using Ninject.Extensions.Logging; -using Timer = System.Timers.Timer; namespace Artemis.Managers { @@ -110,52 +108,49 @@ namespace Artemis.Managers return; } - if (!Monitor.TryEnter(_keyboardManager.ActiveKeyboard)) - return; - - // Skip frame if effect is still initializing - if (renderEffect.Initialized == false) - return; - - // ApplyProperties the current effect - if (renderEffect.Initialized) - renderEffect.Update(); - - // Get ActiveEffect's bitmap - var bitmap = renderEffect.Initialized - ? renderEffect.GenerateBitmap() - : null; - - // Draw enabled overlays on top - foreach (var overlayModel in _effectManager.EnabledOverlays) + lock (_keyboardManager.ActiveKeyboard) { - overlayModel.Update(); - bitmap = bitmap != null - ? overlayModel.GenerateBitmap(bitmap) - : overlayModel.GenerateBitmap(); + // Skip frame if effect is still initializing + if (renderEffect.Initialized == false) + return; + + // ApplyProperties the current effect + if (renderEffect.Initialized) + renderEffect.Update(); + + // Get ActiveEffect's bitmap + var bitmap = renderEffect.Initialized + ? renderEffect.GenerateBitmap() + : null; + + // Draw enabled overlays on top + foreach (var overlayModel in _effectManager.EnabledOverlays) + { + overlayModel.Update(); + bitmap = bitmap != null + ? overlayModel.GenerateBitmap(bitmap) + : overlayModel.GenerateBitmap(); + } + + if (bitmap == null) + return; + + // Fill the bitmap's background with black to avoid trailing colors on some keyboards + var fixedBmp = new Bitmap(bitmap.Width, bitmap.Height); + using (var g = Graphics.FromImage(fixedBmp)) + { + g.Clear(Color.Black); + g.DrawImage(bitmap, 0, 0); + } + + bitmap = fixedBmp; + + // If it exists, send bitmap to the device + _keyboardManager.ActiveKeyboard?.DrawBitmap(bitmap); + + // debugging TODO: Disable when window isn't shown (in Debug VM, or get rid of it, w/e) + _events.PublishOnUIThread(new ChangeBitmap(bitmap)); } - - if (bitmap == null) - return; - - // Fill the bitmap's background with black to avoid trailing colors on some keyboards - var fixedBmp = new Bitmap(bitmap.Width, bitmap.Height); - using (var g = Graphics.FromImage(fixedBmp)) - { - g.Clear(Color.Black); - g.DrawImage(bitmap, 0, 0); - } - - bitmap = fixedBmp; - - // If it exists, send bitmap to the device - _keyboardManager.ActiveKeyboard?.DrawBitmap(bitmap); - - // debugging TODO: Disable when window isn't shown (in Debug VM, or get rid of it, w/e) - _events.PublishOnUIThread(new ChangeBitmap(bitmap)); - - if (_keyboardManager.ActiveKeyboard != null) - Monitor.Exit(_keyboardManager.ActiveKeyboard); } } } \ No newline at end of file diff --git a/Artemis/Artemis/Models/Profiles/Properties/DynamicPropertiesModel.cs b/Artemis/Artemis/Models/Profiles/Properties/DynamicPropertiesModel.cs index 0d809ec60..19144b291 100644 --- a/Artemis/Artemis/Models/Profiles/Properties/DynamicPropertiesModel.cs +++ b/Artemis/Artemis/Models/Profiles/Properties/DynamicPropertiesModel.cs @@ -45,31 +45,49 @@ namespace Artemis.Models.Profiles.Properties ApplyPercentageOfProperty(dataModel, properties); } - private void ApplyPercentageOf(IGameDataModel dataModel, KeyboardPropertiesModel properties, - double percentageSource) + private void ApplyPercentageOf(IGameDataModel dataModel, KeyboardPropertiesModel properties, double src) { - // Property to apply on - var layerProp = properties.GetType().GetProperty(LayerProperty); - // Property to base the percentage upon - var gameProperty = dataModel.GetPropValue(GameProperty); - - if (layerProp == null) + if (GameProperty == null) return; - var percentage = ToDouble(gameProperty)/percentageSource; - var appliedValue = percentage*(double) layerProp.GetValue(properties); + var gameProperty = dataModel.GetPropValue(GameProperty); + var percentage = ToDouble(gameProperty)/src; - // Opacity requires some special treatment as it causes an exception if it's < 0.0 or > 1.0 - if (LayerProperty == "Opacity") - { - appliedValue = percentage; - if (appliedValue < 0.0) - appliedValue = 0.0; - if (appliedValue > 1.0) - appliedValue = 1.0; - } + if (LayerProperty == "Width") + ApplyWidth(properties, percentage); + else if (LayerProperty == "Height") + ApplyHeight(properties, percentage); + else if (LayerProperty == "Opacity") + ApplyOpacity(properties, percentage); + } - layerProp.SetValue(properties, appliedValue); + private void ApplyWidth(KeyboardPropertiesModel properties, double percentage) + { + var newWidth = percentage * properties.Width; + var difference = properties.Width - newWidth; + properties.Width = newWidth; + + // Apply the right to left option + if (LayerPropertyOptions == LayerPropertyOptions.RightToLeft) + properties.X = properties.X + difference; + } + + private void ApplyHeight(KeyboardPropertiesModel properties, double percentage) + { + properties.Height = percentage*properties.Height; + } + + private void ApplyOpacity(KeyboardPropertiesModel properties, double percentage) + { + properties.Opacity = percentage*properties.Opacity; + if (properties.Opacity < 0.0) + properties.Opacity = 0.0; + if (properties.Opacity > 1.0) + properties.Opacity = 1.0; + + // Apply the inverse/decrease option + if (LayerPropertyOptions == LayerPropertyOptions.Decrease) + properties.Opacity = 1.0 - properties.Opacity; } private void ApplyPercentageOfProperty(IGameDataModel dataModel, KeyboardPropertiesModel properties) diff --git a/Artemis/Artemis/Utilities/ExtensionMethods.cs b/Artemis/Artemis/Utilities/ExtensionMethods.cs index 16d37edd9..e64eb58f6 100644 --- a/Artemis/Artemis/Utilities/ExtensionMethods.cs +++ b/Artemis/Artemis/Utilities/ExtensionMethods.cs @@ -61,6 +61,9 @@ namespace Artemis.Utilities /// public static T GetPropValue(this object obj, string name) { + if (name == null) + return default(T); + var retVal = GetPropValue(obj, name); if (retVal == null) return default(T); diff --git a/Artemis/Artemis/ViewModels/LayerEditor/LayerDynamicPropertiesViewModel.cs b/Artemis/Artemis/ViewModels/LayerEditor/LayerDynamicPropertiesViewModel.cs index c5da45aa9..150d23e29 100644 --- a/Artemis/Artemis/ViewModels/LayerEditor/LayerDynamicPropertiesViewModel.cs +++ b/Artemis/Artemis/ViewModels/LayerEditor/LayerDynamicPropertiesViewModel.cs @@ -9,11 +9,10 @@ namespace Artemis.ViewModels.LayerEditor public sealed class LayerDynamicPropertiesViewModel : PropertyChangedBase { private readonly string _property; - private BindableCollection _layerPropertyOptions; + private BindableCollection _layerPropertyOptions; private LayerPropertyType _layerPropertyType; private string _name; private DynamicPropertiesModel _proposed; - private string _selectedLayerPropertyOption; private GeneralHelpers.PropertyCollection _selectedSource; private GeneralHelpers.PropertyCollection _selectedTarget; private bool _sourcesIsVisible; @@ -36,32 +35,8 @@ namespace Artemis.ViewModels.LayerEditor else GeneralHelpers.CopyProperties(Proposed, original); - Name = property + ":"; - - var nullTarget = new GeneralHelpers.PropertyCollection {Display = "None"}; - Targets = new BindableCollection {nullTarget}; - Targets.AddRange(dataModelProps.Where(p => p.Type == "Int32")); - Sources = new BindableCollection(); - Sources.AddRange(dataModelProps.Where(p => p.Type == "Int32")); - UserSourceIsVisible = LayerPropertyType == LayerPropertyType.PercentageOf; - SourcesIsVisible = LayerPropertyType == LayerPropertyType.PercentageOfProperty; - PropertyChanged += OnPropertyChanged; - - // Preselect according to the model - SelectedTarget = dataModelProps.FirstOrDefault(p => p.Path == Proposed.GameProperty); - SelectedSource = dataModelProps.FirstOrDefault(p => p.Path == Proposed.PercentageProperty); - LayerPropertyType = Proposed.LayerPropertyType; - // Set up a default for SelectedTarget if it was null - if (SelectedTarget.Display == null) - SelectedTarget = nullTarget; - - if (property == "Width") - LayerPropertyOptions = new BindableCollection { "Left to right", "Right to left" }; - else if (property == "Height") - LayerPropertyOptions = new BindableCollection { "Downwards", "Upwards" }; - else if (property == "Opacity") - LayerPropertyOptions = new BindableCollection { "Increase", "Decrease" }; + SetupControls(dataModelProps); } public LayerPropertyType LayerPropertyType @@ -120,7 +95,7 @@ namespace Artemis.ViewModels.LayerEditor } } - public BindableCollection LayerPropertyOptions + public BindableCollection LayerPropertyOptions { get { return _layerPropertyOptions; } set @@ -131,17 +106,6 @@ namespace Artemis.ViewModels.LayerEditor } } - public string SelectedLayerPropertyOption - { - get { return _selectedLayerPropertyOption; } - set - { - if (value == _selectedLayerPropertyOption) return; - _selectedLayerPropertyOption = value; - NotifyOfPropertyChange(() => SelectedLayerPropertyOption); - } - } - public bool SourcesIsVisible { get { return _sourcesIsVisible; } @@ -170,13 +134,70 @@ namespace Artemis.ViewModels.LayerEditor public BindableCollection Sources { get; set; } + private void SetupControls(BindableCollection dataModelProps) + { + Name = _property + ":"; + + // Populate target combobox + Targets = new BindableCollection + { + new GeneralHelpers.PropertyCollection {Display = "None"} + }; + Targets.AddRange(dataModelProps.Where(p => p.Type == "Int32")); + + // Populate sources combobox + Sources = new BindableCollection(); + Sources.AddRange(dataModelProps.Where(p => p.Type == "Int32")); + + // Preselect according to the model + SelectedTarget = dataModelProps.FirstOrDefault(p => p.Path == Proposed.GameProperty); + SelectedSource = dataModelProps.FirstOrDefault(p => p.Path == Proposed.PercentageProperty); + LayerPropertyType = Proposed.LayerPropertyType; + + // Populate the extra options combobox + switch (_property) + { + case "Width": + LayerPropertyOptions = new BindableCollection + { + Models.Profiles.Properties.LayerPropertyOptions.LeftToRight, + Models.Profiles.Properties.LayerPropertyOptions.RightToLeft + }; + break; + case "Height": + LayerPropertyOptions = new BindableCollection + { + Models.Profiles.Properties.LayerPropertyOptions.Downwards, + Models.Profiles.Properties.LayerPropertyOptions.Upwards + }; + break; + case "Opacity": + LayerPropertyOptions = new BindableCollection + { + Models.Profiles.Properties.LayerPropertyOptions.Increase, + Models.Profiles.Properties.LayerPropertyOptions.Decrease + }; + break; + } + + UserSourceIsVisible = LayerPropertyType == LayerPropertyType.PercentageOf; + SourcesIsVisible = LayerPropertyType == LayerPropertyType.PercentageOfProperty; + + // Set up a default for SelectedTarget if it was null + if (SelectedTarget.Display == null) + SelectedTarget = Targets.FirstOrDefault(); + // Set up a default for the extra option if it fell outside the range + if (!LayerPropertyOptions.Contains(Proposed.LayerPropertyOptions)) + Proposed.LayerPropertyOptions = LayerPropertyOptions.FirstOrDefault(); + } + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "SelectedTarget") Proposed.GameProperty = SelectedTarget.Path; - if (e.PropertyName == "SelectedSource") + else if (e.PropertyName == "SelectedSource") Proposed.PercentageProperty = SelectedSource.Path; - if (e.PropertyName == "LayerPropertyType") + else if (e.PropertyName == "LayerPropertyType") { Proposed.LayerPropertyType = LayerPropertyType; UserSourceIsVisible = LayerPropertyType == LayerPropertyType.PercentageOf; diff --git a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs index 247f37b0f..2292238eb 100644 --- a/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs +++ b/Artemis/Artemis/ViewModels/ProfileEditorViewModel.cs @@ -248,7 +248,7 @@ namespace Artemis.ViewModels /// public void AddLayer() { - if (_selectedProfile == null) + if (SelectedProfile == null) return; var layer = SelectedProfile.AddLayer(); @@ -262,7 +262,7 @@ namespace Artemis.ViewModels /// public void RemoveLayer() { - if (_selectedProfile == null || _selectedLayer == null) + if (SelectedProfile == null || _selectedLayer == null) return; SelectedProfile.Layers.Remove(_selectedLayer); @@ -352,6 +352,9 @@ namespace Artemis.ViewModels /// public void MouseUpKeyboardPreview(MouseButtonEventArgs e) { + if (SelectedProfile == null) + return; + var timeSinceDown = DateTime.Now - _downTime; if (!(timeSinceDown.TotalMilliseconds < 500)) return; @@ -376,6 +379,9 @@ namespace Artemis.ViewModels /// public void MouseMoveKeyboardPreview(MouseEventArgs e) { + if (SelectedProfile == null) + return; + var pos = e.GetPosition((Image) e.OriginalSource); var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width); var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height); @@ -406,7 +412,7 @@ namespace Artemis.ViewModels private void InvokeUpdateKeyboardPreview(object sender, ElapsedEventArgs e) { - Application.Current.Dispatcher.Invoke(UpdateKeyboardPreview, DispatcherPriority.ContextIdle); + Application.Current.Dispatcher.Invoke(UpdateKeyboardPreview, DispatcherPriority.ContextIdle); } /// @@ -414,9 +420,12 @@ namespace Artemis.ViewModels /// public void UpdateKeyboardPreview() { - if (_selectedProfile == null || ActiveKeyboard == null) + if (SelectedProfile == null || ActiveKeyboard == null) + { + KeyboardPreview = new DrawingImage(); return; - + } + var keyboardRect = ActiveKeyboard.KeyboardRectangle(4); var visual = new DrawingVisual(); using (var drawingContext = visual.RenderOpen()) diff --git a/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml b/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml index d1cf69cc1..cb68eb80d 100644 --- a/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml +++ b/Artemis/Artemis/Views/LayerEditor/LayerDynamicPropertiesView.xaml @@ -12,9 +12,7 @@ - + @@ -89,7 +87,15 @@ - + + + + + + + \ No newline at end of file