1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Performance improvements, especially on large profiles

This commit is contained in:
SpoinkyNL 2016-06-05 22:13:46 +02:00
parent 1ea471280b
commit b7423ad6d6
24 changed files with 208 additions and 299 deletions

View File

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
@ -51,8 +50,7 @@ namespace Artemis.Models.Profiles
return;
// Preview simply shows the properties as they are. When not previewing they are applied
LayerPropertiesModel appliedProperties;
Properties.Brush.Freeze();
AppliedProperties appliedProperties;
if (!preview)
{
if (!ConditionsMet<T>(dataModel))
@ -60,13 +58,12 @@ namespace Artemis.Models.Profiles
appliedProperties = Properties.GetAppliedProperties(dataModel);
}
else
appliedProperties = GeneralHelpers.Clone(Properties);
appliedProperties = Properties.GetAppliedProperties(dataModel, true);
// Update animations on layer types that support them
if (LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif)
{
AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties,
(KeyboardPropertiesModel) appliedProperties, updateAnimations);
AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel) Properties, updateAnimations);
}
switch (LayerType)
@ -77,10 +74,10 @@ namespace Artemis.Models.Profiles
layerModel.Draw<T>(dataModel, c, preview, updateAnimations);
break;
case LayerType.Keyboard:
Drawer.Draw(c, (KeyboardPropertiesModel) Properties, (KeyboardPropertiesModel) appliedProperties);
Drawer.Draw(c, (KeyboardPropertiesModel) Properties, appliedProperties);
break;
case LayerType.KeyboardGif:
GifImage = Drawer.DrawGif(c, (KeyboardPropertiesModel) appliedProperties, GifImage);
GifImage = Drawer.DrawGif(c, (KeyboardPropertiesModel)Properties, appliedProperties, GifImage);
break;
}
}
@ -93,23 +90,17 @@ namespace Artemis.Models.Profiles
return null;
// Preview simply shows the properties as they are. When not previewing they are applied
LayerPropertiesModel appliedProperties;
AppliedProperties appliedProperties;
if (!preview)
{
if (!ConditionsMet<T>(dataModel))
return null; // Don't return the brush when not previewing and the conditions arent met
return null; // Return null when not previewing and the conditions arent met
appliedProperties = Properties.GetAppliedProperties(dataModel);
}
else
appliedProperties = GeneralHelpers.Clone(Properties);
appliedProperties = Properties.GetAppliedProperties(dataModel, true);
// TODO: Mouse/headset animations
// Update animations on layer types that support them
//if (LayerType != LayerType.Folder && updateAnimations)
//{
// AnimationUpdater.UpdateAnimation((KeyboardPropertiesModel)Properties,
// (KeyboardPropertiesModel)appliedProperties);
//}
if (LayerType != LayerType.Folder)
return appliedProperties.Brush;
@ -165,18 +156,24 @@ namespace Artemis.Models.Profiles
/// <returns></returns>
public bool MustDraw()
{
// If any of the parents are disabled, this layer must not be drawn
var parent = Parent;
while (parent != null)
{
if (!parent.Enabled)
return false;
parent = parent.Parent;
}
return Enabled && (LayerType == LayerType.Keyboard || LayerType == LayerType.KeyboardGif);
}
public IEnumerable<LayerModel> GetAllLayers(bool ignoreEnabled)
public IEnumerable<LayerModel> GetLayers()
{
var layers = new List<LayerModel>();
foreach (var layerModel in Children)
{
if (ignoreEnabled && !layerModel.Enabled)
continue;
layers.Add(layerModel);
layers.AddRange(layerModel.Children);
layers.AddRange(layerModel.GetLayers());
}
return layers;

View File

@ -104,17 +104,13 @@ namespace Artemis.Models.Profiles
/// <summary>
/// Gives all the layers and their children in a flat list
/// </summary>
public List<LayerModel> GetLayers(bool ignoreEnabled = true)
public List<LayerModel> GetLayers()
{
var layers = new List<LayerModel>();
foreach (var layerModel in Layers)
{
if (ignoreEnabled && !layerModel.Enabled)
{
continue;
}
layers.Add(layerModel);
layers.AddRange(layerModel.GetAllLayers(ignoreEnabled));
layers.AddRange(layerModel.GetLayers());
}
return layers;
@ -126,7 +122,7 @@ namespace Artemis.Models.Profiles
/// <param name="keyboardRectangle"></param>
public void FixBoundaries(Rect keyboardRectangle)
{
foreach (var layer in GetLayers(false))
foreach (var layer in GetLayers())
{
if (layer.LayerType != LayerType.Keyboard && layer.LayerType != LayerType.KeyboardGif)
continue;

View File

@ -37,7 +37,7 @@ namespace Artemis.Models.Profiles.Properties
/// </summary>
public LayerPropertyOptions LayerPropertyOptions { get; set; }
internal void ApplyProperty(IGameDataModel dataModel, KeyboardPropertiesModel properties)
internal void ApplyProperty(IGameDataModel dataModel, AppliedProperties properties)
{
if (LayerPropertyType == LayerPropertyType.PercentageOf)
ApplyPercentageOf(dataModel, properties, PercentageSource);
@ -45,7 +45,7 @@ namespace Artemis.Models.Profiles.Properties
ApplyPercentageOfProperty(dataModel, properties);
}
private void ApplyPercentageOf(IGameDataModel dataModel, KeyboardPropertiesModel properties, double src)
private void ApplyPercentageOf(IGameDataModel dataModel, AppliedProperties properties, double src)
{
if (GameProperty == null)
return;
@ -61,7 +61,7 @@ namespace Artemis.Models.Profiles.Properties
ApplyOpacity(properties, percentage);
}
private void ApplyWidth(KeyboardPropertiesModel properties, double percentage)
private void ApplyWidth(AppliedProperties properties, double percentage)
{
var newWidth = percentage * properties.Width;
var difference = properties.Width - newWidth;
@ -72,7 +72,7 @@ namespace Artemis.Models.Profiles.Properties
properties.X = properties.X + difference;
}
private void ApplyHeight(KeyboardPropertiesModel properties, double percentage)
private void ApplyHeight(AppliedProperties properties, double percentage)
{
var newHeight = percentage*properties.Height;
var difference = properties.Height - newHeight;
@ -82,7 +82,7 @@ namespace Artemis.Models.Profiles.Properties
properties.Y = properties.Y + difference;
}
private void ApplyOpacity(KeyboardPropertiesModel properties, double percentage)
private void ApplyOpacity(AppliedProperties properties, double percentage)
{
properties.Opacity = percentage*properties.Opacity;
if (properties.Opacity < 0.0)
@ -95,7 +95,7 @@ namespace Artemis.Models.Profiles.Properties
properties.Opacity = 1.0 - properties.Opacity;
}
private void ApplyPercentageOfProperty(IGameDataModel dataModel, KeyboardPropertiesModel properties)
private void ApplyPercentageOfProperty(IGameDataModel dataModel, AppliedProperties properties)
{
var value = dataModel.GetPropValue<int>(PercentageProperty);
ApplyPercentageOf(dataModel, properties, value);

View File

@ -5,9 +5,9 @@ namespace Artemis.Models.Profiles.Properties
{
public class FolderPropertiesModel : LayerPropertiesModel
{
public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel)
public override AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false)
{
return GeneralHelpers.Clone(this);
return new AppliedProperties();
}
}
}

View File

@ -1,14 +1,12 @@
using Artemis.Models.Interfaces;
using Artemis.Utilities;
namespace Artemis.Models.Profiles.Properties
{
public class HeadsetPropertiesModel : LayerPropertiesModel
{
public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel)
public override AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false)
{
// TODO: Apply any properties, if applicable to headsets in the first place.
return GeneralHelpers.Clone(this);
return new AppliedProperties();
}
}
}

View File

@ -1,6 +1,8 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;
using System.Xml.Serialization;
using Artemis.Models.Interfaces;
using Artemis.Utilities;
@ -33,15 +35,31 @@ namespace Artemis.Models.Profiles.Properties
return new Rect(X*scale, Y*scale, Width*scale, Height*scale);
}
public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel)
public override AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false)
{
var properties = GeneralHelpers.Clone(this);
var applied = new AppliedProperties
{
X = X,
Y = Y,
Width = Width,
Height = Height,
Opacity = Opacity,
Brush = Brush.CloneCurrentValue()
};
foreach (var dynamicProperty in properties.DynamicProperties)
dynamicProperty.ApplyProperty(dataModel, properties);
properties.Brush.Opacity = Opacity;
if (ignoreDynamic)
return applied;
return properties;
foreach (var dynamicProperty in DynamicProperties)
dynamicProperty.ApplyProperty(dataModel, applied);
if (Math.Abs(applied.Opacity - 1) > 0.001)
{
applied.Brush = Brush.CloneCurrentValue();
applied.Brush.Opacity = applied.Opacity;
}
return applied;
}
}

