1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-31 09:43:46 +00:00

Undid UI freeze fix since it broker other things :c, implemented dynamic property extra options

This commit is contained in:
SpoinkyNL 2016-05-19 22:31:24 +02:00
parent 028d22bc7b
commit a9373012a8
8 changed files with 191 additions and 124 deletions

View File

@ -1,5 +1,4 @@
using System.Collections.Generic; using System.Drawing;
using System.Drawing;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
using Artemis.Properties; using Artemis.Properties;
@ -9,7 +8,6 @@ using CUE.NET.Brushes;
using CUE.NET.Devices.Generic.Enums; using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard; using CUE.NET.Devices.Keyboard;
using CUE.NET.Exceptions; using CUE.NET.Exceptions;
using Point = System.Drawing.Point;
namespace Artemis.KeyboardProviders.Corsair namespace Artemis.KeyboardProviders.Corsair
{ {

View File

@ -1,12 +1,16 @@
using System.Collections.Generic; using System.Drawing;
using System.Drawing;
using System.Windows; using System.Windows;
using Size = System.Windows.Size; using Size = System.Windows.Size;
namespace Artemis.KeyboardProviders namespace Artemis.KeyboardProviders
{ {
public abstract class KeyboardProvider public abstract class KeyboardProvider : DeviceProvider
{ {
protected KeyboardProvider()
{
Type = DeviceType.Keyboard;
}
public string Name { get; set; } public string Name { get; set; }
public int Height { get; set; } public int Height { get; set; }
public int Width { get; set; } public int Width { get; set; }
@ -15,7 +19,8 @@ namespace Artemis.KeyboardProviders
public PreviewSettings PreviewSettings { get; set; } public PreviewSettings PreviewSettings { get; set; }
public abstract bool CanEnable(); 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 Disable();
public abstract void DrawBitmap(Bitmap bitmap); 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 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 struct PreviewSettings
{ {
public int Width { get; set; } public int Width { get; set; }

View File

@ -1,11 +1,9 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Threading;
using System.Timers; using System.Timers;
using Artemis.Events; using Artemis.Events;
using Caliburn.Micro; using Caliburn.Micro;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
using Timer = System.Timers.Timer;
namespace Artemis.Managers namespace Artemis.Managers
{ {
@ -110,52 +108,49 @@ namespace Artemis.Managers
return; return;
} }
if (!Monitor.TryEnter(_keyboardManager.ActiveKeyboard)) lock (_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)
{ {
overlayModel.Update(); // Skip frame if effect is still initializing
bitmap = bitmap != null if (renderEffect.Initialized == false)
? overlayModel.GenerateBitmap(bitmap) return;
: overlayModel.GenerateBitmap();
// 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);
} }
} }
} }

View File

@ -45,31 +45,49 @@ namespace Artemis.Models.Profiles.Properties
ApplyPercentageOfProperty(dataModel, properties); ApplyPercentageOfProperty(dataModel, properties);
} }
private void ApplyPercentageOf(IGameDataModel dataModel, KeyboardPropertiesModel properties, private void ApplyPercentageOf(IGameDataModel dataModel, KeyboardPropertiesModel properties, double src)
double percentageSource)
{ {
// Property to apply on if (GameProperty == null)
var layerProp = properties.GetType().GetProperty(LayerProperty);
// Property to base the percentage upon
var gameProperty = dataModel.GetPropValue<int>(GameProperty);
if (layerProp == null)
return; return;
var percentage = ToDouble(gameProperty)/percentageSource; var gameProperty = dataModel.GetPropValue<int>(GameProperty);
var appliedValue = percentage*(double) layerProp.GetValue(properties); 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 == "Width")
if (LayerProperty == "Opacity") ApplyWidth(properties, percentage);
{ else if (LayerProperty == "Height")
appliedValue = percentage; ApplyHeight(properties, percentage);
if (appliedValue < 0.0) else if (LayerProperty == "Opacity")
appliedValue = 0.0; ApplyOpacity(properties, percentage);
if (appliedValue > 1.0) }
appliedValue = 1.0;
}
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) private void ApplyPercentageOfProperty(IGameDataModel dataModel, KeyboardPropertiesModel properties)

View File

@ -61,6 +61,9 @@ namespace Artemis.Utilities
/// <returns></returns> /// <returns></returns>
public static T GetPropValue<T>(this object obj, string name) public static T GetPropValue<T>(this object obj, string name)
{ {
if (name == null)
return default(T);
var retVal = GetPropValue(obj, name); var retVal = GetPropValue(obj, name);
if (retVal == null) if (retVal == null)
return default(T); return default(T);

View File

@ -9,11 +9,10 @@ namespace Artemis.ViewModels.LayerEditor
public sealed class LayerDynamicPropertiesViewModel : PropertyChangedBase public sealed class LayerDynamicPropertiesViewModel : PropertyChangedBase
{ {
private readonly string _property; private readonly string _property;
private BindableCollection<string> _layerPropertyOptions; private BindableCollection<LayerPropertyOptions> _layerPropertyOptions;
private LayerPropertyType _layerPropertyType; private LayerPropertyType _layerPropertyType;
private string _name; private string _name;
private DynamicPropertiesModel _proposed; private DynamicPropertiesModel _proposed;
private string _selectedLayerPropertyOption;
private GeneralHelpers.PropertyCollection _selectedSource; private GeneralHelpers.PropertyCollection _selectedSource;
private GeneralHelpers.PropertyCollection _selectedTarget; private GeneralHelpers.PropertyCollection _selectedTarget;
private bool _sourcesIsVisible; private bool _sourcesIsVisible;
@ -36,32 +35,8 @@ namespace Artemis.ViewModels.LayerEditor
else else
GeneralHelpers.CopyProperties(Proposed, original); GeneralHelpers.CopyProperties(Proposed, original);
Name = property + ":";
var nullTarget = new GeneralHelpers.PropertyCollection {Display = "None"};
Targets = new BindableCollection<GeneralHelpers.PropertyCollection> {nullTarget};
Targets.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
Sources = new BindableCollection<GeneralHelpers.PropertyCollection>();
Sources.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
UserSourceIsVisible = LayerPropertyType == LayerPropertyType.PercentageOf;
SourcesIsVisible = LayerPropertyType == LayerPropertyType.PercentageOfProperty;
PropertyChanged += OnPropertyChanged; PropertyChanged += OnPropertyChanged;
SetupControls(dataModelProps);
// 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<string> { "Left to right", "Right to left" };
else if (property == "Height")
LayerPropertyOptions = new BindableCollection<string> { "Downwards", "Upwards" };
else if (property == "Opacity")
LayerPropertyOptions = new BindableCollection<string> { "Increase", "Decrease" };
} }
public LayerPropertyType LayerPropertyType public LayerPropertyType LayerPropertyType
@ -120,7 +95,7 @@ namespace Artemis.ViewModels.LayerEditor
} }
} }
public BindableCollection<string> LayerPropertyOptions public BindableCollection<LayerPropertyOptions> LayerPropertyOptions
{ {
get { return _layerPropertyOptions; } get { return _layerPropertyOptions; }
set 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 public bool SourcesIsVisible
{ {
get { return _sourcesIsVisible; } get { return _sourcesIsVisible; }
@ -170,13 +134,70 @@ namespace Artemis.ViewModels.LayerEditor
public BindableCollection<GeneralHelpers.PropertyCollection> Sources { get; set; } public BindableCollection<GeneralHelpers.PropertyCollection> Sources { get; set; }
private void SetupControls(BindableCollection<GeneralHelpers.PropertyCollection> dataModelProps)
{
Name = _property + ":";
// Populate target combobox
Targets = new BindableCollection<GeneralHelpers.PropertyCollection>
{
new GeneralHelpers.PropertyCollection {Display = "None"}
};
Targets.AddRange(dataModelProps.Where(p => p.Type == "Int32"));
// Populate sources combobox
Sources = new BindableCollection<GeneralHelpers.PropertyCollection>();
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<LayerPropertyOptions>
{
Models.Profiles.Properties.LayerPropertyOptions.LeftToRight,
Models.Profiles.Properties.LayerPropertyOptions.RightToLeft
};
break;
case "Height":
LayerPropertyOptions = new BindableCollection<LayerPropertyOptions>
{
Models.Profiles.Properties.LayerPropertyOptions.Downwards,
Models.Profiles.Properties.LayerPropertyOptions.Upwards
};
break;
case "Opacity":
LayerPropertyOptions = new BindableCollection<LayerPropertyOptions>
{
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) private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == "SelectedTarget") if (e.PropertyName == "SelectedTarget")
Proposed.GameProperty = SelectedTarget.Path; Proposed.GameProperty = SelectedTarget.Path;
if (e.PropertyName == "SelectedSource") else if (e.PropertyName == "SelectedSource")
Proposed.PercentageProperty = SelectedSource.Path; Proposed.PercentageProperty = SelectedSource.Path;
if (e.PropertyName == "LayerPropertyType") else if (e.PropertyName == "LayerPropertyType")
{ {
Proposed.LayerPropertyType = LayerPropertyType; Proposed.LayerPropertyType = LayerPropertyType;
UserSourceIsVisible = LayerPropertyType == LayerPropertyType.PercentageOf; UserSourceIsVisible = LayerPropertyType == LayerPropertyType.PercentageOf;

View File

@ -248,7 +248,7 @@ namespace Artemis.ViewModels
/// </summary> /// </summary>
public void AddLayer() public void AddLayer()
{ {
if (_selectedProfile == null) if (SelectedProfile == null)
return; return;
var layer = SelectedProfile.AddLayer(); var layer = SelectedProfile.AddLayer();
@ -262,7 +262,7 @@ namespace Artemis.ViewModels
/// </summary> /// </summary>
public void RemoveLayer() public void RemoveLayer()
{ {
if (_selectedProfile == null || _selectedLayer == null) if (SelectedProfile == null || _selectedLayer == null)
return; return;
SelectedProfile.Layers.Remove(_selectedLayer); SelectedProfile.Layers.Remove(_selectedLayer);
@ -352,6 +352,9 @@ namespace Artemis.ViewModels
/// <param name="e"></param> /// <param name="e"></param>
public void MouseUpKeyboardPreview(MouseButtonEventArgs e) public void MouseUpKeyboardPreview(MouseButtonEventArgs e)
{ {
if (SelectedProfile == null)
return;
var timeSinceDown = DateTime.Now - _downTime; var timeSinceDown = DateTime.Now - _downTime;
if (!(timeSinceDown.TotalMilliseconds < 500)) if (!(timeSinceDown.TotalMilliseconds < 500))
return; return;
@ -376,6 +379,9 @@ namespace Artemis.ViewModels
/// <param name="e"></param> /// <param name="e"></param>
public void MouseMoveKeyboardPreview(MouseEventArgs e) public void MouseMoveKeyboardPreview(MouseEventArgs e)
{ {
if (SelectedProfile == null)
return;
var pos = e.GetPosition((Image) e.OriginalSource); var pos = e.GetPosition((Image) e.OriginalSource);
var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width); var x = pos.X/((double) ActiveKeyboard.PreviewSettings.Width/ActiveKeyboard.Width);
var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height); var y = pos.Y/((double) ActiveKeyboard.PreviewSettings.Height/ActiveKeyboard.Height);
@ -406,7 +412,7 @@ namespace Artemis.ViewModels
private void InvokeUpdateKeyboardPreview(object sender, ElapsedEventArgs e) private void InvokeUpdateKeyboardPreview(object sender, ElapsedEventArgs e)
{ {
Application.Current.Dispatcher.Invoke(UpdateKeyboardPreview, DispatcherPriority.ContextIdle); Application.Current.Dispatcher.Invoke(UpdateKeyboardPreview, DispatcherPriority.ContextIdle);
} }
/// <summary> /// <summary>
@ -414,8 +420,11 @@ namespace Artemis.ViewModels
/// </summary> /// </summary>
public void UpdateKeyboardPreview() public void UpdateKeyboardPreview()
{ {
if (_selectedProfile == null || ActiveKeyboard == null) if (SelectedProfile == null || ActiveKeyboard == null)
{
KeyboardPreview = new DrawingImage();
return; return;
}
var keyboardRect = ActiveKeyboard.KeyboardRectangle(4); var keyboardRect = ActiveKeyboard.KeyboardRectangle(4);
var visual = new DrawingVisual(); var visual = new DrawingVisual();

View File

@ -12,9 +12,7 @@
<UserControl.Resources> <UserControl.Resources>
<utilities:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" /> <utilities:EnumDescriptionConverter x:Key="HEnumDescriptionConverter" />
<ObjectDataProvider MethodName="GetValues" <ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="DynamicPropertyValues">
ObjectType="{x:Type sys:Enum}"
x:Key="DynamicPropertyValues">
<ObjectDataProvider.MethodParameters> <ObjectDataProvider.MethodParameters>
<x:Type TypeName="properties:LayerPropertyType" /> <x:Type TypeName="properties:LayerPropertyType" />
</ObjectDataProvider.MethodParameters> </ObjectDataProvider.MethodParameters>
@ -89,7 +87,15 @@
</StackPanel> </StackPanel>
<!-- Extra option --> <!-- Extra option -->
<ComboBox Grid.Column="4" x:Name="LayerPropertyOptions" VerticalAlignment="Center" Margin="10,0" <ComboBox SelectedItem="{Binding Path=Proposed.LayerPropertyOptions}" Grid.Column="4"
IsEnabled="{Binding Path=ControlsEnabled}" /> ItemsSource="{Binding Path=LayerPropertyOptions}"
Margin="10,0" VerticalAlignment="Center" Height="22"
IsEnabled="{Binding Path=ControlsEnabled}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource HEnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid> </Grid>
</UserControl> </UserControl>