View File

@ -23,8 +23,6 @@ namespace Artemis.Models.Profiles.Properties
Conditions = new List<LayerConditionModel>();
}
public abstract LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel);
public List<LayerConditionModel> Conditions { get; set; }
public Brush Brush
@ -32,10 +30,35 @@ namespace Artemis.Models.Profiles.Properties
get { return _brush; }
set
{
var cloned = value.Dispatcher.Invoke(() => GeneralHelpers.CloneAlt(value));
if (value == null)
{
_brush = null;
return;
}
if (value.IsFrozen)
{
_brush = value;
return;
}
// Clone the brush off of the UI thread and freeze it
var cloned = value.Dispatcher.Invoke(value.CloneCurrentValue);
cloned.Freeze();
_brush = cloned;
}
}
public abstract AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false);
}
public struct AppliedProperties
{
public double X { get; set; }
public double Y { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public double Opacity { get; set; }
public Brush Brush { get; set; }
}
}

View File

@ -1,14 +1,12 @@
using Artemis.Models.Interfaces;
using Artemis.Utilities;
namespace Artemis.Models.Profiles.Properties
{
public class MousePropertiesModel : LayerPropertiesModel
{
public override LayerPropertiesModel GetAppliedProperties(IGameDataModel dataModel)
public override AppliedProperties GetAppliedProperties(IGameDataModel dataModel, bool ignoreDynamic = false)
{
// TODO: Apply any properties, if applicable to mice in the first place.
return GeneralHelpers.Clone(this);
return new AppliedProperties();
}
}
}

View File

@ -84,7 +84,7 @@ namespace Artemis.Modules.Games.CounterStrike
}
catch (Exception ex)
{
Logger.Error(ex, "Failed to deserialize CS:GO JSON");
Logger?.Error(ex, "Failed to deserialize CS:GO JSON");
throw;
}

View File

@ -141,7 +141,7 @@ namespace Artemis.Modules.Games.Overwatch
{
if (Profile == null || GameDataModel == null)
return null;
return null;
return Profile.GenerateBrush<OverwatchDataModel>(GameDataModel, LayerType.Mouse, false, true);
}
@ -149,7 +149,7 @@ namespace Artemis.Modules.Games.Overwatch
{
if (Profile == null || GameDataModel == null)
return null;
return null;
return Profile.GenerateBrush<OverwatchDataModel>(GameDataModel, LayerType.Headset, false, true);
}
}

View File

@ -78,9 +78,8 @@ namespace Artemis.Modules.Games.Overwatch
}
catch (Exception e)
{
Logger.Error(e, "Couldn't place Overwatch DLL, Overwatch support won't work.");
}
Logger?.Error(e, "Couldn't place Overwatch DLL, Overwatch support won't work.");
}
}
}
}

View File

@ -1,12 +1,11 @@
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Threading;
using System.Threading.Tasks;
using Artemis.Managers;
using Artemis.Models;
using Artemis.Models.Profiles;
using Artemis.Modules.Effects.TypeWave;
using Artemis.Utilities;
using Artemis.Utilities.Keyboard;
using Artemis.Utilities.LogitechDll;
using Brush = System.Windows.Media.Brush;
@ -14,16 +13,11 @@ namespace Artemis.Modules.Games.TheDivision
{
public class TheDivisionModel : GameModel
{
private Wave _ammoWave;
private KeyboardRectangle _hpRect;
private KeyboardRectangle _p2;
private KeyboardRectangle _p3;
private KeyboardRectangle _p4;
private StickyValue<bool> _stickyAmmo;
private StickyValue<bool> _stickyHp;
private int _trans;
public TheDivisionModel(MainManager mainManager, TheDivisionSettings settings) : base(mainManager, settings, new TheDivisionDataModel())
public TheDivisionModel(MainManager mainManager, TheDivisionSettings settings)
: base(mainManager, settings, new TheDivisionDataModel())
{
Name = "TheDivision";
ProcessName = "TheDivision";
@ -37,7 +31,13 @@ namespace Artemis.Modules.Games.TheDivision
public override void Dispose()
{
Initialized = false;
// Delay restoring the DLL to allow The Division to release it
Task.Factory.StartNew(() =>
{
Thread.Sleep(2000);
DllManager.RestoreDll();
});
_stickyAmmo.Dispose();
_stickyHp.Dispose();
@ -47,45 +47,6 @@ namespace Artemis.Modules.Games.TheDivision
{
Initialized = false;
_ammoWave = new Wave(new Point(30, 14), 0, Color.Transparent);
_hpRect = new KeyboardRectangle(MainManager.DeviceManager.ActiveKeyboard, 3*Scale, 0*Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = 7*Scale,
Width = 21*Scale,
Rotate = true,
ContainedBrush = false
};
_p2 = new KeyboardRectangle(MainManager.DeviceManager.ActiveKeyboard, 0*Scale, 1*Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = 2*Scale,
Width = 3*Scale,
Rotate = true,
ContainedBrush = false
};
_p3 = new KeyboardRectangle(MainManager.DeviceManager.ActiveKeyboard, 0*Scale, 3*Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = 2*Scale,
Width = 3*Scale,
Rotate = true,
ContainedBrush = false
};
_p4 = new KeyboardRectangle(MainManager.DeviceManager.ActiveKeyboard, 0*Scale, 5*Scale,
new List<Color>(),
LinearGradientMode.Horizontal)
{
Height = 2*Scale,
Width = 3*Scale,
Rotate = true,
ContainedBrush = false
};
_stickyAmmo = new StickyValue<bool>(200);
_stickyHp = new StickyValue<bool>(200);
@ -133,10 +94,12 @@ namespace Artemis.Modules.Games.TheDivision
newState = PlayerState.Offline;
if (playerId == 1)
gameDataModel.PartyMember1 = newState;
gameDataModel.LowHp = (newState == PlayerState.Hit);
else if (playerId == 2)
gameDataModel.PartyMember2 = newState;
gameDataModel.PartyMember1 = newState;
else if (playerId == 3)
gameDataModel.PartyMember2 = newState;
else if (playerId == 4)
gameDataModel.PartyMember3 = newState;
}
// R blinks white when low on ammo
@ -165,81 +128,16 @@ namespace Artemis.Modules.Games.TheDivision
public override void Update()
{
var gameDataModel = (TheDivisionDataModel)GameDataModel;
if (gameDataModel.LowAmmo)
{
_ammoWave.Size++;
if (_ammoWave.Size > 30)
{
_ammoWave.Size = 0;
_trans = 255;
}
}
else
_ammoWave.Size = 0;
_hpRect.Colors = gameDataModel.LowHp
? new List<Color> {Color.Red, Color.Orange}
: new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
if (gameDataModel.PartyMember1 == PlayerState.Offline)
_p2.Colors = new List<Color> {Color.Gray, Color.White};
else if (gameDataModel.PartyMember1 == PlayerState.Online)
_p2.Colors = new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p2.Colors = new List<Color> {Color.Red, Color.Orange};
if (gameDataModel.PartyMember2 == PlayerState.Offline)
_p3.Colors = new List<Color> {Color.Gray, Color.White};
else if (gameDataModel.PartyMember2 == PlayerState.Online)
_p3.Colors = new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p3.Colors = new List<Color> {Color.Red, Color.Orange};
if (gameDataModel.PartyMember3 == PlayerState.Offline)
_p4.Colors = new List<Color> {Color.Gray, Color.White};
else if (gameDataModel.PartyMember3 == PlayerState.Online)
_p4.Colors = new List<Color> {Color.FromArgb(10, 255, 0), Color.FromArgb(80, 255, 45)};
else
_p4.Colors = new List<Color> {Color.Red, Color.Orange};
// DataModel updating is done whenever a pipe message is received
}
public override Bitmap GenerateBitmap()
{
var bitmap = MainManager.DeviceManager.ActiveKeyboard.KeyboardBitmap(Scale);
using (var g = Graphics.FromImage(bitmap))
{
g.Clear(Color.Transparent);
_hpRect.Draw(g);
_p2.Draw(g);
_p3.Draw(g);
_p4.Draw(g);
// Very, very PH
if (_ammoWave.Size != 0)
{
var path = new GraphicsPath();
path.AddEllipse(_ammoWave.Point.X - _ammoWave.Size/2, _ammoWave.Point.Y - _ammoWave.Size/2,
_ammoWave.Size, _ammoWave.Size);
if (Profile == null || GameDataModel == null)
return null;
if (_ammoWave.Size > 15)
_trans = _trans - 16;
if (_trans < 1)
_trans = 255;
var pthGrBrush = new PathGradientBrush(path)
{
SurroundColors = new[] {_ammoWave.Color},
CenterColor = Color.FromArgb(_trans, 255, 0, 0)
};
g.FillPath(pthGrBrush, path);
pthGrBrush.FocusScales = new PointF(0.3f, 0.8f);
g.FillPath(pthGrBrush, path);
g.DrawEllipse(new Pen(pthGrBrush, 1), _ammoWave.Point.X - _ammoWave.Size/2,
_ammoWave.Point.Y - _ammoWave.Size/2, _ammoWave.Size, _ammoWave.Size);
}
}
return bitmap;
var keyboardRect = MainManager.DeviceManager.ActiveKeyboard.KeyboardRectangle(Scale);
return Profile.GenerateBitmap<TheDivisionDataModel>(keyboardRect, GameDataModel, false, true);
}
public override Brush GenerateMouseBrush()

View File

@ -25,7 +25,7 @@
<Label FontSize="20" HorizontalAlignment="Left">
<Label.Content>
<AccessText TextWrapping="Wrap"
Text="Shows verious game states and events on the keyboard." />
Text="Shows verious game states and events on the keyboard. (BETA, uses much CPU!)" />
</Label.Content>
</Label>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">

View File

@ -62,25 +62,6 @@ namespace Artemis.Utilities
}
}
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T CloneAlt<T>(T source)
{
// Don't serialize a null object, simply return the default for that object
if (ReferenceEquals(source, null))
return default(T);
var xaml = XamlWriter.Save(source);
var xamlString = new StringReader(xaml);
var xmlTextReader = new XmlTextReader(xamlString);
var deepCopyObject = (T)XamlReader.Load(xmlTextReader);
return deepCopyObject;
}
public static string Serialize<T>(T source)
{
// Don't serialize a null object, simply return the default for that object

View File

@ -4,44 +4,40 @@ namespace Artemis.Utilities.Layers
{
public static class AnimationUpdater
{
public static void UpdateAnimation(KeyboardPropertiesModel properties, KeyboardPropertiesModel appliedProperties, bool updateAnimations)
public static void UpdateAnimation(KeyboardPropertiesModel properties, bool updateAnimations)
{
const int scale = 4;
var animateProperties = properties.Contain ? appliedProperties : properties;
appliedProperties.AnimationProgress = properties.AnimationProgress;
var progress = appliedProperties.AnimationProgress;
var progress = properties.AnimationProgress;
switch (animateProperties.Animation)
switch (properties.Animation)
{
case LayerAnimation.SlideRight:
case LayerAnimation.SlideLeft:
if (progress + 1 >= animateProperties.Width*scale)
if (progress + 1 >= properties.Width*scale)
progress = 0;
progress = progress + animateProperties.AnimationSpeed * 2;
progress = progress + properties.AnimationSpeed * 2;
break;
case LayerAnimation.SlideDown:
case LayerAnimation.SlideUp:
if (progress + 1 >= animateProperties.Height*scale)
if (progress + 1 >= properties.Height*scale)
progress = 0;
progress = progress + animateProperties.AnimationSpeed * 2;
progress = progress + properties.AnimationSpeed * 2;
break;
case LayerAnimation.Pulse:
if (progress > 2)
progress = 0;
progress = progress + animateProperties.AnimationSpeed/2;
progress = progress + properties.AnimationSpeed/2;
break;
case LayerAnimation.Grow:
if (progress > 10)
progress = 0;
progress = progress + animateProperties.AnimationSpeed / 2.5;
progress = progress + properties.AnimationSpeed / 2.5;
break;
default:
progress = progress + animateProperties.AnimationSpeed*2;
progress = progress + properties.AnimationSpeed*2;
break;
}
appliedProperties.AnimationProgress = progress;
// If not previewing, store the animation progress in the actual model for the next frame
if (updateAnimations)
properties.AnimationProgress = progress;

View File

@ -14,7 +14,7 @@ namespace Artemis.Utilities.Layers
{
public static class Drawer
{
public static void Draw(DrawingContext c, KeyboardPropertiesModel props, KeyboardPropertiesModel applied)
public static void Draw(DrawingContext c, KeyboardPropertiesModel props, AppliedProperties applied)
{
if (applied.Brush == null)
return;
@ -28,56 +28,52 @@ namespace Artemis.Utilities.Layers
var s1 = new Rect();
var s2 = new Rect();
if (applied.Animation == LayerAnimation.SlideRight)
if (props.Animation == LayerAnimation.SlideRight)
{
s1 = new Rect(new Point(rect.X + applied.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height));
s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + 1, rect.Height));
s1 = new Rect(new Point(rect.X + props.AnimationProgress, rect.Y), new Size(rect.Width, rect.Height));
s2 = new Rect(new Point(s1.X - rect.Width, rect.Y), new Size(rect.Width + 0.05, rect.Height));
}
if (applied.Animation == LayerAnimation.SlideLeft)
if (props.Animation == LayerAnimation.SlideLeft)
{
s1 = new Rect(new Point(rect.X - applied.AnimationProgress, rect.Y),
new Size(rect.Width + 1, rect.Height));
s1 = new Rect(new Point(rect.X - props.AnimationProgress, rect.Y),
new Size(rect.Width + 0.05, rect.Height));
s2 = new Rect(new Point(s1.X + rect.Width, rect.Y), new Size(rect.Width, rect.Height));
}
if (applied.Animation == LayerAnimation.SlideDown)
if (props.Animation == LayerAnimation.SlideDown)
{
s1 = new Rect(new Point(rect.X, rect.Y + applied.AnimationProgress), new Size(rect.Width, rect.Height));
s1 = new Rect(new Point(rect.X, rect.Y + props.AnimationProgress), new Size(rect.Width, rect.Height));
s2 = new Rect(new Point(s1.X, s1.Y - rect.Height), new Size(rect.Width, rect.Height));
}
if (applied.Animation == LayerAnimation.SlideUp)
if (props.Animation == LayerAnimation.SlideUp)
{
s1 = new Rect(new Point(rect.X, rect.Y - applied.AnimationProgress), new Size(rect.Width, rect.Height));
s1 = new Rect(new Point(rect.X, rect.Y - props.AnimationProgress), new Size(rect.Width, rect.Height));
s2 = new Rect(new Point(s1.X, s1.Y + rect.Height), new Size(rect.Width, rect.Height));
}
var clip = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale, applied.Height*scale);
DrawRectangle(c, applied, clip, rect, s1, s2);
DrawRectangle(c, props, applied, clip, rect, s1, s2);
}
private static void DrawRectangle(DrawingContext c, KeyboardPropertiesModel properties, Rect clip,
Rect rectangle,
Rect slide1, Rect slide2)
private static void DrawRectangle(DrawingContext c, KeyboardPropertiesModel props, AppliedProperties applied,
Rect clip, Rect rectangle, Rect slide1, Rect slide2)
{
var brush = properties.Brush.CloneCurrentValue();
brush.Opacity = properties.Opacity;
// Apply the pulse animation
if (properties.Animation == LayerAnimation.Pulse)
brush.Opacity = (Math.Sin(properties.AnimationProgress*Math.PI) + 1)*(properties.Opacity/2);
if (props.Animation == LayerAnimation.Pulse)
applied.Brush.Opacity = (Math.Sin(props.AnimationProgress*Math.PI) + 1)*(props.Opacity/2);
else
brush.Opacity = properties.Opacity;
applied.Brush.Opacity = props.Opacity;
if (properties.Animation == LayerAnimation.Grow)
if (props.Animation == LayerAnimation.Grow)
{
// Take an offset of 4 to allow layers to slightly leave their bounds
var progress = (6.0 - properties.AnimationProgress)*10.0;
var progress = (6.0 - props.AnimationProgress)*10.0;
if (progress < 0)
{
brush.Opacity = 1 + (0.025*progress);
if (brush.Opacity < 0)
brush.Opacity = 0;
if (brush.Opacity > 1)
brush.Opacity = 1;
applied.Brush.Opacity = 1 + 0.025*progress;
if (applied.Brush.Opacity < 0)
applied.Brush.Opacity = 0;
if (applied.Brush.Opacity > 1)
applied.Brush.Opacity = 1;
}
rectangle.Inflate(-rectangle.Width/100.0*progress, -rectangle.Height/100.0*progress);
clip.Inflate(-clip.Width/100.0*progress, -clip.Height/100.0*progress);
@ -85,41 +81,41 @@ namespace Artemis.Utilities.Layers
c.PushClip(new RectangleGeometry(clip));
// Most animation types can be drawn regularly
if (properties.Animation == LayerAnimation.None ||
properties.Animation == LayerAnimation.Grow ||
properties.Animation == LayerAnimation.Pulse)
if (props.Animation == LayerAnimation.None ||
props.Animation == LayerAnimation.Grow ||
props.Animation == LayerAnimation.Pulse)
{
c.DrawRectangle(brush, null, rectangle);
c.DrawRectangle(applied.Brush, null, rectangle);
}
// Sliding animations however, require offsetting two rects
else
{
c.PushClip(new RectangleGeometry(clip));
c.DrawRectangle(brush, null, slide1);
c.DrawRectangle(brush, null, slide2);
c.DrawRectangle(applied.Brush, null, slide1);
c.DrawRectangle(applied.Brush, null, slide2);
c.Pop();
}
c.Pop();
}
public static GifImage DrawGif(DrawingContext c, KeyboardPropertiesModel properties, GifImage gifImage,
bool update = true)
public static GifImage DrawGif(DrawingContext c, KeyboardPropertiesModel props, AppliedProperties applied,
GifImage gifImage, bool update = true)
{
if (string.IsNullOrEmpty(properties.GifFile))
if (string.IsNullOrEmpty(props.GifFile))
return null;
if (!File.Exists(properties.GifFile))
if (!File.Exists(props.GifFile))
return null;
const int scale = 4;
// Only reconstruct GifImage if the underlying source has changed
if (gifImage == null)
gifImage = new GifImage(properties.GifFile);
if (gifImage.Source != properties.GifFile)
gifImage = new GifImage(properties.GifFile);
gifImage = new GifImage(props.GifFile);
if (gifImage.Source != props.GifFile)
gifImage = new GifImage(props.GifFile);
var gifRect = new Rect(properties.X*scale, properties.Y*scale, properties.Width*scale,
properties.Height*scale);
var gifRect = new Rect(applied.X*scale, applied.Y*scale, applied.Width*scale,
applied.Height*scale);
var draw = update ? gifImage.GetNextFrame() : gifImage.GetFrame(0);
c.DrawImage(ImageUtilities.BitmapToBitmapImage(new Bitmap(draw)), gifRect);

View File

@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using Artemis.Properties;
using Microsoft.Win32;
@ -13,6 +14,8 @@ namespace Artemis.Utilities.LogitechDll
if (!File.Exists(LogitechPath + @"\LogitechLed.dll") || !File.Exists(LogitechPath + @"\artemis.txt"))
return false;
try
{
// Get rid of our own DLL
File.Delete(LogitechPath + @"\LogitechLed.dll");
@ -24,6 +27,12 @@ namespace Artemis.Utilities.LogitechDll
return true;
}
catch (Exception)
{
return false;
}
}
public static void PlaceDll()
{
@ -35,8 +44,11 @@ namespace Artemis.Utilities.LogitechDll
// Backup the existing DLL
if (File.Exists(LogitechPath + @"\LogitechLed.dll"))
File.Move(LogitechPath + @"\LogitechLed.dll",
LogitechPath + @"\LogitechLed.dll.bak");
{
if (File.Exists(LogitechPath + @"\LogitechLed.dll.bak"))
File.Delete(LogitechPath + @"\LogitechLed.dll.bak");
File.Move(LogitechPath + @"\LogitechLed.dll", LogitechPath + @"\LogitechLed.dll.bak");
}
// Copy our own DLL in place
File.WriteAllBytes(LogitechPath + @"\LogitechLED.dll",

View File

@ -63,7 +63,6 @@ namespace Artemis.Utilities.LogitechDll
private void HandleMessage(byte[] buffer)
{
var request = Encoding.ASCII.GetString(buffer);
Debug.WriteLine(request);
PipeMessage?.Invoke(request);
}
@ -106,7 +105,6 @@ namespace Artemis.Utilities.LogitechDll
// Convert byte buffer to string
var stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
Debug.WriteLine(stringData + Environment.NewLine);
// Pass message back to calling form
PipeMessage?.Invoke(stringData);

View File

@ -3,6 +3,7 @@ using System.Linq;
using Artemis.Models.Profiles.Properties;
using Artemis.Utilities;
using Caliburn.Micro;
using Castle.Core.Internal;
namespace Artemis.ViewModels.Profiles
{
@ -211,6 +212,7 @@ namespace Artemis.ViewModels.Profiles
if (original != null)
keyboardProperties.DynamicProperties.Remove(original);
if (!Proposed.GameProperty.IsNullOrEmpty())
keyboardProperties.DynamicProperties.Add(Proposed);
}
}

View File

@ -172,6 +172,7 @@ namespace Artemis.ViewModels.Profiles
source.Order = -1;
target.Children.Add(source);
target.FixOrder();
target.Expanded = true;
}
else
{

View File

@ -5,7 +5,6 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using Artemis.Events;
using Artemis.Managers;
using Artemis.Models.Profiles;
@ -112,10 +111,8 @@ namespace Artemis.ViewModels.Profiles
// Draw the layers
var drawLayers = SelectedProfile.Layers
.OrderByDescending(l => l.Order)
.Where(l => l.Enabled &&
(l.LayerType == LayerType.Keyboard ||
l.LayerType == LayerType.KeyboardGif ||
l.LayerType == LayerType.Folder));
.Where(l => l.MustDraw() || (l.Enabled && l.LayerType == LayerType.Folder))
.ToList();
foreach (var layer in drawLayers)
layer.Draw<object>(null, drawingContext, true, false);

View File

@ -14,7 +14,7 @@ namespace Artemis.ViewModels.Profiles.Properties
: base(gameDataModel)
{
ProposedProperties = GeneralHelpers.Clone(properties);
Brush = GeneralHelpers.CloneAlt(ProposedProperties.Brush);
Brush = ProposedProperties.Brush.CloneCurrentValue();
}
public Brush Brush

View File

@ -9,16 +9,16 @@ namespace Artemis.ViewModels.Profiles.Properties
{
public class KeyboardPropertiesViewModel : LayerPropertiesViewModel
{
private Brush _brush;
private bool _isGif;
private KeyboardPropertiesModel _proposedProperties;
private Brush _brush;
public KeyboardPropertiesViewModel(IGameDataModel gameDataModel, LayerPropertiesModel properties)
: base(gameDataModel)
{
var keyboardProperties = (KeyboardPropertiesModel) properties;
ProposedProperties = GeneralHelpers.Clone(keyboardProperties);
Brush = GeneralHelpers.CloneAlt(ProposedProperties.Brush);
Brush = ProposedProperties.Brush.CloneCurrentValue();
DataModelProps = new BindableCollection<GeneralHelpers.PropertyCollection>();
DataModelProps.AddRange(GeneralHelpers.GenerateTypeMap(gameDataModel));
@ -51,6 +51,17 @@ namespace Artemis.ViewModels.Profiles.Properties
}
}
public Brush Brush
{
get { return _brush; }
set
{
if (Equals(value, _brush)) return;
_brush = value;
NotifyOfPropertyChange(() => Brush);
}
}
public bool ShowGif => IsGif;
public bool ShowBrush => !IsGif;
@ -76,7 +87,6 @@ namespace Artemis.ViewModels.Profiles.Properties
public override LayerPropertiesModel GetAppliedProperties()
{
HeightProperties.Apply(ProposedProperties);
WidthProperties.Apply(ProposedProperties);
OpacityProperties.Apply(ProposedProperties);
@ -85,16 +95,5 @@ namespace Artemis.ViewModels.Profiles.Properties
properties.Brush = Brush;
return properties;
}
public Brush Brush
{
get { return _brush; }
set
{
if (Equals(value, _brush)) return;
_brush = value;
NotifyOfPropertyChange(() => Brush);
}
}
}
}

View File

@ -15,7 +15,7 @@ namespace Artemis.ViewModels.Profiles.Properties
: base(gameDataModel)
{
ProposedProperties = GeneralHelpers.Clone(properties);
Brush = GeneralHelpers.CloneAlt(ProposedProperties.Brush);
Brush = ProposedProperties.Brush.CloneCurrentValue();
}
public Brush Brush